diff --git a/package.json b/package.json index 0a0b157..f9456ee 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "lint": "run-s lint:*", "lint:oxlint": "oxlint . --fix", "lint:eslint": "eslint . --fix --cache", - "format": "prettier --write --experimental-cli src/" + "format": "prettier --write src/" }, "dependencies": { "vue": "^3.5.32", diff --git a/public/articles b/public/articles new file mode 120000 index 0000000..75a0fa5 --- /dev/null +++ b/public/articles @@ -0,0 +1 @@ +../articles \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index df36fcf..0000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/src/App.vue b/src/App.vue index abfd315..7c2aa3f 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,11 +1,3 @@ - - - - diff --git a/src/interfaces.ts b/src/interfaces.ts new file mode 100644 index 0000000..1add3a9 --- /dev/null +++ b/src/interfaces.ts @@ -0,0 +1,11 @@ +export interface MarkdownAttributes { + title?: string + draft?: string + thumbnail?: string + path?: string +} + +export interface MarkdownData { + attributes: MarkdownAttributes + html: string +} diff --git a/src/lib/articles.ts b/src/lib/articles.ts new file mode 100644 index 0000000..9753ce5 --- /dev/null +++ b/src/lib/articles.ts @@ -0,0 +1,44 @@ +import type { ArticleList, MarkdownAttributes } from '@/interfaces' +import type { MarkdownData } from '@interfaces' + +function completeAttributes( + srcAttributes: MarkdownAttributes, + pathPrefix: string, +): MarkdownAttributes { + return { + draft: srcAttributes.draft ?? 'false', + thumbnail: srcAttributes.thumbnail + ? pathPrefix + srcAttributes.thumbnail + : pathPrefix + '/thumbnail.jpg', + title: srcAttributes.title ?? 'Untitled', + path: pathPrefix, + } +} + +export async function loadArticle(year: number, month: number, day: number): MarkdownData | null { + const path = `${year}/${month.toString().padStart(2, '0')}/${day.toString().padStart(2, '0')}` + console.log(path) + try { + const data = (await import( + `@articles/${year}/${month.toString().padStart(2, '0')}/${day.toString().padStart(2, '0')}/index.md` + )) as MarkdownData + return { + attributes: completeAttributes(data.attributes, `./articles/${path}`), + html: data.html.replaceAll('./', `./articles/${path}/`), + } + } catch { + return null + } +} + +export async function listArticles(): Promise { + const raw_articles = import.meta.glob('@articles/**/index.md') + const articles: MarkdownAttributes[] = await Promise.all( + Object.keys(raw_articles).map(async (key) => { + const data = (await raw_articles[key]()) as MarkdownData + return completeAttributes(data.attributes, key.replace('/index.md', '')) + }), + ) + articles.sort((article1, article2) => article1.path?.localeCompare(article2.path ?? '') ?? 0) + return articles +} diff --git a/src/router/index.ts b/src/router/index.ts index e1eab52..7bba770 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,8 +1,15 @@ -import { createRouter, createWebHistory } from 'vue-router' +import ArticleView from '@views/ArticleView.vue' +import HomeView from '@views/HomeView.vue' +import NotFoundView from '@views/NotFoundView.vue' +import { createRouter, createWebHashHistory } from 'vue-router' const router = createRouter({ - history: createWebHistory(import.meta.env.BASE_URL), - routes: [], + history: createWebHashHistory(), + routes: [ + { path: '/', component: HomeView }, + { path: '/articles/:year(\\d{4})/:month(\\d{2})/:day(\\d{2})', component: ArticleView }, + { path: '/:pathMatch(.*)', component: NotFoundView }, + ], }) export default router diff --git a/src/views/ArticleView.vue b/src/views/ArticleView.vue new file mode 100644 index 0000000..c4b5054 --- /dev/null +++ b/src/views/ArticleView.vue @@ -0,0 +1,39 @@ + + + + + diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue new file mode 100644 index 0000000..0226f8c --- /dev/null +++ b/src/views/HomeView.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/src/views/NotFoundView.vue b/src/views/NotFoundView.vue new file mode 100644 index 0000000..23f7f88 --- /dev/null +++ b/src/views/NotFoundView.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/tsconfig.app.json b/tsconfig.app.json index c0f2d86..313a8cd 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -1,6 +1,6 @@ { "extends": "@vue/tsconfig/tsconfig.dom.json", - "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "include": ["env.d.ts", "vite.d.ts", "src/**/*", "src/**/*.vue"], "exclude": ["src/**/__tests__/*"], "compilerOptions": { // Extra safety for array and object lookups, but may have false positives. diff --git a/vite.config.ts b/vite.config.ts index b87b405..e6b5bc9 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -11,7 +11,11 @@ export default defineConfig({ resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)), + '@views': fileURLToPath(new URL('./src/views', import.meta.url)), + '@lib': fileURLToPath(new URL('./src/lib', import.meta.url)), '@articles': fileURLToPath(new URL('./articles', import.meta.url)), + '@interfaces': fileURLToPath(new URL('./src/interfaces.ts', import.meta.url)), }, }, + assetsInclude: [/\.\/articles\/.*(?!\.md)'/], }) diff --git a/vite.d.ts b/vite.d.ts new file mode 100644 index 0000000..f05b246 --- /dev/null +++ b/vite.d.ts @@ -0,0 +1,25 @@ +declare module '*.md' { + // "unknown" would be more detailed depends on how you structure frontmatter + const attributes: Record + + // When "Mode.TOC" is requested + const toc: { level: string; content: string }[] + + // When "Mode.HTML" is requested + const html: string + + // When "Mode.RAW" is requested + const raw: string + + // When "Mode.React" is requested. VFC could take a generic like React.VFC<{ MyComponent: TypeOfMyComponent }> + import React from 'react' + const ReactComponent: React.VFC + + // When "Mode.Vue" is requested + import { ComponentOptions, Component } from 'vue' + const VueComponent: ComponentOptions + const VueComponentWith: (components: Record) => ComponentOptions + + // Modify below per your usage + export { attributes, toc, html, ReactComponent, VueComponent, VueComponentWith } +}