diff --git a/docs/sidebar.ts b/docs/sidebar.ts index cd3066b..042fcf7 100644 --- a/docs/sidebar.ts +++ b/docs/sidebar.ts @@ -2,17 +2,22 @@ import fs from "fs"; import path from "path"; import matter, { type GrayMatterFile } from "gray-matter"; import { buildTOC } from "./toc"; +import { getTableOfContents, Items } from "../shared"; const dir = path.join(__dirname, "/wiki/"); -function getMetadata(path: string): GrayMatterFile { +async function getMetadata( + path: string, +): Promise<{ frontmatter: GrayMatterFile; toc: Items }> { const contents = fs.readFileSync(path, "utf8"); - return matter(contents); + const frontmatter = matter(contents); + const toc = await getTableOfContents(contents); + return { frontmatter, toc }; } export function generateSidebar(locale: string): any[] { let localePath = ""; - let items: { text: string; link: string }[] = []; + let items: { text: string; items: { text: string; link: string }[] }[] = []; buildTOC(); @@ -22,17 +27,20 @@ export function generateSidebar(locale: string): any[] { localePath = `${dir}`; } - fs.readdirSync(localePath).forEach((file) => { + fs.readdirSync(localePath).forEach(async (file) => { const filePath = path.join(localePath, file); const stat = fs.statSync(filePath); if (stat.isFile() && path.extname(file) === ".md") { - const title = getMetadata(filePath).data.title; - + const { frontmatter, toc } = await getMetadata(filePath); + const title = frontmatter.data.title; if (!title) throw new Error("Cannot find title in metadata: " + filePath); - + const tocItems = toc.items?.map((item) => ({ + text: item.title, + link: `/wiki/${file.replace(/\.md$/, "")}${item.url}`, + })); items.push({ text: title, - link: `/wiki/${file.replace(/\.md$/, "")}`, + items: tocItems!, }); } }); diff --git a/docs/start.md b/docs/start.md index d1b6296..167a51a 100644 --- a/docs/start.md +++ b/docs/start.md @@ -1,6 +1,7 @@ --- editLink: false --- + # Get Started diff --git a/package.json b/package.json index fe0771f..fdca821 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "wiki", "version": "1.0.0", + "type": "module", "main": "index.js", "scripts": { "format": "prettier --log-level=warn --write .", @@ -23,6 +24,9 @@ } }, "dependencies": { - "gray-matter": "^4.0.3" + "gray-matter": "^4.0.3", + "mdast-util-toc": "^7.0.0", + "remark": "^14.0.3", + "unist-util-visit": "^5.0.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 42c642d..9b39db5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,15 @@ dependencies: gray-matter: specifier: ^4.0.3 version: 4.0.3 + mdast-util-toc: + specifier: ^7.0.0 + version: 7.0.0 + remark: + specifier: ^14.0.3 + version: 14.0.3 + unist-util-visit: + specifier: ^5.0.0 + version: 5.0.0 devDependencies: "@types/node": @@ -572,6 +581,40 @@ packages: } dev: true + /@types/debug@4.1.8: + resolution: + { + integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==, + } + dependencies: + "@types/ms": 0.7.31 + dev: false + + /@types/mdast@3.0.12: + resolution: + { + integrity: sha512-DT+iNIRNX884cx0/Q1ja7NyUPpZuv0KPyL5rGNxm1WC1OtHstl7n4Jb7nk+xacNShQMbczJjt8uFzznpp6kYBg==, + } + dependencies: + "@types/unist": 2.0.7 + dev: false + + /@types/mdast@4.0.0: + resolution: + { + integrity: sha512-YLeG8CujC9adtj/kuDzq1N4tCDYKoZ5l/bnjq8d74+t/3q/tHquJOJKUQXJrLCflOHpKjXgcI/a929gpmLOEng==, + } + dependencies: + "@types/unist": 3.0.0 + dev: false + + /@types/ms@0.7.31: + resolution: + { + integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==, + } + dev: false + /@types/node@20.4.5: resolution: { @@ -579,6 +622,27 @@ packages: } dev: true + /@types/ungap__structured-clone@0.3.0: + resolution: + { + integrity: sha512-eBWREUhVUGPze+bUW22AgUr05k8u+vETzuYdLYSvWqGTUe0KOf+zVnOB1qER5wMcw8V6D9Ar4DfJmVvD1yu0kQ==, + } + dev: false + + /@types/unist@2.0.7: + resolution: + { + integrity: sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==, + } + dev: false + + /@types/unist@3.0.0: + resolution: + { + integrity: sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==, + } + dev: false + /@types/web-bluetooth@0.0.17: resolution: { @@ -586,6 +650,13 @@ packages: } dev: true + /@ungap/structured-clone@1.2.0: + resolution: + { + integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==, + } + dev: false + /@vitejs/plugin-vue@4.2.3(vite@4.4.7)(vue@3.3.4): resolution: { @@ -845,6 +916,13 @@ packages: sprintf-js: 1.0.3 dev: false + /bail@2.0.2: + resolution: + { + integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==, + } + dev: false + /body-scroll-lock@4.0.0-beta.0: resolution: { @@ -852,6 +930,13 @@ packages: } dev: true + /character-entities@2.0.2: + resolution: + { + integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==, + } + dev: false + /csstype@3.1.2: resolution: { @@ -859,6 +944,46 @@ packages: } dev: true + /debug@4.3.4: + resolution: + { + integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==, + } + engines: { node: ">=6.0" } + peerDependencies: + supports-color: "*" + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: false + + /decode-named-character-reference@1.0.2: + resolution: + { + integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==, + } + dependencies: + character-entities: 2.0.2 + dev: false + + /dequal@2.0.3: + resolution: + { + integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==, + } + engines: { node: ">=6" } + dev: false + + /diff@5.1.0: + resolution: + { + integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==, + } + engines: { node: ">=0.3.1" } + dev: false + /esbuild@0.18.17: resolution: { @@ -918,6 +1043,13 @@ packages: is-extendable: 0.1.1 dev: false + /extend@3.0.2: + resolution: + { + integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==, + } + dev: false + /focus-trap@7.5.2: resolution: { @@ -938,6 +1070,13 @@ packages: dev: true optional: true + /github-slugger@2.0.0: + resolution: + { + integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==, + } + dev: false + /gray-matter@4.0.3: resolution: { @@ -951,6 +1090,14 @@ packages: strip-bom-string: 1.0.0 dev: false + /is-buffer@2.0.5: + resolution: + { + integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==, + } + engines: { node: ">=4" } + dev: false + /is-extendable@0.1.1: resolution: { @@ -959,6 +1106,14 @@ packages: engines: { node: ">=0.10.0" } dev: false + /is-plain-obj@4.1.0: + resolution: + { + integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==, + } + engines: { node: ">=12" } + dev: false + /js-yaml@3.14.1: resolution: { @@ -985,6 +1140,21 @@ packages: engines: { node: ">=0.10.0" } dev: false + /kleur@4.1.5: + resolution: + { + integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==, + } + engines: { node: ">=6" } + dev: false + + /longest-streak@3.1.0: + resolution: + { + integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==, + } + dev: false + /magic-string@0.30.2: resolution: { @@ -1002,6 +1172,325 @@ packages: } dev: true + /mdast-util-from-markdown@1.3.1: + resolution: + { + integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==, + } + dependencies: + "@types/mdast": 3.0.12 + "@types/unist": 2.0.7 + decode-named-character-reference: 1.0.2 + mdast-util-to-string: 3.2.0 + micromark: 3.2.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-decode-string: 1.1.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + unist-util-stringify-position: 3.0.3 + uvu: 0.5.6 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-phrasing@3.0.1: + resolution: + { + integrity: sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==, + } + dependencies: + "@types/mdast": 3.0.12 + unist-util-is: 5.2.1 + dev: false + + /mdast-util-to-markdown@1.5.0: + resolution: + { + integrity: sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==, + } + dependencies: + "@types/mdast": 3.0.12 + "@types/unist": 2.0.7 + longest-streak: 3.1.0 + mdast-util-phrasing: 3.0.1 + mdast-util-to-string: 3.2.0 + micromark-util-decode-string: 1.1.0 + unist-util-visit: 4.1.2 + zwitch: 2.0.4 + dev: false + + /mdast-util-to-string@3.2.0: + resolution: + { + integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==, + } + dependencies: + "@types/mdast": 3.0.12 + dev: false + + /mdast-util-to-string@4.0.0: + resolution: + { + integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==, + } + dependencies: + "@types/mdast": 4.0.0 + dev: false + + /mdast-util-toc@7.0.0: + resolution: + { + integrity: sha512-C28UcSqjmnWuvgT8d97qpaItHKvySqVPAECUzqQ51xuMyNFFJwcFoKW77KoMjtXrclTidLQFDzLUmTmrshRweA==, + } + dependencies: + "@types/mdast": 4.0.0 + "@types/ungap__structured-clone": 0.3.0 + "@ungap/structured-clone": 1.2.0 + github-slugger: 2.0.0 + mdast-util-to-string: 4.0.0 + unist-util-is: 6.0.0 + unist-util-visit: 5.0.0 + dev: false + + /micromark-core-commonmark@1.1.0: + resolution: + { + integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==, + } + dependencies: + decode-named-character-reference: 1.0.2 + micromark-factory-destination: 1.1.0 + micromark-factory-label: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-factory-title: 1.1.0 + micromark-factory-whitespace: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-chunked: 1.1.0 + micromark-util-classify-character: 1.1.0 + micromark-util-html-tag-name: 1.2.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-subtokenize: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-factory-destination@1.1.0: + resolution: + { + integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==, + } + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-factory-label@1.1.0: + resolution: + { + integrity: sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==, + } + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-factory-space@1.1.0: + resolution: + { + integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==, + } + dependencies: + micromark-util-character: 1.2.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-factory-title@1.1.0: + resolution: + { + integrity: sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==, + } + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-factory-whitespace@1.1.0: + resolution: + { + integrity: sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==, + } + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-util-character@1.2.0: + resolution: + { + integrity: sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==, + } + dependencies: + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-util-chunked@1.1.0: + resolution: + { + integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==, + } + dependencies: + micromark-util-symbol: 1.1.0 + dev: false + + /micromark-util-classify-character@1.1.0: + resolution: + { + integrity: sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==, + } + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-util-combine-extensions@1.1.0: + resolution: + { + integrity: sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==, + } + dependencies: + micromark-util-chunked: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-util-decode-numeric-character-reference@1.1.0: + resolution: + { + integrity: sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==, + } + dependencies: + micromark-util-symbol: 1.1.0 + dev: false + + /micromark-util-decode-string@1.1.0: + resolution: + { + integrity: sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==, + } + dependencies: + decode-named-character-reference: 1.0.2 + micromark-util-character: 1.2.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-symbol: 1.1.0 + dev: false + + /micromark-util-encode@1.1.0: + resolution: + { + integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==, + } + dev: false + + /micromark-util-html-tag-name@1.2.0: + resolution: + { + integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==, + } + dev: false + + /micromark-util-normalize-identifier@1.1.0: + resolution: + { + integrity: sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==, + } + dependencies: + micromark-util-symbol: 1.1.0 + dev: false + + /micromark-util-resolve-all@1.1.0: + resolution: + { + integrity: sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==, + } + dependencies: + micromark-util-types: 1.1.0 + dev: false + + /micromark-util-sanitize-uri@1.2.0: + resolution: + { + integrity: sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==, + } + dependencies: + micromark-util-character: 1.2.0 + micromark-util-encode: 1.1.0 + micromark-util-symbol: 1.1.0 + dev: false + + /micromark-util-subtokenize@1.1.0: + resolution: + { + integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==, + } + dependencies: + micromark-util-chunked: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-util-symbol@1.1.0: + resolution: + { + integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==, + } + dev: false + + /micromark-util-types@1.1.0: + resolution: + { + integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==, + } + dev: false + + /micromark@3.2.0: + resolution: + { + integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==, + } + dependencies: + "@types/debug": 4.1.8 + debug: 4.3.4 + decode-named-character-reference: 1.0.2 + micromark-core-commonmark: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-chunked: 1.1.0 + micromark-util-combine-extensions: 1.1.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-encode: 1.1.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-sanitize-uri: 1.2.0 + micromark-util-subtokenize: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + transitivePeerDependencies: + - supports-color + dev: false + /minisearch@6.1.0: resolution: { @@ -1009,6 +1498,21 @@ packages: } dev: true + /mri@1.2.0: + resolution: + { + integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==, + } + engines: { node: ">=4" } + dev: false + + /ms@2.1.2: + resolution: + { + integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==, + } + dev: false + /nanoid@3.3.6: resolution: { @@ -1053,6 +1557,44 @@ packages: hasBin: true dev: true + /remark-parse@10.0.2: + resolution: + { + integrity: sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==, + } + dependencies: + "@types/mdast": 3.0.12 + mdast-util-from-markdown: 1.3.1 + unified: 10.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-stringify@10.0.3: + resolution: + { + integrity: sha512-koyOzCMYoUHudypbj4XpnAKFbkddRMYZHwghnxd7ue5210WzGw6kOBwauJTRUMq16jsovXx8dYNvSSWP89kZ3A==, + } + dependencies: + "@types/mdast": 3.0.12 + mdast-util-to-markdown: 1.5.0 + unified: 10.1.2 + dev: false + + /remark@14.0.3: + resolution: + { + integrity: sha512-bfmJW1dmR2LvaMJuAnE88pZP9DktIFYXazkTfOIKZzi3Knk9lT0roItIA24ydOucI3bV/g/tXBA6hzqq3FV9Ew==, + } + dependencies: + "@types/mdast": 3.0.12 + remark-parse: 10.0.2 + remark-stringify: 10.0.3 + unified: 10.1.2 + transitivePeerDependencies: + - supports-color + dev: false + /rollup@3.27.0: resolution: { @@ -1064,6 +1606,16 @@ packages: fsevents: 2.3.2 dev: true + /sade@1.8.1: + resolution: + { + integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==, + } + engines: { node: ">=6" } + dependencies: + mri: 1.2.0 + dev: false + /search-insights@2.7.0: resolution: { @@ -1133,6 +1685,133 @@ packages: engines: { node: ">=4" } dev: true + /trough@2.1.0: + resolution: + { + integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==, + } + dev: false + + /unified@10.1.2: + resolution: + { + integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==, + } + dependencies: + "@types/unist": 2.0.7 + bail: 2.0.2 + extend: 3.0.2 + is-buffer: 2.0.5 + is-plain-obj: 4.1.0 + trough: 2.1.0 + vfile: 5.3.7 + dev: false + + /unist-util-is@5.2.1: + resolution: + { + integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==, + } + dependencies: + "@types/unist": 2.0.7 + dev: false + + /unist-util-is@6.0.0: + resolution: + { + integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==, + } + dependencies: + "@types/unist": 3.0.0 + dev: false + + /unist-util-stringify-position@3.0.3: + resolution: + { + integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==, + } + dependencies: + "@types/unist": 2.0.7 + dev: false + + /unist-util-visit-parents@5.1.3: + resolution: + { + integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==, + } + dependencies: + "@types/unist": 2.0.7 + unist-util-is: 5.2.1 + dev: false + + /unist-util-visit-parents@6.0.1: + resolution: + { + integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==, + } + dependencies: + "@types/unist": 3.0.0 + unist-util-is: 6.0.0 + dev: false + + /unist-util-visit@4.1.2: + resolution: + { + integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==, + } + dependencies: + "@types/unist": 2.0.7 + unist-util-is: 5.2.1 + unist-util-visit-parents: 5.1.3 + dev: false + + /unist-util-visit@5.0.0: + resolution: + { + integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==, + } + dependencies: + "@types/unist": 3.0.0 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + dev: false + + /uvu@0.5.6: + resolution: + { + integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==, + } + engines: { node: ">=8" } + hasBin: true + dependencies: + dequal: 2.0.3 + diff: 5.1.0 + kleur: 4.1.5 + sade: 1.8.1 + dev: false + + /vfile-message@3.1.4: + resolution: + { + integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==, + } + dependencies: + "@types/unist": 2.0.7 + unist-util-stringify-position: 3.0.3 + dev: false + + /vfile@5.3.7: + resolution: + { + integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==, + } + dependencies: + "@types/unist": 2.0.7 + is-buffer: 2.0.5 + unist-util-stringify-position: 3.0.3 + vfile-message: 3.1.4 + dev: false + /vite@4.4.7(@types/node@20.4.5): resolution: { @@ -1263,3 +1942,10 @@ packages: "@vue/server-renderer": 3.3.4(vue@3.3.4) "@vue/shared": 3.3.4 dev: true + + /zwitch@2.0.4: + resolution: + { + integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==, + } + dev: false diff --git a/shared.ts b/shared.ts new file mode 100644 index 0000000..f7f90e1 --- /dev/null +++ b/shared.ts @@ -0,0 +1,78 @@ +// @ts-nocheck + +import { toc } from "mdast-util-toc"; +import { remark } from "remark"; +import { visit } from "unist-util-visit"; + +const textTypes = ["text", "emphasis", "strong", "inlineCode"]; + +function flattenNode(node) { + const p = []; + visit(node, (node) => { + if (!textTypes.includes(node.type)) return; + p.push(node.value); + }); + return p.join(``); +} + +interface Item { + title: string; + url: string; + items?: Item[]; +} + +export interface Items { + items?: Item[]; +} + +function getItems(node, current): Items { + if (!node) { + return {}; + } + + if (node.type === "paragraph") { + visit(node, (item) => { + if (item.type === "link") { + current.url = item.url; + current.title = flattenNode(node); + } + + if (item.type === "text") { + current.title = flattenNode(node); + } + }); + + return current; + } + + if (node.type === "list") { + current.items = node.children.map((i) => getItems(i, {})); + + return current; + } else if (node.type === "listItem") { + const heading = getItems(node.children[0], {}); + + if (node.children.length > 1) { + getItems(node.children[1], heading); + } + + return heading; + } + + return {}; +} + +const getToc = () => (node, file) => { + const table = toc(node); + file.data = getItems(table.map, {}); +}; + +export type TableOfContents = Items; + +export async function getTableOfContents( + content: string, +): Promise { + const result = await remark().use(getToc).process(content); + + return result.data; +} diff --git a/test.ts b/test.ts new file mode 100644 index 0000000..890c53b --- /dev/null +++ b/test.ts @@ -0,0 +1,14 @@ +import fs from "fs"; +import path from "path"; +import { getTableOfContents } from "./shared"; +function saveFile() { + return new Promise((rslv, rjct) => { + getTableOfContents( + fs.readFileSync("./docs/wiki/emulation.md", "utf8"), + ).then((foo) => { + console.log(JSON.stringify(foo, null, 2)); + }); + }); +} + +saveFile();