Files
web_server/vue/src/views/Notes.vue
Adam French 31d4b4c268
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 4m6s
Refactor CV into separate role-specific components and misc frontend tweaks
Split CV.vue into CVGeneral, CVBackend, CVFrontend, and CVHospitality variants.
Also adds halftone body class, reformats index.html, and minor style/layout fixes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 14:03:00 +00:00

76 lines
2.2 KiB
Vue

<script setup>
import Markdown from "@/components/util/Markdown.vue";
import { ref, onMounted } from "vue";
import axios from "axios";
import { useRoute } from "vue-router";
const file = ref(null);
const filename = ref("");
const last_edited = ref(null);
// if the address is https://www.adam-french.co.uk/notes/PATH
// request from https://www.adam-french.co.uk/api/notes/PATH
const route = useRoute();
const pathArray = route.params.path;
const path = Array.isArray(pathArray) ? pathArray.join("/") : pathArray;
const url = `/api/notes/${path}`;
function getFilename(headers) {
const disposition = headers["content-disposition"];
if (!disposition) return null;
const match = disposition.match(/filename="?([^"]+)"?/);
return match ? match[1] : null;
}
async function fetchFile() {
const response = await axios.get(url, { responseType: "blob" });
filename.value = getFilename(response.headers);
const lastModified = response.headers["last-modified"];
last_edited.value = lastModified ? new Date(lastModified) : null;
if (filename.value.toLowerCase().endsWith(".md")) {
const text = await response.data.text();
file.value = fixLinks(text);
} else {
file.value = response.data;
}
}
function fixLinks(filedata) {
return filedata.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, text, url) => {
if (
url.startsWith("http://") ||
url.startsWith("https://") ||
url.startsWith("#") ||
url.startsWith("./") ||
url.startsWith("../") ||
url.startsWith("//")
) {
return match;
}
return `[${text}](/notes/${url})`;
});
}
onMounted(fetchFile);
</script>
<template>
<main class="items-center flex flex-col">
<div class="background" />
<div
v-if="file"
class="a4page-portrait border-primary-1 flex flex-col relative overflow-scroll gap-1 bg-bg_primary"
>
<h1>{{ filename }}</h1>
<small>{{ last_edited }}</small>
<Markdown class="flex-1 border-box text-wrap" :source="file" />
</div>
<div v-else>Loading</div>
</main>
</template>