Changes
20 changed files (+458/-59)
-
-
@@ -24,6 +24,7 @@getAssetToken(path: readonly string[]): AssetToken | Promise<AssetToken>; getDocumentToken( path: readonly string[], fragments?: readonly string[], ): DocumentToken | Promise<DocumentToken>; }
-
-
-
@@ -91,6 +91,13 @@ return node;} } }), getHash(fragments) { const n = fileReader.path.join(SEPARATOR); throw new Error( `You can't reference part of JSONCanvas via hash syntax.` + `Requested ${n} # ${fragments.join(" > ")}`, ); }, }; } }
-
-
-
@@ -13,6 +13,9 @@ async parse(): Promise<NullDocument> {return { kind: "null", content: null, getHash() { throw new Error("Unreachable"); }, }; }, };
-
-
-
@@ -2,7 +2,10 @@ // SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com>// // SPDX-License-Identifier: Apache-2.0 import { assertObjectMatch } from "../deps/deno.land/std/assert/mod.ts"; import { assertEquals, assertObjectMatch, } from "../deps/deno.land/std/assert/mod.ts"; import { MemoryFsReader } from "../filesystem_reader/memory_fs.ts"; import { ObsidianMarkdownParser } from "./obsidian_markdown.ts";
-
@@ -203,3 +206,38 @@ isDefaultDocument: true,}, }); }); Deno.test("Should resolve nested hash", async () => { const fs = new MemoryFsReader([ { path: "Test.md", content: ` # H1 ## H2 ### H3 `, }, ]); const fileReader = (await (fs.getRootDirectory().then((dir) => dir.read()).then((entries) => entries[0] ))) as FileReader; const parser = new ObsidianMarkdownParser(); const content = await parser.parse({ documentMetadata: { title: "Test", name: "Test", }, fileReader, getAssetToken, getDocumentToken, }); const c = "documentContent" in content ? content.documentContent : content; const hash = c.getHash(["H1", "H2", "H3"]); assertEquals(hash, "H3"); });
-
-
-
@@ -6,11 +6,14 @@ import { test as testFrontmatter } from "../deps/deno.land/std/front_matter/test.ts";import * as yamlFrontmatter from "../deps/deno.land/std/front_matter/yaml.ts"; import type * as Mdast from "../deps/esm.sh/mdast/types.ts"; import { fromMarkdown } from "../deps/esm.sh/mdast-util-from-markdown/mod.ts"; import { toString } from "../deps/esm.sh/mdast-util-to-string/mod.ts"; import { headingRange } from "../deps/esm.sh/mdast-util-heading-range/mod.ts"; import { ofm } from "./obsidian_markdown/micromark_extension_ofm.ts"; import { ofmFromMarkdown } from "./obsidian_markdown/mdast_util_ofm.ts"; import { macanaMarkAssets } from "./obsidian_markdown/mdast_util_macana_mark_assets.ts"; import { macanaMarkDocumentToken } from "./obsidian_markdown/mdast_util_macana_mark_document_token.ts"; import { autoHeadingIdFromMarkdown } from "./obsidian_markdown/mdast_util_auto_heading_id.ts"; import type { ContentParser,
-
@@ -96,7 +99,7 @@ >,): Promise<Mdast.Root> { const mdast = fromMarkdown(markdown, { extensions: [ofm()], mdastExtensions: [ofmFromMarkdown()], mdastExtensions: [ofmFromMarkdown(), autoHeadingIdFromMarkdown()], }); await macanaMarkAssets(mdast, getAssetToken);
-
@@ -105,6 +108,81 @@return mdast; } function findNodeId( root: Mdast.Root, selectors: readonly string[], ): string | null { if (!selectors.length) { return null; } const [selector, ...rest] = selectors; const text = toString(fromMarkdown(selector, { extensions: [ofm()], mdastExtensions: [ofmFromMarkdown()], })); let found: string | null = null; headingRange( root, (textContent) => textContent === text, (start, nodes) => { if (rest.length) { found = findNodeId({ type: "root", children: nodes }, rest); return; } if ( !start.data || !("hProperties" in start.data) || typeof start.data.hProperties !== "object" || !start.data.hProperties || !("id" in start.data.hProperties) || typeof start.data.hProperties.id !== "string" ) { return; } found = start.data.hProperties.id; return; }, ); return found; } async function ok( markdown: string | Uint8Array, { fileReader, getDocumentToken, getAssetToken }: Pick< ParseParameters, "getAssetToken" | "getDocumentToken" | "fileReader" >, ): Promise<ObsidianMarkdownDocument> { const mdast = await parseMarkdown(markdown, { getDocumentToken, getAssetToken, }); return { kind: "obsidian_markdown", content: mdast, getHash(selectors) { const id = findNodeId(mdast, selectors); if (!id) { const filepath = fileReader.path.join("/"); throw new Error( `${filepath} does not contain heading or custom block matching "${ selectors.join(" > ") }".`, ); } return id; }, }; } export class ObsidianMarkdownParser implements ContentParser<ObsidianMarkdownDocument> { #frontmatter: boolean;
-
@@ -120,24 +198,12 @@ ): Promise<ContentParseResult<ObsidianMarkdownDocument>> {const bytes = await fileReader.read(); if (!this.#frontmatter) { return { kind: "obsidian_markdown", content: await parseMarkdown(bytes, { getDocumentToken, getAssetToken, }), }; return ok(bytes, { getDocumentToken, getAssetToken, fileReader }); } const decoded = new TextDecoder().decode(bytes); if (!testFrontmatter(decoded)) { return { kind: "obsidian_markdown", content: await parseMarkdown(bytes, { getDocumentToken, getAssetToken, }), }; return ok(bytes, { getDocumentToken, getAssetToken, fileReader }); } const frontmatter = yamlFrontmatter.extract(decoded);
-
@@ -158,13 +224,11 @@ language: lang || documentMetadata.language,createdAt: createdAt || documentMetadata.createdAt, updatedAt: updatedAt || documentMetadata.updatedAt, }, documentContent: { kind: "obsidian_markdown", content: await parseMarkdown(frontmatter.body, { getAssetToken, getDocumentToken, }), }, documentContent: await ok(frontmatter.body, { getDocumentToken, getAssetToken, fileReader, }), }; } }
-
-
-
@@ -0,0 +1,110 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // // SPDX-License-Identifier: Apache-2.0 import { assertObjectMatch } from "../../deps/deno.land/std/assert/mod.ts"; import type * as Mdast from "../../deps/esm.sh/mdast/types.ts"; import { fromMarkdown } from "../../deps/esm.sh/mdast-util-from-markdown/mod.ts"; import { toHast } from "../../deps/esm.sh/mdast-util-to-hast/mod.ts"; import { autoHeadingId, autoHeadingIdFromMarkdown, } from "./mdast_util_auto_heading_id.ts"; Deno.test("Should set ID to heading", () => { const hast = toHast(fromMarkdown("# Foo `Bar` Baz", { mdastExtensions: [autoHeadingIdFromMarkdown()], })); assertObjectMatch(hast, { type: "root", children: [ { type: "element", tagName: "h1", properties: { id: "Foo-Bar-Baz", }, }, ], }); }); Deno.test("Should not set ID if there is already one", () => { const mdast: Mdast.Root = { type: "root", children: [ { type: "heading", depth: 1, data: { hProperties: { id: "Bar", }, }, children: [{ type: "text", value: "Foo", }], }, ], }; autoHeadingId(mdast); const hast = toHast(mdast); assertObjectMatch(hast, { type: "root", children: [ { type: "element", tagName: "h1", properties: { id: "Bar", }, }, ], }); }); Deno.test("Should avoid setting duplicated ID", () => { const hast = toHast(fromMarkdown("# Foo\n## Foo\n### Foo", { mdastExtensions: [autoHeadingIdFromMarkdown()], })); assertObjectMatch(hast, { type: "root", children: [ { type: "element", tagName: "h1", properties: { id: "Foo", }, }, { type: "text", }, { type: "element", tagName: "h2", properties: { id: "Foo__1", }, }, { type: "text", }, { type: "element", tagName: "h3", properties: { id: "Foo__2", }, }, ], }); });
-
-
-
@@ -0,0 +1,61 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // // SPDX-License-Identifier: Apache-2.0 import type * as Mdast from "../../deps/esm.sh/mdast/types.ts"; import type { Extension } from "../../deps/esm.sh/mdast-util-from-markdown/mod.ts"; import { SKIP, visit } from "../../deps/esm.sh/unist-util-visit/mod.ts"; import { toString } from "../../deps/esm.sh/mdast-util-to-string/mod.ts"; import { fastUslug } from "../../deps/esm.sh/@shelf/fast-uslug/mod.ts"; function hasHProperties( data: Mdast.Data | undefined, ): data is Mdast.Data & { hProperties: Record<string, unknown> } { return !!(data && "hProperties" in data && typeof data.hProperties === "object" && data.hProperties); } /** * This function mutates the given node tree. */ export function autoHeadingId(nodes: Mdast.Nodes): void { const counts = new Map<string, number>(); visit(nodes, (node) => node.type === "heading", (node) => { if (node.type !== "heading") { return SKIP; } if (hasHProperties(node.data) && node.data.hProperties.id) { return SKIP; } const id = fastUslug(toString(node), { lower: false, }); const count = counts.get(id) ?? 0; counts.set(id, count + 1); const finalId = count > 0 ? id + "__" + count : id; node.data = { ...node.data, hProperties: { ...(node.data && "hProperties" in node.data && typeof node.data.hProperties === "object" ? node.data.hProperties : {}), id: finalId, }, }; }); } export function autoHeadingIdFromMarkdown(): Extension { return { transforms: [(nodes) => { autoHeadingId(nodes); }], }; }
-
-
-
@@ -14,8 +14,10 @@ import { macanaMarkDocumentToken } from "./mdast_util_macana_mark_document_token.ts";import { ofmWikilinkFromMarkdown } from "./mdast_util_ofm_wikilink.ts"; import { ofmWikilink } from "./micromark_extension_ofm_wikilink.ts"; const getDocumentToken = (path: readonly string[]) => `mxt_${path.join("/")}` as const; const getDocumentToken = ( path: readonly string[], fragments: readonly string[], ) => `mxt_${path.join("/")}${fragments.map((s) => "&" + s).join("")}` as const; function toMdast(markdown: string) { return fromMarkdown(markdown, {
-
@@ -100,3 +102,26 @@ },], }); }); Deno.test("Should parse hash part", async () => { const mdast = toMdast("[[My note#Heading 1#Heading 2]]"); await macanaMarkDocumentToken(mdast, getDocumentToken); assertObjectMatch(mdast, { type: "root", children: [ { type: "paragraph", children: [ { type: "ofmWikilink", data: { macanaDocumentToken: "mxt_My note&Heading 1&Heading 2", }, }, ], }, ], }); });
-
-
-
@@ -12,12 +12,24 @@import type { OfmWikilink } from "./mdast_util_ofm_wikilink.ts"; const SEPARATOR = "/"; const FRAGMENT_PREFIX = "#"; const IGNORE_REGEXP_PATTERN = /^([a-z0-9]+:\/\/|#)/i; function setDocumentToken(node: Mdast.Node, token: DocumentToken): void { node.data ??= {}; // @ts-expect-error: incorrect library type definition. node.data.macanaDocumentToken = token; } function parseInternalLink( link: string, ): { path: readonly string[]; fragments: readonly string[] } { const [ref, ...fragments] = link.split(FRAGMENT_PREFIX); return { path: (ref || "").split(SEPARATOR), fragments: fragments, }; } /**
-
@@ -42,9 +54,9 @@ node.type === "ofmWikilink",(node) => { switch (node.type) { case "ofmWikilink": { const path = node.target.split(SEPARATOR); const { path, fragments } = parseInternalLink(node.target); const token = getDocumentToken(path); const token = getDocumentToken(path, fragments); if (token instanceof Promise) { promises.push(token.then((t) => {
-
@@ -61,9 +73,9 @@ if (IGNORE_REGEXP_PATTERN.test(node.url)) {return SKIP; } const path = node.url.split(SEPARATOR); const { path, fragments } = parseInternalLink(node.url); const token = getDocumentToken(path); const token = getDocumentToken(path, fragments); if (token instanceof Promise) { promises.push(token.then((t) => {
-
@@ -85,9 +97,9 @@ if (IGNORE_REGEXP_PATTERN.test(def.url)) {return SKIP; } const path = def.url.split(SEPARATOR); const { path, fragments } = parseInternalLink(def.url); const token = getDocumentToken(path); const token = getDocumentToken(path, fragments); if (token instanceof Promise) { promises.push(token.then((t) => {
-
-
-
@@ -33,6 +33,9 @@return { kind: x, content: x, getHash() { unreachable(); }, }; }, };
-
-
-
@@ -231,6 +231,7 @@ "https://esm.sh/v135/is-decimal@2.0.1/denonext/is-decimal.mjs": "d58375f587816fc947898747f8e6986158dec29151c185e7a510641b17668e46","https://esm.sh/v135/is-hexadecimal@2.0.1/denonext/is-hexadecimal.mjs": "7e5d0abd99e5d66839f55c05df59e144465bfa47ce974815557481d53d6fd919", "https://esm.sh/v135/katex@0.16.10/denonext/katex.mjs": "caf72dc45c0951b7c0a6602f5e49e990119bde2e4819b1f7ed137a4111c94e5f", "https://esm.sh/v135/katex@0.16.9/denonext/katex.mjs": "75be3261500b25dca3df7a2dbcd2454fe9924242f2ad348fb5f875643e39c186", "https://esm.sh/v135/lodash.iteratee@4.7.0/denonext/lodash.iteratee.mjs": "d723ebd632080fab16fda997acacd457095f3fbe95c05237b8ef39c6353ba8c6", "https://esm.sh/v135/longest-streak@3.1.0/denonext/longest-streak.mjs": "97b1d8c42d407e285971fea218d89a0404270c3b841a26ec62b83f62450ad573", "https://esm.sh/v135/markdown-table@3.0.3/denonext/markdown-table.mjs": "1dd9cb2d2d95fc440cc10489ac77bf979c944e76070997d962e05f627f45df0e", "https://esm.sh/v135/mdast-util-definitions@6.0.0": "b335a17ac86505677a62667dd26fecddb8e94a8629c3193220655ccfd6c50081",
-
@@ -245,12 +246,15 @@ "https://esm.sh/v135/mdast-util-gfm-table@2.0.0/denonext/mdast-util-gfm-table.mjs": "03566441d8a21a76264c54db7f47de32a231296a8774e155d3de9e0a63468638","https://esm.sh/v135/mdast-util-gfm-task-list-item@2.0.0/denonext/mdast-util-gfm-task-list-item.mjs": "a2542fbdb27957f27c170055b85feda34b48d38884afe7f565713f3cc2503301", "https://esm.sh/v135/mdast-util-gfm@3.0.0": "0bef9ce3d7db5662f2a43ba8c34586323d295eb9bde1db802ad9015ceb3c843e", "https://esm.sh/v135/mdast-util-gfm@3.0.0/denonext/mdast-util-gfm.mjs": "0a06fd1def4aadb5defc7f631f6c1d23f8598d57233cba19d4618229db70b10a", "https://esm.sh/v135/mdast-util-heading-range@4.0.0": "49365a1ac680910c25afe07bfdcd8e8a87420df2c90861c2653520c35a0993c6", "https://esm.sh/v135/mdast-util-heading-range@4.0.0/denonext/mdast-util-heading-range.mjs": "8ac8b658d4291906998e00e3184034de87c68e59eb91110cf472b9f53cdf433e", "https://esm.sh/v135/mdast-util-math@3.0.0": "d2479bf44348aaf25af1254ec06cf939b5351a8a5de4ded75d2250b8e53911d0", "https://esm.sh/v135/mdast-util-math@3.0.0/denonext/mdast-util-math.mjs": "1ad4d48cda514289bbda9ace4f2b8af3f7e246f3df3f1b4ab802638919dfd0bf", "https://esm.sh/v135/mdast-util-phrasing@4.0.0/denonext/mdast-util-phrasing.mjs": "ed30057d1949bdde664291eaa5e11ea8c765f573a5c38eba60b099ffd3612f42", "https://esm.sh/v135/mdast-util-to-hast@13.1.0": "3a712fec5d7f4696ec135556925c8c2f7480b21dc39bd96077550d06220d2ba8", "https://esm.sh/v135/mdast-util-to-hast@13.1.0/denonext/mdast-util-to-hast.mjs": "e6ab97ff3f6c94f6c7ccaba485dac8a4fdd5edae1b311ae295b409b462ff5001", "https://esm.sh/v135/mdast-util-to-markdown@2.1.0/denonext/mdast-util-to-markdown.mjs": "45752d146270661e71f91869eba6f6c434b3f564a005542d0e5dbebc8734e45e", "https://esm.sh/v135/mdast-util-to-string@4.0.0": "862af443c8e1834817e59700625f5571ffef65c0441bc998bfc10f0a5f24e45e", "https://esm.sh/v135/mdast-util-to-string@4.0.0/denonext/mdast-util-to-string.mjs": "eda9725fc0c7dc0e7b56998d2d8e4f29312cc5493cb7834c70f32fab2609103b", "https://esm.sh/v135/micromark-core-commonmark@2.0.0/denonext/micromark-core-commonmark.mjs": "29686a813f2fa7fc1801c9c6142f71e32e605e6cf8bb8a9afeab78c814f0216c", "https://esm.sh/v135/micromark-extension-gfm-autolink-literal@2.0.0/denonext/micromark-extension-gfm-autolink-literal.mjs": "3fee7a2d71d4a3ae46f0a7eeea45fb171e32e70a84d79dbe4602d0aad3ac6e51",
-
@@ -604,6 +608,8 @@ "https://esm.sh/v135/temml@0.10.24/denonext/dist/temml.js": "afbf78726dea9ca3a016f1fa69db100535f4ad819bc2c637be4f304d9ffb6551","https://esm.sh/v135/temml@0.10.24/denonext/temml.mjs": "bfe9e77bf34fe3ed54c31e2662e632c54f53b576a53efc9b60d57bbe9ccd830b", "https://esm.sh/v135/temml@0.10.24/dist/temml.mjs": "ee16ff1f4c69b9df8ada84d5800536f3ab620098918b8100262df773f248b509", "https://esm.sh/v135/trim-lines@3.0.1/denonext/trim-lines.mjs": "f01a20253341eb2554f307ab05bc9cd93d6f33bcbb24fde2fc9fcd857564283e", "https://esm.sh/v135/unist-util-find@3.0.0": "6dca4026bd2aaeb2cf49846a5e6a39b37308e8d7a132b1aef128b6fe6d827f9f", "https://esm.sh/v135/unist-util-find@3.0.0/denonext/unist-util-find.mjs": "90382cb0c4e4dfde6f1d4b03574ad4a23e7fe5863980edbd0aa44a8c5c1d5d2e", "https://esm.sh/v135/unist-util-is@6.0.0/denonext/unist-util-is.mjs": "d92da46b3a1084450f150cc06c02f3bf85b93ab4c4b43a960d72a4f5678e95cc", "https://esm.sh/v135/unist-util-position@5.0.0/denonext/unist-util-position.mjs": "aaef05774a54f2b84400e98325219e2ba6cf966e318173bcd895647c56bb8871", "https://esm.sh/v135/unist-util-remove@4.0.0": "b4e11a095e2758fea44136dca7ecd2cf45814e715a1a1d99187119361d7408d4",
-
-
-
@@ -0,0 +1,5 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // // SPDX-License-Identifier: Apache-2.0 export * from "https://esm.sh/v135/mdast-util-heading-range@4.0.0";
-
-
-
@@ -0,0 +1,5 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // // SPDX-License-Identifier: Apache-2.0 export * from "https://esm.sh/v135/mdast-util-to-string@4.0.0";
-
-
-
@@ -0,0 +1,5 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // // SPDX-License-Identifier: Apache-2.0 export * from "https://esm.sh/v135/unist-util-find@3.0.0";
-
-
-
@@ -20,10 +20,12 @@```markdown - [[Overview|Alternative Title]] - [[Overview]] - [[Overview#Arbitrary document tree]] ``` - [[Overview|Alternative Title]] - [[Overview]] - [[Overview#Arbitrary document tree]] ### Image size attributes
-
-
-
@@ -45,7 +45,7 @@ - [x] Relative path to file (extension-less)- [x] Shortest path when possible - [x] Wikilink - [x] Label - [ ] Heading - [x] Heading - [ ] Block reference - [ ] Defining a block - [x] Image size annotation
-
-
-
@@ -278,13 +278,19 @@await macanaReplaceDocumentToken( node.text, async (token) => { const document = tree.exchangeToken(token); const { document, fragments } = tree.exchangeToken( token, ); const hash = fragments.length > 0 ? "#" + document.content.getHash(fragments) : ""; return { path: toRelativePathString( [...document.path, ""], item.path, ), ) + hash, }; }, );
-
@@ -309,14 +315,20 @@ };} if (isDocumentToken(node.file)) { const doc = tree.exchangeToken(node.file); const { document, fragments } = tree.exchangeToken( node.file, ); const hash = fragments.length > 0 ? "#" + document.content.getHash(fragments) : ""; return { ...node, file: toRelativePathString( [...doc.path, "embed.html"], [...document.path, "embed.html"], item.path, ), ) + hash, }; }
-
@@ -374,10 +386,16 @@await macanaReplaceDocumentToken( item.content.content, async (token) => { const document = tree.exchangeToken(token); const { document, fragments } = tree.exchangeToken(token); const hash = fragments.length > 0 ? "#" + document.content.getHash(fragments) : ""; return { path: toRelativePathString([...document.path, ""], item.path), path: toRelativePathString([...document.path, ""], item.path) + hash, }; }, );
-
-
-
@@ -7,6 +7,7 @@ assertEquals,assertNotEquals, assertObjectMatch, assertRejects, unreachable, } from "../deps/deno.land/std/assert/mod.ts"; import { MemoryFsReader } from "../filesystem_reader/memory_fs.ts";
-
@@ -37,6 +38,9 @@return { kind: "testing", content: null, getHash() { unreachable(); }, }; }, };
-
@@ -109,6 +113,9 @@ return {documentContent: { kind: "null", content: null, getHash() { unreachable(); }, }, documentMetadata: { title: "Brown fox",
-
@@ -275,7 +282,7 @@// `as` is required as Deno's assertion function does not return `a is B`. const found = tree.exchangeToken(contentParser.token as DocumentToken); assertObjectMatch(found, { assertObjectMatch(found.document, { path: ["Qux.md"], }); });
-
@@ -305,7 +312,7 @@// `as` is required as Deno's assertion function does not return `a is B`. const found = tree.exchangeToken(contentParser.token as DocumentToken); assertObjectMatch(found, { assertObjectMatch(found.document, { path: ["Qux.md"], }); });
-
@@ -335,7 +342,7 @@// `as` is required as Deno's assertion function does not return `a is B`. const found = tree.exchangeToken(contentParser.token as DocumentToken); assertObjectMatch(found, { assertObjectMatch(found.document, { path: ["Qux.md"], }); });
-
@@ -365,7 +372,7 @@// `as` is required as Deno's assertion function does not return `a is B`. const found = tree.exchangeToken(contentParser.token as DocumentToken); assertObjectMatch(found, { assertObjectMatch(found.document, { path: ["Qux.md"], }); });
-
@@ -396,7 +403,7 @@// `as` is required as Deno's assertion function does not return `a is B`. const found = tree.exchangeToken(contentParser.token as DocumentToken); assertObjectMatch(found, { assertObjectMatch(found.document, { path: ["Qux.md"], }); });
-
@@ -427,7 +434,7 @@// `as` is required as Deno's assertion function does not return `a is B`. const found = tree.exchangeToken(contentParser.token as DocumentToken); assertObjectMatch(found, { assertObjectMatch(found.document, { path: ["Foo", "Bar", "Baz.md"], }); });
-
-
-
@@ -355,6 +355,11 @@ return found[0].path;}); } interface DocumentTokenReference { internalPath: string; fragments: readonly string[]; } interface InternalBuildParameters { contentParser: BuildParameters["contentParser"];
-
@@ -363,7 +368,7 @@parentPath?: readonly string[]; assetTokensToFiles: Map<AssetToken, FileReader>; documentTokenToPaths: Map<DocumentToken, string>; documentTokenToReferences: Map<DocumentToken, DocumentTokenReference>; pathToDocuments: Map<string, Document>; }
-
@@ -441,7 +446,10 @@ const start = performance.now();const root = await fileSystemReader.getRootDirectory(); const assetTokensToFiles = new Map<AssetToken, FileReader>(); const documentTokenToPaths = new Map<DocumentToken, string>(); const documentTokenToReferences = new Map< DocumentToken, DocumentTokenReference >(); const pathToDocuments = new Map<string, Document>(); const children = await root.read();
-
@@ -452,7 +460,7 @@ this.#build(child, {contentParser, root, assetTokensToFiles, documentTokenToPaths, documentTokenToReferences, pathToDocuments, }) ),
-
@@ -504,21 +512,24 @@ return found;} if (isDocumentToken(token)) { const path = documentTokenToPaths.get(token); if (!path) { const ref = documentTokenToReferences.get(token); if (!ref) { throw new Error( `DefaultTreeBuilder: No document path registered for the Document Token ${token}`, ); } const doc = pathToDocuments.get(path); const doc = pathToDocuments.get(ref.internalPath); if (!doc) { throw new Error( `DefaultTreeBuilder: No document at the path ${path}, referenced by token ${token}`, `DefaultTreeBuilder: No document at the path ${ref.internalPath}, referenced by token ${token}`, ); } return doc; return { document: doc, fragments: ref.fragments, }; } throw new Error(`DefaultTreeBuilder: Invalid token type: ${token}`);
-
@@ -532,7 +543,7 @@ {contentParser, root, assetTokensToFiles, documentTokenToPaths, documentTokenToReferences, pathToDocuments, parentPath = [], }: InternalBuildParameters,
-
@@ -602,7 +613,7 @@ );return token; }, getDocumentToken: async (path) => { getDocumentToken: async (path, fragments = []) => { if (!path.length) { throw new Error( `Document link cannot be empty (processing ${
-
@@ -621,9 +632,12 @@ root,resolveFsrPath(path, node.path), ); documentTokenToPaths.set( documentTokenToReferences.set( token, resolvedPath.join(INTERNAL_PATH_SEPARATOR), { internalPath: resolvedPath.join(INTERNAL_PATH_SEPARATOR), fragments, }, ); return token;
-
@@ -655,7 +669,7 @@ this.#build(child, {contentParser, root, assetTokensToFiles, documentTokenToPaths, documentTokenToReferences, pathToDocuments, parentPath: [ ...parentPath,
-
-
-
@@ -97,7 +97,17 @@ Kind extends string = string,Content = unknown, > { kind: Kind; content: Content; /** * Returns hash part of the URL matchin to the selectors. * Format of selector differs by content types. * * If the document does not have section matching to the selectors, * this function throws an error. */ getHash(selectors: readonly string[]): string; } export interface Document<Content extends DocumentContent = DocumentContent> {
-
@@ -140,7 +150,10 @@ /*** Get a document in exchange for the token. * Throws an error if the token is invalid or target document is missing. */ exchangeToken(token: DocumentToken): Document; exchangeToken(token: DocumentToken): { document: Document; fragments: readonly string[]; }; /** * Get an asset file in exchange for the token.
-