diff --git a/.eslintrc.json b/.eslintrc.json index 398f06d..c58fb0c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -13,7 +13,8 @@ ], "parserOptions": { "ecmaVersion": "latest", - "sourceType": "module" + "sourceType": "module", + "parser": "@typescript-eslint/parser" }, "plugins": [ "vue", diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 360bcf4..c1f3c0a 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -1,6 +1,10 @@ -import { defineConfig } from "vitepress"; +import { defineConfigWithTheme } from "vitepress"; +import type { ThemeConfig } from "./theme-config"; +import { getPostList } from "./theme/loader"; -export default defineConfig({ +const year = new Date().getFullYear(); + +export default defineConfigWithTheme({ title: "WhaleVocal", description: "Octobug's blog.", cleanUrls: true, @@ -11,7 +15,7 @@ export default defineConfig({ { rel: "icon", type: "image/png", - href: "/favicon.png", + href: "/avatar.png", }, ], [ @@ -27,12 +31,16 @@ export default defineConfig({ ], themeConfig: { outline: "deep", + docFooter: { + prev: "Previous", + next: "Next", + }, editLink: { pattern: "https://github.com/Octobug/blog/edit/main/:path", }, footer: { message: 'All published under the CC-BY-SA-4.0 license.', - copyright: '© 2019-present Octobug', + copyright: `Copyright © 2019-${year} Octobug`, }, lastUpdated: { formatOptions: { @@ -45,10 +53,18 @@ export default defineConfig({ text: "POSTS", link: "/pages/posts", }, + // { + // text: "VISIONS", + // link: "/pages/visions", + // }, { text: "TAGS", link: "/pages/tags", }, + { + text: "SORTS", + link: "/pages/sorts", + }, { text: "REPO", link: "https://github.com/Octobug/blog", @@ -66,5 +82,15 @@ export default defineConfig({ link: "mailto:whalevocal@gmail.com", }, ], + // Extended configs + avatar: "/avatar.png", + nickname: "Octobug", + bio: "Thoughts on everything.", + location: "Shenzhen, China", + timezone: "Aisa/Shanghai", + pageSize: 10, + postList: await getPostList([ + "./posts", + ]), }, }); diff --git a/.vitepress/theme-config.d.ts b/.vitepress/theme-config.d.ts new file mode 100644 index 0000000..25ae00a --- /dev/null +++ b/.vitepress/theme-config.d.ts @@ -0,0 +1,12 @@ +import { DefaultTheme } from "vitepress"; +import type { Post } from "./theme/post"; + +export interface ThemeConfig extends DefaultTheme.Config { + avatar: string, + nickname: string, + bio: string, + location: string, + timezone: string, + pageSize: number, + postList: Array, +} diff --git a/.vitepress/theme/Layout.vue b/.vitepress/theme/Layout.vue new file mode 100644 index 0000000..d832a1d --- /dev/null +++ b/.vitepress/theme/Layout.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/.vitepress/theme/components/Avatar.vue b/.vitepress/theme/components/Avatar.vue new file mode 100644 index 0000000..71fe7c6 --- /dev/null +++ b/.vitepress/theme/components/Avatar.vue @@ -0,0 +1,28 @@ + + + + + diff --git a/.vitepress/theme/components/Profile.vue b/.vitepress/theme/components/Profile.vue new file mode 100644 index 0000000..77ed01c --- /dev/null +++ b/.vitepress/theme/components/Profile.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/.vitepress/theme/components/ProfileExtra.vue b/.vitepress/theme/components/ProfileExtra.vue new file mode 100644 index 0000000..f69386d --- /dev/null +++ b/.vitepress/theme/components/ProfileExtra.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/.vitepress/theme/index.ts b/.vitepress/theme/index.ts index 4bc67cf..def7098 100644 --- a/.vitepress/theme/index.ts +++ b/.vitepress/theme/index.ts @@ -1,17 +1,15 @@ // https://vitepress.dev/guide/custom-theme -import { h } from "vue"; import Theme from "vitepress/theme"; import "./style.css"; +// import Archives from "./components/Archives.vue"; +// import Tags from "./components/Tags.vue"; +import Layout from "./Layout.vue"; +import Home from "./pages/Home.vue"; export default { extends: Theme, - // eslint-disable-next-line @typescript-eslint/naming-convention - Layout() { - return h(Theme.Layout, null, { - // https://vitepress.dev/guide/extending-default-theme#layout-slots - }); - }, - enhanceApp({ app, router, siteData }) { - // ... + Layout, + enhanceApp({ app }) { + app.component("Home", Home); }, }; diff --git a/.vitepress/theme/loader.ts b/.vitepress/theme/loader.ts new file mode 100644 index 0000000..4f7bf53 --- /dev/null +++ b/.vitepress/theme/loader.ts @@ -0,0 +1,27 @@ +import fs from "fs/promises"; +import globby from "globby"; +import matter from "gray-matter"; +import moment from "moment-timezone"; +import type { Post } from "./post"; + +export async function getPostList(postDirs: readonly string[]) { + const mdList = await globby(postDirs); + const postList = await Promise.all( + mdList.map(async (item) => { + const content = (await fs.readFile(item)).toString(); + const { data } = matter(content); + data.datetime = moment(new Date(data.date)); + data.date = data.datetime.format("YYYY-MM-DD"); + return { + frontMatter: data, + regularPath: `/${item.replace(".md", "")}`, + }; + }) + ); + postList.sort(_compareDate); + return postList; +} + +function _compareDate(a: Post, b: Post) { + return b.frontMatter.datetime - a.frontMatter.datetime; +} diff --git a/.vitepress/theme/pages/Home.vue b/.vitepress/theme/pages/Home.vue new file mode 100644 index 0000000..c2db436 --- /dev/null +++ b/.vitepress/theme/pages/Home.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/.vitepress/theme/post.d.ts b/.vitepress/theme/post.d.ts new file mode 100644 index 0000000..ceb0517 --- /dev/null +++ b/.vitepress/theme/post.d.ts @@ -0,0 +1,4 @@ +export interface Post { + regularPath: string; + frontMatter: { [key: string]: any }; +} diff --git a/.vitepress/theme/style.css b/.vitepress/theme/style.css index 2846037..abe2b97 100644 --- a/.vitepress/theme/style.css +++ b/.vitepress/theme/style.css @@ -134,10 +134,22 @@ } /* - * Customization - */ -.title { + * Custom CSS + * -------------------------------------------------------------------------- */ + +:root { + --vp-avatar-border: #ffffff; + --vp-avatar-large: 10rem; + --vp-avatar-medium: 8rem; + --vp-avatar-small: 6rem; +} + +header a.title { font-family: Georgia, sans-serif; font-size: 1.3rem !important; font-weight: 100 !important; } + +footer a { + color: var(--vp-c-neutral); +} diff --git a/index.md b/index.md index 19a1f54..4ede3e5 100644 --- a/index.md +++ b/index.md @@ -1,8 +1,8 @@ --- -# layout: home date: 2023-10-29 -title: Octobug's Blog +layout: home sidebar: false +title: Octobug's Blog --- -👷 🚧 + diff --git a/package-lock.json b/package-lock.json index 13a53d1..4678eb5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,11 +8,16 @@ "name": "whalevocal", "version": "1.0.0", "license": "CC-BY-SA-4.0", + "dependencies": { + "moment-timezone": "^0.5.43" + }, "devDependencies": { + "@types/node": "^20.8.10", "@typescript-eslint/eslint-plugin": "^6.7.2", "@typescript-eslint/parser": "^6.7.2", "eslint": "^8.50.0", "eslint-plugin-vue": "^9.17.0", + "gray-matter": "^4.0.3", "husky": "^8.0.3", "lint-staged": "^15.0.2", "markdownlint-cli": "^0.37.0", @@ -805,6 +810,15 @@ "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", "dev": true }, + "node_modules/@types/node": { + "version": "20.8.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", + "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/@types/semver": { "version": "7.5.2", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.2.tgz", @@ -1845,6 +1859,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", @@ -1922,6 +1949,18 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2179,6 +2218,43 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dev": true, + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2271,6 +2347,15 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2400,6 +2485,15 @@ "json-buffer": "3.0.1" } }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2788,6 +2882,25 @@ "integrity": "sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==", "dev": true }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.43", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz", + "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -3267,6 +3380,19 @@ "dev": true, "peer": true }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -3385,6 +3511,12 @@ "node": ">=0.10.0" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, "node_modules/string-argv": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", @@ -3484,6 +3616,15 @@ "node": ">=8" } }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", @@ -3599,6 +3740,12 @@ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", "dev": true }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", diff --git a/package.json b/package.json index 8c1f68a..b6a97e0 100644 --- a/package.json +++ b/package.json @@ -30,14 +30,19 @@ }, "homepage": "https://github.com/Octobug/blog#readme", "devDependencies": { + "@types/node": "^20.8.10", "@typescript-eslint/eslint-plugin": "^6.7.2", "@typescript-eslint/parser": "^6.7.2", "eslint": "^8.50.0", "eslint-plugin-vue": "^9.17.0", + "gray-matter": "^4.0.3", "husky": "^8.0.3", "lint-staged": "^15.0.2", "markdownlint-cli": "^0.37.0", "typescript": "^5.2.2", "vitepress": "^1.0.0-rc.15" + }, + "dependencies": { + "moment-timezone": "^0.5.43" } } diff --git a/public/favicon.png b/public/avatar.png similarity index 100% rename from public/favicon.png rename to public/avatar.png