Changes
5 changed files (+99/-15)
-
-
@@ -0,0 +1,19 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // // SPDX-License-Identifier: Apache-2.0 import { assertThrows } from "../deps/deno.land/std/assert/mod.ts"; import { assertDocumentTreeIsValid } from "./assert.ts"; Deno.test("Should throws if locale uses invalid lang subtag format", () => { assertThrows(() => { assertDocumentTreeIsValid({ defaultLocale: "en", locales: new Map([ ["en", []], ["ja_JP", []], ]), }); }); });
-
-
tree_builder/assert.ts (new)
-
@@ -0,0 +1,50 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // // SPDX-License-Identifier: Apache-2.0 import type { Document, DocumentDirectory, DocumentTree } from "./interface.ts"; function fmtDocumentSourceName(node: Document | DocumentDirectory): string { if ("file" in node) { return node.file.path.join("/"); } return node.directory.path.join("/") + "/"; } const LANG_SUBTAG_PATTERN = /^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$/; export function assertDocumentTreeIsValid(tree: DocumentTree): void { for (const [locale, entries] of tree.locales) { // Simple BCP 47 language tag check, based on RFC 4646 (Tags for Identifying Languages) // https://www.rfc-editor.org/rfc/rfc4646.txt if (!(LANG_SUBTAG_PATTERN.test(locale))) { throw new Error(`Invalid BCP 47 language tag, found "${locale}".`); } assertEntryNameIsUnique(entries); } } function assertEntryNameIsUnique( entries: ReadonlyArray<DocumentDirectory | Document>, ): void { entries.forEach((entry, i) => { const firstIndex = entries.findIndex((e) => e.metadata.name === entry.metadata.name ); if (firstIndex !== i) { throw new Error( "You can't have more than one document or directory that have same name: found " + `"${fmtDocumentSourceName(entries[firstIndex])}" and "${ fmtDocumentSourceName(entry) }", ` + "which resulted in same document name.", ); } if ("entries" in entry) { assertEntryNameIsUnique(entry.entries); } }); }
-
-
-
@@ -107,3 +107,16 @@ await assertRejects(() =>builder.build({ fileSystemReader, metadataParser }) ); }); Deno.test("Should abort if name conflicts", async () => { const fileSystemReader = new MemoryFsReader([ { path: "en/Foo Bar/Baz.md", content: "" }, { path: "en/Foo Bar.md", content: "" }, ]); const metadataParser = new VaultParser(); const builder = new MultiLocaleTreeBuilder(); await assertRejects(() => builder.build({ fileSystemReader, metadataParser }) ); });
-
-
-
@@ -15,6 +15,8 @@ DocumentTree,TreeBuilder, } from "./interface.ts"; import { assertDocumentTreeIsValid } from "./assert.ts"; export interface MultiLocaleTreeBuilderConfig { defaultLocale?: string;
-
@@ -56,14 +58,6 @@ );} const locale = node.name; // Simple BCP 47 language tag check, based on RFC 4646 (Tags for Identifying Languages) // https://www.rfc-editor.org/rfc/rfc4646.txt if (!(/^[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*$/.test(locale))) { // TODO: Warning instead? throw new Error(`Invalid BCP 47 language tag, found "${locale}".`); } const children = await node.read(); const entries = await Promise.all( children.map((child) => this.#build(child, metadataParser)),
-
@@ -88,10 +82,14 @@ }).`,); } return { const tree: DocumentTree = { defaultLocale: this.#config.defaultLocale || firstLocale, locales: map, }; assertDocumentTreeIsValid(tree); return tree; } async #build(
-
@@ -121,16 +119,14 @@ }const children = await node.read(); const entries = await Promise.all( const entries = (await Promise.all( children.map((child) => this.#build(child, metadataParser)), ); )).filter((child): child is NonNullable<typeof child> => !!child); return { metadata, directory: node, entries: entries.filter((child): child is NonNullable<typeof child> => !!child ), entries, }; } }
-
-
-
@@ -15,6 +15,8 @@ DocumentTree,TreeBuilder, } from "./interface.ts"; import { assertDocumentTreeIsValid } from "./assert.ts"; export interface SingleLocaleTreeBuilderConfig { /** * Locale string to use.
-
@@ -55,10 +57,14 @@ this.#locale,entries.filter((entry): entry is NonNullable<typeof entry> => !!entry), ); return { const tree: DocumentTree = { locales: map, defaultLocale: this.#locale, }; assertDocumentTreeIsValid(tree); return tree; } async #build(
-