@abraca/cli 2.19.0 → 2.21.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.
@@ -1 +1 @@
1
- {"version":3,"file":"abracadabra-cli.cjs","names":["u64.split","u64.rotrSH","u64.shrSH","u64.rotrSL","u64.shrSL","u64.rotrBH","u64.rotrBL","u64.add4L","u64.add4H","u64.add5L","u64.add5H","u64.add","u64.add3L","u64.add3H","ed","AbracadabraClient","Kind","Y","AbracadabraProvider","toPlain","Y","Y","toPlain","Y","path","Y","nodePath","fs","wtfApiPlugin","wtf","DocumentManager"],"sources":["../src/parser.ts","../../../node_modules/@noble/hashes/utils.js","../../../node_modules/@noble/hashes/_md.js","../../../node_modules/@noble/hashes/_u64.js","../../../node_modules/@noble/hashes/sha2.js","../src/crypto.ts","../src/connection.ts","../src/command.ts","../src/output.ts","../src/commands/help.ts","../src/resolve.ts","../src/commands/spaces.ts","../src/commands/tree.ts","../../convert/src/markdown-to-yjs.ts","../../convert/src/yjs-to-markdown.ts","../../convert/src/spec/nodes.ts","../../convert/src/spec/marks.ts","../../convert/src/spec/universal-meta.ts","../src/commands/documents.ts","../src/commands/content.ts","../src/commands/meta.ts","../src/commands/awareness.ts","../src/commands/files.ts","../src/commands/permissions.ts","../../mcp/src/converters/page-types.ts","../src/commands/page-types.ts","../src/commands/wiki/wikipedia.ts","../src/commands/wiki/snapshot.ts","../src/commands/wiki/render.ts","../src/commands/wiki/connect.ts","../src/commands/wiki/index.ts","../src/index.ts"],"sourcesContent":["/**\n * Minimal argument parser for Abracadabra CLI.\n *\n * Syntax:\n * abracadabra [--flag] <command>[:<subcommand>] [key=value ...] [--flag2]\n * abracadabra [--flag] <command>[:<subcommand>] [key=\"value with spaces\"] [--format=json]\n */\n\nexport interface ParsedArgs {\n /** The command name, e.g. \"tree\", \"spaces:switch\", \"read\" */\n command: string\n /** Key-value parameters, e.g. { name: \"My Doc\", type: \"doc\" } */\n params: Record<string, string>\n /** Boolean flags, e.g. { total: true, verbose: true } */\n flags: Set<string>\n /** Positional arguments (non-flag, non-key=value, after the command) */\n positional: string[]\n}\n\n/**\n * Parse CLI arguments into a structured object.\n * @param argv Raw process.argv (includes node path and script path)\n */\nexport function parseArgs(argv: string[]): ParsedArgs {\n const args = argv.slice(2) // skip node + script\n\n const result: ParsedArgs = {\n command: 'help',\n params: {},\n flags: new Set(),\n positional: [],\n }\n\n let commandFound = false\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]\n\n // --flag or --key=value\n if (arg.startsWith('--')) {\n const stripped = arg.slice(2)\n const eqIdx = stripped.indexOf('=')\n if (eqIdx !== -1) {\n // --format=json style\n const key = stripped.slice(0, eqIdx)\n const value = stripped.slice(eqIdx + 1)\n result.params[key] = value\n } else {\n result.flags.add(stripped)\n }\n continue\n }\n\n // key=value pair\n const eqIdx = arg.indexOf('=')\n if (eqIdx !== -1 && eqIdx > 0) {\n const key = arg.slice(0, eqIdx)\n let value = arg.slice(eqIdx + 1)\n // Strip surrounding quotes if present\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1)\n }\n result.params[key] = value\n continue\n }\n\n // First bare word is the command\n if (!commandFound) {\n result.command = arg\n commandFound = true\n continue\n }\n\n // Subsequent bare words are positional\n result.positional.push(arg)\n }\n\n return result\n}\n","/**\n * Checks if something is Uint8Array. Be careful: nodejs Buffer will return true.\n * @param a - value to test\n * @returns `true` when the value is a Uint8Array-compatible view.\n * @example\n * Check whether a value is a Uint8Array-compatible view.\n * ```ts\n * isBytes(new Uint8Array([1, 2, 3]));\n * ```\n */\nexport function isBytes(a) {\n // Plain `instanceof Uint8Array` is too strict for some Buffer / proxy / cross-realm cases.\n // The fallback still requires a real ArrayBuffer view, so plain\n // JSON-deserialized `{ constructor: ... }` spoofing is rejected, and\n // `BYTES_PER_ELEMENT === 1` keeps the fallback on byte-oriented views.\n return (a instanceof Uint8Array ||\n (ArrayBuffer.isView(a) &&\n a.constructor.name === 'Uint8Array' &&\n 'BYTES_PER_ELEMENT' in a &&\n a.BYTES_PER_ELEMENT === 1));\n}\n/**\n * Asserts something is a non-negative integer.\n * @param n - number to validate\n * @param title - label included in thrown errors\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Validate a non-negative integer option.\n * ```ts\n * anumber(32, 'length');\n * ```\n */\nexport function anumber(n, title = '') {\n if (typeof n !== 'number') {\n const prefix = title && `\"${title}\" `;\n throw new TypeError(`${prefix}expected number, got ${typeof n}`);\n }\n if (!Number.isSafeInteger(n) || n < 0) {\n const prefix = title && `\"${title}\" `;\n throw new RangeError(`${prefix}expected integer >= 0, got ${n}`);\n }\n}\n/**\n * Asserts something is Uint8Array.\n * @param value - value to validate\n * @param length - optional exact length constraint\n * @param title - label included in thrown errors\n * @returns The validated byte array.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Validate that a value is a byte array.\n * ```ts\n * abytes(new Uint8Array([1, 2, 3]));\n * ```\n */\nexport function abytes(value, length, title = '') {\n const bytes = isBytes(value);\n const len = value?.length;\n const needsLen = length !== undefined;\n if (!bytes || (needsLen && len !== length)) {\n const prefix = title && `\"${title}\" `;\n const ofLen = needsLen ? ` of length ${length}` : '';\n const got = bytes ? `length=${len}` : `type=${typeof value}`;\n const message = prefix + 'expected Uint8Array' + ofLen + ', got ' + got;\n if (!bytes)\n throw new TypeError(message);\n throw new RangeError(message);\n }\n return value;\n}\n/**\n * Copies bytes into a fresh Uint8Array.\n * Buffer-style slices can alias the same backing store, so callers that need ownership should copy.\n * @param bytes - source bytes to clone\n * @returns Freshly allocated copy of `bytes`.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Clone a byte array before mutating it.\n * ```ts\n * const copy = copyBytes(new Uint8Array([1, 2, 3]));\n * ```\n */\nexport function copyBytes(bytes) {\n // `Uint8Array.from(...)` would also accept arrays / other typed arrays. Keep this helper strict\n // because callers use it at byte-validation boundaries before mutating the detached copy.\n return Uint8Array.from(abytes(bytes));\n}\n/**\n * Asserts something is a wrapped hash constructor.\n * @param h - hash constructor to validate\n * @throws On wrong argument types or invalid hash wrapper shape. {@link TypeError}\n * @throws On invalid hash metadata ranges or values. {@link RangeError}\n * @throws If the hash metadata allows empty outputs or block sizes. {@link Error}\n * @example\n * Validate a callable hash wrapper.\n * ```ts\n * import { ahash } from '@noble/hashes/utils.js';\n * import { sha256 } from '@noble/hashes/sha2.js';\n * ahash(sha256);\n * ```\n */\nexport function ahash(h) {\n if (typeof h !== 'function' || typeof h.create !== 'function')\n throw new TypeError('Hash must wrapped by utils.createHasher');\n anumber(h.outputLen);\n anumber(h.blockLen);\n // HMAC and KDF callers treat these as real byte lengths; allowing zero lets fake wrappers pass\n // validation and can produce empty outputs instead of failing fast.\n if (h.outputLen < 1)\n throw new Error('\"outputLen\" must be >= 1');\n if (h.blockLen < 1)\n throw new Error('\"blockLen\" must be >= 1');\n}\n/**\n * Asserts a hash instance has not been destroyed or finished.\n * @param instance - hash instance to validate\n * @param checkFinished - whether to reject finalized instances\n * @throws If the hash instance has already been destroyed or finalized. {@link Error}\n * @example\n * Validate that a hash instance is still usable.\n * ```ts\n * import { aexists } from '@noble/hashes/utils.js';\n * import { sha256 } from '@noble/hashes/sha2.js';\n * const hash = sha256.create();\n * aexists(hash);\n * ```\n */\nexport function aexists(instance, checkFinished = true) {\n if (instance.destroyed)\n throw new Error('Hash instance has been destroyed');\n if (checkFinished && instance.finished)\n throw new Error('Hash#digest() has already been called');\n}\n/**\n * Asserts output is a sufficiently-sized byte array.\n * @param out - destination buffer\n * @param instance - hash instance providing output length\n * Oversized buffers are allowed; downstream code only promises to fill the first `outputLen` bytes.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Validate a caller-provided digest buffer.\n * ```ts\n * import { aoutput } from '@noble/hashes/utils.js';\n * import { sha256 } from '@noble/hashes/sha2.js';\n * const hash = sha256.create();\n * aoutput(new Uint8Array(hash.outputLen), hash);\n * ```\n */\nexport function aoutput(out, instance) {\n abytes(out, undefined, 'digestInto() output');\n const min = instance.outputLen;\n if (out.length < min) {\n throw new RangeError('\"digestInto() output\" expected to be of length >=' + min);\n }\n}\n/**\n * Casts a typed array view to Uint8Array.\n * @param arr - source typed array\n * @returns Uint8Array view over the same buffer.\n * @example\n * Reinterpret a typed array as bytes.\n * ```ts\n * u8(new Uint32Array([1, 2]));\n * ```\n */\nexport function u8(arr) {\n return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n/**\n * Casts a typed array view to Uint32Array.\n * `arr.byteOffset` must already be 4-byte aligned or the platform\n * Uint32Array constructor will throw.\n * @param arr - source typed array\n * @returns Uint32Array view over the same buffer.\n * @example\n * Reinterpret a byte array as 32-bit words.\n * ```ts\n * u32(new Uint8Array(8));\n * ```\n */\nexport function u32(arr) {\n return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n}\n/**\n * Zeroizes typed arrays in place. Warning: JS provides no guarantees.\n * @param arrays - arrays to overwrite with zeros\n * @example\n * Zeroize sensitive buffers in place.\n * ```ts\n * clean(new Uint8Array([1, 2, 3]));\n * ```\n */\nexport function clean(...arrays) {\n for (let i = 0; i < arrays.length; i++) {\n arrays[i].fill(0);\n }\n}\n/**\n * Creates a DataView for byte-level manipulation.\n * @param arr - source typed array\n * @returns DataView over the same buffer region.\n * @example\n * Create a DataView over an existing buffer.\n * ```ts\n * createView(new Uint8Array(4));\n * ```\n */\nexport function createView(arr) {\n return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n/**\n * Rotate-right operation for uint32 values.\n * @param word - source word\n * @param shift - shift amount in bits\n * @returns Rotated word.\n * @example\n * Rotate a 32-bit word to the right.\n * ```ts\n * rotr(0x12345678, 8);\n * ```\n */\nexport function rotr(word, shift) {\n return (word << (32 - shift)) | (word >>> shift);\n}\n/**\n * Rotate-left operation for uint32 values.\n * @param word - source word\n * @param shift - shift amount in bits\n * @returns Rotated word.\n * @example\n * Rotate a 32-bit word to the left.\n * ```ts\n * rotl(0x12345678, 8);\n * ```\n */\nexport function rotl(word, shift) {\n return (word << shift) | ((word >>> (32 - shift)) >>> 0);\n}\n/** Whether the current platform is little-endian. */\nexport const isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)();\n/**\n * Byte-swap operation for uint32 values.\n * @param word - source word\n * @returns Word with reversed byte order.\n * @example\n * Reverse the byte order of a 32-bit word.\n * ```ts\n * byteSwap(0x11223344);\n * ```\n */\nexport function byteSwap(word) {\n return (((word << 24) & 0xff000000) |\n ((word << 8) & 0xff0000) |\n ((word >>> 8) & 0xff00) |\n ((word >>> 24) & 0xff));\n}\n/**\n * Conditionally byte-swaps one 32-bit word on big-endian platforms.\n * @param n - source word\n * @returns Original or byte-swapped word depending on platform endianness.\n * @example\n * Normalize a 32-bit word for host endianness.\n * ```ts\n * swap8IfBE(0x11223344);\n * ```\n */\nexport const swap8IfBE = isLE\n ? (n) => n\n : (n) => byteSwap(n) >>> 0;\n/**\n * Byte-swaps every word of a Uint32Array in place.\n * @param arr - array to mutate\n * @returns The same array after mutation; callers pass live state arrays here.\n * @example\n * Reverse the byte order of every word in place.\n * ```ts\n * byteSwap32(new Uint32Array([0x11223344]));\n * ```\n */\nexport function byteSwap32(arr) {\n for (let i = 0; i < arr.length; i++) {\n arr[i] = byteSwap(arr[i]);\n }\n return arr;\n}\n/**\n * Conditionally byte-swaps a Uint32Array on big-endian platforms.\n * @param u - array to normalize for host endianness\n * @returns Original or byte-swapped array depending on platform endianness.\n * On big-endian runtimes this mutates `u` in place via `byteSwap32(...)`.\n * @example\n * Normalize a word array for host endianness.\n * ```ts\n * swap32IfBE(new Uint32Array([0x11223344]));\n * ```\n */\nexport const swap32IfBE = isLE\n ? (u) => u\n : byteSwap32;\n// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex\nconst hasHexBuiltin = /* @__PURE__ */ (() => \n// @ts-ignore\ntypeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function')();\n// Array where index 0xf0 (240) is mapped to string 'f0'\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));\n/**\n * Convert byte array to hex string.\n * Uses the built-in function when available and assumes it matches the tested\n * fallback semantics.\n * @param bytes - bytes to encode\n * @returns Lowercase hexadecimal string.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Convert bytes to lowercase hexadecimal.\n * ```ts\n * bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])); // 'cafe0123'\n * ```\n */\nexport function bytesToHex(bytes) {\n abytes(bytes);\n // @ts-ignore\n if (hasHexBuiltin)\n return bytes.toHex();\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\n// We use optimized technique to convert hex string to byte array\nconst asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };\nfunction asciiToBase16(ch) {\n if (ch >= asciis._0 && ch <= asciis._9)\n return ch - asciis._0; // '2' => 50-48\n if (ch >= asciis.A && ch <= asciis.F)\n return ch - (asciis.A - 10); // 'B' => 66-(65-10)\n if (ch >= asciis.a && ch <= asciis.f)\n return ch - (asciis.a - 10); // 'b' => 98-(97-10)\n return;\n}\n/**\n * Convert hex string to byte array. Uses built-in function, when available.\n * @param hex - hexadecimal string to decode\n * @returns Decoded bytes.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Decode lowercase hexadecimal into bytes.\n * ```ts\n * hexToBytes('cafe0123'); // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n * ```\n */\nexport function hexToBytes(hex) {\n if (typeof hex !== 'string')\n throw new TypeError('hex string expected, got ' + typeof hex);\n if (hasHexBuiltin) {\n try {\n return Uint8Array.fromHex(hex);\n }\n catch (error) {\n if (error instanceof SyntaxError)\n throw new RangeError(error.message);\n throw error;\n }\n }\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2)\n throw new RangeError('hex string expected, got unpadded hex of length ' + hl);\n const array = new Uint8Array(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n const n1 = asciiToBase16(hex.charCodeAt(hi));\n const n2 = asciiToBase16(hex.charCodeAt(hi + 1));\n if (n1 === undefined || n2 === undefined) {\n const char = hex[hi] + hex[hi + 1];\n throw new RangeError('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n }\n array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163\n }\n return array;\n}\n/**\n * There is no setImmediate in browser and setTimeout is slow.\n * This yields to the Promise/microtask scheduler queue, not to timers or the\n * full macrotask event loop.\n * @example\n * Yield to the next scheduler tick.\n * ```ts\n * await nextTick();\n * ```\n */\nexport const nextTick = async () => { };\n/**\n * Returns control to the Promise/microtask scheduler every `tick`\n * milliseconds to avoid blocking long loops.\n * @param iters - number of loop iterations to run\n * @param tick - maximum time slice in milliseconds\n * @param cb - callback executed on each iteration\n * @example\n * Run a loop that periodically yields back to the event loop.\n * ```ts\n * await asyncLoop(2, 0, () => {});\n * ```\n */\nexport async function asyncLoop(iters, tick, cb) {\n let ts = Date.now();\n for (let i = 0; i < iters; i++) {\n cb(i);\n // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n const diff = Date.now() - ts;\n if (diff >= 0 && diff < tick)\n continue;\n await nextTick();\n ts += diff;\n }\n}\n/**\n * Converts string to bytes using UTF8 encoding.\n * Built-in doesn't validate input to be string: we do the check.\n * Non-ASCII details are delegated to the platform `TextEncoder`.\n * @param str - string to encode\n * @returns UTF-8 encoded bytes.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Encode a string as UTF-8 bytes.\n * ```ts\n * utf8ToBytes('abc'); // Uint8Array.from([97, 98, 99])\n * ```\n */\nexport function utf8ToBytes(str) {\n if (typeof str !== 'string')\n throw new TypeError('string expected');\n return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n/**\n * Helper for KDFs: consumes Uint8Array or string.\n * String inputs are UTF-8 encoded; byte-array inputs stay aliased to the caller buffer.\n * @param data - user-provided KDF input\n * @param errorTitle - label included in thrown errors\n * @returns Byte representation of the input.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Normalize KDF input to bytes.\n * ```ts\n * kdfInputToBytes('password');\n * ```\n */\nexport function kdfInputToBytes(data, errorTitle = '') {\n if (typeof data === 'string')\n return utf8ToBytes(data);\n return abytes(data, undefined, errorTitle);\n}\n/**\n * Copies several Uint8Arrays into one.\n * @param arrays - arrays to concatenate\n * @returns Concatenated byte array.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Concatenate multiple byte arrays.\n * ```ts\n * concatBytes(new Uint8Array([1]), new Uint8Array([2]));\n * ```\n */\nexport function concatBytes(...arrays) {\n let sum = 0;\n for (let i = 0; i < arrays.length; i++) {\n const a = arrays[i];\n abytes(a);\n sum += a.length;\n }\n const res = new Uint8Array(sum);\n for (let i = 0, pad = 0; i < arrays.length; i++) {\n const a = arrays[i];\n res.set(a, pad);\n pad += a.length;\n }\n return res;\n}\n/**\n * Merges default options and passed options.\n * @param defaults - base option object\n * @param opts - user overrides\n * @returns Merged option object. The merge mutates `defaults` in place.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Merge user overrides onto default options.\n * ```ts\n * checkOpts({ dkLen: 32 }, { asyncTick: 10 });\n * ```\n */\nexport function checkOpts(defaults, opts) {\n if (opts !== undefined && {}.toString.call(opts) !== '[object Object]')\n throw new TypeError('options must be object or undefined');\n const merged = Object.assign(defaults, opts);\n return merged;\n}\n/**\n * Creates a callable hash function from a stateful class constructor.\n * @param hashCons - hash constructor or factory\n * @param info - optional metadata such as DER OID\n * @returns Frozen callable hash wrapper with `.create()`.\n * Wrapper construction eagerly calls `hashCons(undefined)` once to read\n * `outputLen` / `blockLen`, so constructor side effects happen at module\n * init time.\n * @example\n * Wrap a stateful hash constructor into a callable helper.\n * ```ts\n * import { createHasher } from '@noble/hashes/utils.js';\n * import { sha256 } from '@noble/hashes/sha2.js';\n * const wrapped = createHasher(sha256.create, { oid: sha256.oid });\n * wrapped(new Uint8Array([1]));\n * ```\n */\nexport function createHasher(hashCons, info = {}) {\n const hashC = (msg, opts) => hashCons(opts)\n .update(msg)\n .digest();\n const tmp = hashCons(undefined);\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.canXOF = tmp.canXOF;\n hashC.create = (opts) => hashCons(opts);\n Object.assign(hashC, info);\n return Object.freeze(hashC);\n}\n/**\n * Cryptographically secure PRNG backed by `crypto.getRandomValues`.\n * @param bytesLength - number of random bytes to generate\n * @returns Random bytes.\n * The platform `getRandomValues()` implementation still defines any\n * single-call length cap, and this helper rejects oversize requests\n * with a stable library `RangeError` instead of host-specific errors.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @throws If the current runtime does not provide `crypto.getRandomValues`. {@link Error}\n * @example\n * Generate a fresh random key or nonce.\n * ```ts\n * const key = randomBytes(16);\n * ```\n */\nexport function randomBytes(bytesLength = 32) {\n // Match the repo's other length-taking helpers instead of relying on Uint8Array coercion.\n anumber(bytesLength, 'bytesLength');\n const cr = typeof globalThis === 'object' ? globalThis.crypto : null;\n if (typeof cr?.getRandomValues !== 'function')\n throw new Error('crypto.getRandomValues must be defined');\n // Web Cryptography API Level 2 §10.1.1:\n // if `byteLength > 65536`, throw `QuotaExceededError`.\n // Keep the guard explicit so callers can see the quota in code\n // instead of discovering it by reading the spec or host errors.\n // This wrapper surfaces the same quota as a stable library RangeError.\n if (bytesLength > 65536)\n throw new RangeError(`\"bytesLength\" expected <= 65536, got ${bytesLength}`);\n return cr.getRandomValues(new Uint8Array(bytesLength));\n}\n/**\n * Creates OID metadata for NIST hashes with prefix `06 09 60 86 48 01 65 03 04 02`.\n * @param suffix - final OID byte for the selected hash.\n * The helper accepts any byte even though only the documented NIST hash\n * suffixes are meaningful downstream.\n * @returns Object containing the DER-encoded OID.\n * @example\n * Build OID metadata for a NIST hash.\n * ```ts\n * oidNist(0x01);\n * ```\n */\nexport const oidNist = (suffix) => ({\n // Current NIST hashAlgs suffixes used here fit in one DER subidentifier octet.\n // Larger suffix values would need base-128 OID encoding and a different length byte.\n oid: Uint8Array.from([0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, suffix]),\n});\n//# sourceMappingURL=utils.js.map","/**\n * Internal Merkle-Damgard hash utils.\n * @module\n */\nimport { abytes, aexists, aoutput, clean, createView, } from \"./utils.js\";\n/**\n * Shared 32-bit conditional boolean primitive reused by SHA-256, SHA-1, and MD5 `F`.\n * Returns bits from `b` when `a` is set, otherwise from `c`.\n * The XOR form is equivalent to MD5's `F(X,Y,Z) = XY v not(X)Z` because the masked terms never\n * set the same bit.\n * @param a - selector word\n * @param b - word chosen when selector bit is set\n * @param c - word chosen when selector bit is clear\n * @returns Mixed 32-bit word.\n * @example\n * Combine three words with the shared 32-bit choice primitive.\n * ```ts\n * Chi(0xffffffff, 0x12345678, 0x87654321);\n * ```\n */\nexport function Chi(a, b, c) {\n return (a & b) ^ (~a & c);\n}\n/**\n * Shared 32-bit majority primitive reused by SHA-256 and SHA-1.\n * Returns bits shared by at least two inputs.\n * @param a - first input word\n * @param b - second input word\n * @param c - third input word\n * @returns Mixed 32-bit word.\n * @example\n * Combine three words with the shared 32-bit majority primitive.\n * ```ts\n * Maj(0xffffffff, 0x12345678, 0x87654321);\n * ```\n */\nexport function Maj(a, b, c) {\n return (a & b) ^ (a & c) ^ (b & c);\n}\n/**\n * Merkle-Damgard hash construction base class.\n * Could be used to create MD5, RIPEMD, SHA1, SHA2.\n * Accepts only byte-aligned `Uint8Array` input, even when the underlying spec describes bit\n * strings with partial-byte tails.\n * @param blockLen - internal block size in bytes\n * @param outputLen - digest size in bytes\n * @param padOffset - trailing length field size in bytes\n * @param isLE - whether length and state words are encoded in little-endian\n * @example\n * Use a concrete subclass to get the shared Merkle-Damgard update/digest flow.\n * ```ts\n * import { _SHA1 } from '@noble/hashes/legacy.js';\n * const hash = new _SHA1();\n * hash.update(new Uint8Array([97, 98, 99]));\n * hash.digest();\n * ```\n */\nexport class HashMD {\n blockLen;\n outputLen;\n canXOF = false;\n padOffset;\n isLE;\n // For partial updates less than block size\n buffer;\n view;\n finished = false;\n length = 0;\n pos = 0;\n destroyed = false;\n constructor(blockLen, outputLen, padOffset, isLE) {\n this.blockLen = blockLen;\n this.outputLen = outputLen;\n this.padOffset = padOffset;\n this.isLE = isLE;\n this.buffer = new Uint8Array(blockLen);\n this.view = createView(this.buffer);\n }\n update(data) {\n aexists(this);\n abytes(data);\n const { view, buffer, blockLen } = this;\n const len = data.length;\n for (let pos = 0; pos < len;) {\n const take = Math.min(blockLen - this.pos, len - pos);\n // Fast path only when there is no buffered partial block: `take === blockLen` implies\n // `this.pos === 0`, so we can process full blocks directly from the input view.\n if (take === blockLen) {\n const dataView = createView(data);\n for (; blockLen <= len - pos; pos += blockLen)\n this.process(dataView, pos);\n continue;\n }\n buffer.set(data.subarray(pos, pos + take), this.pos);\n this.pos += take;\n pos += take;\n if (this.pos === blockLen) {\n this.process(view, 0);\n this.pos = 0;\n }\n }\n this.length += data.length;\n this.roundClean();\n return this;\n }\n digestInto(out) {\n aexists(this);\n aoutput(out, this);\n this.finished = true;\n // Padding\n // We can avoid allocation of buffer for padding completely if it\n // was previously not allocated here. But it won't change performance.\n const { buffer, view, blockLen, isLE } = this;\n let { pos } = this;\n // append the bit '1' to the message\n buffer[pos++] = 0b10000000;\n clean(this.buffer.subarray(pos));\n // we have less than padOffset left in buffer, so we cannot put length in\n // current block, need process it and pad again\n if (this.padOffset > blockLen - pos) {\n this.process(view, 0);\n pos = 0;\n }\n // Pad until full block byte with zeros\n for (let i = pos; i < blockLen; i++)\n buffer[i] = 0;\n // `padOffset` reserves the whole length field. For SHA-384/512 the high 64 bits stay zero from\n // the padding fill above, and JS will overflow before user input can make that half non-zero.\n // So we only need to write the low 64 bits here.\n view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE);\n this.process(view, 0);\n const oview = createView(out);\n const len = this.outputLen;\n // NOTE: we do division by 4 later, which must be fused in single op with modulo by JIT\n if (len % 4)\n throw new Error('_sha2: outputLen must be aligned to 32bit');\n const outLen = len / 4;\n const state = this.get();\n if (outLen > state.length)\n throw new Error('_sha2: outputLen bigger than state');\n for (let i = 0; i < outLen; i++)\n oview.setUint32(4 * i, state[i], isLE);\n }\n digest() {\n const { buffer, outputLen } = this;\n this.digestInto(buffer);\n // Copy before destroy(): subclasses wipe `buffer` during cleanup, but `digest()` must return\n // fresh bytes to the caller.\n const res = buffer.slice(0, outputLen);\n this.destroy();\n return res;\n }\n _cloneInto(to) {\n to ||= new this.constructor();\n to.set(...this.get());\n const { blockLen, buffer, length, finished, destroyed, pos } = this;\n to.destroyed = destroyed;\n to.finished = finished;\n to.length = length;\n to.pos = pos;\n // Only partial-block bytes need copying: when `length % blockLen === 0`, `pos === 0` and\n // later `update()` / `digestInto()` overwrite `to.buffer` from the start before reading it.\n if (length % blockLen)\n to.buffer.set(buffer);\n return to;\n }\n clone() {\n return this._cloneInto();\n }\n}\n/**\n * Initial SHA-2 state: fractional parts of square roots of first 16 primes 2..53.\n * Check out `test/misc/sha2-gen-iv.js` for recomputation guide.\n */\n/** Initial SHA256 state from RFC 6234 §6.1: the first 32 bits of the fractional parts of the\n * square roots of the first eight prime numbers. Exported as a shared table; callers must treat\n * it as read-only because constructors copy words from it by index. */\nexport const SHA256_IV = /* @__PURE__ */ Uint32Array.from([\n 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,\n]);\n/** Initial SHA224 state `H(0)` from RFC 6234 §6.1. Exported as a shared table; callers must\n * treat it as read-only because constructors copy words from it by index. */\nexport const SHA224_IV = /* @__PURE__ */ Uint32Array.from([\n 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,\n]);\n/** Initial SHA384 state from RFC 6234 §6.3: eight RFC 64-bit `H(0)` words stored as sixteen\n * big-endian 32-bit halves. Derived from the fractional parts of the square roots of the ninth\n * through sixteenth prime numbers. Exported as a shared table; callers must treat it as read-only\n * because constructors copy halves from it by index. */\nexport const SHA384_IV = /* @__PURE__ */ Uint32Array.from([\n 0xcbbb9d5d, 0xc1059ed8, 0x629a292a, 0x367cd507, 0x9159015a, 0x3070dd17, 0x152fecd8, 0xf70e5939,\n 0x67332667, 0xffc00b31, 0x8eb44a87, 0x68581511, 0xdb0c2e0d, 0x64f98fa7, 0x47b5481d, 0xbefa4fa4,\n]);\n/** Initial SHA512 state from RFC 6234 §6.3: eight RFC 64-bit `H(0)` words stored as sixteen\n * big-endian 32-bit halves. Derived from the fractional parts of the square roots of the first\n * eight prime numbers. Exported as a shared table; callers must treat it as read-only because\n * constructors copy halves from it by index. */\nexport const SHA512_IV = /* @__PURE__ */ Uint32Array.from([\n 0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b, 0x3c6ef372, 0xfe94f82b, 0xa54ff53a, 0x5f1d36f1,\n 0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f, 0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179,\n]);\n//# sourceMappingURL=_md.js.map","const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);\nconst _32n = /* @__PURE__ */ BigInt(32);\n// Split bigint into two 32-bit halves. With `le=true`, returned fields become `{ h: low, l: high\n// }` to match little-endian word order rather than the property names.\nfunction fromBig(n, le = false) {\n if (le)\n return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };\n return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };\n}\n// Split bigint list into `[highWords, lowWords]` when `le=false`; with `le=true`, the first array\n// holds the low halves because `fromBig(...)` swaps the semantic meaning of `h` and `l`.\nfunction split(lst, le = false) {\n const len = lst.length;\n let Ah = new Uint32Array(len);\n let Al = new Uint32Array(len);\n for (let i = 0; i < len; i++) {\n const { h, l } = fromBig(lst[i], le);\n [Ah[i], Al[i]] = [h, l];\n }\n return [Ah, Al];\n}\n// Combine explicit `(high, low)` 32-bit halves into a bigint; `>>> 0` normalizes signed JS\n// bitwise results back to uint32 first, and little-endian callers must swap.\nconst toBig = (h, l) => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0);\n// High 32-bit half of a 64-bit logical right shift for `s` in `0..31`.\nconst shrSH = (h, _l, s) => h >>> s;\n// Low 32-bit half of a 64-bit logical right shift, valid for `s` in `1..31`.\nconst shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);\n// High 32-bit half of a 64-bit right rotate, valid for `s` in `1..31`.\nconst rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s));\n// Low 32-bit half of a 64-bit right rotate, valid for `s` in `1..31`.\nconst rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);\n// High 32-bit half of a 64-bit right rotate, valid for `s` in `33..63`; `32` uses `rotr32*`.\nconst rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32));\n// Low 32-bit half of a 64-bit right rotate, valid for `s` in `33..63`; `32` uses `rotr32*`.\nconst rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s));\n// High 32-bit half of a 64-bit right rotate for `s === 32`; this is just the swapped low half.\nconst rotr32H = (_h, l) => l;\n// Low 32-bit half of a 64-bit right rotate for `s === 32`; this is just the swapped high half.\nconst rotr32L = (h, _l) => h;\n// High 32-bit half of a 64-bit left rotate, valid for `s` in `1..31`.\nconst rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s));\n// Low 32-bit half of a 64-bit left rotate, valid for `s` in `1..31`.\nconst rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s));\n// High 32-bit half of a 64-bit left rotate, valid for `s` in `33..63`; `32` uses `rotr32*`.\nconst rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s));\n// Low 32-bit half of a 64-bit left rotate, valid for `s` in `33..63`; `32` uses `rotr32*`.\nconst rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s));\n// Add two split 64-bit words and return the split `{ h, l }` sum.\n// JS uses 32-bit signed integers for bitwise operations, so we cannot simply shift the carry out\n// of the low sum and instead use division.\nfunction add(Ah, Al, Bh, Bl) {\n const l = (Al >>> 0) + (Bl >>> 0);\n return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };\n}\n// Addition with more than 2 elements\n// Unmasked low-word accumulator for 3-way addition; pass the raw result into `add3H(...)`.\nconst add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);\n// High-word finalize step for 3-way addition; `low` must be the untruncated output of `add3L(...)`.\nconst add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;\n// Unmasked low-word accumulator for 4-way addition; pass the raw result into `add4H(...)`.\nconst add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);\n// High-word finalize step for 4-way addition; `low` must be the untruncated output of `add4L(...)`.\nconst add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;\n// Unmasked low-word accumulator for 5-way addition; pass the raw result into `add5H(...)`.\nconst add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);\n// High-word finalize step for 5-way addition; `low` must be the untruncated output of `add5L(...)`.\nconst add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;\n// prettier-ignore\nexport { add, add3H, add3L, add4H, add4L, add5H, add5L, fromBig, rotlBH, rotlBL, rotlSH, rotlSL, rotr32H, rotr32L, rotrBH, rotrBL, rotrSH, rotrSL, shrSH, shrSL, split, toBig };\n// Canonical grouped namespace for callers that prefer one object.\n// Named exports stay for direct imports.\n// prettier-ignore\nconst u64 = {\n fromBig, split, toBig,\n shrSH, shrSL,\n rotrSH, rotrSL, rotrBH, rotrBL,\n rotr32H, rotr32L,\n rotlSH, rotlSL, rotlBH, rotlBL,\n add, add3L, add3H, add4L, add4H, add5H, add5L,\n};\n// Default export mirrors named `u64` for compatibility with object-style imports.\nexport default u64;\n//# sourceMappingURL=_u64.js.map","/**\n * SHA2 hash function. A.k.a. sha256, sha384, sha512, sha512_224, sha512_256.\n * SHA256 is the fastest hash implementable in JS, even faster than Blake3.\n * Check out {@link https://www.rfc-editor.org/rfc/rfc4634 | RFC 4634} and\n * {@link https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf | FIPS 180-4}.\n * @module\n */\nimport { Chi, HashMD, Maj, SHA224_IV, SHA256_IV, SHA384_IV, SHA512_IV } from \"./_md.js\";\nimport * as u64 from \"./_u64.js\";\nimport { clean, createHasher, oidNist, rotr } from \"./utils.js\";\n/**\n * SHA-224 / SHA-256 round constants from RFC 6234 §5.1: the first 32 bits\n * of the cube roots of the first 64 primes (2..311).\n */\n// prettier-ignore\nconst SHA256_K = /* @__PURE__ */ Uint32Array.from([\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\n]);\n/** Reusable SHA-224 / SHA-256 message schedule buffer `W_t` from RFC 6234 §6.2 step 1. */\nconst SHA256_W = /* @__PURE__ */ new Uint32Array(64);\n/** Internal SHA-224 / SHA-256 compression engine from RFC 6234 §6.2. */\nclass SHA2_32B extends HashMD {\n constructor(outputLen) {\n super(64, outputLen, 8, false);\n }\n get() {\n const { A, B, C, D, E, F, G, H } = this;\n return [A, B, C, D, E, F, G, H];\n }\n // prettier-ignore\n set(A, B, C, D, E, F, G, H) {\n this.A = A | 0;\n this.B = B | 0;\n this.C = C | 0;\n this.D = D | 0;\n this.E = E | 0;\n this.F = F | 0;\n this.G = G | 0;\n this.H = H | 0;\n }\n process(view, offset) {\n // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array\n for (let i = 0; i < 16; i++, offset += 4)\n SHA256_W[i] = view.getUint32(offset, false);\n for (let i = 16; i < 64; i++) {\n const W15 = SHA256_W[i - 15];\n const W2 = SHA256_W[i - 2];\n const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);\n const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);\n SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;\n }\n // Compression function main loop, 64 rounds\n let { A, B, C, D, E, F, G, H } = this;\n for (let i = 0; i < 64; i++) {\n const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);\n const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;\n const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);\n const T2 = (sigma0 + Maj(A, B, C)) | 0;\n H = G;\n G = F;\n F = E;\n E = (D + T1) | 0;\n D = C;\n C = B;\n B = A;\n A = (T1 + T2) | 0;\n }\n // Add the compressed chunk to the current hash value\n A = (A + this.A) | 0;\n B = (B + this.B) | 0;\n C = (C + this.C) | 0;\n D = (D + this.D) | 0;\n E = (E + this.E) | 0;\n F = (F + this.F) | 0;\n G = (G + this.G) | 0;\n H = (H + this.H) | 0;\n this.set(A, B, C, D, E, F, G, H);\n }\n roundClean() {\n clean(SHA256_W);\n }\n destroy() {\n // HashMD callers route post-destroy usability through `destroyed`; zeroizing alone still leaves\n // update()/digest() callable on reused instances.\n this.destroyed = true;\n this.set(0, 0, 0, 0, 0, 0, 0, 0);\n clean(this.buffer);\n }\n}\n/** Internal SHA-256 hash class grounded in RFC 6234 §6.2. */\nexport class _SHA256 extends SHA2_32B {\n // We cannot use array here since array allows indexing by variable\n // which means optimizer/compiler cannot use registers.\n A = SHA256_IV[0] | 0;\n B = SHA256_IV[1] | 0;\n C = SHA256_IV[2] | 0;\n D = SHA256_IV[3] | 0;\n E = SHA256_IV[4] | 0;\n F = SHA256_IV[5] | 0;\n G = SHA256_IV[6] | 0;\n H = SHA256_IV[7] | 0;\n constructor() {\n super(32);\n }\n}\n/** Internal SHA-224 hash class grounded in RFC 6234 §6.2 and §8.5. */\nexport class _SHA224 extends SHA2_32B {\n A = SHA224_IV[0] | 0;\n B = SHA224_IV[1] | 0;\n C = SHA224_IV[2] | 0;\n D = SHA224_IV[3] | 0;\n E = SHA224_IV[4] | 0;\n F = SHA224_IV[5] | 0;\n G = SHA224_IV[6] | 0;\n H = SHA224_IV[7] | 0;\n constructor() {\n super(28);\n }\n}\n// SHA2-512 is slower than sha256 in js because u64 operations are slow.\n// SHA-384 / SHA-512 round constants from RFC 6234 §5.2:\n// 80 full 64-bit words split into high/low halves.\n// prettier-ignore\nconst K512 = /* @__PURE__ */ (() => u64.split([\n '0x428a2f98d728ae22', '0x7137449123ef65cd', '0xb5c0fbcfec4d3b2f', '0xe9b5dba58189dbbc',\n '0x3956c25bf348b538', '0x59f111f1b605d019', '0x923f82a4af194f9b', '0xab1c5ed5da6d8118',\n '0xd807aa98a3030242', '0x12835b0145706fbe', '0x243185be4ee4b28c', '0x550c7dc3d5ffb4e2',\n '0x72be5d74f27b896f', '0x80deb1fe3b1696b1', '0x9bdc06a725c71235', '0xc19bf174cf692694',\n '0xe49b69c19ef14ad2', '0xefbe4786384f25e3', '0x0fc19dc68b8cd5b5', '0x240ca1cc77ac9c65',\n '0x2de92c6f592b0275', '0x4a7484aa6ea6e483', '0x5cb0a9dcbd41fbd4', '0x76f988da831153b5',\n '0x983e5152ee66dfab', '0xa831c66d2db43210', '0xb00327c898fb213f', '0xbf597fc7beef0ee4',\n '0xc6e00bf33da88fc2', '0xd5a79147930aa725', '0x06ca6351e003826f', '0x142929670a0e6e70',\n '0x27b70a8546d22ffc', '0x2e1b21385c26c926', '0x4d2c6dfc5ac42aed', '0x53380d139d95b3df',\n '0x650a73548baf63de', '0x766a0abb3c77b2a8', '0x81c2c92e47edaee6', '0x92722c851482353b',\n '0xa2bfe8a14cf10364', '0xa81a664bbc423001', '0xc24b8b70d0f89791', '0xc76c51a30654be30',\n '0xd192e819d6ef5218', '0xd69906245565a910', '0xf40e35855771202a', '0x106aa07032bbd1b8',\n '0x19a4c116b8d2d0c8', '0x1e376c085141ab53', '0x2748774cdf8eeb99', '0x34b0bcb5e19b48a8',\n '0x391c0cb3c5c95a63', '0x4ed8aa4ae3418acb', '0x5b9cca4f7763e373', '0x682e6ff3d6b2b8a3',\n '0x748f82ee5defb2fc', '0x78a5636f43172f60', '0x84c87814a1f0ab72', '0x8cc702081a6439ec',\n '0x90befffa23631e28', '0xa4506cebde82bde9', '0xbef9a3f7b2c67915', '0xc67178f2e372532b',\n '0xca273eceea26619c', '0xd186b8c721c0c207', '0xeada7dd6cde0eb1e', '0xf57d4f7fee6ed178',\n '0x06f067aa72176fba', '0x0a637dc5a2c898a6', '0x113f9804bef90dae', '0x1b710b35131c471b',\n '0x28db77f523047d84', '0x32caab7b40c72493', '0x3c9ebe0a15c9bebc', '0x431d67c49c100d4c',\n '0x4cc5d4becb3e42b6', '0x597f299cfc657e2a', '0x5fcb6fab3ad6faec', '0x6c44198c4a475817'\n].map(n => BigInt(n))))();\nconst SHA512_Kh = /* @__PURE__ */ (() => K512[0])();\nconst SHA512_Kl = /* @__PURE__ */ (() => K512[1])();\n// Reusable high-half schedule buffer for the RFC 6234 §6.4 64-bit `W_t` words.\nconst SHA512_W_H = /* @__PURE__ */ new Uint32Array(80);\n// Reusable low-half schedule buffer for the RFC 6234 §6.4 64-bit `W_t` words.\nconst SHA512_W_L = /* @__PURE__ */ new Uint32Array(80);\n/** Internal SHA-384 / SHA-512 compression engine from RFC 6234 §6.4. */\nclass SHA2_64B extends HashMD {\n constructor(outputLen) {\n super(128, outputLen, 16, false);\n }\n // prettier-ignore\n get() {\n const { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;\n return [Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl];\n }\n // prettier-ignore\n set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl) {\n this.Ah = Ah | 0;\n this.Al = Al | 0;\n this.Bh = Bh | 0;\n this.Bl = Bl | 0;\n this.Ch = Ch | 0;\n this.Cl = Cl | 0;\n this.Dh = Dh | 0;\n this.Dl = Dl | 0;\n this.Eh = Eh | 0;\n this.El = El | 0;\n this.Fh = Fh | 0;\n this.Fl = Fl | 0;\n this.Gh = Gh | 0;\n this.Gl = Gl | 0;\n this.Hh = Hh | 0;\n this.Hl = Hl | 0;\n }\n process(view, offset) {\n // Extend the first 16 words into the remaining 64 words w[16..79] of the message schedule array\n for (let i = 0; i < 16; i++, offset += 4) {\n SHA512_W_H[i] = view.getUint32(offset);\n SHA512_W_L[i] = view.getUint32((offset += 4));\n }\n for (let i = 16; i < 80; i++) {\n // s0 := (w[i-15] rightrotate 1) xor (w[i-15] rightrotate 8) xor (w[i-15] rightshift 7)\n const W15h = SHA512_W_H[i - 15] | 0;\n const W15l = SHA512_W_L[i - 15] | 0;\n const s0h = u64.rotrSH(W15h, W15l, 1) ^ u64.rotrSH(W15h, W15l, 8) ^ u64.shrSH(W15h, W15l, 7);\n const s0l = u64.rotrSL(W15h, W15l, 1) ^ u64.rotrSL(W15h, W15l, 8) ^ u64.shrSL(W15h, W15l, 7);\n // s1 := (w[i-2] rightrotate 19) xor (w[i-2] rightrotate 61) xor (w[i-2] rightshift 6)\n const W2h = SHA512_W_H[i - 2] | 0;\n const W2l = SHA512_W_L[i - 2] | 0;\n const s1h = u64.rotrSH(W2h, W2l, 19) ^ u64.rotrBH(W2h, W2l, 61) ^ u64.shrSH(W2h, W2l, 6);\n const s1l = u64.rotrSL(W2h, W2l, 19) ^ u64.rotrBL(W2h, W2l, 61) ^ u64.shrSL(W2h, W2l, 6);\n // SHA512_W[i] = s0 + s1 + SHA512_W[i - 7] + SHA512_W[i - 16];\n const SUMl = u64.add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]);\n const SUMh = u64.add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]);\n SHA512_W_H[i] = SUMh | 0;\n SHA512_W_L[i] = SUMl | 0;\n }\n let { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;\n // Compression function main loop, 80 rounds\n for (let i = 0; i < 80; i++) {\n // S1 := (e rightrotate 14) xor (e rightrotate 18) xor (e rightrotate 41)\n const sigma1h = u64.rotrSH(Eh, El, 14) ^ u64.rotrSH(Eh, El, 18) ^ u64.rotrBH(Eh, El, 41);\n const sigma1l = u64.rotrSL(Eh, El, 14) ^ u64.rotrSL(Eh, El, 18) ^ u64.rotrBL(Eh, El, 41);\n //const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;\n const CHIh = (Eh & Fh) ^ (~Eh & Gh);\n const CHIl = (El & Fl) ^ (~El & Gl);\n // T1 = H + sigma1 + Chi(E, F, G) + SHA512_K[i] + SHA512_W[i]\n // prettier-ignore\n const T1ll = u64.add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]);\n const T1h = u64.add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]);\n const T1l = T1ll | 0;\n // S0 := (a rightrotate 28) xor (a rightrotate 34) xor (a rightrotate 39)\n const sigma0h = u64.rotrSH(Ah, Al, 28) ^ u64.rotrBH(Ah, Al, 34) ^ u64.rotrBH(Ah, Al, 39);\n const sigma0l = u64.rotrSL(Ah, Al, 28) ^ u64.rotrBL(Ah, Al, 34) ^ u64.rotrBL(Ah, Al, 39);\n const MAJh = (Ah & Bh) ^ (Ah & Ch) ^ (Bh & Ch);\n const MAJl = (Al & Bl) ^ (Al & Cl) ^ (Bl & Cl);\n Hh = Gh | 0;\n Hl = Gl | 0;\n Gh = Fh | 0;\n Gl = Fl | 0;\n Fh = Eh | 0;\n Fl = El | 0;\n ({ h: Eh, l: El } = u64.add(Dh | 0, Dl | 0, T1h | 0, T1l | 0));\n Dh = Ch | 0;\n Dl = Cl | 0;\n Ch = Bh | 0;\n Cl = Bl | 0;\n Bh = Ah | 0;\n Bl = Al | 0;\n const All = u64.add3L(T1l, sigma0l, MAJl);\n Ah = u64.add3H(All, T1h, sigma0h, MAJh);\n Al = All | 0;\n }\n // Add the compressed chunk to the current hash value\n ({ h: Ah, l: Al } = u64.add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0));\n ({ h: Bh, l: Bl } = u64.add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0));\n ({ h: Ch, l: Cl } = u64.add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0));\n ({ h: Dh, l: Dl } = u64.add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0));\n ({ h: Eh, l: El } = u64.add(this.Eh | 0, this.El | 0, Eh | 0, El | 0));\n ({ h: Fh, l: Fl } = u64.add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0));\n ({ h: Gh, l: Gl } = u64.add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0));\n ({ h: Hh, l: Hl } = u64.add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0));\n this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl);\n }\n roundClean() {\n clean(SHA512_W_H, SHA512_W_L);\n }\n destroy() {\n // HashMD callers route post-destroy usability through `destroyed`; zeroizing alone still leaves\n // update()/digest() callable on reused instances.\n this.destroyed = true;\n clean(this.buffer);\n this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);\n }\n}\n/** Internal SHA-512 hash class grounded in RFC 6234 §6.3 and §6.4. */\nexport class _SHA512 extends SHA2_64B {\n Ah = SHA512_IV[0] | 0;\n Al = SHA512_IV[1] | 0;\n Bh = SHA512_IV[2] | 0;\n Bl = SHA512_IV[3] | 0;\n Ch = SHA512_IV[4] | 0;\n Cl = SHA512_IV[5] | 0;\n Dh = SHA512_IV[6] | 0;\n Dl = SHA512_IV[7] | 0;\n Eh = SHA512_IV[8] | 0;\n El = SHA512_IV[9] | 0;\n Fh = SHA512_IV[10] | 0;\n Fl = SHA512_IV[11] | 0;\n Gh = SHA512_IV[12] | 0;\n Gl = SHA512_IV[13] | 0;\n Hh = SHA512_IV[14] | 0;\n Hl = SHA512_IV[15] | 0;\n constructor() {\n super(64);\n }\n}\n/** Internal SHA-384 hash class grounded in RFC 6234 §6.3 and §6.4. */\nexport class _SHA384 extends SHA2_64B {\n Ah = SHA384_IV[0] | 0;\n Al = SHA384_IV[1] | 0;\n Bh = SHA384_IV[2] | 0;\n Bl = SHA384_IV[3] | 0;\n Ch = SHA384_IV[4] | 0;\n Cl = SHA384_IV[5] | 0;\n Dh = SHA384_IV[6] | 0;\n Dl = SHA384_IV[7] | 0;\n Eh = SHA384_IV[8] | 0;\n El = SHA384_IV[9] | 0;\n Fh = SHA384_IV[10] | 0;\n Fl = SHA384_IV[11] | 0;\n Gh = SHA384_IV[12] | 0;\n Gl = SHA384_IV[13] | 0;\n Hh = SHA384_IV[14] | 0;\n Hl = SHA384_IV[15] | 0;\n constructor() {\n super(48);\n }\n}\n/**\n * Truncated SHA512/256 and SHA512/224.\n * SHA512_IV is XORed with 0xa5a5a5a5a5a5a5a5, then used as \"intermediary\" IV of SHA512/t.\n * Then t hashes string to produce result IV.\n * See the repo-side derivation recipe in `test/misc/sha2-gen-iv.js`.\n * These IV literals are checked against that script rather than a dedicated\n * local RFC section.\n */\n/** SHA-512/224 IV derived by the SHA-512/t recipe in `test/misc/sha2-gen-iv.js` and\n * stored as sixteen big-endian 32-bit halves. */\nconst T224_IV = /* @__PURE__ */ Uint32Array.from([\n 0x8c3d37c8, 0x19544da2, 0x73e19966, 0x89dcd4d6, 0x1dfab7ae, 0x32ff9c82, 0x679dd514, 0x582f9fcf,\n 0x0f6d2b69, 0x7bd44da8, 0x77e36f73, 0x04c48942, 0x3f9d85a8, 0x6a1d36c8, 0x1112e6ad, 0x91d692a1,\n]);\n/** SHA-512/256 IV derived by the SHA-512/t recipe in `test/misc/sha2-gen-iv.js` and\n * stored as sixteen big-endian 32-bit halves. */\nconst T256_IV = /* @__PURE__ */ Uint32Array.from([\n 0x22312194, 0xfc2bf72c, 0x9f555fa3, 0xc84c64c2, 0x2393b86b, 0x6f53b151, 0x96387719, 0x5940eabd,\n 0x96283ee2, 0xa88effe3, 0xbe5e1e25, 0x53863992, 0x2b0199fc, 0x2c85b8aa, 0x0eb72ddc, 0x81c52ca2,\n]);\n/** Internal SHA-512/224 hash class using the derived `T224_IV` and the shared\n * RFC 6234 §6.4 compression engine. */\nexport class _SHA512_224 extends SHA2_64B {\n Ah = T224_IV[0] | 0;\n Al = T224_IV[1] | 0;\n Bh = T224_IV[2] | 0;\n Bl = T224_IV[3] | 0;\n Ch = T224_IV[4] | 0;\n Cl = T224_IV[5] | 0;\n Dh = T224_IV[6] | 0;\n Dl = T224_IV[7] | 0;\n Eh = T224_IV[8] | 0;\n El = T224_IV[9] | 0;\n Fh = T224_IV[10] | 0;\n Fl = T224_IV[11] | 0;\n Gh = T224_IV[12] | 0;\n Gl = T224_IV[13] | 0;\n Hh = T224_IV[14] | 0;\n Hl = T224_IV[15] | 0;\n constructor() {\n super(28);\n }\n}\n/** Internal SHA-512/256 hash class using the derived `T256_IV` and the shared\n * RFC 6234 §6.4 compression engine. */\nexport class _SHA512_256 extends SHA2_64B {\n Ah = T256_IV[0] | 0;\n Al = T256_IV[1] | 0;\n Bh = T256_IV[2] | 0;\n Bl = T256_IV[3] | 0;\n Ch = T256_IV[4] | 0;\n Cl = T256_IV[5] | 0;\n Dh = T256_IV[6] | 0;\n Dl = T256_IV[7] | 0;\n Eh = T256_IV[8] | 0;\n El = T256_IV[9] | 0;\n Fh = T256_IV[10] | 0;\n Fl = T256_IV[11] | 0;\n Gh = T256_IV[12] | 0;\n Gl = T256_IV[13] | 0;\n Hh = T256_IV[14] | 0;\n Hl = T256_IV[15] | 0;\n constructor() {\n super(32);\n }\n}\n/**\n * SHA2-256 hash function from RFC 4634. In JS it's the fastest: even faster than Blake3. Some info:\n *\n * - Trying 2^128 hashes would get 50% chance of collision, using birthday attack.\n * - BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.\n * - Each sha256 hash is executing 2^18 bit operations.\n * - Good 2024 ASICs can do 200Th/sec with 3500 watts of power, corresponding to 2^36 hashes/joule.\n * @param msg - message bytes to hash\n * @returns Digest bytes.\n * @example\n * Hash a message with SHA2-256.\n * ```ts\n * sha256(new Uint8Array([97, 98, 99]));\n * ```\n */\nexport const sha256 = /* @__PURE__ */ createHasher(() => new _SHA256(), \n/* @__PURE__ */ oidNist(0x01));\n/**\n * SHA2-224 hash function from RFC 4634.\n * @param msg - message bytes to hash\n * @returns Digest bytes.\n * @example\n * Hash a message with SHA2-224.\n * ```ts\n * sha224(new Uint8Array([97, 98, 99]));\n * ```\n */\nexport const sha224 = /* @__PURE__ */ createHasher(() => new _SHA224(), \n/* @__PURE__ */ oidNist(0x04));\n/**\n * SHA2-512 hash function from RFC 4634.\n * @param msg - message bytes to hash\n * @returns Digest bytes.\n * @example\n * Hash a message with SHA2-512.\n * ```ts\n * sha512(new Uint8Array([97, 98, 99]));\n * ```\n */\nexport const sha512 = /* @__PURE__ */ createHasher(() => new _SHA512(), \n/* @__PURE__ */ oidNist(0x03));\n/**\n * SHA2-384 hash function from RFC 4634.\n * @param msg - message bytes to hash\n * @returns Digest bytes.\n * @example\n * Hash a message with SHA2-384.\n * ```ts\n * sha384(new Uint8Array([97, 98, 99]));\n * ```\n */\nexport const sha384 = /* @__PURE__ */ createHasher(() => new _SHA384(), \n/* @__PURE__ */ oidNist(0x02));\n/**\n * SHA2-512/256 \"truncated\" hash function, with improved resistance to length extension attacks.\n * See the paper on {@link https://eprint.iacr.org/2010/548.pdf | truncated SHA512}.\n * @param msg - message bytes to hash\n * @returns Digest bytes.\n * @example\n * Hash a message with SHA2-512/256.\n * ```ts\n * sha512_256(new Uint8Array([97, 98, 99]));\n * ```\n */\nexport const sha512_256 = /* @__PURE__ */ createHasher(() => new _SHA512_256(), \n/* @__PURE__ */ oidNist(0x06));\n/**\n * SHA2-512/224 \"truncated\" hash function, with improved resistance to length extension attacks.\n * See the paper on {@link https://eprint.iacr.org/2010/548.pdf | truncated SHA512}.\n * @param msg - message bytes to hash\n * @returns Digest bytes.\n * @example\n * Hash a message with SHA2-512/224.\n * ```ts\n * sha512_224(new Uint8Array([97, 98, 99]));\n * ```\n */\nexport const sha512_224 = /* @__PURE__ */ createHasher(() => new _SHA512_224(), \n/* @__PURE__ */ oidNist(0x05));\n//# sourceMappingURL=sha2.js.map","/**\n * Ed25519 key generation, persistence, and challenge signing for CLI auth.\n * Mirrors @abraca/mcp/src/crypto.ts — standalone to avoid MCP SDK dependency.\n */\nimport * as ed from '@noble/ed25519'\nimport { sha512 } from '@noble/hashes/sha2.js'\nimport { readFile, writeFile, mkdir } from 'node:fs/promises'\n\n// @noble/ed25519 v3 hash hook\ned.hashes.sha512 = sha512\ned.hashes.sha512Async = (m: Uint8Array) => Promise.resolve(sha512(m))\nimport { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join, dirname } from 'node:path'\n\nconst DEFAULT_KEY_PATH = join(homedir(), '.abracadabra', 'cli.key')\n\nfunction toBase64url(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString('base64url')\n}\n\nfunction fromBase64url(b64: string): Uint8Array {\n return new Uint8Array(Buffer.from(b64, 'base64url'))\n}\n\nexport interface CLIKeypair {\n privateKey: Uint8Array\n publicKeyB64: string\n}\n\n/**\n * Load an existing Ed25519 keypair from disk, or generate and persist a new one.\n * The file stores the raw 32-byte private key seed.\n */\nexport async function loadOrCreateKeypair(keyPath?: string): Promise<CLIKeypair> {\n const path = keyPath || DEFAULT_KEY_PATH\n\n if (existsSync(path)) {\n const seed = await readFile(path)\n if (seed.length !== 32) {\n throw new Error(`Invalid key file at ${path}: expected 32 bytes, got ${seed.length}`)\n }\n const privateKey = new Uint8Array(seed)\n const publicKey = ed.getPublicKey(privateKey)\n return { privateKey, publicKeyB64: toBase64url(publicKey) }\n }\n\n // Generate new keypair\n const privateKey = ed.utils.randomSecretKey()\n const publicKey = ed.getPublicKey(privateKey)\n\n // Ensure directory exists and write seed with restricted permissions\n const dir = dirname(path)\n if (!existsSync(dir)) {\n await mkdir(dir, { recursive: true, mode: 0o700 })\n }\n await writeFile(path, Buffer.from(privateKey), { mode: 0o600 })\n\n console.error(`[abracadabra] Generated new keypair at ${path}`)\n console.error(`[abracadabra] Public key: ${toBase64url(publicKey)}`)\n\n return { privateKey, publicKeyB64: toBase64url(publicKey) }\n}\n\n/** Sign a base64url challenge with the private key; returns base64url signature. */\nexport function signChallenge(challengeB64: string, privateKey: Uint8Array): string {\n const challenge = fromBase64url(challengeB64)\n const sig = ed.sign(challenge, privateKey)\n return toBase64url(sig)\n}\n","/**\n * CLIConnection — manages the CRDT connection lifecycle for the CLI.\n *\n * Handles: Ed25519 auth → space discovery → Y.Doc sync → awareness.\n * Reuses the same patterns as AbracadabraMCPServer but without MCP SDK dependency.\n */\nimport * as Y from 'yjs'\nimport { AbracadabraProvider, AbracadabraClient, Kind } from '@abraca/dabra'\nimport type { ServerInfo, DocumentMeta } from '@abraca/dabra'\nimport { loadOrCreateKeypair, signChallenge } from './crypto.ts'\n\nexport interface CLIConnectionConfig {\n url: string\n name?: string\n color?: string\n inviteCode?: string\n keyFile?: string\n /** If true, suppress all stderr logging */\n quiet?: boolean\n}\n\ninterface CachedProvider {\n provider: AbracadabraProvider\n lastAccessed: number\n}\n\nfunction waitForSync(\n provider: { on(event: string, cb: () => void): void; off(event: string, cb: () => void): void },\n timeoutMs = 15000\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => {\n provider.off('synced', handler)\n reject(new Error(`Sync timed out after ${timeoutMs}ms`))\n }, timeoutMs)\n\n function handler() {\n clearTimeout(timer)\n resolve()\n }\n\n provider.on('synced', handler)\n })\n}\n\nexport class CLIConnection {\n readonly config: CLIConnectionConfig\n readonly client: AbracadabraClient\n\n private _serverInfo: ServerInfo | null = null\n private _rootDocId: string | null = null\n private _spaces: DocumentMeta[] = []\n private _rootDoc: Y.Doc | null = null\n private _rootProvider: AbracadabraProvider | null = null\n private _userId: string | null = null\n private _signFn: ((challenge: string) => Promise<string>) | null = null\n private childCache = new Map<string, CachedProvider>()\n\n constructor(config: CLIConnectionConfig) {\n this.config = config\n this.client = new AbracadabraClient({\n url: config.url,\n persistAuth: false,\n })\n }\n\n get displayName(): string {\n return this.config.name || 'CLI User'\n }\n\n get displayColor(): string {\n return this.config.color || 'hsl(45, 90%, 55%)'\n }\n\n get serverInfo(): ServerInfo | null {\n return this._serverInfo\n }\n\n get rootDocId(): string | null {\n return this._rootDocId\n }\n\n get spaces(): DocumentMeta[] {\n return this._spaces\n }\n\n get rootDoc(): Y.Doc | null {\n return this._rootDoc\n }\n\n get rootProvider(): AbracadabraProvider | null {\n return this._rootProvider\n }\n\n get userId(): string | null {\n return this._userId\n }\n\n private log(msg: string): void {\n if (!this.config.quiet) {\n console.error(`[abracadabra] ${msg}`)\n }\n }\n\n /** Connect to the server: authenticate, discover spaces, sync root doc. */\n async connect(): Promise<void> {\n // Step 1: Load or generate Ed25519 keypair\n const keypair = await loadOrCreateKeypair(this.config.keyFile)\n this._userId = keypair.publicKeyB64\n const signFn = (challenge: string) => Promise.resolve(signChallenge(challenge, keypair.privateKey))\n this._signFn = signFn\n\n // Step 2: Authenticate via challenge-response (register on first run)\n try {\n await this.client.loginWithKey(keypair.publicKeyB64, signFn)\n } catch (err: any) {\n const status = err?.status ?? err?.response?.status\n if (status === 404 || status === 422) {\n this.log('Key not registered, creating new account...')\n await this.client.registerWithKey({\n publicKey: keypair.publicKeyB64,\n username: this.displayName.replace(/\\s+/g, '-').toLowerCase(),\n displayName: this.displayName,\n deviceName: 'CLI',\n inviteCode: this.config.inviteCode,\n })\n await this.client.loginWithKey(keypair.publicKeyB64, signFn)\n } else {\n throw err\n }\n }\n this.log(`Authenticated as ${this.displayName} (${keypair.publicKeyB64.slice(0, 12)}...)`)\n\n // Step 3: Discover server info\n this._serverInfo = await this.client.serverInfo()\n\n // Step 4: Pick an entry-point doc — first Space under the server root,\n // falling back to the first top-level doc of any kind.\n const roots = await this.client.listChildren()\n this._spaces = roots.filter(d => d.kind === Kind.Space)\n const first = this._spaces[0] ?? roots[0]\n const initialDocId = first?.id ?? null\n if (first) {\n this.log(`Entry document: ${first.label ?? first.id} (${first.id})`)\n }\n\n if (!initialDocId) {\n throw new Error(\n 'No entry point found: server has no top-level documents. Create a Space first.',\n )\n }\n\n this._rootDocId = initialDocId\n\n // Step 5: Connect provider and sync\n const doc = new Y.Doc({ guid: initialDocId })\n const provider = new AbracadabraProvider({\n name: initialDocId,\n document: doc,\n client: this.client,\n disableOfflineStore: true,\n subdocLoading: 'lazy',\n })\n\n await waitForSync(provider)\n\n provider.awareness.setLocalStateField('user', {\n name: this.displayName,\n color: this.displayColor,\n publicKey: this._userId,\n isAgent: false,\n })\n provider.awareness.setLocalStateField('status', null)\n\n this._rootDoc = doc\n this._rootProvider = provider\n this.log('Connected and synced')\n }\n\n /** Switch active space to a different root document. */\n async switchSpace(docId: string): Promise<void> {\n // Destroy existing child providers\n for (const [, cached] of this.childCache) {\n cached.provider.destroy()\n }\n this.childCache.clear()\n\n // Destroy current root provider\n if (this._rootProvider) {\n this._rootProvider.destroy()\n this._rootProvider = null\n }\n this._rootDoc = null\n\n // Re-authenticate if JWT has expired\n if (!this.client.isTokenValid() && this._signFn && this._userId) {\n await this.client.loginWithKey(this._userId, this._signFn)\n }\n\n // Connect to new space\n const doc = new Y.Doc({ guid: docId })\n const provider = new AbracadabraProvider({\n name: docId,\n document: doc,\n client: this.client,\n disableOfflineStore: true,\n subdocLoading: 'lazy',\n })\n\n await waitForSync(provider)\n\n provider.awareness.setLocalStateField('user', {\n name: this.displayName,\n color: this.displayColor,\n publicKey: this._userId,\n isAgent: false,\n })\n\n this._rootDoc = doc\n this._rootProvider = provider\n this._rootDocId = docId\n this.log(`Switched to space ${docId}`)\n }\n\n /** Get the root doc-tree Y.Map. */\n getTreeMap(): Y.Map<any> | null {\n return this._rootDoc?.getMap('doc-tree') ?? null\n }\n\n /** Get the root doc-trash Y.Map. */\n getTrashMap(): Y.Map<any> | null {\n return this._rootDoc?.getMap('doc-trash') ?? null\n }\n\n /** Get or create a child provider for a document. */\n async getChildProvider(docId: string): Promise<AbracadabraProvider> {\n const cached = this.childCache.get(docId)\n if (cached) {\n cached.lastAccessed = Date.now()\n return cached.provider\n }\n\n if (!this._rootProvider) {\n throw new Error('Not connected. Call connect() first.')\n }\n\n // Re-authenticate if JWT has expired\n if (!this.client.isTokenValid() && this._signFn && this._userId) {\n await this.client.loginWithKey(this._userId, this._signFn)\n }\n\n const childProvider = await this._rootProvider.loadChild(docId)\n await waitForSync(childProvider)\n\n childProvider.awareness.setLocalStateField('user', {\n name: this.displayName,\n color: this.displayColor,\n publicKey: this._userId,\n isAgent: false,\n })\n\n this.childCache.set(docId, {\n provider: childProvider,\n lastAccessed: Date.now(),\n })\n\n return childProvider\n }\n\n /** Graceful shutdown. */\n async destroy(): Promise<void> {\n for (const [, cached] of this.childCache) {\n cached.provider.destroy()\n }\n this.childCache.clear()\n\n if (this._rootProvider) {\n this._rootProvider.awareness.setLocalStateField('status', null)\n this._rootProvider.destroy()\n this._rootProvider = null\n }\n this._rootDoc = null\n\n this.log('Disconnected')\n }\n}\n","/**\n * Command interface and registry.\n */\nimport type { CLIConnection } from './connection.ts'\nimport type { ParsedArgs } from './parser.ts'\n\nexport interface Command {\n name: string\n aliases?: string[]\n description: string\n usage?: string\n run(conn: CLIConnection | null, args: ParsedArgs): Promise<string>\n}\n\nconst commands: Command[] = []\n\nexport function registerCommand(cmd: Command): void {\n commands.push(cmd)\n}\n\nexport function getCommand(name: string): Command | null {\n return commands.find(c =>\n c.name === name || c.aliases?.includes(name)\n ) ?? null\n}\n\nexport function getAllCommands(): Command[] {\n return [...commands]\n}\n","/**\n * Output formatting utilities for Abracadabra CLI.\n *\n * Supports JSON, TSV, tree, and compact text output.\n */\n\nimport type { ParsedArgs } from './parser.ts'\n\nexport type OutputFormat = 'json' | 'tsv' | 'tree' | 'text' | 'md'\n\nexport function getFormat(args: ParsedArgs, defaultFormat: OutputFormat = 'text'): OutputFormat {\n const f = args.params['format']\n if (f && ['json', 'tsv', 'tree', 'text', 'md'].includes(f)) {\n return f as OutputFormat\n }\n return defaultFormat\n}\n\n/** Print a JSON-serializable value. */\nexport function printJson(data: unknown): string {\n return JSON.stringify(data, null, 2)\n}\n\n/** Print a list of objects as TSV. */\nexport function printTsv(rows: Record<string, unknown>[], columns?: string[]): string {\n if (rows.length === 0) return ''\n const cols = columns ?? Object.keys(rows[0])\n const header = cols.map(c => c.toUpperCase()).join('\\t')\n const body = rows.map(row =>\n cols.map(c => {\n const val = row[c]\n if (val == null) return '—'\n if (typeof val === 'object') return JSON.stringify(val)\n return String(val)\n }).join('\\t')\n ).join('\\n')\n return header + '\\n' + body\n}\n\n/** Format a tree of nested items with box-drawing characters. */\nexport function printTree(\n items: TreeNode[],\n opts: { indent?: string, isLast?: boolean[] } = {}\n): string {\n const lines: string[] = []\n for (let i = 0; i < items.length; i++) {\n const item = items[i]\n const isLast = i === items.length - 1\n const prefix = (opts.isLast ?? [])\n .map(last => last ? ' ' : '│ ')\n .join('')\n const connector = isLast ? '└── ' : '├── '\n const typeSuffix = item.type ? ` (${item.type})` : ''\n lines.push(`${prefix}${connector}${item.label}${typeSuffix}`)\n if (item.children && item.children.length > 0) {\n lines.push(printTree(item.children, {\n isLast: [...(opts.isLast ?? []), isLast],\n }))\n }\n }\n return lines.join('\\n')\n}\n\nexport interface TreeNode {\n label: string\n type?: string\n children?: TreeNode[]\n}\n\n/** Format relative time (e.g. \"2m ago\", \"1h ago\"). */\nexport function relativeTime(timestamp: number | undefined | null): string {\n if (!timestamp) return '—'\n const diff = Date.now() - timestamp\n if (diff < 0) return 'just now'\n if (diff < 60_000) return `${Math.floor(diff / 1000)}s ago`\n if (diff < 3_600_000) return `${Math.floor(diff / 60_000)}m ago`\n if (diff < 86_400_000) return `${Math.floor(diff / 3_600_000)}h ago`\n return `${Math.floor(diff / 86_400_000)}d ago`\n}\n\n/** Truncate a string to a max length, appending '…' if truncated. */\nexport function truncate(str: string, max: number): string {\n if (str.length <= max) return str\n return str.slice(0, max - 1) + '…'\n}\n\n/** Pad a string to a fixed width. */\nexport function pad(str: string, width: number): string {\n if (str.length >= width) return str.slice(0, width)\n return str + ' '.repeat(width - str.length)\n}\n\n/** Format a table with auto-column widths. */\nexport function printTable(rows: string[][], headers?: string[]): string {\n const allRows = headers ? [headers, ...rows] : rows\n if (allRows.length === 0) return ''\n\n const colCount = Math.max(...allRows.map(r => r.length))\n const widths: number[] = []\n for (let c = 0; c < colCount; c++) {\n widths[c] = Math.max(...allRows.map(r => (r[c] ?? '').length))\n }\n\n const formatted = allRows.map(row =>\n row.map((cell, i) => pad(cell, widths[i])).join(' ')\n )\n\n return formatted.join('\\n')\n}\n","/**\n * help + version commands.\n */\nimport { registerCommand, getAllCommands } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { pad } from '../output.ts'\n\nregisterCommand({\n name: 'help',\n aliases: ['h', '?'],\n description: 'Show list of all available commands.',\n usage: 'help [<command>]',\n async run(_conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n const target = args.positional[0]\n\n if (target) {\n const cmd = getAllCommands().find(c =>\n c.name === target || c.aliases?.includes(target)\n )\n if (!cmd) {\n return `Unknown command: ${target}\\n\\nRun 'abracadabra help' to see all commands.`\n }\n const aliasStr = cmd.aliases?.length ? ` (aliases: ${cmd.aliases.join(', ')})` : ''\n let text = `${cmd.name}${aliasStr}\\n ${cmd.description}`\n if (cmd.usage) text += `\\n\\n Usage: abracadabra ${cmd.usage}`\n return text\n }\n\n const cmds = getAllCommands()\n const maxLen = Math.max(...cmds.map(c => c.name.length))\n\n const lines = [\n 'Abracadabra CLI — interact with CRDT document workspaces from the terminal.',\n '',\n 'Usage: abracadabra <command> [key=value ...] [--flags]',\n '',\n 'Commands:',\n ...cmds.map(c => {\n const aliasStr = c.aliases?.length ? ` (${c.aliases.join(', ')})` : ''\n return ` ${pad(c.name, maxLen + 2)}${c.description}${aliasStr}`\n }),\n '',\n 'Environment:',\n ' ABRA_URL Server URL (required)',\n ' ABRA_KEY_FILE Path to Ed25519 key file',\n ' ABRA_INVITE_CODE Invite code for first-run registration',\n ' ABRA_NAME Display name',\n ' ABRA_COLOR Presence color',\n '',\n 'Run \"abracadabra help <command>\" for command-specific help.',\n ]\n return lines.join('\\n')\n },\n})\n\nregisterCommand({\n name: 'version',\n aliases: ['v'],\n description: 'Show CLI and server version.',\n async run(conn: CLIConnection | null): Promise<string> {\n const cliVersion = '1.0.0'\n const lines = [`Abracadabra CLI v${cliVersion}`]\n if (conn?.serverInfo) {\n const si = conn.serverInfo\n if (si.version) lines.push(`Server v${si.version}`)\n if (si.name) lines.push(`Server name ${si.name}`)\n if (si.protocol_version) lines.push(`Protocol ${si.protocol_version}`)\n }\n return lines.join('\\n')\n },\n})\n","/**\n * Document resolution utilities for the CLI.\n *\n * Resolves documents by id, name (label), or path (label chain from root).\n * Similar to Obsidian's file= / path= resolution.\n */\nimport * as Y from 'yjs'\nimport type { CLIConnection } from './connection.ts'\n\nexport interface TreeEntry {\n id: string\n label: string\n parentId: string | null\n order: number\n type?: string\n meta?: Record<string, unknown>\n createdAt?: number\n updatedAt?: number\n}\n\n/** Safely read a tree map value, converting Y.Map to plain object if needed. */\nfunction toPlain(val: any): any {\n return val instanceof Y.Map ? val.toJSON() : val\n}\n\n/** Read all tree entries from the Y.Map. */\nexport function readEntries(treeMap: Y.Map<any>): TreeEntry[] {\n const entries: TreeEntry[] = []\n treeMap.forEach((raw: any, id: string) => {\n const value = toPlain(raw)\n if (typeof value !== 'object' || value === null) return\n entries.push({\n id,\n label: value.label || 'Untitled',\n parentId: value.parentId ?? null,\n order: value.order ?? 0,\n type: value.type,\n meta: value.meta,\n createdAt: value.createdAt,\n updatedAt: value.updatedAt,\n })\n })\n return entries\n}\n\n/** Get direct children of a parent, sorted by order. */\nexport function childrenOf(entries: TreeEntry[], parentId: string | null): TreeEntry[] {\n return entries\n .filter(e => e.parentId === parentId)\n .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))\n}\n\n/** Get all descendants of an entry. */\nexport function descendantsOf(entries: TreeEntry[], id: string | null): TreeEntry[] {\n const result: TreeEntry[] = []\n const visited = new Set<string>()\n function collect(pid: string) {\n if (visited.has(pid)) return\n visited.add(pid)\n for (const child of childrenOf(entries, pid)) {\n result.push(child)\n collect(child.id)\n }\n }\n collect(id!)\n return result\n}\n\n/** Build a nested tree structure for display. */\nexport function buildTree(entries: TreeEntry[], rootId: string | null, maxDepth: number, currentDepth = 0, visited = new Set<string>()): TreeDisplayNode[] {\n if (maxDepth >= 0 && currentDepth >= maxDepth) return []\n const children = childrenOf(entries, rootId)\n return children.filter(e => !visited.has(e.id)).map(entry => {\n const next = new Set(visited)\n next.add(entry.id)\n return {\n id: entry.id,\n label: entry.label,\n type: entry.type,\n meta: entry.meta,\n children: buildTree(entries, entry.id, maxDepth, currentDepth + 1, next),\n }\n })\n}\n\nexport interface TreeDisplayNode {\n id: string\n label: string\n type?: string\n meta?: Record<string, unknown>\n children: TreeDisplayNode[]\n}\n\n/**\n * Normalize a document ID so the hub/root doc ID is treated as the tree root (null).\n */\nexport function normalizeRootId(id: string | null | undefined, conn: CLIConnection): string | null {\n if (id == null) return null\n return id === conn.rootDocId ? null : id\n}\n\n/**\n * Resolve a document from parsed args.\n *\n * Resolution order:\n * 1. id=<uuid> — Direct document ID\n * 2. name=<label> — Case-insensitive label match (first match wins)\n * 3. path=<a/b/c> — Resolve by label path from root\n * 4. First positional argument — tries name resolution\n *\n * Returns the document ID or null if not found.\n */\nexport function resolveDocument(\n conn: CLIConnection,\n params: Record<string, string>,\n positional: string[],\n): string | null {\n const treeMap = conn.getTreeMap()\n if (!treeMap) return null\n\n const entries = readEntries(treeMap)\n\n // 1. Direct ID\n if (params['id']) {\n const entry = entries.find(e => e.id === params['id'])\n return entry ? entry.id : null\n }\n\n // 2. Name resolution (case-insensitive label match)\n const name = params['name'] || params['file'] || positional[0]\n if (name) {\n const lower = name.toLowerCase()\n const match = entries.find(e => e.label.toLowerCase() === lower)\n if (match) return match.id\n\n // Substring match as fallback\n const substring = entries.find(e => e.label.toLowerCase().includes(lower))\n if (substring) return substring.id\n }\n\n // 3. Path resolution (slash-separated label chain)\n if (params['path']) {\n const segments = params['path'].split('/').map(s => s.trim()).filter(Boolean)\n let currentParent: string | null = normalizeRootId(conn.rootDocId, conn)\n\n for (const segment of segments) {\n const lower = segment.toLowerCase()\n const children = childrenOf(entries, currentParent)\n const match = children.find(c => c.label.toLowerCase() === lower)\n if (!match) return null\n currentParent = match.id\n }\n\n return currentParent\n }\n\n return null\n}\n\n/** Get the ancestor path labels for a document. */\nexport function getAncestorPath(entries: TreeEntry[], docId: string): string[] {\n const byId = new Map(entries.map(e => [e.id, e]))\n const path: string[] = []\n let current = byId.get(docId)?.parentId\n const visited = new Set<string>()\n while (current && !visited.has(current)) {\n visited.add(current)\n const parent = byId.get(current)\n if (!parent) break\n path.unshift(parent.label)\n current = parent.parentId\n }\n return path\n}\n","/**\n * spaces, spaces:switch, info commands.\n */\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { printJson, printTable, getFormat } from '../output.ts'\nimport { readEntries } from '../resolve.ts'\n\nregisterCommand({\n name: 'info',\n description: 'Show server and space info.',\n async run(conn: CLIConnection | null): Promise<string> {\n if (!conn) return 'Not connected'\n const si = conn.serverInfo\n if (!si) return 'No server info available'\n\n const treeMap = conn.getTreeMap()\n const docCount = treeMap ? readEntries(treeMap).length : 0\n\n const rootProvider = conn.rootProvider\n const onlineUsers = rootProvider\n ? Array.from(rootProvider.awareness.getStates().values()).filter((s: any) => s.user).length\n : 0\n\n const lines = [\n `Server: ${si.name ?? '—'}`,\n `URL: ${conn.config.url}`,\n `Version: ${si.version ?? '—'}`,\n `Protocol: ${si.protocol_version ?? '—'}`,\n `Active Doc: ${conn.rootDocId ?? '—'}`,\n `Auth: ${si.auth_methods?.join(', ') ?? '—'}`,\n `Registration:${si.registration_allowed ? ' open' : ' closed'}${si.invite_only ? ' (invite only)' : ''}`,\n `Documents: ${docCount}`,\n `Users: ${onlineUsers} online`,\n ]\n return lines.join('\\n')\n },\n})\n\nregisterCommand({\n name: 'spaces',\n description: 'List available spaces (top-level documents).',\n usage: 'spaces [--format=json|tsv]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n const spaces = conn.spaces\n if (!spaces.length) return 'No spaces available.'\n\n const format = getFormat(args, 'text')\n const active = conn.rootDocId\n\n if (format === 'json') {\n return printJson(spaces.map(s => ({ ...s, active: s.id === active })))\n }\n\n const rows = spaces.map(s => {\n const visibility = s.public_access === 'observer' ? 'public' : 'private'\n return [\n s.id === active ? '▸' : ' ',\n s.id.slice(0, 8) + '…',\n s.label ?? s.id,\n visibility,\n ]\n })\n\n return printTable(rows, ['', 'ID', 'NAME', 'VISIBILITY'])\n },\n})\n\nregisterCommand({\n name: 'spaces:switch',\n aliases: ['switch'],\n description: 'Switch the active space.',\n usage: 'spaces:switch name=<name> | id=<docId>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const targetName = args.params['name'] || args.positional[0]\n const targetId = args.params['id']\n\n let docId: string | null = null\n\n if (targetId) {\n docId = targetId\n } else if (targetName) {\n const lower = targetName.toLowerCase()\n const space = conn.spaces.find(s =>\n (s.label ?? s.id).toLowerCase() === lower || s.id === targetName\n )\n if (space) docId = space.id\n }\n\n if (!docId) {\n return 'Space not found. Use \"abracadabra spaces\" to list available spaces.'\n }\n\n await conn.switchSpace(docId)\n const space = conn.spaces.find(s => s.id === docId)\n return `Switched to space \"${space?.label ?? docId}\"`\n },\n})\n","/**\n * tree, ls, search commands — navigate and explore the document tree.\n */\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport {\n readEntries,\n childrenOf,\n buildTree,\n normalizeRootId,\n resolveDocument,\n getAncestorPath,\n type TreeDisplayNode,\n} from '../resolve.ts'\nimport { printJson, printTable, printTree, getFormat, relativeTime, type TreeNode } from '../output.ts'\n\nfunction toTreeNodes(nodes: TreeDisplayNode[]): TreeNode[] {\n return nodes.map(n => ({\n label: n.label,\n type: n.type,\n children: n.children.length > 0 ? toTreeNodes(n.children) : undefined,\n }))\n}\n\nregisterCommand({\n name: 'tree',\n aliases: ['t'],\n description: 'Show the full document tree hierarchy.',\n usage: 'tree [id=<docId>] [depth=<n>] [--format=json|tree]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const rootId = normalizeRootId(\n args.params['id'] || args.positional[0] || conn.rootDocId,\n conn\n )\n const maxDepth = args.params['depth'] ? parseInt(args.params['depth'], 10) : -1\n const format = getFormat(args, 'tree')\n\n const entries = readEntries(treeMap)\n const tree = buildTree(entries, rootId, maxDepth)\n\n if (format === 'json') {\n return printJson(tree)\n }\n\n if (tree.length === 0) {\n return '(empty tree)'\n }\n\n // Find root label for header — the active Space, falling back to its id.\n const activeSpace = conn.spaces.find(s => s.id === conn.rootDocId)\n const rootLabel = activeSpace?.label ?? conn.rootDocId ?? 'Workspace'\n\n return rootLabel + '\\n' + printTree(toTreeNodes(tree))\n },\n})\n\nregisterCommand({\n name: 'ls',\n aliases: ['list', 'l'],\n description: 'List direct children of a document (defaults to root).',\n usage: 'ls [id=<parentId>] [name=<parentName>] [--format=json|tsv] [--total]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n let parentId: string | null = null\n if (args.params['id'] || args.params['name'] || args.params['path'] || args.positional[0]) {\n parentId = resolveDocument(conn, args.params, args.positional)\n if (!parentId && (args.params['id'] || args.params['name'] || args.params['path'])) {\n return 'Document not found.'\n }\n }\n\n const targetId = normalizeRootId(parentId || conn.rootDocId, conn)\n const entries = readEntries(treeMap)\n const children = childrenOf(entries, targetId)\n\n if (args.flags.has('total')) {\n return String(children.length)\n }\n\n const format = getFormat(args, 'text')\n\n if (format === 'json') {\n return printJson(children)\n }\n\n if (children.length === 0) {\n return '(no children)'\n }\n\n const rows = children.map(c => [\n c.id.slice(0, 8) + '…',\n c.label,\n c.type ?? '—',\n relativeTime(c.updatedAt),\n ])\n\n return printTable(rows, ['ID', 'LABEL', 'TYPE', 'UPDATED'])\n },\n})\n\nregisterCommand({\n name: 'search',\n aliases: ['find', 's'],\n description: 'Search documents by label across the tree.',\n usage: 'search query=<text> [id=<rootId>] [--format=json|tsv] [--total]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const query = args.params['query'] || args.positional[0]\n if (!query) return 'Missing required parameter: query=<text>'\n\n const entries = readEntries(treeMap)\n const lowerQuery = query.toLowerCase()\n\n const matches = entries.filter(e =>\n e.label.toLowerCase().includes(lowerQuery)\n )\n\n if (args.flags.has('total')) {\n return String(matches.length)\n }\n\n const format = getFormat(args, 'text')\n\n if (matches.length === 0) {\n return `No documents found matching \"${query}\".`\n }\n\n const results = matches.map(entry => ({\n id: entry.id,\n label: entry.label,\n type: entry.type,\n path: getAncestorPath(entries, entry.id),\n }))\n\n if (format === 'json') {\n return printJson(results)\n }\n\n const rows = results.map(r => [\n r.path.length > 0 ? r.path.join(' / ') + ' / ' + r.label : r.label,\n r.label,\n r.type ?? '—',\n ])\n\n return printTable(rows, ['PATH', 'LABEL', 'TYPE'])\n },\n})\n","import * as Y from 'yjs'\nimport type { DocPageMeta } from './types.ts'\n\n// ── Filename → readable label ────────────────────────────────────────────────\n\n/**\n * Converts a filename (without extension) to a human-readable label.\n *\n * - `this-is-a-doc` → `\"This is a doc\"` (kebab/snake: sentence case)\n * - `ThisIsADoc` → `\"This Is A Doc\"` (PascalCase: preserves word caps)\n * - `thisIsADoc` → `\"This Is A Doc\"` (camelCase: preserves word caps)\n */\nexport function filenameToLabel(raw: string): string {\n const base = raw.replace(/\\.[^.]+$/, '') // strip extension if present\n const spaced = base.replace(/([a-z])([A-Z])/g, '$1 $2')\n const clean = spaced.replace(/[-_.]+/g, ' ').replace(/\\s+/g, ' ').trim()\n return clean.charAt(0).toUpperCase() + clean.slice(1)\n}\n\n// ── YAML frontmatter parser ──────────────────────────────────────────────────\n\nexport interface FrontmatterResult {\n title?: string\n type?: string\n meta: Partial<DocPageMeta>\n body: string\n}\n\nfunction coerceScalar(raw: string): string | number | boolean {\n const trimmed = raw.trim()\n if (trimmed === 'true') return true\n if (trimmed === 'false') return false\n const num = Number(trimmed)\n if (!Number.isNaN(num) && trimmed !== '') return num\n // Strip surrounding quotes\n if ((trimmed.startsWith('\"') && trimmed.endsWith('\"'))\n || (trimmed.startsWith('\\'') && trimmed.endsWith('\\''))) {\n return trimmed.slice(1, -1)\n }\n return trimmed\n}\n\nfunction parseInlineArray(raw: string): string[] {\n // e.g. \"[a, b, c]\"\n return raw.slice(1, -1).split(',').map(s => s.trim()).filter(Boolean)\n}\n\nfunction stripQuotes(s: string): string {\n if (s.length >= 2\n && ((s.startsWith('\"') && s.endsWith('\"'))\n || (s.startsWith('\\'') && s.endsWith('\\'')))) {\n return s.slice(1, -1).replace(/\\\\\"/g, '\"').replace(/\\\\\\\\/g, '\\\\')\n }\n return s\n}\n\nexport function parseFrontmatter(markdown: string): FrontmatterResult {\n const noResult: FrontmatterResult = { meta: {}, body: markdown }\n\n const match = markdown.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/)\n if (!match) return noResult\n\n const yamlBlock = match[1]!\n const body = markdown.slice(match[0].length)\n\n // Parse YAML into a raw map\n const raw: Record<string, string | string[]> = {}\n const lines = yamlBlock.split('\\n')\n let i = 0\n while (i < lines.length) {\n const line = lines[i]!\n // Block sequence: \"key:\\n - a\\n - b\"\n const blockSeqKey = line.match(/^(\\w[\\w-]*):\\s*$/)\n if (blockSeqKey && i + 1 < lines.length && /^\\s+-\\s/.test(lines[i + 1]!)) {\n const key = blockSeqKey[1]!\n const items: string[] = []\n i++\n while (i < lines.length && /^\\s+-\\s/.test(lines[i]!)) {\n items.push(lines[i]!.replace(/^\\s+-\\s/, '').trim())\n i++\n }\n raw[key] = items\n continue\n }\n // Scalar or inline array\n const kvMatch = line.match(/^(\\w[\\w-]*):\\s*(.*)$/)\n if (kvMatch) {\n const key = kvMatch[1]!\n const val = kvMatch[2]!.trim()\n if (val.startsWith('[') && val.endsWith(']')) {\n raw[key] = parseInlineArray(val).map(stripQuotes)\n } else {\n // Strip surrounding quotes up-front so downstream readers\n // don't have to. The original quote state is irrelevant — we\n // re-emit with our canonical quoting rules.\n raw[key] = stripQuotes(val)\n }\n }\n i++\n }\n\n // Map raw YAML keys → PageMeta\n const meta: Partial<DocPageMeta> = {}\n\n const getStr = (keys: string[]): string | undefined => {\n for (const k of keys) {\n const v = raw[k]\n if (typeof v === 'string' && v) return v\n }\n }\n const getArr = (keys: string[]): string[] | undefined => {\n for (const k of keys) {\n const v = raw[k]\n if (Array.isArray(v)) return v\n if (typeof v === 'string' && v) return [v]\n }\n }\n\n if (raw['tags']) meta.tags = Array.isArray(raw['tags']) ? raw['tags'] : [raw['tags'] as string]\n const color = getStr(['color'])\n if (color) meta.color = color\n const icon = getStr(['icon'])\n if (icon) meta.icon = icon\n const status = getStr(['status'])\n if (status) meta.status = status\n\n const priorityRaw = getStr(['priority'])\n if (priorityRaw !== undefined) {\n const map: Record<string, number> = { low: 1, medium: 2, high: 3, urgent: 4 }\n meta.priority = map[priorityRaw.toLowerCase()] ?? (Number(priorityRaw) || 0)\n }\n\n const checkedRaw: unknown = raw['checked'] ?? raw['done']\n if (checkedRaw !== undefined) meta.checked = checkedRaw === 'true' || checkedRaw === true\n\n // Canonical keys are checked first, aliases follow — so files that\n // already use the canonical name (dateStart, dateEnd, subtitle) keep\n // round-tripping byte-stably while legacy aliases still parse.\n const dateStart = getStr(['dateStart', 'date', 'created'])\n if (dateStart) meta.dateStart = dateStart\n const dateEnd = getStr(['dateEnd', 'due'])\n if (dateEnd) meta.dateEnd = dateEnd\n\n const subtitle = getStr(['subtitle', 'description'])\n if (subtitle) meta.subtitle = subtitle\n const url = getStr(['url'])\n if (url) meta.url = url\n\n // Code page type meta.\n const language = getStr(['language'])\n if (language) meta.language = language\n const fileExtension = getStr(['fileExtension'])\n if (fileExtension) meta.fileExtension = fileExtension\n const codeTheme = getStr(['codeTheme'])\n if (codeTheme) meta.codeTheme = codeTheme\n\n const ratingRaw = getStr(['rating'])\n if (ratingRaw !== undefined) {\n const n = Number(ratingRaw)\n if (!Number.isNaN(n)) meta.rating = Math.min(5, Math.max(0, n))\n }\n\n const rawTitle = typeof raw['title'] === 'string' ? raw['title'] : undefined\n const title = rawTitle !== undefined ? stripQuotes(rawTitle) : undefined\n const type = getStr(['type'])\n\n return { title, type, meta, body }\n}\n\n// ── Inline token parsing ─────────────────────────────────────────────────────\n\ninterface InlineToken {\n text: string\n attrs?: Record<string, unknown>\n}\n\n// Re-tokenize the inner text of a wrapping mark (bold/italic/strike) so nested\n// atoms (wikilinks, mentions, code, math) and nested marks survive instead of\n// being captured as a single literal leaf. The wrapping mark's attrs are merged\n// onto every produced child token; object-valued attrs (docLink/mention/badge)\n// are preserved alongside the boolean mark. Terminates because `inner` is\n// strictly shorter than the matched delimiter run.\nfunction pushNested(\n out: InlineToken[],\n inner: string,\n wrap: Record<string, unknown>,\n): void {\n const children = parseInline(inner)\n if (children.length === 0) {\n out.push({ text: inner, attrs: { ...wrap } })\n return\n }\n for (const child of children) {\n out.push({ text: child.text, attrs: { ...(child.attrs ?? {}), ...wrap } })\n }\n}\n\nfunction parseInline(text: string): InlineToken[] {\n // Strip MDC attribute annotations on inline code: `string`{lang=\"ts-type\"}\n const stripped = text.replace(/\\{lang=\"[^\"]*\"\\}/g, '')\n // Strip remaining unknown inline MDC components (but NOT badge/icon/kbd — handled below)\n .replace(/:(?!badge|icon|kbd)(\\w[\\w-]*)\\[([^\\]]*)\\](\\{[^}]*\\})?/g, '$2')\n .replace(/:(?!badge|icon|kbd)(\\w[\\w-]*)(\\{[^}]*\\})/g, '')\n\n const tokens: InlineToken[] = []\n // Order matters: math (`$\\u2026$`) before italic (so `$x$` doesn't match\n // `$ \\u2026 $` as italic-with-dollars); inline MDC first; mentions before\n // plain `[\\u2026]` links; wikilinks before plain brackets; strikethrough;\n // bold before italic.\n const re = /\\$([^$\\n]+?)\\$|@\\[([^\\]]+?)\\]\\(user:([^)]+?)\\)|:badge\\[([^\\]]*)\\](\\{[^}]*\\})?|:icon\\{([^}]*)\\}|:kbd\\{([^}]*)\\}|\\[\\[([0-9a-fA-F-]{36})(?:\\|([^\\]]+?))?\\]\\]|~~(.+?)~~|\\*\\*(.+?)\\*\\*|\\*(.+?)\\*|_(.+?)_|`(.+?)`|\\[(.+?)\\]\\((.+?)\\)/g\n let lastIndex = 0\n let match: RegExpExecArray | null\n\n while ((match = re.exec(stripped)) !== null) {\n if (match.index > lastIndex) {\n tokens.push({ text: stripped.slice(lastIndex, match.index) })\n }\n if (match[1] !== undefined) {\n // $expression$ \\u2014 inline math atom\n tokens.push({ text: match[1], attrs: { mathInline: { expression: match[1] } } })\n } else if (match[2] !== undefined && match[3] !== undefined) {\n // @[label](user:uuid) \\u2014 mention atom\n tokens.push({ text: match[2], attrs: { mention: { userId: match[3], label: match[2] } } })\n } else if (match[4] !== undefined) {\n // :badge[text]{props}\n const badgeProps = parseMdcProps(match[5])\n tokens.push({ text: match[4] || 'Badge', attrs: { badge: { label: match[4] || 'Badge', color: badgeProps['color'] || 'neutral', variant: badgeProps['variant'] || 'subtle' } } })\n } else if (match[6] !== undefined) {\n // :icon{name=\"...\"}\n const iconProps = parseMdcProps(`{${match[6]}}`)\n tokens.push({ text: '\\u200B', attrs: { proseIcon: { name: iconProps['name'] || 'i-lucide-star' } } })\n } else if (match[7] !== undefined) {\n // :kbd{value=\"...\"}\n const kbdProps = parseMdcProps(`{${match[7]}}`)\n tokens.push({ text: kbdProps['value'] || '', attrs: { kbd: { value: kbdProps['value'] || '' } } })\n } else if (match[8] !== undefined) {\n // [[uuid]] or [[uuid|label]] \\u2014 inline doc link atom. The docId\n // is the canonical anchor; the label is display-only. The\n // serialiser may regenerate the label from a live doc registry\n // (see SPEC.md \\u00A76); when no resolver is supplied, the parser's\n // stored display text is reused on emit.\n const docId = match[8]\n const label = match[9] ?? docId\n tokens.push({ text: label, attrs: { docLink: { docId } } })\n } else if (match[10] !== undefined) {\n pushNested(tokens, match[10], { strike: true })\n } else if (match[11] !== undefined) {\n pushNested(tokens, match[11], { bold: true })\n } else if (match[12] !== undefined) {\n pushNested(tokens, match[12], { italic: true })\n } else if (match[13] !== undefined) {\n pushNested(tokens, match[13], { italic: true })\n } else if (match[14] !== undefined) {\n tokens.push({ text: match[14], attrs: { code: true } })\n } else if (match[15] !== undefined && match[16] !== undefined) {\n tokens.push({ text: match[15], attrs: { link: { href: match[16] } } })\n }\n lastIndex = match.index + match[0].length\n }\n\n if (lastIndex < stripped.length) {\n tokens.push({ text: stripped.slice(lastIndex) })\n }\n return tokens.filter(t => t.text.length > 0)\n}\n\n// ── Block-level parser ───────────────────────────────────────────────────────\n\ninterface TaskItem {\n text: string\n checked: boolean\n}\n\ninterface ListItemBlock {\n text: string\n innerBlocks?: Block[]\n checked?: boolean\n}\n\ntype Block\n = | { type: 'heading', level: number, text: string }\n | { type: 'paragraph', text: string }\n | { type: 'bulletList', items: ListItemBlock[] }\n | { type: 'orderedList', items: ListItemBlock[] }\n | { type: 'taskList', items: ListItemBlock[] }\n | { type: 'codeBlock', lang: string, code: string }\n | { type: 'blockquote', lines: string[] }\n | { type: 'table', headerRow: string[], dataRows: string[][] }\n | { type: 'hr' }\n | { type: 'callout', calloutType: string, innerBlocks: Block[] }\n | { type: 'collapsible', label: string, open: boolean, innerBlocks: Block[] }\n | { type: 'steps', innerBlocks: Block[] }\n | { type: 'card', title: string, icon: string, to: string, innerBlocks: Block[] }\n | { type: 'cardGroup', cards: Block[] }\n | { type: 'codeCollapse', codeBlocks: Block[] }\n | { type: 'codeGroup', codeBlocks: Block[] }\n | { type: 'codePreview', innerBlocks: Block[], codeBlocks: Block[] }\n | { type: 'codeTree', files: string }\n | { type: 'accordion', items: { label: string, icon: string, innerBlocks: Block[] }[] }\n | { type: 'tabs', items: { label: string, icon: string, innerBlocks: Block[] }[] }\n | { type: 'field', name: string, fieldType: string, required: boolean, innerBlocks: Block[] }\n | { type: 'fieldGroup', fields: Block[] }\n | { type: 'image', src: string, alt: string, width?: string, height?: string }\n | { type: 'docEmbed', docId: string, label: string, props: Record<string, string> }\n | { type: 'mathBlock', expression: string }\n | { type: 'fileBlock', src: string, mime: string, uploadId: string, filename: string }\n\nfunction parseTableRow(line: string): string[] {\n const parts = line.split('|')\n // Remove the first and last (empty from leading/trailing |) and trim each\n return parts.slice(1, parts.length - 1).map(c => c.trim())\n}\n\nfunction isTableSeparator(line: string): boolean {\n return /^\\|[\\s|:-]+\\|$/.test(line.trim())\n}\n\n/** Extract fenced code blocks from MDC #code slot lines. */\nfunction extractFencedCode(lines: string[]): Block[] {\n const result: Block[] = []\n let i = 0\n while (i < lines.length) {\n const line = lines[i]!\n // Match opening fence (```, ````, etc.)\n const fenceMatch = line.match(/^(`{3,})(\\w*)/)\n if (fenceMatch) {\n const fence = fenceMatch[1]!\n const lang = fenceMatch[2] ?? ''\n const codeLines: string[] = []\n i++\n while (i < lines.length && !lines[i]!.startsWith(fence)) {\n codeLines.push(lines[i]!)\n i++\n }\n i++ // skip closing fence\n result.push({ type: 'codeBlock', lang, code: codeLines.join('\\n') })\n continue\n }\n i++\n }\n return result\n}\n\n/** Extract key=\"value\" pairs from MDC prop syntax `{key=\"value\" other=\"x\"}` */\nfunction parseMdcProps(propsStr: string | undefined): Record<string, string> {\n if (!propsStr) return {}\n const result: Record<string, string> = {}\n // Drop the wrapping `{ … }` if present.\n let s = propsStr.trim()\n if (s.startsWith('{') && s.endsWith('}')) s = s.slice(1, -1)\n\n // Three accepted shapes per SPEC.md §5:\n // key=\"value\" (quoted)\n // key=value (bare, no whitespace)\n // key (boolean shorthand → \"true\")\n const re = /(\\w[\\w-]*)(?:=(?:\"([^\"]*)\"|([^\\s\"}]+)))?/g\n let m: RegExpExecArray | null\n while ((m = re.exec(s)) !== null) {\n const key = m[1]!\n if (m[2] !== undefined) result[key] = m[2]\n else if (m[3] !== undefined) result[key] = m[3]\n else result[key] = 'true'\n }\n return result\n}\n\n/** Parse named child MDC blocks from inner lines (e.g. #item for accordion, #tab for tabs) */\nfunction parseMdcChildren(innerLines: string[], slotPrefix: string): { label: string, icon: string, innerBlocks: Block[] }[] {\n const items: { label: string, icon: string, lines: string[] }[] = []\n let current: { label: string, icon: string, lines: string[] } | null = null\n const slotRe = new RegExp(`^#${slotPrefix}(\\\\{[^}]*\\\\})?\\\\s*$`)\n\n for (const line of innerLines) {\n const slotMatch = line.match(slotRe)\n if (slotMatch) {\n if (current) items.push(current)\n const props = parseMdcProps(slotMatch[1])\n current = { label: props['label'] || props['title'] || `Item ${items.length + 1}`, icon: props['icon'] || '', lines: [] }\n continue\n }\n if (current) {\n current.lines.push(line)\n } else {\n // Content before first slot — treat as first unnamed item\n if (!items.length && !current) {\n current = { label: `Item 1`, icon: '', lines: [line] }\n }\n }\n }\n if (current) items.push(current)\n\n return items.map(item => ({\n label: item.label,\n icon: item.icon,\n innerBlocks: parseBlocks(item.lines.join('\\n'))\n }))\n}\n\nconst TASK_RE = /^[-*+]\\s+\\[([ xX])\\]\\s+(.*)/\n\n/**\n * Consume a list (bullet / ordered / task) starting at `start`. Indented\n * continuation lines and nested lists are captured into each item's\n * `innerBlocks` so the parse → serialise → parse cycle preserves tree\n * structure instead of flattening nested lists onto a single line.\n *\n * `indent` is the column of the item marker for the current list. A\n * nested list starts ≥2 columns deeper. Lines with less indent than\n * `indent` belong to the outer block and stop consumption.\n */\nfunction consumeList(\n lines: string[],\n start: number,\n indent: number,\n kind: 'bullet' | 'ordered' | 'task',\n): { items: ListItemBlock[], next: number } {\n const items: ListItemBlock[] = []\n let i = start\n while (i < lines.length) {\n const line = lines[i]!\n if (line.trim() === '') {\n // Blank line — peek ahead: if the next non-blank line still\n // belongs to this list, treat the blank as an inter-item\n // separator. Otherwise terminate.\n let j = i + 1\n while (j < lines.length && lines[j]!.trim() === '') j++\n if (j >= lines.length) break\n const lookahead = lines[j]!\n if (leadingSpaces(lookahead) < indent) break\n if (!matchMarker(lookahead.slice(indent), kind)) break\n i = j\n continue\n }\n const leading = leadingSpaces(line)\n if (leading < indent) break\n if (leading > indent) break // belongs to a nested list opened by the previous item\n const deindented = line.slice(indent)\n const m = matchMarker(deindented, kind)\n if (!m) break\n\n const item: ListItemBlock = { text: m.text }\n if (kind === 'task') item.checked = m.checked\n i++\n\n // Consume continuation: lines indented deeper than `indent`.\n const contLines: string[] = []\n while (i < lines.length) {\n const next = lines[i]!\n if (next.trim() === '') {\n // Blank inside a continuation block — could be part of the\n // continuation if the next non-blank is still indented. Peek.\n let k = i + 1\n while (k < lines.length && lines[k]!.trim() === '') k++\n if (k >= lines.length) break\n const peekIndent = leadingSpaces(lines[k]!)\n if (peekIndent <= indent) break\n // Carry forward the blank line as a paragraph separator.\n contLines.push('')\n i++\n continue\n }\n const nextIndent = leadingSpaces(next)\n if (nextIndent <= indent) break\n // De-indent by exactly 2 to match the canonical wire form.\n const deindentBy = Math.min(nextIndent, indent + 2)\n contLines.push(next.slice(deindentBy))\n i++\n }\n if (contLines.length > 0) {\n item.innerBlocks = parseBlocks(contLines.join('\\n'))\n }\n items.push(item)\n }\n return { items, next: i }\n}\n\nfunction leadingSpaces(s: string): number {\n let n = 0\n while (n < s.length && s[n] === ' ') n++\n return n\n}\n\nfunction matchMarker(\n s: string,\n kind: 'bullet' | 'ordered' | 'task',\n): { text: string, checked: boolean } | null {\n if (kind === 'task') {\n const m = s.match(TASK_RE)\n if (!m) return null\n return { text: m[2]!, checked: m[1]!.toLowerCase() === 'x' }\n }\n if (kind === 'bullet') {\n if (TASK_RE.test(s)) return null\n const m = s.match(/^[-*+]\\s+(.*)$/)\n if (!m) return null\n return { text: m[1]!, checked: false }\n }\n // ordered\n const m = s.match(/^\\d+\\.\\s+(.*)$/)\n if (!m) return null\n return { text: m[1]!, checked: false }\n}\n\nfunction parseBlocks(markdown: string): Block[] {\n // Strip top-level MDX import/export lines (only before the first content block).\n // We must NOT strip `export default ...` etc. inside fenced code blocks.\n const rawLines = markdown.split('\\n')\n let firstContentLine = 0\n while (firstContentLine < rawLines.length) {\n const l = rawLines[firstContentLine]!\n if (l.trim() === '' || /^import\\s/.test(l) || /^export\\s/.test(l)) {\n firstContentLine++\n } else {\n break\n }\n }\n const stripped = rawLines.slice(firstContentLine).join('\\n')\n\n const blocks: Block[] = []\n const lines = stripped.split('\\n')\n let i = 0\n\n while (i < lines.length) {\n const line = lines[i]!\n\n // Fenced code block (supports variable-length fences: ```, ````, etc.)\n const fenceBlockMatch = line.match(/^(`{3,})(.*)$/)\n if (fenceBlockMatch) {\n const fence = fenceBlockMatch[1]!\n const lang = fenceBlockMatch[2]!.trim()\n .replace(/\\{[^}]*\\}$/, '') // strip highlight annotations like {4-5}\n .replace(/\\s*\\[.*\\]$/, '') // strip filename hints like [nuxt.config.ts]\n .trim()\n const codeLines: string[] = []\n i++\n while (i < lines.length && !lines[i]!.startsWith(fence)) {\n codeLines.push(lines[i]!)\n i++\n }\n i++ // skip closing fence\n const code = codeLines.join('\\n')\n if (lang === 'math') {\n // ```math … ``` — block math atom (SPEC.md §6).\n blocks.push({ type: 'mathBlock', expression: code })\n }\n else {\n blocks.push({ type: 'codeBlock', lang, code })\n }\n continue\n }\n\n // Heading\n const headingMatch = line.match(/^(#{1,6})\\s+(.*)/)\n if (headingMatch) {\n blocks.push({ type: 'heading', level: headingMatch[1]!.length, text: headingMatch[2]!.trim() })\n i++\n continue\n }\n\n // Horizontal rule\n if (/^[-*_]{3,}\\s*$/.test(line)) {\n blocks.push({ type: 'hr' })\n i++\n continue\n }\n\n // Doc embed: ![[uuid|label]]{collapsed tall seamless} — block-level,\n // must be on its own line. UUID is required (the bracket syntax\n // without one is reserved for inline doc-link).\n const embedMatch = line.match(/^!\\[\\[([0-9a-fA-F-]{36})(?:\\|([^\\]]+))?\\]\\](\\{[^}]*\\})?\\s*$/)\n if (embedMatch) {\n const docId = embedMatch[1]!\n const label = embedMatch[2] ?? ''\n const props = parseMdcProps(embedMatch[3])\n blocks.push({ type: 'docEmbed', docId, label, props })\n i++\n continue\n }\n\n // Image: ![alt](src){attrs} — must be on its own line\n const imgMatch = line.match(/^!\\[([^\\]]*)\\]\\(([^)]+)\\)(\\{[^}]*\\})?\\s*$/)\n if (imgMatch) {\n const alt = imgMatch[1] ?? ''\n const src = imgMatch[2] ?? ''\n const attrs = parseMdcProps(imgMatch[3])\n blocks.push({ type: 'image', src, alt, width: attrs['width'], height: attrs['height'] })\n i++\n continue\n }\n\n // Blockquote\n if (line.startsWith('> ') || line === '>') {\n const bqLines: string[] = []\n while (i < lines.length && (lines[i]!.startsWith('> ') || lines[i] === '>')) {\n bqLines.push(lines[i]!.replace(/^>\\s?/, ''))\n i++\n }\n blocks.push({ type: 'blockquote', lines: bqLines })\n continue\n }\n\n // Table — detect by leading pipe\n if (/^\\s*\\|/.test(line)) {\n const tableLines: string[] = []\n while (i < lines.length && /^\\s*\\|/.test(lines[i]!)) {\n tableLines.push(lines[i]!)\n i++\n }\n // Need at least: header row, separator row\n if (tableLines.length >= 2 && isTableSeparator(tableLines[1]!)) {\n const headerRow = parseTableRow(tableLines[0]!)\n const dataRows = tableLines.slice(2)\n .filter(l => !isTableSeparator(l))\n .map(parseTableRow)\n blocks.push({ type: 'table', headerRow, dataRows })\n } else {\n // Couldn't parse as table — emit as paragraphs\n for (const l of tableLines) blocks.push({ type: 'paragraph', text: l })\n }\n continue\n }\n\n // MDC atom block (single-colon, no body): `:name{props}` on its\n // own line. Currently recognised: `:file{…}` (fileBlock per\n // SPEC.md §7). Other atom blocks (`:video{…}`, `:embed{…}`, etc.)\n // are reserved for later workstreams.\n const atomMatch = line.match(/^:(\\w[\\w-]*)(\\{[^}]*\\})?\\s*$/)\n if (atomMatch && atomMatch[1] === 'file') {\n const props = parseMdcProps(atomMatch[2])\n const uploadId = props['upload-id'] ?? props['uploadId'] ?? ''\n const filename = props['filename'] ?? ''\n const mime = props['mime'] ?? ''\n const src = props['src'] ?? (uploadId && filename\n ? `.abracadabra/files/${uploadId}-${filename}`\n : '')\n blocks.push({ type: 'fileBlock', src, mime, uploadId, filename })\n i++\n continue\n }\n\n // MDC component block (::component-name ... ::)\n // Allow optional leading whitespace so indented nested blocks are recognised\n const MDC_OPEN = /^\\s*(:{2,})(\\w[\\w-]*)(\\{[^}]*\\})?\\s*$/\n if (MDC_OPEN.test(line)) {\n const colons = line.match(/^\\s*(:+)/)?.[1]?.length ?? 2\n const componentName = line.match(/^\\s*:{2,}(\\w[\\w-]*)/)?.[1] ?? ''\n const innerLines: string[] = []\n i++\n // Collect inner lines, but skip over fenced code blocks so that\n // `::` inside ```...``` or ````...```` doesn't close the MDC block\n while (i < lines.length) {\n const l = lines[i]!\n // Closing tag: same colon count, possibly indented\n if (new RegExp(`^\\\\s*:{${colons}}\\\\s*$`).test(l)) { i++; break }\n // If we hit a fenced code block, consume it entirely\n const innerFence = l.match(/^(\\s*`{3,})/)\n if (innerFence) {\n const fenceStr = innerFence[1]!.trimStart()\n innerLines.push(l)\n i++\n while (i < lines.length && !lines[i]!.trimStart().startsWith(fenceStr)) {\n innerLines.push(lines[i]!)\n i++\n }\n if (i < lines.length) { innerLines.push(lines[i]!); i++ } // push closing fence\n continue\n }\n innerLines.push(l)\n i++\n }\n\n // Strip common leading indentation from inner lines\n const nonBlank = innerLines.filter(l => l.trim().length > 0)\n if (nonBlank.length) {\n const minIndent = Math.min(...nonBlank.map(l => l.match(/^(\\s*)/)?.[1]?.length ?? 0))\n if (minIndent > 0) {\n for (let j = 0; j < innerLines.length; j++) {\n innerLines[j] = innerLines[j]!.slice(Math.min(minIndent, innerLines[j]!.length))\n }\n }\n }\n\n // Strip inline frontmatter props (---...---)\n let contentStart = 0\n if (innerLines[0]?.trim() === '---') {\n const fmEnd = innerLines.findIndex((l, idx) => idx > 0 && l.trim() === '---')\n if (fmEnd !== -1) contentStart = fmEnd + 1\n }\n const contentLines = innerLines.slice(contentStart)\n\n // Split into named slots: collect default slot and #code slot separately\n const defaultSlotLines: string[] = []\n const codeSlotLines: string[] = []\n let currentSlot: 'default' | 'code' | 'other' = 'default'\n for (const l of contentLines) {\n if (/^#code\\s*$/.test(l)) { currentSlot = 'code'; continue }\n if (/^#\\w+/.test(l) && !/^#{2,}\\s/.test(l)) { currentSlot = 'other'; continue }\n if (currentSlot === 'default') defaultSlotLines.push(l)\n else if (currentSlot === 'code') codeSlotLines.push(l)\n }\n const innerBlocks = parseBlocks(defaultSlotLines.join('\\n'))\n\n // Extract fenced code from #code slot and add as code blocks\n const codeBlocks = extractFencedCode(codeSlotLines)\n\n const CALLOUT_NAMES = new Set(['tip', 'note', 'info', 'warning', 'caution', 'danger', 'callout', 'alert'])\n if (CALLOUT_NAMES.has(componentName.toLowerCase())) {\n blocks.push({ type: 'callout', calloutType: componentName.toLowerCase(), innerBlocks })\n } else {\n const mdcProps = parseMdcProps(line.match(MDC_OPEN)?.[3])\n const lc = componentName.toLowerCase()\n\n if (lc === 'collapsible') {\n blocks.push({ type: 'collapsible', label: mdcProps['label'] || 'Details', open: mdcProps['open'] === 'true', innerBlocks })\n } else if (lc === 'steps') {\n blocks.push({ type: 'steps', innerBlocks })\n } else if (lc === 'card') {\n blocks.push({ type: 'card', title: mdcProps['title'] || '', icon: mdcProps['icon'] || '', to: mdcProps['to'] || '', innerBlocks })\n } else if (lc === 'card-group') {\n // Each nested ::card inside card-group is already parsed as inner blocks\n const cards = innerBlocks.filter(b => b.type === 'card')\n if (cards.length) {\n blocks.push({ type: 'cardGroup', cards })\n } else {\n blocks.push(...innerBlocks)\n }\n } else if (lc === 'code-collapse') {\n blocks.push({ type: 'codeCollapse', codeBlocks: codeBlocks.length ? codeBlocks : innerBlocks.filter(b => b.type === 'codeBlock') })\n } else if (lc === 'code-group') {\n const allCode = [...innerBlocks.filter(b => b.type === 'codeBlock'), ...codeBlocks]\n blocks.push({ type: 'codeGroup', codeBlocks: allCode })\n } else if (lc === 'code-preview') {\n blocks.push({ type: 'codePreview', innerBlocks, codeBlocks })\n } else if (lc === 'code-tree') {\n blocks.push({ type: 'codeTree', files: mdcProps['files'] || '[]' })\n } else if (lc === 'accordion') {\n const items = parseMdcChildren(contentLines, 'item')\n if (items.length) {\n blocks.push({ type: 'accordion', items })\n } else {\n blocks.push({ type: 'accordion', items: [{ label: 'Item 1', icon: '', innerBlocks }] })\n }\n } else if (lc === 'tabs') {\n const items = parseMdcChildren(contentLines, 'tab')\n if (items.length) {\n blocks.push({ type: 'tabs', items })\n } else {\n blocks.push({ type: 'tabs', items: [{ label: 'Tab 1', icon: '', innerBlocks }] })\n }\n } else if (lc === 'field') {\n blocks.push({ type: 'field', name: mdcProps['name'] || '', fieldType: mdcProps['type'] || 'string', required: mdcProps['required'] === 'true', innerBlocks })\n } else if (lc === 'field-group') {\n const fields = innerBlocks.filter(b => b.type === 'field')\n if (fields.length) {\n blocks.push({ type: 'fieldGroup', fields })\n } else {\n blocks.push(...innerBlocks)\n }\n } else {\n // Unknown component — inline the content\n blocks.push(...innerBlocks)\n blocks.push(...codeBlocks)\n }\n }\n continue\n }\n\n // Task list (must check before bullet list — `- [x]` starts the same way)\n if (TASK_RE.test(line)) {\n const { items, next } = consumeList(lines, i, 0, 'task')\n i = next\n blocks.push({ type: 'taskList', items })\n continue\n }\n\n // Bullet list\n if (/^[-*+]\\s+/.test(line)) {\n const { items, next } = consumeList(lines, i, 0, 'bullet')\n if (items.length > 0) {\n i = next\n blocks.push({ type: 'bulletList', items })\n continue\n }\n }\n\n // Ordered list\n if (/^\\d+\\.\\s+/.test(line)) {\n const { items, next } = consumeList(lines, i, 0, 'ordered')\n if (items.length > 0) {\n i = next\n blocks.push({ type: 'orderedList', items })\n continue\n }\n }\n\n // Blank line\n if (line.trim() === '') {\n i++\n continue\n }\n\n // Paragraph — consecutive non-special lines\n const paraLines: string[] = []\n while (\n i < lines.length\n && lines[i]!.trim() !== ''\n && !/^(#{1,6}\\s|[-*+]\\s|\\d+\\.\\s|>|`{3,}|\\s*\\||[-*_]{3,}\\s*$|\\s*:{2,}\\w)/.test(lines[i]!)\n ) {\n paraLines.push(lines[i]!)\n i++\n }\n if (paraLines.length) {\n blocks.push({ type: 'paragraph', text: paraLines.join(' ') })\n }\n }\n\n return blocks\n}\n\n// ── Y.js content population ──────────────────────────────────────────────────\n//\n// IMPORTANT — attach-before-fill ordering:\n//\n// Y.XmlText.insert() is only deterministically ordered when the text node is\n// already attached to a Y.Doc (so it can use the doc's logical clock).\n// Inserting text into a standalone Y.XmlText gives every operation clock-0,\n// which causes the YATA algorithm to produce reversed or scrambled text.\n//\n// Rule: attach container to doc → attach Y.XmlText to container → insert text.\n\n/**\n * Insert formatted inline tokens into an already-attached Y.XmlElement.\n * Creates one Y.XmlText per token (attach first, fill second).\n */\nfunction fillTextInto(el: Y.XmlElement, tokens: InlineToken[]): void {\n const filtered = tokens.filter(t => t.text.length > 0)\n if (!filtered.length) return\n\n // Build the child skeleton. A docLink is an inline ATOM NODE, not a text\n // mark: it must be a Y.XmlElement so the y-prosemirror binding materializes\n // it as a `docLink` node (its label is resolved live from the doc tree by\n // the renderer, never stored). Every other token is a Y.XmlText run.\n // Attach all children in one batch first (attach-before-fill), then fill.\n const children: (Y.XmlText | Y.XmlElement)[] = filtered.map((tok) => {\n const dl = tok.attrs?.docLink as { docId?: string } | undefined\n return dl?.docId ? new Y.XmlElement('docLink') : new Y.XmlText()\n })\n el.insert(0, children)\n\n // Fill only after attachment — el is already attached to the doc.\n filtered.forEach((tok, i) => {\n const node = children[i]!\n if (node instanceof Y.XmlElement) {\n const dl = tok.attrs!.docLink as { docId: string }\n node.setAttribute('docId', dl.docId)\n return\n }\n if (tok.attrs) {\n node.insert(0, tok.text, tok.attrs as Record<string, boolean | object>)\n } else {\n node.insert(0, tok.text)\n }\n })\n}\n\nfunction blockElName(b: Block): string {\n switch (b.type) {\n case 'heading': return 'heading'\n case 'paragraph': return 'paragraph'\n case 'bulletList': return 'bulletList'\n case 'orderedList': return 'orderedList'\n case 'taskList': return 'taskList'\n case 'codeBlock': return 'codeBlock'\n case 'blockquote': return 'blockquote'\n case 'table': return 'table'\n case 'hr': return 'horizontalRule'\n case 'callout': return 'callout'\n case 'collapsible': return 'collapsible'\n case 'steps': return 'steps'\n case 'card': return 'card'\n case 'cardGroup': return 'cardGroup'\n case 'codeCollapse': return 'codeCollapse'\n case 'codeGroup': return 'codeGroup'\n case 'codePreview': return 'codePreview'\n case 'codeTree': return 'codeTree'\n case 'accordion': return 'accordion'\n case 'tabs': return 'tabs'\n case 'field': return 'field'\n case 'fieldGroup': return 'fieldGroup'\n case 'image': return 'image'\n case 'docEmbed': return 'docEmbed'\n case 'mathBlock': return 'mathBlock'\n case 'fileBlock': return 'fileBlock'\n }\n}\n\nfunction populateListItemChildren(\n itemEl: Y.XmlElement,\n item: ListItemBlock,\n _itemKind: 'listItem' | 'taskItem',\n): void {\n // Always start with a paragraph carrying the item's inline text.\n const paraEl = new Y.XmlElement('paragraph')\n itemEl.insert(itemEl.length, [paraEl])\n fillTextInto(paraEl, parseInline(item.text))\n\n // Nested blocks (sub-lists, paragraphs, code, etc.) follow.\n if (!item.innerBlocks?.length) return\n const innerEls = item.innerBlocks.map(b => new Y.XmlElement(blockElName(b)))\n itemEl.insert(itemEl.length, innerEls)\n item.innerBlocks.forEach((b, i) => fillBlock(innerEls[i]!, b))\n}\n\nfunction fillBlock(el: Y.XmlElement, block: Block): void {\n switch (block.type) {\n case 'heading': {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n el.setAttribute('level', block.level as any)\n fillTextInto(el, parseInline(block.text))\n break\n }\n case 'paragraph': {\n fillTextInto(el, parseInline(block.text))\n break\n }\n case 'bulletList':\n case 'orderedList': {\n const listItemEls = block.items.map(() => new Y.XmlElement('listItem'))\n el.insert(0, listItemEls)\n block.items.forEach((item, i) => {\n populateListItemChildren(listItemEls[i]!, item, 'listItem')\n })\n break\n }\n case 'taskList': {\n const taskItemEls = block.items.map(() => new Y.XmlElement('taskItem'))\n el.insert(0, taskItemEls)\n block.items.forEach((item, i) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n taskItemEls[i]!.setAttribute('checked', !!item.checked as any)\n populateListItemChildren(taskItemEls[i]!, item, 'taskItem')\n })\n break\n }\n case 'codeBlock': {\n if (block.lang) el.setAttribute('language', block.lang)\n const xt = new Y.XmlText()\n el.insert(0, [xt]) // attach xt to el (already attached)\n xt.insert(0, block.code)\n break\n }\n case 'blockquote': {\n const paraEls = block.lines.map(() => new Y.XmlElement('paragraph'))\n el.insert(0, paraEls)\n block.lines.forEach((line, i) => fillTextInto(paraEls[i]!, parseInline(line)))\n break\n }\n case 'table': {\n const headerRowEl = new Y.XmlElement('tableRow')\n const dataRowEls = block.dataRows.map(() => new Y.XmlElement('tableRow'))\n el.insert(0, [headerRowEl, ...dataRowEls])\n\n // Header cells\n const headerCellEls = block.headerRow.map(() => new Y.XmlElement('tableHeader'))\n headerRowEl.insert(0, headerCellEls)\n block.headerRow.forEach((cellText, i) => {\n const paraEl = new Y.XmlElement('paragraph')\n headerCellEls[i]!.insert(0, [paraEl])\n fillTextInto(paraEl, parseInline(cellText))\n })\n\n // Data rows\n block.dataRows.forEach((row, ri) => {\n const cellEls = row.map(() => new Y.XmlElement('tableCell'))\n dataRowEls[ri]!.insert(0, cellEls)\n row.forEach((cellText, ci) => {\n const paraEl = new Y.XmlElement('paragraph')\n cellEls[ci]!.insert(0, [paraEl])\n fillTextInto(paraEl, parseInline(cellText))\n })\n })\n break\n }\n case 'hr': break // horizontalRule has no content\n case 'callout': {\n el.setAttribute('type', block.calloutType)\n if (!block.innerBlocks.length) {\n const paraEl = new Y.XmlElement('paragraph')\n el.insert(0, [paraEl])\n break\n }\n const innerEls = block.innerBlocks.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, innerEls)\n block.innerBlocks.forEach((b, i) => fillBlock(innerEls[i]!, b))\n break\n }\n case 'collapsible': {\n el.setAttribute('label', block.label)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n el.setAttribute('open', block.open as any)\n const inner = block.innerBlocks.length ? block.innerBlocks : [{ type: 'paragraph' as const, text: '' }]\n const innerEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, innerEls)\n inner.forEach((b, i) => fillBlock(innerEls[i]!, b))\n break\n }\n case 'steps': {\n const inner = block.innerBlocks.length ? block.innerBlocks : [{ type: 'paragraph' as const, text: '' }]\n const innerEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, innerEls)\n inner.forEach((b, i) => fillBlock(innerEls[i]!, b))\n break\n }\n case 'card': {\n if (block.title) el.setAttribute('title', block.title)\n if (block.icon) el.setAttribute('icon', block.icon)\n if (block.to) el.setAttribute('to', block.to)\n const inner = block.innerBlocks.length ? block.innerBlocks : [{ type: 'paragraph' as const, text: '' }]\n const innerEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, innerEls)\n inner.forEach((b, i) => fillBlock(innerEls[i]!, b))\n break\n }\n case 'cardGroup': {\n const cardEls = block.cards.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, cardEls)\n block.cards.forEach((b, i) => fillBlock(cardEls[i]!, b))\n break\n }\n case 'codeCollapse': {\n const codes = block.codeBlocks.length ? block.codeBlocks : [{ type: 'codeBlock' as const, lang: '', code: '' }]\n // Only insert the first code block (content model is singular codeBlock)\n const codeEl = new Y.XmlElement('codeBlock')\n el.insert(0, [codeEl])\n fillBlock(codeEl, codes[0]!)\n break\n }\n case 'codeGroup': {\n const codes = block.codeBlocks.length ? block.codeBlocks : [{ type: 'codeBlock' as const, lang: '', code: '' }]\n const codeEls = codes.map(() => new Y.XmlElement('codeBlock'))\n el.insert(0, codeEls)\n codes.forEach((b, i) => fillBlock(codeEls[i]!, b))\n break\n }\n case 'codePreview': {\n const all = [...block.innerBlocks, ...block.codeBlocks]\n const inner = all.length ? all : [{ type: 'paragraph' as const, text: '' }]\n const innerEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, innerEls)\n inner.forEach((b, i) => fillBlock(innerEls[i]!, b))\n break\n }\n case 'codeTree': {\n el.setAttribute('files', block.files)\n break\n }\n case 'accordion': {\n const itemEls = block.items.map(() => new Y.XmlElement('accordionItem'))\n el.insert(0, itemEls)\n block.items.forEach((item, i) => {\n itemEls[i]!.setAttribute('label', item.label)\n if (item.icon) itemEls[i]!.setAttribute('icon', item.icon)\n const inner = item.innerBlocks.length ? item.innerBlocks : [{ type: 'paragraph' as const, text: '' }]\n const childEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n itemEls[i]!.insert(0, childEls)\n inner.forEach((b, ci) => fillBlock(childEls[ci]!, b))\n })\n break\n }\n case 'tabs': {\n const itemEls = block.items.map(() => new Y.XmlElement('tabsItem'))\n el.insert(0, itemEls)\n block.items.forEach((item, i) => {\n itemEls[i]!.setAttribute('label', item.label)\n if (item.icon) itemEls[i]!.setAttribute('icon', item.icon)\n const inner = item.innerBlocks.length ? item.innerBlocks : [{ type: 'paragraph' as const, text: '' }]\n const childEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n itemEls[i]!.insert(0, childEls)\n inner.forEach((b, ci) => fillBlock(childEls[ci]!, b))\n })\n break\n }\n case 'field': {\n if (block.name) el.setAttribute('name', block.name)\n el.setAttribute('type', block.fieldType)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n el.setAttribute('required', block.required as any)\n const inner = block.innerBlocks.length ? block.innerBlocks : [{ type: 'paragraph' as const, text: '' }]\n const innerEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, innerEls)\n inner.forEach((b, i) => fillBlock(innerEls[i]!, b))\n break\n }\n case 'fieldGroup': {\n const fieldEls = block.fields.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, fieldEls)\n block.fields.forEach((b, i) => fillBlock(fieldEls[i]!, b))\n break\n }\n case 'image': {\n el.setAttribute('src', block.src)\n if (block.alt) el.setAttribute('alt', block.alt)\n if (block.width) el.setAttribute('width', block.width)\n if (block.height) el.setAttribute('height', block.height)\n break\n }\n case 'docEmbed': {\n el.setAttribute('docId', block.docId)\n for (const flag of ['collapsed', 'tall', 'seamless']) {\n if (block.props[flag] === 'true' || block.props[flag] === '1') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n el.setAttribute(flag, true as any)\n }\n }\n break\n }\n case 'mathBlock': {\n el.setAttribute('expression', block.expression)\n break\n }\n case 'fileBlock': {\n if (block.src) el.setAttribute('src', block.src)\n if (block.mime) el.setAttribute('mime', block.mime)\n if (block.uploadId) el.setAttribute('uploadId', block.uploadId)\n if (block.filename) el.setAttribute('filename', block.filename)\n break\n }\n }\n}\n\n// ── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Parses markdown text and writes the result into a Y.XmlFragment that\n * TipTap's Collaboration extension can read.\n *\n * Requires `fragment.doc` to be set (i.e. the fragment must already be\n * obtained from a live Y.Doc via `ydoc.getXmlFragment('default')`).\n *\n * @param fragment The target `Y.Doc.getXmlFragment('default')`\n * @param markdown Raw markdown string\n * @param fallbackTitle Used as the title when the markdown has no H1\n */\nexport function populateYDocFromMarkdown(\n fragment: Y.XmlFragment,\n markdown: string,\n fallbackTitle = 'Untitled'\n): void {\n const ydoc = fragment.doc\n if (!ydoc) {\n console.warn('[markdownToYjs] fragment has no doc — skipping population')\n return\n }\n\n // Strip YAML frontmatter from the head of the input so its `---`\n // fences don't get reinterpreted as horizontal rules.\n const fm = parseFrontmatter(markdown)\n const blocks = parseBlocks(fm.body)\n\n let title = fallbackTitle\n // The title can live in three places: frontmatter, the first body H1,\n // or a filename-derived fallback. We track which so the serialiser\n // can round-trip into the same form. Body H1 wins over frontmatter\n // when both are present (frontmatter's title is typically a stale\n // copy of the body H1).\n let titleSource: 'h1' | 'frontmatter' | undefined\n if (fm.title !== undefined) {\n title = fm.title\n titleSource = 'frontmatter'\n }\n let contentBlocks = blocks\n const h1 = blocks.findIndex(b => b.type === 'heading' && b.level === 1)\n if (h1 !== -1) {\n title = (blocks[h1] as { type: 'heading', level: number, text: string }).text\n contentBlocks = blocks.filter((_, i) => i !== h1)\n titleSource = 'h1'\n }\n // For empty markdown we used to seed an empty paragraph so the\n // editor had something to focus. That bytes-pads the round-trip\n // back to \"\\n\\n\" — keep contentBlocks empty so the serialiser can\n // emit a clean empty file.\n\n ydoc.transact(() => {\n // ── Step 1: create empty skeleton elements ────────────────────────────\n const headerEl = new Y.XmlElement('documentHeader')\n const metaEl = new Y.XmlElement('documentMeta')\n const bodyEls: Y.XmlElement[] = contentBlocks.map((b) => {\n switch (b.type) {\n case 'heading': return new Y.XmlElement('heading')\n case 'paragraph': return new Y.XmlElement('paragraph')\n case 'bulletList': return new Y.XmlElement('bulletList')\n case 'orderedList': return new Y.XmlElement('orderedList')\n case 'taskList': return new Y.XmlElement('taskList')\n case 'codeBlock': return new Y.XmlElement('codeBlock')\n case 'blockquote': return new Y.XmlElement('blockquote')\n case 'table': return new Y.XmlElement('table')\n case 'hr': return new Y.XmlElement('horizontalRule')\n case 'callout': return new Y.XmlElement('callout')\n case 'collapsible': return new Y.XmlElement('collapsible')\n case 'steps': return new Y.XmlElement('steps')\n case 'card': return new Y.XmlElement('card')\n case 'cardGroup': return new Y.XmlElement('cardGroup')\n case 'codeCollapse': return new Y.XmlElement('codeCollapse')\n case 'codeGroup': return new Y.XmlElement('codeGroup')\n case 'codePreview': return new Y.XmlElement('codePreview')\n case 'codeTree': return new Y.XmlElement('codeTree')\n case 'accordion': return new Y.XmlElement('accordion')\n case 'tabs': return new Y.XmlElement('tabs')\n case 'field': return new Y.XmlElement('field')\n case 'fieldGroup': return new Y.XmlElement('fieldGroup')\n case 'image': return new Y.XmlElement('image')\n case 'docEmbed': return new Y.XmlElement('docEmbed')\n case 'mathBlock': return new Y.XmlElement('mathBlock')\n case 'fileBlock': return new Y.XmlElement('fileBlock')\n }\n })\n\n // ── Step 2: attach ALL skeleton elements to fragment in one shot ──────\n // After this line everything is connected to ydoc and subsequent ops\n // use the real doc clock — no more clock-0 scrambling.\n fragment.insert(0, [headerEl, metaEl, ...bodyEls])\n\n // ── Step 3: fill header title + record where it came from ─────────────\n if (titleSource) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n headerEl.setAttribute('titleSource', titleSource as any)\n }\n const headerXt = new Y.XmlText()\n headerEl.insert(0, [headerXt])\n headerXt.insert(0, title)\n\n // ── Step 4: stash parsed frontmatter meta on documentMeta ─────────────\n // Each universal-meta key becomes an attribute on documentMeta so\n // the serialiser can faithfully emit it back to frontmatter. Type\n // (page-type) is also stashed here under the well-known \"type\" key.\n for (const k of Object.keys(fm.meta)) {\n const v = (fm.meta as Record<string, unknown>)[k]\n if (v === undefined || v === null) continue\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n metaEl.setAttribute(k, v as any)\n }\n if (fm.type) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n metaEl.setAttribute('type', fm.type as any)\n }\n\n // ── Step 5: fill body blocks ──────────────────────────────────────────\n contentBlocks.forEach((block, i) => fillBlock(bodyEls[i]!, block))\n })\n}\n","import * as Y from 'yjs'\nimport type { DocPageMeta } from './types.ts'\n\n// ── Cross-yjs-copy node typing ───────────────────────────────────────────────\n//\n// The serializers must decide \"is this a Y.XmlText vs Y.XmlElement\"\n// without `instanceof`. A host that wires @abraca/dabra (file: dep) or\n// bundles us through Vite/esbuild dep-prebundling ends up with a SECOND\n// physical copy of yjs; nodes built by that copy are NOT `instanceof`\n// *our* Y.XmlText/Y.XmlElement, so every check silently fails and text\n// and inline atoms (docLink/mention) serialize to NOTHING. Duck-typed\n// predicates work regardless of which yjs constructed the node — the\n// same lesson as getTreeData's `instanceof Y.Map` fix. (`nodeName` is a\n// plain own-property; `toDelta` only exists on Y.XmlText.)\n// An element is anything carrying a string `nodeName` (paragraph,\n// heading, bulletList, AND inline atoms like docLink/mention — atoms\n// have no children but still have a nodeName). Mirrors the original\n// `instanceof Y.XmlElement` intent with NO extra constraint: requiring\n// `.toArray` wrongly excluded childless atom nodes → docLinks dropped.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction isXElem(n: any): n is Y.XmlElement {\n return !!n && typeof n.nodeName === 'string'\n}\n// Y.XmlText: no nodeName, has toDelta. (Y.XmlFragment has neither →\n// classified as neither, which is correct — it's only ever the root.)\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction isXText(n: any): n is Y.XmlText {\n return !!n && typeof n.nodeName !== 'string' && typeof n.toDelta === 'function'\n}\n\n// No fragment normalization is needed any more — the serializers are\n// duck-typed, so a foreign-yjs fragment serializes directly. Kept as an\n// identity so the public entry points don't need to change.\nfunction localizeFragment(fragment: Y.XmlFragment): Y.XmlFragment {\n return fragment\n}\n\n// ── Inline serialization ────────────────────────────────────────────────────\n\nfunction serializeDelta(delta: any[]): string {\n let result = ''\n for (const op of delta) {\n if (typeof op.insert !== 'string') continue\n let text = op.insert as string\n const attrs = op.attributes ?? {}\n\n if (attrs.code) {\n result += `\\`${text}\\``\n continue\n }\n\n // Badge mark\n if (attrs.badge) {\n const b = attrs.badge as { label?: string, color?: string, variant?: string }\n const props: string[] = []\n if (b.color && b.color !== 'neutral') props.push(`color=\"${b.color}\"`)\n if (b.variant && b.variant !== 'subtle') props.push(`variant=\"${b.variant}\"`)\n result += `:badge[${b.label || text}]${props.length ? `{${props.join(' ')}}` : ''}`\n continue\n }\n\n // Prose icon mark\n if (attrs.proseIcon) {\n const icon = (attrs.proseIcon as { name?: string }).name || 'i-lucide-star'\n result += `:icon{name=\"${icon}\"}`\n continue\n }\n\n // Kbd mark\n if (attrs.kbd) {\n const value = (attrs.kbd as { value?: string }).value || text\n result += `:kbd{value=\"${value}\"}`\n continue\n }\n\n // docLink — inline doc reference. The label is the displayed text;\n // the docId is the canonical anchor. Per SPEC.md §6 the label may\n // be regenerated from a live registry, but the converter is pure —\n // we use the stored text. Consumers that need fresh labels should\n // rewrite them in the Y tree before serialising.\n if (attrs.docLink) {\n const docId = (attrs.docLink as { docId?: string }).docId\n if (docId) {\n result += text === docId ? `[[${docId}]]` : `[[${docId}|${text}]]`\n continue\n }\n }\n\n // mention — `@[label](user:uuid)`\n if (attrs.mention) {\n const { userId, label } = attrs.mention as { userId?: string, label?: string }\n if (userId) {\n result += `@[${label || text}](user:${userId})`\n continue\n }\n }\n\n // Inline math — `$expression$`\n if (attrs.mathInline) {\n const expr = (attrs.mathInline as { expression?: string }).expression ?? text\n result += `$${expr}$`\n continue\n }\n\n if (attrs.bold) text = `**${text}**`\n if (attrs.italic) text = `*${text}*`\n if (attrs.strike) text = `~~${text}~~`\n if (attrs.link) {\n const href = (attrs.link as { href?: string }).href ?? ''\n text = `[${text}](${href})`\n }\n\n result += text\n }\n return result\n}\n\nfunction serializeInline(el: Y.XmlElement | Y.XmlFragment): string {\n const parts: string[] = []\n for (const child of el.toArray()) {\n if (isXText(child)) {\n parts.push(serializeDelta(child.toDelta()))\n } else if (isXElem(child)) {\n if (child.nodeName === 'docLink') {\n // Inline doc-link atom node — bare wire form; label is tree-derived.\n const docId = child.getAttribute('docId') ?? ''\n parts.push(`[[${docId}]]`)\n } else {\n // Nested inline element — just get text\n parts.push(serializeInline(child))\n }\n }\n }\n return parts.join('')\n}\n\n// ── Block serialization ─────────────────────────────────────────────────────\n\nfunction serializeBlock(el: Y.XmlElement | Y.XmlText, indent = ''): string {\n if (isXText(el)) {\n return serializeDelta(el.toDelta())\n }\n\n const name = el.nodeName\n switch (name) {\n case 'documentHeader':\n case 'documentMeta':\n return '' // handled via frontmatter\n\n case 'heading': {\n const level = Number(el.getAttribute('level') ?? 2)\n const hashes = '#'.repeat(level)\n return `${hashes} ${serializeInline(el)}`\n }\n\n case 'paragraph':\n return serializeInline(el)\n\n case 'bulletList':\n return serializeListItems(el, 'bullet', indent)\n\n case 'orderedList':\n return serializeListItems(el, 'ordered', indent)\n\n case 'taskList':\n return serializeTaskList(el, indent)\n\n case 'codeBlock': {\n const lang = el.getAttribute('language') ?? ''\n const code = getCodeBlockText(el)\n // Empty body — single-newline form preserves the `\\`\\`\\`lang\\n\\`\\`\\``\n // wire form (no padding blank line).\n if (code === '') return `\\`\\`\\`${lang}\\n\\`\\`\\``\n return `\\`\\`\\`${lang}\\n${code}\\n\\`\\`\\``\n }\n\n case 'blockquote': {\n const lines: string[] = []\n for (const child of el.toArray()) {\n if (isXElem(child)) {\n const text = serializeBlock(child)\n for (const line of text.split('\\n')) {\n lines.push(`> ${line}`)\n }\n }\n }\n return lines.join('\\n')\n }\n\n case 'table':\n return serializeTable(el)\n\n case 'horizontalRule':\n return '---'\n\n case 'image': {\n const src = el.getAttribute('src') ?? ''\n const alt = el.getAttribute('alt') ?? ''\n const width = el.getAttribute('width')\n const height = el.getAttribute('height')\n const attrs: string[] = []\n // MDC convention is `{width=400 height=300}` — bare values, no\n // quotes — matching what the parser at the time accepts.\n if (width) attrs.push(`width=${width}`)\n if (height) attrs.push(`height=${height}`)\n return `![${alt}](${src})${attrs.length ? `{${attrs.join(' ')}}` : ''}`\n }\n\n case 'docEmbed': {\n const docId = el.getAttribute('docId') ?? ''\n const collapsed: unknown = el.getAttribute('collapsed')\n const tall: unknown = el.getAttribute('tall')\n const seamless: unknown = el.getAttribute('seamless')\n const flags: string[] = []\n if (collapsed === true || collapsed === 'true') flags.push('collapsed')\n if (tall === true || tall === 'true') flags.push('tall')\n if (seamless === true || seamless === 'true') flags.push('seamless')\n return `![[${docId}]]${flags.length ? `{${flags.join(' ')}}` : ''}`\n }\n\n case 'mathBlock': {\n const expr = el.getAttribute('expression') ?? ''\n return `\\`\\`\\`math\\n${expr}\\n\\`\\`\\``\n }\n\n case 'fileBlock': {\n // SPEC.md §7 wire form: `:file{src=… mime=… upload-id=… filename=…}`.\n // The sidecar binary lives under `.abracadabra/files/`; this tag\n // is purely a reference into that store + the manifest.\n const uploadId = el.getAttribute('uploadId') ?? ''\n const filename = el.getAttribute('filename') ?? ''\n const mime = el.getAttribute('mime') ?? ''\n const src = el.getAttribute('src') ?? (uploadId && filename\n ? `.abracadabra/files/${uploadId}-${filename}`\n : '')\n const props: string[] = []\n if (src) props.push(`src=\"${src}\"`)\n if (mime) props.push(`mime=\"${mime}\"`)\n if (uploadId) props.push(`upload-id=\"${uploadId}\"`)\n if (filename) props.push(`filename=\"${filename}\"`)\n return `:file{${props.join(' ')}}`\n }\n\n // MDC components\n case 'callout': {\n const type = el.getAttribute('type') ?? 'note'\n return `::${type}\\n${serializeChildren(el)}\\n::`\n }\n\n case 'collapsible': {\n const label = el.getAttribute('label') ?? 'Details'\n const open: unknown = el.getAttribute('open')\n const props: string[] = [`label=\"${label}\"`]\n if (open === true || open === 'true') props.push('open=\"true\"')\n return `::collapsible{${props.join(' ')}}\\n${serializeChildren(el)}\\n::`\n }\n\n case 'steps':\n return `::steps\\n${serializeChildren(el)}\\n::`\n\n case 'card': {\n const props: string[] = []\n const title = el.getAttribute('title')\n const icon = el.getAttribute('icon')\n const to = el.getAttribute('to')\n if (title) props.push(`title=\"${title}\"`)\n if (icon) props.push(`icon=\"${icon}\"`)\n if (to) props.push(`to=\"${to}\"`)\n return `::card${props.length ? `{${props.join(' ')}}` : ''}\\n${serializeChildren(el)}\\n::`\n }\n\n case 'cardGroup': {\n const cards = el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map(c => serializeBlock(c))\n .join('\\n\\n')\n return `::card-group\\n${cards}\\n::`\n }\n\n case 'codeCollapse': {\n const code = el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c) && c.nodeName === 'codeBlock')\n .map(c => serializeBlock(c))\n .join('\\n\\n')\n return `::code-collapse\\n${code}\\n::`\n }\n\n case 'codeGroup': {\n const code = el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c) && c.nodeName === 'codeBlock')\n .map(c => serializeBlock(c))\n .join('\\n\\n')\n return `::code-group\\n${code}\\n::`\n }\n\n case 'codePreview': {\n const children = el.toArray().filter((c): c is Y.XmlElement => isXElem(c))\n const nonCode = children.filter(c => c.nodeName !== 'codeBlock').map(c => serializeBlock(c)).join('\\n\\n')\n const code = children.filter(c => c.nodeName === 'codeBlock').map(c => serializeBlock(c)).join('\\n\\n')\n const parts = [nonCode]\n if (code) parts.push(`#code\\n${code}`)\n return `::code-preview\\n${parts.filter(Boolean).join('\\n\\n')}\\n::`\n }\n\n case 'codeTree': {\n const files = el.getAttribute('files') ?? '[]'\n return `::code-tree{files=\"${files}\"}\\n::`\n }\n\n case 'accordion':\n return serializeSlottedContainer(el, 'accordion', 'accordionItem', 'item')\n\n case 'tabs':\n return serializeSlottedContainer(el, 'tabs', 'tabsItem', 'tab')\n\n case 'field': {\n const fieldName = el.getAttribute('name') ?? ''\n const fieldType = el.getAttribute('type') ?? 'string'\n const required: unknown = el.getAttribute('required')\n const props = [`name=\"${fieldName}\"`, `type=\"${fieldType}\"`]\n if (required === true || required === 'true') props.push('required=\"true\"')\n return `::field{${props.join(' ')}}\\n${serializeChildren(el)}\\n::`\n }\n\n case 'fieldGroup': {\n const fields = el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map(c => serializeBlock(c))\n .join('\\n\\n')\n return `::field-group\\n${fields}\\n::`\n }\n\n default:\n // Unknown node type — try to serialize children\n return serializeChildren(el)\n }\n}\n\nfunction serializeChildren(el: Y.XmlElement | Y.XmlFragment): string {\n const blocks: string[] = []\n for (const child of el.toArray()) {\n if (isXElem(child)) {\n const text = serializeBlock(child)\n if (text) blocks.push(text)\n } else if (isXText(child)) {\n const text = serializeDelta(child.toDelta())\n if (text) blocks.push(text)\n }\n }\n return blocks.join('\\n\\n')\n}\n\nfunction serializeListItems(el: Y.XmlElement, type: 'bullet' | 'ordered', indent: string): string {\n const lines: string[] = []\n let counter = 1\n for (const child of el.toArray()) {\n if (!(isXElem(child)) || child.nodeName !== 'listItem') continue\n const prefix = type === 'bullet' ? '- ' : `${counter++}. `\n // A listItem may contain paragraphs and nested lists\n const subParts: string[] = []\n for (const sub of child.toArray()) {\n if (!(isXElem(sub))) continue\n if (sub.nodeName === 'bulletList') {\n subParts.push(serializeListItems(sub, 'bullet', indent + ' '))\n } else if (sub.nodeName === 'orderedList') {\n subParts.push(serializeListItems(sub, 'ordered', indent + ' '))\n } else {\n subParts.push(serializeInline(sub))\n }\n }\n if (subParts.length <= 1) {\n lines.push(`${indent}${prefix}${subParts[0] ?? ''}`)\n } else {\n lines.push(`${indent}${prefix}${subParts[0] ?? ''}`)\n for (let i = 1; i < subParts.length; i++) {\n // Nested lists are already indented; plain text gets continuation indent\n lines.push(subParts[i]!)\n }\n }\n }\n return lines.join('\\n')\n}\n\nfunction serializeTaskList(el: Y.XmlElement, indent: string): string {\n const lines: string[] = []\n for (const child of el.toArray()) {\n if (!(isXElem(child)) || child.nodeName !== 'taskItem') continue\n const checked: unknown = child.getAttribute('checked')\n const marker = (checked === true || checked === 'true') ? '[x]' : '[ ]'\n\n let header = ''\n const nestedParts: string[] = []\n for (const sub of child.toArray()) {\n if (!(isXElem(sub))) continue\n if (sub.nodeName === 'paragraph' && header === '') {\n header = serializeInline(sub)\n }\n else if (sub.nodeName === 'bulletList') {\n nestedParts.push(serializeListItems(sub, 'bullet', indent + ' '))\n }\n else if (sub.nodeName === 'orderedList') {\n nestedParts.push(serializeListItems(sub, 'ordered', indent + ' '))\n }\n else if (sub.nodeName === 'taskList') {\n nestedParts.push(serializeTaskList(sub, indent + ' '))\n }\n else {\n // Other block — render under the item with a 2-space hanging indent\n nestedParts.push((indent + ' ') + serializeBlock(sub, indent + ' '))\n }\n }\n lines.push(`${indent}- ${marker} ${header}`)\n for (const part of nestedParts) lines.push(part)\n }\n return lines.join('\\n')\n}\n\nfunction getCodeBlockText(el: Y.XmlElement): string {\n for (const child of el.toArray()) {\n if (isXText(child)) {\n return child.toString()\n }\n }\n return ''\n}\n\nfunction serializeTable(el: Y.XmlElement): string {\n const rows = el.toArray().filter((c): c is Y.XmlElement => isXElem(c))\n if (!rows.length) return ''\n\n const serializedRows: string[][] = []\n for (const row of rows) {\n const cells = row.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map((cell) => {\n // Cell contains paragraphs — join their text\n return cell.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map(c => serializeInline(c))\n .join(' ')\n })\n serializedRows.push(cells)\n }\n\n if (!serializedRows.length) return ''\n\n const colCount = Math.max(...serializedRows.map(r => r.length))\n const headerRow = serializedRows[0]!\n const separator = Array(colCount).fill('---')\n const dataRows = serializedRows.slice(1)\n\n const formatRow = (cells: string[]) => {\n const padded = Array(colCount).fill('').map((_, i) => cells[i] ?? '')\n return `| ${padded.join(' | ')} |`\n }\n\n const lines = [formatRow(headerRow), formatRow(separator), ...dataRows.map(formatRow)]\n return lines.join('\\n')\n}\n\nfunction serializeSlottedContainer(\n el: Y.XmlElement,\n containerName: string,\n childName: string,\n slotPrefix: string\n): string {\n const items = el.toArray().filter((c): c is Y.XmlElement => isXElem(c) && c.nodeName === childName)\n const slots = items.map((item) => {\n const label = item.getAttribute('label') ?? ''\n const icon = item.getAttribute('icon') ?? ''\n const props: string[] = []\n if (label) props.push(`label=\"${label}\"`)\n if (icon) props.push(`icon=\"${icon}\"`)\n const content = serializeChildren(item)\n return `#${slotPrefix}{${props.join(' ')}}\\n${content}`\n })\n return `::${containerName}\\n${slots.join('\\n\\n')}\\n::`\n}\n\n// ── Frontmatter generation ──────────────────────────────────────────────────\n\nfunction generateFrontmatter(label: string | undefined, meta?: DocPageMeta, type?: string): string {\n const lines: string[] = []\n\n if (label !== undefined) lines.push(`title: \"${escapeYaml(label)}\"`)\n\n if (type && type !== 'doc') {\n lines.push(`type: ${type}`)\n }\n\n if (!meta) return `---\\n${lines.join('\\n')}\\n---`\n\n if (meta.tags?.length) {\n lines.push(`tags: [${meta.tags.join(', ')}]`)\n }\n if (meta.color) lines.push(`color: ${yamlScalar(meta.color)}`)\n if (meta.icon) lines.push(`icon: ${yamlScalar(meta.icon)}`)\n if (meta.status) lines.push(`status: ${yamlScalar(meta.status)}`)\n\n if (meta.priority !== undefined && meta.priority !== 0) {\n const map: Record<number, string> = { 1: 'low', 2: 'medium', 3: 'high', 4: 'urgent' }\n lines.push(`priority: ${map[meta.priority] ?? meta.priority}`)\n }\n\n if (meta.checked !== undefined) lines.push(`checked: ${meta.checked}`)\n // Code page type: syntax-highlight language + on-disk extension. These\n // round-trip the `.md` envelope so the companion code file can be re-derived.\n if (meta.language) lines.push(`language: ${yamlScalar(meta.language)}`)\n if (meta.fileExtension) lines.push(`fileExtension: ${yamlScalar(meta.fileExtension)}`)\n if (meta.codeTheme) lines.push(`codeTheme: ${yamlScalar(meta.codeTheme)}`)\n if (meta.dateStart) lines.push(`dateStart: \"${escapeYaml(meta.dateStart)}\"`)\n if (meta.dateEnd) lines.push(`dateEnd: \"${escapeYaml(meta.dateEnd)}\"`)\n if (meta.subtitle) lines.push(`subtitle: \"${escapeYaml(meta.subtitle)}\"`)\n if (meta.url) lines.push(`url: ${meta.url}`)\n if (meta.rating !== undefined && meta.rating !== 0) lines.push(`rating: ${meta.rating}`)\n\n return `---\\n${lines.join('\\n')}\\n---`\n}\n\n/**\n * Render a YAML scalar — bare when safe, double-quoted when the value\n * needs escaping. YAML treats `#`, `:`, leading whitespace, and a few\n * other characters as syntactically significant, so anything starting\n * with one of those gets quoted to stay round-trip safe.\n */\nfunction yamlScalar(s: string): string {\n if (s === '') return '\"\"'\n if (/^[#&*!|>%@`]/.test(s)) return `\"${escapeYaml(s)}\"`\n if (/[:\"]/.test(s)) return `\"${escapeYaml(s)}\"`\n if (/^\\s|\\s$/.test(s)) return `\"${escapeYaml(s)}\"`\n return s\n}\n\nfunction escapeYaml(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')\n}\n\n// ── HTML serialization ──────────────────────────────────────────────────────\n\nfunction serializeBlockToHtml(el: Y.XmlElement | Y.XmlText): string {\n if (isXText(el)) {\n return serializeDeltaToHtml(el.toDelta())\n }\n\n const name = el.nodeName\n switch (name) {\n case 'documentHeader':\n case 'documentMeta':\n return ''\n\n case 'heading': {\n const level = Number(el.getAttribute('level') ?? 2)\n return `<h${level}>${serializeInlineHtml(el)}</h${level}>`\n }\n\n case 'paragraph':\n return `<p>${serializeInlineHtml(el)}</p>`\n\n case 'bulletList':\n return `<ul>${serializeListHtml(el)}</ul>`\n\n case 'orderedList':\n return `<ol>${serializeListHtml(el)}</ol>`\n\n case 'taskList':\n return `<ul>${serializeTaskListHtml(el)}</ul>`\n\n case 'codeBlock': {\n // Restrict the language to a safe identifier charset — it is interpolated\n // into a class attribute below; an unsanitised value is a stored-XSS sink.\n const lang = (el.getAttribute('language') ?? '').replace(/[^\\w.-]/g, '')\n const code = escapeHtml(getCodeBlockText(el))\n return lang\n ? `<pre><code class=\"language-${lang}\">${code}</code></pre>`\n : `<pre><code>${code}</code></pre>`\n }\n\n case 'blockquote': {\n const inner = el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map(c => serializeBlockToHtml(c))\n .join('\\n')\n return `<blockquote>\\n${inner}\\n</blockquote>`\n }\n\n case 'table':\n return serializeTableHtml(el)\n\n case 'horizontalRule':\n return '<hr>'\n\n case 'image': {\n const src = el.getAttribute('src') ?? ''\n const alt = el.getAttribute('alt') ?? ''\n return `<img src=\"${escapeHtml(src)}\" alt=\"${escapeHtml(alt)}\">`\n }\n\n case 'fileBlock': {\n const uploadId = el.getAttribute('uploadId') ?? ''\n const filename = el.getAttribute('filename') ?? 'file'\n if (uploadId) return `<!--fileblock:${uploadId}:${filename}-->`\n return `<!-- file: ${filename} -->`\n }\n\n default: {\n // Generic wrapper for MDC blocks etc.\n const inner = el.toArray()\n .filter((c): c is Y.XmlElement | Y.XmlText => isXElem(c) || isXText(c))\n .map(c => isXElem(c) ? serializeBlockToHtml(c) : serializeDeltaToHtml(c.toDelta()))\n .join('\\n')\n return `<div data-type=\"${name}\">\\n${inner}\\n</div>`\n }\n }\n}\n\nfunction serializeInlineHtml(el: Y.XmlElement | Y.XmlFragment): string {\n const parts: string[] = []\n for (const child of el.toArray()) {\n if (isXText(child)) {\n parts.push(serializeDeltaToHtml(child.toDelta()))\n } else if (isXElem(child)) {\n parts.push(serializeInlineHtml(child))\n }\n }\n return parts.join('')\n}\n\nfunction serializeDeltaToHtml(delta: any[]): string {\n let result = ''\n for (const op of delta) {\n if (typeof op.insert !== 'string') continue\n let text = escapeHtml(op.insert as string)\n const attrs = op.attributes ?? {}\n if (attrs.code) text = `<code>${text}</code>`\n if (attrs.bold) text = `<strong>${text}</strong>`\n if (attrs.italic) text = `<em>${text}</em>`\n if (attrs.strike) text = `<s>${text}</s>`\n if (attrs.link) {\n const href = escapeHtml((attrs.link as { href?: string }).href ?? '')\n text = `<a href=\"${href}\">${text}</a>`\n }\n result += text\n }\n return result\n}\n\nfunction serializeListHtml(el: Y.XmlElement): string {\n return el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c) && c.nodeName === 'listItem')\n .map(li => `<li>${li.toArray().filter((c): c is Y.XmlElement => isXElem(c)).map(c => serializeBlockToHtml(c)).join('')}</li>`)\n .join('\\n')\n}\n\nfunction serializeTaskListHtml(el: Y.XmlElement): string {\n return el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c) && c.nodeName === 'taskItem')\n .map((ti) => {\n const rawChecked: unknown = ti.getAttribute('checked')\n const checked = rawChecked === true || rawChecked === 'true'\n const text = ti.toArray().filter((c): c is Y.XmlElement => isXElem(c)).map(c => serializeInlineHtml(c)).join('')\n return `<li><input type=\"checkbox\"${checked ? ' checked' : ''} disabled> ${text}</li>`\n })\n .join('\\n')\n}\n\nfunction serializeTableHtml(el: Y.XmlElement): string {\n const rows = el.toArray().filter((c): c is Y.XmlElement => isXElem(c))\n if (!rows.length) return ''\n\n const htmlRows = rows.map((row, ri) => {\n const tag = ri === 0 ? 'th' : 'td'\n const cells = row.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map((cell) => {\n const inner = cell.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map(c => serializeInlineHtml(c))\n .join('')\n return `<${tag}>${inner}</${tag}>`\n })\n .join('')\n return `<tr>${cells}</tr>`\n })\n\n return `<table>\\n${htmlRows.join('\\n')}\\n</table>`\n}\n\nfunction escapeHtml(s: string): string {\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;')\n}\n\n// ── Public API ──────────────────────────────────────────────────────────────\n\nexport function yjsToMarkdown(\n fragment: Y.XmlFragment,\n label: string,\n meta?: DocPageMeta,\n type?: string\n): string {\n fragment = localizeFragment(fragment)\n // The title can come from three places. We honour where the parser\n // captured it so the wire form round-trips byte-stably:\n // - 'h1' → emit `# title` as the first body block\n // - 'frontmatter' → emit `title:` in frontmatter\n // - undefined → no real title; skip the frontmatter block\n // when no other meta is set\n const { text: headerText, source: titleSource } = readDocumentHeader(fragment)\n const effectiveTitle = headerText || label\n\n // If the caller didn't pass meta / type, read them from documentMeta —\n // that's where the parser stashes frontmatter fields so they survive\n // round-trip without needing to be piped through the consumer.\n const docMeta = readDocumentMeta(fragment)\n const effectiveMeta = meta ?? docMeta.meta\n const effectiveType = type ?? docMeta.type\n\n const metaIsEmpty = isMetaEmpty(effectiveMeta)\n const typeIsDefault = !effectiveType || effectiveType === 'doc'\n\n const bodyBlocks = collectBodyBlocks(fragment)\n\n // Body assembly — when the parser captured the title from a body H1\n // we restore it at the top of the body before serialising.\n let body: string\n if (titleSource === 'h1' && effectiveTitle) {\n const tail = serializeBlocksClean(bodyBlocks)\n body = tail === '' ? `# ${effectiveTitle}` : `# ${effectiveTitle}\\n\\n${tail}`\n }\n else {\n body = serializeBlocksClean(bodyBlocks)\n }\n\n const wantFrontmatterTitle = titleSource === 'frontmatter'\n const wantFrontmatterMeta = !metaIsEmpty || !typeIsDefault\n if (!wantFrontmatterTitle && !wantFrontmatterMeta) {\n return body === '' ? '' : `${body}\\n`\n }\n const fmTitle = wantFrontmatterTitle ? effectiveTitle : undefined\n const frontmatter = generateFrontmatter(fmTitle, effectiveMeta, effectiveType)\n if (body === '') return `${frontmatter}\\n`\n return `${frontmatter}\\n\\n${body}\\n`\n}\n\nfunction readDocumentMeta(fragment: Y.XmlFragment): { meta: DocPageMeta, type?: string } {\n const meta: DocPageMeta = {}\n let type: string | undefined\n for (const child of fragment.toArray()) {\n if (!(isXElem(child)) || child.nodeName !== 'documentMeta') continue\n const attrs = child.getAttributes() as Record<string, unknown>\n for (const k of Object.keys(attrs)) {\n const v = attrs[k]\n if (v === undefined || v === null) continue\n if (k === 'type' && typeof v === 'string') {\n type = v\n continue\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (meta as Record<string, unknown>)[k] = v\n }\n break\n }\n return { meta, type }\n}\n\ninterface HeaderInfo { text: string, source?: 'h1' | 'frontmatter' }\n\nfunction readDocumentHeader(fragment: Y.XmlFragment): HeaderInfo {\n for (const child of fragment.toArray()) {\n if (!(isXElem(child)) || child.nodeName !== 'documentHeader') continue\n const text = child.toArray().find(c => isXText(c)) as Y.XmlText | undefined\n const src: unknown = child.getAttribute('titleSource')\n const source = src === 'h1' || src === 'frontmatter' ? src : undefined\n return { text: text ? text.toString() : '', source }\n }\n return { text: '' }\n}\n\nfunction collectBodyBlocks(fragment: Y.XmlFragment): Y.XmlElement[] {\n const out: Y.XmlElement[] = []\n for (const child of fragment.toArray()) {\n if (!(isXElem(child))) continue\n if (child.nodeName === 'documentHeader' || child.nodeName === 'documentMeta') continue\n out.push(child)\n }\n return out\n}\n\nfunction serializeBlocksClean(blocks: Y.XmlElement[]): string {\n const parts: string[] = []\n for (const block of blocks) {\n // Empty trailing paragraphs are the parser's placeholder for an\n // \"empty doc\"; skip them so empty input round-trips to \"\".\n if (block.nodeName === 'paragraph' && block.length === 0) {\n parts.push('')\n continue\n }\n parts.push(serializeBlock(block))\n }\n while (parts.length && parts[parts.length - 1] === '') parts.pop()\n return parts.join('\\n\\n')\n}\n\nfunction isMetaEmpty(meta: DocPageMeta | undefined): boolean {\n if (!meta) return true\n for (const key of Object.keys(meta)) {\n const v = (meta as Record<string, unknown>)[key]\n if (v === undefined || v === null) continue\n if (typeof v === 'string' && v === '') continue\n if (Array.isArray(v) && v.length === 0) continue\n return false\n }\n return true\n}\n\n/**\n * Walk the Y.XmlFragment and concatenate all text content with no\n * markup or frontmatter. Block boundaries become newlines. Useful for\n * accessibility tooling, search indexing, and snippet previews.\n */\nexport function yjsToPlainText(fragment: Y.XmlFragment): string {\n fragment = localizeFragment(fragment)\n const out: string[] = []\n const visit = (node: Y.XmlElement | Y.XmlText): void => {\n if (isXText(node)) {\n out.push(node.toString())\n return\n }\n if (node.nodeName === 'documentMeta') return\n if (node.nodeName === 'image') {\n const alt = node.getAttribute('alt') ?? ''\n if (alt) out.push(alt)\n return\n }\n for (const child of node.toArray()) {\n if (isXText(child) || isXElem(child)) visit(child)\n }\n // Insert a single newline after block-level elements so paragraphs\n // and headings produce a readable plain-text form.\n if (node.nodeName !== 'paragraph' && node.length === 0) return\n out.push('\\n')\n }\n for (const child of fragment.toArray()) {\n if (isXText(child) || isXElem(child)) visit(child)\n }\n return out.join('').replace(/\\n+$/, '').replace(/\\n{3,}/g, '\\n\\n')\n}\n\nexport function yjsToHtml(\n fragment: Y.XmlFragment,\n label: string\n): string {\n fragment = localizeFragment(fragment)\n const title = escapeHtml(label)\n const bodyParts: string[] = []\n for (const child of fragment.toArray()) {\n if (isXElem(child)) {\n const html = serializeBlockToHtml(child)\n if (html) bodyParts.push(html)\n }\n }\n return `<!DOCTYPE html>\n<html>\n<head><meta charset=\"utf-8\"><title>${title}</title></head>\n<body>\n<h1>${title}</h1>\n${bodyParts.join('\\n')}\n</body>\n</html>\n`\n}\n","// NodeSpec registry — every TipTap node supported by the converter,\n// paired with its canonical Markdown / MDC wire form.\n//\n// This is **data**, not behaviour. The parser and serialiser\n// (markdown-to-yjs.ts, yjs-to-markdown.ts) consult this table to\n// decide what to do; when the spec and the runtime disagree the\n// registry wins (per SPEC.md).\n//\n// Wire kinds:\n// - vanilla Standard Markdown (paragraph, heading, list, …).\n// - fence Fenced code block with a language tag.\n// - mdc-container `:name{props}\\n…children…\\n::` block with children.\n// - mdc-slotted `:name\\n :name-item{…}\\n…\\n ::\\n…\\n::` slotted container.\n// - mdc-atom-block `:name{props}` single-line block atom.\n// - mdc-atom-inl `:name[label]{props}` or `:name{props}` inline atom.\n// - special Has bespoke parsing/serialising (doc-link, doc-embed,\n// file-block, image, mention, math).\n\nimport type { DocPageMeta } from '../types.ts'\n\nexport type NodeWireKind =\n | 'vanilla'\n | 'fence'\n | 'mdc-container'\n | 'mdc-slotted'\n | 'mdc-atom-block'\n | 'mdc-atom-inl'\n | 'special'\n\nexport interface NodeAttrSpec {\n /** Attribute name on the Y.XmlElement and on the MDC prop. */\n key: string\n /** Wire type — controls how the attr is parsed/serialised in props. */\n type: 'string' | 'number' | 'integer' | 'boolean' | 'json'\n /** Optional default value omitted from serialised output when equal. */\n default?: unknown\n /** Allowed values for enum-like string attrs. */\n values?: readonly string[]\n /** Whether the attr is allowed to be omitted entirely. */\n optional?: boolean\n}\n\nexport interface NodeSpec {\n /** Y.XmlElement nodeName. */\n name: string\n /** Block vs inline. */\n group: 'block' | 'inline'\n /** Wire form on Markdown. */\n wire: NodeWireKind\n /**\n * For slotted containers: name of the child element used as a slot\n * (e.g. `accordion-item` under `accordion`).\n */\n slotChild?: string\n /** Declared attributes. */\n attrs?: readonly NodeAttrSpec[]\n /**\n * For `mdc-container` and `mdc-slotted`: what MDC tag name to emit.\n * Defaults to `name` (kebab-cased — `accordionItem` → `accordion-item`).\n */\n mdcTag?: string\n /**\n * Whether the node is content-bearing (paragraph, listItem, etc.)\n * or a child wrapper (tableRow, tableHeader).\n */\n contentBearing?: boolean\n doc?: string\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\nconst BOOL_FALSE_DEFAULT: NodeAttrSpec = {\n key: '',\n type: 'boolean',\n default: false,\n optional: true,\n}\n\nconst bool = (key: string): NodeAttrSpec => ({ ...BOOL_FALSE_DEFAULT, key })\nconst str = (key: string, def?: string): NodeAttrSpec => ({\n key,\n type: 'string',\n default: def,\n optional: true,\n})\nconst num = (key: string): NodeAttrSpec => ({ key, type: 'number', optional: true })\nconst int = (key: string): NodeAttrSpec => ({ key, type: 'integer', optional: true })\n\n// ── Vanilla block nodes ─────────────────────────────────────────────────────\n\nconst VANILLA_BLOCKS: readonly NodeSpec[] = [\n { name: 'documentHeader', group: 'block', wire: 'special', doc: 'Holds the title; hoisted to frontmatter on serialise.' },\n { name: 'documentMeta', group: 'block', wire: 'special', doc: 'Holds page-level meta; serialised into frontmatter.' },\n { name: 'paragraph', group: 'block', wire: 'vanilla', contentBearing: true },\n { name: 'heading', group: 'block', wire: 'vanilla', attrs: [int('level')], contentBearing: true },\n { name: 'blockquote', group: 'block', wire: 'vanilla', contentBearing: true },\n { name: 'codeBlock', group: 'block', wire: 'fence', attrs: [str('language', '')] },\n { name: 'bulletList', group: 'block', wire: 'vanilla' },\n { name: 'orderedList', group: 'block', wire: 'vanilla' },\n { name: 'listItem', group: 'block', wire: 'vanilla', contentBearing: true },\n { name: 'taskList', group: 'block', wire: 'vanilla' },\n { name: 'taskItem', group: 'block', wire: 'vanilla', attrs: [bool('checked')], contentBearing: true },\n { name: 'table', group: 'block', wire: 'vanilla' },\n { name: 'tableRow', group: 'block', wire: 'vanilla' },\n { name: 'tableHeader', group: 'block', wire: 'vanilla', contentBearing: true },\n { name: 'tableCell', group: 'block', wire: 'vanilla', contentBearing: true },\n { name: 'horizontalRule', group: 'block', wire: 'vanilla' },\n {\n name: 'image',\n group: 'block',\n wire: 'special',\n attrs: [str('src'), str('alt', ''), int('width'), int('height')],\n },\n { name: 'hardBreak', group: 'inline', wire: 'vanilla' },\n]\n\n// ── MDC custom containers ───────────────────────────────────────────────────\n\nconst MDC_CONTAINERS: readonly NodeSpec[] = [\n {\n name: 'callout',\n group: 'block',\n wire: 'mdc-container',\n attrs: [\n { key: 'type', type: 'string', default: 'note', optional: true,\n values: ['note', 'tip', 'warning', 'danger', 'info', 'caution', 'alert', 'success', 'error'] },\n str('title'),\n str('icon'),\n ],\n },\n {\n name: 'collapsible',\n group: 'block',\n wire: 'mdc-container',\n attrs: [str('label', 'Details'), bool('open')],\n },\n {\n name: 'accordion',\n group: 'block',\n wire: 'mdc-slotted',\n slotChild: 'accordionItem',\n },\n {\n name: 'accordionItem',\n group: 'block',\n wire: 'mdc-container',\n mdcTag: 'accordion-item',\n attrs: [str('label', 'Item'), str('icon')],\n },\n {\n name: 'tabs',\n group: 'block',\n wire: 'mdc-slotted',\n slotChild: 'tabsItem',\n },\n {\n name: 'tabsItem',\n group: 'block',\n wire: 'mdc-container',\n mdcTag: 'tabs-item',\n attrs: [str('label'), str('icon')],\n },\n { name: 'steps', group: 'block', wire: 'mdc-container' },\n {\n name: 'card',\n group: 'block',\n wire: 'mdc-container',\n attrs: [str('title'), str('icon'), str('to')],\n },\n {\n name: 'cardGroup',\n group: 'block',\n wire: 'mdc-slotted',\n mdcTag: 'card-group',\n slotChild: 'card',\n },\n {\n name: 'field',\n group: 'block',\n wire: 'mdc-container',\n attrs: [str('name'), str('type', 'string'), bool('required')],\n },\n {\n name: 'fieldGroup',\n group: 'block',\n wire: 'mdc-slotted',\n mdcTag: 'field-group',\n slotChild: 'field',\n },\n { name: 'codeGroup', group: 'block', wire: 'mdc-slotted', mdcTag: 'code-group', slotChild: 'codeBlock' },\n { name: 'codeCollapse', group: 'block', wire: 'mdc-container', mdcTag: 'code-collapse' },\n { name: 'codePreview', group: 'block', wire: 'mdc-container', mdcTag: 'code-preview' },\n {\n name: 'codeTree',\n group: 'block',\n wire: 'mdc-atom-block',\n mdcTag: 'code-tree',\n attrs: [{ key: 'files', type: 'json' }],\n },\n {\n name: 'figure',\n group: 'block',\n wire: 'mdc-container',\n attrs: [str('src'), str('alt', ''), str('caption')],\n },\n {\n name: 'video',\n group: 'block',\n wire: 'mdc-atom-block',\n attrs: [str('src'), str('poster'), bool('autoplay'), bool('loop'), bool('controls')],\n },\n {\n name: 'embed',\n group: 'block',\n wire: 'mdc-atom-block',\n attrs: [str('src'), str('title')],\n },\n {\n name: 'svgEmbed',\n group: 'block',\n wire: 'fence',\n attrs: [str('title')],\n mdcTag: 'svg',\n doc: 'Serialised as a ```svg fenced block; the SVG markup is the body.',\n },\n {\n name: 'divider',\n group: 'block',\n wire: 'mdc-atom-block',\n attrs: [str('label'), str('icon')],\n },\n { name: 'quote', group: 'block', wire: 'mdc-container', attrs: [str('cite')] },\n { name: 'progress', group: 'block', wire: 'mdc-atom-block', attrs: [num('value'), num('max'), str('label')] },\n { name: 'spoiler', group: 'block', wire: 'mdc-container', attrs: [str('label')] },\n { name: 'colorSwatch', group: 'block', wire: 'mdc-atom-block', mdcTag: 'color-swatch', attrs: [str('color'), str('label')] },\n { name: 'stat', group: 'block', wire: 'mdc-container', attrs: [str('label'), str('value'), str('icon')] },\n { name: 'statGroup', group: 'block', wire: 'mdc-slotted', mdcTag: 'stat-group', slotChild: 'stat' },\n { name: 'button', group: 'block', wire: 'mdc-atom-block', attrs: [str('label'), str('to'), str('icon'), str('variant')] },\n { name: 'buttonGroup', group: 'block', wire: 'mdc-slotted', mdcTag: 'button-group', slotChild: 'button' },\n { name: 'timeline', group: 'block', wire: 'mdc-slotted', slotChild: 'timelineItem' },\n { name: 'timelineItem', group: 'block', wire: 'mdc-container', mdcTag: 'timeline-item', attrs: [str('label'), str('icon'), str('date')] },\n { name: 'diff', group: 'block', wire: 'mdc-atom-block', attrs: [str('language', ''), { key: 'value', type: 'string' }] },\n]\n\n// ── Inline atoms / special nodes ────────────────────────────────────────────\n\nconst INLINE_AND_SPECIAL: readonly NodeSpec[] = [\n {\n name: 'docLink',\n group: 'inline',\n wire: 'special',\n attrs: [str('docId')],\n doc: 'Wire form `[[uuid|label]]`; label regenerated on export.',\n },\n {\n name: 'docEmbed',\n group: 'block',\n wire: 'special',\n attrs: [str('docId'), bool('collapsed'), bool('tall'), bool('seamless')],\n doc: 'Wire form `![[uuid|label]]{collapsed tall seamless}`.',\n },\n {\n name: 'mention',\n group: 'inline',\n wire: 'special',\n attrs: [str('userId')],\n doc: 'Wire form `@[label](user:uuid)`; label regenerated on export.',\n },\n {\n name: 'mathInline',\n group: 'inline',\n wire: 'special',\n attrs: [{ key: 'expression', type: 'string' }],\n doc: 'Wire form `$expression$`.',\n },\n {\n name: 'mathBlock',\n group: 'block',\n wire: 'fence',\n attrs: [{ key: 'expression', type: 'string' }],\n mdcTag: 'math',\n doc: 'Wire form ``` ```math\\\\nexpression\\\\n``` ```.',\n },\n {\n name: 'fileBlock',\n group: 'block',\n wire: 'mdc-atom-block',\n mdcTag: 'file',\n attrs: [str('src'), str('mime'), str('uploadId'), str('filename')],\n doc: 'Wire form `:file{src=… mime=… upload-id=… filename=…}`; binary in sidecar.',\n },\n {\n name: 'badge',\n group: 'inline',\n wire: 'mdc-atom-inl',\n attrs: [str('label'), str('color'), str('variant', 'subtle')],\n doc: 'Wire form `:badge[Label]{color=… variant=…}`.',\n },\n {\n name: 'proseIcon',\n group: 'inline',\n wire: 'mdc-atom-inl',\n mdcTag: 'icon',\n attrs: [str('name')],\n doc: 'Wire form `:icon{name=…}`.',\n },\n {\n name: 'kbd',\n group: 'inline',\n wire: 'mdc-atom-inl',\n attrs: [str('value')],\n doc: 'Wire form `:kbd{value=…}`.',\n },\n]\n\nexport const NODE_SPECS: readonly NodeSpec[] = [\n ...VANILLA_BLOCKS,\n ...MDC_CONTAINERS,\n ...INLINE_AND_SPECIAL,\n]\n\nexport const NODE_SPEC_BY_NAME: ReadonlyMap<string, NodeSpec> = new Map(\n NODE_SPECS.map(spec => [spec.name, spec]),\n)\n\n/** Derive the MDC tag for a node — `mdcTag` override or kebab-case of `name`. */\nexport function mdcTagOf(spec: NodeSpec): string {\n if (spec.mdcTag) return spec.mdcTag\n return spec.name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()\n}\n\n/** Type-only re-export so consumers can build typed meta without a second import. */\nexport type { DocPageMeta }\n","// MarkSpec registry — every inline mark supported by the converter,\n// paired with its canonical Markdown wire form.\n//\n// Marks are pure inline annotations on text runs; they have no\n// children. The parser sets these as `op.attributes` on Yjs delta\n// inserts; the serialiser wraps text runs with the matching wire\n// delimiters.\n//\n// See SPEC.md §3-4 for the rendered table and the disambiguation\n// rules between bold (`**…**`) and underline (`__…__`).\n\nexport type MarkWireKind =\n | 'delimited' // `**text**`, `*text*`, `~~text~~`, `` `text` ``\n | 'link' // `[text](href)`\n | 'mdc-span' // `:span[text]{prop=value}` for color/font/textStyle\n\nexport interface MarkAttrSpec {\n key: string\n type: 'string' | 'number' | 'boolean'\n optional?: boolean\n}\n\nexport interface MarkSpec {\n name: string\n wire: MarkWireKind\n /** For `delimited`: the markdown delimiter (e.g. `**`, `*`, `~~`, `` ` ``, `__`, `==`). */\n delim?: string\n attrs?: readonly MarkAttrSpec[]\n doc?: string\n}\n\nexport const MARK_SPECS: readonly MarkSpec[] = [\n // Vanilla MD marks\n { name: 'bold', wire: 'delimited', delim: '**' },\n { name: 'italic', wire: 'delimited', delim: '*' },\n { name: 'strike', wire: 'delimited', delim: '~~' },\n { name: 'code', wire: 'delimited', delim: '`' },\n {\n name: 'link',\n wire: 'link',\n attrs: [\n { key: 'href', type: 'string' },\n { key: 'title', type: 'string', optional: true },\n ],\n },\n\n // Extended marks (lossless via MDC syntax)\n {\n name: 'underline',\n wire: 'delimited',\n delim: '__',\n doc: 'Disambiguated from bold by delimiter character. Two underscores = underline; two asterisks = bold.',\n },\n {\n name: 'highlight',\n wire: 'delimited',\n delim: '==',\n doc: 'Pandoc-style.',\n },\n {\n name: 'subscript',\n wire: 'delimited',\n delim: '~',\n doc: 'Single tilde; double tilde is strike.',\n },\n {\n name: 'superscript',\n wire: 'delimited',\n delim: '^',\n },\n {\n name: 'textStyle',\n wire: 'mdc-span',\n attrs: [\n { key: 'color', type: 'string', optional: true },\n { key: 'backgroundColor', type: 'string', optional: true },\n { key: 'fontSize', type: 'string', optional: true },\n { key: 'fontFamily', type: 'string', optional: true },\n ],\n doc: 'Wire form `:span[text]{color=\"…\" font-size=\"…\"}`. Any of the attrs may be set.',\n },\n]\n\nexport const MARK_SPEC_BY_NAME: ReadonlyMap<string, MarkSpec> = new Map(\n MARK_SPECS.map(spec => [spec.name, spec]),\n)\n\nexport const MARK_SPEC_BY_DELIM: ReadonlyMap<string, MarkSpec> = new Map(\n MARK_SPECS\n .filter((spec): spec is MarkSpec & { delim: string } => spec.wire === 'delimited' && !!spec.delim)\n .map(spec => [spec.delim, spec]),\n)\n","// Universal-meta registry.\n//\n// Mirrors `@abraca/schema/src/types/universal.ts` — the canonical\n// source. We don't import @abraca/schema here to keep this package\n// dependency-free, but the keys MUST stay in sync. A future codegen\n// step in @abraca/schema can verify this file is up to date.\n//\n// Order is significant — it's the canonical key order in serialised\n// YAML frontmatter (see SPEC.md §2). Adding new keys appends to the\n// end so existing fixtures don't churn.\n\nexport type MetaValueType =\n | 'string'\n | 'number'\n | 'integer'\n | 'boolean'\n | 'string[]'\n | 'string-enum'\n | 'iso-date'\n | 'iso-datetime'\n | 'hh-mm'\n | 'members'\n | 'json'\n\nexport interface UniversalMetaKey {\n key: string\n type: MetaValueType\n /** Allowed values for `string-enum`. */\n values?: readonly string[]\n /** Inclusive minimum for `number` / `integer`. */\n min?: number\n /** Inclusive maximum for `number` / `integer`. */\n max?: number\n /**\n * Alternate YAML key names recognised on parse — for backwards\n * compatibility with hand-written frontmatter (e.g. `date` → `dateStart`).\n * Serialise always uses the canonical `key`.\n */\n parseAliases?: readonly string[]\n /** Human-readable hint, surfaced in documentation. */\n doc?: string\n}\n\nexport const UNIVERSAL_META_KEYS: readonly UniversalMetaKey[] = [\n // Identity / display\n { key: 'title', type: 'string', doc: 'Display title; the first H1 is hoisted into this field on import.' },\n { key: 'type', type: 'string', doc: 'Page type (doc, kanban, table, …). Omitted on serialise when \"doc\".' },\n { key: 'color', type: 'string', doc: 'Hex or CSS color name.' },\n { key: 'icon', type: 'string', doc: 'Lucide icon name in kebab-case.' },\n\n // Datetime\n { key: 'datetimeStart', type: 'iso-datetime' },\n { key: 'datetimeEnd', type: 'iso-datetime' },\n { key: 'allDay', type: 'boolean' },\n { key: 'dateTaken', type: 'iso-datetime' },\n { key: 'dateStart', type: 'iso-date', parseAliases: ['date', 'created'] },\n { key: 'dateEnd', type: 'iso-date', parseAliases: ['due'] },\n { key: 'timeStart', type: 'hh-mm' },\n { key: 'timeEnd', type: 'hh-mm' },\n\n // Generic\n { key: 'tags', type: 'string[]' },\n { key: 'checked', type: 'boolean', parseAliases: ['done'] },\n {\n key: 'priority',\n type: 'integer',\n min: 0,\n max: 4,\n doc: 'Numeric or named (low/medium/high/urgent → 1/2/3/4).',\n },\n { key: 'status', type: 'string' },\n { key: 'rating', type: 'number', min: 0, max: 5 },\n { key: 'url', type: 'string' },\n { key: 'email', type: 'string' },\n { key: 'phone', type: 'string' },\n { key: 'number', type: 'number' },\n { key: 'unit', type: 'string' },\n { key: 'subtitle', type: 'string', parseAliases: ['description'] },\n { key: 'note', type: 'string' },\n { key: 'taskProgress', type: 'integer', min: 0, max: 100 },\n { key: 'members', type: 'members' },\n\n // Cover\n { key: 'coverUploadId', type: 'string' },\n { key: 'coverDocId', type: 'string' },\n { key: 'coverMimeType', type: 'string' },\n\n // Geo / map\n { key: 'geoType', type: 'string-enum', values: ['marker', 'line', 'measure'] },\n { key: 'geoLat', type: 'number' },\n { key: 'geoLng', type: 'number' },\n { key: 'geoDescription', type: 'string' },\n\n // Dashboard / mindmap / graph layout\n { key: 'deskX', type: 'number' },\n { key: 'deskY', type: 'number' },\n { key: 'deskZ', type: 'number' },\n { key: 'deskMode', type: 'string-enum', values: ['icon', 'widget-sm', 'widget-lg'] },\n { key: 'mmX', type: 'number' },\n { key: 'mmY', type: 'number' },\n { key: 'graphX', type: 'number' },\n { key: 'graphY', type: 'number' },\n { key: 'graphPinned', type: 'boolean' },\n\n // Spatial\n { key: 'spX', type: 'number' },\n { key: 'spY', type: 'number' },\n { key: 'spZ', type: 'number' },\n { key: 'spRX', type: 'number' },\n { key: 'spRY', type: 'number' },\n { key: 'spRZ', type: 'number' },\n { key: 'spSX', type: 'number' },\n { key: 'spSY', type: 'number' },\n { key: 'spSZ', type: 'number' },\n {\n key: 'spShape',\n type: 'string-enum',\n values: ['box', 'sphere', 'cylinder', 'cone', 'plane', 'torus', 'glb'],\n },\n { key: 'spOpacity', type: 'integer', min: 0, max: 100 },\n { key: 'spModelUploadId', type: 'string' },\n { key: 'spModelDocId', type: 'string' },\n\n // Slides\n { key: 'slidesTransition', type: 'string-enum', values: ['none', 'fade', 'slide'] },\n { key: 'slidesTheme', type: 'string-enum', values: ['dark', 'light'] },\n\n // Migration version (last so unknown keys ahead of it surface clearly)\n { key: '__schemaVersion', type: 'integer', min: 0 },\n] as const\n\nexport const UNIVERSAL_META_KEY_NAMES: ReadonlySet<string> = new Set(\n UNIVERSAL_META_KEYS.map(k => k.key),\n)\n\n/**\n * Build a map of every recognised input key (canonical + aliases) to\n * its canonical key. Used by the frontmatter parser.\n */\nexport function buildAliasMap(): ReadonlyMap<string, string> {\n const map = new Map<string, string>()\n for (const entry of UNIVERSAL_META_KEYS) {\n map.set(entry.key, entry.key)\n for (const alias of entry.parseAliases ?? []) map.set(alias, entry.key)\n }\n return map\n}\n","/**\n * Document CRUD commands: read, create, rename, move, delete, type, doc.\n */\nimport * as Y from 'yjs'\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { readEntries, childrenOf, normalizeRootId, resolveDocument, descendantsOf } from '../resolve.ts'\nimport { printJson, relativeTime } from '../output.ts'\nimport { yjsToMarkdown } from '../converters/yjsToMarkdown.ts'\nimport { populateYDocFromMarkdown, parseFrontmatter } from '../converters/markdownToYjs.ts'\n\n/** Safely read a tree map value, converting Y.Map to plain object if needed. */\nfunction toPlain(val: any): any {\n return val instanceof Y.Map ? val.toJSON() : val\n}\n\nregisterCommand({\n name: 'doc',\n aliases: ['info:doc'],\n description: 'Show document metadata (label, type, meta, dates).',\n usage: 'doc id=<docId> | name=<label> | path=<a/b/c>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found. Specify id=, name=, or path= to identify the document.'\n\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found in tree.`\n\n const entry = toPlain(raw)\n\n const lines = [\n `id: ${docId}`,\n `label: ${entry.label || 'Untitled'}`,\n `type: ${entry.type ?? '—'}`,\n `parent: ${entry.parentId ?? '(root)'}`,\n `order: ${entry.order ?? 0}`,\n `created: ${entry.createdAt ? new Date(entry.createdAt).toISOString() : '—'}`,\n `updated: ${entry.updatedAt ? new Date(entry.updatedAt).toISOString() : '—'} (${relativeTime(entry.updatedAt)})`,\n ]\n\n if (entry.meta && Object.keys(entry.meta).length > 0) {\n lines.push(`meta:`)\n for (const [k, v] of Object.entries(entry.meta)) {\n lines.push(` ${k}: ${typeof v === 'object' ? JSON.stringify(v) : v}`)\n }\n }\n\n // Count children\n const entries = readEntries(treeMap)\n const children = childrenOf(entries, docId)\n lines.push(`children: ${children.length}`)\n\n return lines.join('\\n')\n },\n})\n\nregisterCommand({\n name: 'read',\n aliases: ['cat', 'r'],\n description: 'Read document content as markdown.',\n usage: 'read id=<docId> | name=<label> | path=<a/b/c> [--format=json|md]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found. Specify id=, name=, or path= to identify the document.'\n\n try {\n const provider = await conn.getChildProvider(docId)\n const fragment = provider.document.getXmlFragment('default')\n const markdown = yjsToMarkdown(fragment, '')\n\n if (args.flags.has('json') || args.params['format'] === 'json') {\n // Include tree metadata + children\n const treeMap = conn.getTreeMap()\n let label = ''\n let type: string | undefined\n let meta: Record<string, unknown> | undefined\n let children: Array<{ id: string; label: string; type?: string }> = []\n if (treeMap) {\n const entry = treeMap.get(docId)\n if (entry) {\n label = entry.label || label\n type = entry.type\n meta = entry.meta\n }\n treeMap.forEach((value: any, id: string) => {\n const v = toPlain(value)\n if (v.parentId === docId) {\n children.push({ id, label: v.label || 'Untitled', type: v.type })\n }\n })\n children.sort((a: any, b: any) => {\n const va = treeMap.get(a.id)\n const vb = treeMap.get(b.id)\n return ((va?.order ?? 0) - (vb?.order ?? 0))\n })\n }\n return printJson({ label, type, meta, markdown, children })\n }\n\n return markdown || '(empty document)'\n } catch (error: any) {\n return `Error reading document: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'create',\n aliases: ['new'],\n description: 'Create a new document in the tree.',\n usage: 'create label=<name> [parent=<docId>] [type=<pageType>] [content=<markdown>] [--format=json]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const label = args.params['label'] || args.params['name'] || args.positional[0]\n if (!label) return 'Missing required parameter: label=<name>'\n\n const treeMap = conn.getTreeMap()\n const rootDoc = conn.rootDoc\n if (!treeMap || !rootDoc) return 'Not connected'\n\n // Resolve parent\n let parentId: string | null = null\n if (args.params['parent']) {\n parentId = resolveDocument(conn, { id: args.params['parent'], name: args.params['parent'] }, [])\n if (!parentId) parentId = args.params['parent'] // Use raw value as ID\n }\n\n const normalizedParent = normalizeRootId(parentId || conn.rootDocId, conn)\n const type = args.params['type']\n\n const id = crypto.randomUUID()\n const now = Date.now()\n\n // Parse optional meta from params\n const meta: Record<string, unknown> = {}\n if (args.params['icon']) meta['icon'] = args.params['icon']\n if (args.params['color']) meta['color'] = args.params['color']\n\n rootDoc.transact(() => {\n treeMap.set(id, {\n label,\n parentId: normalizedParent,\n order: now,\n type,\n meta: Object.keys(meta).length > 0 ? meta : undefined,\n createdAt: now,\n updatedAt: now,\n })\n })\n\n // Write content if provided\n const content = args.params['content']\n if (content) {\n try {\n const provider = await conn.getChildProvider(id)\n const fragment = provider.document.getXmlFragment('default')\n const contentToWrite = content.replace(/\\\\n/g, '\\n').replace(/\\\\t/g, '\\t')\n populateYDocFromMarkdown(fragment, contentToWrite, label)\n } catch (error: any) {\n return `Created ${id} \"${label}\" but failed to write content: ${error.message}`\n }\n }\n\n if (args.params['format'] === 'json') {\n return printJson({ id, label, parentId: normalizedParent, type })\n }\n\n return `Created: ${id.slice(0, 8)}… \"${label}\"${type ? ` (${type})` : ''}`\n },\n})\n\nregisterCommand({\n name: 'rename',\n description: 'Rename a document.',\n usage: 'rename id=<docId> | name=<oldLabel> label=<newLabel>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const newLabel = args.params['label'] || args.params['to']\n if (!newLabel) return 'Missing required parameter: label=<newLabel>'\n\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found.`\n\n const entry = toPlain(raw)\n treeMap.set(docId, { ...entry, label: newLabel, updatedAt: Date.now() })\n\n return `Renamed to \"${newLabel}\"`\n },\n})\n\nregisterCommand({\n name: 'move',\n aliases: ['mv'],\n description: 'Move a document to a new parent.',\n usage: 'move id=<docId> | name=<label> to=<parentId> [order=<n>]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const newParentId = args.params['to'] || args.params['parent']\n if (!newParentId) return 'Missing required parameter: to=<parentId>'\n\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found.`\n\n const entry = toPlain(raw)\n const order = args.params['order'] ? parseInt(args.params['order'], 10) : Date.now()\n treeMap.set(docId, {\n ...entry,\n parentId: normalizeRootId(newParentId, conn),\n order,\n updatedAt: Date.now(),\n })\n\n return `Moved ${docId.slice(0, 8)}… to parent ${newParentId.slice(0, 8)}…`\n },\n})\n\nregisterCommand({\n name: 'delete',\n aliases: ['rm', 'del'],\n description: 'Soft-delete a document (moves to trash).',\n usage: 'delete id=<docId> | name=<label>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const treeMap = conn.getTreeMap()\n const trashMap = conn.getTrashMap()\n const rootDoc = conn.rootDoc\n if (!treeMap || !trashMap || !rootDoc) return 'Not connected'\n\n const entries = readEntries(treeMap)\n const toDelete = [docId, ...descendantsOf(entries, docId).map(e => e.id)]\n\n const now = Date.now()\n rootDoc.transact(() => {\n for (const nid of toDelete) {\n const raw = treeMap.get(nid)\n if (!raw) continue\n const entry = toPlain(raw)\n trashMap.set(nid, {\n label: entry.label || 'Untitled',\n parentId: entry.parentId ?? null,\n order: entry.order ?? 0,\n type: entry.type,\n meta: entry.meta,\n deletedAt: now,\n })\n treeMap.delete(nid)\n }\n })\n\n return `Deleted ${toDelete.length} document(s)`\n },\n})\n\nregisterCommand({\n name: 'type',\n description: 'Change the page type view of a document.',\n usage: 'type id=<docId> | name=<label> type=<pageType>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const newType = args.params['type'] || args.positional[1]\n if (!newType) return 'Missing required parameter: type=<pageType>'\n\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found.`\n\n const entry = toPlain(raw)\n treeMap.set(docId, { ...entry, type: newType, updatedAt: Date.now() })\n\n return `Changed type to \"${newType}\"`\n },\n})\n\nregisterCommand({\n name: 'write',\n description: 'Write markdown content to a document (replace or append).',\n usage: 'write id=<docId> | name=<label> content=<markdown> [mode=replace|append]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n // Content from param, or read from stdin if piped\n let content = args.params['content']\n\n if (!content) {\n // Check if stdin is piped (not a TTY)\n if (!process.stdin.isTTY) {\n content = await readStdin()\n }\n }\n\n if (!content) return 'Missing required parameter: content=<markdown> (or pipe via stdin)'\n\n // Unescape \\n and \\t\n content = content.replace(/\\\\n/g, '\\n').replace(/\\\\t/g, '\\t')\n\n try {\n const writeMode = args.params['mode'] ?? 'replace'\n const provider = await conn.getChildProvider(docId)\n const doc = provider.document\n const fragment = doc.getXmlFragment('default')\n\n // Parse optional frontmatter\n const { title, meta, body } = parseFrontmatter(content)\n\n // Update tree metadata if frontmatter provided\n if (title || Object.keys(meta).length > 0) {\n const treeMap = conn.getTreeMap()\n const rootDoc = conn.rootDoc\n if (treeMap && rootDoc) {\n const entry = treeMap.get(docId)\n if (entry) {\n const e = toPlain(entry)\n rootDoc.transact(() => {\n const updates: Record<string, unknown> = { ...e, updatedAt: Date.now() }\n if (title) updates.label = title\n if (Object.keys(meta).length > 0) {\n updates.meta = { ...(e.meta ?? {}), ...meta }\n }\n treeMap.set(docId, updates)\n })\n }\n }\n }\n\n if (writeMode === 'replace') {\n doc.transact(() => {\n while (fragment.length > 0) {\n fragment.delete(0)\n }\n })\n }\n\n const contentToWrite = body || content\n populateYDocFromMarkdown(fragment, contentToWrite, title || 'Untitled')\n\n return `Document ${docId.slice(0, 8)}… updated (${writeMode} mode)`\n } catch (error: any) {\n return `Error writing document: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'duplicate',\n aliases: ['dup'],\n description: 'Shallow-clone a document.',\n usage: 'duplicate id=<docId> | name=<label>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found.`\n\n const entry = toPlain(raw)\n const newId = crypto.randomUUID()\n treeMap.set(newId, {\n ...entry,\n label: (entry.label || 'Untitled') + ' (copy)',\n order: Date.now(),\n })\n\n return `Duplicated: ${newId.slice(0, 8)}… \"${entry.label} (copy)\"`\n },\n})\n\n/** Helper to read all of stdin as a string. */\nfunction readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n let data = ''\n process.stdin.setEncoding('utf-8')\n process.stdin.on('data', (chunk: string) => { data += chunk })\n process.stdin.on('end', () => resolve(data))\n process.stdin.on('error', reject)\n // Safety timeout — don't hang forever\n setTimeout(() => resolve(data), 5000)\n })\n}\n","/**\n * Content commands: append, prepend, wc, export.\n */\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { resolveDocument } from '../resolve.ts'\nimport { yjsToMarkdown } from '../converters/yjsToMarkdown.ts'\nimport { populateYDocFromMarkdown } from '../converters/markdownToYjs.ts'\n\nregisterCommand({\n name: 'append',\n description: 'Append content to a document.',\n usage: 'append id=<docId> | name=<label> content=<text> [--inline]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const content = args.params['content']\n if (!content) return 'Missing required parameter: content=<text>'\n\n try {\n const provider = await conn.getChildProvider(docId)\n const fragment = provider.document.getXmlFragment('default')\n const text = args.flags.has('inline')\n ? content.replace(/\\\\n/g, '\\n').replace(/\\\\t/g, '\\t')\n : '\\n' + content.replace(/\\\\n/g, '\\n').replace(/\\\\t/g, '\\t')\n populateYDocFromMarkdown(fragment, text, '')\n\n return `Appended to ${docId.slice(0, 8)}…`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'prepend',\n description: 'Prepend content to a document (after frontmatter).',\n usage: 'prepend id=<docId> | name=<label> content=<text> [--inline]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const content = args.params['content']\n if (!content) return 'Missing required parameter: content=<text>'\n\n try {\n const provider = await conn.getChildProvider(docId)\n const doc = provider.document\n const fragment = doc.getXmlFragment('default')\n\n // Read existing, prepend, rewrite\n const existing = yjsToMarkdown(fragment, '')\n const text = content.replace(/\\\\n/g, '\\n').replace(/\\\\t/g, '\\t')\n const combined = args.flags.has('inline')\n ? text + existing\n : text + '\\n' + existing\n\n doc.transact(() => {\n while (fragment.length > 0) {\n fragment.delete(0)\n }\n })\n populateYDocFromMarkdown(fragment, combined, '')\n\n return `Prepended to ${docId.slice(0, 8)}…`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'wc',\n aliases: ['wordcount'],\n description: 'Count words and characters in a document.',\n usage: 'wc id=<docId> | name=<label> [--words] [--characters]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n try {\n const provider = await conn.getChildProvider(docId)\n const fragment = provider.document.getXmlFragment('default')\n const markdown = yjsToMarkdown(fragment, '')\n\n const words = markdown.split(/\\s+/).filter(Boolean).length\n const chars = markdown.length\n\n if (args.flags.has('words')) return String(words)\n if (args.flags.has('characters')) return String(chars)\n\n return `Words: ${words}\\nCharacters: ${chars}`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'export',\n description: 'Export a document as markdown to a local file.',\n usage: 'export id=<docId> | name=<label> output=<filepath>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const outputPath = args.params['output'] || args.params['to'] || args.params['path']\n if (!outputPath) return 'Missing required parameter: output=<filepath>'\n\n try {\n const provider = await conn.getChildProvider(docId)\n const fragment = provider.document.getXmlFragment('default')\n const treeMap = conn.getTreeMap()\n const title = (treeMap?.get(docId) as any)?.label as string | undefined\n const markdown = yjsToMarkdown(fragment, title ?? '')\n\n const resolvedPath = path.resolve(outputPath)\n fs.writeFileSync(resolvedPath, markdown, 'utf-8')\n\n return `Exported \"${title || 'document'}\" to ${resolvedPath} (${Buffer.byteLength(markdown)} bytes)`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n","/**\n * Metadata commands: meta, tags.\n */\nimport * as Y from 'yjs'\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { readEntries, resolveDocument } from '../resolve.ts'\nimport { printJson, printTable, getFormat } from '../output.ts'\n\n/** Safely read a tree map value. */\nfunction toPlain(val: any): any {\n return val instanceof Y.Map ? val.toJSON() : val\n}\n\nregisterCommand({\n name: 'meta',\n aliases: ['metadata'],\n description: 'Get or set document metadata.',\n usage: 'meta id=<docId> | name=<label> [key=value ...] [--format=json]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found.`\n\n const entry = toPlain(raw)\n\n // Known meta keys across all page types (universal + renderer-specific).\n // Kept in sync with cou-sh/app/composables/useChildTree.ts DocPageMeta and\n // the MCP PageMeta type.\n const metaKeys = new Set([\n // Universal display\n 'color', 'icon', 'subtitle', 'note',\n // Datetime\n 'datetimeStart', 'datetimeEnd', 'allDay', 'dateStart', 'dateEnd',\n 'timeStart', 'timeEnd', 'dateTaken',\n // Task/status\n 'checked', 'priority', 'status', 'taskProgress', 'rating', 'tags', 'members',\n // Contact/value\n 'url', 'email', 'phone', 'number', 'unit',\n // Cover\n 'coverUploadId', 'coverDocId', 'coverMimeType',\n // Geo/Map (children)\n 'geoType', 'geoLat', 'geoLng', 'geoDescription',\n // Dashboard (children)\n 'deskX', 'deskY', 'deskZ', 'deskMode',\n // Mindmap layout (children)\n 'mmX', 'mmY',\n // Graph layout (children)\n 'graphX', 'graphY', 'graphPinned',\n // Spatial 3D children (plugin) — uses universal `color`, not spColor\n 'spShape', 'spOpacity', 'spX', 'spY', 'spZ',\n 'spRX', 'spRY', 'spRZ', 'spSX', 'spSY', 'spSZ',\n 'spModelUploadId', 'spModelDocId',\n // Slides children\n 'slidesTransition',\n // Coder children (plugin)\n 'fileType', 'entry',\n // Sheets cell formatting\n 'bold', 'italic', 'textColor', 'bgColor', 'align', 'formula',\n // Kanban renderer config (on page doc)\n 'kanbanColumnWidth',\n // Gallery renderer config\n 'galleryColumns', 'galleryAspect', 'galleryCardStyle', 'galleryShowLabels', 'gallerySortBy',\n // Calendar renderer config\n 'calendarView', 'calendarWeekStart', 'calendarShowWeekNumbers',\n // Table renderer config\n 'tableMode', 'tableSortKey', 'tableSortDir',\n // Timeline renderer config\n 'timelineZoom', 'timelinePixelsPerDay', 'timelineCenterDate',\n // Checklist renderer config\n 'checklistFilter', 'checklistSort',\n // Map renderer config\n 'mapShowLabels',\n // Graph renderer config\n 'graphSpacing', 'graphShowLabels', 'graphEdgeThickness', 'showRefEdges',\n // Mindmap renderer config\n 'mmSpacing',\n // Spatial renderer config\n 'spatialGridVisible',\n // Slides renderer config\n 'slidesTheme',\n // Chart renderer config\n 'chartType', 'chartMetric', 'chartColorScheme', 'chartLimit',\n 'chartShowLegend', 'chartShowValues',\n // Sheets renderer config\n 'sheetsDefaultColWidth', 'sheetsDefaultRowHeight', 'sheetsShowGridlines',\n 'sheetsFreezeRows', 'sheetsFreezeCols',\n // Media renderer config (plugin)\n 'mediaRepeat', 'mediaShuffle',\n ])\n\n // Keys whose values should be parsed as numbers.\n const numericKeys = new Set([\n 'priority', 'rating', 'number', 'taskProgress', 'geoLat', 'geoLng',\n 'deskX', 'deskY', 'deskZ', 'mmX', 'mmY', 'graphX', 'graphY',\n 'spOpacity', 'spX', 'spY', 'spZ', 'spRX', 'spRY', 'spRZ',\n 'spSX', 'spSY', 'spSZ',\n 'galleryColumns', 'chartLimit', 'timelinePixelsPerDay',\n 'sheetsDefaultColWidth', 'sheetsDefaultRowHeight',\n 'sheetsFreezeRows', 'sheetsFreezeCols',\n ])\n\n const updates: Record<string, unknown> = {}\n let hasUpdates = false\n\n for (const [key, value] of Object.entries(args.params)) {\n if (metaKeys.has(key)) {\n // Parse special types\n if (value === 'null') {\n updates[key] = null\n } else if (value === 'true') {\n updates[key] = true\n } else if (value === 'false') {\n updates[key] = false\n } else if (numericKeys.has(key)) {\n updates[key] = parseFloat(value)\n } else if (key === 'tags') {\n updates[key] = value.split(',').map(s => s.trim())\n } else {\n updates[key] = value\n }\n hasUpdates = true\n }\n }\n\n if (hasUpdates) {\n // Write mode: merge updates into existing meta\n treeMap.set(docId, {\n ...entry,\n meta: { ...(entry.meta ?? {}), ...updates },\n updatedAt: Date.now(),\n })\n return `Metadata updated for ${docId.slice(0, 8)}…`\n }\n\n // Read mode: display current metadata\n const meta = entry.meta ?? {}\n if (args.params['format'] === 'json') {\n return printJson({ id: docId, label: entry.label, type: entry.type, meta })\n }\n\n if (Object.keys(meta).length === 0) {\n return `Document \"${entry.label}\" has no metadata.`\n }\n\n const lines = Object.entries(meta).map(([k, v]) =>\n `${k}: ${typeof v === 'object' ? JSON.stringify(v) : v}`\n )\n return lines.join('\\n')\n },\n})\n\nregisterCommand({\n name: 'tags',\n description: 'List tags aggregated from document metadata.',\n usage: 'tags [id=<docId>] [--counts] [--total] [--format=json|tsv]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n // If a document is specified, show its tags\n const docId = resolveDocument(conn, args.params, args.positional)\n if (docId) {\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found.`\n const entry = toPlain(raw)\n const tags: string[] = entry.meta?.tags ?? []\n if (tags.length === 0) return 'No tags.'\n return tags.join('\\n')\n }\n\n // Aggregate tags from all documents\n const entries = readEntries(treeMap)\n const tagCounts = new Map<string, number>()\n\n for (const entry of entries) {\n const tags: string[] = (entry.meta as any)?.tags ?? []\n for (const tag of tags) {\n tagCounts.set(tag, (tagCounts.get(tag) ?? 0) + 1)\n }\n }\n\n if (tagCounts.size === 0) return 'No tags found.'\n\n if (args.flags.has('total')) {\n return String(tagCounts.size)\n }\n\n const sorted = [...tagCounts.entries()].sort((a, b) => {\n if (args.params['sort'] === 'count') return b[1] - a[1]\n return a[0].localeCompare(b[0])\n })\n\n const format = getFormat(args, 'text')\n\n if (format === 'json') {\n return printJson(sorted.map(([tag, count]) => ({ tag, count })))\n }\n\n if (args.flags.has('counts')) {\n return sorted.map(([tag, count]) => `${tag}\\t${count}`).join('\\n')\n }\n\n return sorted.map(([tag]) => tag).join('\\n')\n },\n})\n","/**\n * Awareness commands: who, status, chat.\n */\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { printJson, printTable, getFormat } from '../output.ts'\n\nregisterCommand({\n name: 'who',\n aliases: ['users', 'online'],\n description: 'List connected users and their awareness state.',\n usage: 'who [id=<docId>] [--format=json|tsv]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n let awareness\n if (args.params['id']) {\n try {\n const provider = await conn.getChildProvider(args.params['id'])\n awareness = provider.awareness\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n } else {\n const rootProvider = conn.rootProvider\n if (!rootProvider) return 'Not connected'\n awareness = rootProvider.awareness\n }\n\n const states = awareness.getStates()\n const selfId = awareness.clientID\n const users: Array<{\n name: string\n status: string\n docId: string\n isYou: boolean\n isAgent: boolean\n }> = []\n\n for (const [clientId, state] of states) {\n const user = (state as Record<string, any>)['user']\n if (!user) continue\n users.push({\n name: user.name ?? 'Unknown',\n status: (state as Record<string, any>)['status'] ?? '—',\n docId: (state as Record<string, any>)['docId'] ?? '—',\n isYou: clientId === selfId,\n isAgent: user.isAgent ?? false,\n })\n }\n\n const format = getFormat(args, 'text')\n\n if (format === 'json') {\n return printJson(users)\n }\n\n if (users.length === 0) {\n return 'No users connected.'\n }\n\n const rows = users.map(u => [\n u.name + (u.isYou ? ' (you)' : '') + (u.isAgent ? ' 🤖' : ''),\n u.status,\n u.docId === '—' ? '—' : u.docId.slice(0, 8) + '…',\n ])\n\n return printTable(rows, ['NAME', 'STATUS', 'DOCUMENT'])\n },\n})\n\nregisterCommand({\n name: 'status',\n description: 'Set your presence status.',\n usage: 'status <text> | status --clear',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const rootProvider = conn.rootProvider\n if (!rootProvider) return 'Not connected'\n\n if (args.flags.has('clear')) {\n rootProvider.awareness.setLocalStateField('status', null)\n return 'Status cleared.'\n }\n\n const status = args.params['text'] || args.positional[0]\n if (!status) return 'Missing status text. Use: status <text> or status --clear'\n\n rootProvider.awareness.setLocalStateField('status', status)\n return `Status set to \"${status}\"`\n },\n})\n\nregisterCommand({\n name: 'chat',\n aliases: ['send'],\n description: 'Send a chat message to a channel doc.',\n usage: 'chat channel_doc_id=<docId> text=<message>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const rootProvider = conn.rootProvider\n if (!rootProvider) return 'Not connected'\n\n // Accept either `channel_doc_id` or legacy `channel` (with optional\n // `group:` prefix the new server doesn't use — strip it).\n const raw = args.params['channel_doc_id'] || args.params['channel']\n if (!raw) return 'Missing required parameter: channel_doc_id=<docId>'\n const channel_doc_id = raw.startsWith('group:') ? raw.slice(6) : raw\n\n const text = args.params['text'] || args.params['content'] || args.positional[0]\n if (!text) return 'Missing required parameter: text=<message>'\n\n rootProvider.sendStateless(JSON.stringify({\n type: 'messages:send',\n channel_doc_id,\n content: text,\n mentions: [],\n }))\n\n return `Sent to ${channel_doc_id}`\n },\n})\n","/**\n * File attachment commands: upload, uploads.\n */\nimport * as fs from 'node:fs'\nimport * as nodePath from 'node:path'\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { resolveDocument } from '../resolve.ts'\nimport { printJson, printTable, getFormat } from '../output.ts'\n\nregisterCommand({\n name: 'uploads',\n aliases: ['attachments'],\n description: 'List file attachments for a document.',\n usage: 'uploads id=<docId> | name=<label> [--format=json|tsv] [--total]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n try {\n const uploads = await conn.client.listUploads(docId)\n\n if (args.flags.has('total')) {\n return String(uploads.length)\n }\n\n const format = getFormat(args, 'text')\n\n if (format === 'json') {\n return printJson(uploads)\n }\n\n if (uploads.length === 0) {\n return 'No attachments.'\n }\n\n const rows = uploads.map(u => [\n u.id.slice(0, 8) + '…',\n u.filename,\n u.mime_type ?? '—',\n u.size ? formatBytes(u.size) : '—',\n ])\n\n return printTable(rows, ['ID', 'FILENAME', 'TYPE', 'SIZE'])\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'upload',\n description: 'Upload a local file to a document.',\n usage: 'upload id=<docId> | name=<label> file=<localPath> [filename=<override>]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const filePath = args.params['file'] || args.params['path']\n if (!filePath) return 'Missing required parameter: file=<localPath>'\n\n try {\n const resolvedPath = nodePath.resolve(filePath)\n if (!fs.existsSync(resolvedPath)) {\n return `File not found: ${resolvedPath}`\n }\n const data = fs.readFileSync(resolvedPath)\n const filename = args.params['filename'] ?? nodePath.basename(resolvedPath)\n const blob = new Blob([data])\n const result = await conn.client.upload(docId, blob, filename)\n\n return `Uploaded: ${filename} (${formatBytes(data.length)}) → ${result.id}`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'download',\n description: 'Download a file attachment from a document.',\n usage: 'download id=<docId> | name=<label> upload=<uploadId> output=<localPath>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const uploadId = args.params['upload'] || args.params['uploadId']\n if (!uploadId) return 'Missing required parameter: upload=<uploadId>'\n\n const outputPath = args.params['output'] || args.params['to']\n if (!outputPath) return 'Missing required parameter: output=<localPath>'\n\n try {\n const blob = await conn.client.getUpload(docId, uploadId)\n const buffer = Buffer.from(await blob.arrayBuffer())\n const resolvedPath = nodePath.resolve(outputPath)\n fs.writeFileSync(resolvedPath, buffer)\n\n return `Downloaded to ${resolvedPath} (${formatBytes(buffer.length)})`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n","/**\n * Permission commands: permissions.\n */\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { resolveDocument } from '../resolve.ts'\nimport { printJson, printTable, getFormat } from '../output.ts'\n\nregisterCommand({\n name: 'permissions',\n aliases: ['perms'],\n description: 'List or set document permissions.',\n usage: 'permissions id=<docId> [user=<userId> role=<role>] [--effective] [--format=json|tsv]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n // Set permission mode\n const targetUser = args.params['user'] || args.params['user_id']\n const targetRole = args.params['role']\n\n if (targetUser && targetRole) {\n try {\n await conn.client.setPermission(docId, {\n user_id: targetUser,\n role: targetRole as 'owner' | 'editor' | 'viewer' | 'observer',\n })\n return `Set ${targetUser.slice(0, 12)}… → ${targetRole} on ${docId.slice(0, 8)}…`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n }\n\n // Remove permission mode\n if (targetUser && args.flags.has('remove')) {\n try {\n await conn.client.removePermission(docId, { user_id: targetUser })\n return `Removed permissions for ${targetUser.slice(0, 12)}… on ${docId.slice(0, 8)}…`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n }\n\n // List permissions mode\n try {\n const format = getFormat(args, 'text')\n\n if (args.flags.has('effective')) {\n const result = await conn.client.listEffectivePermissions(docId)\n\n if (format === 'json') {\n return printJson(result)\n }\n\n if (result.permissions.length === 0) {\n return `Default role: ${result.default_role}\\nNo explicit permissions.`\n }\n\n const rows = result.permissions.map(p => [\n p.display_name || p.username,\n p.role,\n p.source,\n p.inherited_from_doc_id ? p.inherited_from_doc_id.slice(0, 8) + '…' : '—',\n ])\n\n return `Default role: ${result.default_role}\\n\\n` +\n printTable(rows, ['USER', 'ROLE', 'SOURCE', 'INHERITED FROM'])\n }\n\n const perms = await conn.client.listPermissions(docId)\n\n if (format === 'json') {\n return printJson(perms)\n }\n\n if (perms.length === 0) {\n return 'No explicit permissions set.'\n }\n\n const rows = perms.map(p => [\n p.display_name || p.username,\n p.role,\n p.user_id.slice(0, 12) + '…',\n ])\n\n return printTable(rows, ['USER', 'ROLE', 'USER ID'])\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n","/**\n * Static catalog of Abracadabra page types and their metadata schemas.\n *\n * Kept in sync with `cou-sh/app/utils/docTypes.ts` and the plugin definitions\n * under `cou-sh/plugin-<name>/src/index.ts`. No UI dependencies — it\n * is a plain data description so agents (via MCP) and CLI tooling can discover\n * what fields apply to which renderer without having to read the dashboard\n * source code.\n *\n * Schema semantics (from page-type-guidelines.md):\n *\n * - `metaSchema` — fields that apply to DESCENDANTS (children, grandchildren,\n * and beyond) of a page of this type. E.g. the calendar's schema describes\n * what an *event* meta looks like, not the calendar itself.\n * - `defaultMetaFields` — fields inserted into the page doc's own metadata\n * when first rendered; these are view config knobs (e.g. `calendarView`).\n */\n\nexport type MetaFieldType\n = | 'datetimerange'\n | 'daterange'\n | 'timerange'\n | 'datetime'\n | 'date'\n | 'time'\n | 'slider'\n | 'number'\n | 'toggle'\n | 'select'\n | 'multiselect'\n | 'colorPreset'\n | 'colorPicker'\n | 'location'\n | 'icon'\n | 'textarea'\n | 'url'\n | 'rating'\n | 'tags'\n | 'members'\n\nexport interface PageTypeMetaField {\n type: MetaFieldType\n label?: string\n /** single-value fields */\n key?: string\n /** location */\n latKey?: string\n lngKey?: string\n /** ranges */\n startKey?: string\n endKey?: string\n allDayKey?: string\n /** color preset */\n presets?: string[]\n /** icon / select / tags */\n options?: string[]\n /** slider / number */\n min?: number\n max?: number\n step?: number\n unit?: string\n /** toggle default */\n default?: boolean\n}\n\nexport interface PageTypeInfo {\n key: string\n label: string\n icon: string\n description?: string\n /** true = core type (always available); false = requires plugin */\n core: boolean\n plugin?: string\n supportsChildren: boolean\n childLabel?: string\n grandchildLabel?: string\n /** -1 = unlimited depth */\n defaultDepth?: number\n /** Fields that apply to this doc's descendants (children, grandchildren, ...) */\n metaSchema?: PageTypeMetaField[]\n /** Fields written to this doc's own meta on first render (renderer config) */\n defaultMetaFields?: PageTypeMetaField[]\n}\n\nconst GEO_COLOR_PRESETS = ['#3b82f6', '#f97316', '#22c55e', '#ef4444', '#a855f7']\nconst GEO_ICON_OPTIONS = [\n 'map-pin', 'star', 'flag', 'home', 'building-2', 'coffee', 'utensils',\n 'camera', 'heart', 'zap', 'triangle-alert', 'car', 'plane', 'anchor',\n 'tree-pine', 'mountain', 'waves', 'shield', 'crosshair', 'circle-dot',\n 'bookmark', 'gem', 'radio', 'compass',\n]\n\nexport const GEO_TYPE_META_SCHEMAS: Record<string, PageTypeMetaField[]> = {\n marker: [\n { type: 'location', latKey: 'geoLat', lngKey: 'geoLng', label: 'Location' },\n { type: 'icon', key: 'icon', options: GEO_ICON_OPTIONS, label: 'Icon' },\n { type: 'colorPreset', key: 'color', presets: GEO_COLOR_PRESETS, label: 'Color' },\n ],\n line: [\n { type: 'colorPreset', key: 'color', presets: GEO_COLOR_PRESETS, label: 'Color' },\n ],\n measure: [],\n}\n\nexport const PAGE_TYPES: Record<string, PageTypeInfo> = {\n doc: {\n key: 'doc',\n label: 'Document',\n icon: 'file-text',\n description: 'Rich text document with real-time collaboration',\n core: true,\n supportsChildren: true,\n },\n prose: {\n key: 'prose',\n label: 'Prose',\n icon: 'pen-tool',\n description: 'Long-form prose with serif typography and a narrow readable measure',\n core: true,\n supportsChildren: true,\n childLabel: 'Item',\n defaultDepth: -1,\n },\n kanban: {\n key: 'kanban',\n label: 'Kanban',\n icon: 'kanban',\n description: 'Drag-and-drop task board with columns and cards',\n core: true,\n supportsChildren: true,\n childLabel: 'Column',\n grandchildLabel: 'Card',\n defaultMetaFields: [\n { type: 'select', key: 'kanbanColumnWidth', options: ['narrow', 'default', 'wide'], label: 'Column Width' },\n ],\n },\n gallery: {\n key: 'gallery',\n label: 'Gallery',\n icon: 'images',\n description: 'Visual grid of items with rich content',\n core: true,\n supportsChildren: true,\n childLabel: 'Item',\n metaSchema: [\n { type: 'location', latKey: 'geoLat', lngKey: 'geoLng', label: 'Location' },\n { type: 'datetime', key: 'datetimeStart', label: 'Date' },\n { type: 'tags', key: 'tags', label: 'Tags' },\n { type: 'rating', key: 'rating', max: 5, label: 'Rating' },\n { type: 'icon', key: 'icon', label: 'Icon' },\n { type: 'colorPreset', key: 'color', presets: ['#6366f1', '#ec4899', '#f97316', '#22c55e', '#3b82f6', '#a855f7'], label: 'Color' },\n ],\n defaultMetaFields: [\n { type: 'number', key: 'galleryColumns', min: 1, max: 6, step: 1, label: 'Columns' },\n { type: 'select', key: 'galleryAspect', options: ['square', '4:3', '3:2', '16:9', 'free'], label: 'Aspect Ratio' },\n { type: 'select', key: 'galleryCardStyle', options: ['default', 'compact', 'detailed'], label: 'Card Style' },\n { type: 'toggle', key: 'galleryShowLabels', label: 'Show Labels' },\n { type: 'select', key: 'gallerySortBy', options: ['manual', 'date', 'name', 'rating'], label: 'Sort' },\n ],\n },\n table: {\n key: 'table',\n label: 'Table',\n icon: 'table',\n description: 'Collaborative spreadsheet with custom fields',\n core: true,\n supportsChildren: true,\n childLabel: 'Column',\n grandchildLabel: 'Row',\n defaultMetaFields: [\n { type: 'select', key: 'tableMode', options: ['hierarchy', 'flat'], label: 'Mode' },\n { type: 'select', key: 'tableSortDir', options: ['asc', 'desc'], label: 'Sort Direction' },\n ],\n },\n outline: {\n key: 'outline',\n label: 'Outline',\n icon: 'list-tree',\n description: 'Hierarchical outline with keyboard navigation',\n core: true,\n supportsChildren: true,\n childLabel: 'Item',\n defaultDepth: -1,\n },\n checklist: {\n key: 'checklist',\n label: 'Checklist',\n icon: 'check-square',\n description: 'Collaborative checklist with sub-tasks, drag-and-drop, and due dates',\n core: true,\n supportsChildren: true,\n childLabel: 'Task',\n defaultDepth: -1,\n metaSchema: [\n { type: 'toggle', key: 'checked', label: 'Done' },\n { type: 'select', key: 'priority', options: ['none', 'low', 'medium', 'high'], label: 'Priority' },\n { type: 'date', key: 'dateEnd', label: 'Due date' },\n ],\n defaultMetaFields: [\n { type: 'select', key: 'checklistFilter', options: ['all', 'active', 'completed'], label: 'Filter' },\n { type: 'select', key: 'checklistSort', options: ['manual', 'priority', 'due'], label: 'Sort' },\n ],\n },\n graph: {\n key: 'graph',\n label: 'Graph',\n icon: 'git-fork',\n description: 'Force-directed knowledge graph — full document tree as nodes & edges',\n core: true,\n supportsChildren: true,\n childLabel: 'Node',\n defaultMetaFields: [\n { type: 'toggle', key: 'showRefEdges', label: 'Show Ref Edges', default: true },\n ],\n },\n timeline: {\n key: 'timeline',\n label: 'Timeline',\n icon: 'gantt-chart',\n description: 'Gantt-style project timeline with epics and tasks',\n core: true,\n supportsChildren: true,\n childLabel: 'Epic',\n grandchildLabel: 'Task',\n metaSchema: [\n { type: 'daterange', startKey: 'dateStart', endKey: 'dateEnd' },\n { type: 'slider', key: 'taskProgress', min: 0, max: 100, label: 'Progress' },\n { type: 'colorPreset', key: 'color', presets: ['#6366f1', '#818cf8', '#f97316', '#22c55e', '#3b82f6', '#a855f7'], label: 'Color' },\n ],\n },\n calendar: {\n key: 'calendar',\n label: 'Calendar',\n icon: 'calendar',\n description: 'Event calendar with month, week, and day views',\n core: true,\n supportsChildren: true,\n childLabel: 'Event',\n metaSchema: [\n { type: 'datetimerange', startKey: 'datetimeStart', endKey: 'datetimeEnd', allDayKey: 'allDay' },\n { type: 'colorPreset', key: 'color', presets: ['#6366f1', '#ec4899', '#f97316', '#22c55e', '#3b82f6', '#a855f7'], label: 'Color' },\n { type: 'icon', key: 'icon', label: 'Icon' },\n ],\n defaultMetaFields: [\n { type: 'select', key: 'calendarWeekStart', options: ['sun', 'mon'], label: 'Week Starts' },\n { type: 'select', key: 'calendarView', options: ['month', 'week', 'day'], label: 'Default View' },\n { type: 'toggle', key: 'calendarShowWeekNumbers', label: 'Show Week Numbers' },\n ],\n },\n map: {\n key: 'map',\n label: 'Map',\n icon: 'map',\n description: 'Collaborative world map with shared markers',\n core: true,\n supportsChildren: true,\n childLabel: 'Location',\n defaultMetaFields: [\n { type: 'toggle', key: 'mapShowLabels', label: 'Show Labels', default: true },\n ],\n },\n dashboard: {\n key: 'dashboard',\n label: 'Dashboard',\n icon: 'layout-dashboard',\n description: 'Arrange documents as draggable icons with optional widget views',\n core: true,\n supportsChildren: true,\n childLabel: 'Item',\n },\n call: {\n key: 'call',\n label: 'Call',\n icon: 'phone',\n description: 'Video call room with live audio and screen sharing',\n core: true,\n supportsChildren: false,\n },\n chart: {\n key: 'chart',\n label: 'Chart',\n icon: 'bar-chart-3',\n description: 'Charts — manual data points or aggregation over document trees',\n core: true,\n supportsChildren: true,\n childLabel: 'Data Point',\n grandchildLabel: 'Data Point',\n metaSchema: [\n { type: 'number', key: 'number', step: 0.01, label: 'Value' },\n { type: 'colorPreset', key: 'color', presets: ['#6366f1', '#ec4899', '#f97316', '#22c55e', '#3b82f6', '#a855f7', '#14b8a6', '#eab308'], label: 'Color' },\n { type: 'tags', key: 'tags', label: 'Tags' },\n ],\n defaultMetaFields: [\n { type: 'select', key: 'chartType', options: ['bar', 'stacked bar', 'line', 'donut', 'treemap'], label: 'Chart Type' },\n { type: 'select', key: 'chartMetric', options: ['value', 'type', 'tag', 'status', 'priority', 'activity', 'completion'], label: 'Metric' },\n { type: 'select', key: 'chartColorScheme', options: ['default', 'warm', 'cool', 'mono'], label: 'Colors' },\n { type: 'number', key: 'chartLimit', min: 3, max: 30, step: 1, label: 'Max Items' },\n { type: 'toggle', key: 'chartShowLegend', label: 'Show Legend', default: true },\n { type: 'toggle', key: 'chartShowValues', label: 'Show Values' },\n ],\n },\n sheets: {\n key: 'sheets',\n label: 'Sheets',\n icon: 'grid-3x3',\n description: 'Spreadsheet — cells, formulas, and formatting in a collaborative grid',\n core: true,\n supportsChildren: true,\n childLabel: 'Column',\n grandchildLabel: 'Cell',\n defaultMetaFields: [\n { type: 'number', key: 'sheetsDefaultColWidth', min: 40, max: 500, step: 10, label: 'Column Width' },\n { type: 'number', key: 'sheetsDefaultRowHeight', min: 20, max: 100, step: 2, label: 'Row Height' },\n { type: 'toggle', key: 'sheetsShowGridlines', label: 'Gridlines' },\n ],\n },\n slides: {\n key: 'slides',\n label: 'Slides',\n icon: 'presentation',\n description: 'Presentation slides with two-axis navigation',\n core: true,\n supportsChildren: true,\n childLabel: 'Slide',\n grandchildLabel: 'Sub-slide',\n metaSchema: [\n { type: 'select', key: 'slidesTransition', options: ['none', 'fade', 'slide'], label: 'Transition' },\n { type: 'colorPreset', key: 'color', presets: ['#6366f1', '#ec4899', '#f97316', '#22c55e', '#3b82f6', '#a855f7'], label: 'Accent' },\n ],\n defaultMetaFields: [\n { type: 'select', key: 'slidesTheme', options: ['dark', 'light'], label: 'Theme' },\n ],\n },\n overview: {\n key: 'overview',\n label: 'Overview',\n icon: 'radar',\n description: 'Space home — activity, people, stats, and health at a glance',\n core: true,\n supportsChildren: true,\n childLabel: 'Page',\n },\n\n // Plugin-contributed types — require the named plugin to be enabled server-side.\n\n spatial: {\n key: 'spatial',\n label: 'Spatial',\n icon: 'box',\n description: '3D scene with collaborative objects and real-time presence',\n core: false,\n plugin: 'spatial',\n supportsChildren: true,\n childLabel: 'Object',\n grandchildLabel: 'Part',\n defaultDepth: -1,\n metaSchema: [\n { type: 'select', key: 'spShape', options: ['box', 'sphere', 'cylinder', 'cone', 'plane', 'torus', 'glb'], label: 'Shape' },\n { type: 'colorPreset', key: 'color', presets: ['#6366f1', '#ef4444', '#22c55e', '#3b82f6', '#f97316', '#a855f7', '#ec4899', '#14b8a6'], label: 'Color' },\n { type: 'slider', key: 'spOpacity', min: 0, max: 100, label: 'Opacity' },\n { type: 'number', key: 'spX', step: 0.1, label: 'X' },\n { type: 'number', key: 'spY', step: 0.1, label: 'Y' },\n { type: 'number', key: 'spZ', step: 0.1, label: 'Z' },\n { type: 'number', key: 'spRX', min: -180, max: 180, step: 1, label: 'Rot X' },\n { type: 'number', key: 'spRY', min: -180, max: 180, step: 1, label: 'Rot Y' },\n { type: 'number', key: 'spRZ', min: -180, max: 180, step: 1, label: 'Rot Z' },\n { type: 'number', key: 'spSX', min: 0.01, max: 100, step: 0.1, label: 'Scale X' },\n { type: 'number', key: 'spSY', min: 0.01, max: 100, step: 0.1, label: 'Scale Y' },\n { type: 'number', key: 'spSZ', min: 0.01, max: 100, step: 0.1, label: 'Scale Z' },\n ],\n defaultMetaFields: [\n { type: 'toggle', key: 'spatialGridVisible', label: 'Show Grid', default: true },\n ],\n },\n media: {\n key: 'media',\n label: 'Media',\n icon: 'disc-3',\n description: 'Media player with synced listening and playlists',\n core: false,\n plugin: 'media',\n supportsChildren: true,\n childLabel: 'Track',\n defaultDepth: -1,\n metaSchema: [\n { type: 'tags', key: 'tags', label: 'Tags' },\n ],\n defaultMetaFields: [\n { type: 'select', key: 'mediaRepeat', options: ['off', 'all', 'one'], label: 'Repeat' },\n { type: 'toggle', key: 'mediaShuffle', label: 'Shuffle' },\n ],\n },\n coder: {\n key: 'coder',\n label: 'Coder',\n icon: 'code-2',\n description: 'Collaborative multi-file coding environment',\n core: false,\n plugin: 'coder',\n supportsChildren: true,\n childLabel: 'File',\n defaultDepth: -1,\n metaSchema: [\n { type: 'select', key: 'fileType', options: ['vue', 'ts', 'js', 'css', 'json', 'folder'], label: 'Type' },\n { type: 'toggle', key: 'entry', label: 'Entry Point' },\n ],\n },\n}\n\nexport const TYPE_ALIASES: Record<string, string> = {\n desktop: 'dashboard',\n}\n\nexport function resolvePageType(key: string | undefined): PageTypeInfo | undefined {\n if (!key) return undefined\n const resolved = TYPE_ALIASES[key] ?? key\n return PAGE_TYPES[resolved]\n}\n","/**\n * page-types / type-info commands: enumerate Abracadabra page types and their\n * metadata schemas. Works without a server connection — the catalog is static.\n */\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { printJson } from '../output.ts'\nimport { PAGE_TYPES, TYPE_ALIASES, resolvePageType } from '../converters/page-types.ts'\nimport type { PageTypeInfo, PageTypeMetaField } from '../converters/page-types.ts'\n\nfunction describeField(f: PageTypeMetaField): string {\n const bits: string[] = []\n bits.push(f.type as string)\n if (f.key) bits.push(`key=${f.key}`)\n if (f.latKey) bits.push(`latKey=${f.latKey},lngKey=${f.lngKey}`)\n if (f.startKey) bits.push(`startKey=${f.startKey},endKey=${f.endKey}${f.allDayKey ? `,allDayKey=${f.allDayKey}` : ''}`)\n if (f.options) bits.push(`options=[${f.options.join(', ')}]`)\n if (f.presets) bits.push(`presets=${f.presets.length}`)\n if (typeof f.min === 'number' || typeof f.max === 'number') bits.push(`range=${f.min ?? '?'}..${f.max ?? '?'}`)\n if (f.step) bits.push(`step=${f.step}`)\n if (f.unit) bits.push(`unit=${f.unit}`)\n if (f.default !== undefined) bits.push(`default=${f.default}`)\n return bits.join(' ')\n}\n\nregisterCommand({\n name: 'page-types',\n aliases: ['types', 'doctypes'],\n description: 'List Abracadabra page types and their metadata schemas.',\n usage: 'page-types [key=<type>] [--format=json]',\n async run(_conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n const key = args.params['key'] || args.params['type'] || args.positional[0]\n const asJson = args.flags.has('json') || args.params['format'] === 'json'\n\n if (key) {\n const info = resolvePageType(key)\n if (!info) {\n return `Unknown page type \"${key}\". Run 'abracadabra page-types' to list all.`\n }\n if (asJson) return printJson(info)\n\n const lines: string[] = [\n `${info.label} (${info.key})${info.core ? '' : ` [plugin: ${info.plugin}]`}`,\n info.description ? ` ${info.description}` : '',\n ` icon: ${info.icon}`,\n ` supportsChildren: ${info.supportsChildren}`,\n ]\n if (info.childLabel) lines.push(` childLabel: ${info.childLabel}`)\n if (info.grandchildLabel) lines.push(` grandchildLabel: ${info.grandchildLabel}`)\n if (info.defaultDepth !== undefined) lines.push(` defaultDepth: ${info.defaultDepth === -1 ? 'unlimited' : info.defaultDepth}`)\n\n if (info.metaSchema?.length) {\n lines.push('', ` metaSchema (applies to descendants):`)\n for (const f of info.metaSchema) lines.push(` - ${describeField(f)}${f.label ? ` \"${f.label}\"` : ''}`)\n }\n if (info.defaultMetaFields?.length) {\n lines.push('', ` defaultMetaFields (renderer config on this doc):`)\n for (const f of info.defaultMetaFields) lines.push(` - ${describeField(f)}${f.label ? ` \"${f.label}\"` : ''}`)\n }\n return lines.filter(Boolean).join('\\n')\n }\n\n // List all\n const types = Object.values(PAGE_TYPES) as PageTypeInfo[]\n if (asJson) return printJson({ types, aliases: TYPE_ALIASES })\n\n const coreTypes = types.filter((t) => t.core)\n const pluginTypes = types.filter((t) => !t.core)\n\n const lines: string[] = ['Core page types:']\n for (const t of coreTypes) {\n const depth = t.defaultDepth === -1 ? '∞' : (t.grandchildLabel ? '2' : (t.supportsChildren ? '1' : '0'))\n const nesting = [t.childLabel, t.grandchildLabel].filter(Boolean).join(' → ')\n lines.push(` ${t.key.padEnd(12)}${(nesting || '—').padEnd(28)}depth=${depth}`)\n }\n lines.push('', 'Plugin page types (require plugin):')\n for (const t of pluginTypes) {\n const depth = t.defaultDepth === -1 ? '∞' : (t.grandchildLabel ? '2' : (t.supportsChildren ? '1' : '0'))\n const nesting = [t.childLabel, t.grandchildLabel].filter(Boolean).join(' → ')\n lines.push(` ${t.key.padEnd(12)}${(nesting || '—').padEnd(28)}depth=${depth} [plugin: ${t.plugin}]`)\n }\n lines.push('', 'Aliases:')\n for (const [from, to] of Object.entries(TYPE_ALIASES)) {\n lines.push(` ${from} → ${to}`)\n }\n lines.push('', `Run 'abracadabra page-types <key>' for field-level detail.`)\n return lines.join('\\n')\n },\n})\n","/**\n * Rate-limited wrapper around wtf_wikipedia + wtf-plugin-api.\n *\n * Responsibilities:\n * - Throttle requests to respect Wikimedia API etiquette\n * - Cache parsed Documents by canonical title\n * - Resolve redirects so callers always see the redirect target\n * - Expose getCategoryPages via wtf-plugin-api\n */\n// @ts-ignore — wtf_wikipedia ships its own types but they are imprecise; we\n// cast Link/Section APIs as needed below.\nimport wtf from 'wtf_wikipedia'\n// @ts-ignore — wtf-plugin-api is JS-only with no types; treat as opaque.\nimport wtfApiPlugin from 'wtf-plugin-api'\n\n// Augment wtf at module load so getCategoryPages becomes available.\nlet pluginExtended = false\nfunction ensurePlugin(): void {\n if (pluginExtended) return\n // @ts-ignore — extend is dynamically attached to the wtf default export.\n wtf.extend(wtfApiPlugin)\n pluginExtended = true\n}\n\nexport interface WikipediaClientConfig {\n lang: string\n domain?: string\n userAgent: string\n /** Max requests per second. */\n rate: number\n}\n\ninterface FetchOpts {\n lang?: string\n domain?: string\n 'Api-User-Agent'?: string\n follow_redirects?: boolean\n}\n\n/** A token-bucket-ish throttle: at most `rate` calls per second, FIFO. */\nclass RateLimiter {\n private lastTickMs = 0\n constructor(private intervalMs: number) {}\n\n async wait(): Promise<void> {\n const now = Date.now()\n const earliest = this.lastTickMs + this.intervalMs\n if (now < earliest) {\n await new Promise((r) => setTimeout(r, earliest - now))\n }\n this.lastTickMs = Math.max(now, earliest)\n }\n}\n\nexport class WikipediaClient {\n private cache = new Map<string, any>()\n private redirects = new Map<string, string>()\n private limiter: RateLimiter\n private fetchOpts: FetchOpts\n\n constructor(private config: WikipediaClientConfig) {\n ensurePlugin()\n this.limiter = new RateLimiter(Math.max(50, Math.floor(1000 / Math.max(0.1, config.rate))))\n this.fetchOpts = {\n lang: config.lang,\n 'Api-User-Agent': config.userAgent,\n follow_redirects: true,\n }\n if (config.domain) this.fetchOpts.domain = config.domain\n }\n\n /**\n * Fetch and parse a Wikipedia article.\n * - Returns the cached Document if we've seen this title before.\n * - Follows redirects and caches under both source and target titles.\n * - Returns null when the page does not exist.\n */\n async fetchArticle(rawTitle: string): Promise<any | null> {\n const title = canonicalTitle(rawTitle)\n if (this.cache.has(title)) return this.cache.get(title)\n if (this.redirects.has(title)) {\n const target = this.redirects.get(title)!\n return this.cache.get(target) ?? null\n }\n\n await this.limiter.wait()\n let doc: any\n try {\n doc = await (wtf as any).fetch(title, this.fetchOpts)\n } catch (err: any) {\n throw new Error(`Wikipedia fetch failed for \"${title}\": ${err?.message ?? err}`)\n }\n if (!doc) return null\n\n // wtf usually follows redirects automatically when follow_redirects=true,\n // but defensively handle the case where it surfaces a redirect doc.\n if (typeof doc.isRedirect === 'function' && doc.isRedirect()) {\n const target = doc.redirectTo?.()?.page\n if (typeof target === 'string') {\n this.redirects.set(title, canonicalTitle(target))\n const inner = await this.fetchArticle(target)\n return inner\n }\n }\n\n const resolvedTitle = canonicalTitle(doc.title?.() ?? title)\n this.cache.set(resolvedTitle, doc)\n if (resolvedTitle !== title) this.redirects.set(title, resolvedTitle)\n return doc\n }\n\n /**\n * Fetch the member pages of a category (and optionally sub-categories).\n * @param category Category title (with or without \"Category:\" prefix).\n * @param recursive Whether to traverse sub-categories.\n * @param maxDepth Recursion depth when recursive=true.\n */\n async fetchCategoryPages(\n category: string,\n recursive: boolean,\n maxDepth: number,\n ): Promise<Array<{ title: string; type: 'page' | 'subcat' }>> {\n await this.limiter.wait()\n const opts: Record<string, unknown> = {\n lang: this.config.lang,\n 'Api-User-Agent': this.config.userAgent,\n recursive,\n maxDepth,\n }\n if (this.config.domain) opts.domain = this.config.domain\n // @ts-ignore — getCategoryPages is attached at runtime via wtf.extend.\n const list: any[] = await wtf.getCategoryPages(category, opts)\n return (list ?? []).map((m) => ({\n title: canonicalTitle(m.title),\n type: m.type === 'subcat' ? 'subcat' : 'page',\n }))\n }\n}\n\n/** Normalize a Wikipedia title — trim, collapse spaces, strip leading/trailing colons. */\nexport function canonicalTitle(s: string): string {\n return (s ?? '').toString().replace(/_/g, ' ').replace(/\\s+/g, ' ').trim()\n}\n\n/** Detect a category-namespaced title. */\nconst CATEGORY_PREFIX = /^(Category|Catégorie|Kategorie|Categoría|Categoria|Categorie|Kategoria):/i\nexport function isCategoryTitle(title: string): boolean {\n return CATEGORY_PREFIX.test(title)\n}\n\n/** Strip the \"Category:\" prefix for display. */\nexport function stripCategoryPrefix(title: string): string {\n return title.replace(CATEGORY_PREFIX, '').trim()\n}\n","/**\n * Snapshot a wtf_wikipedia Document into a plain-data shape that's easy to\n * work with downstream. No BFS / no plan-building here — just a pure read\n * of one parsed page.\n */\nimport type { ExtractedArticle, ExtractedSection } from './types.ts'\nimport { canonicalTitle, isCategoryTitle, stripCategoryPrefix } from './wikipedia.ts'\n\nexport { canonicalTitle, isCategoryTitle, stripCategoryPrefix }\n\nexport function snapshotArticle(doc: any, title: string): ExtractedArticle {\n return {\n title,\n linkTitles: collectLinkTitles(doc),\n categories: collectCategories(doc),\n sections: snapshotSections(doc.sections?.() ?? []),\n infobox: snapshotInfobox(doc.infobox?.()),\n lead: leadParagraph(doc),\n url: typeof doc.url === 'function' ? doc.url() : null,\n }\n}\n\nexport function prettyCategoryLabel(catTitle: string): string {\n return stripCategoryPrefix(catTitle)\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Link / category extraction\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction collectLinkTitles(doc: any): string[] {\n const links = doc.links?.() ?? []\n const out = new Set<string>()\n for (const l of links) {\n if (!l) continue\n const page = typeof l.page === 'function' ? l.page() : null\n if (typeof page !== 'string' || page.length === 0) continue\n if (isCategoryTitle(page)) continue\n out.add(canonicalTitle(page))\n }\n return [...out]\n}\n\nfunction collectCategories(doc: any): string[] {\n const out: string[] = []\n for (const c of (doc.categories?.() as string[] | undefined) ?? []) {\n const norm = canonicalTitle(c)\n if (norm) out.push(norm)\n }\n return out\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Sections — flatten wtf's parent-child references into a real tree\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction snapshotSections(rawSections: any[]): ExtractedSection[] {\n const all = rawSections.map((s) => ({\n raw: s,\n title: s.title?.() || '',\n parentRef: typeof s.parent === 'function' ? s.parent() : null,\n children: [] as ExtractedSection[],\n }))\n\n const byRaw = new Map<any, (typeof all)[number]>()\n for (const s of all) byRaw.set(s.raw, s)\n\n const roots: (typeof all)[number][] = []\n for (const s of all) {\n if (s.parentRef && byRaw.has(s.parentRef)) {\n byRaw.get(s.parentRef)!.children.push(materialize(s))\n } else {\n roots.push(s)\n }\n }\n return roots.map(materialize)\n}\n\nfunction materialize(node: {\n raw: any\n title: string\n children: ExtractedSection[]\n}): ExtractedSection {\n const lists = node.raw.lists?.() ?? []\n const paragraphs = node.raw.paragraphs?.() ?? []\n\n let listLength = 0\n for (const l of lists) {\n const lines = l.lines?.() ?? []\n listLength += lines.length\n }\n const isList =\n lists.length > 0 && (paragraphs.length === 0 || listLength >= paragraphs.length * 2)\n\n const bodyParts: string[] = []\n for (const p of paragraphs) {\n const md = paragraphMarkdown(p)\n if (md) bodyParts.push(md)\n }\n for (const l of lists) {\n const lines = (l.lines?.() ?? []) as any[]\n for (const line of lines) {\n const text = lineText(line)\n if (text) bodyParts.push(`- ${text}`)\n }\n }\n\n return {\n title: node.title,\n body: bodyParts.join('\\n\\n'),\n isList,\n listLength,\n children: node.children,\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Infobox\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction snapshotInfobox(box: any | null | undefined): Array<{ key: string; value: string }> | undefined {\n if (!box) return undefined\n const data = typeof box.json === 'function' ? box.json() : null\n if (!data || typeof data !== 'object') return undefined\n const rows: Array<{ key: string; value: string }> = []\n for (const [key, val] of Object.entries(data)) {\n const value = stringifyInfoboxValue(val)\n if (!value) continue\n rows.push({ key: humanKey(key), value })\n }\n return rows.length > 0 ? rows : undefined\n}\n\nfunction stringifyInfoboxValue(val: unknown): string {\n if (val == null) return ''\n if (typeof val === 'string') return val\n if (typeof val === 'number' || typeof val === 'boolean') return String(val)\n if (Array.isArray(val)) {\n return val.map(stringifyInfoboxValue).filter(Boolean).join(', ')\n }\n if (typeof val === 'object') {\n const o = val as Record<string, unknown>\n if (typeof o.text === 'string') return o.text\n if (typeof o.number === 'number') return String(o.number)\n }\n return ''\n}\n\nfunction humanKey(k: string): string {\n return k.replace(/_/g, ' ').replace(/^./, (m) => m.toUpperCase())\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Markdown rendering\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction leadParagraph(doc: any): string {\n const paras = doc.paragraphs?.() ?? []\n const first = paras[0]\n if (!first) return ''\n return paragraphMarkdown(first)\n}\n\n/**\n * Render a paragraph as markdown, replacing internal links with `[[Title]]`.\n * The streaming orchestrator's link rewriter later swaps `[[Title]]` →\n * `[[docId|label]]` once IDs are known.\n */\nfunction paragraphMarkdown(paragraph: any): string {\n const sentences = paragraph.sentences?.() ?? []\n const out: string[] = []\n for (const s of sentences) {\n out.push(sentenceWithWikilinks(s))\n }\n return out.join(' ').trim()\n}\n\nfunction sentenceWithWikilinks(sentence: any): string {\n const text: string = (sentence.text?.() ?? '').toString()\n const links = sentence.links?.() ?? []\n if (links.length === 0) return text\n\n let result = text\n const replacements = links\n .map((l: any) => {\n const page = typeof l.page === 'function' ? l.page() : null\n const display = typeof l.text === 'function' ? l.text() : null\n if (typeof page !== 'string' || page.length === 0) return null\n if (isCategoryTitle(page)) return null\n const shown = (display && display.length > 0 ? display : page) as string\n return { page: canonicalTitle(page), shown }\n })\n .filter((x: any): x is { page: string; shown: string } => x !== null)\n .sort((a: any, b: any) => b.shown.length - a.shown.length)\n\n for (const { page, shown } of replacements) {\n if (!result.includes(shown)) continue\n const replacement = shown === page ? `[[${page}]]` : `[[${page}|${shown}]]`\n result = result.replace(shown, replacement)\n }\n return result\n}\n\nfunction lineText(line: any): string {\n if (!line) return ''\n if (typeof line === 'string') return line\n if (typeof line.text === 'string') return line.text\n if (typeof line.text === 'function') return line.text()\n return ''\n}\n","/**\n * Body rendering + page-type decisions for the streaming orchestrator.\n *\n * All rendering is title-driven: bodies are rendered with `[[Title]]`\n * placeholders, and `rewriteLinks` rewrites them to `[[docId|label]]`\n * using the live title→docId map at write time.\n */\nimport type { ExtractedArticle, ExtractedSection } from './types.ts'\n\nexport const ICONS = {\n graph: 'git-fork',\n article: 'book-open',\n category: 'tag',\n infobox: 'info',\n outline: 'list',\n gallery: 'images',\n section: 'pilcrow',\n categories: 'tags',\n} as const\n\n/** Decide a page type for a section based on its shape. */\nexport function pickSectionType(section: ExtractedSection): { type: string; icon: string } {\n if (section.children.length > 0) return { type: 'outline', icon: ICONS.outline }\n if (section.isList && section.listLength >= 5) return { type: 'outline', icon: ICONS.outline }\n return { type: 'doc', icon: ICONS.section }\n}\n\n/** Render the lead paragraph as the article-doc body. */\nexport function renderArticleLead(article: ExtractedArticle): string {\n return article.lead ?? ''\n}\n\n/** Render the article as a single doc, sections + infobox inlined. */\nexport function renderArticleSingleDoc(article: ExtractedArticle): string {\n const parts: string[] = []\n if (article.lead) parts.push(article.lead)\n if (article.infobox && article.infobox.length > 0) {\n parts.push('## Infobox', renderInfoboxBody(article.infobox))\n }\n for (const section of article.sections) {\n parts.push(...renderSectionInline(section, 2))\n }\n return parts.join('\\n\\n')\n}\n\nfunction renderSectionInline(section: ExtractedSection, level: number): string[] {\n const out: string[] = []\n const prefix = '#'.repeat(Math.min(6, level))\n if (section.title) out.push(`${prefix} ${section.title}`)\n if (section.body.trim()) out.push(section.body)\n for (const child of section.children) {\n out.push(...renderSectionInline(child, level + 1))\n }\n return out\n}\n\nexport function renderInfoboxBody(rows: Array<{ key: string; value: string }>): string {\n return rows.map((r) => `- **${r.key}:** ${r.value}`).join('\\n')\n}\n\nexport function renderCategoryBody(members: string[], subcategories: string[]): string {\n const parts: string[] = []\n if (members.length > 0) {\n parts.push('## Pages')\n parts.push(members.map((m) => `- [[${m}]]`).join('\\n'))\n }\n if (subcategories.length > 0) {\n parts.push('## Sub-categories')\n parts.push(subcategories.map((s) => `- ${s}`).join('\\n'))\n }\n return parts.join('\\n\\n')\n}\n\n/**\n * Replace `[[Title]]` / `[[Title|Alias]]` in markdown with\n * `[[docId|label]]` using the title→docId map. Unresolved titles fall\n * back to plain text (their alias or original title).\n */\nexport function rewriteLinks(\n markdown: string,\n titleToDocId: Map<string, string>,\n): string {\n const re = /\\[\\[([^\\]|]+?)(?:\\|([^\\]]+?))?\\]\\]/g\n return markdown.replace(re, (_match, target: string, alias?: string) => {\n const title = target.trim()\n const docId = titleToDocId.get(title)\n const display = (alias && alias.trim().length > 0 ? alias : title).trim()\n if (!docId) return display\n return `[[${docId}|${display}]]`\n })\n}\n","/**\n * Open a DocumentManager session for the wiki command, mirroring the\n * auth/register flow that CLIConnection uses but using the modern public API.\n *\n * Reuses the CLI's Ed25519 keypair handling (loadOrCreateKeypair, signChallenge)\n * so the wiki command authenticates with the same identity as every other\n * subcommand.\n */\nimport { DocumentManager } from '@abraca/dabra'\nimport { loadOrCreateKeypair, signChallenge } from '../../crypto.ts'\n\nexport interface OpenSessionConfig {\n url: string\n name?: string\n color?: string\n inviteCode?: string\n keyFile?: string\n /** Suppress informational stderr logging. */\n quiet?: boolean\n}\n\nexport interface OpenSessionResult {\n dm: DocumentManager\n /** Active root doc id (the entry-point space). */\n rootDocId: string\n}\n\nexport async function openSession(config: OpenSessionConfig): Promise<OpenSessionResult> {\n const keypair = await loadOrCreateKeypair(config.keyFile)\n const sign = (challenge: string) => Promise.resolve(signChallenge(challenge, keypair.privateKey))\n\n const dm = new DocumentManager({\n url: config.url,\n name: config.name ?? 'Wiki Extractor',\n color: config.color,\n quiet: config.quiet,\n })\n\n // Authenticate first; register on first run.\n try {\n await dm.client.loginWithKey(keypair.publicKeyB64, sign)\n } catch (err: any) {\n const status = err?.status ?? err?.response?.status\n if (status === 404 || status === 422) {\n if (!config.quiet) {\n console.error('[abracadabra] Key not registered, creating new account...')\n }\n await dm.client.registerWithKey({\n publicKey: keypair.publicKeyB64,\n username: (config.name ?? 'wiki-extractor').replace(/\\s+/g, '-').toLowerCase(),\n displayName: config.name ?? 'Wiki Extractor',\n deviceName: 'CLI Wiki',\n inviteCode: config.inviteCode,\n })\n await dm.client.loginWithKey(keypair.publicKeyB64, sign)\n } else {\n throw err\n }\n }\n\n await dm.connect()\n\n const rootDocId = dm.rootDocId\n if (!rootDocId) {\n throw new Error('Connected but no rootDocId — server has no spaces.')\n }\n\n return { dm, rootDocId }\n}\n","/**\n * `abracadabra wiki <title>` — fetch Wikipedia articles and seed them into\n * the active space as a graph of docs.\n *\n * Streaming flow (no buffering): every newly-discovered title becomes a\n * shell doc immediately (visible in the dashboard right away), then bodies\n * are filled in one fetch at a time. The user sees the tree skeleton appear\n * before the first body is written.\n *\n * The command authenticates separately from the parent CLI (it's listed in\n * NO_CONNECT_COMMANDS in src/index.ts) so the parent harness doesn't open a\n * second connection. We use the modern DocumentManager API from @abraca/dabra.\n */\nimport type { DocumentManager } from '@abraca/dabra'\nimport { registerCommand } from '../../command.ts'\nimport type { CLIConnection } from '../../connection.ts'\nimport type { ParsedArgs } from '../../parser.ts'\nimport { WikipediaClient } from './wikipedia.ts'\nimport { snapshotArticle, canonicalTitle, prettyCategoryLabel } from './snapshot.ts'\nimport {\n ICONS,\n pickSectionType,\n renderArticleLead,\n renderArticleSingleDoc,\n renderInfoboxBody,\n renderCategoryBody,\n rewriteLinks,\n} from './render.ts'\nimport { openSession } from './connect.ts'\nimport type { WikiOptions, ExtractMode, ExtractedArticle, ExtractedSection } from './types.ts'\n\nregisterCommand({\n name: 'wiki',\n aliases: ['wikipedia'],\n description: 'Fetch Wikipedia articles into a graph of docs (streaming).',\n usage: [\n 'wiki \"<Article Title>\"',\n ' mode=single|split single doc per article OR split into sections+infobox [split]',\n ' depth=<n> follow internal links to depth N [1]',\n ' category-depth=<n> recurse into sub-categories [1]',\n ' lang=<code> wiki language [en]',\n ' domain=<host> 3rd-party MediaWiki host (overrides lang)',\n ' parent=<docId> parent doc for the new graph [active space root]',\n ' user-agent=<str> Api-User-Agent header (REQUIRED by Wikimedia etiquette)',\n ' rate=<rps> max wikipedia requests per second [3]',\n ' --include-categories expand each article\\'s categories into nested graphs',\n ' --dry-run fetch only the entry article, print outline, no writes',\n ].join('\\n'),\n async run(_conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n const opts = parseOptions(args)\n if (typeof opts === 'string') return opts\n\n const log = (msg: string) => {\n if (!args.flags.has('quiet') && !args.flags.has('q')) {\n console.error(`[wiki] ${msg}`)\n }\n }\n\n const wp = new WikipediaClient({\n lang: opts.lang,\n domain: opts.domain,\n userAgent: opts.userAgent,\n rate: opts.rate,\n })\n\n if (opts.dryRun) {\n // Dry-run: fetch only the entry, print its outline, no server.\n log(`fetch ${opts.title}`)\n const doc = await wp.fetchArticle(opts.title)\n if (!doc) return `Article not found: \"${opts.title}\"`\n const snap = snapshotArticle(doc, canonicalTitle(doc.title?.() ?? opts.title))\n return [\n `Entry: ${snap.title}`,\n `URL: ${snap.url ?? '(none)'}`,\n `Internal links: ${snap.linkTitles.length}`,\n `Categories: ${snap.categories.length}`,\n `Sections: ${snap.sections.length}`,\n `Has infobox: ${snap.infobox && snap.infobox.length > 0 ? 'yes' : 'no'}`,\n '',\n '── Sections ──',\n printSections(snap.sections, ''),\n ].join('\\n')\n }\n\n // ── Connect ──────────────────────────────────────────────────────────\n // process.env access uses bracket notation to satisfy noUncheckedIndexedAccess.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const env = (globalThis as any).process?.env ?? {}\n const url = env['ABRA_URL']\n if (!url) {\n return 'ABRA_URL is required to write to the server. Set it or pass --dry-run.'\n }\n const { dm } = await openSession({\n url,\n name: env['ABRA_NAME'],\n color: env['ABRA_COLOR'],\n inviteCode: env['ABRA_INVITE_CODE'],\n keyFile: env['ABRA_KEY_FILE'],\n quiet: args.flags.has('quiet') || args.flags.has('q'),\n })\n\n try {\n const result = await runStreaming(dm, wp, opts, log)\n return [\n `Done. Created ${result.articleCount} articles${\n result.categoryCount > 0 ? ` + ${result.categoryCount} categories` : ''\n }.`,\n `Root: ${result.rootDocId}`,\n ].join('\\n')\n } finally {\n await dm.destroy().catch(() => {})\n }\n },\n})\n\n// ─────────────────────────────────────────────────────────────────────────\n// Streaming orchestrator\n// ─────────────────────────────────────────────────────────────────────────\n\ninterface StreamResult {\n rootDocId: string\n articleCount: number\n categoryCount: number\n}\n\nasync function runStreaming(\n dm: DocumentManager,\n wp: WikipediaClient,\n opts: WikiOptions,\n log: (msg: string) => void,\n): Promise<StreamResult> {\n // Title → docId map. Drives [[Title]] → [[docId|label]] rewriting at write time.\n const titleToDocId = new Map<string, string>()\n // Snapshots of articles we've already fetched (avoid re-fetching).\n const fetched = new Map<string, ExtractedArticle>()\n // Articles whose section/infobox children have been created (split mode).\n const childrenCreated = new Set<string>()\n // Categories whose shells have been created.\n const categoryToDocId = new Map<string, string>()\n let categoriesContainerId: string | null = null\n\n // ── Fetch entry first; we need its title to label the root graph ─────\n log(`fetch ${opts.title}`)\n const entryDoc = await wp.fetchArticle(opts.title)\n if (!entryDoc) {\n throw new Error(`Article not found: \"${opts.title}\"`)\n }\n const entryTitle = canonicalTitle(entryDoc.title?.() ?? opts.title)\n const entrySnap = snapshotArticle(entryDoc, entryTitle)\n fetched.set(entryTitle, entrySnap)\n\n // ── Step 1: create root graph doc (visible immediately) ──────────────\n const rootEntry = dm.tree.create({\n parentId: opts.parentDocId ?? null,\n label: entryTitle,\n type: 'graph',\n meta: { icon: ICONS.graph },\n })\n log(`+ ${rootEntry.id.slice(0, 8)}… ${entryTitle} (graph)`)\n\n // ── Step 2: create the entry article shell ───────────────────────────\n const entryArticleId = createArticleShell(dm, entrySnap, rootEntry.id, log)\n titleToDocId.set(entryTitle, entryArticleId)\n\n // Queue of (title, depth) to process. Each entry is guaranteed to have\n // a shell doc already in titleToDocId.\n const queue: Array<{ title: string; depth: number }> = [{ title: entryTitle, depth: 0 }]\n let articleCount = 0\n\n // ── Step 3: streaming process ───────────────────────────────────────\n while (queue.length > 0) {\n const { title, depth } = queue.shift()!\n const articleDocId = titleToDocId.get(title)!\n\n // Ensure we've fetched this article.\n let snap = fetched.get(title)\n if (!snap) {\n log(`fetch [d${depth}] ${title}`)\n try {\n const doc = await wp.fetchArticle(title)\n if (!doc) {\n log(` not found — leaving stub`)\n continue\n }\n snap = snapshotArticle(doc, canonicalTitle(doc.title?.() ?? title))\n fetched.set(title, snap)\n } catch (err: any) {\n log(`! fetch failed: ${err?.message ?? err}`)\n continue\n }\n }\n\n // Create this article's section/infobox children (split mode only,\n // and only once per article).\n if (opts.mode === 'split' && !childrenCreated.has(title)) {\n createArticleChildren(dm, snap, articleDocId, log)\n childrenCreated.add(title)\n }\n\n // Discover new linked titles and pre-allocate shells immediately.\n if (depth < opts.depth) {\n for (const linkTitle of snap.linkTitles) {\n if (titleToDocId.has(linkTitle)) continue\n const shell = dm.tree.create({\n parentId: rootEntry.id,\n label: linkTitle,\n type: 'doc',\n meta: { icon: ICONS.article },\n })\n titleToDocId.set(linkTitle, shell.id)\n queue.push({ title: linkTitle, depth: depth + 1 })\n log(`+ ${shell.id.slice(0, 8)}… ${linkTitle} (doc, shell)`)\n }\n }\n\n // Pre-allocate category shells when first discovered.\n if (opts.includeCategories && snap.categories.length > 0) {\n if (!categoriesContainerId) {\n const c = dm.tree.create({\n parentId: rootEntry.id,\n label: 'Categories',\n type: 'graph',\n meta: { icon: ICONS.categories },\n })\n categoriesContainerId = c.id\n log(`+ ${c.id.slice(0, 8)}… Categories (graph)`)\n }\n for (const catTitle of snap.categories) {\n if (categoryToDocId.has(catTitle)) continue\n const cat = dm.tree.create({\n parentId: categoriesContainerId,\n label: prettyCategoryLabel(catTitle),\n type: 'graph',\n meta: { icon: ICONS.category },\n })\n categoryToDocId.set(catTitle, cat.id)\n log(`+ ${cat.id.slice(0, 8)}… ${prettyCategoryLabel(catTitle)} (graph, cat)`)\n }\n }\n\n // Write this article's body NOW (links resolve to whatever shells we\n // have allocated so far — that's all of this article's links since we\n // just allocated them above).\n const body =\n opts.mode === 'split' ? renderArticleLead(snap) : renderArticleSingleDoc(snap)\n if (body.trim().length > 0) {\n const rewritten = rewriteLinks(body, titleToDocId)\n try {\n await dm.content.write(articleDocId, rewritten)\n log(`✓ body ${title}`)\n } catch (err: any) {\n log(`! body write failed for ${title}: ${err?.message ?? err}`)\n }\n }\n\n // In split mode, also write each section/infobox doc body.\n if (opts.mode === 'split') {\n await writeChildrenBodies(dm, snap, articleDocId, titleToDocId, log)\n }\n\n articleCount++\n }\n\n // ── Step 4: fill in category bodies ─────────────────────────────────\n let categoryCount = 0\n if (opts.includeCategories && categoryToDocId.size > 0) {\n for (const [catTitle, catDocId] of categoryToDocId) {\n log(`category ${catTitle}`)\n try {\n const members = await wp.fetchCategoryPages(\n catTitle,\n opts.categoryDepth > 0,\n Math.max(0, opts.categoryDepth),\n )\n const memberArticles: string[] = []\n const subcats: string[] = []\n for (const m of members) {\n if (m.type === 'subcat') subcats.push(prettyCategoryLabel(m.title))\n else memberArticles.push(m.title)\n }\n const body = renderCategoryBody(memberArticles, subcats)\n const rewritten = rewriteLinks(body, titleToDocId)\n if (rewritten.trim().length > 0) {\n await dm.content.write(catDocId, rewritten)\n log(`✓ body category ${catTitle}`)\n }\n categoryCount++\n } catch (err: any) {\n log(`! category ${catTitle}: ${err?.message ?? err}`)\n }\n }\n }\n\n return { rootDocId: rootEntry.id, articleCount, categoryCount }\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Shell + body helpers\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction createArticleShell(\n dm: DocumentManager,\n article: ExtractedArticle,\n parentId: string,\n log: (msg: string) => void,\n): string {\n const meta: Record<string, unknown> = { icon: ICONS.article }\n if (article.url) meta.url = article.url\n const entry = dm.tree.create({\n parentId,\n label: article.title,\n type: 'doc',\n meta,\n })\n log(`+ ${entry.id.slice(0, 8)}… ${article.title} (doc)`)\n return entry.id\n}\n\n/**\n * Create section + infobox child docs for a split-mode article. Returns nothing\n * — children get bodies written later in writeChildrenBodies.\n */\nfunction createArticleChildren(\n dm: DocumentManager,\n article: ExtractedArticle,\n articleDocId: string,\n log: (msg: string) => void,\n): void {\n if (article.infobox && article.infobox.length > 0) {\n const ib = dm.tree.create({\n parentId: articleDocId,\n label: 'Infobox',\n type: 'outline',\n meta: { icon: ICONS.infobox },\n })\n log(` + ${ib.id.slice(0, 8)}… Infobox (outline)`)\n // We attach the docId to the article object so writeChildrenBodies\n // can find it without a second tree query.\n ;(article as any)._infoboxDocId = ib.id\n }\n for (const section of article.sections) {\n createSectionShell(dm, section, articleDocId, log)\n }\n}\n\nfunction createSectionShell(\n dm: DocumentManager,\n section: ExtractedSection,\n parentDocId: string,\n log: (msg: string) => void,\n): void {\n const hasChildren = section.children.length > 0\n if (!section.body.trim() && !hasChildren) return\n const { type, icon } = pickSectionType(section)\n const entry = dm.tree.create({\n parentId: parentDocId,\n label: section.title || 'Untitled section',\n type,\n meta: { icon },\n })\n log(` + ${entry.id.slice(0, 8)}… ${entry.label} (${type})`)\n ;(section as any)._docId = entry.id\n for (const child of section.children) {\n createSectionShell(dm, child, entry.id, log)\n }\n}\n\nasync function writeChildrenBodies(\n dm: DocumentManager,\n article: ExtractedArticle,\n _articleDocId: string,\n titleToDocId: Map<string, string>,\n log: (msg: string) => void,\n): Promise<void> {\n const infoboxDocId = (article as any)._infoboxDocId as string | undefined\n if (infoboxDocId && article.infobox && article.infobox.length > 0) {\n try {\n await dm.content.write(infoboxDocId, renderInfoboxBody(article.infobox))\n } catch (err: any) {\n log(`! infobox body write failed: ${err?.message ?? err}`)\n }\n }\n for (const section of article.sections) {\n await writeSectionBody(dm, section, titleToDocId, log)\n }\n}\n\nasync function writeSectionBody(\n dm: DocumentManager,\n section: ExtractedSection,\n titleToDocId: Map<string, string>,\n log: (msg: string) => void,\n): Promise<void> {\n const docId = (section as any)._docId as string | undefined\n if (docId && section.body.trim().length > 0) {\n try {\n await dm.content.write(docId, rewriteLinks(section.body, titleToDocId))\n } catch (err: any) {\n log(`! section body write failed for ${section.title}: ${err?.message ?? err}`)\n }\n }\n for (const child of section.children) {\n await writeSectionBody(dm, child, titleToDocId, log)\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Argument parsing + dry-run printing\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction parseOptions(args: ParsedArgs): WikiOptions | string {\n const title = args.positional[0]?.trim() || args.params['title']\n if (!title) return 'Missing required positional argument: <title>. Example: abracadabra wiki \"Toronto Raptors\"'\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const env = (globalThis as any).process?.env ?? {}\n const userAgent = args.params['user-agent'] || args.params['userAgent'] || env['ABRA_WIKI_USER_AGENT']\n if (!userAgent) {\n return [\n 'Missing required parameter: user-agent=\"your-name (you@example.com)\"',\n '(Wikimedia etiquette requires an Api-User-Agent header. Pass user-agent=... or set ABRA_WIKI_USER_AGENT.)',\n ].join('\\n')\n }\n\n const mode = (args.params['mode'] ?? 'split') as ExtractMode\n if (mode !== 'single' && mode !== 'split') {\n return `Invalid mode \"${mode}\". Use mode=single or mode=split.`\n }\n\n const depth = parseIntOr(args.params['depth'], 1)\n const categoryDepth = parseIntOr(args.params['category-depth'] ?? args.params['categoryDepth'], 1)\n const rate = parseFloatOr(args.params['rate'], 3)\n\n return {\n title,\n mode,\n depth,\n categoryDepth,\n includeCategories: args.flags.has('include-categories') || args.flags.has('includeCategories'),\n lang: args.params['lang'] ?? 'en',\n domain: args.params['domain'],\n parentDocId: args.params['parent'],\n userAgent,\n rate,\n dryRun: args.flags.has('dry-run') || args.flags.has('dryRun'),\n }\n}\n\nfunction parseIntOr(s: string | undefined, fallback: number): number {\n if (!s) return fallback\n const n = Number.parseInt(s, 10)\n return Number.isFinite(n) && n >= 0 ? n : fallback\n}\n\nfunction parseFloatOr(s: string | undefined, fallback: number): number {\n if (!s) return fallback\n const n = Number.parseFloat(s)\n return Number.isFinite(n) && n > 0 ? n : fallback\n}\n\nfunction printSections(sections: ExtractedSection[], indent: string): string {\n const lines: string[] = []\n for (const s of sections) {\n const hint = s.body ? ` (${s.body.length}b)` : ''\n lines.push(`${indent}- ${s.title}${hint}${s.children.length > 0 ? ` [${s.children.length} sub]` : ''}`)\n if (s.children.length > 0) {\n lines.push(printSections(s.children, indent + ' '))\n }\n }\n return lines.join('\\n')\n}\n","#!/usr/bin/env node\n/**\n * Abracadabra CLI — interact with CRDT document workspaces from the terminal.\n *\n * Usage:\n * abracadabra <command> [key=value ...] [--flags]\n *\n * Environment:\n * ABRA_URL Server URL (required)\n * ABRA_KEY_FILE Path to Ed25519 key file (~/.abracadabra/cli.key)\n * ABRA_INVITE_CODE Invite code for first-run registration\n * ABRA_NAME Display name (default: CLI User)\n * ABRA_COLOR Presence color (default: hsl(45, 90%, 55%))\n */\nimport { parseArgs } from './parser.ts'\nimport { CLIConnection } from './connection.ts'\nimport { getCommand } from './command.ts'\n\n// ── Register all commands ────────────────────────────────────────────────────\n// Side-effect imports: each module calls registerCommand() at module scope.\nimport './commands/help.ts'\nimport './commands/spaces.ts'\nimport './commands/tree.ts'\nimport './commands/documents.ts'\nimport './commands/content.ts'\nimport './commands/meta.ts'\nimport './commands/awareness.ts'\nimport './commands/files.ts'\nimport './commands/permissions.ts'\nimport './commands/page-types.ts'\nimport './commands/wiki/index.ts'\n\n// ── Commands that don't require a connection ─────────────────────────────────\n// \"wiki\" opens its own DocumentManager session via wiki/connect.ts, so the\n// parent harness should NOT pre-open a CLIConnection (which would authenticate\n// twice and hold an unused root provider).\nconst NO_CONNECT_COMMANDS = new Set([\n 'help', 'h', '?',\n 'version', 'v',\n 'page-types', 'types', 'doctypes',\n 'wiki', 'wikipedia',\n])\n\nasync function main() {\n const args = parseArgs(process.argv)\n\n // Resolve command\n const cmd = getCommand(args.command)\n if (!cmd) {\n console.error(`Unknown command: \"${args.command}\"`)\n console.error('Run \"abracadabra help\" to see all commands.')\n process.exit(1)\n }\n\n // Commands that don't need a server connection\n if (NO_CONNECT_COMMANDS.has(args.command)) {\n // Try to connect for extra info (version), but don't fail\n let conn: CLIConnection | null = null\n const url = process.env['ABRA_URL']\n if (url && args.command === 'version') {\n try {\n conn = new CLIConnection({\n url,\n name: process.env['ABRA_NAME'],\n color: process.env['ABRA_COLOR'],\n inviteCode: process.env['ABRA_INVITE_CODE'],\n keyFile: process.env['ABRA_KEY_FILE'],\n quiet: true,\n })\n await conn.connect()\n } catch {\n // Silently fall back to local-only version info\n }\n }\n\n try {\n const output = await cmd.run(conn, args)\n if (output) console.log(output)\n } finally {\n if (conn) await conn.destroy().catch(() => {})\n }\n return\n }\n\n // All other commands require ABRA_URL\n const url = process.env['ABRA_URL']\n if (!url) {\n console.error('Error: ABRA_URL environment variable is required.')\n console.error('')\n console.error('Set it to your Abracadabra server URL:')\n console.error(' export ABRA_URL=https://your-server.example.com')\n console.error('')\n console.error('Run \"abracadabra help\" for more info.')\n process.exit(1)\n }\n\n const conn = new CLIConnection({\n url,\n name: process.env['ABRA_NAME'],\n color: process.env['ABRA_COLOR'],\n inviteCode: process.env['ABRA_INVITE_CODE'],\n keyFile: process.env['ABRA_KEY_FILE'],\n quiet: args.flags.has('quiet') || args.flags.has('q'),\n })\n\n try {\n await conn.connect()\n const output = await cmd.run(conn, args)\n if (output) console.log(output)\n } catch (error: any) {\n console.error(`Error: ${error.message}`)\n if (args.flags.has('verbose')) {\n console.error(error.stack)\n }\n process.exit(1)\n } finally {\n await conn.destroy().catch(() => {})\n }\n}\n\nmain().catch((err) => {\n console.error(`Fatal: ${err.message ?? err}`)\n process.exit(1)\n})\n"],"x_google_ignoreList":[1,2,3,4],"mappings":"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"}
1
+ {"version":3,"file":"abracadabra-cli.cjs","names":["u64.split","u64.rotrSH","u64.shrSH","u64.rotrSL","u64.shrSL","u64.rotrBH","u64.rotrBL","u64.add4L","u64.add4H","u64.add5L","u64.add5H","u64.add","u64.add3L","u64.add3H","ed","AbracadabraClient","Kind","Y","AbracadabraProvider","toPlain","Y","Y","toPlain","Y","path","Y","nodePath","fs","wtfApiPlugin","wtf","DocumentManager"],"sources":["../src/parser.ts","../../../node_modules/@noble/hashes/utils.js","../../../node_modules/@noble/hashes/_md.js","../../../node_modules/@noble/hashes/_u64.js","../../../node_modules/@noble/hashes/sha2.js","../src/crypto.ts","../src/connection.ts","../src/command.ts","../src/output.ts","../src/commands/help.ts","../src/resolve.ts","../src/commands/spaces.ts","../src/commands/tree.ts","../../convert/src/markdown-to-yjs.ts","../../convert/src/yjs-to-markdown.ts","../../convert/src/spec/nodes.ts","../../convert/src/spec/marks.ts","../../convert/src/spec/universal-meta.ts","../src/commands/documents.ts","../src/commands/content.ts","../src/commands/meta.ts","../src/commands/awareness.ts","../src/commands/files.ts","../src/commands/permissions.ts","../../mcp/src/converters/page-types.ts","../src/commands/page-types.ts","../src/commands/wiki/wikipedia.ts","../src/commands/wiki/snapshot.ts","../src/commands/wiki/render.ts","../src/commands/wiki/connect.ts","../src/commands/wiki/index.ts","../src/index.ts"],"sourcesContent":["/**\n * Minimal argument parser for Abracadabra CLI.\n *\n * Syntax:\n * abracadabra [--flag] <command>[:<subcommand>] [key=value ...] [--flag2]\n * abracadabra [--flag] <command>[:<subcommand>] [key=\"value with spaces\"] [--format=json]\n */\n\nexport interface ParsedArgs {\n /** The command name, e.g. \"tree\", \"spaces:switch\", \"read\" */\n command: string\n /** Key-value parameters, e.g. { name: \"My Doc\", type: \"doc\" } */\n params: Record<string, string>\n /** Boolean flags, e.g. { total: true, verbose: true } */\n flags: Set<string>\n /** Positional arguments (non-flag, non-key=value, after the command) */\n positional: string[]\n}\n\n/**\n * Parse CLI arguments into a structured object.\n * @param argv Raw process.argv (includes node path and script path)\n */\nexport function parseArgs(argv: string[]): ParsedArgs {\n const args = argv.slice(2) // skip node + script\n\n const result: ParsedArgs = {\n command: 'help',\n params: {},\n flags: new Set(),\n positional: [],\n }\n\n let commandFound = false\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]\n\n // --flag or --key=value\n if (arg.startsWith('--')) {\n const stripped = arg.slice(2)\n const eqIdx = stripped.indexOf('=')\n if (eqIdx !== -1) {\n // --format=json style\n const key = stripped.slice(0, eqIdx)\n const value = stripped.slice(eqIdx + 1)\n result.params[key] = value\n } else {\n result.flags.add(stripped)\n }\n continue\n }\n\n // key=value pair\n const eqIdx = arg.indexOf('=')\n if (eqIdx !== -1 && eqIdx > 0) {\n const key = arg.slice(0, eqIdx)\n let value = arg.slice(eqIdx + 1)\n // Strip surrounding quotes if present\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1)\n }\n result.params[key] = value\n continue\n }\n\n // First bare word is the command\n if (!commandFound) {\n result.command = arg\n commandFound = true\n continue\n }\n\n // Subsequent bare words are positional\n result.positional.push(arg)\n }\n\n return result\n}\n","/**\n * Checks if something is Uint8Array. Be careful: nodejs Buffer will return true.\n * @param a - value to test\n * @returns `true` when the value is a Uint8Array-compatible view.\n * @example\n * Check whether a value is a Uint8Array-compatible view.\n * ```ts\n * isBytes(new Uint8Array([1, 2, 3]));\n * ```\n */\nexport function isBytes(a) {\n // Plain `instanceof Uint8Array` is too strict for some Buffer / proxy / cross-realm cases.\n // The fallback still requires a real ArrayBuffer view, so plain\n // JSON-deserialized `{ constructor: ... }` spoofing is rejected, and\n // `BYTES_PER_ELEMENT === 1` keeps the fallback on byte-oriented views.\n return (a instanceof Uint8Array ||\n (ArrayBuffer.isView(a) &&\n a.constructor.name === 'Uint8Array' &&\n 'BYTES_PER_ELEMENT' in a &&\n a.BYTES_PER_ELEMENT === 1));\n}\n/**\n * Asserts something is a non-negative integer.\n * @param n - number to validate\n * @param title - label included in thrown errors\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Validate a non-negative integer option.\n * ```ts\n * anumber(32, 'length');\n * ```\n */\nexport function anumber(n, title = '') {\n if (typeof n !== 'number') {\n const prefix = title && `\"${title}\" `;\n throw new TypeError(`${prefix}expected number, got ${typeof n}`);\n }\n if (!Number.isSafeInteger(n) || n < 0) {\n const prefix = title && `\"${title}\" `;\n throw new RangeError(`${prefix}expected integer >= 0, got ${n}`);\n }\n}\n/**\n * Asserts something is Uint8Array.\n * @param value - value to validate\n * @param length - optional exact length constraint\n * @param title - label included in thrown errors\n * @returns The validated byte array.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Validate that a value is a byte array.\n * ```ts\n * abytes(new Uint8Array([1, 2, 3]));\n * ```\n */\nexport function abytes(value, length, title = '') {\n const bytes = isBytes(value);\n const len = value?.length;\n const needsLen = length !== undefined;\n if (!bytes || (needsLen && len !== length)) {\n const prefix = title && `\"${title}\" `;\n const ofLen = needsLen ? ` of length ${length}` : '';\n const got = bytes ? `length=${len}` : `type=${typeof value}`;\n const message = prefix + 'expected Uint8Array' + ofLen + ', got ' + got;\n if (!bytes)\n throw new TypeError(message);\n throw new RangeError(message);\n }\n return value;\n}\n/**\n * Copies bytes into a fresh Uint8Array.\n * Buffer-style slices can alias the same backing store, so callers that need ownership should copy.\n * @param bytes - source bytes to clone\n * @returns Freshly allocated copy of `bytes`.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Clone a byte array before mutating it.\n * ```ts\n * const copy = copyBytes(new Uint8Array([1, 2, 3]));\n * ```\n */\nexport function copyBytes(bytes) {\n // `Uint8Array.from(...)` would also accept arrays / other typed arrays. Keep this helper strict\n // because callers use it at byte-validation boundaries before mutating the detached copy.\n return Uint8Array.from(abytes(bytes));\n}\n/**\n * Asserts something is a wrapped hash constructor.\n * @param h - hash constructor to validate\n * @throws On wrong argument types or invalid hash wrapper shape. {@link TypeError}\n * @throws On invalid hash metadata ranges or values. {@link RangeError}\n * @throws If the hash metadata allows empty outputs or block sizes. {@link Error}\n * @example\n * Validate a callable hash wrapper.\n * ```ts\n * import { ahash } from '@noble/hashes/utils.js';\n * import { sha256 } from '@noble/hashes/sha2.js';\n * ahash(sha256);\n * ```\n */\nexport function ahash(h) {\n if (typeof h !== 'function' || typeof h.create !== 'function')\n throw new TypeError('Hash must wrapped by utils.createHasher');\n anumber(h.outputLen);\n anumber(h.blockLen);\n // HMAC and KDF callers treat these as real byte lengths; allowing zero lets fake wrappers pass\n // validation and can produce empty outputs instead of failing fast.\n if (h.outputLen < 1)\n throw new Error('\"outputLen\" must be >= 1');\n if (h.blockLen < 1)\n throw new Error('\"blockLen\" must be >= 1');\n}\n/**\n * Asserts a hash instance has not been destroyed or finished.\n * @param instance - hash instance to validate\n * @param checkFinished - whether to reject finalized instances\n * @throws If the hash instance has already been destroyed or finalized. {@link Error}\n * @example\n * Validate that a hash instance is still usable.\n * ```ts\n * import { aexists } from '@noble/hashes/utils.js';\n * import { sha256 } from '@noble/hashes/sha2.js';\n * const hash = sha256.create();\n * aexists(hash);\n * ```\n */\nexport function aexists(instance, checkFinished = true) {\n if (instance.destroyed)\n throw new Error('Hash instance has been destroyed');\n if (checkFinished && instance.finished)\n throw new Error('Hash#digest() has already been called');\n}\n/**\n * Asserts output is a sufficiently-sized byte array.\n * @param out - destination buffer\n * @param instance - hash instance providing output length\n * Oversized buffers are allowed; downstream code only promises to fill the first `outputLen` bytes.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Validate a caller-provided digest buffer.\n * ```ts\n * import { aoutput } from '@noble/hashes/utils.js';\n * import { sha256 } from '@noble/hashes/sha2.js';\n * const hash = sha256.create();\n * aoutput(new Uint8Array(hash.outputLen), hash);\n * ```\n */\nexport function aoutput(out, instance) {\n abytes(out, undefined, 'digestInto() output');\n const min = instance.outputLen;\n if (out.length < min) {\n throw new RangeError('\"digestInto() output\" expected to be of length >=' + min);\n }\n}\n/**\n * Casts a typed array view to Uint8Array.\n * @param arr - source typed array\n * @returns Uint8Array view over the same buffer.\n * @example\n * Reinterpret a typed array as bytes.\n * ```ts\n * u8(new Uint32Array([1, 2]));\n * ```\n */\nexport function u8(arr) {\n return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n/**\n * Casts a typed array view to Uint32Array.\n * `arr.byteOffset` must already be 4-byte aligned or the platform\n * Uint32Array constructor will throw.\n * @param arr - source typed array\n * @returns Uint32Array view over the same buffer.\n * @example\n * Reinterpret a byte array as 32-bit words.\n * ```ts\n * u32(new Uint8Array(8));\n * ```\n */\nexport function u32(arr) {\n return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n}\n/**\n * Zeroizes typed arrays in place. Warning: JS provides no guarantees.\n * @param arrays - arrays to overwrite with zeros\n * @example\n * Zeroize sensitive buffers in place.\n * ```ts\n * clean(new Uint8Array([1, 2, 3]));\n * ```\n */\nexport function clean(...arrays) {\n for (let i = 0; i < arrays.length; i++) {\n arrays[i].fill(0);\n }\n}\n/**\n * Creates a DataView for byte-level manipulation.\n * @param arr - source typed array\n * @returns DataView over the same buffer region.\n * @example\n * Create a DataView over an existing buffer.\n * ```ts\n * createView(new Uint8Array(4));\n * ```\n */\nexport function createView(arr) {\n return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n}\n/**\n * Rotate-right operation for uint32 values.\n * @param word - source word\n * @param shift - shift amount in bits\n * @returns Rotated word.\n * @example\n * Rotate a 32-bit word to the right.\n * ```ts\n * rotr(0x12345678, 8);\n * ```\n */\nexport function rotr(word, shift) {\n return (word << (32 - shift)) | (word >>> shift);\n}\n/**\n * Rotate-left operation for uint32 values.\n * @param word - source word\n * @param shift - shift amount in bits\n * @returns Rotated word.\n * @example\n * Rotate a 32-bit word to the left.\n * ```ts\n * rotl(0x12345678, 8);\n * ```\n */\nexport function rotl(word, shift) {\n return (word << shift) | ((word >>> (32 - shift)) >>> 0);\n}\n/** Whether the current platform is little-endian. */\nexport const isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44)();\n/**\n * Byte-swap operation for uint32 values.\n * @param word - source word\n * @returns Word with reversed byte order.\n * @example\n * Reverse the byte order of a 32-bit word.\n * ```ts\n * byteSwap(0x11223344);\n * ```\n */\nexport function byteSwap(word) {\n return (((word << 24) & 0xff000000) |\n ((word << 8) & 0xff0000) |\n ((word >>> 8) & 0xff00) |\n ((word >>> 24) & 0xff));\n}\n/**\n * Conditionally byte-swaps one 32-bit word on big-endian platforms.\n * @param n - source word\n * @returns Original or byte-swapped word depending on platform endianness.\n * @example\n * Normalize a 32-bit word for host endianness.\n * ```ts\n * swap8IfBE(0x11223344);\n * ```\n */\nexport const swap8IfBE = isLE\n ? (n) => n\n : (n) => byteSwap(n) >>> 0;\n/**\n * Byte-swaps every word of a Uint32Array in place.\n * @param arr - array to mutate\n * @returns The same array after mutation; callers pass live state arrays here.\n * @example\n * Reverse the byte order of every word in place.\n * ```ts\n * byteSwap32(new Uint32Array([0x11223344]));\n * ```\n */\nexport function byteSwap32(arr) {\n for (let i = 0; i < arr.length; i++) {\n arr[i] = byteSwap(arr[i]);\n }\n return arr;\n}\n/**\n * Conditionally byte-swaps a Uint32Array on big-endian platforms.\n * @param u - array to normalize for host endianness\n * @returns Original or byte-swapped array depending on platform endianness.\n * On big-endian runtimes this mutates `u` in place via `byteSwap32(...)`.\n * @example\n * Normalize a word array for host endianness.\n * ```ts\n * swap32IfBE(new Uint32Array([0x11223344]));\n * ```\n */\nexport const swap32IfBE = isLE\n ? (u) => u\n : byteSwap32;\n// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex\nconst hasHexBuiltin = /* @__PURE__ */ (() => \n// @ts-ignore\ntypeof Uint8Array.from([]).toHex === 'function' && typeof Uint8Array.fromHex === 'function')();\n// Array where index 0xf0 (240) is mapped to string 'f0'\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));\n/**\n * Convert byte array to hex string.\n * Uses the built-in function when available and assumes it matches the tested\n * fallback semantics.\n * @param bytes - bytes to encode\n * @returns Lowercase hexadecimal string.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Convert bytes to lowercase hexadecimal.\n * ```ts\n * bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])); // 'cafe0123'\n * ```\n */\nexport function bytesToHex(bytes) {\n abytes(bytes);\n // @ts-ignore\n if (hasHexBuiltin)\n return bytes.toHex();\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\n// We use optimized technique to convert hex string to byte array\nconst asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };\nfunction asciiToBase16(ch) {\n if (ch >= asciis._0 && ch <= asciis._9)\n return ch - asciis._0; // '2' => 50-48\n if (ch >= asciis.A && ch <= asciis.F)\n return ch - (asciis.A - 10); // 'B' => 66-(65-10)\n if (ch >= asciis.a && ch <= asciis.f)\n return ch - (asciis.a - 10); // 'b' => 98-(97-10)\n return;\n}\n/**\n * Convert hex string to byte array. Uses built-in function, when available.\n * @param hex - hexadecimal string to decode\n * @returns Decoded bytes.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Decode lowercase hexadecimal into bytes.\n * ```ts\n * hexToBytes('cafe0123'); // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n * ```\n */\nexport function hexToBytes(hex) {\n if (typeof hex !== 'string')\n throw new TypeError('hex string expected, got ' + typeof hex);\n if (hasHexBuiltin) {\n try {\n return Uint8Array.fromHex(hex);\n }\n catch (error) {\n if (error instanceof SyntaxError)\n throw new RangeError(error.message);\n throw error;\n }\n }\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2)\n throw new RangeError('hex string expected, got unpadded hex of length ' + hl);\n const array = new Uint8Array(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n const n1 = asciiToBase16(hex.charCodeAt(hi));\n const n2 = asciiToBase16(hex.charCodeAt(hi + 1));\n if (n1 === undefined || n2 === undefined) {\n const char = hex[hi] + hex[hi + 1];\n throw new RangeError('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n }\n array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163\n }\n return array;\n}\n/**\n * There is no setImmediate in browser and setTimeout is slow.\n * This yields to the Promise/microtask scheduler queue, not to timers or the\n * full macrotask event loop.\n * @example\n * Yield to the next scheduler tick.\n * ```ts\n * await nextTick();\n * ```\n */\nexport const nextTick = async () => { };\n/**\n * Returns control to the Promise/microtask scheduler every `tick`\n * milliseconds to avoid blocking long loops.\n * @param iters - number of loop iterations to run\n * @param tick - maximum time slice in milliseconds\n * @param cb - callback executed on each iteration\n * @example\n * Run a loop that periodically yields back to the event loop.\n * ```ts\n * await asyncLoop(2, 0, () => {});\n * ```\n */\nexport async function asyncLoop(iters, tick, cb) {\n let ts = Date.now();\n for (let i = 0; i < iters; i++) {\n cb(i);\n // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n const diff = Date.now() - ts;\n if (diff >= 0 && diff < tick)\n continue;\n await nextTick();\n ts += diff;\n }\n}\n/**\n * Converts string to bytes using UTF8 encoding.\n * Built-in doesn't validate input to be string: we do the check.\n * Non-ASCII details are delegated to the platform `TextEncoder`.\n * @param str - string to encode\n * @returns UTF-8 encoded bytes.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Encode a string as UTF-8 bytes.\n * ```ts\n * utf8ToBytes('abc'); // Uint8Array.from([97, 98, 99])\n * ```\n */\nexport function utf8ToBytes(str) {\n if (typeof str !== 'string')\n throw new TypeError('string expected');\n return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n/**\n * Helper for KDFs: consumes Uint8Array or string.\n * String inputs are UTF-8 encoded; byte-array inputs stay aliased to the caller buffer.\n * @param data - user-provided KDF input\n * @param errorTitle - label included in thrown errors\n * @returns Byte representation of the input.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Normalize KDF input to bytes.\n * ```ts\n * kdfInputToBytes('password');\n * ```\n */\nexport function kdfInputToBytes(data, errorTitle = '') {\n if (typeof data === 'string')\n return utf8ToBytes(data);\n return abytes(data, undefined, errorTitle);\n}\n/**\n * Copies several Uint8Arrays into one.\n * @param arrays - arrays to concatenate\n * @returns Concatenated byte array.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Concatenate multiple byte arrays.\n * ```ts\n * concatBytes(new Uint8Array([1]), new Uint8Array([2]));\n * ```\n */\nexport function concatBytes(...arrays) {\n let sum = 0;\n for (let i = 0; i < arrays.length; i++) {\n const a = arrays[i];\n abytes(a);\n sum += a.length;\n }\n const res = new Uint8Array(sum);\n for (let i = 0, pad = 0; i < arrays.length; i++) {\n const a = arrays[i];\n res.set(a, pad);\n pad += a.length;\n }\n return res;\n}\n/**\n * Merges default options and passed options.\n * @param defaults - base option object\n * @param opts - user overrides\n * @returns Merged option object. The merge mutates `defaults` in place.\n * @throws On wrong argument types. {@link TypeError}\n * @example\n * Merge user overrides onto default options.\n * ```ts\n * checkOpts({ dkLen: 32 }, { asyncTick: 10 });\n * ```\n */\nexport function checkOpts(defaults, opts) {\n if (opts !== undefined && {}.toString.call(opts) !== '[object Object]')\n throw new TypeError('options must be object or undefined');\n const merged = Object.assign(defaults, opts);\n return merged;\n}\n/**\n * Creates a callable hash function from a stateful class constructor.\n * @param hashCons - hash constructor or factory\n * @param info - optional metadata such as DER OID\n * @returns Frozen callable hash wrapper with `.create()`.\n * Wrapper construction eagerly calls `hashCons(undefined)` once to read\n * `outputLen` / `blockLen`, so constructor side effects happen at module\n * init time.\n * @example\n * Wrap a stateful hash constructor into a callable helper.\n * ```ts\n * import { createHasher } from '@noble/hashes/utils.js';\n * import { sha256 } from '@noble/hashes/sha2.js';\n * const wrapped = createHasher(sha256.create, { oid: sha256.oid });\n * wrapped(new Uint8Array([1]));\n * ```\n */\nexport function createHasher(hashCons, info = {}) {\n const hashC = (msg, opts) => hashCons(opts)\n .update(msg)\n .digest();\n const tmp = hashCons(undefined);\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.canXOF = tmp.canXOF;\n hashC.create = (opts) => hashCons(opts);\n Object.assign(hashC, info);\n return Object.freeze(hashC);\n}\n/**\n * Cryptographically secure PRNG backed by `crypto.getRandomValues`.\n * @param bytesLength - number of random bytes to generate\n * @returns Random bytes.\n * The platform `getRandomValues()` implementation still defines any\n * single-call length cap, and this helper rejects oversize requests\n * with a stable library `RangeError` instead of host-specific errors.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @throws If the current runtime does not provide `crypto.getRandomValues`. {@link Error}\n * @example\n * Generate a fresh random key or nonce.\n * ```ts\n * const key = randomBytes(16);\n * ```\n */\nexport function randomBytes(bytesLength = 32) {\n // Match the repo's other length-taking helpers instead of relying on Uint8Array coercion.\n anumber(bytesLength, 'bytesLength');\n const cr = typeof globalThis === 'object' ? globalThis.crypto : null;\n if (typeof cr?.getRandomValues !== 'function')\n throw new Error('crypto.getRandomValues must be defined');\n // Web Cryptography API Level 2 §10.1.1:\n // if `byteLength > 65536`, throw `QuotaExceededError`.\n // Keep the guard explicit so callers can see the quota in code\n // instead of discovering it by reading the spec or host errors.\n // This wrapper surfaces the same quota as a stable library RangeError.\n if (bytesLength > 65536)\n throw new RangeError(`\"bytesLength\" expected <= 65536, got ${bytesLength}`);\n return cr.getRandomValues(new Uint8Array(bytesLength));\n}\n/**\n * Creates OID metadata for NIST hashes with prefix `06 09 60 86 48 01 65 03 04 02`.\n * @param suffix - final OID byte for the selected hash.\n * The helper accepts any byte even though only the documented NIST hash\n * suffixes are meaningful downstream.\n * @returns Object containing the DER-encoded OID.\n * @example\n * Build OID metadata for a NIST hash.\n * ```ts\n * oidNist(0x01);\n * ```\n */\nexport const oidNist = (suffix) => ({\n // Current NIST hashAlgs suffixes used here fit in one DER subidentifier octet.\n // Larger suffix values would need base-128 OID encoding and a different length byte.\n oid: Uint8Array.from([0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, suffix]),\n});\n//# sourceMappingURL=utils.js.map","/**\n * Internal Merkle-Damgard hash utils.\n * @module\n */\nimport { abytes, aexists, aoutput, clean, createView, } from \"./utils.js\";\n/**\n * Shared 32-bit conditional boolean primitive reused by SHA-256, SHA-1, and MD5 `F`.\n * Returns bits from `b` when `a` is set, otherwise from `c`.\n * The XOR form is equivalent to MD5's `F(X,Y,Z) = XY v not(X)Z` because the masked terms never\n * set the same bit.\n * @param a - selector word\n * @param b - word chosen when selector bit is set\n * @param c - word chosen when selector bit is clear\n * @returns Mixed 32-bit word.\n * @example\n * Combine three words with the shared 32-bit choice primitive.\n * ```ts\n * Chi(0xffffffff, 0x12345678, 0x87654321);\n * ```\n */\nexport function Chi(a, b, c) {\n return (a & b) ^ (~a & c);\n}\n/**\n * Shared 32-bit majority primitive reused by SHA-256 and SHA-1.\n * Returns bits shared by at least two inputs.\n * @param a - first input word\n * @param b - second input word\n * @param c - third input word\n * @returns Mixed 32-bit word.\n * @example\n * Combine three words with the shared 32-bit majority primitive.\n * ```ts\n * Maj(0xffffffff, 0x12345678, 0x87654321);\n * ```\n */\nexport function Maj(a, b, c) {\n return (a & b) ^ (a & c) ^ (b & c);\n}\n/**\n * Merkle-Damgard hash construction base class.\n * Could be used to create MD5, RIPEMD, SHA1, SHA2.\n * Accepts only byte-aligned `Uint8Array` input, even when the underlying spec describes bit\n * strings with partial-byte tails.\n * @param blockLen - internal block size in bytes\n * @param outputLen - digest size in bytes\n * @param padOffset - trailing length field size in bytes\n * @param isLE - whether length and state words are encoded in little-endian\n * @example\n * Use a concrete subclass to get the shared Merkle-Damgard update/digest flow.\n * ```ts\n * import { _SHA1 } from '@noble/hashes/legacy.js';\n * const hash = new _SHA1();\n * hash.update(new Uint8Array([97, 98, 99]));\n * hash.digest();\n * ```\n */\nexport class HashMD {\n blockLen;\n outputLen;\n canXOF = false;\n padOffset;\n isLE;\n // For partial updates less than block size\n buffer;\n view;\n finished = false;\n length = 0;\n pos = 0;\n destroyed = false;\n constructor(blockLen, outputLen, padOffset, isLE) {\n this.blockLen = blockLen;\n this.outputLen = outputLen;\n this.padOffset = padOffset;\n this.isLE = isLE;\n this.buffer = new Uint8Array(blockLen);\n this.view = createView(this.buffer);\n }\n update(data) {\n aexists(this);\n abytes(data);\n const { view, buffer, blockLen } = this;\n const len = data.length;\n for (let pos = 0; pos < len;) {\n const take = Math.min(blockLen - this.pos, len - pos);\n // Fast path only when there is no buffered partial block: `take === blockLen` implies\n // `this.pos === 0`, so we can process full blocks directly from the input view.\n if (take === blockLen) {\n const dataView = createView(data);\n for (; blockLen <= len - pos; pos += blockLen)\n this.process(dataView, pos);\n continue;\n }\n buffer.set(data.subarray(pos, pos + take), this.pos);\n this.pos += take;\n pos += take;\n if (this.pos === blockLen) {\n this.process(view, 0);\n this.pos = 0;\n }\n }\n this.length += data.length;\n this.roundClean();\n return this;\n }\n digestInto(out) {\n aexists(this);\n aoutput(out, this);\n this.finished = true;\n // Padding\n // We can avoid allocation of buffer for padding completely if it\n // was previously not allocated here. But it won't change performance.\n const { buffer, view, blockLen, isLE } = this;\n let { pos } = this;\n // append the bit '1' to the message\n buffer[pos++] = 0b10000000;\n clean(this.buffer.subarray(pos));\n // we have less than padOffset left in buffer, so we cannot put length in\n // current block, need process it and pad again\n if (this.padOffset > blockLen - pos) {\n this.process(view, 0);\n pos = 0;\n }\n // Pad until full block byte with zeros\n for (let i = pos; i < blockLen; i++)\n buffer[i] = 0;\n // `padOffset` reserves the whole length field. For SHA-384/512 the high 64 bits stay zero from\n // the padding fill above, and JS will overflow before user input can make that half non-zero.\n // So we only need to write the low 64 bits here.\n view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE);\n this.process(view, 0);\n const oview = createView(out);\n const len = this.outputLen;\n // NOTE: we do division by 4 later, which must be fused in single op with modulo by JIT\n if (len % 4)\n throw new Error('_sha2: outputLen must be aligned to 32bit');\n const outLen = len / 4;\n const state = this.get();\n if (outLen > state.length)\n throw new Error('_sha2: outputLen bigger than state');\n for (let i = 0; i < outLen; i++)\n oview.setUint32(4 * i, state[i], isLE);\n }\n digest() {\n const { buffer, outputLen } = this;\n this.digestInto(buffer);\n // Copy before destroy(): subclasses wipe `buffer` during cleanup, but `digest()` must return\n // fresh bytes to the caller.\n const res = buffer.slice(0, outputLen);\n this.destroy();\n return res;\n }\n _cloneInto(to) {\n to ||= new this.constructor();\n to.set(...this.get());\n const { blockLen, buffer, length, finished, destroyed, pos } = this;\n to.destroyed = destroyed;\n to.finished = finished;\n to.length = length;\n to.pos = pos;\n // Only partial-block bytes need copying: when `length % blockLen === 0`, `pos === 0` and\n // later `update()` / `digestInto()` overwrite `to.buffer` from the start before reading it.\n if (length % blockLen)\n to.buffer.set(buffer);\n return to;\n }\n clone() {\n return this._cloneInto();\n }\n}\n/**\n * Initial SHA-2 state: fractional parts of square roots of first 16 primes 2..53.\n * Check out `test/misc/sha2-gen-iv.js` for recomputation guide.\n */\n/** Initial SHA256 state from RFC 6234 §6.1: the first 32 bits of the fractional parts of the\n * square roots of the first eight prime numbers. Exported as a shared table; callers must treat\n * it as read-only because constructors copy words from it by index. */\nexport const SHA256_IV = /* @__PURE__ */ Uint32Array.from([\n 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,\n]);\n/** Initial SHA224 state `H(0)` from RFC 6234 §6.1. Exported as a shared table; callers must\n * treat it as read-only because constructors copy words from it by index. */\nexport const SHA224_IV = /* @__PURE__ */ Uint32Array.from([\n 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,\n]);\n/** Initial SHA384 state from RFC 6234 §6.3: eight RFC 64-bit `H(0)` words stored as sixteen\n * big-endian 32-bit halves. Derived from the fractional parts of the square roots of the ninth\n * through sixteenth prime numbers. Exported as a shared table; callers must treat it as read-only\n * because constructors copy halves from it by index. */\nexport const SHA384_IV = /* @__PURE__ */ Uint32Array.from([\n 0xcbbb9d5d, 0xc1059ed8, 0x629a292a, 0x367cd507, 0x9159015a, 0x3070dd17, 0x152fecd8, 0xf70e5939,\n 0x67332667, 0xffc00b31, 0x8eb44a87, 0x68581511, 0xdb0c2e0d, 0x64f98fa7, 0x47b5481d, 0xbefa4fa4,\n]);\n/** Initial SHA512 state from RFC 6234 §6.3: eight RFC 64-bit `H(0)` words stored as sixteen\n * big-endian 32-bit halves. Derived from the fractional parts of the square roots of the first\n * eight prime numbers. Exported as a shared table; callers must treat it as read-only because\n * constructors copy halves from it by index. */\nexport const SHA512_IV = /* @__PURE__ */ Uint32Array.from([\n 0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b, 0x3c6ef372, 0xfe94f82b, 0xa54ff53a, 0x5f1d36f1,\n 0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f, 0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179,\n]);\n//# sourceMappingURL=_md.js.map","const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);\nconst _32n = /* @__PURE__ */ BigInt(32);\n// Split bigint into two 32-bit halves. With `le=true`, returned fields become `{ h: low, l: high\n// }` to match little-endian word order rather than the property names.\nfunction fromBig(n, le = false) {\n if (le)\n return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };\n return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };\n}\n// Split bigint list into `[highWords, lowWords]` when `le=false`; with `le=true`, the first array\n// holds the low halves because `fromBig(...)` swaps the semantic meaning of `h` and `l`.\nfunction split(lst, le = false) {\n const len = lst.length;\n let Ah = new Uint32Array(len);\n let Al = new Uint32Array(len);\n for (let i = 0; i < len; i++) {\n const { h, l } = fromBig(lst[i], le);\n [Ah[i], Al[i]] = [h, l];\n }\n return [Ah, Al];\n}\n// Combine explicit `(high, low)` 32-bit halves into a bigint; `>>> 0` normalizes signed JS\n// bitwise results back to uint32 first, and little-endian callers must swap.\nconst toBig = (h, l) => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0);\n// High 32-bit half of a 64-bit logical right shift for `s` in `0..31`.\nconst shrSH = (h, _l, s) => h >>> s;\n// Low 32-bit half of a 64-bit logical right shift, valid for `s` in `1..31`.\nconst shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);\n// High 32-bit half of a 64-bit right rotate, valid for `s` in `1..31`.\nconst rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s));\n// Low 32-bit half of a 64-bit right rotate, valid for `s` in `1..31`.\nconst rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);\n// High 32-bit half of a 64-bit right rotate, valid for `s` in `33..63`; `32` uses `rotr32*`.\nconst rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32));\n// Low 32-bit half of a 64-bit right rotate, valid for `s` in `33..63`; `32` uses `rotr32*`.\nconst rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s));\n// High 32-bit half of a 64-bit right rotate for `s === 32`; this is just the swapped low half.\nconst rotr32H = (_h, l) => l;\n// Low 32-bit half of a 64-bit right rotate for `s === 32`; this is just the swapped high half.\nconst rotr32L = (h, _l) => h;\n// High 32-bit half of a 64-bit left rotate, valid for `s` in `1..31`.\nconst rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s));\n// Low 32-bit half of a 64-bit left rotate, valid for `s` in `1..31`.\nconst rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s));\n// High 32-bit half of a 64-bit left rotate, valid for `s` in `33..63`; `32` uses `rotr32*`.\nconst rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s));\n// Low 32-bit half of a 64-bit left rotate, valid for `s` in `33..63`; `32` uses `rotr32*`.\nconst rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s));\n// Add two split 64-bit words and return the split `{ h, l }` sum.\n// JS uses 32-bit signed integers for bitwise operations, so we cannot simply shift the carry out\n// of the low sum and instead use division.\nfunction add(Ah, Al, Bh, Bl) {\n const l = (Al >>> 0) + (Bl >>> 0);\n return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };\n}\n// Addition with more than 2 elements\n// Unmasked low-word accumulator for 3-way addition; pass the raw result into `add3H(...)`.\nconst add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);\n// High-word finalize step for 3-way addition; `low` must be the untruncated output of `add3L(...)`.\nconst add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;\n// Unmasked low-word accumulator for 4-way addition; pass the raw result into `add4H(...)`.\nconst add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);\n// High-word finalize step for 4-way addition; `low` must be the untruncated output of `add4L(...)`.\nconst add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;\n// Unmasked low-word accumulator for 5-way addition; pass the raw result into `add5H(...)`.\nconst add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);\n// High-word finalize step for 5-way addition; `low` must be the untruncated output of `add5L(...)`.\nconst add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;\n// prettier-ignore\nexport { add, add3H, add3L, add4H, add4L, add5H, add5L, fromBig, rotlBH, rotlBL, rotlSH, rotlSL, rotr32H, rotr32L, rotrBH, rotrBL, rotrSH, rotrSL, shrSH, shrSL, split, toBig };\n// Canonical grouped namespace for callers that prefer one object.\n// Named exports stay for direct imports.\n// prettier-ignore\nconst u64 = {\n fromBig, split, toBig,\n shrSH, shrSL,\n rotrSH, rotrSL, rotrBH, rotrBL,\n rotr32H, rotr32L,\n rotlSH, rotlSL, rotlBH, rotlBL,\n add, add3L, add3H, add4L, add4H, add5H, add5L,\n};\n// Default export mirrors named `u64` for compatibility with object-style imports.\nexport default u64;\n//# sourceMappingURL=_u64.js.map","/**\n * SHA2 hash function. A.k.a. sha256, sha384, sha512, sha512_224, sha512_256.\n * SHA256 is the fastest hash implementable in JS, even faster than Blake3.\n * Check out {@link https://www.rfc-editor.org/rfc/rfc4634 | RFC 4634} and\n * {@link https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf | FIPS 180-4}.\n * @module\n */\nimport { Chi, HashMD, Maj, SHA224_IV, SHA256_IV, SHA384_IV, SHA512_IV } from \"./_md.js\";\nimport * as u64 from \"./_u64.js\";\nimport { clean, createHasher, oidNist, rotr } from \"./utils.js\";\n/**\n * SHA-224 / SHA-256 round constants from RFC 6234 §5.1: the first 32 bits\n * of the cube roots of the first 64 primes (2..311).\n */\n// prettier-ignore\nconst SHA256_K = /* @__PURE__ */ Uint32Array.from([\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\n]);\n/** Reusable SHA-224 / SHA-256 message schedule buffer `W_t` from RFC 6234 §6.2 step 1. */\nconst SHA256_W = /* @__PURE__ */ new Uint32Array(64);\n/** Internal SHA-224 / SHA-256 compression engine from RFC 6234 §6.2. */\nclass SHA2_32B extends HashMD {\n constructor(outputLen) {\n super(64, outputLen, 8, false);\n }\n get() {\n const { A, B, C, D, E, F, G, H } = this;\n return [A, B, C, D, E, F, G, H];\n }\n // prettier-ignore\n set(A, B, C, D, E, F, G, H) {\n this.A = A | 0;\n this.B = B | 0;\n this.C = C | 0;\n this.D = D | 0;\n this.E = E | 0;\n this.F = F | 0;\n this.G = G | 0;\n this.H = H | 0;\n }\n process(view, offset) {\n // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array\n for (let i = 0; i < 16; i++, offset += 4)\n SHA256_W[i] = view.getUint32(offset, false);\n for (let i = 16; i < 64; i++) {\n const W15 = SHA256_W[i - 15];\n const W2 = SHA256_W[i - 2];\n const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ (W15 >>> 3);\n const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ (W2 >>> 10);\n SHA256_W[i] = (s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16]) | 0;\n }\n // Compression function main loop, 64 rounds\n let { A, B, C, D, E, F, G, H } = this;\n for (let i = 0; i < 64; i++) {\n const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);\n const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;\n const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);\n const T2 = (sigma0 + Maj(A, B, C)) | 0;\n H = G;\n G = F;\n F = E;\n E = (D + T1) | 0;\n D = C;\n C = B;\n B = A;\n A = (T1 + T2) | 0;\n }\n // Add the compressed chunk to the current hash value\n A = (A + this.A) | 0;\n B = (B + this.B) | 0;\n C = (C + this.C) | 0;\n D = (D + this.D) | 0;\n E = (E + this.E) | 0;\n F = (F + this.F) | 0;\n G = (G + this.G) | 0;\n H = (H + this.H) | 0;\n this.set(A, B, C, D, E, F, G, H);\n }\n roundClean() {\n clean(SHA256_W);\n }\n destroy() {\n // HashMD callers route post-destroy usability through `destroyed`; zeroizing alone still leaves\n // update()/digest() callable on reused instances.\n this.destroyed = true;\n this.set(0, 0, 0, 0, 0, 0, 0, 0);\n clean(this.buffer);\n }\n}\n/** Internal SHA-256 hash class grounded in RFC 6234 §6.2. */\nexport class _SHA256 extends SHA2_32B {\n // We cannot use array here since array allows indexing by variable\n // which means optimizer/compiler cannot use registers.\n A = SHA256_IV[0] | 0;\n B = SHA256_IV[1] | 0;\n C = SHA256_IV[2] | 0;\n D = SHA256_IV[3] | 0;\n E = SHA256_IV[4] | 0;\n F = SHA256_IV[5] | 0;\n G = SHA256_IV[6] | 0;\n H = SHA256_IV[7] | 0;\n constructor() {\n super(32);\n }\n}\n/** Internal SHA-224 hash class grounded in RFC 6234 §6.2 and §8.5. */\nexport class _SHA224 extends SHA2_32B {\n A = SHA224_IV[0] | 0;\n B = SHA224_IV[1] | 0;\n C = SHA224_IV[2] | 0;\n D = SHA224_IV[3] | 0;\n E = SHA224_IV[4] | 0;\n F = SHA224_IV[5] | 0;\n G = SHA224_IV[6] | 0;\n H = SHA224_IV[7] | 0;\n constructor() {\n super(28);\n }\n}\n// SHA2-512 is slower than sha256 in js because u64 operations are slow.\n// SHA-384 / SHA-512 round constants from RFC 6234 §5.2:\n// 80 full 64-bit words split into high/low halves.\n// prettier-ignore\nconst K512 = /* @__PURE__ */ (() => u64.split([\n '0x428a2f98d728ae22', '0x7137449123ef65cd', '0xb5c0fbcfec4d3b2f', '0xe9b5dba58189dbbc',\n '0x3956c25bf348b538', '0x59f111f1b605d019', '0x923f82a4af194f9b', '0xab1c5ed5da6d8118',\n '0xd807aa98a3030242', '0x12835b0145706fbe', '0x243185be4ee4b28c', '0x550c7dc3d5ffb4e2',\n '0x72be5d74f27b896f', '0x80deb1fe3b1696b1', '0x9bdc06a725c71235', '0xc19bf174cf692694',\n '0xe49b69c19ef14ad2', '0xefbe4786384f25e3', '0x0fc19dc68b8cd5b5', '0x240ca1cc77ac9c65',\n '0x2de92c6f592b0275', '0x4a7484aa6ea6e483', '0x5cb0a9dcbd41fbd4', '0x76f988da831153b5',\n '0x983e5152ee66dfab', '0xa831c66d2db43210', '0xb00327c898fb213f', '0xbf597fc7beef0ee4',\n '0xc6e00bf33da88fc2', '0xd5a79147930aa725', '0x06ca6351e003826f', '0x142929670a0e6e70',\n '0x27b70a8546d22ffc', '0x2e1b21385c26c926', '0x4d2c6dfc5ac42aed', '0x53380d139d95b3df',\n '0x650a73548baf63de', '0x766a0abb3c77b2a8', '0x81c2c92e47edaee6', '0x92722c851482353b',\n '0xa2bfe8a14cf10364', '0xa81a664bbc423001', '0xc24b8b70d0f89791', '0xc76c51a30654be30',\n '0xd192e819d6ef5218', '0xd69906245565a910', '0xf40e35855771202a', '0x106aa07032bbd1b8',\n '0x19a4c116b8d2d0c8', '0x1e376c085141ab53', '0x2748774cdf8eeb99', '0x34b0bcb5e19b48a8',\n '0x391c0cb3c5c95a63', '0x4ed8aa4ae3418acb', '0x5b9cca4f7763e373', '0x682e6ff3d6b2b8a3',\n '0x748f82ee5defb2fc', '0x78a5636f43172f60', '0x84c87814a1f0ab72', '0x8cc702081a6439ec',\n '0x90befffa23631e28', '0xa4506cebde82bde9', '0xbef9a3f7b2c67915', '0xc67178f2e372532b',\n '0xca273eceea26619c', '0xd186b8c721c0c207', '0xeada7dd6cde0eb1e', '0xf57d4f7fee6ed178',\n '0x06f067aa72176fba', '0x0a637dc5a2c898a6', '0x113f9804bef90dae', '0x1b710b35131c471b',\n '0x28db77f523047d84', '0x32caab7b40c72493', '0x3c9ebe0a15c9bebc', '0x431d67c49c100d4c',\n '0x4cc5d4becb3e42b6', '0x597f299cfc657e2a', '0x5fcb6fab3ad6faec', '0x6c44198c4a475817'\n].map(n => BigInt(n))))();\nconst SHA512_Kh = /* @__PURE__ */ (() => K512[0])();\nconst SHA512_Kl = /* @__PURE__ */ (() => K512[1])();\n// Reusable high-half schedule buffer for the RFC 6234 §6.4 64-bit `W_t` words.\nconst SHA512_W_H = /* @__PURE__ */ new Uint32Array(80);\n// Reusable low-half schedule buffer for the RFC 6234 §6.4 64-bit `W_t` words.\nconst SHA512_W_L = /* @__PURE__ */ new Uint32Array(80);\n/** Internal SHA-384 / SHA-512 compression engine from RFC 6234 §6.4. */\nclass SHA2_64B extends HashMD {\n constructor(outputLen) {\n super(128, outputLen, 16, false);\n }\n // prettier-ignore\n get() {\n const { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;\n return [Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl];\n }\n // prettier-ignore\n set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl) {\n this.Ah = Ah | 0;\n this.Al = Al | 0;\n this.Bh = Bh | 0;\n this.Bl = Bl | 0;\n this.Ch = Ch | 0;\n this.Cl = Cl | 0;\n this.Dh = Dh | 0;\n this.Dl = Dl | 0;\n this.Eh = Eh | 0;\n this.El = El | 0;\n this.Fh = Fh | 0;\n this.Fl = Fl | 0;\n this.Gh = Gh | 0;\n this.Gl = Gl | 0;\n this.Hh = Hh | 0;\n this.Hl = Hl | 0;\n }\n process(view, offset) {\n // Extend the first 16 words into the remaining 64 words w[16..79] of the message schedule array\n for (let i = 0; i < 16; i++, offset += 4) {\n SHA512_W_H[i] = view.getUint32(offset);\n SHA512_W_L[i] = view.getUint32((offset += 4));\n }\n for (let i = 16; i < 80; i++) {\n // s0 := (w[i-15] rightrotate 1) xor (w[i-15] rightrotate 8) xor (w[i-15] rightshift 7)\n const W15h = SHA512_W_H[i - 15] | 0;\n const W15l = SHA512_W_L[i - 15] | 0;\n const s0h = u64.rotrSH(W15h, W15l, 1) ^ u64.rotrSH(W15h, W15l, 8) ^ u64.shrSH(W15h, W15l, 7);\n const s0l = u64.rotrSL(W15h, W15l, 1) ^ u64.rotrSL(W15h, W15l, 8) ^ u64.shrSL(W15h, W15l, 7);\n // s1 := (w[i-2] rightrotate 19) xor (w[i-2] rightrotate 61) xor (w[i-2] rightshift 6)\n const W2h = SHA512_W_H[i - 2] | 0;\n const W2l = SHA512_W_L[i - 2] | 0;\n const s1h = u64.rotrSH(W2h, W2l, 19) ^ u64.rotrBH(W2h, W2l, 61) ^ u64.shrSH(W2h, W2l, 6);\n const s1l = u64.rotrSL(W2h, W2l, 19) ^ u64.rotrBL(W2h, W2l, 61) ^ u64.shrSL(W2h, W2l, 6);\n // SHA512_W[i] = s0 + s1 + SHA512_W[i - 7] + SHA512_W[i - 16];\n const SUMl = u64.add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]);\n const SUMh = u64.add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]);\n SHA512_W_H[i] = SUMh | 0;\n SHA512_W_L[i] = SUMl | 0;\n }\n let { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;\n // Compression function main loop, 80 rounds\n for (let i = 0; i < 80; i++) {\n // S1 := (e rightrotate 14) xor (e rightrotate 18) xor (e rightrotate 41)\n const sigma1h = u64.rotrSH(Eh, El, 14) ^ u64.rotrSH(Eh, El, 18) ^ u64.rotrBH(Eh, El, 41);\n const sigma1l = u64.rotrSL(Eh, El, 14) ^ u64.rotrSL(Eh, El, 18) ^ u64.rotrBL(Eh, El, 41);\n //const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;\n const CHIh = (Eh & Fh) ^ (~Eh & Gh);\n const CHIl = (El & Fl) ^ (~El & Gl);\n // T1 = H + sigma1 + Chi(E, F, G) + SHA512_K[i] + SHA512_W[i]\n // prettier-ignore\n const T1ll = u64.add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]);\n const T1h = u64.add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]);\n const T1l = T1ll | 0;\n // S0 := (a rightrotate 28) xor (a rightrotate 34) xor (a rightrotate 39)\n const sigma0h = u64.rotrSH(Ah, Al, 28) ^ u64.rotrBH(Ah, Al, 34) ^ u64.rotrBH(Ah, Al, 39);\n const sigma0l = u64.rotrSL(Ah, Al, 28) ^ u64.rotrBL(Ah, Al, 34) ^ u64.rotrBL(Ah, Al, 39);\n const MAJh = (Ah & Bh) ^ (Ah & Ch) ^ (Bh & Ch);\n const MAJl = (Al & Bl) ^ (Al & Cl) ^ (Bl & Cl);\n Hh = Gh | 0;\n Hl = Gl | 0;\n Gh = Fh | 0;\n Gl = Fl | 0;\n Fh = Eh | 0;\n Fl = El | 0;\n ({ h: Eh, l: El } = u64.add(Dh | 0, Dl | 0, T1h | 0, T1l | 0));\n Dh = Ch | 0;\n Dl = Cl | 0;\n Ch = Bh | 0;\n Cl = Bl | 0;\n Bh = Ah | 0;\n Bl = Al | 0;\n const All = u64.add3L(T1l, sigma0l, MAJl);\n Ah = u64.add3H(All, T1h, sigma0h, MAJh);\n Al = All | 0;\n }\n // Add the compressed chunk to the current hash value\n ({ h: Ah, l: Al } = u64.add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0));\n ({ h: Bh, l: Bl } = u64.add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0));\n ({ h: Ch, l: Cl } = u64.add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0));\n ({ h: Dh, l: Dl } = u64.add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0));\n ({ h: Eh, l: El } = u64.add(this.Eh | 0, this.El | 0, Eh | 0, El | 0));\n ({ h: Fh, l: Fl } = u64.add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0));\n ({ h: Gh, l: Gl } = u64.add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0));\n ({ h: Hh, l: Hl } = u64.add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0));\n this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl);\n }\n roundClean() {\n clean(SHA512_W_H, SHA512_W_L);\n }\n destroy() {\n // HashMD callers route post-destroy usability through `destroyed`; zeroizing alone still leaves\n // update()/digest() callable on reused instances.\n this.destroyed = true;\n clean(this.buffer);\n this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);\n }\n}\n/** Internal SHA-512 hash class grounded in RFC 6234 §6.3 and §6.4. */\nexport class _SHA512 extends SHA2_64B {\n Ah = SHA512_IV[0] | 0;\n Al = SHA512_IV[1] | 0;\n Bh = SHA512_IV[2] | 0;\n Bl = SHA512_IV[3] | 0;\n Ch = SHA512_IV[4] | 0;\n Cl = SHA512_IV[5] | 0;\n Dh = SHA512_IV[6] | 0;\n Dl = SHA512_IV[7] | 0;\n Eh = SHA512_IV[8] | 0;\n El = SHA512_IV[9] | 0;\n Fh = SHA512_IV[10] | 0;\n Fl = SHA512_IV[11] | 0;\n Gh = SHA512_IV[12] | 0;\n Gl = SHA512_IV[13] | 0;\n Hh = SHA512_IV[14] | 0;\n Hl = SHA512_IV[15] | 0;\n constructor() {\n super(64);\n }\n}\n/** Internal SHA-384 hash class grounded in RFC 6234 §6.3 and §6.4. */\nexport class _SHA384 extends SHA2_64B {\n Ah = SHA384_IV[0] | 0;\n Al = SHA384_IV[1] | 0;\n Bh = SHA384_IV[2] | 0;\n Bl = SHA384_IV[3] | 0;\n Ch = SHA384_IV[4] | 0;\n Cl = SHA384_IV[5] | 0;\n Dh = SHA384_IV[6] | 0;\n Dl = SHA384_IV[7] | 0;\n Eh = SHA384_IV[8] | 0;\n El = SHA384_IV[9] | 0;\n Fh = SHA384_IV[10] | 0;\n Fl = SHA384_IV[11] | 0;\n Gh = SHA384_IV[12] | 0;\n Gl = SHA384_IV[13] | 0;\n Hh = SHA384_IV[14] | 0;\n Hl = SHA384_IV[15] | 0;\n constructor() {\n super(48);\n }\n}\n/**\n * Truncated SHA512/256 and SHA512/224.\n * SHA512_IV is XORed with 0xa5a5a5a5a5a5a5a5, then used as \"intermediary\" IV of SHA512/t.\n * Then t hashes string to produce result IV.\n * See the repo-side derivation recipe in `test/misc/sha2-gen-iv.js`.\n * These IV literals are checked against that script rather than a dedicated\n * local RFC section.\n */\n/** SHA-512/224 IV derived by the SHA-512/t recipe in `test/misc/sha2-gen-iv.js` and\n * stored as sixteen big-endian 32-bit halves. */\nconst T224_IV = /* @__PURE__ */ Uint32Array.from([\n 0x8c3d37c8, 0x19544da2, 0x73e19966, 0x89dcd4d6, 0x1dfab7ae, 0x32ff9c82, 0x679dd514, 0x582f9fcf,\n 0x0f6d2b69, 0x7bd44da8, 0x77e36f73, 0x04c48942, 0x3f9d85a8, 0x6a1d36c8, 0x1112e6ad, 0x91d692a1,\n]);\n/** SHA-512/256 IV derived by the SHA-512/t recipe in `test/misc/sha2-gen-iv.js` and\n * stored as sixteen big-endian 32-bit halves. */\nconst T256_IV = /* @__PURE__ */ Uint32Array.from([\n 0x22312194, 0xfc2bf72c, 0x9f555fa3, 0xc84c64c2, 0x2393b86b, 0x6f53b151, 0x96387719, 0x5940eabd,\n 0x96283ee2, 0xa88effe3, 0xbe5e1e25, 0x53863992, 0x2b0199fc, 0x2c85b8aa, 0x0eb72ddc, 0x81c52ca2,\n]);\n/** Internal SHA-512/224 hash class using the derived `T224_IV` and the shared\n * RFC 6234 §6.4 compression engine. */\nexport class _SHA512_224 extends SHA2_64B {\n Ah = T224_IV[0] | 0;\n Al = T224_IV[1] | 0;\n Bh = T224_IV[2] | 0;\n Bl = T224_IV[3] | 0;\n Ch = T224_IV[4] | 0;\n Cl = T224_IV[5] | 0;\n Dh = T224_IV[6] | 0;\n Dl = T224_IV[7] | 0;\n Eh = T224_IV[8] | 0;\n El = T224_IV[9] | 0;\n Fh = T224_IV[10] | 0;\n Fl = T224_IV[11] | 0;\n Gh = T224_IV[12] | 0;\n Gl = T224_IV[13] | 0;\n Hh = T224_IV[14] | 0;\n Hl = T224_IV[15] | 0;\n constructor() {\n super(28);\n }\n}\n/** Internal SHA-512/256 hash class using the derived `T256_IV` and the shared\n * RFC 6234 §6.4 compression engine. */\nexport class _SHA512_256 extends SHA2_64B {\n Ah = T256_IV[0] | 0;\n Al = T256_IV[1] | 0;\n Bh = T256_IV[2] | 0;\n Bl = T256_IV[3] | 0;\n Ch = T256_IV[4] | 0;\n Cl = T256_IV[5] | 0;\n Dh = T256_IV[6] | 0;\n Dl = T256_IV[7] | 0;\n Eh = T256_IV[8] | 0;\n El = T256_IV[9] | 0;\n Fh = T256_IV[10] | 0;\n Fl = T256_IV[11] | 0;\n Gh = T256_IV[12] | 0;\n Gl = T256_IV[13] | 0;\n Hh = T256_IV[14] | 0;\n Hl = T256_IV[15] | 0;\n constructor() {\n super(32);\n }\n}\n/**\n * SHA2-256 hash function from RFC 4634. In JS it's the fastest: even faster than Blake3. Some info:\n *\n * - Trying 2^128 hashes would get 50% chance of collision, using birthday attack.\n * - BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.\n * - Each sha256 hash is executing 2^18 bit operations.\n * - Good 2024 ASICs can do 200Th/sec with 3500 watts of power, corresponding to 2^36 hashes/joule.\n * @param msg - message bytes to hash\n * @returns Digest bytes.\n * @example\n * Hash a message with SHA2-256.\n * ```ts\n * sha256(new Uint8Array([97, 98, 99]));\n * ```\n */\nexport const sha256 = /* @__PURE__ */ createHasher(() => new _SHA256(), \n/* @__PURE__ */ oidNist(0x01));\n/**\n * SHA2-224 hash function from RFC 4634.\n * @param msg - message bytes to hash\n * @returns Digest bytes.\n * @example\n * Hash a message with SHA2-224.\n * ```ts\n * sha224(new Uint8Array([97, 98, 99]));\n * ```\n */\nexport const sha224 = /* @__PURE__ */ createHasher(() => new _SHA224(), \n/* @__PURE__ */ oidNist(0x04));\n/**\n * SHA2-512 hash function from RFC 4634.\n * @param msg - message bytes to hash\n * @returns Digest bytes.\n * @example\n * Hash a message with SHA2-512.\n * ```ts\n * sha512(new Uint8Array([97, 98, 99]));\n * ```\n */\nexport const sha512 = /* @__PURE__ */ createHasher(() => new _SHA512(), \n/* @__PURE__ */ oidNist(0x03));\n/**\n * SHA2-384 hash function from RFC 4634.\n * @param msg - message bytes to hash\n * @returns Digest bytes.\n * @example\n * Hash a message with SHA2-384.\n * ```ts\n * sha384(new Uint8Array([97, 98, 99]));\n * ```\n */\nexport const sha384 = /* @__PURE__ */ createHasher(() => new _SHA384(), \n/* @__PURE__ */ oidNist(0x02));\n/**\n * SHA2-512/256 \"truncated\" hash function, with improved resistance to length extension attacks.\n * See the paper on {@link https://eprint.iacr.org/2010/548.pdf | truncated SHA512}.\n * @param msg - message bytes to hash\n * @returns Digest bytes.\n * @example\n * Hash a message with SHA2-512/256.\n * ```ts\n * sha512_256(new Uint8Array([97, 98, 99]));\n * ```\n */\nexport const sha512_256 = /* @__PURE__ */ createHasher(() => new _SHA512_256(), \n/* @__PURE__ */ oidNist(0x06));\n/**\n * SHA2-512/224 \"truncated\" hash function, with improved resistance to length extension attacks.\n * See the paper on {@link https://eprint.iacr.org/2010/548.pdf | truncated SHA512}.\n * @param msg - message bytes to hash\n * @returns Digest bytes.\n * @example\n * Hash a message with SHA2-512/224.\n * ```ts\n * sha512_224(new Uint8Array([97, 98, 99]));\n * ```\n */\nexport const sha512_224 = /* @__PURE__ */ createHasher(() => new _SHA512_224(), \n/* @__PURE__ */ oidNist(0x05));\n//# sourceMappingURL=sha2.js.map","/**\n * Ed25519 key generation, persistence, and challenge signing for CLI auth.\n * Mirrors @abraca/mcp/src/crypto.ts — standalone to avoid MCP SDK dependency.\n */\nimport * as ed from '@noble/ed25519'\nimport { sha512 } from '@noble/hashes/sha2.js'\nimport { readFile, writeFile, mkdir } from 'node:fs/promises'\n\n// @noble/ed25519 v3 hash hook\ned.hashes.sha512 = sha512\ned.hashes.sha512Async = (m: Uint8Array) => Promise.resolve(sha512(m))\nimport { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join, dirname } from 'node:path'\n\nconst DEFAULT_KEY_PATH = join(homedir(), '.abracadabra', 'cli.key')\n\nfunction toBase64url(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString('base64url')\n}\n\nfunction fromBase64url(b64: string): Uint8Array {\n return new Uint8Array(Buffer.from(b64, 'base64url'))\n}\n\nexport interface CLIKeypair {\n privateKey: Uint8Array\n publicKeyB64: string\n}\n\n/**\n * Load an existing Ed25519 keypair from disk, or generate and persist a new one.\n * The file stores the raw 32-byte private key seed.\n */\nexport async function loadOrCreateKeypair(keyPath?: string): Promise<CLIKeypair> {\n const path = keyPath || DEFAULT_KEY_PATH\n\n if (existsSync(path)) {\n const seed = await readFile(path)\n if (seed.length !== 32) {\n throw new Error(`Invalid key file at ${path}: expected 32 bytes, got ${seed.length}`)\n }\n const privateKey = new Uint8Array(seed)\n const publicKey = ed.getPublicKey(privateKey)\n return { privateKey, publicKeyB64: toBase64url(publicKey) }\n }\n\n // Generate new keypair\n const privateKey = ed.utils.randomSecretKey()\n const publicKey = ed.getPublicKey(privateKey)\n\n // Ensure directory exists and write seed with restricted permissions\n const dir = dirname(path)\n if (!existsSync(dir)) {\n await mkdir(dir, { recursive: true, mode: 0o700 })\n }\n await writeFile(path, Buffer.from(privateKey), { mode: 0o600 })\n\n console.error(`[abracadabra] Generated new keypair at ${path}`)\n console.error(`[abracadabra] Public key: ${toBase64url(publicKey)}`)\n\n return { privateKey, publicKeyB64: toBase64url(publicKey) }\n}\n\n/** Sign a base64url challenge with the private key; returns base64url signature. */\nexport function signChallenge(challengeB64: string, privateKey: Uint8Array): string {\n const challenge = fromBase64url(challengeB64)\n const sig = ed.sign(challenge, privateKey)\n return toBase64url(sig)\n}\n","/**\n * CLIConnection — manages the CRDT connection lifecycle for the CLI.\n *\n * Handles: Ed25519 auth → space discovery → Y.Doc sync → awareness.\n * Reuses the same patterns as AbracadabraMCPServer but without MCP SDK dependency.\n */\nimport * as Y from 'yjs'\nimport { AbracadabraProvider, AbracadabraClient, Kind } from '@abraca/dabra'\nimport type { ServerInfo, DocumentMeta } from '@abraca/dabra'\nimport { loadOrCreateKeypair, signChallenge } from './crypto.ts'\n\nexport interface CLIConnectionConfig {\n url: string\n name?: string\n color?: string\n inviteCode?: string\n keyFile?: string\n /** If true, suppress all stderr logging */\n quiet?: boolean\n}\n\ninterface CachedProvider {\n provider: AbracadabraProvider\n lastAccessed: number\n}\n\nfunction waitForSync(\n provider: { on(event: string, cb: () => void): void; off(event: string, cb: () => void): void },\n timeoutMs = 15000\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => {\n provider.off('synced', handler)\n reject(new Error(`Sync timed out after ${timeoutMs}ms`))\n }, timeoutMs)\n\n function handler() {\n clearTimeout(timer)\n resolve()\n }\n\n provider.on('synced', handler)\n })\n}\n\nexport class CLIConnection {\n readonly config: CLIConnectionConfig\n readonly client: AbracadabraClient\n\n private _serverInfo: ServerInfo | null = null\n private _rootDocId: string | null = null\n private _spaces: DocumentMeta[] = []\n private _rootDoc: Y.Doc | null = null\n private _rootProvider: AbracadabraProvider | null = null\n private _userId: string | null = null\n private _signFn: ((challenge: string) => Promise<string>) | null = null\n private childCache = new Map<string, CachedProvider>()\n\n constructor(config: CLIConnectionConfig) {\n this.config = config\n this.client = new AbracadabraClient({\n url: config.url,\n persistAuth: false,\n })\n }\n\n get displayName(): string {\n return this.config.name || 'CLI User'\n }\n\n get displayColor(): string {\n return this.config.color || 'hsl(45, 90%, 55%)'\n }\n\n get serverInfo(): ServerInfo | null {\n return this._serverInfo\n }\n\n get rootDocId(): string | null {\n return this._rootDocId\n }\n\n get spaces(): DocumentMeta[] {\n return this._spaces\n }\n\n get rootDoc(): Y.Doc | null {\n return this._rootDoc\n }\n\n get rootProvider(): AbracadabraProvider | null {\n return this._rootProvider\n }\n\n get userId(): string | null {\n return this._userId\n }\n\n private log(msg: string): void {\n if (!this.config.quiet) {\n console.error(`[abracadabra] ${msg}`)\n }\n }\n\n /** Connect to the server: authenticate, discover spaces, sync root doc. */\n async connect(): Promise<void> {\n // Step 1: Load or generate Ed25519 keypair\n const keypair = await loadOrCreateKeypair(this.config.keyFile)\n this._userId = keypair.publicKeyB64\n const signFn = (challenge: string) => Promise.resolve(signChallenge(challenge, keypair.privateKey))\n this._signFn = signFn\n\n // Step 2: Authenticate via challenge-response (register on first run)\n try {\n await this.client.loginWithKey(keypair.publicKeyB64, signFn)\n } catch (err: any) {\n const status = err?.status ?? err?.response?.status\n if (status === 404 || status === 422) {\n this.log('Key not registered, creating new account...')\n await this.client.registerWithKey({\n publicKey: keypair.publicKeyB64,\n username: this.displayName.replace(/\\s+/g, '-').toLowerCase(),\n displayName: this.displayName,\n deviceName: 'CLI',\n inviteCode: this.config.inviteCode,\n })\n await this.client.loginWithKey(keypair.publicKeyB64, signFn)\n } else {\n throw err\n }\n }\n this.log(`Authenticated as ${this.displayName} (${keypair.publicKeyB64.slice(0, 12)}...)`)\n\n // Step 3: Discover server info\n this._serverInfo = await this.client.serverInfo()\n\n // Step 4: Pick an entry-point doc — first Space under the server root,\n // falling back to the first top-level doc of any kind.\n const roots = await this.client.listChildren()\n this._spaces = roots.filter(d => d.kind === Kind.Space)\n const first = this._spaces[0] ?? roots[0]\n const initialDocId = first?.id ?? null\n if (first) {\n this.log(`Entry document: ${first.label ?? first.id} (${first.id})`)\n }\n\n if (!initialDocId) {\n throw new Error(\n 'No entry point found: server has no top-level documents. Create a Space first.',\n )\n }\n\n this._rootDocId = initialDocId\n\n // Step 5: Connect provider and sync\n const doc = new Y.Doc({ guid: initialDocId })\n const provider = new AbracadabraProvider({\n name: initialDocId,\n document: doc,\n client: this.client,\n disableOfflineStore: true,\n subdocLoading: 'lazy',\n })\n\n await waitForSync(provider)\n\n provider.awareness.setLocalStateField('user', {\n name: this.displayName,\n color: this.displayColor,\n publicKey: this._userId,\n isAgent: false,\n })\n provider.awareness.setLocalStateField('status', null)\n\n this._rootDoc = doc\n this._rootProvider = provider\n this.log('Connected and synced')\n }\n\n /** Switch active space to a different root document. */\n async switchSpace(docId: string): Promise<void> {\n // Destroy existing child providers\n for (const [, cached] of this.childCache) {\n cached.provider.destroy()\n }\n this.childCache.clear()\n\n // Destroy current root provider\n if (this._rootProvider) {\n this._rootProvider.destroy()\n this._rootProvider = null\n }\n this._rootDoc = null\n\n // Re-authenticate if JWT has expired\n if (!this.client.isTokenValid() && this._signFn && this._userId) {\n await this.client.loginWithKey(this._userId, this._signFn)\n }\n\n // Connect to new space\n const doc = new Y.Doc({ guid: docId })\n const provider = new AbracadabraProvider({\n name: docId,\n document: doc,\n client: this.client,\n disableOfflineStore: true,\n subdocLoading: 'lazy',\n })\n\n await waitForSync(provider)\n\n provider.awareness.setLocalStateField('user', {\n name: this.displayName,\n color: this.displayColor,\n publicKey: this._userId,\n isAgent: false,\n })\n\n this._rootDoc = doc\n this._rootProvider = provider\n this._rootDocId = docId\n this.log(`Switched to space ${docId}`)\n }\n\n /** Get the root doc-tree Y.Map. */\n getTreeMap(): Y.Map<any> | null {\n return this._rootDoc?.getMap('doc-tree') ?? null\n }\n\n /** Get the root doc-trash Y.Map. */\n getTrashMap(): Y.Map<any> | null {\n return this._rootDoc?.getMap('doc-trash') ?? null\n }\n\n /** Get or create a child provider for a document. */\n async getChildProvider(docId: string): Promise<AbracadabraProvider> {\n const cached = this.childCache.get(docId)\n if (cached) {\n cached.lastAccessed = Date.now()\n return cached.provider\n }\n\n if (!this._rootProvider) {\n throw new Error('Not connected. Call connect() first.')\n }\n\n // Re-authenticate if JWT has expired\n if (!this.client.isTokenValid() && this._signFn && this._userId) {\n await this.client.loginWithKey(this._userId, this._signFn)\n }\n\n const childProvider = await this._rootProvider.loadChild(docId)\n await waitForSync(childProvider)\n\n childProvider.awareness.setLocalStateField('user', {\n name: this.displayName,\n color: this.displayColor,\n publicKey: this._userId,\n isAgent: false,\n })\n\n this.childCache.set(docId, {\n provider: childProvider,\n lastAccessed: Date.now(),\n })\n\n return childProvider\n }\n\n /** Graceful shutdown. */\n async destroy(): Promise<void> {\n for (const [, cached] of this.childCache) {\n cached.provider.destroy()\n }\n this.childCache.clear()\n\n if (this._rootProvider) {\n this._rootProvider.awareness.setLocalStateField('status', null)\n this._rootProvider.destroy()\n this._rootProvider = null\n }\n this._rootDoc = null\n\n this.log('Disconnected')\n }\n}\n","/**\n * Command interface and registry.\n */\nimport type { CLIConnection } from './connection.ts'\nimport type { ParsedArgs } from './parser.ts'\n\nexport interface Command {\n name: string\n aliases?: string[]\n description: string\n usage?: string\n run(conn: CLIConnection | null, args: ParsedArgs): Promise<string>\n}\n\nconst commands: Command[] = []\n\nexport function registerCommand(cmd: Command): void {\n commands.push(cmd)\n}\n\nexport function getCommand(name: string): Command | null {\n return commands.find(c =>\n c.name === name || c.aliases?.includes(name)\n ) ?? null\n}\n\nexport function getAllCommands(): Command[] {\n return [...commands]\n}\n","/**\n * Output formatting utilities for Abracadabra CLI.\n *\n * Supports JSON, TSV, tree, and compact text output.\n */\n\nimport type { ParsedArgs } from './parser.ts'\n\nexport type OutputFormat = 'json' | 'tsv' | 'tree' | 'text' | 'md'\n\nexport function getFormat(args: ParsedArgs, defaultFormat: OutputFormat = 'text'): OutputFormat {\n const f = args.params['format']\n if (f && ['json', 'tsv', 'tree', 'text', 'md'].includes(f)) {\n return f as OutputFormat\n }\n return defaultFormat\n}\n\n/** Print a JSON-serializable value. */\nexport function printJson(data: unknown): string {\n return JSON.stringify(data, null, 2)\n}\n\n/** Print a list of objects as TSV. */\nexport function printTsv(rows: Record<string, unknown>[], columns?: string[]): string {\n if (rows.length === 0) return ''\n const cols = columns ?? Object.keys(rows[0])\n const header = cols.map(c => c.toUpperCase()).join('\\t')\n const body = rows.map(row =>\n cols.map(c => {\n const val = row[c]\n if (val == null) return '—'\n if (typeof val === 'object') return JSON.stringify(val)\n return String(val)\n }).join('\\t')\n ).join('\\n')\n return header + '\\n' + body\n}\n\n/** Format a tree of nested items with box-drawing characters. */\nexport function printTree(\n items: TreeNode[],\n opts: { indent?: string, isLast?: boolean[] } = {}\n): string {\n const lines: string[] = []\n for (let i = 0; i < items.length; i++) {\n const item = items[i]\n const isLast = i === items.length - 1\n const prefix = (opts.isLast ?? [])\n .map(last => last ? ' ' : '│ ')\n .join('')\n const connector = isLast ? '└── ' : '├── '\n const typeSuffix = item.type ? ` (${item.type})` : ''\n lines.push(`${prefix}${connector}${item.label}${typeSuffix}`)\n if (item.children && item.children.length > 0) {\n lines.push(printTree(item.children, {\n isLast: [...(opts.isLast ?? []), isLast],\n }))\n }\n }\n return lines.join('\\n')\n}\n\nexport interface TreeNode {\n label: string\n type?: string\n children?: TreeNode[]\n}\n\n/** Format relative time (e.g. \"2m ago\", \"1h ago\"). */\nexport function relativeTime(timestamp: number | undefined | null): string {\n if (!timestamp) return '—'\n const diff = Date.now() - timestamp\n if (diff < 0) return 'just now'\n if (diff < 60_000) return `${Math.floor(diff / 1000)}s ago`\n if (diff < 3_600_000) return `${Math.floor(diff / 60_000)}m ago`\n if (diff < 86_400_000) return `${Math.floor(diff / 3_600_000)}h ago`\n return `${Math.floor(diff / 86_400_000)}d ago`\n}\n\n/** Truncate a string to a max length, appending '…' if truncated. */\nexport function truncate(str: string, max: number): string {\n if (str.length <= max) return str\n return str.slice(0, max - 1) + '…'\n}\n\n/** Pad a string to a fixed width. */\nexport function pad(str: string, width: number): string {\n if (str.length >= width) return str.slice(0, width)\n return str + ' '.repeat(width - str.length)\n}\n\n/** Format a table with auto-column widths. */\nexport function printTable(rows: string[][], headers?: string[]): string {\n const allRows = headers ? [headers, ...rows] : rows\n if (allRows.length === 0) return ''\n\n const colCount = Math.max(...allRows.map(r => r.length))\n const widths: number[] = []\n for (let c = 0; c < colCount; c++) {\n widths[c] = Math.max(...allRows.map(r => (r[c] ?? '').length))\n }\n\n const formatted = allRows.map(row =>\n row.map((cell, i) => pad(cell, widths[i])).join(' ')\n )\n\n return formatted.join('\\n')\n}\n","/**\n * help + version commands.\n */\nimport { registerCommand, getAllCommands } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { pad } from '../output.ts'\n\nregisterCommand({\n name: 'help',\n aliases: ['h', '?'],\n description: 'Show list of all available commands.',\n usage: 'help [<command>]',\n async run(_conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n const target = args.positional[0]\n\n if (target) {\n const cmd = getAllCommands().find(c =>\n c.name === target || c.aliases?.includes(target)\n )\n if (!cmd) {\n return `Unknown command: ${target}\\n\\nRun 'abracadabra help' to see all commands.`\n }\n const aliasStr = cmd.aliases?.length ? ` (aliases: ${cmd.aliases.join(', ')})` : ''\n let text = `${cmd.name}${aliasStr}\\n ${cmd.description}`\n if (cmd.usage) text += `\\n\\n Usage: abracadabra ${cmd.usage}`\n return text\n }\n\n const cmds = getAllCommands()\n const maxLen = Math.max(...cmds.map(c => c.name.length))\n\n const lines = [\n 'Abracadabra CLI — interact with CRDT document workspaces from the terminal.',\n '',\n 'Usage: abracadabra <command> [key=value ...] [--flags]',\n '',\n 'Commands:',\n ...cmds.map(c => {\n const aliasStr = c.aliases?.length ? ` (${c.aliases.join(', ')})` : ''\n return ` ${pad(c.name, maxLen + 2)}${c.description}${aliasStr}`\n }),\n '',\n 'Environment:',\n ' ABRA_URL Server URL (required)',\n ' ABRA_KEY_FILE Path to Ed25519 key file',\n ' ABRA_INVITE_CODE Invite code for first-run registration',\n ' ABRA_NAME Display name',\n ' ABRA_COLOR Presence color',\n '',\n 'Run \"abracadabra help <command>\" for command-specific help.',\n ]\n return lines.join('\\n')\n },\n})\n\nregisterCommand({\n name: 'version',\n aliases: ['v'],\n description: 'Show CLI and server version.',\n async run(conn: CLIConnection | null): Promise<string> {\n const cliVersion = '1.0.0'\n const lines = [`Abracadabra CLI v${cliVersion}`]\n if (conn?.serverInfo) {\n const si = conn.serverInfo\n if (si.version) lines.push(`Server v${si.version}`)\n if (si.name) lines.push(`Server name ${si.name}`)\n if (si.protocol_version) lines.push(`Protocol ${si.protocol_version}`)\n }\n return lines.join('\\n')\n },\n})\n","/**\n * Document resolution utilities for the CLI.\n *\n * Resolves documents by id, name (label), or path (label chain from root).\n * Similar to Obsidian's file= / path= resolution.\n */\nimport * as Y from 'yjs'\nimport type { CLIConnection } from './connection.ts'\n\nexport interface TreeEntry {\n id: string\n label: string\n parentId: string | null\n order: number\n type?: string\n meta?: Record<string, unknown>\n createdAt?: number\n updatedAt?: number\n}\n\n/** Safely read a tree map value, converting Y.Map to plain object if needed. */\nfunction toPlain(val: any): any {\n return val instanceof Y.Map ? val.toJSON() : val\n}\n\n/** Read all tree entries from the Y.Map. */\nexport function readEntries(treeMap: Y.Map<any>): TreeEntry[] {\n const entries: TreeEntry[] = []\n treeMap.forEach((raw: any, id: string) => {\n const value = toPlain(raw)\n if (typeof value !== 'object' || value === null) return\n entries.push({\n id,\n label: value.label || 'Untitled',\n parentId: value.parentId ?? null,\n order: value.order ?? 0,\n type: value.type,\n meta: value.meta,\n createdAt: value.createdAt,\n updatedAt: value.updatedAt,\n })\n })\n return entries\n}\n\n/** Get direct children of a parent, sorted by order. */\nexport function childrenOf(entries: TreeEntry[], parentId: string | null): TreeEntry[] {\n return entries\n .filter(e => e.parentId === parentId)\n .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))\n}\n\n/** Get all descendants of an entry. */\nexport function descendantsOf(entries: TreeEntry[], id: string | null): TreeEntry[] {\n const result: TreeEntry[] = []\n const visited = new Set<string>()\n function collect(pid: string) {\n if (visited.has(pid)) return\n visited.add(pid)\n for (const child of childrenOf(entries, pid)) {\n result.push(child)\n collect(child.id)\n }\n }\n collect(id!)\n return result\n}\n\n/** Build a nested tree structure for display. */\nexport function buildTree(entries: TreeEntry[], rootId: string | null, maxDepth: number, currentDepth = 0, visited = new Set<string>()): TreeDisplayNode[] {\n if (maxDepth >= 0 && currentDepth >= maxDepth) return []\n const children = childrenOf(entries, rootId)\n return children.filter(e => !visited.has(e.id)).map(entry => {\n const next = new Set(visited)\n next.add(entry.id)\n return {\n id: entry.id,\n label: entry.label,\n type: entry.type,\n meta: entry.meta,\n children: buildTree(entries, entry.id, maxDepth, currentDepth + 1, next),\n }\n })\n}\n\nexport interface TreeDisplayNode {\n id: string\n label: string\n type?: string\n meta?: Record<string, unknown>\n children: TreeDisplayNode[]\n}\n\n/**\n * Normalize a document ID so the hub/root doc ID is treated as the tree root (null).\n */\nexport function normalizeRootId(id: string | null | undefined, conn: CLIConnection): string | null {\n if (id == null) return null\n return id === conn.rootDocId ? null : id\n}\n\n/**\n * Resolve a document from parsed args.\n *\n * Resolution order:\n * 1. id=<uuid> — Direct document ID\n * 2. name=<label> — Case-insensitive label match (first match wins)\n * 3. path=<a/b/c> — Resolve by label path from root\n * 4. First positional argument — tries name resolution\n *\n * Returns the document ID or null if not found.\n */\nexport function resolveDocument(\n conn: CLIConnection,\n params: Record<string, string>,\n positional: string[],\n): string | null {\n const treeMap = conn.getTreeMap()\n if (!treeMap) return null\n\n const entries = readEntries(treeMap)\n\n // 1. Direct ID\n if (params['id']) {\n const entry = entries.find(e => e.id === params['id'])\n return entry ? entry.id : null\n }\n\n // 2. Name resolution (case-insensitive label match)\n const name = params['name'] || params['file'] || positional[0]\n if (name) {\n const lower = name.toLowerCase()\n const match = entries.find(e => e.label.toLowerCase() === lower)\n if (match) return match.id\n\n // Substring match as fallback\n const substring = entries.find(e => e.label.toLowerCase().includes(lower))\n if (substring) return substring.id\n }\n\n // 3. Path resolution (slash-separated label chain)\n if (params['path']) {\n const segments = params['path'].split('/').map(s => s.trim()).filter(Boolean)\n let currentParent: string | null = normalizeRootId(conn.rootDocId, conn)\n\n for (const segment of segments) {\n const lower = segment.toLowerCase()\n const children = childrenOf(entries, currentParent)\n const match = children.find(c => c.label.toLowerCase() === lower)\n if (!match) return null\n currentParent = match.id\n }\n\n return currentParent\n }\n\n return null\n}\n\n/** Get the ancestor path labels for a document. */\nexport function getAncestorPath(entries: TreeEntry[], docId: string): string[] {\n const byId = new Map(entries.map(e => [e.id, e]))\n const path: string[] = []\n let current = byId.get(docId)?.parentId\n const visited = new Set<string>()\n while (current && !visited.has(current)) {\n visited.add(current)\n const parent = byId.get(current)\n if (!parent) break\n path.unshift(parent.label)\n current = parent.parentId\n }\n return path\n}\n","/**\n * spaces, spaces:switch, info commands.\n */\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { printJson, printTable, getFormat } from '../output.ts'\nimport { readEntries } from '../resolve.ts'\n\nregisterCommand({\n name: 'info',\n description: 'Show server and space info.',\n async run(conn: CLIConnection | null): Promise<string> {\n if (!conn) return 'Not connected'\n const si = conn.serverInfo\n if (!si) return 'No server info available'\n\n const treeMap = conn.getTreeMap()\n const docCount = treeMap ? readEntries(treeMap).length : 0\n\n const rootProvider = conn.rootProvider\n const onlineUsers = rootProvider\n ? Array.from(rootProvider.awareness.getStates().values()).filter((s: any) => s.user).length\n : 0\n\n const lines = [\n `Server: ${si.name ?? '—'}`,\n `URL: ${conn.config.url}`,\n `Version: ${si.version ?? '—'}`,\n `Protocol: ${si.protocol_version ?? '—'}`,\n `Active Doc: ${conn.rootDocId ?? '—'}`,\n `Auth: ${si.auth_methods?.join(', ') ?? '—'}`,\n `Registration:${si.registration_allowed ? ' open' : ' closed'}${si.invite_only ? ' (invite only)' : ''}`,\n `Documents: ${docCount}`,\n `Users: ${onlineUsers} online`,\n ]\n return lines.join('\\n')\n },\n})\n\nregisterCommand({\n name: 'spaces',\n description: 'List available spaces (top-level documents).',\n usage: 'spaces [--format=json|tsv]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n const spaces = conn.spaces\n if (!spaces.length) return 'No spaces available.'\n\n const format = getFormat(args, 'text')\n const active = conn.rootDocId\n\n if (format === 'json') {\n return printJson(spaces.map(s => ({ ...s, active: s.id === active })))\n }\n\n const rows = spaces.map(s => {\n const visibility = s.public_access === 'observer' ? 'public' : 'private'\n return [\n s.id === active ? '▸' : ' ',\n s.id.slice(0, 8) + '…',\n s.label ?? s.id,\n visibility,\n ]\n })\n\n return printTable(rows, ['', 'ID', 'NAME', 'VISIBILITY'])\n },\n})\n\nregisterCommand({\n name: 'spaces:switch',\n aliases: ['switch'],\n description: 'Switch the active space.',\n usage: 'spaces:switch name=<name> | id=<docId>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const targetName = args.params['name'] || args.positional[0]\n const targetId = args.params['id']\n\n let docId: string | null = null\n\n if (targetId) {\n docId = targetId\n } else if (targetName) {\n const lower = targetName.toLowerCase()\n const space = conn.spaces.find(s =>\n (s.label ?? s.id).toLowerCase() === lower || s.id === targetName\n )\n if (space) docId = space.id\n }\n\n if (!docId) {\n return 'Space not found. Use \"abracadabra spaces\" to list available spaces.'\n }\n\n await conn.switchSpace(docId)\n const space = conn.spaces.find(s => s.id === docId)\n return `Switched to space \"${space?.label ?? docId}\"`\n },\n})\n","/**\n * tree, ls, search commands — navigate and explore the document tree.\n */\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport {\n readEntries,\n childrenOf,\n buildTree,\n normalizeRootId,\n resolveDocument,\n getAncestorPath,\n type TreeDisplayNode,\n} from '../resolve.ts'\nimport { printJson, printTable, printTree, getFormat, relativeTime, type TreeNode } from '../output.ts'\n\nfunction toTreeNodes(nodes: TreeDisplayNode[]): TreeNode[] {\n return nodes.map(n => ({\n label: n.label,\n type: n.type,\n children: n.children.length > 0 ? toTreeNodes(n.children) : undefined,\n }))\n}\n\nregisterCommand({\n name: 'tree',\n aliases: ['t'],\n description: 'Show the full document tree hierarchy.',\n usage: 'tree [id=<docId>] [depth=<n>] [--format=json|tree]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const rootId = normalizeRootId(\n args.params['id'] || args.positional[0] || conn.rootDocId,\n conn\n )\n const maxDepth = args.params['depth'] ? parseInt(args.params['depth'], 10) : -1\n const format = getFormat(args, 'tree')\n\n const entries = readEntries(treeMap)\n const tree = buildTree(entries, rootId, maxDepth)\n\n if (format === 'json') {\n return printJson(tree)\n }\n\n if (tree.length === 0) {\n return '(empty tree)'\n }\n\n // Find root label for header — the active Space, falling back to its id.\n const activeSpace = conn.spaces.find(s => s.id === conn.rootDocId)\n const rootLabel = activeSpace?.label ?? conn.rootDocId ?? 'Workspace'\n\n return rootLabel + '\\n' + printTree(toTreeNodes(tree))\n },\n})\n\nregisterCommand({\n name: 'ls',\n aliases: ['list', 'l'],\n description: 'List direct children of a document (defaults to root).',\n usage: 'ls [id=<parentId>] [name=<parentName>] [--format=json|tsv] [--total]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n let parentId: string | null = null\n if (args.params['id'] || args.params['name'] || args.params['path'] || args.positional[0]) {\n parentId = resolveDocument(conn, args.params, args.positional)\n if (!parentId && (args.params['id'] || args.params['name'] || args.params['path'])) {\n return 'Document not found.'\n }\n }\n\n const targetId = normalizeRootId(parentId || conn.rootDocId, conn)\n const entries = readEntries(treeMap)\n const children = childrenOf(entries, targetId)\n\n if (args.flags.has('total')) {\n return String(children.length)\n }\n\n const format = getFormat(args, 'text')\n\n if (format === 'json') {\n return printJson(children)\n }\n\n if (children.length === 0) {\n return '(no children)'\n }\n\n const rows = children.map(c => [\n c.id.slice(0, 8) + '…',\n c.label,\n c.type ?? '—',\n relativeTime(c.updatedAt),\n ])\n\n return printTable(rows, ['ID', 'LABEL', 'TYPE', 'UPDATED'])\n },\n})\n\nregisterCommand({\n name: 'search',\n aliases: ['find', 's'],\n description: 'Search documents by label across the tree.',\n usage: 'search query=<text> [id=<rootId>] [--format=json|tsv] [--total]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const query = args.params['query'] || args.positional[0]\n if (!query) return 'Missing required parameter: query=<text>'\n\n const entries = readEntries(treeMap)\n const lowerQuery = query.toLowerCase()\n\n const matches = entries.filter(e =>\n e.label.toLowerCase().includes(lowerQuery)\n )\n\n if (args.flags.has('total')) {\n return String(matches.length)\n }\n\n const format = getFormat(args, 'text')\n\n if (matches.length === 0) {\n return `No documents found matching \"${query}\".`\n }\n\n const results = matches.map(entry => ({\n id: entry.id,\n label: entry.label,\n type: entry.type,\n path: getAncestorPath(entries, entry.id),\n }))\n\n if (format === 'json') {\n return printJson(results)\n }\n\n const rows = results.map(r => [\n r.path.length > 0 ? r.path.join(' / ') + ' / ' + r.label : r.label,\n r.label,\n r.type ?? '—',\n ])\n\n return printTable(rows, ['PATH', 'LABEL', 'TYPE'])\n },\n})\n","import * as Y from 'yjs'\nimport type { DocPageMeta } from './types.ts'\n\n// ── Filename → readable label ────────────────────────────────────────────────\n\n/**\n * Converts a filename (without extension) to a human-readable label.\n *\n * - `this-is-a-doc` → `\"This is a doc\"` (kebab/snake: sentence case)\n * - `ThisIsADoc` → `\"This Is A Doc\"` (PascalCase: preserves word caps)\n * - `thisIsADoc` → `\"This Is A Doc\"` (camelCase: preserves word caps)\n */\nexport function filenameToLabel(raw: string): string {\n const base = raw.replace(/\\.[^.]+$/, '') // strip extension if present\n const spaced = base.replace(/([a-z])([A-Z])/g, '$1 $2')\n const clean = spaced.replace(/[-_.]+/g, ' ').replace(/\\s+/g, ' ').trim()\n return clean.charAt(0).toUpperCase() + clean.slice(1)\n}\n\n// ── YAML frontmatter parser ──────────────────────────────────────────────────\n\nexport interface FrontmatterResult {\n title?: string\n type?: string\n meta: Partial<DocPageMeta>\n body: string\n}\n\nfunction coerceScalar(raw: string): string | number | boolean {\n const trimmed = raw.trim()\n if (trimmed === 'true') return true\n if (trimmed === 'false') return false\n const num = Number(trimmed)\n if (!Number.isNaN(num) && trimmed !== '') return num\n // Strip surrounding quotes\n if ((trimmed.startsWith('\"') && trimmed.endsWith('\"'))\n || (trimmed.startsWith('\\'') && trimmed.endsWith('\\''))) {\n return trimmed.slice(1, -1)\n }\n return trimmed\n}\n\nfunction parseInlineArray(raw: string): string[] {\n // e.g. \"[a, b, c]\"\n return raw.slice(1, -1).split(',').map(s => s.trim()).filter(Boolean)\n}\n\nfunction stripQuotes(s: string): string {\n if (s.length >= 2\n && ((s.startsWith('\"') && s.endsWith('\"'))\n || (s.startsWith('\\'') && s.endsWith('\\'')))) {\n return s.slice(1, -1).replace(/\\\\\"/g, '\"').replace(/\\\\\\\\/g, '\\\\')\n }\n return s\n}\n\nexport function parseFrontmatter(markdown: string): FrontmatterResult {\n const noResult: FrontmatterResult = { meta: {}, body: markdown }\n\n const match = markdown.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/)\n if (!match) return noResult\n\n const yamlBlock = match[1]!\n const body = markdown.slice(match[0].length)\n\n // Parse YAML into a raw map\n const raw: Record<string, string | string[]> = {}\n const lines = yamlBlock.split('\\n')\n let i = 0\n while (i < lines.length) {\n const line = lines[i]!\n // Block sequence: \"key:\\n - a\\n - b\"\n const blockSeqKey = line.match(/^(\\w[\\w-]*):\\s*$/)\n if (blockSeqKey && i + 1 < lines.length && /^\\s+-\\s/.test(lines[i + 1]!)) {\n const key = blockSeqKey[1]!\n const items: string[] = []\n i++\n while (i < lines.length && /^\\s+-\\s/.test(lines[i]!)) {\n items.push(lines[i]!.replace(/^\\s+-\\s/, '').trim())\n i++\n }\n raw[key] = items\n continue\n }\n // Scalar or inline array\n const kvMatch = line.match(/^(\\w[\\w-]*):\\s*(.*)$/)\n if (kvMatch) {\n const key = kvMatch[1]!\n const val = kvMatch[2]!.trim()\n if (val.startsWith('[') && val.endsWith(']')) {\n raw[key] = parseInlineArray(val).map(stripQuotes)\n } else {\n // Strip surrounding quotes up-front so downstream readers\n // don't have to. The original quote state is irrelevant — we\n // re-emit with our canonical quoting rules.\n raw[key] = stripQuotes(val)\n }\n }\n i++\n }\n\n // Map raw YAML keys → PageMeta\n const meta: Partial<DocPageMeta> = {}\n\n const getStr = (keys: string[]): string | undefined => {\n for (const k of keys) {\n const v = raw[k]\n if (typeof v === 'string' && v) return v\n }\n }\n const getArr = (keys: string[]): string[] | undefined => {\n for (const k of keys) {\n const v = raw[k]\n if (Array.isArray(v)) return v\n if (typeof v === 'string' && v) return [v]\n }\n }\n\n if (raw['tags']) meta.tags = Array.isArray(raw['tags']) ? raw['tags'] : [raw['tags'] as string]\n const color = getStr(['color'])\n if (color) meta.color = color\n const icon = getStr(['icon'])\n if (icon) meta.icon = icon\n const status = getStr(['status'])\n if (status) meta.status = status\n\n const priorityRaw = getStr(['priority'])\n if (priorityRaw !== undefined) {\n const map: Record<string, number> = { low: 1, medium: 2, high: 3, urgent: 4 }\n meta.priority = map[priorityRaw.toLowerCase()] ?? (Number(priorityRaw) || 0)\n }\n\n const checkedRaw: unknown = raw['checked'] ?? raw['done']\n if (checkedRaw !== undefined) meta.checked = checkedRaw === 'true' || checkedRaw === true\n\n // Canonical keys are checked first, aliases follow — so files that\n // already use the canonical name (dateStart, dateEnd, subtitle) keep\n // round-tripping byte-stably while legacy aliases still parse.\n const dateStart = getStr(['dateStart', 'date', 'created'])\n if (dateStart) meta.dateStart = dateStart\n const dateEnd = getStr(['dateEnd', 'due'])\n if (dateEnd) meta.dateEnd = dateEnd\n\n const subtitle = getStr(['subtitle', 'description'])\n if (subtitle) meta.subtitle = subtitle\n const url = getStr(['url'])\n if (url) meta.url = url\n\n // Code page type meta.\n const language = getStr(['language'])\n if (language) meta.language = language\n const fileExtension = getStr(['fileExtension'])\n if (fileExtension) meta.fileExtension = fileExtension\n const codeTheme = getStr(['codeTheme'])\n if (codeTheme) meta.codeTheme = codeTheme\n\n const ratingRaw = getStr(['rating'])\n if (ratingRaw !== undefined) {\n const n = Number(ratingRaw)\n if (!Number.isNaN(n)) meta.rating = Math.min(5, Math.max(0, n))\n }\n\n const rawTitle = typeof raw['title'] === 'string' ? raw['title'] : undefined\n const title = rawTitle !== undefined ? stripQuotes(rawTitle) : undefined\n const type = getStr(['type'])\n\n return { title, type, meta, body }\n}\n\n// ── Inline token parsing ─────────────────────────────────────────────────────\n\ninterface InlineToken {\n text: string\n attrs?: Record<string, unknown>\n}\n\n// Re-tokenize the inner text of a wrapping mark (bold/italic/strike) so nested\n// atoms (wikilinks, mentions, code, math) and nested marks survive instead of\n// being captured as a single literal leaf. The wrapping mark's attrs are merged\n// onto every produced child token; object-valued attrs (docLink/mention/badge)\n// are preserved alongside the boolean mark. Terminates because `inner` is\n// strictly shorter than the matched delimiter run.\nfunction pushNested(\n out: InlineToken[],\n inner: string,\n wrap: Record<string, unknown>,\n): void {\n const children = parseInline(inner)\n if (children.length === 0) {\n out.push({ text: inner, attrs: { ...wrap } })\n return\n }\n for (const child of children) {\n out.push({ text: child.text, attrs: { ...(child.attrs ?? {}), ...wrap } })\n }\n}\n\nfunction parseInline(text: string): InlineToken[] {\n // Strip MDC attribute annotations on inline code: `string`{lang=\"ts-type\"}\n const stripped = text.replace(/\\{lang=\"[^\"]*\"\\}/g, '')\n // Strip remaining unknown inline MDC components (but NOT badge/icon/kbd — handled below)\n .replace(/:(?!badge|icon|kbd)(\\w[\\w-]*)\\[([^\\]]*)\\](\\{[^}]*\\})?/g, '$2')\n .replace(/:(?!badge|icon|kbd)(\\w[\\w-]*)(\\{[^}]*\\})/g, '')\n\n const tokens: InlineToken[] = []\n // Order matters: math (`$\\u2026$`) before italic (so `$x$` doesn't match\n // `$ \\u2026 $` as italic-with-dollars); inline MDC first; mentions before\n // plain `[\\u2026]` links; wikilinks before plain brackets; strikethrough;\n // bold before italic.\n const re = /\\$([^$\\n]+?)\\$|@\\[([^\\]]+?)\\]\\(user:([^)]+?)\\)|:badge\\[([^\\]]*)\\](\\{[^}]*\\})?|:icon\\{([^}]*)\\}|:kbd\\{([^}]*)\\}|\\[\\[([0-9a-fA-F-]{36})(?:\\|([^\\]]+?))?\\]\\]|~~(.+?)~~|\\*\\*(.+?)\\*\\*|\\*(.+?)\\*|_(.+?)_|`(.+?)`|\\[(.+?)\\]\\((.+?)\\)/g\n let lastIndex = 0\n let match: RegExpExecArray | null\n\n while ((match = re.exec(stripped)) !== null) {\n if (match.index > lastIndex) {\n tokens.push({ text: stripped.slice(lastIndex, match.index) })\n }\n if (match[1] !== undefined) {\n // $expression$ \\u2014 inline math atom\n tokens.push({ text: match[1], attrs: { mathInline: { expression: match[1] } } })\n } else if (match[2] !== undefined && match[3] !== undefined) {\n // @[label](user:uuid) \\u2014 mention atom\n tokens.push({ text: match[2], attrs: { mention: { userId: match[3], label: match[2] } } })\n } else if (match[4] !== undefined) {\n // :badge[text]{props}\n const badgeProps = parseMdcProps(match[5])\n tokens.push({ text: match[4] || 'Badge', attrs: { badge: { label: match[4] || 'Badge', color: badgeProps['color'] || 'neutral', variant: badgeProps['variant'] || 'subtle' } } })\n } else if (match[6] !== undefined) {\n // :icon{name=\"...\"}\n const iconProps = parseMdcProps(`{${match[6]}}`)\n tokens.push({ text: '\\u200B', attrs: { proseIcon: { name: iconProps['name'] || 'i-lucide-star' } } })\n } else if (match[7] !== undefined) {\n // :kbd{value=\"...\"}\n const kbdProps = parseMdcProps(`{${match[7]}}`)\n tokens.push({ text: kbdProps['value'] || '', attrs: { kbd: { value: kbdProps['value'] || '' } } })\n } else if (match[8] !== undefined) {\n // [[uuid]] or [[uuid|label]] \\u2014 inline doc link atom. The docId\n // is the canonical anchor; the label is display-only. The\n // serialiser may regenerate the label from a live doc registry\n // (see SPEC.md \\u00A76); when no resolver is supplied, the parser's\n // stored display text is reused on emit.\n const docId = match[8]\n const label = match[9] ?? docId\n tokens.push({ text: label, attrs: { docLink: { docId } } })\n } else if (match[10] !== undefined) {\n pushNested(tokens, match[10], { strike: true })\n } else if (match[11] !== undefined) {\n pushNested(tokens, match[11], { bold: true })\n } else if (match[12] !== undefined) {\n pushNested(tokens, match[12], { italic: true })\n } else if (match[13] !== undefined) {\n pushNested(tokens, match[13], { italic: true })\n } else if (match[14] !== undefined) {\n tokens.push({ text: match[14], attrs: { code: true } })\n } else if (match[15] !== undefined && match[16] !== undefined) {\n tokens.push({ text: match[15], attrs: { link: { href: match[16] } } })\n }\n lastIndex = match.index + match[0].length\n }\n\n if (lastIndex < stripped.length) {\n tokens.push({ text: stripped.slice(lastIndex) })\n }\n return tokens.filter(t => t.text.length > 0)\n}\n\n// ── Block-level parser ───────────────────────────────────────────────────────\n\ninterface TaskItem {\n text: string\n checked: boolean\n}\n\ninterface ListItemBlock {\n text: string\n innerBlocks?: Block[]\n checked?: boolean\n}\n\ntype Block\n = | { type: 'heading', level: number, text: string }\n | { type: 'paragraph', text: string }\n | { type: 'bulletList', items: ListItemBlock[] }\n | { type: 'orderedList', items: ListItemBlock[] }\n | { type: 'taskList', items: ListItemBlock[] }\n | { type: 'codeBlock', lang: string, code: string }\n | { type: 'blockquote', lines: string[] }\n | { type: 'table', headerRow: string[], dataRows: string[][] }\n | { type: 'hr' }\n | { type: 'callout', calloutType: string, innerBlocks: Block[] }\n | { type: 'collapsible', label: string, open: boolean, innerBlocks: Block[] }\n | { type: 'steps', innerBlocks: Block[] }\n | { type: 'card', title: string, icon: string, to: string, innerBlocks: Block[] }\n | { type: 'cardGroup', cards: Block[] }\n | { type: 'codeCollapse', codeBlocks: Block[] }\n | { type: 'codeGroup', codeBlocks: Block[] }\n | { type: 'codePreview', innerBlocks: Block[], codeBlocks: Block[] }\n | { type: 'codeTree', files: string }\n | { type: 'accordion', items: { label: string, icon: string, innerBlocks: Block[] }[] }\n | { type: 'tabs', items: { label: string, icon: string, innerBlocks: Block[] }[] }\n | { type: 'field', name: string, fieldType: string, required: boolean, innerBlocks: Block[] }\n | { type: 'fieldGroup', fields: Block[] }\n | { type: 'image', src: string, alt: string, width?: string, height?: string }\n | { type: 'docEmbed', docId: string, label: string, props: Record<string, string> }\n | { type: 'mathBlock', expression: string }\n | { type: 'fileBlock', src: string, mime: string, uploadId: string, filename: string }\n\nfunction parseTableRow(line: string): string[] {\n const parts = line.split('|')\n // Remove the first and last (empty from leading/trailing |) and trim each\n return parts.slice(1, parts.length - 1).map(c => c.trim())\n}\n\nfunction isTableSeparator(line: string): boolean {\n return /^\\|[\\s|:-]+\\|$/.test(line.trim())\n}\n\n/** Extract fenced code blocks from MDC #code slot lines. */\nfunction extractFencedCode(lines: string[]): Block[] {\n const result: Block[] = []\n let i = 0\n while (i < lines.length) {\n const line = lines[i]!\n // Match opening fence (```, ````, etc.)\n const fenceMatch = line.match(/^(`{3,})(\\w*)/)\n if (fenceMatch) {\n const fence = fenceMatch[1]!\n const lang = fenceMatch[2] ?? ''\n const codeLines: string[] = []\n i++\n while (i < lines.length && !lines[i]!.startsWith(fence)) {\n codeLines.push(lines[i]!)\n i++\n }\n i++ // skip closing fence\n result.push({ type: 'codeBlock', lang, code: codeLines.join('\\n') })\n continue\n }\n i++\n }\n return result\n}\n\n/** Extract key=\"value\" pairs from MDC prop syntax `{key=\"value\" other=\"x\"}` */\nfunction parseMdcProps(propsStr: string | undefined): Record<string, string> {\n if (!propsStr) return {}\n const result: Record<string, string> = {}\n // Drop the wrapping `{ … }` if present.\n let s = propsStr.trim()\n if (s.startsWith('{') && s.endsWith('}')) s = s.slice(1, -1)\n\n // Three accepted shapes per SPEC.md §5:\n // key=\"value\" (quoted)\n // key=value (bare, no whitespace)\n // key (boolean shorthand → \"true\")\n const re = /(\\w[\\w-]*)(?:=(?:\"([^\"]*)\"|([^\\s\"}]+)))?/g\n let m: RegExpExecArray | null\n while ((m = re.exec(s)) !== null) {\n const key = m[1]!\n if (m[2] !== undefined) result[key] = m[2]\n else if (m[3] !== undefined) result[key] = m[3]\n else result[key] = 'true'\n }\n return result\n}\n\n/** Parse named child MDC blocks from inner lines (e.g. #item for accordion, #tab for tabs) */\nfunction parseMdcChildren(innerLines: string[], slotPrefix: string): { label: string, icon: string, innerBlocks: Block[] }[] {\n const items: { label: string, icon: string, lines: string[] }[] = []\n let current: { label: string, icon: string, lines: string[] } | null = null\n const slotRe = new RegExp(`^#${slotPrefix}(\\\\{[^}]*\\\\})?\\\\s*$`)\n\n for (const line of innerLines) {\n const slotMatch = line.match(slotRe)\n if (slotMatch) {\n if (current) items.push(current)\n const props = parseMdcProps(slotMatch[1])\n current = { label: props['label'] || props['title'] || `Item ${items.length + 1}`, icon: props['icon'] || '', lines: [] }\n continue\n }\n if (current) {\n current.lines.push(line)\n } else {\n // Content before first slot — treat as first unnamed item\n if (!items.length && !current) {\n current = { label: `Item 1`, icon: '', lines: [line] }\n }\n }\n }\n if (current) items.push(current)\n\n return items.map(item => ({\n label: item.label,\n icon: item.icon,\n innerBlocks: parseBlocks(item.lines.join('\\n'))\n }))\n}\n\nconst TASK_RE = /^[-*+]\\s+\\[([ xX])\\]\\s+(.*)/\n\n/**\n * Consume a list (bullet / ordered / task) starting at `start`. Indented\n * continuation lines and nested lists are captured into each item's\n * `innerBlocks` so the parse → serialise → parse cycle preserves tree\n * structure instead of flattening nested lists onto a single line.\n *\n * `indent` is the column of the item marker for the current list. A\n * nested list starts ≥2 columns deeper. Lines with less indent than\n * `indent` belong to the outer block and stop consumption.\n */\nfunction consumeList(\n lines: string[],\n start: number,\n indent: number,\n kind: 'bullet' | 'ordered' | 'task',\n): { items: ListItemBlock[], next: number } {\n const items: ListItemBlock[] = []\n let i = start\n while (i < lines.length) {\n const line = lines[i]!\n if (line.trim() === '') {\n // Blank line — peek ahead: if the next non-blank line still\n // belongs to this list, treat the blank as an inter-item\n // separator. Otherwise terminate.\n let j = i + 1\n while (j < lines.length && lines[j]!.trim() === '') j++\n if (j >= lines.length) break\n const lookahead = lines[j]!\n if (leadingSpaces(lookahead) < indent) break\n if (!matchMarker(lookahead.slice(indent), kind)) break\n i = j\n continue\n }\n const leading = leadingSpaces(line)\n if (leading < indent) break\n if (leading > indent) break // belongs to a nested list opened by the previous item\n const deindented = line.slice(indent)\n const m = matchMarker(deindented, kind)\n if (!m) break\n\n const item: ListItemBlock = { text: m.text }\n if (kind === 'task') item.checked = m.checked\n i++\n\n // Consume continuation: lines indented deeper than `indent`.\n const contLines: string[] = []\n while (i < lines.length) {\n const next = lines[i]!\n if (next.trim() === '') {\n // Blank inside a continuation block — could be part of the\n // continuation if the next non-blank is still indented. Peek.\n let k = i + 1\n while (k < lines.length && lines[k]!.trim() === '') k++\n if (k >= lines.length) break\n const peekIndent = leadingSpaces(lines[k]!)\n if (peekIndent <= indent) break\n // Carry forward the blank line as a paragraph separator.\n contLines.push('')\n i++\n continue\n }\n const nextIndent = leadingSpaces(next)\n if (nextIndent <= indent) break\n // De-indent by exactly 2 to match the canonical wire form.\n const deindentBy = Math.min(nextIndent, indent + 2)\n contLines.push(next.slice(deindentBy))\n i++\n }\n if (contLines.length > 0) {\n item.innerBlocks = parseBlocks(contLines.join('\\n'))\n }\n items.push(item)\n }\n return { items, next: i }\n}\n\nfunction leadingSpaces(s: string): number {\n let n = 0\n while (n < s.length && s[n] === ' ') n++\n return n\n}\n\nfunction matchMarker(\n s: string,\n kind: 'bullet' | 'ordered' | 'task',\n): { text: string, checked: boolean } | null {\n if (kind === 'task') {\n const m = s.match(TASK_RE)\n if (!m) return null\n return { text: m[2]!, checked: m[1]!.toLowerCase() === 'x' }\n }\n if (kind === 'bullet') {\n if (TASK_RE.test(s)) return null\n const m = s.match(/^[-*+]\\s+(.*)$/)\n if (!m) return null\n return { text: m[1]!, checked: false }\n }\n // ordered\n const m = s.match(/^\\d+\\.\\s+(.*)$/)\n if (!m) return null\n return { text: m[1]!, checked: false }\n}\n\nfunction parseBlocks(markdown: string): Block[] {\n // Strip top-level MDX import/export lines (only before the first content block).\n // We must NOT strip `export default ...` etc. inside fenced code blocks.\n const rawLines = markdown.split('\\n')\n let firstContentLine = 0\n while (firstContentLine < rawLines.length) {\n const l = rawLines[firstContentLine]!\n if (l.trim() === '' || /^import\\s/.test(l) || /^export\\s/.test(l)) {\n firstContentLine++\n } else {\n break\n }\n }\n const stripped = rawLines.slice(firstContentLine).join('\\n')\n\n const blocks: Block[] = []\n const lines = stripped.split('\\n')\n let i = 0\n\n while (i < lines.length) {\n const line = lines[i]!\n\n // Fenced code block (supports variable-length fences: ```, ````, etc.)\n const fenceBlockMatch = line.match(/^(`{3,})(.*)$/)\n if (fenceBlockMatch) {\n const fence = fenceBlockMatch[1]!\n const lang = fenceBlockMatch[2]!.trim()\n .replace(/\\{[^}]*\\}$/, '') // strip highlight annotations like {4-5}\n .replace(/\\s*\\[.*\\]$/, '') // strip filename hints like [nuxt.config.ts]\n .trim()\n const codeLines: string[] = []\n i++\n while (i < lines.length && !lines[i]!.startsWith(fence)) {\n codeLines.push(lines[i]!)\n i++\n }\n i++ // skip closing fence\n const code = codeLines.join('\\n')\n if (lang === 'math') {\n // ```math … ``` — block math atom (SPEC.md §6).\n blocks.push({ type: 'mathBlock', expression: code })\n }\n else {\n blocks.push({ type: 'codeBlock', lang, code })\n }\n continue\n }\n\n // Heading\n const headingMatch = line.match(/^(#{1,6})\\s+(.*)/)\n if (headingMatch) {\n blocks.push({ type: 'heading', level: headingMatch[1]!.length, text: headingMatch[2]!.trim() })\n i++\n continue\n }\n\n // Horizontal rule\n if (/^[-*_]{3,}\\s*$/.test(line)) {\n blocks.push({ type: 'hr' })\n i++\n continue\n }\n\n // Doc embed: ![[uuid|label]]{collapsed tall seamless} — block-level,\n // must be on its own line. UUID is required (the bracket syntax\n // without one is reserved for inline doc-link).\n const embedMatch = line.match(/^!\\[\\[([0-9a-fA-F-]{36})(?:\\|([^\\]]+))?\\]\\](\\{[^}]*\\})?\\s*$/)\n if (embedMatch) {\n const docId = embedMatch[1]!\n const label = embedMatch[2] ?? ''\n const props = parseMdcProps(embedMatch[3])\n blocks.push({ type: 'docEmbed', docId, label, props })\n i++\n continue\n }\n\n // Image: ![alt](src){attrs} — must be on its own line\n const imgMatch = line.match(/^!\\[([^\\]]*)\\]\\(([^)]+)\\)(\\{[^}]*\\})?\\s*$/)\n if (imgMatch) {\n const alt = imgMatch[1] ?? ''\n const src = imgMatch[2] ?? ''\n const attrs = parseMdcProps(imgMatch[3])\n blocks.push({ type: 'image', src, alt, width: attrs['width'], height: attrs['height'] })\n i++\n continue\n }\n\n // Blockquote. Match any line that opens with `>` (CommonMark allows the\n // space after the marker to be omitted, e.g. `>50 comments`). The paragraph\n // collector below treats EVERY `>`-leading line as a block start, so this\n // branch must claim all of them — otherwise a `>x` line matches no branch\n // and the loop spins without advancing `i` (silent infinite hang).\n if (line.startsWith('>')) {\n const bqLines: string[] = []\n while (i < lines.length && lines[i]!.startsWith('>')) {\n bqLines.push(lines[i]!.replace(/^>\\s?/, ''))\n i++\n }\n blocks.push({ type: 'blockquote', lines: bqLines })\n continue\n }\n\n // Table — detect by leading pipe\n if (/^\\s*\\|/.test(line)) {\n const tableLines: string[] = []\n while (i < lines.length && /^\\s*\\|/.test(lines[i]!)) {\n tableLines.push(lines[i]!)\n i++\n }\n // Need at least: header row, separator row\n if (tableLines.length >= 2 && isTableSeparator(tableLines[1]!)) {\n const headerRow = parseTableRow(tableLines[0]!)\n const dataRows = tableLines.slice(2)\n .filter(l => !isTableSeparator(l))\n .map(parseTableRow)\n blocks.push({ type: 'table', headerRow, dataRows })\n } else {\n // Couldn't parse as table — emit as paragraphs\n for (const l of tableLines) blocks.push({ type: 'paragraph', text: l })\n }\n continue\n }\n\n // MDC atom block (single-colon, no body): `:name{props}` on its\n // own line. Currently recognised: `:file{…}` (fileBlock per\n // SPEC.md §7). Other atom blocks (`:video{…}`, `:embed{…}`, etc.)\n // are reserved for later workstreams.\n const atomMatch = line.match(/^:(\\w[\\w-]*)(\\{[^}]*\\})?\\s*$/)\n if (atomMatch && atomMatch[1] === 'file') {\n const props = parseMdcProps(atomMatch[2])\n const uploadId = props['upload-id'] ?? props['uploadId'] ?? ''\n const filename = props['filename'] ?? ''\n const mime = props['mime'] ?? ''\n const src = props['src'] ?? (uploadId && filename\n ? `.abracadabra/files/${uploadId}-${filename}`\n : '')\n blocks.push({ type: 'fileBlock', src, mime, uploadId, filename })\n i++\n continue\n }\n\n // MDC component block (::component-name ... ::)\n // Allow optional leading whitespace so indented nested blocks are recognised\n const MDC_OPEN = /^\\s*(:{2,})(\\w[\\w-]*)(\\{[^}]*\\})?\\s*$/\n if (MDC_OPEN.test(line)) {\n const colons = line.match(/^\\s*(:+)/)?.[1]?.length ?? 2\n const componentName = line.match(/^\\s*:{2,}(\\w[\\w-]*)/)?.[1] ?? ''\n const innerLines: string[] = []\n i++\n // Collect inner lines, but skip over fenced code blocks so that\n // `::` inside ```...``` or ````...```` doesn't close the MDC block\n while (i < lines.length) {\n const l = lines[i]!\n // Closing tag: same colon count, possibly indented\n if (new RegExp(`^\\\\s*:{${colons}}\\\\s*$`).test(l)) { i++; break }\n // If we hit a fenced code block, consume it entirely\n const innerFence = l.match(/^(\\s*`{3,})/)\n if (innerFence) {\n const fenceStr = innerFence[1]!.trimStart()\n innerLines.push(l)\n i++\n while (i < lines.length && !lines[i]!.trimStart().startsWith(fenceStr)) {\n innerLines.push(lines[i]!)\n i++\n }\n if (i < lines.length) { innerLines.push(lines[i]!); i++ } // push closing fence\n continue\n }\n innerLines.push(l)\n i++\n }\n\n // Strip common leading indentation from inner lines\n const nonBlank = innerLines.filter(l => l.trim().length > 0)\n if (nonBlank.length) {\n const minIndent = Math.min(...nonBlank.map(l => l.match(/^(\\s*)/)?.[1]?.length ?? 0))\n if (minIndent > 0) {\n for (let j = 0; j < innerLines.length; j++) {\n innerLines[j] = innerLines[j]!.slice(Math.min(minIndent, innerLines[j]!.length))\n }\n }\n }\n\n // Strip inline frontmatter props (---...---)\n let contentStart = 0\n if (innerLines[0]?.trim() === '---') {\n const fmEnd = innerLines.findIndex((l, idx) => idx > 0 && l.trim() === '---')\n if (fmEnd !== -1) contentStart = fmEnd + 1\n }\n const contentLines = innerLines.slice(contentStart)\n\n // Split into named slots: collect default slot and #code slot separately\n const defaultSlotLines: string[] = []\n const codeSlotLines: string[] = []\n let currentSlot: 'default' | 'code' | 'other' = 'default'\n for (const l of contentLines) {\n if (/^#code\\s*$/.test(l)) { currentSlot = 'code'; continue }\n if (/^#\\w+/.test(l) && !/^#{2,}\\s/.test(l)) { currentSlot = 'other'; continue }\n if (currentSlot === 'default') defaultSlotLines.push(l)\n else if (currentSlot === 'code') codeSlotLines.push(l)\n }\n const innerBlocks = parseBlocks(defaultSlotLines.join('\\n'))\n\n // Extract fenced code from #code slot and add as code blocks\n const codeBlocks = extractFencedCode(codeSlotLines)\n\n const CALLOUT_NAMES = new Set(['tip', 'note', 'info', 'warning', 'caution', 'danger', 'callout', 'alert'])\n if (CALLOUT_NAMES.has(componentName.toLowerCase())) {\n blocks.push({ type: 'callout', calloutType: componentName.toLowerCase(), innerBlocks })\n } else {\n const mdcProps = parseMdcProps(line.match(MDC_OPEN)?.[3])\n const lc = componentName.toLowerCase()\n\n if (lc === 'collapsible') {\n blocks.push({ type: 'collapsible', label: mdcProps['label'] || 'Details', open: mdcProps['open'] === 'true', innerBlocks })\n } else if (lc === 'steps') {\n blocks.push({ type: 'steps', innerBlocks })\n } else if (lc === 'card') {\n blocks.push({ type: 'card', title: mdcProps['title'] || '', icon: mdcProps['icon'] || '', to: mdcProps['to'] || '', innerBlocks })\n } else if (lc === 'card-group') {\n // Each nested ::card inside card-group is already parsed as inner blocks\n const cards = innerBlocks.filter(b => b.type === 'card')\n if (cards.length) {\n blocks.push({ type: 'cardGroup', cards })\n } else {\n blocks.push(...innerBlocks)\n }\n } else if (lc === 'code-collapse') {\n blocks.push({ type: 'codeCollapse', codeBlocks: codeBlocks.length ? codeBlocks : innerBlocks.filter(b => b.type === 'codeBlock') })\n } else if (lc === 'code-group') {\n const allCode = [...innerBlocks.filter(b => b.type === 'codeBlock'), ...codeBlocks]\n blocks.push({ type: 'codeGroup', codeBlocks: allCode })\n } else if (lc === 'code-preview') {\n blocks.push({ type: 'codePreview', innerBlocks, codeBlocks })\n } else if (lc === 'code-tree') {\n blocks.push({ type: 'codeTree', files: mdcProps['files'] || '[]' })\n } else if (lc === 'accordion') {\n const items = parseMdcChildren(contentLines, 'item')\n if (items.length) {\n blocks.push({ type: 'accordion', items })\n } else {\n blocks.push({ type: 'accordion', items: [{ label: 'Item 1', icon: '', innerBlocks }] })\n }\n } else if (lc === 'tabs') {\n const items = parseMdcChildren(contentLines, 'tab')\n if (items.length) {\n blocks.push({ type: 'tabs', items })\n } else {\n blocks.push({ type: 'tabs', items: [{ label: 'Tab 1', icon: '', innerBlocks }] })\n }\n } else if (lc === 'field') {\n blocks.push({ type: 'field', name: mdcProps['name'] || '', fieldType: mdcProps['type'] || 'string', required: mdcProps['required'] === 'true', innerBlocks })\n } else if (lc === 'field-group') {\n const fields = innerBlocks.filter(b => b.type === 'field')\n if (fields.length) {\n blocks.push({ type: 'fieldGroup', fields })\n } else {\n blocks.push(...innerBlocks)\n }\n } else {\n // Unknown component — inline the content\n blocks.push(...innerBlocks)\n blocks.push(...codeBlocks)\n }\n }\n continue\n }\n\n // Task list (must check before bullet list — `- [x]` starts the same way)\n if (TASK_RE.test(line)) {\n const { items, next } = consumeList(lines, i, 0, 'task')\n i = next\n blocks.push({ type: 'taskList', items })\n continue\n }\n\n // Bullet list\n if (/^[-*+]\\s+/.test(line)) {\n const { items, next } = consumeList(lines, i, 0, 'bullet')\n if (items.length > 0) {\n i = next\n blocks.push({ type: 'bulletList', items })\n continue\n }\n }\n\n // Ordered list\n if (/^\\d+\\.\\s+/.test(line)) {\n const { items, next } = consumeList(lines, i, 0, 'ordered')\n if (items.length > 0) {\n i = next\n blocks.push({ type: 'orderedList', items })\n continue\n }\n }\n\n // Blank line\n if (line.trim() === '') {\n i++\n continue\n }\n\n // Paragraph — consecutive non-special lines\n const paraLines: string[] = []\n while (\n i < lines.length\n && lines[i]!.trim() !== ''\n && !/^(#{1,6}\\s|[-*+]\\s|\\d+\\.\\s|>|`{3,}|\\s*\\||[-*_]{3,}\\s*$|\\s*:{2,}\\w)/.test(lines[i]!)\n ) {\n paraLines.push(lines[i]!)\n i++\n }\n if (paraLines.length) {\n blocks.push({ type: 'paragraph', text: paraLines.join(' ') })\n } else {\n // No branch claimed this line and the paragraph collector rejected it too\n // (its guard excludes block-marker leads like `>`). Without forcing\n // progress here `i` never advances and parseBlocks hangs forever. Emit the\n // stray line as a paragraph so it survives the round-trip, and step past it.\n blocks.push({ type: 'paragraph', text: line })\n i++\n }\n }\n\n return blocks\n}\n\n// ── Y.js content population ──────────────────────────────────────────────────\n//\n// IMPORTANT — attach-before-fill ordering:\n//\n// Y.XmlText.insert() is only deterministically ordered when the text node is\n// already attached to a Y.Doc (so it can use the doc's logical clock).\n// Inserting text into a standalone Y.XmlText gives every operation clock-0,\n// which causes the YATA algorithm to produce reversed or scrambled text.\n//\n// Rule: attach container to doc → attach Y.XmlText to container → insert text.\n\n/**\n * Insert formatted inline tokens into an already-attached Y.XmlElement.\n * Creates one Y.XmlText per token (attach first, fill second).\n */\nfunction fillTextInto(el: Y.XmlElement, tokens: InlineToken[]): void {\n const filtered = tokens.filter(t => t.text.length > 0)\n if (!filtered.length) return\n\n // Build the child skeleton. A docLink is an inline ATOM NODE, not a text\n // mark: it must be a Y.XmlElement so the y-prosemirror binding materializes\n // it as a `docLink` node (its label is resolved live from the doc tree by\n // the renderer, never stored). Every other token is a Y.XmlText run.\n // Attach all children in one batch first (attach-before-fill), then fill.\n const children: (Y.XmlText | Y.XmlElement)[] = filtered.map((tok) => {\n const dl = tok.attrs?.docLink as { docId?: string } | undefined\n return dl?.docId ? new Y.XmlElement('docLink') : new Y.XmlText()\n })\n el.insert(0, children)\n\n // Fill only after attachment — el is already attached to the doc.\n filtered.forEach((tok, i) => {\n const node = children[i]!\n if (node instanceof Y.XmlElement) {\n const dl = tok.attrs!.docLink as { docId: string }\n node.setAttribute('docId', dl.docId)\n return\n }\n if (tok.attrs) {\n node.insert(0, tok.text, tok.attrs as Record<string, boolean | object>)\n } else {\n node.insert(0, tok.text)\n }\n })\n}\n\nfunction blockElName(b: Block): string {\n switch (b.type) {\n case 'heading': return 'heading'\n case 'paragraph': return 'paragraph'\n case 'bulletList': return 'bulletList'\n case 'orderedList': return 'orderedList'\n case 'taskList': return 'taskList'\n case 'codeBlock': return 'codeBlock'\n case 'blockquote': return 'blockquote'\n case 'table': return 'table'\n case 'hr': return 'horizontalRule'\n case 'callout': return 'callout'\n case 'collapsible': return 'collapsible'\n case 'steps': return 'steps'\n case 'card': return 'card'\n case 'cardGroup': return 'cardGroup'\n case 'codeCollapse': return 'codeCollapse'\n case 'codeGroup': return 'codeGroup'\n case 'codePreview': return 'codePreview'\n case 'codeTree': return 'codeTree'\n case 'accordion': return 'accordion'\n case 'tabs': return 'tabs'\n case 'field': return 'field'\n case 'fieldGroup': return 'fieldGroup'\n case 'image': return 'image'\n case 'docEmbed': return 'docEmbed'\n case 'mathBlock': return 'mathBlock'\n case 'fileBlock': return 'fileBlock'\n }\n}\n\nfunction populateListItemChildren(\n itemEl: Y.XmlElement,\n item: ListItemBlock,\n _itemKind: 'listItem' | 'taskItem',\n): void {\n // Always start with a paragraph carrying the item's inline text.\n const paraEl = new Y.XmlElement('paragraph')\n itemEl.insert(itemEl.length, [paraEl])\n fillTextInto(paraEl, parseInline(item.text))\n\n // Nested blocks (sub-lists, paragraphs, code, etc.) follow.\n if (!item.innerBlocks?.length) return\n const innerEls = item.innerBlocks.map(b => new Y.XmlElement(blockElName(b)))\n itemEl.insert(itemEl.length, innerEls)\n item.innerBlocks.forEach((b, i) => fillBlock(innerEls[i]!, b))\n}\n\nfunction fillBlock(el: Y.XmlElement, block: Block): void {\n switch (block.type) {\n case 'heading': {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n el.setAttribute('level', block.level as any)\n fillTextInto(el, parseInline(block.text))\n break\n }\n case 'paragraph': {\n fillTextInto(el, parseInline(block.text))\n break\n }\n case 'bulletList':\n case 'orderedList': {\n const listItemEls = block.items.map(() => new Y.XmlElement('listItem'))\n el.insert(0, listItemEls)\n block.items.forEach((item, i) => {\n populateListItemChildren(listItemEls[i]!, item, 'listItem')\n })\n break\n }\n case 'taskList': {\n const taskItemEls = block.items.map(() => new Y.XmlElement('taskItem'))\n el.insert(0, taskItemEls)\n block.items.forEach((item, i) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n taskItemEls[i]!.setAttribute('checked', !!item.checked as any)\n populateListItemChildren(taskItemEls[i]!, item, 'taskItem')\n })\n break\n }\n case 'codeBlock': {\n if (block.lang) el.setAttribute('language', block.lang)\n const xt = new Y.XmlText()\n el.insert(0, [xt]) // attach xt to el (already attached)\n xt.insert(0, block.code)\n break\n }\n case 'blockquote': {\n const paraEls = block.lines.map(() => new Y.XmlElement('paragraph'))\n el.insert(0, paraEls)\n block.lines.forEach((line, i) => fillTextInto(paraEls[i]!, parseInline(line)))\n break\n }\n case 'table': {\n const headerRowEl = new Y.XmlElement('tableRow')\n const dataRowEls = block.dataRows.map(() => new Y.XmlElement('tableRow'))\n el.insert(0, [headerRowEl, ...dataRowEls])\n\n // Header cells\n const headerCellEls = block.headerRow.map(() => new Y.XmlElement('tableHeader'))\n headerRowEl.insert(0, headerCellEls)\n block.headerRow.forEach((cellText, i) => {\n const paraEl = new Y.XmlElement('paragraph')\n headerCellEls[i]!.insert(0, [paraEl])\n fillTextInto(paraEl, parseInline(cellText))\n })\n\n // Data rows\n block.dataRows.forEach((row, ri) => {\n const cellEls = row.map(() => new Y.XmlElement('tableCell'))\n dataRowEls[ri]!.insert(0, cellEls)\n row.forEach((cellText, ci) => {\n const paraEl = new Y.XmlElement('paragraph')\n cellEls[ci]!.insert(0, [paraEl])\n fillTextInto(paraEl, parseInline(cellText))\n })\n })\n break\n }\n case 'hr': break // horizontalRule has no content\n case 'callout': {\n el.setAttribute('type', block.calloutType)\n if (!block.innerBlocks.length) {\n const paraEl = new Y.XmlElement('paragraph')\n el.insert(0, [paraEl])\n break\n }\n const innerEls = block.innerBlocks.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, innerEls)\n block.innerBlocks.forEach((b, i) => fillBlock(innerEls[i]!, b))\n break\n }\n case 'collapsible': {\n el.setAttribute('label', block.label)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n el.setAttribute('open', block.open as any)\n const inner = block.innerBlocks.length ? block.innerBlocks : [{ type: 'paragraph' as const, text: '' }]\n const innerEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, innerEls)\n inner.forEach((b, i) => fillBlock(innerEls[i]!, b))\n break\n }\n case 'steps': {\n const inner = block.innerBlocks.length ? block.innerBlocks : [{ type: 'paragraph' as const, text: '' }]\n const innerEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, innerEls)\n inner.forEach((b, i) => fillBlock(innerEls[i]!, b))\n break\n }\n case 'card': {\n if (block.title) el.setAttribute('title', block.title)\n if (block.icon) el.setAttribute('icon', block.icon)\n if (block.to) el.setAttribute('to', block.to)\n const inner = block.innerBlocks.length ? block.innerBlocks : [{ type: 'paragraph' as const, text: '' }]\n const innerEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, innerEls)\n inner.forEach((b, i) => fillBlock(innerEls[i]!, b))\n break\n }\n case 'cardGroup': {\n const cardEls = block.cards.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, cardEls)\n block.cards.forEach((b, i) => fillBlock(cardEls[i]!, b))\n break\n }\n case 'codeCollapse': {\n const codes = block.codeBlocks.length ? block.codeBlocks : [{ type: 'codeBlock' as const, lang: '', code: '' }]\n // Only insert the first code block (content model is singular codeBlock)\n const codeEl = new Y.XmlElement('codeBlock')\n el.insert(0, [codeEl])\n fillBlock(codeEl, codes[0]!)\n break\n }\n case 'codeGroup': {\n const codes = block.codeBlocks.length ? block.codeBlocks : [{ type: 'codeBlock' as const, lang: '', code: '' }]\n const codeEls = codes.map(() => new Y.XmlElement('codeBlock'))\n el.insert(0, codeEls)\n codes.forEach((b, i) => fillBlock(codeEls[i]!, b))\n break\n }\n case 'codePreview': {\n const all = [...block.innerBlocks, ...block.codeBlocks]\n const inner = all.length ? all : [{ type: 'paragraph' as const, text: '' }]\n const innerEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, innerEls)\n inner.forEach((b, i) => fillBlock(innerEls[i]!, b))\n break\n }\n case 'codeTree': {\n el.setAttribute('files', block.files)\n break\n }\n case 'accordion': {\n const itemEls = block.items.map(() => new Y.XmlElement('accordionItem'))\n el.insert(0, itemEls)\n block.items.forEach((item, i) => {\n itemEls[i]!.setAttribute('label', item.label)\n if (item.icon) itemEls[i]!.setAttribute('icon', item.icon)\n const inner = item.innerBlocks.length ? item.innerBlocks : [{ type: 'paragraph' as const, text: '' }]\n const childEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n itemEls[i]!.insert(0, childEls)\n inner.forEach((b, ci) => fillBlock(childEls[ci]!, b))\n })\n break\n }\n case 'tabs': {\n const itemEls = block.items.map(() => new Y.XmlElement('tabsItem'))\n el.insert(0, itemEls)\n block.items.forEach((item, i) => {\n itemEls[i]!.setAttribute('label', item.label)\n if (item.icon) itemEls[i]!.setAttribute('icon', item.icon)\n const inner = item.innerBlocks.length ? item.innerBlocks : [{ type: 'paragraph' as const, text: '' }]\n const childEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n itemEls[i]!.insert(0, childEls)\n inner.forEach((b, ci) => fillBlock(childEls[ci]!, b))\n })\n break\n }\n case 'field': {\n if (block.name) el.setAttribute('name', block.name)\n el.setAttribute('type', block.fieldType)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n el.setAttribute('required', block.required as any)\n const inner = block.innerBlocks.length ? block.innerBlocks : [{ type: 'paragraph' as const, text: '' }]\n const innerEls = inner.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, innerEls)\n inner.forEach((b, i) => fillBlock(innerEls[i]!, b))\n break\n }\n case 'fieldGroup': {\n const fieldEls = block.fields.map(b => new Y.XmlElement(blockElName(b)))\n el.insert(0, fieldEls)\n block.fields.forEach((b, i) => fillBlock(fieldEls[i]!, b))\n break\n }\n case 'image': {\n el.setAttribute('src', block.src)\n if (block.alt) el.setAttribute('alt', block.alt)\n if (block.width) el.setAttribute('width', block.width)\n if (block.height) el.setAttribute('height', block.height)\n break\n }\n case 'docEmbed': {\n el.setAttribute('docId', block.docId)\n for (const flag of ['collapsed', 'tall', 'seamless']) {\n if (block.props[flag] === 'true' || block.props[flag] === '1') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n el.setAttribute(flag, true as any)\n }\n }\n break\n }\n case 'mathBlock': {\n el.setAttribute('expression', block.expression)\n break\n }\n case 'fileBlock': {\n if (block.src) el.setAttribute('src', block.src)\n if (block.mime) el.setAttribute('mime', block.mime)\n if (block.uploadId) el.setAttribute('uploadId', block.uploadId)\n if (block.filename) el.setAttribute('filename', block.filename)\n break\n }\n }\n}\n\n// ── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Parses markdown text and writes the result into a Y.XmlFragment that\n * TipTap's Collaboration extension can read.\n *\n * Requires `fragment.doc` to be set (i.e. the fragment must already be\n * obtained from a live Y.Doc via `ydoc.getXmlFragment('default')`).\n *\n * @param fragment The target `Y.Doc.getXmlFragment('default')`\n * @param markdown Raw markdown string\n * @param fallbackTitle Used as the title when the markdown has no H1\n */\nexport function populateYDocFromMarkdown(\n fragment: Y.XmlFragment,\n markdown: string,\n fallbackTitle = 'Untitled'\n): void {\n const ydoc = fragment.doc\n if (!ydoc) {\n console.warn('[markdownToYjs] fragment has no doc — skipping population')\n return\n }\n\n // Strip YAML frontmatter from the head of the input so its `---`\n // fences don't get reinterpreted as horizontal rules.\n const fm = parseFrontmatter(markdown)\n const blocks = parseBlocks(fm.body)\n\n let title = fallbackTitle\n // The title can live in three places: frontmatter, the first body H1,\n // or a filename-derived fallback. We track which so the serialiser\n // can round-trip into the same form. Body H1 wins over frontmatter\n // when both are present (frontmatter's title is typically a stale\n // copy of the body H1).\n let titleSource: 'h1' | 'frontmatter' | undefined\n if (fm.title !== undefined) {\n title = fm.title\n titleSource = 'frontmatter'\n }\n let contentBlocks = blocks\n const h1 = blocks.findIndex(b => b.type === 'heading' && b.level === 1)\n if (h1 !== -1) {\n title = (blocks[h1] as { type: 'heading', level: number, text: string }).text\n contentBlocks = blocks.filter((_, i) => i !== h1)\n titleSource = 'h1'\n }\n // For empty markdown we used to seed an empty paragraph so the\n // editor had something to focus. That bytes-pads the round-trip\n // back to \"\\n\\n\" — keep contentBlocks empty so the serialiser can\n // emit a clean empty file.\n\n ydoc.transact(() => {\n // ── Step 1: create empty skeleton elements ────────────────────────────\n const headerEl = new Y.XmlElement('documentHeader')\n const metaEl = new Y.XmlElement('documentMeta')\n const bodyEls: Y.XmlElement[] = contentBlocks.map((b) => {\n switch (b.type) {\n case 'heading': return new Y.XmlElement('heading')\n case 'paragraph': return new Y.XmlElement('paragraph')\n case 'bulletList': return new Y.XmlElement('bulletList')\n case 'orderedList': return new Y.XmlElement('orderedList')\n case 'taskList': return new Y.XmlElement('taskList')\n case 'codeBlock': return new Y.XmlElement('codeBlock')\n case 'blockquote': return new Y.XmlElement('blockquote')\n case 'table': return new Y.XmlElement('table')\n case 'hr': return new Y.XmlElement('horizontalRule')\n case 'callout': return new Y.XmlElement('callout')\n case 'collapsible': return new Y.XmlElement('collapsible')\n case 'steps': return new Y.XmlElement('steps')\n case 'card': return new Y.XmlElement('card')\n case 'cardGroup': return new Y.XmlElement('cardGroup')\n case 'codeCollapse': return new Y.XmlElement('codeCollapse')\n case 'codeGroup': return new Y.XmlElement('codeGroup')\n case 'codePreview': return new Y.XmlElement('codePreview')\n case 'codeTree': return new Y.XmlElement('codeTree')\n case 'accordion': return new Y.XmlElement('accordion')\n case 'tabs': return new Y.XmlElement('tabs')\n case 'field': return new Y.XmlElement('field')\n case 'fieldGroup': return new Y.XmlElement('fieldGroup')\n case 'image': return new Y.XmlElement('image')\n case 'docEmbed': return new Y.XmlElement('docEmbed')\n case 'mathBlock': return new Y.XmlElement('mathBlock')\n case 'fileBlock': return new Y.XmlElement('fileBlock')\n }\n })\n\n // ── Step 2: attach ALL skeleton elements to fragment in one shot ──────\n // After this line everything is connected to ydoc and subsequent ops\n // use the real doc clock — no more clock-0 scrambling.\n fragment.insert(0, [headerEl, metaEl, ...bodyEls])\n\n // ── Step 3: fill header title + record where it came from ─────────────\n if (titleSource) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n headerEl.setAttribute('titleSource', titleSource as any)\n }\n const headerXt = new Y.XmlText()\n headerEl.insert(0, [headerXt])\n headerXt.insert(0, title)\n\n // ── Step 4: stash parsed frontmatter meta on documentMeta ─────────────\n // Each universal-meta key becomes an attribute on documentMeta so\n // the serialiser can faithfully emit it back to frontmatter. Type\n // (page-type) is also stashed here under the well-known \"type\" key.\n for (const k of Object.keys(fm.meta)) {\n const v = (fm.meta as Record<string, unknown>)[k]\n if (v === undefined || v === null) continue\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n metaEl.setAttribute(k, v as any)\n }\n if (fm.type) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n metaEl.setAttribute('type', fm.type as any)\n }\n\n // ── Step 5: fill body blocks ──────────────────────────────────────────\n contentBlocks.forEach((block, i) => fillBlock(bodyEls[i]!, block))\n })\n}\n","import * as Y from 'yjs'\nimport type { DocPageMeta } from './types.ts'\n\n// ── Cross-yjs-copy node typing ───────────────────────────────────────────────\n//\n// The serializers must decide \"is this a Y.XmlText vs Y.XmlElement\"\n// without `instanceof`. A host that wires @abraca/dabra (file: dep) or\n// bundles us through Vite/esbuild dep-prebundling ends up with a SECOND\n// physical copy of yjs; nodes built by that copy are NOT `instanceof`\n// *our* Y.XmlText/Y.XmlElement, so every check silently fails and text\n// and inline atoms (docLink/mention) serialize to NOTHING. Duck-typed\n// predicates work regardless of which yjs constructed the node — the\n// same lesson as getTreeData's `instanceof Y.Map` fix. (`nodeName` is a\n// plain own-property; `toDelta` only exists on Y.XmlText.)\n// An element is anything carrying a string `nodeName` (paragraph,\n// heading, bulletList, AND inline atoms like docLink/mention — atoms\n// have no children but still have a nodeName). Mirrors the original\n// `instanceof Y.XmlElement` intent with NO extra constraint: requiring\n// `.toArray` wrongly excluded childless atom nodes → docLinks dropped.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction isXElem(n: any): n is Y.XmlElement {\n return !!n && typeof n.nodeName === 'string'\n}\n// Y.XmlText: no nodeName, has toDelta. (Y.XmlFragment has neither →\n// classified as neither, which is correct — it's only ever the root.)\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction isXText(n: any): n is Y.XmlText {\n return !!n && typeof n.nodeName !== 'string' && typeof n.toDelta === 'function'\n}\n\n// No fragment normalization is needed any more — the serializers are\n// duck-typed, so a foreign-yjs fragment serializes directly. Kept as an\n// identity so the public entry points don't need to change.\nfunction localizeFragment(fragment: Y.XmlFragment): Y.XmlFragment {\n return fragment\n}\n\n// ── Inline serialization ────────────────────────────────────────────────────\n\nfunction serializeDelta(delta: any[]): string {\n let result = ''\n for (const op of delta) {\n if (typeof op.insert !== 'string') continue\n let text = op.insert as string\n const attrs = op.attributes ?? {}\n\n if (attrs.code) {\n result += `\\`${text}\\``\n continue\n }\n\n // Badge mark\n if (attrs.badge) {\n const b = attrs.badge as { label?: string, color?: string, variant?: string }\n const props: string[] = []\n if (b.color && b.color !== 'neutral') props.push(`color=\"${b.color}\"`)\n if (b.variant && b.variant !== 'subtle') props.push(`variant=\"${b.variant}\"`)\n result += `:badge[${b.label || text}]${props.length ? `{${props.join(' ')}}` : ''}`\n continue\n }\n\n // Prose icon mark\n if (attrs.proseIcon) {\n const icon = (attrs.proseIcon as { name?: string }).name || 'i-lucide-star'\n result += `:icon{name=\"${icon}\"}`\n continue\n }\n\n // Kbd mark\n if (attrs.kbd) {\n const value = (attrs.kbd as { value?: string }).value || text\n result += `:kbd{value=\"${value}\"}`\n continue\n }\n\n // docLink — inline doc reference. The label is the displayed text;\n // the docId is the canonical anchor. Per SPEC.md §6 the label may\n // be regenerated from a live registry, but the converter is pure —\n // we use the stored text. Consumers that need fresh labels should\n // rewrite them in the Y tree before serialising.\n if (attrs.docLink) {\n const docId = (attrs.docLink as { docId?: string }).docId\n if (docId) {\n result += text === docId ? `[[${docId}]]` : `[[${docId}|${text}]]`\n continue\n }\n }\n\n // mention — `@[label](user:uuid)`\n if (attrs.mention) {\n const { userId, label } = attrs.mention as { userId?: string, label?: string }\n if (userId) {\n result += `@[${label || text}](user:${userId})`\n continue\n }\n }\n\n // Inline math — `$expression$`\n if (attrs.mathInline) {\n const expr = (attrs.mathInline as { expression?: string }).expression ?? text\n result += `$${expr}$`\n continue\n }\n\n if (attrs.bold) text = `**${text}**`\n if (attrs.italic) text = `*${text}*`\n if (attrs.strike) text = `~~${text}~~`\n if (attrs.link) {\n const href = (attrs.link as { href?: string }).href ?? ''\n text = `[${text}](${href})`\n }\n\n result += text\n }\n return result\n}\n\nfunction serializeInline(el: Y.XmlElement | Y.XmlFragment): string {\n const parts: string[] = []\n for (const child of el.toArray()) {\n if (isXText(child)) {\n parts.push(serializeDelta(child.toDelta()))\n } else if (isXElem(child)) {\n if (child.nodeName === 'docLink') {\n // Inline doc-link atom node — bare wire form; label is tree-derived.\n const docId = child.getAttribute('docId') ?? ''\n parts.push(`[[${docId}]]`)\n } else {\n // Nested inline element — just get text\n parts.push(serializeInline(child))\n }\n }\n }\n return parts.join('')\n}\n\n// ── Block serialization ─────────────────────────────────────────────────────\n\nfunction serializeBlock(el: Y.XmlElement | Y.XmlText, indent = ''): string {\n if (isXText(el)) {\n return serializeDelta(el.toDelta())\n }\n\n const name = el.nodeName\n switch (name) {\n case 'documentHeader':\n case 'documentMeta':\n return '' // handled via frontmatter\n\n case 'heading': {\n const level = Number(el.getAttribute('level') ?? 2)\n const hashes = '#'.repeat(level)\n return `${hashes} ${serializeInline(el)}`\n }\n\n case 'paragraph':\n return serializeInline(el)\n\n case 'bulletList':\n return serializeListItems(el, 'bullet', indent)\n\n case 'orderedList':\n return serializeListItems(el, 'ordered', indent)\n\n case 'taskList':\n return serializeTaskList(el, indent)\n\n case 'codeBlock': {\n const lang = el.getAttribute('language') ?? ''\n const code = getCodeBlockText(el)\n // Empty body — single-newline form preserves the `\\`\\`\\`lang\\n\\`\\`\\``\n // wire form (no padding blank line).\n if (code === '') return `\\`\\`\\`${lang}\\n\\`\\`\\``\n return `\\`\\`\\`${lang}\\n${code}\\n\\`\\`\\``\n }\n\n case 'blockquote': {\n const lines: string[] = []\n for (const child of el.toArray()) {\n if (isXElem(child)) {\n const text = serializeBlock(child)\n for (const line of text.split('\\n')) {\n lines.push(`> ${line}`)\n }\n }\n }\n return lines.join('\\n')\n }\n\n case 'table':\n return serializeTable(el)\n\n case 'horizontalRule':\n return '---'\n\n case 'image': {\n const src = el.getAttribute('src') ?? ''\n const alt = el.getAttribute('alt') ?? ''\n const width = el.getAttribute('width')\n const height = el.getAttribute('height')\n const attrs: string[] = []\n // MDC convention is `{width=400 height=300}` — bare values, no\n // quotes — matching what the parser at the time accepts.\n if (width) attrs.push(`width=${width}`)\n if (height) attrs.push(`height=${height}`)\n return `![${alt}](${src})${attrs.length ? `{${attrs.join(' ')}}` : ''}`\n }\n\n case 'docEmbed': {\n const docId = el.getAttribute('docId') ?? ''\n const collapsed: unknown = el.getAttribute('collapsed')\n const tall: unknown = el.getAttribute('tall')\n const seamless: unknown = el.getAttribute('seamless')\n const flags: string[] = []\n if (collapsed === true || collapsed === 'true') flags.push('collapsed')\n if (tall === true || tall === 'true') flags.push('tall')\n if (seamless === true || seamless === 'true') flags.push('seamless')\n return `![[${docId}]]${flags.length ? `{${flags.join(' ')}}` : ''}`\n }\n\n case 'mathBlock': {\n const expr = el.getAttribute('expression') ?? ''\n return `\\`\\`\\`math\\n${expr}\\n\\`\\`\\``\n }\n\n case 'fileBlock': {\n // SPEC.md §7 wire form: `:file{src=… mime=… upload-id=… filename=…}`.\n // The sidecar binary lives under `.abracadabra/files/`; this tag\n // is purely a reference into that store + the manifest.\n const uploadId = el.getAttribute('uploadId') ?? ''\n const filename = el.getAttribute('filename') ?? ''\n const mime = el.getAttribute('mime') ?? ''\n const src = el.getAttribute('src') ?? (uploadId && filename\n ? `.abracadabra/files/${uploadId}-${filename}`\n : '')\n const props: string[] = []\n if (src) props.push(`src=\"${src}\"`)\n if (mime) props.push(`mime=\"${mime}\"`)\n if (uploadId) props.push(`upload-id=\"${uploadId}\"`)\n if (filename) props.push(`filename=\"${filename}\"`)\n return `:file{${props.join(' ')}}`\n }\n\n // MDC components\n case 'callout': {\n const type = el.getAttribute('type') ?? 'note'\n return `::${type}\\n${serializeChildren(el)}\\n::`\n }\n\n case 'collapsible': {\n const label = el.getAttribute('label') ?? 'Details'\n const open: unknown = el.getAttribute('open')\n const props: string[] = [`label=\"${label}\"`]\n if (open === true || open === 'true') props.push('open=\"true\"')\n return `::collapsible{${props.join(' ')}}\\n${serializeChildren(el)}\\n::`\n }\n\n case 'steps':\n return `::steps\\n${serializeChildren(el)}\\n::`\n\n case 'card': {\n const props: string[] = []\n const title = el.getAttribute('title')\n const icon = el.getAttribute('icon')\n const to = el.getAttribute('to')\n if (title) props.push(`title=\"${title}\"`)\n if (icon) props.push(`icon=\"${icon}\"`)\n if (to) props.push(`to=\"${to}\"`)\n return `::card${props.length ? `{${props.join(' ')}}` : ''}\\n${serializeChildren(el)}\\n::`\n }\n\n case 'cardGroup': {\n const cards = el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map(c => serializeBlock(c))\n .join('\\n\\n')\n return `::card-group\\n${cards}\\n::`\n }\n\n case 'codeCollapse': {\n const code = el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c) && c.nodeName === 'codeBlock')\n .map(c => serializeBlock(c))\n .join('\\n\\n')\n return `::code-collapse\\n${code}\\n::`\n }\n\n case 'codeGroup': {\n const code = el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c) && c.nodeName === 'codeBlock')\n .map(c => serializeBlock(c))\n .join('\\n\\n')\n return `::code-group\\n${code}\\n::`\n }\n\n case 'codePreview': {\n const children = el.toArray().filter((c): c is Y.XmlElement => isXElem(c))\n const nonCode = children.filter(c => c.nodeName !== 'codeBlock').map(c => serializeBlock(c)).join('\\n\\n')\n const code = children.filter(c => c.nodeName === 'codeBlock').map(c => serializeBlock(c)).join('\\n\\n')\n const parts = [nonCode]\n if (code) parts.push(`#code\\n${code}`)\n return `::code-preview\\n${parts.filter(Boolean).join('\\n\\n')}\\n::`\n }\n\n case 'codeTree': {\n const files = el.getAttribute('files') ?? '[]'\n return `::code-tree{files=\"${files}\"}\\n::`\n }\n\n case 'accordion':\n return serializeSlottedContainer(el, 'accordion', 'accordionItem', 'item')\n\n case 'tabs':\n return serializeSlottedContainer(el, 'tabs', 'tabsItem', 'tab')\n\n case 'field': {\n const fieldName = el.getAttribute('name') ?? ''\n const fieldType = el.getAttribute('type') ?? 'string'\n const required: unknown = el.getAttribute('required')\n const props = [`name=\"${fieldName}\"`, `type=\"${fieldType}\"`]\n if (required === true || required === 'true') props.push('required=\"true\"')\n return `::field{${props.join(' ')}}\\n${serializeChildren(el)}\\n::`\n }\n\n case 'fieldGroup': {\n const fields = el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map(c => serializeBlock(c))\n .join('\\n\\n')\n return `::field-group\\n${fields}\\n::`\n }\n\n default:\n // Unknown node type — try to serialize children\n return serializeChildren(el)\n }\n}\n\nfunction serializeChildren(el: Y.XmlElement | Y.XmlFragment): string {\n const blocks: string[] = []\n for (const child of el.toArray()) {\n if (isXElem(child)) {\n const text = serializeBlock(child)\n if (text) blocks.push(text)\n } else if (isXText(child)) {\n const text = serializeDelta(child.toDelta())\n if (text) blocks.push(text)\n }\n }\n return blocks.join('\\n\\n')\n}\n\nfunction serializeListItems(el: Y.XmlElement, type: 'bullet' | 'ordered', indent: string): string {\n const lines: string[] = []\n let counter = 1\n for (const child of el.toArray()) {\n if (!(isXElem(child)) || child.nodeName !== 'listItem') continue\n const prefix = type === 'bullet' ? '- ' : `${counter++}. `\n // A listItem may contain paragraphs and nested lists\n const subParts: string[] = []\n for (const sub of child.toArray()) {\n if (!(isXElem(sub))) continue\n if (sub.nodeName === 'bulletList') {\n subParts.push(serializeListItems(sub, 'bullet', indent + ' '))\n } else if (sub.nodeName === 'orderedList') {\n subParts.push(serializeListItems(sub, 'ordered', indent + ' '))\n } else {\n subParts.push(serializeInline(sub))\n }\n }\n if (subParts.length <= 1) {\n lines.push(`${indent}${prefix}${subParts[0] ?? ''}`)\n } else {\n lines.push(`${indent}${prefix}${subParts[0] ?? ''}`)\n for (let i = 1; i < subParts.length; i++) {\n // Nested lists are already indented; plain text gets continuation indent\n lines.push(subParts[i]!)\n }\n }\n }\n return lines.join('\\n')\n}\n\nfunction serializeTaskList(el: Y.XmlElement, indent: string): string {\n const lines: string[] = []\n for (const child of el.toArray()) {\n if (!(isXElem(child)) || child.nodeName !== 'taskItem') continue\n const checked: unknown = child.getAttribute('checked')\n const marker = (checked === true || checked === 'true') ? '[x]' : '[ ]'\n\n let header = ''\n const nestedParts: string[] = []\n for (const sub of child.toArray()) {\n if (!(isXElem(sub))) continue\n if (sub.nodeName === 'paragraph' && header === '') {\n header = serializeInline(sub)\n }\n else if (sub.nodeName === 'bulletList') {\n nestedParts.push(serializeListItems(sub, 'bullet', indent + ' '))\n }\n else if (sub.nodeName === 'orderedList') {\n nestedParts.push(serializeListItems(sub, 'ordered', indent + ' '))\n }\n else if (sub.nodeName === 'taskList') {\n nestedParts.push(serializeTaskList(sub, indent + ' '))\n }\n else {\n // Other block — render under the item with a 2-space hanging indent\n nestedParts.push((indent + ' ') + serializeBlock(sub, indent + ' '))\n }\n }\n lines.push(`${indent}- ${marker} ${header}`)\n for (const part of nestedParts) lines.push(part)\n }\n return lines.join('\\n')\n}\n\nfunction getCodeBlockText(el: Y.XmlElement): string {\n for (const child of el.toArray()) {\n if (isXText(child)) {\n return child.toString()\n }\n }\n return ''\n}\n\nfunction serializeTable(el: Y.XmlElement): string {\n const rows = el.toArray().filter((c): c is Y.XmlElement => isXElem(c))\n if (!rows.length) return ''\n\n const serializedRows: string[][] = []\n for (const row of rows) {\n const cells = row.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map((cell) => {\n // Cell contains paragraphs — join their text\n return cell.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map(c => serializeInline(c))\n .join(' ')\n })\n serializedRows.push(cells)\n }\n\n if (!serializedRows.length) return ''\n\n const colCount = Math.max(...serializedRows.map(r => r.length))\n const headerRow = serializedRows[0]!\n const separator = Array(colCount).fill('---')\n const dataRows = serializedRows.slice(1)\n\n const formatRow = (cells: string[]) => {\n const padded = Array(colCount).fill('').map((_, i) => cells[i] ?? '')\n return `| ${padded.join(' | ')} |`\n }\n\n const lines = [formatRow(headerRow), formatRow(separator), ...dataRows.map(formatRow)]\n return lines.join('\\n')\n}\n\nfunction serializeSlottedContainer(\n el: Y.XmlElement,\n containerName: string,\n childName: string,\n slotPrefix: string\n): string {\n const items = el.toArray().filter((c): c is Y.XmlElement => isXElem(c) && c.nodeName === childName)\n const slots = items.map((item) => {\n const label = item.getAttribute('label') ?? ''\n const icon = item.getAttribute('icon') ?? ''\n const props: string[] = []\n if (label) props.push(`label=\"${label}\"`)\n if (icon) props.push(`icon=\"${icon}\"`)\n const content = serializeChildren(item)\n return `#${slotPrefix}{${props.join(' ')}}\\n${content}`\n })\n return `::${containerName}\\n${slots.join('\\n\\n')}\\n::`\n}\n\n// ── Frontmatter generation ──────────────────────────────────────────────────\n\nfunction generateFrontmatter(label: string | undefined, meta?: DocPageMeta, type?: string): string {\n const lines: string[] = []\n\n if (label !== undefined) lines.push(`title: \"${escapeYaml(label)}\"`)\n\n if (type && type !== 'doc') {\n lines.push(`type: ${type}`)\n }\n\n if (!meta) return `---\\n${lines.join('\\n')}\\n---`\n\n if (meta.tags?.length) {\n lines.push(`tags: [${meta.tags.join(', ')}]`)\n }\n if (meta.color) lines.push(`color: ${yamlScalar(meta.color)}`)\n if (meta.icon) lines.push(`icon: ${yamlScalar(meta.icon)}`)\n if (meta.status) lines.push(`status: ${yamlScalar(meta.status)}`)\n\n if (meta.priority !== undefined && meta.priority !== 0) {\n const map: Record<number, string> = { 1: 'low', 2: 'medium', 3: 'high', 4: 'urgent' }\n lines.push(`priority: ${map[meta.priority] ?? meta.priority}`)\n }\n\n if (meta.checked !== undefined) lines.push(`checked: ${meta.checked}`)\n // Code page type: syntax-highlight language + on-disk extension. These\n // round-trip the `.md` envelope so the companion code file can be re-derived.\n if (meta.language) lines.push(`language: ${yamlScalar(meta.language)}`)\n if (meta.fileExtension) lines.push(`fileExtension: ${yamlScalar(meta.fileExtension)}`)\n if (meta.codeTheme) lines.push(`codeTheme: ${yamlScalar(meta.codeTheme)}`)\n if (meta.dateStart) lines.push(`dateStart: \"${escapeYaml(meta.dateStart)}\"`)\n if (meta.dateEnd) lines.push(`dateEnd: \"${escapeYaml(meta.dateEnd)}\"`)\n if (meta.subtitle) lines.push(`subtitle: \"${escapeYaml(meta.subtitle)}\"`)\n if (meta.url) lines.push(`url: ${meta.url}`)\n if (meta.rating !== undefined && meta.rating !== 0) lines.push(`rating: ${meta.rating}`)\n\n return `---\\n${lines.join('\\n')}\\n---`\n}\n\n/**\n * Render a YAML scalar — bare when safe, double-quoted when the value\n * needs escaping. YAML treats `#`, `:`, leading whitespace, and a few\n * other characters as syntactically significant, so anything starting\n * with one of those gets quoted to stay round-trip safe.\n */\nfunction yamlScalar(s: string): string {\n if (s === '') return '\"\"'\n if (/^[#&*!|>%@`]/.test(s)) return `\"${escapeYaml(s)}\"`\n if (/[:\"]/.test(s)) return `\"${escapeYaml(s)}\"`\n if (/^\\s|\\s$/.test(s)) return `\"${escapeYaml(s)}\"`\n return s\n}\n\nfunction escapeYaml(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')\n}\n\n// ── HTML serialization ──────────────────────────────────────────────────────\n\nfunction serializeBlockToHtml(el: Y.XmlElement | Y.XmlText): string {\n if (isXText(el)) {\n return serializeDeltaToHtml(el.toDelta())\n }\n\n const name = el.nodeName\n switch (name) {\n case 'documentHeader':\n case 'documentMeta':\n return ''\n\n case 'heading': {\n const level = Number(el.getAttribute('level') ?? 2)\n return `<h${level}>${serializeInlineHtml(el)}</h${level}>`\n }\n\n case 'paragraph':\n return `<p>${serializeInlineHtml(el)}</p>`\n\n case 'bulletList':\n return `<ul>${serializeListHtml(el)}</ul>`\n\n case 'orderedList':\n return `<ol>${serializeListHtml(el)}</ol>`\n\n case 'taskList':\n return `<ul>${serializeTaskListHtml(el)}</ul>`\n\n case 'codeBlock': {\n // Restrict the language to a safe identifier charset — it is interpolated\n // into a class attribute below; an unsanitised value is a stored-XSS sink.\n const lang = (el.getAttribute('language') ?? '').replace(/[^\\w.-]/g, '')\n const code = escapeHtml(getCodeBlockText(el))\n return lang\n ? `<pre><code class=\"language-${lang}\">${code}</code></pre>`\n : `<pre><code>${code}</code></pre>`\n }\n\n case 'blockquote': {\n const inner = el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map(c => serializeBlockToHtml(c))\n .join('\\n')\n return `<blockquote>\\n${inner}\\n</blockquote>`\n }\n\n case 'table':\n return serializeTableHtml(el)\n\n case 'horizontalRule':\n return '<hr>'\n\n case 'image': {\n const src = el.getAttribute('src') ?? ''\n const alt = el.getAttribute('alt') ?? ''\n return `<img src=\"${escapeHtml(src)}\" alt=\"${escapeHtml(alt)}\">`\n }\n\n case 'fileBlock': {\n const uploadId = el.getAttribute('uploadId') ?? ''\n const filename = el.getAttribute('filename') ?? 'file'\n if (uploadId) return `<!--fileblock:${uploadId}:${filename}-->`\n return `<!-- file: ${filename} -->`\n }\n\n default: {\n // Generic wrapper for MDC blocks etc.\n const inner = el.toArray()\n .filter((c): c is Y.XmlElement | Y.XmlText => isXElem(c) || isXText(c))\n .map(c => isXElem(c) ? serializeBlockToHtml(c) : serializeDeltaToHtml(c.toDelta()))\n .join('\\n')\n return `<div data-type=\"${name}\">\\n${inner}\\n</div>`\n }\n }\n}\n\nfunction serializeInlineHtml(el: Y.XmlElement | Y.XmlFragment): string {\n const parts: string[] = []\n for (const child of el.toArray()) {\n if (isXText(child)) {\n parts.push(serializeDeltaToHtml(child.toDelta()))\n } else if (isXElem(child)) {\n parts.push(serializeInlineHtml(child))\n }\n }\n return parts.join('')\n}\n\nfunction serializeDeltaToHtml(delta: any[]): string {\n let result = ''\n for (const op of delta) {\n if (typeof op.insert !== 'string') continue\n let text = escapeHtml(op.insert as string)\n const attrs = op.attributes ?? {}\n if (attrs.code) text = `<code>${text}</code>`\n if (attrs.bold) text = `<strong>${text}</strong>`\n if (attrs.italic) text = `<em>${text}</em>`\n if (attrs.strike) text = `<s>${text}</s>`\n if (attrs.link) {\n const href = escapeHtml((attrs.link as { href?: string }).href ?? '')\n text = `<a href=\"${href}\">${text}</a>`\n }\n result += text\n }\n return result\n}\n\nfunction serializeListHtml(el: Y.XmlElement): string {\n return el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c) && c.nodeName === 'listItem')\n .map(li => `<li>${li.toArray().filter((c): c is Y.XmlElement => isXElem(c)).map(c => serializeBlockToHtml(c)).join('')}</li>`)\n .join('\\n')\n}\n\nfunction serializeTaskListHtml(el: Y.XmlElement): string {\n return el.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c) && c.nodeName === 'taskItem')\n .map((ti) => {\n const rawChecked: unknown = ti.getAttribute('checked')\n const checked = rawChecked === true || rawChecked === 'true'\n const text = ti.toArray().filter((c): c is Y.XmlElement => isXElem(c)).map(c => serializeInlineHtml(c)).join('')\n return `<li><input type=\"checkbox\"${checked ? ' checked' : ''} disabled> ${text}</li>`\n })\n .join('\\n')\n}\n\nfunction serializeTableHtml(el: Y.XmlElement): string {\n const rows = el.toArray().filter((c): c is Y.XmlElement => isXElem(c))\n if (!rows.length) return ''\n\n const htmlRows = rows.map((row, ri) => {\n const tag = ri === 0 ? 'th' : 'td'\n const cells = row.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map((cell) => {\n const inner = cell.toArray()\n .filter((c): c is Y.XmlElement => isXElem(c))\n .map(c => serializeInlineHtml(c))\n .join('')\n return `<${tag}>${inner}</${tag}>`\n })\n .join('')\n return `<tr>${cells}</tr>`\n })\n\n return `<table>\\n${htmlRows.join('\\n')}\\n</table>`\n}\n\nfunction escapeHtml(s: string): string {\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;')\n}\n\n// ── Public API ──────────────────────────────────────────────────────────────\n\nexport function yjsToMarkdown(\n fragment: Y.XmlFragment,\n label: string,\n meta?: DocPageMeta,\n type?: string\n): string {\n fragment = localizeFragment(fragment)\n // The title can come from three places. We honour where the parser\n // captured it so the wire form round-trips byte-stably:\n // - 'h1' → emit `# title` as the first body block\n // - 'frontmatter' → emit `title:` in frontmatter\n // - undefined → no real title; skip the frontmatter block\n // when no other meta is set\n const { text: headerText, source: titleSource } = readDocumentHeader(fragment)\n const effectiveTitle = headerText || label\n\n // If the caller didn't pass meta / type, read them from documentMeta —\n // that's where the parser stashes frontmatter fields so they survive\n // round-trip without needing to be piped through the consumer.\n const docMeta = readDocumentMeta(fragment)\n const effectiveMeta = meta ?? docMeta.meta\n const effectiveType = type ?? docMeta.type\n\n const metaIsEmpty = isMetaEmpty(effectiveMeta)\n const typeIsDefault = !effectiveType || effectiveType === 'doc'\n\n const bodyBlocks = collectBodyBlocks(fragment)\n\n // Body assembly — when the parser captured the title from a body H1\n // we restore it at the top of the body before serialising.\n let body: string\n if (titleSource === 'h1' && effectiveTitle) {\n const tail = serializeBlocksClean(bodyBlocks)\n body = tail === '' ? `# ${effectiveTitle}` : `# ${effectiveTitle}\\n\\n${tail}`\n }\n else {\n body = serializeBlocksClean(bodyBlocks)\n }\n\n const wantFrontmatterTitle = titleSource === 'frontmatter'\n const wantFrontmatterMeta = !metaIsEmpty || !typeIsDefault\n if (!wantFrontmatterTitle && !wantFrontmatterMeta) {\n return body === '' ? '' : `${body}\\n`\n }\n const fmTitle = wantFrontmatterTitle ? effectiveTitle : undefined\n const frontmatter = generateFrontmatter(fmTitle, effectiveMeta, effectiveType)\n if (body === '') return `${frontmatter}\\n`\n return `${frontmatter}\\n\\n${body}\\n`\n}\n\nfunction readDocumentMeta(fragment: Y.XmlFragment): { meta: DocPageMeta, type?: string } {\n const meta: DocPageMeta = {}\n let type: string | undefined\n for (const child of fragment.toArray()) {\n if (!(isXElem(child)) || child.nodeName !== 'documentMeta') continue\n const attrs = child.getAttributes() as Record<string, unknown>\n for (const k of Object.keys(attrs)) {\n const v = attrs[k]\n if (v === undefined || v === null) continue\n if (k === 'type' && typeof v === 'string') {\n type = v\n continue\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (meta as Record<string, unknown>)[k] = v\n }\n break\n }\n return { meta, type }\n}\n\ninterface HeaderInfo { text: string, source?: 'h1' | 'frontmatter' }\n\nfunction readDocumentHeader(fragment: Y.XmlFragment): HeaderInfo {\n for (const child of fragment.toArray()) {\n if (!(isXElem(child)) || child.nodeName !== 'documentHeader') continue\n const text = child.toArray().find(c => isXText(c)) as Y.XmlText | undefined\n const src: unknown = child.getAttribute('titleSource')\n const source = src === 'h1' || src === 'frontmatter' ? src : undefined\n return { text: text ? text.toString() : '', source }\n }\n return { text: '' }\n}\n\nfunction collectBodyBlocks(fragment: Y.XmlFragment): Y.XmlElement[] {\n const out: Y.XmlElement[] = []\n for (const child of fragment.toArray()) {\n if (!(isXElem(child))) continue\n if (child.nodeName === 'documentHeader' || child.nodeName === 'documentMeta') continue\n out.push(child)\n }\n return out\n}\n\nfunction serializeBlocksClean(blocks: Y.XmlElement[]): string {\n const parts: string[] = []\n for (const block of blocks) {\n // Empty trailing paragraphs are the parser's placeholder for an\n // \"empty doc\"; skip them so empty input round-trips to \"\".\n if (block.nodeName === 'paragraph' && block.length === 0) {\n parts.push('')\n continue\n }\n parts.push(serializeBlock(block))\n }\n while (parts.length && parts[parts.length - 1] === '') parts.pop()\n return parts.join('\\n\\n')\n}\n\nfunction isMetaEmpty(meta: DocPageMeta | undefined): boolean {\n if (!meta) return true\n for (const key of Object.keys(meta)) {\n const v = (meta as Record<string, unknown>)[key]\n if (v === undefined || v === null) continue\n if (typeof v === 'string' && v === '') continue\n if (Array.isArray(v) && v.length === 0) continue\n return false\n }\n return true\n}\n\n/**\n * Walk the Y.XmlFragment and concatenate all text content with no\n * markup or frontmatter. Block boundaries become newlines. Useful for\n * accessibility tooling, search indexing, and snippet previews.\n */\nexport function yjsToPlainText(fragment: Y.XmlFragment): string {\n fragment = localizeFragment(fragment)\n const out: string[] = []\n const visit = (node: Y.XmlElement | Y.XmlText): void => {\n if (isXText(node)) {\n out.push(node.toString())\n return\n }\n if (node.nodeName === 'documentMeta') return\n if (node.nodeName === 'image') {\n const alt = node.getAttribute('alt') ?? ''\n if (alt) out.push(alt)\n return\n }\n for (const child of node.toArray()) {\n if (isXText(child) || isXElem(child)) visit(child)\n }\n // Insert a single newline after block-level elements so paragraphs\n // and headings produce a readable plain-text form.\n if (node.nodeName !== 'paragraph' && node.length === 0) return\n out.push('\\n')\n }\n for (const child of fragment.toArray()) {\n if (isXText(child) || isXElem(child)) visit(child)\n }\n return out.join('').replace(/\\n+$/, '').replace(/\\n{3,}/g, '\\n\\n')\n}\n\nexport function yjsToHtml(\n fragment: Y.XmlFragment,\n label: string\n): string {\n fragment = localizeFragment(fragment)\n const title = escapeHtml(label)\n const bodyParts: string[] = []\n for (const child of fragment.toArray()) {\n if (isXElem(child)) {\n const html = serializeBlockToHtml(child)\n if (html) bodyParts.push(html)\n }\n }\n return `<!DOCTYPE html>\n<html>\n<head><meta charset=\"utf-8\"><title>${title}</title></head>\n<body>\n<h1>${title}</h1>\n${bodyParts.join('\\n')}\n</body>\n</html>\n`\n}\n","// NodeSpec registry — every TipTap node supported by the converter,\n// paired with its canonical Markdown / MDC wire form.\n//\n// This is **data**, not behaviour. The parser and serialiser\n// (markdown-to-yjs.ts, yjs-to-markdown.ts) consult this table to\n// decide what to do; when the spec and the runtime disagree the\n// registry wins (per SPEC.md).\n//\n// Wire kinds:\n// - vanilla Standard Markdown (paragraph, heading, list, …).\n// - fence Fenced code block with a language tag.\n// - mdc-container `:name{props}\\n…children…\\n::` block with children.\n// - mdc-slotted `:name\\n :name-item{…}\\n…\\n ::\\n…\\n::` slotted container.\n// - mdc-atom-block `:name{props}` single-line block atom.\n// - mdc-atom-inl `:name[label]{props}` or `:name{props}` inline atom.\n// - special Has bespoke parsing/serialising (doc-link, doc-embed,\n// file-block, image, mention, math).\n\nimport type { DocPageMeta } from '../types.ts'\n\nexport type NodeWireKind =\n | 'vanilla'\n | 'fence'\n | 'mdc-container'\n | 'mdc-slotted'\n | 'mdc-atom-block'\n | 'mdc-atom-inl'\n | 'special'\n\nexport interface NodeAttrSpec {\n /** Attribute name on the Y.XmlElement and on the MDC prop. */\n key: string\n /** Wire type — controls how the attr is parsed/serialised in props. */\n type: 'string' | 'number' | 'integer' | 'boolean' | 'json'\n /** Optional default value omitted from serialised output when equal. */\n default?: unknown\n /** Allowed values for enum-like string attrs. */\n values?: readonly string[]\n /** Whether the attr is allowed to be omitted entirely. */\n optional?: boolean\n}\n\nexport interface NodeSpec {\n /** Y.XmlElement nodeName. */\n name: string\n /** Block vs inline. */\n group: 'block' | 'inline'\n /** Wire form on Markdown. */\n wire: NodeWireKind\n /**\n * For slotted containers: name of the child element used as a slot\n * (e.g. `accordion-item` under `accordion`).\n */\n slotChild?: string\n /** Declared attributes. */\n attrs?: readonly NodeAttrSpec[]\n /**\n * For `mdc-container` and `mdc-slotted`: what MDC tag name to emit.\n * Defaults to `name` (kebab-cased — `accordionItem` → `accordion-item`).\n */\n mdcTag?: string\n /**\n * Whether the node is content-bearing (paragraph, listItem, etc.)\n * or a child wrapper (tableRow, tableHeader).\n */\n contentBearing?: boolean\n doc?: string\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\nconst BOOL_FALSE_DEFAULT: NodeAttrSpec = {\n key: '',\n type: 'boolean',\n default: false,\n optional: true,\n}\n\nconst bool = (key: string): NodeAttrSpec => ({ ...BOOL_FALSE_DEFAULT, key })\nconst str = (key: string, def?: string): NodeAttrSpec => ({\n key,\n type: 'string',\n default: def,\n optional: true,\n})\nconst num = (key: string): NodeAttrSpec => ({ key, type: 'number', optional: true })\nconst int = (key: string): NodeAttrSpec => ({ key, type: 'integer', optional: true })\n\n// ── Vanilla block nodes ─────────────────────────────────────────────────────\n\nconst VANILLA_BLOCKS: readonly NodeSpec[] = [\n { name: 'documentHeader', group: 'block', wire: 'special', doc: 'Holds the title; hoisted to frontmatter on serialise.' },\n { name: 'documentMeta', group: 'block', wire: 'special', doc: 'Holds page-level meta; serialised into frontmatter.' },\n { name: 'paragraph', group: 'block', wire: 'vanilla', contentBearing: true },\n { name: 'heading', group: 'block', wire: 'vanilla', attrs: [int('level')], contentBearing: true },\n { name: 'blockquote', group: 'block', wire: 'vanilla', contentBearing: true },\n { name: 'codeBlock', group: 'block', wire: 'fence', attrs: [str('language', '')] },\n { name: 'bulletList', group: 'block', wire: 'vanilla' },\n { name: 'orderedList', group: 'block', wire: 'vanilla' },\n { name: 'listItem', group: 'block', wire: 'vanilla', contentBearing: true },\n { name: 'taskList', group: 'block', wire: 'vanilla' },\n { name: 'taskItem', group: 'block', wire: 'vanilla', attrs: [bool('checked')], contentBearing: true },\n { name: 'table', group: 'block', wire: 'vanilla' },\n { name: 'tableRow', group: 'block', wire: 'vanilla' },\n { name: 'tableHeader', group: 'block', wire: 'vanilla', contentBearing: true },\n { name: 'tableCell', group: 'block', wire: 'vanilla', contentBearing: true },\n { name: 'horizontalRule', group: 'block', wire: 'vanilla' },\n {\n name: 'image',\n group: 'block',\n wire: 'special',\n attrs: [str('src'), str('alt', ''), int('width'), int('height')],\n },\n { name: 'hardBreak', group: 'inline', wire: 'vanilla' },\n]\n\n// ── MDC custom containers ───────────────────────────────────────────────────\n\nconst MDC_CONTAINERS: readonly NodeSpec[] = [\n {\n name: 'callout',\n group: 'block',\n wire: 'mdc-container',\n attrs: [\n { key: 'type', type: 'string', default: 'note', optional: true,\n values: ['note', 'tip', 'warning', 'danger', 'info', 'caution', 'alert', 'success', 'error'] },\n str('title'),\n str('icon'),\n ],\n },\n {\n name: 'collapsible',\n group: 'block',\n wire: 'mdc-container',\n attrs: [str('label', 'Details'), bool('open')],\n },\n {\n name: 'accordion',\n group: 'block',\n wire: 'mdc-slotted',\n slotChild: 'accordionItem',\n },\n {\n name: 'accordionItem',\n group: 'block',\n wire: 'mdc-container',\n mdcTag: 'accordion-item',\n attrs: [str('label', 'Item'), str('icon')],\n },\n {\n name: 'tabs',\n group: 'block',\n wire: 'mdc-slotted',\n slotChild: 'tabsItem',\n },\n {\n name: 'tabsItem',\n group: 'block',\n wire: 'mdc-container',\n mdcTag: 'tabs-item',\n attrs: [str('label'), str('icon')],\n },\n { name: 'steps', group: 'block', wire: 'mdc-container' },\n {\n name: 'card',\n group: 'block',\n wire: 'mdc-container',\n attrs: [str('title'), str('icon'), str('to')],\n },\n {\n name: 'cardGroup',\n group: 'block',\n wire: 'mdc-slotted',\n mdcTag: 'card-group',\n slotChild: 'card',\n },\n {\n name: 'field',\n group: 'block',\n wire: 'mdc-container',\n attrs: [str('name'), str('type', 'string'), bool('required')],\n },\n {\n name: 'fieldGroup',\n group: 'block',\n wire: 'mdc-slotted',\n mdcTag: 'field-group',\n slotChild: 'field',\n },\n { name: 'codeGroup', group: 'block', wire: 'mdc-slotted', mdcTag: 'code-group', slotChild: 'codeBlock' },\n { name: 'codeCollapse', group: 'block', wire: 'mdc-container', mdcTag: 'code-collapse' },\n { name: 'codePreview', group: 'block', wire: 'mdc-container', mdcTag: 'code-preview' },\n {\n name: 'codeTree',\n group: 'block',\n wire: 'mdc-atom-block',\n mdcTag: 'code-tree',\n attrs: [{ key: 'files', type: 'json' }],\n },\n {\n name: 'figure',\n group: 'block',\n wire: 'mdc-container',\n attrs: [str('src'), str('alt', ''), str('caption')],\n },\n {\n name: 'video',\n group: 'block',\n wire: 'mdc-atom-block',\n attrs: [str('src'), str('poster'), bool('autoplay'), bool('loop'), bool('controls')],\n },\n {\n name: 'embed',\n group: 'block',\n wire: 'mdc-atom-block',\n attrs: [str('src'), str('title')],\n },\n {\n name: 'svgEmbed',\n group: 'block',\n wire: 'fence',\n attrs: [str('title')],\n mdcTag: 'svg',\n doc: 'Serialised as a ```svg fenced block; the SVG markup is the body.',\n },\n {\n name: 'divider',\n group: 'block',\n wire: 'mdc-atom-block',\n attrs: [str('label'), str('icon')],\n },\n { name: 'quote', group: 'block', wire: 'mdc-container', attrs: [str('cite')] },\n { name: 'progress', group: 'block', wire: 'mdc-atom-block', attrs: [num('value'), num('max'), str('label')] },\n { name: 'spoiler', group: 'block', wire: 'mdc-container', attrs: [str('label')] },\n { name: 'colorSwatch', group: 'block', wire: 'mdc-atom-block', mdcTag: 'color-swatch', attrs: [str('color'), str('label')] },\n { name: 'stat', group: 'block', wire: 'mdc-container', attrs: [str('label'), str('value'), str('icon')] },\n { name: 'statGroup', group: 'block', wire: 'mdc-slotted', mdcTag: 'stat-group', slotChild: 'stat' },\n { name: 'button', group: 'block', wire: 'mdc-atom-block', attrs: [str('label'), str('to'), str('icon'), str('variant')] },\n { name: 'buttonGroup', group: 'block', wire: 'mdc-slotted', mdcTag: 'button-group', slotChild: 'button' },\n { name: 'timeline', group: 'block', wire: 'mdc-slotted', slotChild: 'timelineItem' },\n { name: 'timelineItem', group: 'block', wire: 'mdc-container', mdcTag: 'timeline-item', attrs: [str('label'), str('icon'), str('date')] },\n { name: 'diff', group: 'block', wire: 'mdc-atom-block', attrs: [str('language', ''), { key: 'value', type: 'string' }] },\n]\n\n// ── Inline atoms / special nodes ────────────────────────────────────────────\n\nconst INLINE_AND_SPECIAL: readonly NodeSpec[] = [\n {\n name: 'docLink',\n group: 'inline',\n wire: 'special',\n attrs: [str('docId')],\n doc: 'Wire form `[[uuid|label]]`; label regenerated on export.',\n },\n {\n name: 'docEmbed',\n group: 'block',\n wire: 'special',\n attrs: [str('docId'), bool('collapsed'), bool('tall'), bool('seamless')],\n doc: 'Wire form `![[uuid|label]]{collapsed tall seamless}`.',\n },\n {\n name: 'mention',\n group: 'inline',\n wire: 'special',\n attrs: [str('userId')],\n doc: 'Wire form `@[label](user:uuid)`; label regenerated on export.',\n },\n {\n name: 'mathInline',\n group: 'inline',\n wire: 'special',\n attrs: [{ key: 'expression', type: 'string' }],\n doc: 'Wire form `$expression$`.',\n },\n {\n name: 'mathBlock',\n group: 'block',\n wire: 'fence',\n attrs: [{ key: 'expression', type: 'string' }],\n mdcTag: 'math',\n doc: 'Wire form ``` ```math\\\\nexpression\\\\n``` ```.',\n },\n {\n name: 'fileBlock',\n group: 'block',\n wire: 'mdc-atom-block',\n mdcTag: 'file',\n attrs: [str('src'), str('mime'), str('uploadId'), str('filename')],\n doc: 'Wire form `:file{src=… mime=… upload-id=… filename=…}`; binary in sidecar.',\n },\n {\n name: 'badge',\n group: 'inline',\n wire: 'mdc-atom-inl',\n attrs: [str('label'), str('color'), str('variant', 'subtle')],\n doc: 'Wire form `:badge[Label]{color=… variant=…}`.',\n },\n {\n name: 'proseIcon',\n group: 'inline',\n wire: 'mdc-atom-inl',\n mdcTag: 'icon',\n attrs: [str('name')],\n doc: 'Wire form `:icon{name=…}`.',\n },\n {\n name: 'kbd',\n group: 'inline',\n wire: 'mdc-atom-inl',\n attrs: [str('value')],\n doc: 'Wire form `:kbd{value=…}`.',\n },\n]\n\nexport const NODE_SPECS: readonly NodeSpec[] = [\n ...VANILLA_BLOCKS,\n ...MDC_CONTAINERS,\n ...INLINE_AND_SPECIAL,\n]\n\nexport const NODE_SPEC_BY_NAME: ReadonlyMap<string, NodeSpec> = new Map(\n NODE_SPECS.map(spec => [spec.name, spec]),\n)\n\n/** Derive the MDC tag for a node — `mdcTag` override or kebab-case of `name`. */\nexport function mdcTagOf(spec: NodeSpec): string {\n if (spec.mdcTag) return spec.mdcTag\n return spec.name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()\n}\n\n/** Type-only re-export so consumers can build typed meta without a second import. */\nexport type { DocPageMeta }\n","// MarkSpec registry — every inline mark supported by the converter,\n// paired with its canonical Markdown wire form.\n//\n// Marks are pure inline annotations on text runs; they have no\n// children. The parser sets these as `op.attributes` on Yjs delta\n// inserts; the serialiser wraps text runs with the matching wire\n// delimiters.\n//\n// See SPEC.md §3-4 for the rendered table and the disambiguation\n// rules between bold (`**…**`) and underline (`__…__`).\n\nexport type MarkWireKind =\n | 'delimited' // `**text**`, `*text*`, `~~text~~`, `` `text` ``\n | 'link' // `[text](href)`\n | 'mdc-span' // `:span[text]{prop=value}` for color/font/textStyle\n\nexport interface MarkAttrSpec {\n key: string\n type: 'string' | 'number' | 'boolean'\n optional?: boolean\n}\n\nexport interface MarkSpec {\n name: string\n wire: MarkWireKind\n /** For `delimited`: the markdown delimiter (e.g. `**`, `*`, `~~`, `` ` ``, `__`, `==`). */\n delim?: string\n attrs?: readonly MarkAttrSpec[]\n doc?: string\n}\n\nexport const MARK_SPECS: readonly MarkSpec[] = [\n // Vanilla MD marks\n { name: 'bold', wire: 'delimited', delim: '**' },\n { name: 'italic', wire: 'delimited', delim: '*' },\n { name: 'strike', wire: 'delimited', delim: '~~' },\n { name: 'code', wire: 'delimited', delim: '`' },\n {\n name: 'link',\n wire: 'link',\n attrs: [\n { key: 'href', type: 'string' },\n { key: 'title', type: 'string', optional: true },\n ],\n },\n\n // Extended marks (lossless via MDC syntax)\n {\n name: 'underline',\n wire: 'delimited',\n delim: '__',\n doc: 'Disambiguated from bold by delimiter character. Two underscores = underline; two asterisks = bold.',\n },\n {\n name: 'highlight',\n wire: 'delimited',\n delim: '==',\n doc: 'Pandoc-style.',\n },\n {\n name: 'subscript',\n wire: 'delimited',\n delim: '~',\n doc: 'Single tilde; double tilde is strike.',\n },\n {\n name: 'superscript',\n wire: 'delimited',\n delim: '^',\n },\n {\n name: 'textStyle',\n wire: 'mdc-span',\n attrs: [\n { key: 'color', type: 'string', optional: true },\n { key: 'backgroundColor', type: 'string', optional: true },\n { key: 'fontSize', type: 'string', optional: true },\n { key: 'fontFamily', type: 'string', optional: true },\n ],\n doc: 'Wire form `:span[text]{color=\"…\" font-size=\"…\"}`. Any of the attrs may be set.',\n },\n]\n\nexport const MARK_SPEC_BY_NAME: ReadonlyMap<string, MarkSpec> = new Map(\n MARK_SPECS.map(spec => [spec.name, spec]),\n)\n\nexport const MARK_SPEC_BY_DELIM: ReadonlyMap<string, MarkSpec> = new Map(\n MARK_SPECS\n .filter((spec): spec is MarkSpec & { delim: string } => spec.wire === 'delimited' && !!spec.delim)\n .map(spec => [spec.delim, spec]),\n)\n","// Universal-meta registry.\n//\n// Mirrors `@abraca/schema/src/types/universal.ts` — the canonical\n// source. We don't import @abraca/schema here to keep this package\n// dependency-free, but the keys MUST stay in sync. A future codegen\n// step in @abraca/schema can verify this file is up to date.\n//\n// Order is significant — it's the canonical key order in serialised\n// YAML frontmatter (see SPEC.md §2). Adding new keys appends to the\n// end so existing fixtures don't churn.\n\nexport type MetaValueType =\n | 'string'\n | 'number'\n | 'integer'\n | 'boolean'\n | 'string[]'\n | 'string-enum'\n | 'iso-date'\n | 'iso-datetime'\n | 'hh-mm'\n | 'members'\n | 'json'\n\nexport interface UniversalMetaKey {\n key: string\n type: MetaValueType\n /** Allowed values for `string-enum`. */\n values?: readonly string[]\n /** Inclusive minimum for `number` / `integer`. */\n min?: number\n /** Inclusive maximum for `number` / `integer`. */\n max?: number\n /**\n * Alternate YAML key names recognised on parse — for backwards\n * compatibility with hand-written frontmatter (e.g. `date` → `dateStart`).\n * Serialise always uses the canonical `key`.\n */\n parseAliases?: readonly string[]\n /** Human-readable hint, surfaced in documentation. */\n doc?: string\n}\n\nexport const UNIVERSAL_META_KEYS: readonly UniversalMetaKey[] = [\n // Identity / display\n { key: 'title', type: 'string', doc: 'Display title; the first H1 is hoisted into this field on import.' },\n { key: 'type', type: 'string', doc: 'Page type (doc, kanban, table, …). Omitted on serialise when \"doc\".' },\n { key: 'color', type: 'string', doc: 'Hex or CSS color name.' },\n { key: 'icon', type: 'string', doc: 'Lucide icon name in kebab-case.' },\n\n // Datetime\n { key: 'datetimeStart', type: 'iso-datetime' },\n { key: 'datetimeEnd', type: 'iso-datetime' },\n { key: 'allDay', type: 'boolean' },\n { key: 'dateTaken', type: 'iso-datetime' },\n { key: 'dateStart', type: 'iso-date', parseAliases: ['date', 'created'] },\n { key: 'dateEnd', type: 'iso-date', parseAliases: ['due'] },\n { key: 'timeStart', type: 'hh-mm' },\n { key: 'timeEnd', type: 'hh-mm' },\n\n // Generic\n { key: 'tags', type: 'string[]' },\n { key: 'checked', type: 'boolean', parseAliases: ['done'] },\n {\n key: 'priority',\n type: 'integer',\n min: 0,\n max: 4,\n doc: 'Numeric or named (low/medium/high/urgent → 1/2/3/4).',\n },\n { key: 'status', type: 'string' },\n { key: 'rating', type: 'number', min: 0, max: 5 },\n { key: 'url', type: 'string' },\n { key: 'email', type: 'string' },\n { key: 'phone', type: 'string' },\n { key: 'number', type: 'number' },\n { key: 'unit', type: 'string' },\n { key: 'subtitle', type: 'string', parseAliases: ['description'] },\n { key: 'note', type: 'string' },\n { key: 'taskProgress', type: 'integer', min: 0, max: 100 },\n { key: 'members', type: 'members' },\n\n // Cover\n { key: 'coverUploadId', type: 'string' },\n { key: 'coverDocId', type: 'string' },\n { key: 'coverMimeType', type: 'string' },\n\n // Geo / map\n { key: 'geoType', type: 'string-enum', values: ['marker', 'line', 'measure'] },\n { key: 'geoLat', type: 'number' },\n { key: 'geoLng', type: 'number' },\n { key: 'geoDescription', type: 'string' },\n\n // Dashboard / mindmap / graph layout\n { key: 'deskX', type: 'number' },\n { key: 'deskY', type: 'number' },\n { key: 'deskZ', type: 'number' },\n { key: 'deskMode', type: 'string-enum', values: ['icon', 'widget-sm', 'widget-lg'] },\n { key: 'mmX', type: 'number' },\n { key: 'mmY', type: 'number' },\n { key: 'graphX', type: 'number' },\n { key: 'graphY', type: 'number' },\n { key: 'graphPinned', type: 'boolean' },\n\n // Spatial\n { key: 'spX', type: 'number' },\n { key: 'spY', type: 'number' },\n { key: 'spZ', type: 'number' },\n { key: 'spRX', type: 'number' },\n { key: 'spRY', type: 'number' },\n { key: 'spRZ', type: 'number' },\n { key: 'spSX', type: 'number' },\n { key: 'spSY', type: 'number' },\n { key: 'spSZ', type: 'number' },\n {\n key: 'spShape',\n type: 'string-enum',\n values: ['box', 'sphere', 'cylinder', 'cone', 'plane', 'torus', 'glb'],\n },\n { key: 'spOpacity', type: 'integer', min: 0, max: 100 },\n { key: 'spModelUploadId', type: 'string' },\n { key: 'spModelDocId', type: 'string' },\n\n // Slides\n { key: 'slidesTransition', type: 'string-enum', values: ['none', 'fade', 'slide'] },\n { key: 'slidesTheme', type: 'string-enum', values: ['dark', 'light'] },\n\n // Migration version (last so unknown keys ahead of it surface clearly)\n { key: '__schemaVersion', type: 'integer', min: 0 },\n] as const\n\nexport const UNIVERSAL_META_KEY_NAMES: ReadonlySet<string> = new Set(\n UNIVERSAL_META_KEYS.map(k => k.key),\n)\n\n/**\n * Build a map of every recognised input key (canonical + aliases) to\n * its canonical key. Used by the frontmatter parser.\n */\nexport function buildAliasMap(): ReadonlyMap<string, string> {\n const map = new Map<string, string>()\n for (const entry of UNIVERSAL_META_KEYS) {\n map.set(entry.key, entry.key)\n for (const alias of entry.parseAliases ?? []) map.set(alias, entry.key)\n }\n return map\n}\n","/**\n * Document CRUD commands: read, create, rename, move, delete, type, doc.\n */\nimport * as Y from 'yjs'\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { readEntries, childrenOf, normalizeRootId, resolveDocument, descendantsOf } from '../resolve.ts'\nimport { printJson, relativeTime } from '../output.ts'\nimport { yjsToMarkdown } from '../converters/yjsToMarkdown.ts'\nimport { populateYDocFromMarkdown, parseFrontmatter } from '../converters/markdownToYjs.ts'\n\n/** Safely read a tree map value, converting Y.Map to plain object if needed. */\nfunction toPlain(val: any): any {\n return val instanceof Y.Map ? val.toJSON() : val\n}\n\nregisterCommand({\n name: 'doc',\n aliases: ['info:doc'],\n description: 'Show document metadata (label, type, meta, dates).',\n usage: 'doc id=<docId> | name=<label> | path=<a/b/c>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found. Specify id=, name=, or path= to identify the document.'\n\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found in tree.`\n\n const entry = toPlain(raw)\n\n const lines = [\n `id: ${docId}`,\n `label: ${entry.label || 'Untitled'}`,\n `type: ${entry.type ?? '—'}`,\n `parent: ${entry.parentId ?? '(root)'}`,\n `order: ${entry.order ?? 0}`,\n `created: ${entry.createdAt ? new Date(entry.createdAt).toISOString() : '—'}`,\n `updated: ${entry.updatedAt ? new Date(entry.updatedAt).toISOString() : '—'} (${relativeTime(entry.updatedAt)})`,\n ]\n\n if (entry.meta && Object.keys(entry.meta).length > 0) {\n lines.push(`meta:`)\n for (const [k, v] of Object.entries(entry.meta)) {\n lines.push(` ${k}: ${typeof v === 'object' ? JSON.stringify(v) : v}`)\n }\n }\n\n // Count children\n const entries = readEntries(treeMap)\n const children = childrenOf(entries, docId)\n lines.push(`children: ${children.length}`)\n\n return lines.join('\\n')\n },\n})\n\nregisterCommand({\n name: 'read',\n aliases: ['cat', 'r'],\n description: 'Read document content as markdown.',\n usage: 'read id=<docId> | name=<label> | path=<a/b/c> [--format=json|md]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found. Specify id=, name=, or path= to identify the document.'\n\n try {\n const provider = await conn.getChildProvider(docId)\n const fragment = provider.document.getXmlFragment('default')\n const markdown = yjsToMarkdown(fragment, '')\n\n if (args.flags.has('json') || args.params['format'] === 'json') {\n // Include tree metadata + children\n const treeMap = conn.getTreeMap()\n let label = ''\n let type: string | undefined\n let meta: Record<string, unknown> | undefined\n let children: Array<{ id: string; label: string; type?: string }> = []\n if (treeMap) {\n const entry = treeMap.get(docId)\n if (entry) {\n label = entry.label || label\n type = entry.type\n meta = entry.meta\n }\n treeMap.forEach((value: any, id: string) => {\n const v = toPlain(value)\n if (v.parentId === docId) {\n children.push({ id, label: v.label || 'Untitled', type: v.type })\n }\n })\n children.sort((a: any, b: any) => {\n const va = treeMap.get(a.id)\n const vb = treeMap.get(b.id)\n return ((va?.order ?? 0) - (vb?.order ?? 0))\n })\n }\n return printJson({ label, type, meta, markdown, children })\n }\n\n return markdown || '(empty document)'\n } catch (error: any) {\n return `Error reading document: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'create',\n aliases: ['new'],\n description: 'Create a new document in the tree.',\n usage: 'create label=<name> [parent=<docId>] [type=<pageType>] [content=<markdown>] [--format=json]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const label = args.params['label'] || args.params['name'] || args.positional[0]\n if (!label) return 'Missing required parameter: label=<name>'\n\n const treeMap = conn.getTreeMap()\n const rootDoc = conn.rootDoc\n if (!treeMap || !rootDoc) return 'Not connected'\n\n // Resolve parent\n let parentId: string | null = null\n if (args.params['parent']) {\n parentId = resolveDocument(conn, { id: args.params['parent'], name: args.params['parent'] }, [])\n if (!parentId) parentId = args.params['parent'] // Use raw value as ID\n }\n\n const normalizedParent = normalizeRootId(parentId || conn.rootDocId, conn)\n const type = args.params['type']\n\n const id = crypto.randomUUID()\n const now = Date.now()\n\n // Parse optional meta from params\n const meta: Record<string, unknown> = {}\n if (args.params['icon']) meta['icon'] = args.params['icon']\n if (args.params['color']) meta['color'] = args.params['color']\n\n rootDoc.transact(() => {\n treeMap.set(id, {\n label,\n parentId: normalizedParent,\n order: now,\n type,\n meta: Object.keys(meta).length > 0 ? meta : undefined,\n createdAt: now,\n updatedAt: now,\n })\n })\n\n // Write content if provided\n const content = args.params['content']\n if (content) {\n try {\n const provider = await conn.getChildProvider(id)\n const fragment = provider.document.getXmlFragment('default')\n const contentToWrite = content.replace(/\\\\n/g, '\\n').replace(/\\\\t/g, '\\t')\n populateYDocFromMarkdown(fragment, contentToWrite, label)\n } catch (error: any) {\n return `Created ${id} \"${label}\" but failed to write content: ${error.message}`\n }\n }\n\n if (args.params['format'] === 'json') {\n return printJson({ id, label, parentId: normalizedParent, type })\n }\n\n return `Created: ${id.slice(0, 8)}… \"${label}\"${type ? ` (${type})` : ''}`\n },\n})\n\nregisterCommand({\n name: 'rename',\n description: 'Rename a document.',\n usage: 'rename id=<docId> | name=<oldLabel> label=<newLabel>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const newLabel = args.params['label'] || args.params['to']\n if (!newLabel) return 'Missing required parameter: label=<newLabel>'\n\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found.`\n\n const entry = toPlain(raw)\n treeMap.set(docId, { ...entry, label: newLabel, updatedAt: Date.now() })\n\n return `Renamed to \"${newLabel}\"`\n },\n})\n\nregisterCommand({\n name: 'move',\n aliases: ['mv'],\n description: 'Move a document to a new parent.',\n usage: 'move id=<docId> | name=<label> to=<parentId> [order=<n>]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const newParentId = args.params['to'] || args.params['parent']\n if (!newParentId) return 'Missing required parameter: to=<parentId>'\n\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found.`\n\n const entry = toPlain(raw)\n const order = args.params['order'] ? parseInt(args.params['order'], 10) : Date.now()\n treeMap.set(docId, {\n ...entry,\n parentId: normalizeRootId(newParentId, conn),\n order,\n updatedAt: Date.now(),\n })\n\n return `Moved ${docId.slice(0, 8)}… to parent ${newParentId.slice(0, 8)}…`\n },\n})\n\nregisterCommand({\n name: 'delete',\n aliases: ['rm', 'del'],\n description: 'Soft-delete a document (moves to trash).',\n usage: 'delete id=<docId> | name=<label>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const treeMap = conn.getTreeMap()\n const trashMap = conn.getTrashMap()\n const rootDoc = conn.rootDoc\n if (!treeMap || !trashMap || !rootDoc) return 'Not connected'\n\n const entries = readEntries(treeMap)\n const toDelete = [docId, ...descendantsOf(entries, docId).map(e => e.id)]\n\n const now = Date.now()\n rootDoc.transact(() => {\n for (const nid of toDelete) {\n const raw = treeMap.get(nid)\n if (!raw) continue\n const entry = toPlain(raw)\n trashMap.set(nid, {\n label: entry.label || 'Untitled',\n parentId: entry.parentId ?? null,\n order: entry.order ?? 0,\n type: entry.type,\n meta: entry.meta,\n deletedAt: now,\n })\n treeMap.delete(nid)\n }\n })\n\n return `Deleted ${toDelete.length} document(s)`\n },\n})\n\nregisterCommand({\n name: 'type',\n description: 'Change the page type view of a document.',\n usage: 'type id=<docId> | name=<label> type=<pageType>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const newType = args.params['type'] || args.positional[1]\n if (!newType) return 'Missing required parameter: type=<pageType>'\n\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found.`\n\n const entry = toPlain(raw)\n treeMap.set(docId, { ...entry, type: newType, updatedAt: Date.now() })\n\n return `Changed type to \"${newType}\"`\n },\n})\n\nregisterCommand({\n name: 'write',\n description: 'Write markdown content to a document (replace or append).',\n usage: 'write id=<docId> | name=<label> content=<markdown> [mode=replace|append]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n // Content from param, or read from stdin if piped\n let content = args.params['content']\n\n if (!content) {\n // Check if stdin is piped (not a TTY)\n if (!process.stdin.isTTY) {\n content = await readStdin()\n }\n }\n\n if (!content) return 'Missing required parameter: content=<markdown> (or pipe via stdin)'\n\n // Unescape \\n and \\t\n content = content.replace(/\\\\n/g, '\\n').replace(/\\\\t/g, '\\t')\n\n try {\n const writeMode = args.params['mode'] ?? 'replace'\n const provider = await conn.getChildProvider(docId)\n const doc = provider.document\n const fragment = doc.getXmlFragment('default')\n\n // Parse optional frontmatter\n const { title, meta, body } = parseFrontmatter(content)\n\n // Update tree metadata if frontmatter provided\n if (title || Object.keys(meta).length > 0) {\n const treeMap = conn.getTreeMap()\n const rootDoc = conn.rootDoc\n if (treeMap && rootDoc) {\n const entry = treeMap.get(docId)\n if (entry) {\n const e = toPlain(entry)\n rootDoc.transact(() => {\n const updates: Record<string, unknown> = { ...e, updatedAt: Date.now() }\n if (title) updates.label = title\n if (Object.keys(meta).length > 0) {\n updates.meta = { ...(e.meta ?? {}), ...meta }\n }\n treeMap.set(docId, updates)\n })\n }\n }\n }\n\n if (writeMode === 'replace') {\n doc.transact(() => {\n while (fragment.length > 0) {\n fragment.delete(0)\n }\n })\n }\n\n const contentToWrite = body || content\n populateYDocFromMarkdown(fragment, contentToWrite, title || 'Untitled')\n\n return `Document ${docId.slice(0, 8)}… updated (${writeMode} mode)`\n } catch (error: any) {\n return `Error writing document: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'duplicate',\n aliases: ['dup'],\n description: 'Shallow-clone a document.',\n usage: 'duplicate id=<docId> | name=<label>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found.`\n\n const entry = toPlain(raw)\n const newId = crypto.randomUUID()\n treeMap.set(newId, {\n ...entry,\n label: (entry.label || 'Untitled') + ' (copy)',\n order: Date.now(),\n })\n\n return `Duplicated: ${newId.slice(0, 8)}… \"${entry.label} (copy)\"`\n },\n})\n\n/** Helper to read all of stdin as a string. */\nfunction readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n let data = ''\n process.stdin.setEncoding('utf-8')\n process.stdin.on('data', (chunk: string) => { data += chunk })\n process.stdin.on('end', () => resolve(data))\n process.stdin.on('error', reject)\n // Safety timeout — don't hang forever\n setTimeout(() => resolve(data), 5000)\n })\n}\n","/**\n * Content commands: append, prepend, wc, export.\n */\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { resolveDocument } from '../resolve.ts'\nimport { yjsToMarkdown } from '../converters/yjsToMarkdown.ts'\nimport { populateYDocFromMarkdown } from '../converters/markdownToYjs.ts'\n\nregisterCommand({\n name: 'append',\n description: 'Append content to a document.',\n usage: 'append id=<docId> | name=<label> content=<text> [--inline]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const content = args.params['content']\n if (!content) return 'Missing required parameter: content=<text>'\n\n try {\n const provider = await conn.getChildProvider(docId)\n const fragment = provider.document.getXmlFragment('default')\n const text = args.flags.has('inline')\n ? content.replace(/\\\\n/g, '\\n').replace(/\\\\t/g, '\\t')\n : '\\n' + content.replace(/\\\\n/g, '\\n').replace(/\\\\t/g, '\\t')\n populateYDocFromMarkdown(fragment, text, '')\n\n return `Appended to ${docId.slice(0, 8)}…`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'prepend',\n description: 'Prepend content to a document (after frontmatter).',\n usage: 'prepend id=<docId> | name=<label> content=<text> [--inline]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const content = args.params['content']\n if (!content) return 'Missing required parameter: content=<text>'\n\n try {\n const provider = await conn.getChildProvider(docId)\n const doc = provider.document\n const fragment = doc.getXmlFragment('default')\n\n // Read existing, prepend, rewrite\n const existing = yjsToMarkdown(fragment, '')\n const text = content.replace(/\\\\n/g, '\\n').replace(/\\\\t/g, '\\t')\n const combined = args.flags.has('inline')\n ? text + existing\n : text + '\\n' + existing\n\n doc.transact(() => {\n while (fragment.length > 0) {\n fragment.delete(0)\n }\n })\n populateYDocFromMarkdown(fragment, combined, '')\n\n return `Prepended to ${docId.slice(0, 8)}…`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'wc',\n aliases: ['wordcount'],\n description: 'Count words and characters in a document.',\n usage: 'wc id=<docId> | name=<label> [--words] [--characters]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n try {\n const provider = await conn.getChildProvider(docId)\n const fragment = provider.document.getXmlFragment('default')\n const markdown = yjsToMarkdown(fragment, '')\n\n const words = markdown.split(/\\s+/).filter(Boolean).length\n const chars = markdown.length\n\n if (args.flags.has('words')) return String(words)\n if (args.flags.has('characters')) return String(chars)\n\n return `Words: ${words}\\nCharacters: ${chars}`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'export',\n description: 'Export a document as markdown to a local file.',\n usage: 'export id=<docId> | name=<label> output=<filepath>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const outputPath = args.params['output'] || args.params['to'] || args.params['path']\n if (!outputPath) return 'Missing required parameter: output=<filepath>'\n\n try {\n const provider = await conn.getChildProvider(docId)\n const fragment = provider.document.getXmlFragment('default')\n const treeMap = conn.getTreeMap()\n const title = (treeMap?.get(docId) as any)?.label as string | undefined\n const markdown = yjsToMarkdown(fragment, title ?? '')\n\n const resolvedPath = path.resolve(outputPath)\n fs.writeFileSync(resolvedPath, markdown, 'utf-8')\n\n return `Exported \"${title || 'document'}\" to ${resolvedPath} (${Buffer.byteLength(markdown)} bytes)`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n","/**\n * Metadata commands: meta, tags.\n */\nimport * as Y from 'yjs'\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { readEntries, resolveDocument } from '../resolve.ts'\nimport { printJson, printTable, getFormat } from '../output.ts'\n\n/** Safely read a tree map value. */\nfunction toPlain(val: any): any {\n return val instanceof Y.Map ? val.toJSON() : val\n}\n\nregisterCommand({\n name: 'meta',\n aliases: ['metadata'],\n description: 'Get or set document metadata.',\n usage: 'meta id=<docId> | name=<label> [key=value ...] [--format=json]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found.`\n\n const entry = toPlain(raw)\n\n // Known meta keys across all page types (universal + renderer-specific).\n // Kept in sync with cou-sh/app/composables/useChildTree.ts DocPageMeta and\n // the MCP PageMeta type.\n const metaKeys = new Set([\n // Universal display\n 'color', 'icon', 'subtitle', 'note',\n // Datetime\n 'datetimeStart', 'datetimeEnd', 'allDay', 'dateStart', 'dateEnd',\n 'timeStart', 'timeEnd', 'dateTaken',\n // Task/status\n 'checked', 'priority', 'status', 'taskProgress', 'rating', 'tags', 'members',\n // Contact/value\n 'url', 'email', 'phone', 'number', 'unit',\n // Cover\n 'coverUploadId', 'coverDocId', 'coverMimeType',\n // Geo/Map (children)\n 'geoType', 'geoLat', 'geoLng', 'geoDescription',\n // Dashboard (children)\n 'deskX', 'deskY', 'deskZ', 'deskMode',\n // Mindmap layout (children)\n 'mmX', 'mmY',\n // Graph layout (children)\n 'graphX', 'graphY', 'graphPinned',\n // Spatial 3D children (plugin) — uses universal `color`, not spColor\n 'spShape', 'spOpacity', 'spX', 'spY', 'spZ',\n 'spRX', 'spRY', 'spRZ', 'spSX', 'spSY', 'spSZ',\n 'spModelUploadId', 'spModelDocId',\n // Slides children\n 'slidesTransition',\n // Coder children (plugin)\n 'fileType', 'entry',\n // Sheets cell formatting\n 'bold', 'italic', 'textColor', 'bgColor', 'align', 'formula',\n // Kanban renderer config (on page doc)\n 'kanbanColumnWidth',\n // Gallery renderer config\n 'galleryColumns', 'galleryAspect', 'galleryCardStyle', 'galleryShowLabels', 'gallerySortBy',\n // Calendar renderer config\n 'calendarView', 'calendarWeekStart', 'calendarShowWeekNumbers',\n // Table renderer config\n 'tableMode', 'tableSortKey', 'tableSortDir',\n // Timeline renderer config\n 'timelineZoom', 'timelinePixelsPerDay', 'timelineCenterDate',\n // Checklist renderer config\n 'checklistFilter', 'checklistSort',\n // Map renderer config\n 'mapShowLabels',\n // Graph renderer config\n 'graphSpacing', 'graphShowLabels', 'graphEdgeThickness', 'showRefEdges',\n // Mindmap renderer config\n 'mmSpacing',\n // Spatial renderer config\n 'spatialGridVisible',\n // Slides renderer config\n 'slidesTheme',\n // Chart renderer config\n 'chartType', 'chartMetric', 'chartColorScheme', 'chartLimit',\n 'chartShowLegend', 'chartShowValues',\n // Sheets renderer config\n 'sheetsDefaultColWidth', 'sheetsDefaultRowHeight', 'sheetsShowGridlines',\n 'sheetsFreezeRows', 'sheetsFreezeCols',\n // Media renderer config (plugin)\n 'mediaRepeat', 'mediaShuffle',\n ])\n\n // Keys whose values should be parsed as numbers.\n const numericKeys = new Set([\n 'priority', 'rating', 'number', 'taskProgress', 'geoLat', 'geoLng',\n 'deskX', 'deskY', 'deskZ', 'mmX', 'mmY', 'graphX', 'graphY',\n 'spOpacity', 'spX', 'spY', 'spZ', 'spRX', 'spRY', 'spRZ',\n 'spSX', 'spSY', 'spSZ',\n 'galleryColumns', 'chartLimit', 'timelinePixelsPerDay',\n 'sheetsDefaultColWidth', 'sheetsDefaultRowHeight',\n 'sheetsFreezeRows', 'sheetsFreezeCols',\n ])\n\n const updates: Record<string, unknown> = {}\n let hasUpdates = false\n\n for (const [key, value] of Object.entries(args.params)) {\n if (metaKeys.has(key)) {\n // Parse special types\n if (value === 'null') {\n updates[key] = null\n } else if (value === 'true') {\n updates[key] = true\n } else if (value === 'false') {\n updates[key] = false\n } else if (numericKeys.has(key)) {\n updates[key] = parseFloat(value)\n } else if (key === 'tags') {\n updates[key] = value.split(',').map(s => s.trim())\n } else {\n updates[key] = value\n }\n hasUpdates = true\n }\n }\n\n if (hasUpdates) {\n // Write mode: merge updates into existing meta\n treeMap.set(docId, {\n ...entry,\n meta: { ...(entry.meta ?? {}), ...updates },\n updatedAt: Date.now(),\n })\n return `Metadata updated for ${docId.slice(0, 8)}…`\n }\n\n // Read mode: display current metadata\n const meta = entry.meta ?? {}\n if (args.params['format'] === 'json') {\n return printJson({ id: docId, label: entry.label, type: entry.type, meta })\n }\n\n if (Object.keys(meta).length === 0) {\n return `Document \"${entry.label}\" has no metadata.`\n }\n\n const lines = Object.entries(meta).map(([k, v]) =>\n `${k}: ${typeof v === 'object' ? JSON.stringify(v) : v}`\n )\n return lines.join('\\n')\n },\n})\n\nregisterCommand({\n name: 'tags',\n description: 'List tags aggregated from document metadata.',\n usage: 'tags [id=<docId>] [--counts] [--total] [--format=json|tsv]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n const treeMap = conn.getTreeMap()\n if (!treeMap) return 'Not connected'\n\n // If a document is specified, show its tags\n const docId = resolveDocument(conn, args.params, args.positional)\n if (docId) {\n const raw = treeMap.get(docId)\n if (!raw) return `Document ${docId} not found.`\n const entry = toPlain(raw)\n const tags: string[] = entry.meta?.tags ?? []\n if (tags.length === 0) return 'No tags.'\n return tags.join('\\n')\n }\n\n // Aggregate tags from all documents\n const entries = readEntries(treeMap)\n const tagCounts = new Map<string, number>()\n\n for (const entry of entries) {\n const tags: string[] = (entry.meta as any)?.tags ?? []\n for (const tag of tags) {\n tagCounts.set(tag, (tagCounts.get(tag) ?? 0) + 1)\n }\n }\n\n if (tagCounts.size === 0) return 'No tags found.'\n\n if (args.flags.has('total')) {\n return String(tagCounts.size)\n }\n\n const sorted = [...tagCounts.entries()].sort((a, b) => {\n if (args.params['sort'] === 'count') return b[1] - a[1]\n return a[0].localeCompare(b[0])\n })\n\n const format = getFormat(args, 'text')\n\n if (format === 'json') {\n return printJson(sorted.map(([tag, count]) => ({ tag, count })))\n }\n\n if (args.flags.has('counts')) {\n return sorted.map(([tag, count]) => `${tag}\\t${count}`).join('\\n')\n }\n\n return sorted.map(([tag]) => tag).join('\\n')\n },\n})\n","/**\n * Awareness commands: who, status, chat.\n */\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { printJson, printTable, getFormat } from '../output.ts'\n\nregisterCommand({\n name: 'who',\n aliases: ['users', 'online'],\n description: 'List connected users and their awareness state.',\n usage: 'who [id=<docId>] [--format=json|tsv]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n let awareness\n if (args.params['id']) {\n try {\n const provider = await conn.getChildProvider(args.params['id'])\n awareness = provider.awareness\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n } else {\n const rootProvider = conn.rootProvider\n if (!rootProvider) return 'Not connected'\n awareness = rootProvider.awareness\n }\n\n const states = awareness.getStates()\n const selfId = awareness.clientID\n const users: Array<{\n name: string\n status: string\n docId: string\n isYou: boolean\n isAgent: boolean\n }> = []\n\n for (const [clientId, state] of states) {\n const user = (state as Record<string, any>)['user']\n if (!user) continue\n users.push({\n name: user.name ?? 'Unknown',\n status: (state as Record<string, any>)['status'] ?? '—',\n docId: (state as Record<string, any>)['docId'] ?? '—',\n isYou: clientId === selfId,\n isAgent: user.isAgent ?? false,\n })\n }\n\n const format = getFormat(args, 'text')\n\n if (format === 'json') {\n return printJson(users)\n }\n\n if (users.length === 0) {\n return 'No users connected.'\n }\n\n const rows = users.map(u => [\n u.name + (u.isYou ? ' (you)' : '') + (u.isAgent ? ' 🤖' : ''),\n u.status,\n u.docId === '—' ? '—' : u.docId.slice(0, 8) + '…',\n ])\n\n return printTable(rows, ['NAME', 'STATUS', 'DOCUMENT'])\n },\n})\n\nregisterCommand({\n name: 'status',\n description: 'Set your presence status.',\n usage: 'status <text> | status --clear',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const rootProvider = conn.rootProvider\n if (!rootProvider) return 'Not connected'\n\n if (args.flags.has('clear')) {\n rootProvider.awareness.setLocalStateField('status', null)\n return 'Status cleared.'\n }\n\n const status = args.params['text'] || args.positional[0]\n if (!status) return 'Missing status text. Use: status <text> or status --clear'\n\n rootProvider.awareness.setLocalStateField('status', status)\n return `Status set to \"${status}\"`\n },\n})\n\nregisterCommand({\n name: 'chat',\n aliases: ['send'],\n description: 'Send a chat message to a channel doc.',\n usage: 'chat channel_doc_id=<docId> text=<message>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const rootProvider = conn.rootProvider\n if (!rootProvider) return 'Not connected'\n\n // Accept either `channel_doc_id` or legacy `channel` (with optional\n // `group:` prefix the new server doesn't use — strip it).\n const raw = args.params['channel_doc_id'] || args.params['channel']\n if (!raw) return 'Missing required parameter: channel_doc_id=<docId>'\n const channel_doc_id = raw.startsWith('group:') ? raw.slice(6) : raw\n\n const text = args.params['text'] || args.params['content'] || args.positional[0]\n if (!text) return 'Missing required parameter: text=<message>'\n\n rootProvider.sendStateless(JSON.stringify({\n type: 'messages:send',\n channel_doc_id,\n content: text,\n mentions: [],\n }))\n\n return `Sent to ${channel_doc_id}`\n },\n})\n","/**\n * File attachment commands: upload, uploads.\n */\nimport * as fs from 'node:fs'\nimport * as nodePath from 'node:path'\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { resolveDocument } from '../resolve.ts'\nimport { printJson, printTable, getFormat } from '../output.ts'\n\nregisterCommand({\n name: 'uploads',\n aliases: ['attachments'],\n description: 'List file attachments for a document.',\n usage: 'uploads id=<docId> | name=<label> [--format=json|tsv] [--total]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n try {\n const uploads = await conn.client.listUploads(docId)\n\n if (args.flags.has('total')) {\n return String(uploads.length)\n }\n\n const format = getFormat(args, 'text')\n\n if (format === 'json') {\n return printJson(uploads)\n }\n\n if (uploads.length === 0) {\n return 'No attachments.'\n }\n\n const rows = uploads.map(u => [\n u.id.slice(0, 8) + '…',\n u.filename,\n u.mime_type ?? '—',\n u.size ? formatBytes(u.size) : '—',\n ])\n\n return printTable(rows, ['ID', 'FILENAME', 'TYPE', 'SIZE'])\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'upload',\n description: 'Upload a local file to a document.',\n usage: 'upload id=<docId> | name=<label> file=<localPath> [filename=<override>]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const filePath = args.params['file'] || args.params['path']\n if (!filePath) return 'Missing required parameter: file=<localPath>'\n\n try {\n const resolvedPath = nodePath.resolve(filePath)\n if (!fs.existsSync(resolvedPath)) {\n return `File not found: ${resolvedPath}`\n }\n const data = fs.readFileSync(resolvedPath)\n const filename = args.params['filename'] ?? nodePath.basename(resolvedPath)\n const blob = new Blob([data])\n const result = await conn.client.upload(docId, blob, filename)\n\n return `Uploaded: ${filename} (${formatBytes(data.length)}) → ${result.id}`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n\nregisterCommand({\n name: 'download',\n description: 'Download a file attachment from a document.',\n usage: 'download id=<docId> | name=<label> upload=<uploadId> output=<localPath>',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n const uploadId = args.params['upload'] || args.params['uploadId']\n if (!uploadId) return 'Missing required parameter: upload=<uploadId>'\n\n const outputPath = args.params['output'] || args.params['to']\n if (!outputPath) return 'Missing required parameter: output=<localPath>'\n\n try {\n const blob = await conn.client.getUpload(docId, uploadId)\n const buffer = Buffer.from(await blob.arrayBuffer())\n const resolvedPath = nodePath.resolve(outputPath)\n fs.writeFileSync(resolvedPath, buffer)\n\n return `Downloaded to ${resolvedPath} (${formatBytes(buffer.length)})`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n","/**\n * Permission commands: permissions.\n */\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { resolveDocument } from '../resolve.ts'\nimport { printJson, printTable, getFormat } from '../output.ts'\n\nregisterCommand({\n name: 'permissions',\n aliases: ['perms'],\n description: 'List or set document permissions.',\n usage: 'permissions id=<docId> [user=<userId> role=<role>] [--effective] [--format=json|tsv]',\n async run(conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n if (!conn) return 'Not connected'\n\n const docId = resolveDocument(conn, args.params, args.positional)\n if (!docId) return 'Document not found.'\n\n // Set permission mode\n const targetUser = args.params['user'] || args.params['user_id']\n const targetRole = args.params['role']\n\n if (targetUser && targetRole) {\n try {\n await conn.client.setPermission(docId, {\n user_id: targetUser,\n role: targetRole as 'owner' | 'editor' | 'viewer' | 'observer',\n })\n return `Set ${targetUser.slice(0, 12)}… → ${targetRole} on ${docId.slice(0, 8)}…`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n }\n\n // Remove permission mode\n if (targetUser && args.flags.has('remove')) {\n try {\n await conn.client.removePermission(docId, { user_id: targetUser })\n return `Removed permissions for ${targetUser.slice(0, 12)}… on ${docId.slice(0, 8)}…`\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n }\n\n // List permissions mode\n try {\n const format = getFormat(args, 'text')\n\n if (args.flags.has('effective')) {\n const result = await conn.client.listEffectivePermissions(docId)\n\n if (format === 'json') {\n return printJson(result)\n }\n\n if (result.permissions.length === 0) {\n return `Default role: ${result.default_role}\\nNo explicit permissions.`\n }\n\n const rows = result.permissions.map(p => [\n p.display_name || p.username,\n p.role,\n p.source,\n p.inherited_from_doc_id ? p.inherited_from_doc_id.slice(0, 8) + '…' : '—',\n ])\n\n return `Default role: ${result.default_role}\\n\\n` +\n printTable(rows, ['USER', 'ROLE', 'SOURCE', 'INHERITED FROM'])\n }\n\n const perms = await conn.client.listPermissions(docId)\n\n if (format === 'json') {\n return printJson(perms)\n }\n\n if (perms.length === 0) {\n return 'No explicit permissions set.'\n }\n\n const rows = perms.map(p => [\n p.display_name || p.username,\n p.role,\n p.user_id.slice(0, 12) + '…',\n ])\n\n return printTable(rows, ['USER', 'ROLE', 'USER ID'])\n } catch (error: any) {\n return `Error: ${error.message}`\n }\n },\n})\n","/**\n * Static catalog of Abracadabra page types and their metadata schemas.\n *\n * Kept in sync with `cou-sh/app/utils/docTypes.ts` and the plugin definitions\n * under `cou-sh/plugin-<name>/src/index.ts`. No UI dependencies — it\n * is a plain data description so agents (via MCP) and CLI tooling can discover\n * what fields apply to which renderer without having to read the dashboard\n * source code.\n *\n * Schema semantics (from page-type-guidelines.md):\n *\n * - `metaSchema` — fields that apply to DESCENDANTS (children, grandchildren,\n * and beyond) of a page of this type. E.g. the calendar's schema describes\n * what an *event* meta looks like, not the calendar itself.\n * - `defaultMetaFields` — fields inserted into the page doc's own metadata\n * when first rendered; these are view config knobs (e.g. `calendarView`).\n */\n\nexport type MetaFieldType\n = | 'datetimerange'\n | 'daterange'\n | 'timerange'\n | 'datetime'\n | 'date'\n | 'time'\n | 'slider'\n | 'number'\n | 'toggle'\n | 'select'\n | 'multiselect'\n | 'colorPreset'\n | 'colorPicker'\n | 'location'\n | 'icon'\n | 'textarea'\n | 'url'\n | 'rating'\n | 'tags'\n | 'members'\n\nexport interface PageTypeMetaField {\n type: MetaFieldType\n label?: string\n /** single-value fields */\n key?: string\n /** location */\n latKey?: string\n lngKey?: string\n /** ranges */\n startKey?: string\n endKey?: string\n allDayKey?: string\n /** color preset */\n presets?: string[]\n /** icon / select / tags */\n options?: string[]\n /** slider / number */\n min?: number\n max?: number\n step?: number\n unit?: string\n /** toggle default */\n default?: boolean\n}\n\nexport interface PageTypeInfo {\n key: string\n label: string\n icon: string\n description?: string\n /** true = core type (always available); false = requires plugin */\n core: boolean\n plugin?: string\n supportsChildren: boolean\n childLabel?: string\n grandchildLabel?: string\n /** -1 = unlimited depth */\n defaultDepth?: number\n /** Fields that apply to this doc's descendants (children, grandchildren, ...) */\n metaSchema?: PageTypeMetaField[]\n /** Fields written to this doc's own meta on first render (renderer config) */\n defaultMetaFields?: PageTypeMetaField[]\n}\n\nconst GEO_COLOR_PRESETS = ['#3b82f6', '#f97316', '#22c55e', '#ef4444', '#a855f7']\nconst GEO_ICON_OPTIONS = [\n 'map-pin', 'star', 'flag', 'home', 'building-2', 'coffee', 'utensils',\n 'camera', 'heart', 'zap', 'triangle-alert', 'car', 'plane', 'anchor',\n 'tree-pine', 'mountain', 'waves', 'shield', 'crosshair', 'circle-dot',\n 'bookmark', 'gem', 'radio', 'compass',\n]\n\nexport const GEO_TYPE_META_SCHEMAS: Record<string, PageTypeMetaField[]> = {\n marker: [\n { type: 'location', latKey: 'geoLat', lngKey: 'geoLng', label: 'Location' },\n { type: 'icon', key: 'icon', options: GEO_ICON_OPTIONS, label: 'Icon' },\n { type: 'colorPreset', key: 'color', presets: GEO_COLOR_PRESETS, label: 'Color' },\n ],\n line: [\n { type: 'colorPreset', key: 'color', presets: GEO_COLOR_PRESETS, label: 'Color' },\n ],\n measure: [],\n}\n\nexport const PAGE_TYPES: Record<string, PageTypeInfo> = {\n doc: {\n key: 'doc',\n label: 'Document',\n icon: 'file-text',\n description: 'Rich text document with real-time collaboration',\n core: true,\n supportsChildren: true,\n },\n prose: {\n key: 'prose',\n label: 'Prose',\n icon: 'pen-tool',\n description: 'Long-form prose with serif typography and a narrow readable measure',\n core: true,\n supportsChildren: true,\n childLabel: 'Item',\n defaultDepth: -1,\n },\n kanban: {\n key: 'kanban',\n label: 'Kanban',\n icon: 'kanban',\n description: 'Drag-and-drop task board with columns and cards',\n core: true,\n supportsChildren: true,\n childLabel: 'Column',\n grandchildLabel: 'Card',\n defaultMetaFields: [\n { type: 'select', key: 'kanbanColumnWidth', options: ['narrow', 'default', 'wide'], label: 'Column Width' },\n ],\n },\n gallery: {\n key: 'gallery',\n label: 'Gallery',\n icon: 'images',\n description: 'Visual grid of items with rich content',\n core: true,\n supportsChildren: true,\n childLabel: 'Item',\n metaSchema: [\n { type: 'location', latKey: 'geoLat', lngKey: 'geoLng', label: 'Location' },\n { type: 'datetime', key: 'datetimeStart', label: 'Date' },\n { type: 'tags', key: 'tags', label: 'Tags' },\n { type: 'rating', key: 'rating', max: 5, label: 'Rating' },\n { type: 'icon', key: 'icon', label: 'Icon' },\n { type: 'colorPreset', key: 'color', presets: ['#6366f1', '#ec4899', '#f97316', '#22c55e', '#3b82f6', '#a855f7'], label: 'Color' },\n ],\n defaultMetaFields: [\n { type: 'number', key: 'galleryColumns', min: 1, max: 6, step: 1, label: 'Columns' },\n { type: 'select', key: 'galleryAspect', options: ['square', '4:3', '3:2', '16:9', 'free'], label: 'Aspect Ratio' },\n { type: 'select', key: 'galleryCardStyle', options: ['default', 'compact', 'detailed'], label: 'Card Style' },\n { type: 'toggle', key: 'galleryShowLabels', label: 'Show Labels' },\n { type: 'select', key: 'gallerySortBy', options: ['manual', 'date', 'name', 'rating'], label: 'Sort' },\n ],\n },\n table: {\n key: 'table',\n label: 'Table',\n icon: 'table',\n description: 'Collaborative spreadsheet with custom fields',\n core: true,\n supportsChildren: true,\n childLabel: 'Column',\n grandchildLabel: 'Row',\n defaultMetaFields: [\n { type: 'select', key: 'tableMode', options: ['hierarchy', 'flat'], label: 'Mode' },\n { type: 'select', key: 'tableSortDir', options: ['asc', 'desc'], label: 'Sort Direction' },\n ],\n },\n outline: {\n key: 'outline',\n label: 'Outline',\n icon: 'list-tree',\n description: 'Hierarchical outline with keyboard navigation',\n core: true,\n supportsChildren: true,\n childLabel: 'Item',\n defaultDepth: -1,\n },\n checklist: {\n key: 'checklist',\n label: 'Checklist',\n icon: 'check-square',\n description: 'Collaborative checklist with sub-tasks, drag-and-drop, and due dates',\n core: true,\n supportsChildren: true,\n childLabel: 'Task',\n defaultDepth: -1,\n metaSchema: [\n { type: 'toggle', key: 'checked', label: 'Done' },\n { type: 'select', key: 'priority', options: ['none', 'low', 'medium', 'high'], label: 'Priority' },\n { type: 'date', key: 'dateEnd', label: 'Due date' },\n ],\n defaultMetaFields: [\n { type: 'select', key: 'checklistFilter', options: ['all', 'active', 'completed'], label: 'Filter' },\n { type: 'select', key: 'checklistSort', options: ['manual', 'priority', 'due'], label: 'Sort' },\n ],\n },\n graph: {\n key: 'graph',\n label: 'Graph',\n icon: 'git-fork',\n description: 'Force-directed knowledge graph — full document tree as nodes & edges',\n core: true,\n supportsChildren: true,\n childLabel: 'Node',\n defaultMetaFields: [\n { type: 'toggle', key: 'showRefEdges', label: 'Show Ref Edges', default: true },\n ],\n },\n timeline: {\n key: 'timeline',\n label: 'Timeline',\n icon: 'gantt-chart',\n description: 'Gantt-style project timeline with epics and tasks',\n core: true,\n supportsChildren: true,\n childLabel: 'Epic',\n grandchildLabel: 'Task',\n metaSchema: [\n { type: 'daterange', startKey: 'dateStart', endKey: 'dateEnd' },\n { type: 'slider', key: 'taskProgress', min: 0, max: 100, label: 'Progress' },\n { type: 'colorPreset', key: 'color', presets: ['#6366f1', '#818cf8', '#f97316', '#22c55e', '#3b82f6', '#a855f7'], label: 'Color' },\n ],\n },\n calendar: {\n key: 'calendar',\n label: 'Calendar',\n icon: 'calendar',\n description: 'Event calendar with month, week, and day views',\n core: true,\n supportsChildren: true,\n childLabel: 'Event',\n metaSchema: [\n { type: 'datetimerange', startKey: 'datetimeStart', endKey: 'datetimeEnd', allDayKey: 'allDay' },\n { type: 'colorPreset', key: 'color', presets: ['#6366f1', '#ec4899', '#f97316', '#22c55e', '#3b82f6', '#a855f7'], label: 'Color' },\n { type: 'icon', key: 'icon', label: 'Icon' },\n ],\n defaultMetaFields: [\n { type: 'select', key: 'calendarWeekStart', options: ['sun', 'mon'], label: 'Week Starts' },\n { type: 'select', key: 'calendarView', options: ['month', 'week', 'day'], label: 'Default View' },\n { type: 'toggle', key: 'calendarShowWeekNumbers', label: 'Show Week Numbers' },\n ],\n },\n map: {\n key: 'map',\n label: 'Map',\n icon: 'map',\n description: 'Collaborative world map with shared markers',\n core: true,\n supportsChildren: true,\n childLabel: 'Location',\n defaultMetaFields: [\n { type: 'toggle', key: 'mapShowLabels', label: 'Show Labels', default: true },\n ],\n },\n dashboard: {\n key: 'dashboard',\n label: 'Dashboard',\n icon: 'layout-dashboard',\n description: 'Arrange documents as draggable icons with optional widget views',\n core: true,\n supportsChildren: true,\n childLabel: 'Item',\n },\n call: {\n key: 'call',\n label: 'Call',\n icon: 'phone',\n description: 'Video call room with live audio and screen sharing',\n core: true,\n supportsChildren: false,\n },\n chart: {\n key: 'chart',\n label: 'Chart',\n icon: 'bar-chart-3',\n description: 'Charts — manual data points or aggregation over document trees',\n core: true,\n supportsChildren: true,\n childLabel: 'Data Point',\n grandchildLabel: 'Data Point',\n metaSchema: [\n { type: 'number', key: 'number', step: 0.01, label: 'Value' },\n { type: 'colorPreset', key: 'color', presets: ['#6366f1', '#ec4899', '#f97316', '#22c55e', '#3b82f6', '#a855f7', '#14b8a6', '#eab308'], label: 'Color' },\n { type: 'tags', key: 'tags', label: 'Tags' },\n ],\n defaultMetaFields: [\n { type: 'select', key: 'chartType', options: ['bar', 'stacked bar', 'line', 'donut', 'treemap'], label: 'Chart Type' },\n { type: 'select', key: 'chartMetric', options: ['value', 'type', 'tag', 'status', 'priority', 'activity', 'completion'], label: 'Metric' },\n { type: 'select', key: 'chartColorScheme', options: ['default', 'warm', 'cool', 'mono'], label: 'Colors' },\n { type: 'number', key: 'chartLimit', min: 3, max: 30, step: 1, label: 'Max Items' },\n { type: 'toggle', key: 'chartShowLegend', label: 'Show Legend', default: true },\n { type: 'toggle', key: 'chartShowValues', label: 'Show Values' },\n ],\n },\n sheets: {\n key: 'sheets',\n label: 'Sheets',\n icon: 'grid-3x3',\n description: 'Spreadsheet — cells, formulas, and formatting in a collaborative grid',\n core: true,\n supportsChildren: true,\n childLabel: 'Column',\n grandchildLabel: 'Cell',\n defaultMetaFields: [\n { type: 'number', key: 'sheetsDefaultColWidth', min: 40, max: 500, step: 10, label: 'Column Width' },\n { type: 'number', key: 'sheetsDefaultRowHeight', min: 20, max: 100, step: 2, label: 'Row Height' },\n { type: 'toggle', key: 'sheetsShowGridlines', label: 'Gridlines' },\n ],\n },\n slides: {\n key: 'slides',\n label: 'Slides',\n icon: 'presentation',\n description: 'Presentation slides with two-axis navigation',\n core: true,\n supportsChildren: true,\n childLabel: 'Slide',\n grandchildLabel: 'Sub-slide',\n metaSchema: [\n { type: 'select', key: 'slidesTransition', options: ['none', 'fade', 'slide'], label: 'Transition' },\n { type: 'colorPreset', key: 'color', presets: ['#6366f1', '#ec4899', '#f97316', '#22c55e', '#3b82f6', '#a855f7'], label: 'Accent' },\n ],\n defaultMetaFields: [\n { type: 'select', key: 'slidesTheme', options: ['dark', 'light'], label: 'Theme' },\n ],\n },\n overview: {\n key: 'overview',\n label: 'Overview',\n icon: 'radar',\n description: 'Space home — activity, people, stats, and health at a glance',\n core: true,\n supportsChildren: true,\n childLabel: 'Page',\n },\n\n // Plugin-contributed types — require the named plugin to be enabled server-side.\n\n spatial: {\n key: 'spatial',\n label: 'Spatial',\n icon: 'box',\n description: '3D scene with collaborative objects and real-time presence',\n core: false,\n plugin: 'spatial',\n supportsChildren: true,\n childLabel: 'Object',\n grandchildLabel: 'Part',\n defaultDepth: -1,\n metaSchema: [\n { type: 'select', key: 'spShape', options: ['box', 'sphere', 'cylinder', 'cone', 'plane', 'torus', 'glb'], label: 'Shape' },\n { type: 'colorPreset', key: 'color', presets: ['#6366f1', '#ef4444', '#22c55e', '#3b82f6', '#f97316', '#a855f7', '#ec4899', '#14b8a6'], label: 'Color' },\n { type: 'slider', key: 'spOpacity', min: 0, max: 100, label: 'Opacity' },\n { type: 'number', key: 'spX', step: 0.1, label: 'X' },\n { type: 'number', key: 'spY', step: 0.1, label: 'Y' },\n { type: 'number', key: 'spZ', step: 0.1, label: 'Z' },\n { type: 'number', key: 'spRX', min: -180, max: 180, step: 1, label: 'Rot X' },\n { type: 'number', key: 'spRY', min: -180, max: 180, step: 1, label: 'Rot Y' },\n { type: 'number', key: 'spRZ', min: -180, max: 180, step: 1, label: 'Rot Z' },\n { type: 'number', key: 'spSX', min: 0.01, max: 100, step: 0.1, label: 'Scale X' },\n { type: 'number', key: 'spSY', min: 0.01, max: 100, step: 0.1, label: 'Scale Y' },\n { type: 'number', key: 'spSZ', min: 0.01, max: 100, step: 0.1, label: 'Scale Z' },\n ],\n defaultMetaFields: [\n { type: 'toggle', key: 'spatialGridVisible', label: 'Show Grid', default: true },\n ],\n },\n media: {\n key: 'media',\n label: 'Media',\n icon: 'disc-3',\n description: 'Media player with synced listening and playlists',\n core: false,\n plugin: 'media',\n supportsChildren: true,\n childLabel: 'Track',\n defaultDepth: -1,\n metaSchema: [\n { type: 'tags', key: 'tags', label: 'Tags' },\n ],\n defaultMetaFields: [\n { type: 'select', key: 'mediaRepeat', options: ['off', 'all', 'one'], label: 'Repeat' },\n { type: 'toggle', key: 'mediaShuffle', label: 'Shuffle' },\n ],\n },\n coder: {\n key: 'coder',\n label: 'Coder',\n icon: 'code-2',\n description: 'Collaborative multi-file coding environment',\n core: false,\n plugin: 'coder',\n supportsChildren: true,\n childLabel: 'File',\n defaultDepth: -1,\n metaSchema: [\n { type: 'select', key: 'fileType', options: ['vue', 'ts', 'js', 'css', 'json', 'folder'], label: 'Type' },\n { type: 'toggle', key: 'entry', label: 'Entry Point' },\n ],\n },\n}\n\nexport const TYPE_ALIASES: Record<string, string> = {\n desktop: 'dashboard',\n}\n\nexport function resolvePageType(key: string | undefined): PageTypeInfo | undefined {\n if (!key) return undefined\n const resolved = TYPE_ALIASES[key] ?? key\n return PAGE_TYPES[resolved]\n}\n","/**\n * page-types / type-info commands: enumerate Abracadabra page types and their\n * metadata schemas. Works without a server connection — the catalog is static.\n */\nimport { registerCommand } from '../command.ts'\nimport type { CLIConnection } from '../connection.ts'\nimport type { ParsedArgs } from '../parser.ts'\nimport { printJson } from '../output.ts'\nimport { PAGE_TYPES, TYPE_ALIASES, resolvePageType } from '../converters/page-types.ts'\nimport type { PageTypeInfo, PageTypeMetaField } from '../converters/page-types.ts'\n\nfunction describeField(f: PageTypeMetaField): string {\n const bits: string[] = []\n bits.push(f.type as string)\n if (f.key) bits.push(`key=${f.key}`)\n if (f.latKey) bits.push(`latKey=${f.latKey},lngKey=${f.lngKey}`)\n if (f.startKey) bits.push(`startKey=${f.startKey},endKey=${f.endKey}${f.allDayKey ? `,allDayKey=${f.allDayKey}` : ''}`)\n if (f.options) bits.push(`options=[${f.options.join(', ')}]`)\n if (f.presets) bits.push(`presets=${f.presets.length}`)\n if (typeof f.min === 'number' || typeof f.max === 'number') bits.push(`range=${f.min ?? '?'}..${f.max ?? '?'}`)\n if (f.step) bits.push(`step=${f.step}`)\n if (f.unit) bits.push(`unit=${f.unit}`)\n if (f.default !== undefined) bits.push(`default=${f.default}`)\n return bits.join(' ')\n}\n\nregisterCommand({\n name: 'page-types',\n aliases: ['types', 'doctypes'],\n description: 'List Abracadabra page types and their metadata schemas.',\n usage: 'page-types [key=<type>] [--format=json]',\n async run(_conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n const key = args.params['key'] || args.params['type'] || args.positional[0]\n const asJson = args.flags.has('json') || args.params['format'] === 'json'\n\n if (key) {\n const info = resolvePageType(key)\n if (!info) {\n return `Unknown page type \"${key}\". Run 'abracadabra page-types' to list all.`\n }\n if (asJson) return printJson(info)\n\n const lines: string[] = [\n `${info.label} (${info.key})${info.core ? '' : ` [plugin: ${info.plugin}]`}`,\n info.description ? ` ${info.description}` : '',\n ` icon: ${info.icon}`,\n ` supportsChildren: ${info.supportsChildren}`,\n ]\n if (info.childLabel) lines.push(` childLabel: ${info.childLabel}`)\n if (info.grandchildLabel) lines.push(` grandchildLabel: ${info.grandchildLabel}`)\n if (info.defaultDepth !== undefined) lines.push(` defaultDepth: ${info.defaultDepth === -1 ? 'unlimited' : info.defaultDepth}`)\n\n if (info.metaSchema?.length) {\n lines.push('', ` metaSchema (applies to descendants):`)\n for (const f of info.metaSchema) lines.push(` - ${describeField(f)}${f.label ? ` \"${f.label}\"` : ''}`)\n }\n if (info.defaultMetaFields?.length) {\n lines.push('', ` defaultMetaFields (renderer config on this doc):`)\n for (const f of info.defaultMetaFields) lines.push(` - ${describeField(f)}${f.label ? ` \"${f.label}\"` : ''}`)\n }\n return lines.filter(Boolean).join('\\n')\n }\n\n // List all\n const types = Object.values(PAGE_TYPES) as PageTypeInfo[]\n if (asJson) return printJson({ types, aliases: TYPE_ALIASES })\n\n const coreTypes = types.filter((t) => t.core)\n const pluginTypes = types.filter((t) => !t.core)\n\n const lines: string[] = ['Core page types:']\n for (const t of coreTypes) {\n const depth = t.defaultDepth === -1 ? '∞' : (t.grandchildLabel ? '2' : (t.supportsChildren ? '1' : '0'))\n const nesting = [t.childLabel, t.grandchildLabel].filter(Boolean).join(' → ')\n lines.push(` ${t.key.padEnd(12)}${(nesting || '—').padEnd(28)}depth=${depth}`)\n }\n lines.push('', 'Plugin page types (require plugin):')\n for (const t of pluginTypes) {\n const depth = t.defaultDepth === -1 ? '∞' : (t.grandchildLabel ? '2' : (t.supportsChildren ? '1' : '0'))\n const nesting = [t.childLabel, t.grandchildLabel].filter(Boolean).join(' → ')\n lines.push(` ${t.key.padEnd(12)}${(nesting || '—').padEnd(28)}depth=${depth} [plugin: ${t.plugin}]`)\n }\n lines.push('', 'Aliases:')\n for (const [from, to] of Object.entries(TYPE_ALIASES)) {\n lines.push(` ${from} → ${to}`)\n }\n lines.push('', `Run 'abracadabra page-types <key>' for field-level detail.`)\n return lines.join('\\n')\n },\n})\n","/**\n * Rate-limited wrapper around wtf_wikipedia + wtf-plugin-api.\n *\n * Responsibilities:\n * - Throttle requests to respect Wikimedia API etiquette\n * - Cache parsed Documents by canonical title\n * - Resolve redirects so callers always see the redirect target\n * - Expose getCategoryPages via wtf-plugin-api\n */\n// @ts-ignore — wtf_wikipedia ships its own types but they are imprecise; we\n// cast Link/Section APIs as needed below.\nimport wtf from 'wtf_wikipedia'\n// @ts-ignore — wtf-plugin-api is JS-only with no types; treat as opaque.\nimport wtfApiPlugin from 'wtf-plugin-api'\n\n// Augment wtf at module load so getCategoryPages becomes available.\nlet pluginExtended = false\nfunction ensurePlugin(): void {\n if (pluginExtended) return\n // @ts-ignore — extend is dynamically attached to the wtf default export.\n wtf.extend(wtfApiPlugin)\n pluginExtended = true\n}\n\nexport interface WikipediaClientConfig {\n lang: string\n domain?: string\n userAgent: string\n /** Max requests per second. */\n rate: number\n}\n\ninterface FetchOpts {\n lang?: string\n domain?: string\n 'Api-User-Agent'?: string\n follow_redirects?: boolean\n}\n\n/** A token-bucket-ish throttle: at most `rate` calls per second, FIFO. */\nclass RateLimiter {\n private lastTickMs = 0\n constructor(private intervalMs: number) {}\n\n async wait(): Promise<void> {\n const now = Date.now()\n const earliest = this.lastTickMs + this.intervalMs\n if (now < earliest) {\n await new Promise((r) => setTimeout(r, earliest - now))\n }\n this.lastTickMs = Math.max(now, earliest)\n }\n}\n\nexport class WikipediaClient {\n private cache = new Map<string, any>()\n private redirects = new Map<string, string>()\n private limiter: RateLimiter\n private fetchOpts: FetchOpts\n\n constructor(private config: WikipediaClientConfig) {\n ensurePlugin()\n this.limiter = new RateLimiter(Math.max(50, Math.floor(1000 / Math.max(0.1, config.rate))))\n this.fetchOpts = {\n lang: config.lang,\n 'Api-User-Agent': config.userAgent,\n follow_redirects: true,\n }\n if (config.domain) this.fetchOpts.domain = config.domain\n }\n\n /**\n * Fetch and parse a Wikipedia article.\n * - Returns the cached Document if we've seen this title before.\n * - Follows redirects and caches under both source and target titles.\n * - Returns null when the page does not exist.\n */\n async fetchArticle(rawTitle: string): Promise<any | null> {\n const title = canonicalTitle(rawTitle)\n if (this.cache.has(title)) return this.cache.get(title)\n if (this.redirects.has(title)) {\n const target = this.redirects.get(title)!\n return this.cache.get(target) ?? null\n }\n\n await this.limiter.wait()\n let doc: any\n try {\n doc = await (wtf as any).fetch(title, this.fetchOpts)\n } catch (err: any) {\n throw new Error(`Wikipedia fetch failed for \"${title}\": ${err?.message ?? err}`)\n }\n if (!doc) return null\n\n // wtf usually follows redirects automatically when follow_redirects=true,\n // but defensively handle the case where it surfaces a redirect doc.\n if (typeof doc.isRedirect === 'function' && doc.isRedirect()) {\n const target = doc.redirectTo?.()?.page\n if (typeof target === 'string') {\n this.redirects.set(title, canonicalTitle(target))\n const inner = await this.fetchArticle(target)\n return inner\n }\n }\n\n const resolvedTitle = canonicalTitle(doc.title?.() ?? title)\n this.cache.set(resolvedTitle, doc)\n if (resolvedTitle !== title) this.redirects.set(title, resolvedTitle)\n return doc\n }\n\n /**\n * Fetch the member pages of a category (and optionally sub-categories).\n * @param category Category title (with or without \"Category:\" prefix).\n * @param recursive Whether to traverse sub-categories.\n * @param maxDepth Recursion depth when recursive=true.\n */\n async fetchCategoryPages(\n category: string,\n recursive: boolean,\n maxDepth: number,\n ): Promise<Array<{ title: string; type: 'page' | 'subcat' }>> {\n await this.limiter.wait()\n const opts: Record<string, unknown> = {\n lang: this.config.lang,\n 'Api-User-Agent': this.config.userAgent,\n recursive,\n maxDepth,\n }\n if (this.config.domain) opts.domain = this.config.domain\n // @ts-ignore — getCategoryPages is attached at runtime via wtf.extend.\n const list: any[] = await wtf.getCategoryPages(category, opts)\n return (list ?? []).map((m) => ({\n title: canonicalTitle(m.title),\n type: m.type === 'subcat' ? 'subcat' : 'page',\n }))\n }\n}\n\n/** Normalize a Wikipedia title — trim, collapse spaces, strip leading/trailing colons. */\nexport function canonicalTitle(s: string): string {\n return (s ?? '').toString().replace(/_/g, ' ').replace(/\\s+/g, ' ').trim()\n}\n\n/** Detect a category-namespaced title. */\nconst CATEGORY_PREFIX = /^(Category|Catégorie|Kategorie|Categoría|Categoria|Categorie|Kategoria):/i\nexport function isCategoryTitle(title: string): boolean {\n return CATEGORY_PREFIX.test(title)\n}\n\n/** Strip the \"Category:\" prefix for display. */\nexport function stripCategoryPrefix(title: string): string {\n return title.replace(CATEGORY_PREFIX, '').trim()\n}\n","/**\n * Snapshot a wtf_wikipedia Document into a plain-data shape that's easy to\n * work with downstream. No BFS / no plan-building here — just a pure read\n * of one parsed page.\n */\nimport type { ExtractedArticle, ExtractedSection } from './types.ts'\nimport { canonicalTitle, isCategoryTitle, stripCategoryPrefix } from './wikipedia.ts'\n\nexport { canonicalTitle, isCategoryTitle, stripCategoryPrefix }\n\nexport function snapshotArticle(doc: any, title: string): ExtractedArticle {\n return {\n title,\n linkTitles: collectLinkTitles(doc),\n categories: collectCategories(doc),\n sections: snapshotSections(doc.sections?.() ?? []),\n infobox: snapshotInfobox(doc.infobox?.()),\n lead: leadParagraph(doc),\n url: typeof doc.url === 'function' ? doc.url() : null,\n }\n}\n\nexport function prettyCategoryLabel(catTitle: string): string {\n return stripCategoryPrefix(catTitle)\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Link / category extraction\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction collectLinkTitles(doc: any): string[] {\n const links = doc.links?.() ?? []\n const out = new Set<string>()\n for (const l of links) {\n if (!l) continue\n const page = typeof l.page === 'function' ? l.page() : null\n if (typeof page !== 'string' || page.length === 0) continue\n if (isCategoryTitle(page)) continue\n out.add(canonicalTitle(page))\n }\n return [...out]\n}\n\nfunction collectCategories(doc: any): string[] {\n const out: string[] = []\n for (const c of (doc.categories?.() as string[] | undefined) ?? []) {\n const norm = canonicalTitle(c)\n if (norm) out.push(norm)\n }\n return out\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Sections — flatten wtf's parent-child references into a real tree\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction snapshotSections(rawSections: any[]): ExtractedSection[] {\n const all = rawSections.map((s) => ({\n raw: s,\n title: s.title?.() || '',\n parentRef: typeof s.parent === 'function' ? s.parent() : null,\n children: [] as ExtractedSection[],\n }))\n\n const byRaw = new Map<any, (typeof all)[number]>()\n for (const s of all) byRaw.set(s.raw, s)\n\n const roots: (typeof all)[number][] = []\n for (const s of all) {\n if (s.parentRef && byRaw.has(s.parentRef)) {\n byRaw.get(s.parentRef)!.children.push(materialize(s))\n } else {\n roots.push(s)\n }\n }\n return roots.map(materialize)\n}\n\nfunction materialize(node: {\n raw: any\n title: string\n children: ExtractedSection[]\n}): ExtractedSection {\n const lists = node.raw.lists?.() ?? []\n const paragraphs = node.raw.paragraphs?.() ?? []\n\n let listLength = 0\n for (const l of lists) {\n const lines = l.lines?.() ?? []\n listLength += lines.length\n }\n const isList =\n lists.length > 0 && (paragraphs.length === 0 || listLength >= paragraphs.length * 2)\n\n const bodyParts: string[] = []\n for (const p of paragraphs) {\n const md = paragraphMarkdown(p)\n if (md) bodyParts.push(md)\n }\n for (const l of lists) {\n const lines = (l.lines?.() ?? []) as any[]\n for (const line of lines) {\n const text = lineText(line)\n if (text) bodyParts.push(`- ${text}`)\n }\n }\n\n return {\n title: node.title,\n body: bodyParts.join('\\n\\n'),\n isList,\n listLength,\n children: node.children,\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Infobox\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction snapshotInfobox(box: any | null | undefined): Array<{ key: string; value: string }> | undefined {\n if (!box) return undefined\n const data = typeof box.json === 'function' ? box.json() : null\n if (!data || typeof data !== 'object') return undefined\n const rows: Array<{ key: string; value: string }> = []\n for (const [key, val] of Object.entries(data)) {\n const value = stringifyInfoboxValue(val)\n if (!value) continue\n rows.push({ key: humanKey(key), value })\n }\n return rows.length > 0 ? rows : undefined\n}\n\nfunction stringifyInfoboxValue(val: unknown): string {\n if (val == null) return ''\n if (typeof val === 'string') return val\n if (typeof val === 'number' || typeof val === 'boolean') return String(val)\n if (Array.isArray(val)) {\n return val.map(stringifyInfoboxValue).filter(Boolean).join(', ')\n }\n if (typeof val === 'object') {\n const o = val as Record<string, unknown>\n if (typeof o.text === 'string') return o.text\n if (typeof o.number === 'number') return String(o.number)\n }\n return ''\n}\n\nfunction humanKey(k: string): string {\n return k.replace(/_/g, ' ').replace(/^./, (m) => m.toUpperCase())\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Markdown rendering\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction leadParagraph(doc: any): string {\n const paras = doc.paragraphs?.() ?? []\n const first = paras[0]\n if (!first) return ''\n return paragraphMarkdown(first)\n}\n\n/**\n * Render a paragraph as markdown, replacing internal links with `[[Title]]`.\n * The streaming orchestrator's link rewriter later swaps `[[Title]]` →\n * `[[docId|label]]` once IDs are known.\n */\nfunction paragraphMarkdown(paragraph: any): string {\n const sentences = paragraph.sentences?.() ?? []\n const out: string[] = []\n for (const s of sentences) {\n out.push(sentenceWithWikilinks(s))\n }\n return out.join(' ').trim()\n}\n\nfunction sentenceWithWikilinks(sentence: any): string {\n const text: string = (sentence.text?.() ?? '').toString()\n const links = sentence.links?.() ?? []\n if (links.length === 0) return text\n\n let result = text\n const replacements = links\n .map((l: any) => {\n const page = typeof l.page === 'function' ? l.page() : null\n const display = typeof l.text === 'function' ? l.text() : null\n if (typeof page !== 'string' || page.length === 0) return null\n if (isCategoryTitle(page)) return null\n const shown = (display && display.length > 0 ? display : page) as string\n return { page: canonicalTitle(page), shown }\n })\n .filter((x: any): x is { page: string; shown: string } => x !== null)\n .sort((a: any, b: any) => b.shown.length - a.shown.length)\n\n for (const { page, shown } of replacements) {\n if (!result.includes(shown)) continue\n const replacement = shown === page ? `[[${page}]]` : `[[${page}|${shown}]]`\n result = result.replace(shown, replacement)\n }\n return result\n}\n\nfunction lineText(line: any): string {\n if (!line) return ''\n if (typeof line === 'string') return line\n if (typeof line.text === 'string') return line.text\n if (typeof line.text === 'function') return line.text()\n return ''\n}\n","/**\n * Body rendering + page-type decisions for the streaming orchestrator.\n *\n * All rendering is title-driven: bodies are rendered with `[[Title]]`\n * placeholders, and `rewriteLinks` rewrites them to `[[docId|label]]`\n * using the live title→docId map at write time.\n */\nimport type { ExtractedArticle, ExtractedSection } from './types.ts'\n\nexport const ICONS = {\n graph: 'git-fork',\n article: 'book-open',\n category: 'tag',\n infobox: 'info',\n outline: 'list',\n gallery: 'images',\n section: 'pilcrow',\n categories: 'tags',\n} as const\n\n/** Decide a page type for a section based on its shape. */\nexport function pickSectionType(section: ExtractedSection): { type: string; icon: string } {\n if (section.children.length > 0) return { type: 'outline', icon: ICONS.outline }\n if (section.isList && section.listLength >= 5) return { type: 'outline', icon: ICONS.outline }\n return { type: 'doc', icon: ICONS.section }\n}\n\n/** Render the lead paragraph as the article-doc body. */\nexport function renderArticleLead(article: ExtractedArticle): string {\n return article.lead ?? ''\n}\n\n/** Render the article as a single doc, sections + infobox inlined. */\nexport function renderArticleSingleDoc(article: ExtractedArticle): string {\n const parts: string[] = []\n if (article.lead) parts.push(article.lead)\n if (article.infobox && article.infobox.length > 0) {\n parts.push('## Infobox', renderInfoboxBody(article.infobox))\n }\n for (const section of article.sections) {\n parts.push(...renderSectionInline(section, 2))\n }\n return parts.join('\\n\\n')\n}\n\nfunction renderSectionInline(section: ExtractedSection, level: number): string[] {\n const out: string[] = []\n const prefix = '#'.repeat(Math.min(6, level))\n if (section.title) out.push(`${prefix} ${section.title}`)\n if (section.body.trim()) out.push(section.body)\n for (const child of section.children) {\n out.push(...renderSectionInline(child, level + 1))\n }\n return out\n}\n\nexport function renderInfoboxBody(rows: Array<{ key: string; value: string }>): string {\n return rows.map((r) => `- **${r.key}:** ${r.value}`).join('\\n')\n}\n\nexport function renderCategoryBody(members: string[], subcategories: string[]): string {\n const parts: string[] = []\n if (members.length > 0) {\n parts.push('## Pages')\n parts.push(members.map((m) => `- [[${m}]]`).join('\\n'))\n }\n if (subcategories.length > 0) {\n parts.push('## Sub-categories')\n parts.push(subcategories.map((s) => `- ${s}`).join('\\n'))\n }\n return parts.join('\\n\\n')\n}\n\n/**\n * Replace `[[Title]]` / `[[Title|Alias]]` in markdown with\n * `[[docId|label]]` using the title→docId map. Unresolved titles fall\n * back to plain text (their alias or original title).\n */\nexport function rewriteLinks(\n markdown: string,\n titleToDocId: Map<string, string>,\n): string {\n const re = /\\[\\[([^\\]|]+?)(?:\\|([^\\]]+?))?\\]\\]/g\n return markdown.replace(re, (_match, target: string, alias?: string) => {\n const title = target.trim()\n const docId = titleToDocId.get(title)\n const display = (alias && alias.trim().length > 0 ? alias : title).trim()\n if (!docId) return display\n return `[[${docId}|${display}]]`\n })\n}\n","/**\n * Open a DocumentManager session for the wiki command, mirroring the\n * auth/register flow that CLIConnection uses but using the modern public API.\n *\n * Reuses the CLI's Ed25519 keypair handling (loadOrCreateKeypair, signChallenge)\n * so the wiki command authenticates with the same identity as every other\n * subcommand.\n */\nimport { DocumentManager } from '@abraca/dabra'\nimport { loadOrCreateKeypair, signChallenge } from '../../crypto.ts'\n\nexport interface OpenSessionConfig {\n url: string\n name?: string\n color?: string\n inviteCode?: string\n keyFile?: string\n /** Suppress informational stderr logging. */\n quiet?: boolean\n}\n\nexport interface OpenSessionResult {\n dm: DocumentManager\n /** Active root doc id (the entry-point space). */\n rootDocId: string\n}\n\nexport async function openSession(config: OpenSessionConfig): Promise<OpenSessionResult> {\n const keypair = await loadOrCreateKeypair(config.keyFile)\n const sign = (challenge: string) => Promise.resolve(signChallenge(challenge, keypair.privateKey))\n\n const dm = new DocumentManager({\n url: config.url,\n name: config.name ?? 'Wiki Extractor',\n color: config.color,\n quiet: config.quiet,\n })\n\n // Authenticate first; register on first run.\n try {\n await dm.client.loginWithKey(keypair.publicKeyB64, sign)\n } catch (err: any) {\n const status = err?.status ?? err?.response?.status\n if (status === 404 || status === 422) {\n if (!config.quiet) {\n console.error('[abracadabra] Key not registered, creating new account...')\n }\n await dm.client.registerWithKey({\n publicKey: keypair.publicKeyB64,\n username: (config.name ?? 'wiki-extractor').replace(/\\s+/g, '-').toLowerCase(),\n displayName: config.name ?? 'Wiki Extractor',\n deviceName: 'CLI Wiki',\n inviteCode: config.inviteCode,\n })\n await dm.client.loginWithKey(keypair.publicKeyB64, sign)\n } else {\n throw err\n }\n }\n\n await dm.connect()\n\n const rootDocId = dm.rootDocId\n if (!rootDocId) {\n throw new Error('Connected but no rootDocId — server has no spaces.')\n }\n\n return { dm, rootDocId }\n}\n","/**\n * `abracadabra wiki <title>` — fetch Wikipedia articles and seed them into\n * the active space as a graph of docs.\n *\n * Streaming flow (no buffering): every newly-discovered title becomes a\n * shell doc immediately (visible in the dashboard right away), then bodies\n * are filled in one fetch at a time. The user sees the tree skeleton appear\n * before the first body is written.\n *\n * The command authenticates separately from the parent CLI (it's listed in\n * NO_CONNECT_COMMANDS in src/index.ts) so the parent harness doesn't open a\n * second connection. We use the modern DocumentManager API from @abraca/dabra.\n */\nimport type { DocumentManager } from '@abraca/dabra'\nimport { registerCommand } from '../../command.ts'\nimport type { CLIConnection } from '../../connection.ts'\nimport type { ParsedArgs } from '../../parser.ts'\nimport { WikipediaClient } from './wikipedia.ts'\nimport { snapshotArticle, canonicalTitle, prettyCategoryLabel } from './snapshot.ts'\nimport {\n ICONS,\n pickSectionType,\n renderArticleLead,\n renderArticleSingleDoc,\n renderInfoboxBody,\n renderCategoryBody,\n rewriteLinks,\n} from './render.ts'\nimport { openSession } from './connect.ts'\nimport type { WikiOptions, ExtractMode, ExtractedArticle, ExtractedSection } from './types.ts'\n\nregisterCommand({\n name: 'wiki',\n aliases: ['wikipedia'],\n description: 'Fetch Wikipedia articles into a graph of docs (streaming).',\n usage: [\n 'wiki \"<Article Title>\"',\n ' mode=single|split single doc per article OR split into sections+infobox [split]',\n ' depth=<n> follow internal links to depth N [1]',\n ' category-depth=<n> recurse into sub-categories [1]',\n ' lang=<code> wiki language [en]',\n ' domain=<host> 3rd-party MediaWiki host (overrides lang)',\n ' parent=<docId> parent doc for the new graph [active space root]',\n ' user-agent=<str> Api-User-Agent header (REQUIRED by Wikimedia etiquette)',\n ' rate=<rps> max wikipedia requests per second [3]',\n ' --include-categories expand each article\\'s categories into nested graphs',\n ' --dry-run fetch only the entry article, print outline, no writes',\n ].join('\\n'),\n async run(_conn: CLIConnection | null, args: ParsedArgs): Promise<string> {\n const opts = parseOptions(args)\n if (typeof opts === 'string') return opts\n\n const log = (msg: string) => {\n if (!args.flags.has('quiet') && !args.flags.has('q')) {\n console.error(`[wiki] ${msg}`)\n }\n }\n\n const wp = new WikipediaClient({\n lang: opts.lang,\n domain: opts.domain,\n userAgent: opts.userAgent,\n rate: opts.rate,\n })\n\n if (opts.dryRun) {\n // Dry-run: fetch only the entry, print its outline, no server.\n log(`fetch ${opts.title}`)\n const doc = await wp.fetchArticle(opts.title)\n if (!doc) return `Article not found: \"${opts.title}\"`\n const snap = snapshotArticle(doc, canonicalTitle(doc.title?.() ?? opts.title))\n return [\n `Entry: ${snap.title}`,\n `URL: ${snap.url ?? '(none)'}`,\n `Internal links: ${snap.linkTitles.length}`,\n `Categories: ${snap.categories.length}`,\n `Sections: ${snap.sections.length}`,\n `Has infobox: ${snap.infobox && snap.infobox.length > 0 ? 'yes' : 'no'}`,\n '',\n '── Sections ──',\n printSections(snap.sections, ''),\n ].join('\\n')\n }\n\n // ── Connect ──────────────────────────────────────────────────────────\n // process.env access uses bracket notation to satisfy noUncheckedIndexedAccess.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const env = (globalThis as any).process?.env ?? {}\n const url = env['ABRA_URL']\n if (!url) {\n return 'ABRA_URL is required to write to the server. Set it or pass --dry-run.'\n }\n const { dm } = await openSession({\n url,\n name: env['ABRA_NAME'],\n color: env['ABRA_COLOR'],\n inviteCode: env['ABRA_INVITE_CODE'],\n keyFile: env['ABRA_KEY_FILE'],\n quiet: args.flags.has('quiet') || args.flags.has('q'),\n })\n\n try {\n const result = await runStreaming(dm, wp, opts, log)\n return [\n `Done. Created ${result.articleCount} articles${\n result.categoryCount > 0 ? ` + ${result.categoryCount} categories` : ''\n }.`,\n `Root: ${result.rootDocId}`,\n ].join('\\n')\n } finally {\n await dm.destroy().catch(() => {})\n }\n },\n})\n\n// ─────────────────────────────────────────────────────────────────────────\n// Streaming orchestrator\n// ─────────────────────────────────────────────────────────────────────────\n\ninterface StreamResult {\n rootDocId: string\n articleCount: number\n categoryCount: number\n}\n\nasync function runStreaming(\n dm: DocumentManager,\n wp: WikipediaClient,\n opts: WikiOptions,\n log: (msg: string) => void,\n): Promise<StreamResult> {\n // Title → docId map. Drives [[Title]] → [[docId|label]] rewriting at write time.\n const titleToDocId = new Map<string, string>()\n // Snapshots of articles we've already fetched (avoid re-fetching).\n const fetched = new Map<string, ExtractedArticle>()\n // Articles whose section/infobox children have been created (split mode).\n const childrenCreated = new Set<string>()\n // Categories whose shells have been created.\n const categoryToDocId = new Map<string, string>()\n let categoriesContainerId: string | null = null\n\n // ── Fetch entry first; we need its title to label the root graph ─────\n log(`fetch ${opts.title}`)\n const entryDoc = await wp.fetchArticle(opts.title)\n if (!entryDoc) {\n throw new Error(`Article not found: \"${opts.title}\"`)\n }\n const entryTitle = canonicalTitle(entryDoc.title?.() ?? opts.title)\n const entrySnap = snapshotArticle(entryDoc, entryTitle)\n fetched.set(entryTitle, entrySnap)\n\n // ── Step 1: create root graph doc (visible immediately) ──────────────\n const rootEntry = dm.tree.create({\n parentId: opts.parentDocId ?? null,\n label: entryTitle,\n type: 'graph',\n meta: { icon: ICONS.graph },\n })\n log(`+ ${rootEntry.id.slice(0, 8)}… ${entryTitle} (graph)`)\n\n // ── Step 2: create the entry article shell ───────────────────────────\n const entryArticleId = createArticleShell(dm, entrySnap, rootEntry.id, log)\n titleToDocId.set(entryTitle, entryArticleId)\n\n // Queue of (title, depth) to process. Each entry is guaranteed to have\n // a shell doc already in titleToDocId.\n const queue: Array<{ title: string; depth: number }> = [{ title: entryTitle, depth: 0 }]\n let articleCount = 0\n\n // ── Step 3: streaming process ───────────────────────────────────────\n while (queue.length > 0) {\n const { title, depth } = queue.shift()!\n const articleDocId = titleToDocId.get(title)!\n\n // Ensure we've fetched this article.\n let snap = fetched.get(title)\n if (!snap) {\n log(`fetch [d${depth}] ${title}`)\n try {\n const doc = await wp.fetchArticle(title)\n if (!doc) {\n log(` not found — leaving stub`)\n continue\n }\n snap = snapshotArticle(doc, canonicalTitle(doc.title?.() ?? title))\n fetched.set(title, snap)\n } catch (err: any) {\n log(`! fetch failed: ${err?.message ?? err}`)\n continue\n }\n }\n\n // Create this article's section/infobox children (split mode only,\n // and only once per article).\n if (opts.mode === 'split' && !childrenCreated.has(title)) {\n createArticleChildren(dm, snap, articleDocId, log)\n childrenCreated.add(title)\n }\n\n // Discover new linked titles and pre-allocate shells immediately.\n if (depth < opts.depth) {\n for (const linkTitle of snap.linkTitles) {\n if (titleToDocId.has(linkTitle)) continue\n const shell = dm.tree.create({\n parentId: rootEntry.id,\n label: linkTitle,\n type: 'doc',\n meta: { icon: ICONS.article },\n })\n titleToDocId.set(linkTitle, shell.id)\n queue.push({ title: linkTitle, depth: depth + 1 })\n log(`+ ${shell.id.slice(0, 8)}… ${linkTitle} (doc, shell)`)\n }\n }\n\n // Pre-allocate category shells when first discovered.\n if (opts.includeCategories && snap.categories.length > 0) {\n if (!categoriesContainerId) {\n const c = dm.tree.create({\n parentId: rootEntry.id,\n label: 'Categories',\n type: 'graph',\n meta: { icon: ICONS.categories },\n })\n categoriesContainerId = c.id\n log(`+ ${c.id.slice(0, 8)}… Categories (graph)`)\n }\n for (const catTitle of snap.categories) {\n if (categoryToDocId.has(catTitle)) continue\n const cat = dm.tree.create({\n parentId: categoriesContainerId,\n label: prettyCategoryLabel(catTitle),\n type: 'graph',\n meta: { icon: ICONS.category },\n })\n categoryToDocId.set(catTitle, cat.id)\n log(`+ ${cat.id.slice(0, 8)}… ${prettyCategoryLabel(catTitle)} (graph, cat)`)\n }\n }\n\n // Write this article's body NOW (links resolve to whatever shells we\n // have allocated so far — that's all of this article's links since we\n // just allocated them above).\n const body =\n opts.mode === 'split' ? renderArticleLead(snap) : renderArticleSingleDoc(snap)\n if (body.trim().length > 0) {\n const rewritten = rewriteLinks(body, titleToDocId)\n try {\n await dm.content.write(articleDocId, rewritten)\n log(`✓ body ${title}`)\n } catch (err: any) {\n log(`! body write failed for ${title}: ${err?.message ?? err}`)\n }\n }\n\n // In split mode, also write each section/infobox doc body.\n if (opts.mode === 'split') {\n await writeChildrenBodies(dm, snap, articleDocId, titleToDocId, log)\n }\n\n articleCount++\n }\n\n // ── Step 4: fill in category bodies ─────────────────────────────────\n let categoryCount = 0\n if (opts.includeCategories && categoryToDocId.size > 0) {\n for (const [catTitle, catDocId] of categoryToDocId) {\n log(`category ${catTitle}`)\n try {\n const members = await wp.fetchCategoryPages(\n catTitle,\n opts.categoryDepth > 0,\n Math.max(0, opts.categoryDepth),\n )\n const memberArticles: string[] = []\n const subcats: string[] = []\n for (const m of members) {\n if (m.type === 'subcat') subcats.push(prettyCategoryLabel(m.title))\n else memberArticles.push(m.title)\n }\n const body = renderCategoryBody(memberArticles, subcats)\n const rewritten = rewriteLinks(body, titleToDocId)\n if (rewritten.trim().length > 0) {\n await dm.content.write(catDocId, rewritten)\n log(`✓ body category ${catTitle}`)\n }\n categoryCount++\n } catch (err: any) {\n log(`! category ${catTitle}: ${err?.message ?? err}`)\n }\n }\n }\n\n return { rootDocId: rootEntry.id, articleCount, categoryCount }\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Shell + body helpers\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction createArticleShell(\n dm: DocumentManager,\n article: ExtractedArticle,\n parentId: string,\n log: (msg: string) => void,\n): string {\n const meta: Record<string, unknown> = { icon: ICONS.article }\n if (article.url) meta.url = article.url\n const entry = dm.tree.create({\n parentId,\n label: article.title,\n type: 'doc',\n meta,\n })\n log(`+ ${entry.id.slice(0, 8)}… ${article.title} (doc)`)\n return entry.id\n}\n\n/**\n * Create section + infobox child docs for a split-mode article. Returns nothing\n * — children get bodies written later in writeChildrenBodies.\n */\nfunction createArticleChildren(\n dm: DocumentManager,\n article: ExtractedArticle,\n articleDocId: string,\n log: (msg: string) => void,\n): void {\n if (article.infobox && article.infobox.length > 0) {\n const ib = dm.tree.create({\n parentId: articleDocId,\n label: 'Infobox',\n type: 'outline',\n meta: { icon: ICONS.infobox },\n })\n log(` + ${ib.id.slice(0, 8)}… Infobox (outline)`)\n // We attach the docId to the article object so writeChildrenBodies\n // can find it without a second tree query.\n ;(article as any)._infoboxDocId = ib.id\n }\n for (const section of article.sections) {\n createSectionShell(dm, section, articleDocId, log)\n }\n}\n\nfunction createSectionShell(\n dm: DocumentManager,\n section: ExtractedSection,\n parentDocId: string,\n log: (msg: string) => void,\n): void {\n const hasChildren = section.children.length > 0\n if (!section.body.trim() && !hasChildren) return\n const { type, icon } = pickSectionType(section)\n const entry = dm.tree.create({\n parentId: parentDocId,\n label: section.title || 'Untitled section',\n type,\n meta: { icon },\n })\n log(` + ${entry.id.slice(0, 8)}… ${entry.label} (${type})`)\n ;(section as any)._docId = entry.id\n for (const child of section.children) {\n createSectionShell(dm, child, entry.id, log)\n }\n}\n\nasync function writeChildrenBodies(\n dm: DocumentManager,\n article: ExtractedArticle,\n _articleDocId: string,\n titleToDocId: Map<string, string>,\n log: (msg: string) => void,\n): Promise<void> {\n const infoboxDocId = (article as any)._infoboxDocId as string | undefined\n if (infoboxDocId && article.infobox && article.infobox.length > 0) {\n try {\n await dm.content.write(infoboxDocId, renderInfoboxBody(article.infobox))\n } catch (err: any) {\n log(`! infobox body write failed: ${err?.message ?? err}`)\n }\n }\n for (const section of article.sections) {\n await writeSectionBody(dm, section, titleToDocId, log)\n }\n}\n\nasync function writeSectionBody(\n dm: DocumentManager,\n section: ExtractedSection,\n titleToDocId: Map<string, string>,\n log: (msg: string) => void,\n): Promise<void> {\n const docId = (section as any)._docId as string | undefined\n if (docId && section.body.trim().length > 0) {\n try {\n await dm.content.write(docId, rewriteLinks(section.body, titleToDocId))\n } catch (err: any) {\n log(`! section body write failed for ${section.title}: ${err?.message ?? err}`)\n }\n }\n for (const child of section.children) {\n await writeSectionBody(dm, child, titleToDocId, log)\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Argument parsing + dry-run printing\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction parseOptions(args: ParsedArgs): WikiOptions | string {\n const title = args.positional[0]?.trim() || args.params['title']\n if (!title) return 'Missing required positional argument: <title>. Example: abracadabra wiki \"Toronto Raptors\"'\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const env = (globalThis as any).process?.env ?? {}\n const userAgent = args.params['user-agent'] || args.params['userAgent'] || env['ABRA_WIKI_USER_AGENT']\n if (!userAgent) {\n return [\n 'Missing required parameter: user-agent=\"your-name (you@example.com)\"',\n '(Wikimedia etiquette requires an Api-User-Agent header. Pass user-agent=... or set ABRA_WIKI_USER_AGENT.)',\n ].join('\\n')\n }\n\n const mode = (args.params['mode'] ?? 'split') as ExtractMode\n if (mode !== 'single' && mode !== 'split') {\n return `Invalid mode \"${mode}\". Use mode=single or mode=split.`\n }\n\n const depth = parseIntOr(args.params['depth'], 1)\n const categoryDepth = parseIntOr(args.params['category-depth'] ?? args.params['categoryDepth'], 1)\n const rate = parseFloatOr(args.params['rate'], 3)\n\n return {\n title,\n mode,\n depth,\n categoryDepth,\n includeCategories: args.flags.has('include-categories') || args.flags.has('includeCategories'),\n lang: args.params['lang'] ?? 'en',\n domain: args.params['domain'],\n parentDocId: args.params['parent'],\n userAgent,\n rate,\n dryRun: args.flags.has('dry-run') || args.flags.has('dryRun'),\n }\n}\n\nfunction parseIntOr(s: string | undefined, fallback: number): number {\n if (!s) return fallback\n const n = Number.parseInt(s, 10)\n return Number.isFinite(n) && n >= 0 ? n : fallback\n}\n\nfunction parseFloatOr(s: string | undefined, fallback: number): number {\n if (!s) return fallback\n const n = Number.parseFloat(s)\n return Number.isFinite(n) && n > 0 ? n : fallback\n}\n\nfunction printSections(sections: ExtractedSection[], indent: string): string {\n const lines: string[] = []\n for (const s of sections) {\n const hint = s.body ? ` (${s.body.length}b)` : ''\n lines.push(`${indent}- ${s.title}${hint}${s.children.length > 0 ? ` [${s.children.length} sub]` : ''}`)\n if (s.children.length > 0) {\n lines.push(printSections(s.children, indent + ' '))\n }\n }\n return lines.join('\\n')\n}\n","#!/usr/bin/env node\n/**\n * Abracadabra CLI — interact with CRDT document workspaces from the terminal.\n *\n * Usage:\n * abracadabra <command> [key=value ...] [--flags]\n *\n * Environment:\n * ABRA_URL Server URL (required)\n * ABRA_KEY_FILE Path to Ed25519 key file (~/.abracadabra/cli.key)\n * ABRA_INVITE_CODE Invite code for first-run registration\n * ABRA_NAME Display name (default: CLI User)\n * ABRA_COLOR Presence color (default: hsl(45, 90%, 55%))\n */\nimport { parseArgs } from './parser.ts'\nimport { CLIConnection } from './connection.ts'\nimport { getCommand } from './command.ts'\n\n// ── Register all commands ────────────────────────────────────────────────────\n// Side-effect imports: each module calls registerCommand() at module scope.\nimport './commands/help.ts'\nimport './commands/spaces.ts'\nimport './commands/tree.ts'\nimport './commands/documents.ts'\nimport './commands/content.ts'\nimport './commands/meta.ts'\nimport './commands/awareness.ts'\nimport './commands/files.ts'\nimport './commands/permissions.ts'\nimport './commands/page-types.ts'\nimport './commands/wiki/index.ts'\n\n// ── Commands that don't require a connection ─────────────────────────────────\n// \"wiki\" opens its own DocumentManager session via wiki/connect.ts, so the\n// parent harness should NOT pre-open a CLIConnection (which would authenticate\n// twice and hold an unused root provider).\nconst NO_CONNECT_COMMANDS = new Set([\n 'help', 'h', '?',\n 'version', 'v',\n 'page-types', 'types', 'doctypes',\n 'wiki', 'wikipedia',\n])\n\nasync function main() {\n const args = parseArgs(process.argv)\n\n // Resolve command\n const cmd = getCommand(args.command)\n if (!cmd) {\n console.error(`Unknown command: \"${args.command}\"`)\n console.error('Run \"abracadabra help\" to see all commands.')\n process.exit(1)\n }\n\n // Commands that don't need a server connection\n if (NO_CONNECT_COMMANDS.has(args.command)) {\n // Try to connect for extra info (version), but don't fail\n let conn: CLIConnection | null = null\n const url = process.env['ABRA_URL']\n if (url && args.command === 'version') {\n try {\n conn = new CLIConnection({\n url,\n name: process.env['ABRA_NAME'],\n color: process.env['ABRA_COLOR'],\n inviteCode: process.env['ABRA_INVITE_CODE'],\n keyFile: process.env['ABRA_KEY_FILE'],\n quiet: true,\n })\n await conn.connect()\n } catch {\n // Silently fall back to local-only version info\n }\n }\n\n try {\n const output = await cmd.run(conn, args)\n if (output) console.log(output)\n } finally {\n if (conn) await conn.destroy().catch(() => {})\n }\n return\n }\n\n // All other commands require ABRA_URL\n const url = process.env['ABRA_URL']\n if (!url) {\n console.error('Error: ABRA_URL environment variable is required.')\n console.error('')\n console.error('Set it to your Abracadabra server URL:')\n console.error(' export ABRA_URL=https://your-server.example.com')\n console.error('')\n console.error('Run \"abracadabra help\" for more info.')\n process.exit(1)\n }\n\n const conn = new CLIConnection({\n url,\n name: process.env['ABRA_NAME'],\n color: process.env['ABRA_COLOR'],\n inviteCode: process.env['ABRA_INVITE_CODE'],\n keyFile: process.env['ABRA_KEY_FILE'],\n quiet: args.flags.has('quiet') || args.flags.has('q'),\n })\n\n try {\n await conn.connect()\n const output = await cmd.run(conn, args)\n if (output) console.log(output)\n } catch (error: any) {\n console.error(`Error: ${error.message}`)\n if (args.flags.has('verbose')) {\n console.error(error.stack)\n }\n process.exit(1)\n } finally {\n await conn.destroy().catch(() => {})\n }\n}\n\nmain().catch((err) => {\n console.error(`Fatal: ${err.message ?? err}`)\n process.exit(1)\n})\n"],"x_google_ignoreList":[1,2,3,4],"mappings":"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"}