@restless-dreams/orbit 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/bin/orbit.js +2972 -213
- package/dist/bin/orbit.js.map +25 -13
- package/dist/{chunk-mtrnm0yc.js → chunk-fkdfgtx9.js} +3156 -2854
- package/dist/chunk-fkdfgtx9.js.map +75 -0
- package/dist/{chunk-7n00wx0t.js → chunk-y748hzcr.js} +2 -2
- package/dist/{chunk-0gwh723s.js → chunk-zze4tc9n.js} +2 -2
- package/dist/core/branch-colors.d.ts +57 -0
- package/dist/core/document-source.d.ts +1 -1
- package/dist/core/editing.d.ts +8 -5
- package/dist/core/engine/scene.d.ts +5 -4
- package/dist/core/engine/views.d.ts +10 -2
- package/dist/core/index.d.ts +10 -0
- package/dist/core/input-controller.d.ts +7 -0
- package/dist/core/languages.d.ts +2 -0
- package/dist/core/node-attributes.d.ts +1 -1
- package/dist/core/other-apps/freemind.d.ts +8 -0
- package/dist/core/other-apps/icons.d.ts +16 -0
- package/dist/core/other-apps/ideas.d.ts +76 -0
- package/dist/core/other-apps/import.d.ts +28 -0
- package/dist/core/other-apps/inflate.d.ts +22 -0
- package/dist/core/other-apps/markup.d.ts +51 -0
- package/dist/core/other-apps/notes.d.ts +80 -0
- package/dist/core/other-apps/opml.d.ts +26 -0
- package/dist/core/other-apps/reading.d.ts +36 -0
- package/dist/core/other-apps/xmind.d.ts +14 -0
- package/dist/core/other-apps/zip.d.ts +37 -0
- package/dist/core/print-layout.d.ts +70 -0
- package/dist/core/renderer/content-painter.d.ts +30 -0
- package/dist/core/renderer/dom.d.ts +15 -0
- package/dist/core/renderer/families.d.ts +35 -0
- package/dist/core/renderer/label-painter.d.ts +93 -0
- package/dist/core/renderer/node-painter.d.ts +113 -0
- package/dist/core/renderer/numbers.d.ts +2 -0
- package/dist/core/renderer/options.d.ts +12 -0
- package/dist/core/renderer/rings-and-links.d.ts +23 -0
- package/dist/core/renderer/scene-helpers.d.ts +33 -0
- package/dist/core/renderer/trees.d.ts +22 -0
- package/dist/core/svg-renderer.d.ts +6 -109
- package/dist/core/types.d.ts +9 -1
- package/dist/core/web-page/page.d.ts +2 -1
- package/dist/core/web-page/runtime.d.ts +1 -1
- package/dist/index.js +2935 -26
- package/dist/index.js.map +18 -6
- package/dist/marked/index.js +2 -2
- package/dist/react/index.js +2 -2
- package/dist/web-page.js +79 -79
- package/llms-full.txt +205 -5
- package/llms.txt +2 -1
- package/package.json +1 -1
- package/skills/orbit/SKILL.md +1 -1
- package/skills/orbit/references/editing.md +2 -1
- package/skills/orbit/references/format.md +28 -0
- package/skills/orbit/references/guide.md +25 -1
- package/skills/orbit/references/import-export.md +115 -0
- package/skills/orbit/references/languages.md +1 -0
- package/skills/orbit/references/recipes.md +9 -0
- package/skills/orbit/references/theming.md +15 -0
- package/dist/chunk-mtrnm0yc.js.map +0 -63
- /package/dist/{chunk-7n00wx0t.js.map → chunk-y748hzcr.js.map} +0 -0
- /package/dist/{chunk-0gwh723s.js.map → chunk-zze4tc9n.js.map} +0 -0
package/dist/bin/orbit.js.map
CHANGED
|
@@ -1,48 +1,60 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../bin/orbit.ts", "../../src/core/yaml-mini.ts", "../../src/core/utils.ts", "../../src/core/url-guard.ts", "../../src/core/media.ts", "../../src/core/diagnostics.ts", "../../src/core/source.ts", "../../src/core/suggest.ts", "../../src/core/node-attributes.ts", "../../src/core/themes.ts", "../../src/core/document-options.ts", "../../src/core/node-links.ts", "../../src/core/document-source.ts", "../../src/core/format-upgrades.ts", "../../src/core/parser-markdown.ts", "../../src/core/parser-yaml.ts", "../../src/core/dispatch.ts", "../../src/core/markdown-writing.ts", "../../src/core/source-patch.ts", "../../src/core/serializer-markdown.ts", "../../src/core/serializer-yaml.ts", "../../src/core/languages.ts", "../../src/core/ui/detail-sheet.ts", "../../src/core/extensions.ts", "../../src/core/layout.ts", "../../src/core/browser.ts", "../../src/core/engine/camera.ts", "../../src/core/engine/scene.ts", "../../src/core/engine/display.ts", "../../src/core/engine/colors.ts", "../../src/core/text-layout.ts", "../../src/core/engine/text-measure.ts", "../../src/core/engine/views.ts", "../../src/core/engine/labels.ts", "../../src/core/engine/surface-pattern.ts", "../../src/core/engine/export.ts", "../../src/core/render-to-svg.ts", "../../src/core/web-page/page.ts", "../../bin/example.ts"],
|
|
3
|
+
"sources": ["../../bin/orbit.ts", "../../src/core/yaml-mini.ts", "../../src/core/utils.ts", "../../src/core/url-guard.ts", "../../src/core/media.ts", "../../src/core/diagnostics.ts", "../../src/core/source.ts", "../../src/core/branch-colors.ts", "../../src/core/suggest.ts", "../../src/core/node-attributes.ts", "../../src/core/themes.ts", "../../src/core/document-options.ts", "../../src/core/node-links.ts", "../../src/core/document-source.ts", "../../src/core/format-upgrades.ts", "../../src/core/parser-markdown.ts", "../../src/core/parser-yaml.ts", "../../src/core/dispatch.ts", "../../src/core/markdown-writing.ts", "../../src/core/source-patch.ts", "../../src/core/serializer-markdown.ts", "../../src/core/serializer-yaml.ts", "../../src/core/languages.ts", "../../src/core/ui/detail-sheet.ts", "../../src/core/extensions.ts", "../../src/core/layout.ts", "../../src/core/browser.ts", "../../src/core/engine/camera.ts", "../../src/core/engine/scene.ts", "../../src/core/engine/display.ts", "../../src/core/engine/colors.ts", "../../src/core/text-layout.ts", "../../src/core/engine/text-measure.ts", "../../src/core/engine/views.ts", "../../src/core/engine/labels.ts", "../../src/core/engine/surface-pattern.ts", "../../src/core/engine/export.ts", "../../src/core/render-to-svg.ts", "../../src/core/web-page/page.ts", "../../src/core/other-apps/icons.ts", "../../src/core/other-apps/markup.ts", "../../src/core/other-apps/notes.ts", "../../src/core/other-apps/ideas.ts", "../../src/core/other-apps/reading.ts", "../../src/core/other-apps/freemind.ts", "../../src/core/other-apps/opml.ts", "../../src/core/other-apps/inflate.ts", "../../src/core/other-apps/zip.ts", "../../src/core/other-apps/xmind.ts", "../../src/core/other-apps/import.ts", "../../bin/example.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { readFileSync, writeFileSync } from 'node:fs';\nimport { basename, dirname, extname, relative, resolve, sep } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { orbitFlavor, parseOrbit } from '../src/core/dispatch';\nimport { OrbitParseError, type OrbitDiagnostic } from '../src/core/diagnostics';\nimport { serializeOrbitMarkdown } from '../src/core/serializer-markdown';\nimport { serializeOrbitYAML } from '../src/core/serializer-yaml';\nimport { renderToSVGString, MAX_SVG_EXPORT_SIZE } from '../src/core/render-to-svg';\nimport { exportWebPage } from '../src/core/web-page/page';\nimport { isOrbitThemePreset, themeNames } from '../src/core/themes';\nimport { THEME_SYNONYMS } from '../src/core/document-options';\nimport { didYouMean } from '../src/core/suggest';\nimport { OrbitWords } from '../src/core/languages';\nimport type { OrbitNode, OrbitThemePreset, ParsedOrbitDocument } from '../src/core/types';\nimport { parseOrbitYAML } from '../src/core/parser-yaml';\nimport { EXAMPLE_MAP } from './example';\n\nconst USAGE = `orbit: check, render and convert Orbit mind maps\n\nUsage:\n orbit validate [--json] [--loose] [--tree] <file|->\n Check a map and list every problem, with its line\n orbit render [options] <file|-> Render a map to a standalone SVG\n orbit export --html [options] <file|-> One web page with Orbit, the map and its pictures inside,\n to explore it or present it in any browser, offline\n orbit convert --to <md|yaml> <file|-> Convert between the markdown and YAML flavors\n orbit example [--yaml] Print a map with the main features, to copy\n orbit help Show this message (so does --help after any command)\n orbit --version Print the version of Orbit\n\nValidate options:\n --json Print the result as JSON: valid, flavor, root, nodes, depth (the\n levels below the root) and diagnostics\n --loose Exit 0 even when there are problems the map can work around\n --tree Print the map as Orbit reads it, a node a line with its #id\n (with --json, as \"tree\"), to see what became a node and find ids\n\nRender options:\n --out <file> Write the SVG to a file instead of stdout\n --width <px> Width of the drawing (default 1200)\n --height <px> Height of the drawing (default 800)\n --theme <name> paper, night, glass, glass-night, cosmos, blueprint, ink, contrast,\n flat, flat-night, material, material-night, liquid, liquid-night,\n or auto, which draws paper: a picture can't follow the reader's\n light or dark mode (default: the document's, or paper)\n --view <focus|all> focus draws the map as it opens, where only the node at the center\n and its children have labels; all draws the whole map (default:\n the document's, or focus)\n --focus <node-id> The node at the center in focus mode (default: the root)\n --language <tag> The language of the drawing's few words, such as an untitled\n map's name: en or es (default: en)\n\nExport options:\n --out <file> Write the page to a file instead of stdout\n --title <text> The page's title (default: the map's title, or its root's text)\n --theme, --view, --focus, --language\n As for render; the page follows the reader's light or dark mode\n with --theme auto, and speaks the language's words\n\nUse \"-\" as the file to read from stdin. Output goes to stdout; problems go\nto stderr as file:line: severity: message [code].\n\nExit codes: 0 when it worked (for validate, when the map is valid), 1 when the\nmap has problems or can't be read, and 2 for a mistake in the command itself.\n\nThe whole format and API, for people and coding agents: llms-full.txt in this\npackage, or https://cdn.jsdelivr.net/npm/@restless-dreams/orbit/llms-full.txt\n`;\n\n/** This package's version, from its package.json: beside the built command's folder, or the source's. */\nconst packageVersion = (): string => {\n for (const path of ['../package.json', '../../package.json']) {\n try {\n const manifest = JSON.parse(readFileSync(new URL(path, import.meta.url), 'utf8')) as { name?: string; version?: string };\n\n if (manifest.name === '@restless-dreams/orbit' && manifest.version) {\n return manifest.version;\n }\n } catch {\n // Not in this folder: the command runs from the other one.\n }\n }\n\n return 'unknown';\n};\n\n/** Whether a file is YAML by its name, whatever its first lines look like. */\nconst isYamlFile = (file: string): boolean => {\n return /\\.ya?ml$/i.test(file);\n};\n\n/** A map from a file: YAML for .yaml and .yml files, otherwise the flavor its first lines say. */\nconst parseFile = (file: string, source: string, options: { strict?: boolean; untitled?: string } = {}): ParsedOrbitDocument => {\n return isYamlFile(file) ? parseOrbitYAML(source, options) : parseOrbit(source, options);\n};\n\nconst readInput = (path: string): string => {\n return readFileSync(path === '-' ? 0 : path, 'utf8');\n};\n\nexport const runCli = (argv: string[]): number => {\n const [command, ...rest] = argv;\n\n if (command === undefined || command === 'help' || command === '-h' || command === '--help' || rest.includes('--help') || rest.includes('-h')) {\n process.stdout.write(USAGE);\n return command === undefined ? 2 : 0;\n }\n\n if (command === '--version' || command === '-v' || command === 'version') {\n process.stdout.write(`${packageVersion()}\\n`);\n return 0;\n }\n\n try {\n if (command === 'convert') {\n let to = '';\n let file = '';\n\n for (let i = 0; i < rest.length; i++) {\n if (rest[i] === '--to' || rest[i] === '-t') {\n to = rest[++i] ?? '';\n }\n else if (rest[i].startsWith('-') && rest[i] !== '-') {\n process.stderr.write(`orbit convert: unknown option ${rest[i]}\\n${USAGE}`);\n return 2;\n }\n else {\n file = rest[i];\n }\n }\n\n if (!file || !/^(md|markdown|yaml|yml)$/.test(to)) {\n process.stderr.write(`orbit convert: expected --to <md|yaml> <file|->\\n${USAGE}`);\n return 2;\n }\n\n const doc = parseFile(file, readInput(file));\n printDiagnostics(file, doc.diagnostics ?? []);\n process.stdout.write(/^(md|markdown)$/.test(to) ? serializeOrbitMarkdown(doc, { keepSource: false }) : serializeOrbitYAML(doc));\n return 0;\n }\n\n if (command === 'example') {\n const yaml = rest.includes('--yaml');\n\n if (rest.some((argument) => argument !== '--yaml')) {\n process.stderr.write(`orbit example: the only option is --yaml\\n${USAGE}`);\n return 2;\n }\n\n process.stdout.write(yaml ? serializeOrbitYAML(parseOrbit(EXAMPLE_MAP)) : EXAMPLE_MAP);\n return 0;\n }\n\n if (command === 'export') {\n return exportCommand(rest);\n }\n\n if (command === 'render') {\n return renderCommand(rest);\n }\n\n if (command === 'validate') {\n return validateCommand(rest);\n }\n\n process.stderr.write(`orbit: unknown command \"${command}\"\\n${USAGE}`);\n return 2;\n } catch (err) {\n process.stderr.write(`error: ${(err as Error).message}\\n`);\n return 1;\n }\n};\n\n/** A command's `--name value` options among `names`, and its one file; or the exit code for a mistake in them. */\nconst readOptions = (command: string, argumentsList: string[], names: string[]): { values: Record<string, string>; file: string } | number => {\n const values: Record<string, string> = {};\n let file = '';\n\n for (let index = 0; index < argumentsList.length; index++) {\n const argument = argumentsList[index];\n const name = argument.startsWith('--') ? argument.slice(2) : '';\n\n if (names.includes(name)) {\n const value = argumentsList[++index];\n\n if (value === undefined) {\n process.stderr.write(`orbit ${command}: ${argument} needs a value\\n`);\n return 2;\n }\n\n values[name] = value;\n } else if (argument === '-' || !argument.startsWith('--')) {\n file = argument;\n } else {\n process.stderr.write(`orbit ${command}: unknown option ${argument}\\n${USAGE}`);\n return 2;\n }\n }\n\n if (!file) {\n process.stderr.write(`orbit ${command}: missing <file>\\n${USAGE}`);\n return 2;\n }\n\n return { values, file };\n};\n\n/** The exit code for a --theme or --view that isn't one, or null when they're fine. */\nconst checkLook = (command: string, values: Record<string, string>): number | null => {\n if (values.theme !== undefined && !isOrbitThemePreset(values.theme)) {\n process.stderr.write(`orbit ${command}: unknown theme \"${values.theme}\". Themes: ${themeNames().join(', ')}.${didYouMean(values.theme, themeNames(), THEME_SYNONYMS)}\\n`);\n return 2;\n }\n\n if (values.view !== undefined && values.view !== 'focus' && values.view !== 'all') {\n process.stderr.write(`orbit ${command}: --view must be focus or all\\n`);\n return 2;\n }\n\n return null;\n};\n\n/** The exit code for a --focus no node of the map has, or null when it's fine. */\nconst checkFocus = (command: string, values: Record<string, string>, doc: ParsedOrbitDocument): number | null => {\n if (values.focus !== undefined) {\n const ids = nodeIds(doc.root);\n\n if (!ids.includes(values.focus)) {\n process.stderr.write(`orbit ${command}: no node has the id \"${values.focus}\".${didYouMean(values.focus, ids)} Ids come from the nodes' text: \"Q3 plan\" is q3-plan.\\n`);\n return 2;\n }\n }\n\n return null;\n};\n\nconst renderCommand = (argumentsList: string[]): number => {\n const read = readOptions('render', argumentsList, ['out', 'width', 'height', 'theme', 'view', 'focus', 'language']);\n\n if (typeof read === 'number') {\n return read;\n }\n\n const { values, file } = read;\n const width = values.width === undefined ? 1200 : Number(values.width);\n const height = values.height === undefined ? 800 : Number(values.height);\n\n if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0 || width > MAX_SVG_EXPORT_SIZE || height > MAX_SVG_EXPORT_SIZE) {\n process.stderr.write(`orbit render: --width and --height must be positive numbers no larger than ${MAX_SVG_EXPORT_SIZE}\\n`);\n return 2;\n }\n\n const look = checkLook('render', values);\n\n if (look !== null) {\n return look;\n }\n\n const words = new OrbitWords(values.language);\n const doc = parseFile(file, readInput(file), { untitled: words.text('untitledMap') });\n printDiagnostics(file, doc.diagnostics);\n const focus = checkFocus('render', values, doc);\n\n if (focus !== null) {\n return focus;\n }\n\n const svg = renderToSVGString(doc, {\n width,\n height,\n language: values.language,\n theme: values.theme as OrbitThemePreset | undefined,\n viewMode: values.view as 'focus' | 'all' | undefined,\n focus: values.focus,\n // Relative images are next to the map file, unless the document says otherwise.\n baseUrl: baseUrlFor(doc.options.baseUrl, file),\n });\n // Pictures on this computer are linked from where the SVG goes, so it can move with them.\n const portable = relativeFileLinks(svg, values.out ? resolve(dirname(values.out)) : process.cwd());\n\n if (values.out) {\n writeFileSync(values.out, portable + '\\n');\n } else {\n process.stdout.write(portable + '\\n');\n }\n\n return 0;\n};\n\nconst exportCommand = (argumentsList: string[]): number => {\n if (!argumentsList.includes('--html')) {\n process.stderr.write(`orbit export: say what to export the map as: --html, one web page with the map inside\\n${USAGE}`);\n return 2;\n }\n\n const read = readOptions('export', argumentsList.filter((argument) => argument !== '--html'), ['out', 'title', 'theme', 'view', 'focus', 'language']);\n\n if (typeof read === 'number') {\n return read;\n }\n\n const { values, file } = read;\n const look = checkLook('export', values);\n\n if (look !== null) {\n return look;\n }\n\n const words = new OrbitWords(values.language);\n const source = readInput(file);\n const doc = parseFile(file, source, { untitled: words.text('untitledMap') });\n printDiagnostics(file, doc.diagnostics);\n const focus = checkFocus('export', values, doc);\n\n if (focus !== null) {\n return focus;\n }\n\n const script = webPageScript();\n\n if (script === null) {\n process.stderr.write(\"orbit export: Orbit's web page script (dist/web-page.js) is missing: build Orbit first (bun run build)\\n\");\n return 1;\n }\n\n const html = exportWebPage(isYamlFile(file) ? doc : source, {\n script,\n title: values.title,\n theme: values.theme,\n viewMode: values.view as 'focus' | 'all' | undefined,\n focus: values.focus,\n language: values.language,\n media: localPictures(doc, file),\n });\n\n if (values.out) {\n writeFileSync(values.out, html);\n } else {\n process.stdout.write(html);\n }\n\n return 0;\n};\n\n/** Orbit's web page script: beside the built command's folder, or in the build beside the source's. */\nconst webPageScript = (): string | null => {\n for (const path of ['../web-page.js', '../dist/web-page.js']) {\n try {\n return readFileSync(new URL(path, import.meta.url), 'utf8');\n } catch {\n // Not in this folder: the command runs from the other one.\n }\n }\n\n return null;\n};\n\n/** The types of pictures a web page can take inside it, by extension. */\nconst PICTURE_TYPES: Record<string, string> = {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.avif': 'image/avif',\n '.svg': 'image/svg+xml',\n};\n\n/**\n * The pictures on this computer that the map shows (its nodes' pictures,\n * videos' thumbnails and pictures in notes), as data URLs by the address the\n * map gives them, to go inside the page. Pictures on the web stay links.\n */\nconst localPictures = (doc: ParsedOrbitDocument, file: string): Record<string, string> => {\n const base = baseUrlFor(doc.options.baseUrl, file) ?? pathToFileURL(`${process.cwd()}/`).href;\n const addresses = new Set<string>();\n\n const visit = (node: OrbitNode) => {\n if (node.image?.src) {\n addresses.add(node.image.src);\n }\n\n if (node.video?.thumbnail) {\n addresses.add(node.video.thumbnail);\n }\n\n if (node.note && node.noteFormat !== 'plain') {\n for (const match of node.note.matchAll(/!\\[[^\\]]*\\]\\(([^)\\s]+)/g)) {\n addresses.add(match[1]);\n }\n }\n\n node.children.forEach(visit);\n };\n\n visit(doc.root);\n const media: Record<string, string> = {};\n\n for (const address of addresses) {\n let url: URL;\n\n try {\n url = new URL(address, base);\n } catch {\n continue;\n }\n\n const type = PICTURE_TYPES[extname(url.pathname).toLowerCase()];\n\n if (url.protocol !== 'file:' || type === undefined) {\n continue;\n }\n\n try {\n media[address] = `data:${type};base64,${readFileSync(url).toString('base64')}`;\n } catch {\n process.stderr.write(`${file}: ${address} isn't there, so the page links to it as written\\n`);\n }\n }\n\n return media;\n};\n\n/** Every node's id, in document order. */\nconst nodeIds = (node: OrbitNode): string[] => {\n return [node.id, ...node.children.flatMap(nodeIds)];\n};\n\n/** The SVG with each link to a file on this computer written as a path from `folder`, where the SVG is going. */\nconst relativeFileLinks = (svg: string, folder: string): string => {\n return svg.replace(/(href=\")(file:\\/\\/[^\"]+)(\")/g, (_match, start: string, address: string, end: string) => {\n const path = relative(folder, fileURLToPath(address.replace(/&/g, '&')));\n const link = path.split(sep).map(encodeURIComponent).join('/') || '.';\n return `${start}${link.replace(/&/g, '&')}${end}`;\n });\n};\n\n/**\n * Where the map's relative media live: the document's baseUrl, or the map\n * file's own directory. A relative baseUrl sits next to the map file (or the\n * working directory, for a map read from stdin); one starting with `//` is on\n * the web, so it's read over https, as a browser would.\n */\nconst baseUrlFor = (documentBaseUrl: string | undefined, file: string): string | undefined => {\n const directory = file === '-' ? pathToFileURL(`${process.cwd()}/`) : pathToFileURL(`${resolve(dirname(file))}/`);\n\n if (documentBaseUrl === undefined) {\n return file === '-' ? undefined : directory.href;\n }\n\n try {\n return new URL(documentBaseUrl.startsWith('//') ? `https:${documentBaseUrl}` : documentBaseUrl, directory).href;\n } catch {\n throw new Error(`baseUrl \"${documentBaseUrl}\" is not an address`);\n }\n};\n\n/** What `orbit validate --json` prints. */\ninterface ValidationReport {\n valid: boolean;\n flavor: 'markdown' | 'yaml';\n root: string;\n nodes: number;\n depth: number;\n diagnostics: OrbitDiagnostic[];\n\n /** With --tree: the map as Orbit reads it. */\n tree?: TreeNode;\n}\n\n/** A node as --tree shows it: its id, its text and its children. */\ninterface TreeNode {\n id: string;\n text: string;\n children: TreeNode[];\n}\n\nconst treeOf = (node: OrbitNode): TreeNode => {\n return { id: node.id, text: node.text, children: node.children.map(treeOf) };\n};\n\n/** The tree as lines: each node's text and #id, indented under its parent. */\nconst treeLines = (node: TreeNode, depth = 0): string[] => {\n return [`${' '.repeat(depth)}- ${node.text} #${node.id}`, ...node.children.flatMap((child) => treeLines(child, depth + 1))];\n};\n\nconst validateCommand = (argumentsList: string[]): number => {\n const json = argumentsList.includes('--json');\n const tree = argumentsList.includes('--tree');\n const loose = argumentsList.includes('--loose');\n const unknown = argumentsList.find((argument) => argument.startsWith('--') && argument !== '--json' && argument !== '--loose' && argument !== '--tree');\n const files = argumentsList.filter((argument) => argument === '-' || !argument.startsWith('--'));\n\n if (unknown || files.length !== 1) {\n process.stderr.write(`orbit validate: ${unknown ? `unknown option ${unknown}` : 'expected one <file|->'}\\n${USAGE}`);\n return 2;\n }\n\n const [file] = files;\n let source: string;\n\n try {\n source = readInput(file);\n } catch (error) {\n if (json) {\n process.stdout.write(`${JSON.stringify({ valid: false, error: (error as Error).message }, null, 2)}\\n`);\n return 1;\n }\n\n throw error;\n }\n\n // Every problem at once, so they can all be fixed in one pass; strict mode\n // decides whether the map is valid.\n const doc = parseFile(file, source);\n let failure: OrbitParseError | null = null;\n\n if (!loose) {\n try {\n parseFile(file, source, { strict: true });\n } catch (error) {\n if (!(error instanceof OrbitParseError)) {\n throw error;\n }\n\n failure = error;\n }\n }\n\n // --loose accepts what the map works around, never what it can't read.\n const unreadable = (doc.diagnostics ?? []).some((diagnostic) => diagnostic.severity === 'error');\n const report: ValidationReport = {\n valid: failure === null && !unreadable,\n flavor: isYamlFile(file) ? 'yaml' : orbitFlavor(source),\n root: doc.root.text,\n nodes: countNodes(doc.root),\n depth: depthOf(doc.root),\n diagnostics: doc.diagnostics,\n ...(tree ? { tree: treeOf(doc.root) } : {}),\n };\n\n if (json) {\n process.stdout.write(`${JSON.stringify(report, null, 2)}\\n`);\n return report.valid ? 0 : 1;\n }\n\n if (report.tree) {\n process.stdout.write(`${treeLines(report.tree).join('\\n')}\\n`);\n }\n\n printDiagnostics(file, report.diagnostics);\n\n if (!report.valid) {\n process.stderr.write(loose\n ? `Not valid: fix the errors above (--loose accepts only the problems the map works around).\\n`\n : `Not valid: fix the problems above (or pass --loose to accept the ones the map works around).\\n`);\n return 1;\n }\n\n const warnings = report.diagnostics.length;\n process.stdout.write(`OK: ${plural(report.nodes, 'node')}, ${plural(report.depth + 1, 'level')}, ${plural(warnings, 'warning')}\\n`);\n return 0;\n};\n\n/** Problems as file:line: severity: message [code], the form editors and agents read. */\nconst printDiagnostics = (file: string, diagnostics: OrbitDiagnostic[]): void => {\n const name = file === '-' ? '<stdin>' : file;\n\n for (const diagnostic of diagnostics) {\n const place = diagnostic.line === undefined ? name : `${name}:${diagnostic.line}`;\n process.stderr.write(`${place}: ${diagnostic.severity}: ${diagnostic.message} [${diagnostic.code}]\\n`);\n }\n};\n\nconst plural = (count: number, word: string): string => {\n return `${count} ${word}${count === 1 ? '' : 's'}`;\n};\n\nconst countNodes = (node: OrbitNode): number => {\n return node.children.reduce((count, child) => count + countNodes(child), 1);\n};\n\n/** Levels below the root: 0 for a root alone. */\nconst depthOf = (node: OrbitNode): number => {\n return node.children.reduce((deepest, child) => Math.max(deepest, depthOf(child) + 1), 0);\n};\n\n// Run only when invoked as the orbit executable (not when imported by tests).\nif (typeof process !== 'undefined' && process.argv[1] && /^orbit(\\.[cm]?[jt]s)?$/.test(basename(process.argv[1]))) {\n process.exitCode = runCli(process.argv.slice(2));\n}\n",
|
|
5
|
+
"import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { basename, dirname, extname, join, relative, resolve, sep } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { orbitFlavor, parseOrbit } from '../src/core/dispatch';\nimport { OrbitParseError, type OrbitDiagnostic } from '../src/core/diagnostics';\nimport { serializeOrbitMarkdown } from '../src/core/serializer-markdown';\nimport { serializeOrbitYAML } from '../src/core/serializer-yaml';\nimport { renderToSVGString, MAX_SVG_EXPORT_SIZE } from '../src/core/render-to-svg';\nimport { exportWebPage } from '../src/core/web-page/page';\nimport { isOrbitThemePreset, themeNames } from '../src/core/themes';\nimport { THEME_SYNONYMS } from '../src/core/document-options';\nimport { didYouMean } from '../src/core/suggest';\nimport { OrbitWords } from '../src/core/languages';\nimport type { OrbitDocument, OrbitNode, OrbitThemePreset, ParsedOrbitDocument } from '../src/core/types';\nimport { detectImportFormat, importMap } from '../src/core/other-apps/import';\nimport { OrbitImportError } from '../src/core/other-apps/ideas';\nimport { exportOPML } from '../src/core/other-apps/opml';\nimport type { OrbitImport } from '../src/core/other-apps/reading';\nimport { parseOrbitYAML } from '../src/core/parser-yaml';\nimport { EXAMPLE_MAP } from './example';\n\nconst USAGE = `orbit: check, render and convert Orbit mind maps\n\nUsage:\n orbit validate [--json] [--loose] [--tree] <file|->\n Check a map and list every problem, with its line\n orbit render [options] <file|-> Render a map to a standalone SVG\n orbit export --html [options] <file|-> One web page with Orbit, the map and its pictures inside,\n to explore it or present it in any browser, offline\n orbit convert --to <md|yaml|opml> [--out <file>] <file|->\n Convert between the markdown and YAML flavors and OPML, and\n bring in maps from other apps: OPML, FreeMind and Freeplane\n (.mm) and XMind (.xmind)\n orbit example [--yaml] Print a map with the main features, to copy\n orbit help Show this message (so does --help after any command)\n orbit --version Print the version of Orbit\n\nValidate options:\n --json Print the result as JSON: valid, flavor, root, nodes, depth (the\n levels below the root) and diagnostics\n --loose Exit 0 even when there are problems the map can work around\n --tree Print the map as Orbit reads it, a node a line with its #id\n (with --json, as \"tree\"), to see what became a node and find ids\n\nRender options:\n --out <file> Write the SVG to a file instead of stdout\n --width <px> Width of the drawing (default 1200)\n --height <px> Height of the drawing (default 800)\n --theme <name> paper, night, glass, glass-night, cosmos, blueprint, ink, contrast,\n flat, flat-night, material, material-night, liquid, liquid-night,\n or auto, which draws paper: a picture can't follow the reader's\n light or dark mode (default: the document's, or paper)\n --view <focus|all> focus draws the map as it opens, where only the node at the center\n and its children have labels; all draws the whole map (default:\n the document's, or focus)\n --focus <node-id> The node at the center in focus mode (default: the root)\n --language <tag> The language of the drawing's few words, such as an untitled\n map's name: en or es (default: en)\n\nExport options:\n --out <file> Write the page to a file instead of stdout\n --title <text> The page's title (default: the map's title, or its root's text)\n --theme, --view, --focus, --language\n As for render; the page follows the reader's light or dark mode\n with --theme auto, and speaks the language's words\n\nConvert options:\n --to <md|yaml|opml> The flavor or format to write\n --out <file> Write to a file instead of stdout. An XMind workbook's pictures go\n in media/ next to it, and its other sheets in <file>-2, -3 and on\n\nUse \"-\" as the file to read from stdin. Output goes to stdout; problems go\nto stderr as file:line: severity: message [code].\n\nExit codes: 0 when it worked (for validate, when the map is valid), 1 when the\nmap has problems or can't be read, and 2 for a mistake in the command itself.\n\nThe whole format and API, for people and coding agents: llms-full.txt in this\npackage, or https://cdn.jsdelivr.net/npm/@restless-dreams/orbit/llms-full.txt\n`;\n\n/** This package's version, from its package.json: beside the built command's folder, or the source's. */\nconst packageVersion = (): string => {\n for (const path of ['../package.json', '../../package.json']) {\n try {\n const manifest = JSON.parse(readFileSync(new URL(path, import.meta.url), 'utf8')) as { name?: string; version?: string };\n\n if (manifest.name === '@restless-dreams/orbit' && manifest.version) {\n return manifest.version;\n }\n } catch {\n // Not in this folder: the command runs from the other one.\n }\n }\n\n return 'unknown';\n};\n\n/** Whether a file is YAML by its name, whatever its first lines look like. */\nconst isYamlFile = (file: string): boolean => {\n return /\\.ya?ml$/i.test(file);\n};\n\n/** A map from a file: YAML for .yaml and .yml files, otherwise the flavor its first lines say. */\nconst parseFile = (file: string, source: string, options: { strict?: boolean; untitled?: string } = {}): ParsedOrbitDocument => {\n return isYamlFile(file) ? parseOrbitYAML(source, options) : parseOrbit(source, options);\n};\n\nconst readInput = (path: string): string => {\n return readFileSync(path === '-' ? 0 : path, 'utf8');\n};\n\nexport const runCli = (argv: string[]): number => {\n const [command, ...rest] = argv;\n\n if (command === undefined || command === 'help' || command === '-h' || command === '--help' || rest.includes('--help') || rest.includes('-h')) {\n process.stdout.write(USAGE);\n return command === undefined ? 2 : 0;\n }\n\n if (command === '--version' || command === '-v' || command === 'version') {\n process.stdout.write(`${packageVersion()}\\n`);\n return 0;\n }\n\n try {\n if (command === 'convert') {\n return convertCommand(rest.map((argument) => (argument === '-t' ? '--to' : argument)));\n }\n\n if (command === 'example') {\n const yaml = rest.includes('--yaml');\n\n if (rest.some((argument) => argument !== '--yaml')) {\n process.stderr.write(`orbit example: the only option is --yaml\\n${USAGE}`);\n return 2;\n }\n\n process.stdout.write(yaml ? serializeOrbitYAML(parseOrbit(EXAMPLE_MAP)) : EXAMPLE_MAP);\n return 0;\n }\n\n if (command === 'export') {\n return exportCommand(rest);\n }\n\n if (command === 'render') {\n return renderCommand(rest);\n }\n\n if (command === 'validate') {\n return validateCommand(rest);\n }\n\n process.stderr.write(`orbit: unknown command \"${command}\"\\n${USAGE}`);\n return 2;\n } catch (err) {\n process.stderr.write(`error: ${(err as Error).message}\\n`);\n return 1;\n }\n};\n\n/** A command's `--name value` options among `names`, and its one file; or the exit code for a mistake in them. */\nconst readOptions = (command: string, argumentsList: string[], names: string[]): { values: Record<string, string>; file: string } | number => {\n const values: Record<string, string> = {};\n let file = '';\n\n for (let index = 0; index < argumentsList.length; index++) {\n const argument = argumentsList[index];\n const name = argument.startsWith('--') ? argument.slice(2) : '';\n\n if (names.includes(name)) {\n const value = argumentsList[++index];\n\n if (value === undefined) {\n process.stderr.write(`orbit ${command}: ${argument} needs a value\\n`);\n return 2;\n }\n\n values[name] = value;\n } else if (argument === '-' || !argument.startsWith('--')) {\n file = argument;\n } else {\n process.stderr.write(`orbit ${command}: unknown option ${argument}\\n${USAGE}`);\n return 2;\n }\n }\n\n if (!file) {\n process.stderr.write(`orbit ${command}: missing <file>\\n${USAGE}`);\n return 2;\n }\n\n return { values, file };\n};\n\n/** The exit code for a --theme or --view that isn't one, or null when they're fine. */\nconst checkLook = (command: string, values: Record<string, string>): number | null => {\n if (values.theme !== undefined && !isOrbitThemePreset(values.theme)) {\n process.stderr.write(`orbit ${command}: unknown theme \"${values.theme}\". Themes: ${themeNames().join(', ')}.${didYouMean(values.theme, themeNames(), THEME_SYNONYMS)}\\n`);\n return 2;\n }\n\n if (values.view !== undefined && values.view !== 'focus' && values.view !== 'all') {\n process.stderr.write(`orbit ${command}: --view must be focus or all\\n`);\n return 2;\n }\n\n return null;\n};\n\n/** The exit code for a --focus no node of the map has, or null when it's fine. */\nconst checkFocus = (command: string, values: Record<string, string>, doc: ParsedOrbitDocument): number | null => {\n if (values.focus !== undefined) {\n const ids = nodeIds(doc.root);\n\n if (!ids.includes(values.focus)) {\n process.stderr.write(`orbit ${command}: no node has the id \"${values.focus}\".${didYouMean(values.focus, ids)} Ids come from the nodes' text: \"Q3 plan\" is q3-plan.\\n`);\n return 2;\n }\n }\n\n return null;\n};\n\n/** A map in the flavor or format `--to` names: md, yaml or opml. */\nconst writeAs = (to: string, doc: OrbitDocument): string => {\n if (to === 'opml') {\n return exportOPML(doc);\n }\n\n return /^(md|markdown)$/.test(to) ? serializeOrbitMarkdown(doc, { keepSource: false }) : serializeOrbitYAML(doc);\n};\n\nconst convertCommand = (argumentsList: string[]): number => {\n const values: Record<string, string> = {};\n let file = '';\n\n for (let index = 0; index < argumentsList.length; index++) {\n const argument = argumentsList[index];\n\n if (argument === '--to' || argument === '--out') {\n values[argument.slice(2)] = argumentsList[++index] ?? '';\n } else if (argument.startsWith('-') && argument !== '-') {\n process.stderr.write(`orbit convert: unknown option ${argument}\\n${USAGE}`);\n return 2;\n } else {\n file = argument;\n }\n }\n\n const to = values.to ?? '';\n\n if (!file || !/^(md|markdown|yaml|yml|opml)$/.test(to)) {\n process.stderr.write(`orbit convert: expected --to <md|yaml|opml> <file|->\\n${USAGE}`);\n return 2;\n }\n\n const bytes = new Uint8Array(readFileSync(file === '-' ? 0 : file));\n const format = detectImportFormat(bytes, file === '-' ? undefined : basename(file));\n const name = file === '-' ? '<stdin>' : file;\n\n if (format === null) {\n const doc = parseFile(file, new TextDecoder().decode(bytes));\n printDiagnostics(file, doc.diagnostics ?? []);\n writeOutput(values.out, writeAs(to, doc));\n return 0;\n }\n\n let imported: OrbitImport;\n\n try {\n imported = importMap(bytes, { name: file === '-' ? undefined : basename(file), format });\n } catch (error) {\n if (error instanceof OrbitImportError) {\n process.stderr.write(`${name}: error: ${error.message} [${error.code}]\\n`);\n return 1;\n }\n\n throw error;\n }\n\n const { maps } = imported;\n\n maps.forEach((map, index) => {\n const sheet = maps.length > 1 ? ` (sheet ${index + 1}, ${map.document.root.text || 'untitled'})` : '';\n\n for (const warning of map.warnings) {\n process.stderr.write(`${name}${sheet}: warning: ${warning.message} [${warning.code}]\\n`);\n }\n });\n\n if (!values.out) {\n const pictures = maps.reduce((count, map) => count + Object.keys(map.media).length, 0);\n\n if (maps.length > 1) {\n process.stderr.write(`${name}: the workbook has ${maps.length} sheets: this is the first. Write them all with --out.\\n`);\n }\n\n if (pictures > 0) {\n process.stderr.write(`${name}: ${pictures === 1 ? 'one picture' : `${pictures} pictures`} inside the file ${pictures === 1 ? 'was' : 'were'} left out: write the map with --out to save them in media/ next to it.\\n`);\n }\n\n process.stdout.write(writeAs(to, maps[0].document));\n return 0;\n }\n\n const folder = dirname(values.out);\n const extension = extname(values.out);\n const stem = values.out.slice(0, values.out.length - extension.length);\n\n maps.forEach((map, index) => {\n // Every sheet's pictures share the one media folder: names that clash take the sheet's number.\n const renamed = new Map<string, string>();\n\n for (const [path, data] of Object.entries(map.media)) {\n let target = path;\n\n for (let suffix = 2; existsSync(join(folder, target)) && !sameBytes(join(folder, target), data); suffix++) {\n target = path.replace(/(\\.[^.]+)$/, `-${index + 1}-${suffix}$1`);\n }\n\n mkdirSync(dirname(join(folder, target)), { recursive: true });\n writeFileSync(join(folder, target), data);\n renamed.set(path, target);\n }\n\n const out = index === 0 ? values.out as string : `${stem}-${index + 1}${extension}`;\n let text = writeAs(to, map.document);\n\n for (const [from, target] of renamed) {\n if (from !== target) {\n text = text.split(from).join(target);\n }\n }\n\n writeFileSync(out, text);\n });\n\n return 0;\n};\n\n/** Whether a file holds exactly these bytes. */\nconst sameBytes = (path: string, data: Uint8Array): boolean => {\n return Buffer.from(readFileSync(path)).equals(Buffer.from(data));\n};\n\n/** Writes text to a file, or to stdout without one. */\nconst writeOutput = (out: string | undefined, text: string): void => {\n if (out) {\n writeFileSync(out, text);\n } else {\n process.stdout.write(text);\n }\n};\n\nconst renderCommand = (argumentsList: string[]): number => {\n const read = readOptions('render', argumentsList, ['out', 'width', 'height', 'theme', 'view', 'focus', 'language']);\n\n if (typeof read === 'number') {\n return read;\n }\n\n const { values, file } = read;\n const width = values.width === undefined ? 1200 : Number(values.width);\n const height = values.height === undefined ? 800 : Number(values.height);\n\n if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0 || width > MAX_SVG_EXPORT_SIZE || height > MAX_SVG_EXPORT_SIZE) {\n process.stderr.write(`orbit render: --width and --height must be positive numbers no larger than ${MAX_SVG_EXPORT_SIZE}\\n`);\n return 2;\n }\n\n const look = checkLook('render', values);\n\n if (look !== null) {\n return look;\n }\n\n const words = new OrbitWords(values.language);\n const doc = parseFile(file, readInput(file), { untitled: words.text('untitledMap') });\n printDiagnostics(file, doc.diagnostics);\n const focus = checkFocus('render', values, doc);\n\n if (focus !== null) {\n return focus;\n }\n\n const svg = renderToSVGString(doc, {\n width,\n height,\n language: values.language,\n theme: values.theme as OrbitThemePreset | undefined,\n viewMode: values.view as 'focus' | 'all' | undefined,\n focus: values.focus,\n // Relative images are next to the map file, unless the document says otherwise.\n baseUrl: baseUrlFor(doc.options.baseUrl, file),\n });\n // Pictures on this computer are linked from where the SVG goes, so it can move with them.\n const portable = relativeFileLinks(svg, values.out ? resolve(dirname(values.out)) : process.cwd());\n\n if (values.out) {\n writeFileSync(values.out, portable + '\\n');\n } else {\n process.stdout.write(portable + '\\n');\n }\n\n return 0;\n};\n\nconst exportCommand = (argumentsList: string[]): number => {\n if (!argumentsList.includes('--html')) {\n process.stderr.write(`orbit export: say what to export the map as: --html, one web page with the map inside\\n${USAGE}`);\n return 2;\n }\n\n const read = readOptions('export', argumentsList.filter((argument) => argument !== '--html'), ['out', 'title', 'theme', 'view', 'focus', 'language']);\n\n if (typeof read === 'number') {\n return read;\n }\n\n const { values, file } = read;\n const look = checkLook('export', values);\n\n if (look !== null) {\n return look;\n }\n\n const words = new OrbitWords(values.language);\n const source = readInput(file);\n const doc = parseFile(file, source, { untitled: words.text('untitledMap') });\n printDiagnostics(file, doc.diagnostics);\n const focus = checkFocus('export', values, doc);\n\n if (focus !== null) {\n return focus;\n }\n\n const script = webPageScript();\n\n if (script === null) {\n process.stderr.write(\"orbit export: Orbit's web page script (dist/web-page.js) is missing: build Orbit first (bun run build)\\n\");\n return 1;\n }\n\n const html = exportWebPage(isYamlFile(file) ? doc : source, {\n script,\n title: values.title,\n theme: values.theme,\n viewMode: values.view as 'focus' | 'all' | undefined,\n focus: values.focus,\n language: values.language,\n media: localPictures(doc, file),\n });\n\n if (values.out) {\n writeFileSync(values.out, html);\n } else {\n process.stdout.write(html);\n }\n\n return 0;\n};\n\n/** Orbit's web page script: beside the built command's folder, or in the build beside the source's. */\nconst webPageScript = (): string | null => {\n for (const path of ['../web-page.js', '../dist/web-page.js']) {\n try {\n return readFileSync(new URL(path, import.meta.url), 'utf8');\n } catch {\n // Not in this folder: the command runs from the other one.\n }\n }\n\n return null;\n};\n\n/** The types of pictures a web page can take inside it, by extension. */\nconst PICTURE_TYPES: Record<string, string> = {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.avif': 'image/avif',\n '.svg': 'image/svg+xml',\n};\n\n/**\n * The pictures on this computer that the map shows (its nodes' pictures,\n * videos' thumbnails and pictures in notes), as data URLs by the address the\n * map gives them, to go inside the page. Pictures on the web stay links.\n */\nconst localPictures = (doc: ParsedOrbitDocument, file: string): Record<string, string> => {\n const base = baseUrlFor(doc.options.baseUrl, file) ?? pathToFileURL(`${process.cwd()}/`).href;\n const addresses = new Set<string>();\n\n const visit = (node: OrbitNode) => {\n if (node.image?.src) {\n addresses.add(node.image.src);\n }\n\n if (node.video?.thumbnail) {\n addresses.add(node.video.thumbnail);\n }\n\n if (node.note && node.noteFormat !== 'plain') {\n for (const match of node.note.matchAll(/!\\[[^\\]]*\\]\\(([^)\\s]+)/g)) {\n addresses.add(match[1]);\n }\n }\n\n node.children.forEach(visit);\n };\n\n visit(doc.root);\n const media: Record<string, string> = {};\n\n for (const address of addresses) {\n let url: URL;\n\n try {\n url = new URL(address, base);\n } catch {\n continue;\n }\n\n const type = PICTURE_TYPES[extname(url.pathname).toLowerCase()];\n\n if (url.protocol !== 'file:' || type === undefined) {\n continue;\n }\n\n try {\n media[address] = `data:${type};base64,${readFileSync(url).toString('base64')}`;\n } catch {\n process.stderr.write(`${file}: ${address} isn't there, so the page links to it as written\\n`);\n }\n }\n\n return media;\n};\n\n/** Every node's id, in document order. */\nconst nodeIds = (node: OrbitNode): string[] => {\n return [node.id, ...node.children.flatMap(nodeIds)];\n};\n\n/** The SVG with each link to a file on this computer written as a path from `folder`, where the SVG is going. */\nconst relativeFileLinks = (svg: string, folder: string): string => {\n return svg.replace(/(href=\")(file:\\/\\/[^\"]+)(\")/g, (_match, start: string, address: string, end: string) => {\n const path = relative(folder, fileURLToPath(address.replace(/&/g, '&')));\n const link = path.split(sep).map(encodeURIComponent).join('/') || '.';\n return `${start}${link.replace(/&/g, '&')}${end}`;\n });\n};\n\n/**\n * Where the map's relative media live: the document's baseUrl, or the map\n * file's own directory. A relative baseUrl sits next to the map file (or the\n * working directory, for a map read from stdin); one starting with `//` is on\n * the web, so it's read over https, as a browser would.\n */\nconst baseUrlFor = (documentBaseUrl: string | undefined, file: string): string | undefined => {\n const directory = file === '-' ? pathToFileURL(`${process.cwd()}/`) : pathToFileURL(`${resolve(dirname(file))}/`);\n\n if (documentBaseUrl === undefined) {\n return file === '-' ? undefined : directory.href;\n }\n\n try {\n return new URL(documentBaseUrl.startsWith('//') ? `https:${documentBaseUrl}` : documentBaseUrl, directory).href;\n } catch {\n throw new Error(`baseUrl \"${documentBaseUrl}\" is not an address`);\n }\n};\n\n/** What `orbit validate --json` prints. */\ninterface ValidationReport {\n valid: boolean;\n flavor: 'markdown' | 'yaml';\n root: string;\n nodes: number;\n depth: number;\n diagnostics: OrbitDiagnostic[];\n\n /** With --tree: the map as Orbit reads it. */\n tree?: TreeNode;\n}\n\n/** A node as --tree shows it: its id, its text and its children. */\ninterface TreeNode {\n id: string;\n text: string;\n children: TreeNode[];\n}\n\nconst treeOf = (node: OrbitNode): TreeNode => {\n return { id: node.id, text: node.text, children: node.children.map(treeOf) };\n};\n\n/** The tree as lines: each node's text and #id, indented under its parent. */\nconst treeLines = (node: TreeNode, depth = 0): string[] => {\n return [`${' '.repeat(depth)}- ${node.text} #${node.id}`, ...node.children.flatMap((child) => treeLines(child, depth + 1))];\n};\n\nconst validateCommand = (argumentsList: string[]): number => {\n const json = argumentsList.includes('--json');\n const tree = argumentsList.includes('--tree');\n const loose = argumentsList.includes('--loose');\n const unknown = argumentsList.find((argument) => argument.startsWith('--') && argument !== '--json' && argument !== '--loose' && argument !== '--tree');\n const files = argumentsList.filter((argument) => argument === '-' || !argument.startsWith('--'));\n\n if (unknown || files.length !== 1) {\n process.stderr.write(`orbit validate: ${unknown ? `unknown option ${unknown}` : 'expected one <file|->'}\\n${USAGE}`);\n return 2;\n }\n\n const [file] = files;\n let source: string;\n\n try {\n source = readInput(file);\n } catch (error) {\n if (json) {\n process.stdout.write(`${JSON.stringify({ valid: false, error: (error as Error).message }, null, 2)}\\n`);\n return 1;\n }\n\n throw error;\n }\n\n // Every problem at once, so they can all be fixed in one pass; strict mode\n // decides whether the map is valid.\n const doc = parseFile(file, source);\n let failure: OrbitParseError | null = null;\n\n if (!loose) {\n try {\n parseFile(file, source, { strict: true });\n } catch (error) {\n if (!(error instanceof OrbitParseError)) {\n throw error;\n }\n\n failure = error;\n }\n }\n\n // --loose accepts what the map works around, never what it can't read.\n const unreadable = (doc.diagnostics ?? []).some((diagnostic) => diagnostic.severity === 'error');\n const report: ValidationReport = {\n valid: failure === null && !unreadable,\n flavor: isYamlFile(file) ? 'yaml' : orbitFlavor(source),\n root: doc.root.text,\n nodes: countNodes(doc.root),\n depth: depthOf(doc.root),\n diagnostics: doc.diagnostics,\n ...(tree ? { tree: treeOf(doc.root) } : {}),\n };\n\n if (json) {\n process.stdout.write(`${JSON.stringify(report, null, 2)}\\n`);\n return report.valid ? 0 : 1;\n }\n\n if (report.tree) {\n process.stdout.write(`${treeLines(report.tree).join('\\n')}\\n`);\n }\n\n printDiagnostics(file, report.diagnostics);\n\n if (!report.valid) {\n process.stderr.write(loose\n ? `Not valid: fix the errors above (--loose accepts only the problems the map works around).\\n`\n : `Not valid: fix the problems above (or pass --loose to accept the ones the map works around).\\n`);\n return 1;\n }\n\n const warnings = report.diagnostics.length;\n process.stdout.write(`OK: ${plural(report.nodes, 'node')}, ${plural(report.depth + 1, 'level')}, ${plural(warnings, 'warning')}\\n`);\n return 0;\n};\n\n/** Problems as file:line: severity: message [code], the form editors and agents read. */\nconst printDiagnostics = (file: string, diagnostics: OrbitDiagnostic[]): void => {\n const name = file === '-' ? '<stdin>' : file;\n\n for (const diagnostic of diagnostics) {\n const place = diagnostic.line === undefined ? name : `${name}:${diagnostic.line}`;\n process.stderr.write(`${place}: ${diagnostic.severity}: ${diagnostic.message} [${diagnostic.code}]\\n`);\n }\n};\n\nconst plural = (count: number, word: string): string => {\n return `${count} ${word}${count === 1 ? '' : 's'}`;\n};\n\nconst countNodes = (node: OrbitNode): number => {\n return node.children.reduce((count, child) => count + countNodes(child), 1);\n};\n\n/** Levels below the root: 0 for a root alone. */\nconst depthOf = (node: OrbitNode): number => {\n return node.children.reduce((deepest, child) => Math.max(deepest, depthOf(child) + 1), 0);\n};\n\n// Run only when invoked as the orbit executable (not when imported by tests).\nif (typeof process !== 'undefined' && process.argv[1] && /^orbit(\\.[cm]?[jt]s)?$/.test(basename(process.argv[1]))) {\n process.exitCode = runCli(process.argv.slice(2));\n}\n",
|
|
6
6
|
"/**\n * Tiny YAML subset parser + emitter for Orbit, with no dependencies.\n * Reads what maps and the frontmatter of other apps (Obsidian, static site\n * generators) write: maps, block lists (indented under their key or not),\n * flow lists and maps (`[a, b]`, `{name: Ana}`), strings, numbers,\n * booleans and null, block scalars (`|` literal, `>` folded), plain and\n * quoted strings over several lines, comments, anchors, aliases and merge\n * keys (`&base`, `*base`, `<<: *base`). Not read: tags (`!!str`) and\n * complex keys (`? key`).\n *\n * One leniency on purpose: a value that starts with `#` is text, not a\n * comment, so `color: #FF6B6B` reads as the color people mean.\n */\n\nexport class YamlMiniError extends Error {\n /** 1-based line of the problem in the text given to the parser. */\n line: number;\n\n /** The problem, without where it is. */\n reason: string;\n\n constructor(reason: string, line: number) {\n super(`${reason} at line ${line}`);\n this.name = 'YamlMiniError';\n this.line = line;\n this.reason = reason;\n }\n}\n\nexport type YamlValue = string | number | boolean | null | YamlValue[] | { [k: string]: YamlValue };\n\n/** Values named with `&name` while a document is read, for `*name` to repeat. */\nlet anchors = new Map<string, YamlValue>();\n\n/** Where each key of a block map was written: 1-based lines of the text given to the parser. */\nconst keyLines = new WeakMap<object, Map<string, number>>();\n/** Where each item of a block list starts. */\nconst itemLines = new WeakMap<object, number[]>();\n\nconst noteKeyLine = (map: object, key: string, line: number): void => {\n let lines = keyLines.get(map);\n\n if (!lines) {\n lines = new Map();\n keyLines.set(map, lines);\n }\n\n lines.set(key, line);\n};\n\n/**\n * The line `key` was written on in a map the last `parseYaml` read, or the\n * map's first key's line without one: for problems that point at a node of\n * a YAML document. Flow maps (`{ … }`) have none.\n */\nexport const yamlLineOf = (map: object, key?: string): number | undefined => {\n const lines = keyLines.get(map);\n\n if (!lines) {\n return undefined;\n }\n\n return key === undefined ? lines.values().next().value : lines.get(key);\n};\n\n/** The line item `index` of a block list starts on. */\nexport const yamlItemLine = (list: object, index: number): number | undefined => {\n return itemLines.get(list)?.[index];\n};\n\nexport const parseYaml = (input: string): YamlValue => {\n const lines = normalizeInput(input);\n const previous = anchors;\n anchors = new Map();\n\n try {\n const [value] = parseBlock(lines, 0, 0);\n return value;\n } finally {\n anchors = previous;\n }\n};\n\n/** Lines, without a document's `---` start and `...` end markers. */\nconst normalizeInput = (input: string): string[] => {\n const lines = input.replace(/\\r\\n?/g, '\\n').split('\\n');\n const first = lines.findIndex((line) => line.trim() !== '' && !line.trimStart().startsWith('#'));\n\n if (first !== -1 && /^---\\s*$/.test(lines[first])) {\n lines[first] = '';\n }\n\n let last = lines.length - 1;\n\n while (last >= 0 && lines[last].trim() === '') {\n last--;\n }\n\n if (last !== -1 && /^\\.\\.\\.\\s*$/.test(lines[last])) {\n lines[last] = '';\n }\n\n return lines;\n};\n\nconst parseBlock = (lines: string[], start: number, indent: number): [YamlValue, number] => {\n // Detect: is this block a list (lines start with `- `) or a map?\n const firstContent = nextContentLine(lines, start);\n\n if (firstContent !== -1) {\n const raw = lines[firstContent];\n const lineIndent = leadingSpaces(raw);\n\n if (lineIndent === indent && isListItem(raw, indent)) {\n return parseList(lines, start, indent);\n }\n }\n\n return parseMap(lines, start, indent);\n};\n\n/** Whether the line is a list item at `indent`: `- value`, or a lone `-`. */\nconst isListItem = (raw: string, indent: number): boolean => {\n return raw.slice(indent, indent + 2) === '- ' || raw.slice(indent).trimEnd() === '-';\n};\n\n/** A key as written: unquoted, when it's quoted. */\nconst readKey = (key: string, line: number): string => {\n return key.startsWith('\"') || key.startsWith(\"'\") ? String(parseScalar(key, line)) : key;\n};\n\n/**\n * Sets `obj[key]`, even when `key` is `__proto__`: a plain assignment would\n * then change the object's prototype and lose the key, so it becomes an own\n * enumerable data property.\n */\nexport const assignKey = (obj: Record<string, unknown>, key: string, value: unknown): void => {\n if (key === '__proto__') {\n Object.defineProperty(obj, key, { value, writable: true, enumerable: true, configurable: true });\n } else {\n obj[key] = value;\n }\n};\n\nconst parseMap = (lines: string[], start: number, indent: number): [Record<string, YamlValue>, number] => {\n const obj: Record<string, YamlValue> = {};\n const merged: YamlValue[] = [];\n let i = start;\n\n while (i < lines.length) {\n const raw = lines[i];\n\n if (raw.trim() === '' || raw.trimStart().startsWith('#')) {\n i++;\n continue;\n }\n\n const lineIndent = leadingSpaces(raw);\n\n if (lineIndent < indent) {\n break;\n }\n\n if (lineIndent > indent) {\n throw new YamlMiniError('Unexpected indentation', i + 1);\n }\n\n // A list item here belongs to the key above it (`tags:` then `- a`), which has read it already.\n if (isListItem(raw, indent)) {\n throw new YamlMiniError('Expected \"key: value\"', i + 1);\n }\n\n const content = raw.slice(indent);\n const colonIdx = findUnquotedColon(content);\n\n if (colonIdx < 0) {\n throw new YamlMiniError('Expected \"key: value\"', i + 1);\n }\n\n const key = readKey(content.slice(0, colonIdx).trim(), i + 1);\n const rest = content.slice(colonIdx + 1).trim();\n\n const { value, nextIndex } = parseValueForKey(rest, lines, i, indent);\n\n if (key === '<<') {\n merged.push(value);\n } else {\n assignKey(obj, key, value);\n noteKeyLine(obj, key, i + 1);\n }\n\n i = nextIndex;\n }\n\n // `<<: *base` adds the keys of `base` this map doesn't set itself (its own\n // keys only: `in` would also see `constructor` and `toString` on every object).\n for (const source of merged.flatMap((value) => (Array.isArray(value) ? value : [value]))) {\n if (source && typeof source === 'object' && !Array.isArray(source)) {\n for (const [key, value] of Object.entries(source)) {\n if (!Object.prototype.hasOwnProperty.call(obj, key)) {\n assignKey(obj, key, value);\n }\n }\n }\n }\n\n return [obj, i];\n};\n\nconst parseList = (lines: string[], start: number, indent: number): [YamlValue[], number] => {\n const list: YamlValue[] = [];\n const starts: number[] = [];\n itemLines.set(list, starts);\n let i = start;\n\n while (i < lines.length) {\n const raw = lines[i];\n\n if (raw.trim() === '' || raw.trimStart().startsWith('#')) {\n i++;\n continue;\n }\n\n const lineIndent = leadingSpaces(raw);\n\n if (lineIndent < indent) {\n break;\n }\n\n if (lineIndent > indent || !isListItem(raw, indent)) {\n break;\n }\n\n const itemContent = raw.slice(indent + 2);\n const colonIdx = findUnquotedColon(itemContent);\n const startsValue = /^[&*\"'[{|>]/.test(itemContent.trim());\n starts.push(i + 1);\n\n if (colonIdx >= 0 && !startsValue) {\n const itemMap: Record<string, YamlValue> = {};\n const key = readKey(itemContent.slice(0, colonIdx).trim(), i + 1);\n const rest = itemContent.slice(colonIdx + 1).trim();\n const { value: firstVal, nextIndex: firstNext } = parseValueForKey(rest, lines, i, indent + 2);\n assignKey(itemMap, key, firstVal);\n noteKeyLine(itemMap, key, i + 1);\n i = firstNext;\n\n while (i < lines.length) {\n const r2 = lines[i];\n\n if (r2.trim() === '' || r2.trimStart().startsWith('#')) {\n i++;\n continue;\n }\n\n const ind2 = leadingSpaces(r2);\n\n if (ind2 !== indent + 2) {\n break;\n }\n\n const c2 = r2.slice(indent + 2);\n\n if (isListItem(c2, 0)) {\n break;\n } // next list item, not a continuation key\n\n const k2idx = findUnquotedColon(c2);\n\n if (k2idx < 0) {\n throw new YamlMiniError('Expected \"key: value\"', i + 1);\n }\n\n const key2 = readKey(c2.slice(0, k2idx).trim(), i + 1);\n const rest2 = c2.slice(k2idx + 1).trim();\n const { value: contVal, nextIndex: contNext } = parseValueForKey(rest2, lines, i, indent + 2);\n assignKey(itemMap, key2, contVal);\n noteKeyLine(itemMap, key2, i + 1);\n i = contNext;\n }\n\n list.push(itemMap);\n } else {\n // A scalar, flow value, anchor, alias or block scalar item.\n const { value, nextIndex } = parseValueForKey(itemContent.trim(), lines, i, indent);\n list.push(value);\n i = nextIndex;\n }\n }\n\n return [list, i];\n};\n\n/** A value with its trailing comment taken off: ` # …` outside quotes and brackets, but not at the start. */\nconst stripComment = (text: string): string => {\n let quote: '\"' | \"'\" | null = null;\n\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n\n if (quote) {\n if (c === '\\\\' && quote === '\"') {\n i++;\n } else if (c === quote) {\n if (quote === \"'\" && text[i + 1] === \"'\") {\n i++;\n } else {\n quote = null;\n }\n }\n\n continue;\n }\n\n // A quote only opens a quoted value at its start or inside a flow value: \"it's\" is plain text.\n if ((c === '\"' || c === \"'\") && (i === 0 || /[\\s[{,:]/.test(text[i - 1]))) {\n quote = c;\n } else if (c === '#' && i > 0 && /\\s/.test(text[i - 1])) {\n return text.slice(0, i).trimEnd();\n }\n }\n\n return text;\n};\n\nconst parseValueForKey = (\n written: string,\n lines: string[],\n i: number,\n parentIndent: number,\n): { value: YamlValue; nextIndex: number } => {\n let rest = stripComment(written);\n // `&name value`: remembered for `*name`.\n const anchor = /^&([^\\s,[\\]{}]+)\\s*/.exec(rest);\n\n if (anchor) {\n rest = rest.slice(anchor[0].length);\n const parsed = parseValueForKey(rest, lines, i, parentIndent);\n anchors.set(anchor[1], parsed.value);\n return parsed;\n }\n\n const alias = /^\\*([^\\s,[\\]{}]+)$/.exec(rest);\n\n if (alias) {\n return { value: aliasValue(alias[1], i + 1), nextIndex: i + 1 };\n }\n\n if (rest === '|' || rest === '>' || /^[|>][-+]?\\d?$/.test(rest)) {\n const fold = rest.startsWith('>');\n // Inside a block scalar there are no YAML comments: a first line like\n // \"### heading\" is content and must anchor the child indent.\n const childIndent = detectChildIndent(lines, i + 1, parentIndent, false);\n\n if (childIndent === null) {\n return { value: '', nextIndex: i + 1 };\n }\n\n const collected: string[] = [];\n let j = i + 1;\n\n while (j < lines.length) {\n const r = lines[j];\n\n if (r.trim() === '') {\n collected.push('');\n j++;\n continue;\n }\n\n const ind = leadingSpaces(r);\n\n if (ind < childIndent) {\n break;\n }\n\n collected.push(r.slice(childIndent));\n j++;\n }\n\n while (collected.length && collected[collected.length - 1] === '') {\n collected.pop();\n }\n\n if (fold) {\n return { value: foldLines(collected), nextIndex: j };\n }\n\n return { value: collected.join('\\n'), nextIndex: j };\n }\n\n if (rest === '') {\n // A list right under its key, at the key's own indentation: `tags:` then `- a`.\n const next = nextContentLine(lines, i + 1);\n\n if (next !== -1 && leadingSpaces(lines[next]) === parentIndent && isListItem(lines[next], parentIndent)) {\n const [val, nextIndex] = parseList(lines, i + 1, parentIndent);\n return { value: val, nextIndex };\n }\n\n const childIndent = detectChildIndent(lines, i + 1, parentIndent);\n\n if (childIndent === null) {\n return { value: null, nextIndex: i + 1 };\n }\n\n const [val, nextLine] = parseBlock(lines, i + 1, childIndent);\n return { value: val, nextIndex: nextLine };\n }\n\n // A quoted string, or a flow list or map, may go on over the next lines.\n const opening = rest[0];\n\n if ((opening === '\"' || opening === \"'\" || opening === '[' || opening === '{') && !closes(rest)) {\n let joined = rest;\n let j = i + 1;\n\n while (j < lines.length && !closes(joined)) {\n const line = lines[j].trim();\n joined += opening === '\"' || opening === \"'\" ? (line === '' ? '\\n' : ` ${line}`) : ` ${line}`;\n j++;\n }\n\n return { value: parseScalar(stripComment(joined.replace(/ \\n /g, '\\n')), i + 1), nextIndex: j };\n }\n\n // A plain value may go on over lines indented under its key.\n const continuation: string[] = [];\n let j = i + 1;\n\n while (j < lines.length) {\n const line = lines[j];\n\n if (line.trim() === '') {\n continuation.push('');\n j++;\n continue;\n }\n\n if (leadingSpaces(line) <= parentIndent || line.trimStart().startsWith('#')) {\n break;\n }\n\n if (findUnquotedColon(line.trim()) >= 0 || isListItem(line, leadingSpaces(line))) {\n throw new YamlMiniError('Unexpected indentation', j + 1);\n }\n\n continuation.push(stripComment(line.trim()));\n j++;\n }\n\n while (continuation.length && continuation[continuation.length - 1] === '') {\n continuation.pop();\n j--;\n }\n\n if (continuation.length > 0) {\n // Trailing blank lines belong to what follows, so they're read again.\n while (j > i + 1 && lines[j - 1].trim() === '') {\n j--;\n }\n\n return { value: foldLines([rest, ...continuation]), nextIndex: j };\n }\n\n return { value: parseScalar(rest, i + 1), nextIndex: i + 1 };\n};\n\n/** Folded lines: a line break between paragraphs, a space within one. */\nconst foldLines = (collected: string[]): string => {\n let out = '';\n let prevBlank = false;\n\n for (let k = 0; k < collected.length; k++) {\n const line = collected[k];\n\n if (line === '') {\n prevBlank = true;\n continue;\n }\n\n if (k === 0) {\n out = line;\n } else if (prevBlank) {\n out += '\\n' + line;\n } else {\n out += ' ' + line;\n }\n\n prevBlank = false;\n }\n\n return out;\n};\n\n/** Whether a quoted string or flow value is closed: its quotes and brackets end in the text. */\nconst closes = (text: string): boolean => {\n const opening = text[0];\n\n if (opening === '\"' || opening === \"'\") {\n for (let i = 1; i < text.length; i++) {\n if (opening === '\"' && text[i] === '\\\\') {\n i++;\n } else if (text[i] === opening) {\n if (opening === \"'\" && text[i + 1] === \"'\") {\n i++;\n } else {\n return true;\n }\n }\n }\n\n return false;\n }\n\n let depth = 0;\n let quote: string | null = null;\n\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n\n if (quote) {\n if (c === '\\\\' && quote === '\"') {\n i++;\n } else if (c === quote) {\n quote = null;\n }\n } else if (c === '\"' || c === \"'\") {\n quote = c;\n } else if (c === '[' || c === '{') {\n depth++;\n } else if (c === ']' || c === '}') {\n depth--;\n\n if (depth === 0) {\n return true;\n }\n }\n }\n\n return false;\n};\n\nconst aliasValue = (name: string, line: number): YamlValue => {\n if (!anchors.has(name)) {\n throw new YamlMiniError(`Unknown alias *${name}`, line);\n }\n\n return JSON.parse(JSON.stringify(anchors.get(name))) as YamlValue;\n};\n\nconst detectChildIndent = (lines: string[], start: number, parentIndent: number, skipComments = true): number | null => {\n for (let i = start; i < lines.length; i++) {\n const raw = lines[i];\n\n if (raw.trim() === '') {\n continue;\n }\n\n if (skipComments && raw.trimStart().startsWith('#')) {\n continue;\n }\n\n const ind = leadingSpaces(raw);\n\n if (ind <= parentIndent) {\n return null;\n }\n\n return ind;\n }\n\n return null;\n};\n\nconst nextContentLine = (lines: string[], start: number): number => {\n for (let i = start; i < lines.length; i++) {\n const raw = lines[i];\n\n if (raw.trim() !== '' && !raw.trimStart().startsWith('#')) {\n return i;\n }\n }\n\n return -1;\n};\n\nconst leadingSpaces = (line: string): number => {\n let n = 0;\n\n while (n < line.length && line[n] === ' ') {\n n++;\n }\n\n return n;\n};\n\nconst findUnquotedColon = (s: string): number => {\n let inQ: '\"' | \"'\" | null = null;\n let depth = 0;\n\n for (let i = 0; i < s.length; i++) {\n const c = s[i];\n\n if (inQ) {\n if (c === '\\\\' && inQ === '\"') {\n i++;\n continue;\n }\n\n if (c === inQ) {\n inQ = null;\n }\n } else {\n if ((c === '\"' || c === \"'\") && (i === 0 || /[\\s[{,]/.test(s[i - 1]))) {\n inQ = c;\n } else if (c === '[' || c === '{') {\n depth++;\n } else if (c === ']' || c === '}') {\n depth--;\n } else if (c === ':' && depth === 0 && (i + 1 >= s.length || s[i + 1] === ' ' || s[i + 1] === '\\t')) {\n return i;\n }\n }\n }\n\n return -1;\n};\n\nconst parseScalar = (raw: string, line: number): YamlValue => {\n if (raw === '' || raw === '~' || raw === 'null') {\n return null;\n }\n\n if (raw === 'true') {\n return true;\n }\n\n if (raw === 'false') {\n return false;\n }\n\n if (/^-?\\d+$/.test(raw)) {\n return parseInt(raw, 10);\n }\n\n if (/^-?\\d*\\.\\d+$/.test(raw)) {\n return parseFloat(raw);\n }\n\n // Exponents, as YAML 1.2's core schema has them: `1e3`, `1.5E-2`.\n if (/^-?(?:\\d+\\.?\\d*|\\.\\d+)[eE][-+]?\\d+$/.test(raw)) {\n return parseFloat(raw);\n }\n\n if (raw.startsWith('\"')) {\n return parseDoubleQuoted(raw, line);\n }\n\n if (raw.startsWith(\"'\")) {\n return parseSingleQuoted(raw, line);\n }\n\n if (raw.startsWith('[') || raw.startsWith('{')) {\n return parseFlow(raw, line);\n }\n\n if (/^\\*[^\\s,[\\]{}]+$/.test(raw)) {\n return aliasValue(raw.slice(1), line);\n }\n\n return raw;\n};\n\n/** A flow value: `[a, b]`, `{name: Ana}`, and any mix of them. */\nconst parseFlow = (raw: string, line: number): YamlValue => {\n const reader = { text: raw, at: 0 };\n const value = readFlow(reader, line);\n skipFlowSpace(reader);\n\n if (reader.at < raw.length) {\n throw new YamlMiniError(raw[0] === '[' ? 'Unterminated flow array' : 'Unexpected text after a flow value', line);\n }\n\n return value;\n};\n\ninterface FlowReader {\n text: string;\n at: number;\n}\n\nconst skipFlowSpace = (reader: FlowReader): void => {\n while (reader.at < reader.text.length && /\\s/.test(reader.text[reader.at])) {\n reader.at++;\n }\n};\n\nconst readFlow = (reader: FlowReader, line: number): YamlValue => {\n skipFlowSpace(reader);\n const c = reader.text[reader.at];\n\n if (c === '[') {\n reader.at++;\n const items: YamlValue[] = [];\n\n for (;;) {\n skipFlowSpace(reader);\n\n if (reader.at >= reader.text.length) {\n throw new YamlMiniError('Unterminated flow array', line);\n }\n\n if (reader.text[reader.at] === ']') {\n reader.at++;\n return items;\n }\n\n items.push(readFlow(reader, line));\n skipFlowSpace(reader);\n\n if (reader.text[reader.at] === ',') {\n reader.at++;\n } else if (reader.text[reader.at] !== ']') {\n throw new YamlMiniError('Unterminated flow array', line);\n }\n }\n }\n\n if (c === '{') {\n reader.at++;\n const map: Record<string, YamlValue> = {};\n\n for (;;) {\n skipFlowSpace(reader);\n\n if (reader.at >= reader.text.length) {\n throw new YamlMiniError('Unterminated flow map', line);\n }\n\n if (reader.text[reader.at] === '}') {\n reader.at++;\n return map;\n }\n\n const key = readFlowScalar(reader, line, true);\n skipFlowSpace(reader);\n let value: YamlValue = null;\n\n if (reader.text[reader.at] === ':') {\n reader.at++;\n skipFlowSpace(reader);\n value = reader.text[reader.at] === ',' || reader.text[reader.at] === '}' ? null : readFlow(reader, line);\n }\n\n assignKey(map, String(key), value);\n skipFlowSpace(reader);\n\n if (reader.text[reader.at] === ',') {\n reader.at++;\n } else if (reader.text[reader.at] !== '}') {\n throw new YamlMiniError('Unterminated flow map', line);\n }\n }\n }\n\n return readFlowScalar(reader, line, false);\n};\n\n/** A scalar inside a flow value: quoted, or plain up to `,` `]` `}` (and, for a key, `: `). */\nconst readFlowScalar = (reader: FlowReader, line: number, key: boolean): YamlValue => {\n const { text } = reader;\n const start = reader.at;\n const c = text[start];\n\n if (c === '\"' || c === \"'\") {\n let end = start + 1;\n\n while (end < text.length) {\n if (c === '\"' && text[end] === '\\\\') {\n end += 2;\n continue;\n }\n\n if (text[end] === c) {\n if (c === \"'\" && text[end + 1] === \"'\") {\n end += 2;\n continue;\n }\n\n break;\n }\n\n end++;\n }\n\n reader.at = end + 1;\n return parseScalar(text.slice(start, end + 1), line);\n }\n\n let end = start;\n\n while (end < text.length) {\n const here = text[end];\n\n if (here === ',' || here === ']' || here === '}') {\n break;\n }\n\n if (key && here === ':' && (end + 1 >= text.length || /[\\s,}\\]]/.test(text[end + 1]))) {\n break;\n }\n\n end++;\n }\n\n reader.at = end;\n const plain = text.slice(start, end).trim();\n return key ? plain : parseScalar(plain, line);\n};\n\nconst DOUBLE_QUOTE_ESCAPES: Record<string, string> = {\n '\"': '\"', '\\\\': '\\\\', '/': '/', b: '\\b', f: '\\f', n: '\\n', r: '\\r', t: '\\t', '0': '\\0',\n};\n\nconst parseDoubleQuoted = (raw: string, line: number): string => {\n if (!raw.endsWith('\"') || raw.length < 2) {\n throw new YamlMiniError('Unterminated string', line);\n }\n\n const body = raw.slice(1, -1);\n let out = '';\n\n for (let i = 0; i < body.length; i++) {\n const c = body[i];\n\n if (c !== '\\\\') {\n out += c;\n continue;\n }\n\n const next = body[++i];\n\n if (next === undefined) {\n throw new YamlMiniError('Dangling escape in string', line);\n }\n\n if (next === 'u') {\n const hex = body.slice(i + 1, i + 5);\n\n if (!/^[0-9a-fA-F]{4}$/.test(hex)) {\n throw new YamlMiniError('Invalid \\\\u escape', line);\n }\n\n out += String.fromCharCode(parseInt(hex, 16));\n i += 4;\n continue;\n }\n\n out += DOUBLE_QUOTE_ESCAPES[next] ?? next;\n }\n\n return out;\n};\n\nconst parseSingleQuoted = (raw: string, line: number): string => {\n if (!raw.endsWith(\"'\") || raw.length < 2) {\n throw new YamlMiniError('Unterminated string', line);\n }\n\n return raw.slice(1, -1).replace(/''/g, \"'\");\n};\n\n// Emitter\n\nexport const emitYaml = (value: YamlValue): string => {\n return emit(value, 0).trimEnd() + '\\n';\n};\n\nconst emit = (value: YamlValue, indent: number): string => {\n if (value === null) {\n return 'null\\n';\n }\n\n if (typeof value === 'boolean') {\n return `${value}\\n`;\n }\n\n if (typeof value === 'number') {\n return `${value}\\n`;\n }\n\n if (typeof value === 'string') {\n return emitString(value, indent);\n }\n\n if (Array.isArray(value)) {\n return emitArray(value, indent);\n }\n\n return emitMap(value, indent);\n};\n\n/**\n * A string can be emitted as a `|` literal block only when the parser will\n * reconstruct it exactly: the first content line anchors the block's child\n * indent (so it must not start with whitespace), whitespace-only lines and\n * trailing blank lines are normalized away by the parser, and `\\r` would be\n * normalized to `\\n`. Anything else must be JSON-quoted.\n */\nconst blockScalarSafe = (s: string): boolean => {\n // \"-->\" would end the HTML comment the YAML is written in; quoted, it can be escaped.\n if (s.includes('\\r') || /--!?>/.test(s)) {\n return false;\n }\n\n const lines = s.split('\\n');\n\n if (lines[lines.length - 1].trim() === '') {\n return false;\n }\n\n const firstContent = lines.find((l) => l.trim() !== '');\n\n if (firstContent === undefined || /^[ \\t]/.test(firstContent)) {\n return false;\n }\n\n // A content line that trims to `---` would close the markdown frontmatter\n // around the YAML early: findFrontmatter compares trimmed lines.\n if (lines.some((line) => line.trim() === '---')) {\n return false;\n }\n\n return !lines.some((l) => /^[ \\t]+$/.test(l));\n};\n\nconst emitMultiline = (v: string, keyPrefix: string, blockIndent: number): string => {\n if (blockScalarSafe(v)) {\n const pad = ' '.repeat(blockIndent);\n let out = `${keyPrefix} |\\n`;\n\n for (const line of v.split('\\n')) {\n out += `${pad}${line}\\n`;\n }\n\n return out;\n }\n\n return `${keyPrefix} ${JSON.stringify(v)}\\n`;\n};\n\nconst emitMap = (obj: { [k: string]: YamlValue }, indent: number): string => {\n const pad = ' '.repeat(indent);\n let out = '';\n\n for (const [key, v] of Object.entries(obj)) {\n if (v === undefined) {\n continue;\n } // treat like JSON.stringify: key is absent\n\n const writtenKey = formatKey(key);\n\n if (v === null) {\n out += `${pad}${writtenKey}: null\\n`;\n continue;\n }\n\n if (typeof v === 'string') {\n if (v.includes('\\n')) {\n out += emitMultiline(v, `${pad}${writtenKey}:`, indent + 2);\n } else {\n out += `${pad}${writtenKey}: ${needsQuotes(v) ? JSON.stringify(v) : v}\\n`;\n }\n } else if (typeof v === 'number' || typeof v === 'boolean') {\n out += `${pad}${writtenKey}: ${v}\\n`;\n } else if (Array.isArray(v)) {\n if (v.length === 0) {\n out += `${pad}${writtenKey}: []\\n`;\n continue;\n }\n\n const allScalar = v.every((x) => typeof x === 'string' || typeof x === 'number' || typeof x === 'boolean');\n\n if (allScalar && v.every((x) => typeof x !== 'string' || !needsQuotes(x as string))) {\n out += `${pad}${writtenKey}: [${v.map((x) => formatScalar(x as YamlValue)).join(', ')}]\\n`;\n } else {\n out += `${pad}${writtenKey}:\\n${emitArray(v, indent + 2)}`;\n }\n } else if (Object.values(v).some((item) => item !== undefined)) {\n out += `${pad}${writtenKey}:\\n${emit(v, indent + 2)}`;\n } else {\n // An empty map: written as a flow value, or it would read back as null.\n out += `${pad}${writtenKey}: {}\\n`;\n }\n }\n\n return out;\n};\n\nconst emitArray = (arr: YamlValue[], indent: number): string => {\n const pad = ' '.repeat(indent);\n let out = '';\n\n for (const item of arr) {\n if (item !== null && typeof item === 'object' && !Array.isArray(item)) {\n const entries = Object.entries(item).filter(([, v]) => v !== undefined);\n\n if (entries.length === 0) {\n out += `${pad}- {}\\n`;\n continue;\n }\n\n const [firstKey, firstVal] = entries[0];\n\n if (keyNeedsQuotes(firstKey)) {\n // A quoted key can't start the `- ` line: it would read as a scalar item.\n out += `${pad}-\\n${emitMap(item, indent + 2)}`;\n continue;\n }\n\n if (firstVal !== null && typeof firstVal === 'object') {\n const flow = emptyCollection(firstVal);\n out += flow === null ? `${pad}- ${firstKey}:\\n${emit(firstVal, indent + 4)}` : `${pad}- ${firstKey}: ${flow}\\n`;\n } else if (typeof firstVal === 'string' && firstVal.includes('\\n')) {\n out += emitMultiline(firstVal, `${pad}- ${firstKey}:`, indent + 4);\n } else {\n out += `${pad}- ${firstKey}: ${formatScalar(firstVal)}\\n`;\n }\n\n for (const [k, v] of entries.slice(1)) {\n const writtenKey = formatKey(k);\n\n if (v !== null && typeof v === 'object' && !Array.isArray(v)) {\n const flow = emptyCollection(v);\n out += flow === null ? `${pad} ${writtenKey}:\\n${emit(v, indent + 4)}` : `${pad} ${writtenKey}: ${flow}\\n`;\n } else if (Array.isArray(v)) {\n if (v.length === 0) {\n out += `${pad} ${writtenKey}: []\\n`;\n }\n else {\n const allScalar = v.every((x) => typeof x !== 'object' || x === null);\n\n if (allScalar) {\n out += `${pad} ${writtenKey}: [${v.map((x) => formatScalar(x as YamlValue)).join(', ')}]\\n`;\n }\n else {\n out += `${pad} ${writtenKey}:\\n${emitArray(v, indent + 4)}`;\n }\n }\n } else if (typeof v === 'string' && v.includes('\\n')) {\n out += emitMultiline(v, `${pad} ${writtenKey}:`, indent + 4);\n } else {\n out += `${pad} ${writtenKey}: ${formatScalar(v)}\\n`;\n }\n }\n } else {\n out += `${pad}- ${formatScalar(item)}\\n`;\n }\n }\n\n return out;\n};\n\n/** A map or list with nothing in it, written as a flow value so it doesn't read back as null. */\nconst emptyCollection = (value: YamlValue): string | null => {\n if (Array.isArray(value)) {\n return value.length === 0 ? '[]' : null;\n }\n\n if (typeof value !== 'object' || value === null) {\n return null;\n }\n\n return Object.values(value).some((item) => item !== undefined) ? null : '{}';\n};\n\n/**\n * A key as written: plain when the parser hands it back unchanged, quoted\n * when it wouldn't (`a: b`, ` padded `, `- item`, a quote of its own first).\n */\nconst formatKey = (key: string): string => {\n return keyNeedsQuotes(key) ? JSON.stringify(key) : key;\n};\n\nconst keyNeedsQuotes = (key: string): boolean => {\n if (key === '' || key !== key.trim() || /^[\"']/.test(key) || /^-(\\s|$)/.test(key)) {\n return true;\n }\n\n // Control characters survive only via double-quote escapes.\n // eslint-disable-next-line no-control-regex\n if (/[\\u0000-\\u001F\\u007F]/.test(key)) {\n return true;\n }\n\n // The parser must find the colon that ends the key, not one inside it.\n return findUnquotedColon(`${key}: x`) !== key.length;\n};\n\nconst emitString = (s: string, indent: number): string => {\n if (s.includes('\\n')) {\n if (!blockScalarSafe(s)) {\n return `${JSON.stringify(s)}\\n`;\n }\n\n const pad = ' '.repeat(indent);\n return '|\\n' + s.split('\\n').map((l) => pad + l).join('\\n') + '\\n';\n }\n\n return needsQuotes(s) ? `${JSON.stringify(s)}\\n` : `${s}\\n`;\n};\n\nconst formatScalar = (v: YamlValue): string => {\n if (v === null) {\n return 'null';\n }\n\n if (typeof v === 'string') {\n return needsQuotes(v) ? JSON.stringify(v) : v;\n }\n\n return String(v);\n};\n\n/**\n * Words and numbers other YAML readers take for something besides text:\n * YAML 1.1 booleans (`yes`, `On`), nulls, and numbers in any notation.\n */\nconst NOT_TEXT_ELSEWHERE = /^(?:y|n|yes|no|on|off|true|false|null|~)$|^[-+]?(?:\\.?\\d|\\.(?:inf|nan)$)|^0[xob]/i;\n\n/**\n * Whether a string written plain would read back as itself: no when other\n * YAML readers would take it for a number or boolean, and no when this\n * parser itself would hand back something else. Used by the emitter.\n */\nexport const needsQuotes = (s: string): boolean => {\n if (s === '' || NOT_TEXT_ELSEWHERE.test(s)) {\n return true;\n }\n\n // Anything this reader wouldn't hand back as the same text, written plain.\n try {\n if (parseScalar(s, 0) !== s) {\n return true;\n }\n } catch {\n return true;\n }\n\n if (/[:,#[{}&*!|>'\"%@`]/.test(s)) {\n return true;\n }\n\n if (/^[ ]|[ ]$/.test(s)) {\n return true;\n }\n\n // Control characters (\\r, \\t, ...) survive only via double-quote escapes.\n // eslint-disable-next-line no-control-regex\n if (/[\\u0000-\\u001F\\u007F]/.test(s)) {\n return true;\n }\n\n return false;\n};\n\n/**\n * Whether a one-line value written plain after `key:` reads back as the same\n * string through this parser: no anchors (`&a`), aliases (`*a`), block-scalar\n * starts (`|`, `>+`), comments (` #`), or scalars read as something else\n * (`~`, `.5`). Unlike `needsQuotes` this ignores what *other* YAML readers\n * would do; markdown-writing uses it for values inside `<!-- orbit … -->`\n * comments, which only Orbit reads.\n */\nexport const plainScalarReadsBack = (s: string): boolean => {\n if (s === '' || s !== s.trim()) {\n return false;\n }\n\n if (stripComment(s) !== s) {\n return false;\n }\n\n if (/^&[^\\s,[\\]{}]+/.test(s) || /^\\*[^\\s,[\\]{}]+$/.test(s) || /^[|>][-+]?\\d?$/.test(s)) {\n return false;\n }\n\n try {\n return parseScalar(s, 0) === s;\n } catch {\n return false;\n }\n};\n",
|
|
7
7
|
"import type { OrbitNode } from './types.js';\n\nexport const slugify = (value: string): string => {\n const slug = foldAccents(value)\n .toLowerCase()\n .trim()\n .replace(/[^\\p{L}\\p{N}]+/gu, '-')\n .replace(/^-+|-+$/g, '');\n\n return slug || 'node';\n};\n\n/**\n * Drops accents from Latin, Greek and Cyrillic letters (\"Investigación\" becomes\n * \"Investigacion\") and folds compatibility forms (full-width letters,\n * ligatures) while leaving other scripts intact, so ids stay readable in\n * any language.\n */\nconst foldAccents = (value: string): string => {\n return value\n .normalize('NFKD')\n .replace(/([\\p{Script=Latin}\\p{Script=Greek}\\p{Script=Cyrillic}])\\p{M}+/gu, '$1')\n .normalize('NFC');\n};\n\n/**\n * Slug used for auto-generated node ids in both parsers and for detecting\n * explicit ids in both serializers (`nodesWithExplicitIds`), which is why\n * it lives here.\n */\nexport const nodeSlug = (text: string): string => {\n return (\n Array.from(\n foldAccents(text)\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\s_-]/gu, '')\n .trim()\n .replace(/\\s+/g, '-'),\n )\n .slice(0, 64)\n .join('') || 'node'\n );\n};\n\n/**\n * Links a node to its parent. The link is non-enumerable so a parsed tree\n * stays a plain tree for `JSON.stringify`, spreads and structured clones.\n */\nexport const setParent = (node: OrbitNode, parent: OrbitNode | undefined): void => {\n Object.defineProperty(node, 'parent', { value: parent, writable: true, configurable: true, enumerable: false });\n};\n\n/**\n * Hands out node ids in document order, the way the parsers number them:\n * an id stays as it is the first time, and repeats become `id-2`, `id-3`….\n */\nconst nodeIdAllocator = (): { peek(base: string): string; take(base: string): string } => {\n const used = new Set<string>();\n const nextSuffix = new Map<string, number>();\n\n const candidate = (base: string): { id: string; suffix?: number } => {\n if (!used.has(base)) {\n return { id: base };\n }\n\n let suffix = nextSuffix.get(base) ?? 2;\n\n while (used.has(`${base}-${suffix}`)) {\n suffix += 1;\n }\n\n return { id: `${base}-${suffix}`, suffix };\n };\n\n return {\n peek: (base) => candidate(base).id,\n take: (base) => {\n const { id, suffix } = candidate(base);\n used.add(id);\n nextSuffix.set(base, suffix === undefined ? 2 : suffix + 1);\n return id;\n },\n };\n};\n\nexport const ensureUniqueNodeIds = (root: OrbitNode): void => {\n const ids = nodeIdAllocator();\n\n const walk = (node: OrbitNode): void => {\n node.id = ids.take(node.id.trim() || slugify(node.text));\n\n for (const child of node.children) {\n walk(child);\n }\n };\n\n walk(root);\n};\n\n/**\n * The nodes whose ids a serializer has to write: those the parsers wouldn't\n * give them from their text. A second \"Research\" reads back as\n * `research-2` on its own, so it needs no id attribute.\n */\nexport const nodesWithExplicitIds = (root: OrbitNode): Set<OrbitNode> => {\n const ids = nodeIdAllocator();\n const explicit = new Set<OrbitNode>();\n\n const walk = (node: OrbitNode): void => {\n const fromText = nodeSlug(node.text);\n\n if (ids.peek(fromText) === node.id) {\n ids.take(fromText);\n } else {\n explicit.add(node);\n ids.take(node.id);\n }\n\n for (const child of node.children) {\n walk(child);\n }\n };\n\n walk(root);\n return explicit;\n};\n\nexport const findNodeById = (root: OrbitNode, id: string): OrbitNode | null => {\n if (root.id === id) {\n return root;\n }\n\n for (const child of root.children) {\n const found = findNodeById(child, id);\n\n if (found) {\n return found;\n }\n }\n\n return null;\n};\n\nexport const getNodePath = (root: OrbitNode, id: string): OrbitNode[] => {\n const path: OrbitNode[] = [];\n\n const walk = (node: OrbitNode, current: OrbitNode[]): boolean => {\n const next = [...current, node];\n\n if (node.id === id) {\n path.push(...next);\n return true;\n }\n\n for (const child of node.children) {\n if (walk(child, next)) {\n return true;\n }\n }\n\n return false;\n };\n\n walk(root, []);\n return path;\n};\n\nexport const clamp = (value: number, min: number, max: number): number => {\n return Math.max(min, Math.min(max, value));\n};\n",
|
|
8
8
|
"/**\n * URL guard for Orbit. Validates the scheme per render surface, lets\n * relative URLs through unchanged, and resolves them against an optional\n * baseUrl.\n */\n\nexport type UrlSurface = 'image' | 'video' | 'embed' | 'link';\n\nconst warned = new Set<string>();\nconst WARN_LIMIT = 500;\n\n/**\n * A URL as browsers read it: without the control characters and spaces at\n * its ends, and without tabs and line breaks anywhere. The URL standard drops\n * them before it reads the scheme, so \" javascript:\" and \"java\\tscript:\"\n * are both \"javascript:\" to a browser.\n */\nexport const normalizeUrl = (url: string): string => {\n // eslint-disable-next-line no-control-regex\n return url.replace(/^[\\u0000-\\u0020]+|[\\u0000-\\u0020]+$/g, '').replace(/[\\t\\n\\r]/g, '');\n};\n\n/**\n * The URL to use on `surface`, or null when its scheme isn't allowed there.\n * Checks the URL the way a browser will read it, and returns it in that form.\n * A blocked URL is reported on the console, unless `report` is false: for\n * checking one before it goes into a map.\n */\nexport const guardUrl = (input: string, surface: UrlSurface, report = true): string | null => {\n const warn = report ? warnOnce : () => undefined;\n const url = normalizeUrl(input);\n\n // Protocol-relative URLs (//host/path) are absolute on a base; route through the allowlist.\n if (url.startsWith('//')) {\n const probe = `https:${url}`;\n let parsed: URL;\n\n try {\n parsed = new URL(probe);\n } catch {\n warn(url, 'unparseable URL');\n return null;\n }\n\n if (!schemeAllowed('https', surface, parsed)) {\n warn(url, `surface \"${surface}\" forbidden`);\n return null;\n }\n\n return url;\n }\n\n if (!hasScheme(url)) {\n return url;\n }\n\n let parsed: URL;\n\n try {\n parsed = new URL(url);\n } catch {\n warn(url, 'unparseable URL');\n return null;\n }\n\n const scheme = parsed.protocol.replace(/:$/, '');\n\n if (!schemeAllowed(scheme, surface, parsed)) {\n warn(url, `surface \"${surface}\" forbidden`);\n return null;\n }\n\n return url;\n};\n\nconst hasScheme = (url: string): boolean => {\n return /^[a-z][a-z0-9+.-]*:/i.test(url);\n};\n\nconst schemeAllowed = (scheme: string, surface: UrlSurface, parsed: URL): boolean => {\n if (scheme === 'http' || scheme === 'https') {\n return true;\n }\n\n if (scheme === 'data' && surface === 'image') {\n return /^data:image\\/(png|jpeg|jpg|gif|webp|avif|bmp|ico);/i.test(parsed.href);\n }\n\n if (scheme === 'blob') {\n return surface === 'image' || surface === 'video';\n }\n\n if (scheme === 'mailto' || scheme === 'tel' || scheme === 'sms') {\n return surface === 'link';\n }\n\n return false;\n};\n\nconst warnOnce = (url: string, why: string): void => {\n if (warned.has(url)) {\n return;\n }\n\n if (warned.size >= WARN_LIMIT) {\n return;\n }\n\n warned.add(url);\n\n if (typeof console !== 'undefined') {\n console.warn(`[orbit] blocked URL (${why}): ${url}`);\n }\n};\n\n/**\n * Resolve a baseUrl string to its canonical absolute href.\n *\n * - Absolute baseUrls (`https://example.com/assets/`) are returned as `URL().href`.\n * - Relative baseUrls (`/assets/`, `./foo/`) are resolved against `document.baseURI` in browsers.\n * - Throws if baseUrl is relative and no `document.baseURI` is available (Node/SSR).\n */\nexport const resolveBaseUrl = (baseUrl: string): string => {\n try {\n return new URL(baseUrl).href;\n } catch {\n if (typeof document !== 'undefined' && document.baseURI) {\n return new URL(baseUrl, document.baseURI).href;\n }\n\n throw new Error(\n `RendererOptions.baseUrl is relative (\"${baseUrl}\") and no document.baseURI is available. ` +\n `Provide an absolute baseUrl when running outside a browser document context.`,\n );\n }\n};\n\n/**\n * Resolve `url` against `baseUrl` if relative; pass through if absolute or no baseUrl.\n *\n * - Absolute URLs (https://, http://, etc.) pass through unchanged.\n * - Protocol-relative URLs (//host/path) are treated as already-absolute (resolved by the browser at fetch time).\n * - Relative URLs (foo.jpg, ./x, /assets/y) are resolved against `baseUrl`.\n *\n * For directory-relative resolution, `baseUrl` should end with `/`.\n * Per WHATWG URL spec, `new URL('foo.jpg', 'https://x/dir')` yields `https://x/foo.jpg`\n * (the trailing path segment is consumed); `new URL('foo.jpg', 'https://x/dir/')` yields `https://x/dir/foo.jpg`.\n */\nexport const resolveUrl = (url: string, baseUrl: string | undefined): string => {\n if (!baseUrl) {\n return url;\n }\n\n if (url.startsWith('//')) {\n return url;\n }\n\n try {\n new URL(url);\n return url; // already absolute\n } catch {\n const base = resolveBaseUrl(baseUrl);\n return new URL(url, base).href;\n }\n};\n",
|
|
9
9
|
"/**\n * Video provider helpers shared by the parser (provider detection), the\n * renderer (thumbnail derivation), and the detail sheet and media viewer\n * (embed URL conversion, and links to a video's page on its site).\n *\n * YouTube and Vimeo forbid framing their watch pages (X-Frame-Options /\n * frame-ancestors); only the dedicated embed endpoints may be iframed, so\n * anything that puts a video URL into an <iframe> must go through\n * `toVideoEmbedUrl` first.\n */\n\nimport { normalizeUrl } from './url-guard.js';\n\nexport type VideoProvider = 'youtube' | 'vimeo' | 'native';\n\nconst YOUTUBE_HOSTS = new Set(['youtube.com', 'www.youtube.com', 'm.youtube.com', 'music.youtube.com', 'youtube-nocookie.com', 'www.youtube-nocookie.com', 'youtu.be']);\nconst VIMEO_HOSTS = new Set(['vimeo.com', 'www.vimeo.com', 'player.vimeo.com']);\nconst NATIVE_VIDEO = /\\.(mp4|webm|mov)(?:[?#]|$)/i;\n/** A YouTube or Vimeo address written without its scheme, such as `youtu.be/…`. */\nconst BARE_HOST = /^(?:(?:www|m|music|player)\\.)?(?:youtube\\.com|youtube-nocookie\\.com|youtu\\.be|vimeo\\.com)\\//i;\nconst YOUTUBE_ID = /^[A-Za-z0-9_-]{6,}$/;\n\n/** A web address, by its parts; null for relative URLs and other schemes. */\nconst webUrl = (url: string): URL | null => {\n const text = normalizeUrl(url);\n const absolute = text.startsWith('//') ? `https:${text}` : BARE_HOST.test(text) ? `https://${text}` : text;\n\n try {\n const parsed = new URL(absolute);\n return parsed.protocol === 'https:' || parsed.protocol === 'http:' ? parsed : null;\n } catch {\n return null;\n }\n};\n\n/** Which player a video URL needs, by the site it is on; null when it isn't a video. */\nexport const detectVideoProvider = (url: string): VideoProvider | null => {\n const parsed = webUrl(url);\n const host = parsed?.hostname.toLowerCase();\n\n if (host && YOUTUBE_HOSTS.has(host)) {\n return 'youtube';\n }\n\n if (host && VIMEO_HOSTS.has(host)) {\n return 'vimeo';\n }\n\n if (NATIVE_VIDEO.test(parsed ? parsed.pathname : url)) {\n return 'native';\n }\n\n return null;\n};\n\nexport const isNativeVideoUrl = (url: string): boolean => {\n return NATIVE_VIDEO.test(url);\n};\n\n/** The video id in any of YouTube's URL shapes: watch pages, youtu.be, embeds, Shorts and lives. */\nexport const youtubeVideoId = (url: string): string | null => {\n const parsed = webUrl(url);\n const host = parsed?.hostname.toLowerCase();\n\n if (!parsed || !host || !YOUTUBE_HOSTS.has(host)) {\n return null;\n }\n\n const segments = parsed.pathname.split('/').filter(Boolean);\n let id: string | null | undefined;\n\n if (host === 'youtu.be') {\n id = segments[0];\n } else if (segments[0] === 'watch') {\n id = parsed.searchParams.get('v');\n } else if (['embed', 'shorts', 'live', 'v'].includes(segments[0])) {\n id = segments[1];\n }\n\n return id && YOUTUBE_ID.test(id) ? id : null;\n};\n\n/**\n * A Vimeo video's id, and the hash an unlisted video needs, from its page\n * (`vimeo.com/123`, `/123/abc`, channels, groups, showcases) or its player.\n */\nexport const vimeoVideo = (url: string): { id: string; hash?: string } | null => {\n const parsed = webUrl(url);\n const host = parsed?.hostname.toLowerCase();\n\n if (!parsed || !host || !VIMEO_HOSTS.has(host)) {\n return null;\n }\n\n const segments = parsed.pathname.split('/').filter(Boolean);\n const hash = (value: string | null | undefined) => (value && /^[0-9a-f]{6,}$/i.test(value) ? value : undefined);\n\n if (host === 'player.vimeo.com') {\n return segments[0] === 'video' && /^\\d+$/.test(segments[1] ?? '') ? { id: segments[1], hash: hash(parsed.searchParams.get('h')) } : null;\n }\n\n if (/^\\d+$/.test(segments[0] ?? '')) {\n return { id: segments[0], hash: hash(segments[1]) };\n }\n\n let index = -1;\n\n if (segments[0] === 'video') {\n index = 1;\n } else if (segments[0] === 'channels') {\n index = 2;\n } else if (segments[0] === 'groups' && segments[2] === 'videos') {\n index = 3;\n } else if ((segments[0] === 'album' || segments[0] === 'showcase') && segments[2] === 'video') {\n index = 3;\n }\n\n const id = index > 0 ? segments[index] : undefined;\n return id && /^\\d+$/.test(id) ? { id, hash: hash(segments[index + 1]) } : null;\n};\n\n/** The numeric id of a Vimeo video. */\nexport const vimeoVideoId = (url: string): string | null => {\n return vimeoVideo(url)?.id ?? null;\n};\n\n/**\n * Convert a video URL to a frameable embed URL. Returns null when no\n * conversion is known (callers fall back to the original URL).\n */\nexport const toVideoEmbedUrl = (url: string, provider?: string): string | null => {\n const kind = provider === 'youtube' || provider === 'vimeo' ? provider : detectVideoProvider(url);\n\n if (kind === 'youtube') {\n const id = youtubeVideoId(url);\n return id ? `https://www.youtube-nocookie.com/embed/${id}` : null;\n }\n\n if (kind === 'vimeo') {\n const video = vimeoVideo(url);\n return video ? `https://player.vimeo.com/video/${video.id}${video.hash ? `?h=${video.hash}` : ''}` : null;\n }\n\n return null;\n};\n\n/** Whether a YouTube URL is a Short, a video that plays upright. */\nexport const isYouTubeShort = (url: string): boolean => {\n const parsed = webUrl(url);\n return parsed !== null && YOUTUBE_HOSTS.has(parsed.hostname.toLowerCase()) && parsed.pathname.split('/').filter(Boolean)[0] === 'shorts';\n};\n\n/** Where a video is watched on its site: its YouTube or Vimeo page, or the URL itself. */\nexport const videoPageUrl = (url: string, provider?: string): string => {\n const kind = provider === 'youtube' || provider === 'vimeo' ? provider : detectVideoProvider(url);\n\n if (kind === 'youtube') {\n const id = youtubeVideoId(url);\n\n if (id) {\n return isYouTubeShort(url) ? `https://www.youtube.com/shorts/${id}` : `https://www.youtube.com/watch?v=${id}`;\n }\n }\n\n if (kind === 'vimeo') {\n const video = vimeoVideo(url);\n\n if (video) {\n return `https://vimeo.com/${video.id}${video.hash ? `/${video.hash}` : ''}`;\n }\n }\n\n return url;\n};\n\nexport const youtubeThumbnailUrl = (url: string): string | null => {\n const id = youtubeVideoId(url);\n return id ? `https://img.youtube.com/vi/${id}/hqdefault.jpg` : null;\n};\n\n/** True when an image, video or embed value has a usable `src`. */\nexport const hasMediaSource = (media: { src?: unknown } | undefined | null): media is { src: string } => {\n return Boolean(media) && typeof media!.src === 'string' && media!.src.trim() !== '';\n};\n",
|
|
10
10
|
"/**\n * Parse diagnostics. Parsers are forgiving by default: a problem they can\n * recover from is recorded as a diagnostic and parsing continues. In strict\n * mode (`{ strict: true }`, used by `orbit validate`) the first such\n * problem throws an `OrbitParseError` instead.\n */\n\nimport type { OrbitDocument } from './types.js';\n\n/** Every kind of problem the parsers report. */\nexport const DIAGNOSTIC_CODES = [\n 'empty-document',\n 'no-structure',\n 'synthetic-root',\n 'invalid-frontmatter',\n 'unknown-frontmatter-key',\n 'unsupported-schema-version',\n 'format-upgraded',\n 'invalid-attributes',\n 'unknown-attribute',\n 'invalid-option-value',\n 'media-missing-source',\n 'unknown-content-type',\n 'caption-without-media',\n 'unknown-link-target',\n 'invalid-yaml',\n 'unknown-yaml-key',\n 'ignored-node-entry',\n 'misnamed-node-key',\n 'comment-without-orbit',\n 'attributes-after-list',\n] as const;\n\nexport type OrbitDiagnosticCode = (typeof DIAGNOSTIC_CODES)[number];\n\nexport type OrbitDiagnosticSeverity = 'error' | 'warning';\n\nexport interface OrbitDiagnostic {\n code: OrbitDiagnosticCode;\n message: string;\n\n /** 1-based line in the source passed to the parser, when known. */\n line?: number;\n\n severity: OrbitDiagnosticSeverity;\n}\n\nexport class OrbitParseError extends Error {\n readonly code: OrbitDiagnosticCode;\n readonly line: number;\n\n constructor(message: string, line: number, code: OrbitDiagnosticCode = 'invalid-yaml') {\n super(`${message} at line ${line}`);\n this.name = 'OrbitParseError';\n this.line = line;\n this.code = code;\n }\n}\n\nexport const formatDiagnostic = (diagnostic: OrbitDiagnostic): string => {\n return diagnostic.line === undefined ? diagnostic.message : `Line ${diagnostic.line}: ${diagnostic.message}`;\n};\n\n/**\n * Reports a parsed document's problems to the console, the same signal from\n * every entry point: each error as an error, then the other problems as one\n * warning. A document without diagnostics reports its warnings alone.\n */\nexport const reportParseDiagnostics = (doc: OrbitDocument): void => {\n if (typeof console === 'undefined') {\n return;\n }\n\n const diagnostics = doc.diagnostics;\n const warnings = diagnostics ? diagnostics.filter((diagnostic) => diagnostic.severity !== 'error').map(formatDiagnostic) : doc.warnings;\n\n for (const diagnostic of diagnostics ?? []) {\n if (diagnostic.severity === 'error') {\n console.error(`[orbit] ${formatDiagnostic(diagnostic)}`);\n }\n }\n\n if (warnings.length > 0) {\n console.warn(`[orbit] parse warnings:\\n- ${warnings.join('\\n- ')}`);\n }\n};\n\nexport class DiagnosticCollector {\n readonly diagnostics: OrbitDiagnostic[] = [];\n private readonly strict: boolean;\n\n constructor(strict: boolean) {\n this.strict = strict;\n }\n\n /** A problem the parser works around: thrown in strict mode, recorded otherwise. */\n recover(code: OrbitDiagnosticCode, message: string, line?: number, severity: OrbitDiagnosticSeverity = 'warning'): void {\n if (this.strict) {\n throw new OrbitParseError(message, line ?? 1, code);\n }\n\n this.diagnostics.push({ code, message, line, severity });\n }\n\n /** Worth knowing but never fatal, even in strict mode. */\n note(code: OrbitDiagnosticCode, message: string, line?: number): void {\n this.diagnostics.push({ code, message, line, severity: 'warning' });\n }\n\n get warnings(): string[] {\n return this.diagnostics.map(formatDiagnostic);\n }\n}\n",
|
|
11
11
|
"/**\n * Source text helpers shared by the dispatcher and both parsers. Normalizing\n * never adds or removes lines, so diagnostics keep pointing at the line the\n * author wrote.\n */\n\n/**\n * Strips a byte-order mark, converts CRLF/CR line endings to LF, and removes\n * indentation shared by every non-blank line, so markdown indented inside\n * HTML or a template literal parses like flush-left markdown.\n */\nexport const normalizeSource = (input: string): string => {\n // Only a byte-order mark at the start: U+FEFF inside the text is a zero-width no-break space, and kept.\n const text = input.replace(/^\\uFEFF/, '').replace(/\\r\\n?/g, '\\n');\n return dedent(text);\n};\n\n/** The indentation every non-blank line shares, which `normalizeSource` removes. */\nexport const sharedIndentation = (text: string): string => {\n let common: string | null = null;\n\n for (const line of text.split('\\n')) {\n if (line.trim() === '') {\n continue;\n }\n\n const indent = /^[ \\t]*/.exec(line)![0];\n\n if (common === null) {\n common = indent;\n continue;\n }\n\n let length = 0;\n\n while (length < common.length && length < indent.length && common[length] === indent[length]) {\n length += 1;\n }\n\n common = common.slice(0, length);\n\n if (common === '') {\n return '';\n }\n }\n\n return common ?? '';\n};\n\nexport const dedent = (text: string): string => {\n const lines = text.split('\\n');\n let common: string | null = null;\n\n for (const line of lines) {\n if (line.trim() === '') {\n continue;\n }\n\n const indent = /^[ \\t]*/.exec(line)![0];\n\n if (common === null) {\n common = indent;\n continue;\n }\n\n let length = 0;\n\n while (length < common.length && length < indent.length && common[length] === indent[length]) {\n length += 1;\n }\n\n common = common.slice(0, length);\n\n if (common === '') {\n return text;\n }\n }\n\n if (!common) {\n return text;\n }\n\n const prefix = common;\n return lines\n .map((line) => {\n if (line.startsWith(prefix)) {\n return line.slice(prefix.length);\n }\n\n // Only a blank line can miss the shared indent (a shorter one): drop\n // just the part they share, so saving can put the rest back.\n let shared = 0;\n\n while (shared < line.length && line[shared] === prefix[shared]) {\n shared += 1;\n }\n\n return line.slice(shared);\n })\n .join('\\n');\n};\n\nexport const firstContentLineIndex = (lines: string[]): number => {\n return lines.findIndex((line) => line.trim() !== '');\n};\n\nexport interface FrontmatterBlock {\n /** The YAML between the fences. */\n yaml: string;\n\n /** 0-based index of the opening `---` line. */\n openIndex: number;\n\n /** 0-based index of the closing `---` line. */\n closeIndex: number;\n}\n\n/** Frontmatter is a `---` fenced block starting on the first non-blank line. */\nexport const findFrontmatter = (lines: string[]): FrontmatterBlock | null => {\n const openIndex = firstContentLineIndex(lines);\n\n if (openIndex === -1 || lines[openIndex].trim() !== '---') {\n return null;\n }\n\n for (let index = openIndex + 1; index < lines.length; index += 1) {\n if (lines[index].trim() === '---') {\n return { yaml: lines.slice(openIndex + 1, index).join('\\n'), openIndex, closeIndex: index };\n }\n }\n\n return null;\n};\n\n/** 1-based line of the first `key:` entry inside a frontmatter or YAML block. */\nexport const lineOfKey = (lines: string[], key: string, fromIndex = 0, toIndex = lines.length): number | undefined => {\n const pattern = new RegExp(`^${key.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\s*:`);\n\n for (let index = fromIndex; index < toIndex; index += 1) {\n if (pattern.test(lines[index])) {\n return index + 1;\n }\n }\n\n return undefined;\n};\n",
|
|
12
|
+
"/**\n * Which of the palette's colors each top-level node takes, and how edits\n * keep them. The root takes the palette's first color, and top-level nodes\n * take the others in turn, cycling. A node with a `paletteColor` takes that\n * one instead and gives up its turn, so the nodes after it keep theirs.\n * Edits write a `paletteColor` where a node's turn would change, so adding,\n * moving or removing a node never gives the others new colors.\n */\n\nimport type { OrbitNode } from './types.js';\n\n/** A node's own color, or its type's: what it shows instead of the palette's. */\nexport type OwnColor = (node: OrbitNode) => string | undefined;\n\n/** What an edit needs to keep top-level nodes' colors. */\nexport interface BranchColorRules {\n /** How many colors top-level nodes take turns with: the palette's, after the root's (see `branchPalette`). */\n count: number;\n\n /** A node's own color or its type's, which it shows instead of the palette's. Default: its `color`. */\n ownColor?: OwnColor;\n}\n\n/** Each top-level node's palette number before an edit, from `branchColorsBefore`. */\nexport type BranchColors = Map<OrbitNode, number>;\n\n/** The node an edit was about, for `keepBranchColors`. */\nexport interface EditedBranch {\n node: OrbitNode;\n\n /** Whether the node keeps the color it had (a move), rather than taking one no other top-level node has (a new node). */\n keepsColor: boolean;\n}\n\n/** The colors top-level nodes take turns with: every palette color after the root's, or the only one. */\nexport const branchPalette = (palette: readonly string[]): string[] => {\n return palette.length > 1 ? palette.slice(1) : [...palette];\n};\n\n/** Whether a value is a palette number: a whole number from 1. */\nexport const isPaletteNumber = (value: unknown): value is number => {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= 1;\n};\n\n/** The color a palette number names among `colors` (from `branchPalette`), cycling. */\nexport const paletteColorOf = (colors: readonly string[], paletteNumber: number): string => {\n return colors[(paletteNumber - 1) % colors.length];\n};\n\n/** A palette number brought into 1 to `count`, cycling. */\nconst wrapped = (paletteNumber: number, count: number): number => {\n return ((paletteNumber - 1) % count) + 1;\n};\n\n/**\n * The palette number each of `branches` takes its color from: its\n * `paletteColor`, or else the next number in turn that none of them has as\n * its `paletteColor`. Nodes with a color or type of their own take a turn\n * too, so the nodes after them have the colors they'd have without one.\n */\nexport const branchNumbers = (branches: readonly OrbitNode[], count: number): Map<OrbitNode, number> => {\n const numbers = new Map<OrbitNode, number>();\n const taken = new Set<number>();\n\n for (const branch of branches) {\n if (isPaletteNumber(branch.paletteColor)) {\n taken.add(wrapped(branch.paletteColor, count));\n }\n }\n\n const all = Array.from({ length: count }, (_, index) => index + 1);\n const free = all.filter((paletteNumber) => !taken.has(paletteNumber));\n // With every color taken, turns go round all of them again.\n const turns = free.length > 0 ? free : all;\n let turn = 0;\n\n for (const branch of branches) {\n if (isPaletteNumber(branch.paletteColor)) {\n numbers.set(branch, wrapped(branch.paletteColor, count));\n } else {\n numbers.set(branch, turns[turn % turns.length]);\n turn += 1;\n }\n }\n\n return numbers;\n};\n\n/** Each top-level node's palette number, to keep through an edit with `keepBranchColors`. */\nexport const branchColorsBefore = (root: OrbitNode, rules: BranchColorRules): BranchColors => {\n return branchNumbers(root.children, rules.count);\n};\n\n/**\n * After an edit, gives every top-level node that was there before the color\n * it had, writing its palette number as its `paletteColor` where its turn\n * changed. The node the edit was about keeps its color when it moved within\n * the top level, takes one no other top-level node has when it's new there\n * (while there is one), and drops its `paletteColor` when it left the top\n * level, to take its new branch's color. Nodes showing a color or type of\n * their own are left as they are, and a `paletteColor` is written only where\n * a color would change otherwise.\n *\n * An edit that would write more numbers than the palette has colors writes\n * none: that happens only where the top level has more nodes than colors,\n * which repeat there anyway, and a big orbit's every node would get one.\n * Returns the nodes it changed.\n */\nexport const keepBranchColors = (root: OrbitNode, before: BranchColors, rules: BranchColorRules, edited?: EditedBranch): OrbitNode[] => {\n const ownColor = rules.ownColor ?? ((node: OrbitNode) => node.color);\n const branches = root.children;\n const subject = edited?.node;\n const showsPalette = (node: OrbitNode): boolean => ownColor(node) === undefined;\n // The `paletteColor` each pinned node had, to put back.\n const pinned = new Map<OrbitNode, number | undefined>();\n const changed: OrbitNode[] = [];\n\n const pin = (node: OrbitNode, paletteNumber: number): void => {\n if (!pinned.has(node)) {\n pinned.set(node, node.paletteColor);\n }\n\n node.paletteColor = paletteNumber;\n };\n\n // A top-level node whose color would change: one that was there before, isn't the edited one, and shows the palette's color.\n const moving = (numbers: Map<OrbitNode, number>): OrbitNode | undefined => {\n return branches.find((node) => node !== subject && before.has(node) && showsPalette(node) && numbers.get(node) !== before.get(node));\n };\n\n if (subject && before.has(subject) && !branches.includes(subject) && subject.paletteColor !== undefined) {\n delete subject.paletteColor;\n changed.push(subject);\n }\n\n if (subject && branches.includes(subject) && showsPalette(subject) && !isPaletteNumber(subject.paletteColor)) {\n const numbers = branchNumbers(branches, rules.count);\n const kept = edited?.keepsColor ? before.get(subject) : undefined;\n\n if (kept !== undefined) {\n if (numbers.get(subject) !== kept || moving(numbers)) {\n pin(subject, kept);\n }\n } else {\n const others = branches.filter((node) => node !== subject);\n const shared = others.some((node) => showsPalette(node) && numbers.get(node) === numbers.get(subject));\n\n if (shared || moving(numbers)) {\n // A number none of the others has, alone or in turn, so taking it moves none of them.\n const used = new Set(branchNumbers(others, rules.count).values());\n const unused = Array.from({ length: rules.count }, (_, index) => index + 1).find((paletteNumber) => !used.has(paletteNumber));\n\n if (unused !== undefined) {\n pin(subject, unused);\n }\n }\n }\n }\n\n // Each round keeps one more node's color, the first that would change, so the nodes after it often keep theirs without one.\n for (let round = 0; round < branches.length && pinned.size <= rules.count; round += 1) {\n const node = moving(branchNumbers(branches, rules.count));\n\n if (!node) {\n break;\n }\n\n pin(node, before.get(node) as number);\n }\n\n if (pinned.size > rules.count) {\n for (const [node, paletteNumber] of pinned) {\n if (paletteNumber === undefined) {\n delete node.paletteColor;\n } else {\n node.paletteColor = paletteNumber;\n }\n }\n\n return changed;\n }\n\n return [...changed, ...pinned.keys()];\n};\n",
|
|
12
13
|
"/**\n * \"Did you mean …?\" for keys and values a document misspells: a known\n * synonym (`colour` for `color`, `dark` for `night`), or the closest known name\n * within a couple of typos, ignoring case.\n */\nexport const suggest = (input: string, candidates: readonly string[], synonyms: Readonly<Record<string, string>> = {}): string | undefined => {\n const lowered = input.toLowerCase();\n const synonym = Object.entries(synonyms).find(([word]) => word.toLowerCase() === lowered)?.[1];\n\n if (synonym !== undefined) {\n return synonym;\n }\n\n const allowed = Math.min(2, Math.max(1, Math.floor(input.length / 3)));\n let best: string | undefined;\n let bestDistance = Infinity;\n\n for (const candidate of candidates) {\n const distance = editDistance(lowered, candidate.toLowerCase());\n\n if (distance <= allowed && distance < bestDistance) {\n best = candidate;\n bestDistance = distance;\n }\n }\n\n return best;\n};\n\n/** \" Did you mean \"x\"?\" when there is a suggestion, otherwise nothing. */\nexport const didYouMean = (input: string, candidates: readonly string[], synonyms?: Readonly<Record<string, string>>): string => {\n const suggestion = suggest(input, candidates, synonyms);\n return suggestion === undefined ? '' : ` Did you mean \"${suggestion}\"?`;\n};\n\n/** Edits (insertions, deletions, substitutions and swaps of neighbors) between two words. */\nconst editDistance = (first: string, second: string): number => {\n const rows = first.length + 1;\n const columns = second.length + 1;\n const table: number[][] = Array.from({ length: rows }, (_, row) => Array.from({ length: columns }, (_, column) => (row === 0 ? column : column === 0 ? row : 0)));\n\n for (let row = 1; row < rows; row += 1) {\n for (let column = 1; column < columns; column += 1) {\n const cost = first[row - 1] === second[column - 1] ? 0 : 1;\n table[row][column] = Math.min(table[row - 1][column] + 1, table[row][column - 1] + 1, table[row - 1][column - 1] + cost);\n\n if (row > 1 && column > 1 && first[row - 1] === second[column - 2] && first[row - 2] === second[column - 1]) {\n table[row][column] = Math.min(table[row][column], table[row - 2][column - 2] + 1);\n }\n }\n }\n\n return table[first.length][second.length];\n};\n",
|
|
13
|
-
"import type { DiagnosticCollector } from './diagnostics.js';\nimport type { OrbitNode } from './types.js';\nimport { didYouMean } from './suggest.js';\nimport { assignKey } from './yaml-mini.js';\n\ntype ImageMedia = NonNullable<OrbitNode['image']>;\ntype VideoMedia = NonNullable<OrbitNode['video']>;\ntype EmbedMedia = NonNullable<OrbitNode['embed']>;\n\nconst VIDEO_PROVIDERS = new Set(['youtube', 'vimeo', 'native']);\nconst TRUE_VALUES = new Set(['true', 'yes', 'on', '1']);\nconst FALSE_VALUES = new Set(['false', 'no', 'off', '0']);\n\n/** Fields of a picture, video or embed that Orbit doesn't read, kept to be written back. */\nconst MEDIA_EXTRAS = new WeakMap<object, Record<string, unknown>>();\n\n/**\n * The fields a picture, video or embed was written with that Orbit doesn't\n * read (a `width`, a provider it doesn't know): kept so saving writes them\n * back, for a newer version or another app that reads them.\n */\nexport const mediaExtras = (media: object | undefined): Record<string, unknown> | undefined => {\n return media ? MEDIA_EXTRAS.get(media) : undefined;\n};\n\n/** A copy of a picture, video or embed, with the fields Orbit doesn't read. */\nexport const copyMedia = <Media extends object>(media: Media): Media => {\n const copy = JSON.parse(JSON.stringify(media)) as Media;\n const extras = MEDIA_EXTRAS.get(media);\n\n if (extras) {\n MEDIA_EXTRAS.set(copy, JSON.parse(JSON.stringify(extras)) as Record<string, unknown>);\n }\n\n return copy;\n};\n\nconst keepExtras = (media: object, record: Record<string, unknown>, known: readonly string[]): void => {\n const extras = Object.fromEntries(Object.entries(record).filter(([key]) => !known.includes(key)));\n\n if (Object.keys(extras).length > 0) {\n MEDIA_EXTRAS.set(media, extras);\n }\n};\n\n/** The `src` of a media attribute: a URL string, or an object with a string `src`. */\nconst mediaRecord = (value: unknown): Record<string, unknown> | null => {\n if (typeof value === 'string' && value.trim() !== '') {\n return { src: value.trim() };\n }\n\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n const record = value as Record<string, unknown>;\n\n if (typeof record.src === 'string' && record.src.trim() !== '') {\n return record;\n }\n }\n\n return null;\n};\n\nconst optionalString = (value: unknown): string | undefined => {\n return typeof value === 'string' || typeof value === 'number' ? String(value) : undefined;\n};\n\nexport const readImage = (value: unknown): ImageMedia | undefined => {\n const record = mediaRecord(value);\n\n if (!record) {\n return undefined;\n }\n\n const image: ImageMedia = { src: String(record.src) };\n const alt = optionalString(record.alt);\n const caption = optionalString(record.caption);\n\n if (alt !== undefined) {\n image.alt = alt;\n }\n\n if (caption !== undefined) {\n image.caption = caption;\n }\n\n keepExtras(image, record, ['src', 'alt', 'caption']);\n return image;\n};\n\nexport const readVideo = (value: unknown): VideoMedia | undefined => {\n const record = mediaRecord(value);\n\n if (!record) {\n return undefined;\n }\n\n const video: VideoMedia = { src: String(record.src) };\n const knownProvider = typeof record.provider === 'string' && VIDEO_PROVIDERS.has(record.provider);\n\n if (knownProvider) {\n video.provider = record.provider as VideoMedia['provider'];\n }\n\n const thumbnail = optionalString(record.thumbnail);\n const caption = optionalString(record.caption);\n\n if (thumbnail !== undefined) {\n video.thumbnail = thumbnail;\n }\n\n if (caption !== undefined) {\n video.caption = caption;\n }\n\n // A provider Orbit doesn't know is played as a link, and kept as written.\n keepExtras(video, record, knownProvider ? ['src', 'provider', 'thumbnail', 'caption'] : ['src', 'thumbnail', 'caption']);\n return video;\n};\n\nexport const readEmbed = (value: unknown): EmbedMedia | undefined => {\n const record = mediaRecord(value);\n\n if (!record) {\n return undefined;\n }\n\n const embed: EmbedMedia = { src: String(record.src) };\n const caption = optionalString(record.caption);\n\n if (caption !== undefined) {\n embed.caption = caption;\n }\n\n keepExtras(embed, record, ['src', 'caption']);\n return embed;\n};\n\n/** The attributes every node takes, in `<!-- orbit … -->` blocks and in YAML. */\nexport const NODE_ATTRIBUTE_KEYS = [\n 'color', 'icon', 'status', 'priority', 'tags', 'collapsed', 'link',\n 'note', 'noteFormat', 'image', 'video', 'embed', 'caption', 'id', 'type',\n] as const;\n\n/** Words people (and agents) reach for instead of an attribute's name. */\nconst ATTRIBUTE_SYNONYMS: Record<string, string> = {\n colour: 'color',\n emoji: 'icon',\n state: 'status',\n tag: 'tags',\n labels: 'tags',\n url: 'link',\n href: 'link',\n img: 'image',\n picture: 'image',\n photo: 'image',\n youtube: 'video',\n iframe: 'embed',\n notes: 'note',\n description: 'note',\n details: 'note',\n collapse: 'collapsed',\n folded: 'collapsed',\n kind: 'type',\n};\n\n/** Keys a flavor accepts besides the node attributes, and the words that stand in for them. */\nexport interface AttributeVocabulary {\n keys: readonly string[];\n synonyms?: Readonly<Record<string, string>>;\n}\n\n/** A value Orbit reads as text: a string, or a number or true/false written without quotes. */\nconst scalar = (value: unknown): string | undefined => {\n return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' ? String(value) : undefined;\n};\n\n/**\n * A value Orbit can't read for one of its own attributes: a list where it\n * takes one word, a word where it takes a number. Reported, and kept in\n * `attrs` under its own name, so saving writes it back as it was written:\n * a newer version of Orbit, or another app, may read it.\n */\nconst keepUnread = (node: OrbitNode, key: string, value: unknown, diagnostics: DiagnosticCollector, line: number | undefined, expected: string): void => {\n diagnostics.recover('invalid-attributes', `${key} must be ${expected}; kept as written, but not used`, line);\n node.attrs ??= {};\n assignKey(node.attrs, key, value);\n};\n\n/**\n * Applies one typed attribute (from a `<!-- orbit ... -->` block or a YAML\n * node map) to a node. Unknown keys are kept in `node.attrs`, with a note\n * when they look like a misspelled attribute. Values Orbit can't read are\n * reported and kept in `node.attrs` too, so they're written back.\n */\nexport const assignNodeAttribute = (\n node: OrbitNode,\n key: string,\n value: unknown,\n diagnostics: DiagnosticCollector,\n line?: number,\n vocabulary: AttributeVocabulary = { keys: [] },\n): void => {\n switch (key) {\n case 'color':\n case 'icon':\n case 'status':\n case 'link': {\n const text = scalar(value);\n\n if (text === undefined) {\n keepUnread(node, key, value, diagnostics, line, 'one value');\n } else {\n node[key] = text;\n }\n\n return;\n }\n case 'priority': {\n const priority = typeof value === 'number' || (typeof value === 'string' && value.trim() !== '') ? Number(value) : Number.NaN;\n\n if (Number.isFinite(priority)) {\n node.priority = priority;\n } else {\n keepUnread(node, key, value, diagnostics, line, 'a number');\n }\n\n return;\n }\n case 'tags': {\n // Joins any hashtags from the title. A single value may list several, as `palette` does: `tags: web, mobile`.\n const single = Array.isArray(value) ? undefined : scalar(value);\n const tags = Array.isArray(value)\n ? value.map(scalar)\n : single === undefined ? [undefined] : single.split(',').map((tag) => tag.trim()).filter((tag) => tag !== '');\n\n if (tags.some((tag) => tag === undefined)) {\n keepUnread(node, key, value, diagnostics, line, 'a word or a list of words');\n return;\n }\n\n node.tags = [...new Set([...(node.tags ?? []), ...(tags as string[])])];\n return;\n }\n case 'collapsed': {\n const word = scalar(value)?.toLowerCase();\n\n if (word !== undefined && (TRUE_VALUES.has(word) || FALSE_VALUES.has(word))) {\n node.collapsed = TRUE_VALUES.has(word);\n } else {\n keepUnread(node, key, value, diagnostics, line, 'true or false');\n }\n\n return;\n }\n case 'note': {\n const text = scalar(value);\n\n if (text === undefined) {\n keepUnread(node, key, value, diagnostics, line, 'text');\n return;\n }\n\n node.note = text;\n\n if (node.noteFormat === undefined) {\n node.noteFormat = 'markdown';\n }\n\n return;\n }\n case 'noteFormat':\n if (value === 'markdown' || value === 'plain') {\n node.noteFormat = value;\n } else {\n keepUnread(node, key, value, diagnostics, line, '\"markdown\" or \"plain\"');\n }\n\n return;\n case 'id': {\n const text = scalar(value);\n\n if (text === undefined || text.trim() === '') {\n keepUnread(node, key, value, diagnostics, line, 'one word');\n } else {\n node.id = text;\n }\n\n return;\n }\n case 'type': {\n const text = scalar(value);\n\n if (text === undefined) {\n keepUnread(node, key, value, diagnostics, line, 'one word');\n return;\n }\n\n // `task@2`: the version of the type the node was written for.\n const versioned = /^(.*\\S)@(\\d+)$/.exec(text.trim());\n node.type = versioned ? versioned[1] : text.trim();\n\n if (versioned) {\n node.typeVersion = Number(versioned[2]);\n }\n\n return;\n }\n case 'image': {\n const image = readImage(value);\n\n if (image) {\n node.image = image;\n } else {\n diagnostics.recover('media-missing-source', 'image needs a URL (or an object with a src)', line);\n }\n\n return;\n }\n case 'video': {\n const video = readVideo(value);\n\n if (video) {\n node.video = video;\n } else {\n diagnostics.recover('media-missing-source', 'video needs a URL (or an object with a src)', line);\n }\n\n return;\n }\n case 'embed': {\n const embed = readEmbed(value);\n\n if (embed) {\n node.embed = embed;\n } else {\n diagnostics.recover('media-missing-source', 'embed needs a URL (or an object with a src)', line);\n }\n\n return;\n }\n case 'caption': {\n const target = node.video ?? node.embed ?? node.image;\n\n if (target) {\n if (value !== null && value !== undefined) {\n target.caption = String(value);\n }\n } else {\n diagnostics.note('caption-without-media', 'caption kept, but not shown: the node has no image, video or embed', line);\n node.attrs ??= {};\n node.attrs.caption = value;\n }\n\n return;\n }\n default: {\n const hint = didYouMean(key, [...NODE_ATTRIBUTE_KEYS, ...vocabulary.keys], { ...ATTRIBUTE_SYNONYMS, ...vocabulary.synonyms });\n\n if (hint) {\n diagnostics.note('unknown-attribute', `Unknown attribute \"${key}\", kept as a custom attribute.${hint}`, line);\n }\n\n if (!node.attrs) {\n node.attrs = {};\n }\n\n assignKey(node.attrs, key, value);\n }\n }\n};\n",
|
|
14
|
+
"import type { DiagnosticCollector } from './diagnostics.js';\nimport type { OrbitNode } from './types.js';\nimport { isPaletteNumber } from './branch-colors.js';\nimport { didYouMean } from './suggest.js';\nimport { assignKey } from './yaml-mini.js';\n\ntype ImageMedia = NonNullable<OrbitNode['image']>;\ntype VideoMedia = NonNullable<OrbitNode['video']>;\ntype EmbedMedia = NonNullable<OrbitNode['embed']>;\n\nconst VIDEO_PROVIDERS = new Set(['youtube', 'vimeo', 'native']);\nconst TRUE_VALUES = new Set(['true', 'yes', 'on', '1']);\nconst FALSE_VALUES = new Set(['false', 'no', 'off', '0']);\n\n/** Fields of a picture, video or embed that Orbit doesn't read, kept to be written back. */\nconst MEDIA_EXTRAS = new WeakMap<object, Record<string, unknown>>();\n\n/**\n * The fields a picture, video or embed was written with that Orbit doesn't\n * read (a `width`, a provider it doesn't know): kept so saving writes them\n * back, for a newer version or another app that reads them.\n */\nexport const mediaExtras = (media: object | undefined): Record<string, unknown> | undefined => {\n return media ? MEDIA_EXTRAS.get(media) : undefined;\n};\n\n/** A copy of a picture, video or embed, with the fields Orbit doesn't read. */\nexport const copyMedia = <Media extends object>(media: Media): Media => {\n const copy = JSON.parse(JSON.stringify(media)) as Media;\n const extras = MEDIA_EXTRAS.get(media);\n\n if (extras) {\n MEDIA_EXTRAS.set(copy, JSON.parse(JSON.stringify(extras)) as Record<string, unknown>);\n }\n\n return copy;\n};\n\nconst keepExtras = (media: object, record: Record<string, unknown>, known: readonly string[]): void => {\n const extras = Object.fromEntries(Object.entries(record).filter(([key]) => !known.includes(key)));\n\n if (Object.keys(extras).length > 0) {\n MEDIA_EXTRAS.set(media, extras);\n }\n};\n\n/** The `src` of a media attribute: a URL string, or an object with a string `src`. */\nconst mediaRecord = (value: unknown): Record<string, unknown> | null => {\n if (typeof value === 'string' && value.trim() !== '') {\n return { src: value.trim() };\n }\n\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n const record = value as Record<string, unknown>;\n\n if (typeof record.src === 'string' && record.src.trim() !== '') {\n return record;\n }\n }\n\n return null;\n};\n\nconst optionalString = (value: unknown): string | undefined => {\n return typeof value === 'string' || typeof value === 'number' ? String(value) : undefined;\n};\n\nexport const readImage = (value: unknown): ImageMedia | undefined => {\n const record = mediaRecord(value);\n\n if (!record) {\n return undefined;\n }\n\n const image: ImageMedia = { src: String(record.src) };\n const alt = optionalString(record.alt);\n const caption = optionalString(record.caption);\n\n if (alt !== undefined) {\n image.alt = alt;\n }\n\n if (caption !== undefined) {\n image.caption = caption;\n }\n\n keepExtras(image, record, ['src', 'alt', 'caption']);\n return image;\n};\n\nexport const readVideo = (value: unknown): VideoMedia | undefined => {\n const record = mediaRecord(value);\n\n if (!record) {\n return undefined;\n }\n\n const video: VideoMedia = { src: String(record.src) };\n const knownProvider = typeof record.provider === 'string' && VIDEO_PROVIDERS.has(record.provider);\n\n if (knownProvider) {\n video.provider = record.provider as VideoMedia['provider'];\n }\n\n const thumbnail = optionalString(record.thumbnail);\n const caption = optionalString(record.caption);\n\n if (thumbnail !== undefined) {\n video.thumbnail = thumbnail;\n }\n\n if (caption !== undefined) {\n video.caption = caption;\n }\n\n // A provider Orbit doesn't know is played as a link, and kept as written.\n keepExtras(video, record, knownProvider ? ['src', 'provider', 'thumbnail', 'caption'] : ['src', 'thumbnail', 'caption']);\n return video;\n};\n\nexport const readEmbed = (value: unknown): EmbedMedia | undefined => {\n const record = mediaRecord(value);\n\n if (!record) {\n return undefined;\n }\n\n const embed: EmbedMedia = { src: String(record.src) };\n const caption = optionalString(record.caption);\n\n if (caption !== undefined) {\n embed.caption = caption;\n }\n\n keepExtras(embed, record, ['src', 'caption']);\n return embed;\n};\n\n/** The attributes every node takes, in `<!-- orbit … -->` blocks and in YAML. */\nexport const NODE_ATTRIBUTE_KEYS = [\n 'color', 'paletteColor', 'icon', 'status', 'priority', 'tags', 'collapsed', 'link',\n 'note', 'noteFormat', 'image', 'video', 'embed', 'caption', 'id', 'type',\n] as const;\n\n/** Words people (and agents) reach for instead of an attribute's name. */\nconst ATTRIBUTE_SYNONYMS: Record<string, string> = {\n colour: 'color',\n emoji: 'icon',\n state: 'status',\n tag: 'tags',\n labels: 'tags',\n url: 'link',\n href: 'link',\n img: 'image',\n picture: 'image',\n photo: 'image',\n youtube: 'video',\n iframe: 'embed',\n notes: 'note',\n description: 'note',\n details: 'note',\n collapse: 'collapsed',\n folded: 'collapsed',\n kind: 'type',\n};\n\n/** Keys a flavor accepts besides the node attributes, and the words that stand in for them. */\nexport interface AttributeVocabulary {\n keys: readonly string[];\n synonyms?: Readonly<Record<string, string>>;\n}\n\n/** A value Orbit reads as text: a string, or a number or true/false written without quotes. */\nconst scalar = (value: unknown): string | undefined => {\n return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' ? String(value) : undefined;\n};\n\n/**\n * A value Orbit can't read for one of its own attributes: a list where it\n * takes one word, a word where it takes a number. Reported, and kept in\n * `attrs` under its own name, so saving writes it back as it was written:\n * a newer version of Orbit, or another app, may read it.\n */\nconst keepUnread = (node: OrbitNode, key: string, value: unknown, diagnostics: DiagnosticCollector, line: number | undefined, expected: string): void => {\n diagnostics.recover('invalid-attributes', `${key} must be ${expected}; kept as written, but not used`, line);\n node.attrs ??= {};\n assignKey(node.attrs, key, value);\n};\n\n/**\n * Applies one typed attribute (from a `<!-- orbit ... -->` block or a YAML\n * node map) to a node. Unknown keys are kept in `node.attrs`, with a note\n * when they look like a misspelled attribute. Values Orbit can't read are\n * reported and kept in `node.attrs` too, so they're written back.\n */\nexport const assignNodeAttribute = (\n node: OrbitNode,\n key: string,\n value: unknown,\n diagnostics: DiagnosticCollector,\n line?: number,\n vocabulary: AttributeVocabulary = { keys: [] },\n): void => {\n switch (key) {\n case 'color':\n case 'icon':\n case 'status':\n case 'link': {\n const text = scalar(value);\n\n if (text === undefined) {\n keepUnread(node, key, value, diagnostics, line, 'one value');\n } else {\n node[key] = text;\n }\n\n return;\n }\n case 'paletteColor': {\n const paletteNumber = typeof value === 'number' || (typeof value === 'string' && value.trim() !== '') ? Number(value) : Number.NaN;\n\n if (isPaletteNumber(paletteNumber)) {\n node.paletteColor = paletteNumber;\n } else {\n keepUnread(node, key, value, diagnostics, line, 'a whole number from 1');\n }\n\n return;\n }\n case 'priority': {\n const priority = typeof value === 'number' || (typeof value === 'string' && value.trim() !== '') ? Number(value) : Number.NaN;\n\n if (Number.isFinite(priority)) {\n node.priority = priority;\n } else {\n keepUnread(node, key, value, diagnostics, line, 'a number');\n }\n\n return;\n }\n case 'tags': {\n // Joins any hashtags from the title. A single value may list several, as `palette` does: `tags: web, mobile`.\n const single = Array.isArray(value) ? undefined : scalar(value);\n const tags = Array.isArray(value)\n ? value.map(scalar)\n : single === undefined ? [undefined] : single.split(',').map((tag) => tag.trim()).filter((tag) => tag !== '');\n\n if (tags.some((tag) => tag === undefined)) {\n keepUnread(node, key, value, diagnostics, line, 'a word or a list of words');\n return;\n }\n\n node.tags = [...new Set([...(node.tags ?? []), ...(tags as string[])])];\n return;\n }\n case 'collapsed': {\n const word = scalar(value)?.toLowerCase();\n\n if (word !== undefined && (TRUE_VALUES.has(word) || FALSE_VALUES.has(word))) {\n node.collapsed = TRUE_VALUES.has(word);\n } else {\n keepUnread(node, key, value, diagnostics, line, 'true or false');\n }\n\n return;\n }\n case 'note': {\n const text = scalar(value);\n\n if (text === undefined) {\n keepUnread(node, key, value, diagnostics, line, 'text');\n return;\n }\n\n node.note = text;\n\n if (node.noteFormat === undefined) {\n node.noteFormat = 'markdown';\n }\n\n return;\n }\n case 'noteFormat':\n if (value === 'markdown' || value === 'plain') {\n node.noteFormat = value;\n } else {\n keepUnread(node, key, value, diagnostics, line, '\"markdown\" or \"plain\"');\n }\n\n return;\n case 'id': {\n const text = scalar(value);\n\n if (text === undefined || text.trim() === '') {\n keepUnread(node, key, value, diagnostics, line, 'one word');\n } else {\n node.id = text;\n }\n\n return;\n }\n case 'type': {\n const text = scalar(value);\n\n if (text === undefined) {\n keepUnread(node, key, value, diagnostics, line, 'one word');\n return;\n }\n\n // `task@2`: the version of the type the node was written for.\n const versioned = /^(.*\\S)@(\\d+)$/.exec(text.trim());\n node.type = versioned ? versioned[1] : text.trim();\n\n if (versioned) {\n node.typeVersion = Number(versioned[2]);\n }\n\n return;\n }\n case 'image': {\n const image = readImage(value);\n\n if (image) {\n node.image = image;\n } else {\n diagnostics.recover('media-missing-source', 'image needs a URL (or an object with a src)', line);\n }\n\n return;\n }\n case 'video': {\n const video = readVideo(value);\n\n if (video) {\n node.video = video;\n } else {\n diagnostics.recover('media-missing-source', 'video needs a URL (or an object with a src)', line);\n }\n\n return;\n }\n case 'embed': {\n const embed = readEmbed(value);\n\n if (embed) {\n node.embed = embed;\n } else {\n diagnostics.recover('media-missing-source', 'embed needs a URL (or an object with a src)', line);\n }\n\n return;\n }\n case 'caption': {\n const target = node.video ?? node.embed ?? node.image;\n\n if (target) {\n if (value !== null && value !== undefined) {\n target.caption = String(value);\n }\n } else {\n diagnostics.note('caption-without-media', 'caption kept, but not shown: the node has no image, video or embed', line);\n node.attrs ??= {};\n node.attrs.caption = value;\n }\n\n return;\n }\n default: {\n const hint = didYouMean(key, [...NODE_ATTRIBUTE_KEYS, ...vocabulary.keys], { ...ATTRIBUTE_SYNONYMS, ...vocabulary.synonyms });\n\n if (hint) {\n diagnostics.note('unknown-attribute', `Unknown attribute \"${key}\", kept as a custom attribute.${hint}`, line);\n }\n\n if (!node.attrs) {\n node.attrs = {};\n }\n\n assignKey(node.attrs, key, value);\n }\n }\n};\n",
|
|
14
15
|
"import type { OrbitRendererTheme, OrbitThemePreset } from './types.js';\n\n/**\n * Theme tokens. Each token is a CSS custom property: set `--orbit-<token>` on\n * the map or any ancestor to override it. Presets only provide defaults:\n * internally every token resolves as `var(--orbit-<token>, <preset value>)`.\n */\nexport const THEME_TOKENS = [\n 'sans-font', 'serif-font', 'mono-font',\n 'font-family', 'label-font', 'display-font', 'label-weight', 'display-weight', 'label-letter-spacing', 'label-shadow',\n 'surface', 'surface-pattern', 'text', 'muted-text',\n 'root-text', 'node-text', 'node-text-inverse',\n 'color-root', 'color-1', 'color-2', 'color-3', 'color-4', 'color-5', 'color-6', 'color-7',\n 'shade-light', 'shade-dark',\n 'node-fill-opacity', 'moon-opacity', 'node-highlight', 'node-terminator', 'node-shading', 'node-shade-circle',\n 'node-stroke', 'node-stroke-tint', 'node-stroke-width', 'badge-stroke',\n 'node-shadow', 'node-shadow-tint', 'node-shadow-opacity', 'node-shadow-offset', 'node-shadow-size',\n 'sun-shadow-opacity', 'sun-shadow-size',\n 'sun-halo', 'sun-halo-tint', 'sun-halo-opacity', 'sun-halo-width', 'sun-halo-dash', 'sun-halo-size',\n 'ring-stroke', 'ring-tint', 'ring-opacity', 'ring-width', 'ring-dash',\n 'link-stroke', 'link-tint', 'link-opacity', 'link-width', 'link-dash',\n 'focus-ring', 'note-indicator',\n 'control-background', 'control-border', 'control-text', 'control-muted-text',\n 'control-active-background', 'control-active-text', 'control-shadow', 'control-blur',\n 'tooltip-background', 'tooltip-text',\n 'action-background', 'action-border', 'action-text', 'action-shadow',\n 'sheet-background', 'sheet-text', 'sheet-muted-text', 'sheet-border', 'sheet-backdrop', 'sheet-shadow', 'sheet-blur',\n 'chip-background', 'chip-text', 'link-text',\n 'status-active', 'status-done', 'status-blocked', 'status-todo', 'status-neutral',\n 'error-background', 'error-border', 'error-text',\n] as const;\n\nexport type OrbitThemeToken = (typeof THEME_TOKENS)[number];\nexport type OrbitThemeTokens = Record<OrbitThemeToken, string>;\nexport type OrbitThemeName =\n | 'paper' | 'night' | 'glass' | 'glass-night' | 'cosmos' | 'blueprint' | 'ink' | 'contrast'\n | 'flat' | 'flat-night' | 'material' | 'material-night' | 'liquid' | 'liquid-night';\n\nconst SYSTEM_FONTS = 'ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif';\nconst SERIF_FONTS = 'ui-serif, \"Iowan Old Style\", \"Palatino Linotype\", Palatino, Georgia, Cambria, \"Times New Roman\", serif';\nconst MONOSPACE_FONTS = 'ui-monospace, \"SF Mono\", \"Cascadia Mono\", \"Roboto Mono\", Menlo, Consolas, \"Liberation Mono\", monospace';\n\n/** Pastel planets with a soft colored shadow and a fine rim of their own color, on the page's own background. */\nconst PAPER: OrbitThemeTokens = {\n // The page's fonts of each kind: set `--orbit-sans-font` to draw every sans-serif theme in your own.\n 'sans-font': SYSTEM_FONTS,\n 'serif-font': SERIF_FONTS,\n 'mono-font': MONOSPACE_FONTS,\n 'font-family': 'var(--_orbit-sans-font)',\n 'label-font': 'var(--_orbit-font-family)',\n 'display-font': 'var(--_orbit-font-family)',\n 'label-weight': '600',\n 'display-weight': '650',\n 'label-letter-spacing': '-0.005em',\n 'label-shadow': 'none',\n surface: 'transparent',\n 'surface-pattern': 'none',\n text: '#1F2733',\n 'muted-text': '#5B6474',\n 'root-text': '#1F2733',\n 'node-text': '#1F2733',\n 'node-text-inverse': '#FFFFFF',\n 'color-root': '#FAD86F',\n 'color-1': '#FEBAB6',\n 'color-2': '#99E0BA',\n 'color-3': '#9ED5FD',\n 'color-4': '#D6C2FE',\n 'color-5': '#F9C191',\n 'color-6': '#FCB6D6',\n 'color-7': '#82E1E0',\n 'shade-light': '#FFFFFF',\n 'shade-dark': '#1F2733',\n 'node-fill-opacity': '1',\n 'moon-opacity': '0.94',\n 'node-highlight': 'rgba(255, 255, 255, 0.55)',\n 'node-terminator': 'rgba(31, 39, 51, 0)',\n 'node-shading': 'rgba(31, 39, 51, 0.12)',\n 'node-shade-circle': '0.34 0.3 0.78',\n 'node-stroke': '#1F2733',\n 'node-stroke-tint': '78%',\n 'node-stroke-width': '1',\n 'badge-stroke': '#FFFFFF',\n 'node-shadow': '#1F2733',\n 'node-shadow-tint': '45%',\n 'node-shadow-opacity': '0.26',\n 'node-shadow-offset': '0.16',\n 'node-shadow-size': '0.96',\n 'sun-shadow-opacity': '0.3',\n 'sun-shadow-size': '0.98',\n 'sun-halo': '#1F2733',\n 'sun-halo-tint': '72%',\n 'sun-halo-opacity': '0.55',\n 'sun-halo-width': '1',\n 'sun-halo-dash': 'none',\n 'sun-halo-size': '1.15',\n 'ring-stroke': '#1F2733',\n 'ring-tint': '35%',\n 'ring-opacity': '0.4',\n 'ring-width': '1.5',\n 'ring-dash': '1 6',\n 'link-stroke': '#1F2733',\n 'link-tint': '60%',\n 'link-opacity': '0.45',\n 'link-width': '1.5',\n 'link-dash': 'none',\n 'focus-ring': '#2563EB',\n 'note-indicator': '#1F2733',\n 'control-background': 'rgba(255, 255, 255, 0.92)',\n 'control-border': 'rgba(31, 39, 51, 0.12)',\n 'control-text': '#1F2733',\n 'control-muted-text': '#5B6474',\n 'control-active-background': '#1F2733',\n 'control-active-text': '#FFFFFF',\n 'control-shadow': '0 6px 20px rgba(31, 39, 51, 0.12)',\n 'control-blur': '12px',\n 'tooltip-background': '#1F2733',\n 'tooltip-text': '#FFFFFF',\n 'action-background': '#FFFFFF',\n 'action-border': 'rgba(31, 39, 51, 0.16)',\n 'action-text': '#1F2733',\n 'action-shadow': '0 6px 16px rgba(31, 39, 51, 0.18)',\n 'sheet-background': '#FFFFFF',\n 'sheet-text': '#1F2733',\n 'sheet-muted-text': '#5B6474',\n 'sheet-border': 'rgba(31, 39, 51, 0.12)',\n 'sheet-backdrop': 'rgba(15, 23, 42, 0.45)',\n 'sheet-shadow': '0 24px 64px rgba(15, 23, 42, 0.28)',\n 'sheet-blur': '0px',\n 'chip-background': '#F1F5F9',\n 'chip-text': '#334155',\n 'link-text': '#2563EB',\n 'status-active': '#2563EB',\n 'status-done': '#16A34A',\n 'status-blocked': '#DC2626',\n 'status-todo': '#94A3B8',\n 'status-neutral': '#64748B',\n 'error-background': '#FFF6F5',\n 'error-border': '#E58A8A',\n 'error-text': '#7A1F1F',\n};\n\n/** Luminous planets that glow on a deep navy sky. */\nconst NIGHT: OrbitThemeTokens = {\n ...PAPER,\n surface: '#0B1120',\n 'surface-pattern': 'radial-gradient(120% 90% at 50% 42%, rgba(64, 84, 160, 0.26), transparent 70%)',\n text: '#E6EAF2',\n 'muted-text': '#97A3B6',\n 'root-text': '#0B1120',\n 'node-text': '#0B1120',\n 'color-root': '#FEDB6D',\n 'color-1': '#FFAAA7',\n 'color-2': '#80DAAC',\n 'color-3': '#86CDFF',\n 'color-4': '#CEB5FE',\n 'color-5': '#F8B478',\n 'color-6': '#FAA6CE',\n 'color-7': '#5EDADA',\n 'shade-dark': '#0B1120',\n 'node-highlight': 'rgba(255, 255, 255, 0.45)',\n 'node-terminator': 'rgba(11, 17, 32, 0)',\n 'node-shading': 'rgba(11, 17, 32, 0.2)',\n 'node-stroke': '#FFFFFF',\n 'node-stroke-tint': '55%',\n 'badge-stroke': '#0B1120',\n 'node-shadow': '#FFFFFF',\n 'node-shadow-tint': '100%',\n 'node-shadow-opacity': '0.42',\n 'node-shadow-offset': '0',\n 'node-shadow-size': '1.16',\n 'sun-shadow-opacity': '0.5',\n 'sun-shadow-size': '1.4',\n 'sun-halo-opacity': '0',\n 'ring-stroke': '#FFFFFF',\n 'ring-tint': '55%',\n 'ring-opacity': '0.34',\n 'link-stroke': '#FFFFFF',\n 'link-tint': '70%',\n 'link-opacity': '0.36',\n 'focus-ring': '#93C5FD',\n 'note-indicator': '#E6EAF2',\n 'control-background': 'rgba(20, 26, 44, 0.84)',\n 'control-border': 'rgba(148, 163, 184, 0.22)',\n 'control-text': '#E6EAF2',\n 'control-muted-text': '#97A3B6',\n 'control-active-background': '#E6EAF2',\n 'control-active-text': '#0B1120',\n 'control-shadow': '0 8px 24px rgba(0, 0, 0, 0.4)',\n 'tooltip-background': '#E6EAF2',\n 'tooltip-text': '#0B1120',\n 'action-background': '#1B2338',\n 'action-border': 'rgba(148, 163, 184, 0.3)',\n 'action-text': '#E6EAF2',\n 'action-shadow': '0 6px 16px rgba(0, 0, 0, 0.45)',\n 'sheet-background': '#131A2E',\n 'sheet-text': '#E6EAF2',\n 'sheet-muted-text': '#97A3B6',\n 'sheet-border': 'rgba(148, 163, 184, 0.2)',\n 'sheet-backdrop': 'rgba(2, 6, 23, 0.6)',\n 'sheet-shadow': '0 24px 64px rgba(0, 0, 0, 0.6)',\n 'chip-background': 'rgba(148, 163, 184, 0.16)',\n 'chip-text': '#E2E8F0',\n 'link-text': '#93C5FD',\n 'status-active': '#60A5FA',\n 'status-done': '#4ADE80',\n 'status-blocked': '#F87171',\n 'status-neutral': '#94A3B8',\n 'error-background': '#2A1215',\n 'error-border': '#F87171',\n 'error-text': '#FECACA',\n};\n\n/** Frosted, translucent planets with a bright rim, on a soft pastel backdrop of their own. */\nconst GLASS: OrbitThemeTokens = {\n ...PAPER,\n surface: '#E7EAF8',\n 'surface-pattern': [\n 'radial-gradient(60% 50% at 16% 18%, rgba(196, 181, 253, 0.75), transparent 70%)',\n 'radial-gradient(55% 48% at 86% 24%, rgba(251, 207, 232, 0.85), transparent 70%)',\n 'radial-gradient(65% 55% at 52% 96%, rgba(153, 246, 228, 0.7), transparent 70%)',\n 'radial-gradient(40% 40% at 90% 85%, rgba(191, 219, 254, 0.8), transparent 70%)',\n ].join(', '),\n text: '#16213A',\n 'muted-text': '#414C66',\n 'root-text': '#16213A',\n 'node-text': '#16213A',\n 'color-root': '#FEEEBD',\n 'color-1': '#FED6D4',\n 'color-2': '#B6F1D0',\n 'color-3': '#C7E6FD',\n 'color-4': '#E6DAFE',\n 'color-5': '#FDDABD',\n 'color-6': '#FFD3E6',\n 'color-7': '#A5F2F1',\n 'shade-dark': '#16213A',\n 'node-fill-opacity': '0.55',\n 'moon-opacity': '0.5',\n 'node-highlight': 'rgba(255, 255, 255, 0.85)',\n 'node-terminator': 'rgba(22, 33, 58, 0)',\n 'node-shading': 'rgba(22, 33, 58, 0.08)',\n 'node-stroke': 'rgba(255, 255, 255, 0.92)',\n 'node-stroke-tint': '0%',\n 'node-stroke-width': '1.5',\n 'node-shadow': '#16213A',\n 'node-shadow-tint': '25%',\n 'node-shadow-opacity': '0.18',\n 'node-shadow-offset': '0.18',\n 'node-shadow-size': '0.98',\n 'sun-shadow-opacity': '0.22',\n 'sun-shadow-size': '1',\n 'sun-halo': '#FFFFFF',\n 'sun-halo-tint': '0%',\n 'sun-halo-opacity': '0.7',\n 'sun-halo-width': '1.5',\n 'sun-halo-size': '1.13',\n 'ring-stroke': '#FFFFFF',\n 'ring-tint': '0%',\n 'ring-opacity': '0.85',\n 'link-stroke': '#FFFFFF',\n 'link-tint': '0%',\n 'link-opacity': '0.8',\n 'note-indicator': '#16213A',\n 'control-background': 'rgba(255, 255, 255, 0.42)',\n 'control-border': 'rgba(255, 255, 255, 0.62)',\n 'control-text': '#16213A',\n 'control-muted-text': '#414C66',\n 'control-active-background': 'rgba(255, 255, 255, 0.78)',\n 'control-active-text': '#16213A',\n 'control-shadow': '0 8px 28px rgba(28, 44, 72, 0.18)',\n 'control-blur': '18px',\n 'tooltip-background': 'rgba(255, 255, 255, 0.86)',\n 'tooltip-text': '#16213A',\n 'action-background': 'rgba(255, 255, 255, 0.62)',\n 'action-border': 'rgba(255, 255, 255, 0.78)',\n 'action-text': '#16213A',\n 'action-shadow': '0 6px 18px rgba(28, 44, 72, 0.2)',\n 'sheet-background': 'rgba(255, 255, 255, 0.8)',\n 'sheet-text': '#16213A',\n 'sheet-muted-text': '#414C66',\n 'sheet-border': 'rgba(255, 255, 255, 0.7)',\n 'sheet-backdrop': 'rgba(18, 28, 45, 0.32)',\n 'sheet-shadow': '0 24px 70px rgba(28, 44, 72, 0.3)',\n 'sheet-blur': '24px',\n 'chip-background': 'rgba(255, 255, 255, 0.6)',\n};\n\n/** The glass look at night: tinted glass planets that glow over an aurora. */\nconst GLASS_NIGHT: OrbitThemeTokens = {\n ...NIGHT,\n surface: '#0E1326',\n 'surface-pattern': [\n 'radial-gradient(60% 50% at 18% 16%, rgba(99, 102, 241, 0.42), transparent 70%)',\n 'radial-gradient(55% 50% at 86% 78%, rgba(219, 39, 119, 0.3), transparent 70%)',\n 'radial-gradient(45% 40% at 74% 12%, rgba(20, 184, 166, 0.26), transparent 70%)',\n ].join(', '),\n 'label-shadow': '0 1px 3px rgba(5, 8, 20, 0.55)',\n text: '#F4F6FF',\n 'muted-text': '#A9B2D0',\n // Light labels on every planet: the glass lets the dark sky through.\n 'root-text': '#F4F6FF',\n 'node-text': '#F4F6FF',\n 'node-text-inverse': '#F4F6FF',\n 'color-root': '#F8DC86',\n 'color-1': '#FFAAA7',\n 'color-2': '#6FDEA7',\n 'color-3': '#86CDFF',\n 'color-4': '#CEB5FE',\n 'color-5': '#FEB16B',\n 'color-6': '#FFA3CF',\n 'color-7': '#36DEDE',\n 'shade-dark': '#0E1326',\n 'node-fill-opacity': '0.16',\n 'moon-opacity': '0.14',\n 'node-highlight': 'rgba(255, 255, 255, 0.1)',\n 'node-terminator': 'rgba(14, 19, 38, 0)',\n 'node-shading': 'rgba(14, 19, 38, 0.18)',\n 'node-stroke': 'rgba(255, 255, 255, 0.6)',\n 'node-stroke-tint': '45%',\n 'node-stroke-width': '1.5',\n 'node-shadow-opacity': '0.3',\n 'node-shadow-size': '1.14',\n 'sun-shadow-opacity': '0.38',\n 'sun-shadow-size': '1.35',\n 'ring-tint': '20%',\n 'ring-opacity': '0.32',\n 'link-tint': '30%',\n 'link-opacity': '0.32',\n 'note-indicator': '#F4F6FF',\n 'control-background': 'rgba(30, 38, 64, 0.5)',\n 'control-border': 'rgba(255, 255, 255, 0.16)',\n 'control-text': '#F4F6FF',\n 'control-muted-text': '#A9B2D0',\n 'control-active-background': '#F4F6FF',\n 'control-active-text': '#0E1326',\n 'control-blur': '18px',\n 'tooltip-background': 'rgba(244, 246, 255, 0.92)',\n 'tooltip-text': '#0E1326',\n 'action-background': 'rgba(30, 38, 64, 0.62)',\n 'action-border': 'rgba(255, 255, 255, 0.2)',\n 'action-text': '#F4F6FF',\n 'sheet-background': 'rgba(24, 32, 56, 0.78)',\n 'sheet-text': '#F4F6FF',\n 'sheet-muted-text': '#A9B2D0',\n 'sheet-border': 'rgba(255, 255, 255, 0.14)',\n 'sheet-blur': '24px',\n};\n\n/** Stars for `cosmos`, scattered at random over a 640 px tile: each `M x y h0` is a dot (a zero-length, round-capped stroke). */\nconst STARS = [\n { width: 1.1, color: '#fff', opacity: 0.45, points: 'M462 375h0M252 311h0M202 477h0M298 443h0M208 600h0M167 216h0M541 306h0M47 605h0M401 38h0M101 610h0M620 113h0M189 63h0M293 536h0M199 606h0M241 266h0M82 304h0M52 6h0M50 137h0M104 532h0M103 368h0M278 199h0M245 328h0M51 59h0M194 68h0M37 219h0M322 310h0M339 230h0M552 48h0M576 155h0M612 480h0' },\n { width: 1.5, color: '#e3e9ff', opacity: 0.75, points: 'M568 195h0M633 111h0M342 180h0M527 323h0M532 283h0M623 494h0M123 125h0M310 588h0M127 394h0M36 377h0M297 418h0M306 11h0M244 382h0M153 210h0M173 288h0M104 454h0' },\n { width: 2.1, color: '#fff', opacity: 0.95, points: 'M221 502h0M523 249h0M489 393h0M633 604h0M173 467h0M218 505h0' },\n { width: 1.5, color: '#ffe7c7', opacity: 0.8, points: 'M382 480h0M367 90h0M103 79h0M497 64h0M339 614h0M541 446h0' },\n];\n\n/** The star tile as a CSS background layer. */\nconst starfield = (): string => {\n const paths = STARS.map((stars) => `<path d='${stars.points}' stroke='${stars.color}' stroke-opacity='${stars.opacity}' stroke-width='${stars.width}' stroke-linecap='round'/>`);\n const svg = `<svg xmlns='http://www.w3.org/2000/svg' width='640' height='640'>${paths.join('')}</svg>`;\n return `url(\"data:image/svg+xml,${svg.replace(/</g, '%3C').replace(/>/g, '%3E').replace(/#/g, '%23')}\") 0 0 / 640px 640px`;\n};\n\n/** Jewel-toned planets lit from one side, a star with a corona, and a field of stars. */\nconst COSMOS: OrbitThemeTokens = {\n ...NIGHT,\n surface: '#05060E',\n 'surface-pattern': [\n starfield(),\n 'radial-gradient(80% 60% at 78% 16%, rgba(98, 70, 214, 0.26), transparent 70%)',\n 'radial-gradient(70% 55% at 14% 88%, rgba(16, 150, 160, 0.16), transparent 70%)',\n ].join(', '),\n 'label-shadow': '0 1px 2px rgba(0, 0, 0, 0.45)',\n text: '#E7E9F7',\n 'muted-text': '#9CA3C4',\n 'root-text': '#1A1206',\n 'node-text': '#14102B',\n 'node-text-inverse': '#FFFFFF',\n 'color-root': '#FFC75A',\n 'color-1': '#285CC2',\n 'color-2': '#863CA4',\n 'color-3': '#A42C71',\n 'color-4': '#017272',\n 'color-5': '#0B7643',\n 'color-6': '#A14206',\n 'color-7': '#5D4DBE',\n 'shade-light': '#4B4F7A',\n 'shade-dark': '#05060E',\n 'moon-opacity': '1',\n 'node-highlight': 'rgba(255, 244, 214, 0.1)',\n 'node-terminator': 'rgba(5, 6, 14, 0.28)',\n 'node-shading': 'rgba(5, 6, 14, 0.6)',\n 'node-stroke': 'rgba(255, 255, 255, 0.6)',\n 'node-stroke-tint': '50%',\n 'badge-stroke': '#05060E',\n 'node-shadow-opacity': '0.4',\n 'node-shadow-size': '1.12',\n 'sun-shadow-opacity': '0.7',\n 'sun-shadow-size': '1.55',\n 'ring-stroke': '#8EA2FF',\n 'ring-tint': '20%',\n 'ring-opacity': '0.32',\n 'ring-width': '1',\n 'ring-dash': 'none',\n 'link-stroke': '#8EA2FF',\n 'link-tint': '45%',\n 'link-opacity': '0.4',\n 'link-width': '1',\n 'focus-ring': '#A5B4FF',\n 'note-indicator': '#E7E9F7',\n 'control-background': 'rgba(14, 16, 32, 0.8)',\n 'control-border': 'rgba(142, 162, 255, 0.2)',\n 'control-text': '#E7E9F7',\n 'control-muted-text': '#9CA3C4',\n 'control-active-background': '#E7E9F7',\n 'control-active-text': '#05060E',\n 'control-shadow': '0 8px 24px rgba(0, 0, 0, 0.5)',\n 'control-blur': '14px',\n 'tooltip-background': '#E7E9F7',\n 'tooltip-text': '#05060E',\n 'action-background': '#14172B',\n 'action-border': 'rgba(142, 162, 255, 0.28)',\n 'action-text': '#E7E9F7',\n 'action-shadow': '0 6px 16px rgba(0, 0, 0, 0.5)',\n 'sheet-background': '#0D0F1E',\n 'sheet-text': '#E7E9F7',\n 'sheet-muted-text': '#9CA3C4',\n 'sheet-border': 'rgba(142, 162, 255, 0.16)',\n 'sheet-backdrop': 'rgba(2, 3, 10, 0.65)',\n 'sheet-shadow': '0 24px 64px rgba(0, 0, 0, 0.65)',\n 'chip-background': 'rgba(142, 162, 255, 0.14)',\n 'chip-text': '#DDE3FF',\n 'link-text': '#A5B4FF',\n};\n\n/** A technical drawing: outlined planets, construction lines and monospaced labels on a gridded blue sheet. */\nconst BLUEPRINT: OrbitThemeTokens = {\n ...NIGHT,\n 'font-family': 'var(--_orbit-mono-font)',\n 'label-weight': '500',\n 'display-weight': '600',\n // Monospaced letters, set a little tighter so names stay compact.\n 'label-letter-spacing': '-0.02em',\n 'label-shadow': 'none',\n surface: '#123A7A',\n 'surface-pattern': [\n 'linear-gradient(rgba(255, 255, 255, 0.12) 1px, transparent 1px) 0 0 / 120px 120px',\n 'linear-gradient(90deg, rgba(255, 255, 255, 0.12) 1px, transparent 1px) 0 0 / 120px 120px',\n 'linear-gradient(rgba(255, 255, 255, 0.06) 1px, transparent 1px) 0 0 / 24px 24px',\n 'linear-gradient(90deg, rgba(255, 255, 255, 0.06) 1px, transparent 1px) 0 0 / 24px 24px',\n ].join(', '),\n text: '#FFFFFF',\n 'muted-text': 'rgba(255, 255, 255, 0.72)',\n // White lines and lettering throughout, as on a print.\n 'root-text': '#FFFFFF',\n 'node-text': '#FFFFFF',\n 'node-text-inverse': '#FFFFFF',\n 'color-root': '#FFFFFF',\n 'color-1': '#C2F3F5',\n 'color-2': '#CCF3DD',\n 'color-3': '#D4ECFD',\n 'color-4': '#EBE3FC',\n 'color-5': '#FFE2CA',\n 'color-6': '#FEDEEC',\n 'color-7': '#C2F3F2',\n 'shade-light': '#FFFFFF',\n 'shade-dark': '#123A7A',\n 'node-fill-opacity': '0.12',\n 'moon-opacity': '0.12',\n 'node-highlight': 'rgba(255, 255, 255, 0)',\n 'node-terminator': 'rgba(18, 58, 122, 0)',\n 'node-shading': 'rgba(18, 58, 122, 0)',\n 'node-stroke': '#FFFFFF',\n 'node-stroke-tint': '30%',\n 'node-stroke-width': '1.5',\n 'badge-stroke': '#123A7A',\n 'node-shadow-opacity': '0',\n 'sun-shadow-opacity': '0',\n 'sun-halo': '#FFFFFF',\n 'sun-halo-tint': '0%',\n 'sun-halo-opacity': '0.7',\n 'sun-halo-width': '1',\n 'sun-halo-dash': '4 4',\n 'sun-halo-size': '1.2',\n 'ring-stroke': '#FFFFFF',\n 'ring-tint': '0%',\n 'ring-opacity': '0.5',\n 'ring-width': '1',\n 'ring-dash': '7 5',\n 'link-stroke': '#FFFFFF',\n 'link-tint': '0%',\n 'link-opacity': '0.55',\n 'link-width': '1',\n 'focus-ring': '#FFD166',\n 'note-indicator': '#FFFFFF',\n 'control-background': 'rgba(14, 45, 99, 0.9)',\n 'control-border': 'rgba(255, 255, 255, 0.32)',\n 'control-text': '#FFFFFF',\n 'control-muted-text': 'rgba(255, 255, 255, 0.72)',\n 'control-active-background': '#FFFFFF',\n 'control-active-text': '#123A7A',\n 'control-shadow': 'none',\n 'control-blur': '0px',\n 'tooltip-background': '#FFFFFF',\n 'tooltip-text': '#123A7A',\n 'action-background': '#123A7A',\n 'action-border': 'rgba(255, 255, 255, 0.6)',\n 'action-text': '#FFFFFF',\n 'action-shadow': 'none',\n 'sheet-background': '#0F3470',\n 'sheet-text': '#FFFFFF',\n 'sheet-muted-text': 'rgba(255, 255, 255, 0.75)',\n 'sheet-border': 'rgba(255, 255, 255, 0.25)',\n 'sheet-backdrop': 'rgba(5, 18, 42, 0.6)',\n 'sheet-shadow': '0 24px 64px rgba(0, 0, 0, 0.45)',\n 'chip-background': 'rgba(255, 255, 255, 0.12)',\n 'chip-text': '#FFFFFF',\n 'link-text': '#BFE3FF',\n 'status-active': '#7CC4FF',\n 'status-done': '#7EE2A8',\n 'status-blocked': '#FF8A8A',\n 'status-todo': 'rgba(255, 255, 255, 0.6)',\n 'status-neutral': 'rgba(255, 255, 255, 0.75)',\n 'error-background': '#3A1622',\n 'error-border': '#FF8A8A',\n 'error-text': '#FFD7D7',\n};\n\n/** Black line art on the page's own background: outlined planets, a black sun and serif lettering. */\nconst INK: OrbitThemeTokens = {\n ...PAPER,\n 'label-font': 'var(--_orbit-serif-font)',\n 'display-font': 'var(--_orbit-serif-font)',\n 'label-weight': '600',\n 'display-weight': '600',\n 'label-letter-spacing': '0',\n text: '#111111',\n 'muted-text': '#55555F',\n 'root-text': '#111111',\n 'node-text': '#111111',\n 'color-root': '#111111',\n 'color-1': '#FFFFFF',\n 'color-2': '#F7F4EE',\n 'color-3': '#EEF2F6',\n 'color-4': '#F4F0F7',\n 'color-5': '#F1F5EF',\n 'color-6': '#F8F1EF',\n 'color-7': '#EFF4F4',\n 'shade-dark': '#111111',\n 'moon-opacity': '1',\n 'node-highlight': 'rgba(255, 255, 255, 0)',\n 'node-terminator': 'rgba(17, 17, 17, 0)',\n 'node-shading': 'rgba(17, 17, 17, 0)',\n 'node-stroke': '#111111',\n 'node-stroke-tint': '0%',\n 'node-stroke-width': '1.5',\n 'node-shadow-opacity': '0',\n 'sun-shadow-opacity': '0',\n 'sun-halo': '#111111',\n 'sun-halo-tint': '0%',\n 'sun-halo-opacity': '1',\n 'sun-halo-width': '1',\n 'sun-halo-size': '1.12',\n 'ring-stroke': '#111111',\n 'ring-tint': '0%',\n 'ring-opacity': '0.6',\n 'ring-width': '1.5',\n 'ring-dash': '0.5 5',\n 'link-stroke': '#111111',\n 'link-tint': '0%',\n 'link-opacity': '0.7',\n 'link-width': '1',\n 'focus-ring': '#C81E1E',\n 'note-indicator': '#C81E1E',\n 'control-background': 'rgba(255, 255, 255, 0.95)',\n 'control-border': '#111111',\n 'control-text': '#111111',\n 'control-muted-text': '#55555F',\n 'control-active-background': '#111111',\n 'control-active-text': '#FFFFFF',\n 'control-shadow': '2px 2px 0 #111111',\n 'control-blur': '0px',\n 'tooltip-background': '#111111',\n 'tooltip-text': '#FFFFFF',\n 'action-background': '#FFFFFF',\n 'action-border': '#111111',\n 'action-text': '#111111',\n 'action-shadow': '2px 2px 0 #111111',\n 'sheet-background': '#FFFFFF',\n 'sheet-text': '#111111',\n 'sheet-muted-text': '#55555F',\n 'sheet-border': '#111111',\n 'sheet-backdrop': 'rgba(17, 17, 17, 0.35)',\n 'sheet-shadow': '6px 6px 0 #111111',\n 'chip-background': '#F3F1EC',\n 'chip-text': '#111111',\n 'link-text': '#C81E1E',\n 'status-active': '#1D4ED8',\n 'status-done': '#15803D',\n 'status-blocked': '#C81E1E',\n 'status-todo': '#9CA3AF',\n 'status-neutral': '#6B7280',\n 'error-background': '#FFF5F5',\n 'error-border': '#C81E1E',\n 'error-text': '#7A1414',\n};\n\n/** Maximum legibility: black text and outlines, solid colors and bold labels on white. */\nconst CONTRAST: OrbitThemeTokens = {\n ...PAPER,\n 'label-weight': '700',\n 'display-weight': '800',\n 'label-letter-spacing': '0',\n surface: '#FFFFFF',\n text: '#000000',\n 'muted-text': '#3D3D3D',\n 'root-text': '#000000',\n 'node-text': '#000000',\n 'color-root': '#FFE066',\n 'color-1': '#FFA8A8',\n 'color-2': '#8CE99A',\n 'color-3': '#74C0FC',\n 'color-4': '#B197FC',\n 'color-5': '#FFC078',\n 'color-6': '#F783AC',\n 'color-7': '#63E6BE',\n // Deeper nodes only get lighter, so black text stays well above AAA.\n 'shade-dark': '#FFFFFF',\n 'moon-opacity': '1',\n 'node-highlight': 'rgba(255, 255, 255, 0)',\n 'node-terminator': 'rgba(0, 0, 0, 0)',\n 'node-shading': 'rgba(0, 0, 0, 0)',\n 'node-stroke': '#000000',\n 'node-stroke-tint': '0%',\n 'node-stroke-width': '2',\n 'node-shadow-opacity': '0',\n 'sun-shadow-opacity': '0',\n 'sun-halo-opacity': '0',\n 'ring-stroke': '#000000',\n 'ring-tint': '0%',\n 'ring-opacity': '0.7',\n 'ring-width': '1.5',\n 'ring-dash': '3 5',\n 'link-stroke': '#000000',\n 'link-tint': '0%',\n 'link-opacity': '0.8',\n 'link-width': '2',\n 'focus-ring': '#0040DD',\n 'note-indicator': '#000000',\n 'control-background': '#FFFFFF',\n 'control-border': '#000000',\n 'control-text': '#000000',\n 'control-muted-text': '#3D3D3D',\n 'control-active-background': '#000000',\n 'control-active-text': '#FFFFFF',\n 'control-shadow': 'none',\n 'control-blur': '0px',\n 'tooltip-background': '#000000',\n 'tooltip-text': '#FFFFFF',\n 'action-background': '#FFFFFF',\n 'action-border': '#000000',\n 'action-text': '#000000',\n 'action-shadow': 'none',\n 'sheet-background': '#FFFFFF',\n 'sheet-text': '#000000',\n 'sheet-muted-text': '#3D3D3D',\n 'sheet-border': '#000000',\n 'sheet-backdrop': 'rgba(0, 0, 0, 0.6)',\n 'sheet-shadow': 'none',\n 'chip-background': '#F0F0F0',\n 'chip-text': '#000000',\n 'link-text': '#0040DD',\n 'status-active': '#0040DD',\n 'status-done': '#007A33',\n 'status-blocked': '#C00000',\n 'status-todo': '#595959',\n 'status-neutral': '#3D3D3D',\n 'error-background': '#FFFFFF',\n 'error-border': '#C00000',\n 'error-text': '#7A0000',\n};\n\n/** Solid, saturated planets with white lettering: no shading, shadows or glow, and a white edge where bodies overlap. */\nconst FLAT: OrbitThemeTokens = {\n ...PAPER,\n 'label-weight': '650',\n 'display-weight': '750',\n 'label-letter-spacing': '0',\n text: '#111827',\n 'muted-text': '#4B5563',\n 'root-text': '#111827',\n 'node-text': '#111827',\n 'node-text-inverse': '#FFFFFF',\n 'color-root': '#FFC233',\n 'color-1': '#C82F2C',\n 'color-2': '#007B3D',\n 'color-3': '#0C66D7',\n 'color-4': '#844DCC',\n 'color-5': '#AD5000',\n 'color-6': '#BE307D',\n 'color-7': '#007777',\n 'shade-dark': '#111827',\n 'moon-opacity': '1',\n 'node-highlight': 'rgba(255, 255, 255, 0)',\n 'node-terminator': 'rgba(17, 24, 39, 0)',\n 'node-shading': 'rgba(17, 24, 39, 0)',\n 'node-stroke': '#FFFFFF',\n 'node-stroke-tint': '0%',\n 'node-stroke-width': '2',\n 'node-shadow-opacity': '0',\n 'sun-shadow-opacity': '0',\n 'sun-halo': '#111827',\n 'sun-halo-tint': '100%',\n 'sun-halo-opacity': '0.3',\n 'sun-halo-width': '6',\n 'sun-halo-dash': 'none',\n 'sun-halo-size': '1.14',\n 'ring-stroke': '#111827',\n 'ring-tint': '0%',\n 'ring-opacity': '0.14',\n 'ring-width': '1.5',\n 'ring-dash': 'none',\n 'link-stroke': '#111827',\n 'link-tint': '100%',\n 'link-opacity': '0.55',\n 'link-width': '2',\n 'link-dash': 'none',\n 'focus-ring': '#0C66D7',\n 'note-indicator': '#111827',\n 'control-background': '#FFFFFF',\n 'control-border': '#E5E7EB',\n 'control-text': '#111827',\n 'control-muted-text': '#4B5563',\n 'control-active-background': '#111827',\n 'control-active-text': '#FFFFFF',\n 'control-shadow': 'none',\n 'control-blur': '0px',\n 'tooltip-background': '#111827',\n 'tooltip-text': '#FFFFFF',\n 'action-background': '#FFFFFF',\n 'action-border': '#E5E7EB',\n 'action-text': '#111827',\n 'action-shadow': 'none',\n 'sheet-background': '#FFFFFF',\n 'sheet-text': '#111827',\n 'sheet-muted-text': '#4B5563',\n 'sheet-border': '#E5E7EB',\n 'sheet-backdrop': 'rgba(17, 24, 39, 0.5)',\n 'sheet-shadow': 'none',\n 'chip-background': '#F3F4F6',\n 'chip-text': '#111827',\n 'link-text': '#0C66D7',\n 'status-active': '#0C66D7',\n 'status-done': '#007B3D',\n 'status-blocked': '#C82F2C',\n 'status-todo': '#9CA3AF',\n 'status-neutral': '#6B7280',\n 'error-background': '#FEF2F2',\n 'error-border': '#C82F2C',\n 'error-text': '#7F1D1D',\n};\n\n/** The flat look at night: bright solid planets with dark lettering, cut out from a near-black page. */\nconst FLAT_NIGHT: OrbitThemeTokens = {\n ...FLAT,\n surface: '#121418',\n text: '#F3F4F6',\n 'muted-text': '#9CA3AF',\n 'root-text': '#0B0D12',\n 'node-text': '#0B0D12',\n 'node-text-inverse': '#F3F4F6',\n 'color-root': '#FFD25A',\n 'color-1': '#FF9287',\n 'color-2': '#3EC873',\n 'color-3': '#7EB2FF',\n 'color-4': '#C29FFF',\n 'color-5': '#FF9657',\n 'color-6': '#FF8BC1',\n 'color-7': '#00C4C5',\n 'shade-dark': '#121418',\n 'node-stroke': '#121418',\n 'badge-stroke': '#121418',\n 'sun-halo': '#FFFFFF',\n 'sun-halo-opacity': '0.55',\n 'sun-halo-width': '4',\n 'ring-stroke': '#FFFFFF',\n 'link-stroke': '#FFFFFF',\n 'link-opacity': '0.6',\n 'focus-ring': '#7EB2FF',\n 'note-indicator': '#F3F4F6',\n 'control-background': '#1C1F26',\n 'control-border': '#2D3139',\n 'control-text': '#F3F4F6',\n 'control-muted-text': '#9CA3AF',\n 'control-active-background': '#F3F4F6',\n 'control-active-text': '#121418',\n 'tooltip-background': '#F3F4F6',\n 'tooltip-text': '#121418',\n 'action-background': '#1C1F26',\n 'action-border': '#2D3139',\n 'action-text': '#F3F4F6',\n 'sheet-background': '#1A1D23',\n 'sheet-text': '#F3F4F6',\n 'sheet-muted-text': '#9CA3AF',\n 'sheet-border': '#2D3139',\n 'sheet-backdrop': 'rgba(0, 0, 0, 0.6)',\n 'chip-background': '#262A32',\n 'chip-text': '#E5E7EB',\n 'link-text': '#7EB2FF',\n 'status-active': '#7EB2FF',\n 'status-done': '#3EC873',\n 'status-blocked': '#FF9287',\n 'status-todo': '#6B7280',\n 'status-neutral': '#9CA3AF',\n 'error-background': '#2A1517',\n 'error-border': '#FF9287',\n 'error-text': '#FECACA',\n};\n\n/** What Material themes share whatever their color: flat tonal surfaces, no rims or shadows on planets, raised controls. */\nconst MATERIAL_LOOK: Partial<OrbitThemeTokens> = {\n 'label-weight': '550',\n 'display-weight': '650',\n 'label-letter-spacing': '0',\n 'surface-pattern': 'none',\n 'node-fill-opacity': '1',\n 'moon-opacity': '1',\n 'node-highlight': 'rgba(255, 255, 255, 0)',\n 'node-terminator': 'rgba(0, 0, 0, 0)',\n 'node-shading': 'rgba(0, 0, 0, 0)',\n 'node-stroke-tint': '0%',\n 'node-stroke-width': '0',\n 'node-shadow-opacity': '0',\n 'sun-shadow-opacity': '0',\n 'sun-halo-tint': '0%',\n 'sun-halo-opacity': '0.18',\n 'sun-halo-width': '8',\n 'sun-halo-dash': 'none',\n 'sun-halo-size': '1.16',\n 'ring-tint': '0%',\n 'ring-opacity': '1',\n 'ring-width': '1',\n 'ring-dash': 'none',\n 'link-tint': '0%',\n 'link-opacity': '0.7',\n 'link-width': '1.5',\n 'link-dash': 'none',\n 'control-border': 'transparent',\n 'control-shadow': '0 1px 2px rgba(0, 0, 0, 0.3), 0 2px 6px 2px rgba(0, 0, 0, 0.15)',\n 'control-blur': '0px',\n 'action-border': 'transparent',\n 'action-shadow': '0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 3px 1px rgba(0, 0, 0, 0.15)',\n 'sheet-backdrop': 'rgba(0, 0, 0, 0.32)',\n 'sheet-shadow': '0 1px 3px rgba(0, 0, 0, 0.3), 0 4px 8px 3px rgba(0, 0, 0, 0.15)',\n 'sheet-blur': '0px',\n};\n\n/**\n * Material 3: tonal containers in hues spread around the wheel from\n * Material's baseline purple, the sun in its primary color, on a tonal\n * surface. `materialTheme(color)` builds the same look from any color; these\n * values are what it gives for Material's baseline color (`MATERIAL_SEED`).\n */\nconst MATERIAL: OrbitThemeTokens = {\n ...PAPER,\n ...MATERIAL_LOOK,\n surface: '#FAF9FF',\n text: '#1C1B21',\n 'muted-text': '#484553',\n 'root-text': '#1C1B21',\n 'node-text': '#1C1B21',\n 'node-text-inverse': '#FFFFFF',\n 'color-root': '#6750A4',\n 'color-1': '#DFD8FF',\n 'color-2': '#FBD985',\n 'color-3': '#BCE1FF',\n 'color-4': '#FFD3C7',\n 'color-5': '#76F0EA',\n 'color-6': '#FFD0E9',\n 'color-7': '#B3EBA5',\n 'shade-light': '#C7C4D6',\n 'shade-dark': '#787585',\n 'node-stroke': '#C7C4D6',\n 'badge-stroke': '#FAF9FF',\n 'sun-halo': '#6750A4',\n 'ring-stroke': '#C7C4D6',\n 'link-stroke': '#787585',\n 'focus-ring': '#6750A4',\n 'note-indicator': '#6750A4',\n 'control-background': '#EEEDF6',\n 'control-text': '#1C1B21',\n 'control-muted-text': '#484553',\n 'control-active-background': '#E4DFFF',\n 'control-active-text': '#1D182F',\n 'tooltip-background': '#313036',\n 'tooltip-text': '#F1F0F9',\n 'action-background': '#E9E7F0',\n 'action-text': '#1C1B21',\n 'sheet-background': '#F4F2FB',\n 'sheet-text': '#1C1B21',\n 'sheet-muted-text': '#484553',\n 'sheet-border': '#C7C4D6',\n 'chip-background': '#E4DFFF',\n 'chip-text': '#1D182F',\n 'link-text': '#6750A4',\n 'status-active': '#6750A4',\n 'status-done': '#1C6D26',\n 'status-blocked': '#B91B25',\n 'status-todo': '#928F9F',\n 'status-neutral': '#787585',\n 'error-background': '#FFDAD6',\n 'error-border': '#B91B25',\n 'error-text': '#410004',\n};\n\n/** Material 3's dark scheme: deep tonal containers with light lettering, the sun in the light primary. */\nconst MATERIAL_NIGHT: OrbitThemeTokens = {\n ...NIGHT,\n ...MATERIAL_LOOK,\n 'control-shadow': '0 1px 3px rgba(0, 0, 0, 0.3), 0 4px 8px 3px rgba(0, 0, 0, 0.15)',\n surface: '#141318',\n text: '#E3E1EA',\n 'muted-text': '#C7C4D6',\n 'root-text': '#1C1B21',\n 'node-text': '#1C1B21',\n 'node-text-inverse': '#E3E1EA',\n 'color-root': '#CBBEFF',\n 'color-1': '#524084',\n 'color-2': '#5F4800',\n 'color-3': '#004F7B',\n 'color-4': '#7F341F',\n 'color-5': '#005552',\n 'color-6': '#78335D',\n 'color-7': '#245615',\n 'shade-light': '#5F5D65',\n 'shade-dark': '#201F25',\n 'node-stroke': '#484553',\n 'badge-stroke': '#141318',\n 'sun-halo': '#CBBEFF',\n 'ring-stroke': '#484553',\n 'link-stroke': '#928F9F',\n 'focus-ring': '#CBBEFF',\n 'note-indicator': '#CBBEFF',\n 'control-background': '#201F25',\n 'control-text': '#E3E1EA',\n 'control-muted-text': '#C7C4D6',\n 'control-active-background': '#49435D',\n 'control-active-text': '#E4DFFF',\n 'tooltip-background': '#E3E1EA',\n 'tooltip-text': '#313036',\n 'action-background': '#2A2930',\n 'action-text': '#E3E1EA',\n 'sheet-background': '#1C1B21',\n 'sheet-text': '#E3E1EA',\n 'sheet-muted-text': '#C7C4D6',\n 'sheet-border': '#484553',\n 'chip-background': '#49435D',\n 'chip-text': '#E4DFFF',\n 'link-text': '#CBBEFF',\n 'status-active': '#CBBEFF',\n 'status-done': '#8AD88D',\n 'status-blocked': '#FFB3AD',\n 'status-todo': '#928F9F',\n 'status-neutral': '#ACA9BA',\n 'error-background': '#930014',\n 'error-border': '#FFB3AD',\n 'error-text': '#FFDAD6',\n};\n\n/**\n * Liquid glass: clear planets with a bright specular highlight, a white\n * rim and light caught along the far edge, over a vivid wallpaper of their\n * own that the glass lets through.\n */\nconst LIQUID: OrbitThemeTokens = {\n ...PAPER,\n 'label-letter-spacing': '-0.01em',\n surface: '#E9EEF8',\n 'surface-pattern': [\n 'radial-gradient(70% 55% at 12% 14%, rgba(90, 140, 255, 0.55), transparent 70%)',\n 'radial-gradient(60% 50% at 88% 20%, rgba(255, 120, 190, 0.5), transparent 70%)',\n 'radial-gradient(70% 60% at 30% 92%, rgba(60, 220, 200, 0.45), transparent 72%)',\n 'radial-gradient(55% 45% at 92% 88%, rgba(255, 190, 90, 0.55), transparent 70%)',\n ].join(', '),\n text: '#0F1630',\n 'muted-text': '#3B4560',\n // Dark labels on every planet: the glass lets the light wallpaper through.\n 'root-text': '#0F1630',\n 'node-text': '#0F1630',\n 'node-text-inverse': '#0F1630',\n 'color-root': '#FFC83D',\n 'color-1': '#FF6B7A',\n 'color-2': '#2FD08A',\n 'color-3': '#4DA3FF',\n 'color-4': '#9B7BFF',\n 'color-5': '#FF9A3D',\n 'color-6': '#FF6FB5',\n 'color-7': '#22C7D6',\n 'shade-dark': '#0F1630',\n 'node-fill-opacity': '0.32',\n 'moon-opacity': '0.28',\n // Clear in the middle, with a lens edge: the shading's circle sits a little\n // to the bottom right, so light catches the rim all around, most at the top\n // left, just past a faint darker band where the glass bends the light.\n 'node-highlight': 'rgba(255, 255, 255, 0)',\n 'node-terminator': 'rgba(16, 24, 60, 0.07)',\n 'node-shading': 'rgba(255, 255, 255, 0.95)',\n 'node-shade-circle': '0.53 0.55 0.56',\n 'node-stroke': '#FFFFFF',\n 'node-stroke-tint': '0%',\n 'node-stroke-width': '1.25',\n 'node-shadow': '#1B2550',\n 'node-shadow-tint': '0%',\n 'node-shadow-opacity': '0.16',\n 'node-shadow-offset': '0.14',\n 'node-shadow-size': '1',\n 'sun-shadow-opacity': '0.2',\n 'sun-shadow-size': '1.02',\n 'sun-halo': '#FFFFFF',\n 'sun-halo-tint': '0%',\n 'sun-halo-opacity': '0.9',\n 'sun-halo-width': '1.5',\n 'sun-halo-dash': 'none',\n 'sun-halo-size': '1.1',\n 'ring-stroke': '#FFFFFF',\n 'ring-tint': '0%',\n 'ring-opacity': '0.7',\n 'ring-width': '1.25',\n 'ring-dash': 'none',\n 'link-stroke': '#FFFFFF',\n 'link-tint': '0%',\n 'link-opacity': '0.75',\n 'link-dash': 'none',\n 'note-indicator': '#0F1630',\n 'control-background': 'rgba(255, 255, 255, 0.38)',\n 'control-border': 'rgba(255, 255, 255, 0.75)',\n 'control-text': '#0F1630',\n 'control-muted-text': '#3B4560',\n 'control-active-background': 'rgba(255, 255, 255, 0.85)',\n 'control-active-text': '#0F1630',\n 'control-shadow': '0 10px 30px rgba(20, 30, 70, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.9)',\n 'control-blur': '24px',\n 'tooltip-background': 'rgba(255, 255, 255, 0.88)',\n 'tooltip-text': '#0F1630',\n 'action-background': 'rgba(255, 255, 255, 0.55)',\n 'action-border': 'rgba(255, 255, 255, 0.85)',\n 'action-text': '#0F1630',\n 'action-shadow': '0 6px 18px rgba(20, 30, 70, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.9)',\n 'sheet-background': 'rgba(255, 255, 255, 0.7)',\n 'sheet-text': '#0F1630',\n 'sheet-muted-text': '#3B4560',\n 'sheet-border': 'rgba(255, 255, 255, 0.8)',\n 'sheet-backdrop': 'rgba(15, 22, 48, 0.25)',\n 'sheet-shadow': '0 30px 80px rgba(20, 30, 70, 0.3)',\n 'sheet-blur': '30px',\n 'chip-background': 'rgba(255, 255, 255, 0.6)',\n 'chip-text': '#1E293B',\n 'link-text': '#1D4ED8',\n};\n\n/** Liquid glass at night: clear planets that glow in their own color over a deep, vivid wallpaper. */\nconst LIQUID_NIGHT: OrbitThemeTokens = {\n ...NIGHT,\n 'label-letter-spacing': '-0.01em',\n 'label-shadow': '0 1px 3px rgba(3, 6, 20, 0.6)',\n surface: '#070B1A',\n 'surface-pattern': [\n 'radial-gradient(70% 55% at 14% 12%, rgba(79, 70, 229, 0.55), transparent 70%)',\n 'radial-gradient(60% 50% at 88% 22%, rgba(219, 39, 119, 0.42), transparent 70%)',\n 'radial-gradient(70% 60% at 26% 94%, rgba(6, 182, 212, 0.36), transparent 72%)',\n 'radial-gradient(55% 45% at 92% 90%, rgba(249, 115, 22, 0.32), transparent 70%)',\n ].join(', '),\n text: '#F5F7FF',\n 'muted-text': '#B4BDD8',\n // Light labels on every planet: the glass lets the dark wallpaper through.\n 'root-text': '#F8FAFF',\n 'node-text': '#F8FAFF',\n 'node-text-inverse': '#F8FAFF',\n 'color-root': '#FFD66B',\n 'color-1': '#FF6B8B',\n 'color-2': '#34D399',\n 'color-3': '#60A5FA',\n 'color-4': '#A78BFA',\n 'color-5': '#FB923C',\n 'color-6': '#F472B6',\n 'color-7': '#22D3EE',\n 'shade-dark': '#070B1A',\n 'node-fill-opacity': '0.2',\n 'moon-opacity': '0.16',\n 'node-highlight': 'rgba(255, 255, 255, 0)',\n 'node-terminator': 'rgba(255, 255, 255, 0.04)',\n 'node-shading': 'rgba(255, 255, 255, 0.7)',\n 'node-shade-circle': '0.53 0.55 0.56',\n 'node-stroke': 'rgba(255, 255, 255, 0.75)',\n 'node-stroke-tint': '0%',\n 'node-stroke-width': '1.25',\n 'badge-stroke': '#070B1A',\n 'node-shadow-opacity': '0.3',\n 'node-shadow-size': '1.1',\n 'sun-shadow-opacity': '0.45',\n 'sun-shadow-size': '1.3',\n 'sun-halo': '#FFFFFF',\n 'sun-halo-tint': '0%',\n 'sun-halo-opacity': '0.6',\n 'sun-halo-width': '1.5',\n 'sun-halo-dash': 'none',\n 'sun-halo-size': '1.1',\n 'ring-tint': '0%',\n 'ring-opacity': '0.28',\n 'ring-width': '1.25',\n 'ring-dash': 'none',\n 'link-tint': '0%',\n 'link-opacity': '0.35',\n 'link-dash': 'none',\n 'note-indicator': '#F5F7FF',\n 'control-background': 'rgba(255, 255, 255, 0.1)',\n 'control-border': 'rgba(255, 255, 255, 0.22)',\n 'control-text': '#F5F7FF',\n 'control-muted-text': '#B4BDD8',\n 'control-active-background': 'rgba(255, 255, 255, 0.9)',\n 'control-active-text': '#070B1A',\n 'control-shadow': '0 10px 30px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.25)',\n 'control-blur': '24px',\n 'tooltip-background': 'rgba(245, 247, 255, 0.92)',\n 'tooltip-text': '#070B1A',\n 'action-background': 'rgba(255, 255, 255, 0.12)',\n 'action-border': 'rgba(255, 255, 255, 0.28)',\n 'action-text': '#F5F7FF',\n 'action-shadow': '0 6px 18px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.25)',\n 'sheet-background': 'rgba(22, 28, 52, 0.72)',\n 'sheet-text': '#F5F7FF',\n 'sheet-muted-text': '#B4BDD8',\n 'sheet-border': 'rgba(255, 255, 255, 0.18)',\n 'sheet-backdrop': 'rgba(2, 4, 14, 0.5)',\n 'sheet-shadow': '0 30px 80px rgba(0, 0, 0, 0.6)',\n 'sheet-blur': '30px',\n 'chip-background': 'rgba(255, 255, 255, 0.12)',\n 'chip-text': '#E8ECFF',\n};\n\nexport const ORBIT_THEME_PRESETS: Readonly<Record<OrbitThemeName, Readonly<OrbitThemeTokens>>> = {\n paper: PAPER,\n night: NIGHT,\n glass: GLASS,\n 'glass-night': GLASS_NIGHT,\n cosmos: COSMOS,\n blueprint: BLUEPRINT,\n ink: INK,\n contrast: CONTRAST,\n flat: FLAT,\n 'flat-night': FLAT_NIGHT,\n material: MATERIAL,\n 'material-night': MATERIAL_NIGHT,\n liquid: LIQUID,\n 'liquid-night': LIQUID_NIGHT,\n};\n\n/** Themes drawn on a dark background, so the browser's own widgets (scrollbars, form controls) match. */\nconst DARK_THEMES = new Set<OrbitThemeName>(['night', 'glass-night', 'cosmos', 'blueprint', 'flat-night', 'material-night', 'liquid-night']);\n\n/** Whether `value` names a built-in theme: one of the presets or `auto`. */\nexport const isOrbitThemePreset = (value: unknown): value is OrbitThemePreset => {\n return typeof value === 'string' && (value === 'auto' || Object.prototype.hasOwnProperty.call(ORBIT_THEME_PRESETS, value));\n};\n\n/** The built-in theme a `theme` option starts from (registered names followed), `paper` when it names none. */\nexport const themeName = (theme: string | OrbitRendererTheme | undefined): OrbitThemePreset => {\n const expanded = expandTheme(theme);\n const preset = typeof expanded === 'string' ? expanded : expanded?.preset;\n return isOrbitThemePreset(preset) ? preset : 'paper';\n};\n\nconst registeredThemes = new Map<string, OrbitRendererTheme>();\n\n/**\n * Names a theme for every map, so `theme: 'brand'` works in options, in a\n * document's frontmatter and on `<orbit-map theme=\"brand\">`. It starts from\n * `preset` (a built-in theme or another registered one) and sets its own\n * tokens. Returns a function that removes it again.\n */\nexport const registerTheme = (name: string, theme: OrbitRendererTheme): () => void => {\n if (isOrbitThemePreset(name)) {\n throw new Error(`\"${name}\" is one of Orbit's own themes; give yours another name.`);\n }\n\n if (!/^[\\w-]+$/.test(name)) {\n throw new Error(`Theme names use letters, digits, \"-\" and \"_\", so they work in attributes and frontmatter: \"${name}\".`);\n }\n\n const definition: OrbitRendererTheme = { preset: theme.preset, tokens: { ...theme.tokens } };\n registeredThemes.set(name, definition);\n\n return () => {\n if (registeredThemes.get(name) === definition) {\n registeredThemes.delete(name);\n }\n };\n};\n\n/** Whether `value` names a theme: a built-in one, `auto`, or a registered one. */\nexport const isThemeName = (value: unknown): value is string => {\n return isOrbitThemePreset(value) || (typeof value === 'string' && registeredThemes.has(value));\n};\n\n/** Every theme name: the built-in ones, `auto`, then the registered ones. */\nexport const themeNames = (): string[] => {\n return [...Object.keys(ORBIT_THEME_PRESETS), 'auto', ...registeredThemes.keys()];\n};\n\n/**\n * A `theme` option with registered names replaced by what they stand for:\n * `'brand'` becomes its `{ preset, tokens }`, and `{ preset: 'brand', tokens }`\n * adds its own tokens on top of brand's.\n */\nexport const expandTheme = (theme: string | OrbitRendererTheme | undefined): string | OrbitRendererTheme | undefined => {\n let expanded = theme;\n\n // A registered theme may start from another; a few steps cover any sensible chain.\n for (let depth = 0; depth < 4; depth += 1) {\n const name = typeof expanded === 'string' ? expanded : expanded?.preset;\n const registered = name === undefined ? undefined : registeredThemes.get(name);\n\n if (!registered) {\n break;\n }\n\n expanded = typeof expanded === 'string' ? registered : { preset: registered.preset, tokens: { ...registered.tokens, ...expanded?.tokens } };\n }\n\n return expanded;\n};\n\n/**\n * Combines a `theme` option with one set before it, such as the document's\n * `theme:`: a theme object without a `preset` builds on the earlier theme\n * instead of replacing it.\n */\nexport const mergeThemes = (\n base: string | OrbitRendererTheme | undefined,\n override: string | OrbitRendererTheme | undefined,\n): string | OrbitRendererTheme | undefined => {\n if (override === undefined || typeof override === 'string' || override.preset !== undefined || base === undefined) {\n return override ?? base;\n }\n\n const preset = typeof base === 'string' ? base : base.preset;\n return preset === undefined ? override : { ...override, preset };\n};\n\n/** Concrete token values for a theme name, built in or registered, e.g. for exports outside a page. `auto` resolves to `paper`. */\nexport const themeTokens = (name: string | undefined): OrbitThemeTokens => {\n const expanded = expandTheme(name);\n return resolveThemeTokens(themeName(expanded), typeof expanded === 'object' ? expanded : undefined);\n};\n\n/** A preset's values as written, where a token may refer to another (`var(--_orbit-font-family)`). */\nconst presetTokens = (preset: OrbitThemePreset | undefined): OrbitThemeTokens => {\n const name = preset ?? 'paper';\n return { ...ORBIT_THEME_PRESETS[name === 'auto' ? 'paper' : name] };\n};\n\n/**\n * Concrete values for every token: the preset's, then the theme object's,\n * then any the page resolved (`page`, already concrete). A token that refers\n * to another, such as the label font following `font-family`, follows it\n * through all three.\n */\nexport const resolveThemeTokens = (\n preset: OrbitThemePreset | undefined,\n theme?: OrbitRendererTheme,\n page: Partial<Record<OrbitThemeToken, string>> = {},\n): OrbitThemeTokens => {\n return resolveTokenReferences({ ...presetTokens(preset), ...themeObjectTokens(theme), ...page }) as OrbitThemeTokens;\n};\n\nconst resolveTokenReferences = (tokens: Record<string, string>): Record<string, string> => {\n const resolved: Record<string, string> = {};\n\n const resolve = (value: string, depth: number): string => {\n if (depth > 4 || !value.includes('var(')) {\n return value;\n }\n\n const substituted = value.replace(/var\\(--_?orbit-([a-z0-9-]+)(?:\\s*,\\s*([^()]+))?\\)/gi, (whole, token: string, fallback?: string) => {\n return tokens[token] ?? fallback?.trim() ?? whole;\n });\n\n return substituted === value ? value : resolve(substituted, depth + 1);\n };\n\n for (const [token, value] of Object.entries(tokens)) {\n resolved[token] = resolve(value, 0);\n }\n\n return resolved;\n};\n\nconst tokenDeclarations = (tokens: OrbitThemeTokens): string => {\n return THEME_TOKENS.map((token) => `--_orbit-${token}:var(--orbit-${token},${tokens[token]});`).join('');\n};\n\n/**\n * Where the stylesheet mixes a node's own color into a theme color, with\n * `color-mix()`: what it paints, the theme color, the tint (how much of the\n * node's own color goes in) and the node's own color.\n */\ninterface ColorMix {\n paints: string;\n base: OrbitThemeToken;\n tint: OrbitThemeToken;\n own: string;\n}\n\nconst MIXES: readonly ColorMix[] = [\n { paints: '.orbit-node__shade{stroke:', base: 'node-stroke', tint: 'node-stroke-tint', own: 'var(--orbit-node-color,var(--_orbit-node-stroke))' },\n { paints: '.orbit-node__shadow{fill:', base: 'node-shadow', tint: 'node-shadow-tint', own: 'var(--orbit-node-color)' },\n { paints: '.orbit-node__halo{stroke:', base: 'sun-halo', tint: 'sun-halo-tint', own: 'var(--orbit-node-color)' },\n { paints: '.orbit-ring{stroke:', base: 'ring-stroke', tint: 'ring-tint', own: 'var(--orbit-ring-color,var(--_orbit-ring-stroke))' },\n { paints: '.orbit-link{stroke:', base: 'link-stroke', tint: 'link-tint', own: 'var(--orbit-link-color,var(--_orbit-link-stroke))' },\n];\n\n/**\n * For browsers without `color-mix()`: each mix of a theme as one of its two\n * colors. The node's own only where the mix is mostly that: even a quarter\n * of the theme's color is what makes a sun's halo show on a light page.\n */\nconst plainMixes = (selector: string, tokens: OrbitThemeTokens): string => {\n return MIXES.map((mix) => `${selector} ${mix.paints}${parseFloat(tokens[mix.tint]) >= 75 ? mix.own : `var(--_orbit-${mix.base})`}}`).join('');\n};\n\n/** CSS that gives `.orbit[data-orbit-theme=\"…\"]` each preset's token defaults. */\nexport const themeStylesheet = (): string => {\n const names = Object.keys(ORBIT_THEME_PRESETS) as OrbitThemeName[];\n const presets = names\n .map((name) => `.orbit[data-orbit-theme=\"${name}\"]{${tokenDeclarations(ORBIT_THEME_PRESETS[name])}color-scheme:${DARK_THEMES.has(name) ? 'dark' : 'light'};}`)\n .join('');\n const automatic = `.orbit[data-orbit-theme=\"auto\"]{${tokenDeclarations(PAPER)}color-scheme:light;}`\n + `@media (prefers-color-scheme: dark){.orbit[data-orbit-theme=\"auto\"]{${tokenDeclarations(NIGHT)}color-scheme:dark;}}`;\n const plain = names.map((name) => plainMixes(`.orbit[data-orbit-theme=\"${name}\"]`, ORBIT_THEME_PRESETS[name])).join('')\n + plainMixes('.orbit[data-orbit-theme=\"auto\"]', PAPER)\n + `@media (prefers-color-scheme: dark){${plainMixes('.orbit[data-orbit-theme=\"auto\"]', NIGHT)}}`;\n return presets + automatic + `@supports not (color: color-mix(in srgb, red, blue)){${plain}}`;\n};\n\nconst PALETTE_TOKENS: OrbitThemeToken[] = ['color-root', 'color-1', 'color-2', 'color-3', 'color-4', 'color-5', 'color-6', 'color-7'];\n\nconst KNOWN_TOKENS = new Set<string>(THEME_TOKENS);\n\n/** The token values a `theme` object sets. Unknown tokens and empty values are skipped. */\nexport const themeObjectTokens = (theme: OrbitRendererTheme | undefined): Partial<OrbitThemeTokens> => {\n const tokens: Partial<OrbitThemeTokens> = {};\n\n for (const [token, value] of Object.entries(theme?.tokens ?? {})) {\n if (KNOWN_TOKENS.has(token) && typeof value === 'string' && value !== '') {\n tokens[token as OrbitThemeToken] = value;\n }\n }\n\n return tokens;\n};\n\n/**\n * Custom properties to set inline on the map for a `theme` object. Each\n * value replaces the preset's default but still yields to a `--orbit-*`\n * property the page sets in its own CSS.\n */\nexport const themeOverrides = (theme: OrbitRendererTheme | undefined): Record<string, string> => {\n const properties: Record<string, string> = {};\n\n for (const [token, value] of Object.entries(themeObjectTokens(theme))) {\n properties[`--_orbit-${token}`] = `var(--orbit-${token}, ${value})`;\n }\n\n return properties;\n};\n\n/**\n * The colors nodes are painted with: the custom palette when given (first\n * entry for the root), otherwise the theme's palette tokens.\n */\nexport const resolvePalette = (palette: string[] | undefined): string[] => {\n if (palette && palette.length > 0) {\n return [...palette];\n }\n\n return PALETTE_TOKENS.map((token) => `var(--_orbit-${token})`);\n};\n",
|
|
15
16
|
"import type { OrbitDocumentOptions, RendererOptions } from './types.js';\nimport { isThemeName, themeNames } from './themes.js';\nimport { didYouMean } from './suggest.js';\n\n/** Document-level options accepted in markdown frontmatter and as YAML top-level keys. */\nexport const DOCUMENT_OPTION_KEYS = new Set([\n 'title', 'theme', 'view', 'showRings', 'interactive',\n 'animation', 'speed', 'palette', 'height', 'maxDepth',\n 'className', 'baseUrl', 'schemaVersion', 'flavor',\n]);\n\n/** Keys people (and agents) reach for instead of a document option's name. */\nconst OPTION_SYNONYMS: Record<string, string> = {\n viewMode: 'view',\n mode: 'view',\n rings: 'showRings',\n depth: 'maxDepth',\n colors: 'palette',\n name: 'title',\n orbitAnimation: 'animation',\n orbitSpeed: 'speed',\n class: 'className',\n};\n\n/** Words people (and agents) reach for instead of a theme's name. */\nexport const THEME_SYNONYMS: Record<string, string> = {\n dark: 'night',\n light: 'paper',\n default: 'paper',\n frosted: 'glass',\n 'glass-dark': 'glass-night',\n 'dark-glass': 'glass-night',\n space: 'cosmos',\n stars: 'cosmos',\n 'high-contrast': 'contrast',\n monochrome: 'ink',\n sketch: 'ink',\n solid: 'flat',\n 'flat-dark': 'flat-night',\n 'dark-flat': 'flat-night',\n 'material-you': 'material',\n 'material-dark': 'material-night',\n 'dark-material': 'material-night',\n 'liquid-glass': 'liquid',\n 'liquid-dark': 'liquid-night',\n 'dark-liquid': 'liquid-night',\n 'liquid-glass-night': 'liquid-night',\n};\n\n\n/** The message for a key that isn't a document option, with the option it probably means. */\nexport const unknownOptionMessage = (key: string, place: 'frontmatter' | 'top-level'): string => {\n const known = place === 'top-level' ? [...DOCUMENT_OPTION_KEYS, 'nodes'] : [...DOCUMENT_OPTION_KEYS];\n return `Unknown ${place} key \"${key}\" (ignored).${didYouMean(key, known, place === 'top-level' ? { ...OPTION_SYNONYMS, ...NODES_SYNONYMS } : OPTION_SYNONYMS)}`;\n};\n\n/** Keys people (and agents) reach for instead of a YAML map's `nodes`. */\nconst NODES_SYNONYMS: Record<string, string> = {\n root: 'nodes',\n tree: 'nodes',\n map: 'nodes',\n children: 'nodes',\n items: 'nodes',\n};\n\n/** `true`, `false` and their usual spellings in YAML (`yes`, `off`, `1`, …). */\nconst readFlag = (value: unknown): boolean | undefined => {\n if (typeof value === 'boolean') {\n return value;\n }\n\n const word = String(value).trim().toLowerCase();\n\n if (['true', 'yes', 'on', '1'].includes(word)) {\n return true;\n }\n\n if (['false', 'no', 'off', '0'].includes(word)) {\n return false;\n }\n\n return undefined;\n};\n\n/**\n * Sets one document option from its frontmatter (or YAML top-level) value.\n * A value that can't be used is left out and described to `report`.\n */\nexport const applyDocumentOption = (\n options: OrbitDocumentOptions,\n key: string,\n value: unknown,\n report: (message: string) => void = () => undefined,\n): void => {\n const positiveNumber = (minimum: number): number | undefined => {\n const number = typeof value === 'number' ? value : Number(String(value).trim());\n\n if (Number.isFinite(number) && number >= minimum && String(value).trim() !== '') {\n return number;\n }\n\n report(`${key} must be a number${minimum > 0 ? ' above 0' : ' of 0 or more'}, got \"${String(value)}\".`);\n return undefined;\n };\n\n switch (key) {\n case 'view':\n if (value === 'focus' || value === 'all') {\n options.viewMode = value;\n } else {\n report(`view must be \"focus\" or \"all\" (the overview), got \"${String(value)}\".${didYouMean(String(value), ['focus', 'all'], { overview: 'all', tree: 'all', full: 'all' })}`);\n }\n\n return;\n case 'palette':\n if (Array.isArray(value)) {\n options.palette = value.map(String);\n } else if (typeof value === 'string' && value.trim() !== '') {\n options.palette = value.split(',').map((color) => color.trim()).filter(Boolean);\n } else {\n report('palette must be a list of colors, such as [\"#F8D978\", \"#F5A3A8\"].');\n }\n\n return;\n case 'showRings':\n case 'interactive':\n case 'animation': {\n const flag = readFlag(value);\n\n if (flag === undefined) {\n report(`${key} must be true or false, got \"${String(value)}\".`);\n return;\n }\n\n if (key === 'animation') {\n options.orbitAnimation = flag;\n } else if (key === 'interactive') {\n options.interactive = flag;\n } else {\n options.showRings = flag;\n }\n\n return;\n }\n case 'speed':\n case 'height':\n case 'schemaVersion': {\n const number = positiveNumber(Number.MIN_VALUE);\n\n if (number !== undefined) {\n options[key === 'speed' ? 'orbitSpeed' : key] = number;\n }\n\n return;\n }\n case 'maxDepth': {\n const number = positiveNumber(0);\n\n if (number !== undefined) {\n options.maxDepth = number;\n }\n\n return;\n }\n case 'theme':\n options.theme = String(value);\n\n if (!isThemeName(options.theme)) {\n report(`Unknown theme \"${options.theme}\". Themes: ${themeNames().join(', ')}.${didYouMean(options.theme, themeNames(), THEME_SYNONYMS)}`);\n }\n\n return;\n case 'title':\n case 'className':\n case 'baseUrl':\n if (value !== null && value !== undefined) {\n options[key] = String(value);\n }\n\n return;\n case 'flavor':\n // Read by the dispatcher, not stored.\n if (value !== 'markdown' && value !== 'yaml') {\n report(`flavor must be \"markdown\" or \"yaml\", got \"${String(value)}\".`);\n }\n\n return;\n default:\n return;\n }\n};\n\n/**\n * The renderer options a document asks for in its frontmatter (or YAML\n * top-level keys). `title` becomes the map's accessible label. Container\n * concerns (`height`, `className`) are left to the caller.\n */\nexport const documentToRendererOptions = (options: OrbitDocumentOptions): RendererOptions => {\n const result: RendererOptions = {};\n\n if (options.viewMode) {\n result.viewMode = options.viewMode;\n }\n\n if (options.showRings !== undefined) {\n result.showRings = options.showRings;\n }\n\n if (options.interactive !== undefined) {\n result.interactive = options.interactive;\n }\n\n if (options.orbitAnimation !== undefined) {\n result.orbitAnimation = options.orbitAnimation;\n }\n\n if (Number.isFinite(options.orbitSpeed)) {\n result.orbitSpeed = options.orbitSpeed;\n }\n\n if (Number.isFinite(options.maxDepth)) {\n result.maxDepth = options.maxDepth;\n }\n\n if (options.palette && options.palette.length > 0) {\n result.palette = options.palette;\n }\n\n if (isThemeName(options.theme)) {\n result.theme = options.theme;\n }\n\n if (options.title) {\n result.ariaLabel = options.title;\n }\n\n if (options.baseUrl) {\n result.baseUrl = options.baseUrl;\n }\n\n return result;\n};\n",
|
|
16
17
|
"/**\n * Links between nodes. A node's link, or a link in its note, written as\n * `#id` points at another node of the same map, the way `#heading` links\n * point at a heading in a markdown page.\n */\n\nimport type { OrbitNode } from './types.js';\nimport type { DiagnosticCollector } from './diagnostics.js';\nimport { findNodeById, nodeSlug } from './utils.js';\nimport { suggest } from './suggest.js';\n\n/** Whether a link points at a node of the same map: `#research`. */\nexport const isNodeLink = (href: string | undefined): href is string => {\n return typeof href === 'string' && /^#\\S/.test(href);\n};\n\n/**\n * The node a `#id` link points at: the node with that id, or the one whose\n * id the fragment's text would get, so `#Research` and GitHub-style\n * `#-research` anchors find `research` too.\n */\nexport const findLinkedNode = (root: OrbitNode, href: string): OrbitNode | null => {\n return resolveNodeLink(href, (id) => findNodeById(root, id));\n};\n\n/** `findLinkedNode` with the map's nodes indexed by `indexNodes`, for checking many links at once. */\nexport const findIndexedLinkedNode = (nodes: Map<string, OrbitNode>, href: string): OrbitNode | null => {\n return resolveNodeLink(href, (id) => nodes.get(id) ?? null);\n};\n\n/** The map's nodes by id; when ids repeat, the first in the tree, as `findNodeById` finds it. */\nexport const indexNodes = (root: OrbitNode): Map<string, OrbitNode> => {\n const nodes = new Map<string, OrbitNode>();\n\n const visit = (node: OrbitNode): void => {\n if (!nodes.has(node.id)) {\n nodes.set(node.id, node);\n }\n\n for (const child of node.children) {\n visit(child);\n }\n };\n\n visit(root);\n return nodes;\n};\n\nconst resolveNodeLink = (href: string, lookup: (id: string) => OrbitNode | null): OrbitNode | null => {\n if (!isNodeLink(href)) {\n return null;\n }\n\n let fragment = href.slice(1);\n\n try {\n fragment = decodeURIComponent(fragment);\n } catch {\n // A malformed escape: look the fragment up as written.\n }\n\n return lookup(fragment) ?? lookup(nodeSlug(fragment).replace(/^-+|-+$/g, ''));\n};\n\nconst NOTE_NODE_LINK = /\\]\\((#[^)\\s]+)\\)/g;\n\n/** The `#id` links a node has: its link, then the ones in its note. */\nexport const nodeLinksOf = (node: OrbitNode): string[] => {\n // A plain note never renders its `[x](#y)` as a link, so it isn't one.\n const links = node.noteFormat === 'plain' ? [] : [...(node.note ?? '').matchAll(NOTE_NODE_LINK)].map((match) => match[1]);\n\n if (isNodeLink(node.link)) {\n links.unshift(node.link);\n }\n\n return links;\n};\n\n/** Where a parser saw a node's link (`inNote` false) or a link in its note: the line it's on, when it knows. */\nexport type LinkLine = (node: OrbitNode, href: string, inNote: boolean) => number | undefined;\n\n/** Reports each `#id` link, in a node's link or note, that points at no node of the map, on its own line where `lineOf` knows it. */\nexport const checkNodeLinks = (root: OrbitNode, diagnostics: DiagnosticCollector, lineOf?: LinkLine): void => {\n const ids: string[] = [];\n collectIds(root, ids);\n // Large maps link between their nodes hundreds of times: look ids up, don't search the tree.\n const nodes = indexNodes(root);\n\n const visit = (node: OrbitNode): void => {\n nodeLinksOf(node).forEach((href, index) => {\n if (!findIndexedLinkedNode(nodes, href)) {\n const suggestion = suggest(href.slice(1), ids);\n const hint = suggestion === undefined ? ' Ids come from the nodes\\' text: \"Q3 plan\" is #q3-plan.' : ` Did you mean #${suggestion}?`;\n const inNote = !(index === 0 && isNodeLink(node.link));\n diagnostics.recover(\n 'unknown-link-target',\n `\"${node.text}\" links to ${href}, but no node has that id.${hint}`,\n lineOf?.(node, href, inNote) ?? node.source?.line,\n );\n }\n });\n\n for (const child of node.children) {\n visit(child);\n }\n };\n\n visit(root);\n};\n\nconst collectIds = (node: OrbitNode, ids: string[]): void => {\n ids.push(node.id);\n\n for (const child of node.children) {\n collectIds(child, ids);\n }\n};\n",
|
|
17
|
-
"/**\n * Where a markdown document came from: its text, and which lines each node\n * owns. Saving uses it to write back only what an edit changed, so a map\n * written by hand (or by another app) keeps its own formatting, and\n * everything Orbit doesn't read, through edits.\n */\n\nimport type { OrbitDocument, OrbitDocumentOptions, OrbitNode } from './types.js';\nimport { copyMedia } from './node-attributes.js';\n\n/** What a line is to the node that owns it. */\nexport type LineRole =\n /** The frontmatter block, and blank lines before it. */\n | 'frontmatter'\n /** A heading or list item line (a setext heading's underline too), or the paragraph that names a generated root. */\n | 'title'\n /** An `<!-- orbit … -->` block. */\n | 'attributes'\n /** A picture or video line, and the comment after it that sets its caption or content type. */\n | 'media'\n /** Text of the node's note: paragraphs, quotes, code, or headings under a list item. */\n | 'note'\n /**\n * The end of the document, which stays at its end: link and footnote\n * definitions there (the root's note), and the blank lines around them.\n */\n | 'end'\n /** Text Orbit keeps without reading: other HTML comments, rules, attribute blocks it couldn't read. */\n | 'foreign'\n | 'blank';\n\n/** How a node was written. */\nexport type NodeShape =\n | { kind: 'heading'; level: number; setext: boolean }\n /** `indent` is the marker's column, `content` the column its text starts at. */\n | { kind: 'item'; indent: number; marker: string; content: number }\n /** A root Orbit made up: named after the title or a lead paragraph (`lead`), or \"Untitled map\". */\n | { kind: 'generated'; lead: boolean };\n\n/** A node's own fields, as they were read: to tell which ones an edit changed. */\nexport type NodeFields = Pick<OrbitNode, 'id' | 'text' | 'icon' | 'link' | 'status' | 'tags' | 'color' | 'priority' | 'collapsed' | 'type' | 'typeVersion' | 'note' | 'noteFormat' | 'image' | 'video' | 'embed' | 'attrs'>;\n\nexport interface NodeRecord {\n shape: NodeShape;\n\n /** The title line, 0-based; null for a generated root without a lead paragraph. */\n titleLine: number | null;\n\n /** The lines the node and everything under it span, 0-based, end exclusive. */\n start: number;\n\n end: number;\n\n /** Whether every line in the span is the node's or under it, so the span can be written back as one piece. */\n contiguous: boolean;\n\n /** Its children, in their order in the source. */\n children: OrbitNode[];\n\n fields: NodeFields;\n\n /** Whether the node's id was written as an attribute (or would have to be). */\n explicitId: boolean;\n}\n\nexport interface DocumentSource {\n /** The lines as the parser read them: line endings as `\\n`, without a byte-order mark or shared indentation. */\n lines: string[];\n\n /** For each line, the node it belongs to (null for the frontmatter) and what it is there. */\n owners: (OrbitNode | null)[];\n\n roles: LineRole[];\n records: WeakMap<OrbitNode, NodeRecord>;\n root: OrbitNode;\n\n /** The options as read, to tell which ones changed. */\n options: OrbitDocumentOptions;\n\n /** The frontmatter keys Orbit doesn't read, as read, to tell which ones changed. */\n extra: Record<string, unknown>;\n\n /** The frontmatter's fences, 0-based, when the document has frontmatter. */\n frontmatter: { open: number; close: number } | null;\n\n /** How the file was written, so it's written back the same way. */\n encoding: SourceEncoding;\n}\n\nexport interface SourceEncoding {\n lineEnding: '\\n' | '\\r\\n';\n byteOrderMark: boolean;\n\n /** Indentation every line shared (a map indented inside HTML or a template), put back on save. */\n indentation: string;\n\n /** Lines around the map that the parser unwrapped: a ```` ```orbit ```` fence. */\n before: string[];\n\n after: string[];\n}\n\n/** How a text is written: its line endings and byte-order mark. Indentation and wrapping are set where they're found. */\nexport const encodingOf = (text: string): SourceEncoding => {\n const crlf = (text.match(/\\r\\n/g) ?? []).length;\n const lf = (text.match(/\\n/g) ?? []).length;\n return {\n lineEnding: crlf > 0 && crlf * 2 >= lf ? '\\r\\n' : '\\n',\n byteOrderMark: text.startsWith('\\uFEFF'),\n indentation: '',\n before: [],\n after: [],\n };\n};\n\n/** Sources by the root of the tree read from them: copies of a document (`{ ...document, options }`) share it. */\nconst SOURCES = new WeakMap<OrbitNode, DocumentSource>();\n\n/**\n * The source a document's tree was read from, when it was read from\n * markdown. Kept by the tree's root, off the document itself, so documents\n * stay plain data that JSON leaves out, and a copy of a document with other\n * options (or a map holding the tree) still saves from its source.\n */\nexport const documentSource = (document: Pick<OrbitDocument, 'root'>): DocumentSource | undefined => {\n const source = SOURCES.get(document.root);\n return source?.root === document.root ? source : undefined;\n};\n\n/** Remembers where a document's tree came from (see `documentSource`). */\nexport const setDocumentSource = (document: Pick<OrbitDocument, 'root'>, source: DocumentSource): void => {\n SOURCES.set(document.root, source);\n};\n\n/** A copy of a node's own fields, deep enough that edits to the node don't reach it. */\nexport const nodeFields = (node: OrbitNode): NodeFields => {\n const copy = (value: unknown): unknown => (value === undefined ? undefined : JSON.parse(JSON.stringify(value)));\n return {\n id: node.id,\n text: node.text,\n icon: node.icon,\n link: node.link,\n status: node.status,\n tags: copy(node.tags) as string[] | undefined,\n color: node.color,\n priority: node.priority,\n collapsed: node.collapsed,\n type: node.type,\n typeVersion: node.typeVersion,\n note: node.note,\n noteFormat: node.noteFormat,\n image: node.image && copyMedia(node.image),\n video: node.video && copyMedia(node.video),\n embed: node.embed && copyMedia(node.embed),\n attrs: copy(node.attrs) as NodeFields['attrs'],\n };\n};\n\n/**\n * Collects, while a document is parsed, which node owns each line and what\n * the line is, then works out each node's span.\n */\nexport class SourceRecorder {\n readonly owners: (OrbitNode | null)[];\n readonly roles: (LineRole | undefined)[];\n private readonly lines: string[];\n private readonly shapes = new Map<OrbitNode, { shape: NodeShape; titleLine: number | null }>();\n\n constructor(lines: string[]) {\n this.lines = lines;\n this.owners = new Array(lines.length).fill(null);\n this.roles = new Array(lines.length).fill(undefined);\n }\n\n /** Lines `first` to `last` (1-based, inclusive) belong to `node` as `role`. */\n mark(first: number, last: number, node: OrbitNode | null, role: LineRole): void {\n for (let line = Math.max(1, first); line <= last && line <= this.lines.length; line += 1) {\n this.owners[line - 1] = node;\n this.roles[line - 1] = role;\n }\n }\n\n /** A line's text (1-based), as read. */\n line(line: number): string {\n return this.lines[line - 1] ?? '';\n }\n\n /** How `node` was written, and its title line (1-based), if it has one. */\n shape(node: OrbitNode, shape: NodeShape, titleLine: number | null): void {\n this.shapes.set(node, { shape, titleLine: titleLine === null ? null : titleLine - 1 });\n }\n\n /**\n * The finished source. Blank lines nothing claimed go with the text they\n * lead up to (an idea moved takes the blank line before it, and the\n * paragraph after a list keeps the blank line that keeps it out of the\n * list); at the end of the document, with the line above. Every line has\n * an owner, so spans cover the whole document.\n */\n finish(\n root: OrbitNode,\n options: OrbitDocumentOptions,\n extra: Record<string, unknown>,\n frontmatter: DocumentSource['frontmatter'],\n explicitIds: ReadonlySet<OrbitNode>,\n ): DocumentSource {\n const owners = [...this.owners];\n const claimed = [...this.roles];\n let next: OrbitNode | null = null;\n let nextRole: LineRole | undefined;\n\n for (let index = this.lines.length - 1; index >= 0; index -= 1) {\n const role = claimed[index];\n\n if (role !== undefined) {\n if (role !== 'frontmatter') {\n next = owners[index];\n nextRole = role;\n }\n } else if (next && this.lines[index].trim() === '') {\n owners[index] = next;\n // The blank line before definitions at the end stays with them.\n claimed[index] = nextRole === 'end' ? 'end' : 'blank';\n }\n }\n\n const roles: LineRole[] = [];\n let owner: OrbitNode | null = null;\n let lastClaimed = -1;\n\n claimed.forEach((role, index) => {\n if (role !== undefined && role !== 'frontmatter') {\n lastClaimed = index;\n }\n });\n\n for (let index = 0; index < this.lines.length; index += 1) {\n const role = claimed[index];\n\n if (role !== undefined) {\n roles.push(role);\n\n if (role !== 'frontmatter') {\n owner = owners[index];\n }\n\n continue;\n }\n\n const blank = this.lines[index].trim() === '';\n\n if (index > lastClaimed) {\n // After every node: the end of the document, which stays at the end.\n owners[index] = root;\n roles.push(blank ? 'end' : 'foreign');\n } else {\n owners[index] = owner ?? root;\n roles.push(blank ? 'blank' : 'foreign');\n }\n }\n\n const records = new WeakMap<OrbitNode, NodeRecord>();\n const firstLines = new Map<OrbitNode, number>();\n const lastLines = new Map<OrbitNode, number>();\n\n owners.forEach((node, index) => {\n if (node) {\n if (!firstLines.has(node)) {\n firstLines.set(node, index);\n }\n\n lastLines.set(node, index);\n }\n });\n\n const spanOf = (node: OrbitNode): { start: number; end: number } => {\n let start = firstLines.get(node) ?? Number.POSITIVE_INFINITY;\n let end = (lastLines.get(node) ?? -1) + 1;\n\n for (const child of node.children) {\n const span = spanOf(child);\n start = Math.min(start, span.start);\n end = Math.max(end, span.end);\n }\n\n const known = this.shapes.get(node);\n const shape: NodeShape = known?.shape ?? { kind: 'generated', lead: false };\n\n if (!Number.isFinite(start)) {\n start = end = 0;\n }\n\n records.set(node, {\n shape,\n titleLine: known?.titleLine ?? null,\n start,\n end,\n contiguous: true,\n children: [...node.children],\n fields: nodeFields(node),\n explicitId: explicitIds.has(node),\n });\n return { start, end };\n };\n\n spanOf(root);\n // A span with another node's line inside it (definitions written halfway through an idea's text, say).\n // A depth-first walk's enter/exit counters bracket a node's descendants, so the ancestor test is O(1).\n const brackets = new Map<OrbitNode, [number, number]>();\n let order = 0;\n\n const bracket = (node: OrbitNode): void => {\n const enter = order;\n order += 1;\n\n for (const child of node.children) {\n bracket(child);\n }\n\n brackets.set(node, [enter, order]);\n };\n\n bracket(root);\n\n const insideOf = (node: OrbitNode, ancestor: OrbitNode): boolean => {\n const [enter, exit] = brackets.get(ancestor)!;\n const bracketed = brackets.get(node)!;\n return bracketed[0] >= enter && bracketed[0] < exit;\n };\n\n const check = (node: OrbitNode): void => {\n const record = records.get(node)!;\n\n for (let index = record.start; index < record.end; index += 1) {\n const owner = owners[index];\n\n if (owner && !insideOf(owner, node)) {\n record.contiguous = false;\n break;\n }\n }\n\n node.children.forEach(check);\n };\n\n root.children.forEach(check);\n // The root spans the whole body, blank lines at the end included.\n const rootRecord = records.get(root)!;\n rootRecord.start = Math.min(rootRecord.start, frontmatter ? frontmatter.close + 1 : 0);\n rootRecord.end = this.lines.length;\n return {\n lines: this.lines,\n owners,\n roles,\n records,\n root,\n options: JSON.parse(JSON.stringify(options)) as OrbitDocumentOptions,\n extra: JSON.parse(JSON.stringify(extra)) as Record<string, unknown>,\n frontmatter,\n encoding: { lineEnding: '\\n', byteOrderMark: false, indentation: '', before: [], after: [] },\n };\n }\n}\n",
|
|
18
|
+
"/**\n * Where a markdown document came from: its text, and which lines each node\n * owns. Saving uses it to write back only what an edit changed, so a map\n * written by hand (or by another app) keeps its own formatting, and\n * everything Orbit doesn't read, through edits.\n */\n\nimport type { OrbitDocument, OrbitDocumentOptions, OrbitNode } from './types.js';\nimport { copyMedia } from './node-attributes.js';\n\n/** What a line is to the node that owns it. */\nexport type LineRole =\n /** The frontmatter block, and blank lines before it. */\n | 'frontmatter'\n /** A heading or list item line (a setext heading's underline too), or the paragraph that names a generated root. */\n | 'title'\n /** An `<!-- orbit … -->` block. */\n | 'attributes'\n /** A picture or video line, and the comment after it that sets its caption or content type. */\n | 'media'\n /** Text of the node's note: paragraphs, quotes, code, or headings under a list item. */\n | 'note'\n /**\n * The end of the document, which stays at its end: link and footnote\n * definitions there (the root's note), and the blank lines around them.\n */\n | 'end'\n /** Text Orbit keeps without reading: other HTML comments, rules, attribute blocks it couldn't read. */\n | 'foreign'\n | 'blank';\n\n/** How a node was written. */\nexport type NodeShape =\n | { kind: 'heading'; level: number; setext: boolean }\n /** `indent` is the marker's column, `content` the column its text starts at. */\n | { kind: 'item'; indent: number; marker: string; content: number }\n /** A root Orbit made up: named after the title or a lead paragraph (`lead`), or \"Untitled map\". */\n | { kind: 'generated'; lead: boolean };\n\n/** A node's own fields, as they were read: to tell which ones an edit changed. */\nexport type NodeFields = Pick<OrbitNode, 'id' | 'text' | 'icon' | 'link' | 'status' | 'tags' | 'color' | 'paletteColor' | 'priority' | 'collapsed' | 'type' | 'typeVersion' | 'note' | 'noteFormat' | 'image' | 'video' | 'embed' | 'attrs'>;\n\nexport interface NodeRecord {\n shape: NodeShape;\n\n /** The title line, 0-based; null for a generated root without a lead paragraph. */\n titleLine: number | null;\n\n /** The lines the node and everything under it span, 0-based, end exclusive. */\n start: number;\n\n end: number;\n\n /** Whether every line in the span is the node's or under it, so the span can be written back as one piece. */\n contiguous: boolean;\n\n /** Its children, in their order in the source. */\n children: OrbitNode[];\n\n fields: NodeFields;\n\n /** Whether the node's id was written as an attribute (or would have to be). */\n explicitId: boolean;\n}\n\nexport interface DocumentSource {\n /** The lines as the parser read them: line endings as `\\n`, without a byte-order mark or shared indentation. */\n lines: string[];\n\n /** For each line, the node it belongs to (null for the frontmatter) and what it is there. */\n owners: (OrbitNode | null)[];\n\n roles: LineRole[];\n records: WeakMap<OrbitNode, NodeRecord>;\n root: OrbitNode;\n\n /** The options as read, to tell which ones changed. */\n options: OrbitDocumentOptions;\n\n /** The frontmatter keys Orbit doesn't read, as read, to tell which ones changed. */\n extra: Record<string, unknown>;\n\n /** The frontmatter's fences, 0-based, when the document has frontmatter. */\n frontmatter: { open: number; close: number } | null;\n\n /** How the file was written, so it's written back the same way. */\n encoding: SourceEncoding;\n}\n\nexport interface SourceEncoding {\n lineEnding: '\\n' | '\\r\\n';\n byteOrderMark: boolean;\n\n /** Indentation every line shared (a map indented inside HTML or a template), put back on save. */\n indentation: string;\n\n /** Lines around the map that the parser unwrapped: a ```` ```orbit ```` fence. */\n before: string[];\n\n after: string[];\n}\n\n/** How a text is written: its line endings and byte-order mark. Indentation and wrapping are set where they're found. */\nexport const encodingOf = (text: string): SourceEncoding => {\n const crlf = (text.match(/\\r\\n/g) ?? []).length;\n const lf = (text.match(/\\n/g) ?? []).length;\n return {\n lineEnding: crlf > 0 && crlf * 2 >= lf ? '\\r\\n' : '\\n',\n byteOrderMark: text.startsWith('\\uFEFF'),\n indentation: '',\n before: [],\n after: [],\n };\n};\n\n/** Sources by the root of the tree read from them: copies of a document (`{ ...document, options }`) share it. */\nconst SOURCES = new WeakMap<OrbitNode, DocumentSource>();\n\n/**\n * The source a document's tree was read from, when it was read from\n * markdown. Kept by the tree's root, off the document itself, so documents\n * stay plain data that JSON leaves out, and a copy of a document with other\n * options (or a map holding the tree) still saves from its source.\n */\nexport const documentSource = (document: Pick<OrbitDocument, 'root'>): DocumentSource | undefined => {\n const source = SOURCES.get(document.root);\n return source?.root === document.root ? source : undefined;\n};\n\n/** Remembers where a document's tree came from (see `documentSource`). */\nexport const setDocumentSource = (document: Pick<OrbitDocument, 'root'>, source: DocumentSource): void => {\n SOURCES.set(document.root, source);\n};\n\n/** A copy of a node's own fields, deep enough that edits to the node don't reach it. */\nexport const nodeFields = (node: OrbitNode): NodeFields => {\n const copy = (value: unknown): unknown => (value === undefined ? undefined : JSON.parse(JSON.stringify(value)));\n return {\n id: node.id,\n text: node.text,\n icon: node.icon,\n link: node.link,\n status: node.status,\n tags: copy(node.tags) as string[] | undefined,\n color: node.color,\n paletteColor: node.paletteColor,\n priority: node.priority,\n collapsed: node.collapsed,\n type: node.type,\n typeVersion: node.typeVersion,\n note: node.note,\n noteFormat: node.noteFormat,\n image: node.image && copyMedia(node.image),\n video: node.video && copyMedia(node.video),\n embed: node.embed && copyMedia(node.embed),\n attrs: copy(node.attrs) as NodeFields['attrs'],\n };\n};\n\n/**\n * Collects, while a document is parsed, which node owns each line and what\n * the line is, then works out each node's span.\n */\nexport class SourceRecorder {\n readonly owners: (OrbitNode | null)[];\n readonly roles: (LineRole | undefined)[];\n private readonly lines: string[];\n private readonly shapes = new Map<OrbitNode, { shape: NodeShape; titleLine: number | null }>();\n\n constructor(lines: string[]) {\n this.lines = lines;\n this.owners = new Array(lines.length).fill(null);\n this.roles = new Array(lines.length).fill(undefined);\n }\n\n /** Lines `first` to `last` (1-based, inclusive) belong to `node` as `role`. */\n mark(first: number, last: number, node: OrbitNode | null, role: LineRole): void {\n for (let line = Math.max(1, first); line <= last && line <= this.lines.length; line += 1) {\n this.owners[line - 1] = node;\n this.roles[line - 1] = role;\n }\n }\n\n /** A line's text (1-based), as read. */\n line(line: number): string {\n return this.lines[line - 1] ?? '';\n }\n\n /** How `node` was written, and its title line (1-based), if it has one. */\n shape(node: OrbitNode, shape: NodeShape, titleLine: number | null): void {\n this.shapes.set(node, { shape, titleLine: titleLine === null ? null : titleLine - 1 });\n }\n\n /**\n * The finished source. Blank lines nothing claimed go with the text they\n * lead up to (an idea moved takes the blank line before it, and the\n * paragraph after a list keeps the blank line that keeps it out of the\n * list); at the end of the document, with the line above. Every line has\n * an owner, so spans cover the whole document.\n */\n finish(\n root: OrbitNode,\n options: OrbitDocumentOptions,\n extra: Record<string, unknown>,\n frontmatter: DocumentSource['frontmatter'],\n explicitIds: ReadonlySet<OrbitNode>,\n ): DocumentSource {\n const owners = [...this.owners];\n const claimed = [...this.roles];\n let next: OrbitNode | null = null;\n let nextRole: LineRole | undefined;\n\n for (let index = this.lines.length - 1; index >= 0; index -= 1) {\n const role = claimed[index];\n\n if (role !== undefined) {\n if (role !== 'frontmatter') {\n next = owners[index];\n nextRole = role;\n }\n } else if (next && this.lines[index].trim() === '') {\n owners[index] = next;\n // The blank line before definitions at the end stays with them.\n claimed[index] = nextRole === 'end' ? 'end' : 'blank';\n }\n }\n\n const roles: LineRole[] = [];\n let owner: OrbitNode | null = null;\n let lastClaimed = -1;\n\n claimed.forEach((role, index) => {\n if (role !== undefined && role !== 'frontmatter') {\n lastClaimed = index;\n }\n });\n\n for (let index = 0; index < this.lines.length; index += 1) {\n const role = claimed[index];\n\n if (role !== undefined) {\n roles.push(role);\n\n if (role !== 'frontmatter') {\n owner = owners[index];\n }\n\n continue;\n }\n\n const blank = this.lines[index].trim() === '';\n\n if (index > lastClaimed) {\n // After every node: the end of the document, which stays at the end.\n owners[index] = root;\n roles.push(blank ? 'end' : 'foreign');\n } else {\n owners[index] = owner ?? root;\n roles.push(blank ? 'blank' : 'foreign');\n }\n }\n\n const records = new WeakMap<OrbitNode, NodeRecord>();\n const firstLines = new Map<OrbitNode, number>();\n const lastLines = new Map<OrbitNode, number>();\n\n owners.forEach((node, index) => {\n if (node) {\n if (!firstLines.has(node)) {\n firstLines.set(node, index);\n }\n\n lastLines.set(node, index);\n }\n });\n\n const spanOf = (node: OrbitNode): { start: number; end: number } => {\n let start = firstLines.get(node) ?? Number.POSITIVE_INFINITY;\n let end = (lastLines.get(node) ?? -1) + 1;\n\n for (const child of node.children) {\n const span = spanOf(child);\n start = Math.min(start, span.start);\n end = Math.max(end, span.end);\n }\n\n const known = this.shapes.get(node);\n const shape: NodeShape = known?.shape ?? { kind: 'generated', lead: false };\n\n if (!Number.isFinite(start)) {\n start = end = 0;\n }\n\n records.set(node, {\n shape,\n titleLine: known?.titleLine ?? null,\n start,\n end,\n contiguous: true,\n children: [...node.children],\n fields: nodeFields(node),\n explicitId: explicitIds.has(node),\n });\n return { start, end };\n };\n\n spanOf(root);\n // A span with another node's line inside it (definitions written halfway through an idea's text, say).\n // A depth-first walk's enter/exit counters bracket a node's descendants, so the ancestor test is O(1).\n const brackets = new Map<OrbitNode, [number, number]>();\n let order = 0;\n\n const bracket = (node: OrbitNode): void => {\n const enter = order;\n order += 1;\n\n for (const child of node.children) {\n bracket(child);\n }\n\n brackets.set(node, [enter, order]);\n };\n\n bracket(root);\n\n const insideOf = (node: OrbitNode, ancestor: OrbitNode): boolean => {\n const [enter, exit] = brackets.get(ancestor)!;\n const bracketed = brackets.get(node)!;\n return bracketed[0] >= enter && bracketed[0] < exit;\n };\n\n const check = (node: OrbitNode): void => {\n const record = records.get(node)!;\n\n for (let index = record.start; index < record.end; index += 1) {\n const owner = owners[index];\n\n if (owner && !insideOf(owner, node)) {\n record.contiguous = false;\n break;\n }\n }\n\n node.children.forEach(check);\n };\n\n root.children.forEach(check);\n // The root spans the whole body, blank lines at the end included.\n const rootRecord = records.get(root)!;\n rootRecord.start = Math.min(rootRecord.start, frontmatter ? frontmatter.close + 1 : 0);\n rootRecord.end = this.lines.length;\n return {\n lines: this.lines,\n owners,\n roles,\n records,\n root,\n options: JSON.parse(JSON.stringify(options)) as OrbitDocumentOptions,\n extra: JSON.parse(JSON.stringify(extra)) as Record<string, unknown>,\n frontmatter,\n encoding: { lineEnding: '\\n', byteOrderMark: false, indentation: '', before: [], after: [] },\n };\n }\n}\n",
|
|
18
19
|
"/**\n * The format's versions. A document says which version it's written for\n * with `schemaVersion` (none means 1). When the format changes, the change\n * goes here with a step that brings older documents up to date, and\n * `SUPPORTED_SCHEMA_VERSION` goes up: documents are upgraded as they're\n * read, and the next save writes them in the new format, changing only\n * what the upgrade changed.\n *\n * A document written for a newer version than this one is read as well as\n * it can be, and reported (`unsupported-schema-version`, an error), so apps\n * can open it without editing it: everything it says is kept on save, but\n * what this version doesn't know of it isn't understood.\n */\n\nimport type { OrbitDocument } from './types.js';\nimport type { DiagnosticCollector } from './diagnostics.js';\n\n/** A change to the format: how a document written for version `from` becomes one for `from + 1`. */\nexport interface FormatUpgrade {\n from: number;\n\n /** Changes the document in place: its options, and its nodes' fields. */\n upgrade: (document: OrbitDocument) => void;\n}\n\n/**\n * The format's changes, oldest first. Empty while the format is at its\n * first version; tests check it ends at `SUPPORTED_SCHEMA_VERSION`.\n */\nexport const FORMAT_UPGRADES: FormatUpgrade[] = [];\n\n/** The newest `schemaVersion` this version of Orbit reads and writes. */\nexport const SUPPORTED_SCHEMA_VERSION = 1;\n\n/**\n * Upgrades a document written for an older version of the format, one step\n * at a time, and says so. A document for a newer version is reported.\n */\nexport const upgradeFormat = (document: OrbitDocument, diagnostics: DiagnosticCollector, line: number | undefined, upgrades: readonly FormatUpgrade[] = FORMAT_UPGRADES): void => {\n const written = document.options.schemaVersion ?? 1;\n const supported = Math.max(SUPPORTED_SCHEMA_VERSION, ...upgrades.map((step) => step.from + 1));\n\n if (written > supported) {\n diagnostics.recover(\n 'unsupported-schema-version',\n `This map is written for version ${written} of the format, and this version of Orbit reads up to ${supported}. Everything in it is kept, but open it with a newer Orbit to change it.`,\n line,\n 'error',\n );\n return;\n }\n\n let version = written;\n\n for (const step of upgrades) {\n if (step.from === version) {\n step.upgrade(document);\n version += 1;\n }\n }\n\n if (version !== written) {\n document.options.schemaVersion = version;\n diagnostics.note('format-upgraded', `Upgraded from version ${written} of the format to ${version}; saving writes it as version ${version}.`, line);\n }\n};\n",
|
|
19
20
|
"import type { OrbitDocumentOptions, OrbitNode, ParsedOrbitDocument } from './types.js';\nimport { parseYaml, YamlMiniError } from './yaml-mini.js';\nimport { ensureUniqueNodeIds, nodeSlug, setParent } from './utils.js';\nimport { detectVideoProvider } from './media.js';\nimport { DiagnosticCollector } from './diagnostics.js';\nimport { findFrontmatter, firstContentLineIndex, lineOfKey, normalizeSource, sharedIndentation } from './source.js';\nimport { assignNodeAttribute, NODE_ATTRIBUTE_KEYS } from './node-attributes.js';\nimport { applyDocumentOption, DOCUMENT_OPTION_KEYS, unknownOptionMessage } from './document-options.js';\nimport { checkNodeLinks, type LinkLine } from './node-links.js';\nimport { encodingOf, setDocumentSource, SourceRecorder, type LineRole, type NodeShape } from './document-source.js';\nimport { nodesWithExplicitIds } from './utils.js';\nimport { upgradeFormat } from './format-upgrades.js';\n\nexport { OrbitParseError } from './diagnostics.js';\n\nexport { SUPPORTED_SCHEMA_VERSION } from './format-upgrades.js';\n\nexport interface ParseOptions {\n /**\n * Throw an `OrbitParseError` on the first problem instead of recording a\n * diagnostic and carrying on. Off by default; `orbit validate` turns it on.\n */\n strict?: boolean;\n\n /**\n * The name of the root Orbit makes up for a document with no single top\n * heading and no title, in the reader's language. Default \"Untitled map\".\n * Its id is `untitled-map` whatever its name.\n */\n untitled?: string;\n}\n\n/** Text of the generated root when a document has no single top-level heading or title. */\nexport const UNTITLED_ROOT_TEXT = 'Untitled map';\n/** The generated root's id, whatever the `untitled` option names it. */\nexport const UNTITLED_ROOT_ID = 'untitled-map';\n\n// Titles: status checkbox, emoji icon, hashtags, links and inline markdown\n\n// A single emoji: a flag (pair of regional indicators), a keycap, or a\n// pictograph with an optional variation selector and skin-tone modifier.\n// ©, ® and ™ are pictographs too but read as text in titles, so they never\n// become icons.\nconst EMOJI_UNIT = String.raw`(?:\\p{Regional_Indicator}{2}|[0-9#*]️?⃣|(?![©®™])\\p{Extended_Pictographic}️?\\p{Emoji_Modifier}?)`;\nconst EMOJI = String.raw`${EMOJI_UNIT}(?:${EMOJI_UNIT})*`;\nconst LEADING_EMOJI = new RegExp(String.raw`^((?:${EMOJI})+)\\s+(.*)$`, 'u');\nconst ONLY_EMOJI = new RegExp(String.raw`^(?:${EMOJI})+$`, 'u');\n\n/** Whether an icon reads back from the start of a title (emoji do; other symbols need an `icon:` attribute). */\nexport const isTitleIcon = (icon: string): boolean => {\n return ONLY_EMOJI.test(icon);\n};\n\n/** The emoji a title starts with, which a map reads as the node's icon, and the text after it; null for a title without one. */\nexport const leadingEmoji = (title: string): { icon: string; text: string } | null => {\n const match = LEADING_EMOJI.exec(title);\n return match ? { icon: match[1], text: match[2].trim() } : null;\n};\n\nconst TASK_MARKER = /^\\[( |x|X|\\/)\\]\\s+(.*)$/;\nconst TASK_STATUSES: Record<string, string> = { ' ': 'todo', x: 'done', X: 'done', '/': 'active' };\n// A backslash before ASCII punctuation keeps it literal: `\\*`, `\\#`, `\\[`.\nconst ESCAPE = /\\\\([!-/:-@[-`{-~])/g;\n// While a title is read, escaped characters and code spans wait in\n// private-use characters, so nothing inside them is read as markup.\nconst HIDDEN_BASE = 0x100000;\nconst HIDDEN = /[\\u{100000}-\\u{10fffd}]/gu;\n/** The last code point the reveal pattern reads: how many tokens one line can hide. */\nconst HIDDEN_LIMIT = 0x10fffd - HIDDEN_BASE + 1;\n// A hashtag at the end, after a space: `#frontend`, `#sprint-3`, `#team/web`.\n// It needs a letter, so `#42` stays text; `C#` has no space before it.\nconst TRAILING_TAG = /\\s+#([\\p{L}\\p{N}_][\\p{L}\\p{N}_/-]*)$/u;\nconst CODE_SPAN = /(`+)(?!`)([\\s\\S]*?[^`])\\1(?!`)/g;\n// The destination allows one level of balanced parentheses, as in CommonMark.\nconst TITLE_LINK = /(!?)\\[([^\\]]*)\\]\\(\\s*((?:[^\\s()]|\\([^\\s()]*\\))+)(?:\\s+\"[^\"]*\")?\\s*\\)/g;\nconst EMPHASIS = [\n /~~(?=\\S)([\\s\\S]*?\\S)~~/g,\n /\\*\\*(?=\\S)([\\s\\S]*?\\S)\\*\\*/g,\n /(?<![\\p{L}\\p{N}_])__(?=\\S)([\\s\\S]*?\\S)__(?![\\p{L}\\p{N}_])/gu,\n /\\*(?=\\S)([\\s\\S]*?\\S)\\*/g,\n /(?<![\\p{L}\\p{N}_])_(?=\\S)([\\s\\S]*?\\S)_(?![\\p{L}\\p{N}_])/gu,\n];\n\nexport interface TitleParts {\n text: string;\n icon?: string;\n link?: string;\n status?: string;\n tags?: string[];\n}\n\n/**\n * Reads a heading's or list item's text. `[ ]`, `[x]` and `[/]` set the\n * status, an emoji first is the icon, hashtags at the end are tags, a link\n * gives the node its link, and bold, italics, code and strikethrough show\n * as plain text. A backslash keeps any of those characters literal.\n */\nexport const parseTitle = (raw: string): TitleParts => {\n const hidden: string[] = [];\n\n const hide = (value: string): string => {\n if (hidden.length >= HIDDEN_LIMIT) {\n // Out of private-use codes (a line with ~64k escapes): the text stays literal.\n return value;\n }\n\n return String.fromCodePoint(HIDDEN_BASE + hidden.push(value) - 1);\n };\n\n let text = raw.trim().replace(ESCAPE, (_match, character: string) => hide(character));\n text = text.replace(HIDDEN_COMMENT, (_match, before: string, _body: string, after: string) => (before || after ? ' ' : '')).trim();\n const parts: Omit<TitleParts, 'text'> = {};\n\n const task = TASK_MARKER.exec(text);\n\n if (task) {\n parts.status = TASK_STATUSES[task[1]];\n text = task[2].trim();\n }\n\n const emoji = LEADING_EMOJI.exec(text);\n\n if (emoji) {\n parts.icon = emoji[1];\n text = emoji[2].trim();\n }\n\n const tags: string[] = [];\n\n for (let match = TRAILING_TAG.exec(text); match && /\\p{L}/u.test(match[1]); match = TRAILING_TAG.exec(text)) {\n tags.unshift(match[1]);\n text = text.slice(0, match.index);\n }\n\n if (tags.length > 0) {\n parts.tags = tags;\n }\n\n text = text.replace(CODE_SPAN, (_match, _ticks: string, code: string) => hide(code.replace(/^ ([\\s\\S]*) $/, '$1')));\n\n text = text.replace(TITLE_LINK, (match, image: string, label: string, url: string) => {\n if (image) {\n return match;\n }\n\n parts.link ??= reveal(url, hidden);\n return label;\n });\n\n // An emoji at the start of a link's text: `[🚀 Launch](…)`.\n const linkedEmoji = parts.icon ? null : LEADING_EMOJI.exec(text);\n\n if (linkedEmoji) {\n parts.icon = linkedEmoji[1];\n text = linkedEmoji[2].trim();\n }\n\n for (let pass = 0; pass < 3; pass += 1) {\n const before = text;\n\n for (const pattern of EMPHASIS) {\n text = text.replace(pattern, '$1');\n }\n\n if (text === before) {\n break;\n }\n }\n\n return { text: reveal(text, hidden).trim(), ...parts };\n};\n\nconst reveal = (text: string, hidden: string[]): string => {\n let revealed = text;\n\n // Code spans can hold escaped characters, so reveal until nothing is hidden.\n for (let pass = 0; pass < 4; pass += 1) {\n const next = revealed.replace(HIDDEN, (character) => hidden[character.codePointAt(0)! - HIDDEN_BASE] ?? character);\n\n if (next === revealed) {\n break;\n }\n\n revealed = next;\n }\n\n return revealed;\n};\n\n// Blocks\n\ninterface SourceLine { text: string; line: number; /** Leading spaces (after tab expansion), computed once per line. */ indent: number; }\n\n// Every block knows its first and last line (1-based), so saving can keep\n// the lines of whatever an edit didn't touch.\ninterface HeaderBlock { kind: 'header'; level: number; text: string; line: number; last: number; setext: boolean; }\ninterface ListBlock { kind: 'list'; items: ListItem[]; line: number; last: number; }\ninterface ParagraphBlock { kind: 'paragraph'; text: string; line: number; last: number; }\n/** A blockquote: a note written as one, never read again as structure. */\ninterface NoteBlock { kind: 'note'; text: string; line: number; last: number; }\ninterface BlankBlock { kind: 'blank'; line: number; last: number; }\n/** Text Orbit keeps without reading: an HTML comment that isn't Orbit's (`comment` is its text), or a rule. */\ninterface ForeignBlock { kind: 'foreign'; line: number; last: number; comment?: string; }\ntype MediaKind = 'image' | 'wrapped' | 'link';\n\ninterface MediaBlock {\n kind: 'media';\n mediaKind: MediaKind;\n url: string;\n alt?: string;\n thumb?: string;\n text?: string;\n line: number;\n last: number;\n}\n\n/** An `<!-- orbit … -->` comment. `inline` when it ends a heading's or list item's line. */\ninterface CommentBlock {\n kind: 'comment';\n body: string;\n line: number;\n last: number;\n\n /** Line of the body's first line, when it starts below the comment's opening. */\n bodyLine?: number;\n\n inline?: boolean;\n}\n\ntype Block = HeaderBlock | ListBlock | ParagraphBlock | NoteBlock | BlankBlock | ForeignBlock | MediaBlock | CommentBlock;\n\ninterface ListItem {\n text: string;\n line: number;\n inlineAttrs?: string;\n\n /** Everything written under the item: its note, media, attributes and nested items. */\n content: Block[];\n}\n\ntype ContentType = 'image' | 'video' | 'embed' | 'none';\nconst CONTENT_TYPES = new Set<ContentType>(['image', 'video', 'embed', 'none']);\n\nconst HEADER = /^ {0,3}(#{1,6})\\s+(.*\\S)\\s*$/;\nconst HEADER_START = /^ {0,3}#{1,6}\\s+/;\nconst SETEXT_UNDERLINE = /^ {0,3}(?:=+|-+)\\s*$/;\nconst THEMATIC_BREAK = /^ {0,3}([-*_])(?:\\s*\\1){2,}\\s*$/;\nconst LIST_ITEM = /^(\\s*)(?:[-*+]|\\d{1,9}[.)])\\s+(.*\\S)\\s*$/;\n// A list may interrupt a paragraph only with a bullet or an ordered list\n// starting at 1, as in CommonMark, so \"2024. A good year\" stays prose.\nconst LIST_INTERRUPTS_PARAGRAPH = /^\\s*(?:[-*+]|1[.)])\\s+\\S/;\nconst QUOTE = /^\\s*>/;\nconst FENCE = /^ {0,3}(```|~~~)/;\n// `orbit` in any case, with or without a colon after it: <!-- Orbit: status: done -->.\nconst INLINE_ATTRIBUTES = /^(.*\\S)\\s+<!--\\s*orbit:?\\s+([\\s\\S]*?)\\s*-->\\s*$/i;\n/** A heading or list item with no text, only attributes: an idea without a name yet, say one holding a picture. */\nconst ONLY_ATTRIBUTES = /^()<!--\\s*orbit:?\\s+([\\s\\S]*?)\\s*-->\\s*$/i;\n/** Any other HTML comment, hidden as markdown hides it; a backslash before `<` keeps it as text. */\nconst HIDDEN_COMMENT = /(\\s*)(?<!\\\\)<!--([\\s\\S]*?)-->(\\s*)/g;\nconst WRAPPED_LINE = /^\\[!\\[([^\\]]*)\\]\\(([^)]+)\\)\\]\\(([^)]+)\\)$/;\nconst IMAGE_LINE = /^!\\[([^\\]]*)\\]\\(([^)]+)\\)$/;\nconst LINK_LINE = /^\\[([^\\]]*)\\]\\(([^)]+)\\)$/;\n\n// Public API\n\nexport const parseOrbitMarkdown = (input: string, options: ParseOptions = {}): ParsedOrbitDocument => {\n const diagnostics = new DiagnosticCollector(options.strict ?? false);\n const rawLines = normalizeSource(input).split('\\n');\n const { options: docOptions, extra, bodyStartIndex } = readFrontmatter(rawLines, diagnostics);\n\n const recorder = new SourceRecorder(rawLines);\n recorder.mark(1, bodyStartIndex, null, 'frontmatter');\n\n const lines = rawLines.slice(bodyStartIndex).map((raw, index) => {\n const text = expandLeadingTabs(raw);\n return { text, line: bodyStartIndex + index + 1, indent: indentation(text) };\n });\n\n const root = buildTree(tokenize(lines, { headings: true }), docOptions, diagnostics, firstContentLineIndex(rawLines) === -1, recorder, options.untitled);\n fixLevels(root, 0);\n ensureUniqueNodeIds(root);\n checkNodeLinks(root, diagnostics, noteLinkLines(root, rawLines));\n const document: ParsedOrbitDocument = { root, options: docOptions, warnings: diagnostics.warnings, diagnostics: diagnostics.diagnostics };\n\n if (Object.keys(extra).length > 0) {\n document.extra = extra;\n }\n\n const frontmatter = findFrontmatter(rawLines);\n const fences = frontmatter && bodyStartIndex > 0 ? { open: frontmatter.openIndex, close: frontmatter.closeIndex } : null;\n const source = recorder.finish(root, docOptions, extra, fences, nodesWithExplicitIds(root));\n source.encoding = { ...encodingOf(input), indentation: sharedIndentation(input.replace(/^\\uFEFF/, '').replace(/\\r\\n?/g, '\\n')) };\n setDocumentSource(document, source);\n // Upgraded after the source is noted: saving then writes the upgraded nodes, and only them.\n upgradeFormat(document, diagnostics, lineOfKey(rawLines, 'schemaVersion'));\n document.warnings = diagnostics.warnings;\n return document;\n};\n\n// Frontmatter\n\nconst readFrontmatter = (\n lines: string[],\n diagnostics: DiagnosticCollector,\n): { options: OrbitDocumentOptions; extra: Record<string, unknown>; bodyStartIndex: number } => {\n const extra: Record<string, unknown> = {};\n const frontmatter = findFrontmatter(lines);\n\n if (!frontmatter) {\n warnUnclosedFrontmatter(lines, diagnostics);\n return { options: {}, extra, bodyStartIndex: 0 };\n }\n\n if (isMarkdownBetweenRules(lines, frontmatter.openIndex, frontmatter.closeIndex)) {\n return { options: {}, extra, bodyStartIndex: 0 };\n }\n\n const bodyStartIndex = frontmatter.closeIndex + 1;\n let parsed: unknown;\n\n try {\n parsed = parseYaml(frontmatter.yaml) ?? {};\n } catch (error) {\n // The frontmatter's first line is the one after the opening fence.\n const problem = error instanceof YamlMiniError ? error : null;\n const line = problem ? frontmatter.openIndex + 1 + problem.line : frontmatter.openIndex + 1;\n diagnostics.recover('invalid-frontmatter', `Invalid frontmatter YAML: ${problem?.reason ?? (error as Error).message}`, line, 'error');\n return { options: {}, extra, bodyStartIndex };\n }\n\n if (typeof parsed !== 'object' || Array.isArray(parsed)) {\n diagnostics.recover('invalid-frontmatter', 'Frontmatter must contain \"key: value\" pairs.', frontmatter.openIndex + 1, 'error');\n return { options: {}, extra, bodyStartIndex };\n }\n\n const options: OrbitDocumentOptions = {};\n\n for (const [key, value] of Object.entries(parsed as Record<string, unknown>)) {\n const line = lineOfKey(lines, key, frontmatter.openIndex, frontmatter.closeIndex) ?? frontmatter.openIndex + 1;\n\n if (!DOCUMENT_OPTION_KEYS.has(key)) {\n diagnostics.recover('unknown-frontmatter-key', unknownOptionMessage(key, 'frontmatter'), line);\n extra[key] = value;\n continue;\n }\n\n applyDocumentOption(options, key, value, (message) => diagnostics.recover('invalid-option-value', message, line));\n }\n\n return { options, extra, bodyStartIndex };\n};\n\n/** A heading or a list item: the lines that give a map its shape. */\nconst isStructureLine = (line: string): boolean => {\n return /^ {0,3}#{1,6}\\s+\\S/.test(line) || /^\\s*(?:[-*+]|\\d+[.)])\\s+\\S/.test(line);\n};\n\n/**\n * A map written between two `---` rules, which only looks like frontmatter:\n * the block holds headings or items and no `key: value` line, and nothing\n * after it has a shape of its own. Read as frontmatter, it would be an empty map.\n */\nconst isMarkdownBetweenRules = (lines: string[], openIndex: number, closeIndex: number): boolean => {\n const block = lines.slice(openIndex + 1, closeIndex);\n return block.some(isStructureLine)\n && !block.some((line) => /^[A-Za-z_][\\w-]*\\s*:/.test(line))\n && !lines.slice(closeIndex + 1).some(isStructureLine);\n};\n\n/** Frontmatter that opens with `---` and never closes is read as markdown: say so. */\nconst warnUnclosedFrontmatter = (lines: string[], diagnostics: DiagnosticCollector): void => {\n const openIndex = firstContentLineIndex(lines);\n\n if (openIndex === -1 || lines[openIndex].trim() !== '---') {\n return;\n }\n\n const next = lines.slice(openIndex + 1).find((line) => line.trim() !== '');\n\n if (next !== undefined && /^[A-Za-z_][\\w-]*\\s*:/.test(next)) {\n diagnostics.recover('invalid-frontmatter', 'The frontmatter has no closing \"---\" line, so it reads as part of the map. Close it with \"---\".', openIndex + 1);\n }\n};\n\n// Tokenizer\n\ninterface TokenizeOptions {\n /** Headings make nodes at the top level; under a list item they are note text. */\n headings: boolean;\n}\n\nconst tokenize = (lines: SourceLine[], options: TokenizeOptions): Block[] => {\n const blocks: Block[] = [];\n let index = 0;\n\n while (index < lines.length) {\n const { text: raw, line } = lines[index];\n\n if (raw.trim() === '') {\n blocks.push({ kind: 'blank', line, last: line });\n index += 1;\n continue;\n }\n\n const header = options.headings ? HEADER.exec(raw) : null;\n\n if (header) {\n // Drop an optional closing sequence: `## Title ##`.\n blocks.push(...headerBlocks(header[1].length, header[2].replace(/\\s+#+$/, ''), line, line, false));\n index += 1;\n continue;\n }\n\n if (raw.trim().startsWith('<!--')) {\n index = readComment(lines, index, blocks);\n continue;\n }\n\n if (QUOTE.test(raw)) {\n const quoted: string[] = [];\n\n while (index < lines.length && QUOTE.test(lines[index].text)) {\n quoted.push(lines[index].text.replace(/^\\s*> ?/, ''));\n index += 1;\n }\n\n blocks.push({ kind: 'note', text: quoted.join('\\n'), line, last: lines[index - 1].line });\n continue;\n }\n\n if (THEMATIC_BREAK.test(raw)) {\n blocks.push({ kind: 'foreign', line, last: line });\n index += 1;\n continue;\n }\n\n const item = LIST_ITEM.exec(raw);\n\n if (item) {\n const items: ListItem[] = [];\n index = readList(lines, index, item[1].length, items);\n blocks.push({ kind: 'list', items, line, last: lines[index - 1].line });\n continue;\n }\n\n const media = mediaBlock(raw.trim(), line);\n\n if (media) {\n blocks.push(media);\n index += 1;\n continue;\n }\n\n const fence = FENCE.exec(raw);\n\n if (fence) {\n let buffer = raw;\n index += 1;\n\n while (index < lines.length) {\n buffer += '\\n' + lines[index].text;\n index += 1;\n\n if (lines[index - 1].text.trimStart().startsWith(fence[1])) {\n break;\n }\n }\n\n blocks.push({ kind: 'paragraph', text: buffer, line, last: lines[index - 1].line });\n continue;\n }\n\n // A paragraph runs until a blank line or another block. Underlined with\n // `===` or `---`, it is a heading instead.\n let buffer = raw;\n index += 1;\n let heading = false;\n\n while (index < lines.length) {\n const next = lines[index].text;\n\n if (options.headings && SETEXT_UNDERLINE.test(next)) {\n const level = next.trim().startsWith('=') ? 1 : 2;\n blocks.push(...headerBlocks(level, buffer.split('\\n').map((part) => part.trim()).join(' '), line, lines[index].line, true));\n index += 1;\n heading = true;\n break;\n }\n\n if (endsParagraph(next)) {\n break;\n }\n\n buffer += '\\n' + next;\n index += 1;\n }\n\n if (!heading) {\n blocks.push({ kind: 'paragraph', text: buffer, line, last: lines[index - 1].line });\n }\n }\n\n return blocks;\n};\n\nconst headerBlocks = (level: number, text: string, line: number, last: number, setext: boolean): Block[] => {\n const inline = INLINE_ATTRIBUTES.exec(text) ?? ONLY_ATTRIBUTES.exec(text);\n\n if (inline) {\n return [\n { kind: 'header', level, text: inline[1], line, last, setext },\n { kind: 'comment', body: inline[2], line, last: line, inline: true },\n ];\n }\n\n return [{ kind: 'header', level, text, line, last, setext }];\n};\n\nconst endsParagraph = (next: string): boolean => {\n const trimmed = next.trim();\n return (\n trimmed === '' ||\n HEADER_START.test(next) ||\n LIST_INTERRUPTS_PARAGRAPH.test(next) ||\n QUOTE.test(next) ||\n FENCE.test(next) ||\n THEMATIC_BREAK.test(next) ||\n trimmed.startsWith('<!--') ||\n isStandaloneMedia(trimmed)\n );\n};\n\n/** A picture or video on a line of its own is media, even right after a paragraph line. */\nconst isStandaloneMedia = (text: string): boolean => {\n if (WRAPPED_LINE.test(text) || IMAGE_LINE.test(text)) {\n return true;\n }\n\n const link = LINK_LINE.exec(text);\n return link !== null && detectVideoProvider(mediaDestination(link[2])) !== null;\n};\n\n/** The destination of a media line's parens: the src, with CommonMark's optional \"title\" dropped. */\nconst mediaDestination = (raw: string): string => {\n return raw.replace(/\\s+(?:\"[^\"]*\"|'[^']*')?\\s*$/, '');\n};\n\nconst mediaBlock = (text: string, line: number): MediaBlock | null => {\n const wrapped = WRAPPED_LINE.exec(text);\n\n if (wrapped) {\n return { kind: 'media', mediaKind: 'wrapped', alt: wrapped[1], thumb: mediaDestination(wrapped[2]), url: mediaDestination(wrapped[3]), line, last: line };\n }\n\n const image = IMAGE_LINE.exec(text);\n\n if (image) {\n return { kind: 'media', mediaKind: 'image', alt: image[1], url: mediaDestination(image[2]), line, last: line };\n }\n\n const link = LINK_LINE.exec(text);\n\n if (link) {\n return { kind: 'media', mediaKind: 'link', text: link[1], url: mediaDestination(link[2]), line, last: line };\n }\n\n return null;\n};\n\n/**\n * Reads an HTML comment from `start`: `<!-- orbit … -->` ones become comment\n * blocks, others are kept as they are, unread.\n */\nconst readComment = (lines: SourceLine[], start: number, blocks: Block[]): number => {\n let index = start;\n let buffer = lines[index].text;\n index += 1;\n\n while (index < lines.length && !buffer.includes('-->')) {\n buffer += '\\n' + lines[index].text;\n index += 1;\n }\n\n const comment = /<!--\\s*([\\s\\S]*?)\\s*-->/.exec(buffer);\n\n if (comment && /^orbit(?::|\\b)/i.test(comment[1])) {\n // Only the `orbit` keyword's own line is trimmed, then the body is\n // dedented, so YAML indented under the comment keeps its nesting.\n const startsBelow = /^orbit:?[^\\S\\n]*\\n/i.test(comment[1]);\n const body = comment[1].replace(/^orbit:?[^\\S\\n]*\\n?/i, '');\n blocks.push({\n kind: 'comment',\n body: dedent(body.split('\\n')).join('\\n'),\n line: lines[start].line,\n last: lines[index - 1].line,\n bodyLine: startsBelow ? lines[start].line + 1 : lines[start].line,\n });\n } else {\n blocks.push({ kind: 'foreign', line: lines[start].line, last: lines[index - 1].line, comment: comment?.[1] });\n }\n\n return index;\n};\n\nconst readList = (lines: SourceLine[], start: number, baseIndent: number, items: ListItem[]): number => {\n let index = start;\n\n while (index < lines.length) {\n const { text: raw, line } = lines[index];\n\n if (raw.trim() === '') {\n index += 1;\n continue;\n }\n\n const match = THEMATIC_BREAK.test(raw) ? null : LIST_ITEM.exec(raw);\n\n if (!match || match[1].length < baseIndent) {\n break;\n }\n\n let text = match[2];\n let inlineAttrs: string | undefined;\n const inline = INLINE_ATTRIBUTES.exec(text) ?? ONLY_ATTRIBUTES.exec(text);\n\n if (inline) {\n text = inline[1];\n inlineAttrs = inline[2];\n }\n\n index += 1;\n\n // The item's first line is its title. Lines indented under it, and lines\n // that continue it without a blank line in between, are its content.\n const indented: SourceLine[] = [];\n const content: SourceLine[] = [];\n let blanks: SourceLine[] = [];\n let continues = true;\n\n while (index < lines.length) {\n const next = lines[index];\n\n if (isBlank(next)) {\n blanks.push(next);\n continues = false;\n index += 1;\n continue;\n }\n\n if (next.indent > baseIndent) {\n content.push(...blanks, next);\n indented.push(next);\n blanks = [];\n index += 1;\n continue;\n }\n\n if (continues && continuesItem(next.text)) {\n content.push({ text: next.text.trimStart(), line: next.line, indent: 0 });\n index += 1;\n continue;\n }\n\n break;\n }\n\n let shift = Number.POSITIVE_INFINITY;\n\n for (const entry of indented) {\n shift = Math.min(shift, entry.indent);\n }\n\n const indentedSet = new Set(indented);\n const dedented = content.map((entry) =>\n indentedSet.has(entry) ? { text: entry.text.slice(shift), line: entry.line, indent: entry.indent - shift } : entry);\n items.push({ text, line, inlineAttrs, content: tokenize(dedented, { headings: false }) });\n }\n\n return index;\n};\n\n/** A line right after a list item, not indented, that still belongs to it (CommonMark's lazy continuation). */\nconst continuesItem = (text: string): boolean => {\n return !(\n LIST_ITEM.test(text) ||\n HEADER_START.test(text) ||\n QUOTE.test(text) ||\n FENCE.test(text) ||\n THEMATIC_BREAK.test(text) ||\n text.trim().startsWith('<!--')\n );\n};\n\nconst indentation = (text: string): number => {\n return /^ */.exec(text)![0].length;\n};\n\n/** A line with nothing but whitespace: its leading spaces are its whole length. No trim() copy. */\nconst isBlank = (line: SourceLine): boolean => {\n if (line.indent === line.text.length) {\n return true;\n }\n\n // Printable ASCII past the indent is visible; a control character (a form\n // feed, a vertical tab) or exotic whitespace needs the slow check.\n const code = line.text.charCodeAt(line.indent);\n return (code < 33 || code > 126) && /^\\s*$/.test(line.text);\n};\n\n/** Tabs in the indentation count to the next multiple of four columns. */\nconst expandLeadingTabs = (text: string): string => {\n const leading = /^[ \\t]*/.exec(text)![0];\n\n if (!leading.includes('\\t')) {\n return text;\n }\n\n let columns = 0;\n\n for (const character of leading) {\n columns = character === '\\t' ? columns + 4 - (columns % 4) : columns + 1;\n }\n\n return ' '.repeat(columns) + text.slice(leading.length);\n};\n\nconst dedent = (lines: string[]): string[] => {\n const shift = Math.min(...lines.filter((line) => line.trim() !== '').map(indentation));\n return Number.isFinite(shift) && shift > 0 ? lines.map((line) => line.slice(Math.min(shift, indentation(line)))) : lines;\n};\n\n// Tree building\n\nconst buildTree = (\n blocks: Block[],\n docOptions: OrbitDocumentOptions,\n diagnostics: DiagnosticCollector,\n inputIsBlank: boolean,\n recorder: SourceRecorder,\n untitled: string | undefined,\n): OrbitNode => {\n const attacher = new ContentAttacher(diagnostics, recorder, untitled);\n const headers = blocks.filter((block): block is HeaderBlock => block.kind === 'header');\n const root = headers.length > 0\n ? buildFromHeadings(blocks, headers, docOptions, attacher)\n : buildFromLists(blocks, docOptions, diagnostics, attacher, inputIsBlank);\n attacher.finish();\n return root;\n};\n\n/**\n * Headings nest by level, and everything else belongs to the heading above\n * it. One heading at the top level, written first, is the root; several\n * share a root named after the title.\n */\nconst buildFromHeadings = (\n blocks: Block[],\n headers: HeaderBlock[],\n docOptions: OrbitDocumentOptions,\n attacher: ContentAttacher,\n): OrbitNode => {\n const topLevel = Math.min(...headers.map((header) => header.level));\n const topHeaders = headers.filter((header) => header.level === topLevel);\n const rootHeader = topHeaders.length === 1 && topHeaders[0] === headers[0] ? headers[0] : null;\n const lead = rootHeader || docOptions.title !== undefined ? null : leadParagraph(blocks, headers[0]);\n const root = rootHeader ? attacher.addHeading(rootHeader) : attacher.addGeneratedRoot(docOptions.title ?? lead?.text, lead, headers[0].line);\n attacher.setRoot(root);\n attacher.keepAtDocumentLevel(blocks);\n // Text before the root heading belongs to the root too.\n const stack: { node: OrbitNode; level: number }[] = [{ node: root, level: rootHeader ? topLevel : 0 }];\n\n for (const block of blocks) {\n if (block === lead || block === rootHeader) {\n continue;\n }\n\n if (block.kind !== 'header') {\n attacher.attach(block, stack[stack.length - 1].node);\n continue;\n }\n\n while (stack.length > 1 && stack[stack.length - 1].level >= block.level) {\n stack.pop();\n }\n\n const node = attacher.addHeading(block);\n const parent = stack[stack.length - 1].node;\n setParent(node, parent);\n parent.children.push(node);\n stack.push({ node, level: block.level });\n attacher.reset();\n }\n\n return root;\n};\n\n/** Documents without headings: the outline comes from their bullet or numbered lists. */\nconst buildFromLists = (\n blocks: Block[],\n docOptions: OrbitDocumentOptions,\n diagnostics: DiagnosticCollector,\n attacher: ContentAttacher,\n inputIsBlank: boolean,\n): OrbitNode => {\n const lists = blocks.filter((block): block is ListBlock => block.kind === 'list');\n\n if (lists.length === 0) {\n if (inputIsBlank) {\n diagnostics.recover('empty-document', 'The document is empty.', 1);\n const empty = emptyNode();\n attacher.setRoot(empty);\n return empty;\n }\n\n const firstContent = blocks.find((block) => block.kind !== 'blank');\n diagnostics.recover(\n 'no-structure',\n 'No headings or lists found. Start the map with a \"# Title\" heading or a bullet list.',\n firstContent?.line,\n );\n // Only text: it's the note of a map with no ideas yet, so editing the map keeps it.\n const root = attacher.addGeneratedRoot(docOptions.title, null, firstContent?.line ?? 1, true);\n attacher.setRoot(root);\n\n for (const block of blocks) {\n attacher.attach(block, root);\n }\n\n return root;\n }\n\n const [firstList] = lists;\n const lead = docOptions.title !== undefined ? null : leadParagraph(blocks, firstList);\n\n if (!docOptions.title && !lead && lists.length === 1 && firstList.items.length === 1) {\n // A single top-level item is the root: `- Project\\n - Research`.\n const root = attacher.addItem(firstList.items[0], undefined);\n attacher.setRoot(root);\n attacher.keepAtDocumentLevel(blocks);\n\n for (const block of blocks) {\n if (block !== firstList) {\n attacher.attach(block, root);\n }\n }\n\n return root;\n }\n\n const root = attacher.addGeneratedRoot(docOptions.title ?? lead?.text, lead, firstList.line);\n attacher.setRoot(root);\n attacher.keepAtDocumentLevel(blocks);\n\n for (const block of blocks) {\n if (block !== lead) {\n attacher.attach(block, root);\n }\n }\n\n return root;\n};\n\n/** A single-line paragraph directly before `target` (with only blank lines between) names the generated root. */\nconst leadParagraph = (blocks: Block[], target: Block): ParagraphBlock | null => {\n const targetIndex = blocks.indexOf(target);\n const before = blocks.slice(0, targetIndex).filter((block) => block.kind !== 'blank');\n\n if (before.length !== 1 || before[0].kind !== 'paragraph' || before[0].text.includes('\\n')) {\n return null;\n }\n\n return before[0];\n};\n\nconst syntheticRoot = (text: string | undefined, diagnostics: DiagnosticCollector, line: number, quiet = false, untitled = UNTITLED_ROOT_TEXT): OrbitNode => {\n if (text !== undefined) {\n return makeNode({ text, line });\n }\n\n if (!quiet) {\n diagnostics.note(\n 'synthetic-root',\n `No single top-level heading, so the map is rooted at \"${untitled}\". Add a \"# Title\" heading or a title in the frontmatter to name it.`,\n line,\n );\n }\n\n // Named in the reader's language, with the same id in every one.\n return { ...makeNode({ text: untitled, line }), id: UNTITLED_ROOT_ID };\n};\n\n/**\n * A paragraph of link reference or footnote definitions (`[docs]: https://…`,\n * `[^1]: …`). They belong to the whole document, wherever they're written:\n * deleting the idea above them mustn't take them along.\n */\nconst isDefinitions = (text: string): boolean => {\n const lines = text.split('\\n');\n return DEFINITION.test(lines[0]) && lines.every((line) => DEFINITION.test(line) || /^\\s{2,}\\S/.test(line));\n};\n\nconst DEFINITION = /^ {0,3}\\[\\^?[^\\]\\n]+\\]:\\s*\\S/;\n\n/** How a list item's line is written: where its marker is, the marker, and where its text starts. */\nconst itemShape = (raw: string): NodeShape => {\n const match = /^([ \\t]*)([-*+]|\\d{1,9}[.)])([ \\t]+)/.exec(raw);\n\n if (!match) {\n return { kind: 'item', indent: 0, marker: '-', content: 2 };\n }\n\n const indent = expandLeadingTabs(match[1]).length;\n return { kind: 'item', indent, marker: match[2], content: indent + match[2].length + match[3].length };\n};\n\n// Content: lists become children; everything else is a note, media or attributes\n\ntype MediaAssign = 'image' | 'video' | 'embed' | 'note';\n\n/**\n * Attaches blocks to nodes in document order: every list's items become\n * children, and paragraphs, quotes, code, media lines and attribute\n * comments go to the node itself.\n */\nclass ContentAttacher {\n private readonly diagnostics: DiagnosticCollector;\n private readonly recorder: SourceRecorder;\n private readonly notes = new Map<OrbitNode, string[]>();\n\n /** The map's root, which definitions belong to. */\n private root: OrbitNode | null = null;\n\n /** Blocks of the whole document rather than of the idea above them: definitions at its end. */\n private documentLevel = new Set<Block>();\n\n /** The list item made last, in reading order. */\n private lastItem: OrbitNode | null = null;\n\n /** The node a list was just attached to, and that list's last item, until anything else comes (a blank line too). */\n private afterList: { node: OrbitNode; item: OrbitNode; lastLine: number } | null = null;\n\n /** The media line just read, which a `contentType` comment below it can reclassify. */\n private lastMedia: { node: OrbitNode; block: MediaBlock; result: MediaAssign } | null = null;\n\n /** A `contentType` comment waiting for the media line below it. */\n private pendingContentType: { node: OrbitNode; kind: ContentType } | null = null;\n\n /** The made-up root's name, when it has no title. */\n private readonly untitled: string | undefined;\n\n constructor(diagnostics: DiagnosticCollector, recorder: SourceRecorder, untitled?: string) {\n this.diagnostics = diagnostics;\n this.recorder = recorder;\n this.untitled = untitled;\n }\n\n setRoot(root: OrbitNode): void {\n this.root = root;\n }\n\n /**\n * Link reference and footnote definitions at the end of the document\n * (`[docs]: https://…`, `[^1]: …`) belong to the whole map, not to the\n * idea above them: deleting that idea mustn't take them along.\n */\n keepAtDocumentLevel(blocks: Block[]): void {\n for (let index = blocks.length - 1; index >= 0; index -= 1) {\n const block = blocks[index];\n\n if (block.kind === 'blank') {\n continue;\n }\n\n if (block.kind !== 'paragraph' || !isDefinitions(block.text)) {\n return;\n }\n\n this.documentLevel.add(block);\n }\n }\n\n /** A heading's node, its line recorded as its title. */\n addHeading(header: HeaderBlock): OrbitNode {\n noteAttributeComments(header.text, header.line, this.diagnostics);\n const node = makeNode(header);\n this.recorder.mark(header.line, header.last, node, 'title');\n this.recorder.shape(node, { kind: 'heading', level: header.level, setext: header.setext }, header.line);\n return node;\n }\n\n /** A root Orbit makes up: named after the title, the paragraph `lead`, or \"Untitled map\". */\n addGeneratedRoot(text: string | undefined, lead: ParagraphBlock | null, line: number, quiet = false): OrbitNode {\n const node = syntheticRoot(text, this.diagnostics, line, quiet, this.untitled);\n\n if (lead) {\n this.recorder.mark(lead.line, lead.last, node, 'title');\n }\n\n this.recorder.shape(node, { kind: 'generated', lead: lead !== null }, lead ? lead.line : null);\n return node;\n }\n\n attach(block: Block, node: OrbitNode): void {\n if (block.kind === 'comment' && !block.inline && this.afterList?.node === node && block.line === this.afterList.lastLine + 1) {\n const item = this.afterList.item.text;\n this.diagnostics.note('attributes-after-list', `This attribute block sets \"${node.text}\"'s attributes: it isn't indented under \"${item}\" above it. Indent it to set \"${item}\"'s.`, block.line);\n }\n\n this.afterList = null;\n\n switch (block.kind) {\n case 'blank':\n // A blank line goes with the line above it (see SourceRecorder.finish).\n return;\n case 'foreign':\n if (block.comment !== undefined) {\n noteAttributeComments(`<!--${block.comment}-->`, block.line, this.diagnostics);\n }\n\n this.recorder.mark(block.line, block.last, node, 'foreign');\n return;\n case 'comment':\n this.applyComment(block, node);\n return;\n case 'media': {\n const forced = this.pendingContentType?.node === node ? this.pendingContentType.kind : null;\n this.pendingContentType = null;\n const result = assignMedia(block, node, this.noteParts(node), forced);\n this.lastMedia = { node, block, result };\n this.recorder.mark(block.line, block.last, node, result === 'note' ? 'note' : 'media');\n return;\n }\n case 'list':\n for (const item of block.items) {\n this.addItem(item, node);\n }\n\n this.afterList = this.lastItem ? { node, item: this.lastItem, lastLine: lastLineOf(block.items) } : null;\n break;\n case 'header':\n this.noteParts(node).push(`${'#'.repeat(block.level)} ${block.text}`);\n this.recorder.mark(block.line, block.last, node, 'note');\n break;\n case 'note':\n case 'paragraph': {\n const documentLevel = this.documentLevel.has(block) && this.root !== null;\n const owner = documentLevel ? this.root! : node;\n this.noteParts(owner).push(block.text);\n this.recorder.mark(block.line, block.last, owner, documentLevel ? 'end' : 'note');\n break;\n }\n }\n\n this.reset();\n }\n\n /** Builds a list item's node (under `parent`, if any) with everything written under it. */\n addItem(item: ListItem, parent: OrbitNode | undefined): OrbitNode {\n noteAttributeComments(item.text, item.line, this.diagnostics);\n const node = makeNode(item);\n this.lastItem = node;\n this.recorder.mark(item.line, item.line, node, 'title');\n this.recorder.shape(node, itemShape(this.recorder.line(item.line)), item.line);\n\n if (parent) {\n setParent(node, parent);\n parent.children.push(node);\n }\n\n if (item.inlineAttrs !== undefined) {\n applyAttributeBlock(node, { kind: 'comment', body: item.inlineAttrs, line: item.line, last: item.line, inline: true }, this.diagnostics);\n }\n\n this.reset();\n\n for (const block of item.content) {\n this.attach(block, node);\n }\n\n this.reset();\n return node;\n }\n\n /** Forgets the media line just read, at a new heading or after other content. */\n reset(): void {\n this.lastMedia = null;\n this.pendingContentType = null;\n }\n\n /** Writes the collected notes, after any `note` attribute. */\n finish(): void {\n for (const [node, parts] of this.notes) {\n const note = parts.join('\\n\\n');\n\n // Emptiness is checked on the trimmed form, but the stored note keeps\n // its whitespace: blockquote notes carry it on purpose.\n if (note.trim()) {\n node.note = node.note ? `${node.note}\\n\\n${note}` : note;\n // Only a default: an explicit `noteFormat` attribute wins.\n node.noteFormat = node.noteFormat ?? 'markdown';\n }\n }\n }\n\n private noteParts(node: OrbitNode): string[] {\n let parts = this.notes.get(node);\n\n if (!parts) {\n parts = [];\n this.notes.set(node, parts);\n }\n\n return parts;\n }\n\n private applyComment(block: CommentBlock, node: OrbitNode): void {\n const keys = applyAttributeBlock(node, block, this.diagnostics, {\n applyContentType: (kind) => {\n if (this.lastMedia?.node === node) {\n reclassify(node, this.lastMedia.block, kind, this.noteParts(node), this.lastMedia.result);\n this.lastMedia.result = kind === 'none' ? 'note' : kind;\n const media = this.lastMedia.block;\n this.recorder.mark(media.line, media.last, node, this.lastMedia.result === 'note' ? 'note' : 'media');\n } else {\n this.pendingContentType = { node, kind };\n }\n },\n clearLastMedia: () => {\n this.lastMedia = null;\n },\n captionTarget: () => {\n const last = this.lastMedia;\n return last?.node === node && (last.result === 'image' || last.result === 'video' || last.result === 'embed') ? last.result : null;\n },\n });\n\n if (!block.inline) {\n // A comment that only says what the media line above it is goes with it; one Orbit\n // couldn't read is kept as it's written.\n const role: LineRole = keys === null ? 'foreign' : keys.length > 0 && keys.every((key) => key === 'contentType' || key === 'caption') ? 'media' : 'attributes';\n this.recorder.mark(block.line, block.last, node, role);\n }\n }\n}\n\nconst reclassify = (\n node: OrbitNode,\n media: MediaBlock,\n kind: ContentType,\n noteLines: string[],\n previous: MediaAssign | null,\n): void => {\n // Undo only what this media block was read as, so an earlier block's\n // assignment survives.\n if (previous === 'image') {\n node.image = undefined;\n } else if (previous === 'video') {\n node.video = undefined;\n } else if (previous === 'embed') {\n node.embed = undefined;\n } else if (previous === 'note') {\n const reconstructed = reconstructMediaSource(media);\n\n if (noteLines.length && noteLines[noteLines.length - 1] === reconstructed) {\n noteLines.pop();\n }\n }\n\n if (kind === 'none') {\n noteLines.push(reconstructMediaSource(media));\n return;\n }\n\n if (kind === 'image') {\n node.image = { src: media.url, alt: media.alt || undefined };\n return;\n }\n\n if (kind === 'video') {\n const provider = detectVideoProvider(media.url) ?? 'native';\n node.video = { src: media.url, provider, thumbnail: media.mediaKind === 'wrapped' ? media.thumb : undefined };\n return;\n }\n\n node.embed = { src: media.url };\n};\n\ninterface AttributeContext {\n applyContentType: (kind: ContentType) => void;\n clearLastMedia: () => void;\n\n /** The media of the line just above the block, which a caption in it describes. */\n captionTarget: () => MediaKey | null;\n}\n\ntype MediaKey = 'image' | 'video' | 'embed';\n\n/** Keys an attribute block takes besides the node attributes. */\nconst MARKDOWN_ATTRIBUTE_VOCABULARY = { keys: ['contentType'] };\n\n/**\n * Applies a `<!-- orbit ... -->` block to a node. Media keys are applied\n * before `caption`, which describes, in order: the one image, video or embed\n * the block itself sets; the media line just above the block; or else the\n * node's video, embed or image.\n */\nconst applyAttributeBlock = (\n node: OrbitNode,\n comment: CommentBlock,\n diagnostics: DiagnosticCollector,\n context?: AttributeContext,\n): string[] | null => {\n const body = comment.body.trim();\n\n if (body === '') {\n return [];\n }\n\n // On one line, `status: active, priority: 1` is two attributes.\n const pairs = comment.inline ? commaSeparatedAttributes(body) : null;\n let parsed: Record<string, unknown>;\n\n try {\n parsed = pairs\n ? Object.assign({}, ...pairs.map((pair) => parseYaml(pair) as Record<string, unknown>))\n : ((parseYaml(body) ?? {}) as Record<string, unknown>);\n } catch (error) {\n const problem = error instanceof YamlMiniError ? error : null;\n // A pair split out of a one-line comment keeps no line numbers of its own.\n const line = problem && !pairs ? (comment.bodyLine ?? comment.line) + problem.line - 1 : comment.line;\n diagnostics.recover('invalid-attributes', `Invalid YAML in attribute block: ${problem?.reason ?? (error as Error).message}`, line);\n return null;\n }\n\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n diagnostics.recover('invalid-attributes', 'An attribute block must contain \"key: value\" pairs.', comment.line);\n return null;\n }\n\n const entries = Object.entries(parsed);\n\n for (const [key, value] of entries) {\n if (key === 'caption') {\n continue;\n }\n\n if (key === 'contentType') {\n if (!CONTENT_TYPES.has(value as ContentType)) {\n diagnostics.recover(\n 'unknown-content-type',\n `Unknown contentType \"${String(value)}\"; expected image, video, embed or none.`,\n comment.line,\n );\n continue;\n }\n\n context?.applyContentType(value as ContentType);\n continue;\n }\n\n assignNodeAttribute(node, key, value, diagnostics, comment.line, MARKDOWN_ATTRIBUTE_VOCABULARY);\n\n if (key === 'image' || key === 'video' || key === 'embed') {\n context?.clearLastMedia();\n }\n }\n\n const mediaSet = entries.map(([key]) => key).filter((key): key is MediaKey => key === 'image' || key === 'video' || key === 'embed');\n\n for (const [key, value] of entries) {\n if (key !== 'caption') {\n continue;\n }\n\n const described = mediaSet.length === 1 ? mediaSet[0] : mediaSet.length === 0 ? context?.captionTarget() ?? null : null;\n const media = described ? node[described] : undefined;\n\n if (media && value !== null && value !== undefined) {\n media.caption = String(value);\n } else {\n assignNodeAttribute(node, key, value, diagnostics, comment.line);\n }\n }\n\n return entries.map(([key]) => key);\n};\n\nconst assignMedia = (block: MediaBlock, node: OrbitNode, noteLines: string[], forced: ContentType | null): MediaAssign => {\n const toNote = (): MediaAssign => {\n noteLines.push(reconstructMediaSource(block));\n return 'note';\n };\n\n if (forced === 'none') {\n return toNote();\n }\n\n if (forced === 'image') {\n if (node.image) {\n return toNote();\n }\n\n node.image = { src: block.url, alt: block.alt || undefined };\n return 'image';\n }\n\n if (forced === 'video') {\n if (node.video) {\n return toNote();\n }\n\n node.video = { src: block.url, provider: detectVideoProvider(block.url) ?? 'native', thumbnail: block.mediaKind === 'wrapped' ? block.thumb : undefined };\n return 'video';\n }\n\n if (forced === 'embed') {\n if (node.embed) {\n return toNote();\n }\n\n node.embed = { src: block.url };\n return 'embed';\n }\n\n // Auto-detect path\n if (block.mediaKind === 'wrapped') {\n const provider = detectVideoProvider(block.url);\n\n if (provider) {\n // Wrapped video: only consume into node.video; if taken, fall to note.\n if (!node.video) {\n node.video = { src: block.url, provider, thumbnail: block.thumb };\n return 'video';\n }\n } else if (!node.image) {\n // Wrapped link that's not a video: treat the inner thumbnail as the image.\n node.image = { src: block.thumb!, alt: block.alt || undefined };\n return 'image';\n }\n } else if (block.mediaKind === 'image') {\n if (!node.image) {\n node.image = { src: block.url, alt: block.alt || undefined };\n return 'image';\n }\n } else if (block.mediaKind === 'link') {\n const provider = detectVideoProvider(block.url);\n\n if (!node.video && provider) {\n node.video = { src: block.url, provider };\n return 'video';\n }\n }\n\n return toNote();\n};\n\n/**\n * `key: value, key: value` on one line, split into its pairs; null when the\n * text isn't a list of pairs. Commas inside quotes or brackets don't split,\n * and a backslash escapes the next character inside double quotes.\n */\nconst commaSeparatedAttributes = (body: string): string[] | null => {\n if (body.includes('\\n')) {\n return null;\n }\n\n const pairs: string[] = [];\n let depth = 0;\n let quote = '';\n let start = 0;\n\n for (let index = 0; index < body.length; index += 1) {\n const character = body[index];\n\n if (quote) {\n if (character === '\\\\' && quote === '\"') {\n index += 1;\n } else if (character === quote) {\n quote = '';\n }\n } else if (character === '\"' || character === \"'\") {\n quote = character;\n } else if (character === '[' || character === '{') {\n depth += 1;\n } else if (character === ']' || character === '}') {\n depth -= 1;\n } else if (character === ',' && depth === 0) {\n pairs.push(body.slice(start, index).trim());\n start = index + 1;\n }\n }\n\n pairs.push(body.slice(start).trim());\n const isPair = (text: string) => /^[A-Za-z][\\w-]*\\s*:(\\s|$)/.test(text);\n return pairs.length > 1 && pairs.every(isPair) ? pairs : null;\n};\n\nconst reconstructMediaSource = (block: MediaBlock): string => {\n if (block.mediaKind === 'image') {\n return ``;\n }\n\n if (block.mediaKind === 'wrapped') {\n return `[](${block.url})`;\n }\n\n return `[${block.text ?? ''}](${block.url})`;\n};\n\n// Shared helpers\n\n/** Where a link in a node's note is: the first line from the node's title up to the next node's that has it. */\nconst noteLinkLines = (root: OrbitNode, rawLines: string[]): LinkLine => {\n const titles: number[] = [];\n\n const collect = (node: OrbitNode): void => {\n if (node.source?.line !== undefined) {\n titles.push(node.source.line);\n }\n\n node.children.forEach(collect);\n };\n\n collect(root);\n titles.sort((a, b) => a - b);\n\n return (node, href, inNote) => {\n const start = node.source?.line;\n\n if (start === undefined || !inNote) {\n return start;\n }\n\n const end = titles.find((line) => line > start) ?? rawLines.length + 1;\n\n for (let line = start; line < end; line += 1) {\n if (rawLines[line - 1].includes(`](${href})`)) {\n return line;\n }\n }\n\n return start;\n };\n};\n\n/** The last line a list's items take, blank lines after them aside. */\nconst lastLineOf = (items: ListItem[]): number => {\n const item = items[items.length - 1];\n const content = item.content.filter((block) => block.kind !== 'blank');\n const last = content[content.length - 1];\n\n if (last?.kind === 'list') {\n return lastLineOf(last.items);\n }\n\n return last ? last.last : item.line;\n};\n\n/**\n * Notes a comment that sets nothing because it lacks the `orbit` keyword,\n * although it reads like attributes: `<!-- status: done -->`.\n */\nconst noteAttributeComments = (text: string, line: number, diagnostics: DiagnosticCollector): void => {\n for (const match of text.matchAll(HIDDEN_COMMENT)) {\n const body = match[2].trim();\n const key = /^([A-Za-z]+)\\s*:/.exec(body)?.[1];\n\n if (key !== undefined && (NODE_ATTRIBUTE_KEYS as readonly string[]).includes(key)) {\n diagnostics.note('comment-without-orbit', `This comment is hidden, so it sets nothing: to set \"${key}\", write <!-- orbit ${body} -->.`, line);\n }\n }\n};\n\nconst makeNode = (source: { text: string; line: number }): OrbitNode => {\n const parts = parseTitle(source.text);\n const node: OrbitNode = {\n id: nodeSlug(parts.text),\n text: parts.text,\n level: 0,\n children: [],\n icon: parts.icon,\n link: parts.link,\n source: { line: source.line, raw: '' },\n };\n\n if (parts.status) {\n node.status = parts.status;\n }\n\n if (parts.tags) {\n node.tags = parts.tags;\n }\n\n return node;\n};\n\nconst emptyNode = (): OrbitNode => {\n return { id: 'empty', text: '', level: 0, children: [] };\n};\n\nconst fixLevels = (node: OrbitNode, level: number): void => {\n node.level = level;\n\n for (const child of node.children) {\n setParent(child, node);\n fixLevels(child, level + 1);\n }\n};\n",
|
|
20
21
|
"import type { OrbitDocumentOptions, OrbitNode, ParsedOrbitDocument } from './types.js';\nimport { parseYaml, yamlItemLine, yamlLineOf, YamlMiniError } from './yaml-mini.js';\nimport { UNTITLED_ROOT_ID, UNTITLED_ROOT_TEXT } from './parser-markdown.js';\nimport { upgradeFormat } from './format-upgrades.js';\nimport { checkNodeLinks } from './node-links.js';\nimport { ensureUniqueNodeIds, nodeSlug, setParent } from './utils.js';\nimport { DiagnosticCollector } from './diagnostics.js';\nimport { applyDocumentOption, DOCUMENT_OPTION_KEYS, unknownOptionMessage } from './document-options.js';\nimport { assignNodeAttribute, type AttributeVocabulary } from './node-attributes.js';\nimport { lineOfKey, normalizeSource } from './source.js';\n\nexport interface ParseYamlOptions {\n /** Throw on the first problem instead of recording a diagnostic. Off by default. */\n strict?: boolean;\n\n /** The name of the root Orbit makes up for several top-level nodes and no title. Default \"Untitled map\"; its id is `untitled-map` whatever its name. */\n untitled?: string;\n}\n\nexport const parseOrbitYAML = (input: string, options: ParseYamlOptions = {}): ParsedOrbitDocument => {\n const diagnostics = new DiagnosticCollector(options.strict ?? false);\n const source = normalizeSource(input);\n const lines = source.split('\\n');\n const extra: Record<string, unknown> = {};\n const result = (root: OrbitNode, docOptions: OrbitDocumentOptions): ParsedOrbitDocument => ({\n root,\n options: docOptions,\n ...(Object.keys(extra).length > 0 ? { extra } : {}),\n warnings: diagnostics.warnings,\n diagnostics: diagnostics.diagnostics,\n });\n\n let parsed: unknown;\n\n try {\n parsed = parseYaml(source);\n } catch (error) {\n const problem = error instanceof YamlMiniError ? error : null;\n diagnostics.recover('invalid-yaml', `Invalid YAML: ${problem?.reason ?? (error as Error).message}`, problem?.line ?? 1, 'error');\n return result(emptyNode(), {});\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n diagnostics.recover('invalid-yaml', 'A YAML map needs top-level \"key: value\" entries such as \"nodes:\".', 1, 'error');\n return result(emptyNode(), {});\n }\n\n const docOptions: OrbitDocumentOptions = {};\n const map = parsed as Record<string, unknown>;\n\n for (const [key, value] of Object.entries(map)) {\n if (key === 'nodes') {\n continue;\n }\n\n const line = lineOfKey(lines, key);\n\n if (!DOCUMENT_OPTION_KEYS.has(key)) {\n diagnostics.recover('unknown-yaml-key', unknownOptionMessage(key, 'top-level'), line);\n extra[key] = value;\n continue;\n }\n\n applyDocumentOption(docOptions, key, value, (message) => diagnostics.recover('invalid-option-value', message, line));\n }\n\n const nodes = map.nodes;\n\n if (!Array.isArray(nodes) || nodes.length === 0) {\n const message = nodes !== undefined && nodes !== null && !Array.isArray(nodes)\n ? '\"nodes\" must be a list: start the root on the line below it with \"- text: …\".'\n : 'No nodes found. Add a \"nodes:\" list with one root node.';\n diagnostics.recover('no-structure', message, lineOfKey(lines, 'nodes') ?? 1);\n return result(emptyNode(), docOptions);\n }\n\n const root = nodes.length === 1 ? buildNode(nodes[0], 0, undefined, diagnostics, yamlItemLine(nodes, 0)) : sharedRoot(docOptions.title, diagnostics, lineOfKey(lines, 'nodes'), options.untitled);\n\n if (nodes.length > 1) {\n // Several top-level nodes share a root named after the title.\n nodes.forEach((raw, index) => {\n root.children.push(buildNode(raw, 1, root, diagnostics, yamlItemLine(nodes, index)));\n });\n }\n\n ensureUniqueNodeIds(root);\n checkNodeLinks(root, diagnostics, (node, _href, inNote) => nodeKeyLines.get(node)?.(inNote ? 'note' : 'link'));\n const document = result(root, docOptions);\n upgradeFormat(document, diagnostics, lineOfKey(lines, 'schemaVersion'));\n document.warnings = diagnostics.warnings;\n return document;\n};\n\nconst sharedRoot = (title: string | undefined, diagnostics: DiagnosticCollector, line: number | undefined, untitled = UNTITLED_ROOT_TEXT): OrbitNode => {\n if (title !== undefined) {\n return { id: nodeSlug(title), text: title, level: 0, children: [] };\n }\n\n diagnostics.note(\n 'synthetic-root',\n `Several top-level nodes, so the map is rooted at \"${untitled}\". Add a title to name it.`,\n line,\n );\n // Named in the reader's language, with the same id in every one.\n return { id: UNTITLED_ROOT_ID, text: untitled, level: 0, children: [] };\n};\n\n/** A YAML node's own keys: its text and its children. */\nconst YAML_NODE_VOCABULARY: AttributeVocabulary = {\n keys: ['text', 'children'],\n synonyms: { title: 'text', label: 'text', name: 'text', items: 'children', nodes: 'children', subnodes: 'children' },\n};\n\n/** Keys people (and agents) write for a node's text and its children: read as them when the real key is missing, and reported. */\nconst TEXT_SYNONYMS = ['title', 'name', 'label'];\nconst CHILDREN_SYNONYMS = ['items', 'nodes', 'subnodes'];\n\n/** The key a node's text or children are under: the real one, or a synonym standing in for it. */\nconst misnamedKey = (map: Record<string, unknown>, key: 'text' | 'children', diagnostics: DiagnosticCollector, lineOf: (key: string) => number | undefined): string => {\n if (map[key] !== undefined && map[key] !== null) {\n return key;\n }\n\n const synonym = key === 'text'\n ? TEXT_SYNONYMS.find((candidate) => typeof map[candidate] === 'string' || typeof map[candidate] === 'number')\n : CHILDREN_SYNONYMS.find((candidate) => Array.isArray(map[candidate]));\n\n if (synonym === undefined) {\n return key;\n }\n\n const what = key === 'text' ? 'text goes' : 'children go';\n diagnostics.recover('misnamed-node-key', `A node's ${what} in \"${key}\", not \"${synonym}\": read as its ${key === 'text' ? 'text' : 'children'}. Rename \"${synonym}\" to \"${key}\".`, lineOf(synonym));\n return synonym;\n};\n\n/** Where each node's keys were written, for problems found once the tree is built (links to missing nodes). */\nconst nodeKeyLines = new WeakMap<OrbitNode, (key: string) => number | undefined>();\n\n/** A YAML node, from its map (or plain text); `line` is where its list item starts, for problems Orbit can't place closer. */\nconst buildNode = (raw: unknown, level: number, parent: OrbitNode | undefined, diagnostics: DiagnosticCollector, line?: number): OrbitNode => {\n // Scalar shorthand: a plain string/number/boolean child is its text.\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n const text = raw === null || Array.isArray(raw) ? '' : String(raw);\n\n if (raw === null || Array.isArray(raw)) {\n diagnostics.note('ignored-node-entry', `Ignored ${Array.isArray(raw) ? 'an array' : 'a null'} node entry: expected a map or plain text.`, line);\n }\n\n const node: OrbitNode = { id: nodeSlug(text), text, level, children: [] };\n setParent(node, parent);\n nodeKeyLines.set(node, () => line);\n return node;\n }\n\n const map = raw as Record<string, unknown>;\n const lineOf = (key: string) => yamlLineOf(map, key) ?? line;\n\n if (map.text !== undefined && map.text !== null && typeof map.text === 'object') {\n diagnostics.recover('invalid-attributes', `text must be a word or a number, not ${Array.isArray(map.text) ? 'a list' : 'a map'}; its text form is used`, lineOf('text'));\n }\n\n if (map.children !== undefined && map.children !== null && !Array.isArray(map.children)) {\n const got = typeof map.children === 'object' ? 'a map' : `\"${String(map.children)}\"`;\n diagnostics.recover('invalid-attributes', `children must be a list of nodes, not ${got}; ignored`, lineOf('children'));\n }\n\n const textKey = misnamedKey(map, 'text', diagnostics, lineOf);\n const childrenKey = misnamedKey(map, 'children', diagnostics, lineOf);\n const node: OrbitNode = {\n id: (typeof map.id === 'string' || typeof map.id === 'number') && String(map.id).trim() !== '' ? String(map.id) : nodeSlug(String(map[textKey] ?? '')),\n text: String(map[textKey] ?? ''),\n level,\n children: [],\n };\n setParent(node, parent);\n nodeKeyLines.set(node, lineOf);\n const entries = Object.entries(map);\n\n for (const [key, value] of entries) {\n if (key === 'text' || key === 'id' || key === 'children' || key === 'caption' || key === textKey || key === childrenKey) {\n continue;\n }\n\n assignNodeAttribute(node, key, value, diagnostics, lineOf(key), YAML_NODE_VOCABULARY);\n }\n\n // A node-level caption applies to the media set above.\n if ('caption' in map) {\n assignNodeAttribute(node, 'caption', map.caption, diagnostics, lineOf('caption'));\n }\n\n const children = map[childrenKey];\n\n if (Array.isArray(children)) {\n children.forEach((child, index) => {\n node.children.push(buildNode(child, level + 1, node, diagnostics, yamlItemLine(children, index) ?? lineOf(childrenKey)));\n });\n }\n\n return node;\n};\n\nconst emptyNode = (): OrbitNode => {\n return { id: 'empty', text: '', level: 0, children: [] };\n};\n",
|
|
21
22
|
"import type { OrbitDocument, ParsedOrbitDocument } from './types.js';\nimport type { ParseOptions } from './parser-markdown.js';\nimport { parseOrbitMarkdown } from './parser-markdown.js';\nimport { parseOrbitYAML } from './parser-yaml.js';\nimport { parseYaml } from './yaml-mini.js';\nimport { DOCUMENT_OPTION_KEYS } from './document-options.js';\nimport { findFrontmatter, firstContentLineIndex, normalizeSource, sharedIndentation } from './source.js';\nimport { documentSource, encodingOf } from './document-source.js';\n\n/**\n * Parses an orbit document in either flavor. Markdown is the default; a\n * document is read as YAML when its first line is a top-level YAML key\n * (`nodes:`, `title:`, `view:`, …), it has a top-level `nodes:` list, or its\n * frontmatter says `flavor: yaml`. A fenced ```orbit block is unwrapped first.\n *\n * Problems the parser can work around are listed in `diagnostics` (each with\n * a `code`, `line`, `severity` and a message that says how to fix it); pass\n * `{ strict: true }` to throw an `OrbitParseError` on the first one instead.\n *\n * @example\n * ```ts\n * import { parseOrbit } from '@restless-dreams/orbit';\n *\n * const { root, diagnostics } = parseOrbit('# Launch\\n## Research <!-- orbit status: active -->');\n * for (const problem of diagnostics ?? []) console.warn(`line ${problem.line}: ${problem.message}`);\n * ```\n */\nexport const parseOrbit = (input: string, options: ParseOptions = {}): ParsedOrbitDocument => {\n const unfenced = stripOrbitFence(input);\n const source = normalizeSource(unfenced);\n const lines = source.split('\\n');\n\n if (chooseFlavor(source, lines) === 'markdown') {\n const document = parseOrbitMarkdown(source, options);\n keepEncoding(document, input, unfenced);\n return document;\n }\n\n const frontmatter = findFrontmatter(lines);\n\n if (frontmatter) {\n // The frontmatter keys join the YAML document. Blanking the fences keeps\n // every line where it was, so diagnostics point at the right line.\n const yamlLines = [...lines];\n yamlLines[frontmatter.openIndex] = '';\n yamlLines[frontmatter.closeIndex] = '';\n return parseOrbitYAML(yamlLines.join('\\n'), options);\n }\n\n return parseOrbitYAML(source, options);\n};\n\n/** The flavor `parseOrbit` reads a document as: `markdown` or `yaml`. */\nexport const orbitFlavor = (input: string): 'markdown' | 'yaml' => {\n const source = normalizeSource(stripOrbitFence(input));\n return chooseFlavor(source, source.split('\\n'));\n};\n\n/**\n * YAML when the document is a YAML map of a map: its first line is\n * `nodes:`, or it reads as YAML with a `nodes:` list, or it starts with one\n * of the map's options and reads as YAML. Markdown with headings, lists or\n * paragraphs doesn't read as a YAML map, so a note that starts with\n * \"nodes:\" or \"title:\" never turns a markdown map into a YAML one.\n */\nconst chooseFlavor = (source: string, lines: string[]): 'markdown' | 'yaml' => {\n const frontmatter = findFrontmatter(lines);\n\n if (frontmatter) {\n return frontmatterFlavor(frontmatter.yaml) === 'yaml' ? 'yaml' : 'markdown';\n }\n\n const firstIndex = firstContentLineIndex(lines);\n\n if (firstIndex === -1) {\n return 'markdown';\n }\n\n const first = lines[firstIndex];\n\n // A plausible YAML `nodes` key: nothing after the colon (a list below), or\n // a flow value or comment. Prose like \"nodes: the points of a graph\" stays markdown.\n if (/^nodes\\s*:\\s*(?:$|[#[{])/.test(first)) {\n return 'yaml';\n }\n\n const startsWithOption = isOptionLine(first);\n\n if (!startsWithOption && !/^nodes\\s*:/m.test(source)) {\n return 'markdown';\n }\n\n let value: unknown;\n\n try {\n value = parseYaml(source);\n } catch {\n // Not YAML at all: markdown, unless it starts like a YAML map with a mistake further down.\n return startsWithOption && /^nodes\\s*:/m.test(source) ? 'yaml' : 'markdown';\n }\n\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return 'markdown';\n }\n\n return Array.isArray((value as Record<string, unknown>).nodes) || startsWithOption ? 'yaml' : 'markdown';\n};\n\n/** A first line like `title: …` or `theme: …`: one of a map's options. */\nconst isOptionLine = (line: string): boolean => {\n const match = /^([A-Za-z][\\w-]*)\\s*:(\\s|$)/.exec(line);\n return match !== null && DOCUMENT_OPTION_KEYS.has(match[1]);\n};\n\n/**\n * Notes how the text was written before it was normalized (line endings, a\n * byte-order mark, shared indentation, a ```` ```orbit ```` fence around\n * it), so saving writes it back the same way.\n */\nconst keepEncoding = (document: OrbitDocument, input: string, unfenced: string): void => {\n const source = documentSource(document);\n\n if (!source) {\n return;\n }\n\n const plain = (text: string) => text.replace(/^\\uFEFF/, '').replace(/\\r\\n?/g, '\\n');\n const fence = unfenced === input ? null : ORBIT_FENCE.exec(input);\n let before: string[] = [];\n let after: string[] = [];\n\n if (fence) {\n // The body starts on the line after the opening fence: indexOf can't be\n // trusted (an empty body, or one repeated in the fence's info string).\n const bodyStart = fence[1].length;\n before = plain(input.slice(0, bodyStart)).split('\\n').slice(0, -1);\n const rest = plain(input.slice(bodyStart + fence[3].length));\n // A body of its own lines ends with a line break before the closing fence.\n after = rest.startsWith('\\n') || rest === '' ? rest.split('\\n').slice(1) : rest.split('\\n');\n }\n\n source.encoding = { ...encodingOf(input), indentation: sharedIndentation(plain(unfenced)), before, after };\n};\n\n/**\n * A document wrapped in a ```` ```orbit ```` fence: the opening line, the\n * fence's kind, the body, then a closing fence of the same kind, indented or\n * not. The info string is `orbit`, alone or followed by display options after\n * a space (```` ```orbit height=480 ````), so ```` ```orbital ```` stays\n * markdown. The body ends before the closing line's break, `\\r\\n` included.\n */\nconst ORBIT_FENCE = /^(\\s*(```|~~~)orbit(?:[^\\S\\n][^\\n]*)?\\n)([\\s\\S]*?)(?:\\r?\\n)?[^\\S\\n]*\\2\\s*$/;\n\nconst stripOrbitFence = (input: string): string => {\n const match = ORBIT_FENCE.exec(input);\n return match ? match[3] : input;\n};\n\nconst frontmatterFlavor = (yaml: string): string | undefined => {\n try {\n const frontmatter = parseYaml(yaml) as Record<string, unknown> | null;\n return frontmatter && typeof frontmatter.flavor === 'string' ? frontmatter.flavor : undefined;\n } catch {\n return undefined;\n }\n};\n",
|
|
22
|
-
"/**\n * How Orbit writes a map as markdown: its own form, the way people write\n * maps. `serializeOrbitMarkdown` writes a whole map this way, and saving an\n * edited map writes its changed ideas this way (see source-patch.ts).\n */\n\nimport type { OrbitDocument, OrbitNode } from './types.js';\nimport { emitYaml, assignKey, plainScalarReadsBack, type YamlValue } from './yaml-mini.js';\nimport { nodesWithExplicitIds } from './utils.js';\nimport { detectVideoProvider } from './media.js';\nimport { isTitleIcon, parseOrbitMarkdown, parseTitle } from './parser-markdown.js';\nimport { mediaExtras } from './node-attributes.js';\n\n/** A whole map in Orbit's own form. */\nexport const writeMarkdown = (doc: OrbitDocument): string => {\n let out = '';\n const fmKeys = collectFrontmatter(doc);\n\n if (Object.keys(fmKeys).length > 0) {\n out += '---\\n' + emitYaml(fmKeys as unknown as YamlValue) + '---\\n\\n';\n }\n\n out += emitHeading(doc.root, 1, { explicitIds: nodesWithExplicitIds(doc.root) });\n return out;\n};\n\nexport const collectFrontmatter = (doc: Pick<OrbitDocument, 'options' | 'extra'>): Record<string, unknown> => {\n const o = doc.options;\n const r: Record<string, unknown> = {};\n\n if (o.title) {\n r.title = o.title;\n }\n\n if (o.theme) {\n r.theme = o.theme;\n }\n\n if (o.viewMode) {\n r.view = o.viewMode;\n }\n\n if (o.showRings !== undefined) {\n r.showRings = o.showRings;\n }\n\n if (o.interactive !== undefined) {\n r.interactive = o.interactive;\n }\n\n if (o.orbitAnimation !== undefined) {\n r.animation = o.orbitAnimation;\n }\n\n if (o.orbitSpeed !== undefined) {\n r.speed = o.orbitSpeed;\n }\n\n if (o.palette) {\n r.palette = o.palette;\n }\n\n if (o.height !== undefined) {\n r.height = o.height;\n }\n\n if (o.maxDepth !== undefined) {\n r.maxDepth = o.maxDepth;\n }\n\n if (o.className) {\n r.className = o.className;\n }\n\n if (o.baseUrl) {\n r.baseUrl = o.baseUrl;\n }\n\n if (o.schemaVersion !== undefined) {\n r.schemaVersion = o.schemaVersion;\n }\n\n // Keys Orbit doesn't read, after its own: as they were written.\n for (const [key, value] of Object.entries(doc.extra ?? {})) {\n if (!Object.prototype.hasOwnProperty.call(r, key)) {\n assignKey(r, key, value);\n }\n }\n\n return r;\n};\n\n/**\n * The root and its children are headings; everything under them is a\n * list, the way people write maps. Below two levels, headings would only\n * make a map harder to read.\n */\nexport const HEADING_LEVELS = 2;\n\n/** The statuses a list item writes as a checkbox. */\nexport const CHECKBOXES: Record<string, string> = { todo: '[ ]', done: '[x]', active: '[/]' };\n\n/** What writing a node needs besides the node: which ids to write. */\nexport interface Writing {\n /** The nodes whose ids the parsers wouldn't make from their text, so they are written. */\n explicitIds: ReadonlySet<OrbitNode>;\n}\n\nexport const emitHeading = (node: OrbitNode, level: number, writing: Writing): string => {\n const parts = nodeParts(node, false, writing, '');\n const out = `${'#'.repeat(level)} ${parts.line}\\n${parts.body}`;\n\n if (node.children.length === 0) {\n return out;\n }\n\n if (level < HEADING_LEVELS) {\n return out + node.children.map((child) => `\\n${emitHeading(child, level + 1, writing)}`).join('');\n }\n\n return out + emitList(node.children, '', writing);\n};\n\nexport const emitList = (children: OrbitNode[], indent: string, writing: Writing): string => {\n let out = '';\n\n for (const child of children) {\n const parts = nodeParts(child, true, writing, `${indent} `);\n out += `${indent}- ${parts.line}\\n${parts.body}`;\n out += emitList(child.children, `${indent} `, writing);\n }\n\n return out;\n};\n\n/**\n * A node as written: its line after the heading's `#`s or the item's\n * marker (title, then the attributes that fit on it), and what follows the\n * line, indented by `indent`.\n */\nexport const nodeParts = (node: OrbitNode, listItem: boolean, writing: Writing, indent: string): { line: string; title: string; inline: string; body: string } => {\n const pieces = nodePieces(node, listItem, writing, indent);\n return { line: `${pieces.title}${pieces.inline}`.trimStart(), title: pieces.title, inline: pieces.inline, body: pieces.attributes + pieces.media + pieces.note };\n};\n\n/** The pieces of a node as written, each ending with a line break (or empty): see `nodeParts`. */\nexport interface NodePieces {\n title: string;\n\n /** The attributes on the title line, with the space before them; empty when they don't fit there. */\n inline: string;\n\n /** The attributes that didn't fit on the line, as a block of their own. */\n attributes: string;\n\n media: string;\n note: string;\n}\n\nexport const nodePieces = (node: OrbitNode, listItem: boolean, writing: Writing, indent: string): NodePieces => {\n const { title, attributes } = titleLine(node, listItem, writing);\n let inline = inlineAttributes(attributes);\n let block = inline ? {} : attributes;\n\n if (title === '' && inline === '') {\n // A line without a title only reads back with an attribute on it: the id, at least.\n inline = ` <!-- orbit id: ${inlineValue(node.id) ?? JSON.stringify(node.id)} -->`;\n block = Object.fromEntries(Object.entries(attributes).filter(([key]) => key !== 'id'));\n }\n\n return {\n title,\n inline,\n attributes: attributeBlock(block, indent),\n media: indentLines(renderMedia(node).trimEnd(), indent),\n note: noteLines(node, indent),\n };\n};\n\n/**\n * A node's title as written: a checkbox for a list item's status, its\n * icon, its text, its link around them and its tags as hashtags, with the\n * attributes those don't carry.\n */\n/** A link markdown can hold in a title, `[text](link)`: no spaces, parentheses, quotes, angle brackets or backslashes. */\nconst isTitleLink = (link: string): boolean => {\n return /^[^\\s()<>\"'\\\\]+$/.test(link);\n};\n\nexport const titleLine = (node: OrbitNode, listItem: boolean, writing: Writing): { title: string; attributes: Record<string, unknown> } => {\n const attributes = collectAttrs(node, writing.explicitIds);\n let title = escapeTitle(node.text);\n const linked = node.link !== undefined && isTitleLink(node.link);\n\n if (linked && title === node.text) {\n // Inside the link's brackets, brackets of the text's own would end it.\n title = title.replace(/[[\\]]/g, '\\\\$&');\n }\n\n if (node.icon && isTitleIcon(node.icon)) {\n title = `${node.icon} ${title}`;\n }\n\n if (linked) {\n title = `[${title}](${node.link})`;\n }\n\n const checkbox = listItem && node.status ? CHECKBOXES[node.status] : undefined;\n\n if (checkbox) {\n title = `${checkbox} ${title}`;\n delete attributes.status;\n }\n\n if (node.tags?.length && node.tags.every(isHashtag)) {\n title += node.tags.map((tag) => ` #${tag}`).join('');\n delete attributes.tags;\n }\n\n return { title, attributes };\n};\n\n/** Whether a tag reads back as a hashtag at the end of a title. */\nconst isHashtag = (tag: string): boolean => {\n return /^[\\p{L}\\p{N}_][\\p{L}\\p{N}_/-]*$/u.test(tag) && /\\p{L}/u.test(tag);\n};\n\n/** The longest comment of more than `INLINE_ENTRIES` attributes that still goes on the node's line. */\nconst INLINE_LENGTH = 80;\n/** Up to this many attributes go on the node's line however long their values are, within `inlineValue`'s limit. */\nconst INLINE_ENTRIES = 3;\n\n/**\n * Attributes on the node's own line, `<!-- orbit status: done, priority: 2 -->`,\n * when they are short, plain values: up to three of them, or more while the\n * comment stays short, as a goal's numbers are (`type: goal, target: 5,\n * current: 2, unit: apples`). Keys that wouldn't survive the comma-separated\n * form (with a quote, a comma, a colon or a space of their own) go to the\n * block form instead.\n */\nexport const inlineAttributes = (attributes: Record<string, unknown>): string => {\n const entries = Object.entries(attributes);\n\n if (entries.length === 0 || !entries.every(([key, value]) => INLINE_KEY.test(key) && inlineValue(value) !== null)) {\n return '';\n }\n\n const comment = ` <!-- orbit ${entries.map(([key, value]) => `${key}: ${inlineValue(value)}`).join(', ')} -->`;\n return entries.length <= INLINE_ENTRIES || comment.length <= INLINE_LENGTH ? comment : '';\n};\n\n/** A key the comma-separated inline form reads back: what its pair pattern accepts. */\nconst INLINE_KEY = /^[A-Za-z][\\w-]*$/;\n\nexport const inlineValue = (value: unknown): string | null => {\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n\n if (typeof value !== 'string' || value.length > 60 || /[\\r\\n]|--/.test(value)) {\n return null;\n }\n\n // Quoted when the parser wouldn't hand it back plain, when it holds a\n // character the inline form itself reads (a comma splits attributes, a\n // quote toggles them, a bracket or brace nests so the comma after it\n // doesn't split, \":\" and \"#\" are syntax anywhere they appear), or when it\n // starts like a number (`2026-11-01` reads as text, but plain it would look\n // like one).\n return plainScalarReadsBack(value) && !/[\"',:#[\\]{}]/.test(value) && !/^-?\\d/.test(value) ? value : JSON.stringify(value);\n};\n\n/** What follows a node's line, indented under a list item: attributes that didn't fit on the line, media, then the note. */\nexport const body = (node: OrbitNode, blockAttributes: Record<string, unknown>, indent: string): string => {\n return attributeBlock(blockAttributes, indent) + indentLines(renderMedia(node).trimEnd(), indent) + noteLines(node, indent);\n};\n\n/** Attributes as a `<!-- orbit … -->` block of their own, indented by `indent`; nothing when there are none. */\nexport const attributeBlock = (attributes: Record<string, unknown>, indent: string): string => {\n return Object.keys(attributes).length > 0 ? indentLines(`<!-- orbit\\n${commentYaml(attributes)}\\n-->`, indent) : '';\n};\n\n/** A node's note as written under it, indented by `indent`. */\nexport const noteLines = (node: OrbitNode, indent: string): string => {\n return node.note ? indentLines(noteText(node.note, indent !== ''), indent) : '';\n};\n\n/**\n * A note as paragraphs when they read back as the same note, otherwise\n * quoted: quoted lines never turn into nodes, so a note can hold lines that\n * look like headings, lists or media.\n */\nexport const noteText = (note: string, listItem: boolean): string => {\n return plainNoteReadsBack(note, listItem) ? note : note.split('\\n').map((line) => (line === '' ? '>' : `> ${line}`)).join('\\n');\n};\n\n/**\n * Whether a note written as plain paragraphs reads back as the same note,\n * and leaves what follows it alone: a node after it must still be a node\n * (an unclosed code fence, say, would swallow it).\n */\nconst plainNoteReadsBack = (note: string, listItem: boolean): boolean => {\n // Indentation inside a list item is measured against its other lines: quoted, it stays exact.\n if (/^[ \\t]/m.test(note)) {\n return false;\n }\n\n const source = listItem\n ? `# Map\\n\\n## Branch\\n- Node\\n${indentLines(note, ' ')} - Next\\n- After\\n`\n : `# Map\\n\\n## Node\\n${note}\\n- Next\\n\\n## After\\n`;\n const document = parseOrbitMarkdown(source);\n const branches = document.root.children;\n const node = listItem ? branches[0]?.children[0] : branches[0];\n const after = listItem ? branches[0]?.children[1] : branches[1];\n\n if (!node || node.note !== note || node.children.length !== 1 || node.children[0].text !== 'Next' || after?.text !== 'After') {\n return false;\n }\n\n // Nothing in the note may read as the node's own attributes or media.\n const read = new Set(['id', 'text', 'level', 'children', 'source', 'note']);\n return Object.entries(node).every(([key, value]) => read.has(key) || value === undefined || (key === 'noteFormat' && value === 'markdown'));\n};\n\nexport const indentLines = (text: string, indent: string): string => {\n if (text === '') {\n return '';\n }\n\n return `${text.split('\\n').map((line) => (line === '' ? '' : `${indent}${line}`)).join('\\n')}\\n`;\n};\n\n/** Characters a title reads as markup: emphasis, code, links, checkboxes, hashtags. */\nconst TITLE_MARKUP = /[\\\\`*_~[\\]#<]/g;\n\n/**\n * A node's text as a heading or list item title: as is when it reads back\n * unchanged, otherwise with its markup characters escaped.\n */\nexport const escapeTitle = (text: string): string => {\n // A comment would be read as attributes, and a closing `#` run dropped from a heading.\n const misread = /<!--/.test(text) || /\\s#+$/.test(text) || !readsBack(text);\n return misread ? text.replace(TITLE_MARKUP, '\\\\$&') : text;\n};\n\nconst readsBack = (text: string): boolean => {\n const parts = parseTitle(text);\n return parts.text === text && parts.icon === undefined && parts.link === undefined && parts.tags === undefined && parts.status === undefined;\n};\n\n/**\n * A node's media as markdown lines, each followed (when needed) by an\n * attribute comment carrying what the line form cannot express: an explicit\n * `contentType` when auto-detection would misclassify, and the caption.\n */\n/** Media a markdown line can hold: plain addresses, and alt text without brackets. Others go in the attributes. */\nconst fitsOnALine = (media: { src: string; alt?: string; thumbnail?: string; provider?: string }): boolean => {\n // A media line reads its provider back from the address: one set differently would be rewritten.\n const providerKept = media.provider === undefined || media.provider === (detectVideoProvider(media.src) ?? 'native');\n return providerKept && isTitleLink(media.src) && (media.thumbnail === undefined || isTitleLink(media.thumbnail)) && !/[[\\]\\n]/.test(media.alt ?? '')\n && mediaExtras(media) === undefined;\n};\n\n/** A media value as an attribute: its defined fields, and a video's provider only when its address doesn't say it. */\nconst mediaAttribute = (media: { src: string; alt?: string; caption?: string; thumbnail?: string; provider?: string }): Record<string, unknown> => {\n // Fields Orbit doesn't read go first, as written; Orbit's own follow.\n const value: Record<string, unknown> = { src: media.src, ...mediaExtras(media) };\n\n for (const key of ['alt', 'thumbnail', 'caption'] as const) {\n if (media[key] !== undefined) {\n value[key] = media[key];\n }\n }\n\n if (media.provider !== undefined && media.provider !== (detectVideoProvider(media.src) ?? 'native')) {\n value.provider = media.provider;\n }\n\n return value;\n};\n\nexport const renderMedia = (node: OrbitNode): string => {\n let out = '';\n\n if (node.image && fitsOnALine(node.image)) {\n out += `\\n`;\n out += mediaMarker(undefined, node.image.caption);\n }\n\n if (node.video && fitsOnALine(node.video)) {\n const v = node.video;\n const detected = detectVideoProvider(v.src);\n out += v.thumbnail ? `[](${v.src})\\n` : `[video](${v.src})\\n`;\n out += mediaMarker(detected === null ? 'video' : undefined, v.caption);\n }\n\n if (node.embed && fitsOnALine(node.embed)) {\n out += `[embed](${node.embed.src})\\n`;\n out += mediaMarker('embed', node.embed.caption);\n }\n\n return out;\n};\n\nconst mediaMarker = (contentType: 'video' | 'embed' | undefined, caption: string | undefined): string => {\n const fields: Record<string, unknown> = {};\n\n if (contentType) {\n fields.contentType = contentType;\n }\n\n if (caption !== undefined) {\n fields.caption = caption;\n }\n\n if (Object.keys(fields).length === 0) {\n return '';\n }\n\n const yaml = commentYaml(fields);\n return yaml.includes('\\n') ? `<!-- orbit\\n${yaml}\\n-->\\n` : `<!-- orbit ${yaml} -->\\n`;\n};\n\n/**\n * YAML to write inside an HTML comment. A \"-->\" in a value would end the\n * comment early, so its \">\" is written as an escape; strings holding one are\n * always double-quoted, where the escape reads back as \">\".\n */\nexport const commentYaml = (value: Record<string, unknown>): string => {\n return emitYaml(value as unknown as YamlValue).trimEnd().replace(/--(!?)>/g, '--$1\\\\u003e');\n};\n\n/** Attributes carried in `<!-- orbit ... -->` comments: the ones a node's title and lines don't show. */\nexport const collectAttrs = (node: OrbitNode, explicitIds: ReadonlySet<OrbitNode>): Record<string, unknown> => {\n const r: Record<string, unknown> = {};\n\n if (node.icon && !isTitleIcon(node.icon)) {\n r.icon = node.icon;\n }\n\n if (node.color) {\n r.color = node.color;\n }\n\n if (node.status) {\n r.status = node.status;\n }\n\n if (node.priority !== undefined) {\n r.priority = node.priority;\n }\n\n if (node.tags) {\n r.tags = node.tags;\n }\n\n if (node.collapsed !== undefined) {\n r.collapsed = node.collapsed;\n }\n\n if (node.type) {\n r.type = node.typeVersion === undefined ? node.type : `${node.type}@${node.typeVersion}`;\n }\n\n if (node.link && !isTitleLink(node.link)) {\n r.link = node.link;\n }\n\n for (const key of ['image', 'video', 'embed'] as const) {\n const media = node[key];\n\n if (media && !fitsOnALine(media)) {\n r[key] = mediaAttribute(media);\n }\n }\n\n if (node.noteFormat && node.noteFormat !== 'markdown' && node.note) {\n r.noteFormat = node.noteFormat;\n }\n\n if (explicitIds.has(node)) {\n r.id = node.id;\n }\n\n if (node.attrs) {\n for (const [k, v] of Object.entries(node.attrs)) {\n // A value Orbit couldn't read for one of its own attributes is written back, unless one was set since.\n if (!Object.prototype.hasOwnProperty.call(r, k)) {\n assignKey(r, k, v);\n }\n }\n }\n\n return r;\n};\n",
|
|
23
|
+
"/**\n * How Orbit writes a map as markdown: its own form, the way people write\n * maps. `serializeOrbitMarkdown` writes a whole map this way, and saving an\n * edited map writes its changed ideas this way (see source-patch.ts).\n */\n\nimport type { OrbitDocument, OrbitNode } from './types.js';\nimport { emitYaml, assignKey, plainScalarReadsBack, type YamlValue } from './yaml-mini.js';\nimport { nodesWithExplicitIds } from './utils.js';\nimport { detectVideoProvider } from './media.js';\nimport { isTitleIcon, parseOrbitMarkdown, parseTitle } from './parser-markdown.js';\nimport { mediaExtras } from './node-attributes.js';\n\n/** A whole map in Orbit's own form. */\nexport const writeMarkdown = (doc: OrbitDocument): string => {\n let out = '';\n const fmKeys = collectFrontmatter(doc);\n\n if (Object.keys(fmKeys).length > 0) {\n out += '---\\n' + emitYaml(fmKeys as unknown as YamlValue) + '---\\n\\n';\n }\n\n out += emitHeading(doc.root, 1, { explicitIds: nodesWithExplicitIds(doc.root) });\n return out;\n};\n\nexport const collectFrontmatter = (doc: Pick<OrbitDocument, 'options' | 'extra'>): Record<string, unknown> => {\n const o = doc.options;\n const r: Record<string, unknown> = {};\n\n if (o.title) {\n r.title = o.title;\n }\n\n if (o.theme) {\n r.theme = o.theme;\n }\n\n if (o.viewMode) {\n r.view = o.viewMode;\n }\n\n if (o.showRings !== undefined) {\n r.showRings = o.showRings;\n }\n\n if (o.interactive !== undefined) {\n r.interactive = o.interactive;\n }\n\n if (o.orbitAnimation !== undefined) {\n r.animation = o.orbitAnimation;\n }\n\n if (o.orbitSpeed !== undefined) {\n r.speed = o.orbitSpeed;\n }\n\n if (o.palette) {\n r.palette = o.palette;\n }\n\n if (o.height !== undefined) {\n r.height = o.height;\n }\n\n if (o.maxDepth !== undefined) {\n r.maxDepth = o.maxDepth;\n }\n\n if (o.className) {\n r.className = o.className;\n }\n\n if (o.baseUrl) {\n r.baseUrl = o.baseUrl;\n }\n\n if (o.schemaVersion !== undefined) {\n r.schemaVersion = o.schemaVersion;\n }\n\n // Keys Orbit doesn't read, after its own: as they were written.\n for (const [key, value] of Object.entries(doc.extra ?? {})) {\n if (!Object.prototype.hasOwnProperty.call(r, key)) {\n assignKey(r, key, value);\n }\n }\n\n return r;\n};\n\n/**\n * The root and its children are headings; everything under them is a\n * list, the way people write maps. Below two levels, headings would only\n * make a map harder to read.\n */\nexport const HEADING_LEVELS = 2;\n\n/** The statuses a list item writes as a checkbox. */\nexport const CHECKBOXES: Record<string, string> = { todo: '[ ]', done: '[x]', active: '[/]' };\n\n/** What writing a node needs besides the node: which ids to write. */\nexport interface Writing {\n /** The nodes whose ids the parsers wouldn't make from their text, so they are written. */\n explicitIds: ReadonlySet<OrbitNode>;\n}\n\nexport const emitHeading = (node: OrbitNode, level: number, writing: Writing): string => {\n const parts = nodeParts(node, false, writing, '');\n const out = `${'#'.repeat(level)} ${parts.line}\\n${parts.body}`;\n\n if (node.children.length === 0) {\n return out;\n }\n\n if (level < HEADING_LEVELS) {\n return out + node.children.map((child) => `\\n${emitHeading(child, level + 1, writing)}`).join('');\n }\n\n return out + emitList(node.children, '', writing);\n};\n\nexport const emitList = (children: OrbitNode[], indent: string, writing: Writing): string => {\n let out = '';\n\n for (const child of children) {\n const parts = nodeParts(child, true, writing, `${indent} `);\n out += `${indent}- ${parts.line}\\n${parts.body}`;\n out += emitList(child.children, `${indent} `, writing);\n }\n\n return out;\n};\n\n/**\n * A node as written: its line after the heading's `#`s or the item's\n * marker (title, then the attributes that fit on it), and what follows the\n * line, indented by `indent`.\n */\nexport const nodeParts = (node: OrbitNode, listItem: boolean, writing: Writing, indent: string): { line: string; title: string; inline: string; body: string } => {\n const pieces = nodePieces(node, listItem, writing, indent);\n return { line: `${pieces.title}${pieces.inline}`.trimStart(), title: pieces.title, inline: pieces.inline, body: pieces.attributes + pieces.media + pieces.note };\n};\n\n/** The pieces of a node as written, each ending with a line break (or empty): see `nodeParts`. */\nexport interface NodePieces {\n title: string;\n\n /** The attributes on the title line, with the space before them; empty when they don't fit there. */\n inline: string;\n\n /** The attributes that didn't fit on the line, as a block of their own. */\n attributes: string;\n\n media: string;\n note: string;\n}\n\nexport const nodePieces = (node: OrbitNode, listItem: boolean, writing: Writing, indent: string): NodePieces => {\n const { title, attributes } = titleLine(node, listItem, writing);\n let inline = inlineAttributes(attributes);\n let block = inline ? {} : attributes;\n\n if (title === '' && inline === '') {\n // A line without a title only reads back with an attribute on it: the id, at least.\n inline = ` <!-- orbit id: ${inlineValue(node.id) ?? JSON.stringify(node.id)} -->`;\n block = Object.fromEntries(Object.entries(attributes).filter(([key]) => key !== 'id'));\n }\n\n return {\n title,\n inline,\n attributes: attributeBlock(block, indent),\n media: indentLines(renderMedia(node).trimEnd(), indent),\n note: noteLines(node, indent),\n };\n};\n\n/**\n * A node's title as written: a checkbox for a list item's status, its\n * icon, its text, its link around them and its tags as hashtags, with the\n * attributes those don't carry.\n */\n/** A link markdown can hold in a title, `[text](link)`: no spaces, parentheses, quotes, angle brackets or backslashes. */\nconst isTitleLink = (link: string): boolean => {\n return /^[^\\s()<>\"'\\\\]+$/.test(link);\n};\n\nexport const titleLine = (node: OrbitNode, listItem: boolean, writing: Writing): { title: string; attributes: Record<string, unknown> } => {\n const attributes = collectAttrs(node, writing.explicitIds);\n let title = escapeTitle(node.text);\n const linked = node.link !== undefined && isTitleLink(node.link);\n\n if (linked && title === node.text) {\n // Inside the link's brackets, brackets of the text's own would end it.\n title = title.replace(/[[\\]]/g, '\\\\$&');\n }\n\n if (node.icon && isTitleIcon(node.icon)) {\n title = `${node.icon} ${title}`;\n }\n\n if (linked) {\n title = `[${title}](${node.link})`;\n }\n\n const checkbox = listItem && node.status ? CHECKBOXES[node.status] : undefined;\n\n if (checkbox) {\n title = `${checkbox} ${title}`;\n delete attributes.status;\n }\n\n if (node.tags?.length && node.tags.every(isHashtag)) {\n title += node.tags.map((tag) => ` #${tag}`).join('');\n delete attributes.tags;\n }\n\n return { title, attributes };\n};\n\n/** Whether a tag reads back as a hashtag at the end of a title. */\nconst isHashtag = (tag: string): boolean => {\n return /^[\\p{L}\\p{N}_][\\p{L}\\p{N}_/-]*$/u.test(tag) && /\\p{L}/u.test(tag);\n};\n\n/** The longest comment of more than `INLINE_ENTRIES` attributes that still goes on the node's line. */\nconst INLINE_LENGTH = 80;\n/** Up to this many attributes go on the node's line however long their values are, within `inlineValue`'s limit. */\nconst INLINE_ENTRIES = 3;\n\n/**\n * Attributes on the node's own line, `<!-- orbit status: done, priority: 2 -->`,\n * when they are short, plain values: up to three of them, or more while the\n * comment stays short, as a goal's numbers are (`type: goal, target: 5,\n * current: 2, unit: apples`). Keys that wouldn't survive the comma-separated\n * form (with a quote, a comma, a colon or a space of their own) go to the\n * block form instead.\n */\nexport const inlineAttributes = (attributes: Record<string, unknown>): string => {\n const entries = Object.entries(attributes);\n\n if (entries.length === 0 || !entries.every(([key, value]) => INLINE_KEY.test(key) && inlineValue(value) !== null)) {\n return '';\n }\n\n const comment = ` <!-- orbit ${entries.map(([key, value]) => `${key}: ${inlineValue(value)}`).join(', ')} -->`;\n return entries.length <= INLINE_ENTRIES || comment.length <= INLINE_LENGTH ? comment : '';\n};\n\n/** A key the comma-separated inline form reads back: what its pair pattern accepts. */\nconst INLINE_KEY = /^[A-Za-z][\\w-]*$/;\n\nexport const inlineValue = (value: unknown): string | null => {\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n\n if (typeof value !== 'string' || value.length > 60 || /[\\r\\n]|--/.test(value)) {\n return null;\n }\n\n // Quoted when the parser wouldn't hand it back plain, when it holds a\n // character the inline form itself reads (a comma splits attributes, a\n // quote toggles them, a bracket or brace nests so the comma after it\n // doesn't split, \":\" and \"#\" are syntax anywhere they appear), or when it\n // starts like a number (`2026-11-01` reads as text, but plain it would look\n // like one).\n return plainScalarReadsBack(value) && !/[\"',:#[\\]{}]/.test(value) && !/^-?\\d/.test(value) ? value : JSON.stringify(value);\n};\n\n/** What follows a node's line, indented under a list item: attributes that didn't fit on the line, media, then the note. */\nexport const body = (node: OrbitNode, blockAttributes: Record<string, unknown>, indent: string): string => {\n return attributeBlock(blockAttributes, indent) + indentLines(renderMedia(node).trimEnd(), indent) + noteLines(node, indent);\n};\n\n/** Attributes as a `<!-- orbit … -->` block of their own, indented by `indent`; nothing when there are none. */\nexport const attributeBlock = (attributes: Record<string, unknown>, indent: string): string => {\n return Object.keys(attributes).length > 0 ? indentLines(`<!-- orbit\\n${commentYaml(attributes)}\\n-->`, indent) : '';\n};\n\n/** A node's note as written under it, indented by `indent`. */\nexport const noteLines = (node: OrbitNode, indent: string): string => {\n return node.note ? indentLines(noteText(node.note, indent !== ''), indent) : '';\n};\n\n/**\n * A note as paragraphs when they read back as the same note, otherwise\n * quoted: quoted lines never turn into nodes, so a note can hold lines that\n * look like headings, lists or media.\n */\nexport const noteText = (note: string, listItem: boolean): string => {\n return plainNoteReadsBack(note, listItem) ? note : note.split('\\n').map((line) => (line === '' ? '>' : `> ${line}`)).join('\\n');\n};\n\n/**\n * Whether a note written as plain paragraphs reads back as the same note,\n * and leaves what follows it alone: a node after it must still be a node\n * (an unclosed code fence, say, would swallow it).\n */\nconst plainNoteReadsBack = (note: string, listItem: boolean): boolean => {\n // Indentation inside a list item is measured against its other lines: quoted, it stays exact.\n if (/^[ \\t]/m.test(note)) {\n return false;\n }\n\n const source = listItem\n ? `# Map\\n\\n## Branch\\n- Node\\n${indentLines(note, ' ')} - Next\\n- After\\n`\n : `# Map\\n\\n## Node\\n${note}\\n- Next\\n\\n## After\\n`;\n const document = parseOrbitMarkdown(source);\n const branches = document.root.children;\n const node = listItem ? branches[0]?.children[0] : branches[0];\n const after = listItem ? branches[0]?.children[1] : branches[1];\n\n if (!node || node.note !== note || node.children.length !== 1 || node.children[0].text !== 'Next' || after?.text !== 'After') {\n return false;\n }\n\n // Nothing in the note may read as the node's own attributes or media.\n const read = new Set(['id', 'text', 'level', 'children', 'source', 'note']);\n return Object.entries(node).every(([key, value]) => read.has(key) || value === undefined || (key === 'noteFormat' && value === 'markdown'));\n};\n\nexport const indentLines = (text: string, indent: string): string => {\n if (text === '') {\n return '';\n }\n\n return `${text.split('\\n').map((line) => (line === '' ? '' : `${indent}${line}`)).join('\\n')}\\n`;\n};\n\n/** Characters a title reads as markup: emphasis, code, links, checkboxes, hashtags. */\nconst TITLE_MARKUP = /[\\\\`*_~[\\]#<]/g;\n\n/**\n * A node's text as a heading or list item title: as is when it reads back\n * unchanged, otherwise with its markup characters escaped.\n */\nexport const escapeTitle = (text: string): string => {\n // A comment would be read as attributes, and a closing `#` run dropped from a heading.\n const misread = /<!--/.test(text) || /\\s#+$/.test(text) || !readsBack(text);\n return misread ? text.replace(TITLE_MARKUP, '\\\\$&') : text;\n};\n\nconst readsBack = (text: string): boolean => {\n const parts = parseTitle(text);\n return parts.text === text && parts.icon === undefined && parts.link === undefined && parts.tags === undefined && parts.status === undefined;\n};\n\n/**\n * A node's media as markdown lines, each followed (when needed) by an\n * attribute comment carrying what the line form cannot express: an explicit\n * `contentType` when auto-detection would misclassify, and the caption.\n */\n/** Media a markdown line can hold: plain addresses, and alt text without brackets. Others go in the attributes. */\nconst fitsOnALine = (media: { src: string; alt?: string; thumbnail?: string; provider?: string }): boolean => {\n // A media line reads its provider back from the address: one set differently would be rewritten.\n const providerKept = media.provider === undefined || media.provider === (detectVideoProvider(media.src) ?? 'native');\n return providerKept && isTitleLink(media.src) && (media.thumbnail === undefined || isTitleLink(media.thumbnail)) && !/[[\\]\\n]/.test(media.alt ?? '')\n && mediaExtras(media) === undefined;\n};\n\n/** A media value as an attribute: its defined fields, and a video's provider only when its address doesn't say it. */\nconst mediaAttribute = (media: { src: string; alt?: string; caption?: string; thumbnail?: string; provider?: string }): Record<string, unknown> => {\n // Fields Orbit doesn't read go first, as written; Orbit's own follow.\n const value: Record<string, unknown> = { src: media.src, ...mediaExtras(media) };\n\n for (const key of ['alt', 'thumbnail', 'caption'] as const) {\n if (media[key] !== undefined) {\n value[key] = media[key];\n }\n }\n\n if (media.provider !== undefined && media.provider !== (detectVideoProvider(media.src) ?? 'native')) {\n value.provider = media.provider;\n }\n\n return value;\n};\n\nexport const renderMedia = (node: OrbitNode): string => {\n let out = '';\n\n if (node.image && fitsOnALine(node.image)) {\n out += `\\n`;\n out += mediaMarker(undefined, node.image.caption);\n }\n\n if (node.video && fitsOnALine(node.video)) {\n const v = node.video;\n const detected = detectVideoProvider(v.src);\n out += v.thumbnail ? `[](${v.src})\\n` : `[video](${v.src})\\n`;\n out += mediaMarker(detected === null ? 'video' : undefined, v.caption);\n }\n\n if (node.embed && fitsOnALine(node.embed)) {\n out += `[embed](${node.embed.src})\\n`;\n out += mediaMarker('embed', node.embed.caption);\n }\n\n return out;\n};\n\nconst mediaMarker = (contentType: 'video' | 'embed' | undefined, caption: string | undefined): string => {\n const fields: Record<string, unknown> = {};\n\n if (contentType) {\n fields.contentType = contentType;\n }\n\n if (caption !== undefined) {\n fields.caption = caption;\n }\n\n if (Object.keys(fields).length === 0) {\n return '';\n }\n\n const yaml = commentYaml(fields);\n return yaml.includes('\\n') ? `<!-- orbit\\n${yaml}\\n-->\\n` : `<!-- orbit ${yaml} -->\\n`;\n};\n\n/**\n * YAML to write inside an HTML comment. A \"-->\" in a value would end the\n * comment early, so its \">\" is written as an escape; strings holding one are\n * always double-quoted, where the escape reads back as \">\".\n */\nexport const commentYaml = (value: Record<string, unknown>): string => {\n return emitYaml(value as unknown as YamlValue).trimEnd().replace(/--(!?)>/g, '--$1\\\\u003e');\n};\n\n/** Attributes carried in `<!-- orbit ... -->` comments: the ones a node's title and lines don't show. */\nexport const collectAttrs = (node: OrbitNode, explicitIds: ReadonlySet<OrbitNode>): Record<string, unknown> => {\n const r: Record<string, unknown> = {};\n\n if (node.icon && !isTitleIcon(node.icon)) {\n r.icon = node.icon;\n }\n\n if (node.color) {\n r.color = node.color;\n }\n\n if (node.paletteColor !== undefined) {\n r.paletteColor = node.paletteColor;\n }\n\n if (node.status) {\n r.status = node.status;\n }\n\n if (node.priority !== undefined) {\n r.priority = node.priority;\n }\n\n if (node.tags) {\n r.tags = node.tags;\n }\n\n if (node.collapsed !== undefined) {\n r.collapsed = node.collapsed;\n }\n\n if (node.type) {\n r.type = node.typeVersion === undefined ? node.type : `${node.type}@${node.typeVersion}`;\n }\n\n if (node.link && !isTitleLink(node.link)) {\n r.link = node.link;\n }\n\n for (const key of ['image', 'video', 'embed'] as const) {\n const media = node[key];\n\n if (media && !fitsOnALine(media)) {\n r[key] = mediaAttribute(media);\n }\n }\n\n if (node.noteFormat && node.noteFormat !== 'markdown' && node.note) {\n r.noteFormat = node.noteFormat;\n }\n\n if (explicitIds.has(node)) {\n r.id = node.id;\n }\n\n if (node.attrs) {\n for (const [k, v] of Object.entries(node.attrs)) {\n // A value Orbit couldn't read for one of its own attributes is written back, unless one was set since.\n if (!Object.prototype.hasOwnProperty.call(r, k)) {\n assignKey(r, k, v);\n }\n }\n }\n\n return r;\n};\n",
|
|
23
24
|
"/**\n * Saving an edited map without rewriting it. Every line an edit didn't\n * change is written back as it was, and only what changed is written again,\n * in place, in Orbit's own form: a renamed idea gets a new title, a moved\n * one takes its lines along. A map written by hand, or by another app,\n * keeps its formatting and everything Orbit doesn't read: other HTML\n * comments, rules, the frontmatter keys of other apps.\n *\n * The result is read back before it's used: when it doesn't read as the\n * edited map, saving falls back to rewriting the changed ideas whole, then\n * to Orbit's own form for the whole map.\n */\n\nimport type { OrbitDocument, OrbitDocumentOptions, OrbitNode } from './types.js';\nimport { nodeFields, type DocumentSource, type LineRole, type NodeFields, type NodeRecord, type NodeShape } from './document-source.js';\nimport { CHECKBOXES, collectFrontmatter, HEADING_LEVELS, nodePieces, renderMedia, titleLine, type NodePieces, type Writing } from './markdown-writing.js';\nimport { emitYaml, type YamlValue } from './yaml-mini.js';\nimport { nodesWithExplicitIds } from './utils.js';\nimport { parseOrbit } from './dispatch.js';\nimport { UNTITLED_ROOT_ID } from './parser-markdown.js';\n\n/** Where a node is written: as a heading of a level, a list item at a column, or as the made-up root. */\ntype Context =\n | { kind: 'heading'; level: number }\n | { kind: 'item'; indent: number; marker: string }\n | { kind: 'generated' };\n\n/** Lines of a node's own, in a row, with one role: after which of its children they come (-1: before them all). */\ninterface Run {\n from: number;\n to: number;\n role: LineRole;\n after: number;\n}\n\n/** What an edit changed in a node's own lines. */\ninterface Changes {\n title: boolean;\n attributes: boolean;\n media: boolean;\n note: boolean;\n}\n\n/** Thrown when the map can't be written by patching; saving falls back to the next way. */\nclass CannotPatch extends Error {}\n\n/**\n * The document as markdown, its source's lines kept wherever nothing\n * changed; null when that can't be done faithfully.\n */\nexport const patchMarkdown = (document: OrbitDocument, source: DocumentSource): string | null => {\n if (document.root !== source.root) {\n return null;\n }\n\n for (const coarse of [false, true]) {\n const patcher = new Patcher(document, source, coarse);\n let lines: string[];\n\n try {\n lines = patcher.write();\n } catch (error) {\n if (error instanceof CannotPatch) {\n continue;\n }\n\n throw error;\n }\n\n const text = encode(lines, source);\n\n // The made-up root's new name may be written as the title option. A document without extra keys of its own\n // keeps the ones its file has, so that's what the text should read back with.\n if (lines === source.lines || readsAs(text, { ...document, options: patcher.writtenOptions, extra: document.extra ?? source.extra })) {\n return text;\n }\n }\n\n return null;\n};\n\n/**\n * The patched text without checking that it reads back, or why it couldn't\n * be made: for tests and debugging.\n */\nexport const patchedText = (document: OrbitDocument, source: DocumentSource, coarse = false): string => {\n return encode(new Patcher(document, source, coarse).write(), source);\n};\n\n/**\n * Whether `text` reads back as the `expected` map: the same options and\n * keys, and the same tree, each node with the same id and the same\n * fields, as Orbit would write them.\n */\nconst readsAs = (text: string, expected: OrbitDocument): boolean => {\n let read: OrbitDocument;\n\n try {\n // A made-up root keeps its id in every language: read it back with the name it was given.\n read = parseOrbit(text, { untitled: expected.root.id === UNTITLED_ROOT_ID ? expected.root.text : undefined });\n } catch {\n return false;\n }\n\n if (JSON.stringify(collectFrontmatter(read)) !== JSON.stringify(collectFrontmatter(expected))) {\n return false;\n }\n\n const readIds = nodesWithExplicitIds(read.root);\n const expectedIds = nodesWithExplicitIds(expected.root);\n const same = (left: OrbitNode, right: OrbitNode): boolean =>\n left.id === right.id\n && JSON.stringify(describe(left, false, readIds.has(left))) === JSON.stringify(describe(right, false, expectedIds.has(right)))\n && left.children.length === right.children.length\n && left.children.every((child, index) => same(child, right.children[index]));\n return same(read.root, expected.root);\n};\n\n/** Lines written as the source was: its line endings, byte-order mark, indentation and wrapping. */\nconst encode = (lines: string[], source: DocumentSource): string => {\n const { encoding } = source;\n const indented = encoding.indentation ? lines.map((line) => (line.trim() === '' ? line : encoding.indentation + line)) : lines;\n const text = [...encoding.before, ...indented, ...encoding.after].join(encoding.lineEnding);\n return encoding.byteOrderMark ? `\\uFEFF${text}` : text;\n};\n\nclass Patcher {\n private readonly lines: string[];\n private readonly records: WeakMap<OrbitNode, NodeRecord>;\n private readonly writing: Writing;\n private readonly cleanness = new Map<OrbitNode, boolean>();\n private readonly document: OrbitDocument;\n private readonly source: DocumentSource;\n\n /** Rewrite changed ideas whole, instead of only their changed lines. */\n private readonly coarse: boolean;\n\n /** The node whose own lines are being written. */\n private current: OrbitNode | null = null;\n\n /** The options the frontmatter was written with. */\n writtenOptions: OrbitDocumentOptions = {};\n\n /** Whether the made-up root is written as a heading of its own. */\n private rootHeading = false;\n\n constructor(document: OrbitDocument, source: DocumentSource, coarse: boolean) {\n this.document = document;\n this.source = source;\n this.coarse = coarse;\n this.lines = source.lines;\n this.records = source.records;\n this.writing = { explicitIds: nodesWithExplicitIds(document.root) };\n }\n\n write(): string[] {\n const root = this.document.root;\n const record = this.record(root);\n this.rootHeading = record.shape.kind === 'generated' && this.becomesHeading(root, record);\n const options = this.options();\n this.writtenOptions = options;\n const optionsChanged = JSON.stringify(this.frontmatterKeys(options)) !== JSON.stringify(this.frontmatterKeys(this.source.options, this.source.extra));\n\n if (!optionsChanged && this.isClean(root)) {\n return this.lines;\n }\n\n const out = this.frontmatter(options);\n const body: string[] = [];\n const context: Context = this.rootHeading ? { kind: 'heading', level: 1 } : contextOf(record.shape);\n this.emit(root, context, body);\n\n // A frontmatter that went takes the blank line that kept it apart with it: the map starts at its first line.\n if (this.source.frontmatter && out.length === 0) {\n while (body.length > 0 && body[0].trim() === '') {\n body.shift();\n }\n }\n\n out.push(...body);\n\n // A file that ended with a line break still does.\n if (this.lines[this.lines.length - 1] === '' && out[out.length - 1] !== '') {\n out.push('');\n }\n\n return out;\n }\n\n /**\n * Whether the root Orbit made up gets a heading of its own: when it's\n * renamed, or its attributes or media change (a heading line is where they\n * go), or a map of only text gets its first idea. Not when its children are\n * top-level headings themselves: a heading above them would change their\n * levels, so a new name goes to the frontmatter's title instead.\n */\n private becomesHeading(root: OrbitNode, record: NodeRecord): boolean {\n if (record.children.some((child) => this.records.get(child)?.shape.kind === 'heading')) {\n return false;\n }\n\n if (record.children.length === 0 && root.children.length > 0) {\n return true;\n }\n\n const changes = this.changes(root, record, this.ownRuns(root, record));\n return changes.title || changes.attributes || changes.media;\n }\n\n /** The options to write: the document's, with the made-up root's new name as its title when it has no heading. */\n private options(): OrbitDocumentOptions {\n const options = { ...this.document.options };\n const root = this.document.root;\n const record = this.record(root);\n\n if (record.shape.kind === 'generated' && !this.rootHeading && root.text !== record.fields.text) {\n options.title = root.text;\n }\n\n return options;\n }\n\n private record(node: OrbitNode): NodeRecord {\n const record = this.records.get(node);\n\n if (!record) {\n throw new CannotPatch('A node without a record');\n }\n\n return record;\n }\n\n /** Whether a node and everything under it are as they were read. */\n private isClean(node: OrbitNode): boolean {\n let clean = this.cleanness.get(node);\n\n if (clean === undefined) {\n const record = this.records.get(node);\n clean = record !== undefined\n && this.ownUnchanged(node, record)\n && sameChildren(node.children, record.children)\n && node.children.every((child) => this.isClean(child));\n this.cleanness.set(node, clean);\n }\n\n return clean;\n }\n\n private ownUnchanged(node: OrbitNode, record: NodeRecord): boolean {\n return JSON.stringify(nodeFields(node)) === JSON.stringify(record.fields) && this.writing.explicitIds.has(node) === record.explicitId;\n }\n\n // Frontmatter\n\n /**\n * The frontmatter's keys and values for `options`, with the keys Orbit\n * doesn't read (`extra`, by default the document's): other apps' keys, and\n * keys an app keeps there itself, are saved when they change too. A\n * document without `extra` changes none of them: one built from a tree and\n * options alone would otherwise drop every key another app wrote, so only\n * an `extra` object, even an empty one, removes keys.\n */\n private frontmatterKeys(options: OrbitDocumentOptions, extra = this.document.extra ?? this.source.extra): Record<string, unknown> {\n return collectFrontmatter({ options, extra });\n }\n\n /** The frontmatter, with the keys whose values changed written again and the rest as they were. */\n private frontmatter(options: OrbitDocumentOptions): string[] {\n const fences = this.source.frontmatter;\n const before = this.frontmatterKeys(this.source.options, this.source.extra);\n const after = this.frontmatterKeys(options);\n const lines = fences ? this.lines.slice(0, fences.close + 1) : [];\n const keys = [...new Set([...Object.keys(before), ...Object.keys(after)])];\n const changed = keys.filter((key) => JSON.stringify(before[key]) !== JSON.stringify(after[key]));\n\n if (changed.length === 0) {\n return fences ? lines : this.lines.slice(0, this.bodyStart());\n }\n\n if (!fences) {\n const written = Object.fromEntries(Object.entries(after));\n return ['---', ...yamlLines(written), '---', '', ...this.lines.slice(0, this.bodyStart())];\n }\n\n const open = fences.open;\n let close = fences.close;\n\n for (const key of changed) {\n const range = keyRange(lines, key, open + 1, close);\n const replacement = after[key] === undefined ? [] : yamlLines({ [key]: after[key] });\n\n if (range) {\n lines.splice(range.from, range.to - range.from, ...replacement);\n close += replacement.length - (range.to - range.from);\n } else {\n lines.splice(close, 0, ...replacement);\n close += replacement.length;\n }\n }\n\n // A frontmatter left with nothing in it goes.\n if (lines.slice(open + 1, close).every((line) => line.trim() === '')) {\n lines.splice(open, close - open + 1);\n }\n\n return lines;\n }\n\n private bodyStart(): number {\n const fences = this.source.frontmatter;\n return fences ? fences.close + 1 : 0;\n }\n\n // Nodes\n\n /** Writes `node` and everything under it, as `context` asks, into `out`. */\n private emit(node: OrbitNode, context: Context, out: string[]): void {\n const record = this.records.get(node);\n\n if (!record) {\n this.generate(node, context, out);\n return;\n }\n\n if (this.isClean(node) && sameContext(record.shape, context) && record.contiguous) {\n // An underlined heading needs a blank line before it, or its text would join the paragraph above.\n if (record.shape.kind === 'heading' && record.shape.setext && this.lines[record.start]?.trim() !== '') {\n separate(out);\n }\n\n const lines = this.lines.slice(record.start, record.end);\n\n // An indented heading starts at the margin: with what's around it written again, a list item before it could take it.\n if (context.kind === 'heading' && record.titleLine !== null) {\n const index = record.titleLine - record.start;\n lines[index] = lines[index].replace(/^ {1,3}(?=#)/, '');\n }\n\n out.push(...lines);\n return;\n }\n\n const runs = this.ownRuns(node, record);\n const changes = this.changes(node, record, runs);\n this.current = node;\n const kindChanged = record.shape.kind !== context.kind;\n const pieces = nodePieces(node, context.kind === 'item', this.writing, ' '.repeat(contentColumn(record.shape, context)));\n const head = runs.filter((run) => run.after < 0);\n\n if (kindChanged && record.shape.kind !== 'generated') {\n this.rewriteOwn(record, context, pieces, runs, out);\n } else {\n this.patchOwn(record, context, pieces, head, changes, out);\n }\n\n this.emitChildren(node, record, context, runs, changes, out);\n }\n\n /** The lines a node owns, in runs of one role. */\n private ownRuns(node: OrbitNode, record: NodeRecord): Run[] {\n const starts = record.children.map((child) => this.record(child).start);\n const runs: Run[] = [];\n\n for (let line = record.start; line < record.end; line += 1) {\n if (this.source.owners[line] !== node) {\n continue;\n }\n\n const role = this.source.roles[line];\n let after = -1;\n\n while (after + 1 < starts.length && starts[after + 1] <= line) {\n after += 1;\n }\n\n const last = runs[runs.length - 1];\n\n if (last && last.to === line && last.role === role && last.after === after) {\n last.to = line + 1;\n } else {\n runs.push({ from: line, to: line + 1, role, after });\n }\n }\n\n return runs;\n }\n\n private changes(node: OrbitNode, record: NodeRecord, runs: Run[]): Changes {\n const listItem = record.shape.kind === 'item';\n const before = describe(asNode(record.fields), listItem, record.explicitId);\n const after = describe(node, listItem, this.writing.explicitIds.has(node));\n const changes: Changes = {\n title: before.title !== after.title,\n attributes: before.attributes !== after.attributes,\n media: before.media !== after.media,\n note: before.note !== after.note,\n };\n // A note written (partly) as a `note:` attribute is written again as text whenever either changes.\n const noteAttribute = /(^|[\\s,])note\\s*:/;\n const titleComment = record.titleLine === null ? '' : (INLINE_COMMENT.exec(this.lines[record.titleLine]) ?? [''])[0];\n\n if (runs.some((run) => run.role === 'attributes' && noteAttribute.test(this.text(run))) || noteAttribute.test(titleComment)) {\n if (changes.note || changes.attributes) {\n changes.note = true;\n changes.attributes = true;\n }\n }\n\n if (this.coarse && Object.values(changes).some(Boolean)) {\n return { title: true, attributes: true, media: true, note: true };\n }\n\n return changes;\n }\n\n private text(run: Run): string {\n return this.lines.slice(run.from, run.to).join('\\n');\n }\n\n /**\n * A node's own lines with what changed written again in place: a new\n * title on its line, new attributes after it, media and note where the old\n * ones were. Everything else, including what Orbit doesn't read, stays.\n */\n private patchOwn(record: NodeRecord, context: Context, pieces: NodePieces, head: Run[], changes: Changes, out: string[]): void {\n const shift = indentShift(record.shape, context);\n const own: string[] = [];\n let afterTitle = 0;\n let wroteAttributes = false;\n let wroteMedia = false;\n let wroteNote = false;\n const generated = record.shape.kind === 'generated';\n\n // The made-up root that becomes a heading: its line goes first.\n if (generated && context.kind === 'heading') {\n own.push(`${'#'.repeat(context.level)} ${`${pieces.title}${pieces.inline}`.trimStart()}`);\n afterTitle = own.length;\n\n if (pieces.attributes) {\n own.push(...splitLines(pieces.attributes));\n afterTitle = own.length;\n }\n\n wroteAttributes = true;\n }\n\n for (const run of head) {\n const lines = this.lines.slice(run.from, run.to);\n\n switch (run.role) {\n case 'title': {\n if (generated) {\n // A lead paragraph names the root. Once the root has a heading, or a new name in the frontmatter, it goes.\n if (context.kind !== 'heading' && !changes.title) {\n own.push(...lines);\n }\n\n afterTitle = own.length;\n break;\n }\n\n own.push(...this.patchTitle(lines, record, context, pieces, changes));\n afterTitle = own.length;\n\n if (changes.attributes && pieces.attributes) {\n own.push(...splitLines(pieces.attributes));\n afterTitle = own.length;\n }\n\n wroteAttributes = true;\n break;\n }\n case 'attributes':\n if (!changes.attributes) {\n own.push(...shiftLines(lines, shift));\n }\n\n break;\n case 'media':\n if (!changes.media) {\n own.push(...shiftLines(lines, shift));\n } else if (!wroteMedia) {\n own.push(...splitLines(pieces.media));\n wroteMedia = true;\n }\n\n break;\n case 'note':\n case 'end':\n if (!changes.note) {\n own.push(...shiftLines(lines, shift));\n } else if (!wroteNote) {\n own.push(...splitLines(pieces.note));\n wroteNote = true;\n }\n\n break;\n default:\n own.push(...shiftLines(lines, shift));\n }\n }\n\n // A generated root has no title line: its attributes go first, on lines of their own.\n if (changes.attributes && !wroteAttributes && pieces.attributes) {\n own.splice(afterTitle, 0, ...splitLines(pieces.attributes));\n afterTitle += splitLines(pieces.attributes).length;\n }\n\n if (changes.media && !wroteMedia && pieces.media) {\n own.splice(afterTitle, 0, ...splitLines(pieces.media));\n }\n\n if (changes.note && !wroteNote && pieces.note) {\n let end = own.length;\n\n while (end > afterTitle && own[end - 1].trim() === '') {\n end -= 1;\n }\n\n const note = splitLines(pieces.note);\n // Between a heading and its note, a blank line, as Orbit writes them.\n own.splice(end, 0, ...note);\n }\n\n // A heading the root just got, or an underlined one, needs a blank line before it; others are kept as written.\n const blankBefore = record.shape.kind !== 'heading' || (record.shape.setext && own[0] === this.lines[record.titleLine ?? -1]);\n\n if (context.kind === 'heading' && own.length > 0 && own[0].trim() !== '' && blankBefore) {\n separate(out);\n }\n\n out.push(...own);\n }\n\n /** A node that changed between heading and list item: its own lines written again, keeping what Orbit doesn't read. */\n private rewriteOwn(record: NodeRecord, context: Context, pieces: NodePieces, runs: Run[], out: string[]): void {\n if (context.kind === 'heading') {\n separate(out);\n out.push(`${'#'.repeat(context.level)} ${`${pieces.title}${pieces.inline}`.trimStart()}`);\n } else if (context.kind === 'item') {\n out.push(`${' '.repeat(context.indent)}${markerOf(record.shape, context)} ${`${pieces.title}${pieces.inline}`.trimStart()}`);\n } else {\n throw new CannotPatch('A node can only become the root by being it');\n }\n\n out.push(...splitLines(pieces.attributes + pieces.media + pieces.note));\n const column = contentColumn(record.shape, context);\n\n for (const run of runs) {\n if (run.role === 'foreign') {\n out.push(...this.lines.slice(run.from, run.to).map((line) => ' '.repeat(column) + line.trimStart()));\n }\n }\n }\n\n /** The title line, with its new title, attributes, level or indentation. */\n private patchTitle(lines: string[], record: NodeRecord, context: Context, pieces: NodePieces, changes: Changes): string[] {\n const shape = record.shape;\n const fresh = `${pieces.title}${pieces.inline}`.trimStart();\n\n if (shape.kind === 'heading' && context.kind === 'heading') {\n const match = ATX.exec(lines[0]);\n\n if (shape.setext || !match) {\n return !changes.title && !changes.attributes && shape.level === context.level ? lines : [`${'#'.repeat(context.level)} ${fresh}`];\n }\n\n // Written again, a heading starts at the margin: indented, a list item before it could take it.\n return [`${'#'.repeat(context.level)}${match[3]}${this.titleText(match[4], record, pieces, changes)}`];\n }\n\n if (shape.kind === 'item' && context.kind === 'item') {\n const match = ITEM.exec(lines[0]);\n\n if (!match) {\n return [`${' '.repeat(context.indent)}${shape.marker} ${fresh}`];\n }\n\n const indent = context.indent === shape.indent ? match[1] : ' '.repeat(context.indent);\n return [`${indent}${match[2]}${match[3]}${this.titleText(match[4], record, pieces, changes)}`];\n }\n\n throw new CannotPatch('A title line of another kind');\n }\n\n /** A title line's text after its marker: the title and the attributes on it, each kept unless it changed. */\n private titleText(text: string, record: NodeRecord, pieces: NodePieces, changes: Changes): string {\n const inline = INLINE_COMMENT.exec(text);\n let title = inline ? text.slice(0, inline.index) : text;\n const comment = changes.attributes ? pieces.inline : inline ? text.slice(inline.index) : '';\n\n // A heading's closing `#`s only close it at the end of its line: before a comment, they'd join its title.\n if (record.shape.kind === 'heading' && comment) {\n title = title.replace(/\\s+#+\\s*$/, '');\n }\n\n const hidden = changes.title ? TRAILING_COMMENTS.exec(title) : null;\n const bare = hidden ? title.slice(0, hidden.index) : title;\n const written = `${changes.title ? `${this.retitle(bare, record, pieces)}${hidden ? hidden[0].trimEnd() : ''}` : title}${comment}`;\n return written.trimStart();\n }\n\n /**\n * A changed title. When only a list item's checkbox changed (an idea\n * checked off, say), only the checkbox is written again, so the title\n * keeps its own markdown: bold, code, links.\n */\n private retitle(title: string, record: NodeRecord, pieces: NodePieces): string {\n if (record.shape.kind !== 'item' || this.coarse) {\n return pieces.title;\n }\n\n const node = this.current;\n const box = node?.status ? CHECKBOXES[node.status] : undefined;\n const before = titleLine(asNode({ ...record.fields, status: node?.status }), true, { explicitIds: new Set() }).title;\n\n if (!node || before !== pieces.title) {\n return pieces.title;\n }\n\n const written = CHECKBOX.exec(title);\n const rest = written ? title.slice(written[0].length) : title.trimStart();\n return box ? `${box} ${rest}` : rest;\n }\n\n /**\n * The children, each followed by what the node wrote right after it.\n * What came after the last child stays after all of them: the node's\n * closing text. Text after a heading belongs to that heading, so under a\n * heading (or at the top level) the node's own text goes before its first\n * child heading, and definitions at the end of the document stay at its end.\n */\n private emitChildren(node: OrbitNode, record: NodeRecord, context: Context, runs: Run[], changes: Changes, out: string[]): void {\n let previous: Context | null = null;\n let headings = false;\n const kinds = this.childKinds(node, context);\n const last = record.children.length - 1;\n const placed = new Set<number>();\n const originalIndex = new Map(record.children.map((child, index) => [child, index]));\n\n const flush = (): void => {\n for (let index = 0; index <= last; index += 1) {\n if (!placed.has(index)) {\n this.emitGap(record, index, runs, changes, context, out);\n placed.add(index);\n }\n }\n };\n\n node.children.forEach((child, position) => {\n const index = originalIndex.get(child) ?? -1;\n const childContext = this.childContext(child, record, context, previous, kinds[position], index !== -1);\n\n if (childContext.kind === 'heading' && !headings) {\n flush();\n headings = true;\n }\n\n this.emit(child, childContext, out);\n previous = childContext;\n\n if (index !== -1 && index !== last && !placed.has(index)) {\n this.emitGap(record, index, runs, changes, context, out);\n placed.add(index);\n }\n });\n\n // What came after children that moved away, or were deleted, is still the node's own.\n flush();\n\n for (const run of runs) {\n // The document's end stays at its end. Definitions there are the root's note: written\n // again with it when it changed, though the blank lines around them stay.\n const definitions = run.role === 'end' && this.lines.slice(run.from, run.to).some((line) => line.trim() !== '');\n\n if (run.role === 'end' && !(definitions && changes.note)) {\n out.push(...this.lines.slice(run.from, run.to));\n }\n }\n }\n\n private emitGap(record: NodeRecord, index: number, runs: Run[], changes: Changes, context: Context, out: string[]): void {\n const shift = indentShift(record.shape, context);\n\n for (const run of runs) {\n if (run.after !== index || run.role === 'end') {\n continue;\n }\n\n const dropped = (run.role === 'attributes' && changes.attributes) || (run.role === 'media' && changes.media) || (run.role === 'note' && changes.note);\n\n if (!dropped) {\n out.push(...shiftLines(this.lines.slice(run.from, run.to), shift));\n }\n }\n }\n\n /**\n * Under a heading, or at the top level, whether each child is written as\n * a list item or a heading. Items have to come first: after a heading,\n * they'd belong to it. Each child would rather stay as it was written (a\n * new one, like the sibling before it), so the split between items and\n * headings is where the fewest children change.\n */\n private childKinds(node: OrbitNode, context: Context): ('heading' | 'item')[] {\n // Markdown has six levels of headings: below the sixth, children are list items.\n if (context.kind === 'item' || (context.kind === 'heading' && context.level >= 6)) {\n return node.children.map(() => 'item');\n }\n\n const preferHeadings = context.kind === 'generated' || context.level < HEADING_LEVELS;\n\n const written = node.children.map((child) => {\n const shape = this.records.get(child)?.shape;\n return shape?.kind === 'heading' || shape?.kind === 'item' ? shape.kind : null;\n });\n\n // New children take after the sibling before them, or the one after them.\n const before: ('heading' | 'item' | null)[] = [];\n let seen: 'heading' | 'item' | null = null;\n\n for (const kind of written) {\n before.push(seen);\n seen = kind ?? seen;\n }\n\n const after: ('heading' | 'item' | null)[] = new Array(written.length).fill(null);\n seen = null;\n\n for (let index = written.length - 1; index >= 0; index -= 1) {\n after[index] = seen;\n seen = written[index] ?? seen;\n }\n\n const wanted = written.map((kind, index) => kind ?? before[index] ?? after[index] ?? (preferHeadings ? 'heading' : 'item'));\n // Changes for each split: headings before it become items, items after it become headings.\n const total = wanted.filter((kind) => kind === 'item').length;\n let split = preferHeadings ? 0 : wanted.length;\n let fewest = Number.POSITIVE_INFINITY;\n let headingsBefore = 0;\n let itemsBefore = 0;\n\n for (let candidate = 0; candidate <= wanted.length; candidate += 1) {\n const changes = headingsBefore + (total - itemsBefore);\n\n if (changes < fewest || (changes === fewest && !preferHeadings)) {\n fewest = changes;\n split = candidate;\n }\n\n if (candidate < wanted.length) {\n if (wanted[candidate] === 'heading') {\n headingsBefore += 1;\n } else {\n itemsBefore += 1;\n }\n }\n }\n\n return wanted.map((_kind, index) => (index < split ? 'item' : 'heading'));\n }\n\n /**\n * Where a child is written, as `kind` says (see `childKinds`): an item\n * keeps its marker; a heading keeps its level relative to its parent, so\n * a map that skips a level (`#`, then `###`) keeps skipping it.\n */\n private childContext(child: OrbitNode, record: NodeRecord, context: Context, previous: Context | null, kind: 'heading' | 'item', original: boolean): Context {\n const shape = this.records.get(child)?.shape;\n\n if (context.kind === 'item') {\n const column = contentColumn(record.shape, context);\n return { kind: 'item', indent: column, marker: shape?.kind === 'item' ? shape.marker : nextMarker(previous) };\n }\n\n if (kind === 'item') {\n return { kind: 'item', indent: 0, marker: shape?.kind === 'item' ? shape.marker : nextMarker(previous) };\n }\n\n const firstShape = record.children.length > 0 ? this.records.get(record.children[0])?.shape : undefined;\n const parentLevel = context.kind === 'heading' ? context.level : 0;\n const shift = context.kind === 'heading' && record.shape.kind === 'heading' ? context.level - record.shape.level : 0;\n const wanted = original && shape?.kind === 'heading'\n ? shape.level + shift\n : previous?.kind === 'heading'\n ? previous.level\n : firstShape?.kind === 'heading' ? firstShape.level + shift : parentLevel + 1;\n // No deeper than the heading before it, or it would read as that heading's child.\n const level = Math.max(parentLevel + 1, previous?.kind === 'heading' ? Math.min(wanted, previous.level) : wanted);\n\n if (level > 6) {\n throw new CannotPatch('Headings only go six levels deep');\n }\n\n return { kind: 'heading', level };\n }\n\n /** A node Orbit didn't read, with everything under it, in Orbit's own form. */\n private generate(node: OrbitNode, context: Context, out: string[]): void {\n if (context.kind === 'heading') {\n const pieces = nodePieces(node, false, this.writing, '');\n separate(out);\n out.push(`${'#'.repeat(context.level)} ${`${pieces.title}${pieces.inline}`.trimStart()}`, ...splitLines(pieces.attributes + pieces.media + pieces.note));\n let previous: Context | null = null;\n\n for (const child of node.children) {\n const childContext: Context = context.level < HEADING_LEVELS\n ? { kind: 'heading', level: context.level + 1 }\n : { kind: 'item', indent: 0, marker: nextMarker(previous) };\n this.generate(child, childContext, out);\n previous = childContext;\n }\n\n return;\n }\n\n if (context.kind === 'item') {\n const column = context.indent + context.marker.length + 1;\n const pieces = nodePieces(node, true, this.writing, ' '.repeat(column));\n out.push(`${' '.repeat(context.indent)}${context.marker} ${`${pieces.title}${pieces.inline}`.trimStart()}`, ...splitLines(pieces.attributes + pieces.media + pieces.note));\n let previous: Context | null = null;\n\n for (const child of node.children) {\n const childContext: Context = { kind: 'item', indent: column, marker: nextMarker(previous) };\n this.generate(child, childContext, out);\n previous = childContext;\n }\n\n return;\n }\n\n throw new CannotPatch('A new root');\n }\n}\n\nconst ATX = /^( {0,3})(#{1,6})([ \\t]+)(.*)$/;\nconst CHECKBOX = /^\\s*\\[( |x|X|\\/)\\]\\s+/;\nconst ITEM = /^([ \\t]*)([-*+]|\\d{1,9}[.)])([ \\t]+)(.*)$/;\nconst INLINE_COMMENT = /\\s*<!--\\s*orbit:?\\s[\\s\\S]*-->\\s*$/i;\n/** Other comments at the end of a title: hidden, and kept when the title changes. */\nconst TRAILING_COMMENTS = /(?:\\s*(?<!\\\\)<!--[\\s\\S]*?-->)+\\s*$/;\n\nconst contextOf = (shape: NodeShape): Context => {\n if (shape.kind === 'heading') {\n return { kind: 'heading', level: shape.level };\n }\n\n if (shape.kind === 'item') {\n return { kind: 'item', indent: shape.indent, marker: shape.marker };\n }\n\n return { kind: 'generated' };\n};\n\nconst sameContext = (shape: NodeShape, context: Context): boolean => {\n if (shape.kind === 'heading') {\n return context.kind === 'heading' && context.level === shape.level;\n }\n\n if (shape.kind === 'item') {\n return context.kind === 'item' && context.indent === shape.indent;\n }\n\n return context.kind === 'generated';\n};\n\nconst sameChildren = (current: OrbitNode[], original: OrbitNode[]): boolean => {\n return current.length === original.length && current.every((child, index) => child === original[index]);\n};\n\n/** Columns an item's lines move by in its new place. */\nconst indentShift = (shape: NodeShape, context: Context): number => {\n return shape.kind === 'item' && context.kind === 'item' ? context.indent - shape.indent : 0;\n};\n\n/** The column a node's own text starts at under it (0 for headings). */\nconst contentColumn = (shape: NodeShape, context: Context): number => {\n if (context.kind !== 'item') {\n return 0;\n }\n\n if (shape.kind === 'item') {\n return shape.content + context.indent - shape.indent;\n }\n\n return context.indent + context.marker.length + 1;\n};\n\nconst markerOf = (shape: NodeShape, context: Context): string => {\n if (shape.kind === 'item') {\n return shape.marker;\n }\n\n return context.kind === 'item' ? context.marker : '-';\n};\n\n/** The marker after a sibling's: the next number in a numbered list, the same bullet otherwise. */\nconst nextMarker = (previous: Context | null): string => {\n if (previous?.kind !== 'item') {\n return '-';\n }\n\n const numbered = /^(\\d+)([.)])$/.exec(previous.marker);\n return numbered ? `${Number(numbered[1]) + 1}${numbered[2]}` : previous.marker;\n};\n\n/** Moves lines right (or left, as far as their indentation goes) by `shift` columns. */\nconst shiftLines = (lines: string[], shift: number): string[] => {\n if (shift === 0) {\n return lines;\n }\n\n return lines.map((line) => {\n if (line.trim() === '') {\n return line;\n }\n\n const expanded = line.replace(/^[ \\t]+/, (indent) => expandTabs(indent));\n\n if (shift > 0) {\n return ' '.repeat(shift) + expanded;\n }\n\n const indent = /^ */.exec(expanded)![0].length;\n return expanded.slice(Math.min(indent, -shift));\n });\n};\n\nconst expandTabs = (indent: string): string => {\n let columns = 0;\n\n for (const character of indent) {\n columns = character === '\\t' ? columns + 4 - (columns % 4) : columns + 1;\n }\n\n return ' '.repeat(columns);\n};\n\nconst splitLines = (text: string): string[] => {\n if (text === '') {\n return [];\n }\n\n const lines = text.split('\\n');\n\n if (lines[lines.length - 1] === '') {\n lines.pop();\n }\n\n return lines;\n};\n\n/** A blank line before a heading, unless the line before is blank already. */\nconst separate = (out: string[]): void => {\n if (out.length > 0 && out[out.length - 1].trim() !== '') {\n out.push('');\n }\n};\n\n/** A node's own fields as a node, to write them as they were. */\nconst asNode = (fields: NodeFields): OrbitNode => {\n return { ...fields, level: 0, children: [] } as OrbitNode;\n};\n\n/** What Orbit would write for a node's title, attributes, media and note, to compare before and after an edit. */\nconst describe = (node: OrbitNode, listItem: boolean, explicitId: boolean): { title: string; attributes: string; media: string; note: string } => {\n const writing = { explicitIds: explicitId ? new Set([node]) : new Set<OrbitNode>() };\n const { title, attributes } = titleLine(node, listItem, writing);\n // The note as text, not as written: writing it decides whether to quote it, which reads it again (slow on big maps).\n return { title, attributes: JSON.stringify(attributes), media: renderMedia(node), note: node.note ?? '' };\n};\n\n/** A key's lines in a frontmatter: its own line and the lines indented under it (or a list right below it). */\nconst keyRange = (lines: string[], key: string, from: number, to: number): { from: number; to: number } | null => {\n // The key as it may be written: bare, or quoted (the emitter double-quotes keys that need it).\n const written = [key, JSON.stringify(key), `'${key.replace(/'/g, \"''\")}'`]\n .map((form) => form.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'));\n const pattern = new RegExp(`^(?:${written.join('|')})\\\\s*:`);\n\n for (let index = from; index < to; index += 1) {\n if (pattern.test(lines[index])) {\n let end = index + 1;\n\n while (end < to && (lines[end].trim() === '' || /^\\s/.test(lines[end]) || /^-(\\s|$)/.test(lines[end]))) {\n end += 1;\n }\n\n // Blank lines after the value belong to what follows.\n while (end > index + 1 && lines[end - 1].trim() === '') {\n end -= 1;\n }\n\n return { from: index, to: end };\n }\n }\n\n return null;\n};\n\nconst yamlLines = (value: Record<string, unknown>): string[] => {\n return splitLines(emitYaml(value as unknown as YamlValue));\n};\n",
|
|
24
25
|
"import type { OrbitDocument } from './types.js';\nimport { documentSource } from './document-source.js';\nimport { writeMarkdown } from './markdown-writing.js';\nimport { patchMarkdown } from './source-patch.js';\n\nexport interface SerializeOptions {\n /**\n * Keep the source's own lines for everything an edit didn't change (the\n * default, for a document parsed from markdown): its formatting, and the\n * text Orbit doesn't read, such as other HTML comments or frontmatter\n * keys of other apps. `false` writes the whole map in Orbit's own form.\n */\n keepSource?: boolean;\n}\n\n/**\n * A map as orbit-md. A document parsed from markdown comes back as it was\n * written, with only what changed since rewritten, so maps written by hand\n * or by other apps keep their formatting and everything Orbit doesn't read.\n * Other documents (built in code, or read from YAML) are written in Orbit's\n * own form: headings for the root and its children, lists below them.\n */\nexport const serializeOrbitMarkdown = (doc: OrbitDocument, options: SerializeOptions = {}): string => {\n const source = options.keepSource === false ? undefined : documentSource(doc);\n\n if (source) {\n const patched = patchMarkdown(doc, source);\n\n if (patched !== null) {\n return patched;\n }\n }\n\n return writeMarkdown(doc);\n};\n",
|
|
25
|
-
"import type { OrbitDocument, OrbitNode } from './types.js';\nimport { assignKey, emitYaml, type YamlValue } from './yaml-mini.js';\nimport { nodesWithExplicitIds } from './utils.js';\nimport { mediaExtras } from './node-attributes.js';\n\nexport const serializeOrbitYAML = (doc: OrbitDocument): string => {\n const out: Record<string, YamlValue> = {};\n const opts = doc.options;\n\n if (opts.title) {\n out.title = opts.title;\n }\n\n if (opts.theme) {\n out.theme = opts.theme;\n }\n\n if (opts.viewMode) {\n out.view = opts.viewMode;\n }\n\n if (opts.showRings !== undefined) {\n out.showRings = opts.showRings;\n }\n\n if (opts.interactive !== undefined) {\n out.interactive = opts.interactive;\n }\n\n if (opts.orbitAnimation !== undefined) {\n out.animation = opts.orbitAnimation;\n }\n\n if (opts.orbitSpeed !== undefined) {\n out.speed = opts.orbitSpeed;\n }\n\n if (opts.palette) {\n out.palette = opts.palette as YamlValue;\n }\n\n if (opts.height !== undefined) {\n out.height = opts.height;\n }\n\n if (opts.maxDepth !== undefined) {\n out.maxDepth = opts.maxDepth;\n }\n\n if (opts.className) {\n out.className = opts.className;\n }\n\n if (opts.baseUrl) {\n out.baseUrl = opts.baseUrl;\n }\n\n if (opts.schemaVersion !== undefined) {\n out.schemaVersion = opts.schemaVersion;\n }\n\n // Keys Orbit doesn't read, after its own: as they were written.\n for (const [key, value] of Object.entries(doc.extra ?? {})) {\n if (!Object.prototype.hasOwnProperty.call(out, key) && key !== 'nodes') {\n assignKey(out, key, value as YamlValue);\n }\n }\n\n out.nodes = [serializeNode(doc.root, nodesWithExplicitIds(doc.root))];\n return emitYaml(out);\n};\n\nconst serializeNode = (n: OrbitNode, explicitIds: ReadonlySet<OrbitNode>): YamlValue => {\n const obj: Record<string, YamlValue> = { text: n.text };\n\n if (explicitIds.has(n)) {\n obj.id = n.id;\n }\n\n if (n.icon) {\n obj.icon = n.icon;\n }\n\n if (n.color) {\n obj.color = n.color;\n }\n\n if (n.type) {\n obj.type = n.typeVersion === undefined ? n.type : `${n.type}@${n.typeVersion}`;\n }\n\n if (n.link) {\n obj.link = n.link;\n }\n\n if (n.tags) {\n obj.tags = n.tags;\n }\n\n if (n.status) {\n obj.status = n.status;\n }\n\n if (n.priority !== undefined) {\n obj.priority = n.priority;\n }\n\n if (n.collapsed !== undefined) {\n obj.collapsed = n.collapsed;\n }\n\n // A picture, video or embed keeps the fields Orbit doesn't read.\n if (n.image) {\n obj.image = { ...mediaExtras(n.image), ...n.image } as unknown as YamlValue;\n }\n\n if (n.video) {\n obj.video = { ...mediaExtras(n.video), ...n.video } as unknown as YamlValue;\n }\n\n if (n.embed) {\n obj.embed = { ...mediaExtras(n.embed), ...n.embed } as unknown as YamlValue;\n }\n\n if (n.note) {\n obj.note = n.note;\n\n if (n.noteFormat && n.noteFormat !== 'markdown') {\n obj.noteFormat = n.noteFormat;\n }\n }\n\n if (n.attrs) {\n for (const [k, v] of Object.entries(n.attrs)) {\n // A value Orbit couldn't read for one of its own attributes is written back, unless one was set since:\n // it reads back the same way. Keys a node map reads as structure (its\n // text, its children) are never written from attrs: they would reparse\n // as real structure.\n if (!RESERVED_NODE_KEYS.has(k) && !Object.prototype.hasOwnProperty.call(obj, k)) {\n assignKey(obj, k, v as YamlValue);\n }\n }\n }\n\n if (n.children.length) {\n obj.children = n.children.map((child) => serializeNode(child, explicitIds));\n }\n\n return obj;\n};\n\n/** Keys `buildNode` reads as the node's structure: a value under them would become a title or children. */\nconst RESERVED_NODE_KEYS = new Set(['text', 'children']);\n",
|
|
26
|
-
"/**\n * The words Orbit shows and says: the controls, the detail sheet, the\n * outline and what it announces, what a screen reader hears about each\n * idea, the media viewer and the empty map. English and Spanish are built\n * in; `registerLanguage` adds others, or changes words of one Orbit has.\n *\n * A map speaks the language its `language` option names, or else the one\n * its element is in: the closest `lang` attribute around it, through shadow\n * roots, then the document's. A language Orbit doesn't have falls back to\n * its base (es-MX reads es), then to English.\n */\n\n/**\n * Text that depends on a number: one form for each plural category the\n * language uses (see `Intl.PluralRules`), `other` for any it leaves out.\n * `{count}` is the number, written the language's way.\n */\nexport interface OrbitPluralText {\n zero?: string;\n one?: string;\n two?: string;\n few?: string;\n many?: string;\n other: string;\n}\n\n/**\n * Everything Orbit says, in one language. `{name}`-style placeholders are\n * filled in as described on each; keep them in a translation, in any order.\n */\nexport interface OrbitStrings {\n /** The map's name for assistive technology, and an exported SVG's title, when it has no `ariaLabel` and its root no text. */\n mindMap: string;\n\n /** What assistive technology calls the map (`aria-roledescription`), in lower case. */\n mindMapRole: string;\n\n /** An idea with no text, wherever its name shows. */\n untitled: string;\n\n /** The root Orbit makes up for a map that's just a list, or has several top headings, and no title. */\n untitledMap: string;\n\n /** The message on a map with nothing in it. */\n emptyMap: string;\n\n /** The hint under it. */\n emptyMapHint: string;\n\n /** The title of the card shown where a map couldn't be drawn. */\n mapNotDrawn: string;\n\n /** The card's message when the problem came with none of its own. */\n mapNotDrawnReason: string;\n\n /** The card's message for a problem on a line of the map's source: `{line}` and `{message}`, which stays as Orbit wrote it. */\n problemOnLine: string;\n\n /** The breadcrumbs, for assistive technology. */\n mapPath: string;\n\n /** The back button, when the idea it goes back to has no name. */\n back: string;\n\n /** The back button's label: `{name}` is the idea it goes back to. */\n backTo: string;\n\n /** The back button's label when that idea has no text. */\n backToParent: string;\n\n /** The group of view buttons. */\n view: string;\n\n /** The button that shows the focused idea with the ideas around it. */\n focus: string;\n\n /** The button that shows the whole map at once. */\n overview: string;\n\n /** The button that shows the map as a list. */\n showOutline: string;\n\n /** The group of zoom buttons. */\n zoom: string;\n\n zoomIn: string;\n zoomOut: string;\n\n /** The button that zooms to fit the view. */\n fitMap: string;\n\n /** Shown when the wheel scrolls the page over a map: `{key}` is Ctrl, or ⌘ on Apple devices. */\n scrollToZoom: string;\n\n /** The map as a list, for assistive technology. */\n outline: string;\n\n /** Announced when the overview opens. */\n overviewAnnouncement: string;\n\n /** How many ideas an idea holds, as announced and in its description: `{count}`. */\n ideaCount: OrbitPluralText;\n\n /** Announced when an idea is added: `{name}`. */\n added: string;\n\n /** Announced when an idea is deleted: `{name}`. */\n removed: string;\n\n /** Announced when an idea moves: `{name}` into `{parent}`. */\n moved: string;\n\n /** Announced when an idea moves to a parent with no text: `{name}`. */\n movedToTop: string;\n\n /** `{name}` in those announcements when the idea has no text. */\n anIdea: string;\n\n /** Part of an idea's description: `{status}` is its status word. */\n status: string;\n\n /** The status in the tooltip: `{status}`. */\n statusLabel: string;\n\n /** Part of an idea's description: `{list}` lists what it has, from the words below. */\n has: string;\n\n hasDetails: string;\n hasNote: string;\n hasImage: string;\n hasVideo: string;\n hasEmbed: string;\n hasLink: string;\n\n /** The text field over an idea being renamed: `{name}`. */\n textOf: string;\n\n /** The text field for a new idea: `{name}` is the idea it goes into. */\n newIdeaFor: string;\n\n /** The empty text field's placeholder for a new idea. */\n newIdea: string;\n\n /** The + in an orbit: `{name}` is the idea it adds to. */\n addIdeaTo: string;\n\n /** Where an idea being moved would land: `{name}` is that idea. */\n moveHere: string;\n\n /** `{name}` in the text fields and the + when the idea has no text. */\n thisIdea: string;\n\n /** `{name}` in `moveHere` when the idea has no text. */\n theIdea: string;\n\n /** The buttons under an idea: `{name}`. */\n ideaActions: string;\n\n /** The buttons under an idea with no text. */\n ideaActionsUntitled: string;\n\n showDetails: string;\n viewImage: string;\n\n /** The picture in the detail sheet, which opens the viewer: `{description}` is its alternative text. */\n viewImageOf: string;\n\n playVideo: string;\n openEmbed: string;\n readNote: string;\n openLink: string;\n\n /** A link to another idea of the map: `{name}` is that idea, or `theIdea` when it has no text. */\n goTo: string;\n\n /** The detail sheet's name when the idea has no text. */\n details: string;\n\n close: string;\n previous: string;\n next: string;\n\n /** The button that presents a map shared as a web page, one idea at a time with its note as a caption. */\n present: string;\n\n /** The priority chip: `{priority}`. */\n priority: string;\n\n /** The button over a video in the detail sheet. */\n expand: string;\n\n /** That button, for assistive technology. */\n expandVideo: string;\n\n /** A picture's name in the viewer when it has no description or caption. */\n picture: string;\n\n /** A video's name in the viewer when it has no caption. */\n video: string;\n\n /** Where the viewer is among the map's pictures and videos: `{index}` of `{total}`. */\n position: string;\n\n /** The viewer's button that zooms the picture to fit. */\n fitPicture: string;\n\n pictureUnavailable: string;\n videoUnavailable: string;\n\n /** A video its site doesn't let other pages play. */\n videoUnavailableHere: string;\n\n openPictureInNewTab: string;\n openVideoInNewTab: string;\n\n /** A video's link to its site: `{provider}` is YouTube or Vimeo. */\n watchOn: string;\n}\n\ntype TextKey = { [Key in keyof OrbitStrings]: OrbitStrings[Key] extends string ? Key : never }[keyof OrbitStrings];\ntype CountKey = { [Key in keyof OrbitStrings]: OrbitStrings[Key] extends OrbitPluralText ? Key : never }[keyof OrbitStrings];\ntype Values = Record<string, string | number>;\n\nconst ENGLISH: OrbitStrings = {\n mindMap: 'Mind map',\n mindMapRole: 'mind map',\n untitled: 'Untitled',\n untitledMap: 'Untitled map',\n emptyMap: 'This map is empty',\n emptyMapHint: 'Start it with a # heading or a bullet list',\n mapNotDrawn: 'This map couldn’t be drawn',\n mapNotDrawnReason: 'The map could not be drawn.',\n problemOnLine: 'Line {line}: {message}',\n\n mapPath: 'Map path',\n back: 'Back',\n backTo: 'Back to {name}',\n backToParent: 'Back to the parent node',\n view: 'View',\n focus: 'Focus',\n overview: 'Overview',\n showOutline: 'Show the map as a list',\n zoom: 'Zoom',\n zoomIn: 'Zoom in',\n zoomOut: 'Zoom out',\n fitMap: 'Fit the map',\n scrollToZoom: 'Use {key} + scroll to zoom the map',\n\n outline: 'Map outline',\n overviewAnnouncement: 'Overview of the whole map',\n ideaCount: { one: '{count} item', other: '{count} items' },\n added: 'Added {name}',\n removed: 'Removed {name}',\n moved: 'Moved {name} to {parent}',\n movedToTop: 'Moved {name} to the top',\n anIdea: 'a node',\n\n status: 'status {status}',\n statusLabel: 'Status: {status}',\n has: 'has {list}',\n hasDetails: 'details',\n hasNote: 'note',\n hasImage: 'image',\n hasVideo: 'video',\n hasEmbed: 'embed',\n hasLink: 'link',\n\n textOf: 'Text of {name}',\n newIdeaFor: 'New idea for {name}',\n newIdea: 'New idea',\n addIdeaTo: 'Add an idea to {name}',\n moveHere: 'Move {name} here',\n thisIdea: 'this node',\n theIdea: 'the idea',\n\n ideaActions: '{name} actions',\n ideaActionsUntitled: 'Node actions',\n showDetails: 'Show details',\n viewImage: 'View image',\n viewImageOf: 'View image: {description}',\n playVideo: 'Play video',\n openEmbed: 'Open embed',\n readNote: 'Read note',\n openLink: 'Open link',\n goTo: 'Go to {name}',\n details: 'Details',\n close: 'Close',\n previous: 'Previous',\n next: 'Next',\n present: 'Present',\n priority: 'Priority {priority}',\n expand: 'Expand',\n expandVideo: 'Expand the video',\n\n picture: 'Picture',\n video: 'Video',\n position: '{index} of {total}',\n fitPicture: 'Fit the picture',\n pictureUnavailable: 'This picture can’t be shown.',\n videoUnavailable: 'This video can’t be played.',\n videoUnavailableHere: 'This video can’t be played here.',\n openPictureInNewTab: 'Open the picture in a new tab',\n openVideoInNewTab: 'Open the video in a new tab',\n watchOn: 'Watch on {provider}',\n};\n\nconst SPANISH: OrbitStrings = {\n mindMap: 'Mapa mental',\n mindMapRole: 'mapa mental',\n untitled: 'Sin título',\n untitledMap: 'Mapa sin título',\n emptyMap: 'Este mapa está vacío',\n emptyMapHint: 'Empiézalo con un encabezado # o una lista con viñetas',\n mapNotDrawn: 'No se pudo dibujar este mapa',\n mapNotDrawnReason: 'No se pudo dibujar el mapa.',\n problemOnLine: 'Línea {line}: {message}',\n\n mapPath: 'Ruta del mapa',\n back: 'Atrás',\n backTo: 'Volver a {name}',\n backToParent: 'Volver a la idea superior',\n view: 'Vista',\n focus: 'Enfoque',\n overview: 'Vista general',\n showOutline: 'Mostrar el mapa como lista',\n zoom: 'Zoom',\n zoomIn: 'Acercar',\n zoomOut: 'Alejar',\n fitMap: 'Ajustar el mapa',\n scrollToZoom: 'Usa {key} + desplazamiento para acercar o alejar el mapa',\n\n outline: 'Esquema del mapa',\n overviewAnnouncement: 'Vista general de todo el mapa',\n ideaCount: { one: '{count} idea', many: '{count} ideas', other: '{count} ideas' },\n added: 'Se agregó {name}',\n removed: 'Se eliminó {name}',\n moved: 'Se movió {name} a {parent}',\n movedToTop: 'Se movió {name} al nivel superior',\n anIdea: 'una idea',\n\n status: 'estado {status}',\n statusLabel: 'Estado: {status}',\n has: 'tiene {list}',\n hasDetails: 'detalles',\n hasNote: 'nota',\n hasImage: 'imagen',\n hasVideo: 'video',\n hasEmbed: 'contenido insertado',\n hasLink: 'enlace',\n\n textOf: 'Texto de {name}',\n newIdeaFor: 'Idea nueva en {name}',\n newIdea: 'Idea nueva',\n addIdeaTo: 'Agregar una idea a {name}',\n moveHere: 'Mover {name} aquí',\n thisIdea: 'esta idea',\n theIdea: 'la idea',\n\n ideaActions: 'Acciones de {name}',\n ideaActionsUntitled: 'Acciones de la idea',\n showDetails: 'Ver detalles',\n viewImage: 'Ver imagen',\n viewImageOf: 'Ver imagen: {description}',\n playVideo: 'Reproducir video',\n openEmbed: 'Abrir contenido insertado',\n readNote: 'Leer nota',\n openLink: 'Abrir enlace',\n goTo: 'Ir a {name}',\n details: 'Detalles',\n close: 'Cerrar',\n previous: 'Anterior',\n next: 'Siguiente',\n present: 'Presentar',\n priority: 'Prioridad {priority}',\n expand: 'Ampliar',\n expandVideo: 'Ampliar el video',\n\n picture: 'Imagen',\n video: 'Video',\n position: '{index} de {total}',\n fitPicture: 'Ajustar la imagen',\n pictureUnavailable: 'No se puede mostrar esta imagen.',\n videoUnavailable: 'No se puede reproducir este video.',\n videoUnavailableHere: 'Este video no se puede reproducir aquí.',\n openPictureInNewTab: 'Abrir la imagen en una pestaña nueva',\n openVideoInNewTab: 'Abrir el video en una pestaña nueva',\n watchOn: 'Ver en {provider}',\n};\n\nconst BUILT_IN = new Map<string, OrbitStrings>([['en', ENGLISH], ['es', SPANISH]]);\nconst registered = new Map<string, OrbitStrings>(BUILT_IN);\nconst KEYS = Object.keys(ENGLISH) as (keyof OrbitStrings)[];\nconst PLURAL_CATEGORIES = ['zero', 'one', 'two', 'few', 'many', 'other'] as const;\n\n/**\n * Adds a language for every map, by its BCP 47 tag (`fr`, `pt-BR`), or\n * changes some words of one Orbit has. Words it leaves out come from the\n * language it narrows (`pt` for `pt-BR`), then English. Returns a function\n * that puts the language back as it was.\n */\nexport const registerLanguage = (language: string, strings: Partial<OrbitStrings>): () => void => {\n const tag = canonicalTag(language);\n\n if (tag === null) {\n throw new Error(`\"${language}\" isn't a language tag: use one like \"fr\", \"pt-BR\" or \"zh-Hant\".`);\n }\n\n const previous = registered.get(tag);\n const definition: OrbitStrings = { ...(previous ?? registered.get(baseOf(tag)) ?? ENGLISH), ...validStrings(strings, tag) };\n registered.set(tag, definition);\n\n return () => {\n if (registered.get(tag) !== definition) {\n return;\n }\n\n if (previous) {\n registered.set(tag, previous);\n } else {\n registered.delete(tag);\n }\n };\n};\n\n/** The tags of the languages every map can speak: the built-in ones and the registered ones. */\nexport const languageTags = (): string[] => {\n return [...registered.keys()];\n};\n\n/**\n * The language an element is in: the closest `lang` attribute around it,\n * through shadow roots, then the document's. Null when none says.\n */\nexport const languageOf = (element: Element | null | undefined): string | null => {\n let node: Node | null = element ?? null;\n\n while (node) {\n if (node.nodeType === 1) {\n const lang = (node as Element).getAttribute('lang');\n\n if (lang) {\n return lang;\n }\n }\n\n node = node.parentNode ?? ((node as ShadowRoot).host ?? null);\n }\n\n return element?.ownerDocument?.documentElement?.getAttribute('lang') || null;\n};\n\n/** The words of one map: its language's, with the `strings` it was given on top. */\nexport class OrbitWords {\n /** The tag of the language the words come from: `es` for a map asked for `es-MX`. */\n readonly language: string;\n\n /** The tag numbers, plurals and lists are written for: `es-MX` there. */\n readonly locale: string;\n\n private readonly table: OrbitStrings;\n\n constructor(requested?: string | null, strings?: Partial<OrbitStrings>) {\n const tag = requested ? canonicalTag(requested) : null;\n this.language = tag === null ? 'en' : registered.has(tag) ? tag : registered.has(baseOf(tag)) ? baseOf(tag) : 'en';\n this.locale = tag !== null && (tag === this.language || baseOf(tag) === this.language) ? tag : this.language;\n const table = registered.get(this.language) ?? ENGLISH;\n this.table = strings ? { ...table, ...validStrings(strings, 'strings') } : table;\n }\n\n /** Whether these words are the same as `other`'s: the same language and the same table. */\n sameAs(other: OrbitWords | null): boolean {\n return other !== null && other.locale === this.locale && other.table === this.table;\n }\n\n text(key: TextKey, values?: Values): string {\n return this.fill(this.table[key], values);\n }\n\n /** A text with a number in it, in the form the number takes in the language. */\n count(key: CountKey, count: number, values?: Values): string {\n const forms = this.table[key];\n const category = pluralRules(this.locale)?.select(count) ?? (count === 1 ? 'one' : 'other');\n return this.fill(forms[category] ?? forms.other, { ...values, count });\n }\n\n /** Items as the language lists them: \"a, b and c\". */\n list(items: string[]): string {\n const format = listFormat(this.locale);\n return format ? format.format(items) : items.join(', ');\n }\n\n number(value: number): string {\n return numberFormat(this.locale)?.format(value) ?? String(value);\n }\n\n private fill(template: string, values?: Values): string {\n if (!values) {\n return template;\n }\n\n return template.replace(/\\{(\\w+)\\}/g, (placeholder, name: string) => {\n const value = values[name];\n\n if (value === undefined) {\n return placeholder;\n }\n\n return typeof value === 'number' ? this.number(value) : value;\n });\n }\n}\n\n/** The words a map speaks when it's asked for `requested`, or for the language around `element`. */\nexport const wordsFor = (requested: string | undefined, element: Element | null | undefined, strings?: Partial<OrbitStrings>): OrbitWords => {\n return new OrbitWords(requested ?? languageOf(element), strings);\n};\n\n/** Only known keys with the right kind of value: a mistake in one word shouldn't break the map. */\nconst validStrings = (strings: Partial<OrbitStrings>, source: string): Partial<OrbitStrings> => {\n const valid: Partial<Record<keyof OrbitStrings, unknown>> = {};\n\n if (!strings || typeof strings !== 'object') {\n return valid as Partial<OrbitStrings>;\n }\n\n for (const [key, value] of Object.entries(strings)) {\n if (!KEYS.includes(key as keyof OrbitStrings)) {\n warnOnce(`${source}: Orbit has no words called \"${key}\".`);\n continue;\n }\n\n const plural = typeof ENGLISH[key as keyof OrbitStrings] !== 'string';\n\n if (!plural && typeof value === 'string') {\n valid[key as keyof OrbitStrings] = value;\n } else if (plural && isPluralText(value)) {\n valid[key as keyof OrbitStrings] = pluralText(value);\n } else if (plural && typeof value === 'string') {\n valid[key as keyof OrbitStrings] = { other: value };\n } else {\n warnOnce(`${source}: \"${key}\" should be ${plural ? 'an object of plural forms with at least \"other\"' : 'a string'}.`);\n }\n }\n\n return valid as Partial<OrbitStrings>;\n};\n\nconst isPluralText = (value: unknown): value is OrbitPluralText => {\n return typeof value === 'object' && value !== null && typeof (value as OrbitPluralText).other === 'string';\n};\n\nconst pluralText = (value: OrbitPluralText): OrbitPluralText => {\n const forms: OrbitPluralText = { other: value.other };\n\n for (const category of PLURAL_CATEGORIES) {\n if (typeof value[category] === 'string') {\n forms[category] = value[category];\n }\n }\n\n return forms;\n};\n\nconst canonicalTag = (language: string): string | null => {\n if (typeof language !== 'string' || language.trim() === '') {\n return null;\n }\n\n try {\n const [tag] = Intl.getCanonicalLocales(language.trim().replace(/_/g, '-'));\n return tag ?? null;\n } catch {\n return null;\n }\n};\n\nconst baseOf = (tag: string): string => {\n return tag.split('-')[0];\n};\n\nconst warned = new Set<string>();\n\nconst warnOnce = (message: string): void => {\n if (!warned.has(message)) {\n warned.add(message);\n console.warn(`[orbit] ${message}`);\n }\n};\n\nconst pluralRulesCache = new Map<string, Intl.PluralRules | null>();\nconst numberFormatCache = new Map<string, Intl.NumberFormat | null>();\nconst listFormatCache = new Map<string, Intl.ListFormat | null>();\n\nconst pluralRules = (locale: string): Intl.PluralRules | null => {\n return cached(pluralRulesCache, locale, () => new Intl.PluralRules(locale));\n};\n\nconst numberFormat = (locale: string): Intl.NumberFormat | null => {\n return cached(numberFormatCache, locale, () => new Intl.NumberFormat(locale));\n};\n\nconst listFormat = (locale: string): Intl.ListFormat | null => {\n return cached(listFormatCache, locale, () => (typeof Intl.ListFormat === 'function' ? new Intl.ListFormat(locale, { type: 'conjunction' }) : null));\n};\n\nconst cached = <Value>(cache: Map<string, Value | null>, locale: string, make: () => Value | null): Value | null => {\n if (!cache.has(locale)) {\n try {\n cache.set(locale, make());\n } catch {\n cache.set(locale, null);\n }\n }\n\n return cache.get(locale) ?? null;\n};\n",
|
|
26
|
+
"import type { OrbitDocument, OrbitNode } from './types.js';\nimport { assignKey, emitYaml, type YamlValue } from './yaml-mini.js';\nimport { nodesWithExplicitIds } from './utils.js';\nimport { mediaExtras } from './node-attributes.js';\n\nexport const serializeOrbitYAML = (doc: OrbitDocument): string => {\n const out: Record<string, YamlValue> = {};\n const opts = doc.options;\n\n if (opts.title) {\n out.title = opts.title;\n }\n\n if (opts.theme) {\n out.theme = opts.theme;\n }\n\n if (opts.viewMode) {\n out.view = opts.viewMode;\n }\n\n if (opts.showRings !== undefined) {\n out.showRings = opts.showRings;\n }\n\n if (opts.interactive !== undefined) {\n out.interactive = opts.interactive;\n }\n\n if (opts.orbitAnimation !== undefined) {\n out.animation = opts.orbitAnimation;\n }\n\n if (opts.orbitSpeed !== undefined) {\n out.speed = opts.orbitSpeed;\n }\n\n if (opts.palette) {\n out.palette = opts.palette as YamlValue;\n }\n\n if (opts.height !== undefined) {\n out.height = opts.height;\n }\n\n if (opts.maxDepth !== undefined) {\n out.maxDepth = opts.maxDepth;\n }\n\n if (opts.className) {\n out.className = opts.className;\n }\n\n if (opts.baseUrl) {\n out.baseUrl = opts.baseUrl;\n }\n\n if (opts.schemaVersion !== undefined) {\n out.schemaVersion = opts.schemaVersion;\n }\n\n // Keys Orbit doesn't read, after its own: as they were written.\n for (const [key, value] of Object.entries(doc.extra ?? {})) {\n if (!Object.prototype.hasOwnProperty.call(out, key) && key !== 'nodes') {\n assignKey(out, key, value as YamlValue);\n }\n }\n\n out.nodes = [serializeNode(doc.root, nodesWithExplicitIds(doc.root))];\n return emitYaml(out);\n};\n\nconst serializeNode = (n: OrbitNode, explicitIds: ReadonlySet<OrbitNode>): YamlValue => {\n const obj: Record<string, YamlValue> = { text: n.text };\n\n if (explicitIds.has(n)) {\n obj.id = n.id;\n }\n\n if (n.icon) {\n obj.icon = n.icon;\n }\n\n if (n.color) {\n obj.color = n.color;\n }\n\n if (n.paletteColor !== undefined) {\n obj.paletteColor = n.paletteColor;\n }\n\n if (n.type) {\n obj.type = n.typeVersion === undefined ? n.type : `${n.type}@${n.typeVersion}`;\n }\n\n if (n.link) {\n obj.link = n.link;\n }\n\n if (n.tags) {\n obj.tags = n.tags;\n }\n\n if (n.status) {\n obj.status = n.status;\n }\n\n if (n.priority !== undefined) {\n obj.priority = n.priority;\n }\n\n if (n.collapsed !== undefined) {\n obj.collapsed = n.collapsed;\n }\n\n // A picture, video or embed keeps the fields Orbit doesn't read.\n if (n.image) {\n obj.image = { ...mediaExtras(n.image), ...n.image } as unknown as YamlValue;\n }\n\n if (n.video) {\n obj.video = { ...mediaExtras(n.video), ...n.video } as unknown as YamlValue;\n }\n\n if (n.embed) {\n obj.embed = { ...mediaExtras(n.embed), ...n.embed } as unknown as YamlValue;\n }\n\n if (n.note) {\n obj.note = n.note;\n\n if (n.noteFormat && n.noteFormat !== 'markdown') {\n obj.noteFormat = n.noteFormat;\n }\n }\n\n if (n.attrs) {\n for (const [k, v] of Object.entries(n.attrs)) {\n // A value Orbit couldn't read for one of its own attributes is written back, unless one was set since:\n // it reads back the same way. Keys a node map reads as structure (its\n // text, its children) are never written from attrs: they would reparse\n // as real structure.\n if (!RESERVED_NODE_KEYS.has(k) && !Object.prototype.hasOwnProperty.call(obj, k)) {\n assignKey(obj, k, v as YamlValue);\n }\n }\n }\n\n if (n.children.length) {\n obj.children = n.children.map((child) => serializeNode(child, explicitIds));\n }\n\n return obj;\n};\n\n/** Keys `buildNode` reads as the node's structure: a value under them would become a title or children. */\nconst RESERVED_NODE_KEYS = new Set(['text', 'children']);\n",
|
|
27
|
+
"/**\n * The words Orbit shows and says: the controls, the detail sheet, the\n * outline and what it announces, what a screen reader hears about each\n * idea, the media viewer and the empty map. English and Spanish are built\n * in; `registerLanguage` adds others, or changes words of one Orbit has.\n *\n * A map speaks the language its `language` option names, or else the one\n * its element is in: the closest `lang` attribute around it, through shadow\n * roots, then the document's. A language Orbit doesn't have falls back to\n * its base (es-MX reads es), then to English.\n */\n\n/**\n * Text that depends on a number: one form for each plural category the\n * language uses (see `Intl.PluralRules`), `other` for any it leaves out.\n * `{count}` is the number, written the language's way.\n */\nexport interface OrbitPluralText {\n zero?: string;\n one?: string;\n two?: string;\n few?: string;\n many?: string;\n other: string;\n}\n\n/**\n * Everything Orbit says, in one language. `{name}`-style placeholders are\n * filled in as described on each; keep them in a translation, in any order.\n */\nexport interface OrbitStrings {\n /** The map's name for assistive technology, and an exported SVG's title, when it has no `ariaLabel` and its root no text. */\n mindMap: string;\n\n /** What assistive technology calls the map (`aria-roledescription`), in lower case. */\n mindMapRole: string;\n\n /** An idea with no text, wherever its name shows. */\n untitled: string;\n\n /** The root Orbit makes up for a map that's just a list, or has several top headings, and no title. */\n untitledMap: string;\n\n /** The message on a map with nothing in it. */\n emptyMap: string;\n\n /** The hint under it. */\n emptyMapHint: string;\n\n /** The title of the card shown where a map couldn't be drawn. */\n mapNotDrawn: string;\n\n /** The card's message when the problem came with none of its own. */\n mapNotDrawnReason: string;\n\n /** The card's message for a problem on a line of the map's source: `{line}` and `{message}`, which stays as Orbit wrote it. */\n problemOnLine: string;\n\n /** The breadcrumbs, for assistive technology. */\n mapPath: string;\n\n /** The back button, when the idea it goes back to has no name. */\n back: string;\n\n /** The back button's label: `{name}` is the idea it goes back to. */\n backTo: string;\n\n /** The back button's label when that idea has no text. */\n backToParent: string;\n\n /** The group of view buttons. */\n view: string;\n\n /** The button that shows the focused idea with the ideas around it. */\n focus: string;\n\n /** The button that shows the whole map at once. */\n overview: string;\n\n /** The button that shows the map as a list. */\n showOutline: string;\n\n /** The group of zoom buttons. */\n zoom: string;\n\n zoomIn: string;\n zoomOut: string;\n\n /** The button that zooms to fit the view. */\n fitMap: string;\n\n /** Shown when the wheel scrolls the page over a map: `{key}` is Ctrl, or ⌘ on Apple devices. */\n scrollToZoom: string;\n\n /** The map as a list, for assistive technology. */\n outline: string;\n\n /** Announced when the overview opens. */\n overviewAnnouncement: string;\n\n /** How many ideas an idea holds, as announced and in its description: `{count}`. */\n ideaCount: OrbitPluralText;\n\n /** Announced when an idea is added: `{name}`. */\n added: string;\n\n /** Announced when an idea is deleted: `{name}`. */\n removed: string;\n\n /** Announced when an idea moves: `{name}` into `{parent}`. */\n moved: string;\n\n /** Announced when an idea moves to a parent with no text: `{name}`. */\n movedToTop: string;\n\n /** `{name}` in those announcements when the idea has no text. */\n anIdea: string;\n\n /** Part of an idea's description: `{status}` is its status word. */\n status: string;\n\n /** The status in the tooltip: `{status}`. */\n statusLabel: string;\n\n /** Part of an idea's description: `{list}` lists what it has, from the words below. */\n has: string;\n\n hasDetails: string;\n hasNote: string;\n hasImage: string;\n hasVideo: string;\n hasEmbed: string;\n hasLink: string;\n\n /** The text field over an idea being renamed: `{name}`. */\n textOf: string;\n\n /** The text field for a new idea: `{name}` is the idea it goes into. */\n newIdeaFor: string;\n\n /** The empty text field's placeholder for a new idea. */\n newIdea: string;\n\n /** The + in an orbit: `{name}` is the idea it adds to. */\n addIdeaTo: string;\n\n /** Where an idea being moved would land: `{name}` is that idea. */\n moveHere: string;\n\n /** `{name}` in the text fields and the + when the idea has no text. */\n thisIdea: string;\n\n /** `{name}` in `moveHere` when the idea has no text. */\n theIdea: string;\n\n /** The buttons under an idea: `{name}`. */\n ideaActions: string;\n\n /** The buttons under an idea with no text. */\n ideaActionsUntitled: string;\n\n showDetails: string;\n viewImage: string;\n\n /** The picture in the detail sheet, which opens the viewer: `{description}` is its alternative text. */\n viewImageOf: string;\n\n playVideo: string;\n openEmbed: string;\n readNote: string;\n openLink: string;\n\n /** A link to another idea of the map: `{name}` is that idea, or `theIdea` when it has no text. */\n goTo: string;\n\n /** The same link printed, where it can't be followed: `{name}` is that idea. */\n seeIdea: string;\n\n /** The detail sheet's name when the idea has no text. */\n details: string;\n\n close: string;\n previous: string;\n next: string;\n\n /** The button that presents a map shared as a web page, one idea at a time with its note as a caption. */\n present: string;\n\n /** The priority chip: `{priority}`. */\n priority: string;\n\n /** The button over a video in the detail sheet. */\n expand: string;\n\n /** That button, for assistive technology. */\n expandVideo: string;\n\n /** A picture's name in the viewer when it has no description or caption. */\n picture: string;\n\n /** A video's name in the viewer when it has no caption. */\n video: string;\n\n /** Where the viewer is among the map's pictures and videos: `{index}` of `{total}`. */\n position: string;\n\n /** The viewer's button that zooms the picture to fit. */\n fitPicture: string;\n\n pictureUnavailable: string;\n videoUnavailable: string;\n\n /** A video its site doesn't let other pages play. */\n videoUnavailableHere: string;\n\n openPictureInNewTab: string;\n openVideoInNewTab: string;\n\n /** A video's link to its site: `{provider}` is YouTube or Vimeo. */\n watchOn: string;\n}\n\ntype TextKey = { [Key in keyof OrbitStrings]: OrbitStrings[Key] extends string ? Key : never }[keyof OrbitStrings];\ntype CountKey = { [Key in keyof OrbitStrings]: OrbitStrings[Key] extends OrbitPluralText ? Key : never }[keyof OrbitStrings];\ntype Values = Record<string, string | number>;\n\nconst ENGLISH: OrbitStrings = {\n mindMap: 'Mind map',\n mindMapRole: 'mind map',\n untitled: 'Untitled',\n untitledMap: 'Untitled map',\n emptyMap: 'This map is empty',\n emptyMapHint: 'Start it with a # heading or a bullet list',\n mapNotDrawn: 'This map couldn’t be drawn',\n mapNotDrawnReason: 'The map could not be drawn.',\n problemOnLine: 'Line {line}: {message}',\n\n mapPath: 'Map path',\n back: 'Back',\n backTo: 'Back to {name}',\n backToParent: 'Back to the parent node',\n view: 'View',\n focus: 'Focus',\n overview: 'Overview',\n showOutline: 'Show the map as a list',\n zoom: 'Zoom',\n zoomIn: 'Zoom in',\n zoomOut: 'Zoom out',\n fitMap: 'Fit the map',\n scrollToZoom: 'Use {key} + scroll to zoom the map',\n\n outline: 'Map outline',\n overviewAnnouncement: 'Overview of the whole map',\n ideaCount: { one: '{count} item', other: '{count} items' },\n added: 'Added {name}',\n removed: 'Removed {name}',\n moved: 'Moved {name} to {parent}',\n movedToTop: 'Moved {name} to the top',\n anIdea: 'a node',\n\n status: 'status {status}',\n statusLabel: 'Status: {status}',\n has: 'has {list}',\n hasDetails: 'details',\n hasNote: 'note',\n hasImage: 'image',\n hasVideo: 'video',\n hasEmbed: 'embed',\n hasLink: 'link',\n\n textOf: 'Text of {name}',\n newIdeaFor: 'New idea for {name}',\n newIdea: 'New idea',\n addIdeaTo: 'Add an idea to {name}',\n moveHere: 'Move {name} here',\n thisIdea: 'this node',\n theIdea: 'the idea',\n\n ideaActions: '{name} actions',\n ideaActionsUntitled: 'Node actions',\n showDetails: 'Show details',\n viewImage: 'View image',\n viewImageOf: 'View image: {description}',\n playVideo: 'Play video',\n openEmbed: 'Open embed',\n readNote: 'Read note',\n openLink: 'Open link',\n goTo: 'Go to {name}',\n seeIdea: 'See {name}',\n details: 'Details',\n close: 'Close',\n previous: 'Previous',\n next: 'Next',\n present: 'Present',\n priority: 'Priority {priority}',\n expand: 'Expand',\n expandVideo: 'Expand the video',\n\n picture: 'Picture',\n video: 'Video',\n position: '{index} of {total}',\n fitPicture: 'Fit the picture',\n pictureUnavailable: 'This picture can’t be shown.',\n videoUnavailable: 'This video can’t be played.',\n videoUnavailableHere: 'This video can’t be played here.',\n openPictureInNewTab: 'Open the picture in a new tab',\n openVideoInNewTab: 'Open the video in a new tab',\n watchOn: 'Watch on {provider}',\n};\n\nconst SPANISH: OrbitStrings = {\n mindMap: 'Mapa mental',\n mindMapRole: 'mapa mental',\n untitled: 'Sin título',\n untitledMap: 'Mapa sin título',\n emptyMap: 'Este mapa está vacío',\n emptyMapHint: 'Empiézalo con un encabezado # o una lista con viñetas',\n mapNotDrawn: 'No se pudo dibujar este mapa',\n mapNotDrawnReason: 'No se pudo dibujar el mapa.',\n problemOnLine: 'Línea {line}: {message}',\n\n mapPath: 'Ruta del mapa',\n back: 'Atrás',\n backTo: 'Volver a {name}',\n backToParent: 'Volver a la idea superior',\n view: 'Vista',\n focus: 'Enfoque',\n overview: 'Vista general',\n showOutline: 'Mostrar el mapa como lista',\n zoom: 'Zoom',\n zoomIn: 'Acercar',\n zoomOut: 'Alejar',\n fitMap: 'Ajustar el mapa',\n scrollToZoom: 'Usa {key} + desplazamiento para acercar o alejar el mapa',\n\n outline: 'Esquema del mapa',\n overviewAnnouncement: 'Vista general de todo el mapa',\n ideaCount: { one: '{count} idea', many: '{count} ideas', other: '{count} ideas' },\n added: 'Se agregó {name}',\n removed: 'Se eliminó {name}',\n moved: 'Se movió {name} a {parent}',\n movedToTop: 'Se movió {name} al nivel superior',\n anIdea: 'una idea',\n\n status: 'estado {status}',\n statusLabel: 'Estado: {status}',\n has: 'tiene {list}',\n hasDetails: 'detalles',\n hasNote: 'nota',\n hasImage: 'imagen',\n hasVideo: 'video',\n hasEmbed: 'contenido insertado',\n hasLink: 'enlace',\n\n textOf: 'Texto de {name}',\n newIdeaFor: 'Idea nueva en {name}',\n newIdea: 'Idea nueva',\n addIdeaTo: 'Agregar una idea a {name}',\n moveHere: 'Mover {name} aquí',\n thisIdea: 'esta idea',\n theIdea: 'la idea',\n\n ideaActions: 'Acciones de {name}',\n ideaActionsUntitled: 'Acciones de la idea',\n showDetails: 'Ver detalles',\n viewImage: 'Ver imagen',\n viewImageOf: 'Ver imagen: {description}',\n playVideo: 'Reproducir video',\n openEmbed: 'Abrir contenido insertado',\n readNote: 'Leer nota',\n openLink: 'Abrir enlace',\n goTo: 'Ir a {name}',\n seeIdea: 'Ver {name}',\n details: 'Detalles',\n close: 'Cerrar',\n previous: 'Anterior',\n next: 'Siguiente',\n present: 'Presentar',\n priority: 'Prioridad {priority}',\n expand: 'Ampliar',\n expandVideo: 'Ampliar el video',\n\n picture: 'Imagen',\n video: 'Video',\n position: '{index} de {total}',\n fitPicture: 'Ajustar la imagen',\n pictureUnavailable: 'No se puede mostrar esta imagen.',\n videoUnavailable: 'No se puede reproducir este video.',\n videoUnavailableHere: 'Este video no se puede reproducir aquí.',\n openPictureInNewTab: 'Abrir la imagen en una pestaña nueva',\n openVideoInNewTab: 'Abrir el video en una pestaña nueva',\n watchOn: 'Ver en {provider}',\n};\n\nconst BUILT_IN = new Map<string, OrbitStrings>([['en', ENGLISH], ['es', SPANISH]]);\nconst registered = new Map<string, OrbitStrings>(BUILT_IN);\nconst KEYS = Object.keys(ENGLISH) as (keyof OrbitStrings)[];\nconst PLURAL_CATEGORIES = ['zero', 'one', 'two', 'few', 'many', 'other'] as const;\n\n/**\n * Adds a language for every map, by its BCP 47 tag (`fr`, `pt-BR`), or\n * changes some words of one Orbit has. Words it leaves out come from the\n * language it narrows (`pt` for `pt-BR`), then English. Returns a function\n * that puts the language back as it was.\n */\nexport const registerLanguage = (language: string, strings: Partial<OrbitStrings>): () => void => {\n const tag = canonicalTag(language);\n\n if (tag === null) {\n throw new Error(`\"${language}\" isn't a language tag: use one like \"fr\", \"pt-BR\" or \"zh-Hant\".`);\n }\n\n const previous = registered.get(tag);\n const definition: OrbitStrings = { ...(previous ?? registered.get(baseOf(tag)) ?? ENGLISH), ...validStrings(strings, tag) };\n registered.set(tag, definition);\n\n return () => {\n if (registered.get(tag) !== definition) {\n return;\n }\n\n if (previous) {\n registered.set(tag, previous);\n } else {\n registered.delete(tag);\n }\n };\n};\n\n/** The tags of the languages every map can speak: the built-in ones and the registered ones. */\nexport const languageTags = (): string[] => {\n return [...registered.keys()];\n};\n\n/**\n * The language an element is in: the closest `lang` attribute around it,\n * through shadow roots, then the document's. Null when none says.\n */\nexport const languageOf = (element: Element | null | undefined): string | null => {\n let node: Node | null = element ?? null;\n\n while (node) {\n if (node.nodeType === 1) {\n const lang = (node as Element).getAttribute('lang');\n\n if (lang) {\n return lang;\n }\n }\n\n node = node.parentNode ?? ((node as ShadowRoot).host ?? null);\n }\n\n return element?.ownerDocument?.documentElement?.getAttribute('lang') || null;\n};\n\n/** The words of one map: its language's, with the `strings` it was given on top. */\nexport class OrbitWords {\n /** The tag of the language the words come from: `es` for a map asked for `es-MX`. */\n readonly language: string;\n\n /** The tag numbers, plurals and lists are written for: `es-MX` there. */\n readonly locale: string;\n\n private readonly table: OrbitStrings;\n\n constructor(requested?: string | null, strings?: Partial<OrbitStrings>) {\n const tag = requested ? canonicalTag(requested) : null;\n this.language = tag === null ? 'en' : registered.has(tag) ? tag : registered.has(baseOf(tag)) ? baseOf(tag) : 'en';\n this.locale = tag !== null && (tag === this.language || baseOf(tag) === this.language) ? tag : this.language;\n const table = registered.get(this.language) ?? ENGLISH;\n this.table = strings ? { ...table, ...validStrings(strings, 'strings') } : table;\n }\n\n /** Whether these words are the same as `other`'s: the same language and the same table. */\n sameAs(other: OrbitWords | null): boolean {\n return other !== null && other.locale === this.locale && other.table === this.table;\n }\n\n text(key: TextKey, values?: Values): string {\n return this.fill(this.table[key], values);\n }\n\n /** A text with a number in it, in the form the number takes in the language. */\n count(key: CountKey, count: number, values?: Values): string {\n const forms = this.table[key];\n const category = pluralRules(this.locale)?.select(count) ?? (count === 1 ? 'one' : 'other');\n return this.fill(forms[category] ?? forms.other, { ...values, count });\n }\n\n /** Items as the language lists them: \"a, b and c\". */\n list(items: string[]): string {\n const format = listFormat(this.locale);\n return format ? format.format(items) : items.join(', ');\n }\n\n number(value: number): string {\n return numberFormat(this.locale)?.format(value) ?? String(value);\n }\n\n private fill(template: string, values?: Values): string {\n if (!values) {\n return template;\n }\n\n return template.replace(/\\{(\\w+)\\}/g, (placeholder, name: string) => {\n const value = values[name];\n\n if (value === undefined) {\n return placeholder;\n }\n\n return typeof value === 'number' ? this.number(value) : value;\n });\n }\n}\n\n/** The words a map speaks when it's asked for `requested`, or for the language around `element`. */\nexport const wordsFor = (requested: string | undefined, element: Element | null | undefined, strings?: Partial<OrbitStrings>): OrbitWords => {\n return new OrbitWords(requested ?? languageOf(element), strings);\n};\n\n/** Only known keys with the right kind of value: a mistake in one word shouldn't break the map. */\nconst validStrings = (strings: Partial<OrbitStrings>, source: string): Partial<OrbitStrings> => {\n const valid: Partial<Record<keyof OrbitStrings, unknown>> = {};\n\n if (!strings || typeof strings !== 'object') {\n return valid as Partial<OrbitStrings>;\n }\n\n for (const [key, value] of Object.entries(strings)) {\n if (!KEYS.includes(key as keyof OrbitStrings)) {\n warnOnce(`${source}: Orbit has no words called \"${key}\".`);\n continue;\n }\n\n const plural = typeof ENGLISH[key as keyof OrbitStrings] !== 'string';\n\n if (!plural && typeof value === 'string') {\n valid[key as keyof OrbitStrings] = value;\n } else if (plural && isPluralText(value)) {\n valid[key as keyof OrbitStrings] = pluralText(value);\n } else if (plural && typeof value === 'string') {\n valid[key as keyof OrbitStrings] = { other: value };\n } else {\n warnOnce(`${source}: \"${key}\" should be ${plural ? 'an object of plural forms with at least \"other\"' : 'a string'}.`);\n }\n }\n\n return valid as Partial<OrbitStrings>;\n};\n\nconst isPluralText = (value: unknown): value is OrbitPluralText => {\n return typeof value === 'object' && value !== null && typeof (value as OrbitPluralText).other === 'string';\n};\n\nconst pluralText = (value: OrbitPluralText): OrbitPluralText => {\n const forms: OrbitPluralText = { other: value.other };\n\n for (const category of PLURAL_CATEGORIES) {\n if (typeof value[category] === 'string') {\n forms[category] = value[category];\n }\n }\n\n return forms;\n};\n\nconst canonicalTag = (language: string): string | null => {\n if (typeof language !== 'string' || language.trim() === '') {\n return null;\n }\n\n try {\n const [tag] = Intl.getCanonicalLocales(language.trim().replace(/_/g, '-'));\n return tag ?? null;\n } catch {\n return null;\n }\n};\n\nconst baseOf = (tag: string): string => {\n return tag.split('-')[0];\n};\n\nconst warned = new Set<string>();\n\nconst warnOnce = (message: string): void => {\n if (!warned.has(message)) {\n warned.add(message);\n console.warn(`[orbit] ${message}`);\n }\n};\n\nconst pluralRulesCache = new Map<string, Intl.PluralRules | null>();\nconst numberFormatCache = new Map<string, Intl.NumberFormat | null>();\nconst listFormatCache = new Map<string, Intl.ListFormat | null>();\n\nconst pluralRules = (locale: string): Intl.PluralRules | null => {\n return cached(pluralRulesCache, locale, () => new Intl.PluralRules(locale));\n};\n\nconst numberFormat = (locale: string): Intl.NumberFormat | null => {\n return cached(numberFormatCache, locale, () => new Intl.NumberFormat(locale));\n};\n\nconst listFormat = (locale: string): Intl.ListFormat | null => {\n return cached(listFormatCache, locale, () => (typeof Intl.ListFormat === 'function' ? new Intl.ListFormat(locale, { type: 'conjunction' }) : null));\n};\n\nconst cached = <Value>(cache: Map<string, Value | null>, locale: string, make: () => Value | null): Value | null => {\n if (!cache.has(locale)) {\n try {\n cache.set(locale, make());\n } catch {\n cache.set(locale, null);\n }\n }\n\n return cache.get(locale) ?? null;\n};\n",
|
|
27
28
|
"/**\n * The detail sheet: a node's media, note, status, tags and link. A native\n * `<dialog>` opened as a modal, so it sits in the top layer, traps focus,\n * closes with Esc and makes the page behind it inert. Phones get a bottom\n * sheet that can be swiped down to close.\n */\n\nimport type { OrbitNode } from '../types.js';\nimport { OrbitWords } from '../languages.js';\nimport { guardUrl, resolveUrl } from '../url-guard.js';\nimport { hasMediaSource, isNativeVideoUrl, toVideoEmbedUrl } from '../media.js';\nimport { createActionIcon, createIcon } from './icons.js';\nimport { embedFrame, playerFrame } from './frames.js';\nimport { renderNoteMarkdown } from './note-markdown.js';\nimport { isNodeLink } from '../node-links.js';\n\nexport type DetailSection = 'details' | 'image' | 'video' | 'embed' | 'note';\n\n/** What the map tells the sheet about the node it shows, beyond its content: its type, actions and status look. */\nexport interface SheetExtensions {\n icon(node: OrbitNode): string | undefined;\n typeLabel(node: OrbitNode): string | undefined;\n\n /** Draws the node type's section, if it has one. */\n details(node: OrbitNode): ((element: HTMLElement) => void) | undefined;\n\n actions(node: OrbitNode): { id: string; label: string; icon?: string }[];\n runAction(node: OrbitNode, action: string, event: MouseEvent): void;\n status(word: string): { tone: string; color?: string };\n}\n\nexport interface DetailRequest {\n node: OrbitNode;\n\n /** Ancestors from the root, for the path above the title. */\n path: OrbitNode[];\n\n /** Siblings to step through with the previous / next buttons and arrow keys. */\n siblings: OrbitNode[];\n\n section?: DetailSection;\n baseUrl?: string;\n noteRenderer?: (note: string, context: { node: OrbitNode; format: 'markdown' | 'plain' }) => string;\n\n /** Called when the reader steps to a sibling. */\n onNavigate?: (node: OrbitNode) => void;\n\n /** The node a `#id` link points at, if the map has it. */\n resolveLink?: (href: string) => OrbitNode | null;\n\n /** Called, after the sheet closes, when the reader follows a link to another node. */\n onFollowLink?: (node: OrbitNode) => void;\n\n /** The map's node types, actions and status words. */\n extensions?: SheetExtensions;\n\n /**\n * Opens the media viewer on the node's picture or video: with it, the\n * picture is a button and the video gets one. `startAt` is where the\n * sheet's own player of a video file was.\n */\n onViewMedia?: (node: OrbitNode, kind: 'image' | 'video', event: MouseEvent, startAt?: number) => void;\n\n /** The map's words, in its language. Default: English. */\n words?: OrbitWords;\n}\n\nconst SWIPE_CLOSE_DISTANCE = 80;\nconst ENGLISH = new OrbitWords('en');\n\nexport class DetailSheet {\n private readonly host: HTMLElement;\n private dialog: HTMLDialogElement | null = null;\n private request: DetailRequest | null = null;\n private returnFocus: HTMLElement | SVGElement | null = null;\n\n constructor(host: HTMLElement) {\n this.host = host;\n }\n\n get isOpen(): boolean {\n return this.dialog?.open ?? false;\n }\n\n /** The words of the map that opened the sheet. */\n private get words(): OrbitWords {\n return this.request?.words ?? ENGLISH;\n }\n\n /** The node being shown, if the sheet is open. */\n get node(): OrbitNode | null {\n return this.isOpen ? this.request?.node ?? null : null;\n }\n\n open(request: DetailRequest): void {\n const active = (this.host.ownerDocument ?? document).activeElement;\n\n if (!this.isOpen && (active instanceof HTMLElement || active instanceof SVGElement)) {\n this.returnFocus = active;\n }\n\n this.request = request;\n const dialog = this.ensureDialog();\n dialog.replaceChildren(...this.buildContent(request));\n dialog.setAttribute('aria-label', request.node.text || this.words.text('details'));\n\n if (!dialog.open) {\n if (typeof dialog.showModal === 'function') {\n dialog.showModal();\n } else {\n dialog.setAttribute('open', '');\n }\n }\n\n const target = request.section ? dialog.querySelector(`[data-section=\"${request.section}\"]`) : null;\n target?.scrollIntoView?.({ block: 'nearest' });\n dialog.querySelector<HTMLButtonElement>('.orbit-sheet__close')?.focus();\n }\n\n close(): void {\n const dialog = this.dialog;\n\n if (!dialog || !dialog.open) {\n return;\n }\n\n if (typeof dialog.close === 'function') {\n dialog.close();\n } else {\n dialog.removeAttribute('open');\n }\n\n this.restoreFocus();\n }\n\n /** Closes the sheet, then hands the linked node to the map to fly to. */\n private followLink(node: OrbitNode): void {\n const follow = this.request?.onFollowLink;\n this.close();\n follow?.(node);\n }\n\n destroy(): void {\n this.close();\n this.dialog?.remove();\n this.dialog = null;\n this.request = null;\n }\n\n private restoreFocus(): void {\n const target = this.returnFocus;\n this.returnFocus = null;\n\n if (target && target.isConnected) {\n target.focus({ preventScroll: true });\n }\n }\n\n private ensureDialog(): HTMLDialogElement {\n if (this.dialog) {\n return this.dialog;\n }\n\n const dialog = document.createElement('dialog');\n dialog.className = 'orbit-sheet';\n dialog.addEventListener('close', () => this.restoreFocus());\n\n // A click on the dialog box itself (outside its content) is a backdrop click.\n dialog.addEventListener('click', (event) => {\n if (event.target === dialog) {\n const box = dialog.getBoundingClientRect();\n const inside = event.clientX >= box.left && event.clientX <= box.right && event.clientY >= box.top && event.clientY <= box.bottom;\n\n if (!inside || (box.width === 0 && box.height === 0)) {\n this.close();\n }\n }\n });\n\n dialog.addEventListener('keydown', (event) => {\n if (event.key === 'Escape' && typeof dialog.showModal !== 'function') {\n this.close();\n return;\n }\n\n if ((event.key === 'ArrowLeft' || event.key === 'ArrowRight') && !isEditable(event.target)) {\n if (this.step(event.key === 'ArrowRight' ? 1 : -1)) {\n event.preventDefault();\n }\n }\n });\n\n this.enableSwipeToClose(dialog);\n this.host.appendChild(dialog);\n this.dialog = dialog;\n return dialog;\n }\n\n private step(direction: 1 | -1): boolean {\n const request = this.request;\n\n if (!request) {\n return false;\n }\n\n const index = request.siblings.findIndex((sibling) => sibling.id === request.node.id);\n const next = request.siblings[index + direction];\n\n if (index === -1 || !next) {\n return false;\n }\n\n request.onNavigate?.(next);\n this.open({ ...request, node: next, section: undefined });\n return true;\n }\n\n private enableSwipeToClose(dialog: HTMLDialogElement): void {\n let startY: number | null = null;\n\n dialog.addEventListener('pointerdown', (event) => {\n const handle = (event.target as Element).closest?.('.orbit-sheet__handle, .orbit-sheet__header');\n\n if (handle && event.pointerType !== 'mouse') {\n startY = event.clientY;\n }\n });\n\n dialog.addEventListener('pointermove', (event) => {\n if (startY === null) {\n return;\n }\n\n const distance = Math.max(0, event.clientY - startY);\n dialog.style.transform = distance > 0 ? `translateY(${distance}px)` : '';\n });\n\n const finish = (event: PointerEvent) => {\n if (startY === null) {\n return;\n }\n\n const distance = event.clientY - startY;\n startY = null;\n dialog.style.transform = '';\n\n if (distance > SWIPE_CLOSE_DISTANCE) {\n this.close();\n }\n };\n\n dialog.addEventListener('pointerup', finish);\n dialog.addEventListener('pointercancel', finish);\n }\n\n private buildContent(request: DetailRequest): HTMLElement[] {\n const { node } = request;\n const handle = element('div', 'orbit-sheet__handle');\n\n const header = element('header', 'orbit-sheet__header');\n const heading = element('div', 'orbit-sheet__heading');\n\n if (request.path.length > 0) {\n const path = element('p', 'orbit-sheet__path');\n path.textContent = request.path.map((ancestor) => ancestor.text).join(' › ');\n heading.appendChild(path);\n }\n\n const title = element('h2', 'orbit-sheet__title');\n title.textContent = [request.extensions ? request.extensions.icon(node) : node.icon, node.text].filter(Boolean).join(' ');\n heading.appendChild(title);\n const chips = this.buildChips(node, request.extensions);\n\n if (chips) {\n heading.appendChild(chips);\n }\n\n const close = element('button', 'orbit-button orbit-button--icon orbit-sheet__close');\n close.type = 'button';\n close.setAttribute('aria-label', this.words.text('close'));\n close.appendChild(createIcon('close'));\n close.addEventListener('click', () => this.close());\n header.append(heading, close);\n\n const body = element('div', 'orbit-sheet__body');\n\n for (const media of this.buildMedia(request)) {\n body.appendChild(media);\n }\n\n const details = request.extensions?.details(node);\n\n if (details) {\n const section = element('section', 'orbit-sheet__details');\n section.dataset.section = 'details';\n details(section);\n body.appendChild(section);\n }\n\n if (node.note) {\n const note = element('div', 'orbit-sheet__note');\n note.dataset.section = 'note';\n const format = node.noteFormat ?? 'markdown';\n\n if (request.noteRenderer) {\n // Documented: a custom renderer's HTML is inserted as-is.\n note.innerHTML = request.noteRenderer(node.note, { node, format });\n } else if (format === 'plain') {\n const paragraph = element('p', '');\n paragraph.style.whiteSpace = 'pre-wrap';\n paragraph.textContent = node.note;\n note.appendChild(paragraph);\n } else {\n note.appendChild(renderNoteMarkdown(node.note, { baseUrl: request.baseUrl, resolveLink: request.resolveLink }));\n }\n\n // `#id` links, from the markdown or a custom renderer, go to that node.\n note.addEventListener('click', (event) => {\n const anchor = event.target instanceof Element ? event.target.closest('a[href^=\"#\"]') : null;\n const linked = anchor ? request.resolveLink?.(anchor.getAttribute('href') ?? '') : null;\n\n if (linked) {\n event.preventDefault();\n this.followLink(linked);\n }\n });\n\n body.appendChild(note);\n }\n\n const footer = element('footer', 'orbit-sheet__footer');\n const navigation = element('div', '');\n const index = request.siblings.findIndex((sibling) => sibling.id === node.id);\n\n if (request.siblings.length > 1 && index !== -1) {\n navigation.append(\n this.stepButton('previous', this.words.text('previous'), index > 0, -1),\n this.stepButton('next', this.words.text('next'), index < request.siblings.length - 1, 1),\n );\n }\n\n footer.appendChild(navigation);\n const actions = request.extensions?.actions(node) ?? [];\n\n if (actions.length > 0) {\n const group = element('div', 'orbit-sheet__actions');\n\n for (const action of actions) {\n const button = element('button', 'orbit-sheet__action');\n button.type = 'button';\n button.dataset.action = action.id;\n button.append(createActionIcon(action.icon, action.label), document.createTextNode(action.label));\n\n // The sheet closes first, so what the action opens isn't behind it.\n button.addEventListener('click', (event) => {\n const run = request.extensions?.runAction;\n this.close();\n run?.(node, action.id, event);\n });\n\n group.appendChild(button);\n }\n\n footer.appendChild(group);\n }\n\n const linked = isNodeLink(node.link) ? request.resolveLink?.(node.link) ?? null : null;\n const link = node.link && !isNodeLink(node.link) ? guardUrl(node.link, 'link') : null;\n\n if (linked) {\n const button = element('button', 'orbit-sheet__link');\n button.type = 'button';\n button.textContent = `${this.words.text('goTo', { name: linked.text || this.words.text('theIdea') })} →`;\n button.addEventListener('click', () => this.followLink(linked));\n footer.appendChild(button);\n } else if (link) {\n const anchor = element('a', 'orbit-sheet__link');\n anchor.href = resolveUrl(link, request.baseUrl);\n anchor.target = '_blank';\n anchor.rel = 'noopener noreferrer';\n anchor.textContent = `${this.words.text('openLink')} ↗`;\n footer.appendChild(anchor);\n }\n\n const parts = [handle, header, body];\n\n if (navigation.childElementCount > 0 || link || linked || actions.length > 0) {\n parts.push(footer);\n }\n\n return parts;\n }\n\n private stepButton(icon: 'previous' | 'next', label: string, enabled: boolean, direction: 1 | -1): HTMLButtonElement {\n const button = element('button', 'orbit-button orbit-button--icon');\n button.type = 'button';\n button.setAttribute('aria-label', label);\n button.disabled = !enabled;\n button.appendChild(createIcon(icon));\n button.addEventListener('click', () => this.step(direction));\n return button;\n }\n\n private buildChips(node: OrbitNode, extensions: SheetExtensions | undefined): HTMLElement | null {\n const chips: HTMLElement[] = [];\n const typeLabel = extensions?.typeLabel(node);\n\n if (typeLabel) {\n const chip = element('span', 'orbit-sheet__chip orbit-sheet__chip--type');\n chip.textContent = typeLabel;\n chips.push(chip);\n }\n\n if (node.status) {\n const chip = element('span', 'orbit-sheet__chip orbit-sheet__chip--status');\n chip.textContent = node.status;\n const look = extensions?.status(node.status) ?? { tone: statusTone(node.status) };\n chip.style.setProperty('--orbit-chip-dot', look.color ?? `var(--_orbit-status-${look.tone})`);\n chips.push(chip);\n }\n\n if (node.priority !== undefined) {\n const chip = element('span', 'orbit-sheet__chip');\n chip.textContent = this.words.text('priority', { priority: node.priority });\n chips.push(chip);\n }\n\n for (const tag of node.tags ?? []) {\n const chip = element('span', 'orbit-sheet__chip');\n chip.textContent = `#${tag}`;\n chips.push(chip);\n }\n\n if (chips.length === 0) {\n return null;\n }\n\n const container = element('div', 'orbit-sheet__chips');\n container.append(...chips);\n return container;\n }\n\n private buildMedia(request: DetailRequest): HTMLElement[] {\n const { node, baseUrl, onViewMedia } = request;\n const figures: HTMLElement[] = [];\n\n if (hasMediaSource(node.image)) {\n const source = guardUrl(node.image.src, 'image');\n\n if (source) {\n const figure = this.figure('image', node.image.caption);\n const image = document.createElement('img');\n image.src = resolveUrl(source, baseUrl);\n image.alt = node.image.alt ?? '';\n\n if (onViewMedia) {\n const button = element('button', 'orbit-sheet__picture');\n button.type = 'button';\n button.setAttribute('aria-label', image.alt ? this.words.text('viewImageOf', { description: image.alt }) : this.words.text('viewImage'));\n button.appendChild(image);\n button.addEventListener('click', (event) => onViewMedia(node, 'image', event));\n figure.prepend(button);\n } else {\n figure.prepend(image);\n }\n\n figures.push(figure);\n }\n }\n\n if (hasMediaSource(node.video)) {\n const source = guardUrl(node.video.src, 'video');\n\n if (source) {\n const resolved = resolveUrl(source, baseUrl);\n // The same rule the media viewer's createPlayer applies: files, blob: URLs and provider 'native' play in a <video>.\n let player: HTMLVideoElement | HTMLIFrameElement | null = null;\n\n if (node.video.provider === 'native' || isNativeVideoUrl(resolved) || /^blob:/i.test(resolved)) {\n const video = document.createElement('video');\n video.src = resolved;\n video.controls = true;\n video.preload = 'metadata';\n player = video;\n } else {\n const embed = toVideoEmbedUrl(resolved, node.video.provider);\n player = embed ? playerFrame(embed, node.text) : embedFrame(resolved, baseUrl, node.text);\n\n if (player) {\n player.loading = 'lazy';\n }\n }\n\n if (player) {\n const figure = this.figure('video', node.video.caption);\n figure.prepend(player);\n\n if (onViewMedia) {\n figure.appendChild(this.expandButton(figure, (event, startAt) => onViewMedia(node, 'video', event, startAt)));\n }\n\n figures.push(figure);\n }\n }\n }\n\n if (hasMediaSource(node.embed) && !hasMediaSource(node.video)) {\n const frame = embedFrame(node.embed.src, baseUrl, node.text);\n\n if (frame) {\n frame.loading = 'lazy';\n const figure = this.figure('embed', node.embed.caption);\n figure.prepend(frame);\n figures.push(figure);\n }\n }\n\n return figures;\n }\n\n /**\n * The button that moves a video to the media viewer. The sheet's own\n * player stops first; a video file goes on from where it was.\n */\n private expandButton(figure: HTMLElement, expand: (event: MouseEvent, startAt?: number) => void): HTMLButtonElement {\n const button = element('button', 'orbit-sheet__expand');\n button.type = 'button';\n button.setAttribute('aria-label', this.words.text('expandVideo'));\n button.append(createIcon('expand'), document.createTextNode(this.words.text('expand')));\n\n button.addEventListener('click', (event) => {\n let startAt: number | undefined;\n const video = figure.querySelector('video');\n\n if (video) {\n startAt = video.currentTime > 0 ? video.currentTime : undefined;\n video.pause();\n }\n\n // A frame stops playing only by loading again.\n const frame = figure.querySelector('iframe');\n frame?.replaceWith(frame.cloneNode(true));\n expand(event, startAt);\n });\n\n return button;\n }\n\n private figure(section: DetailSection, caption: string | undefined): HTMLElement {\n const figure = element('figure', 'orbit-sheet__media');\n figure.dataset.section = section;\n\n if (caption) {\n const text = element('figcaption', '');\n text.textContent = caption;\n figure.appendChild(text);\n }\n\n return figure;\n }\n}\n\n/** Maps a free-text status onto a theme color: active, done, blocked, todo or neutral. */\nexport const statusTone = (status: string): 'active' | 'done' | 'blocked' | 'todo' | 'neutral' => {\n const value = status.trim().toLowerCase();\n\n if (/^(done|complete|completed|shipped|finished|closed)$/.test(value)) {\n return 'done';\n }\n\n if (/^(active|doing|in[ -]?progress|wip|started|ongoing)$/.test(value)) {\n return 'active';\n }\n\n if (/^(blocked|stuck|at[ -]?risk|failed)$/.test(value)) {\n return 'blocked';\n }\n\n if (/^(todo|to[ -]?do|planned|backlog|next|open)$/.test(value)) {\n return 'todo';\n }\n\n return 'neutral';\n};\n\nconst element = <Name extends keyof HTMLElementTagNameMap>(name: Name, className: string): HTMLElementTagNameMap[Name] => {\n const created = document.createElement(name);\n\n if (className) {\n created.className = className;\n }\n\n return created;\n};\n\nconst isEditable = (target: EventTarget | null): boolean => {\n return target instanceof HTMLElement && (target.isContentEditable || /^(INPUT|TEXTAREA|SELECT|IFRAME|VIDEO)$/.test(target.tagName));\n};\n",
|
|
28
29
|
"/**\n * Ways to extend Orbit: node types, actions and status words. Each works for\n * one map, through its options, or for every map once registered, which also\n * covers `<orbit-map>` elements and maps in markdown pages. A map's own\n * options win over registered ones.\n */\n\nimport type { OrbitNode } from './types.js';\nimport type { OrbitThemeToken } from './themes.js';\nimport { statusTone } from './ui/detail-sheet.js';\n\n/** The colored dots statuses get. */\nexport type OrbitStatusTone = 'active' | 'done' | 'blocked' | 'todo' | 'neutral';\n\n/** How a status word looks: one of the dot tones, or any CSS color. */\nexport type OrbitStatusStyle = OrbitStatusTone | (string & {});\n\n/** A button under the focused node and in its detail sheet. */\nexport interface OrbitAction {\n /** Names the action in the `action` event: `event.action === 'assign'`. */\n id: string;\n\n /** The button's name, read by screen readers, shown as its tooltip and in the detail sheet. */\n label: string | ((node: OrbitNode) => string);\n\n /**\n * The icon: an emoji or short symbol (`'✏️'`), SVG path data on a 24-unit\n * grid (`'M4 20h4L20 8l-4-4L4 16z'`), or one of Orbit's icons (`'note'`,\n * `'link'`, `'goto'`, `'image'`, `'video'`, `'list'`). Default: the\n * label's first letter.\n */\n icon?: string;\n\n /** Which nodes offer the action. Default: every node. */\n when?: (node: OrbitNode) => boolean;\n\n /** Runs when the button is pressed, unless an `action` listener prevents it. */\n run: (node: OrbitNode, event: MouseEvent | KeyboardEvent) => void;\n}\n\n/** How nodes of one type look and behave. Nodes pick a type with `type: name`. */\nexport interface OrbitNodeType {\n /** The type's name for people, shown in the detail sheet and the tooltip: `'Milestone'`. */\n label?: string;\n\n /** The icon these nodes get unless they set their own. */\n icon?: string;\n\n /** The color these nodes get unless they set their own; their children take shades of it. */\n color?: string;\n\n /**\n * Theme tokens for these nodes only, without `--orbit-`: their rim,\n * shadow, glow, label and status colors, such as\n * `{ 'node-stroke': '#B45309', 'node-stroke-width': '3' }`.\n */\n tokens?: Partial<Record<OrbitThemeToken, string>>;\n\n /**\n * Draws inside the node, the way a picture does: `element` is a 100 × 100 px\n * box clipped to the node's circle and scaled with it, and the label moves\n * outside. Return a function to clean up when the node leaves the map.\n */\n render?: (node: OrbitNode, element: HTMLElement) => void | (() => void);\n\n /** Adds a section to the detail sheet, above the note; the node gets a \"Details\" button. */\n details?: (node: OrbitNode, element: HTMLElement) => void;\n\n /** Actions only nodes of this type offer, after the map's own. */\n actions?: OrbitAction[];\n\n /**\n * The version of the fields these nodes keep in their attributes, once\n * the type changes them: 1 at first. Nodes say which version they were\n * written for (`type: task@2`; none means 1), and older ones are brought\n * up to date with `upgrade` when a map is drawn.\n */\n version?: number;\n\n /**\n * Brings a node written for an older version of the type up to date:\n * renames or reshapes its attributes, in place. `from` is the version it\n * was written for. Runs once per node when a map is drawn (or with\n * `upgradeNodeTypes`), and the next save writes the node as upgraded.\n * Nodes written for a newer version than this one are left as they are.\n */\n upgrade?: (node: OrbitNode, from: number) => void;\n}\n\n/** The extensions a map is created with, before the registered ones. */\nexport interface OrbitExtensionOptions {\n /** Node types by name. */\n nodeTypes?: Record<string, OrbitNodeType>;\n\n /** Actions every node offers (or the ones `when` picks). */\n actions?: OrbitAction[];\n\n /** Status words and how they look: `{ review: 'active', 'on hold': '#A855F7' }`. */\n statuses?: Record<string, OrbitStatusStyle>;\n\n /**\n * The type a node is drawn as when it names none: its look, content and\n * actions, as if it said `type: name`, for display only. Orbit never writes\n * it to the map, never upgrades a node for it, and asks again whenever it\n * draws, so return undefined to draw the node as it is. Called often: keep\n * it quick.\n */\n nodeTypeFor?: (node: OrbitNode) => string | undefined;\n}\n\nconst registeredTypes = new Map<string, OrbitNodeType>();\nconst registeredActions = new Map<string, OrbitAction>();\nconst registeredStatuses = new Map<string, OrbitStatusStyle>();\n\n/**\n * Defines a node type for every map: nodes with `type: name` (any case) take\n * it. Returns a function that removes it again.\n */\nexport const registerNodeType = (name: string, definition: OrbitNodeType): () => void => {\n return register(registeredTypes, wordKey(name), definition);\n};\n\n/** Adds an action to every map. Returns a function that removes it again. */\nexport const registerAction = (action: OrbitAction): () => void => {\n return register(registeredActions, action.id, action);\n};\n\n/**\n * Gives a status word its look on every map: one of the tones (`active`,\n * `done`, `blocked`, `todo`, `neutral`) or any CSS color. Returns a function\n * that removes it again.\n */\nexport const registerStatus = (word: string, style: OrbitStatusStyle): () => void => {\n return register(registeredStatuses, wordKey(word), style);\n};\n\nconst register = <Value>(registry: Map<string, Value>, key: string, value: Value): () => void => {\n registry.set(key, value);\n\n return () => {\n if (registry.get(key) === value) {\n registry.delete(key);\n }\n };\n};\n\n/** Types and status words match whatever their case and surrounding spaces. */\nconst wordKey = (word: string): string => {\n return word.trim().toLowerCase();\n};\n\nconst TONES = new Set<string>(['active', 'done', 'blocked', 'todo', 'neutral']);\n\n/** How a status looks on a map: its tone, and its own color when it has one. */\nexport interface StatusLook {\n tone: OrbitStatusTone;\n color?: string;\n}\n\n/**\n * One map's view of the extensions: its own node types, actions and status\n * words first, then the registered ones. Lookups read the registries each\n * time, so a type registered after the map was created applies on its next\n * redraw.\n */\nexport class MapExtensions {\n private readonly types = new Map<string, OrbitNodeType>();\n private readonly statuses = new Map<string, OrbitStatusStyle>();\n private readonly actionList: OrbitAction[];\n private readonly typeFor: ((node: OrbitNode) => string | undefined) | undefined;\n\n /** `nodeTypeFor` threw: it's asked on every frame, so the console hears of it once. */\n private typeForFailed = false;\n\n constructor(options: OrbitExtensionOptions = {}) {\n for (const [name, definition] of Object.entries(options.nodeTypes ?? {})) {\n this.types.set(wordKey(name), definition);\n }\n\n for (const [word, style] of Object.entries(options.statuses ?? {})) {\n this.statuses.set(wordKey(word), style);\n }\n\n this.actionList = options.actions ?? [];\n this.typeFor = options.nodeTypeFor;\n }\n\n /**\n * The name of the type the node is drawn as: its own `type`, or for a node\n * that names none, the one `nodeTypeFor` gives it for display.\n */\n typeName(node: OrbitNode): string | undefined {\n if (node.type) {\n return node.type;\n }\n\n const typeFor = this.typeFor;\n\n if (!typeFor) {\n return undefined;\n }\n\n let name: string | undefined;\n\n try {\n name = typeFor(node);\n } catch (error) {\n if (!this.typeForFailed) {\n this.typeForFailed = true;\n console.error('[orbit] nodeTypeFor() threw:', error);\n }\n\n return undefined;\n }\n\n return typeof name === 'string' && name.trim() !== '' ? name : undefined;\n }\n\n /** The type the node is drawn as, if this map knows it: its own, or one given for display (see `typeName`). */\n nodeType(node: OrbitNode): OrbitNodeType | undefined {\n const name = this.typeName(node);\n return name === undefined ? undefined : this.typeNamed(name);\n }\n\n /** The node's own type (`type`), never one given for display: what upgrades go by. */\n ownType(node: OrbitNode): OrbitNodeType | undefined {\n return node.type ? this.typeNamed(node.type) : undefined;\n }\n\n private typeNamed(name: string): OrbitNodeType | undefined {\n const key = wordKey(name);\n return this.types.get(key) ?? registeredTypes.get(key);\n }\n\n /** The node's icon: its own, or its type's. */\n icon(node: OrbitNode): string | undefined {\n return node.icon ?? this.nodeType(node)?.icon;\n }\n\n /** The node's own color, or its type's. */\n color(node: OrbitNode): string | undefined {\n return node.color ?? this.nodeType(node)?.color;\n }\n\n /** The actions a node offers: the map's, the registered ones, then its type's, each id once. */\n actions(node: OrbitNode): OrbitAction[] {\n const seen = new Set<string>();\n const offered: OrbitAction[] = [];\n\n for (const action of [...this.actionList, ...registeredActions.values(), ...(this.nodeType(node)?.actions ?? [])]) {\n if (seen.has(action.id)) {\n continue;\n }\n\n seen.add(action.id);\n\n if (!action.when || guarded(`the \"${action.id}\" action's when()`, false, () => action.when!(node))) {\n offered.push(action);\n }\n }\n\n return offered;\n }\n\n /** How a status looks: a word this map or a registration names, or one of the built-in words. */\n status(word: string): StatusLook {\n const key = wordKey(word);\n const style = this.statuses.get(key) ?? registeredStatuses.get(key);\n\n if (style === undefined) {\n return { tone: statusTone(word) };\n }\n\n return TONES.has(style) ? { tone: style as OrbitStatusTone } : { tone: 'neutral', color: style };\n }\n}\n\n/**\n * Brings nodes written for older versions of their types up to date (see\n * `OrbitNodeType.version`), with the types `nodeTypes` defines or the\n * registered ones. Maps do this when they're drawn; this is for documents\n * read without one, on a server or in a script. Returns how many nodes\n * were upgraded.\n */\nexport const upgradeNodeTypes = (root: OrbitNode, nodeTypes?: Record<string, OrbitNodeType>): number => {\n return upgradeTypes(root, new MapExtensions({ nodeTypes }));\n};\n\n/** Upgrades the nodes under `root` with the types `extensions` knows. */\nexport const upgradeTypes = (root: OrbitNode, extensions: MapExtensions): number => {\n let upgraded = 0;\n\n const visit = (node: OrbitNode): void => {\n // Only a type the node names: one given for display is never written, so there's nothing to upgrade.\n const type = extensions.ownType(node);\n const from = node.typeVersion ?? 1;\n\n if (type?.version !== undefined && type.upgrade && from < type.version) {\n const upgrade = type.upgrade;\n\n const done = guarded(`the \"${node.type}\" type's upgrade()`, false, () => {\n upgrade(node, from);\n return true;\n });\n\n if (done) {\n node.typeVersion = type.version;\n upgraded += 1;\n }\n }\n\n node.children.forEach(visit);\n };\n\n visit(root);\n return upgraded;\n};\n\n/** An action's label for a node. */\nexport const actionLabel = (action: OrbitAction, node: OrbitNode): string => {\n return typeof action.label === 'function' ? guarded(`the \"${action.id}\" action's label()`, action.id, () => (action.label as (node: OrbitNode) => string)(node)) : action.label;\n};\n\n/**\n * Runs code a map was extended with. If it throws, the map carries on and\n * the console says which extension failed.\n */\nexport const guarded = <Result>(what: string, fallback: Result, run: () => Result): Result => {\n try {\n return run();\n } catch (error) {\n console.error(`[orbit] ${what} threw:`, error);\n return fallback;\n }\n};\n",
|
|
29
|
-
"import type { OrbitNode } from './types.js';\nimport { clamp } from './utils.js';\n\n/** Where the layout puts the map and how much room it has. */\nexport interface LayoutConfig {\n cx: number;\n cy: number;\n containerWidth: number;\n containerHeight: number;\n\n /** Levels below the layout root to render; deeper nodes are omitted. */\n maxDepth?: number;\n\n /**\n * Focus layouts: ring radii to keep where the orbit has as many rings,\n * instead of making room for the moons again. A drag along the orbit keeps\n * the rings it began with. Rings never come out smaller than the planets need.\n */\n keptRings?: number[];\n}\n\n/** A node with its place in the layout. */\nexport interface PositionedNode extends OrbitNode {\n x: number;\n y: number;\n radius: number;\n\n /** Degrees: 0 is right, -90 is up. */\n angle: number;\n\n /** Distance from the parent. */\n orbitRadius: number;\n}\n\ninterface MeasuredNode {\n node: OrbitNode;\n radius: number;\n subtreeRadius: number;\n childOrbitRadius: number;\n children: MeasuredNode[];\n}\n\nconst SPACING_FACTOR = 1.32;\nconst NODE_GAP = 14;\nconst MIN_SUN_RADIUS = 34;\nconst MIN_PLANET_RADIUS = 18;\nconst MAX_SUN_RADIUS = 76;\nconst MAX_PLANET_RADIUS = 48;\nconst MAX_FOCUS_RING_COUNT = 7;\nconst FOCUS_RING_GAP_FACTOR = 2.15;\n/**\n * Crowded orbits of planets without moons pack closer: rings start right\n * outside the sun and sit a planet's width apart, with more of them, so the\n * planets come out as big as the screen allows.\n */\nconst COMPACT_RING_GAP = 8;\nconst MAX_COMPACT_RING_COUNT = 12;\n/** An orbit of this many rings or more is crowded: its sun grows (see calculateFocusLayout). */\nconst CROWDED_RING_COUNT = 4;\n\n/** Moons drawn around a planet; more children show as \"+N\". */\nexport const MOON_LIMIT = 6;\n/**\n * The room kept between a moon and another planet. Moons of different\n * planets keep a moon's radius apart, so that where two fans meet they read\n * as two.\n */\nconst MOON_CLEARANCE = 2;\n\n/** Where a planet's moons go: `distance` from its center, at `offsets` degrees from the direction away from the sun. */\nexport interface MoonPlacement {\n distance: number;\n radius: number;\n offsets: number[];\n}\n\n/** The moons of a planet fan out on its outer side, 30° apart, 150° at most. */\nexport const moonPlacement = (planetRadius: number, moonCount: number): MoonPlacement => {\n const count = Math.min(moonCount, MOON_LIMIT);\n const spread = Math.min(150, (count - 1) * 30);\n return {\n distance: planetRadius * 1.45,\n radius: Math.min(7, Math.max(2.5, planetRadius * 0.17)),\n offsets: Array.from({ length: count }, (_, index) => (count === 1 ? 0 : -spread / 2 + (spread * index) / (count - 1))),\n };\n};\n\n/**\n * Calculate layout for focus mode (center sun + direct children).\n * The orbit radius is never clamped below the collision-free radius. If the\n * result is wider than the container, the renderer auto-fits the whole group.\n */\nexport const calculateFocusLayout = (\n focusedNode: OrbitNode,\n config: LayoutConfig,\n): { sun: PositionedNode; planets: PositionedNode[]; orbitRadius: number; orbitRings: number[] } => {\n const { cx, cy, containerWidth, containerHeight } = config;\n const depthCapped = config.maxDepth !== undefined && focusedNode.level >= config.maxDepth;\n const children = depthCapped ? [] : visibleChildren(focusedNode);\n const childCount = children.length;\n const baseDim = layoutBasis(containerWidth, containerHeight);\n\n let sunRadius = clamp(baseDim * 0.115, MIN_SUN_RADIUS, MAX_SUN_RADIUS);\n const planetDensityScale = childCount === 0\n ? 1\n : clamp(Math.pow(10 / childCount, 0.32), 0.58, 1.1);\n const planetRadius = clamp(\n baseDim * 0.074 * planetDensityScale,\n MIN_PLANET_RADIUS,\n MAX_PLANET_RADIUS,\n );\n const compact = children.every((child) => visibleChildren(child).length === 0);\n let orbitPlan = calculateFocusRingPlan(childCount, sunRadius, planetRadius, baseDim, compact);\n\n // A crowded orbit shrinks its sun on screen with everything else: the sun grows with its rings,\n // so the focused node stays the focus and its name stays legible.\n if (orbitPlan.rings.length >= CROWDED_RING_COUNT) {\n const grown = Math.min(MAX_SUN_RADIUS, sunRadius * (1 + 0.06 * (orbitPlan.rings.length - 1)));\n\n if (grown > sunRadius) {\n sunRadius = grown;\n orbitPlan = calculateFocusRingPlan(childCount, sunRadius, planetRadius, baseDim, compact);\n }\n }\n\n const keptRings = config.keptRings;\n\n if (keptRings && keptRings.length === orbitPlan.rings.length) {\n orbitPlan.rings = orbitPlan.rings.map((radius, index) => Math.max(radius, keptRings[index]));\n } else {\n const moonsHidden = config.maxDepth !== undefined && focusedNode.level + 1 >= config.maxDepth;\n const moonCounts = children.map((child) => (moonsHidden ? 0 : Math.min(visibleChildren(child).length, MOON_LIMIT)));\n makeRoomForMoons(orbitPlan, planetRadius, moonCounts);\n }\n\n const orbitRadius = orbitPlan.rings[orbitPlan.rings.length - 1] ?? 0;\n\n const sun: PositionedNode = {\n ...focusedNode,\n parent: focusedNode.parent,\n x: cx,\n y: cy,\n radius: sunRadius,\n angle: -90,\n orbitRadius: 0,\n };\n\n const planets: PositionedNode[] = [];\n let childIndex = 0;\n\n orbitPlan.rings.forEach((ringRadius, ringIndex) => {\n const ringCount = orbitPlan.counts[ringIndex] ?? 0;\n const angleStep = 360 / ringCount;\n const startAngle = ringStartAngle(ringIndex, ringCount);\n\n for (let localIndex = 0; localIndex < ringCount; localIndex += 1) {\n const child = children[childIndex];\n\n if (!child) {\n break;\n }\n\n const angleDeg = startAngle + angleStep * localIndex;\n const angleRad = toRadians(angleDeg);\n\n planets.push({\n ...child,\n parent: child.parent,\n x: cx + ringRadius * Math.cos(angleRad),\n y: cy + ringRadius * Math.sin(angleRad),\n radius: planetRadius,\n angle: angleDeg,\n orbitRadius: ringRadius,\n });\n childIndex += 1;\n }\n });\n\n return { sun, planets, orbitRadius, orbitRings: orbitPlan.rings };\n};\n\n/**\n * Calculate layout for all mode. Each node owns a measured subtree circle; a\n * parent's child orbit is sized so sibling subtree circles cannot overlap.\n */\nexport const calculateAllLayout = (\n node: OrbitNode,\n config: LayoutConfig,\n parentAngle: number = -90,\n): PositionedNode[] => {\n const baseDim = layoutBasis(config.containerWidth, config.containerHeight);\n const complexityScale = clamp(Math.pow(18 / countVisibleNodes(node), 0.18), 0.74, 1.08);\n const measured = measureSubtree(node, baseDim, complexityScale, config.maxDepth ?? Infinity);\n const positionedNodes: PositionedNode[] = [];\n\n placeSubtree(measured, config.cx, config.cy, parentAngle, 0, positionedNodes);\n return positionedNodes;\n};\n\n/**\n * The rings of the overview: one around each node with children, through them.\n */\nexport const getOrbitRings = (\n positionedNodes: PositionedNode[],\n): { centerId: string; cx: number; cy: number; r: number }[] => {\n const rings: { centerId: string; cx: number; cy: number; r: number }[] = [];\n const seen = new Set<string>();\n\n for (const node of positionedNodes) {\n if (visibleChildren(node).length === 0) {\n continue;\n }\n\n const childNode = positionedNodes.find(\n (n) => n.parent?.id === node.id && n.id !== node.id,\n );\n\n if (!childNode) {\n continue;\n }\n\n const dx = childNode.x - node.x;\n const dy = childNode.y - node.y;\n const r = Math.sqrt(dx * dx + dy * dy);\n const key = `${node.x.toFixed(1)},${node.y.toFixed(1)},${r.toFixed(1)}`;\n\n if (!seen.has(key) && r > 10) {\n seen.add(key);\n rings.push({ centerId: node.id, cx: node.x, cy: node.y, r });\n }\n }\n\n return rings;\n};\n\nconst measureSubtree = (\n node: OrbitNode,\n baseDim: number,\n complexityScale: number,\n depthRemaining: number,\n): MeasuredNode => {\n const radius = radiusForLevel(baseDim, node.level, complexityScale);\n const children = depthRemaining > 0 ? visibleChildren(node) : [];\n const childMeasures = children.map((child) => measureSubtree(child, baseDim, complexityScale, depthRemaining - 1));\n\n const childBounds = childMeasures.map((child) => child.subtreeRadius);\n const childOrbitRadius = requiredOrbitRadius(radius, childBounds);\n const maxChildBound = childBounds.length > 0 ? Math.max(...childBounds) : 0;\n\n return {\n node,\n radius,\n subtreeRadius: Math.max(radius, childOrbitRadius + maxChildBound),\n childOrbitRadius,\n children: childMeasures,\n };\n};\n\nconst MAX_FAN_DEGREES = 270;\n\nconst placeSubtree = (\n measured: MeasuredNode,\n x: number,\n y: number,\n angle: number,\n orbitRadius: number,\n positionedNodes: PositionedNode[],\n): void => {\n const positioned: PositionedNode = {\n ...measured.node,\n parent: measured.node.parent,\n x,\n y,\n radius: measured.radius,\n angle,\n orbitRadius,\n };\n\n positionedNodes.push(positioned);\n\n const childCount = measured.children.length;\n\n if (childCount === 0) {\n return;\n }\n\n const isRoot = measured.node.level === 0;\n const fullCircle = isRoot || childCount === 1;\n const naturalFan = (childCount - 1) * (360 / childCount);\n const fanDegrees = fullCircle ? 360 : Math.min(naturalFan, MAX_FAN_DEGREES);\n const angleStep = childCount === 1\n ? 0\n : fullCircle\n ? 360 / childCount\n : fanDegrees / (childCount - 1);\n\n const startAngle = childCount === 1\n ? angle\n : isRoot\n ? -90\n : angle - fanDegrees / 2;\n\n measured.children.forEach((child, index) => {\n const childAngle = startAngle + angleStep * index;\n const angleRad = toRadians(childAngle);\n const childX = x + measured.childOrbitRadius * Math.cos(angleRad);\n const childY = y + measured.childOrbitRadius * Math.sin(angleRad);\n placeSubtree(child, childX, childY, childAngle, measured.childOrbitRadius, positionedNodes);\n });\n};\n\nconst requiredOrbitRadius = (centerRadius: number, childRadii: number[]): number => {\n if (childRadii.length === 0) {\n return 0;\n }\n\n const parentClearance = Math.max(\n ...childRadii.map((childRadius) => centerRadius + childRadius + NODE_GAP),\n );\n\n if (childRadii.length === 1) {\n return parentClearance;\n }\n\n const angleStep = (2 * Math.PI) / childRadii.length;\n const chordFactor = 2 * Math.sin(angleStep / 2);\n\n const siblingClearance = childRadii.reduce((max, childRadius, index) => {\n const nextRadius = childRadii[(index + 1) % childRadii.length];\n const required = ((childRadius + nextRadius) * SPACING_FACTOR + NODE_GAP) / chordFactor;\n return Math.max(max, required);\n }, 0);\n\n return Math.max(parentClearance, siblingClearance);\n};\n\nconst calculateFocusRingPlan = (\n childCount: number,\n sunRadius: number,\n planetRadius: number,\n baseDim: number,\n compact = false,\n): RingPlan => {\n if (childCount === 0) {\n return { rings: [], counts: [], ringGap: 0 };\n }\n\n const roomy = ringPlan(\n childCount,\n planetRadius,\n Math.max(baseDim * 0.26, sunRadius + planetRadius + NODE_GAP * 1.3),\n planetRadius * FOCUS_RING_GAP_FACTOR + NODE_GAP,\n MAX_FOCUS_RING_COUNT,\n );\n\n // One ring keeps its roomy layout. Planets without moons that need several\n // rings pack closer, when that makes the orbit smaller.\n if (!compact || roomy.rings.length <= 1) {\n return roomy;\n }\n\n const close = ringPlan(childCount, planetRadius, sunRadius + planetRadius + NODE_GAP, planetRadius * 2 + COMPACT_RING_GAP, MAX_COMPACT_RING_COUNT);\n return (close.rings.at(-1) ?? 0) < (roomy.rings.at(-1) ?? 0) ? close : roomy;\n};\n\n/** The rings of a focus view, the number of planets on each, and the distance between rings. */\ninterface RingPlan {\n rings: number[];\n counts: number[];\n ringGap: number;\n}\n\n/** Rings from `innerRingRadius` out, `ringGap` apart, until they hold every child (or there are `maximumRings`). */\nconst ringPlan = (\n childCount: number,\n planetRadius: number,\n innerRingRadius: number,\n ringGap: number,\n maximumRings: number,\n): RingPlan => {\n const rings: number[] = [];\n let totalCapacity = 0;\n\n while (totalCapacity < childCount && rings.length < maximumRings) {\n const radius = innerRingRadius + ringGap * rings.length;\n rings.push(radius);\n totalCapacity += focusRingCapacity(radius, planetRadius);\n }\n\n const counts = distributeAcrossRings(childCount, rings, planetRadius);\n return { rings, counts, ringGap };\n};\n\n/** The first planet on each ring is at the top; every other ring is turned half a step. */\nconst ringStartAngle = (ringIndex: number, count: number): number => {\n return ringIndex % 2 === 0 ? -90 : -90 + 360 / count / 2;\n};\n\ninterface Circle {\n x: number;\n y: number;\n radius: number;\n}\n\n/** A planet on a ring and its moons. */\ninterface PlanetBodies {\n planet: Circle;\n moons: Circle[];\n}\n\nconst planetBodies = (ringRadius: number, angle: number, planetRadius: number, moonCount: number): PlanetBodies => {\n const x = ringRadius * Math.cos(toRadians(angle));\n const y = ringRadius * Math.sin(toRadians(angle));\n const { distance, radius, offsets } = moonPlacement(planetRadius, moonCount);\n return {\n planet: { x, y, radius: planetRadius },\n moons: offsets.map((offset) => ({\n x: x + distance * Math.cos(toRadians(angle + offset)),\n y: y + distance * Math.sin(toRadians(angle + offset)),\n radius,\n })),\n };\n};\n\nconst apart = (first: Circle, second: Circle, gap: number): boolean => {\n return Math.hypot(first.x - second.x, first.y - second.y) >= first.radius + second.radius + gap;\n};\n\n/** Whether the moons of either planet keep clear of the other planet and its moons (see `MOON_CLEARANCE`). */\nconst moonsClear = (first: PlanetBodies, second: PlanetBodies): boolean => {\n return first.moons.every((moon) => apart(moon, second.planet, MOON_CLEARANCE) && second.moons.every((other) => apart(moon, other, moon.radius)))\n && second.moons.every((moon) => apart(moon, first.planet, MOON_CLEARANCE));\n};\n\n/** Whether every moon of `planet` is nearer it than `neighbor`: a moon past the middle reads as the neighbor's. */\nconst moonsOnOwnSide = (planet: PlanetBodies, neighbor: PlanetBodies): boolean => {\n return planet.moons.every((moon) => {\n return Math.hypot(moon.x - planet.planet.x, moon.y - planet.planet.y) < Math.hypot(moon.x - neighbor.planet.x, moon.y - neighbor.planet.y);\n });\n};\n\n/**\n * Rings are planned for the planets' bodies, but moons fan out on the outer\n * side of their planets, toward the neighbors on the ring and the next ring\n * out. Each ring with moons on it or inside it moves out (and the rings\n * beyond it with it) just as far as its moons need; orbits whose moons\n * already have room keep their rings.\n */\nconst makeRoomForMoons = (plan: RingPlan, planetRadius: number, moonCounts: number[]): void => {\n if (moonCounts.every((count) => count === 0)) {\n return;\n }\n\n const moonReach = moonPlacement(planetRadius, 1);\n // Planets farther apart than this can't touch each other's moons.\n const reach = 2 * (moonReach.distance + moonReach.radius) + Math.max(MOON_CLEARANCE, moonReach.radius);\n let first = 0;\n let inner: { radius: number; start: number; step: number; planets: PlanetBodies[] } | undefined;\n\n plan.rings.forEach((planned, ringIndex) => {\n const count = plan.counts[ringIndex] ?? 0;\n const moons = moonCounts.slice(first, first + count);\n const start = ringStartAngle(ringIndex, count);\n const step = 360 / Math.max(1, count);\n const innerPlanets = inner?.planets.some((planet) => planet.moons.length > 0) ? inner : undefined;\n // Neighbors on a ring are all `step` apart, so one pair of each kind tells for all of them.\n const neighborPairs = count < 2\n ? []\n : [...new Set(moons.map((moonCount, index) => `${moonCount},${moons[(index + 1) % count]}`))].map((pair) => pair.split(',').map(Number));\n\n const besideNeighbors = (radius: number): boolean => {\n return neighborPairs.every(([before, after]) => {\n const planet = planetBodies(radius, 0, planetRadius, before);\n const next = planetBodies(radius, step, planetRadius, after);\n return moonsClear(planet, next) && moonsOnOwnSide(planet, next) && moonsOnOwnSide(next, planet);\n });\n };\n\n // Moons on the ring inside reach out toward the planets on this one: check those within reach.\n const besideInnerRing = (radius: number): boolean => {\n if (!innerPlanets) {\n return true;\n }\n\n const total = innerPlanets.planets.length;\n const window = innerPlanets.radius <= reach ? 180 : toDegrees(Math.asin(reach / innerPlanets.radius));\n\n return moons.every((moonCount, index) => {\n const angle = start + step * index;\n const planet = planetBodies(radius, angle, planetRadius, moonCount);\n const lowest = Math.floor((angle - window - innerPlanets.start) / innerPlanets.step);\n const highest = Math.min(lowest + total - 1, Math.ceil((angle + window - innerPlanets.start) / innerPlanets.step));\n\n for (let candidate = lowest; candidate <= highest; candidate += 1) {\n const other = innerPlanets.planets[((candidate % total) + total) % total];\n\n if (Math.hypot(other.planet.x - planet.planet.x, other.planet.y - planet.planet.y) < reach && !moonsClear(other, planet)) {\n return false;\n }\n }\n\n return true;\n });\n };\n\n const lowest = ringIndex === 0 ? planned : Math.max(planned, plan.rings[ringIndex - 1] + plan.ringGap);\n const radius = smallestFitting(lowest, planetRadius, (candidate) => besideNeighbors(candidate) && besideInnerRing(candidate));\n plan.rings[ringIndex] = radius;\n inner = { radius, start, step, planets: moons.map((moonCount, index) => planetBodies(radius, start + step * index, planetRadius, moonCount)) };\n first += count;\n });\n};\n\n/** The smallest radius from `lowest` up that `fits`, to within a quarter; `fits` holds for every radius past one where it holds. */\nconst smallestFitting = (lowest: number, stride: number, fits: (radius: number) => boolean): number => {\n if (fits(lowest)) {\n return lowest;\n }\n\n let low = lowest;\n let high = lowest + stride;\n\n while (!fits(high)) {\n low = high;\n high += stride;\n }\n\n while (high - low > 0.25) {\n const middle = (low + high) / 2;\n\n if (fits(middle)) {\n high = middle;\n } else {\n low = middle;\n }\n }\n\n return high;\n};\n\nconst distributeAcrossRings = (childCount: number, rings: number[], planetRadius: number): number[] => {\n const capacities = rings.map((radius) => focusRingCapacity(radius, planetRadius));\n const counts: number[] = [];\n let remaining = childCount;\n\n for (let index = 0; index < rings.length; index += 1) {\n const ringsLeft = rings.length - index;\n const capacity = capacities[index] ?? remaining;\n const count = index === rings.length - 1\n ? remaining\n : Math.min(capacity, Math.ceil(remaining / ringsLeft));\n counts.push(count);\n remaining -= count;\n }\n\n const lastIndex = rings.length - 1;\n\n if (lastIndex >= 0) {\n rings[lastIndex] = Math.max(\n rings[lastIndex],\n requiredRingRadiusForCount(planetRadius, counts[lastIndex] ?? 0),\n );\n }\n\n return counts;\n};\n\nconst focusRingCapacity = (radius: number, planetRadius: number): number => {\n const minimumChord = planetRadius * 2 + NODE_GAP * 0.85;\n\n if (minimumChord >= radius * 2) {\n return 1;\n }\n\n const minAngle = 2 * Math.asin(minimumChord / (radius * 2));\n return Math.max(1, Math.floor((2 * Math.PI) / minAngle));\n};\n\nconst requiredRingRadiusForCount = (planetRadius: number, count: number): number => {\n if (count <= 1) {\n return 0;\n }\n\n const chordFactor = 2 * Math.sin(Math.PI / count);\n return (planetRadius * 2 + NODE_GAP * 0.85) / chordFactor;\n};\n\nconst radiusForLevel = (baseDim: number, level: number, scale: number): number => {\n if (level === 0) {\n return clamp(baseDim * 0.115 * scale, MIN_SUN_RADIUS, MAX_SUN_RADIUS);\n }\n\n if (level === 1) {\n return clamp(baseDim * 0.074 * scale, MIN_PLANET_RADIUS, MAX_PLANET_RADIUS);\n }\n\n if (level === 2) {\n return clamp(baseDim * 0.056 * scale, 15, 36);\n }\n\n return clamp(baseDim * 0.044 * scale, 12, 28);\n};\n\nconst layoutBasis = (containerWidth: number, containerHeight: number): number => {\n const shortSide = Math.min(containerWidth, containerHeight);\n const areaDim = Math.sqrt(containerWidth * containerHeight);\n return Math.min(areaDim, shortSide * 1.25);\n};\n\nconst countVisibleNodes = (node: OrbitNode): number => {\n return 1 + visibleChildren(node).reduce((sum, child) => sum + countVisibleNodes(child), 0);\n};\n\nconst visibleChildren = (node: OrbitNode): OrbitNode[] => {\n return node.collapsed ? [] : node.children;\n};\n\nconst toRadians = (degrees: number): number => {\n return (degrees * Math.PI) / 180;\n};\n\nconst toDegrees = (radians: number): number => {\n return (radians * 180) / Math.PI;\n};\n",
|
|
30
|
+
"import type { OrbitNode } from './types.js';\nimport { clamp } from './utils.js';\n\n/** Where the layout puts the map and how much room it has. */\nexport interface LayoutConfig {\n cx: number;\n cy: number;\n containerWidth: number;\n containerHeight: number;\n\n /** Levels below the layout root to render; deeper nodes are omitted. */\n maxDepth?: number;\n\n /**\n * Focus layouts: ring radii to keep where the orbit has as many rings,\n * instead of making room for the moons again. A drag along the orbit keeps\n * the rings it began with. Rings never come out smaller than the planets need.\n */\n keptRings?: number[];\n}\n\n/** A node with its place in the layout. */\nexport interface PositionedNode extends OrbitNode {\n x: number;\n y: number;\n radius: number;\n\n /** Degrees: 0 is right, -90 is up. */\n angle: number;\n\n /** Distance from the parent. */\n orbitRadius: number;\n}\n\ninterface MeasuredNode {\n node: OrbitNode;\n radius: number;\n subtreeRadius: number;\n childOrbitRadius: number;\n children: MeasuredNode[];\n}\n\nconst SPACING_FACTOR = 1.32;\nconst NODE_GAP = 14;\nconst MIN_SUN_RADIUS = 34;\nconst MIN_PLANET_RADIUS = 18;\nconst MAX_SUN_RADIUS = 76;\nconst MAX_PLANET_RADIUS = 48;\n/**\n * An orbit's planets fill rings out from the sun until they all fit. Past\n * this many rings, the last of them may stretch to take the rest instead,\n * when that keeps the orbit smaller than more rings would.\n */\nconst ROOMY_RING_LIMIT = 7;\nconst FOCUS_RING_GAP_FACTOR = 2.15;\n/**\n * Crowded orbits of planets without moons pack closer: rings start right\n * outside the sun and sit a planet's width apart, with more of them before\n * the last may stretch, so the planets come out as big as the screen allows.\n */\nconst COMPACT_RING_GAP = 8;\nconst COMPACT_RING_LIMIT = 12;\n/** An orbit of this many rings or more is crowded: its sun grows (see calculateFocusLayout). */\nconst CROWDED_RING_COUNT = 4;\n\n/** Moons drawn around a planet; more children show as \"+N\". */\nexport const MOON_LIMIT = 6;\n/**\n * The room kept between a moon and another planet. Moons of different\n * planets keep a moon's radius apart, so that where two fans meet they read\n * as two.\n */\nconst MOON_CLEARANCE = 2;\n\n/** Where a planet's moons go: `distance` from its center, at `offsets` degrees from the direction away from the sun. */\nexport interface MoonPlacement {\n distance: number;\n radius: number;\n offsets: number[];\n}\n\n/** The moons of a planet fan out on its outer side, 30° apart, 150° at most. */\nexport const moonPlacement = (planetRadius: number, moonCount: number): MoonPlacement => {\n const count = Math.min(moonCount, MOON_LIMIT);\n const spread = Math.min(150, (count - 1) * 30);\n return {\n distance: planetRadius * 1.45,\n radius: Math.min(7, Math.max(2.5, planetRadius * 0.17)),\n offsets: Array.from({ length: count }, (_, index) => (count === 1 ? 0 : -spread / 2 + (spread * index) / (count - 1))),\n };\n};\n\n/**\n * Calculate layout for focus mode (center sun + direct children).\n * The orbit radius is never clamped below the collision-free radius. If the\n * result is wider than the container, the renderer auto-fits the whole group.\n */\nexport const calculateFocusLayout = (\n focusedNode: OrbitNode,\n config: LayoutConfig,\n): { sun: PositionedNode; planets: PositionedNode[]; orbitRadius: number; orbitRings: number[] } => {\n const { cx, cy, containerWidth, containerHeight } = config;\n const depthCapped = config.maxDepth !== undefined && focusedNode.level >= config.maxDepth;\n const children = depthCapped ? [] : visibleChildren(focusedNode);\n const childCount = children.length;\n const baseDim = layoutBasis(containerWidth, containerHeight);\n\n let sunRadius = clamp(baseDim * 0.115, MIN_SUN_RADIUS, MAX_SUN_RADIUS);\n const planetDensityScale = childCount === 0\n ? 1\n : clamp(Math.pow(10 / childCount, 0.32), 0.58, 1.1);\n const planetRadius = clamp(\n baseDim * 0.074 * planetDensityScale,\n MIN_PLANET_RADIUS,\n MAX_PLANET_RADIUS,\n );\n const compact = children.every((child) => visibleChildren(child).length === 0);\n let orbitPlan = calculateFocusRingPlan(childCount, sunRadius, planetRadius, baseDim, compact);\n\n // A crowded orbit shrinks its sun on screen with everything else: the sun grows with its rings,\n // so the focused node stays the focus and its name stays legible.\n if (orbitPlan.rings.length >= CROWDED_RING_COUNT) {\n const grown = Math.min(MAX_SUN_RADIUS, sunRadius * (1 + 0.06 * (orbitPlan.rings.length - 1)));\n\n if (grown > sunRadius) {\n sunRadius = grown;\n orbitPlan = calculateFocusRingPlan(childCount, sunRadius, planetRadius, baseDim, compact);\n }\n }\n\n const keptRings = config.keptRings;\n\n if (keptRings && keptRings.length === orbitPlan.rings.length) {\n orbitPlan.rings = orbitPlan.rings.map((radius, index) => Math.max(radius, keptRings[index]));\n } else {\n const moonsHidden = config.maxDepth !== undefined && focusedNode.level + 1 >= config.maxDepth;\n const moonCounts = children.map((child) => (moonsHidden ? 0 : Math.min(visibleChildren(child).length, MOON_LIMIT)));\n makeRoomForMoons(orbitPlan, planetRadius, moonCounts);\n }\n\n const orbitRadius = orbitPlan.rings[orbitPlan.rings.length - 1] ?? 0;\n\n const sun: PositionedNode = {\n ...focusedNode,\n parent: focusedNode.parent,\n x: cx,\n y: cy,\n radius: sunRadius,\n angle: -90,\n orbitRadius: 0,\n };\n\n const planets: PositionedNode[] = [];\n let childIndex = 0;\n\n orbitPlan.rings.forEach((ringRadius, ringIndex) => {\n const ringCount = orbitPlan.counts[ringIndex] ?? 0;\n const angleStep = 360 / ringCount;\n const startAngle = ringStartAngle(ringIndex, ringCount);\n\n for (let localIndex = 0; localIndex < ringCount; localIndex += 1) {\n const child = children[childIndex];\n\n if (!child) {\n break;\n }\n\n const angleDeg = startAngle + angleStep * localIndex;\n const angleRad = toRadians(angleDeg);\n\n planets.push({\n ...child,\n parent: child.parent,\n x: cx + ringRadius * Math.cos(angleRad),\n y: cy + ringRadius * Math.sin(angleRad),\n radius: planetRadius,\n angle: angleDeg,\n orbitRadius: ringRadius,\n });\n childIndex += 1;\n }\n });\n\n return { sun, planets, orbitRadius, orbitRings: orbitPlan.rings };\n};\n\n/**\n * Calculate layout for all mode. Each node owns a measured subtree circle; a\n * parent's child orbit is sized so sibling subtree circles cannot overlap.\n */\nexport const calculateAllLayout = (\n node: OrbitNode,\n config: LayoutConfig,\n parentAngle: number = -90,\n): PositionedNode[] => {\n const baseDim = layoutBasis(config.containerWidth, config.containerHeight);\n const complexityScale = clamp(Math.pow(18 / countVisibleNodes(node), 0.18), 0.74, 1.08);\n const measured = measureSubtree(node, baseDim, complexityScale, config.maxDepth ?? Infinity);\n const positionedNodes: PositionedNode[] = [];\n\n placeSubtree(measured, config.cx, config.cy, parentAngle, 0, positionedNodes);\n return positionedNodes;\n};\n\n/**\n * The rings of the overview: one around each node with children, through them.\n */\nexport const getOrbitRings = (\n positionedNodes: PositionedNode[],\n): { centerId: string; cx: number; cy: number; r: number }[] => {\n const rings: { centerId: string; cx: number; cy: number; r: number }[] = [];\n const seen = new Set<string>();\n\n for (const node of positionedNodes) {\n if (visibleChildren(node).length === 0) {\n continue;\n }\n\n const childNode = positionedNodes.find(\n (n) => n.parent?.id === node.id && n.id !== node.id,\n );\n\n if (!childNode) {\n continue;\n }\n\n const dx = childNode.x - node.x;\n const dy = childNode.y - node.y;\n const r = Math.sqrt(dx * dx + dy * dy);\n const key = `${node.x.toFixed(1)},${node.y.toFixed(1)},${r.toFixed(1)}`;\n\n if (!seen.has(key) && r > 10) {\n seen.add(key);\n rings.push({ centerId: node.id, cx: node.x, cy: node.y, r });\n }\n }\n\n return rings;\n};\n\nconst measureSubtree = (\n node: OrbitNode,\n baseDim: number,\n complexityScale: number,\n depthRemaining: number,\n): MeasuredNode => {\n const radius = radiusForLevel(baseDim, node.level, complexityScale);\n const children = depthRemaining > 0 ? visibleChildren(node) : [];\n const childMeasures = children.map((child) => measureSubtree(child, baseDim, complexityScale, depthRemaining - 1));\n\n const childBounds = childMeasures.map((child) => child.subtreeRadius);\n const childOrbitRadius = requiredOrbitRadius(radius, childBounds);\n const maxChildBound = childBounds.length > 0 ? Math.max(...childBounds) : 0;\n\n return {\n node,\n radius,\n subtreeRadius: Math.max(radius, childOrbitRadius + maxChildBound),\n childOrbitRadius,\n children: childMeasures,\n };\n};\n\nconst MAX_FAN_DEGREES = 270;\n\nconst placeSubtree = (\n measured: MeasuredNode,\n x: number,\n y: number,\n angle: number,\n orbitRadius: number,\n positionedNodes: PositionedNode[],\n): void => {\n const positioned: PositionedNode = {\n ...measured.node,\n parent: measured.node.parent,\n x,\n y,\n radius: measured.radius,\n angle,\n orbitRadius,\n };\n\n positionedNodes.push(positioned);\n\n const childCount = measured.children.length;\n\n if (childCount === 0) {\n return;\n }\n\n const isRoot = measured.node.level === 0;\n const fullCircle = isRoot || childCount === 1;\n const naturalFan = (childCount - 1) * (360 / childCount);\n const fanDegrees = fullCircle ? 360 : Math.min(naturalFan, MAX_FAN_DEGREES);\n const angleStep = childCount === 1\n ? 0\n : fullCircle\n ? 360 / childCount\n : fanDegrees / (childCount - 1);\n\n const startAngle = childCount === 1\n ? angle\n : isRoot\n ? -90\n : angle - fanDegrees / 2;\n\n measured.children.forEach((child, index) => {\n const childAngle = startAngle + angleStep * index;\n const angleRad = toRadians(childAngle);\n const childX = x + measured.childOrbitRadius * Math.cos(angleRad);\n const childY = y + measured.childOrbitRadius * Math.sin(angleRad);\n placeSubtree(child, childX, childY, childAngle, measured.childOrbitRadius, positionedNodes);\n });\n};\n\nconst requiredOrbitRadius = (centerRadius: number, childRadii: number[]): number => {\n if (childRadii.length === 0) {\n return 0;\n }\n\n const parentClearance = Math.max(\n ...childRadii.map((childRadius) => centerRadius + childRadius + NODE_GAP),\n );\n\n if (childRadii.length === 1) {\n return parentClearance;\n }\n\n const angleStep = (2 * Math.PI) / childRadii.length;\n const chordFactor = 2 * Math.sin(angleStep / 2);\n\n const siblingClearance = childRadii.reduce((max, childRadius, index) => {\n const nextRadius = childRadii[(index + 1) % childRadii.length];\n const required = ((childRadius + nextRadius) * SPACING_FACTOR + NODE_GAP) / chordFactor;\n return Math.max(max, required);\n }, 0);\n\n return Math.max(parentClearance, siblingClearance);\n};\n\nconst calculateFocusRingPlan = (\n childCount: number,\n sunRadius: number,\n planetRadius: number,\n baseDim: number,\n compact = false,\n): RingPlan => {\n if (childCount === 0) {\n return { rings: [], counts: [], ringGap: 0 };\n }\n\n const roomy = ringPlan(\n childCount,\n planetRadius,\n Math.max(baseDim * 0.26, sunRadius + planetRadius + NODE_GAP * 1.3),\n planetRadius * FOCUS_RING_GAP_FACTOR + NODE_GAP,\n ROOMY_RING_LIMIT,\n );\n\n // One ring keeps its roomy layout. Planets without moons that need several\n // rings pack closer, when that makes the orbit smaller.\n if (!compact || roomy.rings.length <= 1) {\n return roomy;\n }\n\n const close = ringPlan(childCount, planetRadius, sunRadius + planetRadius + NODE_GAP, planetRadius * 2 + COMPACT_RING_GAP, COMPACT_RING_LIMIT);\n return (close.rings.at(-1) ?? 0) < (roomy.rings.at(-1) ?? 0) ? close : roomy;\n};\n\n/** The rings of a focus view, the number of planets on each, and the distance between rings. */\ninterface RingPlan {\n rings: number[];\n counts: number[];\n ringGap: number;\n}\n\n/**\n * Rings from `innerRingRadius` out, `ringGap` apart, until they hold every\n * child. Past `ringLimit` rings, the last of the first `ringLimit` may\n * stretch to take the rest instead, when that keeps the orbit smaller: for a\n * few more planets it does, but a big orbit's last ring would stretch so far\n * out that every planet came out a speck.\n */\nconst ringPlan = (\n childCount: number,\n planetRadius: number,\n innerRingRadius: number,\n ringGap: number,\n ringLimit: number,\n): RingPlan => {\n const rings: number[] = [];\n let totalCapacity = 0;\n\n while (totalCapacity < childCount) {\n const radius = innerRingRadius + ringGap * rings.length;\n rings.push(radius);\n totalCapacity += focusRingCapacity(radius, planetRadius);\n }\n\n const fewer = rings.slice(0, ringLimit);\n const stretched: RingPlan = { rings: fewer, counts: distributeAcrossRings(childCount, fewer, planetRadius), ringGap };\n\n if (rings.length <= ringLimit) {\n return stretched;\n }\n\n const all: RingPlan = { rings, counts: distributeAcrossRings(childCount, rings, planetRadius), ringGap };\n return (all.rings.at(-1) ?? 0) < (stretched.rings.at(-1) ?? 0) ? all : stretched;\n};\n\n/** The first planet on each ring is at the top; every other ring is turned half a step. */\nconst ringStartAngle = (ringIndex: number, count: number): number => {\n return ringIndex % 2 === 0 ? -90 : -90 + 360 / count / 2;\n};\n\ninterface Circle {\n x: number;\n y: number;\n radius: number;\n}\n\n/** A planet on a ring and its moons. */\ninterface PlanetBodies {\n planet: Circle;\n moons: Circle[];\n}\n\nconst planetBodies = (ringRadius: number, angle: number, planetRadius: number, moonCount: number): PlanetBodies => {\n const x = ringRadius * Math.cos(toRadians(angle));\n const y = ringRadius * Math.sin(toRadians(angle));\n const { distance, radius, offsets } = moonPlacement(planetRadius, moonCount);\n return {\n planet: { x, y, radius: planetRadius },\n moons: offsets.map((offset) => ({\n x: x + distance * Math.cos(toRadians(angle + offset)),\n y: y + distance * Math.sin(toRadians(angle + offset)),\n radius,\n })),\n };\n};\n\nconst apart = (first: Circle, second: Circle, gap: number): boolean => {\n return Math.hypot(first.x - second.x, first.y - second.y) >= first.radius + second.radius + gap;\n};\n\n/** Whether the moons of either planet keep clear of the other planet and its moons (see `MOON_CLEARANCE`). */\nconst moonsClear = (first: PlanetBodies, second: PlanetBodies): boolean => {\n return first.moons.every((moon) => apart(moon, second.planet, MOON_CLEARANCE) && second.moons.every((other) => apart(moon, other, moon.radius)))\n && second.moons.every((moon) => apart(moon, first.planet, MOON_CLEARANCE));\n};\n\n/** Whether every moon of `planet` is nearer it than `neighbor`: a moon past the middle reads as the neighbor's. */\nconst moonsOnOwnSide = (planet: PlanetBodies, neighbor: PlanetBodies): boolean => {\n return planet.moons.every((moon) => {\n return Math.hypot(moon.x - planet.planet.x, moon.y - planet.planet.y) < Math.hypot(moon.x - neighbor.planet.x, moon.y - neighbor.planet.y);\n });\n};\n\n/**\n * Rings are planned for the planets' bodies, but moons fan out on the outer\n * side of their planets, toward the neighbors on the ring and the next ring\n * out. Each ring with moons on it or inside it moves out (and the rings\n * beyond it with it) just as far as its moons need; orbits whose moons\n * already have room keep their rings.\n */\nconst makeRoomForMoons = (plan: RingPlan, planetRadius: number, moonCounts: number[]): void => {\n if (moonCounts.every((count) => count === 0)) {\n return;\n }\n\n const moonReach = moonPlacement(planetRadius, 1);\n // Planets farther apart than this can't touch each other's moons.\n const reach = 2 * (moonReach.distance + moonReach.radius) + Math.max(MOON_CLEARANCE, moonReach.radius);\n let first = 0;\n let inner: { radius: number; start: number; step: number; planets: PlanetBodies[] } | undefined;\n\n plan.rings.forEach((planned, ringIndex) => {\n const count = plan.counts[ringIndex] ?? 0;\n const moons = moonCounts.slice(first, first + count);\n const start = ringStartAngle(ringIndex, count);\n const step = 360 / Math.max(1, count);\n const innerPlanets = inner?.planets.some((planet) => planet.moons.length > 0) ? inner : undefined;\n // Neighbors on a ring are all `step` apart, so one pair of each kind tells for all of them.\n const neighborPairs = count < 2\n ? []\n : [...new Set(moons.map((moonCount, index) => `${moonCount},${moons[(index + 1) % count]}`))].map((pair) => pair.split(',').map(Number));\n\n const besideNeighbors = (radius: number): boolean => {\n return neighborPairs.every(([before, after]) => {\n const planet = planetBodies(radius, 0, planetRadius, before);\n const next = planetBodies(radius, step, planetRadius, after);\n return moonsClear(planet, next) && moonsOnOwnSide(planet, next) && moonsOnOwnSide(next, planet);\n });\n };\n\n // Moons on the ring inside reach out toward the planets on this one: check those within reach.\n const besideInnerRing = (radius: number): boolean => {\n if (!innerPlanets) {\n return true;\n }\n\n const total = innerPlanets.planets.length;\n const window = innerPlanets.radius <= reach ? 180 : toDegrees(Math.asin(reach / innerPlanets.radius));\n\n return moons.every((moonCount, index) => {\n const angle = start + step * index;\n const planet = planetBodies(radius, angle, planetRadius, moonCount);\n const lowest = Math.floor((angle - window - innerPlanets.start) / innerPlanets.step);\n const highest = Math.min(lowest + total - 1, Math.ceil((angle + window - innerPlanets.start) / innerPlanets.step));\n\n for (let candidate = lowest; candidate <= highest; candidate += 1) {\n const other = innerPlanets.planets[((candidate % total) + total) % total];\n\n if (Math.hypot(other.planet.x - planet.planet.x, other.planet.y - planet.planet.y) < reach && !moonsClear(other, planet)) {\n return false;\n }\n }\n\n return true;\n });\n };\n\n const lowest = ringIndex === 0 ? planned : Math.max(planned, plan.rings[ringIndex - 1] + plan.ringGap);\n const radius = smallestFitting(lowest, planetRadius, (candidate) => besideNeighbors(candidate) && besideInnerRing(candidate));\n plan.rings[ringIndex] = radius;\n inner = { radius, start, step, planets: moons.map((moonCount, index) => planetBodies(radius, start + step * index, planetRadius, moonCount)) };\n first += count;\n });\n};\n\n/** The smallest radius from `lowest` up that `fits`, to within a quarter; `fits` holds for every radius past one where it holds. */\nconst smallestFitting = (lowest: number, stride: number, fits: (radius: number) => boolean): number => {\n if (fits(lowest)) {\n return lowest;\n }\n\n let low = lowest;\n let high = lowest + stride;\n\n while (!fits(high)) {\n low = high;\n high += stride;\n }\n\n while (high - low > 0.25) {\n const middle = (low + high) / 2;\n\n if (fits(middle)) {\n high = middle;\n } else {\n low = middle;\n }\n }\n\n return high;\n};\n\nconst distributeAcrossRings = (childCount: number, rings: number[], planetRadius: number): number[] => {\n const capacities = rings.map((radius) => focusRingCapacity(radius, planetRadius));\n const counts: number[] = [];\n let remaining = childCount;\n\n for (let index = 0; index < rings.length; index += 1) {\n const ringsLeft = rings.length - index;\n const capacity = capacities[index] ?? remaining;\n const count = index === rings.length - 1\n ? remaining\n : Math.min(capacity, Math.ceil(remaining / ringsLeft));\n counts.push(count);\n remaining -= count;\n }\n\n const lastIndex = rings.length - 1;\n\n if (lastIndex >= 0) {\n rings[lastIndex] = Math.max(\n rings[lastIndex],\n requiredRingRadiusForCount(planetRadius, counts[lastIndex] ?? 0),\n );\n }\n\n return counts;\n};\n\nconst focusRingCapacity = (radius: number, planetRadius: number): number => {\n const minimumChord = planetRadius * 2 + NODE_GAP * 0.85;\n\n if (minimumChord >= radius * 2) {\n return 1;\n }\n\n const minAngle = 2 * Math.asin(minimumChord / (radius * 2));\n return Math.max(1, Math.floor((2 * Math.PI) / minAngle));\n};\n\nconst requiredRingRadiusForCount = (planetRadius: number, count: number): number => {\n if (count <= 1) {\n return 0;\n }\n\n const chordFactor = 2 * Math.sin(Math.PI / count);\n return (planetRadius * 2 + NODE_GAP * 0.85) / chordFactor;\n};\n\nconst radiusForLevel = (baseDim: number, level: number, scale: number): number => {\n if (level === 0) {\n return clamp(baseDim * 0.115 * scale, MIN_SUN_RADIUS, MAX_SUN_RADIUS);\n }\n\n if (level === 1) {\n return clamp(baseDim * 0.074 * scale, MIN_PLANET_RADIUS, MAX_PLANET_RADIUS);\n }\n\n if (level === 2) {\n return clamp(baseDim * 0.056 * scale, 15, 36);\n }\n\n return clamp(baseDim * 0.044 * scale, 12, 28);\n};\n\nconst layoutBasis = (containerWidth: number, containerHeight: number): number => {\n const shortSide = Math.min(containerWidth, containerHeight);\n const areaDim = Math.sqrt(containerWidth * containerHeight);\n return Math.min(areaDim, shortSide * 1.25);\n};\n\nconst countVisibleNodes = (node: OrbitNode): number => {\n return 1 + visibleChildren(node).reduce((sum, child) => sum + countVisibleNodes(child), 0);\n};\n\nconst visibleChildren = (node: OrbitNode): OrbitNode[] => {\n return node.collapsed ? [] : node.children;\n};\n\nconst toRadians = (degrees: number): number => {\n return (degrees * Math.PI) / 180;\n};\n\nconst toDegrees = (radians: number): number => {\n return (radians * 180) / Math.PI;\n};\n",
|
|
30
31
|
"const supports = (property: string, value: string): boolean => {\n const css = (globalThis as { CSS?: { supports?: (property: string, value: string) => boolean } }).CSS;\n return typeof css?.supports !== 'function' || css.supports(property, value);\n};\n\n/**\n * What the browser draws with, checked once. A few effects need newer CSS:\n * older browsers, such as the WebViews of phones that don't update theirs,\n * get plainer versions of them instead of broken ones. Outside a browser (on\n * a server, or tests without a DOM) everything counts as there.\n */\nexport const browser = {\n /** CSS `color-mix()` (Chromium 111, Safari 16.2, Firefox 113). Without it, siblings keep their branch's own color. */\n mixesColors: supports('color', 'color-mix(in oklab, red 50%, blue)'),\n\n /** The `translate` property (Chromium 104, Safari 14.1, Firefox 72). Without it, overlays are centered through their transform. */\n translates: supports('translate', '1px'),\n};\n\nconst coarseQueries = new WeakMap<Window, MediaQueryList>();\n\n/**\n * Whether `element`'s page is used with a finger (`pointer: coarse`), where\n * the stylesheet makes buttons bigger. The query is made once per window.\n */\nexport const pointsCoarsely = (element: Element): boolean => {\n const view = element.ownerDocument.defaultView;\n\n if (!view || typeof view.matchMedia !== 'function') {\n return false;\n }\n\n let query = coarseQueries.get(view);\n\n if (!query) {\n query = view.matchMedia('(pointer: coarse)');\n coarseQueries.set(view, query);\n }\n\n return query.matches;\n};\n\n/**\n * The transform that puts an overlay at `x`, `y`. `centering` is the\n * stylesheet's `translate` for it, as `translate()` takes it: where the\n * browser lacks that property, the transform moves the overlay instead.\n */\nexport const overlayTransform = (x: number, y: number, centering: string): string => {\n const position = `translate3d(${x}px, ${y}px, 0)`;\n return browser.translates ? position : `${position} translate(${centering})`;\n};\n",
|
|
31
32
|
"/**\n * Camera math. A camera is the world point shown at the viewport's center\n * and a zoom factor. Everything is plain geometry so it can be unit-tested\n * without a DOM.\n */\n\nexport interface Camera {\n x: number;\n y: number;\n scale: number;\n}\n\nexport interface Viewport {\n width: number;\n height: number;\n}\n\nexport interface Point {\n x: number;\n y: number;\n}\n\n/** Maps world points onto the screen: `p ↦ (p − center) × scale + viewport center`. */\nexport const worldToScreen = (camera: Camera, viewport: Viewport, point: Point): Point => {\n return {\n x: (point.x - camera.x) * camera.scale + viewport.width / 2,\n y: (point.y - camera.y) * camera.scale + viewport.height / 2,\n };\n};\n\nexport const screenToWorld = (camera: Camera, viewport: Viewport, point: Point): Point => {\n return {\n x: (point.x - viewport.width / 2) / camera.scale + camera.x,\n y: (point.y - viewport.height / 2) / camera.scale + camera.y,\n };\n};\n\n/** SVG `transform` for the world group. */\nexport const cameraTransform = (camera: Camera, viewport: Viewport): string => {\n return `translate(${round(viewport.width / 2)} ${round(viewport.height / 2)}) scale(${round(camera.scale, 5)}) translate(${round(-camera.x)} ${round(-camera.y)})`;\n};\n\n/** Zooms by `factor` keeping the world point under `anchor` (screen coordinates) in place. */\nexport const zoomAround = (camera: Camera, viewport: Viewport, factor: number, anchor: Point): Camera => {\n const fixed = screenToWorld(camera, viewport, anchor);\n const scale = camera.scale * factor;\n return {\n scale,\n x: fixed.x - (anchor.x - viewport.width / 2) / scale,\n y: fixed.y - (anchor.y - viewport.height / 2) / scale,\n };\n};\n\n/** Moves the camera so the content shifts by a screen-space delta. */\nexport const panBy = (camera: Camera, deltaX: number, deltaY: number): Camera => {\n return { scale: camera.scale, x: camera.x - deltaX / camera.scale, y: camera.y - deltaY / camera.scale };\n};\n\n/**\n * A camera that keeps `center` at the middle of the viewport and fits\n * content reaching `extent` away from it on each axis, inside `padding`.\n */\n/** Room the page's own controls take at the viewport's edges, in px. */\nexport interface Insets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\nexport const NO_INSETS: Insets = { top: 0, right: 0, bottom: 0, left: 0 };\n\n/**\n * The camera that shows `extent` around `center`, `padding` px from the\n * edges of what `insets` leave of the viewport, and centered there.\n */\nexport const fitAround = (center: Point, extent: Point, viewport: Viewport, padding: number, maximumScale: number, insets: Insets = NO_INSETS): Camera => {\n const width = Math.max(1, viewport.width - insets.left - insets.right);\n const height = Math.max(1, viewport.height - insets.top - insets.bottom);\n const usableWidth = Math.max(width - padding * 2, width * 0.35);\n const usableHeight = Math.max(height - padding * 2, height * 0.35);\n const fitted = Math.min(\n extent.x > 0 ? usableWidth / (extent.x * 2) : maximumScale,\n extent.y > 0 ? usableHeight / (extent.y * 2) : maximumScale,\n maximumScale,\n );\n const scale = fitted > 0 && Number.isFinite(fitted) ? fitted : 1;\n // The middle of what's left is off the viewport's middle: the camera looks the other way by as much.\n return {\n x: center.x - (insets.left - insets.right) / 2 / scale,\n y: center.y - (insets.top - insets.bottom) / 2 / scale,\n scale,\n };\n};\n\n/** A similarity transform `p ↦ p × scale + (x, y)`, used to place one scene inside another. */\nexport interface Similarity {\n scale: number;\n x: number;\n y: number;\n}\n\nexport const IDENTITY: Similarity = { scale: 1, x: 0, y: 0 };\n\nexport const applySimilarity = (transform: Similarity, point: Point): Point => {\n return { x: point.x * transform.scale + transform.x, y: point.y * transform.scale + transform.y };\n};\n\nexport const invertSimilarity = (transform: Similarity): Similarity => {\n return { scale: 1 / transform.scale, x: -transform.x / transform.scale, y: -transform.y / transform.scale };\n};\n\n/** `outer ∘ inner`: apply `inner` first, then `outer`. */\nexport const composeSimilarity = (outer: Similarity, inner: Similarity): Similarity => {\n return {\n scale: outer.scale * inner.scale,\n x: inner.x * outer.scale + outer.x,\n y: inner.y * outer.scale + outer.y,\n };\n};\n\n/** The same view expressed in coordinates transformed by `transform`. */\nexport const transformCamera = (transform: Similarity, camera: Camera): Camera => {\n const center = applySimilarity(transform, camera);\n return { x: center.x, y: center.y, scale: camera.scale / transform.scale };\n};\n\nconst RHO = Math.SQRT2;\nconst RHO_SQUARED = 2;\nconst RHO_FOURTH = 4;\n\nexport interface CameraPath {\n /** The camera at `progress` ∈ [0, 1]. */\n at(progress: number): Camera;\n\n /** Path length in the paper's units; flights take time proportional to it. */\n length: number;\n}\n\n/**\n * Van Wijk & Nuij, \"Smooth and efficient zooming and panning\" (2003): the\n * path that zooms out a little, travels, then zooms in, so the start and the\n * destination stay in view for as long as possible. It is the same path\n * d3's `interpolateZoom` follows.\n */\nexport const smoothZoomPath = (from: Camera, to: Camera, viewport: Viewport): CameraPath => {\n const viewWidth = Math.max(viewport.width, 1);\n const startX = from.x;\n const startY = from.y;\n const startWidth = viewWidth / from.scale;\n const endWidth = viewWidth / to.scale;\n const deltaX = to.x - from.x;\n const deltaY = to.y - from.y;\n const distanceSquared = deltaX * deltaX + deltaY * deltaY;\n\n if (distanceSquared < 1e-12) {\n const length = Math.log(endWidth / startWidth) / RHO;\n return {\n length: Math.abs(length),\n at: (progress) => ({\n x: startX + progress * deltaX,\n y: startY + progress * deltaY,\n scale: viewWidth / (startWidth * Math.exp(RHO * progress * length)),\n }),\n };\n }\n\n const distance = Math.sqrt(distanceSquared);\n const startTerm = (endWidth * endWidth - startWidth * startWidth + RHO_FOURTH * distanceSquared) / (2 * startWidth * RHO_SQUARED * distance);\n const endTerm = (endWidth * endWidth - startWidth * startWidth - RHO_FOURTH * distanceSquared) / (2 * endWidth * RHO_SQUARED * distance);\n const startRatio = Math.log(Math.sqrt(startTerm * startTerm + 1) - startTerm);\n const endRatio = Math.log(Math.sqrt(endTerm * endTerm + 1) - endTerm);\n const length = (endRatio - startRatio) / RHO;\n const coshStart = Math.cosh(startRatio);\n\n return {\n length: Math.abs(length),\n at: (progress) => {\n const position = progress * length;\n const travelled = (startWidth / (RHO_SQUARED * distance)) * (coshStart * Math.tanh(RHO * position + startRatio) - Math.sinh(startRatio));\n const width = (startWidth * coshStart) / Math.cosh(RHO * position + startRatio);\n return {\n x: startX + travelled * deltaX,\n y: startY + travelled * deltaY,\n scale: viewWidth / width,\n };\n },\n };\n};\n\nconst round = (value: number, decimals = 3): number => {\n const factor = 10 ** decimals;\n return Math.round(value * factor) / factor;\n};\n",
|
|
32
|
-
"/**\n * Scenes: what each view of a map contains, in world coordinates.\n *\n * A focus scene puts the focused node (the sun) at the origin with its\n * children (planets) on rings and its grandchildren as small moons around\n * them. An overview scene lays out the whole tree around the root. Every\n * node keeps one color in every scene, and nodes are keyed by id so a\n * transition can morph the same node from one scene into the next: the\n * moons of a planet grow into the planets of the next view.\n */\n\nimport type { OrbitNode } from '../types.js';\nimport { calculateAllLayout, calculateFocusLayout, getOrbitRings, MOON_LIMIT, moonPlacement } from '../layout.js';\nimport { findNodeById } from '../utils.js';\nimport { browser } from '../browser.js';\nimport { fitAround, type Camera, type Insets, type Similarity, type Viewport, applySimilarity } from './camera.js';\n\nexport type NodeRole = 'sun' | 'planet' | 'moon' | 'node';\n\nexport interface SceneNode {\n id: string;\n node: OrbitNode;\n role: NodeRole;\n\n /** World position of the center, before any orbit spin. */\n x: number;\n\n y: number;\n radius: number;\n color: string;\n depth: number;\n parentId?: string;\n\n /** Planets: angle around the sun (degrees, −90 = top) and distance from it. */\n orbitAngle?: number;\n\n orbitRadius?: number;\n\n /** Moons: the planet they circle, their angle relative to the direction from the sun to the planet, and their distance. */\n hostId?: string;\n\n hostOffset?: number;\n hostDistance?: number;\n\n /** Children that exist but aren't drawn: beyond the moon limit, or under a collapsed node. */\n hiddenChildren: number;\n\n /** Turns with the orbit when it spins. */\n spins: boolean;\n\n /** A planet of an orbit too crowded for each planet's shadow to read: drawn flat. */\n crowded?: boolean;\n}\n\nexport interface SceneRing {\n id: string;\n centerId: string;\n cx: number;\n cy: number;\n radius: number;\n color: string;\n\n /** Openings around each body on the ring, so the line never runs through a node. */\n gaps: { angle: number; halfWidth: number }[];\n\n spins: boolean;\n}\n\nexport interface SceneLink {\n id: string;\n fromId: string;\n toId: string;\n color: string;\n}\n\nexport interface Scene {\n kind: 'focus' | 'overview';\n focusId: string;\n nodes: Map<string, SceneNode>;\n rings: SceneRing[];\n links: SceneLink[];\n\n /** The camera that fits the scene into the viewport. */\n frame: Camera;\n\n /**\n * How far the scene reaches from its focus node on each axis, in world\n * units: what `frame` fits. A focus scene reaches as far on both, the edge\n * of its orbit at every turn.\n */\n extent: { x: number; y: number };\n\n /** Focus scenes of editable maps: the free place in the orbit where a new idea goes. */\n addSlot?: SceneSlot;\n}\n\n/** A free place in the sun's orbit, laid out like a planet, for the next child. */\nexport interface SceneSlot {\n /** The node a new idea there becomes a child of: the sun. */\n parentId: string;\n\n /** Its position among the sun's children. */\n index: number;\n\n x: number;\n y: number;\n radius: number;\n orbitAngle: number;\n orbitRadius: number;\n}\n\nexport interface SceneOptions {\n viewport: Viewport;\n\n /** The parts of the viewport the page's own controls cover: views are fitted into the rest. */\n insets?: Insets;\n\n colors: Map<string, string>;\n maxDepth?: number;\n\n /** Keep a place in the orbit for a new idea, after the sun's children (or at `index`). Focus scenes only. */\n addSlot?: { index?: number };\n\n /**\n * One of the sun's children being dragged to another place among them: it's\n * laid out at `index` among the others, so they make room for it there.\n * Focus scenes only.\n */\n reorder?: { id: string; index: number };\n\n /**\n * While a node is carried along the orbit of `focusId`: the radii its rings\n * had when the drag began. They keep them until the drop, so the orbit\n * doesn't grow or shrink as the places in it move. Focus scenes only.\n */\n keptRings?: { focusId: string; radii: number[] };\n}\n\n/** The id the slot uses while it is laid out with the planets; no node can have it. */\nconst SLOT_ID = '\\u0000orbit-add';\n\nexport { MOON_LIMIT };\n/** More planets than this in one view, and their shadows overlap into a haze: they're drawn flat. */\nexport const CROWDED_ORBIT = 48;\n/** The largest zoom a fitted view uses, so small maps don't balloon. */\nconst MAXIMUM_FIT_SCALE = 1.35;\nconst FOCUS_PADDING = 40;\nconst OVERVIEW_PADDING = 48;\n\n/** Room kept around a fitted view: less on small screens, where every pixel counts. */\nconst fitPadding = (viewport: Viewport, padding: number): number => {\n return Math.min(padding, Math.max(16, Math.min(viewport.width, viewport.height) * 0.05));\n};\n\n/**\n * The camera that fits a view reaching `extent` from its focus node into\n * `viewport`, inside what `insets` leave of it, with at least `below` px\n * between the view and the lower edge of that.\n */\nconst fitExtent = (kind: Scene['kind'], extent: Scene['extent'], viewport: Viewport, insets: Insets | undefined, below = 0): Camera => {\n const padding = fitPadding(viewport, kind === 'focus' ? FOCUS_PADDING : OVERVIEW_PADDING);\n const room = Math.max(0, below - padding);\n const sides = insets ?? { top: 0, right: 0, bottom: 0, left: 0 };\n return fitAround({ x: 0, y: 0 }, extent, viewport, padding, MAXIMUM_FIT_SCALE, room > 0 ? { ...sides, bottom: sides.bottom + room } : sides);\n};\n\n/**\n * The camera that fits `scene` into `viewport` as its `frame` does, inside\n * what `insets` leave of it, and with at least `below` px under it: room for\n * something drawn there, such as the focused node's buttons.\n */\nexport const fitScene = (scene: Scene, viewport: Viewport, insets?: Insets, below = 0): Camera => {\n return fitExtent(scene.kind, scene.extent, viewport, insets, below);\n};\n\nconst RING_GAP_PADDING = 7;\n\n/**\n * One color per node, the same in every view. The root uses the first\n * palette entry; each top-level branch takes the next; deeper nodes use\n * their branch's color, mixed toward the theme's `shade-light` or\n * `shade-dark` by position so siblings stay distinguishable. A node's own\n * color always wins: its `color`, or its type's (see `ownColor`).\n */\nexport const assignNodeColors = (\n tree: OrbitNode,\n palette: string[],\n ownColor: (node: OrbitNode) => string | undefined = (node) => node.color,\n): Map<string, string> => {\n const colors = new Map<string, string>();\n const branchColors = palette.length > 1 ? palette.slice(1) : palette;\n colors.set(tree.id, ownColor(tree) ?? palette[0]);\n\n tree.children.forEach((branch, branchIndex) => {\n const branchColor = ownColor(branch) ?? branchColors[branchIndex % branchColors.length];\n colors.set(branch.id, branchColor);\n\n const visit = (node: OrbitNode, inherited: string) => {\n node.children.forEach((child, siblingIndex) => {\n const own = ownColor(child);\n colors.set(child.id, own ?? shade(inherited, siblingIndex));\n visit(child, own ?? inherited);\n });\n };\n\n visit(branch, branchColor);\n });\n\n return colors;\n};\n\n/** How much of the branch color each sibling keeps, and what the rest is mixed with. */\nexport const SHADES: [number, 'light' | 'dark'][] = [\n [100, 'light'],\n [78, 'light'],\n [86, 'dark'],\n [62, 'light'],\n [76, 'dark'],\n];\n\nconst shade = (color: string, siblingIndex: number): string => {\n const [amount, toward] = SHADES[siblingIndex % SHADES.length];\n return amount === 100 || !browser.mixesColors ? color : `color-mix(in oklab, ${color} ${amount}%, var(--_orbit-shade-${toward}))`;\n};\n\n/** `children` with the one `reorder` names moved to its index among the others (unchanged without it). */\nconst reordered = (children: OrbitNode[], reorder: SceneOptions['reorder']): OrbitNode[] => {\n const moving = reorder ? children.find((child) => child.id === reorder.id) : undefined;\n\n if (!reorder || !moving) {\n return children;\n }\n\n const others = children.filter((child) => child !== moving);\n const index = Math.min(others.length, Math.max(0, Math.trunc(reorder.index)));\n return [...others.slice(0, index), moving, ...others.slice(index)];\n};\n\nconst visibleChildren = (node: OrbitNode, maxDepth: number | undefined): OrbitNode[] => {\n if (node.collapsed) {\n return [];\n }\n\n if (maxDepth !== undefined && node.level >= maxDepth) {\n return [];\n }\n\n return node.children;\n};\n\nexport const buildFocusScene = (tree: OrbitNode, focusId: string, options: SceneOptions): Scene => {\n const focused = findNodeById(tree, focusId) ?? tree;\n const { viewport, colors, maxDepth, reorder } = options;\n const children = reordered(focused.children, reorder);\n const canGrow = maxDepth === undefined || focused.level < maxDepth;\n const slotIndex = options.addSlot && canGrow\n ? Math.min(children.length, Math.max(0, Math.trunc(options.addSlot.index ?? children.length)))\n : null;\n // Entering a collapsed node opens it: `collapsed` folds a node away\n // elsewhere (no moons, a \"+N\" count), never in its own focus view. The\n // slot for a new idea is laid out as one more child.\n const laidOut: OrbitNode = focused.collapsed || slotIndex !== null || children !== focused.children\n ? { ...focused, collapsed: false, children }\n : focused;\n\n if (slotIndex !== null) {\n const slot: OrbitNode = { id: SLOT_ID, text: '', level: focused.level + 1, children: [] };\n laidOut.children = [...children.slice(0, slotIndex), slot, ...children.slice(slotIndex)];\n }\n\n const layout = calculateFocusLayout(laidOut, {\n cx: 0,\n cy: 0,\n containerWidth: viewport.width,\n containerHeight: viewport.height,\n maxDepth,\n keptRings: options.keptRings?.focusId === focused.id ? options.keptRings.radii : undefined,\n });\n const slotCount = slotIndex === null ? 0 : 1;\n const nodes = new Map<string, SceneNode>();\n const colorOf = (node: OrbitNode) => colors.get(node.id) ?? node.color ?? '#999999';\n\n nodes.set(focused.id, {\n id: focused.id,\n node: focused,\n role: 'sun',\n x: 0,\n y: 0,\n radius: layout.sun.radius,\n color: colorOf(focused),\n depth: focused.level,\n parentId: focused.parent?.id,\n hiddenChildren: Math.max(0, children.length - (layout.planets.length - slotCount)),\n spins: false,\n });\n\n let extentX = layout.sun.radius;\n let extentY = layout.sun.radius;\n const planetRadius = roomyPlanetRadius(layout);\n const crowded = layout.planets.length - slotCount > CROWDED_ORBIT;\n let addSlot: SceneSlot | undefined;\n\n for (const planet of layout.planets) {\n if (planet.id === SLOT_ID) {\n addSlot = {\n parentId: focused.id,\n index: slotIndex ?? focused.children.length,\n x: planet.x,\n y: planet.y,\n radius: planetRadius ?? planet.radius,\n orbitAngle: planet.angle,\n orbitRadius: planet.orbitRadius,\n };\n extentX = Math.max(extentX, planet.orbitRadius + addSlot.radius);\n extentY = Math.max(extentY, planet.orbitRadius + addSlot.radius);\n continue;\n }\n\n const node = findNodeById(focused, planet.id) ?? planet;\n const moons = visibleChildren(node, maxDepth).slice(0, MOON_LIMIT);\n const radius = planetRadius ?? planet.radius;\n nodes.set(planet.id, {\n id: planet.id,\n node,\n role: 'planet',\n x: planet.x,\n y: planet.y,\n radius,\n color: colorOf(node),\n depth: node.level,\n parentId: focused.id,\n orbitAngle: planet.angle,\n orbitRadius: planet.orbitRadius,\n hiddenChildren: node.children.length - moons.length,\n spins: true,\n crowded,\n });\n const { distance: moonDistance, radius: moonRadius, offsets } = moonPlacement(radius, moons.length);\n\n moons.forEach((moon, index) => {\n const offset = offsets[index];\n const angle = toRadians(planet.angle + offset);\n nodes.set(moon.id, {\n id: moon.id,\n node: moon,\n role: 'moon',\n x: planet.x + moonDistance * Math.cos(angle),\n y: planet.y + moonDistance * Math.sin(angle),\n radius: moonRadius,\n color: colorOf(moon),\n depth: moon.level,\n parentId: planet.id,\n hostId: planet.id,\n hostOffset: offset,\n hostDistance: moonDistance,\n hiddenChildren: moon.children.length,\n spins: true,\n });\n });\n\n const reach = planet.orbitRadius + (moons.length > 0 ? moonDistance + moonRadius : radius);\n extentX = Math.max(extentX, reach);\n extentY = Math.max(extentY, reach);\n }\n\n const rings: SceneRing[] = layout.planets.length === 0\n ? []\n : layout.orbitRings.map((radius, index) => ({\n id: `${focused.id}#${index}`,\n centerId: focused.id,\n cx: 0,\n cy: 0,\n radius,\n color: colorOf(focused),\n gaps: layout.planets\n .filter((planet) => Math.abs(planet.orbitRadius - radius) < 0.5)\n .map((planet) => ({ angle: planet.angle, halfWidth: gapHalfWidth(planetRadius ?? planet.radius, radius) })),\n spins: true,\n }));\n\n const extent = { x: extentX, y: extentY };\n return {\n kind: 'focus',\n focusId: focused.id,\n nodes,\n rings,\n links: [],\n frame: fitExtent('focus', extent, viewport, options.insets),\n extent,\n addSlot,\n };\n};\n\n/**\n * A single ring of planets usually has room to spare: grow the planets\n * (and with them their moons) toward the sun's size, as far as the\n * neighbors and the sun allow. Null keeps the layout's size.\n */\nconst roomyPlanetRadius = (layout: ReturnType<typeof calculateFocusLayout>): number | null => {\n if (layout.orbitRings.length !== 1 || layout.planets.length === 0) {\n return null;\n }\n\n const ring = layout.orbitRings[0];\n const count = layout.planets.length;\n // Half the distance to a neighbor, less the moons that reach sideways.\n const besideNeighbors = count > 1 ? (ring * Math.sin(Math.PI / count) - 14) / 1.45 : Infinity;\n const besideSun = ring - layout.sun.radius - 24;\n const current = layout.planets[0].radius;\n return Math.max(current, Math.min(layout.sun.radius * 0.72, besideNeighbors, besideSun));\n};\n\nexport const buildOverviewScene = (tree: OrbitNode, options: SceneOptions): Scene => {\n const { viewport, colors, maxDepth } = options;\n const positioned = calculateAllLayout(tree, {\n cx: 0,\n cy: 0,\n containerWidth: viewport.width,\n containerHeight: viewport.height,\n maxDepth,\n });\n const nodes = new Map<string, SceneNode>();\n const links: SceneLink[] = [];\n const byId = indexTree(tree);\n let extentX = 0;\n let extentY = 0;\n\n for (const entry of positioned) {\n const node = byId.get(entry.id) ?? entry;\n const color = colors.get(node.id) ?? '#999999';\n const shown = visibleChildren(node, maxDepth).length;\n nodes.set(entry.id, {\n id: entry.id,\n node,\n role: 'node',\n x: entry.x,\n y: entry.y,\n radius: entry.radius,\n color,\n depth: node.level,\n parentId: entry.parent?.id,\n hiddenChildren: node.children.length - shown,\n spins: false,\n });\n\n if (entry.parent && node.level > 0) {\n links.push({ id: `${entry.parent.id}->${entry.id}`, fromId: entry.parent.id, toId: entry.id, color: colors.get(entry.parent.id) ?? color });\n }\n\n extentX = Math.max(extentX, Math.abs(entry.x) + entry.radius);\n extentY = Math.max(extentY, Math.abs(entry.y) + entry.radius);\n }\n\n const bodiesByCenter = new Map<string, typeof positioned>();\n\n for (const entry of positioned) {\n const parentId = entry.parent?.id;\n\n if (parentId !== undefined) {\n const bodies = bodiesByCenter.get(parentId) ?? [];\n bodies.push(entry);\n bodiesByCenter.set(parentId, bodies);\n }\n }\n\n const rings: SceneRing[] = getOrbitRings(positioned).map((ring) => {\n const { centerId } = ring;\n const bodies = bodiesByCenter.get(centerId) ?? [];\n return {\n id: `${centerId}#overview`,\n centerId,\n cx: ring.cx,\n cy: ring.cy,\n radius: ring.r,\n color: colors.get(centerId) ?? '#999999',\n gaps: bodies.map((body) => ({\n angle: toDegrees(Math.atan2(body.y - ring.cy, body.x - ring.cx)),\n halfWidth: gapHalfWidth(body.radius, ring.r),\n })),\n spins: false,\n };\n });\n\n // A ring reaches past the bodies on it where none of them sit near its extremes.\n for (const ring of rings) {\n extentX = Math.max(extentX, Math.abs(ring.cx) + ring.radius);\n extentY = Math.max(extentY, Math.abs(ring.cy) + ring.radius);\n }\n\n const extent = { x: extentX, y: extentY };\n return {\n kind: 'overview',\n focusId: tree.id,\n nodes,\n rings,\n links,\n frame: fitExtent('overview', extent, viewport, options.insets),\n extent,\n };\n};\n\n/** Every node of a tree by id. */\nconst indexTree = (tree: OrbitNode): Map<string, OrbitNode> => {\n const byId = new Map<string, OrbitNode>();\n\n const visit = (node: OrbitNode) => {\n byId.set(node.id, node);\n node.children.forEach(visit);\n };\n\n visit(tree);\n return byId;\n};\n\n/**\n * The transform that places `target` so the node `anchorId` lands exactly\n * where it is displayed now (`current`): used to fly from one view to the\n * next without any jump.\n */\nexport const alignScene = (target: Scene, anchorId: string, current: { x: number; y: number; radius: number }): Similarity => {\n const anchor = target.nodes.get(anchorId);\n\n if (!anchor || anchor.radius <= 0) {\n return { scale: 1, x: 0, y: 0 };\n }\n\n const scale = current.radius / anchor.radius;\n return { scale, x: current.x - anchor.x * scale, y: current.y - anchor.y * scale };\n};\n\n/** Applies a placement to a scene node's position and size. */\nexport const placeNode = (node: SceneNode, transform: Similarity): { x: number; y: number; radius: number } => {\n const point = applySimilarity(transform, node);\n return { x: point.x, y: point.y, radius: node.radius * transform.scale };\n};\n\n/** Gap half-width (degrees) that keeps a ring line clear of a body of `bodyRadius` sitting on it. */\nconst gapHalfWidth = (bodyRadius: number, ringRadius: number): number => {\n const ratio = Math.min(1, (bodyRadius + RING_GAP_PADDING) / Math.max(ringRadius, 1));\n return toDegrees(Math.asin(ratio));\n};\n\nexport const toRadians = (degrees: number): number => {\n return (degrees * Math.PI) / 180;\n};\n\nexport const toDegrees = (radians: number): number => {\n return (radians * 180) / Math.PI;\n};\n",
|
|
33
|
+
"/**\n * Scenes: what each view of a map contains, in world coordinates.\n *\n * A focus scene puts the focused node (the sun) at the origin with its\n * children (planets) on rings and its grandchildren as small moons around\n * them. An overview scene lays out the whole tree around the root. Every\n * node keeps one color in every scene, and nodes are keyed by id so a\n * transition can morph the same node from one scene into the next: the\n * moons of a planet grow into the planets of the next view.\n */\n\nimport type { OrbitNode } from '../types.js';\nimport { branchNumbers, branchPalette, isPaletteNumber, paletteColorOf } from '../branch-colors.js';\nimport { calculateAllLayout, calculateFocusLayout, getOrbitRings, MOON_LIMIT, moonPlacement } from '../layout.js';\nimport { findNodeById } from '../utils.js';\nimport { browser } from '../browser.js';\nimport { fitAround, type Camera, type Insets, type Similarity, type Viewport, applySimilarity } from './camera.js';\n\nexport type NodeRole = 'sun' | 'planet' | 'moon' | 'node';\n\nexport interface SceneNode {\n id: string;\n node: OrbitNode;\n role: NodeRole;\n\n /** World position of the center, before any orbit spin. */\n x: number;\n\n y: number;\n radius: number;\n color: string;\n depth: number;\n parentId?: string;\n\n /** Planets: angle around the sun (degrees, −90 = top) and distance from it. */\n orbitAngle?: number;\n\n orbitRadius?: number;\n\n /** Moons: the planet they circle, their angle relative to the direction from the sun to the planet, and their distance. */\n hostId?: string;\n\n hostOffset?: number;\n hostDistance?: number;\n\n /** Children that exist but aren't drawn: beyond the moon limit, or under a collapsed node. */\n hiddenChildren: number;\n\n /** Turns with the orbit when it spins. */\n spins: boolean;\n\n /** A planet of an orbit too crowded for each planet's shadow to read: drawn flat. */\n crowded?: boolean;\n}\n\nexport interface SceneRing {\n id: string;\n centerId: string;\n cx: number;\n cy: number;\n radius: number;\n color: string;\n\n /** Openings around each body on the ring, so the line never runs through a node. */\n gaps: { angle: number; halfWidth: number }[];\n\n spins: boolean;\n}\n\nexport interface SceneLink {\n id: string;\n fromId: string;\n toId: string;\n color: string;\n}\n\nexport interface Scene {\n kind: 'focus' | 'overview';\n focusId: string;\n nodes: Map<string, SceneNode>;\n rings: SceneRing[];\n links: SceneLink[];\n\n /** The camera that fits the scene into the viewport. */\n frame: Camera;\n\n /**\n * How far the scene reaches from its focus node on each axis, in world\n * units: what `frame` fits. A focus scene reaches as far on both, the edge\n * of its orbit at every turn.\n */\n extent: { x: number; y: number };\n\n /** Focus scenes of editable maps: the free place in the orbit where a new idea goes. */\n addSlot?: SceneSlot;\n}\n\n/** A free place in the sun's orbit, laid out like a planet, for the next child. */\nexport interface SceneSlot {\n /** The node a new idea there becomes a child of: the sun. */\n parentId: string;\n\n /** Its position among the sun's children. */\n index: number;\n\n x: number;\n y: number;\n radius: number;\n orbitAngle: number;\n orbitRadius: number;\n}\n\nexport interface SceneOptions {\n viewport: Viewport;\n\n /** The parts of the viewport the page's own controls cover: views are fitted into the rest. */\n insets?: Insets;\n\n colors: Map<string, string>;\n maxDepth?: number;\n\n /** Keep a place in the orbit for a new idea, after the sun's children (or at `index`). Focus scenes only. */\n addSlot?: { index?: number };\n\n /**\n * One of the sun's children being dragged to another place among them: it's\n * laid out at `index` among the others, so they make room for it there.\n * Focus scenes only.\n */\n reorder?: { id: string; index: number };\n\n /**\n * While a node is carried along the orbit of `focusId`: the radii its rings\n * had when the drag began. They keep them until the drop, so the orbit\n * doesn't grow or shrink as the places in it move. Focus scenes only.\n */\n keptRings?: { focusId: string; radii: number[] };\n}\n\n/** The id the slot uses while it is laid out with the planets; no node can have it. */\nconst SLOT_ID = '\\u0000orbit-add';\n\nexport { MOON_LIMIT };\n/** More planets than this in one view, and their shadows overlap into a haze: they're drawn flat. */\nexport const CROWDED_ORBIT = 48;\n/** The largest zoom a fitted view uses, so small maps don't balloon. */\nconst MAXIMUM_FIT_SCALE = 1.35;\nconst FOCUS_PADDING = 40;\nconst OVERVIEW_PADDING = 48;\n\n/** Room kept around a fitted view: less on small screens, where every pixel counts. */\nconst fitPadding = (viewport: Viewport, padding: number): number => {\n return Math.min(padding, Math.max(16, Math.min(viewport.width, viewport.height) * 0.05));\n};\n\n/**\n * The camera that fits a view reaching `extent` from its focus node into\n * `viewport`, inside what `insets` leave of it, with at least `below` px\n * between the view and the lower edge of that.\n */\nconst fitExtent = (kind: Scene['kind'], extent: Scene['extent'], viewport: Viewport, insets: Insets | undefined, below = 0): Camera => {\n const padding = fitPadding(viewport, kind === 'focus' ? FOCUS_PADDING : OVERVIEW_PADDING);\n const room = Math.max(0, below - padding);\n const sides = insets ?? { top: 0, right: 0, bottom: 0, left: 0 };\n return fitAround({ x: 0, y: 0 }, extent, viewport, padding, MAXIMUM_FIT_SCALE, room > 0 ? { ...sides, bottom: sides.bottom + room } : sides);\n};\n\n/**\n * The camera that fits `scene` into `viewport` as its `frame` does, inside\n * what `insets` leave of it, and with at least `below` px under it: room for\n * something drawn there, such as the focused node's buttons.\n */\nexport const fitScene = (scene: Scene, viewport: Viewport, insets?: Insets, below = 0): Camera => {\n return fitExtent(scene.kind, scene.extent, viewport, insets, below);\n};\n\nconst RING_GAP_PADDING = 7;\n\n/**\n * One color per node, the same in every view. The root uses the first\n * palette entry; top-level branches take the others in turn (see\n * `branchNumbers`); deeper nodes use their branch's color, mixed toward the\n * theme's `shade-light` or `shade-dark` by position so siblings stay\n * distinguishable. A node's own color always wins: its `color`, or its\n * type's (see `ownColor`); then its `paletteColor`.\n */\nexport const assignNodeColors = (\n tree: OrbitNode,\n palette: string[],\n ownColor: (node: OrbitNode) => string | undefined = (node) => node.color,\n): Map<string, string> => {\n const colors = new Map<string, string>();\n const branchColors = branchPalette(palette);\n const numbers = branchNumbers(tree.children, branchColors.length);\n const chosen = (node: OrbitNode): string | undefined => ownColor(node) ?? (isPaletteNumber(node.paletteColor) ? paletteColorOf(branchColors, node.paletteColor) : undefined);\n colors.set(tree.id, chosen(tree) ?? palette[0]);\n\n for (const branch of tree.children) {\n const branchColor = ownColor(branch) ?? paletteColorOf(branchColors, numbers.get(branch) as number);\n colors.set(branch.id, branchColor);\n\n const visit = (node: OrbitNode, inherited: string) => {\n node.children.forEach((child, siblingIndex) => {\n const own = chosen(child);\n colors.set(child.id, own ?? shade(inherited, siblingIndex));\n visit(child, own ?? inherited);\n });\n };\n\n visit(branch, branchColor);\n }\n\n return colors;\n};\n\n/** How much of the branch color each sibling keeps, and what the rest is mixed with. */\nexport const SHADES: [number, 'light' | 'dark'][] = [\n [100, 'light'],\n [78, 'light'],\n [86, 'dark'],\n [62, 'light'],\n [76, 'dark'],\n];\n\nconst shade = (color: string, siblingIndex: number): string => {\n const [amount, toward] = SHADES[siblingIndex % SHADES.length];\n return amount === 100 || !browser.mixesColors ? color : `color-mix(in oklab, ${color} ${amount}%, var(--_orbit-shade-${toward}))`;\n};\n\n/** `children` with the one `reorder` names moved to its index among the others (unchanged without it). */\nconst reordered = (children: OrbitNode[], reorder: SceneOptions['reorder']): OrbitNode[] => {\n const moving = reorder ? children.find((child) => child.id === reorder.id) : undefined;\n\n if (!reorder || !moving) {\n return children;\n }\n\n const others = children.filter((child) => child !== moving);\n const index = Math.min(others.length, Math.max(0, Math.trunc(reorder.index)));\n return [...others.slice(0, index), moving, ...others.slice(index)];\n};\n\nconst visibleChildren = (node: OrbitNode, maxDepth: number | undefined): OrbitNode[] => {\n if (node.collapsed) {\n return [];\n }\n\n if (maxDepth !== undefined && node.level >= maxDepth) {\n return [];\n }\n\n return node.children;\n};\n\nexport const buildFocusScene = (tree: OrbitNode, focusId: string, options: SceneOptions): Scene => {\n const focused = findNodeById(tree, focusId) ?? tree;\n const { viewport, colors, maxDepth, reorder } = options;\n const children = reordered(focused.children, reorder);\n const canGrow = maxDepth === undefined || focused.level < maxDepth;\n const slotIndex = options.addSlot && canGrow\n ? Math.min(children.length, Math.max(0, Math.trunc(options.addSlot.index ?? children.length)))\n : null;\n // Entering a collapsed node opens it: `collapsed` folds a node away\n // elsewhere (no moons, a \"+N\" count), never in its own focus view. The\n // slot for a new idea is laid out as one more child.\n const laidOut: OrbitNode = focused.collapsed || slotIndex !== null || children !== focused.children\n ? { ...focused, collapsed: false, children }\n : focused;\n\n if (slotIndex !== null) {\n const slot: OrbitNode = { id: SLOT_ID, text: '', level: focused.level + 1, children: [] };\n laidOut.children = [...children.slice(0, slotIndex), slot, ...children.slice(slotIndex)];\n }\n\n const layout = calculateFocusLayout(laidOut, {\n cx: 0,\n cy: 0,\n containerWidth: viewport.width,\n containerHeight: viewport.height,\n maxDepth,\n keptRings: options.keptRings?.focusId === focused.id ? options.keptRings.radii : undefined,\n });\n const slotCount = slotIndex === null ? 0 : 1;\n const nodes = new Map<string, SceneNode>();\n const colorOf = (node: OrbitNode) => colors.get(node.id) ?? node.color ?? '#999999';\n\n nodes.set(focused.id, {\n id: focused.id,\n node: focused,\n role: 'sun',\n x: 0,\n y: 0,\n radius: layout.sun.radius,\n color: colorOf(focused),\n depth: focused.level,\n parentId: focused.parent?.id,\n hiddenChildren: Math.max(0, children.length - (layout.planets.length - slotCount)),\n spins: false,\n });\n\n let extentX = layout.sun.radius;\n let extentY = layout.sun.radius;\n const planetRadius = roomyPlanetRadius(layout);\n const crowded = layout.planets.length - slotCount > CROWDED_ORBIT;\n let addSlot: SceneSlot | undefined;\n\n for (const planet of layout.planets) {\n if (planet.id === SLOT_ID) {\n addSlot = {\n parentId: focused.id,\n index: slotIndex ?? focused.children.length,\n x: planet.x,\n y: planet.y,\n radius: planetRadius ?? planet.radius,\n orbitAngle: planet.angle,\n orbitRadius: planet.orbitRadius,\n };\n extentX = Math.max(extentX, planet.orbitRadius + addSlot.radius);\n extentY = Math.max(extentY, planet.orbitRadius + addSlot.radius);\n continue;\n }\n\n const node = findNodeById(focused, planet.id) ?? planet;\n const moons = visibleChildren(node, maxDepth).slice(0, MOON_LIMIT);\n const radius = planetRadius ?? planet.radius;\n nodes.set(planet.id, {\n id: planet.id,\n node,\n role: 'planet',\n x: planet.x,\n y: planet.y,\n radius,\n color: colorOf(node),\n depth: node.level,\n parentId: focused.id,\n orbitAngle: planet.angle,\n orbitRadius: planet.orbitRadius,\n hiddenChildren: node.children.length - moons.length,\n spins: true,\n crowded,\n });\n const { distance: moonDistance, radius: moonRadius, offsets } = moonPlacement(radius, moons.length);\n\n moons.forEach((moon, index) => {\n const offset = offsets[index];\n const angle = toRadians(planet.angle + offset);\n nodes.set(moon.id, {\n id: moon.id,\n node: moon,\n role: 'moon',\n x: planet.x + moonDistance * Math.cos(angle),\n y: planet.y + moonDistance * Math.sin(angle),\n radius: moonRadius,\n color: colorOf(moon),\n depth: moon.level,\n parentId: planet.id,\n hostId: planet.id,\n hostOffset: offset,\n hostDistance: moonDistance,\n hiddenChildren: moon.children.length,\n spins: true,\n });\n });\n\n const reach = planet.orbitRadius + (moons.length > 0 ? moonDistance + moonRadius : radius);\n extentX = Math.max(extentX, reach);\n extentY = Math.max(extentY, reach);\n }\n\n const rings: SceneRing[] = layout.planets.length === 0\n ? []\n : layout.orbitRings.map((radius, index) => ({\n id: `${focused.id}#${index}`,\n centerId: focused.id,\n cx: 0,\n cy: 0,\n radius,\n color: colorOf(focused),\n gaps: layout.planets\n .filter((planet) => Math.abs(planet.orbitRadius - radius) < 0.5)\n .map((planet) => ({ angle: planet.angle, halfWidth: gapHalfWidth(planetRadius ?? planet.radius, radius) })),\n spins: true,\n }));\n\n const extent = { x: extentX, y: extentY };\n return {\n kind: 'focus',\n focusId: focused.id,\n nodes,\n rings,\n links: [],\n frame: fitExtent('focus', extent, viewport, options.insets),\n extent,\n addSlot,\n };\n};\n\n/**\n * A single ring of planets usually has room to spare: grow the planets\n * (and with them their moons) toward the sun's size, as far as the\n * neighbors and the sun allow. Null keeps the layout's size.\n */\nconst roomyPlanetRadius = (layout: ReturnType<typeof calculateFocusLayout>): number | null => {\n if (layout.orbitRings.length !== 1 || layout.planets.length === 0) {\n return null;\n }\n\n const ring = layout.orbitRings[0];\n const count = layout.planets.length;\n // Half the distance to a neighbor, less the moons that reach sideways.\n const besideNeighbors = count > 1 ? (ring * Math.sin(Math.PI / count) - 14) / 1.45 : Infinity;\n const besideSun = ring - layout.sun.radius - 24;\n const current = layout.planets[0].radius;\n return Math.max(current, Math.min(layout.sun.radius * 0.72, besideNeighbors, besideSun));\n};\n\nexport const buildOverviewScene = (tree: OrbitNode, options: SceneOptions): Scene => {\n const { viewport, colors, maxDepth } = options;\n const positioned = calculateAllLayout(tree, {\n cx: 0,\n cy: 0,\n containerWidth: viewport.width,\n containerHeight: viewport.height,\n maxDepth,\n });\n const nodes = new Map<string, SceneNode>();\n const links: SceneLink[] = [];\n const byId = indexTree(tree);\n let extentX = 0;\n let extentY = 0;\n\n for (const entry of positioned) {\n const node = byId.get(entry.id) ?? entry;\n const color = colors.get(node.id) ?? '#999999';\n const shown = visibleChildren(node, maxDepth).length;\n nodes.set(entry.id, {\n id: entry.id,\n node,\n role: 'node',\n x: entry.x,\n y: entry.y,\n radius: entry.radius,\n color,\n depth: node.level,\n parentId: entry.parent?.id,\n hiddenChildren: node.children.length - shown,\n spins: false,\n });\n\n if (entry.parent && node.level > 0) {\n links.push({ id: `${entry.parent.id}->${entry.id}`, fromId: entry.parent.id, toId: entry.id, color: colors.get(entry.parent.id) ?? color });\n }\n\n extentX = Math.max(extentX, Math.abs(entry.x) + entry.radius);\n extentY = Math.max(extentY, Math.abs(entry.y) + entry.radius);\n }\n\n const bodiesByCenter = new Map<string, typeof positioned>();\n\n for (const entry of positioned) {\n const parentId = entry.parent?.id;\n\n if (parentId !== undefined) {\n const bodies = bodiesByCenter.get(parentId) ?? [];\n bodies.push(entry);\n bodiesByCenter.set(parentId, bodies);\n }\n }\n\n const rings: SceneRing[] = getOrbitRings(positioned).map((ring) => {\n const { centerId } = ring;\n const bodies = bodiesByCenter.get(centerId) ?? [];\n return {\n id: `${centerId}#overview`,\n centerId,\n cx: ring.cx,\n cy: ring.cy,\n radius: ring.r,\n color: colors.get(centerId) ?? '#999999',\n gaps: bodies.map((body) => ({\n angle: toDegrees(Math.atan2(body.y - ring.cy, body.x - ring.cx)),\n halfWidth: gapHalfWidth(body.radius, ring.r),\n })),\n spins: false,\n };\n });\n\n // A ring reaches past the bodies on it where none of them sit near its extremes.\n for (const ring of rings) {\n extentX = Math.max(extentX, Math.abs(ring.cx) + ring.radius);\n extentY = Math.max(extentY, Math.abs(ring.cy) + ring.radius);\n }\n\n const extent = { x: extentX, y: extentY };\n return {\n kind: 'overview',\n focusId: tree.id,\n nodes,\n rings,\n links,\n frame: fitExtent('overview', extent, viewport, options.insets),\n extent,\n };\n};\n\n/** Every node of a tree by id. */\nconst indexTree = (tree: OrbitNode): Map<string, OrbitNode> => {\n const byId = new Map<string, OrbitNode>();\n\n const visit = (node: OrbitNode) => {\n byId.set(node.id, node);\n node.children.forEach(visit);\n };\n\n visit(tree);\n return byId;\n};\n\n/**\n * The transform that places `target` so the node `anchorId` lands exactly\n * where it is displayed now (`current`): used to fly from one view to the\n * next without any jump.\n */\nexport const alignScene = (target: Scene, anchorId: string, current: { x: number; y: number; radius: number }): Similarity => {\n const anchor = target.nodes.get(anchorId);\n\n if (!anchor || anchor.radius <= 0) {\n return { scale: 1, x: 0, y: 0 };\n }\n\n const scale = current.radius / anchor.radius;\n return { scale, x: current.x - anchor.x * scale, y: current.y - anchor.y * scale };\n};\n\n/** Applies a placement to a scene node's position and size. */\nexport const placeNode = (node: SceneNode, transform: Similarity): { x: number; y: number; radius: number } => {\n const point = applySimilarity(transform, node);\n return { x: point.x, y: point.y, radius: node.radius * transform.scale };\n};\n\n/** Gap half-width (degrees) that keeps a ring line clear of a body of `bodyRadius` sitting on it. */\nconst gapHalfWidth = (bodyRadius: number, ringRadius: number): number => {\n const ratio = Math.min(1, (bodyRadius + RING_GAP_PADDING) / Math.max(ringRadius, 1));\n return toDegrees(Math.asin(ratio));\n};\n\nexport const toRadians = (degrees: number): number => {\n return (degrees * Math.PI) / 180;\n};\n\nexport const toDegrees = (radians: number): number => {\n return (radians * 180) / Math.PI;\n};\n",
|
|
33
34
|
"/**\n * What is on screen this frame. Pure functions: a scene plus the orbit's\n * rotation gives the resting display; during a flight, the current display\n * morphs into the target scene placed in today's world coordinates.\n */\n\nimport type { OrbitNode } from '../types.js';\nimport { applySimilarity, transformCamera, type Camera, type CameraPath, type Similarity } from './camera.js';\nimport { interpolate, within } from './animation-clock.js';\nimport { toRadians, type NodeRole, type Scene, type SceneRing } from './scene.js';\n\nexport interface DisplayNode {\n id: string;\n node: OrbitNode;\n role: NodeRole;\n x: number;\n y: number;\n radius: number;\n opacity: number;\n\n /** Multiplies the label's own visibility rules (level of detail, role). */\n labelOpacity: number;\n\n color: string;\n depth: number;\n hiddenChildren: number;\n parentId?: string;\n hostId?: string;\n\n /** A planet of a crowded orbit, drawn flat (see `drawsFlat`). */\n crowded?: boolean;\n\n /** During a flight, how the node comes or goes with its siblings (see `Cluster`). */\n cluster?: Cluster;\n\n /** A body that turns with its orbit: where it is in the unturned orbit (see `OrbitTurn`). */\n unturned?: Point;\n}\n\n/**\n * A focused orbit at rest, turned `rotation` degrees about its sun at\n * (`cx`, `cy`). Each body that turns with it (those with `unturned`) is drawn\n * where it is in the unturned orbit, in a group that turns, so spinning the\n * orbit moves the group instead of every body in it.\n */\nexport interface OrbitTurn {\n cx: number;\n cy: number;\n rotation: number;\n}\n\ninterface Point {\n readonly x: number;\n readonly y: number;\n}\n\n/**\n * During a flight, nodes that come or go together: the children of one\n * parent growing out of it, shrinking into it, or fading where they are.\n * Each is drawn at its own `x`, `y`, `radius` and `nodeOpacity`, which hold\n * still, scaled by `scale` about the pivot with `opacity` on top, which are\n * the same for all of them, so a family can be moved as one.\n */\nexport interface Cluster {\n pivotX: number;\n pivotY: number;\n scale: number;\n opacity: number;\n x: number;\n y: number;\n radius: number;\n nodeOpacity: number;\n}\n\nexport interface DisplayRing {\n id: string;\n centerId: string;\n cx: number;\n cy: number;\n radius: number;\n color: string;\n gaps: SceneRing['gaps'];\n\n /** Degrees added to every gap angle (the orbit's spin). */\n rotation: number;\n\n opacity: number;\n}\n\nexport interface DisplayLink {\n id: string;\n fromId: string;\n toId: string;\n color: string;\n opacity: number;\n}\n\n/** The free place in the orbit for a new idea (see `SceneSlot`), where it is this frame. */\nexport interface DisplaySlot {\n parentId: string;\n index: number;\n x: number;\n y: number;\n radius: number;\n opacity: number;\n\n /** Where the slot is in the unturned orbit (see `OrbitTurn`). */\n unturned?: Point;\n}\n\nexport interface Display {\n nodes: Map<string, DisplayNode>;\n rings: DisplayRing[];\n links: DisplayLink[];\n camera: Camera;\n addSlot?: DisplaySlot;\n\n /** A focused orbit at rest. */\n turn?: OrbitTurn;\n}\n\n/** A scene at rest, with its orbit turned by `rotation` degrees. */\nexport const sceneDisplay = (scene: Scene, rotation: number, camera: Camera): Display => {\n const nodes = new Map<string, DisplayNode>();\n const sun = scene.nodes.get(scene.focusId);\n const centerX = sun?.x ?? 0;\n const centerY = sun?.y ?? 0;\n\n for (const node of scene.nodes.values()) {\n let x = node.x;\n let y = node.y;\n let unturned: Point | undefined;\n\n if (node.spins && node.role === 'planet' && node.orbitAngle !== undefined && node.orbitRadius !== undefined) {\n const angle = toRadians(node.orbitAngle + rotation);\n x = centerX + node.orbitRadius * Math.cos(angle);\n y = centerY + node.orbitRadius * Math.sin(angle);\n unturned = node;\n }\n\n nodes.set(node.id, {\n id: node.id,\n node: node.node,\n role: node.role,\n x,\n y,\n radius: node.radius,\n opacity: 1,\n labelOpacity: 1,\n color: node.color,\n depth: node.depth,\n hiddenChildren: node.hiddenChildren,\n parentId: node.parentId,\n hostId: node.hostId,\n crowded: node.crowded,\n unturned,\n });\n }\n\n // Moons follow their planet around the sun.\n for (const node of scene.nodes.values()) {\n if (node.role !== 'moon' || !node.hostId) {\n continue;\n }\n\n const host = scene.nodes.get(node.hostId);\n const hostDisplay = nodes.get(node.hostId);\n const moon = nodes.get(node.id);\n\n if (!host || !hostDisplay || !moon || host.orbitAngle === undefined) {\n continue;\n }\n\n const angle = toRadians(host.orbitAngle + rotation + (node.hostOffset ?? 0));\n moon.x = hostDisplay.x + (node.hostDistance ?? 0) * Math.cos(angle);\n moon.y = hostDisplay.y + (node.hostDistance ?? 0) * Math.sin(angle);\n moon.unturned = hostDisplay.unturned && node;\n }\n\n let addSlot: DisplaySlot | undefined;\n\n if (scene.addSlot) {\n const { parentId, index, orbitAngle, orbitRadius, radius } = scene.addSlot;\n const angle = toRadians(orbitAngle + rotation);\n addSlot = { parentId, index, x: centerX + orbitRadius * Math.cos(angle), y: centerY + orbitRadius * Math.sin(angle), radius, opacity: 1, unturned: scene.addSlot };\n }\n\n return {\n nodes,\n rings: scene.rings.map((ring) => ({ ...ring, rotation: ring.spins ? rotation : 0, opacity: 1 })),\n links: scene.links.map((link) => ({ ...link, opacity: 1 })),\n camera,\n addSlot,\n turn: scene.kind === 'focus' ? { cx: centerX, cy: centerY, rotation } : undefined,\n };\n};\n\nexport interface Transition {\n /** The display when the flight started, in the current world. */\n from: Display;\n\n /** Fade out and in without moving anything, for readers who prefer reduced motion. */\n fade?: boolean;\n\n /** The destination scene in its own coordinates. */\n target: Scene;\n\n /** Places `target` in the current world. */\n placement: Similarity;\n\n cameraPath: CameraPath;\n startedAt: number;\n duration: number;\n}\n\n/** The camera that frames `scene` once it is placed by `placement`. */\nexport const placedFrame = (scene: Scene, placement: Similarity): Camera => {\n return transformCamera(placement, scene.frame);\n};\n\n/**\n * The display `progress` (0–1, already eased) of the way through a flight.\n * Nodes in both views travel; new nodes grow out of their parent (or fade\n * in where they will be); nodes that leave shrink into their parent in the\n * new view (or fade where they are, as the camera passes them).\n */\n/** A flight's destination at rest, placed in today's world: the same on every frame of the flight. */\ninterface PlacedTarget {\n resting: Display;\n nodes: Map<string, DisplayNode>;\n}\n\nconst placedTargets = new WeakMap<Transition, PlacedTarget>();\n\nconst placedTarget = (transition: Transition): PlacedTarget => {\n const cached = placedTargets.get(transition);\n\n if (cached) {\n return cached;\n }\n\n const { target, placement } = transition;\n const resting = sceneDisplay(target, 0, target.frame);\n const nodes = new Map<string, DisplayNode>();\n\n for (const node of resting.nodes.values()) {\n const point = applySimilarity(placement, node);\n nodes.set(node.id, { ...node, x: point.x, y: point.y, radius: node.radius * placement.scale });\n }\n\n const placed = { resting, nodes };\n placedTargets.set(transition, placed);\n return placed;\n};\n\nexport const transitionDisplay = (transition: Transition, progress: number): Display => {\n const { from, target, placement } = transition;\n const { resting: restingTarget, nodes: destination } = placedTarget(transition);\n\n const nodes = new Map<string, DisplayNode>();\n const enterProgress = within(progress, 0.25, 1);\n const exitProgress = within(progress, 0, 0.6);\n\n for (const [id, end] of destination) {\n const start = from.nodes.get(id);\n\n if (start) {\n nodes.set(id, {\n ...end,\n role: progress < 0.5 ? start.role : end.role,\n x: interpolate(start.x, end.x, progress),\n y: interpolate(start.y, end.y, progress),\n radius: interpolate(start.radius, end.radius, progress),\n opacity: interpolate(start.opacity, 1, progress),\n labelOpacity: interpolate(start.labelOpacity, 1, progress),\n });\n continue;\n }\n\n const origin = (end.parentId && from.nodes.get(end.parentId)) || undefined;\n\n if (origin) {\n const opacity = within(progress, 0.25, 0.6);\n nodes.set(id, {\n ...end,\n x: interpolate(origin.x, end.x, enterProgress),\n y: interpolate(origin.y, end.y, enterProgress),\n radius: end.radius * enterProgress,\n opacity,\n labelOpacity: within(progress, 0.6, 1),\n cluster: { pivotX: origin.x, pivotY: origin.y, scale: enterProgress, opacity, x: end.x, y: end.y, radius: end.radius, nodeOpacity: 1 },\n });\n } else {\n nodes.set(id, {\n ...end,\n opacity: enterProgress,\n labelOpacity: within(progress, 0.6, 1),\n cluster: { pivotX: 0, pivotY: 0, scale: 1, opacity: enterProgress, x: end.x, y: end.y, radius: end.radius, nodeOpacity: 1 },\n });\n }\n }\n\n for (const [id, start] of from.nodes) {\n if (destination.has(id)) {\n continue;\n }\n\n const into = (start.parentId && destination.get(start.parentId)) || undefined;\n const remaining = 1 - exitProgress;\n\n if (into) {\n nodes.set(id, {\n ...start,\n x: interpolate(start.x, into.x, exitProgress),\n y: interpolate(start.y, into.y, exitProgress),\n radius: start.radius * remaining,\n opacity: start.opacity * remaining,\n labelOpacity: start.labelOpacity * (1 - within(progress, 0, 0.35)),\n cluster: { pivotX: into.x, pivotY: into.y, scale: remaining, opacity: remaining, x: start.x, y: start.y, radius: start.radius, nodeOpacity: start.opacity },\n });\n } else {\n nodes.set(id, {\n ...start,\n opacity: start.opacity * remaining,\n labelOpacity: start.labelOpacity * (1 - within(progress, 0, 0.35)),\n cluster: { pivotX: 0, pivotY: 0, scale: 1, opacity: remaining, x: start.x, y: start.y, radius: start.radius, nodeOpacity: start.opacity },\n });\n }\n }\n\n const rings: DisplayRing[] = [];\n\n for (const ring of from.rings) {\n rings.push({ ...ring, opacity: ring.opacity * (1 - within(progress, 0, 0.5)) });\n }\n\n for (const ring of restingTarget.rings) {\n const center = applySimilarity(placement, { x: ring.cx, y: ring.cy });\n const finalRadius = ring.radius * placement.scale;\n const startCenter = from.nodes.get(ring.centerId);\n const startRadius = startCenter ? Math.min(finalRadius, startCenter.radius * 1.6) : finalRadius * 0.6;\n const ringProgress = within(progress, 0.2, 1);\n rings.push({\n ...ring,\n id: `${ring.id}@target`,\n cx: center.x,\n cy: center.y,\n radius: interpolate(startRadius, finalRadius, ringProgress),\n opacity: within(progress, 0.3, 1),\n });\n }\n\n const targetLinks = new Set(target.links.map((link) => link.id));\n const links: DisplayLink[] = from.links\n .filter((link) => !targetLinks.has(link.id))\n .map((link) => ({ ...link, opacity: link.opacity * (1 - within(progress, 0, 0.5)) }));\n const sharedLinks = new Set(from.links.map((link) => link.id));\n\n for (const link of target.links) {\n links.push({ ...link, opacity: sharedLinks.has(link.id) ? 1 : within(progress, 0.4, 1) });\n }\n\n return {\n nodes,\n rings,\n links,\n camera: transition.cameraPath.at(progress),\n addSlot: transitionSlot(from.addSlot, restingTarget.addSlot && placeSlot(restingTarget.addSlot, placement), progress),\n };\n};\n\nconst placeSlot = (slot: DisplaySlot, placement: Similarity): DisplaySlot => {\n const point = applySimilarity(placement, slot);\n return { ...slot, x: point.x, y: point.y, radius: slot.radius * placement.scale };\n};\n\n/**\n * The slot for a new idea during a flight: it slides to its next place in\n * the same orbit (after an idea joins it, say); otherwise the old one fades\n * as the flight starts and the new one appears as it lands.\n */\nconst transitionSlot = (start: DisplaySlot | undefined, end: DisplaySlot | undefined, progress: number): DisplaySlot | undefined => {\n if (start && end && start.parentId === end.parentId) {\n return {\n ...end,\n x: interpolate(start.x, end.x, progress),\n y: interpolate(start.y, end.y, progress),\n radius: interpolate(start.radius, end.radius, progress),\n opacity: interpolate(start.opacity, 1, progress),\n };\n }\n\n if (end && progress >= 0.5) {\n return { ...end, opacity: within(progress, 0.7, 1) };\n }\n\n return start && { ...start, opacity: start.opacity * (1 - within(progress, 0, 0.3)) };\n};\n\n/**\n * A view change without movement: the old view fades out, then the new one\n * fades in already in place (in its own coordinates, with its own camera).\n */\nexport const fadeDisplay = (transition: Transition, progress: number): Display => {\n if (progress < 0.5) {\n const visible = 1 - progress * 2;\n const nodes = new Map<string, DisplayNode>();\n\n for (const [id, node] of transition.from.nodes) {\n nodes.set(id, { ...node, opacity: node.opacity * visible, labelOpacity: node.labelOpacity * visible });\n }\n\n const slot = transition.from.addSlot;\n return {\n nodes,\n rings: transition.from.rings.map((ring) => ({ ...ring, opacity: ring.opacity * visible })),\n links: transition.from.links.map((link) => ({ ...link, opacity: link.opacity * visible })),\n camera: transition.from.camera,\n addSlot: slot && { ...slot, opacity: slot.opacity * visible },\n };\n }\n\n const visible = (progress - 0.5) * 2;\n const resting = sceneDisplay(transition.target, 0, transition.target.frame);\n\n for (const node of resting.nodes.values()) {\n node.opacity = visible;\n node.labelOpacity = visible;\n }\n\n return {\n ...resting,\n rings: resting.rings.map((ring) => ({ ...ring, opacity: visible })),\n links: resting.links.map((link) => ({ ...link, opacity: visible })),\n addSlot: resting.addSlot && { ...resting.addSlot, opacity: visible },\n };\n};\n",
|
|
34
35
|
"/**\n * Small color helpers: parse the formats browsers report for computed\n * colors, mix in OKLab like CSS `color-mix(in oklab, …)`, measure WCAG\n * contrast to choose label colors, and resolve the map's theme tokens into\n * plain hex colors for exports that leave the page.\n */\n\n/** sRGB channels and alpha, each 0–1. */\nexport interface Rgb {\n red: number;\n green: number;\n blue: number;\n alpha: number;\n}\n\nconst NAMED: Record<string, string> = {\n white: '#ffffff',\n black: '#000000',\n transparent: '#00000000',\n};\n\n/**\n * A CSS number: signed, with or without digits before the point, with an\n * exponent. Browsers report a mixed node's fill as `oklab(0.73 -0.089 0.027)`,\n * and people write `rgba(0, 0, 0, .5)`. Malformed text like `1.2.3` or\n * `1-2` doesn't match, so it never becomes a NaN channel.\n */\nconst NUMBER = String.raw`[-+]?(?:\\d*\\.\\d+|\\d+)(?:e[-+]?\\d+)?`;\nconst RGB = new RegExp(String.raw`^rgba?\\(\\s*(${NUMBER})(%?)[\\s,]+(${NUMBER})(%?)[\\s,]+(${NUMBER})(%?)(?:\\s*[,/]\\s*(${NUMBER})(%?))?\\s*\\)$`);\nconst SRGB = new RegExp(String.raw`^color\\(srgb\\s+(${NUMBER})\\s+(${NUMBER})\\s+(${NUMBER})(?:\\s*\\/\\s*(${NUMBER})(%?))?\\s*\\)$`);\nconst OKLAB = new RegExp(String.raw`^oklab\\(\\s*(${NUMBER})(%?)\\s+(${NUMBER})\\s+(${NUMBER})(?:\\s*\\/\\s*(${NUMBER})(%?))?\\s*\\)$`);\nconst OKLCH = new RegExp(String.raw`^oklch\\(\\s*(${NUMBER})(%?)\\s+(${NUMBER})\\s+(${NUMBER})(?:deg)?(?:\\s*\\/\\s*(${NUMBER})(%?))?\\s*\\)$`);\n\nexport const parseColor = (input: string): Rgb | null => {\n const value = input.trim().toLowerCase();\n\n if (NAMED[value]) {\n return parseColor(NAMED[value]);\n }\n\n let match = /^#([0-9a-f]{3,8})$/.exec(value);\n\n if (match) {\n return parseHex(match[1]);\n }\n\n match = RGB.exec(value);\n\n if (match) {\n // A channel is out of 255, or out of 100 when written as a percentage.\n const channel = (amount: string, percent: string) => Number(amount) / (percent === '%' ? 100 : 255);\n return {\n red: channel(match[1], match[2]),\n green: channel(match[3], match[4]),\n blue: channel(match[5], match[6]),\n alpha: readAlpha(match[7], match[8]),\n };\n }\n\n match = SRGB.exec(value);\n\n if (match) {\n return { red: Number(match[1]), green: Number(match[2]), blue: Number(match[3]), alpha: readAlpha(match[4], match[5]) };\n }\n\n match = OKLAB.exec(value);\n\n if (match) {\n const lightness = Number(match[1]) / (match[2] === '%' ? 100 : 1);\n return fromOklab(lightness, Number(match[3]), Number(match[4]), readAlpha(match[5], match[6]));\n }\n\n match = OKLCH.exec(value);\n\n if (match) {\n const lightness = Number(match[1]) / (match[2] === '%' ? 100 : 1);\n const chroma = Number(match[3]);\n const hue = (Number(match[4]) * Math.PI) / 180;\n return fromOklab(lightness, chroma * Math.cos(hue), chroma * Math.sin(hue), readAlpha(match[5], match[6]));\n }\n\n return null;\n};\n\nconst parseHex = (digits: string): Rgb | null => {\n const expanded = digits.length === 3 || digits.length === 4\n ? digits.split('').map((digit) => digit + digit).join('')\n : digits;\n\n if (expanded.length !== 6 && expanded.length !== 8) {\n return null;\n }\n\n const channel = (index: number) => parseInt(expanded.slice(index, index + 2), 16) / 255;\n return { red: channel(0), green: channel(2), blue: channel(4), alpha: expanded.length === 8 ? channel(6) : 1 };\n};\n\nconst readAlpha = (value: string | undefined, percent: string | undefined): number => {\n if (value === undefined) {\n return 1;\n }\n\n return Number(value) / (percent === '%' ? 100 : 1);\n};\n\nexport const toHex = (color: Rgb): string => {\n const channel = (value: number) => Math.round(Math.min(1, Math.max(0, value)) * 255).toString(16).padStart(2, '0');\n const alpha = color.alpha < 1 ? channel(color.alpha) : '';\n return `#${channel(color.red)}${channel(color.green)}${channel(color.blue)}${alpha}`;\n};\n\nconst toLinear = (channel: number): number => {\n return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;\n};\n\nconst fromLinear = (channel: number): number => {\n return channel <= 0.0031308 ? channel * 12.92 : 1.055 * channel ** (1 / 2.4) - 0.055;\n};\n\nconst toOklab = (color: Rgb): [number, number, number] => {\n const red = toLinear(color.red);\n const green = toLinear(color.green);\n const blue = toLinear(color.blue);\n const long = Math.cbrt(0.4122214708 * red + 0.5363325363 * green + 0.0514459929 * blue);\n const medium = Math.cbrt(0.2119034982 * red + 0.6806995451 * green + 0.1073969566 * blue);\n const short = Math.cbrt(0.0883024619 * red + 0.2817188376 * green + 0.6299787005 * blue);\n return [\n 0.2104542553 * long + 0.793617785 * medium - 0.0040720468 * short,\n 1.9779984951 * long - 2.428592205 * medium + 0.4505937099 * short,\n 0.0259040371 * long + 0.7827717662 * medium - 0.808675766 * short,\n ];\n};\n\n/** An OKLab color's linear-light sRGB channels, unclamped: outside 0–1 when sRGB can't show it. */\nconst oklabToLinear = (lightness: number, a: number, b: number): [number, number, number] => {\n const long = (lightness + 0.3963377774 * a + 0.2158037573 * b) ** 3;\n const medium = (lightness - 0.1055613458 * a - 0.0638541728 * b) ** 3;\n const short = (lightness - 0.0894841775 * a - 1.291485548 * b) ** 3;\n return [\n 4.0767416621 * long - 3.3077115913 * medium + 0.2309699292 * short,\n -1.2684380046 * long + 2.6097574011 * medium - 0.3413193965 * short,\n -0.0041960863 * long - 0.7034186147 * medium + 1.707614701 * short,\n ];\n};\n\nconst fromOklab = (lightness: number, a: number, b: number, alpha: number): Rgb => {\n const [red, green, blue] = oklabToLinear(lightness, a, b);\n return { red: fromLinear(red), green: fromLinear(green), blue: fromLinear(blue), alpha };\n};\n\n/** A color's OKLCH coordinates: lightness (0–1), chroma and hue in degrees. */\nexport interface Oklch {\n lightness: number;\n chroma: number;\n hue: number;\n}\n\nexport const toOklch = (color: Rgb): Oklch => {\n const [lightness, a, b] = toOklab(color);\n const chroma = Math.hypot(a, b);\n const hue = chroma < 1e-4 ? 0 : ((Math.atan2(b, a) * 180) / Math.PI + 360) % 360;\n return { lightness, chroma, hue };\n};\n\n/**\n * The relative luminance of a Material tone, which is CIELAB's L*: tone 0 is\n * black, 50 a middle gray and 100 white. Two tones 50 apart always have at\n * least 4.5:1 contrast, which is how Material keeps text readable.\n */\nconst toneLuminance = (tone: number): number => {\n return tone > 8 ? ((tone + 16) / 116) ** 3 : tone / 903.2962962962963;\n};\n\n/** Luminance and whether sRGB can show the OKLCH color. */\nconst measureOklch = (lightness: number, chroma: number, hue: number): { luminance: number; shown: boolean } => {\n const angle = (hue * Math.PI) / 180;\n const channels = oklabToLinear(lightness, chroma * Math.cos(angle), chroma * Math.sin(angle));\n const [red, green, blue] = channels;\n return {\n luminance: 0.2126 * red + 0.7152 * green + 0.0722 * blue,\n shown: channels.every((channel) => channel >= -1e-5 && channel <= 1 + 1e-5),\n };\n};\n\n/** The OKLab lightness that gives a color of this chroma and hue the luminance asked for. */\nconst lightnessFor = (luminance: number, chroma: number, hue: number): number => {\n let low = 0;\n let high = 1;\n\n for (let step = 0; step < 32; step += 1) {\n const middle = (low + high) / 2;\n\n if (measureOklch(middle, chroma, hue).luminance < luminance) {\n low = middle;\n } else {\n high = middle;\n }\n }\n\n return (low + high) / 2;\n};\n\n/**\n * A color of `hue` (OKLCH degrees) at a Material tone: as much of `chroma` as\n * sRGB can show at that luminance, so every hue at one tone has the same\n * contrast with every other tone.\n */\nexport const toneColor = (hue: number, chroma: number, tone: number): Rgb => {\n const luminance = toneLuminance(Math.min(100, Math.max(0, tone)));\n const fits = (candidate: number) => measureOklch(lightnessFor(luminance, candidate, hue), candidate, hue).shown;\n let shown = chroma;\n\n if (!fits(chroma)) {\n let low = 0;\n let high = chroma;\n\n for (let step = 0; step < 20; step += 1) {\n const middle = (low + high) / 2;\n\n if (fits(middle)) {\n low = middle;\n } else {\n high = middle;\n }\n }\n\n shown = low;\n }\n\n const lightness = lightnessFor(luminance, shown, hue);\n const angle = (hue * Math.PI) / 180;\n const color = fromOklab(lightness, shown * Math.cos(angle), shown * Math.sin(angle), 1);\n const clamp = (channel: number) => Math.min(1, Math.max(0, channel));\n return { red: clamp(color.red), green: clamp(color.green), blue: clamp(color.blue), alpha: 1 };\n};\n\n/** `color-mix(in oklab, first amount, second)` with `amount` from 0 to 1. */\nexport const mixOklab = (first: Rgb, second: Rgb, amount: number): Rgb => {\n const [firstLightness, firstA, firstB] = toOklab(first);\n const [secondLightness, secondA, secondB] = toOklab(second);\n const mix = (from: number, to: number) => from * amount + to * (1 - amount);\n return fromOklab(\n mix(firstLightness, secondLightness),\n mix(firstA, secondA),\n mix(firstB, secondB),\n mix(first.alpha, second.alpha),\n );\n};\n\n/** WCAG relative luminance (0–1) of a color's sRGB channels, ignoring alpha. */\nexport const relativeLuminance = (color: Rgb): number => {\n return 0.2126 * toLinear(color.red) + 0.7152 * toLinear(color.green) + 0.0722 * toLinear(color.blue);\n};\n\n/** WCAG contrast ratio (1–21) between two opaque colors. */\nexport const contrastRatio = (first: Rgb, second: Rgb): number => {\n const [lighter, darker] = [relativeLuminance(first), relativeLuminance(second)].sort((left, right) => right - left);\n return (lighter + 0.05) / (darker + 0.05);\n};\n\n/**\n * Whether `lightText` reads better than `darkText` on `fill`: the one with\n * more contrast wins, a tie going to the light text. When the text colors\n * can't be parsed, light text goes on fills darker than mid-gray.\n */\nexport const prefersLightText = (fill: string, lightText: string, darkText: string): boolean => {\n const background = parseColor(fill);\n\n if (!background) {\n return false;\n }\n\n const light = parseColor(lightText);\n const dark = parseColor(darkText);\n\n if (!light || !dark) {\n return relativeLuminance(background) < 0.18;\n }\n\n return contrastRatio(background, light) >= contrastRatio(background, dark);\n};\n\n/** A color as an opaque hex value and an opacity, for SVG attributes that design tools read. */\nexport const splitAlpha = (color: string): { color: string; opacity: number } => {\n const parsed = parseColor(color);\n\n if (!parsed) {\n return { color, opacity: 1 };\n }\n\n return { color: toHex({ ...parsed, alpha: 1 }), opacity: Math.round(parsed.alpha * 1000) / 1000 };\n};\n\n/**\n * Resolves `var(--_orbit-token)` references and `color-mix(in oklab, …)`\n * into a hex color using concrete token values. Returns the input unchanged\n * when part of it can't be resolved.\n */\nexport const resolveColor = (value: string, tokens: Record<string, string>): string => {\n const substituted = value.replace(/var\\(--_?orbit-([a-z0-9-]+)(?:\\s*,\\s*([^()]+))?\\)/gi, (whole, token: string, fallback?: string) => {\n return tokens[token] ?? fallback?.trim() ?? whole;\n });\n\n const mix = /^color-mix\\(\\s*in\\s+oklab\\s*,\\s*(.+?)\\s+(\\d*\\.\\d+|\\d+)%\\s*,\\s*(.+?)\\s*\\)$/i.exec(substituted.trim());\n\n if (mix) {\n const first = parseColor(resolveColor(mix[1], tokens));\n const second = parseColor(resolveColor(mix[3], tokens));\n\n if (first && second) {\n return toHex(mixOklab(first, second, Number(mix[2]) / 100));\n }\n\n return value;\n }\n\n const parsed = parseColor(substituted);\n return parsed ? toHex(parsed) : substituted;\n};\n",
|
|
35
36
|
"/**\n * Text broken into pieces and wrapped, for labels in exported SVGs and for\n * planning where labels go. Without a font to measure with, widths are\n * estimates from the kind of each character: CJK, kana, Hangul and emoji\n * are about as wide as the font is tall, and other letters a little over\n * half that.\n */\n\nimport type { TextMeasure } from './engine/text-measure.js';\n\nexport interface TextLayout {\n lines: string[];\n truncated: boolean;\n lineHeight: number;\n totalHeight: number;\n}\n\n/** Average width of a narrow character, in ems. */\nexport const NARROW_EMS = 0.55;\n\n/**\n * Characters about as wide as the font is tall: Hangul jamo, CJK (radicals\n * and punctuation through ideographs, kana, bopomofo and Yi), Hangul\n * syllables, CJK compatibility and full-width forms, the ideographs past\n * U+20000, and emoji.\n */\nexport const WIDE_CHARACTER = /[\\u1100-\\u115F\\u2E80-\\uA4CF\\uA960-\\uA97F\\uAC00-\\uD7A3\\uF900-\\uFAFF\\uFE30-\\uFE4F\\uFF00-\\uFF60\\uFFE0-\\uFFE6\\u{20000}-\\u{3FFFD}]|\\p{Extended_Pictographic}/u;\n\n/** Scripts written without spaces, which may break between any two of their characters. */\nconst BREAKS_ANYWHERE = /[⺀-〾ぁ-㏿㐀-䶿一-鿿가-힣豈--⦆\\u{20000}-\\u{3FFFD}]/u;\n\n/**\n * Text in Latin-1 and plain spaces only: one character is one grapheme, none\n * of them wide or breaking anywhere. Most names are, and they skip the\n * segmenter, which is slow to call for each of a big map's names.\n */\nconst PLAIN = /^[\\x20-\\x7e\\xa0-\\xff\\u2000-\\u200a]*$/;\n\nlet segmenter: Intl.Segmenter | null | undefined;\n\n/** The characters of `text` as people see them, so an emoji with its modifiers stays whole. */\nexport const graphemes = (text: string): string[] => {\n if (PLAIN.test(text)) {\n return text.split('');\n }\n\n if (segmenter === undefined) {\n segmenter = typeof Intl !== 'undefined' && 'Segmenter' in Intl ? new Intl.Segmenter(undefined, { granularity: 'grapheme' }) : null;\n }\n\n return segmenter ? Array.from(segmenter.segment(text), (part) => part.segment) : Array.from(text);\n};\n\n/** How many narrow and wide characters `text` has. */\nexport const characterWidths = (text: string): { narrow: number; wide: number } => {\n if (PLAIN.test(text)) {\n return { narrow: text.length, wide: 0 };\n }\n\n let wide = 0;\n const all = graphemes(text);\n\n for (const character of all) {\n if (WIDE_CHARACTER.test(character)) {\n wide += 1;\n }\n }\n\n return { narrow: all.length - wide, wide };\n};\n\n/** Estimated width of `text`, in ems. */\nexport const textEms = (text: string): number => {\n const { narrow, wide } = characterWidths(text);\n return narrow * NARROW_EMS + wide;\n};\n\nconst estimatedEms = textEms;\n\n/** A piece of text that stays on one line, and whether a space comes before it. */\nexport interface TextUnit {\n text: string;\n spaced: boolean;\n}\n\n/** Spaces a line may break at: every kind but the no-break ones, which keep their neighbors together. */\nexport const BREAKING_SPACE = /[^\\S\\u00a0\\u202f\\ufeff]+/u;\n\n/**\n * Where a word may break besides between CJK characters: after an\n * underscore, slash or hyphen, after a dot or colon a letter follows, and\n * between a lowercase and an uppercase letter. Identifiers such as\n * `contact_tec_mail_address_key`, `docs/format.md` or `startedAt` then wrap\n * where they read, instead of being cut short.\n */\nconst WORD_BREAK = /(?<=[_/\\\\-])(?=.)|(?<=[.:])(?=\\p{L})|(?<=\\p{Ll})(?=\\p{Lu})/u;\n\n/** A word cut where it may break onto another line. */\nexport const wordPieces = (word: string): string[] => {\n return word.split(WORD_BREAK).filter(Boolean);\n};\n\n/**\n * Where text may break: between words, inside long words where they read\n * (`wordPieces`), and between the characters of scripts written without spaces.\n */\nexport const breakUnits = (text: string): TextUnit[] => {\n const units: TextUnit[] = [];\n\n for (const [index, word] of text.split(BREAKING_SPACE).filter(Boolean).entries()) {\n let run = '';\n let first = true;\n\n const push = (piece: string) => {\n units.push({ text: piece, spaced: first && index > 0 });\n first = false;\n };\n\n for (const piece of wordPieces(word)) {\n if (PLAIN.test(piece)) {\n push(piece);\n continue;\n }\n\n for (const character of graphemes(piece)) {\n if (BREAKS_ANYWHERE.test(character)) {\n if (run) {\n push(run);\n run = '';\n }\n\n push(character);\n } else {\n run += character;\n }\n }\n\n if (run) {\n push(run);\n run = '';\n }\n }\n }\n\n return units;\n};\n\n/** Joins units back into text, with their spaces. */\nexport const joinUnits = (units: TextUnit[]): string => {\n return units.map((unit, index) => (index > 0 && unit.spaced ? ` ${unit.text}` : unit.text)).join('');\n};\n\n/** As much of `text` as fits in `maxEms` with an ellipsis after it, cut between characters. */\nconst truncate = (text: string, maxEms: number, ems: (value: string) => number): string => {\n let kept = '';\n\n for (const character of graphemes(text)) {\n if (ems(`${kept}${character}…`) > maxEms) {\n break;\n }\n\n kept += character;\n }\n\n return `${kept.trimEnd()}…`;\n};\n\n/**\n * Wraps text into at most `maxLines` lines of `maxWidth` pixels, ending with\n * an ellipsis when cut. Widths are estimates, unless `measure` measures them\n * in the font the text is drawn with.\n */\nexport const wrapText = (\n text: string,\n maxWidth: number,\n fontSize: number,\n maxLines = 3,\n measure?: Pick<TextMeasure, 'ems'>,\n): TextLayout => {\n const textEms = measure ? (value: string) => measure.ems(value, fontSize) : estimatedEms;\n // Room for at least three narrow characters, however small the space.\n const maxEms = Math.max(3 * NARROW_EMS, maxWidth / fontSize);\n const lineHeight = fontSize * 1.3;\n\n const lines: string[] = [];\n let current: TextUnit[] = [];\n\n for (const unit of breakUnits(text)) {\n const candidate = joinUnits([...current, unit]);\n\n if (current.length === 0 || textEms(candidate) <= maxEms) {\n current.push(unit);\n\n if (current.length === 1 && textEms(unit.text) > maxEms) {\n lines.push(truncate(unit.text, maxEms, textEms));\n current = [];\n }\n\n continue;\n }\n\n lines.push(joinUnits(current));\n current = [{ ...unit, spaced: false }];\n\n if (textEms(unit.text) > maxEms) {\n lines.push(truncate(unit.text, maxEms, textEms));\n current = [];\n }\n }\n\n if (current.length > 0) {\n lines.push(joinUnits(current));\n }\n\n const truncated = lines.length > maxLines;\n const resultLines = lines.slice(0, maxLines);\n\n if (truncated && resultLines.length === maxLines) {\n const last = resultLines[maxLines - 1];\n\n if (!last.endsWith('…')) {\n resultLines[maxLines - 1] = textEms(`${last}…`) <= maxEms ? `${last}…` : truncate(last, maxEms, textEms);\n }\n }\n\n return {\n lines: resultLines,\n truncated,\n lineHeight,\n totalHeight: resultLines.length * lineHeight,\n };\n};\n",
|
|
36
37
|
"/**\n * How wide label text is, in ems of the font it's drawn with. In a browser,\n * names are measured with the fonts the page gives the map's labels (each\n * theme's, a node type's own, a page's brand font), so a name fills its\n * node as far as it really reaches and never spills out of it. Where there's\n * no canvas to measure with (a server, tests), widths are estimated from the\n * kind of each character.\n */\n\nimport type { OrbitNode } from '../types.js';\nimport type { MapExtensions } from '../extensions.js';\nimport type { OrbitThemeToken } from '../themes.js';\nimport type { NodeRole } from './scene.js';\nimport { WIDE_CHARACTER, characterWidths, graphemes } from '../text-layout.js';\n\n/** Text widths in one font. */\nexport interface TextMeasure {\n /** Equal keys measure alike: caches of fitted labels are kept by it. */\n readonly key: string;\n\n /** Whether widths in ems differ by font size (fonts with optical sizes); estimates don't. */\n readonly bySize: boolean;\n\n /** The width of `text` on one line at `fontSize` px, in ems. */\n ems(text: string, fontSize: number): number;\n\n /** The space between two words, in ems. */\n space(fontSize: number): number;\n\n /** The ellipsis a cut name ends with, in ems. */\n ellipsis(fontSize: number): number;\n\n /** How wide the font draws, as `font-stretch` (a percentage of its normal width). */\n readonly stretch: number;\n\n /**\n * The same font drawn narrower, for names that don't fit at its width,\n * or null when it has no narrower width (most fonts don't: only those\n * with a width axis or condensed faces do).\n */\n narrower(): TextMeasure | null;\n}\n\n/** The measures a map's labels are fitted with: names inside nodes, pills beside them, and the \"+N\" names keep clear of. */\nexport interface LabelMeasures {\n /** Equal keys measure alike. */\n readonly key: string;\n\n /** For a node's name inside it. */\n inside(role: NodeRole, node?: OrbitNode): TextMeasure;\n\n /** For a node's name on its pill. */\n pill(role: NodeRole, node?: OrbitNode): TextMeasure;\n\n /** For the \"+N\" a node shows for children that aren't drawn. */\n count(): TextMeasure;\n}\n\n/** Widths estimated from the kind of each character: wide ones (CJK, emoji) take an em, the rest `narrow`. */\nclass EstimatedMeasure implements TextMeasure {\n readonly key: string;\n readonly bySize = false;\n readonly stretch = 100;\n private readonly narrow: number;\n private readonly spaceWidth: number;\n private readonly ellipsisWidth: number;\n\n constructor(narrow: number, spaceWidth: number, ellipsisWidth: number) {\n this.narrow = narrow;\n this.spaceWidth = spaceWidth;\n this.ellipsisWidth = ellipsisWidth;\n this.key = `estimate ${narrow}`;\n }\n\n ems(text: string): number {\n // One character at a time, when a cut name is filled to its ellipsis.\n if (text.length === 1) {\n return WIDE_CHARACTER.test(text) ? 1 : this.narrow;\n }\n\n const { narrow, wide } = characterWidths(text);\n return narrow * this.narrow + wide;\n }\n\n space(): number {\n return this.spaceWidth;\n }\n\n ellipsis(): number {\n return this.ellipsisWidth;\n }\n\n narrower(): TextMeasure | null {\n return null;\n }\n}\n\n/** A name inside its node: semibold UI fonts average a little under 0.58 em a character. */\nexport const INSIDE_ESTIMATE: TextMeasure = new EstimatedMeasure(0.58, 0.3, 0.8);\n/** A name on a pill: 6.4 px a character in its 11.5 px text. */\nexport const PILL_ESTIMATE: TextMeasure = new EstimatedMeasure(6.4 / 11.5, 0.3, 0.8);\n/** A \"+N\": its plus sign and figures, in semibold text, take a little over two thirds of an em each. */\nexport const COUNT_ESTIMATE: TextMeasure = new EstimatedMeasure(0.7, 0.3, 0.8);\n\n/** Estimates for every label, where nothing can be measured. */\nexport const ESTIMATED_LABELS: LabelMeasures = {\n key: 'estimate',\n inside: () => INSIDE_ESTIMATE,\n pill: () => PILL_ESTIMATE,\n count: () => COUNT_ESTIMATE,\n};\n\ntype MeasuringContext = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;\n\n/**\n * The two sizes text is measured at. Labels are drawn between them, and\n * fonts with optical sizes draw small text wider: widths at the sizes in\n * between are interpolated.\n */\nconst SMALL_SIZE = 9;\nconst LARGE_SIZE = 16;\n\n/** What a label's font is, as the page computes it. */\nexport interface LabelFont {\n family: string;\n weight: string;\n style: string;\n\n /** `font-stretch`, as a percentage of the normal width. */\n stretch: number;\n\n /** Space after each character, in ems. */\n letterSpacing: number;\n}\n\n/** The canvas keyword for a width, as `font-stretch` percentages map to them. */\nconst stretchKeyword = (stretch: number): string => {\n const keywords: [number, string][] = [\n [50, 'ultra-condensed'], [62.5, 'extra-condensed'], [75, 'condensed'], [87.5, 'semi-condensed'], [100, 'normal'],\n [112.5, 'semi-expanded'], [125, 'expanded'], [150, 'extra-expanded'], [200, 'ultra-expanded'],\n ];\n let nearest = keywords[4];\n\n for (const keyword of keywords) {\n if (Math.abs(keyword[0] - stretch) < Math.abs(nearest[0] - stretch)) {\n nearest = keyword;\n }\n }\n\n return nearest[1];\n};\n\n/** The widths a name tries, narrowest last, when it doesn't fit at its font's own: semi-condensed, then condensed. */\nconst NARROWER_WIDTHS = [87.5, 75];\n/** A narrower width counts only if it draws text at least this much narrower. */\nconst NOTICEABLY_NARROWER = 0.97;\n\n/**\n * Text in scripts that draw each letter on its own (Latin, Greek, Cyrillic,\n * with digits, punctuation and spaces): its width is the sum of its\n * letters', give or take kerning, which only ever makes a word narrower.\n * Measuring letters instead of words takes a canvas call per letter of the\n * alphabet, not per name: a big map brings hundreds of new names into view\n * at a time.\n */\nconst LETTER_BY_LETTER = /^[\\u0020-\\u052F\\u1E00-\\u1FFF\\u2000-\\u206F\\u20A0-\\u20BF]*$/;\n\n/** Text measured in a font with a canvas, at two sizes, interpolated between them. */\nclass CanvasMeasure implements TextMeasure {\n readonly key: string;\n readonly bySize = true;\n private readonly context: MeasuringContext;\n private readonly font: LabelFont;\n private readonly widths = new Map<string, [number, number]>();\n private readonly letters = new Map<string, [number, number]>();\n private narrowerMeasure: TextMeasure | null | undefined;\n\n constructor(context: MeasuringContext, font: LabelFont, key: string) {\n this.context = context;\n this.font = font;\n this.key = key;\n }\n\n ems(text: string, fontSize: number): number {\n let widths = this.widths.get(text);\n\n if (!widths) {\n widths = LETTER_BY_LETTER.test(text) ? this.sumOfLetters(text) : [this.measure(text, SMALL_SIZE), this.measure(text, LARGE_SIZE)];\n\n if (this.widths.size >= MEASURED_TEXTS_LIMIT) {\n this.widths.clear();\n }\n\n this.widths.set(text, widths);\n }\n\n const share = Math.min(1, Math.max(0, (fontSize - SMALL_SIZE) / (LARGE_SIZE - SMALL_SIZE)));\n return widths[0] + (widths[1] - widths[0]) * share;\n }\n\n space(fontSize: number): number {\n return this.ems(' ', fontSize);\n }\n\n ellipsis(fontSize: number): number {\n return this.ems('…', fontSize);\n }\n\n get stretch(): number {\n return this.font.stretch;\n }\n\n narrower(): TextMeasure | null {\n if (this.narrowerMeasure !== undefined) {\n return this.narrowerMeasure;\n }\n\n this.narrowerMeasure = null;\n const stretch = NARROWER_WIDTHS.find((width) => width < this.font.stretch);\n\n if (stretch !== undefined && 'fontStretch' in this.context) {\n const narrower = measureFor({ ...this.font, stretch });\n const sample = 'Orbit names';\n\n if (narrower && narrower.ems(sample, 13) < this.ems(sample, 13) * NOTICEABLY_NARROWER) {\n this.narrowerMeasure = narrower;\n }\n }\n\n return this.narrowerMeasure;\n }\n\n private sumOfLetters(text: string): [number, number] {\n let small = 0;\n let large = 0;\n\n for (const letter of text) {\n let widths = this.letters.get(letter);\n\n if (!widths) {\n widths = [this.measure(letter, SMALL_SIZE), this.measure(letter, LARGE_SIZE)];\n this.letters.set(letter, widths);\n }\n\n small += widths[0];\n large += widths[1];\n }\n\n return [small, large];\n }\n\n private measure(text: string, size: number): number {\n const { context, font } = this;\n context.font = `${font.style} ${font.weight} ${size}px ${font.family}`;\n\n if ('fontStretch' in context) {\n context.fontStretch = stretchKeyword(font.stretch) as CanvasFontStretch;\n }\n\n const spacing = font.letterSpacing === 0 ? 0 : font.letterSpacing * graphemes(text).length;\n return context.measureText(text).width / size + spacing;\n }\n}\n\n/** More texts than the largest maps have; past it, a font's measurements start over. */\nconst MEASURED_TEXTS_LIMIT = 50000;\n\nlet sharedContext: MeasuringContext | null | undefined;\n\n/** A canvas to measure with, or null where there's none that measures (a server, a DOM without canvas). */\nconst measuringContext = (): MeasuringContext | null => {\n if (sharedContext !== undefined) {\n return sharedContext;\n }\n\n sharedContext = null;\n\n try {\n let context: MeasuringContext | null = null;\n\n if (typeof OffscreenCanvas === 'function') {\n context = new OffscreenCanvas(1, 1).getContext('2d');\n }\n\n if (!context && typeof document !== 'undefined' && typeof document.createElement === 'function') {\n context = document.createElement('canvas').getContext('2d');\n }\n\n // A stand-in canvas (some test DOMs have one) measures nothing: estimates are better than zeros.\n if (context && typeof context.measureText === 'function') {\n context.font = '16px sans-serif';\n\n if (context.measureText('Orbit').width > 0) {\n sharedContext = context;\n }\n }\n } catch {\n sharedContext = null;\n }\n\n if (sharedContext) {\n watchFontLoads();\n }\n\n return sharedContext;\n};\n\n/** Measures by font, shared by every map that draws with the same one. */\nconst canvasMeasures = new Map<string, CanvasMeasure>();\n/** Names the measures: their keys go into the cache key of every label fitted each frame, so they're short. */\nlet measureCount = 0;\n\n/** The measure for a font, or null when nothing can measure it. */\nexport const measureFor = (font: LabelFont): TextMeasure | null => {\n const context = measuringContext();\n\n if (!context || !font.family) {\n return null;\n }\n\n const spec = `${font.style} ${font.weight} ${font.stretch}% ${font.letterSpacing} ${font.family}`;\n let measure = canvasMeasures.get(spec);\n\n if (!measure) {\n measureCount += 1;\n measure = new CanvasMeasure(context, font, `font ${measureCount}`);\n canvasMeasures.set(spec, measure);\n }\n\n return measure;\n};\n\nconst resetListeners = new Set<() => void>();\n\n/**\n * Calls `listener` whenever measurements start over: a font finished loading,\n * so text measured while the page drew it with a fallback measures anew.\n * Returns a function that stops listening.\n */\nexport const onMeasurementsReset = (listener: () => void): () => void => {\n resetListeners.add(listener);\n\n return () => {\n resetListeners.delete(listener);\n };\n};\n\n/** Forgets every measurement, and tells whoever keeps fits made from them. */\nexport const resetMeasurements = (): void => {\n canvasMeasures.clear();\n\n for (const listener of Array.from(resetListeners)) {\n listener();\n }\n};\n\nlet watchingFonts = false;\n\n/** Measures again when the page's fonts finish loading: until then a name may have been measured in a fallback font. */\nconst watchFontLoads = (): void => {\n if (watchingFonts || typeof document === 'undefined') {\n return;\n }\n\n const fonts = (document as Document & { fonts?: FontFaceSet }).fonts;\n\n if (!fonts || typeof fonts.addEventListener !== 'function') {\n return;\n }\n\n watchingFonts = true;\n fonts.addEventListener('loadingdone', () => resetMeasurements());\n};\n\n/** Font properties that set how wide text is, among a node type's tokens. */\nconst FONT_TOKENS: OrbitThemeToken[] = ['font-family', 'label-font', 'display-font', 'label-weight', 'display-weight', 'label-letter-spacing'];\n\n/**\n * The fonts a map's labels are drawn with, read from the page: a hidden\n * label of each kind in the map's label layer, so the theme, the page's\n * own CSS and a node type's tokens all count. Read again when `refresh` is\n * called (the theme or the page may have changed), not on every frame.\n */\nexport class LabelFonts implements LabelMeasures {\n private readonly layer: HTMLElement;\n private readonly extensions: () => MapExtensions | undefined;\n\n /** A hidden box in the label layer holding a label of each kind, to read its font from. */\n private shelf: HTMLElement | null = null;\n\n private probes = new Map<string, HTMLElement>();\n\n /** By kind of label (and node type with a font of its own); null where nothing measures. */\n private measures = new Map<string, TextMeasure | null>();\n\n /** The sun's and other nodes' measures, for nodes without a type: looked up for every label on every frame. */\n private sunMeasure: TextMeasure | null | undefined;\n\n private nameMeasure: TextMeasure | null | undefined;\n\n /** The \"+N\"'s measure: looked up for every label on every frame. */\n private countMeasure: TextMeasure | null | undefined;\n\n private stale = true;\n private currentKey = 'estimate';\n\n /** A recheck waiting for the page to be idle (see `recheckWhenIdle`). */\n private recheck: { cancel: () => void } | null = null;\n\n constructor(layer: HTMLElement, extensions: () => MapExtensions | undefined) {\n this.layer = layer;\n this.extensions = extensions;\n }\n\n /** Equal keys measure alike: a change of font changes the key. */\n get key(): string {\n this.read();\n return this.currentKey;\n }\n\n /** The theme, the page or the fonts may have changed: read the fonts again before the next fit. */\n refresh(): void {\n this.stale = true;\n }\n\n inside(role: NodeRole, node?: OrbitNode): TextMeasure {\n return this.measure(role, node) ?? INSIDE_ESTIMATE;\n }\n\n pill(role: NodeRole, node?: OrbitNode): TextMeasure {\n return this.measure(role, node) ?? PILL_ESTIMATE;\n }\n\n count(): TextMeasure {\n if (this.stale) {\n this.read();\n }\n\n if (this.countMeasure === undefined) {\n const font = this.computedFont('count', 'orbit-count', undefined);\n this.countMeasure = font ? measureFor(font) : null;\n }\n\n return this.countMeasure ?? COUNT_ESTIMATE;\n }\n\n /**\n * Once the page is idle, reads the fonts again and calls `changed` if they\n * differ: a page may switch its fonts at any time (a class, a brand font).\n * Off the frames that draw, so reading doesn't make one late.\n */\n recheckWhenIdle(changed: () => void): void {\n if (this.recheck || measuringContext() === null) {\n return;\n }\n\n const run = () => {\n this.recheck = null;\n const before = this.key;\n this.refresh();\n\n if (this.key !== before) {\n changed();\n }\n };\n\n const idle = (globalThis as { requestIdleCallback?: (callback: () => void, options?: { timeout: number }) => number }).requestIdleCallback;\n\n if (typeof idle === 'function') {\n const handle = idle(run, { timeout: 2000 });\n this.recheck = { cancel: () => (globalThis as { cancelIdleCallback?: (handle: number) => void }).cancelIdleCallback?.(handle) };\n } else {\n const handle = setTimeout(run, 250);\n this.recheck = { cancel: () => clearTimeout(handle) };\n }\n }\n\n /** Takes the hidden labels out of the page. */\n destroy(): void {\n this.recheck?.cancel();\n this.recheck = null;\n this.shelf?.remove();\n this.shelf = null;\n this.probes.clear();\n this.measures.clear();\n }\n\n private read(): void {\n if (!this.stale) {\n return;\n }\n\n this.stale = false;\n this.measures.clear();\n this.sunMeasure = undefined;\n this.nameMeasure = undefined;\n this.countMeasure = undefined;\n const keys = [this.measure('planet'), this.measure('sun'), this.count()].map((measure) => measure?.key ?? 'estimate');\n this.currentKey = keys.join(' | ');\n }\n\n private measure(role: NodeRole, node?: OrbitNode): TextMeasure | null {\n if (this.stale) {\n this.read();\n }\n\n const type = node ? this.extensions()?.typeName(node) ?? node.type : undefined;\n\n if (!node || !type) {\n if (role === 'sun') {\n if (this.sunMeasure === undefined) {\n this.sunMeasure = this.measureOf('sun', role, undefined);\n }\n\n return this.sunMeasure;\n }\n\n if (this.nameMeasure === undefined) {\n this.nameMeasure = this.measureOf('name', role, undefined);\n }\n\n return this.nameMeasure;\n }\n\n // A node type may set its own font: measured on its own, or as untyped nodes are.\n const key = `${role === 'sun' ? 'sun' : 'name'} ${type.toLowerCase()}`;\n const known = this.measures.get(key);\n\n if (known !== undefined || this.measures.has(key)) {\n return known ?? null;\n }\n\n const tokens = this.extensions()?.nodeType(node)?.tokens;\n const ownFont = tokens !== undefined && FONT_TOKENS.some((token) => typeof tokens[token] === 'string' && tokens[token] !== '');\n const measure = ownFont ? this.measureOf(key, role, tokens) : this.measure(role);\n this.measures.set(key, measure);\n return measure;\n }\n\n private measureOf(key: string, role: NodeRole, tokens: Record<string, unknown> | undefined): TextMeasure | null {\n const font = this.computedFont(key, `orbit-label orbit-label--${role === 'sun' ? 'sun' : 'planet'}`, tokens);\n return font ? measureFor(font) : null;\n }\n\n /** The font of a hidden element of `className` (a label, or a \"+N\") in the label layer, with a node type's `tokens`. */\n private computedFont(key: string, className: string, tokens: Record<string, unknown> | undefined): LabelFont | null {\n if (typeof getComputedStyle !== 'function' || !this.layer.isConnected || measuringContext() === null) {\n return null;\n }\n\n let probe = this.probes.get(key);\n\n if (!probe) {\n const document = this.layer.ownerDocument;\n\n if (!this.shelf) {\n this.shelf = document.createElement('div');\n this.shelf.className = 'orbit__font-probes';\n this.shelf.style.display = 'none';\n this.shelf.setAttribute('aria-hidden', 'true');\n this.layer.appendChild(this.shelf);\n }\n\n probe = document.createElement('div');\n probe.className = className;\n\n for (const [token, value] of Object.entries(tokens ?? {})) {\n if (typeof value === 'string' && value !== '') {\n probe.style.setProperty(`--_orbit-${token}`, value);\n }\n }\n\n this.shelf.appendChild(probe);\n this.probes.set(key, probe);\n }\n\n const style = getComputedStyle(probe);\n const fontSize = Number.parseFloat(style.fontSize) || 13;\n const spacing = Number.parseFloat(style.letterSpacing);\n const stretch = Number.parseFloat(style.fontStretch);\n\n if (!style.fontFamily) {\n return null;\n }\n\n return {\n family: style.fontFamily,\n weight: style.fontWeight || '400',\n style: style.fontStyle || 'normal',\n stretch: Number.isFinite(stretch) ? stretch : 100,\n letterSpacing: Number.isFinite(spacing) ? spacing / fontSize : 0,\n };\n }\n}\n",
|
|
37
|
-
"/**\n * DOM views for the map content. Nodes are SVG groups drawn at unit radius\n * and positioned with a single `translate() scale()`, so moving or resizing\n * a node is one attribute write per frame; spinning an orbit turns the group\n * its bodies are in instead (see `OrbitTurn`). Labels are HTML in screen\n * space, so text never scales with the camera and keeps a readable size.\n */\n\nimport type { OrbitNode } from '../types.js';\nimport type { DisplayNode, DisplayRing, DisplaySlot } from './display.js';\nimport type { NodeRole } from './scene.js';\nimport { guardUrl, resolveUrl } from '../url-guard.js';\nimport { hasMediaSource, youtubeThumbnailUrl } from '../media.js';\nimport type { MapExtensions, OrbitNodeType } from '../extensions.js';\nimport { breakUnits, graphemes, wordPieces, type TextUnit } from '../text-layout.js';\nimport { COUNT_ESTIMATE, INSIDE_ESTIMATE, onMeasurementsReset, type TextMeasure } from './text-measure.js';\nimport { OrbitWords } from '../languages.js';\n\n\nexport const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n\nexport interface ViewIds {\n /** Unit-circle clip path shared by every node image. */\n clip: string;\n\n /** Sphere shading gradient. */\n shade: string;\n\n /**\n * The shading of specks: the same, turned back by the turn they're drawn in\n * once their orbit rests, so it comes from the top left (see `turnShading`).\n */\n speckShade: string;\n\n /** Blur for the shadow (or glow) of planets and moons. */\n shadow: string;\n\n /** A wider blur for the sun's. */\n sunShadow: string;\n}\n\nexport const svgElement = <Name extends keyof SVGElementTagNameMap>(name: Name, attributes: Record<string, string> = {}): SVGElementTagNameMap[Name] => {\n const element = document.createElementNS(SVG_NAMESPACE, name);\n\n for (const [key, value] of Object.entries(attributes)) {\n element.setAttribute(key, value);\n }\n\n return element;\n};\n\n/**\n * Where the sphere shading changes, from the lit side (top left) to the far\n * edge. The theme colors each stop (`node-highlight`, `node-terminator`,\n * `node-shading`); the stylesheet and the SVG export share these offsets.\n */\nexport const SHADE_STOPS = [\n { offset: 0, part: 'highlight' },\n { offset: 0.45, part: 'highlight-fade' },\n { offset: 0.55, part: 'terminator-start' },\n { offset: 0.78, part: 'terminator' },\n { offset: 1, part: 'shading' },\n] as const;\n\n/**\n * The circle the shading spreads over, in fractions of a node's box: its\n * center, then its radius. The default lights spheres from the top left; a\n * theme moves it with the `node-shade-circle` token, such as to the bottom\n * right so the far stops catch light along the top left rim, as glass does.\n */\nexport interface ShadeCircle {\n x: number;\n y: number;\n radius: number;\n}\n\nexport const DEFAULT_SHADE_CIRCLE: ShadeCircle = { x: 0.34, y: 0.3, radius: 0.78 };\n\n/** A `node-shade-circle` value (`0.34 0.3 0.78`) read, or the default when it isn't three numbers with a radius above 0. */\nexport const readShadeCircle = (value: string | undefined): ShadeCircle => {\n const numbers = (value ?? '').trim().split(/[\\s,]+/).map(Number);\n\n if (numbers.length !== 3 || !numbers.every(Number.isFinite) || numbers[2] <= 0) {\n return DEFAULT_SHADE_CIRCLE;\n }\n\n const [x, y, radius] = numbers;\n return { x, y, radius };\n};\n\n/** Moves the shading of every node (specks follow it) to the theme's circle. */\nexport const placeShading = (defs: SVGDefsElement, ids: ViewIds, circle: ShadeCircle): void => {\n const gradient = Array.from(defs.children).find((child) => child.id === ids.shade);\n gradient?.setAttribute('cx', String(circle.x));\n gradient?.setAttribute('cy', String(circle.y));\n gradient?.setAttribute('r', String(circle.radius));\n};\n\n/** Blur radius of a shadow, in node radii: planets and moons, then the sun. */\nexport const SHADOW_BLUR = { planet: 0.16, sun: 0.3 } as const;\n\n/** Shared definitions: the image clip, sphere shading and shadow blurs, with instance-scoped ids. */\nexport const createDefinitions = (ids: ViewIds): SVGDefsElement => {\n const defs = svgElement('defs');\n const clip = svgElement('clipPath', { id: ids.clip, clipPathUnits: 'userSpaceOnUse' });\n clip.appendChild(svgElement('circle', { r: '1' }));\n defs.appendChild(clip);\n\n const shade = svgElement('radialGradient', {\n id: ids.shade,\n cx: String(DEFAULT_SHADE_CIRCLE.x),\n cy: String(DEFAULT_SHADE_CIRCLE.y),\n r: String(DEFAULT_SHADE_CIRCLE.radius),\n });\n\n for (const stop of SHADE_STOPS) {\n shade.appendChild(svgElement('stop', { offset: String(stop.offset), class: `orbit-shade__${stop.part}` }));\n }\n\n defs.appendChild(shade);\n defs.appendChild(svgElement('radialGradient', { id: ids.speckShade, href: `#${ids.shade}` }));\n\n for (const [id, blur] of [[ids.shadow, SHADOW_BLUR.planet], [ids.sunShadow, SHADOW_BLUR.sun]] as const) {\n const filter = svgElement('filter', { id, x: '-60%', y: '-60%', width: '220%', height: '220%' });\n filter.appendChild(svgElement('feGaussianBlur', { stdDeviation: String(blur) }));\n defs.appendChild(filter);\n }\n\n return defs;\n};\n\n/**\n * Turns the shading of specks back by `turn` degrees, the turn they're drawn\n * in, so their light comes from the top left. One write for every speck, but\n * the browser draws each of them again: not on every frame of a spin.\n */\nexport const turnShading = (defs: SVGDefsElement, ids: ViewIds, turn: number): void => {\n const gradient = Array.from(defs.children).find((child) => child.id === ids.speckShade);\n\n if (turn === 0) {\n gradient?.removeAttribute('gradientTransform');\n } else {\n gradient?.setAttribute('gradientTransform', `rotate(${-turn} 0.5 0.5)`);\n }\n};\n\nconst ENGLISH = new OrbitWords('en');\n\n/** Labels and the assistive name of a node, in the map's language (English without one). */\nexport const describeNode = (\n node: OrbitNode,\n hiddenChildren: number,\n visibleChildren: number,\n extensions?: MapExtensions,\n words: OrbitWords = ENGLISH,\n): string => {\n const type = extensions?.nodeType(node);\n const parts = [[extensions ? extensions.icon(node) : node.icon, node.text || words.text('untitled')].filter(Boolean).join(' ')];\n\n if (type?.label) {\n parts.push(type.label);\n }\n\n if (node.status) {\n parts.push(words.text('status', { status: node.status }));\n }\n\n const total = visibleChildren + hiddenChildren;\n\n if (total > 0) {\n parts.push(words.count('ideaCount', total));\n }\n\n const content = [\n type?.details ? words.text('hasDetails') : '',\n node.note ? words.text('hasNote') : '',\n hasMediaSource(node.image) ? words.text('hasImage') : '',\n hasMediaSource(node.video) ? words.text('hasVideo') : '',\n hasMediaSource(node.embed) ? words.text('hasEmbed') : '',\n node.link ? words.text('hasLink') : '',\n ].filter(Boolean);\n\n if (content.length > 0) {\n parts.push(words.text('has', { list: words.list(content) }));\n }\n\n return parts.join(', ');\n};\n\n/** Bodies smaller than this on screen (px) are drawn flat: there a shadow is a smudge. */\nconst SMALL_BODY_RADIUS = 12;\n/**\n * Flat bodies smaller than this on screen, in device pixels, are specks: too\n * few pixels for their shading or badges to show which way is up (see\n * `NodeView.update`).\n */\nconst SPECK_DEVICE_RADIUS = 5;\n\n/** The on-screen radius (px) below which flat bodies are specks, at `pixelRatio` device pixels per px. */\nexport const speckRadius = (pixelRatio: number): number => {\n return SPECK_DEVICE_RADIUS / (pixelRatio > 0 ? pixelRatio : 1);\n};\n\n/** The focus ring's radius, in node radii. */\nconst FOCUS_RING_RADIUS = 1.22;\n\n/** What every node is drawn with this frame, besides its own place (see `NodeView.update`). */\nexport interface NodeDrawing {\n /** In an orbit turned as one, the degrees it's turned (see `OrbitTurn`). */\n turn?: number;\n\n /** The on-screen radius (px) below which flat bodies are specks (see `speckRadius`). */\n speckRadius: number;\n\n /**\n * How many more nodes may become specks, or stop being them, this frame.\n * The rest wait for the next: a zoom across the size where a whole orbit\n * becomes specks doesn't redraw all of it at once.\n */\n switches: number;\n\n /** Set when a node is waiting for its turn to switch. */\n waiting: boolean;\n\n /**\n * During a flight bodies don't become specks: one shrinking as the camera\n * pulls away costs less to leave as it is until the flight lands.\n */\n flight: boolean;\n}\n\n/**\n * Whether a body leaves out its blurred shadow (and hidden halo): when it's\n * too small on screen for a shadow to show, a planet of a crowded orbit,\n * where shadows overlap into a haze, or one coming or going in a flight,\n * fading in or out while the camera sweeps past it (and may draw it huge).\n * Blurring hundreds of shadows on every frame is also what makes a crowded\n * orbit or a flight slow.\n */\nexport const drawsFlat = (display: DisplayNode, screenRadius: number): boolean => {\n return display.crowded === true || display.cluster !== undefined || screenRadius < SMALL_BODY_RADIUS;\n};\n\nexport class NodeView {\n readonly element: SVGGElement;\n readonly id: string;\n readonly node: OrbitNode;\n\n /** The type the node was drawn as. One given for display can change with the map around it, and the view is drawn again then. */\n readonly typeName: string | undefined;\n\n /** Shows a picture (an image, or a video's thumbnail) rather than a plain color. */\n hasImage = false;\n\n private readonly body: SVGGElement;\n private readonly disc: SVGCircleElement;\n private readonly shade: SVGCircleElement;\n private readonly shadeFills: { body: string; speck: string };\n private readonly shadowFilters: { planet: string; sun: string };\n\n /**\n * Created once a node shows them: a shadow when it's drawn with one (not\n * the hundreds of flat planets of a crowded orbit, or overview nodes), the\n * halo when it becomes the sun, the focus ring when it's focused.\n */\n private shadow: SVGCircleElement | null = null;\n\n private halo: SVGCircleElement | null = null;\n private focusRing: SVGCircleElement | null = null;\n private status: SVGCircleElement | null = null;\n private role: NodeRole | null = null;\n private color = '';\n private visible = true;\n\n /** Where the node was last drawn, and how: what its transform (or a speck's circles) is worked out from. */\n private drawn = { x: Number.NaN, y: Number.NaN, radius: Number.NaN, upright: 0, opacity: Number.NaN };\n\n private transform = '';\n private opacity = '';\n private editing = false;\n private lifted = false;\n private dropTarget = false;\n private flat = false;\n private crowded = false;\n private speck = false;\n private turnedBack = false;\n\n constructor(display: DisplayNode, screenRadius: number, ids: ViewIds, baseUrl: string | undefined, extensions: MapExtensions, drawing?: NodeDrawing, onImageError?: () => void) {\n this.id = display.id;\n this.node = display.node;\n const { node } = display;\n const type = extensions.nodeType(node);\n this.typeName = extensions.typeName(node);\n this.element = svgElement('g', { class: 'orbit-node', 'data-orbit-node-id': node.id, tabindex: '-1' });\n this.element.setAttribute('role', 'button');\n markNode(this.element, node, this.typeName);\n applyTypeTokens(this.element, type);\n this.body = svgElement('g', { class: 'orbit-node__body' });\n this.shadowFilters = { planet: `url(#${ids.shadow})`, sun: `url(#${ids.sunShadow})` };\n this.disc = svgElement('circle', { class: 'orbit-node__disc', r: '1' });\n this.body.append(this.disc);\n\n const thumbnail = nodeThumbnail(node);\n const source = thumbnail ? guardUrl(thumbnail, 'image') : null;\n\n if (source) {\n const image = svgElement('image', {\n class: 'orbit-node__image',\n x: '-1',\n y: '-1',\n width: '2',\n height: '2',\n preserveAspectRatio: 'xMidYMid slice',\n 'clip-path': `url(#${ids.clip})`,\n });\n image.setAttribute('href', resolveUrl(source, baseUrl));\n\n image.addEventListener('error', () => {\n image.remove();\n this.hasImage = false;\n // The label planned for a picture (its pill outside) belongs inside now: ask for a paint.\n onImageError?.();\n });\n\n this.body.appendChild(image);\n this.hasImage = true;\n }\n\n // Shading and rim in one element: the gradient fills it, the rim is its stroke.\n this.shadeFills = { body: `url(#${ids.shade})`, speck: `url(#${ids.speckShade})` };\n this.shade = svgElement('circle', { class: 'orbit-node__shade', r: '1', fill: this.shadeFills.body });\n this.body.appendChild(this.shade);\n\n if (hasMediaSource(node.video)) {\n const play = svgElement('g', { class: 'orbit-node__play', transform: 'translate(0.62 0.62) scale(0.3)' });\n play.appendChild(svgElement('circle', { r: '1' }));\n play.appendChild(svgElement('path', { d: 'M-0.32 -0.48 L0.52 0 L-0.32 0.48 Z' }));\n this.body.appendChild(play);\n } else if (node.note || hasMediaSource(node.image) || hasMediaSource(node.embed) || node.link || type?.details) {\n this.body.appendChild(svgElement('circle', { class: 'orbit-node__marker', cx: '0.72', cy: '0.72', r: '0.13' }));\n }\n\n if (node.status) {\n const look = extensions.status(node.status);\n this.status = svgElement('circle', { class: `orbit-node__status orbit-node__status--${look.tone}` });\n\n if (look.color) {\n this.status.style.fill = look.color;\n }\n\n this.body.appendChild(this.status);\n }\n\n this.element.appendChild(this.body);\n // A new node starts out as what it is now, before it's on the map: that costs nothing to switch.\n this.update(display, screenRadius, drawing && { ...drawing, switches: Number.POSITIVE_INFINITY, flight: false });\n }\n\n /**\n * Draws the node as `display` places it, `screenRadius` px across on screen.\n *\n * A speck (see `speckRadius`) is drawn with its circles' own coordinates\n * instead of a transform, its badges left out: the browser handles a\n * thousand of them far faster that way, as long as they hold still. A node\n * `moving` on its own (one travelling in a flight) is drawn as a body:\n * moving it is one write instead of one per circle.\n *\n * In an orbit turned as one (see `OrbitTurn`), a body that turns with it is\n * drawn where it is in the unturned orbit: a speck turns with the orbit,\n * shading and all, and anything bigger is turned back upright.\n */\n update(display: DisplayNode, screenRadius = Infinity, drawing?: NodeDrawing, moving = false): void {\n const flat = drawsFlat(display, screenRadius);\n\n if (flat !== this.flat) {\n this.element.classList.toggle('orbit-node--flat', flat);\n this.flat = flat;\n }\n\n const crowded = display.crowded === true;\n\n if (crowded !== this.crowded) {\n this.element.classList.toggle('orbit-node--crowded', crowded);\n this.crowded = crowded;\n }\n\n if (display.role !== this.role) {\n if (this.role) {\n this.element.classList.remove(`orbit-node--${this.role}`);\n }\n\n this.element.classList.add(`orbit-node--${display.role}`);\n this.role = display.role;\n this.shadow?.setAttribute('filter', display.role === 'sun' ? this.shadowFilters.sun : this.shadowFilters.planet);\n\n if (display.role === 'sun') {\n this.element.setAttribute('aria-current', 'true');\n } else {\n this.element.removeAttribute('aria-current');\n }\n\n // The sun is big: a smaller share of it keeps its status dot in proportion.\n const statusRadius = display.role === 'sun' ? 0.11 : 0.17;\n const statusOffset = display.role === 'sun' ? 0.68 : 0.72;\n this.status?.setAttribute('r', String(statusRadius));\n this.status?.setAttribute('cx', String(statusOffset));\n this.status?.setAttribute('cy', String(-statusOffset));\n }\n\n if (!flat && display.role !== 'node' && !this.shadow) {\n this.shadow = svgElement('circle', { class: 'orbit-node__shadow', r: '1' });\n this.shadow.setAttribute('filter', display.role === 'sun' ? this.shadowFilters.sun : this.shadowFilters.planet);\n this.body.insertBefore(this.shadow, this.halo ?? this.disc);\n }\n\n if (display.role === 'sun' && !this.halo) {\n this.halo = svgElement('circle', { class: 'orbit-node__halo', r: '1' });\n this.body.insertBefore(this.halo, this.disc);\n }\n\n if (display.color !== this.color) {\n this.disc.style.fill = display.color;\n // The rim, shadow and halo mix the theme's colors with this one.\n this.element.style.setProperty('--orbit-node-color', display.color);\n this.color = display.color;\n }\n\n const visible = display.opacity > 0.01 && display.radius > 0.05;\n\n if (visible !== this.visible) {\n this.element.style.display = visible ? '' : 'none';\n this.visible = visible;\n }\n\n // Decided while hidden too: a hidden node switches at almost no cost, and needn't wait.\n const speck = !moving && flat && !this.hasImage && screenRadius < (drawing?.speckRadius ?? speckRadius(1));\n\n if (speck !== this.speck && !(visible && speck && drawing?.flight)) {\n // A speck that starts moving can't wait either: each frame it waited would cost more than the switch.\n if (visible && drawing && drawing.switches <= 0 && !moving) {\n drawing.waiting = true;\n } else {\n if (visible && drawing) {\n drawing.switches -= 1;\n }\n\n this.setSpeck(speck);\n }\n }\n\n if (!visible) {\n return;\n }\n\n const turn = drawing?.turn;\n const unturned = turn === undefined ? undefined : display.unturned;\n const place = unturned ?? display;\n this.turnedBack = unturned !== undefined && !this.speck;\n const upright = this.turnedBack && turn ? turn : 0;\n // Only touch the DOM when something moved: panning repaints every node, and a spin every body that turns with its orbit.\n const drawn = this.drawn;\n\n if (place.x !== drawn.x || place.y !== drawn.y || display.radius !== drawn.radius || upright !== drawn.upright) {\n if (this.speck) {\n this.placeSpeck(place.x, place.y, display.radius);\n } else {\n const transform = `translate(${round(place.x)} ${round(place.y)})${upright ? ` rotate(${-upright})` : ''} scale(${round(display.radius, 4)})`;\n\n if (transform !== this.transform) {\n this.element.setAttribute('transform', transform);\n this.transform = transform;\n }\n }\n\n drawn.x = place.x;\n drawn.y = place.y;\n drawn.radius = display.radius;\n drawn.upright = upright;\n }\n\n if (display.opacity !== drawn.opacity) {\n const opacity = display.opacity >= 0.999 ? '' : String(round(display.opacity, 3));\n\n if (opacity !== this.opacity) {\n this.element.style.opacity = opacity;\n this.opacity = opacity;\n }\n\n drawn.opacity = display.opacity;\n }\n }\n\n /** Whether it was last drawn turned back upright in an orbit turned as one: it moves as the orbit turns. */\n get isTurnedBack(): boolean {\n return this.turnedBack;\n }\n\n /** Draws the node as a speck from now on, or as a body again. */\n private setSpeck(speck: boolean): void {\n this.speck = speck;\n this.element.classList.toggle('orbit-node--speck', speck);\n this.shade.setAttribute('fill', speck ? this.shadeFills.speck : this.shadeFills.body);\n\n if (speck) {\n this.element.removeAttribute('transform');\n this.transform = '';\n } else {\n for (const circle of this.unitCircles()) {\n circle.removeAttribute('cx');\n circle.removeAttribute('cy');\n circle.setAttribute('r', circle === this.focusRing ? String(FOCUS_RING_RADIUS) : '1');\n }\n\n this.shade.style.removeProperty('--orbit-speck-radius');\n }\n\n // Drawn again where it is, the new way.\n this.drawn.x = Number.NaN;\n }\n\n /** Puts a speck's circles at (`x`, `y`), `radius` in size, in the map's own units. */\n private placeSpeck(x: number, y: number, radius: number): void {\n const cx = String(round(x));\n const cy = String(round(y));\n\n for (const circle of this.unitCircles()) {\n circle.setAttribute('cx', cx);\n circle.setAttribute('cy', cy);\n circle.setAttribute('r', String(round(radius * (circle === this.focusRing ? FOCUS_RING_RADIUS : 1), 4)));\n }\n\n // The rim grows and shrinks with the speck (see the stylesheet).\n this.shade.style.setProperty('--orbit-speck-radius', String(round(radius, 4)));\n }\n\n /** The circles a body draws at unit radius around its center, and a speck at its own place. */\n private unitCircles(): SVGCircleElement[] {\n return this.focusRing ? [this.disc, this.shade, this.focusRing] : [this.disc, this.shade];\n }\n\n /** The fill as the browser resolved it (theme tokens and color mixes included). */\n resolvedFill(): string {\n return typeof getComputedStyle === 'function' ? getComputedStyle(this.disc).fill : '';\n }\n\n /** Marks the node whose text is being edited on the map. */\n setEditing(editing: boolean): void {\n if (editing !== this.editing) {\n if (editing) {\n this.showFocusRing();\n }\n\n this.element.classList.toggle('orbit-node--editing', editing);\n this.editing = editing;\n }\n }\n\n /** Held up by a press, to be dragged somewhere else: it grows, its shadow deepens. */\n setLifted(lifted: boolean): void {\n if (lifted !== this.lifted) {\n this.element.classList.toggle('orbit-node--lifted', lifted);\n this.lifted = lifted;\n }\n }\n\n /** Where a node being dragged would go if let go now: it grows to take it, ringed. */\n setDropTarget(target: boolean): void {\n if (target !== this.dropTarget) {\n if (target) {\n this.showFocusRing();\n }\n\n this.element.classList.toggle('orbit-node--drop-target', target);\n this.dropTarget = target;\n }\n }\n\n /** Adds the ring that shows while the node has keyboard focus or is being edited. */\n showFocusRing(): void {\n if (!this.focusRing) {\n this.focusRing = svgElement('circle', { class: 'orbit-node__focus-ring', r: String(FOCUS_RING_RADIUS) });\n this.body.appendChild(this.focusRing);\n\n if (this.speck) {\n this.placeSpeck(this.drawn.x, this.drawn.y, this.drawn.radius);\n }\n }\n }\n}\n\n/**\n * The free place in the orbit for a new idea: a dashed circle with a plus,\n * drawn at unit radius like a node. While a new idea is typed there, it\n * fills in around the field.\n */\nexport class AddSlotView {\n readonly element: SVGGElement;\n private shown = false;\n private pending = false;\n private drop: 'target' | 'waiting' | false = false;\n private label = '';\n private transform = '';\n private opacity = '';\n\n get isShown(): boolean {\n return this.shown;\n }\n\n /** `held`: the place held for a node being dragged, which only shows, rather than the + to press. */\n constructor(held = false) {\n this.element = held\n ? svgElement('g', { class: 'orbit-add orbit-add--held', 'aria-hidden': 'true' })\n : svgElement('g', { class: 'orbit-add', 'data-orbit-add': '', tabindex: '-1' });\n\n if (!held) {\n this.element.setAttribute('role', 'button');\n }\n\n const body = svgElement('g', { class: 'orbit-add__body' });\n body.append(\n svgElement('circle', { class: 'orbit-add__disc', r: '1' }),\n svgElement('path', { class: 'orbit-add__plus', d: 'M-0.3 0H0.3M0 -0.3V0.3' }),\n svgElement('circle', { class: 'orbit-add__focus-ring', r: String(FOCUS_RING_RADIUS) }),\n );\n this.element.appendChild(body);\n this.element.style.display = 'none';\n }\n\n /**\n * Draws the slot where `slot` says, or hides it. `label` names it for\n * assistive technology. `drop` shows it as the place held open for a node\n * being dragged, without its plus: the `target`, or `waiting` while the\n * node is over another one. In an orbit turned `turn` degrees, it's drawn\n * where it is in the unturned orbit, turned back upright.\n */\n update(slot: DisplaySlot | undefined, label: string, pending: boolean, turn?: number, drop: 'target' | 'waiting' | false = false): void {\n const shown = slot !== undefined && slot.opacity > 0.01 && slot.radius > 0.05;\n\n if (shown !== this.shown) {\n this.element.style.display = shown ? '' : 'none';\n this.shown = shown;\n }\n\n if (!slot || !shown) {\n return;\n }\n\n if (pending !== this.pending) {\n this.element.classList.toggle('orbit-add--pending', pending);\n this.pending = pending;\n }\n\n if (drop !== this.drop) {\n this.element.classList.toggle('orbit-add--drop', drop !== false);\n this.element.classList.toggle('orbit-add--waiting', drop === 'waiting');\n this.drop = drop;\n }\n\n if (label !== this.label) {\n if (label) {\n this.element.setAttribute('aria-label', label);\n } else {\n this.element.removeAttribute('aria-label');\n }\n\n this.label = label;\n }\n\n const unturned = turn === undefined ? undefined : slot.unturned;\n const place = unturned ?? slot;\n const upright = unturned && turn ? ` rotate(${-turn})` : '';\n const transform = `translate(${round(place.x)} ${round(place.y)})${upright} scale(${round(slot.radius, 4)})`;\n\n if (transform !== this.transform) {\n this.element.setAttribute('transform', transform);\n this.transform = transform;\n }\n\n const opacity = slot.opacity >= 0.999 ? '' : String(round(slot.opacity, 3));\n\n if (opacity !== this.opacity) {\n this.element.style.opacity = opacity;\n this.opacity = opacity;\n }\n }\n}\n\n/** CSS hooks for a node's element and label: `data-orbit-type`, `data-orbit-status` and `data-orbit-tags`. */\nexport const markNode = (element: HTMLElement | SVGElement, node: OrbitNode, type: string | undefined = node.type): void => {\n if (type) {\n element.setAttribute('data-orbit-type', type.toLowerCase());\n }\n\n if (node.status) {\n element.setAttribute('data-orbit-status', node.status.trim().toLowerCase());\n }\n\n if (node.tags?.length) {\n element.setAttribute('data-orbit-tags', node.tags.join(' '));\n }\n};\n\n/** A node type's theme tokens, set on its node's elements so they win over the map's theme there. */\nexport const applyTypeTokens = (element: HTMLElement | SVGElement, type: OrbitNodeType | undefined): void => {\n for (const [token, value] of Object.entries(type?.tokens ?? {})) {\n if (typeof value === 'string' && value !== '') {\n element.style.setProperty(`--_orbit-${token}`, value);\n }\n }\n};\n\n/** The picture a node shows: its image, or its video's thumbnail. */\nexport const nodeThumbnail = (node: OrbitNode): string | undefined => {\n if (hasMediaSource(node.image)) {\n return node.image.src;\n }\n\n if (hasMediaSource(node.video)) {\n if (node.video.thumbnail) {\n return node.video.thumbnail;\n }\n\n if (node.video.provider !== 'vimeo' && node.video.provider !== 'native') {\n return youtubeThumbnailUrl(node.video.src) ?? undefined;\n }\n }\n\n return undefined;\n};\n\n/** Inside the node, as a pill outside it, or not shown. */\nexport type LabelPlacement = 'inside' | 'outside' | 'hidden';\n\n/** The size (px) a node's name starts at inside it, before it shrinks to fit. */\nconst LABEL_FONT_SIZE: Record<NodeRole, number> = { sun: 16, planet: 13, node: 12, moon: 13 };\n/**\n * The smallest a name gets inside its node. Crowded orbits need small text\n * to keep names inside their nodes, the focused node's too, since its own\n * orbit shrinks it; a node too small even for this shows no name until you\n * zoom in (the focused node always shows its name). An overview node's name\n * has its pill to go to, so it stays closer to the pills' size.\n */\nconst MINIMUM_FONT_SIZE: Record<NodeRole, number> = { sun: 9, planet: 9, node: 10, moon: 9 };\n/** The most lines a name wraps to inside its node. */\nconst LABEL_LINES: Record<NodeRole, number> = { sun: 4, planet: 3, node: 3, moon: 2 };\n/** Height of a line of label text, and of the icon above it, in ems (as the stylesheet sets them). */\nconst LINE_HEIGHT = 1.22;\nconst ICON_HEIGHT = 1.45;\n/** Pixels between the icon and the text. */\nconst ICON_GAP = 2;\n/** A name cut short still shows this many characters, or none: a few letters don't say what a node is. */\nconst SHORTEST_CUT = 8;\n\n/** The width (px) of a label typed into a node of this on-screen radius. Snapped to 6 px steps so zooming doesn't re-wrap text every frame. */\nexport const insideLabelWidth = (role: NodeRole, screenRadius: number): number => {\n return Math.max(44, Math.min(260, Math.round((screenRadius * (role === 'sun' ? 1.6 : 1.68)) / 6) * 6));\n};\n\n/** A piece of a name a line can't break inside, its width in ems, and whether a space comes before it. */\ninterface MeasuredUnit {\n text: string;\n ems: number;\n spaced: boolean;\n}\n\n/** A name measured at one font size. */\ninterface SizedText {\n units: MeasuredUnit[];\n\n /** Width (em) of the longest run a line can't break inside: a word piece, or a single wide character. */\n longestUnbreakable: number;\n\n /** Width (em) of the whole text on one line. */\n total: number;\n\n /** A space between words, an ellipsis and a hyphen, in ems. */\n space: number;\n\n ellipsis: number;\n hyphen: number;\n}\n\n/**\n * The size (px) a name is measured at for text of `fontSize`: text shrunk\n * below 12 px at 9 px, and the rest at 12 px. Fonts with optical sizes draw\n * small text a few percent wider, so measuring at the smallest size of each\n * kind never measures a name narrower than it's drawn.\n */\nconst measuredSize = (fontSize: number): number => {\n return fontSize < 12 ? 9 : 12;\n};\n\n/** A name's pieces, measured at the sizes it's fitted at (see `measuredSize`). */\nclass TextMetrics {\n readonly measure: TextMeasure;\n private readonly pieces: TextUnit[];\n private readonly sizes = new Map<number, SizedText>();\n\n constructor(text: string, measure: TextMeasure) {\n this.measure = measure;\n this.pieces = breakUnits(text);\n }\n\n at(fontSize: number): SizedText {\n const size = this.measure.bySize ? measuredSize(fontSize) : 0;\n let sized = this.sizes.get(size);\n\n if (!sized) {\n const { measure } = this;\n const units = this.pieces.map((unit) => ({ text: unit.text, ems: measure.ems(unit.text, size), spaced: unit.spaced }));\n const space = measure.space(size);\n sized = {\n units,\n longestUnbreakable: units.reduce((longest, unit) => Math.max(longest, unit.ems), 0),\n total: units.reduce((sum, unit, index) => sum + unit.ems + (index > 0 && unit.spaced ? space : 0), 0),\n space,\n ellipsis: measure.ellipsis(size),\n hyphen: measure.ems('-', size),\n };\n this.sizes.set(size, sized);\n }\n\n return sized;\n }\n\n /** Width (em) of one character in text of `fontSize`, for cutting a name between characters. */\n character(character: string, fontSize: number): number {\n return this.measure.ems(character, this.measure.bySize ? measuredSize(fontSize) : 0);\n }\n}\n\n/**\n * Metrics by font and text. Every label's fit is worked out each frame while\n * the map moves, but the text rarely changes and measuring it walks every\n * character.\n */\nconst textMetricsCache = new Map<string, TextMetrics>();\n/** More texts than the largest maps have; past it, the measurements start over. */\nconst TEXT_METRICS_LIMIT = 20000;\n\nconst textMetrics = (text: string, measure: TextMeasure): TextMetrics => {\n const key = `${measure.key}\\n${text}`;\n const cached = textMetricsCache.get(key);\n\n if (cached) {\n return cached;\n }\n\n if (textMetricsCache.size >= TEXT_METRICS_LIMIT) {\n textMetricsCache.clear();\n }\n\n const metrics = new TextMetrics(text, measure);\n textMetricsCache.set(key, metrics);\n return metrics;\n};\n\n/**\n * The font size (px) of text typed into a node: the role's size, reduced\n * (down to its minimum) until the longest word fits on one line.\n */\nexport const insideFontSize = (role: NodeRole, width: number, text: string, measure: TextMeasure = INSIDE_ESTIMATE): number => {\n const longest = textMetrics(text, measure).at(LABEL_FONT_SIZE[role]).longestUnbreakable;\n const fitting = longest > 0 ? width / longest : LABEL_FONT_SIZE[role];\n return Math.max(MINIMUM_FONT_SIZE[role], Math.min(LABEL_FONT_SIZE[role], Math.floor(fitting * 2) / 2));\n};\n\nexport interface InsideLabelLayout {\n /** Width of the text block (px): its widest line's room. */\n width: number;\n\n fontSize: number;\n\n /** The name as it shows, line by line; the last ends with an ellipsis when the name is cut short. */\n lines: string[];\n\n /** Whether the node's icon shows above its name. */\n icon: boolean;\n\n /** The name doesn't fit whole. */\n truncated: boolean;\n\n /** A narrower width of the font the name is drawn in, as `font-stretch` (a percentage), when it needs one to fit. */\n stretch?: number;\n\n /** How far above the node's center (px) the lines and icon are centered: they rise to clear the node's \"+N\". */\n lift: number;\n}\n\n/** Joins units onto one line, with their spaces. */\nconst lineText = (units: MeasuredUnit[]): string => {\n return units.map((unit, index) => (index > 0 && unit.spaced ? ` ${unit.text}` : unit.text)).join('');\n};\n\n/** How wide (em) units are on one line, with their spaces. */\nconst lineEms = (units: MeasuredUnit[], sized: SizedText): number => {\n return units.reduce((sum, unit, index) => sum + unit.ems + (index > 0 && unit.spaced ? sized.space : 0), 0);\n};\n\n/** Whether lines this wide (ems) fit the room each has (px), in text of `fontSize`. */\nconst fitRooms = (ems: number[], widths: number[], fontSize: number): boolean => {\n return ems.length <= widths.length && ems.every((width, index) => width * fontSize <= widths[index] + 1e-9);\n};\n\n/**\n * Units of text wrapped onto lines `widths` ems wide, the first unit that\n * doesn't fit starting the next line; null when they need more lines, or a\n * unit is wider than its line.\n */\nconst wrapUnits = (sized: SizedText, widths: number[]): MeasuredUnit[][] | null => {\n const lines: MeasuredUnit[][] = [];\n let line: MeasuredUnit[] = [];\n let used = 0;\n\n for (const unit of sized.units) {\n const space = used > 0 && unit.spaced ? sized.space : 0;\n\n if (used > 0 && used + space + unit.ems > widths[lines.length]) {\n lines.push(line);\n\n if (lines.length >= widths.length) {\n return null;\n }\n\n line = [];\n used = 0;\n }\n\n if (unit.ems > widths[lines.length]) {\n return null;\n }\n\n used += (used > 0 && unit.spaced ? sized.space : 0) + unit.ems;\n line.push(unit);\n }\n\n lines.push(line);\n return lines;\n};\n\n/**\n * The same units on as many lines, broken where every line fills as little\n * of its room as can be (a circle's lines are widest in the middle), so a\n * name's shape follows its node's instead of crowding the first line:\n * \"Lanzamiento / en México\" rather than \"Lanzamiento en / México\".\n */\nconst balanceLines = (lines: MeasuredUnit[][], sized: SizedText, widths: number[]): MeasuredUnit[][] => {\n const count = lines.length;\n\n if (count < 2) {\n return lines;\n }\n\n const units = count === 2 ? [...lines[0], ...lines[1]] : lines.flat();\n const total = units.length;\n\n if (total <= count) {\n return lines;\n }\n\n // Ems before each unit, and the spaces before each unit (a line drops the one before its first unit).\n const ems = new Float64Array(total + 1);\n const spaces = new Float64Array(total + 1);\n\n for (let index = 0; index < total; index += 1) {\n ems[index + 1] = ems[index] + units[index].ems;\n spaces[index + 1] = spaces[index] + (units[index].spaced ? sized.space : 0);\n }\n\n const fill = (start: number, end: number, line: number) => (ems[end] - ems[start] + spaces[end] - spaces[start + 1]) / widths[line];\n const splits = count === 4 ? fourLineSplits(total, fill) : fewLineSplits(count, total, fill);\n\n if (!splits) {\n return lines;\n }\n\n const balanced: MeasuredUnit[][] = [];\n let start = 0;\n\n for (const end of [...splits, total]) {\n balanced.push(units.slice(start, end));\n start = end;\n }\n\n return balanced;\n};\n\n/** Where two or three lines break (the units each starts at, after the first) so the fullest is as empty as can be; null when none fits. */\nconst fewLineSplits = (count: number, total: number, fill: (start: number, end: number, line: number) => number): number[] | null => {\n let best = Infinity;\n let splits: number[] | null = null;\n\n if (count === 2) {\n for (let first = 1; first < total; first += 1) {\n const worst = Math.max(fill(0, first, 0), fill(first, total, 1));\n\n if (worst <= 1 && worst < best - 1e-9) {\n best = worst;\n splits = [first];\n }\n }\n\n return splits;\n }\n\n for (let first = 1; first < total - 1; first += 1) {\n const top = fill(0, first, 0);\n\n if (top > 1) {\n break;\n }\n\n for (let second = first + 1; second < total; second += 1) {\n const worst = Math.max(top, fill(first, second, 1), fill(second, total, 2));\n\n if (worst <= 1 && worst < best - 1e-9) {\n best = worst;\n splits = [first, second];\n }\n }\n }\n\n return splits;\n};\n\n/** As `fewLineSplits`, for four lines (a sun's longest names): the least fullest line, line by line. */\nconst fourLineSplits = (total: number, fill: (start: number, end: number, line: number) => number): number[] | null => {\n // fills[line][end]: the least fullest line for units before `end` on lines up to `line`; starts: where that last line starts.\n const fills = Array.from({ length: 4 }, () => new Float64Array(total + 1).fill(Infinity));\n const starts = Array.from({ length: 4 }, () => new Int32Array(total + 1));\n\n for (let end = 1; end <= total; end += 1) {\n const first = fill(0, end, 0);\n fills[0][end] = first <= 1 ? first : Infinity;\n }\n\n for (let line = 1; line < 4; line += 1) {\n for (let end = line + 1; end <= total; end += 1) {\n for (let start = line; start < end; start += 1) {\n const before = fills[line - 1][start];\n const own = fill(start, end, line);\n const worst = Math.max(before, own);\n\n if (own <= 1 && worst < fills[line][end] - 1e-9) {\n fills[line][end] = worst;\n starts[line][end] = start;\n }\n }\n }\n }\n\n if (fills[3][total] === Infinity) {\n return null;\n }\n\n const splits: number[] = [];\n let end = total;\n\n for (let line = 3; line > 0; line -= 1) {\n end = starts[line][end];\n splits.unshift(end);\n }\n\n return splits;\n};\n\n/** A name cut to fit its lines: the lines, how wide each is (ems), how many characters show, and whether any don't. */\ninterface CutText {\n lines: string[];\n widths: number[];\n shown: number;\n truncated: boolean;\n}\n\n/**\n * As much of the text as `widths` hold, word pieces kept whole, the last line\n * ending with an ellipsis when text was cut (cut between characters if need\n * be), and how many characters show. Null when a line can't hold even its\n * first piece.\n */\nconst cutUnits = (metrics: TextMetrics, fontSize: number, widths: number[]): CutText | null => {\n const sized = metrics.at(fontSize);\n const total = sized.units.reduce((sum, unit) => sum + unit.text.length, 0);\n const lines: string[] = [];\n const usedEms: number[] = [];\n const last = widths.length - 1;\n const widest = Math.max(...widths);\n const room = () => widths[lines.length] - (lines.length === last ? sized.ellipsis : 0);\n let line = '';\n let used = 0;\n let shown = 0;\n\n for (let unit of sized.units) {\n let space = used > 0 && unit.spaced ? sized.space : 0;\n\n if (used + space + unit.ems > room() && lines.length < last) {\n if (used > 0) {\n lines.push(line);\n usedEms.push(used);\n line = '';\n used = 0;\n space = 0;\n }\n\n // A long word wider than any line breaks with a hyphen; anything else waits for a wider line.\n if (unit.ems > room() && unit.ems <= widest) {\n return null;\n }\n\n while (unit.ems > room() && lines.length < last) {\n const split = hyphenate(unit, room(), metrics, fontSize);\n\n if (!split) {\n return null;\n }\n\n lines.push(split.head);\n usedEms.push(split.headEms);\n shown += split.head.length - 1;\n unit = split.rest;\n }\n }\n\n if (used + space + unit.ems <= room()) {\n line += space > 0 ? ` ${unit.text}` : unit.text;\n used += space + unit.ems;\n shown += unit.text.length;\n continue;\n }\n\n // The last line is full: as much of this piece as fits before the ellipsis.\n for (const character of graphemes(unit.text)) {\n const width = metrics.character(character, fontSize);\n\n if (used + space + width > room()) {\n break;\n }\n\n line += space > 0 ? ` ${character}` : character;\n used += space + width;\n space = 0;\n shown += character.length;\n }\n\n break;\n }\n\n // A long word hyphenated across lines can leave everything fitting after all: nothing cut, no ellipsis.\n const truncated = shown < total;\n lines.push(truncated ? `${line.trimEnd()}…` : line.trimEnd());\n usedEms.push(used + (truncated ? sized.ellipsis : 0));\n return { lines, widths: usedEms, shown, truncated };\n};\n\n/** Words this long or longer may break with a hyphen when a name is cut short anyway. */\nconst HYPHENATED_WORD = /^\\p{L}{8,}$/u;\n\n/** A long word's head (with a hyphen) that fits in `room` ems, how wide it is (ems), and the rest of the word; null for anything else. */\nconst hyphenate = (unit: MeasuredUnit, room: number, metrics: TextMetrics, fontSize: number): { head: string; headEms: number; rest: MeasuredUnit } | null => {\n if (!HYPHENATED_WORD.test(unit.text)) {\n return null;\n }\n\n const characters = graphemes(unit.text);\n let head = '';\n let used = metrics.at(fontSize).hyphen;\n let count = 0;\n let headEms = 0;\n\n for (const character of characters) {\n const width = metrics.character(character, fontSize);\n\n if (used + width > room) {\n break;\n }\n\n head += character;\n used += width;\n headEms += width;\n count += 1;\n }\n\n // At least three letters on each side of the hyphen.\n if (count < 3 || characters.length - count < 3) {\n return null;\n }\n\n const rest = characters.slice(count).join('');\n // What's left of the word is as wide as the word less its head (give or take kerning).\n return { head: `${head}-`, headEms: used, rest: { text: rest, ems: Math.max(0, unit.ems - headEms), spaced: false } };\n};\n\n/** The width (px) of a circle of radius `room` at height `y` from its center. */\nconst chordAt = (room: number, y: number): number => {\n return Math.abs(y) >= room ? 0 : 2 * Math.sqrt(room * room - y * y);\n};\n\n/**\n * The \"+N\" of a node with children that aren't drawn (the renderer's\n * `paintCounts`) is centered this share of the node's radius right of and\n * below the node's center.\n */\nexport const COUNT_POSITION = 0.74;\n/** A \"+N\" is this tall (px): its line and padding, as the stylesheet sets them. */\nexport const COUNT_HEIGHT = 15;\n/** A \"+N\"'s text size (px), and its padding on each side (px), as the stylesheet sets them. */\nconst COUNT_FONT_SIZE = 10.5;\nconst COUNT_PADDING = 6;\n/** Pixels a name inside a node keeps from the node's \"+N\". */\nconst COUNT_GAP = 1.5;\n/** The space under a line's letters (ems), which may pass over a \"+N\": the tails of g, p and y end this far above the line's bottom. */\nconst UNDER_TAILS = 0.15;\n\n/** Whether a node of this role and on-screen radius shows a \"+N\" for children that aren't drawn (flights and faded nodes hide it for a while). */\nexport const showsCount = (role: NodeRole, screenRadius: number, hiddenChildren: number): boolean => {\n return hiddenChildren > 0 && role !== 'moon' && screenRadius >= 10;\n};\n\n/** \"+N\" widths (px) by font, then by how many figures the count has: its figures are all as wide (tabular). */\nconst countWidths = new Map<TextMeasure, number[]>();\n\n/** How wide (px) a node's \"+N\" is for `hiddenChildren` children, in `measure` (the font it's drawn in). */\nexport const measureCount = (hiddenChildren: number, measure: TextMeasure = COUNT_ESTIMATE): number => {\n let figures = 1;\n\n for (let rest = hiddenChildren; rest >= 10; rest = Math.floor(rest / 10)) {\n figures += 1;\n }\n\n let widths = countWidths.get(measure);\n\n if (!widths) {\n widths = [];\n countWidths.set(measure, widths);\n }\n\n let width = widths[figures];\n\n if (width === undefined) {\n // Tabular figures are as wide as each other: a canvas, which draws the font's own figures, measures zeros.\n width = 2 * COUNT_PADDING + measure.ems(`+${'0'.repeat(figures)}`, COUNT_FONT_SIZE) * COUNT_FONT_SIZE;\n widths[figures] = width;\n }\n\n return width;\n};\n\n/** A node's \"+N\" as the name inside it keeps clear of it, from the node's center (px): lines reaching below `top` end left of `left`. */\ninterface CountBox {\n top: number;\n left: number;\n}\n\n/**\n * Where a node of this radius shows its \"+N\", `width` px wide, gap included;\n * null when it shows none. Fits round the radius down, so the count is\n * never nearer the center than this.\n */\nconst countBox = (radius: number, width: number): CountBox | null => {\n return width > 0 ? { top: COUNT_POSITION * radius - COUNT_HEIGHT / 2 - COUNT_GAP, left: COUNT_POSITION * radius - width / 2 - COUNT_GAP } : null;\n};\n\n/** The room for each line of a name (px), and how far above the node's center (px) its lines and icon are centered. */\ninterface LineRoom {\n widths: number[];\n lift: number;\n}\n\n/**\n * Room for each of `count` lines of `fontSize` px text centered in a circle of\n * radius `room`, under an icon when `icon` (null when the icon itself doesn't\n * fit). Each line gets the circle's width at its middle. Beside a \"+N\"\n * (`badge`), the lines and icon rise, as far as the circle allows, until the\n * last line's letters clear it, and a line still beside it ends short of it:\n * lines are centered, so they end as far from the center on the left too.\n */\nconst lineWidths = (room: number, fontSize: number, count: number, icon: boolean, badge: CountBox | null = null): LineRoom | null => {\n const lineHeight = fontSize * LINE_HEIGHT;\n const iconHeight = icon ? fontSize * ICON_HEIGHT + ICON_GAP : 0;\n const height = iconHeight + count * lineHeight;\n\n if (height > room * 2) {\n return null;\n }\n\n // How low the bottom of a line may sit: the space under its letters may pass over the \"+N\".\n const lowest = badge ? badge.top + fontSize * UNDER_TAILS : Infinity;\n const lift = badge ? Math.min(Math.max(0, height / 2 - lowest), room - height / 2) : 0;\n const top = -height / 2 - lift;\n\n if (icon && chordAt(room, top + (fontSize * ICON_HEIGHT) / 2) < fontSize * ICON_HEIGHT) {\n return null;\n }\n\n const widths: number[] = [];\n\n for (let index = 0; index < count; index += 1) {\n const lineTop = top + iconHeight + index * lineHeight;\n const width = chordAt(room, lineTop + lineHeight / 2);\n widths.push(badge && lineTop + lineHeight > lowest + 1e-9 ? Math.min(width, 2 * Math.max(0, badge.left)) : width);\n }\n\n return { widths, lift };\n};\n\n/** How far below its node's center (px) a name laid out inside it reaches: its lines and icon are centered `lift` above it. */\nexport const insideLabelReach = (layout: InsideLabelLayout): number => {\n const iconHeight = layout.icon ? layout.fontSize * ICON_HEIGHT + ICON_GAP : 0;\n return (iconHeight + layout.lines.length * layout.fontSize * LINE_HEIGHT) / 2 - layout.lift;\n};\n\n/**\n * A name's fit at one size, in its font's own width, and once tried (when\n * the map is still), the narrower one it may need.\n */\ninterface InsideFits {\n own: InsideLabelLayout | null;\n narrower?: InsideLabelLayout | null;\n}\n\n/** Fitted labels by font, then role, size and text: labels are fitted on every frame while the map moves. */\nconst insideLayouts = new Map<TextMeasure, Map<string, InsideFits>>();\nconst INSIDE_LAYOUTS_LIMIT = 20000;\n\n// Fits made from measurements start over with them (a font finished loading).\nonMeasurementsReset(() => {\n textMetricsCache.clear();\n insideLayouts.clear();\n countWidths.clear();\n});\n\n/**\n * How a node's name fits inside it at this on-screen radius, or null when it\n * doesn't. The name shrinks (down to the role's minimum) and wraps (at\n * spaces, and inside long words where they read), its lines balanced and\n * each as wide as the circle is where it sits. The icon above it stays while\n * the name only shrinks a little. A name too long to fit whole even then\n * shows as much as fits, ending with an ellipsis, as long as that's enough\n * to read. `measure` measures the text in the font it's drawn with (by\n * default, widths are estimated).\n *\n * A name that doesn't fit at its font's width tries narrower ones (see\n * `fitInside`) only when `narrower` allows, as it does while the map is\n * still: while the map moves, trying hundreds of names in each width would\n * make frames late. A fit already made with them is kept, though.\n *\n * A node showing a \"+N\" `countWidth` px wide (see `measureCount`) keeps its\n * name clear of it: the name rises above it, or gets smaller.\n */\nexport const insideLabelLayout = (role: NodeRole, screenRadius: number, text: string, hasIcon = false, measure: TextMeasure = INSIDE_ESTIMATE, narrower = true, countWidth = 0): InsideLabelLayout | null => {\n // In steps of about 6% (2 px at least), so a zoom or a flight doesn't fit and write the text again on every frame.\n const step = Math.max(2, Math.round(screenRadius * 0.06));\n const radius = Math.floor(screenRadius / step) * step;\n\n // Most of a crowded orbit has no room for any name: no need to look each one up on every frame it moves.\n if (insideRoom(radius) < SMALLEST_INSIDE_ROOM) {\n return null;\n }\n\n let inFont = insideLayouts.get(measure);\n\n if (!inFont) {\n inFont = new Map();\n insideLayouts.set(measure, inFont);\n }\n\n const key = `${role}|${radius}|${hasIcon ? 1 : 0}|${countWidth}|${text}`;\n let fits = inFont.get(key);\n\n if (fits === undefined) {\n if (inFont.size >= INSIDE_LAYOUTS_LIMIT) {\n inFont.clear();\n }\n\n const own = fitInFont(role, radius, text, hasIcon, measure, countWidth);\n // A name that shows whole in its font's own width needs nothing narrower.\n fits = own !== null && !own.truncated ? { own, narrower: own } : { own };\n inFont.set(key, fits);\n }\n\n if (fits.narrower !== undefined) {\n return fits.narrower;\n }\n\n if (!narrower) {\n return fits.own;\n }\n\n fits.narrower = fitNarrower(role, radius, text, hasIcon, measure, countWidth) ?? fits.own;\n return fits.narrower;\n};\n\n/** How far below its usual size a name shrinks before its node's icon makes way (px). */\nconst ICON_SHRINK = 3;\n\n/** The radius (px) a name has inside a node of this on-screen radius: text keeps a little off the rim. */\nconst insideRoom = (radius: number): number => {\n return radius - Math.max(2, radius * 0.05);\n};\n\n/** Below this room (px), no name fits inside. */\nconst SMALLEST_INSIDE_ROOM = 6;\n\n/**\n * Only in nodes with at least this much room (px): a crowded orbit's small\n * planets can't show a name whole in any width, and trying each one at\n * every step of a zoom would slow the zoom down.\n */\nconst NARROWER_ROOM = 16;\n\n/**\n * A name that's cut short or has no room in its font's own width, fitted\n * in a narrower width of it (a font with a width axis draws semi-condensed,\n * then condensed), when that shows it whole; null when none does.\n */\nconst fitNarrower = (role: NodeRole, radius: number, text: string, hasIcon: boolean, measure: TextMeasure, countWidth: number): InsideLabelLayout | null => {\n const narrower = insideRoom(radius) >= NARROWER_ROOM ? measure.narrower() : null;\n\n if (!narrower || !mightFitWhole(role, radius, text, narrower.narrower() ?? narrower)) {\n return null;\n }\n\n for (let width: TextMeasure | null = narrower; width; width = width.narrower()) {\n const attempt = fitInFont(role, radius, text, hasIcon, width, countWidth);\n\n if (attempt && !attempt.truncated) {\n return { ...attempt, stretch: width.stretch };\n }\n }\n\n return null;\n};\n\n/**\n * Whether a name could fit whole in this node in `measure`, at the role's\n * smallest size: its longest piece across the circle, and all of it in the\n * circle's area. Most names in a crowded orbit can't, at any width.\n */\nconst mightFitWhole = (role: NodeRole, radius: number, text: string, measure: TextMeasure): boolean => {\n const smallest = MINIMUM_FONT_SIZE[role];\n const sized = textMetrics(text, measure).at(smallest);\n const room = insideRoom(radius);\n const breakable = Math.max(sized.total - sized.space * LABEL_LINES[role], 0.01);\n return sized.longestUnbreakable * smallest <= 2 * room && smallest <= room * Math.sqrt((1.25 * Math.PI) / (LINE_HEIGHT * breakable));\n};\n\nconst fitInFont = (role: NodeRole, radius: number, text: string, hasIcon: boolean, measure: TextMeasure, countWidth: number): InsideLabelLayout | null => {\n const room = insideRoom(radius);\n const badge = countBox(radius, countWidth);\n\n if (room < SMALLEST_INSIDE_ROOM) {\n return null;\n }\n\n const metrics = textMetrics(text, measure);\n const largest = LABEL_FONT_SIZE[role];\n const smallest = MINIMUM_FONT_SIZE[role];\n // No size above these fits: the longest piece must fit the circle's width, and the text (less the\n // spaces lines break at) its area, with room to spare, since lines are as wide as the circle at their middle.\n const breakableAt = (sized: SizedText) => Math.max(sized.total - sized.space * LABEL_LINES[role], 0.01);\n const widest = metrics.at(largest);\n const fitting = Math.min(largest, (2 * room) / Math.max(widest.longestUnbreakable, 0.01), room * Math.sqrt((1.25 * Math.PI) / (LINE_HEIGHT * breakableAt(widest))));\n const start = Math.floor(fitting * 2) / 2;\n const attempts: [boolean, number][] = [];\n\n if (hasIcon) {\n for (let fontSize = start; fontSize >= Math.max(smallest, largest - ICON_SHRINK); fontSize -= 0.5) {\n attempts.push([true, fontSize]);\n }\n }\n\n for (let fontSize = start; fontSize >= smallest; fontSize -= 0.5) {\n attempts.push([false, fontSize]);\n }\n\n for (const [icon, fontSize] of attempts) {\n const sized = metrics.at(fontSize);\n const breakable = breakableAt(sized);\n\n // No fewer lines than the text's width (less the spaces lines break at) over the circle's.\n for (let count = Math.max(1, Math.ceil((breakable * fontSize) / (2 * room))); count <= LABEL_LINES[role]; count += 1) {\n const tried = lineWidths(room, fontSize, count, icon, badge);\n\n if (!tried) {\n break;\n }\n\n const wrapped = wrapUnits(sized, tried.widths.map((width) => width / fontSize));\n\n if (!wrapped) {\n continue;\n }\n\n // Balanced over the lines it takes, each as wide as the circle where those lines sit. Fewer lines than\n // tried sit elsewhere, where the circle may be narrower or the \"+N\" nearer: they show only if they fit there.\n const shown = wrapped.length === count ? tried : lineWidths(room, fontSize, wrapped.length, icon, badge);\n\n if (!shown) {\n continue;\n }\n\n const lines = balanceLines(wrapped, sized, shown.widths.map((width) => width / fontSize));\n\n if (!fitRooms(lines.map((units) => lineEms(units, sized)), shown.widths, fontSize)) {\n continue;\n }\n\n return { width: Math.floor(Math.max(...shown.widths.slice(0, lines.length))), fontSize, lines: lines.map(lineText), icon, truncated: false, lift: shown.lift };\n }\n }\n\n // An overview node's name that doesn't fit whole reads better whole, on its pill.\n if (role === 'node') {\n return null;\n }\n\n // Too long to fit whole: as many lines of the smallest text as show the most of it.\n let best: InsideLabelLayout | null = null;\n let mostShown = 0;\n\n for (let count = 1; count <= LABEL_LINES[role]; count += 1) {\n const tried = lineWidths(room, smallest, count, false, badge);\n\n if (!tried) {\n break;\n }\n\n const cut = cutUnits(metrics, smallest, tried.widths.map((width) => width / smallest));\n\n if (!cut || cut.shown <= mostShown) {\n continue;\n }\n\n // A word hyphenated across lines can leave fewer lines than tried, drawn elsewhere: shown only if they fit there.\n const shown = cut.lines.length === count ? tried : lineWidths(room, smallest, cut.lines.length, false, badge);\n\n if (!shown || !fitRooms(cut.widths, shown.widths, smallest)) {\n continue;\n }\n\n mostShown = cut.shown;\n best = { width: Math.floor(Math.max(...shown.widths)), fontSize: smallest, lines: cut.lines, icon: false, truncated: cut.truncated, lift: shown.lift };\n }\n\n return role === 'sun' || mostShown >= SHORTEST_CUT ? best : null;\n};\n\n/**\n * Where a node's label goes at this on-screen size. A name goes inside its\n * node whenever it fits there (see `insideLabelLayout`). A pill beside the\n * node is for the nodes that need one: nodes showing a picture, the focused\n * node when its name doesn't fit inside, and overview nodes too small for\n * their names. Any other node too small for its name shows none until you\n * zoom in. A name inside a node keeps clear of its \"+N\", `countWidth` px wide.\n */\nexport const labelPlacement = (role: NodeRole, screenRadius: number, text: string, hasImage: boolean, hasIcon = false, measure: TextMeasure = INSIDE_ESTIMATE, narrower = true, countWidth = 0): LabelPlacement => {\n if (!hasImage && insideLabelLayout(role, screenRadius, text, hasIcon, measure, narrower, countWidth)) {\n return 'inside';\n }\n\n if (role === 'sun') {\n return 'outside';\n }\n\n if (hasImage || role === 'node') {\n return screenRadius >= (role === 'moon' ? 11 : 4) ? 'outside' : 'hidden';\n }\n\n return 'hidden';\n};\n\n/** Fills `element` with `text`, marking where long words may break (`wordPieces`), as fitting the label assumes. */\nconst setBreakableText = (element: HTMLElement, text: string): void => {\n element.textContent = '';\n\n for (const part of text.split(/(\\s+)/)) {\n if (!part) {\n continue;\n }\n\n if (/^\\s+$/.test(part)) {\n element.append(part);\n continue;\n }\n\n wordPieces(part).forEach((piece, index) => {\n if (index > 0) {\n element.append(document.createElement('wbr'));\n }\n\n element.append(piece);\n });\n }\n};\n\n/** How a node's label is drawn on a frame (see `NodeLabel.update`). */\nexport interface LabelDrawing {\n /** The node's center on screen (px). */\n x: number;\n\n y: number;\n\n /** The node's radius on screen (px). */\n screenRadius: number;\n\n role: NodeRole;\n placement: LabelPlacement;\n opacity: number;\n\n /** Whether a name inside its node takes the theme's light text. */\n light?: boolean;\n\n /** The font a name inside its node is fitted in, as its placement was (default: estimated widths). */\n measure?: TextMeasure;\n\n /** Whether a name inside its node may try narrower widths of its font, as it does while the map is still (default: true). */\n narrower?: boolean;\n\n /** The width (px) of the node's \"+N\", which a name inside it keeps clear of (default: 0, when it shows none). */\n countWidth?: number;\n\n /** The side of its node a pill touches, a unit vector (default: below). */\n direction?: { x: number; y: number };\n\n /** How far from the node's center a pill sits (px; see `pillDistance` in `labels.ts`; default: 5 px past its edge). */\n distance?: number;\n\n /** Pixels a pill above or below its node slid sideways to stay on the map. */\n offset?: number;\n\n /** A pill's lines, and the width (px) it wraps at on two. */\n lines?: 1 | 2;\n\n width?: number;\n\n /** What a pill says (default: the node's name). */\n pillText?: string;\n}\n\n/** Where a pill goes when nothing says: below its node. */\nconst BELOW = { x: 0, y: 1 };\n\nexport class NodeLabel {\n readonly element: HTMLDivElement;\n readonly node: OrbitNode;\n\n /** The type the node was drawn as, as for its view. */\n readonly typeName: string | undefined;\n\n private readonly text: HTMLSpanElement;\n\n /** Whether the node has an icon, shown above its name when there's room. */\n private readonly hasIcon: boolean;\n\n /** The side an outside label sat on last (a unit vector), or null. */\n direction: { x: number; y: number } | null = null;\n\n private placement: LabelPlacement | null = null;\n private role: NodeRole | null = null;\n private fontSize = 0;\n\n /** The `font-stretch` written for a name drawn narrower to fit (0: the font's own width). */\n private stretch = 0;\n\n /** The lines written into the label inside its node, or null while it holds the whole name (pills wrap it themselves). */\n private shownLines: string | null = null;\n\n /** What the label's pill says, while it's a pill. */\n private pillText: string | null = null;\n\n private iconHidden = false;\n private light: boolean | null = null;\n\n /** An outside pill on two lines, and the width it wraps at. */\n private wrapped = false;\n\n private pillWidth = 0;\n\n /** What was last written, so a label that didn't move isn't touched: the map repaints every frame while it moves. */\n private shown = true;\n\n private transform = '';\n private opacity = '';\n\n constructor(node: OrbitNode, extensions: MapExtensions) {\n this.node = node;\n this.element = document.createElement('div');\n this.element.className = 'orbit-label';\n this.element.setAttribute('aria-hidden', 'true');\n this.element.dataset.orbitFor = node.id;\n this.typeName = extensions.typeName(node);\n markNode(this.element, node, this.typeName);\n applyTypeTokens(this.element, extensions.nodeType(node));\n const iconText = extensions.icon(node);\n this.hasIcon = Boolean(iconText);\n\n if (iconText) {\n const icon = document.createElement('span');\n icon.className = 'orbit-label__icon';\n icon.textContent = iconText;\n this.element.appendChild(icon);\n }\n\n this.text = document.createElement('span');\n this.text.className = 'orbit-label__text';\n setBreakableText(this.text, node.text);\n this.element.appendChild(this.text);\n }\n\n get currentPlacement(): LabelPlacement {\n return this.placement ?? 'hidden';\n }\n\n /** Whether the label shows: placed somewhere and not hidden. */\n get isShown(): boolean {\n return this.shown && this.placement !== null && this.placement !== 'hidden';\n }\n\n /** Draws the label as `drawing` says: inside its node, fitted as its placement was, or as a pill beside it. */\n update(drawing: LabelDrawing): void {\n const { x, y, screenRadius, role, placement, opacity } = drawing;\n\n if (placement !== this.placement || role !== this.role) {\n this.element.className = `orbit-label orbit-label--${role}${placement === 'outside' ? ' orbit-label--outside' : ''}`;\n this.placement = placement;\n this.role = role;\n this.light = null;\n this.wrapped = false;\n }\n\n const shown = placement !== 'hidden' && opacity > 0.01;\n\n if (shown !== this.shown) {\n this.element.style.display = shown ? '' : 'none';\n this.shown = shown;\n }\n\n if (!shown) {\n return;\n }\n\n let transform: string;\n\n if (placement === 'inside') {\n const layout = insideLabelLayout(role, screenRadius, this.node.text, this.hasIcon, drawing.measure, drawing.narrower, drawing.countWidth) ?? {\n width: insideLabelWidth(role, screenRadius),\n fontSize: MINIMUM_FONT_SIZE[role],\n lines: [this.node.text],\n icon: false,\n truncated: true,\n lift: 0,\n };\n const light = drawing.light ?? false;\n\n if (light !== this.light) {\n this.element.classList.toggle('orbit-label--light', light);\n this.light = light;\n }\n\n if (layout.fontSize !== this.fontSize) {\n this.element.style.fontSize = `${layout.fontSize}px`;\n this.fontSize = layout.fontSize;\n }\n\n const stretch = layout.stretch ?? 0;\n\n if (stretch !== this.stretch) {\n this.element.style.fontStretch = stretch ? `${stretch}%` : '';\n this.stretch = stretch;\n }\n\n // The lines the fit chose, exactly: the browser doesn't wrap them again.\n const shownLines = layout.lines.join('\\n');\n\n if (shownLines !== this.shownLines) {\n this.text.textContent = shownLines;\n this.shownLines = shownLines;\n this.pillText = null;\n }\n\n const iconHidden = this.hasIcon && !layout.icon;\n\n if (iconHidden !== this.iconHidden) {\n this.element.classList.toggle('orbit-label--no-icon', iconHidden);\n this.iconHidden = iconHidden;\n }\n\n transform = `translate3d(${round(x, 1)}px, ${round(y - layout.lift, 1)}px, 0) translate(-50%, -50%)`;\n } else {\n const { direction = BELOW, distance = screenRadius + 5, offset = 0, lines = 1, width = 0, pillText = this.node.text } = drawing;\n\n if (this.fontSize !== 0) {\n this.element.style.fontSize = '';\n this.fontSize = 0;\n }\n\n if (this.stretch !== 0) {\n this.element.style.fontStretch = '';\n this.stretch = 0;\n }\n\n if (this.shownLines !== null || this.pillText !== pillText) {\n setBreakableText(this.text, pillText);\n this.shownLines = null;\n this.pillText = pillText;\n }\n\n const wrapped = lines === 2;\n\n if (wrapped !== this.wrapped) {\n this.element.classList.toggle('orbit-label--wrapped', wrapped);\n this.wrapped = wrapped;\n }\n\n // No wider than the box label planning kept on the map.\n if (wrapped && width !== this.pillWidth) {\n this.element.style.setProperty('--orbit-pill-width', `${Math.floor(width)}px`);\n this.pillWidth = width;\n }\n\n // The pill's point that matches its side sits `distance` from the node's center (see `pillDistance`).\n this.direction = direction;\n const shiftX = round(-50 + direction.x * 50, 1);\n const shiftY = round(-50 + direction.y * 50, 1);\n transform = `translate3d(${round(x + direction.x * distance + offset, 1)}px, ${round(y + direction.y * distance, 1)}px, 0) translate(${shiftX}%, ${shiftY}%)`;\n }\n\n if (transform !== this.transform) {\n this.element.style.transform = transform;\n this.transform = transform;\n }\n\n const opacityValue = opacity >= 0.999 ? '' : String(round(opacity, 3));\n\n if (opacityValue !== this.opacity) {\n this.element.style.opacity = opacityValue;\n this.opacity = opacityValue;\n }\n }\n}\n\n/** Dashed ring arcs between the bodies on a ring (centered on the origin). */\nexport const ringPath = (radius: number, gaps: DisplayRing['gaps']): string => {\n if (radius <= 0) {\n return '';\n }\n\n const openings = gaps\n .map((gap) => ({ start: normalizeAngle(gap.angle - gap.halfWidth), width: gap.halfWidth * 2 }))\n .filter((gap) => gap.width > 0)\n .sort((left, right) => left.start - right.start);\n\n if (openings.length === 0) {\n return `M ${round(radius)} 0 A ${round(radius)} ${round(radius)} 0 1 1 ${round(-radius)} 0 A ${round(radius)} ${round(radius)} 0 1 1 ${round(radius)} 0`;\n }\n\n const commands: string[] = [];\n\n for (let index = 0; index < openings.length; index += 1) {\n const current = openings[index];\n const next = openings[(index + 1) % openings.length];\n const arcStart = current.start + current.width;\n let arcEnd = next.start;\n\n if (index === openings.length - 1) {\n arcEnd += 360;\n }\n\n const sweep = arcEnd - arcStart;\n\n if (sweep <= 0.5) {\n continue;\n }\n\n const from = polar(radius, arcStart);\n const to = polar(radius, arcEnd);\n commands.push(`M ${round(from.x)} ${round(from.y)} A ${round(radius)} ${round(radius)} 0 ${sweep > 180 ? 1 : 0} 1 ${round(to.x)} ${round(to.y)}`);\n }\n\n return commands.join(' ');\n};\n\nconst polar = (radius: number, degrees: number): { x: number; y: number } => {\n const radians = (degrees * Math.PI) / 180;\n return { x: radius * Math.cos(radians), y: radius * Math.sin(radians) };\n};\n\nconst normalizeAngle = (degrees: number): number => {\n return ((degrees % 360) + 360) % 360;\n};\n\nconst round = (value: number, decimals = 2): number => {\n const factor = 10 ** decimals;\n return Math.round(value * factor) / factor;\n};\n",
|
|
38
|
+
"/**\n * DOM views for the map content. Nodes are SVG groups drawn at unit radius\n * and positioned with a single `translate() scale()`, so moving or resizing\n * a node is one attribute write per frame; spinning an orbit turns the group\n * its bodies are in instead (see `OrbitTurn`). Labels are HTML in screen\n * space, so text never scales with the camera and keeps a readable size.\n */\n\nimport type { OrbitNode } from '../types.js';\nimport type { DisplayNode, DisplayRing, DisplaySlot } from './display.js';\nimport type { NodeRole } from './scene.js';\nimport { guardUrl, resolveUrl } from '../url-guard.js';\nimport { hasMediaSource, youtubeThumbnailUrl } from '../media.js';\nimport type { MapExtensions, OrbitNodeType } from '../extensions.js';\nimport { breakUnits, graphemes, wordPieces, type TextUnit } from '../text-layout.js';\nimport { COUNT_ESTIMATE, INSIDE_ESTIMATE, onMeasurementsReset, type TextMeasure } from './text-measure.js';\nimport { OrbitWords } from '../languages.js';\n\n\nexport const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n\nexport interface ViewIds {\n /** Unit-circle clip path shared by every node image. */\n clip: string;\n\n /** Sphere shading gradient. */\n shade: string;\n\n /**\n * The shading of specks: the same, turned back by the turn they're drawn in\n * once their orbit rests, so it comes from the top left (see `turnShading`).\n */\n speckShade: string;\n\n /** Blur for the shadow (or glow) of planets and moons. */\n shadow: string;\n\n /** A wider blur for the sun's. */\n sunShadow: string;\n}\n\nexport const svgElement = <Name extends keyof SVGElementTagNameMap>(name: Name, attributes: Record<string, string> = {}): SVGElementTagNameMap[Name] => {\n const element = document.createElementNS(SVG_NAMESPACE, name);\n\n for (const [key, value] of Object.entries(attributes)) {\n element.setAttribute(key, value);\n }\n\n return element;\n};\n\n/**\n * Where the sphere shading changes, from the lit side (top left) to the far\n * edge. The theme colors each stop (`node-highlight`, `node-terminator`,\n * `node-shading`); the stylesheet and the SVG export share these offsets.\n */\nexport const SHADE_STOPS = [\n { offset: 0, part: 'highlight' },\n { offset: 0.45, part: 'highlight-fade' },\n { offset: 0.55, part: 'terminator-start' },\n { offset: 0.78, part: 'terminator' },\n { offset: 1, part: 'shading' },\n] as const;\n\n/**\n * The circle the shading spreads over, in fractions of a node's box: its\n * center, then its radius. The default lights spheres from the top left; a\n * theme moves it with the `node-shade-circle` token, such as to the bottom\n * right so the far stops catch light along the top left rim, as glass does.\n */\nexport interface ShadeCircle {\n x: number;\n y: number;\n radius: number;\n}\n\nexport const DEFAULT_SHADE_CIRCLE: ShadeCircle = { x: 0.34, y: 0.3, radius: 0.78 };\n\n/** A `node-shade-circle` value (`0.34 0.3 0.78`) read, or the default when it isn't three numbers with a radius above 0. */\nexport const readShadeCircle = (value: string | undefined): ShadeCircle => {\n const numbers = (value ?? '').trim().split(/[\\s,]+/).map(Number);\n\n if (numbers.length !== 3 || !numbers.every(Number.isFinite) || numbers[2] <= 0) {\n return DEFAULT_SHADE_CIRCLE;\n }\n\n const [x, y, radius] = numbers;\n return { x, y, radius };\n};\n\n/** Moves the shading of every node (specks follow it) to the theme's circle. */\nexport const placeShading = (defs: SVGDefsElement, ids: ViewIds, circle: ShadeCircle): void => {\n const gradient = Array.from(defs.children).find((child) => child.id === ids.shade);\n gradient?.setAttribute('cx', String(circle.x));\n gradient?.setAttribute('cy', String(circle.y));\n gradient?.setAttribute('r', String(circle.radius));\n};\n\n/** Blur radius of a shadow, in node radii: planets and moons, then the sun. */\nexport const SHADOW_BLUR = { planet: 0.16, sun: 0.3 } as const;\n\n/** Shared definitions: the image clip, sphere shading and shadow blurs, with instance-scoped ids. */\nexport const createDefinitions = (ids: ViewIds): SVGDefsElement => {\n const defs = svgElement('defs');\n const clip = svgElement('clipPath', { id: ids.clip, clipPathUnits: 'userSpaceOnUse' });\n clip.appendChild(svgElement('circle', { r: '1' }));\n defs.appendChild(clip);\n\n const shade = svgElement('radialGradient', {\n id: ids.shade,\n cx: String(DEFAULT_SHADE_CIRCLE.x),\n cy: String(DEFAULT_SHADE_CIRCLE.y),\n r: String(DEFAULT_SHADE_CIRCLE.radius),\n });\n\n for (const stop of SHADE_STOPS) {\n shade.appendChild(svgElement('stop', { offset: String(stop.offset), class: `orbit-shade__${stop.part}` }));\n }\n\n defs.appendChild(shade);\n defs.appendChild(svgElement('radialGradient', { id: ids.speckShade, href: `#${ids.shade}` }));\n\n for (const [id, blur] of [[ids.shadow, SHADOW_BLUR.planet], [ids.sunShadow, SHADOW_BLUR.sun]] as const) {\n const filter = svgElement('filter', { id, x: '-60%', y: '-60%', width: '220%', height: '220%' });\n filter.appendChild(svgElement('feGaussianBlur', { stdDeviation: String(blur) }));\n defs.appendChild(filter);\n }\n\n return defs;\n};\n\n/**\n * Turns the shading of specks back by `turn` degrees, the turn they're drawn\n * in, so their light comes from the top left. One write for every speck, but\n * the browser draws each of them again: not on every frame of a spin.\n */\nexport const turnShading = (defs: SVGDefsElement, ids: ViewIds, turn: number): void => {\n const gradient = Array.from(defs.children).find((child) => child.id === ids.speckShade);\n\n if (turn === 0) {\n gradient?.removeAttribute('gradientTransform');\n } else {\n gradient?.setAttribute('gradientTransform', `rotate(${-turn} 0.5 0.5)`);\n }\n};\n\nconst ENGLISH = new OrbitWords('en');\n\n/** Labels and the assistive name of a node, in the map's language (English without one). */\nexport const describeNode = (\n node: OrbitNode,\n hiddenChildren: number,\n visibleChildren: number,\n extensions?: MapExtensions,\n words: OrbitWords = ENGLISH,\n): string => {\n const type = extensions?.nodeType(node);\n const parts = [[extensions ? extensions.icon(node) : node.icon, node.text || words.text('untitled')].filter(Boolean).join(' ')];\n\n if (type?.label) {\n parts.push(type.label);\n }\n\n if (node.status) {\n parts.push(words.text('status', { status: node.status }));\n }\n\n const total = visibleChildren + hiddenChildren;\n\n if (total > 0) {\n parts.push(words.count('ideaCount', total));\n }\n\n const content = [\n type?.details ? words.text('hasDetails') : '',\n node.note ? words.text('hasNote') : '',\n hasMediaSource(node.image) ? words.text('hasImage') : '',\n hasMediaSource(node.video) ? words.text('hasVideo') : '',\n hasMediaSource(node.embed) ? words.text('hasEmbed') : '',\n node.link ? words.text('hasLink') : '',\n ].filter(Boolean);\n\n if (content.length > 0) {\n parts.push(words.text('has', { list: words.list(content) }));\n }\n\n return parts.join(', ');\n};\n\n/** Bodies smaller than this on screen (px) are drawn flat: there a shadow is a smudge. */\nconst SMALL_BODY_RADIUS = 12;\n/**\n * Flat bodies smaller than this on screen, in device pixels, are specks: too\n * few pixels for their shading or badges to show which way is up (see\n * `NodeView.update`).\n */\nconst SPECK_DEVICE_RADIUS = 5;\n/**\n * A crowded orbit's planets without badges are specks below this instead.\n * Drawn flat, with rims that grow with them, they look the same as specks,\n * and their shading, which turns with the orbit while it spins, is too faint\n * at this size to show which way is up.\n */\nconst CROWDED_SPECK_DEVICE_RADIUS = 16;\n\n/**\n * The on-screen radius (px) below which flat bodies are specks, at\n * `pixelRatio` device pixels per px: bigger for a `plainCrowded` planet, one\n * of a crowded orbit without badges (a status, a note's marker, a play button).\n */\nexport const speckRadius = (pixelRatio: number, plainCrowded = false): number => {\n return (plainCrowded ? CROWDED_SPECK_DEVICE_RADIUS : SPECK_DEVICE_RADIUS) / (pixelRatio > 0 ? pixelRatio : 1);\n};\n\n/** The focus ring's radius, in node radii. */\nconst FOCUS_RING_RADIUS = 1.22;\n\n/** What every node is drawn with this frame, besides its own place (see `NodeView.update`). */\nexport interface NodeDrawing {\n /** In an orbit turned as one, the degrees it's turned (see `OrbitTurn`). */\n turn?: number;\n\n /** The on-screen radius (px) below which flat bodies are specks (see `speckRadius`). */\n speckRadius: number;\n\n /** The same for a crowded orbit's planets without badges. */\n crowdedSpeckRadius: number;\n\n /**\n * How many more nodes may become specks, or stop being them, this frame.\n * The rest wait for the next: a zoom across the size where a whole orbit\n * becomes specks doesn't redraw all of it at once.\n */\n switches: number;\n\n /** Set when a node is waiting for its turn to switch. */\n waiting: boolean;\n\n /**\n * During a flight bodies don't become specks: one shrinking as the camera\n * pulls away costs less to leave as it is until the flight lands.\n */\n flight: boolean;\n}\n\n/**\n * Whether a body leaves out its blurred shadow (and hidden halo): when it's\n * too small on screen for a shadow to show, a planet of a crowded orbit,\n * where shadows overlap into a haze, or one coming or going in a flight,\n * fading in or out while the camera sweeps past it (and may draw it huge).\n * Blurring hundreds of shadows on every frame is also what makes a crowded\n * orbit or a flight slow.\n */\nexport const drawsFlat = (display: DisplayNode, screenRadius: number): boolean => {\n return display.crowded === true || display.cluster !== undefined || screenRadius < SMALL_BODY_RADIUS;\n};\n\nexport class NodeView {\n readonly element: SVGGElement;\n readonly id: string;\n readonly node: OrbitNode;\n\n /** The type the node was drawn as. One given for display can change with the map around it, and the view is drawn again then. */\n readonly typeName: string | undefined;\n\n /** Shows a picture (an image, or a video's thumbnail) rather than a plain color. */\n hasImage = false;\n\n /** Shows a status, a note's marker or a play button: a crowded orbit's planet with one stays a body down to the usual size (see `speckRadius`). */\n private readonly hasBadges: boolean;\n\n private readonly body: SVGGElement;\n private readonly disc: SVGCircleElement;\n private readonly shade: SVGCircleElement;\n private readonly shadeFills: { body: string; speck: string };\n private readonly shadowFilters: { planet: string; sun: string };\n\n /**\n * Created once a node shows them: a shadow when it's drawn with one (not\n * the hundreds of flat planets of a crowded orbit, or overview nodes), the\n * halo when it becomes the sun, the focus ring when it's focused.\n */\n private shadow: SVGCircleElement | null = null;\n\n private halo: SVGCircleElement | null = null;\n private focusRing: SVGCircleElement | null = null;\n private status: SVGCircleElement | null = null;\n private role: NodeRole | null = null;\n private color = '';\n private visible = true;\n\n /** Where the node was last drawn, and how: what its transform (or a speck's circles) is worked out from. */\n private drawn = { x: Number.NaN, y: Number.NaN, radius: Number.NaN, upright: 0, opacity: Number.NaN };\n\n private transform = '';\n private opacity = '';\n private editing = false;\n private lifted = false;\n private dropTarget = false;\n private flat = false;\n private crowded = false;\n private speck = false;\n private turnedBack = false;\n\n constructor(display: DisplayNode, screenRadius: number, ids: ViewIds, baseUrl: string | undefined, extensions: MapExtensions, drawing?: NodeDrawing, onImageError?: () => void) {\n this.id = display.id;\n this.node = display.node;\n const { node } = display;\n const type = extensions.nodeType(node);\n this.typeName = extensions.typeName(node);\n this.element = svgElement('g', { class: 'orbit-node', 'data-orbit-node-id': node.id, tabindex: '-1' });\n this.element.setAttribute('role', 'button');\n markNode(this.element, node, this.typeName);\n applyTypeTokens(this.element, type);\n this.body = svgElement('g', { class: 'orbit-node__body' });\n this.shadowFilters = { planet: `url(#${ids.shadow})`, sun: `url(#${ids.sunShadow})` };\n this.disc = svgElement('circle', { class: 'orbit-node__disc', r: '1' });\n this.body.append(this.disc);\n\n const thumbnail = nodeThumbnail(node);\n const source = thumbnail ? guardUrl(thumbnail, 'image') : null;\n\n if (source) {\n const image = svgElement('image', {\n class: 'orbit-node__image',\n x: '-1',\n y: '-1',\n width: '2',\n height: '2',\n preserveAspectRatio: 'xMidYMid slice',\n 'clip-path': `url(#${ids.clip})`,\n });\n image.setAttribute('href', resolveUrl(source, baseUrl));\n\n image.addEventListener('error', () => {\n image.remove();\n this.hasImage = false;\n // The label planned for a picture (its pill outside) belongs inside now: ask for a paint.\n onImageError?.();\n });\n\n this.body.appendChild(image);\n this.hasImage = true;\n }\n\n // Shading and rim in one element: the gradient fills it, the rim is its stroke.\n this.shadeFills = { body: `url(#${ids.shade})`, speck: `url(#${ids.speckShade})` };\n this.shade = svgElement('circle', { class: 'orbit-node__shade', r: '1', fill: this.shadeFills.body });\n this.body.appendChild(this.shade);\n\n const hasMarker = node.note || hasMediaSource(node.image) || hasMediaSource(node.embed) || node.link || type?.details;\n\n if (hasMediaSource(node.video)) {\n const play = svgElement('g', { class: 'orbit-node__play', transform: 'translate(0.62 0.62) scale(0.3)' });\n play.appendChild(svgElement('circle', { r: '1' }));\n play.appendChild(svgElement('path', { d: 'M-0.32 -0.48 L0.52 0 L-0.32 0.48 Z' }));\n this.body.appendChild(play);\n } else if (hasMarker) {\n this.body.appendChild(svgElement('circle', { class: 'orbit-node__marker', cx: '0.72', cy: '0.72', r: '0.13' }));\n }\n\n this.hasBadges = hasMediaSource(node.video) || Boolean(hasMarker) || Boolean(node.status);\n\n if (node.status) {\n const look = extensions.status(node.status);\n this.status = svgElement('circle', { class: `orbit-node__status orbit-node__status--${look.tone}` });\n\n if (look.color) {\n this.status.style.fill = look.color;\n }\n\n this.body.appendChild(this.status);\n }\n\n this.element.appendChild(this.body);\n // A new node starts out as what it is now, before it's on the map: that costs nothing to switch.\n this.update(display, screenRadius, drawing && { ...drawing, switches: Number.POSITIVE_INFINITY, flight: false });\n }\n\n /**\n * Draws the node as `display` places it, `screenRadius` px across on screen.\n *\n * A speck (see `speckRadius`) is drawn with its circles' own coordinates\n * instead of a transform, its badges left out: the browser handles a\n * thousand of them far faster that way, as long as they hold still. A node\n * `moving` on its own (one travelling in a flight) is drawn as a body:\n * moving it is one write instead of one per circle.\n *\n * In an orbit turned as one (see `OrbitTurn`), a body that turns with it is\n * drawn where it is in the unturned orbit: a speck turns with the orbit,\n * shading and all, and anything bigger is turned back upright.\n */\n update(display: DisplayNode, screenRadius = Infinity, drawing?: NodeDrawing, moving = false): void {\n const flat = drawsFlat(display, screenRadius);\n\n if (flat !== this.flat) {\n this.element.classList.toggle('orbit-node--flat', flat);\n this.flat = flat;\n }\n\n const crowded = display.crowded === true;\n\n if (crowded !== this.crowded) {\n this.element.classList.toggle('orbit-node--crowded', crowded);\n this.crowded = crowded;\n }\n\n if (display.role !== this.role) {\n if (this.role) {\n this.element.classList.remove(`orbit-node--${this.role}`);\n }\n\n this.element.classList.add(`orbit-node--${display.role}`);\n this.role = display.role;\n this.shadow?.setAttribute('filter', display.role === 'sun' ? this.shadowFilters.sun : this.shadowFilters.planet);\n\n if (display.role === 'sun') {\n this.element.setAttribute('aria-current', 'true');\n } else {\n this.element.removeAttribute('aria-current');\n }\n\n // The sun is big: a smaller share of it keeps its status dot in proportion.\n const statusRadius = display.role === 'sun' ? 0.11 : 0.17;\n const statusOffset = display.role === 'sun' ? 0.68 : 0.72;\n this.status?.setAttribute('r', String(statusRadius));\n this.status?.setAttribute('cx', String(statusOffset));\n this.status?.setAttribute('cy', String(-statusOffset));\n }\n\n if (!flat && display.role !== 'node' && !this.shadow) {\n this.shadow = svgElement('circle', { class: 'orbit-node__shadow', r: '1' });\n this.shadow.setAttribute('filter', display.role === 'sun' ? this.shadowFilters.sun : this.shadowFilters.planet);\n this.body.insertBefore(this.shadow, this.halo ?? this.disc);\n }\n\n if (display.role === 'sun' && !this.halo) {\n this.halo = svgElement('circle', { class: 'orbit-node__halo', r: '1' });\n this.body.insertBefore(this.halo, this.disc);\n }\n\n if (display.color !== this.color) {\n this.disc.style.fill = display.color;\n // The rim, shadow and halo mix the theme's colors with this one.\n this.element.style.setProperty('--orbit-node-color', display.color);\n this.color = display.color;\n }\n\n const visible = display.opacity > 0.01 && display.radius > 0.05;\n\n if (visible !== this.visible) {\n this.element.style.display = visible ? '' : 'none';\n this.visible = visible;\n }\n\n // Decided while hidden too: a hidden node switches at almost no cost, and needn't wait.\n const below = crowded && !this.hasBadges ? drawing?.crowdedSpeckRadius ?? speckRadius(1, true) : drawing?.speckRadius ?? speckRadius(1);\n const speck = !moving && flat && !this.hasImage && screenRadius < below;\n\n if (speck !== this.speck && !(visible && speck && drawing?.flight)) {\n // A speck that starts moving can't wait either: each frame it waited would cost more than the switch.\n if (visible && drawing && drawing.switches <= 0 && !moving) {\n drawing.waiting = true;\n } else {\n if (visible && drawing) {\n drawing.switches -= 1;\n }\n\n this.setSpeck(speck);\n }\n }\n\n if (!visible) {\n return;\n }\n\n const turn = drawing?.turn;\n const unturned = turn === undefined ? undefined : display.unturned;\n const place = unturned ?? display;\n this.turnedBack = unturned !== undefined && !this.speck;\n const upright = this.turnedBack && turn ? turn : 0;\n // Only touch the DOM when something moved: panning repaints every node, and a spin every body that turns with its orbit.\n const drawn = this.drawn;\n\n if (place.x !== drawn.x || place.y !== drawn.y || display.radius !== drawn.radius || upright !== drawn.upright) {\n if (this.speck) {\n this.placeSpeck(place.x, place.y, display.radius);\n } else {\n const transform = `translate(${round(place.x)} ${round(place.y)})${upright ? ` rotate(${-upright})` : ''} scale(${round(display.radius, 4)})`;\n\n if (transform !== this.transform) {\n this.element.setAttribute('transform', transform);\n this.transform = transform;\n }\n }\n\n drawn.x = place.x;\n drawn.y = place.y;\n drawn.radius = display.radius;\n drawn.upright = upright;\n }\n\n if (display.opacity !== drawn.opacity) {\n const opacity = display.opacity >= 0.999 ? '' : String(round(display.opacity, 3));\n\n if (opacity !== this.opacity) {\n this.element.style.opacity = opacity;\n this.opacity = opacity;\n }\n\n drawn.opacity = display.opacity;\n }\n }\n\n /** Whether it was last drawn turned back upright in an orbit turned as one: it moves as the orbit turns. */\n get isTurnedBack(): boolean {\n return this.turnedBack;\n }\n\n /** Draws the node as a speck from now on, or as a body again. */\n private setSpeck(speck: boolean): void {\n this.speck = speck;\n this.element.classList.toggle('orbit-node--speck', speck);\n this.shade.setAttribute('fill', speck ? this.shadeFills.speck : this.shadeFills.body);\n\n if (speck) {\n this.element.removeAttribute('transform');\n this.transform = '';\n } else {\n for (const circle of this.unitCircles()) {\n circle.removeAttribute('cx');\n circle.removeAttribute('cy');\n circle.setAttribute('r', circle === this.focusRing ? String(FOCUS_RING_RADIUS) : '1');\n }\n\n this.shade.style.removeProperty('--orbit-speck-radius');\n }\n\n // Drawn again where it is, the new way.\n this.drawn.x = Number.NaN;\n }\n\n /** Puts a speck's circles at (`x`, `y`), `radius` in size, in the map's own units. */\n private placeSpeck(x: number, y: number, radius: number): void {\n const cx = String(round(x));\n const cy = String(round(y));\n\n for (const circle of this.unitCircles()) {\n circle.setAttribute('cx', cx);\n circle.setAttribute('cy', cy);\n circle.setAttribute('r', String(round(radius * (circle === this.focusRing ? FOCUS_RING_RADIUS : 1), 4)));\n }\n\n // The rim grows and shrinks with the speck (see the stylesheet).\n this.shade.style.setProperty('--orbit-speck-radius', String(round(radius, 4)));\n }\n\n /** The circles a body draws at unit radius around its center, and a speck at its own place. */\n private unitCircles(): SVGCircleElement[] {\n return this.focusRing ? [this.disc, this.shade, this.focusRing] : [this.disc, this.shade];\n }\n\n /** The fill as the browser resolved it (theme tokens and color mixes included). */\n resolvedFill(): string {\n return typeof getComputedStyle === 'function' ? getComputedStyle(this.disc).fill : '';\n }\n\n /** Marks the node whose text is being edited on the map. */\n setEditing(editing: boolean): void {\n if (editing !== this.editing) {\n if (editing) {\n this.showFocusRing();\n }\n\n this.element.classList.toggle('orbit-node--editing', editing);\n this.editing = editing;\n }\n }\n\n /** Held up by a press, to be dragged somewhere else: it grows, its shadow deepens. */\n setLifted(lifted: boolean): void {\n if (lifted !== this.lifted) {\n this.element.classList.toggle('orbit-node--lifted', lifted);\n this.lifted = lifted;\n }\n }\n\n /** Where a node being dragged would go if let go now: it grows to take it, ringed. */\n setDropTarget(target: boolean): void {\n if (target !== this.dropTarget) {\n if (target) {\n this.showFocusRing();\n }\n\n this.element.classList.toggle('orbit-node--drop-target', target);\n this.dropTarget = target;\n }\n }\n\n /** Adds the ring that shows while the node has keyboard focus or is being edited. */\n showFocusRing(): void {\n if (!this.focusRing) {\n this.focusRing = svgElement('circle', { class: 'orbit-node__focus-ring', r: String(FOCUS_RING_RADIUS) });\n this.body.appendChild(this.focusRing);\n\n if (this.speck) {\n this.placeSpeck(this.drawn.x, this.drawn.y, this.drawn.radius);\n }\n }\n }\n}\n\n/**\n * The free place in the orbit for a new idea: a dashed circle with a plus,\n * drawn at unit radius like a node. While a new idea is typed there, it\n * fills in around the field.\n */\nexport class AddSlotView {\n readonly element: SVGGElement;\n private shown = false;\n private pending = false;\n private drop: 'target' | 'waiting' | false = false;\n private label = '';\n private transform = '';\n private opacity = '';\n\n get isShown(): boolean {\n return this.shown;\n }\n\n /** `held`: the place held for a node being dragged, which only shows, rather than the + to press. */\n constructor(held = false) {\n this.element = held\n ? svgElement('g', { class: 'orbit-add orbit-add--held', 'aria-hidden': 'true' })\n : svgElement('g', { class: 'orbit-add', 'data-orbit-add': '', tabindex: '-1' });\n\n if (!held) {\n this.element.setAttribute('role', 'button');\n }\n\n const body = svgElement('g', { class: 'orbit-add__body' });\n body.append(\n svgElement('circle', { class: 'orbit-add__disc', r: '1' }),\n svgElement('path', { class: 'orbit-add__plus', d: 'M-0.3 0H0.3M0 -0.3V0.3' }),\n svgElement('circle', { class: 'orbit-add__focus-ring', r: String(FOCUS_RING_RADIUS) }),\n );\n this.element.appendChild(body);\n this.element.style.display = 'none';\n }\n\n /**\n * Draws the slot where `slot` says, or hides it. `label` names it for\n * assistive technology. `drop` shows it as the place held open for a node\n * being dragged, without its plus: the `target`, or `waiting` while the\n * node is over another one. In an orbit turned `turn` degrees, it's drawn\n * where it is in the unturned orbit, turned back upright.\n */\n update(slot: DisplaySlot | undefined, label: string, pending: boolean, turn?: number, drop: 'target' | 'waiting' | false = false): void {\n const shown = slot !== undefined && slot.opacity > 0.01 && slot.radius > 0.05;\n\n if (shown !== this.shown) {\n this.element.style.display = shown ? '' : 'none';\n this.shown = shown;\n }\n\n if (!slot || !shown) {\n return;\n }\n\n if (pending !== this.pending) {\n this.element.classList.toggle('orbit-add--pending', pending);\n this.pending = pending;\n }\n\n if (drop !== this.drop) {\n this.element.classList.toggle('orbit-add--drop', drop !== false);\n this.element.classList.toggle('orbit-add--waiting', drop === 'waiting');\n this.drop = drop;\n }\n\n if (label !== this.label) {\n if (label) {\n this.element.setAttribute('aria-label', label);\n } else {\n this.element.removeAttribute('aria-label');\n }\n\n this.label = label;\n }\n\n const unturned = turn === undefined ? undefined : slot.unturned;\n const place = unturned ?? slot;\n const upright = unturned && turn ? ` rotate(${-turn})` : '';\n const transform = `translate(${round(place.x)} ${round(place.y)})${upright} scale(${round(slot.radius, 4)})`;\n\n if (transform !== this.transform) {\n this.element.setAttribute('transform', transform);\n this.transform = transform;\n }\n\n const opacity = slot.opacity >= 0.999 ? '' : String(round(slot.opacity, 3));\n\n if (opacity !== this.opacity) {\n this.element.style.opacity = opacity;\n this.opacity = opacity;\n }\n }\n}\n\n/** CSS hooks for a node's element and label: `data-orbit-type`, `data-orbit-status` and `data-orbit-tags`. */\nexport const markNode = (element: HTMLElement | SVGElement, node: OrbitNode, type: string | undefined = node.type): void => {\n if (type) {\n element.setAttribute('data-orbit-type', type.toLowerCase());\n }\n\n if (node.status) {\n element.setAttribute('data-orbit-status', node.status.trim().toLowerCase());\n }\n\n if (node.tags?.length) {\n element.setAttribute('data-orbit-tags', node.tags.join(' '));\n }\n};\n\n/** A node type's theme tokens, set on its node's elements so they win over the map's theme there. */\nexport const applyTypeTokens = (element: HTMLElement | SVGElement, type: OrbitNodeType | undefined): void => {\n for (const [token, value] of Object.entries(type?.tokens ?? {})) {\n if (typeof value === 'string' && value !== '') {\n element.style.setProperty(`--_orbit-${token}`, value);\n }\n }\n};\n\n/** The picture a node shows: its image, or its video's thumbnail. */\nexport const nodeThumbnail = (node: OrbitNode): string | undefined => {\n if (hasMediaSource(node.image)) {\n return node.image.src;\n }\n\n if (hasMediaSource(node.video)) {\n if (node.video.thumbnail) {\n return node.video.thumbnail;\n }\n\n if (node.video.provider !== 'vimeo' && node.video.provider !== 'native') {\n return youtubeThumbnailUrl(node.video.src) ?? undefined;\n }\n }\n\n return undefined;\n};\n\n/** Inside the node, as a pill outside it, or not shown. */\nexport type LabelPlacement = 'inside' | 'outside' | 'hidden';\n\n/** The size (px) a node's name starts at inside it, before it shrinks to fit. */\nconst LABEL_FONT_SIZE: Record<NodeRole, number> = { sun: 16, planet: 13, node: 12, moon: 13 };\n/**\n * The smallest a name gets inside its node. Crowded orbits need small text\n * to keep names inside their nodes, the focused node's too, since its own\n * orbit shrinks it; a node too small even for this shows no name until you\n * zoom in (the focused node always shows its name). An overview node's name\n * has its pill to go to, so it stays closer to the pills' size.\n */\nconst MINIMUM_FONT_SIZE: Record<NodeRole, number> = { sun: 9, planet: 9, node: 10, moon: 9 };\n/** The most lines a name wraps to inside its node. */\nconst LABEL_LINES: Record<NodeRole, number> = { sun: 4, planet: 3, node: 3, moon: 2 };\n/** Height of a line of label text, and of the icon above it, in ems (as the stylesheet sets them). */\nconst LINE_HEIGHT = 1.22;\nconst ICON_HEIGHT = 1.45;\n/** Pixels between the icon and the text. */\nconst ICON_GAP = 2;\n/** A name cut short still shows this many characters, or none: a few letters don't say what a node is. */\nconst SHORTEST_CUT = 8;\n\n/** The width (px) of a label typed into a node of this on-screen radius. Snapped to 6 px steps so zooming doesn't re-wrap text every frame. */\nexport const insideLabelWidth = (role: NodeRole, screenRadius: number): number => {\n return Math.max(44, Math.min(260, Math.round((screenRadius * (role === 'sun' ? 1.6 : 1.68)) / 6) * 6));\n};\n\n/** A piece of a name a line can't break inside, its width in ems, and whether a space comes before it. */\ninterface MeasuredUnit {\n text: string;\n ems: number;\n spaced: boolean;\n}\n\n/** A name measured at one font size. */\ninterface SizedText {\n units: MeasuredUnit[];\n\n /** Width (em) of the longest run a line can't break inside: a word piece, or a single wide character. */\n longestUnbreakable: number;\n\n /** Width (em) of the whole text on one line. */\n total: number;\n\n /** A space between words, an ellipsis and a hyphen, in ems. */\n space: number;\n\n ellipsis: number;\n hyphen: number;\n}\n\n/**\n * The size (px) a name is measured at for text of `fontSize`: text shrunk\n * below 12 px at 9 px, and the rest at 12 px. Fonts with optical sizes draw\n * small text a few percent wider, so measuring at the smallest size of each\n * kind never measures a name narrower than it's drawn.\n */\nconst measuredSize = (fontSize: number): number => {\n return fontSize < 12 ? 9 : 12;\n};\n\n/** A name's pieces, measured at the sizes it's fitted at (see `measuredSize`). */\nclass TextMetrics {\n readonly measure: TextMeasure;\n private readonly pieces: TextUnit[];\n private readonly sizes = new Map<number, SizedText>();\n\n constructor(text: string, measure: TextMeasure) {\n this.measure = measure;\n this.pieces = breakUnits(text);\n }\n\n at(fontSize: number): SizedText {\n const size = this.measure.bySize ? measuredSize(fontSize) : 0;\n let sized = this.sizes.get(size);\n\n if (!sized) {\n const { measure } = this;\n const units = this.pieces.map((unit) => ({ text: unit.text, ems: measure.ems(unit.text, size), spaced: unit.spaced }));\n const space = measure.space(size);\n sized = {\n units,\n longestUnbreakable: units.reduce((longest, unit) => Math.max(longest, unit.ems), 0),\n total: units.reduce((sum, unit, index) => sum + unit.ems + (index > 0 && unit.spaced ? space : 0), 0),\n space,\n ellipsis: measure.ellipsis(size),\n hyphen: measure.ems('-', size),\n };\n this.sizes.set(size, sized);\n }\n\n return sized;\n }\n\n /** Width (em) of one character in text of `fontSize`, for cutting a name between characters. */\n character(character: string, fontSize: number): number {\n return this.measure.ems(character, this.measure.bySize ? measuredSize(fontSize) : 0);\n }\n}\n\n/**\n * Metrics by font and text. Every label's fit is worked out each frame while\n * the map moves, but the text rarely changes and measuring it walks every\n * character.\n */\nconst textMetricsCache = new Map<string, TextMetrics>();\n/** More texts than the largest maps have; past it, the measurements start over. */\nconst TEXT_METRICS_LIMIT = 20000;\n\nconst textMetrics = (text: string, measure: TextMeasure): TextMetrics => {\n const key = `${measure.key}\\n${text}`;\n const cached = textMetricsCache.get(key);\n\n if (cached) {\n return cached;\n }\n\n if (textMetricsCache.size >= TEXT_METRICS_LIMIT) {\n textMetricsCache.clear();\n }\n\n const metrics = new TextMetrics(text, measure);\n textMetricsCache.set(key, metrics);\n return metrics;\n};\n\n/**\n * The font size (px) of text typed into a node: the role's size, reduced\n * (down to its minimum) until the longest word fits on one line.\n */\nexport const insideFontSize = (role: NodeRole, width: number, text: string, measure: TextMeasure = INSIDE_ESTIMATE): number => {\n const longest = textMetrics(text, measure).at(LABEL_FONT_SIZE[role]).longestUnbreakable;\n const fitting = longest > 0 ? width / longest : LABEL_FONT_SIZE[role];\n return Math.max(MINIMUM_FONT_SIZE[role], Math.min(LABEL_FONT_SIZE[role], Math.floor(fitting * 2) / 2));\n};\n\nexport interface InsideLabelLayout {\n /** Width of the text block (px): its widest line's room. */\n width: number;\n\n fontSize: number;\n\n /** The name as it shows, line by line; the last ends with an ellipsis when the name is cut short. */\n lines: string[];\n\n /** Whether the node's icon shows above its name. */\n icon: boolean;\n\n /** The name doesn't fit whole. */\n truncated: boolean;\n\n /** A narrower width of the font the name is drawn in, as `font-stretch` (a percentage), when it needs one to fit. */\n stretch?: number;\n\n /** How far above the node's center (px) the lines and icon are centered: they rise to clear the node's \"+N\". */\n lift: number;\n}\n\n/** Joins units onto one line, with their spaces. */\nconst lineText = (units: MeasuredUnit[]): string => {\n return units.map((unit, index) => (index > 0 && unit.spaced ? ` ${unit.text}` : unit.text)).join('');\n};\n\n/** How wide (em) units are on one line, with their spaces. */\nconst lineEms = (units: MeasuredUnit[], sized: SizedText): number => {\n return units.reduce((sum, unit, index) => sum + unit.ems + (index > 0 && unit.spaced ? sized.space : 0), 0);\n};\n\n/** Whether lines this wide (ems) fit the room each has (px), in text of `fontSize`. */\nconst fitRooms = (ems: number[], widths: number[], fontSize: number): boolean => {\n return ems.length <= widths.length && ems.every((width, index) => width * fontSize <= widths[index] + 1e-9);\n};\n\n/**\n * Units of text wrapped onto lines `widths` ems wide, the first unit that\n * doesn't fit starting the next line; null when they need more lines, or a\n * unit is wider than its line.\n */\nconst wrapUnits = (sized: SizedText, widths: number[]): MeasuredUnit[][] | null => {\n const lines: MeasuredUnit[][] = [];\n let line: MeasuredUnit[] = [];\n let used = 0;\n\n for (const unit of sized.units) {\n const space = used > 0 && unit.spaced ? sized.space : 0;\n\n if (used > 0 && used + space + unit.ems > widths[lines.length]) {\n lines.push(line);\n\n if (lines.length >= widths.length) {\n return null;\n }\n\n line = [];\n used = 0;\n }\n\n if (unit.ems > widths[lines.length]) {\n return null;\n }\n\n used += (used > 0 && unit.spaced ? sized.space : 0) + unit.ems;\n line.push(unit);\n }\n\n lines.push(line);\n return lines;\n};\n\n/**\n * The same units on as many lines, broken where every line fills as little\n * of its room as can be (a circle's lines are widest in the middle), so a\n * name's shape follows its node's instead of crowding the first line:\n * \"Lanzamiento / en México\" rather than \"Lanzamiento en / México\".\n */\nconst balanceLines = (lines: MeasuredUnit[][], sized: SizedText, widths: number[]): MeasuredUnit[][] => {\n const count = lines.length;\n\n if (count < 2) {\n return lines;\n }\n\n const units = count === 2 ? [...lines[0], ...lines[1]] : lines.flat();\n const total = units.length;\n\n if (total <= count) {\n return lines;\n }\n\n // Ems before each unit, and the spaces before each unit (a line drops the one before its first unit).\n const ems = new Float64Array(total + 1);\n const spaces = new Float64Array(total + 1);\n\n for (let index = 0; index < total; index += 1) {\n ems[index + 1] = ems[index] + units[index].ems;\n spaces[index + 1] = spaces[index] + (units[index].spaced ? sized.space : 0);\n }\n\n const fill = (start: number, end: number, line: number) => (ems[end] - ems[start] + spaces[end] - spaces[start + 1]) / widths[line];\n const splits = count === 4 ? fourLineSplits(total, fill) : fewLineSplits(count, total, fill);\n\n if (!splits) {\n return lines;\n }\n\n const balanced: MeasuredUnit[][] = [];\n let start = 0;\n\n for (const end of [...splits, total]) {\n balanced.push(units.slice(start, end));\n start = end;\n }\n\n return balanced;\n};\n\n/** Where two or three lines break (the units each starts at, after the first) so the fullest is as empty as can be; null when none fits. */\nconst fewLineSplits = (count: number, total: number, fill: (start: number, end: number, line: number) => number): number[] | null => {\n let best = Infinity;\n let splits: number[] | null = null;\n\n if (count === 2) {\n for (let first = 1; first < total; first += 1) {\n const worst = Math.max(fill(0, first, 0), fill(first, total, 1));\n\n if (worst <= 1 && worst < best - 1e-9) {\n best = worst;\n splits = [first];\n }\n }\n\n return splits;\n }\n\n for (let first = 1; first < total - 1; first += 1) {\n const top = fill(0, first, 0);\n\n if (top > 1) {\n break;\n }\n\n for (let second = first + 1; second < total; second += 1) {\n const worst = Math.max(top, fill(first, second, 1), fill(second, total, 2));\n\n if (worst <= 1 && worst < best - 1e-9) {\n best = worst;\n splits = [first, second];\n }\n }\n }\n\n return splits;\n};\n\n/** As `fewLineSplits`, for four lines (a sun's longest names): the least fullest line, line by line. */\nconst fourLineSplits = (total: number, fill: (start: number, end: number, line: number) => number): number[] | null => {\n // fills[line][end]: the least fullest line for units before `end` on lines up to `line`; starts: where that last line starts.\n const fills = Array.from({ length: 4 }, () => new Float64Array(total + 1).fill(Infinity));\n const starts = Array.from({ length: 4 }, () => new Int32Array(total + 1));\n\n for (let end = 1; end <= total; end += 1) {\n const first = fill(0, end, 0);\n fills[0][end] = first <= 1 ? first : Infinity;\n }\n\n for (let line = 1; line < 4; line += 1) {\n for (let end = line + 1; end <= total; end += 1) {\n for (let start = line; start < end; start += 1) {\n const before = fills[line - 1][start];\n const own = fill(start, end, line);\n const worst = Math.max(before, own);\n\n if (own <= 1 && worst < fills[line][end] - 1e-9) {\n fills[line][end] = worst;\n starts[line][end] = start;\n }\n }\n }\n }\n\n if (fills[3][total] === Infinity) {\n return null;\n }\n\n const splits: number[] = [];\n let end = total;\n\n for (let line = 3; line > 0; line -= 1) {\n end = starts[line][end];\n splits.unshift(end);\n }\n\n return splits;\n};\n\n/** A name cut to fit its lines: the lines, how wide each is (ems), how many characters show, and whether any don't. */\ninterface CutText {\n lines: string[];\n widths: number[];\n shown: number;\n truncated: boolean;\n}\n\n/**\n * As much of the text as `widths` hold, word pieces kept whole, the last line\n * ending with an ellipsis when text was cut (cut between characters if need\n * be), and how many characters show. Null when a line can't hold even its\n * first piece.\n */\nconst cutUnits = (metrics: TextMetrics, fontSize: number, widths: number[]): CutText | null => {\n const sized = metrics.at(fontSize);\n const total = sized.units.reduce((sum, unit) => sum + unit.text.length, 0);\n const lines: string[] = [];\n const usedEms: number[] = [];\n const last = widths.length - 1;\n const widest = Math.max(...widths);\n const room = () => widths[lines.length] - (lines.length === last ? sized.ellipsis : 0);\n let line = '';\n let used = 0;\n let shown = 0;\n\n for (let unit of sized.units) {\n let space = used > 0 && unit.spaced ? sized.space : 0;\n\n if (used + space + unit.ems > room() && lines.length < last) {\n if (used > 0) {\n lines.push(line);\n usedEms.push(used);\n line = '';\n used = 0;\n space = 0;\n }\n\n // A long word wider than any line breaks with a hyphen; anything else waits for a wider line.\n if (unit.ems > room() && unit.ems <= widest) {\n return null;\n }\n\n while (unit.ems > room() && lines.length < last) {\n const split = hyphenate(unit, room(), metrics, fontSize);\n\n if (!split) {\n return null;\n }\n\n lines.push(split.head);\n usedEms.push(split.headEms);\n shown += split.head.length - 1;\n unit = split.rest;\n }\n }\n\n if (used + space + unit.ems <= room()) {\n line += space > 0 ? ` ${unit.text}` : unit.text;\n used += space + unit.ems;\n shown += unit.text.length;\n continue;\n }\n\n // The last line is full: as much of this piece as fits before the ellipsis.\n for (const character of graphemes(unit.text)) {\n const width = metrics.character(character, fontSize);\n\n if (used + space + width > room()) {\n break;\n }\n\n line += space > 0 ? ` ${character}` : character;\n used += space + width;\n space = 0;\n shown += character.length;\n }\n\n break;\n }\n\n // A long word hyphenated across lines can leave everything fitting after all: nothing cut, no ellipsis.\n const truncated = shown < total;\n lines.push(truncated ? `${line.trimEnd()}…` : line.trimEnd());\n usedEms.push(used + (truncated ? sized.ellipsis : 0));\n return { lines, widths: usedEms, shown, truncated };\n};\n\n/** Words this long or longer may break with a hyphen when a name is cut short anyway. */\nconst HYPHENATED_WORD = /^\\p{L}{8,}$/u;\n\n/** A long word's head (with a hyphen) that fits in `room` ems, how wide it is (ems), and the rest of the word; null for anything else. */\nconst hyphenate = (unit: MeasuredUnit, room: number, metrics: TextMetrics, fontSize: number): { head: string; headEms: number; rest: MeasuredUnit } | null => {\n if (!HYPHENATED_WORD.test(unit.text)) {\n return null;\n }\n\n const characters = graphemes(unit.text);\n let head = '';\n let used = metrics.at(fontSize).hyphen;\n let count = 0;\n let headEms = 0;\n\n for (const character of characters) {\n const width = metrics.character(character, fontSize);\n\n if (used + width > room) {\n break;\n }\n\n head += character;\n used += width;\n headEms += width;\n count += 1;\n }\n\n // At least three letters on each side of the hyphen.\n if (count < 3 || characters.length - count < 3) {\n return null;\n }\n\n const rest = characters.slice(count).join('');\n // What's left of the word is as wide as the word less its head (give or take kerning).\n return { head: `${head}-`, headEms: used, rest: { text: rest, ems: Math.max(0, unit.ems - headEms), spaced: false } };\n};\n\n/** The width (px) of a circle of radius `room` at height `y` from its center. */\nconst chordAt = (room: number, y: number): number => {\n return Math.abs(y) >= room ? 0 : 2 * Math.sqrt(room * room - y * y);\n};\n\n/**\n * The \"+N\" of a node with children that aren't drawn (the renderer's\n * `paintCounts`) is centered this share of the node's radius right of and\n * below the node's center.\n */\nexport const COUNT_POSITION = 0.74;\n/** A \"+N\" is this tall (px): its line and padding, as the stylesheet sets them. */\nexport const COUNT_HEIGHT = 15;\n/** A \"+N\"'s text size (px), and its padding on each side (px), as the stylesheet sets them. */\nconst COUNT_FONT_SIZE = 10.5;\nconst COUNT_PADDING = 6;\n/** Pixels a name inside a node keeps from the node's \"+N\". */\nconst COUNT_GAP = 1.5;\n/** The space under a line's letters (ems), which may pass over a \"+N\": the tails of g, p and y end this far above the line's bottom. */\nconst UNDER_TAILS = 0.15;\n\n/** Whether a node of this role and on-screen radius shows a \"+N\" for children that aren't drawn (flights and faded nodes hide it for a while). */\nexport const showsCount = (role: NodeRole, screenRadius: number, hiddenChildren: number): boolean => {\n return hiddenChildren > 0 && role !== 'moon' && screenRadius >= 10;\n};\n\n/** \"+N\" widths (px) by font, then by how many figures the count has: its figures are all as wide (tabular). */\nconst countWidths = new Map<TextMeasure, number[]>();\n\n/** How wide (px) a node's \"+N\" is for `hiddenChildren` children, in `measure` (the font it's drawn in). */\nexport const measureCount = (hiddenChildren: number, measure: TextMeasure = COUNT_ESTIMATE): number => {\n let figures = 1;\n\n for (let rest = hiddenChildren; rest >= 10; rest = Math.floor(rest / 10)) {\n figures += 1;\n }\n\n let widths = countWidths.get(measure);\n\n if (!widths) {\n widths = [];\n countWidths.set(measure, widths);\n }\n\n let width = widths[figures];\n\n if (width === undefined) {\n // Tabular figures are as wide as each other: a canvas, which draws the font's own figures, measures zeros.\n width = 2 * COUNT_PADDING + measure.ems(`+${'0'.repeat(figures)}`, COUNT_FONT_SIZE) * COUNT_FONT_SIZE;\n widths[figures] = width;\n }\n\n return width;\n};\n\n/** A node's \"+N\" as the name inside it keeps clear of it, from the node's center (px): lines reaching below `top` end left of `left`. */\ninterface CountBox {\n top: number;\n left: number;\n}\n\n/**\n * Where a node of this radius shows its \"+N\", `width` px wide, gap included;\n * null when it shows none. Fits round the radius down, so the count is\n * never nearer the center than this.\n */\nconst countBox = (radius: number, width: number): CountBox | null => {\n return width > 0 ? { top: COUNT_POSITION * radius - COUNT_HEIGHT / 2 - COUNT_GAP, left: COUNT_POSITION * radius - width / 2 - COUNT_GAP } : null;\n};\n\n/** The room for each line of a name (px), and how far above the node's center (px) its lines and icon are centered. */\ninterface LineRoom {\n widths: number[];\n lift: number;\n}\n\n/**\n * Room for each of `count` lines of `fontSize` px text centered in a circle of\n * radius `room`, under an icon when `icon` (null when the icon itself doesn't\n * fit). Each line gets the circle's width at its middle. Beside a \"+N\"\n * (`badge`), the lines and icon rise, as far as the circle allows, until the\n * last line's letters clear it, and a line still beside it ends short of it:\n * lines are centered, so they end as far from the center on the left too.\n */\nconst lineWidths = (room: number, fontSize: number, count: number, icon: boolean, badge: CountBox | null = null): LineRoom | null => {\n const lineHeight = fontSize * LINE_HEIGHT;\n const iconHeight = icon ? fontSize * ICON_HEIGHT + ICON_GAP : 0;\n const height = iconHeight + count * lineHeight;\n\n if (height > room * 2) {\n return null;\n }\n\n // How low the bottom of a line may sit: the space under its letters may pass over the \"+N\".\n const lowest = badge ? badge.top + fontSize * UNDER_TAILS : Infinity;\n const lift = badge ? Math.min(Math.max(0, height / 2 - lowest), room - height / 2) : 0;\n const top = -height / 2 - lift;\n\n if (icon && chordAt(room, top + (fontSize * ICON_HEIGHT) / 2) < fontSize * ICON_HEIGHT) {\n return null;\n }\n\n const widths: number[] = [];\n\n for (let index = 0; index < count; index += 1) {\n const lineTop = top + iconHeight + index * lineHeight;\n const width = chordAt(room, lineTop + lineHeight / 2);\n widths.push(badge && lineTop + lineHeight > lowest + 1e-9 ? Math.min(width, 2 * Math.max(0, badge.left)) : width);\n }\n\n return { widths, lift };\n};\n\n/** How far below its node's center (px) a name laid out inside it reaches: its lines and icon are centered `lift` above it. */\nexport const insideLabelReach = (layout: InsideLabelLayout): number => {\n const iconHeight = layout.icon ? layout.fontSize * ICON_HEIGHT + ICON_GAP : 0;\n return (iconHeight + layout.lines.length * layout.fontSize * LINE_HEIGHT) / 2 - layout.lift;\n};\n\n/**\n * A name's fit at one size, in its font's own width, and once tried (when\n * the map is still), the narrower one it may need.\n */\ninterface InsideFits {\n own: InsideLabelLayout | null;\n narrower?: InsideLabelLayout | null;\n}\n\n/** Fitted labels by font, then role, size and text: labels are fitted on every frame while the map moves. */\nconst insideLayouts = new Map<TextMeasure, Map<string, InsideFits>>();\nconst INSIDE_LAYOUTS_LIMIT = 20000;\n\n// Fits made from measurements start over with them (a font finished loading).\nonMeasurementsReset(() => {\n textMetricsCache.clear();\n insideLayouts.clear();\n countWidths.clear();\n});\n\n/**\n * How a node's name fits inside it at this on-screen radius, or null when it\n * doesn't. The name shrinks (down to the role's minimum) and wraps (at\n * spaces, and inside long words where they read), its lines balanced and\n * each as wide as the circle is where it sits. The icon above it stays while\n * the name only shrinks a little. A name too long to fit whole even then\n * shows as much as fits, ending with an ellipsis, as long as that's enough\n * to read. `measure` measures the text in the font it's drawn with (by\n * default, widths are estimated).\n *\n * A name that doesn't fit at its font's width tries narrower ones (see\n * `fitInside`) only when `narrower` allows, as it does while the map is\n * still: while the map moves, trying hundreds of names in each width would\n * make frames late. A fit already made with them is kept, though.\n *\n * A node showing a \"+N\" `countWidth` px wide (see `measureCount`) keeps its\n * name clear of it: the name rises above it, or gets smaller.\n */\nexport const insideLabelLayout = (role: NodeRole, screenRadius: number, text: string, hasIcon = false, measure: TextMeasure = INSIDE_ESTIMATE, narrower = true, countWidth = 0): InsideLabelLayout | null => {\n // In steps of about 6% (2 px at least), so a zoom or a flight doesn't fit and write the text again on every frame.\n const step = Math.max(2, Math.round(screenRadius * 0.06));\n const radius = Math.floor(screenRadius / step) * step;\n\n // Most of a crowded orbit has no room for any name: no need to look each one up on every frame it moves.\n if (insideRoom(radius) < SMALLEST_INSIDE_ROOM) {\n return null;\n }\n\n let inFont = insideLayouts.get(measure);\n\n if (!inFont) {\n inFont = new Map();\n insideLayouts.set(measure, inFont);\n }\n\n const key = `${role}|${radius}|${hasIcon ? 1 : 0}|${countWidth}|${text}`;\n let fits = inFont.get(key);\n\n if (fits === undefined) {\n if (inFont.size >= INSIDE_LAYOUTS_LIMIT) {\n inFont.clear();\n }\n\n const own = fitInFont(role, radius, text, hasIcon, measure, countWidth);\n // A name that shows whole in its font's own width needs nothing narrower.\n fits = own !== null && !own.truncated ? { own, narrower: own } : { own };\n inFont.set(key, fits);\n }\n\n if (fits.narrower !== undefined) {\n return fits.narrower;\n }\n\n if (!narrower) {\n return fits.own;\n }\n\n fits.narrower = fitNarrower(role, radius, text, hasIcon, measure, countWidth) ?? fits.own;\n return fits.narrower;\n};\n\n/** How far below its usual size a name shrinks before its node's icon makes way (px). */\nconst ICON_SHRINK = 3;\n\n/** The radius (px) a name has inside a node of this on-screen radius: text keeps a little off the rim. */\nconst insideRoom = (radius: number): number => {\n return radius - Math.max(2, radius * 0.05);\n};\n\n/** Below this room (px), no name fits inside. */\nconst SMALLEST_INSIDE_ROOM = 6;\n\n/**\n * Only in nodes with at least this much room (px): a crowded orbit's small\n * planets can't show a name whole in any width, and trying each one at\n * every step of a zoom would slow the zoom down.\n */\nconst NARROWER_ROOM = 16;\n\n/**\n * A name that's cut short or has no room in its font's own width, fitted\n * in a narrower width of it (a font with a width axis draws semi-condensed,\n * then condensed), when that shows it whole; null when none does.\n */\nconst fitNarrower = (role: NodeRole, radius: number, text: string, hasIcon: boolean, measure: TextMeasure, countWidth: number): InsideLabelLayout | null => {\n const narrower = insideRoom(radius) >= NARROWER_ROOM ? measure.narrower() : null;\n\n if (!narrower || !mightFitWhole(role, radius, text, narrower.narrower() ?? narrower)) {\n return null;\n }\n\n for (let width: TextMeasure | null = narrower; width; width = width.narrower()) {\n const attempt = fitInFont(role, radius, text, hasIcon, width, countWidth);\n\n if (attempt && !attempt.truncated) {\n return { ...attempt, stretch: width.stretch };\n }\n }\n\n return null;\n};\n\n/**\n * Whether a name could fit whole in this node in `measure`, at the role's\n * smallest size: its longest piece across the circle, and all of it in the\n * circle's area. Most names in a crowded orbit can't, at any width.\n */\nconst mightFitWhole = (role: NodeRole, radius: number, text: string, measure: TextMeasure): boolean => {\n const smallest = MINIMUM_FONT_SIZE[role];\n const sized = textMetrics(text, measure).at(smallest);\n const room = insideRoom(radius);\n const breakable = Math.max(sized.total - sized.space * LABEL_LINES[role], 0.01);\n return sized.longestUnbreakable * smallest <= 2 * room && smallest <= room * Math.sqrt((1.25 * Math.PI) / (LINE_HEIGHT * breakable));\n};\n\nconst fitInFont = (role: NodeRole, radius: number, text: string, hasIcon: boolean, measure: TextMeasure, countWidth: number): InsideLabelLayout | null => {\n const room = insideRoom(radius);\n const badge = countBox(radius, countWidth);\n\n if (room < SMALLEST_INSIDE_ROOM) {\n return null;\n }\n\n const metrics = textMetrics(text, measure);\n const largest = LABEL_FONT_SIZE[role];\n const smallest = MINIMUM_FONT_SIZE[role];\n // No size above these fits: the longest piece must fit the circle's width, and the text (less the\n // spaces lines break at) its area, with room to spare, since lines are as wide as the circle at their middle.\n const breakableAt = (sized: SizedText) => Math.max(sized.total - sized.space * LABEL_LINES[role], 0.01);\n const widest = metrics.at(largest);\n const fitting = Math.min(largest, (2 * room) / Math.max(widest.longestUnbreakable, 0.01), room * Math.sqrt((1.25 * Math.PI) / (LINE_HEIGHT * breakableAt(widest))));\n const start = Math.floor(fitting * 2) / 2;\n const attempts: [boolean, number][] = [];\n\n if (hasIcon) {\n for (let fontSize = start; fontSize >= Math.max(smallest, largest - ICON_SHRINK); fontSize -= 0.5) {\n attempts.push([true, fontSize]);\n }\n }\n\n for (let fontSize = start; fontSize >= smallest; fontSize -= 0.5) {\n attempts.push([false, fontSize]);\n }\n\n for (const [icon, fontSize] of attempts) {\n const sized = metrics.at(fontSize);\n const breakable = breakableAt(sized);\n\n // No fewer lines than the text's width (less the spaces lines break at) over the circle's.\n for (let count = Math.max(1, Math.ceil((breakable * fontSize) / (2 * room))); count <= LABEL_LINES[role]; count += 1) {\n const tried = lineWidths(room, fontSize, count, icon, badge);\n\n if (!tried) {\n break;\n }\n\n const wrapped = wrapUnits(sized, tried.widths.map((width) => width / fontSize));\n\n if (!wrapped) {\n continue;\n }\n\n // Balanced over the lines it takes, each as wide as the circle where those lines sit. Fewer lines than\n // tried sit elsewhere, where the circle may be narrower or the \"+N\" nearer: they show only if they fit there.\n const shown = wrapped.length === count ? tried : lineWidths(room, fontSize, wrapped.length, icon, badge);\n\n if (!shown) {\n continue;\n }\n\n const lines = balanceLines(wrapped, sized, shown.widths.map((width) => width / fontSize));\n\n if (!fitRooms(lines.map((units) => lineEms(units, sized)), shown.widths, fontSize)) {\n continue;\n }\n\n return { width: Math.floor(Math.max(...shown.widths.slice(0, lines.length))), fontSize, lines: lines.map(lineText), icon, truncated: false, lift: shown.lift };\n }\n }\n\n // An overview node's name that doesn't fit whole reads better whole, on its pill.\n if (role === 'node') {\n return null;\n }\n\n // Too long to fit whole: as many lines of the smallest text as show the most of it.\n let best: InsideLabelLayout | null = null;\n let mostShown = 0;\n\n for (let count = 1; count <= LABEL_LINES[role]; count += 1) {\n const tried = lineWidths(room, smallest, count, false, badge);\n\n if (!tried) {\n break;\n }\n\n const cut = cutUnits(metrics, smallest, tried.widths.map((width) => width / smallest));\n\n if (!cut || cut.shown <= mostShown) {\n continue;\n }\n\n // A word hyphenated across lines can leave fewer lines than tried, drawn elsewhere: shown only if they fit there.\n const shown = cut.lines.length === count ? tried : lineWidths(room, smallest, cut.lines.length, false, badge);\n\n if (!shown || !fitRooms(cut.widths, shown.widths, smallest)) {\n continue;\n }\n\n mostShown = cut.shown;\n best = { width: Math.floor(Math.max(...shown.widths)), fontSize: smallest, lines: cut.lines, icon: false, truncated: cut.truncated, lift: shown.lift };\n }\n\n return role === 'sun' || mostShown >= SHORTEST_CUT ? best : null;\n};\n\n/**\n * Where a node's label goes at this on-screen size. A name goes inside its\n * node whenever it fits there (see `insideLabelLayout`). A pill beside the\n * node is for the nodes that need one: nodes showing a picture, the focused\n * node when its name doesn't fit inside, and overview nodes too small for\n * their names. Any other node too small for its name shows none until you\n * zoom in. A name inside a node keeps clear of its \"+N\", `countWidth` px wide.\n */\nexport const labelPlacement = (role: NodeRole, screenRadius: number, text: string, hasImage: boolean, hasIcon = false, measure: TextMeasure = INSIDE_ESTIMATE, narrower = true, countWidth = 0): LabelPlacement => {\n if (!hasImage && insideLabelLayout(role, screenRadius, text, hasIcon, measure, narrower, countWidth)) {\n return 'inside';\n }\n\n if (role === 'sun') {\n return 'outside';\n }\n\n if (hasImage || role === 'node') {\n return screenRadius >= (role === 'moon' ? 11 : 4) ? 'outside' : 'hidden';\n }\n\n return 'hidden';\n};\n\n/** Fills `element` with `text`, marking where long words may break (`wordPieces`), as fitting the label assumes. */\nconst setBreakableText = (element: HTMLElement, text: string): void => {\n element.textContent = '';\n\n for (const part of text.split(/(\\s+)/)) {\n if (!part) {\n continue;\n }\n\n if (/^\\s+$/.test(part)) {\n element.append(part);\n continue;\n }\n\n wordPieces(part).forEach((piece, index) => {\n if (index > 0) {\n element.append(document.createElement('wbr'));\n }\n\n element.append(piece);\n });\n }\n};\n\n/** How a node's label is drawn on a frame (see `NodeLabel.update`). */\nexport interface LabelDrawing {\n /** The node's center on screen (px). */\n x: number;\n\n y: number;\n\n /** The node's radius on screen (px). */\n screenRadius: number;\n\n role: NodeRole;\n placement: LabelPlacement;\n opacity: number;\n\n /** Whether a name inside its node takes the theme's light text. */\n light?: boolean;\n\n /** The font a name inside its node is fitted in, as its placement was (default: estimated widths). */\n measure?: TextMeasure;\n\n /** Whether a name inside its node may try narrower widths of its font, as it does while the map is still (default: true). */\n narrower?: boolean;\n\n /** The width (px) of the node's \"+N\", which a name inside it keeps clear of (default: 0, when it shows none). */\n countWidth?: number;\n\n /** The side of its node a pill touches, a unit vector (default: below). */\n direction?: { x: number; y: number };\n\n /** How far from the node's center a pill sits (px; see `pillDistance` in `labels.ts`; default: 5 px past its edge). */\n distance?: number;\n\n /** Pixels a pill above or below its node slid sideways to stay on the map. */\n offset?: number;\n\n /** A pill's lines, and the width (px) it wraps at on two. */\n lines?: 1 | 2;\n\n width?: number;\n\n /** What a pill says (default: the node's name). */\n pillText?: string;\n}\n\n/** Where a pill goes when nothing says: below its node. */\nconst BELOW = { x: 0, y: 1 };\n\nexport class NodeLabel {\n readonly element: HTMLDivElement;\n readonly node: OrbitNode;\n\n /** The type the node was drawn as, as for its view. */\n readonly typeName: string | undefined;\n\n private readonly text: HTMLSpanElement;\n\n /** Whether the node has an icon, shown above its name when there's room. */\n private readonly hasIcon: boolean;\n\n /** The side an outside label sat on last (a unit vector), or null. */\n direction: { x: number; y: number } | null = null;\n\n private placement: LabelPlacement | null = null;\n private role: NodeRole | null = null;\n private fontSize = 0;\n\n /** The `font-stretch` written for a name drawn narrower to fit (0: the font's own width). */\n private stretch = 0;\n\n /** The lines written into the label inside its node, or null while it holds the whole name (pills wrap it themselves). */\n private shownLines: string | null = null;\n\n /** What the label's pill says, while it's a pill. */\n private pillText: string | null = null;\n\n private iconHidden = false;\n private light: boolean | null = null;\n\n /** An outside pill on two lines, and the width it wraps at. */\n private wrapped = false;\n\n private pillWidth = 0;\n\n /** What was last written, so a label that didn't move isn't touched: the map repaints every frame while it moves. */\n private shown = true;\n\n private transform = '';\n private opacity = '';\n\n constructor(node: OrbitNode, extensions: MapExtensions) {\n this.node = node;\n this.element = document.createElement('div');\n this.element.className = 'orbit-label';\n this.element.setAttribute('aria-hidden', 'true');\n this.element.dataset.orbitFor = node.id;\n this.typeName = extensions.typeName(node);\n markNode(this.element, node, this.typeName);\n applyTypeTokens(this.element, extensions.nodeType(node));\n const iconText = extensions.icon(node);\n this.hasIcon = Boolean(iconText);\n\n if (iconText) {\n const icon = document.createElement('span');\n icon.className = 'orbit-label__icon';\n icon.textContent = iconText;\n this.element.appendChild(icon);\n }\n\n this.text = document.createElement('span');\n this.text.className = 'orbit-label__text';\n setBreakableText(this.text, node.text);\n this.element.appendChild(this.text);\n }\n\n get currentPlacement(): LabelPlacement {\n return this.placement ?? 'hidden';\n }\n\n /** Whether the label shows: placed somewhere and not hidden. */\n get isShown(): boolean {\n return this.shown && this.placement !== null && this.placement !== 'hidden';\n }\n\n /** Draws the label as `drawing` says: inside its node, fitted as its placement was, or as a pill beside it. */\n update(drawing: LabelDrawing): void {\n const { x, y, screenRadius, role, placement, opacity } = drawing;\n\n if (placement !== this.placement || role !== this.role) {\n this.element.className = `orbit-label orbit-label--${role}${placement === 'outside' ? ' orbit-label--outside' : ''}`;\n this.placement = placement;\n this.role = role;\n this.light = null;\n this.wrapped = false;\n }\n\n const shown = placement !== 'hidden' && opacity > 0.01;\n\n if (shown !== this.shown) {\n this.element.style.display = shown ? '' : 'none';\n this.shown = shown;\n }\n\n if (!shown) {\n return;\n }\n\n let transform: string;\n\n if (placement === 'inside') {\n const layout = insideLabelLayout(role, screenRadius, this.node.text, this.hasIcon, drawing.measure, drawing.narrower, drawing.countWidth) ?? {\n width: insideLabelWidth(role, screenRadius),\n fontSize: MINIMUM_FONT_SIZE[role],\n lines: [this.node.text],\n icon: false,\n truncated: true,\n lift: 0,\n };\n const light = drawing.light ?? false;\n\n if (light !== this.light) {\n this.element.classList.toggle('orbit-label--light', light);\n this.light = light;\n }\n\n if (layout.fontSize !== this.fontSize) {\n this.element.style.fontSize = `${layout.fontSize}px`;\n this.fontSize = layout.fontSize;\n }\n\n const stretch = layout.stretch ?? 0;\n\n if (stretch !== this.stretch) {\n this.element.style.fontStretch = stretch ? `${stretch}%` : '';\n this.stretch = stretch;\n }\n\n // The lines the fit chose, exactly: the browser doesn't wrap them again.\n const shownLines = layout.lines.join('\\n');\n\n if (shownLines !== this.shownLines) {\n this.text.textContent = shownLines;\n this.shownLines = shownLines;\n this.pillText = null;\n }\n\n const iconHidden = this.hasIcon && !layout.icon;\n\n if (iconHidden !== this.iconHidden) {\n this.element.classList.toggle('orbit-label--no-icon', iconHidden);\n this.iconHidden = iconHidden;\n }\n\n transform = `translate3d(${round(x, 1)}px, ${round(y - layout.lift, 1)}px, 0) translate(-50%, -50%)`;\n } else {\n const { direction = BELOW, distance = screenRadius + 5, offset = 0, lines = 1, width = 0, pillText = this.node.text } = drawing;\n\n if (this.fontSize !== 0) {\n this.element.style.fontSize = '';\n this.fontSize = 0;\n }\n\n if (this.stretch !== 0) {\n this.element.style.fontStretch = '';\n this.stretch = 0;\n }\n\n if (this.shownLines !== null || this.pillText !== pillText) {\n setBreakableText(this.text, pillText);\n this.shownLines = null;\n this.pillText = pillText;\n }\n\n const wrapped = lines === 2;\n\n if (wrapped !== this.wrapped) {\n this.element.classList.toggle('orbit-label--wrapped', wrapped);\n this.wrapped = wrapped;\n }\n\n // No wider than the box label planning kept on the map.\n if (wrapped && width !== this.pillWidth) {\n this.element.style.setProperty('--orbit-pill-width', `${Math.floor(width)}px`);\n this.pillWidth = width;\n }\n\n // The pill's point that matches its side sits `distance` from the node's center (see `pillDistance`).\n this.direction = direction;\n const shiftX = round(-50 + direction.x * 50, 1);\n const shiftY = round(-50 + direction.y * 50, 1);\n transform = `translate3d(${round(x + direction.x * distance + offset, 1)}px, ${round(y + direction.y * distance, 1)}px, 0) translate(${shiftX}%, ${shiftY}%)`;\n }\n\n if (transform !== this.transform) {\n this.element.style.transform = transform;\n this.transform = transform;\n }\n\n const opacityValue = opacity >= 0.999 ? '' : String(round(opacity, 3));\n\n if (opacityValue !== this.opacity) {\n this.element.style.opacity = opacityValue;\n this.opacity = opacityValue;\n }\n }\n}\n\n/** Dashed ring arcs between the bodies on a ring (centered on the origin). */\nexport const ringPath = (radius: number, gaps: DisplayRing['gaps']): string => {\n if (radius <= 0) {\n return '';\n }\n\n const openings = gaps\n .map((gap) => ({ start: normalizeAngle(gap.angle - gap.halfWidth), width: gap.halfWidth * 2 }))\n .filter((gap) => gap.width > 0)\n .sort((left, right) => left.start - right.start);\n\n if (openings.length === 0) {\n return `M ${round(radius)} 0 A ${round(radius)} ${round(radius)} 0 1 1 ${round(-radius)} 0 A ${round(radius)} ${round(radius)} 0 1 1 ${round(radius)} 0`;\n }\n\n const commands: string[] = [];\n\n for (let index = 0; index < openings.length; index += 1) {\n const current = openings[index];\n const next = openings[(index + 1) % openings.length];\n const arcStart = current.start + current.width;\n let arcEnd = next.start;\n\n if (index === openings.length - 1) {\n arcEnd += 360;\n }\n\n const sweep = arcEnd - arcStart;\n\n if (sweep <= 0.5) {\n continue;\n }\n\n const from = polar(radius, arcStart);\n const to = polar(radius, arcEnd);\n commands.push(`M ${round(from.x)} ${round(from.y)} A ${round(radius)} ${round(radius)} 0 ${sweep > 180 ? 1 : 0} 1 ${round(to.x)} ${round(to.y)}`);\n }\n\n return commands.join(' ');\n};\n\nconst polar = (radius: number, degrees: number): { x: number; y: number } => {\n const radians = (degrees * Math.PI) / 180;\n return { x: radius * Math.cos(radians), y: radius * Math.sin(radians) };\n};\n\nconst normalizeAngle = (degrees: number): number => {\n return ((degrees % 360) + 360) % 360;\n};\n\nconst round = (value: number, decimals = 2): number => {\n const factor = 10 ** decimals;\n return Math.round(value * factor) / factor;\n};\n",
|
|
38
39
|
"/**\n * Where every label goes, frame by frame: inside its node, on a chip, as a\n * pill beside the node, or nowhere. Pills try the sides of their node in\n * order of preference and take the first one that covers no other label,\n * no other node and doesn't run off the map. The browser renderer and the\n * SVG export both use this, so an export looks like the live map.\n */\n\nimport type { Viewport } from './camera.js';\nimport { worldToScreen } from './camera.js';\nimport type { Display, DisplayNode } from './display.js';\nimport { labelPlacement, measureCount, showsCount, type LabelPlacement } from './views.js';\nimport { breakUnits, joinUnits } from '../text-layout.js';\nimport { ESTIMATED_LABELS, INSIDE_ESTIMATE, PILL_ESTIMATE, onMeasurementsReset, type LabelMeasures, type TextMeasure } from './text-measure.js';\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface Box {\n left: number;\n right: number;\n top: number;\n bottom: number;\n}\n\nexport interface PlannedLabel {\n entry: DisplayNode;\n\n /** The node's center on screen. */\n x: number;\n\n y: number;\n screenRadius: number;\n placement: Exclude<LabelPlacement, 'hidden'>;\n\n /** Which side of the node an outside label sits on (a unit vector). */\n direction: Point;\n\n /** How far from the node's center a pill sits (px; see `pillDistance`). */\n distance: number;\n\n /** Pixels a pill above or below its node slid sideways to stay on the map. */\n offset: number;\n\n /** A pill's lines: two when one line fits nowhere. */\n lines: 1 | 2;\n\n /** A pill's estimated width. */\n width: number;\n\n opacity: number;\n\n /** What a pill says: the node's name, after its icon when `pillIcon` gives one. */\n text: string;\n\n /** The width (px) of the node's \"+N\", which a name inside it keeps clear of; 0 when it shows none. */\n countWidth: number;\n}\n\nexport interface LabelPlanOptions {\n viewport: Viewport;\n\n /** Whether the node shows a picture, which pushes its label outside. */\n hasImage(entry: DisplayNode): boolean;\n\n /** Whether the node has an icon to show above its name (the fit is the label's own, cached). */\n hasIcon?(entry: DisplayNode): boolean;\n\n /**\n * An icon to show on the node's pill, before its name: for a node whose\n * picture or content fills it, so the icon has no place inside.\n */\n pillIcon?(entry: DisplayNode): string | undefined;\n\n /** The side a label sat on last frame, so labels don't hop around while the map moves. */\n previousSide?(id: string): Point | null;\n\n /** While nodes fly between views, pills stay hidden; they'd flicker as nodes grow and shrink. */\n inFlight?: boolean;\n\n /** Measures names in the fonts the map draws them with; by default, widths are estimated. */\n measures?: LabelMeasures;\n\n /**\n * While the map moves, names that don't fit at their font's width don't\n * try narrower ones, and names not yet showing only start to when they'd\n * fit by the estimate too (`isShown` says which show): measured names fit\n * more often, and hundreds starting to show mid-zoom would make frames\n * late. Once the map is still (and by default), every name that fits shows.\n */\n moving?: boolean;\n\n /** Whether a node's label shows now. */\n isShown?(id: string): boolean;\n\n /** Whether nodes show a \"+N\" for children that aren't drawn, which names inside them keep clear of: the map does, an export doesn't. */\n counts?: boolean;\n}\n\nconst BELOW: Point = { x: 0, y: 1 };\nconst ABOVE: Point = { x: 0, y: -1 };\n/** Nodes this far outside the map get no label at all. */\nconst OFF_SCREEN_MARGIN = 120;\n/** A pill slid sideways still reaches this far past its node's center, so it reads as the node's. */\nconst NUDGE_REACH = 10;\n\nconst ROLE_PRIORITY = { sun: 0, planet: 1, node: 1, moon: 2 } as const;\n\n/** What covering a body with a pill costs: the sun's own label matters most. */\nconst COVER_COST = { sun: 4, planet: 1, node: 1, moon: 0.5 } as const;\n\n/** The order labels are placed in, so the important ones win when they would overlap. */\nexport const labelOrder = (nodes: Iterable<DisplayNode>): DisplayNode[] => {\n return Array.from(nodes).sort((left, right) => (\n ROLE_PRIORITY[left.role] - ROLE_PRIORITY[right.role] || left.depth - right.depth || right.radius - left.radius\n ));\n};\n\ninterface Disc extends Point {\n id: string;\n radius: number;\n cost: number;\n}\n\ninterface Spot {\n side: Point;\n offset: number;\n lines: 1 | 2;\n box: Box;\n}\n\n/** The labels to show this frame, in `order`. Nodes missing from the result show no label. */\nexport const planLabels = (display: Display, order: DisplayNode[], options: LabelPlanOptions): PlannedLabel[] => {\n const { camera } = display;\n const { viewport } = options;\n // Every body a pill keeps clear of, with how much covering it would cost\n // when a planet's pill has nowhere free to go. Bodies 2 px or smaller don't count.\n const discs = new ScreenGrid<Disc>(viewport);\n\n const addDisc = (id: string, center: Point, radius: number, cost: number) => {\n if (radius > 2) {\n discs.add({ id, x: center.x, y: center.y, radius, cost }, { left: center.x - radius, right: center.x + radius, top: center.y - radius, bottom: center.y + radius });\n }\n };\n\n for (const entry of display.nodes.values()) {\n if (entry.opacity > 0.3) {\n addDisc(entry.id, worldToScreen(camera, viewport, entry), entry.radius * camera.scale, COVER_COST[entry.role]);\n }\n }\n\n // Pills keep clear of the + in the orbit too.\n if (display.addSlot && display.addSlot.opacity > 0.3) {\n addDisc('', worldToScreen(camera, viewport, display.addSlot), display.addSlot.radius * camera.scale, 0.75);\n }\n\n const taken = new ScreenGrid<Box>(viewport);\n const measures = options.measures ?? ESTIMATED_LABELS;\n const countMeasure = options.counts ? measures.count() : null;\n const planned: PlannedLabel[] = [];\n\n for (const entry of order) {\n const point = worldToScreen(camera, viewport, entry);\n const screenRadius = entry.radius * camera.scale;\n const opacity = entry.opacity * entry.labelOpacity;\n\n if (opacity <= 0.01 || isOffScreen(point, screenRadius, viewport)) {\n continue;\n }\n\n const countWidth = countMeasure && showsCount(entry.role, screenRadius, entry.hiddenChildren) ? measureCount(entry.hiddenChildren, countMeasure) : 0;\n const placement = labelPlacement(entry.role, screenRadius, entry.node.text, options.hasImage(entry), options.hasIcon?.(entry), measures.inside(entry.role, entry.node), !options.moving, countWidth);\n\n if (placement === 'hidden' || (placement === 'outside' && options.inFlight)) {\n continue;\n }\n\n // While the map moves, a name starts to show only where the estimate would show it too, and during a\n // flight between views, only such names show at all; the rest wait for the map to be still.\n if (placement === 'inside' && options.moving && measures !== ESTIMATED_LABELS && (options.inFlight || !options.isShown?.(entry.id))\n && labelPlacement(entry.role, screenRadius, entry.node.text, false, options.hasIcon?.(entry), INSIDE_ESTIMATE, true, countWidth) !== 'inside') {\n continue;\n }\n\n let direction = BELOW;\n let fromCenter = 0;\n let offset = 0;\n let lines: 1 | 2 = 1;\n let width = 0;\n const icon = placement === 'outside' ? options.pillIcon?.(entry) : undefined;\n const text = icon ? `${icon} ${entry.node.text}`.trim() : entry.node.text;\n\n if (placement === 'outside') {\n const sides = labelSides(entry, display);\n const previous = options.previousSide?.(entry.id);\n\n if (previous) {\n sides.sort((left, right) => distance(left, previous) - distance(right, previous));\n }\n\n const maximumWidth = entry.role === 'sun' ? 280 : 160;\n const pill = measures.pill(entry.role, entry.node);\n\n const spotFor = (side: Point, lineCount: 1 | 2): Spot => {\n const box = outsideLabelBox(text, point, screenRadius, side, maximumWidth, 0, lineCount, pill);\n const nudge = side.x === 0 ? horizontalNudge(box, point.x, viewport) : 0;\n return { side, offset: nudge, lines: lineCount, box: nudge === 0 ? box : outsideLabelBox(text, point, screenRadius, side, maximumWidth, nudge, lineCount, pill) };\n };\n\n const coversNode = (box: Box) => discs.some(box, (disc) => disc.id !== entry.id && discOverlapsBox(disc, box));\n const coverCost = (box: Box) => discs.sum(box, (disc) => (disc.id !== entry.id && discOverlapsBox(disc, box) ? disc.cost : 0));\n const coversLabel = (box: Box) => taken.some(box, (other) => overlaps(box, other));\n const isFree = ({ box }: Spot) => insideViewport(box, viewport) && !coversLabel(box) && !coversNode(box);\n const spots = sides.map((side) => spotFor(side, 1));\n // A pill too wide for every side tries again on two lines, narrower.\n let wrapped: Spot[] | undefined;\n const wrappedSpots = () => (wrapped ??= canWrap(text, pill) ? sides.map((side) => spotFor(side, 2)) : []);\n let spot = spots.find(isFree) ?? wrappedSpots().find(isFree);\n\n if (!spot && entry.role === 'sun') {\n // The focused node always says what it is, even over its neighbors…\n spot = spots.find(({ box }) => insideViewport(box, viewport)) ?? spots[0];\n } else if (!spot && entry.role === 'planet') {\n // …and so does each planet: over as few nodes as it can, never over another label.\n let cheapest = Infinity;\n\n for (const candidate of [...spots, ...wrappedSpots()]) {\n if (insideViewport(candidate.box, viewport) && !coversLabel(candidate.box)) {\n const cost = coverCost(candidate.box);\n\n if (cost < cheapest) {\n spot = candidate;\n cheapest = cost;\n }\n }\n }\n }\n\n if (!spot) {\n continue;\n }\n\n direction = spot.side;\n offset = spot.offset;\n lines = spot.lines;\n width = spot.box.right - spot.box.left;\n fromCenter = pillDistance(screenRadius, direction, width, lines);\n taken.add(spot.box, spot.box);\n }\n\n planned.push({ entry, x: point.x, y: point.y, screenRadius, placement, direction, distance: fromCenter, offset, lines, width, opacity, text, countWidth });\n }\n\n return planned;\n};\n\n/**\n * The sides a node's pill may go, best first. Toward the parent is usually\n * free (a planet's moons and a branch's children sit on the far side); a\n * leaf in the overview has its far side free too. Moons look away from\n * their planet. Below and above are the fallbacks.\n */\nexport const labelSides = (entry: DisplayNode, display: Display): Point[] => {\n const parent = entry.parentId === undefined ? undefined : display.nodes.get(entry.parentId);\n const length = parent ? Math.hypot(parent.x - entry.x, parent.y - entry.y) : 0;\n\n if (!parent || length < 1e-6) {\n return [BELOW, ABOVE];\n }\n\n const inward = { x: (parent.x - entry.x) / length, y: (parent.y - entry.y) / length };\n const outward = { x: -inward.x, y: -inward.y };\n\n if (entry.role === 'moon') {\n return [outward];\n }\n\n const isLeaf = entry.node.children.length === 0 || entry.hiddenChildren >= entry.node.children.length;\n return isLeaf && entry.role === 'node' ? [outward, inward, BELOW, ABOVE] : [inward, BELOW, ABOVE, outward];\n};\n\n/**\n * Where an outside label will be, from its text's width in `measure` (by\n * default, an estimate), slid `offset` pixels sideways, on `lines` lines.\n * The pill is drawn no bigger than this box: its width holds the text, the\n * pill's padding (16 px) and 2 px to spare, and the stylesheet counts the\n * padding in a pill's width, capped at the same 160 px (280 px for the\n * focused node).\n */\nexport const outsideLabelBox = (text: string, point: Point, screenRadius: number, direction: Point, maximumWidth: number, offset = 0, lines: 1 | 2 = 1, measure: TextMeasure = PILL_ESTIMATE): Box => {\n const width = Math.min(maximumWidth, pillTextWidth(text, lines, measure) + 18);\n const height = PILL_HEIGHT[lines];\n const distance = pillDistance(screenRadius, direction, width, lines);\n const centerX = point.x + direction.x * (distance + width / 2) + offset;\n const centerY = point.y + direction.y * (distance + height / 2);\n return { left: centerX - width / 2, right: centerX + width / 2, top: centerY - height / 2, bottom: centerY + height / 2 };\n};\n\n/** The room (px) between a node's edge and its pill. */\nconst PILL_GAP = 5;\n\n/** A pill's height (px) on one line and on two: the stylesheet's, and a little to spare. */\nconst PILL_HEIGHT = { 1: 21, 2: 35 } as const;\n\n/** How round a pill's corners are (px): half a one-line pill's height (the stylesheet rounds two-line pills by 11 px). */\nconst PILL_CORNER = 10.5;\n\n/**\n * How far from its node's center a pill toward `direction` sits. A pill is\n * placed by its point that matches its side: the middle of its top when it's\n * below the node, the middle of its left end when it's to the right, and on a\n * slant a point between them, inside the pill. That point sits past the node's\n * edge by the gap, which keeps a pill on a side clear of its node, but on a\n * slant the pill's nearest end would reach back over it: there the pill sits\n * farther out, as far as that end keeps the same gap.\n */\nexport const pillDistance = (screenRadius: number, direction: Point, width: number, lines: 1 | 2): number => {\n const gap = screenRadius + PILL_GAP;\n const corner = Math.min(PILL_CORNER, width / 2);\n const x = Math.abs(direction.x);\n const y = Math.abs(direction.y);\n // Placed `distance` from the node's center, the pill has the center of its nearest corner's rounding\n // `distance * x - backX` across and `distance * y - backY` up or down from the node's center. It keeps\n // the gap while that point keeps the gap and the rounding from the node's center (or, once the pill\n // reaches across the node's middle, while its straight side does).\n const backX = ((1 - x) * width) / 2 - corner;\n const backY = ((1 - y) * PILL_HEIGHT[lines]) / 2 - corner;\n const clearance = gap + corner;\n\n if (keepsClear(gap, x, y, backX, backY, clearance)) {\n return gap;\n }\n\n // Otherwise it first keeps the gap where its rounded corner does, where its top or bottom does (a wide\n // pill across the node's middle) or where its end does: the nearest of these that keeps it.\n const along = backX * x + backY * y;\n const cornerDistance = along + Math.sqrt(Math.max(0, along * along + clearance * clearance - backX * backX - backY * backY));\n const sideDistance = y > 0 ? (clearance + backY) / y : Infinity;\n const endDistance = x > 0 ? (clearance + backX) / x : Infinity;\n let distance = Infinity;\n\n if (keepsClear(cornerDistance, x, y, backX, backY, clearance)) {\n distance = cornerDistance;\n }\n\n if (sideDistance < distance && keepsClear(sideDistance, x, y, backX, backY, clearance)) {\n distance = sideDistance;\n }\n\n if (endDistance < distance && keepsClear(endDistance, x, y, backX, backY, clearance)) {\n distance = endDistance;\n }\n\n // One of them always does, give or take rounding.\n return Number.isFinite(distance) ? distance : gap;\n};\n\n/** Whether a pill `distance` from its node's center keeps the gap, give or take a thousandth of a pixel (see `pillDistance`). */\nconst keepsClear = (distance: number, x: number, y: number, backX: number, backY: number, clearance: number): boolean => {\n return Math.hypot(Math.max(0, distance * x - backX), Math.max(0, distance * y - backY)) >= clearance - 0.001;\n};\n\n/** The size (px) of a pill's text, as the stylesheet sets it. */\nconst PILL_FONT_SIZE = 11.5;\n\ninterface PillMeasure {\n /** The text's width on one line (px). */\n oneLine: number;\n\n /** The longer line's width when the text breaks where its two lines balance best. */\n twoLines: number;\n\n /** Whether the text can break onto a second line: at a space, or between CJK characters. */\n wraps: boolean;\n}\n\n/**\n * Pill measurements by font and text. Labels are planned every frame while\n * the map moves, but their text rarely changes, and measuring it means\n * splitting it into characters.\n */\nconst pillMeasures = new Map<string, PillMeasure>();\n/** More texts than the largest maps have; past it, the measurements start over. */\nconst PILL_MEASURES_LIMIT = 20000;\n\n// Measurements start over when a font finishes loading.\nonMeasurementsReset(() => pillMeasures.clear());\n\nconst measurePill = (text: string, measure: TextMeasure): PillMeasure => {\n const key = `${measure.key}\\n${text}`;\n const cached = pillMeasures.get(key);\n\n if (cached) {\n return cached;\n }\n\n const width = (part: string) => measure.ems(part, PILL_FONT_SIZE) * PILL_FONT_SIZE;\n const oneLine = width(text);\n const units = breakUnits(text);\n let twoLines = oneLine;\n\n for (let index = 1; index < units.length; index += 1) {\n const first = width(joinUnits(units.slice(0, index)));\n const second = width(joinUnits(units.slice(index)));\n twoLines = Math.min(twoLines, Math.max(first, second));\n }\n\n if (pillMeasures.size >= PILL_MEASURES_LIMIT) {\n pillMeasures.clear();\n }\n\n const measured = { oneLine, twoLines, wraps: units.length > 1 };\n pillMeasures.set(key, measured);\n return measured;\n};\n\nconst canWrap = (text: string, measure: TextMeasure): boolean => {\n return measurePill(text, measure).wraps;\n};\n\n/** A pill's text width (px): on two lines, its longer line when it breaks where the two balance best. Estimated, unless `measure` measures it. */\nexport const pillTextWidth = (text: string, lines: 1 | 2, measure: TextMeasure = PILL_ESTIMATE): number => {\n const measured = measurePill(text, measure);\n return lines === 1 ? measured.oneLine : measured.twoLines;\n};\n\n/** Side of a cell of the grid that finds what a label spot covers (px). */\nconst GRID_CELL = 64;\n/** The grid reaches a little past the map's edges, so boxes along them fall in its cells. */\nconst GRID_MARGIN = 8;\n\n/**\n * Items bucketed by where their boxes sit on the map, so a label spot only\n * checks the bodies and labels near it. Only the map (and its margin) is\n * covered: spots are checked against it only when they fit on the map.\n */\nclass ScreenGrid<Item> {\n private readonly cells = new Map<number, Item[]>();\n private readonly columns: number;\n private readonly rows: number;\n private readonly seen = new Set<Item>();\n\n constructor(viewport: Viewport) {\n this.columns = Math.max(1, Math.ceil((viewport.width + 2 * GRID_MARGIN) / GRID_CELL));\n this.rows = Math.max(1, Math.ceil((viewport.height + 2 * GRID_MARGIN) / GRID_CELL));\n }\n\n add(item: Item, box: Box): void {\n this.visitCells(box, (key) => {\n const cell = this.cells.get(key);\n\n if (cell) {\n cell.push(item);\n } else {\n this.cells.set(key, [item]);\n }\n\n return false;\n });\n }\n\n /** Whether `test` holds for any item near `box`. */\n some(box: Box, test: (item: Item) => boolean): boolean {\n return this.visitCells(box, (key) => this.cells.get(key)?.some(test) ?? false);\n }\n\n /** The sum of `value` over the items near `box`, each counted once. */\n sum(box: Box, value: (item: Item) => number): number {\n let total = 0;\n this.seen.clear();\n\n this.visitCells(box, (key) => {\n for (const item of this.cells.get(key) ?? []) {\n if (!this.seen.has(item)) {\n this.seen.add(item);\n total += value(item);\n }\n }\n\n return false;\n });\n\n return total;\n }\n\n /** Calls `visit` with each cell `box` touches, until it returns true. */\n private visitCells(box: Box, visit: (key: number) => boolean): boolean {\n const firstColumn = Math.max(0, Math.floor((box.left + GRID_MARGIN) / GRID_CELL));\n const lastColumn = Math.min(this.columns - 1, Math.floor((box.right + GRID_MARGIN) / GRID_CELL));\n const firstRow = Math.max(0, Math.floor((box.top + GRID_MARGIN) / GRID_CELL));\n const lastRow = Math.min(this.rows - 1, Math.floor((box.bottom + GRID_MARGIN) / GRID_CELL));\n\n for (let row = firstRow; row <= lastRow; row += 1) {\n for (let column = firstColumn; column <= lastColumn; column += 1) {\n if (visit(row * this.columns + column)) {\n return true;\n }\n }\n }\n\n return false;\n }\n}\n\n/**\n * How far a pill above or below a node near the edge slides sideways to\n * stay on the map, as long as it still reaches past the node's center.\n */\nconst horizontalNudge = (box: Box, nodeX: number, viewport: Viewport): number => {\n const shift = box.left < 0 ? -box.left : box.right > viewport.width ? viewport.width - box.right : 0;\n const left = box.left + shift;\n const right = box.right + shift;\n return nodeX >= left + NUDGE_REACH && nodeX <= right - NUDGE_REACH ? shift : 0;\n};\n\nconst isOffScreen = (point: Point, radius: number, viewport: Viewport): boolean => {\n return point.x + radius < -OFF_SCREEN_MARGIN || point.x - radius > viewport.width + OFF_SCREEN_MARGIN\n || point.y + radius < -OFF_SCREEN_MARGIN || point.y - radius > viewport.height + OFF_SCREEN_MARGIN;\n};\n\n/** How far (px) a label box may reach past the map's edges: boxes are worked out in fractions of a pixel. */\nconst ROUNDING = 0.5;\n\n/** Whether a label box fits on the map, all of it: a pill is drawn as wide as its box, or narrower. */\nconst insideViewport = (box: Box, viewport: Viewport): boolean => {\n return box.left >= -ROUNDING && box.top >= -ROUNDING && box.right <= viewport.width + ROUNDING && box.bottom <= viewport.height + ROUNDING;\n};\n\nconst overlaps = (first: Box, second: Box): boolean => {\n return first.left < second.right && second.left < first.right && first.top < second.bottom && second.top < first.bottom;\n};\n\nconst discOverlapsBox = (disc: Point & { radius: number }, box: Box): boolean => {\n const nearestX = Math.min(box.right, Math.max(box.left, disc.x));\n const nearestY = Math.min(box.bottom, Math.max(box.top, disc.y));\n const dx = disc.x - nearestX;\n const dy = disc.y - nearestY;\n return dx * dx + dy * dy < disc.radius * disc.radius;\n};\n\nconst distance = (first: Point, second: Point): number => {\n return Math.hypot(first.x - second.x, first.y - second.y);\n};\n",
|
|
39
40
|
"/**\n * A theme's `surface-pattern` (CSS backgrounds) drawn as SVG, so exported\n * pictures keep the wallpaper glass shows through, a starfield or a grid.\n * Reads the kinds of layers Orbit's own themes use: radial gradients of one\n * color fading out, `linear-gradient` lines tiled by a size, and tiled\n * images. A layer of any other kind is left out of the picture.\n */\n\nimport { splitAlpha } from './colors.js';\n\nexport interface PatternLayers {\n /** `<defs>` entries the layers use. */\n definitions: string[];\n\n /** One full-size rectangle per layer, bottom layer first. */\n layers: string[];\n}\n\n/**\n * The layers of `pattern` for a picture `width` × `height`, with ids made\n * from `prefix`. `color` resolves a theme color to a plain value.\n */\nexport const patternLayers = (pattern: string, width: number, height: number, prefix: string, color: (value: string) => string): PatternLayers => {\n const definitions: string[] = [];\n const layers: string[] = [];\n\n // CSS draws the first layer on top: SVG paints in order, so they go last first.\n splitLayers(pattern).reverse().forEach((layer, index) => {\n const id = `${prefix}-surface-${index}`;\n const drawn = radialLayer(layer, width, height, id, color) ?? lineLayer(layer, id, color) ?? imageLayer(layer, id);\n\n if (drawn) {\n definitions.push(drawn);\n layers.push(`<rect width=\"${width}\" height=\"${height}\" fill=\"url(#${id})\"/>`);\n }\n });\n\n return { definitions, layers };\n};\n\n/** The layers of a CSS background list, split at the commas between them. */\nexport const splitLayers = (value: string): string[] => {\n const layers: string[] = [];\n let depth = 0;\n let quote = '';\n let start = 0;\n\n for (let index = 0; index < value.length; index += 1) {\n const character = value[index];\n\n if (quote) {\n quote = character === quote ? '' : quote;\n } else if (character === '\"' || character === \"'\") {\n quote = character;\n } else if (character === '(') {\n depth += 1;\n } else if (character === ')') {\n depth -= 1;\n } else if (character === ',' && depth === 0) {\n layers.push(value.slice(start, index).trim());\n start = index + 1;\n }\n }\n\n layers.push(value.slice(start).trim());\n return layers.filter((layer) => layer !== '' && layer !== 'none');\n};\n\n/** The arguments inside `name(…)`, split at their top-level commas. */\nconst argumentsOf = (layer: string, name: string): string[] | null => {\n const open = layer.indexOf(`${name}(`);\n\n if (open !== 0) {\n return null;\n }\n\n let depth = 0;\n\n for (let index = name.length; index < layer.length; index += 1) {\n if (layer[index] === '(') {\n depth += 1;\n } else if (layer[index] === ')') {\n depth -= 1;\n\n if (depth === 0) {\n return splitLayers(layer.slice(name.length + 1, index));\n }\n }\n }\n\n return null;\n};\n\n/** `radial-gradient(70% 55% at 12% 14%, <color>, transparent 70%)`: an ellipse of one color fading out. */\nconst radialLayer = (layer: string, width: number, height: number, id: string, color: (value: string) => string): string | null => {\n const parts = argumentsOf(layer, 'radial-gradient');\n\n if (!parts || parts.length < 3) {\n return null;\n }\n\n const shape = /^(\\d+(?:\\.\\d+)?)%\\s+(\\d+(?:\\.\\d+)?)%\\s+at\\s+(\\d+(?:\\.\\d+)?)%\\s+(\\d+(?:\\.\\d+)?)%$/.exec(parts[0]);\n\n if (!shape) {\n return null;\n }\n\n const [radiusX, radiusY, x, y] = shape.slice(1).map(Number);\n\n const stops = parts.slice(1).map((part, index, all) => {\n const match = /^(.*?)(?:\\s+(\\d+(?:\\.\\d+)?)%)?$/.exec(part)!;\n const offset = match[2] !== undefined ? Number(match[2]) / 100 : index / (all.length - 1);\n return { color: match[1].trim(), offset };\n });\n\n // Faded to `transparent`, a stop keeps the color it fades from, so the edge doesn't go grey.\n const solid = stops.find((stop) => stop.color !== 'transparent')?.color ?? 'transparent';\n const centerX = (x / 100) * width;\n const centerY = (y / 100) * height;\n const rx = (radiusX / 100) * width;\n const ry = (radiusY / 100) * height;\n\n if (rx <= 0 || ry <= 0) {\n return null;\n }\n\n const stopElements = stops.map((stop) => {\n const { color: value, opacity } = stop.color === 'transparent' ? { color: splitAlpha(color(solid)).color, opacity: 0 } : splitAlpha(color(stop.color));\n return `<stop offset=\"${round(stop.offset)}\" stop-color=\"${escapeXml(value)}\" stop-opacity=\"${round(opacity)}\"/>`;\n });\n\n return `<radialGradient id=\"${id}\" gradientUnits=\"userSpaceOnUse\" cx=\"${round(centerX)}\" cy=\"${round(centerY)}\" r=\"${round(rx)}\" gradientTransform=\"translate(${round(centerX)} ${round(centerY)}) scale(1 ${round(ry / rx)}) translate(${round(-centerX)} ${round(-centerY)})\">${stopElements.join('')}</radialGradient>`;\n};\n\n/** `linear-gradient([90deg, ]<color> 1px, transparent 1px) 0 0 / 120px 120px`: a line along each tile's top (or left) edge. */\nconst lineLayer = (layer: string, id: string, color: (value: string) => string): string | null => {\n const parts = argumentsOf(layer, 'linear-gradient');\n const tile = /\\)\\s*0\\s+0\\s*\\/\\s*(\\d+(?:\\.\\d+)?)px\\s+(\\d+(?:\\.\\d+)?)px\\s*$/.exec(layer);\n\n if (!parts || !tile) {\n return null;\n }\n\n const vertical = parts[0] === '90deg';\n const stops = vertical ? parts.slice(1) : parts;\n const line = /^(.*?)\\s+(\\d+(?:\\.\\d+)?)px$/.exec(stops[0] ?? '');\n\n if (!line || stops.length !== 2 || !/^transparent\\s/.test(stops[1])) {\n return null;\n }\n\n const [tileWidth, tileHeight] = [Number(tile[1]), Number(tile[2])];\n const thickness = Number(line[2]);\n const { color: value, opacity } = splitAlpha(color(line[1].trim()));\n const rect = vertical ? `width=\"${thickness}\" height=\"${tileHeight}\"` : `width=\"${tileWidth}\" height=\"${thickness}\"`;\n return `<pattern id=\"${id}\" patternUnits=\"userSpaceOnUse\" width=\"${tileWidth}\" height=\"${tileHeight}\"><rect ${rect} fill=\"${escapeXml(value)}\" fill-opacity=\"${round(opacity)}\"/></pattern>`;\n};\n\n/** `url(\"data:image/svg+xml,…\") 0 0 / 640px 640px`: an image tiled at its size. */\nconst imageLayer = (layer: string, id: string): string | null => {\n // The image's own markup may hold the other kind of quote: the URL ends at its closing quote and `)`.\n const match = /^url\\(([\"']?)(data:image\\/.+?)\\1\\)\\s*0\\s+0\\s*\\/\\s*(\\d+(?:\\.\\d+)?)px\\s+(\\d+(?:\\.\\d+)?)px$/s.exec(layer);\n\n if (!match) {\n return null;\n }\n\n const [source, tileWidth, tileHeight] = [match[2], match[3], match[4]];\n return `<pattern id=\"${id}\" patternUnits=\"userSpaceOnUse\" width=\"${tileWidth}\" height=\"${tileHeight}\"><image href=\"${escapeXml(source)}\" width=\"${tileWidth}\" height=\"${tileHeight}\"/></pattern>`;\n};\n\nconst round = (value: number): number => {\n return Math.round(value * 1000) / 1000;\n};\n\nconst escapeXml = (text: string): string => {\n return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n};\n",
|
|
40
41
|
"/**\n * Standalone SVG for a display. Every color is resolved to a plain value,\n * labels are SVG text and nothing depends on the page's stylesheet, so the\n * file looks the same in any viewer or editor.\n */\n\nimport type { Display, DisplayNode } from './display.js';\nimport { worldToScreen, type Viewport } from './camera.js';\nimport { mixOklab, parseColor, prefersLightText, resolveColor, splitAlpha, toHex } from './colors.js';\nimport { SHADE_STOPS, SHADOW_BLUR, drawsFlat, insideLabelLayout, nodeThumbnail, readShadeCircle, ringPath } from './views.js';\nimport { labelOrder, outsideLabelBox, planLabels, type PlannedLabel } from './labels.js';\nimport { hasMediaSource } from '../media.js';\nimport { statusTone } from '../ui/detail-sheet.js';\nimport type { MapExtensions } from '../extensions.js';\nimport type { OrbitWords } from '../languages.js';\nimport { wrapText } from '../text-layout.js';\nimport { patternLayers } from './surface-pattern.js';\nimport { ESTIMATED_LABELS, type LabelMeasures } from './text-measure.js';\nimport { guardUrl, resolveUrl } from '../url-guard.js';\n\nexport interface ExportOptions {\n viewport: Viewport;\n\n /** Concrete theme values, keyed by token name (`surface`, `color-1`, …). */\n tokens: Record<string, string>;\n\n showRings: boolean;\n title: string;\n\n /** The fill the page resolved for a node, when it is on screen. */\n fills?: (node: DisplayNode) => string;\n\n baseUrl?: string;\n\n /** Size the SVG to its container (100% wide and tall) instead of in pixels. */\n responsive?: boolean;\n\n /** Prefix for the SVG's ids; give each SVG inlined in one page its own. */\n idPrefix?: string;\n\n /** The map's node types and status words, for icons, status colors and type tokens. */\n extensions?: MapExtensions;\n\n /** Measures names in the fonts the map draws them with, so labels break as on the live map; by default, widths are estimated. */\n measures?: LabelMeasures;\n\n /** The map's words, for the name of an idea without text. Default: English. */\n words?: OrbitWords;\n}\n\nconst ROLE_ORDER = { moon: 0, node: 1, planet: 1, sun: 2 } as const;\nconst FONT_SIZE = { sun: 16, planet: 13, node: 12, moon: 13 } as const;\nconst LINES = { sun: 3, planet: 2, node: 2, moon: 2 } as const;\n\n/** Theme values read as plain colors, numbers and mixes. */\nclass ThemeReader {\n readonly tokens: Record<string, string>;\n\n constructor(tokens: Record<string, string>) {\n this.tokens = tokens;\n }\n\n value(name: string, fallback = ''): string {\n return this.tokens[name] ?? fallback;\n }\n\n color(value: string): string {\n return resolveColor(value, this.tokens);\n }\n\n token(name: string, fallback = '#000000'): string {\n return this.color(this.value(name, fallback));\n }\n\n number(name: string, fallback: number): number {\n const parsed = Number.parseFloat(this.value(name));\n return Number.isFinite(parsed) ? parsed : fallback;\n }\n\n /** `color-mix(in oklab, own <tint>, <base token>)`, as the stylesheet mixes rims, shadows, rings and links. */\n tinted(own: string, base: string, tint: string): string {\n const ownColor = parseColor(this.color(own));\n const baseColor = parseColor(this.token(base));\n const amount = this.number(tint, 0) / 100;\n\n if (!ownColor || !baseColor) {\n return this.token(base);\n }\n\n return toHex(mixOklab(ownColor, baseColor, Math.min(1, Math.max(0, amount))));\n }\n}\n\n/**\n * `fill=\"#rrggbb\" fill-opacity=\"…\"`: the color's alpha times `opacity`, written\n * apart for design tools. A color Orbit can't read is written as given (SVG\n * takes any CSS color), escaped, since maps and themes can hold any text.\n */\nconst paint = (kind: 'fill' | 'stroke' | 'stop', color: string, opacity = 1): string => {\n const { color: value, opacity: alpha } = splitAlpha(color);\n const hex = escapeXml(value);\n const total = round(alpha * opacity);\n const name = kind === 'stop' ? 'stop-color' : kind;\n const opacityName = kind === 'stop' ? 'stop-opacity' : `${kind}-opacity`;\n return total < 1 || kind === 'stop' ? `${name}=\"${hex}\" ${opacityName}=\"${total}\"` : `${name}=\"${hex}\"`;\n};\n\nconst dashAttribute = (dash: string): string => {\n return dash.trim() === '' || dash.trim() === 'none' ? '' : ` stroke-dasharray=\"${escapeXml(dash.trim())}\"`;\n};\n\nexport const exportDisplay = (display: Display | null, options: ExportOptions): string => {\n const { viewport } = options;\n const theme = new ThemeReader(options.tokens);\n const width = Math.round(viewport.width);\n const height = Math.round(viewport.height);\n const prefix = escapeXml(options.idPrefix ?? 'orbit-export');\n const untitled = options.words?.text('untitled') ?? 'Untitled';\n const size = options.responsive ? 'width=\"100%\" height=\"100%\" preserveAspectRatio=\"xMidYMid meet\"' : `width=\"${width}\" height=\"${height}\"`;\n const parts: string[] = [\n `<svg xmlns=\"http://www.w3.org/2000/svg\" ${size} viewBox=\"0 0 ${width} ${height}\" role=\"img\" aria-label=\"${escapeXml(options.title)}\">`,\n `<title>${escapeXml(options.title)}</title>`,\n ];\n const definitions: string[] = [shadeGradient(`${prefix}-shade`, theme)];\n const body: string[] = [];\n // The surface color, and the theme's pattern over it: the wallpaper glass shows through, stars, a grid.\n const surface = theme.token('surface', 'transparent');\n const surfaceColor = parseColor(surface);\n\n if (surfaceColor && surfaceColor.alpha > 0) {\n body.push(`<rect width=\"${width}\" height=\"${height}\" ${paint('fill', surface)}/>`);\n }\n\n const pattern = patternLayers(theme.value('surface-pattern', 'none'), width, height, prefix, (value) => theme.color(value));\n definitions.push(...pattern.definitions);\n body.push(...pattern.layers);\n\n if (display) {\n const { camera } = display;\n const place = (node: { x: number; y: number }) => worldToScreen(camera, viewport, node);\n\n if (options.showRings) {\n const ringOpacity = theme.number('ring-opacity', 0.5);\n const ringWidth = theme.number('ring-width', 1.5);\n const ringDash = dashAttribute(theme.value('ring-dash', 'none'));\n\n for (const ring of display.rings) {\n if (ring.opacity <= 0.01) {\n continue;\n }\n\n const center = place({ x: ring.cx, y: ring.cy });\n const d = ringPath(ring.radius * camera.scale, ring.gaps);\n const stroke = theme.tinted(ring.color, 'ring-stroke', 'ring-tint');\n body.push(`<path d=\"${d}\" transform=\"translate(${round(center.x)} ${round(center.y)}) rotate(${round(ring.rotation)})\" fill=\"none\" ${paint('stroke', stroke, ringOpacity)} stroke-width=\"${ringWidth}\"${ringDash} stroke-linecap=\"round\"/>`);\n }\n }\n\n const linkOpacity = theme.number('link-opacity', 0.5);\n const linkWidth = theme.number('link-width', 1.5);\n const linkDash = dashAttribute(theme.value('link-dash', 'none'));\n\n for (const link of display.links) {\n const from = display.nodes.get(link.fromId);\n const to = display.nodes.get(link.toId);\n\n if (!from || !to) {\n continue;\n }\n\n const start = place(from);\n const end = place(to);\n const length = Math.hypot(end.x - start.x, end.y - start.y);\n const fromRadius = from.radius * camera.scale;\n const toRadius = to.radius * camera.scale;\n\n if (length <= fromRadius + toRadius) {\n continue;\n }\n\n const unitX = (end.x - start.x) / length;\n const unitY = (end.y - start.y) / length;\n const stroke = theme.tinted(link.color, 'link-stroke', 'link-tint');\n body.push(`<line x1=\"${round(start.x + unitX * fromRadius)}\" y1=\"${round(start.y + unitY * fromRadius)}\" x2=\"${round(end.x - unitX * toRadius)}\" y2=\"${round(end.y - unitY * toRadius)}\" ${paint('stroke', stroke, linkOpacity)} stroke-width=\"${linkWidth}\"${linkDash} stroke-linecap=\"round\"/>`);\n }\n\n const nodes = Array.from(display.nodes.values())\n .filter((node) => node.opacity > 0.01 && node.radius > 0)\n .sort((left, right) => ROLE_ORDER[left.role] - ROLE_ORDER[right.role]);\n const fills = new Map<string, string>();\n const pictures = new Set<string>();\n // A node type's tokens win over the theme for its nodes.\n const typeThemes = new Map<string, ThemeReader>();\n\n const themeFor = (node: DisplayNode): ThemeReader => {\n const tokens = options.extensions?.nodeType(node.node)?.tokens;\n const type = options.extensions?.typeName(node.node) ?? node.node.type;\n\n if (!tokens || !type) {\n return theme;\n }\n\n const key = type.toLowerCase();\n let reader = typeThemes.get(key);\n\n if (!reader) {\n const own = Object.fromEntries(Object.entries(tokens).filter((entry): entry is [string, string] => typeof entry[1] === 'string' && entry[1] !== ''));\n reader = new ThemeReader({ ...options.tokens, ...own });\n typeThemes.set(key, reader);\n }\n\n return reader;\n };\n\n const hasShadow = (node: DisplayNode) => node.role !== 'node'\n && !drawsFlat(node, node.radius * camera.scale)\n && themeFor(node).number(node.role === 'sun' ? 'sun-shadow-opacity' : 'node-shadow-opacity', 0) > 0;\n\n if (nodes.some(hasShadow)) {\n for (const [id, blur] of [[`${prefix}-shadow`, SHADOW_BLUR.planet], [`${prefix}-sun-shadow`, SHADOW_BLUR.sun]] as const) {\n definitions.push(`<filter id=\"${id}\" x=\"-60%\" y=\"-60%\" width=\"220%\" height=\"220%\"><feGaussianBlur stdDeviation=\"${blur}\"/></filter>`);\n }\n }\n\n nodes.forEach((node, index) => {\n const nodeTheme = themeFor(node);\n const center = place(node);\n const radius = node.radius * camera.scale;\n const resolved = options.fills?.(node);\n const own = resolved ? nodeTheme.color(resolved) : nodeTheme.color(node.color);\n fills.set(node.id, own);\n const isSun = node.role === 'sun';\n const fillOpacity = nodeTheme.number('node-fill-opacity', 1);\n const strokeWidth = nodeTheme.number('node-stroke-width', 1.5);\n\n if (hasShadow(node)) {\n const shadow = nodeTheme.tinted(own, 'node-shadow', 'node-shadow-tint');\n const opacity = nodeTheme.number(isSun ? 'sun-shadow-opacity' : 'node-shadow-opacity', 0);\n const scale = radius * nodeTheme.number(isSun ? 'sun-shadow-size' : 'node-shadow-size', 1);\n const offset = radius * nodeTheme.number('node-shadow-offset', 0);\n // A unit circle, scaled like the live map's, so one blur fits every size.\n body.push(`<circle r=\"1\" transform=\"translate(${round(center.x)} ${round(center.y + offset)}) scale(${round(scale, 3)})\" ${paint('fill', shadow, opacity)} filter=\"url(#${prefix}-${isSun ? 'sun-shadow' : 'shadow'})\"/>`);\n }\n\n if (isSun) {\n body.push(...halo(center, radius, own, nodeTheme));\n }\n\n const circle = `cx=\"${round(center.x)}\" cy=\"${round(center.y)}\" r=\"${round(radius)}\"`;\n body.push(`<circle ${circle} ${paint('fill', own, node.role === 'moon' ? nodeTheme.number('moon-opacity', fillOpacity) : fillOpacity)}/>`);\n const thumbnail = nodeThumbnail(node.node);\n const source = thumbnail ? guardUrl(thumbnail, 'image') : null;\n\n if (source) {\n pictures.add(node.id);\n const clip = `${prefix}-clip-${index}`;\n definitions.push(`<clipPath id=\"${clip}\"><circle ${circle}/></clipPath>`);\n body.push(`<image href=\"${escapeXml(resolveUrl(source, options.baseUrl))}\" x=\"${round(center.x - radius)}\" y=\"${round(center.y - radius)}\" width=\"${round(radius * 2)}\" height=\"${round(radius * 2)}\" preserveAspectRatio=\"xMidYMid slice\" clip-path=\"url(#${clip})\"/>`);\n }\n\n const rim = nodeTheme.tinted(own, 'node-stroke', 'node-stroke-tint');\n // A crowded orbit's rims grow with their planets, as on the live map.\n const rimWidth = node.crowded ? strokeWidth * 0.04 * radius : node.role === 'moon' ? strokeWidth * 0.7 : strokeWidth;\n body.push(`<circle ${circle} fill=\"url(#${prefix}-shade)\" ${paint('stroke', rim)} stroke-width=\"${round(rimWidth)}\"/>`);\n body.push(...badges(node, center, radius, nodeTheme, options.extensions));\n });\n\n const iconOf = (entry: DisplayNode) => (options.extensions ? options.extensions.icon(entry.node) : entry.node.icon);\n const measures = options.measures ?? ESTIMATED_LABELS;\n const planned = planLabels(display, labelOrder(nodes), {\n viewport,\n hasImage: (entry) => pictures.has(entry.id),\n hasIcon: (entry) => Boolean(iconOf(entry)),\n // A picture fills the node: its icon goes on the pill, as on the live map.\n pillIcon: (entry) => (pictures.has(entry.id) ? iconOf(entry) : undefined),\n measures,\n });\n\n for (const plan of planned) {\n body.push(...exportLabel(plan, fills.get(plan.entry.id) ?? '#ffffff', themeFor(plan.entry), iconOf(plan.entry), measures, untitled));\n }\n }\n\n parts.push(`<defs>${definitions.join('')}</defs>`, ...body, '</svg>');\n return parts.join('');\n};\n\n/** The sphere shading, with the stops the stylesheet colors from the theme. */\nconst shadeGradient = (id: string, theme: ThemeReader): string => {\n const highlight = theme.token('node-highlight', 'rgba(255, 255, 255, 0.5)');\n const terminator = theme.token('node-terminator', 'rgba(0, 0, 0, 0)');\n const shading = theme.token('node-shading', 'rgba(0, 0, 0, 0.12)');\n\n const stops = SHADE_STOPS.map(({ offset, part }) => {\n switch (part) {\n case 'highlight':\n return `<stop offset=\"${offset}\" ${paint('stop', highlight)}/>`;\n case 'highlight-fade':\n return `<stop offset=\"${offset}\" ${paint('stop', highlight, 0.2)}/>`;\n case 'terminator-start':\n return `<stop offset=\"${offset}\" ${paint('stop', terminator, 0)}/>`;\n case 'terminator':\n return `<stop offset=\"${offset}\" ${paint('stop', terminator)}/>`;\n default:\n return `<stop offset=\"${offset}\" ${paint('stop', shading)}/>`;\n }\n });\n\n const circle = readShadeCircle(theme.value('node-shade-circle', ''));\n return `<radialGradient id=\"${id}\" cx=\"${circle.x}\" cy=\"${circle.y}\" r=\"${circle.radius}\">${stops.join('')}</radialGradient>`;\n};\n\n/** The ring the theme draws around the sun, if any. */\nconst halo = (center: { x: number; y: number }, radius: number, own: string, theme: ThemeReader): string[] => {\n const opacity = theme.number('sun-halo-opacity', 0);\n const width = theme.number('sun-halo-width', 0);\n\n if (opacity <= 0 || width <= 0) {\n return [];\n }\n\n const stroke = theme.tinted(own, 'sun-halo', 'sun-halo-tint');\n const dash = dashAttribute(theme.value('sun-halo-dash', 'none'));\n return [`<circle cx=\"${round(center.x)}\" cy=\"${round(center.y)}\" r=\"${round(radius * theme.number('sun-halo-size', 1.15))}\" fill=\"none\" ${paint('stroke', stroke, opacity)} stroke-width=\"${width}\"${dash}/>`];\n};\n\n/** Status dot, content marker and video badge, placed as on the live map. */\nconst badges = (node: DisplayNode, center: { x: number; y: number }, radius: number, theme: ThemeReader, extensions?: MapExtensions): string[] => {\n const parts: string[] = [];\n const stroke = paint('stroke', theme.token('badge-stroke', '#ffffff'));\n const isSun = node.role === 'sun';\n\n if (node.node.status && radius > 6) {\n const offset = (isSun ? 0.68 : 0.72) * radius;\n const look = extensions?.status(node.node.status) ?? { tone: statusTone(node.node.status) };\n const color = look.color ?? theme.token(`status-${look.tone}`, '#94a3b8');\n parts.push(`<circle cx=\"${round(center.x + offset)}\" cy=\"${round(center.y - offset)}\" r=\"${round((isSun ? 0.11 : 0.17) * radius)}\" ${paint('fill', color)} ${stroke} stroke-width=\"${round((isSun ? 0.025 : 0.04) * radius)}\"/>`);\n }\n\n // The focused node's buttons offer its content, so it has no marker or badge.\n if (isSun || radius <= 8) {\n return parts;\n }\n\n if (hasMediaSource(node.node.video)) {\n const x = center.x + 0.62 * radius;\n const y = center.y + 0.62 * radius;\n const size = 0.3 * radius;\n parts.push(`<circle cx=\"${round(x)}\" cy=\"${round(y)}\" r=\"${round(size)}\" fill=\"#0f172a\" fill-opacity=\"0.62\"/>`);\n parts.push(`<path d=\"M${round(x - 0.32 * size)} ${round(y - 0.48 * size)} L${round(x + 0.52 * size)} ${round(y)} L${round(x - 0.32 * size)} ${round(y + 0.48 * size)} Z\" fill=\"#ffffff\"/>`);\n } else if (node.node.note || hasMediaSource(node.node.image) || hasMediaSource(node.node.embed) || node.node.link || extensions?.nodeType(node.node)?.details) {\n parts.push(`<circle cx=\"${round(center.x + 0.72 * radius)}\" cy=\"${round(center.y + 0.72 * radius)}\" r=\"${round(0.13 * radius)}\" ${paint('fill', theme.token('note-indicator', '#1b2333'))} ${stroke} stroke-width=\"${round(0.04 * radius)}\"/>`);\n }\n\n return parts;\n};\n\nconst exportLabel = (plan: PlannedLabel, fill: string, theme: ThemeReader, icon: string | undefined, measures: LabelMeasures, untitled: string): string[] => {\n const { entry, x, y, screenRadius } = plan;\n const text = entry.node.text || untitled;\n const isSun = entry.role === 'sun';\n const font = escapeXml(theme.value(isSun ? 'display-font' : 'label-font', theme.value('font-family', 'sans-serif')));\n const weight = escapeXml(theme.value(isSun ? 'display-weight' : 'label-weight', isSun ? '650' : '600'));\n const letterSpacing = theme.value('label-letter-spacing', '0').trim();\n const spacing = letterSpacing === '0' || letterSpacing === '' || letterSpacing === 'normal' ? '' : ` letter-spacing=\"${escapeXml(letterSpacing)}\"`;\n const opacity = plan.opacity >= 0.999 ? '' : ` opacity=\"${round(plan.opacity)}\"`;\n const inside = plan.placement === 'inside' ? insideLabelLayout(entry.role, screenRadius, text, Boolean(icon), measures.inside(entry.role, entry.node)) : null;\n\n if (plan.placement === 'outside') {\n const fontSize = 11.5;\n const lineCount = plan.lines;\n const pill = measures.pill(entry.role, entry.node);\n // The pill's own text: the name, after the node's icon when a picture fills the node.\n const pillText = plan.text || untitled;\n const box = outsideLabelBox(pillText, { x, y }, screenRadius, plan.direction, isSun ? 280 : 160, plan.offset, lineCount, pill);\n const width = box.right - box.left;\n const pillLines = wrapText(pillText, width - 12, fontSize, lineCount, pill).lines;\n const middle = (box.top + box.bottom) / 2;\n const height = lineCount === 1 ? 20 : 34;\n const lineHeight = 14;\n const firstBaseline = middle - ((pillLines.length - 1) * lineHeight) / 2 + fontSize * 0.36;\n const spans = pillLines\n .map((line, index) => `<tspan x=\"${round((box.left + box.right) / 2)}\" y=\"${round(firstBaseline + index * lineHeight)}\">${escapeXml(line)}</tspan>`)\n .join('');\n return [\n `<g${opacity}>`,\n `<rect x=\"${round(box.left)}\" y=\"${round(middle - height / 2)}\" width=\"${round(width)}\" height=\"${height}\" rx=\"10\" ${paint('fill', theme.token('control-background', '#ffffff'))}/>`,\n `<text text-anchor=\"middle\" font-family=\"${font}\" font-size=\"${fontSize}\" font-weight=\"${weight}\"${spacing} ${paint('fill', theme.token('control-text', '#1b2333'))}>${spans}</text>`,\n '</g>',\n ];\n }\n\n const fontSize = inside?.fontSize ?? FONT_SIZE[entry.role];\n // The lines the live map shows; a label that doesn't fit falls back to wrapping at the usual width.\n const textLines = inside?.lines ?? wrapText(text, screenRadius * 1.68, fontSize, LINES[entry.role], measures.inside(entry.role, entry.node)).lines;\n const lines = icon && (inside?.icon ?? true) ? [icon, ...textLines] : textLines;\n const lineHeight = fontSize * 1.22;\n const lightText = theme.token('node-text-inverse', '#ffffff');\n const darkText = theme.token(isSun ? 'root-text' : 'node-text', '#1b2333');\n const textColor = prefersLightText(fill, lightText, darkText) ? lightText : darkText;\n const firstBaseline = y - ((lines.length - 1) * lineHeight) / 2 + fontSize * 0.35;\n const spans = lines\n .map((line, index) => `<tspan x=\"${round(x)}\" y=\"${round(firstBaseline + index * lineHeight)}\">${escapeXml(line)}</tspan>`)\n .join('');\n // A name drawn narrower to fit, as on the live map.\n const stretch = inside?.stretch ? ` font-stretch=\"${inside.stretch}%\"` : '';\n return [`<text text-anchor=\"middle\" font-family=\"${font}\" font-size=\"${fontSize}\" font-weight=\"${weight}\"${stretch}${spacing} ${paint('fill', textColor)}${opacity}>${spans}</text>`];\n};\n\nexport const escapeXml = (value: string): string => {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n};\n\nconst round = (value: number, decimals = 2): number => {\n const factor = 10 ** decimals;\n return Math.round(value * factor) / factor;\n};\n",
|
|
41
42
|
"import { MapExtensions, type OrbitNodeType, type OrbitStatusStyle } from './extensions.js';\nimport type { OrbitDocument, OrbitNode, OrbitRendererTheme, OrbitThemePreset, ViewMode } from './types.js';\nimport { parseOrbit } from './dispatch.js';\nimport { documentToRendererOptions } from './document-options.js';\nimport { findNodeById } from './utils.js';\nimport { hasMediaSource } from './media.js';\nimport { expandTheme, mergeThemes, resolvePalette, resolveThemeTokens, themeName } from './themes.js';\nimport { assignNodeColors, buildFocusScene, buildOverviewScene } from './engine/scene.js';\nimport { sceneDisplay } from './engine/display.js';\nimport { escapeXml, exportDisplay } from './engine/export.js';\nimport { resolveColor } from './engine/colors.js';\nimport { OrbitWords, type OrbitStrings } from './languages.js';\n\n/**\n * The largest width or height the exporter accepts: a million pixels, far\n * past any drawing. The label grid numbers its 64 px cells, and past about\n * 6 × 10⁹ px a side those numbers stop being exact; past about 6 × 10¹⁷ its\n * loops stop advancing and the export never finishes.\n */\nexport const MAX_SVG_EXPORT_SIZE = 1_000_000;\n\nexport interface RenderToSVGOptions {\n /** Width of the drawing, in pixels: positive, at most `MAX_SVG_EXPORT_SIZE`. Default 800. */\n width?: number;\n\n /** Height of the drawing, in pixels: positive, at most `MAX_SVG_EXPORT_SIZE`. Default 600. */\n height?: number;\n\n /** `focus` (default) or `all` for the overview. */\n viewMode?: ViewMode;\n\n /** The node at the center in focus mode, by id. Default: the root. */\n focus?: string;\n\n /** A theme name or an object of theme values. Default: the document's theme, or `paper`. */\n theme?: OrbitThemePreset | (string & {}) | OrbitRendererTheme;\n\n palette?: string[];\n maxDepth?: number;\n showRings?: boolean;\n\n /** The SVG's title and accessible name. Default: the document's title, or the root's text. */\n title?: string;\n\n /** The language of the few words the drawing has (an untitled idea, the empty map): a BCP 47 tag. Default: English. */\n language?: string;\n\n /** Words to change, over the language's. */\n strings?: Partial<OrbitStrings>;\n\n /** Resolves relative image URLs. */\n baseUrl?: string;\n\n /** Size the SVG to its container (100% wide and tall) instead of in pixels. */\n responsive?: boolean;\n\n /** Prefix for the SVG's ids; give each SVG inlined in one page its own. */\n idPrefix?: string;\n\n /** Node types by name, before the registered ones: their icons, colors and tokens. */\n nodeTypes?: Record<string, OrbitNodeType>;\n\n /** Status words and how they look, before the registered ones. */\n statuses?: Record<string, OrbitStatusStyle>;\n\n /** The type a node that names none is drawn as, for display only (see `RendererOptions.nodeTypeFor`). */\n nodeTypeFor?: (node: OrbitNode) => string | undefined;\n}\n\n/**\n * Renders a map to a standalone SVG string, without a browser: for files,\n * the command line, static sites and server rendering. It draws what the\n * renderer shows at rest, with the theme's colors resolved to plain values\n * and the labels as SVG text.\n *\n * @example\n * ```ts\n * import { renderToSVGString } from '@restless-dreams/orbit';\n *\n * const svg = renderToSVGString('# Launch\\n## Research\\n## Build', { width: 1200, height: 800, theme: 'cosmos' });\n * ```\n */\nexport const renderToSVGString = (input: string | OrbitDocument | OrbitNode, options: RenderToSVGOptions = {}): string => {\n const words = new OrbitWords(options.language, options.strings);\n const doc: OrbitDocument | null = typeof input === 'string' ? parseOrbit(input, { untitled: words.text('untitledMap') }) : isDocument(input) ? input : null;\n const tree = doc ? doc.root : (input as OrbitNode);\n const fromDocument = doc ? documentToRendererOptions(doc.options) : {};\n const viewport = { width: readSize(options.width, 800, 'width'), height: readSize(options.height, 600, 'height') };\n const theme = expandTheme(mergeThemes(fromDocument.theme, options.theme));\n const tokens: Record<string, string> = resolveThemeTokens(themeName(theme), typeof theme === 'object' ? theme : undefined);\n const title = options.title ?? fromDocument.ariaLabel ?? (tree.text || words.text('mindMap'));\n const extensions = new MapExtensions({ nodeTypes: options.nodeTypes, statuses: options.statuses, nodeTypeFor: options.nodeTypeFor });\n const exportOptions = {\n viewport,\n extensions,\n tokens,\n showRings: options.showRings ?? fromDocument.showRings ?? true,\n title,\n baseUrl: options.baseUrl ?? fromDocument.baseUrl,\n responsive: options.responsive,\n idPrefix: options.idPrefix,\n words,\n };\n\n if (isEmptyTree(tree)) {\n return emptyMap(exportOptions.title, words.text('emptyMap'), viewport, tokens, options.responsive);\n }\n\n const sceneOptions = {\n viewport,\n colors: assignNodeColors(tree, resolvePalette(options.palette ?? fromDocument.palette), (node) => extensions.color(node)),\n maxDepth: options.maxDepth ?? fromDocument.maxDepth,\n };\n const viewMode = options.viewMode ?? fromDocument.viewMode ?? 'focus';\n const focusId = options.focus && findNodeById(tree, options.focus) ? options.focus : tree.id;\n const scene = viewMode === 'all' ? buildOverviewScene(tree, sceneOptions) : buildFocusScene(tree, focusId, sceneOptions);\n return exportDisplay(sceneDisplay(scene, 0, scene.frame), exportOptions);\n};\n\nconst isDocument = (input: OrbitDocument | OrbitNode): input is OrbitDocument => {\n return typeof (input as OrbitDocument).root === 'object' && (input as OrbitDocument).root !== null && !('children' in input);\n};\n\nconst readSize = (value: number | undefined, fallback: number, name: 'width' | 'height'): number => {\n const size = value ?? fallback;\n\n if (!Number.isFinite(size) || size <= 0 || size > MAX_SVG_EXPORT_SIZE) {\n throw new Error(`RenderToSVGOptions.${name} must be a positive number no larger than ${MAX_SVG_EXPORT_SIZE}: got ${size}.`);\n }\n\n return size;\n};\n\nconst isEmptyTree = (tree: OrbitNode): boolean => {\n return tree.text.trim() === '' && !tree.icon && tree.children.length === 0\n && !hasMediaSource(tree.image) && !hasMediaSource(tree.video) && !hasMediaSource(tree.embed);\n};\n\nconst emptyMap = (title: string, message: string, viewport: { width: number; height: number }, tokens: Record<string, string>, responsive?: boolean): string => {\n const { width, height } = viewport;\n const size = responsive ? 'width=\"100%\" height=\"100%\"' : `width=\"${width}\" height=\"${height}\"`;\n const color = resolveColor(tokens['muted-text'] ?? '#5F6B7D', tokens);\n const font = escapeXml(tokens['font-family'] ?? 'sans-serif');\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" ${size} viewBox=\"0 0 ${width} ${height}\" role=\"img\" aria-label=\"${escapeXml(title)}\">`\n + `<text x=\"${width / 2}\" y=\"${height / 2}\" text-anchor=\"middle\" font-family=\"${font}\" font-size=\"15\" fill=\"${color}\">${escapeXml(message)}</text></svg>`;\n};\n",
|
|
42
|
-
"/**\n * A map as a web page: one HTML file with Orbit, the map and its pictures\n * inside, which opens in any browser, offline. Readers explore it with\n * Orbit's own controls, or present it: one idea at a time, in reading order,\n * with its note as a caption (see runtime.ts, the page's script).\n */\n\nimport { parseOrbit } from '../dispatch.js';\nimport { serializeOrbitMarkdown } from '../serializer-markdown.js';\nimport { OrbitWords, type OrbitStrings } from '../languages.js';\nimport { expandTheme, isOrbitThemePreset, themeTokens, type OrbitThemeTokens } from '../themes.js';\nimport type { OrbitDocument, OrbitRendererTheme, ViewMode } from '../types.js';\n\nexport interface OrbitWebPageOptions {\n /**\n * Orbit's web page script, the file `@restless-dreams/orbit/web-page.js`,\n * as text. It goes inside the page, so the page needs nothing else.\n */\n script: string;\n\n /** The page's title. Default: the map's `title`, or its root's text. */\n title?: string;\n\n /** The map's theme, instead of its frontmatter's: a theme name or `{ preset, tokens }`. */\n theme?: string | OrbitRendererTheme;\n\n /** How the map opens: `focus` (default) or `all`, the overview. */\n viewMode?: ViewMode;\n\n /** The node in focus when the map opens, by id. Default: the root. */\n focus?: string;\n\n /** The language of the page and the map's words: a tag like `es`. Default: English. */\n language?: string;\n\n /** Single words to change: `{ present: 'Show' }`. */\n strings?: Partial<OrbitStrings>;\n\n /**\n * Pictures to put inside the page, by the address the map gives them:\n * `{ 'photos/summit.jpg': 'data:image/jpeg;base64,…' }`. A node's picture,\n * a video's thumbnail and pictures in notes are swapped for them, so they\n * show wherever the page goes.\n */\n media?: Record<string, string>;\n}\n\n/** Orbit's logo, the page's icon. */\nconst ORBIT_ICON = \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='18 18 72 72'%3E%3Cdefs%3E%3CradialGradient id='d' gradientUnits='userSpaceOnUse' cx='32.4' cy='23.76' r='102.6'%3E%3Cstop offset='0' stop-color='%234A35A8'/%3E%3Cstop offset='1' stop-color='%2318134A'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect x='18' y='18' width='72' height='72' rx='16' fill='url(%23d)'/%3E%3Cpath d='M67.53,35.36 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M69.84,37.38 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M71.86,39.69 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M76.52,57.07 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M75.92,60.08 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M74.93,62.99 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M62.21,75.71 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M59.3,76.7 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M56.29,77.3 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M38.91,72.64 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M36.6,70.62 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M34.58,68.31 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M29.92,50.93 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M30.52,47.92 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M31.51,45.01 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M44.23,32.29 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M47.14,31.3 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M50.15,30.7 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z' fill='%23E2E6FF' fill-opacity='.5'/%3E%3Ccircle cx='54' cy='54' r='11' fill='%23FAD86F'/%3E%3Ccircle cx='60.08' cy='31.3' r='6.4' fill='%23FF9E96'/%3E%3Ccircle cx='76.7' cy='47.92' r='6.4' fill='%23F8B478'/%3E%3Ccircle cx='70.62' cy='70.62' r='6.4' fill='%237FDAAB'/%3E%3Ccircle cx='47.92' cy='76.7' r='6.4' fill='%2386CDFF'/%3E%3Ccircle cx='31.3' cy='60.08' r='6.4' fill='%23C9B1FE'/%3E%3Ccircle cx='37.38' cy='37.38' r='6.4' fill='%23F7A3D4'/%3E%3C/svg%3E\";\n\n/** What a web page carries for its script, as JSON in `#orbit-page`. */\nexport interface WebPageData {\n /** The map, in markdown or YAML. */\n source: string;\n\n theme?: string | OrbitRendererTheme;\n viewMode?: ViewMode;\n focus?: string;\n language?: string;\n strings?: Partial<OrbitStrings>;\n media: Record<string, string>;\n}\n\n/**\n * The map as one HTML page, with Orbit inside (`options.script`): open it in\n * any browser, offline, to explore the map or present it.\n *\n * ```ts\n * import { readFileSync } from 'node:fs';\n * import { exportWebPage } from '@restless-dreams/orbit';\n *\n * const script = readFileSync(new URL(import.meta.resolve('@restless-dreams/orbit/web-page.js')), 'utf8');\n * const html = exportWebPage(markdown, { script, theme: 'night' });\n * ```\n */\nexport const exportWebPage = (input: string | OrbitDocument, options: OrbitWebPageOptions): string => {\n const document = typeof input === 'string' ? parseOrbit(input) : input;\n const source = typeof input === 'string' ? input : serializeOrbitMarkdown(input);\n const words = new OrbitWords(options.language, options.strings);\n const title = options.title ?? (document.options.title || document.root.text || 'Orbit');\n const data: WebPageData = {\n source,\n theme: options.theme,\n viewMode: options.viewMode,\n focus: options.focus,\n language: options.language,\n strings: options.strings,\n media: options.media ?? {},\n };\n const theme = options.theme ?? document.options.theme;\n return `<!doctype html>\n<html lang=\"${escapeAttribute(words.locale)}\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, viewport-fit=cover\">\n<meta name=\"generator\" content=\"Orbit\">\n<link rel=\"icon\" href=\"${ORBIT_ICON}\">\n<title>${escapeText(title)}</title>\n<style>\n${pageStyles(theme)}\n</style>\n</head>\n<body>\n<div class=\"page\" id=\"page\">\n <div class=\"page__map\" id=\"page-map\" aria-label=\"${escapeAttribute(title)}\"></div>\n <button class=\"page__present\" type=\"button\" data-present><span aria-hidden=\"true\">▶</span> ${escapeText(words.text('present'))}</button>\n <section class=\"page__caption\" id=\"page-caption\" aria-live=\"polite\" hidden>\n <h1 class=\"page__title\" id=\"page-title\"></h1>\n <div class=\"page__note\" id=\"page-note\"></div>\n </section>\n <nav class=\"page__controls\" id=\"page-controls\" hidden>\n <button class=\"page__button\" type=\"button\" data-step=\"-1\" aria-label=\"${escapeAttribute(words.text('previous'))}\">‹</button>\n <span class=\"page__count\" id=\"page-count\"></span>\n <button class=\"page__button\" type=\"button\" data-step=\"1\" aria-label=\"${escapeAttribute(words.text('next'))}\">›</button>\n <button class=\"page__button\" type=\"button\" data-close aria-label=\"${escapeAttribute(words.text('close'))}\">✕</button>\n </nav>\n</div>\n<script type=\"application/json\" id=\"orbit-page\">${scriptJson(data)}</script>\n<script type=\"application/json\" id=\"orbit-script\">${scriptJson(options.script)}</script>\n<script>\n // Orbit runs from a script element made here: text inside one is never read as HTML.\n (function () {\n var script = document.createElement('script');\n script.textContent = JSON.parse(document.getElementById('orbit-script').textContent);\n document.body.appendChild(script);\n })();\n</script>\n</body>\n</html>\n`;\n};\n\n/** The colors the page takes from the theme: its background, and the caption's, from the detail sheet's. */\nconst pageColors = (tokens: OrbitThemeTokens): string => {\n const surface = tokens.surface === 'transparent' ? '#ffffff' : tokens.surface;\n return [\n `--page-background: ${surface};`,\n `--page-card: ${tokens['sheet-background']};`,\n `--page-text: ${tokens['sheet-text']};`,\n `--page-muted: ${tokens['sheet-muted-text']};`,\n `--page-border: ${tokens['sheet-border']};`,\n `--page-shadow: ${tokens['sheet-shadow']};`,\n ].join(' ');\n};\n\n/** The tokens a theme option stands for: a built-in theme's, with the option's own on top. */\nconst tokensOf = (theme: string | OrbitRendererTheme | undefined): OrbitThemeTokens => {\n const expanded = expandTheme(theme);\n const preset = typeof expanded === 'string' ? expanded : expanded?.preset;\n const base = themeTokens(isOrbitThemePreset(preset) ? preset : 'paper');\n return typeof expanded === 'object' && expanded?.tokens ? { ...base, ...expanded.tokens } as OrbitThemeTokens : base;\n};\n\nconst pageStyles = (theme: string | OrbitRendererTheme | undefined): string => {\n const automatic = (typeof theme === 'string' ? theme : theme?.preset) === 'auto';\n const colors = automatic\n ? `:root { ${pageColors(themeTokens('paper'))} }\\n@media (prefers-color-scheme: dark) { :root { ${pageColors(themeTokens('night'))} } }`\n : `:root { ${pageColors(tokensOf(theme))} }`;\n return `${colors}\nhtml, body { margin: 0; height: 100%; background: var(--page-background); }\nbody { font: 16px/1.5 system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif; color: var(--page-text); }\n.page__map { position: fixed; inset: 0; }\n.page__present, .page__controls {\n position: fixed; left: 50%; bottom: max(16px, env(safe-area-inset-bottom)); transform: translateX(-50%);\n display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 18px; border: 1px solid var(--page-border);\n border-radius: 22px; background: var(--page-card); color: var(--page-text); box-shadow: var(--page-shadow); font: inherit; font-weight: 600;\n}\n.page__present { cursor: pointer; }\n.page__controls { padding: 0 6px; transition: opacity 200ms ease; }\n.page__button { min-width: 44px; min-height: 44px; border: 0; border-radius: 22px; background: none; color: inherit; font: inherit; font-size: 20px; cursor: pointer; }\n.page__button:focus-visible, .page__present:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.page__count { min-width: 4em; text-align: center; color: var(--page-muted); font-variant-numeric: tabular-nums; }\n.page__caption {\n position: fixed; left: 50%; bottom: calc(max(16px, env(safe-area-inset-bottom)) + 60px); transform: translateX(-50%);\n box-sizing: border-box; width: min(720px, calc(100% - 32px)); max-height: 40vh; overflow: auto; padding: 16px 20px;\n border: 1px solid var(--page-border); border-radius: 16px; background: var(--page-card); color: var(--page-text); box-shadow: var(--page-shadow);\n}\n.page__title { margin: 0; font-size: 20px; line-height: 1.3; }\n.page__note:not(:empty) { margin-top: 8px; }\n.page__note p { margin: 0 0 8px; }\n.page__note img { max-width: 100%; border-radius: 8px; }\n.page__note a { color: inherit; }\n.page--presenting .page__present { display: none; }\n.page--presenting:not(.page--controls) .page__controls { opacity: 0; }\n.page--presenting:not(.page--controls) { cursor: none; }\n[hidden] { display: none !important; }`;\n};\n\n/** JSON inside a script element: `<` written as `\\\\u003c`, so nothing in it can end the element or open a comment. */\nconst scriptJson = (value: unknown): string => {\n return JSON.stringify(value).replace(/</g, '\\\\u003c').replace(/\\u2028/g, '\\\\u2028').replace(/\\u2029/g, '\\\\u2029');\n};\n\nconst escapeText = (text: string): string => {\n return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n};\n\nconst escapeAttribute = (text: string): string => {\n return escapeText(text).replace(/\"/g, '"');\n};\n",
|
|
43
|
+
"/**\n * A map as a web page: one HTML file with Orbit, the map and its pictures\n * inside, which opens in any browser, offline. Readers explore it with\n * Orbit's own controls, or present it: one idea at a time, in reading order,\n * with its note as a caption (see runtime.ts, the page's script). Printed,\n * it's the map laid out for paper (print-layout.ts) instead.\n */\n\nimport { parseOrbit } from '../dispatch.js';\nimport { serializeOrbitMarkdown } from '../serializer-markdown.js';\nimport { OrbitWords, type OrbitStrings } from '../languages.js';\nimport { expandTheme, isOrbitThemePreset, themeTokens, type OrbitThemeTokens } from '../themes.js';\nimport type { OrbitDocument, OrbitRendererTheme, ViewMode } from '../types.js';\n\nexport interface OrbitWebPageOptions {\n /**\n * Orbit's web page script, the file `@restless-dreams/orbit/web-page.js`,\n * as text. It goes inside the page, so the page needs nothing else.\n */\n script: string;\n\n /** The page's title. Default: the map's `title`, or its root's text. */\n title?: string;\n\n /** The map's theme, instead of its frontmatter's: a theme name or `{ preset, tokens }`. */\n theme?: string | OrbitRendererTheme;\n\n /** How the map opens: `focus` (default) or `all`, the overview. */\n viewMode?: ViewMode;\n\n /** The node in focus when the map opens, by id. Default: the root. */\n focus?: string;\n\n /** The language of the page and the map's words: a tag like `es`. Default: English. */\n language?: string;\n\n /** Single words to change: `{ present: 'Show' }`. */\n strings?: Partial<OrbitStrings>;\n\n /**\n * Pictures to put inside the page, by the address the map gives them:\n * `{ 'photos/summit.jpg': 'data:image/jpeg;base64,…' }`. A node's picture,\n * a video's thumbnail and pictures in notes are swapped for them, so they\n * show wherever the page goes.\n */\n media?: Record<string, string>;\n}\n\n/** Orbit's logo, the page's icon. */\nconst ORBIT_ICON = \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='18 18 72 72'%3E%3Cdefs%3E%3CradialGradient id='d' gradientUnits='userSpaceOnUse' cx='32.4' cy='23.76' r='102.6'%3E%3Cstop offset='0' stop-color='%234A35A8'/%3E%3Cstop offset='1' stop-color='%2318134A'/%3E%3C/radialGradient%3E%3C/defs%3E%3Crect x='18' y='18' width='72' height='72' rx='16' fill='url(%23d)'/%3E%3Cpath d='M67.53,35.36 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M69.84,37.38 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M71.86,39.69 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M76.52,57.07 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M75.92,60.08 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M74.93,62.99 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M62.21,75.71 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M59.3,76.7 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M56.29,77.3 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M38.91,72.64 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M36.6,70.62 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M34.58,68.31 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M29.92,50.93 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M30.52,47.92 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M31.51,45.01 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M44.23,32.29 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M47.14,31.3 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z M50.15,30.7 a0.78,0.78 0 1,0 1.56,0 a0.78,0.78 0 1,0 -1.56,0 Z' fill='%23E2E6FF' fill-opacity='.5'/%3E%3Ccircle cx='54' cy='54' r='11' fill='%23FAD86F'/%3E%3Ccircle cx='60.08' cy='31.3' r='6.4' fill='%23FF9E96'/%3E%3Ccircle cx='76.7' cy='47.92' r='6.4' fill='%23F8B478'/%3E%3Ccircle cx='70.62' cy='70.62' r='6.4' fill='%237FDAAB'/%3E%3Ccircle cx='47.92' cy='76.7' r='6.4' fill='%2386CDFF'/%3E%3Ccircle cx='31.3' cy='60.08' r='6.4' fill='%23C9B1FE'/%3E%3Ccircle cx='37.38' cy='37.38' r='6.4' fill='%23F7A3D4'/%3E%3C/svg%3E\";\n\n/** What a web page carries for its script, as JSON in `#orbit-page`. */\nexport interface WebPageData {\n /** The map, in markdown or YAML. */\n source: string;\n\n theme?: string | OrbitRendererTheme;\n viewMode?: ViewMode;\n focus?: string;\n language?: string;\n strings?: Partial<OrbitStrings>;\n media: Record<string, string>;\n}\n\n/**\n * The map as one HTML page, with Orbit inside (`options.script`): open it in\n * any browser, offline, to explore the map or present it.\n *\n * ```ts\n * import { readFileSync } from 'node:fs';\n * import { exportWebPage } from '@restless-dreams/orbit';\n *\n * const script = readFileSync(new URL(import.meta.resolve('@restless-dreams/orbit/web-page.js')), 'utf8');\n * const html = exportWebPage(markdown, { script, theme: 'night' });\n * ```\n */\nexport const exportWebPage = (input: string | OrbitDocument, options: OrbitWebPageOptions): string => {\n const document = typeof input === 'string' ? parseOrbit(input) : input;\n const source = typeof input === 'string' ? input : serializeOrbitMarkdown(input);\n const words = new OrbitWords(options.language, options.strings);\n const title = options.title ?? (document.options.title || document.root.text || 'Orbit');\n const data: WebPageData = {\n source,\n theme: options.theme,\n viewMode: options.viewMode,\n focus: options.focus,\n language: options.language,\n strings: options.strings,\n media: options.media ?? {},\n };\n const theme = options.theme ?? document.options.theme;\n return `<!doctype html>\n<html lang=\"${escapeAttribute(words.locale)}\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, viewport-fit=cover\">\n<meta name=\"generator\" content=\"Orbit\">\n<link rel=\"icon\" href=\"${ORBIT_ICON}\">\n<title>${escapeText(title)}</title>\n<style>\n${pageStyles(theme)}\n</style>\n</head>\n<body>\n<div class=\"page\" id=\"page\">\n <div class=\"page__map\" id=\"page-map\" aria-label=\"${escapeAttribute(title)}\"></div>\n <button class=\"page__present\" type=\"button\" data-present><span aria-hidden=\"true\">▶</span> ${escapeText(words.text('present'))}</button>\n <section class=\"page__caption\" id=\"page-caption\" aria-live=\"polite\" hidden>\n <h1 class=\"page__title\" id=\"page-title\"></h1>\n <div class=\"page__note\" id=\"page-note\"></div>\n </section>\n <nav class=\"page__controls\" id=\"page-controls\" hidden>\n <button class=\"page__button\" type=\"button\" data-step=\"-1\" aria-label=\"${escapeAttribute(words.text('previous'))}\">‹</button>\n <span class=\"page__count\" id=\"page-count\"></span>\n <button class=\"page__button\" type=\"button\" data-step=\"1\" aria-label=\"${escapeAttribute(words.text('next'))}\">›</button>\n <button class=\"page__button\" type=\"button\" data-close aria-label=\"${escapeAttribute(words.text('close'))}\">✕</button>\n </nav>\n</div>\n<div class=\"page__print\" id=\"page-print\"></div>\n<script type=\"application/json\" id=\"orbit-page\">${scriptJson(data)}</script>\n<script type=\"application/json\" id=\"orbit-script\">${scriptJson(options.script)}</script>\n<script>\n // Orbit runs from a script element made here: text inside one is never read as HTML.\n (function () {\n var script = document.createElement('script');\n script.textContent = JSON.parse(document.getElementById('orbit-script').textContent);\n document.body.appendChild(script);\n })();\n</script>\n</body>\n</html>\n`;\n};\n\n/** The colors the page takes from the theme: its background, and the caption's, from the detail sheet's. */\nconst pageColors = (tokens: OrbitThemeTokens): string => {\n const surface = tokens.surface === 'transparent' ? '#ffffff' : tokens.surface;\n return [\n `--page-background: ${surface};`,\n `--page-card: ${tokens['sheet-background']};`,\n `--page-text: ${tokens['sheet-text']};`,\n `--page-muted: ${tokens['sheet-muted-text']};`,\n `--page-border: ${tokens['sheet-border']};`,\n `--page-shadow: ${tokens['sheet-shadow']};`,\n ].join(' ');\n};\n\n/** The tokens a theme option stands for: a built-in theme's, with the option's own on top. */\nconst tokensOf = (theme: string | OrbitRendererTheme | undefined): OrbitThemeTokens => {\n const expanded = expandTheme(theme);\n const preset = typeof expanded === 'string' ? expanded : expanded?.preset;\n const base = themeTokens(isOrbitThemePreset(preset) ? preset : 'paper');\n return typeof expanded === 'object' && expanded?.tokens ? { ...base, ...expanded.tokens } as OrbitThemeTokens : base;\n};\n\nconst pageStyles = (theme: string | OrbitRendererTheme | undefined): string => {\n const automatic = (typeof theme === 'string' ? theme : theme?.preset) === 'auto';\n const colors = automatic\n ? `:root { ${pageColors(themeTokens('paper'))} }\\n@media (prefers-color-scheme: dark) { :root { ${pageColors(themeTokens('night'))} } }`\n : `:root { ${pageColors(tokensOf(theme))} }`;\n return `${colors}\nhtml, body { margin: 0; height: 100%; background: var(--page-background); }\nbody { font: 16px/1.5 system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif; color: var(--page-text); }\n.page__map { position: fixed; inset: 0; }\n.page__present, .page__controls {\n position: fixed; left: 50%; bottom: max(16px, env(safe-area-inset-bottom)); transform: translateX(-50%);\n display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 18px; border: 1px solid var(--page-border);\n border-radius: 22px; background: var(--page-card); color: var(--page-text); box-shadow: var(--page-shadow); font: inherit; font-weight: 600;\n}\n.page__present { cursor: pointer; }\n.page__controls { padding: 0 6px; transition: opacity 200ms ease; }\n.page__button { min-width: 44px; min-height: 44px; border: 0; border-radius: 22px; background: none; color: inherit; font: inherit; font-size: 20px; cursor: pointer; }\n.page__button:focus-visible, .page__present:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.page__count { min-width: 4em; text-align: center; color: var(--page-muted); font-variant-numeric: tabular-nums; }\n.page__caption {\n position: fixed; left: 50%; bottom: calc(max(16px, env(safe-area-inset-bottom)) + 60px); transform: translateX(-50%);\n box-sizing: border-box; width: min(720px, calc(100% - 32px)); max-height: 40vh; overflow: auto; padding: 16px 20px;\n border: 1px solid var(--page-border); border-radius: 16px; background: var(--page-card); color: var(--page-text); box-shadow: var(--page-shadow);\n}\n.page__title { margin: 0; font-size: 20px; line-height: 1.3; }\n.page__note:not(:empty) { margin-top: 8px; }\n.page__note p { margin: 0 0 8px; }\n.page__note img { max-width: 100%; border-radius: 8px; }\n.page__note a { color: inherit; }\n.page--presenting .page__present { display: none; }\n.page--presenting:not(.page--controls) .page__controls { opacity: 0; }\n.page--presenting:not(.page--controls) { cursor: none; }\n[hidden] { display: none !important; }\n.page__print { display: none; }\n@media print {\n @page { margin: 16mm 14mm; }\n html, body { height: auto; background: #ffffff; }\n .page { display: none; }\n .page__print { display: block; }\n}`;\n};\n\n/** JSON inside a script element: `<` written as `\\\\u003c`, so nothing in it can end the element or open a comment. */\nconst scriptJson = (value: unknown): string => {\n return JSON.stringify(value).replace(/</g, '\\\\u003c').replace(/\\u2028/g, '\\\\u2028').replace(/\\u2029/g, '\\\\u2029');\n};\n\nconst escapeText = (text: string): string => {\n return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n};\n\nconst escapeAttribute = (text: string): string => {\n return escapeText(text).replace(/\"/g, '"');\n};\n",
|
|
44
|
+
"/**\n * Other apps' icons and markers, as Orbit says the same thing: an emoji for\n * the idea's icon, a priority, or a status. An icon with no meaning here\n * returns null, and the reader warns that it was left out.\n */\n\nexport type IconMeaning = { icon: string } | { priority: number } | { status: string };\n\n/** FreeMind's and Freeplane's built-in icons, by name. */\nconst FREEMIND_ICONS = new Map<string, string>(Object.entries({\n idea: '💡', help: '❓', yes: '❗', messagebox_warning: '⚠️', info: 'ℹ️', 'stop-sign': '🛑', closed: '⛔',\n button_ok: '✅', button_cancel: '❌', stop: '🔴', prepare: '🟡', go: '🟢',\n back: '⬅️', forward: '➡️', up: '⬆️', down: '⬇️', attach: '📎', ksmiletris: '🙂', 'smiley-neutral': '😐', 'smiley-oh': '😮',\n 'smiley-angry': '😠', smily_bad: '😞', clanbomber: '💣', desktop_new: '📌', flag: '🚩', 'flag-black': '🏴', 'flag-blue': '🚩',\n 'flag-green': '🚩', 'flag-orange': '🚩', 'flag-pink': '🚩', 'flag-yellow': '🚩', gohome: '🏠', folder: '📁', korn: '📫', Mail: '✉️',\n kmail: '📧', list: '📋', edit: '✏️', pencil: '✏️', kaddressbook: '☎️', knotify: '🎵', password: '🔑', encrypted: '🔒', decrypted: '🔓',\n wizard: '🪄', xmag: '🔍', bell: '🔔', bookmark: '🔖', penguin: '🐧', licq: '🌸', freemind_butterfly: '🦋', 'broken-line': '💔',\n calendar: '📅', clock: '⏰', hourglass: '⏳', launch: '🚀', family: '👪', female1: '👩', female2: '👩', male1: '👨', male2: '👨',\n fema: '👫', group: '👥', bee: '🐝', mindmap: '🗺️', unchecked: '⬜', checked: '✅',\n}));\n\n/** Freeplane's progress icons, as statuses. */\nconst FREEMIND_PROGRESS = new Map<string, string>(Object.entries({ '0%': 'todo', '25%': 'active', '50%': 'active', '75%': 'active', '100%': 'done', checked: 'done', unchecked: 'todo' }));\n\n/** A FreeMind or Freeplane icon's meaning: `full-3` is priority 3, `100%` done, `emoji-1F680` 🚀. */\nexport const freeMindIcon = (name: string): IconMeaning | null => {\n const priority = /^full-(\\d)$/.exec(name);\n\n if (priority) {\n return { priority: Number(priority[1]) };\n }\n\n const progress = FREEMIND_PROGRESS.get(name);\n\n if (progress) {\n return { status: progress };\n }\n\n const emoji = /^emoji-([0-9A-Fa-f]{2,6}(?:-[0-9A-Fa-f]{2,6})*)$/.exec(name);\n\n if (emoji) {\n const codes = emoji[1].split('-').map((code) => parseInt(code, 16));\n\n if (codes.every((code) => code > 0 && code <= 0x10ffff)) {\n return { icon: String.fromCodePoint(...codes) };\n }\n }\n\n const icon = FREEMIND_ICONS.get(name);\n return icon ? { icon } : null;\n};\n\n/** XMind's markers, by the name after their family: `smiley-laugh`, `arrow-up`. */\nconst XMIND_MARKERS = new Map<string, string>(Object.entries({\n 'smiley-smile': '🙂', 'smiley-laugh': '😄', 'smiley-angry': '😠', 'smiley-cry': '😢', 'smiley-surprise': '😮', 'smiley-boring': '😐',\n 'arrow-up': '⬆️', 'arrow-down': '⬇️', 'arrow-left': '⬅️', 'arrow-right': '➡️', 'arrow-up-right': '↗️', 'arrow-down-right': '↘️',\n 'arrow-down-left': '↙️', 'arrow-up-left': '↖️', 'arrow-refresh': '🔄',\n 'symbol-plus': '➕', 'symbol-minus': '➖', 'symbol-question': '❓', 'symbol-exclam': '❗', 'symbol-info': 'ℹ️', 'symbol-wrong': '❌',\n 'symbol-right': '✅', 'symbol-attention': '⚠️', 'symbol-code': '💻', 'symbol-pin': '📌', 'symbol-heart': '❤️', 'symbol-star': '⭐',\n 'other-calendar': '📅', 'other-email': '✉️', 'other-phone': '☎️', 'other-question': '❓', 'other-exclam': '❗', 'other-lightbulb': '💡',\n 'other-clock': '⏰', 'other-people': '👥', 'other-money': '💰', 'other-books': '📚', 'other-music': '🎵', 'other-yes': '👍', 'other-no': '👎',\n 'other-hourglass': '⏳', 'other-flag': '🚩', 'other-star': '⭐', 'other-coffee-cup': '☕', 'other-bomb': '💣', 'other-mic': '🎤',\n 'other-phone-call': '📞', 'other-map': '🗺️', 'other-code': '💻', 'other-search': '🔍', 'other-dollar': '💵', 'other-heart': '❤️',\n c_symbol_like: '👍', c_symbol_dislike: '👎', c_symbol_heart: '❤️', c_symbol_star: '⭐', c_symbol_question: '❓', c_symbol_exclam: '❗',\n c_symbol_pin: '📌', c_symbol_idea: '💡', c_symbol_check: '✅', c_symbol_cross: '❌', c_symbol_fire: '🔥', c_symbol_trophy: '🏆',\n}));\n\n/** Marker families whose every color shows the same emoji. */\nconst XMIND_FAMILIES = new Map<string, string>(Object.entries({\n flag: '🚩', star: '⭐', people: '👤', tag: '🏷️', month: '📅', week: '📅', 'half-star': '⭐',\n}));\n\nconst XMIND_TASKS = new Map<string, string>(Object.entries({\n 'task-start': 'todo', 'task-oct': 'active', 'task-quarter': 'active', 'task-3oct': 'active', 'task-half': 'active', 'task-5oct': 'active',\n 'task-3quar': 'active', 'task-7oct': 'active', 'task-done': 'done', 'task-pause': 'paused',\n}));\n\n/** An XMind marker's meaning: `priority-2` is priority 2, `task-done` done, `flag-red` 🚩. */\nexport const xmindMarker = (markerId: string): IconMeaning | null => {\n const priority = /^priority-(\\d)$/.exec(markerId);\n\n if (priority) {\n return { priority: Number(priority[1]) };\n }\n\n const status = XMIND_TASKS.get(markerId);\n\n if (status) {\n return { status };\n }\n\n const icon = XMIND_MARKERS.get(markerId);\n\n if (icon) {\n return { icon };\n }\n\n const family = [...XMIND_FAMILIES.keys()].sort((first, second) => second.length - first.length).find((name) => markerId.startsWith(`${name}-`));\n return family ? { icon: XMIND_FAMILIES.get(family) as string } : null;\n};\n",
|
|
45
|
+
"/**\n * A small XML reader for other apps' map files, and a forgiving reader for\n * the HTML in their notes. Neither loads anything a file points to: XML\n * reads its five entities and numeric references only, HTML adds a fixed\n * table of common named ones, a DOCTYPE is skipped without reading what it\n * declares, and the size of the input and the depth of nesting are capped.\n */\n\nexport interface MarkupElement {\n /** The element's name as written, with its prefix: `xhtml:p`. */\n name: string;\n\n /** The name without a prefix, lowercased in HTML: `p`. */\n localName: string;\n\n /** Attributes by name as written, values decoded. */\n attributes: Record<string, string>;\n\n children: MarkupNode[];\n}\n\n/** An element, or text. */\nexport type MarkupNode = MarkupElement | string;\n\n/** A file that isn't well-formed XML, or too big or too deep to read. */\nexport class MarkupError extends Error {\n /** The 1-based line of the problem. */\n readonly line: number;\n\n constructor(message: string, line: number) {\n super(`${message} (line ${line})`);\n this.name = 'MarkupError';\n this.line = line;\n }\n}\n\n/** The most characters a file may have: far beyond any map, short of exhausting memory. */\nexport const MAX_MARKUP_LENGTH = 64 * 1024 * 1024;\n\n/** The deepest nesting read: deeper files are refused rather than risking the stack. */\nexport const MAX_MARKUP_DEPTH = 1000;\n\nconst XML_ENTITIES: Record<string, string> = { lt: '<', gt: '>', amp: '&', quot: '\"', apos: \"'\" };\n\n/** Named character references HTML notes use beyond XML's five. */\nconst HTML_ENTITIES: Record<string, string> = {\n ...XML_ENTITIES,\n nbsp: '\\u00a0', copy: '©', reg: '®', trade: '™', hellip: '…', mdash: '—', ndash: '–', lsquo: '‘', rsquo: '’', ldquo: '“', rdquo: '”',\n laquo: '«', raquo: '»', bull: '•', middot: '·', deg: '°', plusmn: '±', times: '×', divide: '÷', euro: '€', pound: '£', yen: '¥', cent: '¢',\n sect: '§', para: '¶', iexcl: '¡', iquest: '¿', ordf: 'ª', ordm: 'º', acute: '´', uml: '¨', shy: '\\u00ad', frac12: '½', frac14: '¼', frac34: '¾',\n sup1: '¹', sup2: '²', sup3: '³', micro: 'µ', larr: '←', rarr: '→', uarr: '↑', darr: '↓', harr: '↔', rArr: '⇒', lArr: '⇐', hArr: '⇔',\n aacute: 'á', eacute: 'é', iacute: 'í', oacute: 'ó', uacute: 'ú', yacute: 'ý', Aacute: 'Á', Eacute: 'É', Iacute: 'Í', Oacute: 'Ó', Uacute: 'Ú', Yacute: 'Ý',\n agrave: 'à', egrave: 'è', igrave: 'ì', ograve: 'ò', ugrave: 'ù', Agrave: 'À', Egrave: 'È', Igrave: 'Ì', Ograve: 'Ò', Ugrave: 'Ù',\n acirc: 'â', ecirc: 'ê', icirc: 'î', ocirc: 'ô', ucirc: 'û', Acirc: 'Â', Ecirc: 'Ê', Icirc: 'Î', Ocirc: 'Ô', Ucirc: 'Û',\n auml: 'ä', euml: 'ë', iuml: 'ï', ouml: 'ö', uuml: 'ü', yuml: 'ÿ', Auml: 'Ä', Euml: 'Ë', Iuml: 'Ï', Ouml: 'Ö', Uuml: 'Ü',\n atilde: 'ã', otilde: 'õ', ntilde: 'ñ', Atilde: 'Ã', Otilde: 'Õ', Ntilde: 'Ñ', ccedil: 'ç', Ccedil: 'Ç', aring: 'å', Aring: 'Å',\n aelig: 'æ', AElig: 'Æ', oslash: 'ø', Oslash: 'Ø', szlig: 'ß', thorn: 'þ', THORN: 'Þ', eth: 'ð', ETH: 'Ð', oelig: 'œ', OElig: 'Œ',\n};\n\n/** Elements HTML never closes. */\nconst VOID_ELEMENTS = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr']);\n\n/** Elements whose content is code to run or styles, not text to keep. */\nconst RAW_TEXT_ELEMENTS = new Set(['script', 'style']);\n\nconst NAME = /^[^\\s/>=]+/;\nconst ATTRIBUTE = /([^\\s=/>]+)(?:\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'>]+)))?/y;\n\ninterface ReadingMode {\n html: boolean;\n}\n\n/**\n * An XML file's bytes as text, in the encoding its byte order mark or its\n * declaration names (UTF-8 when neither does). Old OPML files are often\n * ISO-8859-1. A file that isn't valid UTF-8 and names no encoding is read as\n * Windows-1252, which every byte is.\n */\nexport const decodeMarkup = (bytes: Uint8Array): string => {\n if (bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf) {\n return new TextDecoder('utf-8').decode(bytes.subarray(3));\n }\n\n if (bytes[0] === 0xff && bytes[1] === 0xfe) {\n return new TextDecoder('utf-16le').decode(bytes.subarray(2));\n }\n\n if (bytes[0] === 0xfe && bytes[1] === 0xff) {\n return new TextDecoder('utf-16be').decode(bytes.subarray(2));\n }\n\n // UTF-16 without a byte order mark still starts \"<?xml\": every other byte is zero.\n if (bytes[0] === 0x3c && bytes[1] === 0x00) {\n return new TextDecoder('utf-16le').decode(bytes);\n }\n\n if (bytes[0] === 0x00 && bytes[1] === 0x3c) {\n return new TextDecoder('utf-16be').decode(bytes);\n }\n\n const start = String.fromCharCode(...bytes.subarray(0, 200));\n const declared = /^\\s*<\\?xml[^>]*\\bencoding\\s*=\\s*[\"']([A-Za-z0-9._:-]+)[\"']/.exec(start)?.[1];\n\n if (declared && !/^utf-?8$/i.test(declared)) {\n try {\n return new TextDecoder(declared).decode(bytes);\n } catch {\n // An encoding this browser can't decode: read the file as UTF-8 below.\n }\n }\n\n try {\n return new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n } catch {\n return new TextDecoder(declared ? 'utf-8' : 'windows-1252').decode(bytes);\n }\n};\n\n/**\n * The document element of an XML file. Throws a `MarkupError` for a file\n * that isn't well-formed, so a damaged map is refused rather than read in part.\n */\nexport const parseXml = (text: string): MarkupElement => {\n const root = readMarkup(text, { html: false });\n const elements = root.children.filter(isElement);\n\n if (elements.length !== 1) {\n throw new MarkupError(elements.length === 0 ? 'No element in the file' : 'More than one top element', 1);\n }\n\n return elements[0];\n};\n\n/** A piece of HTML, as the children of an element named `#fragment`. Never throws for markup it can read some way. */\nexport const parseHtml = (text: string): MarkupElement => {\n return readMarkup(text, { html: true });\n};\n\nexport const isElement = (node: MarkupNode): node is MarkupElement => {\n return typeof node !== 'string';\n};\n\n/** The element's child elements, all of them or those with one local name. */\nexport const childElements = (element: MarkupElement, localName?: string): MarkupElement[] => {\n return element.children.filter((child): child is MarkupElement => isElement(child) && (localName === undefined || child.localName === localName));\n};\n\n/** The element's first child element with this local name. */\nexport const childElement = (element: MarkupElement, localName: string): MarkupElement | undefined => {\n return element.children.find((child): child is MarkupElement => isElement(child) && child.localName === localName);\n};\n\n/** An attribute by its name without a prefix: `href` finds `xlink:href`. */\nexport const attributeOf = (element: MarkupElement, localName: string): string | undefined => {\n if (Object.prototype.hasOwnProperty.call(element.attributes, localName)) {\n return element.attributes[localName];\n }\n\n for (const [name, value] of Object.entries(element.attributes)) {\n if (localPart(name) === localName) {\n return value;\n }\n }\n\n return undefined;\n};\n\n/** All the text inside an element, as written. */\nexport const textContent = (node: MarkupNode): string => {\n if (!isElement(node)) {\n return node;\n }\n\n let text = '';\n const pending: MarkupNode[] = [node];\n\n while (pending.length > 0) {\n const next = pending.pop() as MarkupNode;\n\n if (isElement(next)) {\n for (let index = next.children.length - 1; index >= 0; index--) {\n pending.push(next.children[index]);\n }\n } else {\n text += next;\n }\n }\n\n return text;\n};\n\nconst localPart = (name: string): string => {\n const colon = name.indexOf(':');\n return colon === -1 ? name : name.slice(colon + 1);\n};\n\nconst lineAt = (text: string, index: number): number => {\n let line = 1;\n\n for (let position = text.indexOf('\\n'); position !== -1 && position < index; position = text.indexOf('\\n', position + 1)) {\n line += 1;\n }\n\n return line;\n};\n\nconst readMarkup = (input: string, mode: ReadingMode): MarkupElement => {\n if (input.length > MAX_MARKUP_LENGTH) {\n throw new MarkupError(`The file is larger than ${MAX_MARKUP_LENGTH / 1024 / 1024} MB of text`, 1);\n }\n\n // XML reads every line break as a line feed.\n const text = input.replace(/^\\ufeff/, '').replace(/\\r\\n?/g, '\\n');\n const fragment: MarkupElement = { name: '#fragment', localName: '#fragment', attributes: {}, children: [] };\n const open: MarkupElement[] = [fragment];\n const entities = mode.html ? HTML_ENTITIES : XML_ENTITIES;\n let index = 0;\n\n const fail = (message: string, at: number): never => {\n throw new MarkupError(message, lineAt(text, at));\n };\n\n const current = (): MarkupElement => open[open.length - 1];\n\n const addText = (value: string): void => {\n if (value === '') {\n return;\n }\n\n const children = current().children;\n const last = children.length - 1;\n\n if (last >= 0 && typeof children[last] === 'string') {\n children[last] = (children[last] as string) + value;\n } else {\n children.push(value);\n }\n };\n\n while (index < text.length) {\n const tag = text.indexOf('<', index);\n\n if (tag === -1) {\n addText(decodeEntities(text.slice(index), entities));\n break;\n }\n\n if (tag > index) {\n addText(decodeEntities(text.slice(index, tag), entities));\n }\n\n index = tag;\n\n if (text.startsWith('<!--', index)) {\n const end = text.indexOf('-->', index + 4);\n\n if (end === -1) {\n if (mode.html) {\n break;\n }\n\n fail('A comment that never ends', index);\n }\n\n index = end + 3;\n continue;\n }\n\n if (text.startsWith('<![CDATA[', index)) {\n const end = text.indexOf(']]>', index + 9);\n\n if (end === -1) {\n fail('A CDATA section that never ends', index);\n }\n\n addText(text.slice(index + 9, end));\n index = end + 3;\n continue;\n }\n\n if (text.startsWith('<?', index)) {\n const end = text.indexOf('?>', index + 2);\n\n if (end === -1) {\n fail('A processing instruction that never ends', index);\n }\n\n index = end + 2;\n continue;\n }\n\n if (text.startsWith('<!', index)) {\n // A DOCTYPE, its internal subset included: skipped, never read.\n index = skipDeclaration(text, index, fail);\n continue;\n }\n\n if (text.startsWith('</', index)) {\n const end = text.indexOf('>', index + 2);\n\n if (end === -1) {\n fail('An end tag that never closes', index);\n }\n\n const name = text.slice(index + 2, end).trim();\n closeElement(open, name, mode, () => fail(`</${name}> doesn't match <${current().name}>`, index));\n index = end + 1;\n continue;\n }\n\n const nameMatch = NAME.exec(text.slice(index + 1, index + 257));\n\n if (!nameMatch || !/^[\\p{L}_:]/u.test(nameMatch[0])) {\n if (mode.html) {\n // A lone \"<\" in HTML is text.\n addText('<');\n index += 1;\n continue;\n }\n\n fail('A \"<\" that starts no tag', index);\n }\n\n const name = (nameMatch as RegExpExecArray)[0];\n const [attributes, afterAttributes, selfClosing] = readAttributes(text, index + 1 + name.length, entities, mode, fail);\n const localName = mode.html ? localPart(name).toLowerCase() : localPart(name);\n const element: MarkupElement = { name, localName, attributes, children: [] };\n current().children.push(element);\n index = afterAttributes;\n\n if (mode.html && RAW_TEXT_ELEMENTS.has(localName)) {\n // Code and styles are left out, up to their end tag.\n const end = text.toLowerCase().indexOf(`</${localName}`, index);\n index = end === -1 ? text.length : text.indexOf('>', end) + 1 || text.length;\n continue;\n }\n\n if (selfClosing || (mode.html && VOID_ELEMENTS.has(localName))) {\n continue;\n }\n\n if (open.length > MAX_MARKUP_DEPTH) {\n fail(`Elements nested more than ${MAX_MARKUP_DEPTH} deep`, index);\n }\n\n open.push(element);\n }\n\n if (!mode.html && open.length > 1) {\n fail(`<${current().name}> is never closed`, text.length);\n }\n\n return fragment;\n};\n\n/** Reads a tag's attributes up to its `>`: the attributes, where the tag ends, and whether it closed itself. */\nconst readAttributes = (\n text: string,\n start: number,\n entities: Record<string, string>,\n mode: ReadingMode,\n fail: (message: string, at: number) => never,\n): [Record<string, string>, number, boolean] => {\n const attributes: Record<string, string> = {};\n let index = start;\n\n while (index < text.length) {\n while (index < text.length && /\\s/.test(text[index])) {\n index += 1;\n }\n\n if (text[index] === '>') {\n return [attributes, index + 1, false];\n }\n\n if (text.startsWith('/>', index)) {\n return [attributes, index + 2, true];\n }\n\n if (text[index] === '/') {\n index += 1;\n continue;\n }\n\n ATTRIBUTE.lastIndex = index;\n const match = ATTRIBUTE.exec(text);\n\n if (!match || match[0].length === 0) {\n fail('A tag that never closes', start);\n }\n\n const [whole, name, doubleQuoted, singleQuoted, unquoted] = match as RegExpExecArray;\n\n if (unquoted !== undefined && !mode.html) {\n fail(`The value of ${name} has no quotes`, index);\n }\n\n const raw = doubleQuoted ?? singleQuoted ?? unquoted ?? '';\n // XML reads tabs and line breaks written in a value as spaces; stays a line break.\n attributes[name] = decodeEntities(mode.html ? raw : raw.replace(/[\\t\\n]/g, ' '), entities);\n index += whole.length;\n }\n\n return fail('A tag that never closes', start);\n};\n\nconst skipDeclaration = (text: string, start: number, fail: (message: string, at: number) => never): number => {\n let depth = 0;\n let quote: string | null = null;\n\n for (let index = start + 2; index < text.length; index++) {\n const character = text[index];\n\n if (quote) {\n if (character === quote) {\n quote = null;\n }\n } else if (character === '\"' || character === \"'\") {\n quote = character;\n } else if (character === '[') {\n depth += 1;\n } else if (character === ']') {\n depth -= 1;\n } else if (character === '>' && depth <= 0) {\n return index + 1;\n }\n }\n\n return fail('A declaration that never ends', start);\n};\n\nconst closeElement = (open: MarkupElement[], name: string, mode: ReadingMode, mismatch: () => never): void => {\n const top = open[open.length - 1];\n\n if (open.length > 1 && (top.name === name || (mode.html && top.localName === localPart(name).toLowerCase()))) {\n open.pop();\n return;\n }\n\n if (!mode.html) {\n mismatch();\n }\n\n // HTML closes what's open up to the element the end tag names, and ignores one that names none.\n const wanted = localPart(name).toLowerCase();\n\n for (let depth = open.length - 1; depth > 0; depth--) {\n if (open[depth].localName === wanted) {\n open.length = depth;\n return;\n }\n }\n};\n\n/** Text with its character references read: numeric ones, and the named ones in `entities`; any other stays as written. */\nconst decodeEntities = (text: string, entities: Record<string, string>): string => {\n if (!text.includes('&')) {\n return text;\n }\n\n return text.replace(/&(#[xX][0-9a-fA-F]{1,6}|#[0-9]{1,7}|[A-Za-z][A-Za-z0-9]{1,31});/g, (whole, reference: string) => {\n if (reference.startsWith('#')) {\n const code = reference[1] === 'x' || reference[1] === 'X' ? parseInt(reference.slice(2), 16) : parseInt(reference.slice(1), 10);\n return code > 0 && code <= 0x10ffff && !(code >= 0xd800 && code <= 0xdfff) ? String.fromCodePoint(code) : whole;\n }\n\n return Object.prototype.hasOwnProperty.call(entities, reference) ? entities[reference] : whole;\n });\n};\n",
|
|
46
|
+
"/**\n * Notes and titles from other apps. HTML notes become markdown (paragraphs,\n * headings, lists, quotes, code, bold, italic, strikethrough, links and\n * pictures), never HTML. When markdown would show the note's text any other\n * way (a `*` or `_` in it, a line that starts like a list), the note is kept\n * as plain text instead, exactly as written: formatting can be lost, words\n * never are.\n */\n\nimport { childElements, isElement, parseHtml, textContent, type MarkupElement, type MarkupNode } from './markup.js';\n\n/** A note as Orbit keeps it. */\nexport interface ImportedNote {\n text: string;\n format: 'markdown' | 'plain';\n}\n\n/** Inline content, as the note's reader shows it. */\nexport type NoteInline =\n | { kind: 'text'; text: string }\n | { kind: 'break' }\n | { kind: 'strong' | 'emphasis' | 'strike'; children: NoteInline[] }\n | { kind: 'code'; text: string }\n | { kind: 'link'; href: string; children: NoteInline[] }\n | { kind: 'image'; src: string; alt: string };\n\n/** A block of a note. */\nexport type NoteBlock =\n | { kind: 'paragraph'; inline: NoteInline[] }\n | { kind: 'heading'; level: number; inline: NoteInline[] }\n | { kind: 'list'; ordered: boolean; items: NoteBlock[][] }\n | { kind: 'quote'; blocks: NoteBlock[] }\n | { kind: 'code'; text: string };\n\n/** How addresses in a note are kept. */\nexport interface NoteAddresses {\n /** The address a link keeps, or null for its text alone. Default: web and mail addresses, and `#` links. */\n link?: (href: string) => string | null;\n\n /** The address a picture keeps, or null for its description alone. Default: web addresses. */\n picture?: (src: string) => string | null;\n}\n\nconst BLOCK_CONTAINERS = new Set([\n 'html', 'body', 'div', 'p', 'section', 'article', 'header', 'footer', 'main', 'aside', 'nav', 'center', 'figure', 'figcaption',\n 'address', 'details', 'summary', 'dl', 'dt', 'dd', 'form', 'fieldset', 'tbody', 'thead', 'tfoot', 'caption', '#fragment',\n]);\nconst SKIPPED = new Set(['head', 'title', 'script', 'style', 'meta', 'link', 'template', 'object', 'iframe', 'svg', 'math']);\nconst HEADINGS = new Map<string, number>([['h1', 1], ['h2', 2], ['h3', 3], ['h4', 4], ['h5', 5], ['h6', 6]]);\nconst INLINE_KINDS = new Map<string, 'strong' | 'emphasis' | 'strike'>([\n ['strong', 'strong'], ['b', 'strong'], ['em', 'emphasis'], ['i', 'emphasis'], ['cite', 'emphasis'], ['s', 'strike'], ['strike', 'strike'], ['del', 'strike'],\n]);\nconst CODE_ELEMENTS = new Set(['code', 'tt', 'kbd', 'samp', 'var']);\n\n/** Web and mail addresses, and links within the map. */\nexport const isKeptLink = (href: string): boolean => {\n return /^(https?:\\/\\/|mailto:)\\S+$/i.test(href) || /^#\\S+$/.test(href);\n};\n\n/** An address as a link keeps it: `www.example.com` is a web address; a file or anything else is null. */\nexport const keptAddress = (href: string): string | null => {\n const address = href.trim();\n\n if (/^www\\.[^\\s/]+\\.\\S+$/i.test(address)) {\n return `https://${address}`;\n }\n\n return isKeptLink(address) ? address : null;\n};\n\nconst isWebAddress = (src: string): boolean => {\n return /^https?:\\/\\/\\S+$/i.test(src);\n};\n\n/** An HTML note (an element, or HTML as text) as an Orbit note; undefined when it holds no text. */\nexport const noteFromHtml = (html: MarkupElement | string, addresses: NoteAddresses = {}): ImportedNote | undefined => {\n const element = typeof html === 'string' ? parseHtml(html) : html;\n return noteFromBlocks(readBlocks(element.children, addresses), addresses);\n};\n\n/** A plain text note: markdown when it reads the same as markdown, otherwise plain, as written. */\nexport const noteFromPlainText = (text: string | undefined): ImportedNote | undefined => {\n const cleaned = (text ?? '')\n .replace(/\\r\\n?/g, '\\n')\n .split('\\n')\n .map((line) => line.replace(/[ \\t]+$/, ''))\n .join('\\n')\n .replace(/^\\n+|\\n+$/g, '');\n\n if (cleaned.trim() === '') {\n return undefined;\n }\n\n const paragraphs = cleaned.split(/\\n{2,}/);\n const readsTheSame = paragraphs.every((paragraph) => !paragraph.includes('\\n') && isInertText(paragraph) && isInertLineStart(paragraph));\n return { text: cleaned, format: readsTheSame ? 'markdown' : 'plain' };\n};\n\n/** Blocks as a note: markdown when every word reads back as written, otherwise plain text. */\nexport const noteFromBlocks = (blocks: NoteBlock[], addresses: NoteAddresses = {}): ImportedNote | undefined => {\n const kept = blocks.filter((block) => !isEmptyBlock(block));\n\n if (kept.length === 0) {\n return undefined;\n }\n\n const writer = new MarkdownWriter(addresses);\n const markdown = writer.blocks(kept);\n\n if (writer.inert && markdown.trim() !== '') {\n return { text: markdown, format: 'markdown' };\n }\n\n const plain = plainBlocks(kept).trim();\n return plain === '' ? undefined : { text: plain, format: 'plain' };\n};\n\n/** Two or more notes as one: markdown if all are, otherwise plain text, separated by blank lines. */\nexport const joinNotes = (notes: (ImportedNote | undefined)[]): ImportedNote | undefined => {\n const present = notes.filter((note): note is ImportedNote => note !== undefined && note.text.trim() !== '');\n\n if (present.length <= 1) {\n return present[0];\n }\n\n return {\n text: present.map((note) => note.text).join('\\n\\n'),\n format: present.every((note) => note.format === 'markdown') ? 'markdown' : 'plain',\n };\n};\n\n/** A title from HTML: what a reader sees, on one line, and the address of its first link. */\nexport const titleFromHtml = (html: MarkupElement | string): { text: string; link?: string } => {\n const element = typeof html === 'string' ? parseHtml(html) : html;\n const pieces = inlineFrom(element.children, {});\n const link = firstLink(pieces);\n return { text: plainInline(pieces, false, false).replace(/\\s+/g, ' ').trim(), ...(link ? { link } : {}) };\n};\n\nconst firstLink = (pieces: NoteInline[]): string | undefined => {\n for (const piece of pieces) {\n if (piece.kind === 'link') {\n return piece.href;\n }\n\n if (piece.kind === 'strong' || piece.kind === 'emphasis' || piece.kind === 'strike') {\n const inner = firstLink(piece.children);\n\n if (inner) {\n return inner;\n }\n }\n }\n\n return undefined;\n};\n\n/** The note's blocks, from HTML nodes. */\nexport const readBlocks = (nodes: MarkupNode[], addresses: NoteAddresses): NoteBlock[] => {\n const blocks: NoteBlock[] = [];\n let inline: NoteInline[] = [];\n\n const flush = (): void => {\n const trimmed = trimInline(inline);\n\n if (trimmed.length > 0) {\n blocks.push({ kind: 'paragraph', inline: trimmed });\n }\n\n inline = [];\n };\n\n for (const node of nodes) {\n if (!isElement(node)) {\n inline.push(...inlineFrom([node], addresses));\n continue;\n }\n\n const name = node.localName.toLowerCase();\n\n if (SKIPPED.has(name)) {\n continue;\n }\n\n const headingLevel = HEADINGS.get(name);\n\n if (headingLevel !== undefined) {\n flush();\n const content = trimInline(inlineFrom(node.children, addresses).map((piece) => (piece.kind === 'break' ? { kind: 'text', text: ' ' } as NoteInline : piece)));\n\n if (content.length > 0) {\n blocks.push({ kind: 'heading', level: headingLevel, inline: content });\n }\n } else if (name === 'ul' || name === 'ol' || name === 'menu' || name === 'dir') {\n flush();\n const items = node.children\n .filter((child) => isElement(child) || child.trim() !== '')\n .map((child) => readBlocks(isElement(child) && child.localName.toLowerCase() === 'li' ? child.children : [child], addresses))\n .filter((item) => item.some((block) => !isEmptyBlock(block)));\n\n if (items.length > 0) {\n blocks.push({ kind: 'list', ordered: name === 'ol', items });\n }\n } else if (name === 'li') {\n flush();\n blocks.push({ kind: 'list', ordered: false, items: [readBlocks(node.children, addresses)] });\n } else if (name === 'blockquote') {\n flush();\n const quoted = readBlocks(node.children, addresses);\n\n if (quoted.length > 0) {\n blocks.push({ kind: 'quote', blocks: quoted });\n }\n } else if (name === 'pre') {\n flush();\n const code = textContent(node).replace(/^\\n/, '').replace(/\\s+$/, '');\n\n if (code !== '') {\n blocks.push({ kind: 'code', text: code });\n }\n } else if (name === 'table') {\n flush();\n blocks.push(...tableRows(node, addresses));\n } else if (name === 'hr') {\n flush();\n } else if (BLOCK_CONTAINERS.has(name)) {\n flush();\n blocks.push(...readBlocks(node.children, addresses));\n } else {\n inline.push(...inlineFrom([node], addresses));\n }\n }\n\n flush();\n return blocks;\n};\n\n/** Each row of a table as a paragraph, its cells' text between middle dots. */\nconst tableRows = (table: MarkupElement, addresses: NoteAddresses): NoteBlock[] => {\n const rows: NoteBlock[] = [];\n const pending: MarkupElement[] = [table];\n\n while (pending.length > 0) {\n const element = pending.shift() as MarkupElement;\n\n for (const child of childElements(element)) {\n const name = child.localName.toLowerCase();\n\n if (name === 'tr') {\n const cells = childElements(child).filter((cell) => /^t[dh]$/.test(cell.localName.toLowerCase()));\n const inline: NoteInline[] = [];\n\n for (const cell of cells) {\n const content = trimInline(inlineFrom(cell.children, addresses).map((piece) => (piece.kind === 'break' ? { kind: 'text', text: ' ' } as NoteInline : piece)));\n\n if (content.length > 0) {\n if (inline.length > 0) {\n inline.push({ kind: 'text', text: ' · ' });\n }\n\n inline.push(...content);\n }\n }\n\n if (inline.length > 0) {\n rows.push({ kind: 'paragraph', inline });\n }\n } else if (name !== 'td' && name !== 'th') {\n pending.push(child);\n }\n }\n }\n\n return rows;\n};\n\n/** Inline content from HTML nodes; block elements inside it read as their text. */\nconst inlineFrom = (nodes: MarkupNode[], addresses: NoteAddresses): NoteInline[] => {\n const pieces: NoteInline[] = [];\n\n for (const node of nodes) {\n if (!isElement(node)) {\n const text = node.replace(/[ \\t\\n\\r\\f]+/g, ' ');\n\n if (text !== '') {\n pieces.push({ kind: 'text', text });\n }\n\n continue;\n }\n\n const name = node.localName.toLowerCase();\n\n if (SKIPPED.has(name)) {\n continue;\n }\n\n if (name === 'br') {\n pieces.push({ kind: 'break' });\n } else if (name === 'img') {\n const src = node.attributes.src ?? Object.entries(node.attributes).find(([key]) => key.endsWith(':src'))?.[1] ?? '';\n pieces.push({ kind: 'image', src, alt: (node.attributes.alt ?? node.attributes.title ?? '').trim() });\n } else if (INLINE_KINDS.has(name)) {\n pieces.push({ kind: INLINE_KINDS.get(name) as 'strong' | 'emphasis' | 'strike', children: inlineFrom(node.children, addresses) });\n } else if (CODE_ELEMENTS.has(name)) {\n pieces.push({ kind: 'code', text: textContent(node).replace(/\\s+/g, ' ') });\n } else if (name === 'a') {\n const href = (node.attributes.href ?? Object.entries(node.attributes).find(([key]) => key.endsWith(':href'))?.[1] ?? '').trim();\n const children = inlineFrom(node.children, addresses);\n\n if (href) {\n pieces.push({ kind: 'link', href, children });\n } else {\n pieces.push(...children);\n }\n } else {\n // A block inside a line, or an element HTML only uses for looks: its content, between spaces where blocks part.\n const block = BLOCK_CONTAINERS.has(name) || HEADINGS.has(name) || name === 'li' || name === 'tr';\n const content = inlineFrom(node.children, addresses);\n\n if (block && pieces.length > 0) {\n pieces.push({ kind: 'break' });\n }\n\n pieces.push(...content);\n }\n }\n\n return pieces;\n};\n\n/** Inline content without the spaces and line breaks at its ends. */\nconst trimInline = (pieces: NoteInline[]): NoteInline[] => {\n const result = [...pieces];\n\n while (result.length > 0 && isBlankPiece(result[0])) {\n result.shift();\n }\n\n while (result.length > 0 && isBlankPiece(result[result.length - 1])) {\n result.pop();\n }\n\n if (result.length > 0 && result[0].kind === 'text') {\n result[0] = { kind: 'text', text: result[0].text.replace(/^ +/, '') };\n }\n\n const last = result.length - 1;\n\n if (last >= 0 && result[last].kind === 'text') {\n result[last] = { kind: 'text', text: (result[last] as { text: string }).text.replace(/ +$/, '') };\n }\n\n return result;\n};\n\nconst isBlankPiece = (piece: NoteInline): boolean => {\n return piece.kind === 'break' || (piece.kind === 'text' && piece.text.trim() === '');\n};\n\nconst isEmptyBlock = (block: NoteBlock): boolean => {\n switch (block.kind) {\n case 'paragraph':\n case 'heading':\n return plainInline(block.inline, false).trim() === '' && !block.inline.some((piece) => piece.kind === 'image' && piece.src !== '');\n case 'list':\n return block.items.every((item) => item.every(isEmptyBlock));\n case 'quote':\n return block.blocks.every(isEmptyBlock);\n case 'code':\n return block.text.trim() === '';\n }\n};\n\n// Text markdown would read as something else: emphasis, code, links, pictures, escapes, HTML and character references.\nconst ACTIVE_CHARACTERS = /[`*_~[\\]<\\\\]|&#?[A-Za-z0-9]+;/;\n// Lines markdown reads as headings, quotes, lists, rules, fences or code.\nconst ACTIVE_LINE_START = /^(\\s{4,}|\\s*(#{1,6}(\\s|$)|>|[-*+](\\s|$)|\\d{1,9}[.)](\\s|$)|```|~~~|[-=_]{3,}\\s*$))/;\n\nconst isInertText = (text: string): boolean => {\n return !ACTIVE_CHARACTERS.test(text);\n};\n\nconst isInertLineStart = (line: string): boolean => {\n return !ACTIVE_LINE_START.test(line);\n};\n\n/** Writes blocks as markdown, and notes whether any text would read back differently (`inert` turns false). */\nclass MarkdownWriter {\n inert = true;\n private readonly addresses: NoteAddresses;\n\n constructor(addresses: NoteAddresses) {\n this.addresses = addresses;\n }\n\n blocks(blocks: NoteBlock[]): string {\n return blocks.map((block) => this.block(block)).filter((text) => text !== '').join('\\n\\n');\n }\n\n private block(block: NoteBlock): string {\n switch (block.kind) {\n case 'paragraph': {\n // Markdown in notes has no line breaks inside a paragraph: each line becomes a paragraph of its own.\n const lines = this.inlineLines(block.inline);\n return lines.map((line) => this.lineStart(line)).filter((line) => line !== '').join('\\n\\n');\n }\n case 'heading': {\n const text = this.inlineLines(block.inline).join(' ').trim();\n return text === '' ? '' : `${'#'.repeat(block.level)} ${text}`;\n }\n case 'list':\n return this.list(block, 0);\n case 'quote': {\n const inner = this.blocks(block.blocks);\n return inner.split('\\n').map((line) => (line === '' ? '>' : `> ${line}`)).join('\\n');\n }\n case 'code': {\n if (/^\\s*(```|~~~)/m.test(block.text)) {\n this.inert = false;\n }\n\n return `\\`\\`\\`\\n${block.text}\\n\\`\\`\\``;\n }\n }\n }\n\n private list(list: Extract<NoteBlock, { kind: 'list' }>, indent: number): string {\n const lines: string[] = [];\n\n list.items.forEach((item, index) => {\n const marker = list.ordered ? `${index + 1}.` : '-';\n const nested: string[] = [];\n const words: string[] = [];\n\n for (const block of item) {\n if (block.kind === 'list') {\n nested.push(this.list(block, indent + marker.length + 1));\n } else {\n words.push(this.flatText(block));\n }\n }\n\n const text = words.filter((word) => word !== '').join(' ');\n lines.push(`${' '.repeat(indent)}${marker} ${text}`.trimEnd());\n lines.push(...nested);\n });\n\n return lines.join('\\n');\n }\n\n /** A block inside a list item, on the item's line. */\n private flatText(block: NoteBlock): string {\n switch (block.kind) {\n case 'paragraph':\n case 'heading':\n return this.inlineLines(block.inline).join(' ').trim();\n case 'quote':\n return block.blocks.map((inner) => this.flatText(inner)).join(' ');\n case 'code':\n return this.code(block.text.replace(/\\s+/g, ' '));\n case 'list':\n return this.list(block, 0);\n }\n }\n\n /** A paragraph's first characters, checked: a line that starts like a list or a heading would read as one. */\n private lineStart(line: string): string {\n if (!isInertLineStart(line)) {\n this.inert = false;\n }\n\n return line.trim();\n }\n\n /** Inline content as markdown lines, split where it breaks. */\n private inlineLines(pieces: NoteInline[]): string[] {\n return this.inlineText(pieces).split('\\n').map((line) => line.replace(/ {2,}/g, ' ').trim());\n }\n\n /** Inline content as markdown, breaks as line feeds, spaces where the note had them. */\n private inlineText(pieces: NoteInline[]): string {\n return mergeNeighbors(pieces).map((piece) => (piece.kind === 'break' ? '\\n' : this.inline(piece))).join('');\n }\n\n private inline(piece: NoteInline): string {\n switch (piece.kind) {\n case 'text':\n if (!isInertText(piece.text)) {\n this.inert = false;\n }\n\n return piece.text;\n case 'break':\n return ' ';\n case 'strong':\n case 'emphasis':\n case 'strike': {\n const inner = this.inlineText(piece.children).replace(/\\n/g, ' ').replace(/ {2,}/g, ' ');\n // Spaces at the ends go outside the marks: markdown doesn't read \"** bold**\" as bold.\n const [, before, middle, after] = /^(\\s*)([\\s\\S]*?)(\\s*)$/.exec(inner) as RegExpExecArray;\n\n if (middle === '') {\n return inner;\n }\n\n const mark = piece.kind === 'strong' ? '**' : piece.kind === 'emphasis' ? '*' : '~~';\n return `${before}${mark}${middle}${mark}${after}`;\n }\n case 'code':\n return this.code(piece.text);\n case 'link': {\n const label = this.inlineLines(piece.children).join(' ').trim();\n const href = (this.addresses.link ?? defaultLink)(piece.href);\n\n if (!href) {\n return label;\n }\n\n return label === '' || label === href ? `<${encodeAddress(href)}>` : `[${label}](${encodeAddress(href)})`;\n }\n case 'image': {\n const src = piece.src ? (this.addresses.picture ?? defaultPicture)(piece.src) : null;\n\n if (!src) {\n if (!isInertText(piece.alt)) {\n this.inert = false;\n }\n\n return piece.alt;\n }\n\n if (!isInertText(piece.alt)) {\n this.inert = false;\n }\n\n return `})`;\n }\n }\n }\n\n private code(text: string): string {\n const trimmed = text.trim();\n\n if (trimmed === '') {\n return '';\n }\n\n if (trimmed.includes('`')) {\n this.inert = false;\n }\n\n return `\\`${trimmed}\\``;\n }\n}\n\n/** Neighbors of the same kind as one: two italic runs side by side would close and reopen their marks, which markdown misreads. */\nconst mergeNeighbors = (pieces: NoteInline[]): NoteInline[] => {\n const merged: NoteInline[] = [];\n\n for (const piece of pieces) {\n const last = merged[merged.length - 1];\n\n if (last && last.kind === piece.kind && (piece.kind === 'strong' || piece.kind === 'emphasis' || piece.kind === 'strike')) {\n merged[merged.length - 1] = { kind: piece.kind, children: [...(last as { children: NoteInline[] }).children, ...piece.children] };\n } else {\n merged.push(piece);\n }\n }\n\n return merged;\n};\n\nconst defaultLink = (href: string): string | null => {\n return keptAddress(href);\n};\n\nconst defaultPicture = (src: string): string | null => {\n return isWebAddress(src) ? src : null;\n};\n\n/** An address as a markdown link takes it: spaces and parentheses escaped. */\nconst encodeAddress = (address: string): string => {\n return address.replace(/ /g, '%20').replace(/\\(/g, '%28').replace(/\\)/g, '%29').replace(/</g, '%3C').replace(/>/g, '%3E');\n};\n\n/** Blocks as plain text: lists keep their markers, links their addresses. */\nconst plainBlocks = (blocks: NoteBlock[], indent = ''): string => {\n return blocks.map((block) => plainBlock(block, indent)).filter((text) => text.trim() !== '').join('\\n\\n');\n};\n\nconst plainBlock = (block: NoteBlock, indent: string): string => {\n switch (block.kind) {\n case 'paragraph':\n return prefixLines(plainInline(block.inline, true), indent);\n case 'heading':\n return prefixLines(plainInline(block.inline, false).trim(), indent);\n case 'list':\n return block.items.map((item, index) => {\n const marker = block.ordered ? `${index + 1}. ` : '- ';\n const text = plainBlocks(item.filter((inner) => inner.kind !== 'list'), '').replace(/\\n+/g, ' ').trim();\n const nested = item.filter((inner) => inner.kind === 'list').map((inner) => plainBlock(inner, `${indent}${' '.repeat(marker.length)}`));\n return [`${indent}${marker}${text}`.trimEnd(), ...nested].join('\\n');\n }).join('\\n');\n case 'quote':\n return prefixLines(plainBlocks(block.blocks), `${indent}> `);\n case 'code':\n return prefixLines(block.text, indent);\n }\n};\n\nconst prefixLines = (text: string, prefix: string): string => {\n return prefix === '' ? text : text.split('\\n').map((line) => `${prefix}${line}`).join('\\n');\n};\n\n/** Inline content as plain text; `breaks` keeps line breaks, otherwise they're spaces, and `addresses` writes a link's address after its text. */\nconst plainInline = (pieces: NoteInline[], breaks: boolean, addresses = true): string => {\n let text = '';\n\n for (const piece of pieces) {\n switch (piece.kind) {\n case 'text':\n text += piece.text;\n break;\n case 'break':\n text += breaks ? '\\n' : ' ';\n break;\n case 'strong':\n case 'emphasis':\n case 'strike':\n text += plainInline(piece.children, breaks, addresses);\n break;\n case 'code':\n text += piece.text;\n break;\n case 'link': {\n const label = plainInline(piece.children, breaks, addresses).trim();\n const href = addresses && isKeptLink(piece.href) && !piece.href.startsWith('#') ? piece.href : '';\n text += href && label && label !== href ? `${label} (${href})` : label || href;\n break;\n }\n case 'image':\n text += piece.alt;\n break;\n }\n }\n\n return text.split('\\n').map((line) => line.replace(/ {2,}/g, ' ').trim()).join('\\n');\n};\n",
|
|
47
|
+
"/**\n * What every reader of another app's file builds: a tree of ideas with what\n * Orbit can show of each, the warnings for what it can't, and the step that\n * turns the tree into an Orbit document, with ids the parsers would give it\n * and links between ideas pointing at those ids.\n */\n\nimport { leadingEmoji } from '../parser-markdown.js';\nimport { findIndexedLinkedNode, indexNodes, isNodeLink } from '../node-links.js';\nimport { ensureUniqueNodeIds, nodeSlug, setParent } from '../utils.js';\nimport type { OrbitDocument, OrbitNode } from '../types.js';\nimport { joinNotes, type ImportedNote } from './notes.js';\n\n/** Every kind of warning reading another app's map gives. */\nexport const IMPORT_WARNING_CODES = [\n 'floating-ideas-moved',\n 'summaries-moved',\n 'callouts-moved',\n 'boundaries-in-notes',\n 'links-in-notes',\n 'missing-link-targets',\n 'icons-not-kept',\n 'pictures-not-kept',\n 'attachments-not-kept',\n 'local-links-not-kept',\n 'encrypted-branches-not-read',\n 'formatting-not-kept',\n] as const;\n\nexport type OrbitImportWarningCode = (typeof IMPORT_WARNING_CODES)[number];\n\n/** Something the other app's map had that Orbit keeps another way, or can't keep. */\nexport interface OrbitImportWarning {\n code: OrbitImportWarningCode;\n message: string;\n\n /** How many places in the map it's about. */\n count: number;\n}\n\n/** Every reason a file can't be read as a map. */\nexport const IMPORT_ERROR_CODES = ['unknown-format', 'unreadable', 'empty', 'password-protected', 'too-large'] as const;\n\nexport type OrbitImportErrorCode = (typeof IMPORT_ERROR_CODES)[number];\n\n/** A file that can't be read as a map at all. */\nexport class OrbitImportError extends Error {\n readonly code: OrbitImportErrorCode;\n\n constructor(code: OrbitImportErrorCode, message: string) {\n super(message);\n this.name = 'OrbitImportError';\n this.code = code;\n }\n}\n\n/** The most ideas a map read from another app may have. */\nexport const MAX_IMPORTED_IDEAS = 100_000;\n\n/** The deepest a map read from another app may go. */\nexport const MAX_IMPORTED_DEPTH = 500;\n\n/** A link from one idea to another, by the other app's id for it. */\nexport interface IdeaLink {\n target: string;\n\n /** What the other app calls the link, if anything. */\n label?: string;\n}\n\n/** An idea as a reader finds it, before it becomes a node. */\nexport interface ImportedIdea {\n text: string;\n\n /** The other app's id for it, which links between ideas point at. */\n sourceId?: string;\n\n /** Its note, in parts: they're joined in order. */\n notes: ImportedNote[];\n\n /** A web or mail address. */\n link?: string;\n\n /** Links to other ideas: the first one becomes the idea's link when it has none, the others go in its note. */\n ideaLinks: IdeaLink[];\n\n collapsed?: boolean;\n status?: string;\n priority?: number;\n tags: string[];\n\n /** Emoji for its icons, in order: Orbit shows the first. */\n icons: string[];\n\n color?: string;\n\n /** Its picture: a web address, or a file in the map's `media`. */\n image?: string;\n\n children: ImportedIdea[];\n}\n\nexport const newIdea = (text: string): ImportedIdea => {\n return { text, notes: [], ideaLinks: [], tags: [], icons: [], children: [] };\n};\n\nconst MESSAGES: Record<OrbitImportWarningCode, (count: number, examples: string) => string> = {\n 'floating-ideas-moved': (count, examples) => `${plural(count, 'floating topic')}${examples} had no place in the tree: ${count === 1 ? \"it's\" : \"they're\"} now under the center.`,\n 'summaries-moved': (count, examples) => `${plural(count, 'summary')}${examples} became ${count === 1 ? 'an idea' : 'ideas'} beside the ideas ${count === 1 ? 'it sums' : 'they sum'} up.`,\n 'callouts-moved': (count, examples) => `${plural(count, 'callout')}${examples} became ${count === 1 ? 'an idea' : 'ideas'} under the topic ${count === 1 ? 'it points' : 'they point'} at.`,\n 'boundaries-in-notes': (count, examples) => `${plural(count, 'boundary title')}${examples} ${count === 1 ? 'is' : 'are'} now in the note of the idea whose ideas ${count === 1 ? 'it surrounds' : 'they surround'}.`,\n 'links-in-notes': (count, examples) => `${plural(count, 'link')}${examples} beyond an idea's first ${count === 1 ? 'is' : 'are'} now in its note.`,\n 'missing-link-targets': (count, examples) => `${plural(count, 'link')}${examples} ${count === 1 ? 'points' : 'point'} at an idea that isn't in this map, so ${count === 1 ? 'it was' : 'they were'} left out.`,\n 'icons-not-kept': (count, examples) => `${plural(count, 'icon')}${examples} ${count === 1 ? 'was' : 'were'} left out: an idea in Orbit has one icon, an emoji.`,\n 'pictures-not-kept': (count, examples) => `${plural(count, 'picture')}${examples} ${count === 1 ? \"isn't\" : \"aren't\"} in the file, so ${count === 1 ? 'it was' : 'they were'} left out.`,\n 'attachments-not-kept': (count, examples) => `${plural(count, 'attached file')}${examples} ${count === 1 ? 'was' : 'were'} left out; the ideas keep their names.`,\n 'local-links-not-kept': (count, examples) => `${plural(count, 'link')}${examples} to files on the computer the map was made on ${count === 1 ? 'was' : 'were'} left out.`,\n 'encrypted-branches-not-read': (count, examples) => `${plural(count, 'encrypted branch')}${examples} couldn't be read: the ideas in ${count === 1 ? 'it' : 'them'} were left out.`,\n 'formatting-not-kept': (count, examples) => `${plural(count, 'note')}${examples} ${count === 1 ? 'is' : 'are'} kept as plain text, without bold, italics or lists: markdown would have shown ${count === 1 ? 'it' : 'them'} differently.`,\n};\n\nconst plural = (count: number, noun: string): string => {\n const word = count === 1 ? noun : noun.endsWith('y') ? `${noun.slice(0, -1)}ies` : /(ch|sh|s|x)$/.test(noun) ? `${noun}es` : `${noun}s`;\n return `${count === 1 ? 'One' : count} ${word}`;\n};\n\n/** The warnings for one map, each kind counted once with a few examples. */\nexport class ImportReport {\n private readonly found = new Map<OrbitImportWarningCode, { count: number; examples: string[] }>();\n\n add(code: OrbitImportWarningCode, example?: string): void {\n const entry = this.found.get(code) ?? { count: 0, examples: [] };\n const shown = example === undefined ? '' : oneLine(example);\n entry.count += 1;\n\n if (shown !== '' && entry.examples.length < 3 && !entry.examples.includes(shown)) {\n entry.examples.push(shown);\n }\n\n this.found.set(code, entry);\n }\n\n /** The warnings in the order of `IMPORT_WARNING_CODES`. */\n get warnings(): OrbitImportWarning[] {\n const order = (code: OrbitImportWarningCode): number => IMPORT_WARNING_CODES.indexOf(code);\n\n return [...this.found.entries()].sort(([first], [second]) => order(first) - order(second)).map(([code, { count, examples }]) => {\n const shown = examples.map((example) => `“${example.length > 40 ? `${example.slice(0, 39)}…` : example}”`);\n const more = count > examples.length && examples.length > 0 ? ', …' : '';\n return { code, count, message: MESSAGES[code](count, shown.length > 0 ? ` (${shown.join(', ')}${more})` : '') };\n });\n }\n}\n\n/** A title on one line, as Orbit keeps titles: line breaks, tabs and runs of spaces become one space; other spaces stay as they are. */\nexport const oneLine = (text: string): string => {\n return text.replace(/[\\t\\n\\v\\f\\r\\u2028\\u2029 ]+/g, ' ').replace(/^ | $/g, '');\n};\n\n/** Placeholder for links to ideas until the ideas have Orbit's ids. */\nconst SOURCE_LINK = '#orbit-source:';\n\n/** A link in a note to the idea with this id in the other app: it points at the idea's Orbit id once the map is built. */\nexport const sourceLink = (sourceId: string): string => {\n return `${SOURCE_LINK}${encodeURIComponent(sourceId)}`;\n};\n\n/**\n * The tree as an Orbit document: titles on one line, an emoji at the start\n * of a title as the idea's icon (as Orbit's markdown reads it), ids from the\n * titles as the parsers give them, and links between ideas pointing at them.\n */\nexport const buildDocument = (rootIdea: ImportedIdea, report: ImportReport): OrbitDocument => {\n let count = 0;\n const bySource = new Map<string, OrbitNode>();\n const pending: [ImportedIdea, OrbitNode][] = [];\n\n const build = (idea: ImportedIdea, level: number): OrbitNode => {\n count += 1;\n\n if (count > MAX_IMPORTED_IDEAS) {\n throw new OrbitImportError('too-large', `The map has more than ${MAX_IMPORTED_IDEAS.toLocaleString('en')} ideas.`);\n }\n\n if (level > MAX_IMPORTED_DEPTH) {\n throw new OrbitImportError('too-large', `The map goes more than ${MAX_IMPORTED_DEPTH} levels deep.`);\n }\n\n let text = oneLine(idea.text);\n const icons = idea.icons.filter((icon) => icon !== '');\n let icon = icons[0];\n const emoji = icon === undefined ? leadingEmoji(text) : null;\n\n if (emoji) {\n icon = emoji.icon;\n text = emoji.text;\n }\n\n for (const extra of icons.slice(1)) {\n report.add('icons-not-kept', extra);\n }\n\n const node: OrbitNode = { id: nodeSlug(text), text, level, children: [] };\n\n if (icon) {\n node.icon = icon;\n }\n\n if (idea.collapsed && idea.children.length > 0) {\n node.collapsed = true;\n }\n\n if (idea.status) {\n node.status = idea.status;\n }\n\n if (idea.priority !== undefined && Number.isFinite(idea.priority)) {\n node.priority = idea.priority;\n }\n\n const tags = [...new Set(idea.tags.map((tag) => oneLine(tag)).filter((tag) => tag !== ''))];\n\n if (tags.length > 0) {\n node.tags = tags;\n }\n\n if (idea.color) {\n node.color = idea.color;\n }\n\n if (idea.link) {\n node.link = idea.link;\n }\n\n if (idea.image) {\n node.image = { src: idea.image };\n }\n\n if (idea.sourceId !== undefined && !bySource.has(idea.sourceId)) {\n bySource.set(idea.sourceId, node);\n }\n\n pending.push([idea, node]);\n\n for (const child of idea.children) {\n const childNode = build(child, level + 1);\n setParent(childNode, node);\n node.children.push(childNode);\n }\n\n return node;\n };\n\n const root = build(rootIdea, 0);\n ensureUniqueNodeIds(root);\n\n for (const [idea, node] of pending) {\n const extraLines: { label: string; target: OrbitNode }[] = [];\n\n for (const link of idea.ideaLinks) {\n const target = bySource.get(link.target);\n\n if (!target) {\n report.add('missing-link-targets', link.label ?? node.text);\n continue;\n }\n\n if (!node.link && !link.label) {\n node.link = `#${target.id}`;\n } else {\n report.add('links-in-notes', link.label ?? target.text);\n extraLines.push({ label: link.label ?? target.text, target });\n }\n }\n\n const note = joinNotes([...idea.notes, linkNote(extraLines, idea.notes)]);\n\n if (note) {\n node.note = resolveSourceLinks(note.text, bySource, note.format);\n\n if (note.format === 'plain') {\n node.noteFormat = 'plain';\n }\n }\n }\n\n // A file's own `#id` links (an OPML file Orbit wrote) point at the ids the titles give, or nowhere.\n const nodes = indexNodes(root);\n\n for (const [, node] of pending) {\n if (isNodeLink(node.link) && !findIndexedLinkedNode(nodes, node.link)) {\n report.add('missing-link-targets', node.link);\n delete node.link;\n }\n }\n\n return { root, options: {}, warnings: [], diagnostics: [] };\n};\n\n/** Links to other ideas as lines of a note: markdown links, or their names in a plain note. */\nconst linkNote = (lines: { label: string; target: OrbitNode }[], notes: ImportedNote[]): ImportedNote | undefined => {\n if (lines.length === 0) {\n return undefined;\n }\n\n const plain = notes.some((note) => note.format === 'plain') || lines.some(({ label }) => /[[\\]`*_~<\\\\]/.test(label));\n\n if (plain) {\n return { text: lines.map(({ label, target }) => (label === target.text ? `→ ${label}` : `→ ${label}: ${target.text}`)).join('\\n'), format: 'plain' };\n }\n\n return { text: lines.map(({ label, target }) => `→ [${label || target.text}](#${target.id})`).join('\\n\\n'), format: 'markdown' };\n};\n\n/** Links in a markdown note to the other app's ids, pointed at Orbit's ids; links to ideas that aren't in the map keep their text. */\nconst resolveSourceLinks = (text: string, bySource: Map<string, OrbitNode>, format: 'markdown' | 'plain'): string => {\n if (format !== 'markdown' || !text.includes(SOURCE_LINK)) {\n return text;\n }\n\n const target = (encoded: string): OrbitNode | undefined => {\n try {\n return bySource.get(decodeURIComponent(encoded));\n } catch {\n return undefined;\n }\n };\n\n return text\n .replace(/\\[([^\\]]*)\\]\\(#orbit-source:([^)\\s]+)\\)/g, (_, label: string, encoded: string) => {\n const node = target(encoded);\n return node ? `[${label || node.text}](#${node.id})` : label;\n })\n .replace(/<#orbit-source:([^>\\s]+)>/g, (_, encoded: string) => {\n const node = target(encoded);\n return node ? `[${node.text}](#${node.id})` : '';\n });\n};\n",
|
|
48
|
+
"/**\n * What reading another app's map gives back, and the first steps every\n * reader shares: a file's bytes as text, and its XML read, with problems\n * reported as `OrbitImportError`s.\n */\n\nimport type { OrbitDocument } from '../types.js';\nimport { OrbitImportError, type OrbitImportWarning } from './ideas.js';\nimport { decodeMarkup, MarkupError, parseXml, type MarkupElement } from './markup.js';\n\n/** The other apps' formats Orbit reads. */\nexport type OrbitImportFormat = 'opml' | 'freemind' | 'xmind';\n\nexport interface OrbitImportOptions {\n /** The file's name: its extension tells the format, and a map with no single center is named after it. */\n name?: string;\n\n /** The file's format, when you know it. Default: from the name, then from what the file holds. */\n format?: OrbitImportFormat;\n\n /** The name of the center Orbit adds to a map with several top ideas and nothing to name it after. Default \"Untitled map\". */\n untitled?: string;\n}\n\n/** One map read from another app's file. */\nexport interface OrbitImportedMap {\n document: OrbitDocument;\n\n /** Pictures from inside the file, by the address the map gives them: `media/sunrise.png`. Save them next to the map. */\n media: Record<string, Uint8Array>;\n\n /** What the other app had that Orbit keeps another way, or couldn't keep. */\n warnings: OrbitImportWarning[];\n}\n\n/** What reading another app's file gives. */\nexport interface OrbitImport {\n format: OrbitImportFormat;\n\n /** The file's maps: one, or one for each sheet of an XMind workbook. */\n maps: OrbitImportedMap[];\n}\n\n/** An XML file's top element, which must be `rootName`; `what` names the file in errors (\"an OPML file\"). */\nexport const readXmlFile = (data: Uint8Array | string, rootName: string, what: string): MarkupElement => {\n const text = typeof data === 'string' ? data : decodeMarkup(data);\n let root: MarkupElement;\n\n try {\n root = parseXml(text);\n } catch (error) {\n if (error instanceof MarkupError) {\n throw new OrbitImportError('unreadable', `The file isn't ${what} Orbit can read: ${error.message}.`);\n }\n\n throw error;\n }\n\n if (root.localName !== rootName) {\n throw new OrbitImportError('unreadable', `The file isn't ${what}: it starts with <${root.name}>, not <${rootName}>.`);\n }\n\n return root;\n};\n\n/** A file's name without its folder or a map's extension: `notes/Trip.opml` is `Trip`. */\nexport const baseName = (name: string | undefined): string => {\n return (name ?? '').replace(/^.*[/\\\\]/, '').replace(/\\.(opml|xml|mm|xmind|txt|md)$/i, '').trim();\n};\n",
|
|
49
|
+
"/**\n * FreeMind and Freeplane maps (`.mm`): nodes with their text (plain, or\n * HTML), notes and Freeplane's details, links and arrow links, folds, icons,\n * background colors, attributes and pictures.\n */\n\nimport { freeMindIcon } from './icons.js';\nimport { buildDocument, ImportReport, newIdea, oneLine, OrbitImportError, sourceLink, type ImportedIdea } from './ideas.js';\nimport { attributeOf, childElement, childElements, textContent, type MarkupElement } from './markup.js';\nimport { keptAddress, noteFromBlocks, noteFromHtml, noteFromPlainText, titleFromHtml, type ImportedNote, type NoteAddresses, type NoteBlock } from './notes.js';\nimport { baseName, readXmlFile, type OrbitImport, type OrbitImportOptions } from './reading.js';\n\n/** A FreeMind or Freeplane map, from its file's bytes or text. */\nexport const importFreeMind = (data: Uint8Array | string, options: OrbitImportOptions = {}): OrbitImport => {\n const map = readXmlFile(data, 'map', 'a FreeMind or Freeplane map');\n const nodes = childElements(map, 'node');\n\n if (nodes.length === 0) {\n throw new OrbitImportError('empty', 'The map has no nodes.');\n }\n\n const report = new ImportReport();\n let root: ImportedIdea;\n\n if (nodes.length === 1) {\n root = readNode(nodes[0], report);\n } else {\n root = newIdea(baseName(options.name) || options.untitled || 'Untitled map');\n root.children = nodes.map((node) => readNode(node, report));\n }\n\n return { format: 'freemind', maps: [{ document: buildDocument(root, report), media: {}, warnings: report.warnings }] };\n};\n\nconst readNode = (node: MarkupElement, report: ImportReport): ImportedIdea => {\n const idea = newIdea('');\n const id = node.attributes.ID;\n\n if (id) {\n idea.sourceId = id;\n }\n\n readTitle(node, idea, report);\n const addresses = noteAddresses(report);\n const details: ImportedNote[] = [];\n const notes: ImportedNote[] = [];\n\n for (const content of childElements(node, 'richcontent')) {\n const type = (content.attributes.TYPE ?? '').toUpperCase();\n\n if (type === 'NOTE' || type === 'DETAILS') {\n const note = richContentNote(content, addresses, report, idea.text);\n\n if (note) {\n (type === 'DETAILS' ? details : notes).push(note);\n }\n }\n }\n\n // FreeMind before 0.9 kept notes in a hook.\n for (const hook of childElements(node, 'hook')) {\n if (/NodeNote/.test(hook.attributes.NAME ?? '')) {\n const text = childElement(hook, 'text');\n const note = noteFromPlainText(text ? textContent(text) : undefined);\n\n if (note) {\n notes.push(note);\n }\n }\n }\n\n idea.notes.push(...details, ...notes);\n const attributes = attributeNote(node);\n\n if (attributes) {\n idea.notes.push(attributes);\n }\n\n readLink(node.attributes.LINK, idea, report);\n\n for (const arrow of childElements(node, 'arrowlink')) {\n const target = arrow.attributes.DESTINATION;\n\n if (target) {\n const label = oneLine(arrow.attributes.MIDDLE_LABEL || arrow.attributes.SOURCE_LABEL || arrow.attributes.TARGET_LABEL || '');\n idea.ideaLinks.push(label ? { target, label } : { target });\n }\n }\n\n if (node.attributes.FOLDED === 'true') {\n idea.collapsed = true;\n }\n\n const background = node.attributes.BACKGROUND_COLOR;\n\n if (background && /^#[0-9A-Fa-f]{6}$/.test(background)) {\n idea.color = background.toUpperCase();\n }\n\n for (const icon of childElements(node, 'icon')) {\n const name = icon.attributes.BUILTIN ?? '';\n const meaning = freeMindIcon(name);\n\n if (!meaning) {\n report.add('icons-not-kept', name.replace(/^.*\\//, ''));\n } else if ('icon' in meaning) {\n idea.icons.push(meaning.icon);\n } else if ('priority' in meaning) {\n idea.priority ??= meaning.priority;\n } else {\n idea.status ??= meaning.status;\n }\n }\n\n for (const hook of childElements(node, 'hook')) {\n if (hook.attributes.NAME === 'ExternalObject' && hook.attributes.URI) {\n readPicture(hook.attributes.URI, idea, report);\n }\n }\n\n if (node.attributes.ENCRYPTED_CONTENT) {\n report.add('encrypted-branches-not-read', idea.text || undefined);\n }\n\n idea.children = childElements(node, 'node').map((child) => readNode(child, report));\n return idea;\n};\n\n/** The node's text: its `TEXT`, or its rich content as a reader sees it, whose first link becomes the node's link. */\nconst readTitle = (node: MarkupElement, idea: ImportedIdea, report: ImportReport): void => {\n const rich = childElements(node, 'richcontent').find((content) => (content.attributes.TYPE ?? '').toUpperCase() === 'NODE');\n const text = node.attributes.TEXT ?? node.attributes.LOCALIZED_TEXT;\n\n if (rich) {\n const html = childElement(rich, 'html');\n const plain = childElement(rich, 'text');\n\n if (html) {\n const title = titleFromHtml(html);\n idea.text = title.text;\n readLink(title.link, idea, report);\n\n for (const image of findElements(html, 'img')) {\n readPicture(image.attributes.src ?? '', idea, report);\n }\n } else {\n idea.text = plain ? textContent(plain) : textContent(rich);\n }\n\n return;\n }\n\n if (text !== undefined && /^\\s*<html>/i.test(text)) {\n // FreeMind before 0.9 wrote HTML titles into the attribute.\n const title = titleFromHtml(text);\n idea.text = title.text;\n readLink(title.link, idea, report);\n return;\n }\n\n idea.text = text ?? '';\n};\n\nconst readLink = (link: string | undefined, idea: ImportedIdea, report: ImportReport): void => {\n const address = link?.trim();\n\n if (!address || idea.link) {\n return;\n }\n\n const kept = keptAddress(address);\n\n if (address.startsWith('#') || /^(ID_\\d+|_?Freemind_Link_\\d+)$/.test(address)) {\n // Freeplane sometimes writes a link to another node without its \"#\".\n idea.ideaLinks.push({ target: address.replace(/^#/, '') });\n } else if (kept) {\n idea.link = kept;\n } else {\n report.add('local-links-not-kept', address);\n }\n};\n\nconst readPicture = (address: string, idea: ImportedIdea, report: ImportReport): void => {\n if (/^https?:\\/\\/\\S+$/i.test(address)) {\n idea.image ??= address;\n } else if (address !== '') {\n report.add('pictures-not-kept', address.replace(/^.*[/\\\\]/, ''));\n }\n};\n\n/** Links and pictures in a note: other nodes by their ids, web addresses as they are; files on the author's computer can't come along. */\nconst noteAddresses = (report: ImportReport): NoteAddresses => {\n return {\n link: (href) => {\n if (href.startsWith('#')) {\n return sourceLink(href.slice(1));\n }\n\n const kept = keptAddress(href);\n\n if (kept) {\n return kept;\n }\n\n report.add('local-links-not-kept', href);\n return null;\n },\n picture: (src) => {\n if (/^https?:\\/\\/\\S+$/i.test(src)) {\n return src;\n }\n\n report.add('pictures-not-kept', src.replace(/^.*[/\\\\]/, ''));\n return null;\n },\n };\n};\n\n/** A note or details: HTML, or Freeplane's plain text (markdown when it says so). */\nconst richContentNote = (content: MarkupElement, addresses: NoteAddresses, report: ImportReport, title: string): ImportedNote | undefined => {\n const html = childElement(content, 'html');\n\n if (html) {\n const note = noteFromHtml(html, addresses);\n\n if (note?.format === 'plain') {\n report.add('formatting-not-kept', title || undefined);\n }\n\n return note;\n }\n\n const plain = childElement(content, 'text');\n const text = plain ? textContent(plain) : textContent(content);\n\n if (/\\/markdown$/i.test(content.attributes['CONTENT-TYPE'] ?? '') && text.trim() !== '') {\n return { text: text.replace(/\\r\\n?/g, '\\n').trim(), format: 'markdown' };\n }\n\n return noteFromPlainText(text);\n};\n\n/** Freeplane's attributes, as a list in the note: name, then value. */\nconst attributeNote = (node: MarkupElement): ImportedNote | undefined => {\n const items: NoteBlock[][] = [];\n\n for (const attribute of childElements(node, 'attribute')) {\n const name = (attributeOf(attribute, 'NAME') ?? '').trim();\n const value = (attributeOf(attribute, 'VALUE') ?? '').trim();\n\n if (name !== '' || value !== '') {\n items.push([{ kind: 'paragraph', inline: name === '' ? [{ kind: 'text', text: value }] : [{ kind: 'strong', children: [{ kind: 'text', text: `${name}:` }] }, { kind: 'text', text: ` ${value}` }] }]);\n }\n }\n\n return items.length === 0 ? undefined : noteFromBlocks([{ kind: 'list', ordered: false, items }]);\n};\n\n/** Every element with this local name inside `element`. */\nconst findElements = (element: MarkupElement, localName: string): MarkupElement[] => {\n const found: MarkupElement[] = [];\n const pending = [element];\n\n while (pending.length > 0) {\n const next = pending.pop() as MarkupElement;\n\n for (const child of childElements(next)) {\n if (child.localName.toLowerCase() === localName) {\n found.push(child);\n }\n\n pending.push(child);\n }\n }\n\n return found;\n};\n",
|
|
50
|
+
"/**\n * OPML, the outline format outliners and most mind map apps read and write.\n * Reading keeps each outline's text, its note (`_note`, the convention\n * OmniOutliner started and Workflowy, Dynalist and MindNode follow), its\n * done or todo state (`_status`, `_complete`, `complete`), its link\n * (`type=\"link\"`'s `url`, a feed's `htmlUrl` or `xmlUrl`) and its categories\n * as tags. Writing gives the same back, so a map Orbit writes reads back the\n * same, and other apps read its text, notes, links and checkboxes.\n */\n\nimport { parseOrbit } from '../dispatch.js';\nimport { isNodeLink } from '../node-links.js';\nimport type { OrbitDocument, OrbitNode } from '../types.js';\nimport { buildDocument, ImportReport, newIdea, OrbitImportError, type ImportedIdea } from './ideas.js';\nimport { attributeOf, childElement, childElements, textContent, type MarkupElement } from './markup.js';\nimport { isKeptLink, keptAddress, noteFromHtml, noteFromPlainText, titleFromHtml, type ImportedNote } from './notes.js';\nimport { baseName, readXmlFile, type OrbitImport, type OrbitImportOptions } from './reading.js';\n\n/** Tags that make an outline's text or note HTML, as Workflowy writes its formatting. */\nconst HTML_TAGS = /<\\/?(b|i|u|s|em|strong|a|span|br|code|mark|strike|del|sup|sub|font|p|div|ul|ol|li)\\b[^>]*>/i;\n\n/** An OPML file, from its bytes or text. */\nexport const importOPML = (data: Uint8Array | string, options: OrbitImportOptions = {}): OrbitImport => {\n const opml = readXmlFile(data, 'opml', 'an OPML file');\n const head = childElement(opml, 'head');\n const titleElement = head ? childElement(head, 'title') : undefined;\n const title = titleElement ? baseName(textContent(titleElement).replace(/\\s+/g, ' ').trim()) : '';\n const body = childElement(opml, 'body');\n const outlines = body ? childElements(body, 'outline') : [];\n\n if (outlines.length === 0) {\n throw new OrbitImportError('empty', 'The OPML file has no outlines.');\n }\n\n const report = new ImportReport();\n let root: ImportedIdea;\n\n if (outlines.length === 1) {\n root = readOutline(outlines[0], report);\n } else {\n root = newIdea(title || baseName(options.name) || options.untitled || 'Untitled map');\n root.children = outlines.map((outline) => readOutline(outline, report));\n }\n\n return { format: 'opml', maps: [{ document: buildDocument(root, report), media: {}, warnings: report.warnings }] };\n};\n\nconst readOutline = (outline: MarkupElement, report: ImportReport): ImportedIdea => {\n const text = attributeOf(outline, 'text') ?? attributeOf(outline, 'title') ?? '';\n const idea = newIdea(text);\n\n // Orbit says when a title that looks like HTML is plain text.\n if (HTML_TAGS.test(text) && outline.attributes._textFormat !== 'plain') {\n const title = titleFromHtml(text);\n idea.text = title.text;\n\n if (title.link && isKeptLink(title.link) && !title.link.startsWith('#')) {\n idea.link = title.link;\n }\n }\n\n const note = readNote(outline, idea, report);\n\n if (note) {\n idea.notes.push(note);\n }\n\n idea.status = readStatus(outline);\n const link = readLink(outline);\n const kept = link ? keptAddress(link) : null;\n\n if (kept) {\n idea.link = kept;\n } else if (link) {\n report.add('local-links-not-kept', link);\n }\n\n const categories = attributeOf(outline, 'category');\n\n if (categories) {\n idea.tags.push(...categories.split(',').map((category) => category.trim().replace(/^\\/+/, '')).filter((category) => category !== ''));\n }\n\n idea.children = childElements(outline, 'outline').map((child) => readOutline(child, report));\n return idea;\n};\n\n/** The outline's note: `_note`, an older app's `note`, or a feed's description. */\nconst readNote = (outline: MarkupElement, idea: ImportedIdea, report: ImportReport): ImportedNote | undefined => {\n const text = attributeOf(outline, '_note') ?? outline.attributes.note ?? attributeOf(outline, 'description');\n\n if (text === undefined || text.trim() === '') {\n return undefined;\n }\n\n // Orbit says how to read a note when its text alone wouldn't.\n const format = outline.attributes._noteFormat;\n\n if (format === 'markdown' || format === 'plain') {\n return { text: text.replace(/\\r\\n?/g, '\\n').trim(), format };\n }\n\n if (HTML_TAGS.test(text)) {\n const note = noteFromHtml(text.replace(/\\r\\n?|\\n/g, '<br>'));\n\n if (note?.format === 'plain') {\n report.add('formatting-not-kept', idea.text || undefined);\n }\n\n return note;\n }\n\n return noteFromPlainText(text);\n};\n\n/** OmniOutliner's `_status`, Workflowy's `_complete` and Dynalist's `complete`, as Orbit's statuses. */\nconst readStatus = (outline: MarkupElement): string | undefined => {\n const status = attributeOf(outline, '_status')?.trim();\n\n if (status) {\n return CHECKBOX_STATUSES.get(status.toLowerCase()) ?? status;\n }\n\n const complete = (outline.attributes._complete ?? outline.attributes.complete ?? outline.attributes.checked ?? outline.attributes._checked)?.trim().toLowerCase();\n\n if (complete === 'true') {\n return 'done';\n }\n\n return outline.attributes.checkbox === 'true' ? 'todo' : undefined;\n};\n\n/** The outline's address: a link's or an include's `url`, a feed's site or the feed itself. */\nconst readLink = (outline: MarkupElement): string | undefined => {\n const url = outline.attributes.url ?? outline.attributes.htmlUrl ?? outline.attributes.xmlUrl;\n return url?.trim() || undefined;\n};\n\nexport interface OrbitOPMLOptions {\n /** The outline's title, in its head. Default: the map's `title`, or its root's text. */\n title?: string;\n}\n\n/** Orbit's statuses that are checkboxes in OPML, the others written as they are. */\nconst STATUS_CHECKBOXES = new Map([['done', 'checked'], ['todo', 'unchecked'], ['active', 'indeterminate']]);\nconst CHECKBOX_STATUSES = new Map([...STATUS_CHECKBOXES].map(([status, checkbox]) => [checkbox, status]));\n\n/** Statuses Workflowy should show crossed out. */\nconst DONE_WORDS = new Set(['done', 'complete', 'completed', 'shipped']);\n\n/**\n * A map as OPML: the root is the one top outline, each node an outline\n * with its icon and text, its note in `_note`, its link as `type=\"link\"`\n * with a `url`, its status in `_status` (`checked`, `unchecked` and\n * `indeterminate` for done, todo and active; any other word as it is) and\n * `_complete`, and its tags as `category`. Pictures, videos, colors and\n * priorities have no place in OPML: a zip or the map's own file keeps them.\n */\nexport const exportOPML = (input: string | OrbitDocument, options: OrbitOPMLOptions = {}): string => {\n const document = typeof input === 'string' ? parseOrbit(input) : input;\n const title = options.title ?? (document.options.title || document.root.text);\n const lines = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n '<opml version=\"2.0\">',\n ' <head>',\n ` <title>${escapeXml(title)}</title>`,\n ' </head>',\n ' <body>',\n ];\n\n const write = (node: OrbitNode, depth: number): void => {\n const indent = ' '.repeat(depth + 2);\n const attributes = outlineAttributes(node).map(([name, value]) => ` ${name}=\"${escapeXml(value, true)}\"`).join('');\n\n if (node.children.length === 0) {\n lines.push(`${indent}<outline${attributes}/>`);\n return;\n }\n\n lines.push(`${indent}<outline${attributes}>`);\n\n for (const child of node.children) {\n write(child, depth + 1);\n }\n\n lines.push(`${indent}</outline>`);\n };\n\n write(document.root, 0);\n lines.push(' </body>', '</opml>', '');\n return lines.join('\\n');\n};\n\nconst outlineAttributes = (node: OrbitNode): [string, string][] => {\n const text = node.icon ? `${node.icon} ${node.text}` : node.text;\n const attributes: [string, string][] = [['text', text]];\n\n if (HTML_TAGS.test(text)) {\n attributes.push(['_textFormat', 'plain']);\n }\n\n if (node.note) {\n attributes.push(['_note', node.note]);\n const format = node.noteFormat ?? 'markdown';\n\n // Said only when the note's text alone would read the other way.\n if (noteFromPlainText(node.note)?.format !== format) {\n attributes.push(['_noteFormat', format]);\n }\n }\n\n const status = node.status?.trim();\n\n if (status) {\n attributes.push(['_status', STATUS_CHECKBOXES.get(status) ?? status]);\n\n if (DONE_WORDS.has(status.toLowerCase())) {\n attributes.push(['_complete', 'true']);\n }\n }\n\n if (node.link && (isKeptLink(node.link) || isNodeLink(node.link))) {\n attributes.push(['type', 'link'], ['url', node.link]);\n }\n\n if (node.tags && node.tags.length > 0) {\n attributes.push(['category', node.tags.map((tag) => tag.replace(/,/g, ' ')).join(',')]);\n }\n\n return attributes;\n};\n\n/** Text for XML; in an attribute, line breaks and tabs are written as references, so readers keep them. */\nconst escapeXml = (text: string, attribute = false): string => {\n const escaped = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n return attribute ? escaped.replace(/\"/g, '"').replace(/\\n/g, ' ').replace(/\\r/g, ' ').replace(/\\t/g, '	') : escaped;\n};\n",
|
|
51
|
+
"/**\n * Inflate (RFC 1951), the compression inside zip files, read synchronously\n * and without `DecompressionStream`: the oldest browsers Orbit draws in\n * can't decompress raw deflate data, and a command line has no need to wait.\n * Codes are decoded the canonical way, a bit at a time, which is plenty fast\n * for the few megabytes a map holds.\n */\n\n/** Data that isn't valid deflate data, or holds more than it said it would. */\nexport class InflateError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'InflateError';\n }\n}\n\nconst LENGTH_BASES = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258];\nconst LENGTH_EXTRA_BITS = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0];\nconst DISTANCE_BASES = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577];\nconst DISTANCE_EXTRA_BITS = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13];\nconst CODE_LENGTH_ORDER = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];\nconst MAX_BITS = 15;\n\n/** A canonical Huffman code: how many codes have each length, and the symbols in code order. */\ninterface HuffmanCode {\n counts: Uint16Array;\n symbols: Uint16Array;\n}\n\nconst buildCode = (lengths: Uint8Array): HuffmanCode => {\n const counts = new Uint16Array(MAX_BITS + 1);\n\n for (const length of lengths) {\n counts[length] += 1;\n }\n\n counts[0] = 0;\n let left = 1;\n\n for (let length = 1; length <= MAX_BITS; length++) {\n left = left * 2 - counts[length];\n\n if (left < 0) {\n throw new InflateError('A Huffman code with more codes than its lengths allow');\n }\n }\n\n const offsets = new Uint16Array(MAX_BITS + 2);\n\n for (let length = 1; length <= MAX_BITS; length++) {\n offsets[length + 1] = offsets[length] + counts[length];\n }\n\n const symbols = new Uint16Array(lengths.length);\n\n for (let symbol = 0; symbol < lengths.length; symbol++) {\n if (lengths[symbol] !== 0) {\n symbols[offsets[lengths[symbol]]++] = symbol;\n }\n }\n\n return { counts, symbols };\n};\n\nconst fixedLengths = new Uint8Array(288);\nfixedLengths.fill(8, 0, 144);\nfixedLengths.fill(9, 144, 256);\nfixedLengths.fill(7, 256, 280);\nfixedLengths.fill(8, 280, 288);\nconst FIXED_LITERALS = buildCode(fixedLengths);\nconst FIXED_DISTANCES = buildCode(new Uint8Array(30).fill(5));\n\nclass BitReader {\n private readonly data: Uint8Array;\n private position: number;\n private buffer = 0;\n private count = 0;\n\n constructor(data: Uint8Array, start: number) {\n this.data = data;\n this.position = start;\n }\n\n bits(needed: number): number {\n while (this.count < needed) {\n if (this.position >= this.data.length) {\n throw new InflateError('The data ends in the middle of a block');\n }\n\n this.buffer |= this.data[this.position++] << this.count;\n this.count += 8;\n }\n\n const value = this.buffer & ((1 << needed) - 1);\n this.buffer >>>= needed;\n this.count -= needed;\n return value;\n }\n\n /** Skips to the next whole byte and reads `length` bytes from there. */\n bytes(length: number): Uint8Array {\n this.buffer = 0;\n this.count = 0;\n\n if (this.position + length > this.data.length) {\n throw new InflateError('The data ends in the middle of a stored block');\n }\n\n const bytes = this.data.subarray(this.position, this.position + length);\n this.position += length;\n return bytes;\n }\n\n /** Skips to the next whole byte and reads a 16-bit little-endian number. */\n word(): number {\n const [low, high] = this.bytes(2);\n return low | (high << 8);\n }\n\n decode(code: HuffmanCode): number {\n let value = 0;\n let first = 0;\n let index = 0;\n\n for (let length = 1; length <= MAX_BITS; length++) {\n value |= this.bits(1);\n const count = code.counts[length];\n\n if (value - first < count) {\n return code.symbols[index + value - first];\n }\n\n index += count;\n first = (first + count) << 1;\n value <<= 1;\n }\n\n throw new InflateError('A code that no Huffman table has');\n }\n}\n\n/** Grows as it's written, never past its limit. */\nclass Output {\n bytes: Uint8Array;\n length = 0;\n private readonly limit: number;\n\n constructor(expected: number | undefined, limit: number) {\n this.limit = limit;\n this.bytes = new Uint8Array(Math.max(16, Math.min(expected ?? 65536, limit)));\n }\n\n private room(extra: number): void {\n const needed = this.length + extra;\n\n if (needed > this.limit) {\n throw new InflateError(`The data holds more than the ${this.limit} bytes it may`);\n }\n\n if (needed > this.bytes.length) {\n const grown = new Uint8Array(Math.min(this.limit, Math.max(needed, this.bytes.length * 2)));\n grown.set(this.bytes.subarray(0, this.length));\n this.bytes = grown;\n }\n }\n\n push(byte: number): void {\n this.room(1);\n this.bytes[this.length++] = byte;\n }\n\n append(bytes: Uint8Array): void {\n this.room(bytes.length);\n this.bytes.set(bytes, this.length);\n this.length += bytes.length;\n }\n\n copy(distance: number, length: number): void {\n if (distance > this.length) {\n throw new InflateError('A back reference to before the start of the data');\n }\n\n this.room(length);\n\n for (let index = 0; index < length; index++) {\n this.bytes[this.length] = this.bytes[this.length - distance];\n this.length += 1;\n }\n }\n}\n\n/**\n * Raw deflate data, inflated. `expected` sizes the output when it's known\n * (a zip entry says so); the output never grows past `limit`, so a small\n * file can't unpack into an enormous one.\n */\nexport const inflate = (data: Uint8Array, options: { expected?: number; limit?: number } = {}): Uint8Array => {\n const limit = options.limit ?? Math.max(options.expected ?? 0, 64 * 1024 * 1024);\n const reader = new BitReader(data, 0);\n const output = new Output(options.expected, limit);\n let last = 0;\n\n while (last === 0) {\n last = reader.bits(1);\n const type = reader.bits(2);\n\n if (type === 0) {\n const length = reader.word();\n const complement = reader.word();\n\n if ((length ^ 0xffff) !== complement) {\n throw new InflateError(\"A stored block whose length doesn't match its complement\");\n }\n\n output.append(reader.bytes(length));\n } else if (type === 1) {\n inflateBlock(reader, output, FIXED_LITERALS, FIXED_DISTANCES);\n } else if (type === 2) {\n const [literals, distances] = readDynamicCodes(reader);\n inflateBlock(reader, output, literals, distances);\n } else {\n throw new InflateError('A block of an unknown type');\n }\n }\n\n return output.bytes.subarray(0, output.length);\n};\n\nconst readDynamicCodes = (reader: BitReader): [HuffmanCode, HuffmanCode] => {\n const literalCount = reader.bits(5) + 257;\n const distanceCount = reader.bits(5) + 1;\n const codeLengthCount = reader.bits(4) + 4;\n\n if (literalCount > 286 || distanceCount > 30) {\n throw new InflateError('A block with more codes than deflate has');\n }\n\n const codeLengths = new Uint8Array(19);\n\n for (let index = 0; index < codeLengthCount; index++) {\n codeLengths[CODE_LENGTH_ORDER[index]] = reader.bits(3);\n }\n\n const codeLengthCode = buildCode(codeLengths);\n const lengths = new Uint8Array(literalCount + distanceCount);\n let index = 0;\n\n while (index < lengths.length) {\n const symbol = reader.decode(codeLengthCode);\n\n if (symbol < 16) {\n lengths[index++] = symbol;\n continue;\n }\n\n let repeat: number;\n let value = 0;\n\n if (symbol === 16) {\n if (index === 0) {\n throw new InflateError('A repeat with nothing before it');\n }\n\n value = lengths[index - 1];\n repeat = 3 + reader.bits(2);\n } else if (symbol === 17) {\n repeat = 3 + reader.bits(3);\n } else {\n repeat = 11 + reader.bits(7);\n }\n\n if (index + repeat > lengths.length) {\n throw new InflateError('Code lengths that run past their table');\n }\n\n lengths.fill(value, index, index + repeat);\n index += repeat;\n }\n\n if (lengths[256] === 0) {\n throw new InflateError('A block with no code for its end');\n }\n\n return [buildCode(lengths.subarray(0, literalCount)), buildCode(lengths.subarray(literalCount))];\n};\n\nconst inflateBlock = (reader: BitReader, output: Output, literals: HuffmanCode, distances: HuffmanCode): void => {\n for (;;) {\n const symbol = reader.decode(literals);\n\n if (symbol < 256) {\n output.push(symbol);\n } else if (symbol === 256) {\n return;\n } else {\n const lengthIndex = symbol - 257;\n\n if (lengthIndex >= LENGTH_BASES.length) {\n throw new InflateError('A length code deflate has no length for');\n }\n\n const length = LENGTH_BASES[lengthIndex] + reader.bits(LENGTH_EXTRA_BITS[lengthIndex]);\n const distanceSymbol = reader.decode(distances);\n\n if (distanceSymbol >= DISTANCE_BASES.length) {\n throw new InflateError('A distance code deflate has no distance for');\n }\n\n output.copy(DISTANCE_BASES[distanceSymbol] + reader.bits(DISTANCE_EXTRA_BITS[distanceSymbol]), length);\n }\n }\n};\n\nlet crcTable: Uint32Array | null = null;\n\n/** The CRC-32 zip files check their entries with. */\nexport const crc32 = (bytes: Uint8Array): number => {\n if (!crcTable) {\n crcTable = new Uint32Array(256);\n\n for (let index = 0; index < 256; index++) {\n let value = index;\n\n for (let bit = 0; bit < 8; bit++) {\n value = value & 1 ? 0xedb88320 ^ (value >>> 1) : value >>> 1;\n }\n\n crcTable[index] = value >>> 0;\n }\n }\n\n let crc = 0xffffffff;\n\n for (const byte of bytes) {\n crc = crcTable[(crc ^ byte) & 0xff] ^ (crc >>> 8);\n }\n\n return (crc ^ 0xffffffff) >>> 0;\n};\n",
|
|
52
|
+
"/**\n * Reads files out of a zip archive, such as an XMind map: its directory,\n * then each entry on request, stored or deflated, checked against its\n * CRC-32. Archives that span disks, need ZIP64 or are encrypted are refused,\n * and so is an entry that would unpack past the archive's limits.\n */\n\nimport { crc32, inflate, InflateError } from './inflate.js';\n\n/** An archive that can't be read, or an entry that can't be unpacked. */\nexport class ZipError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ZipError';\n }\n}\n\nexport interface ZipLimits {\n /** The most entries an archive may list. */\n entries: number;\n\n /** The most bytes one entry may unpack to. */\n entrySize: number;\n\n /** The most bytes all the entries read may unpack to, together. */\n totalSize: number;\n}\n\nexport const DEFAULT_ZIP_LIMITS: ZipLimits = {\n entries: 20000,\n entrySize: 64 * 1024 * 1024,\n totalSize: 256 * 1024 * 1024,\n};\n\ninterface ZipEntry {\n name: string;\n flags: number;\n method: number;\n crc: number;\n compressedSize: number;\n size: number;\n headerOffset: number;\n}\n\nconst END_OF_DIRECTORY = 0x06054b50;\nconst DIRECTORY_ENTRY = 0x02014b50;\nconst LOCAL_HEADER = 0x04034b50;\n\n/** Whether bytes start the way every zip archive does. */\nexport const isZip = (bytes: Uint8Array): boolean => {\n return bytes.length >= 4 && bytes[0] === 0x50 && bytes[1] === 0x4b && bytes[2] === 0x03 && bytes[3] === 0x04;\n};\n\nexport class ZipArchive {\n private readonly bytes: Uint8Array;\n private readonly view: DataView;\n private readonly limits: ZipLimits;\n private readonly entries = new Map<string, ZipEntry>();\n private unpacked = 0;\n\n constructor(bytes: Uint8Array, limits: Partial<ZipLimits> = {}) {\n this.bytes = bytes;\n this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n this.limits = { ...DEFAULT_ZIP_LIMITS, ...limits };\n this.readDirectory();\n }\n\n /** The names of the files in the archive, folders left out. */\n get names(): string[] {\n return [...this.entries.keys()].filter((name) => !name.endsWith('/'));\n }\n\n has(name: string): boolean {\n return this.entries.has(name);\n }\n\n /** An entry's bytes, or null when the archive has no such file. */\n read(name: string): Uint8Array | null {\n const entry = this.entries.get(name);\n\n if (!entry) {\n return null;\n }\n\n if (entry.flags & 1) {\n throw new ZipError(`${name} is encrypted`);\n }\n\n if (entry.size > this.limits.entrySize || this.unpacked + entry.size > this.limits.totalSize) {\n throw new ZipError(`${name} is too large to unpack`);\n }\n\n const offset = entry.headerOffset;\n\n if (offset + 30 > this.bytes.length || this.view.getUint32(offset, true) !== LOCAL_HEADER) {\n throw new ZipError(`The archive has no data where ${name} should start`);\n }\n\n const start = offset + 30 + this.view.getUint16(offset + 26, true) + this.view.getUint16(offset + 28, true);\n const end = start + entry.compressedSize;\n\n if (end > this.bytes.length) {\n throw new ZipError(`${name} runs past the end of the archive`);\n }\n\n const stored = this.bytes.subarray(start, end);\n let data: Uint8Array;\n\n if (entry.method === 0) {\n data = stored;\n } else if (entry.method === 8) {\n try {\n data = inflate(stored, { expected: entry.size, limit: entry.size });\n } catch (error) {\n throw new ZipError(`${name} can't be unpacked: ${error instanceof InflateError ? error.message : String(error)}`);\n }\n } else {\n throw new ZipError(`${name} is compressed a way Orbit can't read (method ${entry.method})`);\n }\n\n if (data.length !== entry.size || crc32(data) !== entry.crc) {\n throw new ZipError(`${name} is damaged: its contents don't match its checksum`);\n }\n\n this.unpacked += data.length;\n return data;\n }\n\n /** An entry as UTF-8 text, or null when the archive has no such file. */\n text(name: string): string | null {\n const data = this.read(name);\n return data === null ? null : new TextDecoder('utf-8').decode(data);\n }\n\n private readDirectory(): void {\n const bytes = this.bytes;\n const view = this.view;\n let end = -1;\n\n // The directory's end record sits in the last 22 bytes, or before a comment of up to 64 KB.\n for (let index = bytes.length - 22; index >= Math.max(0, bytes.length - 22 - 65535); index--) {\n if (view.getUint32(index, true) === END_OF_DIRECTORY) {\n end = index;\n break;\n }\n }\n\n if (end === -1) {\n throw new ZipError('The file is not a zip archive, or its end is missing');\n }\n\n const disk = view.getUint16(end + 4, true);\n const count = view.getUint16(end + 10, true);\n const size = view.getUint32(end + 12, true);\n const offset = view.getUint32(end + 16, true);\n\n if (disk !== 0) {\n throw new ZipError('The archive spans several disks');\n }\n\n if (count === 0xffff || size === 0xffffffff || offset === 0xffffffff) {\n throw new ZipError('The archive needs ZIP64, which Orbit reads no map from');\n }\n\n if (count > this.limits.entries) {\n throw new ZipError(`The archive lists more than ${this.limits.entries} files`);\n }\n\n if (offset + size > end) {\n throw new ZipError(\"The archive's directory runs past its end\");\n }\n\n const decoder = new TextDecoder('utf-8');\n let position = offset;\n\n for (let index = 0; index < count; index++) {\n if (position + 46 > end || view.getUint32(position, true) !== DIRECTORY_ENTRY) {\n throw new ZipError(\"The archive's directory is damaged\");\n }\n\n const nameLength = view.getUint16(position + 28, true);\n const extraLength = view.getUint16(position + 30, true);\n const commentLength = view.getUint16(position + 32, true);\n\n if (position + 46 + nameLength > end) {\n throw new ZipError(\"The archive's directory is damaged\");\n }\n\n const name = decoder.decode(bytes.subarray(position + 46, position + 46 + nameLength));\n const entry: ZipEntry = {\n name,\n flags: view.getUint16(position + 8, true),\n method: view.getUint16(position + 10, true),\n crc: view.getUint32(position + 16, true),\n compressedSize: view.getUint32(position + 20, true),\n size: view.getUint32(position + 24, true),\n headerOffset: view.getUint32(position + 42, true),\n };\n\n if (!this.entries.has(name)) {\n this.entries.set(name, entry);\n }\n\n position += 46 + nameLength + extraLength + commentLength;\n }\n }\n}\n",
|
|
53
|
+
"/**\n * XMind workbooks (`.xmind`): zip archives holding `content.json` (XMind\n * 2020 and later, and XMind Zen) or `content.xml` (XMind 8 and earlier),\n * with their pictures. Each sheet becomes a map: its topics with their notes,\n * labels, markers, links, folds, fill colors and pictures, floating topics,\n * summaries and callouts under the topics they belong with, and\n * relationships as links.\n */\n\nimport { xmindMarker } from './icons.js';\nimport { buildDocument, ImportReport, newIdea, OrbitImportError, sourceLink, type ImportedIdea } from './ideas.js';\nimport { attributeOf, childElement, childElements, isElement, MarkupError, parseXml, textContent, type MarkupElement } from './markup.js';\nimport { keptAddress, noteFromBlocks, noteFromHtml, noteFromPlainText, type ImportedNote, type NoteAddresses, type NoteBlock, type NoteInline } from './notes.js';\nimport type { OrbitImportedMap, OrbitImport, OrbitImportOptions } from './reading.js';\nimport { isZip, ZipArchive, ZipError } from './zip.js';\n\n/** The extensions of the pictures a map keeps. */\nconst PICTURE_EXTENSIONS = new Set(['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp', 'avif', 'heic', 'heif']);\n\n/**\n * An XMind workbook, from its bytes; or its `content.json` or `content.xml`\n * as text, which reads without pictures.\n */\nexport const importXMind = (data: Uint8Array | string, options: OrbitImportOptions = {}): OrbitImport => {\n const workbook = openWorkbook(data);\n const maps: OrbitImportedMap[] = [];\n\n if (workbook.json !== undefined) {\n for (const sheet of workbook.json) {\n if (isObject(sheet) && isObject(sheet.rootTopic)) {\n maps.push(new JsonSheetReader(workbook.archive).read(sheet));\n }\n }\n } else if (workbook.xml) {\n const styles = workbook.archive ? readStyles(workbook.archive) : new Map<string, string>();\n const comments = workbook.archive ? readComments(workbook.archive) : new Map<string, string[]>();\n\n for (const sheet of childElements(workbook.xml, 'sheet')) {\n const topic = childElement(sheet, 'topic');\n\n if (topic) {\n maps.push(new XmlSheetReader(workbook.archive, styles, comments).read(sheet, topic));\n }\n }\n }\n\n if (maps.length === 0) {\n throw new OrbitImportError('empty', `The workbook${options.name ? ` ${options.name}` : ''} has no sheet with a topic.`);\n }\n\n return { format: 'xmind', maps };\n};\n\ninterface Workbook {\n archive: ZipArchive | null;\n json?: unknown[];\n xml?: MarkupElement;\n}\n\nconst openWorkbook = (data: Uint8Array | string): Workbook => {\n if (typeof data === 'string') {\n return readContent(data, null, data.trimStart().startsWith('[') ? 'json' : 'xml');\n }\n\n if (!isZip(data)) {\n return readContent(new TextDecoder('utf-8').decode(data), null, 'xml');\n }\n\n let archive: ZipArchive;\n\n try {\n archive = new ZipArchive(data);\n } catch (error) {\n throw unreadable(error);\n }\n\n if (isEncrypted(archive)) {\n throw new OrbitImportError('password-protected', 'The workbook is protected with a password: open it in XMind and save it without one first.');\n }\n\n try {\n // XMind 2020 and later also write a content.xml that only says to open the file in a newer XMind.\n if (archive.has('content.json')) {\n return readContent(archive.text('content.json') ?? '', archive, 'json');\n }\n\n if (archive.has('content.xml')) {\n return readContent(archive.text('content.xml') ?? '', archive, 'xml');\n }\n } catch (error) {\n throw unreadable(error);\n }\n\n throw new OrbitImportError('unreadable', \"The file is a zip archive, but not an XMind workbook: it has no content.json or content.xml.\");\n};\n\nconst readContent = (text: string, archive: ZipArchive | null, kind: 'json' | 'xml'): Workbook => {\n if (kind === 'json') {\n let json: unknown;\n\n try {\n json = JSON.parse(text);\n } catch (error) {\n throw new OrbitImportError('unreadable', `The workbook's content.json can't be read: ${(error as Error).message}.`);\n }\n\n if (!Array.isArray(json)) {\n throw new OrbitImportError('unreadable', \"The workbook's content.json isn't a list of sheets.\");\n }\n\n return { archive, json };\n }\n\n let xml: MarkupElement;\n\n try {\n xml = parseXml(text);\n } catch (error) {\n throw unreadable(error);\n }\n\n if (xml.localName !== 'xmap-content') {\n throw new OrbitImportError('unreadable', `The file isn't an XMind workbook: it starts with <${xml.name}>, not <xmap-content>.`);\n }\n\n return { archive, xml };\n};\n\nconst unreadable = (error: unknown): OrbitImportError => {\n if (error instanceof ZipError && /encrypted/.test(error.message)) {\n return new OrbitImportError('password-protected', 'The workbook is protected with a password: open it in XMind and save it without one first.');\n }\n\n if (error instanceof ZipError || error instanceof MarkupError) {\n return new OrbitImportError('unreadable', `The workbook can't be read: ${error.message}.`);\n }\n\n return error instanceof OrbitImportError ? error : new OrbitImportError('unreadable', `The workbook can't be read: ${(error as Error).message}.`);\n};\n\n/** Whether XMind encrypted the workbook's content with a password. */\nconst isEncrypted = (archive: ZipArchive): boolean => {\n try {\n const manifest = archive.has('META-INF/manifest.xml') ? archive.text('META-INF/manifest.xml') ?? '' : '';\n const json = archive.has('manifest.json') ? archive.text('manifest.json') ?? '' : '';\n return /<encryption-data/.test(manifest) || /\"encryption/.test(json);\n } catch {\n return false;\n }\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> => {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n};\n\nconst asString = (value: unknown): string | undefined => {\n return typeof value === 'string' ? value : undefined;\n};\n\n/** What reading one sheet shares: its warnings, its pictures, and its topics by id for relationships. */\nabstract class SheetReader {\n protected readonly archive: ZipArchive | null;\n protected readonly report = new ImportReport();\n protected readonly media: Record<string, Uint8Array> = {};\n protected readonly topics = new Map<string, ImportedIdea>();\n private readonly pictureNames = new Map<string, string | null>();\n\n constructor(archive: ZipArchive | null) {\n this.archive = archive;\n }\n\n protected finish(root: ImportedIdea): OrbitImportedMap {\n return { document: buildDocument(root, this.report), media: this.media, warnings: this.report.warnings };\n }\n\n /** A topic's link: to another topic, a web or mail address; an attached file or a file elsewhere can't come along. */\n protected readLink(href: string | undefined, idea: ImportedIdea): void {\n const address = href?.trim();\n\n if (!address) {\n return;\n }\n\n const topic = /^xmind:#(.+)$/.exec(address);\n\n const kept = address.startsWith('#') ? null : keptAddress(address);\n\n if (topic) {\n idea.ideaLinks.push({ target: topic[1] });\n } else if (kept) {\n idea.link = kept;\n } else if (/^xap:/.test(address)) {\n if (PICTURE_EXTENSIONS.has(extensionOf(address)) && !idea.image) {\n idea.image = this.picture(address, idea.text) ?? undefined;\n } else {\n this.report.add('attachments-not-kept', idea.text || address.replace(/^.*\\//, ''));\n }\n } else {\n this.report.add('local-links-not-kept', address);\n }\n }\n\n /** A picture's address in the map: a web address as it is, a picture inside the workbook as a file of the map's `media`. */\n protected picture(src: string, example: string): string | null {\n if (/^https?:\\/\\/\\S+$/i.test(src)) {\n return src;\n }\n\n const inside = /^xap:(.+)$/.exec(src)?.[1];\n\n if (!inside || !this.archive) {\n this.report.add('pictures-not-kept', example || src.replace(/^.*[/\\\\]/, ''));\n return null;\n }\n\n if (!this.pictureNames.has(inside)) {\n this.pictureNames.set(inside, this.unpackPicture(inside));\n }\n\n const name = this.pictureNames.get(inside) ?? null;\n\n if (!name) {\n this.report.add('pictures-not-kept', example || inside.replace(/^.*\\//, ''));\n }\n\n return name;\n }\n\n private unpackPicture(path: string): string | null {\n const extension = extensionOf(path);\n\n if (!PICTURE_EXTENSIONS.has(extension)) {\n return null;\n }\n\n let bytes: Uint8Array | null;\n\n try {\n bytes = this.archive?.read(path) ?? null;\n } catch {\n bytes = null;\n }\n\n if (!bytes) {\n return null;\n }\n\n const base = path.replace(/^.*\\//, '').replace(/\\.[^.]*$/, '').replace(/[^A-Za-z0-9._-]+/g, '-').replace(/^[^A-Za-z0-9]+/, '') || 'picture';\n let name = `media/${base}.${extension}`;\n\n for (let suffix = 2; this.media[name] !== undefined; suffix++) {\n name = `media/${base}-${suffix}.${extension}`;\n }\n\n this.media[name] = bytes;\n return name;\n }\n\n protected noteAddresses(example: string): NoteAddresses {\n return {\n link: (href) => {\n const topic = /^xmind:#(.+)$/.exec(href);\n\n if (topic) {\n return sourceLink(topic[1]);\n }\n\n const kept = href.startsWith('#') ? null : keptAddress(href);\n\n if (kept) {\n return kept;\n }\n\n this.report.add('local-links-not-kept', href);\n return null;\n },\n picture: (src) => this.picture(src, example),\n };\n }\n\n protected htmlNote(html: MarkupElement | string, idea: ImportedIdea): ImportedNote | undefined {\n const note = noteFromHtml(html, this.noteAddresses(idea.text));\n\n if (note?.format === 'plain') {\n this.report.add('formatting-not-kept', idea.text || undefined);\n }\n\n return note;\n }\n\n protected readMarker(markerId: string, idea: ImportedIdea): void {\n const meaning = xmindMarker(markerId);\n\n if (!meaning) {\n this.report.add('icons-not-kept', markerId);\n } else if ('icon' in meaning) {\n idea.icons.push(meaning.icon);\n } else if ('priority' in meaning) {\n idea.priority ??= meaning.priority;\n } else {\n idea.status ??= meaning.status;\n }\n }\n\n /** Relationships between topics, as links from the first topic to the second. */\n protected relate(fromId: string | undefined, toId: string | undefined, title: string | undefined): void {\n const from = fromId ? this.topics.get(fromId) : undefined;\n\n if (!from || !toId) {\n this.report.add('missing-link-targets', title || undefined);\n return;\n }\n\n const label = title?.trim();\n from.ideaLinks.push(label ? { target: toId, label } : { target: toId });\n }\n\n /** Topics XMind places beside the tree, under the topic they belong with, warned about by kind. */\n protected adopt(idea: ImportedIdea, children: ImportedIdea[], code: 'floating-ideas-moved' | 'summaries-moved' | 'callouts-moved'): void {\n for (const child of children) {\n this.report.add(code, child.text || undefined);\n idea.children.push(child);\n }\n }\n\n /** A titled boundary's title, as a line of the note of the topic whose subtopics it surrounds. */\n protected boundaryNote(titles: string[], idea: ImportedIdea): void {\n for (const title of titles) {\n const text = title.trim();\n\n if (text !== '') {\n this.report.add('boundaries-in-notes', text);\n const note = noteFromPlainText(text);\n\n if (note) {\n idea.notes.push(note);\n }\n }\n }\n }\n}\n\nconst extensionOf = (path: string): string => {\n return /\\.([A-Za-z0-9]+)$/.exec(path)?.[1].toLowerCase() ?? '';\n};\n\n/** A sheet of `content.json`. */\nclass JsonSheetReader extends SheetReader {\n read(sheet: Record<string, unknown>): OrbitImportedMap {\n const root = this.topic(sheet.rootTopic as Record<string, unknown>, 0);\n\n for (const relationship of Array.isArray(sheet.relationships) ? sheet.relationships : []) {\n if (isObject(relationship)) {\n this.relate(asString(relationship.end1Id), asString(relationship.end2Id), asString(relationship.title));\n }\n }\n\n return this.finish(root);\n }\n\n private topic(topic: Record<string, unknown>, depth: number): ImportedIdea {\n if (depth > 500) {\n throw new OrbitImportError('too-large', 'The sheet goes more than 500 levels deep.');\n }\n\n const idea = newIdea(asString(topic.title) ?? '');\n const id = asString(topic.id);\n\n if (id) {\n idea.sourceId = id;\n this.topics.set(id, idea);\n }\n\n const note = this.note(topic.notes, idea);\n\n if (note) {\n idea.notes.push(note);\n }\n\n if (Array.isArray(topic.labels)) {\n idea.tags.push(...topic.labels.filter((label): label is string => typeof label === 'string'));\n }\n\n for (const marker of Array.isArray(topic.markers) ? topic.markers : []) {\n const markerId = isObject(marker) ? asString(marker.markerId) : undefined;\n\n if (markerId) {\n this.readMarker(markerId, idea);\n }\n }\n\n this.readLink(asString(topic.href), idea);\n\n if (isObject(topic.image)) {\n const src = asString(topic.image.src);\n\n if (src) {\n idea.image ??= this.picture(src, idea.text) ?? undefined;\n }\n }\n\n if (topic.branch === 'folded') {\n idea.collapsed = true;\n }\n\n const style = isObject(topic.style) && isObject(topic.style.properties) ? topic.style.properties : {};\n const fill = asString(style['svg:fill']);\n\n if (fill && /^#[0-9A-Fa-f]{6}$/.test(fill)) {\n idea.color = fill.toUpperCase();\n }\n\n const children = isObject(topic.children) ? topic.children : {};\n const kind = (name: string): ImportedIdea[] => (Array.isArray(children[name]) ? children[name] as unknown[] : [])\n .filter(isObject)\n .map((child) => this.topic(child, depth + 1));\n\n idea.children.push(...kind('attached'));\n this.adopt(idea, kind('summary'), 'summaries-moved');\n this.adopt(idea, kind('callout'), 'callouts-moved');\n this.adopt(idea, kind('detached'), 'floating-ideas-moved');\n\n const boundaries = Array.isArray(topic.boundaries) ? topic.boundaries.filter(isObject).map((boundary) => asString(boundary.title) ?? '') : [];\n this.boundaryNote(boundaries, idea);\n return idea;\n }\n\n /** A topic's note: its HTML (XMind 2020 and later), its paragraphs (XMind Zen), or its plain text. */\n private note(notes: unknown, idea: ImportedIdea): ImportedNote | undefined {\n if (!isObject(notes)) {\n return undefined;\n }\n\n const html = isObject(notes.realHTML) ? asString(notes.realHTML.content) : undefined;\n\n if (html) {\n return this.htmlNote(html, idea);\n }\n\n const paragraphs = isObject(notes.html) && isObject(notes.html.content) && Array.isArray(notes.html.content.paragraphs) ? notes.html.content.paragraphs : null;\n\n if (paragraphs) {\n const blocks: NoteBlock[] = paragraphs.filter(isObject).map((paragraph) => ({\n kind: 'paragraph',\n inline: (Array.isArray(paragraph.spans) ? paragraph.spans : []).filter(isObject).map((span) => styledSpan(span)),\n }));\n const note = noteFromBlocks(blocks);\n\n if (note?.format === 'plain') {\n this.report.add('formatting-not-kept', idea.text || undefined);\n }\n\n return note;\n }\n\n return noteFromPlainText(isObject(notes.plain) ? asString(notes.plain.content) : undefined);\n }\n}\n\n/** A span of an XMind Zen note, with its bold, italics and strikethrough. */\nconst styledSpan = (span: Record<string, unknown>): NoteInline => {\n const properties = isObject(span.style) && isObject(span.style.properties) ? span.style.properties : {};\n let piece: NoteInline = { kind: 'text', text: (asString(span.text) ?? '').replace(/\\s+/g, ' ') };\n\n if (/line-through/.test(asString(properties['fo:text-decoration']) ?? '')) {\n piece = { kind: 'strike', children: [piece] };\n }\n\n if (asString(properties['fo:font-style']) === 'italic') {\n piece = { kind: 'emphasis', children: [piece] };\n }\n\n if (/^(bold|[6-9]00)$/.test(asString(properties['fo:font-weight']) ?? '')) {\n piece = { kind: 'strong', children: [piece] };\n }\n\n return piece;\n};\n\n/** A sheet of `content.xml`. */\nclass XmlSheetReader extends SheetReader {\n private readonly styles: Map<string, string>;\n private readonly comments: Map<string, string[]>;\n\n constructor(archive: ZipArchive | null, styles: Map<string, string>, comments: Map<string, string[]>) {\n super(archive);\n this.styles = styles;\n this.comments = comments;\n }\n\n read(sheet: MarkupElement, topic: MarkupElement): OrbitImportedMap {\n const root = this.topic(topic);\n\n for (const relationships of childElements(sheet, 'relationships')) {\n for (const relationship of childElements(relationships, 'relationship')) {\n const title = childElement(relationship, 'title');\n this.relate(relationship.attributes.end1, relationship.attributes.end2, title ? textContent(title) : undefined);\n }\n }\n\n return this.finish(root);\n }\n\n private topic(topic: MarkupElement): ImportedIdea {\n const title = childElement(topic, 'title');\n const idea = newIdea(title ? textContent(title) : '');\n const id = topic.attributes.id;\n\n if (id) {\n idea.sourceId = id;\n this.topics.set(id, idea);\n }\n\n const notes = childElement(topic, 'notes');\n\n if (notes) {\n const html = childElement(notes, 'html');\n const plain = childElement(notes, 'plain');\n const note = html ? this.htmlNote(html, idea) : noteFromPlainText(plain ? textContent(plain) : undefined);\n\n if (note) {\n idea.notes.push(note);\n }\n }\n\n for (const comment of id ? this.comments.get(id) ?? [] : []) {\n const note = noteFromPlainText(comment);\n\n if (note) {\n idea.notes.push(note);\n }\n }\n\n for (const labels of childElements(topic, 'labels')) {\n idea.tags.push(...childElements(labels, 'label').map((label) => textContent(label)));\n }\n\n for (const markers of childElements(topic, 'marker-refs')) {\n for (const marker of childElements(markers, 'marker-ref')) {\n const markerId = marker.attributes['marker-id'];\n\n if (markerId) {\n this.readMarker(markerId, idea);\n }\n }\n }\n\n this.readLink(attributeOf(topic, 'href'), idea);\n const image = childElement(topic, 'img');\n const src = image ? attributeOf(image, 'src') : undefined;\n\n if (src) {\n idea.image ??= this.picture(src, idea.text) ?? undefined;\n }\n\n if (topic.attributes.branch === 'folded') {\n idea.collapsed = true;\n }\n\n const fill = this.styles.get(topic.attributes['style-id'] ?? '');\n\n if (fill) {\n idea.color = fill;\n }\n\n const children = childElement(topic, 'children');\n const kind = (type: string): ImportedIdea[] => (children ? childElements(children, 'topics') : [])\n .filter((topics) => (topics.attributes.type ?? 'attached') === type)\n .flatMap((topics) => childElements(topics, 'topic').map((child) => this.topic(child)));\n\n idea.children.push(...kind('attached'));\n this.adopt(idea, kind('summary'), 'summaries-moved');\n this.adopt(idea, kind('callout'), 'callouts-moved');\n this.adopt(idea, kind('detached'), 'floating-ideas-moved');\n\n const boundaries = childElements(topic, 'boundaries').flatMap((list) => childElements(list, 'boundary')).map((boundary) => {\n const boundaryTitle = childElement(boundary, 'title');\n return boundaryTitle ? textContent(boundaryTitle) : '';\n });\n\n this.boundaryNote(boundaries, idea);\n return idea;\n }\n}\n\n/** Topic fill colors by style id, from `styles.xml`. */\nconst readStyles = (archive: ZipArchive): Map<string, string> => {\n const fills = new Map<string, string>();\n\n try {\n const text = archive.has('styles.xml') ? archive.text('styles.xml') : null;\n\n if (!text) {\n return fills;\n }\n\n const pending = [parseXml(text)];\n\n while (pending.length > 0) {\n const element = pending.pop() as MarkupElement;\n\n for (const child of element.children) {\n if (!isElement(child)) {\n continue;\n }\n\n if (child.localName === 'style' && child.attributes.type === 'topic' && child.attributes.id) {\n const properties = childElement(child, 'topic-properties');\n const fill = properties ? attributeOf(properties, 'fill') : undefined;\n\n if (fill && /^#[0-9A-Fa-f]{6}$/.test(fill)) {\n fills.set(child.attributes.id, fill.toUpperCase());\n }\n }\n\n pending.push(child);\n }\n }\n } catch {\n // Styles only color topics: a map without them still reads.\n }\n\n return fills;\n};\n\n/** Comments by topic id, from `comments.xml`: \"author: text\". */\nconst readComments = (archive: ZipArchive): Map<string, string[]> => {\n const comments = new Map<string, string[]>();\n\n try {\n const text = archive.has('comments.xml') ? archive.text('comments.xml') : null;\n\n if (!text) {\n return comments;\n }\n\n for (const comment of childElements(parseXml(text), 'comment')) {\n const topic = comment.attributes['object-id'];\n const content = childElement(comment, 'content');\n const words = content ? textContent(content).replace(/\\r\\n?/g, '\\n').trim() : '';\n\n if (topic && words !== '') {\n const author = (comment.attributes.author ?? '').trim();\n comments.set(topic, [...(comments.get(topic) ?? []), author ? `${author}: ${words}` : words]);\n }\n }\n } catch {\n // Comments are extra: a map without them still reads.\n }\n\n return comments;\n};\n",
|
|
54
|
+
"/**\n * Maps from other apps: OPML from outliners and most mind map apps,\n * FreeMind and Freeplane's `.mm`, and XMind's `.xmind`. `importMap` tells\n * the format from the file's name or what it holds and reads it into Orbit\n * maps, with the pictures inside the file and warnings for what Orbit keeps\n * another way or couldn't keep.\n */\n\nimport { importFreeMind } from './freemind.js';\nimport { OrbitImportError } from './ideas.js';\nimport { decodeMarkup } from './markup.js';\nimport { importOPML } from './opml.js';\nimport type { OrbitImport, OrbitImportFormat, OrbitImportOptions } from './reading.js';\nimport { importXMind } from './xmind.js';\nimport { isZip, ZipArchive } from './zip.js';\n\nconst EXTENSIONS: Record<string, OrbitImportFormat> = { opml: 'opml', mm: 'freemind', xmind: 'xmind' };\n\n/**\n * The format of another app's map, from what the file holds, then from its\n * name; null when it's none Orbit reads. Orbit's own markdown and YAML, and\n * its zips, are null too: read those with `parseOrbit`.\n */\nexport const detectImportFormat = (data: Uint8Array | string, name?: string): OrbitImportFormat | null => {\n const extension = /\\.([A-Za-z0-9]+)$/.exec(name ?? '')?.[1].toLowerCase() ?? '';\n return formatInside(data) ?? (Object.prototype.hasOwnProperty.call(EXTENSIONS, extension) ? EXTENSIONS[extension] : null);\n};\n\n/** The format a file's content shows: an XMind archive, or XML whose top element is OPML's, FreeMind's or XMind's. */\nconst formatInside = (data: Uint8Array | string): OrbitImportFormat | null => {\n if (typeof data !== 'string' && isZip(data)) {\n try {\n const archive = new ZipArchive(data);\n return archive.has('content.json') || archive.has('content.xml') ? 'xmind' : null;\n } catch {\n return null;\n }\n }\n\n const text = typeof data === 'string' ? data.slice(0, 4096) : decodeMarkup(data.subarray(0, 4096));\n const root = /^(?:\\s|<\\?[\\s\\S]*?\\?>|<!--[\\s\\S]*?-->|<!DOCTYPE[^>]*>)*<([A-Za-z_][\\w.:-]*)/.exec(text.replace(/^\\ufeff/, ''))?.[1];\n const formats: Record<string, OrbitImportFormat> = { opml: 'opml', map: 'freemind', 'xmap-content': 'xmind' };\n return root && Object.prototype.hasOwnProperty.call(formats, root) ? formats[root] : null;\n};\n\n/**\n * Another app's map as Orbit maps: OPML, FreeMind and Freeplane, or XMind.\n * Pass the file's bytes (its text works for OPML and `.mm`) and its name.\n * Throws an `OrbitImportError` for a file it can't read: one in no format it\n * knows (`unknown-format`), a damaged one (`unreadable`), one with no ideas\n * (`empty`), an XMind workbook with a password (`password-protected`), or one\n * past its limits (`too-large`).\n *\n * ```ts\n * const { maps } = importMap(bytes, { name: 'Trip.xmind' });\n * const markdown = serializeOrbitMarkdown(maps[0].document);\n * ```\n */\nexport const importMap = (data: Uint8Array | string, options: OrbitImportOptions = {}): OrbitImport => {\n const format = options.format ?? detectImportFormat(data, options.name);\n\n switch (format) {\n case 'opml':\n return importOPML(data, options);\n case 'freemind':\n return importFreeMind(data, options);\n case 'xmind':\n return importXMind(data, options);\n default:\n throw new OrbitImportError('unknown-format', `${options.name ? `${options.name} isn't` : \"The file isn't\"} a map Orbit can bring in from another app: it reads OPML, FreeMind and Freeplane (.mm), and XMind (.xmind).`);\n }\n};\n",
|
|
43
55
|
"/**\n * The map `orbit example` prints: every feature of the format in one\n * small roadmap, to copy and change. Tests keep it free of problems.\n */\nexport const EXAMPLE_MAP = `---\ntitle: Product roadmap\ntheme: paper\n---\n# 🚀 Product roadmap\nWhat ships this year. Click a planet to fly into it; flick the orbit to spin it.\n\n## 🔭 Discovery <!-- orbit status: done -->\nSix weeks of research before we commit to scope.\n- [x] User interviews\n- [x] Pricing survey\n- Competitor teardown #research\n\n## 🎨 Design\n<!-- orbit\nstatus: active\ncolor: \"#C6B4F2\"\n-->\n\n\n- [/] Design system refresh\n- Onboarding flow\n Three screens, one decision each.\n- Dark mode\n\n## 🛠 Build <!-- orbit status: active -->\n### Frontend\n- App shell\n- Offline sync <!-- orbit status: blocked -->\n Waits on the [search index](#search-index).\n### Backend\n- Auth service <!-- orbit priority: 1, status: active -->\n- Search index\n\n## 📈 [Growth](https://example.com/growth-plan)\n- SEO content #marketing\n- Referral program <!-- orbit owner: Ana -->\n\n## 🎬 Launch\n[Launch trailer](https://www.youtube.com/watch?v=aqz-KE-bpKQ)\n\n- [ ] Launch event\n- [ ] Press kit\n`;\n"
|
|
44
56
|
],
|
|
45
|
-
"mappings": "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",
|
|
46
|
-
"debugId": "
|
|
57
|
+
"mappings": "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",
|
|
58
|
+
"debugId": "7AC091CE99A9461164756E2164756E21",
|
|
47
59
|
"names": []
|
|
48
60
|
}
|