@rohal12/twee-ts 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/compiler.ts","../src/ifid.ts","../src/escape.ts","../src/passage.ts","../src/story.ts","../src/filesystem.ts","../src/media-types.ts","../src/formats.ts","../src/util.ts","../src/loader.ts","../src/lexer.ts","../src/twee2-compat.ts","../src/parser.ts","../src/version.ts","../src/output-twine2.ts","../src/output-twine1.ts","../src/output-twee.ts","../src/modules.ts","../src/remote-formats.ts","../src/inspect.ts","../src/config.ts"],"sourcesContent":["/**\n * Main compiler orchestrator.\n * compile(), compileToFile(), watch().\n * Ported from tweego.go + config.go.\n */\nimport { writeFileSync } from 'node:fs';\nimport type {\n CompileOptions,\n CompileToFileOptions,\n WatchOptions,\n CompileResult,\n CompileStats,\n Diagnostic,\n Story,\n StoryFormatInfo,\n OutputMode,\n InlineSource,\n} from './types.js';\nimport { createStory, storyHas, getStoryStats } from './story.js';\nimport { getFilenames, watchFilesystem } from './filesystem.js';\nimport { discoverFormats, getFormatSearchDirs, getFormatIdByNameAndVersion } from './formats.js';\nimport { loadSources, loadInlineSources } from './loader.js';\nimport { applyTagAliases, hasTag } from './passage.js';\nimport { toTwine2HTML, toTwine2Archive } from './output-twine2.js';\nimport { toTwine1HTML, toTwine1Archive } from './output-twine1.js';\nimport { toTwee } from './output-twee.js';\nimport { modifyHead } from './modules.js';\nimport { resolveRemoteFormat, clearIndexCache } from './remote-formats.js';\nimport { VERSION } from './version.js';\n\nconst CREATOR_NAME = 'Twee-ts';\n\nconst DEFAULT_FORMAT_ID = 'sugarcube-2';\nconst DEFAULT_START_NAME = 'Start';\n\nexport class TweeTsError extends Error {\n constructor(\n message: string,\n public diagnostics: Diagnostic[] = [],\n ) {\n super(message);\n this.name = 'TweeTsError';\n }\n}\n\n/**\n * Compile Twee sources to HTML, Twee, or JSON.\n */\nexport async function compile(options: CompileOptions): Promise<CompileResult> {\n return buildOutput(options);\n}\n\n/**\n * Compile and write to a file.\n */\nexport async function compileToFile(options: CompileToFileOptions): Promise<CompileResult> {\n const result = await compile(options);\n writeFileSync(options.outFile, result.output, 'utf-8');\n return result;\n}\n\n/**\n * Watch for file changes and recompile.\n */\nexport async function watch(options: WatchOptions): Promise<AbortController> {\n const controller = new AbortController();\n\n // Separate file paths from inline sources\n const filePaths = options.sources.filter((s): s is string => typeof s === 'string');\n const modulePaths = options.modules ?? [];\n const allPaths = [...filePaths, ...modulePaths];\n\n const handle = watchFilesystem(allPaths, options.outFile, () => {\n buildOutput(options)\n .then((result) => {\n writeFileSync(options.outFile, result.output, 'utf-8');\n options.onBuild?.(result);\n })\n .catch((e) => {\n options.onError?.(e instanceof Error ? e : new Error(String(e)));\n });\n });\n\n controller.signal.addEventListener('abort', () => handle.close());\n return controller;\n}\n\nasync function buildOutput(options: CompileOptions): Promise<CompileResult> {\n const diagnostics: Diagnostic[] = [];\n const outputMode: OutputMode = options.outputMode ?? 'html';\n const trim = options.trim ?? true;\n const twee2Compat = options.twee2Compat ?? false;\n const testMode = options.testMode ?? false;\n const noRemote = options.noRemote ?? false;\n\n // Clear per-compile index cache\n clearIndexCache();\n\n // Separate file paths from inline sources\n const filePaths: string[] = [];\n const inlineSources: InlineSource[] = [];\n for (const source of options.sources) {\n if (typeof source === 'string') {\n filePaths.push(source);\n } else {\n inlineSources.push(source);\n }\n }\n\n // Walk file paths to get all source filenames\n const sourceFilenames = getFilenames(filePaths);\n\n // Create story and load sources\n const story = createStory();\n const processedFiles = new Set<string>();\n\n loadSources(story, sourceFilenames, { trim, twee2Compat }, diagnostics, processedFiles);\n loadInlineSources(story, inlineSources, { trim, twee2Compat }, diagnostics);\n\n // Apply tag aliases (e.g. library → script)\n if (options.tagAliases) {\n story.passages = applyTagAliases(story.passages, options.tagAliases);\n }\n\n // Resolve format\n let format: StoryFormatInfo | undefined;\n let formatId = options.formatId ?? '';\n\n if (outputMode === 'html') {\n const formatSearchDirs = getFormatSearchDirs(options.formatPaths, options.useTweegoPath ?? true);\n const formats = discoverFormats(formatSearchDirs);\n\n if (!formatId && story.twine2.format) {\n formatId = getFormatIdByNameAndVersion(formats, story.twine2.format, story.twine2.formatVersion) ?? '';\n }\n if (!formatId) {\n formatId = DEFAULT_FORMAT_ID;\n }\n\n format = formats.get(formatId);\n\n // Remote format fallback\n if (!format && !noRemote) {\n // Determine the format name and version for remote lookup\n const remoteName = story.twine2.format || formatId;\n const remoteVersion = story.twine2.formatVersion || '';\n\n try {\n format = await resolveRemoteFormat(remoteName, remoteVersion, options.formatIndices, options.formatUrls);\n } catch (e) {\n diagnostics.push({\n level: 'warning',\n message: `Remote format fetch failed for \"${remoteName}\": ${e instanceof Error ? e.message : String(e)}`,\n });\n }\n }\n\n if (!format) {\n const reason = noRemote ? ' (remote fetching disabled)' : '';\n diagnostics.push({\n level: 'error',\n message: `Story format \"${formatId}\" is not available${reason}. Found: ${[...formats.keys()].join(', ') || 'none'}`,\n });\n }\n }\n\n // Merge config from StoryData: command-line > StoryData > default\n const startName = options.startPassage || story.twine2.start || DEFAULT_START_NAME;\n\n // Apply test mode\n if (testMode) {\n story.twine2.options.set('debug', true);\n }\n\n // Generate output\n let output: string;\n\n switch (outputMode) {\n case 'twee3':\n case 'twee1':\n output = toTwee(story, outputMode);\n break;\n\n case 'twine2-archive':\n output = toTwine2Archive(story, startName, diagnostics);\n break;\n\n case 'twine1-archive':\n output = toTwine1Archive(story, startName);\n break;\n\n case 'json':\n output = storyToJSON(story);\n break;\n\n case 'html': {\n // Sanity checks for HTML mode\n if (!storyHas(story, startName)) {\n diagnostics.push({\n level: 'error',\n message: `Starting passage \"${startName}\" not found.`,\n });\n }\n\n if (!format) {\n throw new TweeTsError('No story format available for HTML output.', diagnostics);\n }\n\n if (format.isTwine2) {\n output = toTwine2HTML(story, format, startName, diagnostics);\n } else {\n if (story.name === '' && !storyHas(story, 'StoryTitle')) {\n diagnostics.push({\n level: 'error',\n message: 'Special passage \"StoryTitle\" not found.',\n });\n }\n output = toTwine1HTML(story, format, startName, diagnostics);\n }\n\n // Inject modules and head file\n const modulePaths = options.modules ? getFilenames(options.modules) : [];\n output = modifyHead(output, modulePaths, options.headFile, diagnostics);\n break;\n }\n\n default: {\n const _exhaustive: never = outputMode;\n throw new TweeTsError(`Unhandled output mode: ${_exhaustive as string}`, diagnostics);\n }\n }\n\n // Compute stats\n const stats: CompileStats = {\n ...getStoryStats(story),\n files: [...processedFiles],\n };\n\n return { output, story, format, diagnostics, stats };\n}\n\n/**\n * Serialize a Story to JSON per the Twine 2 JSON Output Specification (v1.0):\n * https://github.com/iftechfoundation/twine-specs/blob/master/twine-2-jsonoutput-doc.md\n */\nfunction storyToJSON(story: Story): string {\n // Gather script and stylesheet content, excluding them from passages.\n const scripts: string[] = [];\n const stylesheets: string[] = [];\n const storyPassages: { name: string; tags: string[]; text: string; metadata?: Record<string, string> }[] = [];\n\n for (const p of story.passages) {\n if (p.name === 'StoryTitle' || p.name === 'StoryData') continue;\n if (hasTag(p, 'Twine.private')) continue;\n\n if (hasTag(p, 'script')) {\n scripts.push(p.text);\n } else if (hasTag(p, 'stylesheet')) {\n stylesheets.push(p.text);\n } else {\n const entry: { name: string; tags: string[]; text: string; metadata?: Record<string, string> } = {\n name: p.name,\n tags: p.tags,\n text: p.text,\n };\n if (p.metadata && (p.metadata.position || p.metadata.size)) {\n const meta: Record<string, string> = {};\n if (p.metadata.position) meta.position = p.metadata.position;\n if (p.metadata.size) meta.size = p.metadata.size;\n entry.metadata = meta;\n }\n storyPassages.push(entry);\n }\n }\n\n const obj: Record<string, unknown> = {\n name: story.name,\n };\n\n if (story.ifid) obj.ifid = story.ifid;\n if (story.twine2.format) obj.format = story.twine2.format;\n if (story.twine2.formatVersion) obj['format-version'] = story.twine2.formatVersion;\n if (story.twine2.start) obj.start = story.twine2.start;\n if (story.twine2.tagColors.size > 0) obj['tag-colors'] = Object.fromEntries(story.twine2.tagColors);\n if (story.twine2.zoom !== 1) obj.zoom = story.twine2.zoom;\n obj.creator = CREATOR_NAME;\n obj['creator-version'] = VERSION;\n obj.style = stylesheets.join('\\n');\n obj.script = scripts.join('\\n');\n obj.passages = storyPassages;\n\n return JSON.stringify(obj, null, 2);\n}\n","/**\n * IFID (Interactive Fiction IDentifier) generation and validation.\n * Ported from ifid.go.\n */\nimport { randomUUID } from 'node:crypto';\n\n/** Generate a new IFID (UUID v4, uppercase). */\nexport function generateIFID(): string {\n return randomUUID().toUpperCase();\n}\n\n/**\n * Validate an IFID string.\n * Accepts both bare UUIDs and UUID://...// wrapped format.\n * Returns null if valid, or an error message string.\n */\nexport function validateIFID(ifid: string): string | null {\n let uuid = ifid;\n\n switch (ifid.length) {\n case 36:\n break;\n case 45: {\n if (ifid.slice(0, 7).toUpperCase() !== 'UUID://' || ifid.slice(43) !== '//') {\n return 'invalid IFID UUID://...// format';\n }\n uuid = ifid.slice(7, 43);\n break;\n }\n default:\n return `invalid IFID length: ${ifid.length}`;\n }\n\n for (let i = 0; i < uuid.length; i++) {\n const ch = uuid[i]!;\n switch (i) {\n case 8:\n case 13:\n case 18:\n case 23:\n if (ch !== '-') {\n return `invalid IFID character '${ch}' at position ${i + 1}`;\n }\n break;\n case 14:\n if (ch < '1' || ch > '5') {\n return `invalid version '${ch}' at position ${i + 1}`;\n }\n break;\n case 19:\n if (!['8', '9', 'a', 'A', 'b', 'B'].includes(ch)) {\n return `invalid variant '${ch}' at position ${i + 1}`;\n }\n break;\n default:\n if (!/^[0-9a-fA-F]$/.test(ch)) {\n return `invalid IFID hex value '${ch}' at position ${i + 1}`;\n }\n break;\n }\n }\n\n return null;\n}\n","/**\n * HTML, attribute, tiddler, and twee escaping/unescaping utilities.\n * Ported from escaping.go.\n */\n\n/** Escape the minimum characters required for HTML attribute values. */\nexport function attrEscape(s: string): string {\n if (s.length === 0) return s;\n return s.replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/'/g, '&#39;');\n}\n\n/** Escape the minimum characters required for general HTML content. */\nexport function htmlEscape(s: string): string {\n if (s.length === 0) return s;\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\n/** Escape for Twine 1 tiddler format. */\nexport function tiddlerEscape(s: string): string {\n if (s.length === 0) return s;\n return s\n .replace(/\\\\/g, '\\\\s')\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/\\t/g, '\\\\t')\n .replace(/\\n/g, '\\\\n');\n}\n\n/** Unescape from Twine 1 tiddler format. */\nexport function tiddlerUnescape(s: string): string {\n if (s.length === 0) return s;\n return s.replace(/\\\\n/g, '\\n').replace(/\\\\t/g, '\\t').replace(/\\\\s/g, '\\\\');\n}\n\n/** Escape characters that are special in Twee passage names/tags. */\nexport function tweeEscape(s: string): string {\n if (s.length === 0) return s;\n return s.replace(/[\\\\[\\]{}]/g, (ch) => '\\\\' + ch);\n}\n\n/** Escape a string for safe inclusion in a JavaScript string literal. */\nexport function jsStringEscape(s: string): string {\n if (s.length === 0) return s;\n return s\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/'/g, \"\\\\'\")\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n}\n\n/** Sanitize a string for safe inclusion in a CSS or JS block comment. */\nexport function commentSanitize(s: string): string {\n return s.replace(/\\*\\//g, '* /');\n}\n\n/** Sanitize a string for safe inclusion in an HTML comment. */\nexport function htmlCommentSanitize(s: string): string {\n return s.replace(/-->/g, '-- >');\n}\n\n/** Unescape backslash-escaped Twee characters. */\nexport function tweeUnescape(s: string): string {\n if (s.length === 0) return s;\n let result = '';\n for (let i = 0; i < s.length; i++) {\n if (s[i] === '\\\\') {\n i++;\n if (i >= s.length) {\n result += '\\\\';\n break;\n }\n }\n result += s[i];\n }\n return result;\n}\n","/**\n * Passage helpers and output methods.\n * Ported from passage.go / passagedata.go.\n */\nimport type { Passage, PassageMetadata, OutputMode } from './types.js';\nimport { attrEscape, htmlEscape, tiddlerEscape, tweeEscape } from './escape.js';\n\n// Info passages contain structural data, metadata, and code rather than story content.\nconst INFO_PASSAGE_NAMES = new Set([\n 'StoryAuthor',\n 'StoryInit',\n 'StoryMenu',\n 'StorySubtitle',\n 'StoryTitle',\n 'PassageReady',\n 'PassageDone',\n 'PassageHeader',\n 'PassageFooter',\n 'StoryBanner',\n 'StoryCaption',\n 'MenuOptions',\n 'MenuShare',\n 'MenuStory',\n 'StoryInterface',\n 'StoryShare',\n 'StorySettings',\n 'StoryData',\n 'StoryIncludes',\n]);\n\nconst INFO_TAGS = ['annotation', 'script', 'stylesheet', 'widget'];\n\nexport function hasTag(p: Passage, tag: string): boolean {\n return p.tags.includes(tag);\n}\n\nexport function hasAnyTag(p: Passage, ...tags: string[]): boolean {\n return p.tags.some((t) => tags.includes(t));\n}\n\nexport function hasTagStartingWith(p: Passage, prefix: string): boolean {\n return p.tags.some((t) => t.startsWith(prefix));\n}\n\nexport function hasInfoTags(p: Passage): boolean {\n return hasAnyTag(p, ...INFO_TAGS) || hasTagStartingWith(p, 'Twine.');\n}\n\nexport function hasInfoName(p: Passage): boolean {\n return INFO_PASSAGE_NAMES.has(p.name);\n}\n\nexport function isInfoPassage(p: Passage): boolean {\n return hasInfoName(p) || hasInfoTags(p);\n}\n\nexport function isStoryPassage(p: Passage): boolean {\n return !hasInfoName(p) && !hasInfoTags(p);\n}\n\nexport function hasMetadataPosition(p: Passage): boolean {\n return p.metadata != null && p.metadata.position != null && p.metadata.position !== '';\n}\n\nexport function hasMetadataSize(p: Passage): boolean {\n return p.metadata != null && p.metadata.size != null && p.metadata.size !== '';\n}\n\nexport function hasAnyMetadata(p: Passage): boolean {\n return hasMetadataPosition(p) || hasMetadataSize(p);\n}\n\nexport function marshalMetadata(meta: PassageMetadata): string {\n const obj: Record<string, string> = {};\n if (meta.position) obj.position = meta.position;\n if (meta.size) obj.size = meta.size;\n return JSON.stringify(obj);\n}\n\nexport function unmarshalMetadata(json: string): PassageMetadata {\n const raw: unknown = JSON.parse(json);\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n return {};\n }\n const parsed = raw as Record<string, unknown>;\n const meta: PassageMetadata = {};\n if (typeof parsed.position === 'string') meta.position = parsed.position;\n if (typeof parsed.size === 'string') meta.size = parsed.size;\n return meta;\n}\n\n/** Convert passage to Twee source. */\nexport function passageToTwee(p: Passage, outMode: OutputMode): string {\n let output: string;\n if (outMode === 'twee3') {\n output = ':: ' + tweeEscape(p.name);\n if (p.tags.length > 0) {\n output += ' [' + tweeEscape(p.tags.join(' ')) + ']';\n }\n if (hasAnyMetadata(p) && p.metadata) {\n output += ' ' + marshalMetadata(p.metadata);\n }\n } else {\n output = ':: ' + p.name;\n if (p.tags.length > 0) {\n output += ' [' + p.tags.join(' ') + ']';\n }\n }\n output += '\\n';\n if (p.text.length > 0) {\n output += p.text + '\\n';\n }\n output += '\\n\\n';\n return output;\n}\n\n/** Generate `<tw-passagedata>` HTML for Twine 2. */\nexport function passageToPassagedata(p: Passage, pid: number): string {\n let position: string;\n let size: string;\n\n if (hasMetadataPosition(p)) {\n position = p.metadata?.position ?? '';\n } else {\n const x = pid % 10;\n const y = Math.floor(pid / 10);\n const xp = x === 0 ? 10 : x;\n const yp = x === 0 ? y : y + 1;\n position = `${xp * 125 - 25},${yp * 125 - 25}`;\n }\n\n if (hasMetadataSize(p)) {\n size = p.metadata?.size ?? '';\n } else {\n size = '100,100';\n }\n\n return `<tw-passagedata pid=\"${pid}\" name=${quote(attrEscape(p.name))} tags=${quote(attrEscape(p.tags.join(' ')))} position=${quote(attrEscape(position))} size=${quote(attrEscape(size))}>${htmlEscape(p.text)}</tw-passagedata>`;\n}\n\n/** Generate `<div tiddler>` HTML for Twine 1. */\nexport function passageToTiddler(p: Passage, pid: number): string {\n let position: string;\n\n if (hasMetadataPosition(p)) {\n position = p.metadata?.position ?? '';\n } else {\n const x = pid % 10;\n const y = Math.floor(pid / 10);\n const xp = x === 0 ? 10 : x;\n const yp = x === 0 ? y : y + 1;\n position = `${xp * 140 - 130},${yp * 140 - 130}`;\n }\n\n return `<div tiddler=${quote(attrEscape(p.name))} tags=${quote(attrEscape(p.tags.join(' ')))} twine-position=${quote(attrEscape(position))}>${tiddlerEscape(p.text)}</div>`;\n}\n\n/**\n * Count words in a passage using the Tweego method:\n * Strip newlines, strip comments, count NFKD-normalized characters, divide by 5.\n */\nexport function countWords(p: Passage): number {\n let text = p.text;\n text = text.replace(/\\n/g, '');\n text = text.replace(/(?:\\/%.+?%\\/|\\/\\*.+?\\*\\/|<!--.+?-->)/gs, '');\n // Normalize to NFKD and count characters\n const normalized = text.normalize('NFKD');\n const count = [...normalized].length;\n if (count === 0) return 0;\n const words = Math.floor(count / 5);\n return count % 5 > 0 ? words + 1 : words;\n}\n\n/**\n * Apply tag aliases: for each passage carrying an alias tag, add the canonical\n * tag if not already present. Returns new passage objects where tags changed;\n * unchanged passages are returned as-is. Idempotent — safe to call multiple times.\n */\nexport function applyTagAliases(passages: readonly Passage[], aliases: Record<string, string>): Passage[] {\n const entries = Object.entries(aliases);\n if (entries.length === 0) return [...passages];\n return passages.map((p) => {\n const original = p.tags;\n const added: string[] = [];\n for (const [alias, canonical] of entries) {\n if (original.includes(alias) && !original.includes(canonical) && !added.includes(canonical)) {\n added.push(canonical);\n }\n }\n return added.length > 0 ? { ...p, tags: [...original, ...added] } : p;\n });\n}\n\nfunction quote(s: string): string {\n return `\"${s}\"`;\n}\n","/**\n * Story model + StoryData JSON marshal/unmarshal.\n * Ported from story.go + storydata.go.\n */\nimport type { Story, Passage, Diagnostic } from './types.js';\nimport { validateIFID } from './ifid.js';\nimport { isStoryPassage, countWords } from './passage.js';\n\nexport function createStory(): Story {\n return {\n name: '',\n ifid: '',\n passages: [],\n legacyIFID: '',\n twine1: { settings: new Map() },\n twine2: {\n format: '',\n formatVersion: '',\n options: new Map(),\n start: '',\n tagColors: new Map(),\n zoom: 1,\n },\n };\n}\n\nexport function storyHas(story: Story, name: string): boolean {\n return story.passages.some((p) => p.name === name);\n}\n\nexport function storyIndex(story: Story, name: string): number {\n return story.passages.findIndex((p) => p.name === name);\n}\n\nexport function storyGet(story: Story, name: string): Passage | undefined {\n return story.passages.find((p) => p.name === name);\n}\n\nexport function storyAppend(story: Story, p: Passage, diagnostics: Diagnostic[]): void {\n const i = storyIndex(story, p.name);\n if (i === -1) {\n story.passages.push(p);\n } else {\n diagnostics.push({\n level: 'warning',\n message: `Replacing existing passage \"${p.name}\" with duplicate.`,\n });\n story.passages[i] = p;\n }\n}\n\nexport function storyPrepend(story: Story, p: Passage, diagnostics: Diagnostic[]): void {\n const i = storyIndex(story, p.name);\n if (i === -1) {\n story.passages.unshift(p);\n } else {\n diagnostics.push({\n level: 'warning',\n message: `Replacing existing passage \"${p.name}\" with duplicate.`,\n });\n story.passages[i] = p;\n }\n}\n\n// --- StoryData JSON ---\n\ninterface StoryDataJSON {\n ifid?: string;\n format?: string;\n 'format-version'?: string;\n options?: string[];\n start?: string;\n 'tag-colors'?: Record<string, string>;\n zoom?: number;\n}\n\nexport function marshalStoryData(story: Story): string {\n const data: StoryDataJSON = {};\n if (story.ifid) data.ifid = story.ifid;\n if (story.twine2.format) data.format = story.twine2.format;\n if (story.twine2.formatVersion) data['format-version'] = story.twine2.formatVersion;\n\n const options: string[] = [];\n for (const [opt, val] of story.twine2.options) {\n if (val) options.push(opt);\n }\n if (options.length > 0) data.options = options;\n\n if (story.twine2.start) data.start = story.twine2.start;\n\n if (story.twine2.tagColors.size > 0) {\n data['tag-colors'] = Object.fromEntries(story.twine2.tagColors);\n }\n if (story.twine2.zoom !== 1) data.zoom = story.twine2.zoom;\n\n return JSON.stringify(data, null, '\\t');\n}\n\nexport function unmarshalStoryData(story: Story, json: string): string | null {\n let raw: unknown;\n try {\n raw = JSON.parse(json) as unknown;\n } catch (e) {\n return `Cannot unmarshal \"StoryData\"; ${e instanceof Error ? e.message : String(e)}`;\n }\n\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n return 'Cannot unmarshal \"StoryData\"; expected a JSON object';\n }\n const data = raw as StoryDataJSON;\n\n if (typeof data.ifid === 'string' && data.ifid) story.ifid = data.ifid.toUpperCase();\n if (typeof data.format === 'string' && data.format) story.twine2.format = data.format;\n if (typeof data['format-version'] === 'string' && data['format-version'])\n story.twine2.formatVersion = data['format-version'];\n if (Array.isArray(data.options)) {\n for (const opt of data.options) {\n if (typeof opt === 'string') story.twine2.options.set(opt, true);\n }\n }\n if (typeof data.start === 'string' && data.start) story.twine2.start = data.start;\n if (typeof data['tag-colors'] === 'object' && data['tag-colors'] !== null && !Array.isArray(data['tag-colors'])) {\n for (const [tag, color] of Object.entries(data['tag-colors'])) {\n if (typeof color === 'string') story.twine2.tagColors.set(tag, color);\n }\n }\n if (typeof data.zoom === 'number' && data.zoom !== 0) story.twine2.zoom = data.zoom;\n\n return null;\n}\n\n// --- StorySettings (legacy) ---\n\nexport function unmarshalStorySettings(story: Story, text: string, diagnostics: Diagnostic[]): void {\n const obsolete: string[] = [];\n\n for (const rawLine of text.split('\\n')) {\n const line = rawLine.trim();\n if (line.length === 0) continue;\n\n const colonIdx = line.indexOf(':');\n if (colonIdx === -1) {\n diagnostics.push({\n level: 'warning',\n message: `Malformed \"StorySettings\" entry; skipping \"${line}\".`,\n });\n continue;\n }\n\n const key = line.slice(0, colonIdx).trim().toLowerCase();\n const val = line\n .slice(colonIdx + 1)\n .trim()\n .toLowerCase();\n\n switch (key) {\n case 'ifid': {\n const err = validateIFID(val);\n if (err === null) {\n story.legacyIFID = val.toUpperCase();\n }\n obsolete.push('\"ifid\"');\n continue;\n }\n case 'zoom':\n obsolete.push('\"zoom\"');\n continue;\n }\n\n story.twine1.settings.set(key, val);\n }\n\n if (obsolete.length > 0) {\n const entries = obsolete.length === 1 ? 'entry' : 'entries';\n const pronoun = obsolete.length === 1 ? 'it' : 'them';\n diagnostics.push({\n level: 'warning',\n message:\n `Detected obsolete \"StorySettings\" ${entries}: ${obsolete.join(', ')}. ` +\n `Please remove ${pronoun} from the \"StorySettings\" special passage.`,\n });\n }\n}\n\n/**\n * Process a passage and add it to the story, handling special passages.\n * Creates new passage objects where text is modified rather than mutating the input.\n */\nexport function storyAdd(story: Story, p: Passage, diagnostics: Diagnostic[]): void {\n let processed = p;\n\n switch (p.name) {\n case 'StoryIncludes':\n diagnostics.push({\n level: 'warning',\n message:\n 'Ignoring \"StoryIncludes\" compiler special passage; twee-ts allows you to specify project files and/or directories to recursively search.',\n });\n break;\n\n case 'StoryData': {\n const err = unmarshalStoryData(story, p.text);\n if (err === null) {\n // Validate the IFID if present.\n if (story.ifid.length > 0) {\n const vErr = validateIFID(story.ifid);\n if (vErr !== null) {\n diagnostics.push({\n level: 'error',\n message: `Cannot validate IFID; ${vErr}.`,\n });\n }\n }\n // Rebuild passage contents to normalize.\n processed = { ...p, text: marshalStoryData(story) };\n } else {\n diagnostics.push({\n level: 'error',\n message: `Cannot unmarshal \"StoryData\" compiler special passage; ${err}.`,\n });\n }\n break;\n }\n\n case 'StorySettings':\n unmarshalStorySettings(story, p.text, diagnostics);\n break;\n\n case 'StoryTitle': {\n const trimmed = p.text.trim();\n processed = { ...p, text: trimmed };\n story.name = trimmed;\n break;\n }\n }\n\n storyAppend(story, processed, diagnostics);\n}\n\n/** Get story passage count and word count stats. */\nexport function getStoryStats(story: Story): { passages: number; storyPassages: number; words: number } {\n let storyPassages = 0;\n let words = 0;\n for (const p of story.passages) {\n if (isStoryPassage(p)) {\n storyPassages++;\n words += countWords(p);\n }\n }\n return { passages: story.passages.length, storyPassages, words };\n}\n","/**\n * File system utilities: path walking, file type detection, watch mode.\n * Ported from filesystem.go.\n */\nimport { readdirSync, statSync, watch as fsWatch } from 'node:fs';\nimport { resolve, relative, join } from 'node:path';\nimport { isKnownFileType } from './media-types.js';\n\n/**\n * Recursively walk directories, collecting regular file paths.\n * Filters out the output file to prevent circular compilation.\n */\nexport function getFilenames(pathnames: string[], outFilename?: string): string[] {\n const filenames: string[] = [];\n const absOutFile = outFilename ? resolve(outFilename) : '';\n\n function walk(pathname: string): void {\n let stat;\n try {\n stat = statSync(pathname);\n } catch {\n return;\n }\n\n if (stat.isFile()) {\n const abs = resolve(pathname);\n if (abs === absOutFile) return;\n const rel = relative(process.cwd(), abs);\n filenames.push(rel || abs);\n } else if (stat.isDirectory()) {\n let entries;\n try {\n entries = readdirSync(pathname);\n } catch {\n return;\n }\n for (const entry of entries) {\n walk(join(pathname, entry));\n }\n }\n }\n\n for (const pathname of pathnames) {\n walk(pathname);\n }\n\n return filenames;\n}\n\nexport interface WatchHandle {\n close(): void;\n}\n\n/**\n * Watch paths for changes, calling the build callback on known file type changes.\n * Uses debouncing to avoid rapid rebuilds.\n */\nexport function watchFilesystem(pathnames: string[], outFilename: string, callback: () => void): WatchHandle {\n const absOutFile = resolve(outFilename);\n const watchers: ReturnType<typeof fsWatch>[] = [];\n let buildTimer: ReturnType<typeof setTimeout> | null = null;\n const BUILD_DEBOUNCE = 500;\n\n function scheduleBuild(): void {\n if (buildTimer) clearTimeout(buildTimer);\n buildTimer = setTimeout(() => {\n buildTimer = null;\n callback();\n }, BUILD_DEBOUNCE);\n }\n\n for (const pathname of pathnames) {\n try {\n const watcher = fsWatch(pathname, { recursive: true }, (_event, filename) => {\n if (!filename) return;\n const abs = resolve(pathname, filename);\n if (abs === absOutFile) return;\n if (isKnownFileType(filename)) {\n scheduleBuild();\n }\n });\n watchers.push(watcher);\n } catch {\n // Ignore inaccessible paths\n }\n }\n\n // Build once initially.\n callback();\n\n return {\n close() {\n if (buildTimer) clearTimeout(buildTimer);\n for (const w of watchers) w.close();\n },\n };\n}\n","/**\n * Extension → MIME type mapping.\n * Ported from util.go:mediaTypeFromExt().\n */\n\nimport { extname } from 'node:path';\n\nconst MEDIA_TYPE_MAP: Record<string, string> = {\n // Audio\n aac: 'audio/aac',\n flac: 'audio/flac',\n ogg: 'audio/ogg',\n wav: 'audio/wav',\n mp3: 'audio/mpeg',\n m4a: 'audio/mp4',\n oga: 'audio/ogg',\n opus: 'audio/ogg',\n wave: 'audio/wav',\n weba: 'audio/webm',\n\n // Fonts\n otf: 'font/otf',\n ttf: 'font/ttf',\n woff: 'font/woff',\n woff2: 'font/woff2',\n\n // Images\n gif: 'image/gif',\n jpeg: 'image/jpeg',\n jpg: 'image/jpeg',\n png: 'image/png',\n svg: 'image/svg+xml',\n tif: 'image/tiff',\n tiff: 'image/tiff',\n webp: 'image/webp',\n\n // Metadata\n vtt: 'text/vtt',\n\n // Video\n mp4: 'video/mp4',\n ogv: 'video/ogg',\n webm: 'video/webm',\n};\n\nexport function mediaTypeFromExt(ext: string): string {\n return MEDIA_TYPE_MAP[ext] ?? 'application/octet-stream';\n}\n\nexport function mediaTypeFromFilename(filename: string): string {\n return mediaTypeFromExt(normalizedFileExt(filename));\n}\n\nexport function normalizedFileExt(filename: string): string {\n const ext = extname(filename);\n if (!ext) return '';\n return ext.slice(1).toLowerCase();\n}\n\n/** Slugify a string for safe use as a DOM ID. */\nexport function slugify(original: string): string {\n return original.replace(/[\\x00-\\x20!-/:-@[-^`{-\\x9f]+/g, '_');\n}\n\n/** Check if a file has a known type that should be processed. */\nexport function isKnownFileType(filename: string): boolean {\n const ext = normalizedFileExt(filename);\n return KNOWN_EXTENSIONS.has(ext);\n}\n\nconst KNOWN_EXTENSIONS = new Set([\n 'tw',\n 'twee',\n 'tw2',\n 'twee2',\n 'css',\n 'js',\n 'otf',\n 'ttf',\n 'woff',\n 'woff2',\n 'gif',\n 'jpeg',\n 'jpg',\n 'png',\n 'svg',\n 'tif',\n 'tiff',\n 'webp',\n 'aac',\n 'flac',\n 'm4a',\n 'mp3',\n 'oga',\n 'ogg',\n 'opus',\n 'wav',\n 'wave',\n 'weba',\n 'mp4',\n 'ogv',\n 'webm',\n 'vtt',\n]);\n\n/** Font format hint for @font-face. */\nexport function fontFormatHint(ext: string): string {\n switch (ext) {\n case 'ttf':\n return 'truetype';\n case 'otf':\n return 'opentype';\n default:\n return ext;\n }\n}\n","/**\n * Story format discovery, loading, and SemVer matching.\n * Ported from formats.go + config.go.\n */\nimport { readdirSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { StoryFormatInfo, Twine2FormatJSON } from './types.js';\nimport { readUTF8 } from './util.js';\n\n/**\n * Parse the Twine 2 format.js JSON chunk.\n * Handles Harlowe's malformed JSON by stripping the \"setup\" function property.\n */\nexport function parseFormatJSON(source: string, formatId: string): Twine2FormatJSON | null {\n const first = source.indexOf('{');\n const last = source.lastIndexOf('}');\n if (first === -1 || last === -1) return null;\n\n let chunk = source.slice(first, last + 1);\n\n const parse = (json: string): Twine2FormatJSON | null => {\n const raw: unknown = JSON.parse(json);\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) return null;\n const obj = raw as Record<string, unknown>;\n if (typeof obj.name !== 'string' || typeof obj.version !== 'string' || typeof obj.source !== 'string') return null;\n return { name: obj.name, version: obj.version, source: obj.source, proofing: obj.proofing === true };\n };\n\n try {\n return parse(chunk);\n } catch {\n // Harlowe workaround: strip the \"setup\" function property\n if (formatId.toLowerCase().startsWith('harlowe')) {\n const setupIdx = chunk.lastIndexOf(',\"setup\": function');\n if (setupIdx !== -1) {\n chunk = chunk.slice(0, setupIdx) + '}';\n try {\n return parse(chunk);\n } catch {\n // fall through\n }\n }\n }\n return null;\n }\n}\n\n/**\n * Discover all story formats in the given search directories.\n */\nexport function discoverFormats(searchDirs: string[]): Map<string, StoryFormatInfo> {\n const formats = new Map<string, StoryFormatInfo>();\n const baseFilenames = ['format.js', 'header.html'];\n\n for (const searchDir of searchDirs) {\n try {\n const stat = statSync(searchDir);\n if (!stat.isDirectory()) continue;\n } catch {\n continue;\n }\n\n let entries;\n try {\n entries = readdirSync(searchDir);\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n const formatDir = join(searchDir, entry);\n try {\n if (!statSync(formatDir).isDirectory()) continue;\n } catch {\n continue;\n }\n\n for (const baseFilename of baseFilenames) {\n const formatFilename = join(formatDir, baseFilename);\n try {\n const stat = statSync(formatFilename);\n if (!stat.isFile()) continue;\n } catch {\n continue;\n }\n\n const isTwine2 = baseFilename === 'format.js';\n const format: StoryFormatInfo = {\n id: entry,\n filename: formatFilename,\n isTwine2,\n name: '',\n version: '',\n proofing: false,\n };\n\n if (isTwine2) {\n try {\n const source = readUTF8(formatFilename);\n const data = parseFormatJSON(source, entry);\n if (!data) continue;\n format.name = data.name;\n format.version = data.version;\n format.proofing = data.proofing ?? false;\n } catch {\n continue;\n }\n }\n\n formats.set(entry, format);\n break; // Found format file for this directory\n }\n }\n }\n\n return formats;\n}\n\n/**\n * Get the default format search directories.\n */\nexport function getFormatSearchDirs(extraPaths: string[] = [], useTweegoPath = true): string[] {\n const subdirNames = ['storyformats', '.storyformats', 'story-formats', 'storyFormats', 'targets'];\n const basePaths = new Set<string>();\n\n // Home directory\n try {\n basePaths.add(homedir());\n } catch {\n // ignore\n }\n\n // Working directory\n basePaths.add(process.cwd());\n\n const dirs: string[] = [];\n for (const base of basePaths) {\n for (const sub of subdirNames) {\n const dir = join(base, sub);\n try {\n if (statSync(dir).isDirectory()) {\n dirs.push(dir);\n }\n } catch {\n // skip\n }\n }\n }\n\n // Extra user-provided paths\n dirs.push(...extraPaths);\n\n // TWEEGO_PATH environment variable\n if (useTweegoPath) {\n const tweegoPath = process.env.TWEEGO_PATH;\n if (tweegoPath) {\n dirs.push(...tweegoPath.split(process.platform === 'win32' ? ';' : ':'));\n }\n }\n\n return dirs;\n}\n\n/** Parse a simple semver string into [major, minor, patch]. */\nexport function parseSemver(v: string): [number, number, number] | null {\n const m = /^(\\d+)\\.(\\d+)\\.(\\d+)/.exec(v);\n if (!m) return null;\n return [Number(m[1]), Number(m[2]), Number(m[3])];\n}\n\nexport function semverCompare(a: [number, number, number], b: [number, number, number]): number {\n const [aMajor, aMinor, aPatch] = a;\n const [bMajor, bMinor, bPatch] = b;\n if (aMajor !== bMajor) return aMajor - bMajor;\n if (aMinor !== bMinor) return aMinor - bMinor;\n if (aPatch !== bPatch) return aPatch - bPatch;\n return 0;\n}\n\n/** Get format ID from Twine 2 name, picking the greatest version. */\nexport function getFormatIdByName(formats: Map<string, StoryFormatInfo>, name: string): string | undefined {\n let bestVersion: [number, number, number] | null = null;\n let bestId: string | undefined;\n\n for (const [id, f] of formats) {\n if (!f.isTwine2 || f.name !== name) continue;\n const v = parseSemver(f.version);\n if (!v) continue;\n if (!bestVersion || semverCompare(v, bestVersion) > 0) {\n bestVersion = v;\n bestId = id;\n }\n }\n\n return bestId;\n}\n\n/** Get format ID from Twine 2 name and version, using SemVer major matching. */\nexport function getFormatIdByNameAndVersion(\n formats: Map<string, StoryFormatInfo>,\n name: string,\n version: string,\n): string | undefined {\n const wanted = parseSemver(version);\n let bestVersion: [number, number, number] | null = null;\n let bestId: string | undefined;\n\n for (const [id, f] of formats) {\n if (!f.isTwine2 || f.name !== name) continue;\n const have = parseSemver(f.version);\n if (!have) continue;\n\n if (wanted === null || (have[0] === wanted[0] && semverCompare(have, wanted) >= 0)) {\n if (!bestVersion || semverCompare(have, bestVersion) > 0) {\n bestVersion = have;\n bestId = id;\n }\n }\n }\n\n return bestId;\n}\n\n/** Read the story format source (for Twine 2, extract the `source` property from JSON). */\nexport function readFormatSource(format: StoryFormatInfo): string {\n const source = readUTF8(format.filename);\n if (format.isTwine2) {\n const data = parseFormatJSON(source, format.id);\n if (!data) throw new Error(`Cannot parse format ${format.id} JSON`);\n return data.source;\n }\n return source;\n}\n\n/** Read a file as UTF-8 (re-exported for loader use). */\nexport { readUTF8 as readFileUTF8 } from './util.js';\n","/**\n * Shared file I/O utilities.\n */\nimport { readFileSync } from 'node:fs';\nimport { parse as parsePath } from 'node:path';\n\n/** Read a file as UTF-8 with BOM stripping and line ending normalization. */\nexport function readUTF8(filename: string): string {\n let content = readFileSync(filename, 'utf-8');\n if (content.charCodeAt(0) === 0xfeff) content = content.slice(1);\n content = content.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n return content;\n}\n\n/** Read a file as base64. */\nexport function readBase64(filename: string): string {\n return readFileSync(filename).toString('base64');\n}\n\n/** Get the filename without extension, falling back to the full basename for dotfiles. */\nexport function baseNameWithoutExt(filename: string): string {\n const { name, ext } = parsePath(filename);\n return name || ext;\n}\n","/**\n * File loading: dispatch by file extension.\n * Ported from storyload.go.\n */\nimport { basename } from 'node:path';\nimport type { Story, Diagnostic, InlineSource } from './types.js';\nimport { normalizedFileExt, mediaTypeFromFilename, mediaTypeFromExt, fontFormatHint } from './media-types.js';\nimport { storyAdd, storyPrepend } from './story.js';\nimport { parseTwee } from './parser.js';\nimport { readUTF8, readBase64, baseNameWithoutExt } from './util.js';\n\ninterface LoadOptions {\n trim?: boolean;\n twee2Compat?: boolean;\n}\n\n/**\n * Load all source files into a story.\n */\nexport function loadSources(\n story: Story,\n filenames: string[],\n opts: LoadOptions,\n diagnostics: Diagnostic[],\n processedFiles: Set<string>,\n): void {\n for (const filename of filenames) {\n if (processedFiles.has(filename)) {\n diagnostics.push({ level: 'warning', message: `load ${filename}: Skipping duplicate.` });\n continue;\n }\n\n const ext = normalizedFileExt(filename);\n try {\n switch (ext) {\n case 'tw':\n case 'twee':\n loadTwee(story, filename, opts, diagnostics);\n break;\n case 'tw2':\n case 'twee2':\n loadTwee(story, filename, { ...opts, twee2Compat: true }, diagnostics);\n break;\n case 'css':\n loadTagged(story, 'stylesheet', filename, diagnostics);\n break;\n case 'js':\n loadTagged(story, 'script', filename, diagnostics);\n break;\n case 'otf':\n case 'ttf':\n case 'woff':\n case 'woff2':\n loadFont(story, filename, diagnostics);\n break;\n case 'gif':\n case 'jpeg':\n case 'jpg':\n case 'png':\n case 'svg':\n case 'tif':\n case 'tiff':\n case 'webp':\n loadMedia(story, 'Twine.image', filename, diagnostics);\n break;\n case 'aac':\n case 'flac':\n case 'm4a':\n case 'mp3':\n case 'oga':\n case 'ogg':\n case 'opus':\n case 'wav':\n case 'wave':\n case 'weba':\n loadMedia(story, 'Twine.audio', filename, diagnostics);\n break;\n case 'mp4':\n case 'ogv':\n case 'webm':\n loadMedia(story, 'Twine.video', filename, diagnostics);\n break;\n case 'vtt':\n loadMedia(story, 'Twine.vtt', filename, diagnostics);\n break;\n default:\n continue;\n }\n } catch (e) {\n diagnostics.push({\n level: 'error',\n message: `load ${filename}: ${e instanceof Error ? e.message : String(e)}`,\n file: filename,\n });\n continue;\n }\n processedFiles.add(filename);\n }\n\n // Prepend StoryTitle if we have a name but no StoryTitle passage.\n if (story.name !== '' && !story.passages.some((p) => p.name === 'StoryTitle')) {\n storyPrepend(story, { name: 'StoryTitle', tags: [], text: story.name }, diagnostics);\n }\n}\n\n/**\n * Load inline sources (string content or InlineSource objects).\n */\nexport function loadInlineSources(\n story: Story,\n sources: (string | InlineSource)[],\n opts: LoadOptions,\n diagnostics: Diagnostic[],\n): void {\n for (const source of sources) {\n if (typeof source === 'string') {\n // Treat as a file path — handled externally\n continue;\n }\n const content = typeof source.content === 'string' ? source.content : source.content.toString('utf-8');\n\n const ext = normalizedFileExt(source.filename);\n if (ext === 'tw' || ext === 'twee' || ext === 'tw2' || ext === 'twee2' || !ext) {\n const twee2 = ext === 'tw2' || ext === 'twee2' || opts.twee2Compat;\n const result = parseTwee(content, {\n filename: source.filename,\n trim: opts.trim ?? true,\n twee2Compat: twee2,\n });\n diagnostics.push(...result.diagnostics);\n for (const p of result.passages) {\n storyAdd(story, p, diagnostics);\n }\n }\n }\n}\n\nfunction loadTwee(story: Story, filename: string, opts: LoadOptions, diagnostics: Diagnostic[]): void {\n const source = readUTF8(filename);\n const result = parseTwee(source, {\n filename,\n trim: opts.trim ?? true,\n twee2Compat: opts.twee2Compat ?? false,\n });\n diagnostics.push(...result.diagnostics);\n for (const p of result.passages) {\n storyAdd(story, p, diagnostics);\n }\n}\n\nfunction loadTagged(story: Story, tag: string, filename: string, diagnostics: Diagnostic[]): void {\n const source = readUTF8(filename);\n storyAdd(story, { name: basename(filename), tags: [tag], text: source }, diagnostics);\n}\n\nfunction loadMedia(story: Story, tag: string, filename: string, diagnostics: Diagnostic[]): void {\n const source = readBase64(filename);\n const name = baseNameWithoutExt(filename);\n storyAdd(\n story,\n {\n name,\n tags: [tag],\n text: `data:${mediaTypeFromFilename(filename)};base64,${source}`,\n },\n diagnostics,\n );\n}\n\nfunction loadFont(story: Story, filename: string, diagnostics: Diagnostic[]): void {\n const source = readBase64(filename);\n const name = basename(filename);\n const family = baseNameWithoutExt(filename);\n const ext = normalizedFileExt(filename);\n const mediaType = mediaTypeFromExt(ext);\n const hint = fontFormatHint(ext);\n\n storyAdd(\n story,\n {\n name,\n tags: ['stylesheet'],\n text: `@font-face {\\n\\tfont-family: \"${family}\";\\n\\tsrc: url(\"data:${mediaType};base64,${source}\") format(\"${hint}\");\\n}`,\n },\n diagnostics,\n );\n}\n","/**\n * Twee 3 state-machine lexer implemented as a synchronous generator.\n * Ported from tweelexer.go — Go channels become `yield`.\n */\nimport type { LexerItem } from './types.js';\nimport { ItemType } from './types.js';\n\nconst EOF = -1;\nconst HEADER_DELIM = '::';\nconst NEWLINE_HEADER_DELIM = '\\n::';\n\ntype StateFn = ((ctx: LexerContext) => StateFn | null) | null;\n\nclass LexerContext {\n readonly input: string;\n line = 1;\n start = 0;\n pos = 0;\n private items: LexerItem[] = [];\n\n constructor(input: string) {\n this.input = input;\n }\n\n next(): number {\n if (this.pos >= this.input.length) return EOF;\n const ch = this.input.charCodeAt(this.pos);\n this.pos++;\n if (ch === 0x0a) this.line++;\n return ch;\n }\n\n peek(): number {\n if (this.pos >= this.input.length) return EOF;\n return this.input.charCodeAt(this.pos);\n }\n\n backup(): void {\n if (this.pos > this.start) {\n this.pos--;\n if (this.input.charCodeAt(this.pos) === 0x0a) this.line--;\n } else {\n throw new Error('backup would leave pos < start');\n }\n }\n\n emit(type: ItemType): void {\n const val = this.input.slice(this.start, this.pos);\n this.items.push({ type, line: this.line, pos: this.start, val });\n // Content items may contain newlines that must be counted.\n if (type === ItemType.Content) {\n for (let i = this.start; i < this.pos; i++) {\n if (this.input.charCodeAt(i) === 0x0a) this.line++;\n }\n }\n this.start = this.pos;\n }\n\n ignore(): void {\n for (let i = this.start; i < this.pos; i++) {\n if (this.input.charCodeAt(i) === 0x0a) this.line++;\n }\n this.start = this.pos;\n }\n\n acceptRun(valid: string): void {\n let ch: number;\n for (ch = this.next(); ch !== EOF && valid.includes(String.fromCharCode(ch)); ch = this.next()) {\n // consume\n }\n if (ch !== EOF) this.backup();\n }\n\n errorf(message: string): null {\n this.items.push({\n type: ItemType.Error,\n line: this.line,\n pos: this.start,\n val: message,\n });\n return null;\n }\n\n /** Drain all pending items and return them. */\n drainItems(): LexerItem[] {\n const result = this.items;\n this.items = [];\n return result;\n }\n}\n\nfunction acceptQuoted(ctx: LexerContext, quote: number): string | null {\n for (;;) {\n const ch = ctx.next();\n switch (ch) {\n case 0x5c: {\n // backslash\n const r = ctx.next();\n if (r !== 0x0a && r !== EOF) break;\n // fall through\n }\n // falls through\n case 0x0a:\n case EOF:\n return 'unterminated quoted string';\n default:\n if (ch === quote) return null;\n break;\n }\n }\n}\n\n// --- State functions ---\n\nfunction lexProlog(ctx: LexerContext): StateFn {\n if (ctx.input.startsWith(HEADER_DELIM, ctx.pos)) {\n return lexHeaderDelim;\n }\n const i = ctx.input.indexOf(NEWLINE_HEADER_DELIM, ctx.pos);\n if (i > -1) {\n ctx.pos = i + 1; // skip to the newline, then past it\n ctx.ignore();\n return lexHeaderDelim;\n }\n ctx.emit(ItemType.EOF);\n return null;\n}\n\nfunction lexContent(ctx: LexerContext): StateFn {\n if (ctx.input.startsWith(HEADER_DELIM, ctx.pos)) {\n return lexHeaderDelim;\n }\n const i = ctx.input.indexOf(NEWLINE_HEADER_DELIM, ctx.pos);\n if (i > -1) {\n ctx.pos = i + 1;\n ctx.emit(ItemType.Content);\n return lexHeaderDelim;\n }\n ctx.pos = ctx.input.length;\n if (ctx.pos > ctx.start) {\n ctx.emit(ItemType.Content);\n }\n ctx.emit(ItemType.EOF);\n return null;\n}\n\nfunction lexHeaderDelim(ctx: LexerContext): StateFn {\n ctx.pos += HEADER_DELIM.length;\n ctx.emit(ItemType.Header);\n return lexName;\n}\n\nfunction lexName(ctx: LexerContext): StateFn {\n let r: number;\n outer: for (;;) {\n r = ctx.next();\n switch (r) {\n case 0x5c: {\n // backslash\n const next = ctx.next();\n if (next !== 0x0a && next !== EOF) break;\n // fall through to terminators\n r = next;\n }\n // falls through\n case 0x5b: // [\n case 0x5d: // ]\n case 0x7b: // {\n case 0x7d: // }\n case 0x0a: // \\n\n case EOF:\n if (r !== EOF) ctx.backup();\n break outer;\n }\n }\n // Always emit a name item, even if empty.\n ctx.emit(ItemType.Name);\n\n switch (r) {\n case 0x5b:\n return lexTags; // [\n case 0x5d:\n return ctx.errorf(`unexpected right square bracket ']'`);\n case 0x7b:\n return lexMetadata; // {\n case 0x7d:\n return ctx.errorf(`unexpected right curly brace '}'`);\n case 0x0a: // newline\n ctx.pos++;\n ctx.ignore();\n return lexContent;\n }\n ctx.emit(ItemType.EOF);\n return null;\n}\n\nfunction lexNextOptionalBlock(ctx: LexerContext): StateFn {\n // Consume whitespace.\n ctx.acceptRun(' \\t');\n ctx.ignore();\n\n const r = ctx.peek();\n switch (r) {\n case 0x5b:\n return lexTags; // [\n case 0x5d:\n return ctx.errorf(`unexpected right square bracket ']'`);\n case 0x7b:\n return lexMetadata; // {\n case 0x7d:\n return ctx.errorf(`unexpected right curly brace '}'`);\n case 0x0a: // newline\n ctx.pos++;\n ctx.ignore();\n return lexContent;\n case EOF:\n ctx.emit(ItemType.EOF);\n return null;\n }\n return ctx.errorf(`illegal character '${String.fromCharCode(r)}' amid the optional blocks`);\n}\n\nfunction lexTags(ctx: LexerContext): StateFn {\n // Consume the left delimiter '['.\n ctx.pos++;\n\n for (;;) {\n const r = ctx.next();\n switch (r) {\n case 0x5c: {\n // backslash\n const next = ctx.next();\n if (next !== 0x0a && next !== EOF) break;\n // fall through\n }\n // falls through\n case 0x0a:\n case EOF:\n if (r === 0x0a) ctx.backup();\n return ctx.errorf('unterminated tag block');\n case 0x5d: // ]\n if (ctx.pos > ctx.start) ctx.emit(ItemType.Tags);\n return lexNextOptionalBlock;\n case 0x5b: // [\n return ctx.errorf(`unexpected left square bracket '['`);\n case 0x7b: // {\n return ctx.errorf(`unexpected left curly brace '{'`);\n case 0x7d: // }\n return ctx.errorf(`unexpected right curly brace '}'`);\n }\n }\n}\n\nfunction lexMetadata(ctx: LexerContext): StateFn {\n // Consume the left delimiter '{'.\n ctx.pos++;\n\n let depth = 1;\n for (;;) {\n const r = ctx.next();\n switch (r) {\n case 0x22: {\n // double quote\n const err = acceptQuoted(ctx, 0x22);\n if (err) return ctx.errorf(err);\n break;\n }\n case 0x0a: // newline\n ctx.backup();\n // falls through\n case EOF:\n return ctx.errorf('unterminated metadata block');\n case 0x7b: // {\n depth++;\n break;\n case 0x7d: // }\n depth--;\n if (depth === 0) {\n if (ctx.pos > ctx.start) ctx.emit(ItemType.Metadata);\n return lexNextOptionalBlock;\n }\n break;\n }\n }\n}\n\n/**\n * Twee 3 lexer — yields LexerItem tokens from Twee source text.\n *\n * In the Go reference, this uses goroutines and channels.\n * Here we use a synchronous generator that accumulates items per state step.\n */\nexport function* tweeLexer(input: string): Generator<LexerItem, void, undefined> {\n const ctx = new LexerContext(input);\n let state: StateFn = lexProlog;\n while (state !== null) {\n state = state(ctx);\n const items = ctx.drainItems();\n for (const item of items) {\n yield item;\n }\n }\n // Drain any remaining items.\n const remaining = ctx.drainItems();\n for (const item of remaining) {\n yield item;\n }\n}\n\n/** Convenience class wrapper for the lexer generator. */\nexport class TweeLexer {\n private gen: Generator<LexerItem, void, undefined>;\n\n constructor(input: string) {\n this.gen = tweeLexer(input);\n }\n\n nextItem(): { item: LexerItem; done: boolean } {\n const result = this.gen.next();\n if (result.done) {\n return { item: { type: ItemType.EOF, line: 0, pos: 0, val: '' }, done: true };\n }\n return { item: result.value, done: false };\n }\n\n *[Symbol.iterator](): Generator<LexerItem, void, undefined> {\n yield* this.gen;\n }\n}\n","/**\n * Twee2 to Twee3 header syntax conversion.\n * Ported from twee2compat.go.\n */\n\nconst twee2DetectRe = /^:: *[^[]*?(?: *\\[.*?\\])? *<(.*?)> *$/m;\nconst twee2HeaderRe = /^(:: *[^[]*?)( *\\[.*?\\])?(?: *<(.*?)>)? *$/gm;\nconst twee2BadPosRe = /^(::.*?) *\\{\"position\":\" *\"\\}$/gm;\n\nfunction hasTwee2Syntax(s: string): boolean {\n return twee2DetectRe.test(s);\n}\n\n/**\n * Convert Twee2-style position blocks `<x,y>` to Twee3 metadata blocks `{\"position\":\"x,y\"}`.\n */\nexport function twee2ToV3(s: string): string {\n if (!hasTwee2Syntax(s)) return s;\n let result = s.replace(twee2HeaderRe, (_, p1: string, p2: string | undefined, p3: string | undefined) => {\n const tags = p2 ?? '';\n const pos = p3 ?? '';\n return `${p1}${tags} {\"position\":\"${pos}\"}`;\n });\n result = result.replace(twee2BadPosRe, '$1');\n return result;\n}\n","/**\n * Parse lexer items into Passage[].\n * Ported from storyload.go:loadTwee().\n */\nimport type { Passage, PassageMetadata, Diagnostic } from './types.js';\nimport { ItemType } from './types.js';\nimport { tweeLexer } from './lexer.js';\nimport { tweeUnescape } from './escape.js';\nimport { twee2ToV3 } from './twee2-compat.js';\n\nexport interface ParseOptions {\n /** Filename for diagnostics. */\n filename?: string;\n /** Trim whitespace from passage content. Default: true. */\n trim?: boolean;\n /** Enable Twee2 compatibility. Default: false. */\n twee2Compat?: boolean;\n}\n\nexport interface ParseResult {\n passages: Passage[];\n diagnostics: Diagnostic[];\n}\n\n/**\n * Parse Twee source text into passages.\n */\nexport function parseTwee(source: string, options: ParseOptions = {}): ParseResult {\n const { filename = '<inline>', trim = true, twee2Compat = false } = options;\n const diagnostics: Diagnostic[] = [];\n\n if (twee2Compat) {\n source = twee2ToV3(source);\n }\n\n const passages: Passage[] = [];\n let current: Passage | null = null;\n let pCount = 0;\n let lastType: ItemType = ItemType.EOF;\n\n for (const item of tweeLexer(source)) {\n switch (item.type) {\n case ItemType.Error:\n diagnostics.push({\n level: 'error',\n message: `line ${item.line}: Malformed twee source; ${item.val}.`,\n file: filename,\n line: item.line,\n });\n // Fatal: return what we have\n return { passages, diagnostics };\n\n case ItemType.EOF:\n if (pCount > 0 && current) {\n passages.push(current);\n }\n return { passages, diagnostics };\n\n case ItemType.Header:\n pCount++;\n if (pCount > 1 && current) {\n passages.push(current);\n }\n current = { name: '', tags: [], text: '' };\n break;\n\n case ItemType.Name: {\n if (!current) break;\n const name = tweeUnescape(item.val).trim();\n if (name.length === 0) {\n diagnostics.push({\n level: 'error',\n message: `line ${item.line}: Malformed twee source; passage with no name.`,\n file: filename,\n line: item.line,\n });\n return { passages, diagnostics };\n }\n current.name = name;\n break;\n }\n\n case ItemType.Tags: {\n if (!current) break;\n if (lastType !== ItemType.Name) {\n diagnostics.push({\n level: 'error',\n message: `line ${item.line}: Malformed twee source; optional tags block must immediately follow the passage name.`,\n file: filename,\n line: item.line,\n });\n return { passages, diagnostics };\n }\n // Strip the surrounding [ and ]\n const inner = item.val.slice(1, -1);\n current.tags = tweeUnescape(inner).split(/\\s+/).filter(Boolean);\n break;\n }\n\n case ItemType.Metadata: {\n if (!current) break;\n if (lastType !== ItemType.Name && lastType !== ItemType.Tags) {\n diagnostics.push({\n level: 'error',\n message: `line ${item.line}: Malformed twee source; optional metadata block must immediately follow the passage name or tags block.`,\n file: filename,\n line: item.line,\n });\n return { passages, diagnostics };\n }\n try {\n const raw: unknown = JSON.parse(item.val);\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n throw new Error('expected a JSON object');\n }\n const parsed = raw as Record<string, unknown>;\n const meta: PassageMetadata = {};\n if (typeof parsed.position === 'string') meta.position = parsed.position;\n if (typeof parsed.size === 'string') meta.size = parsed.size;\n current.metadata = meta;\n } catch (e) {\n diagnostics.push({\n level: 'warning',\n message: `load ${filename}: line ${item.line}: Malformed twee source; could not decode metadata (reason: ${e instanceof Error ? e.message : String(e)}).`,\n file: filename,\n line: item.line,\n });\n }\n break;\n }\n\n case ItemType.Content: {\n if (!current) break;\n current.text = trim ? item.val.trim() : item.val;\n break;\n }\n\n default: {\n const _exhaustive: never = item.type;\n diagnostics.push({\n level: 'error',\n message: `line ${item.line}: Unhandled lexer item type: ${_exhaustive}.`,\n file: filename,\n line: item.line,\n });\n return { passages, diagnostics };\n }\n }\n\n lastType = item.type;\n }\n\n // Shouldn't reach here (EOF is always emitted), but just in case:\n if (pCount > 0 && current) {\n passages.push(current);\n }\n return { passages, diagnostics };\n}\n","/** Single source of truth for the twee-ts version. Update here when releasing. */\nexport const VERSION = '1.2.0';\n","/**\n * Twine 2 HTML and archive output.\n * Ported from storyout.go.\n */\nimport type { Story, StoryFormatInfo, Diagnostic } from './types.js';\nimport { attrEscape, htmlEscape, commentSanitize, htmlCommentSanitize } from './escape.js';\nimport { passageToPassagedata, hasTag, hasAnyTag } from './passage.js';\nimport { generateIFID } from './ifid.js';\nimport { readFormatSource } from './formats.js';\nimport { VERSION } from './version.js';\n\nconst CREATOR_NAME = 'Twee-ts';\n\nexport function toTwine2Archive(story: Story, startName: string, diagnostics: Diagnostic[]): string {\n return getTwine2DataChunk(story, startName, diagnostics) + '\\n';\n}\n\nexport function toTwine2HTML(\n story: Story,\n format: StoryFormatInfo,\n startName: string,\n diagnostics: Diagnostic[],\n): string {\n let template = readFormatSource(format);\n\n if (template.includes('{{STORY_NAME}}')) {\n template = template.replaceAll('{{STORY_NAME}}', htmlEscape(story.name));\n }\n if (template.includes('{{STORY_DATA}}')) {\n template = template.replace('{{STORY_DATA}}', getTwine2DataChunk(story, startName, diagnostics));\n }\n\n return template;\n}\n\nfunction getTwine2DataChunk(story: Story, startName: string, diagnostics: Diagnostic[]): string {\n // Check IFID status and generate if missing.\n ensureIFID(story, diagnostics);\n\n const parts: string[] = [];\n let startID = '';\n let pid = 0;\n\n // Gather script and stylesheet passages.\n const scripts: typeof story.passages = [];\n const stylesheets: typeof story.passages = [];\n for (const p of story.passages) {\n if (hasTag(p, 'Twine.private')) continue;\n if (hasTag(p, 'script')) scripts.push(p);\n else if (hasTag(p, 'stylesheet')) stylesheets.push(p);\n }\n\n // Style element\n let styleContent = '';\n if (stylesheets.length === 1) {\n styleContent = stylesheets[0]?.text ?? '';\n } else if (stylesheets.length > 1) {\n let pidS = 1;\n for (const p of stylesheets) {\n if (pidS > 1 && !styleContent.endsWith('\\n')) styleContent += '\\n';\n styleContent += `/* twine-user-stylesheet #${pidS}: \"${commentSanitize(p.name)}\" */\\n`;\n styleContent += p.text;\n pidS++;\n }\n }\n parts.push(`<style role=\"stylesheet\" id=\"twine-user-stylesheet\" type=\"text/twine-css\">${styleContent}</style>`);\n\n // Script element\n let scriptContent = '';\n if (scripts.length === 1) {\n scriptContent = scripts[0]?.text ?? '';\n } else if (scripts.length > 1) {\n let pidS = 1;\n for (const p of scripts) {\n if (pidS > 1 && !scriptContent.endsWith('\\n')) scriptContent += '\\n';\n scriptContent += `/* twine-user-script #${pidS}: \"${commentSanitize(p.name)}\" */\\n`;\n scriptContent += p.text;\n pidS++;\n }\n }\n parts.push(`<script role=\"script\" id=\"twine-user-script\" type=\"text/twine-javascript\">${scriptContent}</script>`);\n\n // Tag color elements\n for (const [tag, color] of story.twine2.tagColors) {\n parts.push(`<tw-tag name=\"${attrEscape(tag)}\" color=\"${attrEscape(color)}\"></tw-tag>`);\n }\n\n // Normal passage elements\n pid = 1;\n for (const p of story.passages) {\n if (p.name === 'StoryTitle' || p.name === 'StoryData' || hasAnyTag(p, 'script', 'stylesheet', 'Twine.private')) {\n continue;\n }\n // Drop empty StorySettings\n if (p.name === 'StorySettings' && story.twine1.settings.size === 0) {\n continue;\n }\n\n parts.push(passageToPassagedata(p, pid));\n if (startName === p.name) {\n startID = String(pid);\n }\n pid++;\n }\n\n // Build options string\n const opts: string[] = [];\n for (const [opt, val] of story.twine2.options) {\n if (val) opts.push(opt);\n }\n const options = opts.join(' ');\n\n // Wrap in tw-storydata\n const zoom = String(story.twine2.zoom);\n\n const wrapper =\n `<!-- UUID://${htmlCommentSanitize(story.ifid)}// -->` +\n `<tw-storydata name=\"${attrEscape(story.name)}\" startnode=\"${attrEscape(startID)}\" ` +\n `creator=\"${attrEscape(CREATOR_NAME)}\" creator-version=\"${attrEscape(VERSION)}\" ` +\n `ifid=\"${attrEscape(story.ifid)}\" zoom=\"${attrEscape(zoom)}\" ` +\n `format=\"${attrEscape(story.twine2.format)}\" ` +\n `format-version=\"${attrEscape(story.twine2.formatVersion)}\" ` +\n `options=\"${attrEscape(options)}\" hidden>`;\n\n return wrapper + parts.join('') + '</tw-storydata>';\n}\n\nfunction ensureIFID(story: Story, diagnostics: Diagnostic[]): void {\n if (story.ifid !== '') return;\n\n if (story.legacyIFID !== '') {\n story.ifid = story.legacyIFID;\n diagnostics.push({\n level: 'warning',\n message: 'Story IFID not found; reusing \"ifid\" entry from the \"StorySettings\" special passage.',\n });\n } else {\n const ifid = generateIFID();\n story.ifid = ifid;\n diagnostics.push({\n level: 'error',\n message: `Story IFID not found. Add a StoryData passage with: {\"ifid\":\"${ifid}\"}`,\n });\n }\n}\n","/**\n * Twine 1 HTML and archive output.\n * Ported from storyout.go.\n */\nimport { readFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport type { Story, StoryFormatInfo, Diagnostic } from './types.js';\nimport { hasTag, passageToTiddler } from './passage.js';\nimport { readFormatSource } from './formats.js';\nimport { jsStringEscape, htmlCommentSanitize } from './escape.js';\nimport { VERSION } from './version.js';\n\nconst CREATOR_NAME = 'twee-ts';\n\nexport function toTwine1Archive(story: Story, _startName: string): string {\n const { data, count } = getTwine1PassageChunk(story);\n return `<div id=\"storeArea\" data-size=\"${count}\" hidden>${data}</div>\\n`;\n}\n\nexport function toTwine1HTML(\n story: Story,\n format: StoryFormatInfo,\n startName: string,\n _diagnostics: Diagnostic[],\n): string {\n const formatDir = dirname(format.filename);\n const parentDir = dirname(formatDir);\n let template = readFormatSource(format);\n const { data, count } = getTwine1PassageChunk(story);\n\n // Component replacements\n template = tryReplaceComponent(template, '\"USER_LIB\"', join(formatDir, 'userlib.js'), false);\n template = tryReplaceComponent(template, '\"ENGINE\"', join(parentDir, 'engine.js'), true);\n template = tryReplaceComponent(template, '\"SUGARCANE\"', join(formatDir, 'code.js'), true);\n template = tryReplaceComponent(template, '\"JONAH\"', join(formatDir, 'code.js'), true);\n\n if (story.twine1.settings.get('jquery') === 'on') {\n template = tryReplaceComponent(template, '\"JQUERY\"', join(parentDir, 'jquery.js'), true);\n }\n if (story.twine1.settings.get('modernizr') === 'on') {\n template = tryReplaceComponent(template, '\"MODERNIZR\"', join(parentDir, 'modernizr.js'), true);\n }\n\n // Story instance replacements\n const displayStart = startName === 'Start' ? '' : startName;\n template = template.replace('\"VERSION\"', `Compiled with ${CREATOR_NAME}, ${VERSION}`);\n template = template.replace('\"TIME\"', `Built on ${new Date().toUTCString()}`);\n template = template.replace('\"START_AT\"', `\"${jsStringEscape(displayStart)}\"`);\n template = template.replace('\"STORY_SIZE\"', `\"${count}\"`);\n\n if (template.includes('\"STORY\"')) {\n template = template.replace('\"STORY\"', data);\n } else {\n // Pre-1.4 format: append data + footer\n let footer: string;\n try {\n footer = readFileSync(join(formatDir, 'footer.html'), 'utf-8');\n } catch {\n footer = '</div>\\n</body>\\n</html>\\n';\n }\n template += data + footer;\n }\n\n // IFID replacement\n if (story.ifid) {\n const safeIfid = htmlCommentSanitize(story.ifid);\n if (template.includes('<div id=\"store-area\"')) {\n template = template.replace('<div id=\"store-area\"', `<!-- UUID://${safeIfid}// --><div id=\"store-area\"`);\n } else {\n template = template.replace('<div id=\"storeArea\"', `<!-- UUID://${safeIfid}// --><div id=\"storeArea\"`);\n }\n }\n\n return template;\n}\n\nfunction getTwine1PassageChunk(story: Story): { data: string; count: number } {\n let data = '';\n let count = 0;\n\n for (const p of story.passages) {\n if (hasTag(p, 'Twine.private')) continue;\n count++;\n data += passageToTiddler(p, count);\n }\n\n return { data, count };\n}\n\nfunction tryReplaceComponent(template: string, placeholder: string, componentPath: string, required: boolean): string {\n if (!template.includes(placeholder)) return template;\n try {\n let content = readFileSync(componentPath, 'utf-8');\n if (content.charCodeAt(0) === 0xfeff) content = content.slice(1);\n return template.replace(placeholder, content);\n } catch (e) {\n if (required) {\n throw new Error(\n `Required format component not found: ${componentPath}: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n return template;\n }\n}\n","/**\n * Twee 3/1 decompile output.\n * Ported from storyout.go.\n */\nimport type { Story, OutputMode } from './types.js';\nimport { passageToTwee } from './passage.js';\n\nexport function toTwee(story: Story, outMode: OutputMode): string {\n let data = '';\n for (const p of story.passages) {\n data += passageToTwee(p, outMode);\n }\n return data;\n}\n","/**\n * Module/head injection into <head>.\n * Ported from module.go + io.go:modifyHead().\n */\nimport type { Diagnostic } from './types.js';\nimport { normalizedFileExt, mediaTypeFromExt, fontFormatHint, slugify } from './media-types.js';\nimport { readUTF8, readBase64, baseNameWithoutExt } from './util.js';\n\n/**\n * Load modules and return HTML tags to inject before </head>.\n */\nexport function loadModules(filenames: string[]): string {\n const processed = new Set<string>();\n const headTags: string[] = [];\n\n for (const filename of filenames) {\n if (processed.has(filename)) continue;\n\n const ext = normalizedFileExt(filename);\n let tag: string | null = null;\n\n switch (ext) {\n case 'css':\n tag = loadModuleTagged('style', filename);\n break;\n case 'js':\n tag = loadModuleTagged('script', filename);\n break;\n case 'otf':\n case 'ttf':\n case 'woff':\n case 'woff2':\n tag = loadModuleFont(filename);\n break;\n default:\n continue;\n }\n\n if (tag) headTags.push(tag);\n processed.add(filename);\n }\n\n return headTags.join('\\n');\n}\n\nfunction loadModuleTagged(tag: string, filename: string): string | null {\n const source = readUTF8(filename).trim();\n if (source.length === 0) return null;\n\n const family = baseNameWithoutExt(filename);\n const idSlug = `${tag}-module-${slugify(family)}`;\n const mimeType = tag === 'script' ? 'text/javascript' : 'text/css';\n\n return `<${tag} id=\"${idSlug}\" type=\"${mimeType}\">${source}</${tag}>`;\n}\n\nfunction loadModuleFont(filename: string): string | null {\n const source = readBase64(filename);\n const family = baseNameWithoutExt(filename);\n const idSlug = `style-module-${slugify(family)}`;\n const ext = normalizedFileExt(filename);\n const mediaType = mediaTypeFromExt(ext);\n const hint = fontFormatHint(ext);\n\n return `<style id=\"${idSlug}\" type=\"text/css\">@font-face {\\n\\tfont-family: \"${family}\";\\n\\tsrc: url(\"data:${mediaType};base64,${source}\") format(\"${hint}\");\\n}</style>`;\n}\n\n/**\n * Inject modules and head file content before </head>.\n */\nexport function modifyHead(html: string, modulePaths: string[], headFile?: string, diagnostics?: Diagnostic[]): string {\n const parts: string[] = [];\n\n if (modulePaths.length > 0) {\n const modules = loadModules(modulePaths).trim();\n if (modules.length > 0) parts.push(modules);\n }\n\n if (headFile) {\n try {\n const source = readUTF8(headFile).trim();\n if (source.length > 0) parts.push(source);\n } catch (e) {\n diagnostics?.push({\n level: 'warning',\n message: `Failed to read head file \"${headFile}\": ${e instanceof Error ? e.message : String(e)}`,\n });\n }\n }\n\n if (parts.length > 0) {\n parts.push('</head>');\n return html.replace('</head>', parts.join('\\n'));\n }\n return html;\n}\n","/**\n * Remote story format fetching, caching, and checksum verification.\n * Uses the Story Formats Archive (SFA) as the default source.\n */\nimport { mkdirSync, readFileSync, writeFileSync, existsSync, readdirSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { SFAIndex, SFAIndexEntry, StoryFormatInfo } from './types.js';\nimport { parseSemver, semverCompare, parseFormatJSON } from './formats.js';\n\nconst DEFAULT_SFA_INDICES = [\n 'https://videlais.github.io/story-formats-archive/official/index.json',\n 'https://videlais.github.io/story-formats-archive/unofficial/index.json',\n];\n\n/** Get the cache directory for downloaded story formats. */\nexport function getCacheDir(): string {\n const xdg = process.env['XDG_CACHE_HOME'];\n const base = xdg || join(homedir(), '.cache');\n return join(base, 'twee-ts', 'storyformats');\n}\n\n/** In-memory index cache, keyed by URL. Cleared each compile. */\nconst indexCache = new Map<string, SFAIndex>();\n\n/** Clear the in-memory index cache. */\nexport function clearIndexCache(): void {\n indexCache.clear();\n}\n\n/** Validate that a JSON value is a valid SFAIndexEntry. */\nfunction isValidEntry(val: unknown): val is SFAIndexEntry {\n if (typeof val !== 'object' || val === null || Array.isArray(val)) return false;\n const obj = val as Record<string, unknown>;\n return (\n typeof obj.name === 'string' &&\n typeof obj.version === 'string' &&\n typeof obj.checksums === 'object' &&\n obj.checksums !== null &&\n !Array.isArray(obj.checksums)\n );\n}\n\n/** Validate that a JSON value conforms to the SFAIndex shape. */\nfunction validateSFAIndex(json: unknown): SFAIndex {\n if (typeof json !== 'object' || json === null) {\n throw new Error('SFA index is not an object');\n }\n const obj = json as Record<string, unknown>;\n const twine1 = Array.isArray(obj['twine1']) ? (obj['twine1'] as unknown[]).filter(isValidEntry) : [];\n const twine2 = Array.isArray(obj['twine2']) ? (obj['twine2'] as unknown[]).filter(isValidEntry) : [];\n return { twine1, twine2 };\n}\n\n/** Generate a format ID from name and version. */\nfunction makeFormatId(name: string, version: string): string {\n const major = parseSemver(version)?.[0] ?? '0';\n return `${name.toLowerCase().replace(/\\s+/g, '-')}-${major}`;\n}\n\n/** Fetch and parse an SFA index.json, with in-memory caching. */\nexport async function fetchIndex(url: string): Promise<SFAIndex> {\n const cached = indexCache.get(url);\n if (cached) return cached;\n\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Failed to fetch format index from ${url}: ${res.status} ${res.statusText}`);\n }\n const data = validateSFAIndex(await res.json());\n indexCache.set(url, data);\n return data;\n}\n\ninterface FindEntryResult {\n entry: SFAIndexEntry;\n formatType: 'twine1' | 'twine2';\n}\n\n/**\n * Find the best matching entry in an SFA index.\n * Exact version preferred, then highest version with same major.\n */\nexport function findEntry(index: SFAIndex, name: string, version: string): FindEntryResult | undefined {\n const wanted = parseSemver(version);\n\n const searchArrays: Array<{ entries: SFAIndexEntry[]; formatType: 'twine1' | 'twine2' }> = [\n { entries: index.twine2 ?? [], formatType: 'twine2' },\n { entries: index.twine1 ?? [], formatType: 'twine1' },\n ];\n\n let bestResult: FindEntryResult | undefined;\n let bestVersion: [number, number, number] | null = null;\n\n for (const { entries, formatType } of searchArrays) {\n for (const entry of entries) {\n if (entry.name.toLowerCase() !== name.toLowerCase()) continue;\n const have = parseSemver(entry.version);\n if (!have) continue;\n\n // Exact match — return immediately\n if (wanted && semverCompare(have, wanted) === 0) return { entry, formatType };\n\n // Same-major, highest version\n if (wanted === null || (have[0] === wanted[0] && semverCompare(have, wanted) >= 0)) {\n if (!bestVersion || semverCompare(have, bestVersion) > 0) {\n bestVersion = have;\n bestResult = { entry, formatType };\n }\n }\n }\n }\n\n return bestResult;\n}\n\n/** Verify SHA-256 checksum using Web Crypto API (Node 22 built-in). */\nexport async function verifySHA256(content: Uint8Array<ArrayBuffer>, expectedHex: string): Promise<boolean> {\n const digest = await crypto.subtle.digest('SHA-256', content);\n const hex = Array.from(new Uint8Array(digest))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n return hex === expectedHex.toLowerCase();\n}\n\n/** Derive the download URL for a format.js from the index URL and entry. */\nfunction getDownloadUrl(indexUrl: string, entry: SFAIndexEntry, formatType: 'twine1' | 'twine2'): string {\n const base = indexUrl.replace(/\\/index\\.json$/, '');\n return `${base}/${formatType}/${entry.name}/${entry.version}/format.js`;\n}\n\n/** Download a format, verify its checksum, write to cache, and return StoryFormatInfo. */\nexport async function fetchAndCacheFormat(entry: SFAIndexEntry, downloadUrl: string): Promise<StoryFormatInfo> {\n const res = await fetch(downloadUrl);\n if (!res.ok) {\n throw new Error(`Failed to download format from ${downloadUrl}: ${res.status} ${res.statusText}`);\n }\n const text = await res.text();\n\n // Verify checksum if available\n const checksumKey = Object.keys(entry.checksums ?? {}).find((k) => k.endsWith('format.js'));\n if (checksumKey) {\n const expected = entry.checksums[checksumKey];\n if (!expected) throw new Error(`Missing checksum value for key \"${checksumKey}\"`);\n const encoder = new TextEncoder();\n const valid = await verifySHA256(encoder.encode(text), expected);\n if (!valid) {\n throw new Error(`Checksum verification failed for ${entry.name} ${entry.version}`);\n }\n }\n\n // Parse format JSON to extract name/version/source\n const id = makeFormatId(entry.name, entry.version);\n const data = parseFormatJSON(text, id);\n if (!data) {\n throw new Error(`Failed to parse format JSON from ${downloadUrl}`);\n }\n\n // Write to cache\n const cacheDir = getCacheDir();\n const formatDir = join(cacheDir, entry.name, entry.version);\n mkdirSync(formatDir, { recursive: true });\n const formatPath = join(formatDir, 'format.js');\n writeFileSync(formatPath, text, 'utf-8');\n\n return {\n id,\n filename: formatPath,\n isTwine2: true,\n name: data.name,\n version: data.version,\n proofing: data.proofing ?? false,\n };\n}\n\n/** Download a direct format.js URL, parse its JSON, cache it, and return StoryFormatInfo. */\nexport async function fetchDirectFormat(url: string): Promise<StoryFormatInfo> {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Failed to download format from ${url}: ${res.status} ${res.statusText}`);\n }\n const text = await res.text();\n\n const tempId = 'direct-url';\n const data = parseFormatJSON(text, tempId);\n if (!data) {\n throw new Error(`Failed to parse format JSON from ${url}`);\n }\n\n const id = makeFormatId(data.name, data.version);\n\n // Write to cache\n const cacheDir = getCacheDir();\n const formatDir = join(cacheDir, data.name, data.version);\n mkdirSync(formatDir, { recursive: true });\n const formatPath = join(formatDir, 'format.js');\n writeFileSync(formatPath, text, 'utf-8');\n\n return {\n id,\n filename: formatPath,\n isTwine2: true,\n name: data.name,\n version: data.version,\n proofing: data.proofing ?? false,\n };\n}\n\n/**\n * Try to resolve a remote story format by name and version.\n * 1. Try direct format URLs\n * 2. Try custom index URLs\n * 3. Try default SFA indices\n */\nexport async function resolveRemoteFormat(\n name: string,\n version: string,\n indices?: string[],\n urls?: string[],\n): Promise<StoryFormatInfo | undefined> {\n let lastError: Error | undefined;\n\n // 1. Try direct URLs — check if any match by name\n if (urls) {\n for (const url of urls) {\n try {\n const info = await fetchDirectFormat(url);\n if (info.name.toLowerCase() === name.toLowerCase()) {\n const wanted = parseSemver(version);\n const have = parseSemver(info.version);\n if (!wanted || (have && have[0] === wanted[0] && semverCompare(have, wanted) >= 0)) {\n return info;\n }\n }\n } catch (e) {\n lastError = e instanceof Error ? e : new Error(String(e));\n }\n }\n }\n\n // 2. Try custom indices, then default SFA indices\n const allIndices = [...(indices ?? []), ...DEFAULT_SFA_INDICES];\n for (const indexUrl of allIndices) {\n try {\n const index = await fetchIndex(indexUrl);\n const result = findEntry(index, name, version);\n if (result) {\n // Check cache first\n const cached = getCachedFormat(result.entry.name, result.entry.version);\n if (cached) return cached;\n\n const downloadUrl = getDownloadUrl(indexUrl, result.entry, result.formatType);\n return await fetchAndCacheFormat(result.entry, downloadUrl);\n }\n } catch (e) {\n lastError = e instanceof Error ? e : new Error(String(e));\n }\n }\n\n // If all sources failed with errors, propagate the last one\n if (lastError) throw lastError;\n return undefined;\n}\n\n/** Check if a format is already in the local cache. */\nfunction getCachedFormat(name: string, version: string): StoryFormatInfo | undefined {\n const formatPath = join(getCacheDir(), name, version, 'format.js');\n try {\n if (!existsSync(formatPath)) return undefined;\n const source = readFileSync(formatPath, 'utf-8');\n const id = makeFormatId(name, version);\n const data = parseFormatJSON(source, id);\n if (!data) return undefined;\n return {\n id,\n filename: formatPath,\n isTwine2: true,\n name: data.name,\n version: data.version,\n proofing: data.proofing ?? false,\n };\n } catch {\n return undefined;\n }\n}\n\n/** Discover all cached remote formats. Returns a Map like discoverFormats(). */\nexport function discoverCachedFormats(): Map<string, StoryFormatInfo> {\n const formats = new Map<string, StoryFormatInfo>();\n const cacheDir = getCacheDir();\n\n try {\n if (!existsSync(cacheDir)) return formats;\n } catch {\n return formats;\n }\n\n let names: string[];\n try {\n names = readdirSync(cacheDir);\n } catch {\n return formats;\n }\n\n for (const name of names) {\n const nameDir = join(cacheDir, name);\n try {\n if (!statSync(nameDir).isDirectory()) continue;\n } catch {\n continue;\n }\n\n let versions: string[];\n try {\n versions = readdirSync(nameDir);\n } catch {\n continue;\n }\n\n for (const version of versions) {\n const info = getCachedFormat(name, version);\n if (info) {\n formats.set(`${info.id}-${version}`, info);\n }\n }\n }\n\n return formats;\n}\n","/**\n * Story inspection utilities for unit testing.\n *\n * Extracts structural information from a compiled story:\n * passage names, tags, link graph, broken links, dead ends, orphans.\n *\n * Usage:\n * const result = await compile({ sources: ['./story'] });\n * const map = storyInspect(result.story);\n * expect(map.passages).toContain('Start');\n * expect(map.brokenLinks).toHaveLength(0);\n */\nimport type { Story } from './types.js';\nimport { isInfoPassage, isStoryPassage } from './passage.js';\n\nexport interface StoryMap {\n /** All passage names, in source order. */\n passages: string[];\n /** Only story passages (excludes StoryData, StoryTitle, scripts, stylesheets, etc.). */\n storyPassages: string[];\n /** Only info/special passages. */\n infoPassages: string[];\n /** All unique tags used across the story, sorted alphabetically. */\n tags: string[];\n /** Map of tag → passage names that carry that tag. */\n passagesByTag: Map<string, string[]>;\n /** Map of passage name → tags on that passage. */\n tagsByPassage: Map<string, string[]>;\n /**\n * Map of passage name → passage names it links to.\n * Parses `[[target]]`, `[[display->target]]`, `[[display|target]]`,\n * and SugarCube's `<<goto \"target\">>` / `<<link \"display\" \"target\">>`.\n */\n links: Map<string, string[]>;\n /** Broken links: `{ from, to }` pairs where `to` doesn't exist as a passage. */\n brokenLinks: BrokenLink[];\n /** Story passages with no outgoing links (potential dead ends). */\n deadEnds: string[];\n /** Story passages that no other passage links to (excluding the start passage). */\n orphans: string[];\n /** The configured start passage name, if any. */\n start: string;\n}\n\nexport interface BrokenLink {\n from: string;\n to: string;\n}\n\n/**\n * Extract all [[wiki-style links]] from passage text.\n *\n * Supported syntaxes:\n * - `[[PassageName]]`\n * - `[[Display Text->PassageName]]` (Twine 2 / SugarCube arrow)\n * - `[[Display Text|PassageName]]` (Twine 1 / Harlowe pipe)\n * - `<<goto \"PassageName\">>` (SugarCube macro)\n * - `<<link \"Display\" \"PassageName\">>` (SugarCube macro)\n */\nfunction extractLinksFromText(text: string): string[] {\n const targets = new Set<string>();\n\n // [[...]] links\n const wikiLinkRe = /\\[\\[([^\\]]+)\\]\\]/g;\n let m;\n while ((m = wikiLinkRe.exec(text)) !== null) {\n const content = m[1]!;\n\n // [[display->target]]\n const arrowIdx = content.indexOf('->');\n if (arrowIdx !== -1) {\n targets.add(content.slice(arrowIdx + 2).trim());\n continue;\n }\n\n // [[display|target]]\n const pipeIdx = content.indexOf('|');\n if (pipeIdx !== -1) {\n targets.add(content.slice(pipeIdx + 1).trim());\n continue;\n }\n\n // [[target]]\n targets.add(content.trim());\n }\n\n // <<goto \"target\">>\n const gotoRe = /<<goto\\s+[\"']([^\"']+)[\"']\\s*>>/g;\n while ((m = gotoRe.exec(text)) !== null) {\n targets.add(m[1]!);\n }\n\n // <<link \"display\" \"target\">> (second argument is the target passage)\n const linkMacroRe = /<<link\\s+[\"'][^\"']*[\"']\\s+[\"']([^\"']+)[\"']\\s*>>/g;\n while ((m = linkMacroRe.exec(text)) !== null) {\n targets.add(m[1]!);\n }\n\n return [...targets];\n}\n\n/**\n * Inspect a story and return its full structural map.\n *\n * Designed for story authors to use in unit tests:\n * ```ts\n * const result = await compile({ sources: ['./story'] });\n * const map = storyInspect(result.story);\n *\n * // Assert structure\n * expect(map.passages).toContain('Start');\n * expect(map.tags).toContain('location');\n * expect(map.passagesByTag.get('location')).toContain('Kitchen');\n * expect(map.brokenLinks).toEqual([]);\n * expect(map.deadEnds).not.toContain('Start');\n * ```\n */\nexport function storyInspect(story: Story): StoryMap {\n const allNames = new Set(story.passages.map((p) => p.name));\n\n const passages: string[] = [];\n const storyPassages: string[] = [];\n const infoPassages: string[] = [];\n const tagSet = new Set<string>();\n const passagesByTag = new Map<string, string[]>();\n const tagsByPassage = new Map<string, string[]>();\n const links = new Map<string, string[]>();\n\n for (const p of story.passages) {\n passages.push(p.name);\n\n if (isStoryPassage(p)) {\n storyPassages.push(p.name);\n }\n if (isInfoPassage(p)) {\n infoPassages.push(p.name);\n }\n\n // Tags\n tagsByPassage.set(p.name, [...p.tags]);\n for (const tag of p.tags) {\n tagSet.add(tag);\n let list = passagesByTag.get(tag);\n if (!list) {\n list = [];\n passagesByTag.set(tag, list);\n }\n list.push(p.name);\n }\n\n // Links\n const targets = extractLinksFromText(p.text);\n links.set(p.name, targets);\n }\n\n // Broken links: link targets that don't exist as passages\n const brokenLinks: BrokenLink[] = [];\n for (const [from, targets] of links) {\n for (const to of targets) {\n if (!allNames.has(to)) {\n brokenLinks.push({ from, to });\n }\n }\n }\n\n // Dead ends: story passages with no outgoing links\n const deadEnds: string[] = [];\n for (const name of storyPassages) {\n const targets = links.get(name);\n if (!targets || targets.length === 0) {\n deadEnds.push(name);\n }\n }\n\n // Orphans: story passages nobody links to (excluding start)\n const start = story.twine2.start || 'Start';\n const linkedTo = new Set<string>();\n for (const targets of links.values()) {\n for (const t of targets) {\n linkedTo.add(t);\n }\n }\n const orphans: string[] = [];\n for (const name of storyPassages) {\n if (name !== start && !linkedTo.has(name)) {\n orphans.push(name);\n }\n }\n\n return {\n passages,\n storyPassages,\n infoPassages,\n tags: [...tagSet].sort(),\n passagesByTag,\n tagsByPassage,\n links,\n brokenLinks,\n deadEnds,\n orphans,\n start,\n };\n}\n","/**\n * Config file loading and validation for twee-ts.\n */\nimport { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { TweeTsConfig, OutputMode } from './types.js';\n\nexport const CONFIG_FILENAME = 'twee-ts.config.json';\n\nconst VALID_OUTPUT_MODES: OutputMode[] = ['html', 'twee3', 'twee1', 'twine2-archive', 'twine1-archive', 'json'];\n\n/** Load a config file from the given directory (default: cwd). Returns null if not found. */\nexport function loadConfig(dir?: string): TweeTsConfig | null {\n const base = dir ?? process.cwd();\n const configPath = join(base, CONFIG_FILENAME);\n\n if (!existsSync(configPath)) return null;\n\n let raw: string;\n try {\n raw = readFileSync(configPath, 'utf-8');\n } catch {\n return null;\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (e) {\n throw new Error(`Invalid JSON in ${configPath}: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n const errors = validateConfig(data);\n if (errors.length > 0) {\n throw new Error(`Invalid config in ${configPath}:\\n ${errors.join('\\n ')}`);\n }\n\n return data as TweeTsConfig;\n}\n\n/** Load a config from a specific file path. */\nexport function loadConfigFile(filePath: string): TweeTsConfig {\n let raw: string;\n try {\n raw = readFileSync(filePath, 'utf-8');\n } catch (e) {\n throw new Error(`Cannot read config file ${filePath}: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (e) {\n throw new Error(`Invalid JSON in ${filePath}: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n const errors = validateConfig(data);\n if (errors.length > 0) {\n throw new Error(`Invalid config in ${filePath}:\\n ${errors.join('\\n ')}`);\n }\n\n return data as TweeTsConfig;\n}\n\n/** Validate a config object. Returns an array of error strings (empty = valid). */\nexport function validateConfig(data: unknown): string[] {\n const errors: string[] = [];\n\n if (typeof data !== 'object' || data === null || Array.isArray(data)) {\n errors.push('Config must be a JSON object.');\n return errors;\n }\n\n const obj = data as Record<string, unknown>;\n\n // String fields\n for (const key of ['output', 'formatId', 'startPassage', 'headFile'] as const) {\n if (key in obj && typeof obj[key] !== 'string') {\n errors.push(`\"${key}\" must be a string.`);\n }\n }\n\n // Boolean fields\n for (const key of ['useTweegoPath', 'trim', 'twee2Compat', 'testMode', 'noRemote'] as const) {\n if (key in obj && typeof obj[key] !== 'boolean') {\n errors.push(`\"${key}\" must be a boolean.`);\n }\n }\n\n // String array fields\n for (const key of ['sources', 'formatPaths', 'formatIndices', 'formatUrls', 'modules'] as const) {\n if (key in obj) {\n if (!Array.isArray(obj[key])) {\n errors.push(`\"${key}\" must be an array.`);\n } else if (!(obj[key] as unknown[]).every((v) => typeof v === 'string')) {\n errors.push(`\"${key}\" must be an array of strings.`);\n }\n }\n }\n\n // tagAliases validation\n if ('tagAliases' in obj) {\n if (typeof obj['tagAliases'] !== 'object' || obj['tagAliases'] === null || Array.isArray(obj['tagAliases'])) {\n errors.push('\"tagAliases\" must be an object.');\n } else {\n const aliases = obj['tagAliases'] as Record<string, unknown>;\n for (const [key, val] of Object.entries(aliases)) {\n if (typeof val !== 'string') {\n errors.push(`\"tagAliases.${key}\" must be a string.`);\n }\n }\n }\n }\n\n // OutputMode validation\n if ('outputMode' in obj) {\n if (typeof obj['outputMode'] !== 'string' || !VALID_OUTPUT_MODES.includes(obj['outputMode'] as OutputMode)) {\n errors.push(`\"outputMode\" must be one of: ${VALID_OUTPUT_MODES.join(', ')}.`);\n }\n }\n\n return errors;\n}\n\n/** Return a default config JSON string for --init scaffolding. */\nexport function scaffoldConfig(): string {\n const config: TweeTsConfig = {\n sources: ['src/'],\n output: 'story.html',\n };\n return JSON.stringify(config, null, 2) + '\\n';\n}\n"],"mappings":"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","names":["writeFileSync","readdirSync","statSync","join","statSync","readdirSync","join","quote","readFileSync","join","CREATOR_NAME","join","readFileSync","readFileSync","readdirSync","statSync","join","homedir","join","homedir","readFileSync","readdirSync","statSync","CREATOR_NAME","writeFileSync","readFileSync","existsSync","join"]}
1
+ {"version":3,"sources":["../src/compiler.ts","../src/ifid.ts","../src/escape.ts","../src/passage.ts","../src/story.ts","../src/filesystem.ts","../src/media-types.ts","../src/formats.ts","../src/util.ts","../src/loader.ts","../src/lexer.ts","../src/twee2-compat.ts","../src/parser.ts","../src/version.ts","../src/output-twine2.ts","../src/output-twine1.ts","../src/output-twee.ts","../src/modules.ts","../src/remote-formats.ts","../src/inspect.ts","../src/config.ts"],"sourcesContent":["/**\n * Main compiler orchestrator.\n * compile(), compileToFile(), watch().\n * Ported from tweego.go + config.go.\n */\nimport { writeFileSync } from 'node:fs';\nimport type {\n CompileOptions,\n CompileToFileOptions,\n WatchOptions,\n CompileResult,\n CompileStats,\n Diagnostic,\n Story,\n StoryFormatInfo,\n OutputMode,\n InlineSource,\n} from './types.js';\nimport { createStory, storyHas, getStoryStats } from './story.js';\nimport { getFilenames, watchFilesystem } from './filesystem.js';\nimport { discoverFormats, getFormatSearchDirs, getFormatIdByNameAndVersion } from './formats.js';\nimport { loadSources, loadInlineSources } from './loader.js';\nimport { applyTagAliases, hasTag } from './passage.js';\nimport { toTwine2HTML, toTwine2Archive } from './output-twine2.js';\nimport { toTwine1HTML, toTwine1Archive } from './output-twine1.js';\nimport { toTwee } from './output-twee.js';\nimport { modifyHead } from './modules.js';\nimport { resolveRemoteFormat, clearIndexCache } from './remote-formats.js';\nimport { VERSION } from './version.js';\n\nconst CREATOR_NAME = 'Twee-ts';\n\nconst DEFAULT_FORMAT_ID = 'sugarcube-2';\nconst DEFAULT_START_NAME = 'Start';\n\nexport class TweeTsError extends Error {\n constructor(\n message: string,\n public diagnostics: Diagnostic[] = [],\n ) {\n super(message);\n this.name = 'TweeTsError';\n }\n}\n\n/**\n * Compile Twee sources to HTML, Twee, or JSON.\n */\nexport async function compile(options: CompileOptions): Promise<CompileResult> {\n return buildOutput(options);\n}\n\n/**\n * Compile and write to a file.\n */\nexport async function compileToFile(options: CompileToFileOptions): Promise<CompileResult> {\n const result = await compile(options);\n writeFileSync(options.outFile, result.output, 'utf-8');\n return result;\n}\n\n/**\n * Watch for file changes and recompile.\n */\nexport async function watch(options: WatchOptions): Promise<AbortController> {\n const controller = new AbortController();\n\n // Separate file paths from inline sources\n const filePaths = options.sources.filter((s): s is string => typeof s === 'string');\n const modulePaths = options.modules ?? [];\n const allPaths = [...filePaths, ...modulePaths];\n\n const handle = watchFilesystem(allPaths, options.outFile, () => {\n buildOutput(options)\n .then((result) => {\n writeFileSync(options.outFile, result.output, 'utf-8');\n options.onBuild?.(result);\n })\n .catch((e) => {\n options.onError?.(e instanceof Error ? e : new Error(String(e)));\n });\n });\n\n controller.signal.addEventListener('abort', () => handle.close());\n return controller;\n}\n\nasync function buildOutput(options: CompileOptions): Promise<CompileResult> {\n const diagnostics: Diagnostic[] = [];\n const outputMode: OutputMode = options.outputMode ?? 'html';\n const trim = options.trim ?? true;\n const twee2Compat = options.twee2Compat ?? false;\n const testMode = options.testMode ?? false;\n const noRemote = options.noRemote ?? false;\n\n // Clear per-compile index cache\n clearIndexCache();\n\n // Separate file paths from inline sources\n const filePaths: string[] = [];\n const inlineSources: InlineSource[] = [];\n for (const source of options.sources) {\n if (typeof source === 'string') {\n filePaths.push(source);\n } else {\n inlineSources.push(source);\n }\n }\n\n // Walk file paths to get all source filenames\n const sourceFilenames = getFilenames(filePaths);\n\n // Create story and load sources\n const story = createStory();\n const processedFiles = new Set<string>();\n\n loadSources(story, sourceFilenames, { trim, twee2Compat }, diagnostics, processedFiles);\n loadInlineSources(story, inlineSources, { trim, twee2Compat }, diagnostics);\n\n // Apply tag aliases (e.g. library → script)\n if (options.tagAliases) {\n story.passages = applyTagAliases(story.passages, options.tagAliases);\n }\n\n // Resolve format\n let format: StoryFormatInfo | undefined;\n let formatId = options.formatId ?? '';\n\n if (outputMode === 'html') {\n const formatSearchDirs = getFormatSearchDirs(options.formatPaths, options.useTweegoPath ?? true);\n const formats = discoverFormats(formatSearchDirs);\n\n if (!formatId && story.twine2.format) {\n formatId = getFormatIdByNameAndVersion(formats, story.twine2.format, story.twine2.formatVersion) ?? '';\n }\n if (!formatId) {\n formatId = DEFAULT_FORMAT_ID;\n }\n\n format = formats.get(formatId);\n\n // Remote format fallback\n if (!format && !noRemote) {\n // Determine the format name and version for remote lookup\n const remoteName = story.twine2.format || formatId;\n const remoteVersion = story.twine2.formatVersion || '';\n\n try {\n format = await resolveRemoteFormat(remoteName, remoteVersion, options.formatIndices, options.formatUrls);\n } catch (e) {\n diagnostics.push({\n level: 'warning',\n message: `Remote format fetch failed for \"${remoteName}\": ${e instanceof Error ? e.message : String(e)}`,\n });\n }\n }\n\n if (!format) {\n const reason = noRemote ? ' (remote fetching disabled)' : '';\n diagnostics.push({\n level: 'error',\n message: `Story format \"${formatId}\" is not available${reason}. Found: ${[...formats.keys()].join(', ') || 'none'}`,\n });\n }\n }\n\n // Merge config from StoryData: command-line > StoryData > default\n const startName = options.startPassage || story.twine2.start || DEFAULT_START_NAME;\n\n // Apply test mode\n if (testMode) {\n story.twine2.options.set('debug', true);\n }\n\n // Generate output\n let output: string;\n\n switch (outputMode) {\n case 'twee3':\n case 'twee1':\n output = toTwee(story, outputMode);\n break;\n\n case 'twine2-archive':\n output = toTwine2Archive(story, startName, diagnostics);\n break;\n\n case 'twine1-archive':\n output = toTwine1Archive(story, startName);\n break;\n\n case 'json':\n output = storyToJSON(story);\n break;\n\n case 'html': {\n // Sanity checks for HTML mode\n if (!storyHas(story, startName)) {\n diagnostics.push({\n level: 'error',\n message: `Starting passage \"${startName}\" not found.`,\n });\n }\n\n if (!format) {\n throw new TweeTsError('No story format available for HTML output.', diagnostics);\n }\n\n if (format.isTwine2) {\n output = toTwine2HTML(story, format, startName, diagnostics);\n } else {\n if (story.name === '' && !storyHas(story, 'StoryTitle')) {\n diagnostics.push({\n level: 'error',\n message: 'Special passage \"StoryTitle\" not found.',\n });\n }\n output = toTwine1HTML(story, format, startName, diagnostics);\n }\n\n // Inject modules and head file\n const modulePaths = options.modules ? getFilenames(options.modules) : [];\n output = modifyHead(output, modulePaths, options.headFile, diagnostics);\n break;\n }\n\n default: {\n const _exhaustive: never = outputMode;\n throw new TweeTsError(`Unhandled output mode: ${_exhaustive as string}`, diagnostics);\n }\n }\n\n // Compute stats\n const stats: CompileStats = {\n ...getStoryStats(story),\n files: [...processedFiles],\n };\n\n return { output, story, format, diagnostics, stats };\n}\n\n/**\n * Serialize a Story to JSON per the Twine 2 JSON Output Specification (v1.0):\n * https://github.com/iftechfoundation/twine-specs/blob/master/twine-2-jsonoutput-doc.md\n */\nfunction storyToJSON(story: Story): string {\n // Gather script and stylesheet content, excluding them from passages.\n const scripts: string[] = [];\n const stylesheets: string[] = [];\n const storyPassages: { name: string; tags: string[]; text: string; metadata?: Record<string, string> }[] = [];\n\n for (const p of story.passages) {\n if (p.name === 'StoryTitle' || p.name === 'StoryData') continue;\n if (hasTag(p, 'Twine.private')) continue;\n\n if (hasTag(p, 'script')) {\n scripts.push(p.text);\n } else if (hasTag(p, 'stylesheet')) {\n stylesheets.push(p.text);\n } else {\n const entry: { name: string; tags: string[]; text: string; metadata?: Record<string, string> } = {\n name: p.name,\n tags: p.tags,\n text: p.text,\n };\n if (p.metadata) {\n const meta: Record<string, string> = {};\n for (const [key, value] of Object.entries(p.metadata)) {\n if (typeof value === 'string') meta[key] = value;\n }\n if (Object.keys(meta).length > 0) {\n entry.metadata = meta;\n }\n }\n storyPassages.push(entry);\n }\n }\n\n const obj: Record<string, unknown> = {\n name: story.name,\n };\n\n if (story.ifid) obj.ifid = story.ifid;\n if (story.twine2.format) obj.format = story.twine2.format;\n if (story.twine2.formatVersion) obj['format-version'] = story.twine2.formatVersion;\n if (story.twine2.start) obj.start = story.twine2.start;\n if (story.twine2.tagColors.size > 0) obj['tag-colors'] = Object.fromEntries(story.twine2.tagColors);\n if (story.twine2.zoom !== 1) obj.zoom = story.twine2.zoom;\n obj.creator = CREATOR_NAME;\n obj['creator-version'] = VERSION;\n obj.style = stylesheets.join('\\n');\n obj.script = scripts.join('\\n');\n obj.passages = storyPassages;\n\n return JSON.stringify(obj, null, 2);\n}\n","/**\n * IFID (Interactive Fiction IDentifier) generation and validation.\n * Ported from ifid.go.\n */\nimport { randomUUID } from 'node:crypto';\n\n/** Generate a new IFID (UUID v4, uppercase). */\nexport function generateIFID(): string {\n return randomUUID().toUpperCase();\n}\n\n/**\n * Validate an IFID string.\n * Accepts both bare UUIDs and UUID://...// wrapped format.\n * Returns null if valid, or an error message string.\n */\nexport function validateIFID(ifid: string): string | null {\n let uuid = ifid;\n\n switch (ifid.length) {\n case 36:\n break;\n case 45: {\n if (ifid.slice(0, 7).toUpperCase() !== 'UUID://' || ifid.slice(43) !== '//') {\n return 'invalid IFID UUID://...// format';\n }\n uuid = ifid.slice(7, 43);\n break;\n }\n default:\n return `invalid IFID length: ${ifid.length}`;\n }\n\n for (let i = 0; i < uuid.length; i++) {\n const ch = uuid[i]!;\n switch (i) {\n case 8:\n case 13:\n case 18:\n case 23:\n if (ch !== '-') {\n return `invalid IFID character '${ch}' at position ${i + 1}`;\n }\n break;\n case 14:\n if (ch < '1' || ch > '5') {\n return `invalid version '${ch}' at position ${i + 1}`;\n }\n break;\n case 19:\n if (!['8', '9', 'a', 'A', 'b', 'B'].includes(ch)) {\n return `invalid variant '${ch}' at position ${i + 1}`;\n }\n break;\n default:\n if (!/^[0-9a-fA-F]$/.test(ch)) {\n return `invalid IFID hex value '${ch}' at position ${i + 1}`;\n }\n break;\n }\n }\n\n return null;\n}\n","/**\n * HTML, attribute, tiddler, and twee escaping/unescaping utilities.\n * Ported from escaping.go.\n */\n\n/** Escape the minimum characters required for HTML attribute values. */\nexport function attrEscape(s: string): string {\n if (s.length === 0) return s;\n return s.replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/'/g, '&#39;');\n}\n\n/** Escape for HTML attribute values including < and > (for spec-compliant output). */\nexport function fullAttrEscape(s: string): string {\n if (s.length === 0) return s;\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\n/** Escape the minimum characters required for general HTML content. */\nexport function htmlEscape(s: string): string {\n if (s.length === 0) return s;\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\n/** Escape for Twine 1 tiddler format. */\nexport function tiddlerEscape(s: string): string {\n if (s.length === 0) return s;\n return s\n .replace(/\\\\/g, '\\\\s')\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/\\t/g, '\\\\t')\n .replace(/\\n/g, '\\\\n');\n}\n\n/** Unescape from Twine 1 tiddler format. */\nexport function tiddlerUnescape(s: string): string {\n if (s.length === 0) return s;\n return s.replace(/\\\\n/g, '\\n').replace(/\\\\t/g, '\\t').replace(/\\\\s/g, '\\\\');\n}\n\n/** Escape characters that are special in Twee passage names/tags. */\nexport function tweeEscape(s: string): string {\n if (s.length === 0) return s;\n return s.replace(/[\\\\[\\]{}]/g, (ch) => '\\\\' + ch);\n}\n\n/** Escape a string for safe inclusion in a JavaScript string literal. */\nexport function jsStringEscape(s: string): string {\n if (s.length === 0) return s;\n return s\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/'/g, \"\\\\'\")\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n}\n\n/** Sanitize a string for safe inclusion in a CSS or JS block comment. */\nexport function commentSanitize(s: string): string {\n return s.replace(/\\*\\//g, '* /');\n}\n\n/** Sanitize a string for safe inclusion in an HTML comment. */\nexport function htmlCommentSanitize(s: string): string {\n return s.replace(/-->/g, '-- >');\n}\n\n/** Apply ROT13 encoding to a string (only affects [A-Za-z]). */\nexport function rot13(s: string): string {\n if (s.length === 0) return s;\n return s.replace(/[A-Za-z]/g, (ch) => {\n const base = ch <= 'Z' ? 65 : 97;\n return String.fromCharCode(((ch.charCodeAt(0) - base + 13) % 26) + base);\n });\n}\n\n/** Unescape backslash-escaped Twee characters. */\nexport function tweeUnescape(s: string): string {\n if (s.length === 0) return s;\n let result = '';\n for (let i = 0; i < s.length; i++) {\n if (s[i] === '\\\\') {\n i++;\n if (i >= s.length) {\n result += '\\\\';\n break;\n }\n }\n result += s[i];\n }\n return result;\n}\n","/**\n * Passage helpers and output methods.\n * Ported from passage.go / passagedata.go.\n */\nimport type { Passage, PassageMetadata, OutputMode } from './types.js';\nimport { attrEscape, fullAttrEscape, htmlEscape, tiddlerEscape, tweeEscape, rot13, commentSanitize } from './escape.js';\n\n// Info passages contain structural data, metadata, and code rather than story content.\nconst INFO_PASSAGE_NAMES = new Set([\n 'StoryAuthor',\n 'StoryInit',\n 'StoryMenu',\n 'StorySubtitle',\n 'StoryTitle',\n 'PassageReady',\n 'PassageDone',\n 'PassageHeader',\n 'PassageFooter',\n 'StoryBanner',\n 'StoryCaption',\n 'MenuOptions',\n 'MenuShare',\n 'MenuStory',\n 'StoryInterface',\n 'StoryShare',\n 'StorySettings',\n 'StoryData',\n 'StoryIncludes',\n]);\n\nconst INFO_TAGS = ['annotation', 'script', 'stylesheet', 'widget'];\n\nexport function hasTag(p: Passage, tag: string): boolean {\n return p.tags.includes(tag);\n}\n\nexport function hasAnyTag(p: Passage, ...tags: string[]): boolean {\n return p.tags.some((t) => tags.includes(t));\n}\n\nexport function hasTagStartingWith(p: Passage, prefix: string): boolean {\n return p.tags.some((t) => t.startsWith(prefix));\n}\n\nexport function hasInfoTags(p: Passage): boolean {\n return hasAnyTag(p, ...INFO_TAGS) || hasTagStartingWith(p, 'Twine.');\n}\n\nexport function hasInfoName(p: Passage): boolean {\n return INFO_PASSAGE_NAMES.has(p.name);\n}\n\nexport function isInfoPassage(p: Passage): boolean {\n return hasInfoName(p) || hasInfoTags(p);\n}\n\nexport function isStoryPassage(p: Passage): boolean {\n return !hasInfoName(p) && !hasInfoTags(p);\n}\n\nexport function hasMetadataPosition(p: Passage): boolean {\n return p.metadata != null && p.metadata.position != null && p.metadata.position !== '';\n}\n\nexport function hasMetadataSize(p: Passage): boolean {\n return p.metadata != null && p.metadata.size != null && p.metadata.size !== '';\n}\n\nexport function hasAnyMetadata(p: Passage): boolean {\n if (!p.metadata) return false;\n return Object.values(p.metadata).some((v) => v != null && v !== '');\n}\n\nexport function marshalMetadata(meta: PassageMetadata): string {\n const obj: Record<string, string> = {};\n for (const [key, value] of Object.entries(meta)) {\n if (typeof value === 'string' && value) obj[key] = value;\n }\n return JSON.stringify(obj);\n}\n\nexport function unmarshalMetadata(json: string): PassageMetadata {\n const raw: unknown = JSON.parse(json);\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n return {};\n }\n const parsed = raw as Record<string, unknown>;\n const meta: PassageMetadata = {};\n for (const [key, value] of Object.entries(parsed)) {\n if (typeof value === 'string') meta[key] = value;\n }\n return meta;\n}\n\n/** Convert passage to Twee source. */\nexport function passageToTwee(p: Passage, outMode: OutputMode): string {\n let output: string;\n if (outMode === 'twee3') {\n output = ':: ' + tweeEscape(p.name);\n if (p.tags.length > 0) {\n output += ' [' + tweeEscape(p.tags.join(' ')) + ']';\n }\n if (hasAnyMetadata(p) && p.metadata) {\n output += ' ' + marshalMetadata(p.metadata);\n }\n } else {\n output = ':: ' + p.name;\n if (p.tags.length > 0) {\n output += ' [' + p.tags.join(' ') + ']';\n }\n }\n output += '\\n';\n if (p.text.length > 0) {\n output += p.text + '\\n';\n }\n output += '\\n\\n';\n return output;\n}\n\n/** Generate `<tw-passagedata>` HTML for Twine 2. */\nexport function passageToPassagedata(p: Passage, pid: number): string {\n let position: string;\n let size: string;\n\n if (hasMetadataPosition(p)) {\n position = p.metadata?.position ?? '';\n } else {\n const x = pid % 10;\n const y = Math.floor(pid / 10);\n const xp = x === 0 ? 10 : x;\n const yp = x === 0 ? y : y + 1;\n position = `${xp * 125 - 25},${yp * 125 - 25}`;\n }\n\n if (hasMetadataSize(p)) {\n size = p.metadata?.size ?? '';\n } else {\n size = '100,100';\n }\n\n return `<tw-passagedata pid=\"${pid}\" name=${quote(fullAttrEscape(p.name))} tags=${quote(attrEscape(p.tags.join(' ')))} position=${quote(attrEscape(position))} size=${quote(attrEscape(size))}>${htmlEscape(p.text)}</tw-passagedata>`;\n}\n\n/** Generate `<div tiddler>` HTML for Twine 1. */\nexport function passageToTiddler(p: Passage, pid: number, obfuscateRot13 = false): string {\n let position: string;\n\n if (hasMetadataPosition(p)) {\n position = p.metadata?.position ?? '';\n } else {\n const x = pid % 10;\n const y = Math.floor(pid / 10);\n const xp = x === 0 ? 10 : x;\n const yp = x === 0 ? y : y + 1;\n position = `${xp * 140 - 130},${yp * 140 - 130}`;\n }\n\n const created = new Date().toISOString().replace(/[-:T]/g, '').slice(0, 12);\n const content = obfuscateRot13 && p.name !== 'StorySettings' ? tiddlerEscape(rot13(p.text)) : tiddlerEscape(p.text);\n const nameComment = obfuscateRot13 ? `<!-- ${commentSanitize(p.name)} -->` : '';\n return `<div tiddler=${quote(attrEscape(p.name))} tags=${quote(attrEscape(p.tags.join(' ')))} created=${quote(created)} modifier=${quote('twee')} twine-position=${quote(attrEscape(position))}>${nameComment}${content}</div>`;\n}\n\n/**\n * Count words in a passage using the Tweego method:\n * Strip newlines, strip comments, count NFKD-normalized characters, divide by 5.\n */\nexport function countWords(p: Passage): number {\n let text = p.text;\n text = text.replace(/\\n/g, '');\n text = text.replace(/(?:\\/%.+?%\\/|\\/\\*.+?\\*\\/|<!--.+?-->)/gs, '');\n // Normalize to NFKD and count characters\n const normalized = text.normalize('NFKD');\n const count = [...normalized].length;\n if (count === 0) return 0;\n const words = Math.floor(count / 5);\n return count % 5 > 0 ? words + 1 : words;\n}\n\n/**\n * Apply tag aliases: for each passage carrying an alias tag, add the canonical\n * tag if not already present. Returns new passage objects where tags changed;\n * unchanged passages are returned as-is. Idempotent — safe to call multiple times.\n */\nexport function applyTagAliases(passages: readonly Passage[], aliases: Record<string, string>): Passage[] {\n const entries = Object.entries(aliases);\n if (entries.length === 0) return [...passages];\n return passages.map((p) => {\n const original = p.tags;\n const added: string[] = [];\n for (const [alias, canonical] of entries) {\n if (original.includes(alias) && !original.includes(canonical) && !added.includes(canonical)) {\n added.push(canonical);\n }\n }\n return added.length > 0 ? { ...p, tags: [...original, ...added] } : p;\n });\n}\n\nfunction quote(s: string): string {\n return `\"${s}\"`;\n}\n","/**\n * Story model + StoryData JSON marshal/unmarshal.\n * Ported from story.go + storydata.go.\n */\nimport type { Story, Passage, Diagnostic } from './types.js';\nimport { validateIFID } from './ifid.js';\nimport { isStoryPassage, countWords } from './passage.js';\n\nexport function createStory(): Story {\n return {\n name: '',\n ifid: '',\n passages: [],\n legacyIFID: '',\n twine1: { settings: new Map() },\n twine2: {\n format: '',\n formatVersion: '',\n options: new Map(),\n start: '',\n tags: '',\n tagColors: new Map(),\n zoom: 1,\n },\n };\n}\n\nexport function storyHas(story: Story, name: string): boolean {\n return story.passages.some((p) => p.name === name);\n}\n\nexport function storyIndex(story: Story, name: string): number {\n return story.passages.findIndex((p) => p.name === name);\n}\n\nexport function storyGet(story: Story, name: string): Passage | undefined {\n return story.passages.find((p) => p.name === name);\n}\n\nexport function storyAppend(story: Story, p: Passage, diagnostics: Diagnostic[]): void {\n const i = storyIndex(story, p.name);\n if (i === -1) {\n story.passages.push(p);\n } else {\n diagnostics.push({\n level: 'warning',\n message: `Replacing existing passage \"${p.name}\" with duplicate.`,\n });\n story.passages[i] = p;\n }\n}\n\nexport function storyPrepend(story: Story, p: Passage, diagnostics: Diagnostic[]): void {\n const i = storyIndex(story, p.name);\n if (i === -1) {\n story.passages.unshift(p);\n } else {\n diagnostics.push({\n level: 'warning',\n message: `Replacing existing passage \"${p.name}\" with duplicate.`,\n });\n story.passages[i] = p;\n }\n}\n\n// --- StoryData JSON ---\n\ninterface StoryDataJSON {\n ifid?: string;\n format?: string;\n 'format-version'?: string;\n options?: string[];\n start?: string;\n tags?: string;\n 'tag-colors'?: Record<string, string>;\n zoom?: number;\n}\n\nexport function marshalStoryData(story: Story): string {\n const data: StoryDataJSON = {};\n if (story.ifid) data.ifid = story.ifid;\n if (story.twine2.format) data.format = story.twine2.format;\n if (story.twine2.formatVersion) data['format-version'] = story.twine2.formatVersion;\n\n const options: string[] = [];\n for (const [opt, val] of story.twine2.options) {\n if (val) options.push(opt);\n }\n if (options.length > 0) data.options = options;\n\n if (story.twine2.start) data.start = story.twine2.start;\n if (story.twine2.tags) data.tags = story.twine2.tags;\n\n if (story.twine2.tagColors.size > 0) {\n data['tag-colors'] = Object.fromEntries(story.twine2.tagColors);\n }\n if (story.twine2.zoom !== 1) data.zoom = story.twine2.zoom;\n\n return JSON.stringify(data, null, '\\t');\n}\n\nexport function unmarshalStoryData(story: Story, json: string): string | null {\n let raw: unknown;\n try {\n raw = JSON.parse(json) as unknown;\n } catch (e) {\n return `Cannot unmarshal \"StoryData\"; ${e instanceof Error ? e.message : String(e)}`;\n }\n\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n return 'Cannot unmarshal \"StoryData\"; expected a JSON object';\n }\n const data = raw as StoryDataJSON;\n\n if (typeof data.ifid === 'string' && data.ifid) story.ifid = data.ifid.toUpperCase();\n if (typeof data.format === 'string' && data.format) story.twine2.format = data.format;\n if (typeof data['format-version'] === 'string' && data['format-version'])\n story.twine2.formatVersion = data['format-version'];\n if (Array.isArray(data.options)) {\n for (const opt of data.options) {\n if (typeof opt === 'string') story.twine2.options.set(opt, true);\n }\n }\n if (typeof data.start === 'string' && data.start) story.twine2.start = data.start;\n if (typeof data.tags === 'string') story.twine2.tags = data.tags;\n if (typeof data['tag-colors'] === 'object' && data['tag-colors'] !== null && !Array.isArray(data['tag-colors'])) {\n for (const [tag, color] of Object.entries(data['tag-colors'])) {\n if (typeof color === 'string') story.twine2.tagColors.set(tag, color);\n }\n }\n if (typeof data.zoom === 'number' && data.zoom !== 0) story.twine2.zoom = data.zoom;\n\n return null;\n}\n\n// --- StorySettings (legacy) ---\n\nexport function unmarshalStorySettings(story: Story, text: string, diagnostics: Diagnostic[]): void {\n const obsolete: string[] = [];\n\n for (const rawLine of text.split('\\n')) {\n const line = rawLine.trim();\n if (line.length === 0) continue;\n\n const colonIdx = line.indexOf(':');\n if (colonIdx === -1) {\n diagnostics.push({\n level: 'warning',\n message: `Malformed \"StorySettings\" entry; skipping \"${line}\".`,\n });\n continue;\n }\n\n const key = line.slice(0, colonIdx).trim().toLowerCase();\n const val = line\n .slice(colonIdx + 1)\n .trim()\n .toLowerCase();\n\n switch (key) {\n case 'ifid': {\n const err = validateIFID(val);\n if (err === null) {\n story.legacyIFID = val.toUpperCase();\n }\n obsolete.push('\"ifid\"');\n continue;\n }\n case 'zoom':\n obsolete.push('\"zoom\"');\n continue;\n }\n\n story.twine1.settings.set(key, val);\n }\n\n if (obsolete.length > 0) {\n const entries = obsolete.length === 1 ? 'entry' : 'entries';\n const pronoun = obsolete.length === 1 ? 'it' : 'them';\n diagnostics.push({\n level: 'warning',\n message:\n `Detected obsolete \"StorySettings\" ${entries}: ${obsolete.join(', ')}. ` +\n `Please remove ${pronoun} from the \"StorySettings\" special passage.`,\n });\n }\n}\n\n/**\n * Process a passage and add it to the story, handling special passages.\n * Creates new passage objects where text is modified rather than mutating the input.\n */\nexport function storyAdd(story: Story, p: Passage, diagnostics: Diagnostic[]): void {\n let processed = p;\n\n switch (p.name) {\n case 'StoryIncludes':\n diagnostics.push({\n level: 'warning',\n message:\n 'Ignoring \"StoryIncludes\" compiler special passage; twee-ts allows you to specify project files and/or directories to recursively search.',\n });\n break;\n\n case 'StoryData': {\n const err = unmarshalStoryData(story, p.text);\n if (err === null) {\n // Validate the IFID if present.\n if (story.ifid.length > 0) {\n const vErr = validateIFID(story.ifid);\n if (vErr !== null) {\n diagnostics.push({\n level: 'error',\n message: `Cannot validate IFID; ${vErr}.`,\n });\n }\n }\n // Rebuild passage contents to normalize.\n processed = { ...p, text: marshalStoryData(story) };\n } else {\n diagnostics.push({\n level: 'warning',\n message: `Cannot unmarshal \"StoryData\" compiler special passage; ${err}.`,\n });\n }\n break;\n }\n\n case 'StorySettings':\n unmarshalStorySettings(story, p.text, diagnostics);\n break;\n\n case 'StoryTitle': {\n const trimmed = p.text.trim();\n processed = { ...p, text: trimmed };\n story.name = trimmed;\n break;\n }\n }\n\n storyAppend(story, processed, diagnostics);\n}\n\n/** Get story passage count and word count stats. */\nexport function getStoryStats(story: Story): { passages: number; storyPassages: number; words: number } {\n let storyPassages = 0;\n let words = 0;\n for (const p of story.passages) {\n if (isStoryPassage(p)) {\n storyPassages++;\n words += countWords(p);\n }\n }\n return { passages: story.passages.length, storyPassages, words };\n}\n","/**\n * File system utilities: path walking, file type detection, watch mode.\n * Ported from filesystem.go.\n */\nimport { readdirSync, statSync, watch as fsWatch } from 'node:fs';\nimport { resolve, relative, join } from 'node:path';\nimport { isKnownFileType } from './media-types.js';\n\n/**\n * Recursively walk directories, collecting regular file paths.\n * Filters out the output file to prevent circular compilation.\n */\nexport function getFilenames(pathnames: string[], outFilename?: string): string[] {\n const filenames: string[] = [];\n const absOutFile = outFilename ? resolve(outFilename) : '';\n\n function walk(pathname: string): void {\n let stat;\n try {\n stat = statSync(pathname);\n } catch {\n return;\n }\n\n if (stat.isFile()) {\n const abs = resolve(pathname);\n if (abs === absOutFile) return;\n const rel = relative(process.cwd(), abs);\n filenames.push(rel || abs);\n } else if (stat.isDirectory()) {\n let entries;\n try {\n entries = readdirSync(pathname);\n } catch {\n return;\n }\n for (const entry of entries) {\n walk(join(pathname, entry));\n }\n }\n }\n\n for (const pathname of pathnames) {\n walk(pathname);\n }\n\n return filenames;\n}\n\nexport interface WatchHandle {\n close(): void;\n}\n\n/**\n * Watch paths for changes, calling the build callback on known file type changes.\n * Uses debouncing to avoid rapid rebuilds.\n */\nexport function watchFilesystem(pathnames: string[], outFilename: string, callback: () => void): WatchHandle {\n const absOutFile = resolve(outFilename);\n const watchers: ReturnType<typeof fsWatch>[] = [];\n let buildTimer: ReturnType<typeof setTimeout> | null = null;\n const BUILD_DEBOUNCE = 500;\n\n function scheduleBuild(): void {\n if (buildTimer) clearTimeout(buildTimer);\n buildTimer = setTimeout(() => {\n buildTimer = null;\n callback();\n }, BUILD_DEBOUNCE);\n }\n\n for (const pathname of pathnames) {\n try {\n const watcher = fsWatch(pathname, { recursive: true }, (_event, filename) => {\n if (!filename) return;\n const abs = resolve(pathname, filename);\n if (abs === absOutFile) return;\n if (isKnownFileType(filename)) {\n scheduleBuild();\n }\n });\n watchers.push(watcher);\n } catch {\n // Ignore inaccessible paths\n }\n }\n\n // Build once initially.\n callback();\n\n return {\n close() {\n if (buildTimer) clearTimeout(buildTimer);\n for (const w of watchers) w.close();\n },\n };\n}\n","/**\n * Extension → MIME type mapping.\n * Ported from util.go:mediaTypeFromExt().\n */\n\nimport { extname } from 'node:path';\n\nconst MEDIA_TYPE_MAP: Record<string, string> = {\n // Audio\n aac: 'audio/aac',\n flac: 'audio/flac',\n ogg: 'audio/ogg',\n wav: 'audio/wav',\n mp3: 'audio/mpeg',\n m4a: 'audio/mp4',\n oga: 'audio/ogg',\n opus: 'audio/ogg',\n wave: 'audio/wav',\n weba: 'audio/webm',\n\n // Fonts\n otf: 'font/otf',\n ttf: 'font/ttf',\n woff: 'font/woff',\n woff2: 'font/woff2',\n\n // Images\n gif: 'image/gif',\n jpeg: 'image/jpeg',\n jpg: 'image/jpeg',\n png: 'image/png',\n svg: 'image/svg+xml',\n tif: 'image/tiff',\n tiff: 'image/tiff',\n webp: 'image/webp',\n\n // Metadata\n vtt: 'text/vtt',\n\n // Video\n mp4: 'video/mp4',\n ogv: 'video/ogg',\n webm: 'video/webm',\n};\n\nexport function mediaTypeFromExt(ext: string): string {\n return MEDIA_TYPE_MAP[ext] ?? 'application/octet-stream';\n}\n\nexport function mediaTypeFromFilename(filename: string): string {\n return mediaTypeFromExt(normalizedFileExt(filename));\n}\n\nexport function normalizedFileExt(filename: string): string {\n const ext = extname(filename);\n if (!ext) return '';\n return ext.slice(1).toLowerCase();\n}\n\n/** Slugify a string for safe use as a DOM ID. */\nexport function slugify(original: string): string {\n return original.replace(/[\\x00-\\x20!-/:-@[-^`{-\\x9f]+/g, '_');\n}\n\n/** Check if a file has a known type that should be processed. */\nexport function isKnownFileType(filename: string): boolean {\n const ext = normalizedFileExt(filename);\n return KNOWN_EXTENSIONS.has(ext);\n}\n\nconst KNOWN_EXTENSIONS = new Set([\n 'tw',\n 'twee',\n 'tw2',\n 'twee2',\n 'css',\n 'js',\n 'otf',\n 'ttf',\n 'woff',\n 'woff2',\n 'gif',\n 'jpeg',\n 'jpg',\n 'png',\n 'svg',\n 'tif',\n 'tiff',\n 'webp',\n 'aac',\n 'flac',\n 'm4a',\n 'mp3',\n 'oga',\n 'ogg',\n 'opus',\n 'wav',\n 'wave',\n 'weba',\n 'mp4',\n 'ogv',\n 'webm',\n 'vtt',\n]);\n\n/** Font format hint for @font-face. */\nexport function fontFormatHint(ext: string): string {\n switch (ext) {\n case 'ttf':\n return 'truetype';\n case 'otf':\n return 'opentype';\n default:\n return ext;\n }\n}\n","/**\n * Story format discovery, loading, and SemVer matching.\n * Ported from formats.go + config.go.\n */\nimport { readdirSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { StoryFormatInfo, Twine2FormatJSON } from './types.js';\nimport { readUTF8 } from './util.js';\n\n/**\n * Attempt to fix non-strict JSON (trailing commas, single quotes, unquoted keys).\n */\nfunction relaxedJSONParse(json: string): unknown {\n // First try standard parse\n try {\n return JSON.parse(json);\n } catch {\n // fall through to relaxed parsing\n }\n\n let fixed = json;\n\n // Replace single-quoted string values with double-quoted\n // Match single-quoted strings: 'value' -> \"value\"\n fixed = fixed.replace(/'([^'\\\\]*(?:\\\\.[^'\\\\]*)*)'/g, '\"$1\"');\n\n // Add quotes around unquoted property names\n // Match word chars before a colon that aren't already quoted\n fixed = fixed.replace(/(?<=^|[{,]\\s*)([A-Za-z_$][A-Za-z0-9_$]*)\\s*:/gm, '\"$1\":');\n\n // Remove trailing commas before } or ]\n fixed = fixed.replace(/,\\s*([}\\]])/g, '$1');\n\n return JSON.parse(fixed);\n}\n\n/**\n * Parse the Twine 2 format.js JSON chunk.\n * Handles Harlowe's malformed JSON by stripping the \"setup\" function property.\n * Per spec, the name key is Optional.\n */\nexport function parseFormatJSON(source: string, formatId: string): Twine2FormatJSON | null {\n const first = source.indexOf('{');\n const last = source.lastIndexOf('}');\n if (first === -1 || last === -1) return null;\n\n let chunk = source.slice(first, last + 1);\n\n const parse = (json: string): Twine2FormatJSON | null => {\n const raw: unknown = relaxedJSONParse(json);\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) return null;\n const obj = raw as Record<string, unknown>;\n // version and source are required; name is optional per spec\n if (typeof obj.version !== 'string' || typeof obj.source !== 'string') return null;\n // Validate version is semver\n if (!parseSemver(obj.version)) return null;\n const name = typeof obj.name === 'string' ? obj.name : 'Untitled Story Format';\n const result: Twine2FormatJSON = {\n name,\n version: obj.version,\n source: obj.source,\n proofing: obj.proofing === true,\n };\n if (typeof obj.author === 'string') result.author = obj.author;\n if (typeof obj.description === 'string') result.description = obj.description;\n if (typeof obj.image === 'string') result.image = obj.image;\n if (typeof obj.url === 'string') result.url = obj.url;\n if (typeof obj.license === 'string') result.license = obj.license;\n return result;\n };\n\n try {\n return parse(chunk);\n } catch {\n // Harlowe workaround: strip the \"setup\" function property\n if (formatId.toLowerCase().startsWith('harlowe')) {\n const setupIdx = chunk.lastIndexOf(',\"setup\": function');\n if (setupIdx !== -1) {\n chunk = chunk.slice(0, setupIdx) + '}';\n try {\n return parse(chunk);\n } catch {\n // fall through\n }\n }\n }\n return null;\n }\n}\n\n/**\n * Discover all story formats in the given search directories.\n * Implements SemVer-based version pruning: within each (name, major) group,\n * only the highest minor.patch survives.\n */\nexport function discoverFormats(searchDirs: string[]): Map<string, StoryFormatInfo> {\n const formats = new Map<string, StoryFormatInfo>();\n const baseFilenames = ['format.js', 'header.html'];\n\n for (const searchDir of searchDirs) {\n try {\n const stat = statSync(searchDir);\n if (!stat.isDirectory()) continue;\n } catch {\n continue;\n }\n\n let entries;\n try {\n entries = readdirSync(searchDir);\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n const formatDir = join(searchDir, entry);\n try {\n if (!statSync(formatDir).isDirectory()) continue;\n } catch {\n continue;\n }\n\n for (const baseFilename of baseFilenames) {\n const formatFilename = join(formatDir, baseFilename);\n try {\n const stat = statSync(formatFilename);\n if (!stat.isFile()) continue;\n } catch {\n continue;\n }\n\n const isTwine2 = baseFilename === 'format.js';\n const format: StoryFormatInfo = {\n id: entry,\n filename: formatFilename,\n isTwine2,\n name: '',\n version: '',\n proofing: false,\n };\n\n if (isTwine2) {\n try {\n const source = readUTF8(formatFilename);\n const data = parseFormatJSON(source, entry);\n if (!data) continue;\n format.name = data.name;\n format.version = data.version;\n format.proofing = data.proofing ?? false;\n if (data.author) format.author = data.author;\n if (data.description) format.description = data.description;\n if (data.image) format.image = data.image;\n if (data.url) format.url = data.url;\n if (data.license) format.license = data.license;\n } catch {\n continue;\n }\n } else {\n // Twine 1 format: use folder name as default name\n format.name = entry;\n }\n\n formats.set(entry, format);\n break; // Found format file for this directory\n }\n }\n }\n\n // SemVer pruning: for formats with the same name, within each major version\n // keep only the highest minor.patch. Also, same name+version from different\n // directories: keep the first one found.\n pruneFormats(formats);\n\n return formats;\n}\n\n/**\n * Prune formats by SemVer: within each (name, major) group,\n * keep only the highest version. First-found wins for same name+version.\n */\nfunction pruneFormats(formats: Map<string, StoryFormatInfo>): void {\n // Group by (name, major) -> best entry\n const bestByNameMajor = new Map<string, { id: string; version: [number, number, number] }>();\n // Track seen name+version combos (first wins)\n const seenNameVersion = new Set<string>();\n\n for (const [id, f] of formats) {\n if (!f.isTwine2 || !f.name || !f.version) continue;\n const v = parseSemver(f.version);\n if (!v) continue;\n\n const nameVersionKey = `${f.name}@${f.version}`;\n if (seenNameVersion.has(nameVersionKey)) {\n // Duplicate name+version: remove the later one\n formats.delete(id);\n continue;\n }\n seenNameVersion.add(nameVersionKey);\n\n const groupKey = `${f.name}@${v[0]}`;\n const existing = bestByNameMajor.get(groupKey);\n if (!existing || semverCompare(v, existing.version) > 0) {\n bestByNameMajor.set(groupKey, { id, version: v });\n }\n }\n\n // Remove all non-best entries within each group\n for (const [id, f] of [...formats]) {\n if (!f.isTwine2 || !f.name || !f.version) continue;\n const v = parseSemver(f.version);\n if (!v) continue;\n\n const groupKey = `${f.name}@${v[0]}`;\n const best = bestByNameMajor.get(groupKey);\n if (best && best.id !== id) {\n formats.delete(id);\n }\n }\n}\n\n/**\n * Get the default format search directories.\n */\nexport function getFormatSearchDirs(extraPaths: string[] = [], useTweegoPath = true): string[] {\n const subdirNames = ['storyformats', '.storyformats', 'story-formats', 'storyFormats', 'targets'];\n const basePaths = new Set<string>();\n\n // Home directory\n try {\n basePaths.add(homedir());\n } catch {\n // ignore\n }\n\n // Working directory\n basePaths.add(process.cwd());\n\n const dirs: string[] = [];\n for (const base of basePaths) {\n for (const sub of subdirNames) {\n const dir = join(base, sub);\n try {\n if (statSync(dir).isDirectory()) {\n dirs.push(dir);\n }\n } catch {\n // skip\n }\n }\n }\n\n // Extra user-provided paths\n dirs.push(...extraPaths);\n\n // TWEEGO_PATH environment variable\n if (useTweegoPath) {\n const tweegoPath = process.env.TWEEGO_PATH;\n if (tweegoPath) {\n dirs.push(...tweegoPath.split(process.platform === 'win32' ? ';' : ':'));\n }\n }\n\n return dirs;\n}\n\n/** Parse a simple semver string into [major, minor, patch]. */\nexport function parseSemver(v: string): [number, number, number] | null {\n const m = /^(\\d+)\\.(\\d+)\\.(\\d+)/.exec(v);\n if (!m) return null;\n return [Number(m[1]), Number(m[2]), Number(m[3])];\n}\n\nexport function semverCompare(a: [number, number, number], b: [number, number, number]): number {\n const [aMajor, aMinor, aPatch] = a;\n const [bMajor, bMinor, bPatch] = b;\n if (aMajor !== bMajor) return aMajor - bMajor;\n if (aMinor !== bMinor) return aMinor - bMinor;\n if (aPatch !== bPatch) return aPatch - bPatch;\n return 0;\n}\n\n/** Get format ID from Twine 2 name, picking the greatest version. */\nexport function getFormatIdByName(formats: Map<string, StoryFormatInfo>, name: string): string | undefined {\n let bestVersion: [number, number, number] | null = null;\n let bestId: string | undefined;\n\n for (const [id, f] of formats) {\n if (!f.isTwine2 || f.name !== name) continue;\n const v = parseSemver(f.version);\n if (!v) continue;\n if (!bestVersion || semverCompare(v, bestVersion) > 0) {\n bestVersion = v;\n bestId = id;\n }\n }\n\n return bestId;\n}\n\n/** Get format ID from Twine 2 name and version, using SemVer major matching. */\nexport function getFormatIdByNameAndVersion(\n formats: Map<string, StoryFormatInfo>,\n name: string,\n version: string,\n): string | undefined {\n const wanted = parseSemver(version);\n let bestVersion: [number, number, number] | null = null;\n let bestId: string | undefined;\n\n for (const [id, f] of formats) {\n if (!f.isTwine2 || f.name !== name) continue;\n const have = parseSemver(f.version);\n if (!have) continue;\n\n if (wanted === null || (have[0] === wanted[0] && semverCompare(have, wanted) >= 0)) {\n if (!bestVersion || semverCompare(have, bestVersion) > 0) {\n bestVersion = have;\n bestId = id;\n }\n }\n }\n\n return bestId;\n}\n\n/** Read the story format source (for Twine 2, extract the `source` property from JSON). */\nexport function readFormatSource(format: StoryFormatInfo): string {\n const source = readUTF8(format.filename);\n if (format.isTwine2) {\n const data = parseFormatJSON(source, format.id);\n if (!data) throw new Error(`Cannot parse format ${format.id} JSON`);\n return data.source;\n }\n return source;\n}\n\n/** Read a file as UTF-8 (re-exported for loader use). */\nexport { readUTF8 as readFileUTF8 } from './util.js';\n","/**\n * Shared file I/O utilities.\n */\nimport { readFileSync } from 'node:fs';\nimport { parse as parsePath } from 'node:path';\n\n/** Read a file as UTF-8 with BOM stripping and line ending normalization. */\nexport function readUTF8(filename: string): string {\n let content = readFileSync(filename, 'utf-8');\n if (content.charCodeAt(0) === 0xfeff) content = content.slice(1);\n content = content.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n return content;\n}\n\n/** Read a file as base64. */\nexport function readBase64(filename: string): string {\n return readFileSync(filename).toString('base64');\n}\n\n/** Get the filename without extension, falling back to the full basename for dotfiles. */\nexport function baseNameWithoutExt(filename: string): string {\n const { name, ext } = parsePath(filename);\n return name || ext;\n}\n","/**\n * File loading: dispatch by file extension.\n * Ported from storyload.go.\n */\nimport { basename } from 'node:path';\nimport type { Story, Diagnostic, InlineSource } from './types.js';\nimport { normalizedFileExt, mediaTypeFromFilename, mediaTypeFromExt, fontFormatHint } from './media-types.js';\nimport { storyAdd, storyPrepend } from './story.js';\nimport { parseTwee } from './parser.js';\nimport { readUTF8, readBase64, baseNameWithoutExt } from './util.js';\n\ninterface LoadOptions {\n trim?: boolean;\n twee2Compat?: boolean;\n}\n\n/**\n * Load all source files into a story.\n */\nexport function loadSources(\n story: Story,\n filenames: string[],\n opts: LoadOptions,\n diagnostics: Diagnostic[],\n processedFiles: Set<string>,\n): void {\n for (const filename of filenames) {\n if (processedFiles.has(filename)) {\n diagnostics.push({ level: 'warning', message: `load ${filename}: Skipping duplicate.` });\n continue;\n }\n\n const ext = normalizedFileExt(filename);\n try {\n switch (ext) {\n case 'tw':\n case 'twee':\n loadTwee(story, filename, opts, diagnostics);\n break;\n case 'tw2':\n case 'twee2':\n loadTwee(story, filename, { ...opts, twee2Compat: true }, diagnostics);\n break;\n case 'css':\n loadTagged(story, 'stylesheet', filename, diagnostics);\n break;\n case 'js':\n loadTagged(story, 'script', filename, diagnostics);\n break;\n case 'otf':\n case 'ttf':\n case 'woff':\n case 'woff2':\n loadFont(story, filename, diagnostics);\n break;\n case 'gif':\n case 'jpeg':\n case 'jpg':\n case 'png':\n case 'svg':\n case 'tif':\n case 'tiff':\n case 'webp':\n loadMedia(story, 'Twine.image', filename, diagnostics);\n break;\n case 'aac':\n case 'flac':\n case 'm4a':\n case 'mp3':\n case 'oga':\n case 'ogg':\n case 'opus':\n case 'wav':\n case 'wave':\n case 'weba':\n loadMedia(story, 'Twine.audio', filename, diagnostics);\n break;\n case 'mp4':\n case 'ogv':\n case 'webm':\n loadMedia(story, 'Twine.video', filename, diagnostics);\n break;\n case 'vtt':\n loadMedia(story, 'Twine.vtt', filename, diagnostics);\n break;\n default:\n continue;\n }\n } catch (e) {\n diagnostics.push({\n level: 'error',\n message: `load ${filename}: ${e instanceof Error ? e.message : String(e)}`,\n file: filename,\n });\n continue;\n }\n processedFiles.add(filename);\n }\n\n // Prepend StoryTitle if we have a name but no StoryTitle passage.\n if (story.name !== '' && !story.passages.some((p) => p.name === 'StoryTitle')) {\n storyPrepend(story, { name: 'StoryTitle', tags: [], text: story.name }, diagnostics);\n }\n}\n\n/**\n * Load inline sources (string content or InlineSource objects).\n */\nexport function loadInlineSources(\n story: Story,\n sources: (string | InlineSource)[],\n opts: LoadOptions,\n diagnostics: Diagnostic[],\n): void {\n for (const source of sources) {\n if (typeof source === 'string') {\n // Treat as a file path — handled externally\n continue;\n }\n const content = typeof source.content === 'string' ? source.content : source.content.toString('utf-8');\n\n const ext = normalizedFileExt(source.filename);\n if (ext === 'tw' || ext === 'twee' || ext === 'tw2' || ext === 'twee2' || !ext) {\n const twee2 = ext === 'tw2' || ext === 'twee2' || opts.twee2Compat;\n const result = parseTwee(content, {\n filename: source.filename,\n trim: opts.trim ?? true,\n twee2Compat: twee2,\n });\n diagnostics.push(...result.diagnostics);\n for (const p of result.passages) {\n storyAdd(story, p, diagnostics);\n }\n }\n }\n}\n\nfunction loadTwee(story: Story, filename: string, opts: LoadOptions, diagnostics: Diagnostic[]): void {\n const source = readUTF8(filename);\n const result = parseTwee(source, {\n filename,\n trim: opts.trim ?? true,\n twee2Compat: opts.twee2Compat ?? false,\n });\n diagnostics.push(...result.diagnostics);\n for (const p of result.passages) {\n storyAdd(story, p, diagnostics);\n }\n}\n\nfunction loadTagged(story: Story, tag: string, filename: string, diagnostics: Diagnostic[]): void {\n const source = readUTF8(filename);\n storyAdd(story, { name: basename(filename), tags: [tag], text: source }, diagnostics);\n}\n\nfunction loadMedia(story: Story, tag: string, filename: string, diagnostics: Diagnostic[]): void {\n const source = readBase64(filename);\n const name = baseNameWithoutExt(filename);\n storyAdd(\n story,\n {\n name,\n tags: [tag],\n text: `data:${mediaTypeFromFilename(filename)};base64,${source}`,\n },\n diagnostics,\n );\n}\n\nfunction loadFont(story: Story, filename: string, diagnostics: Diagnostic[]): void {\n const source = readBase64(filename);\n const name = basename(filename);\n const family = baseNameWithoutExt(filename);\n const ext = normalizedFileExt(filename);\n const mediaType = mediaTypeFromExt(ext);\n const hint = fontFormatHint(ext);\n\n storyAdd(\n story,\n {\n name,\n tags: ['stylesheet'],\n text: `@font-face {\\n\\tfont-family: \"${family}\";\\n\\tsrc: url(\"data:${mediaType};base64,${source}\") format(\"${hint}\");\\n}`,\n },\n diagnostics,\n );\n}\n","/**\n * Twee 3 state-machine lexer implemented as a synchronous generator.\n * Ported from tweelexer.go — Go channels become `yield`.\n */\nimport type { LexerItem } from './types.js';\nimport { ItemType } from './types.js';\n\nconst EOF = -1;\nconst HEADER_DELIM = '::';\nconst NEWLINE_HEADER_DELIM = '\\n::';\n\ntype StateFn = ((ctx: LexerContext) => StateFn | null) | null;\n\nclass LexerContext {\n readonly input: string;\n line = 1;\n start = 0;\n pos = 0;\n private items: LexerItem[] = [];\n\n constructor(input: string) {\n this.input = input;\n }\n\n next(): number {\n if (this.pos >= this.input.length) return EOF;\n const ch = this.input.charCodeAt(this.pos);\n this.pos++;\n if (ch === 0x0a) this.line++;\n return ch;\n }\n\n peek(): number {\n if (this.pos >= this.input.length) return EOF;\n return this.input.charCodeAt(this.pos);\n }\n\n backup(): void {\n if (this.pos > this.start) {\n this.pos--;\n if (this.input.charCodeAt(this.pos) === 0x0a) this.line--;\n } else {\n throw new Error('backup would leave pos < start');\n }\n }\n\n emit(type: ItemType): void {\n const val = this.input.slice(this.start, this.pos);\n this.items.push({ type, line: this.line, pos: this.start, val });\n // Content items may contain newlines that must be counted.\n if (type === ItemType.Content) {\n for (let i = this.start; i < this.pos; i++) {\n if (this.input.charCodeAt(i) === 0x0a) this.line++;\n }\n }\n this.start = this.pos;\n }\n\n ignore(): void {\n for (let i = this.start; i < this.pos; i++) {\n if (this.input.charCodeAt(i) === 0x0a) this.line++;\n }\n this.start = this.pos;\n }\n\n acceptRun(valid: string): void {\n let ch: number;\n for (ch = this.next(); ch !== EOF && valid.includes(String.fromCharCode(ch)); ch = this.next()) {\n // consume\n }\n if (ch !== EOF) this.backup();\n }\n\n errorf(message: string): null {\n this.items.push({\n type: ItemType.Error,\n line: this.line,\n pos: this.start,\n val: message,\n });\n return null;\n }\n\n /** Drain all pending items and return them. */\n drainItems(): LexerItem[] {\n const result = this.items;\n this.items = [];\n return result;\n }\n}\n\nfunction acceptQuoted(ctx: LexerContext, quote: number): string | null {\n for (;;) {\n const ch = ctx.next();\n switch (ch) {\n case 0x5c: {\n // backslash\n const r = ctx.next();\n if (r !== 0x0a && r !== EOF) break;\n // fall through\n }\n // falls through\n case 0x0a:\n case EOF:\n return 'unterminated quoted string';\n default:\n if (ch === quote) return null;\n break;\n }\n }\n}\n\n// --- State functions ---\n\nfunction lexProlog(ctx: LexerContext): StateFn {\n if (ctx.input.startsWith(HEADER_DELIM, ctx.pos)) {\n return lexHeaderDelim;\n }\n const i = ctx.input.indexOf(NEWLINE_HEADER_DELIM, ctx.pos);\n if (i > -1) {\n ctx.pos = i + 1; // skip to the newline, then past it\n ctx.ignore();\n return lexHeaderDelim;\n }\n ctx.emit(ItemType.EOF);\n return null;\n}\n\nfunction lexContent(ctx: LexerContext): StateFn {\n if (ctx.input.startsWith(HEADER_DELIM, ctx.pos)) {\n return lexHeaderDelim;\n }\n const i = ctx.input.indexOf(NEWLINE_HEADER_DELIM, ctx.pos);\n if (i > -1) {\n ctx.pos = i + 1;\n ctx.emit(ItemType.Content);\n return lexHeaderDelim;\n }\n ctx.pos = ctx.input.length;\n if (ctx.pos > ctx.start) {\n ctx.emit(ItemType.Content);\n }\n ctx.emit(ItemType.EOF);\n return null;\n}\n\nfunction lexHeaderDelim(ctx: LexerContext): StateFn {\n ctx.pos += HEADER_DELIM.length;\n ctx.emit(ItemType.Header);\n return lexName;\n}\n\nfunction lexName(ctx: LexerContext): StateFn {\n let r: number;\n outer: for (;;) {\n r = ctx.next();\n switch (r) {\n case 0x5c: {\n // backslash\n const next = ctx.next();\n if (next !== 0x0a && next !== EOF) break;\n // fall through to terminators\n r = next;\n }\n // falls through\n case 0x5b: // [\n case 0x5d: // ]\n case 0x7b: // {\n case 0x7d: // }\n case 0x0a: // \\n\n case EOF:\n if (r !== EOF) ctx.backup();\n break outer;\n }\n }\n // Always emit a name item, even if empty.\n ctx.emit(ItemType.Name);\n\n switch (r) {\n case 0x5b:\n return lexTags; // [\n case 0x5d:\n return ctx.errorf(`unexpected right square bracket ']'`);\n case 0x7b:\n return lexMetadata; // {\n case 0x7d:\n return ctx.errorf(`unexpected right curly brace '}'`);\n case 0x0a: // newline\n ctx.pos++;\n ctx.ignore();\n return lexContent;\n }\n ctx.emit(ItemType.EOF);\n return null;\n}\n\nfunction lexNextOptionalBlock(ctx: LexerContext): StateFn {\n // Consume whitespace.\n ctx.acceptRun(' \\t');\n ctx.ignore();\n\n const r = ctx.peek();\n switch (r) {\n case 0x5b:\n return lexTags; // [\n case 0x5d:\n return ctx.errorf(`unexpected right square bracket ']'`);\n case 0x7b:\n return lexMetadata; // {\n case 0x7d:\n return ctx.errorf(`unexpected right curly brace '}'`);\n case 0x0a: // newline\n ctx.pos++;\n ctx.ignore();\n return lexContent;\n case EOF:\n ctx.emit(ItemType.EOF);\n return null;\n }\n return ctx.errorf(`illegal character '${String.fromCharCode(r)}' amid the optional blocks`);\n}\n\nfunction lexTags(ctx: LexerContext): StateFn {\n // Consume the left delimiter '['.\n ctx.pos++;\n\n for (;;) {\n const r = ctx.next();\n switch (r) {\n case 0x5c: {\n // backslash\n const next = ctx.next();\n if (next !== 0x0a && next !== EOF) break;\n // fall through\n }\n // falls through\n case 0x0a:\n case EOF:\n if (r === 0x0a) ctx.backup();\n return ctx.errorf('unterminated tag block');\n case 0x5d: // ]\n if (ctx.pos > ctx.start) ctx.emit(ItemType.Tags);\n return lexNextOptionalBlock;\n case 0x5b: // [\n return ctx.errorf(`unexpected left square bracket '['`);\n case 0x7b: // {\n return ctx.errorf(`unexpected left curly brace '{'`);\n case 0x7d: // }\n return ctx.errorf(`unexpected right curly brace '}'`);\n }\n }\n}\n\nfunction lexMetadata(ctx: LexerContext): StateFn {\n // Consume the left delimiter '{'.\n ctx.pos++;\n\n let depth = 1;\n for (;;) {\n const r = ctx.next();\n switch (r) {\n case 0x22: {\n // double quote\n const err = acceptQuoted(ctx, 0x22);\n if (err) return ctx.errorf(err);\n break;\n }\n case 0x0a: // newline\n ctx.backup();\n // falls through\n case EOF:\n return ctx.errorf('unterminated metadata block');\n case 0x7b: // {\n depth++;\n break;\n case 0x7d: // }\n depth--;\n if (depth === 0) {\n if (ctx.pos > ctx.start) ctx.emit(ItemType.Metadata);\n return lexNextOptionalBlock;\n }\n break;\n }\n }\n}\n\n/**\n * Twee 3 lexer — yields LexerItem tokens from Twee source text.\n *\n * In the Go reference, this uses goroutines and channels.\n * Here we use a synchronous generator that accumulates items per state step.\n */\nexport function* tweeLexer(input: string): Generator<LexerItem, void, undefined> {\n const ctx = new LexerContext(input);\n let state: StateFn = lexProlog;\n while (state !== null) {\n state = state(ctx);\n const items = ctx.drainItems();\n for (const item of items) {\n yield item;\n }\n }\n // Drain any remaining items.\n const remaining = ctx.drainItems();\n for (const item of remaining) {\n yield item;\n }\n}\n\n/** Convenience class wrapper for the lexer generator. */\nexport class TweeLexer {\n private gen: Generator<LexerItem, void, undefined>;\n\n constructor(input: string) {\n this.gen = tweeLexer(input);\n }\n\n nextItem(): { item: LexerItem; done: boolean } {\n const result = this.gen.next();\n if (result.done) {\n return { item: { type: ItemType.EOF, line: 0, pos: 0, val: '' }, done: true };\n }\n return { item: result.value, done: false };\n }\n\n *[Symbol.iterator](): Generator<LexerItem, void, undefined> {\n yield* this.gen;\n }\n}\n","/**\n * Twee2 to Twee3 header syntax conversion.\n * Ported from twee2compat.go.\n */\n\nconst twee2DetectRe = /^:: *[^[]*?(?: *\\[.*?\\])? *<(.*?)> *$/m;\nconst twee2HeaderRe = /^(:: *[^[]*?)( *\\[.*?\\])?(?: *<(.*?)>)? *$/gm;\nconst twee2BadPosRe = /^(::.*?) *\\{\"position\":\" *\"\\}$/gm;\n\nfunction hasTwee2Syntax(s: string): boolean {\n return twee2DetectRe.test(s);\n}\n\n/**\n * Convert Twee2-style position blocks `<x,y>` to Twee3 metadata blocks `{\"position\":\"x,y\"}`.\n */\nexport function twee2ToV3(s: string): string {\n if (!hasTwee2Syntax(s)) return s;\n let result = s.replace(twee2HeaderRe, (_, p1: string, p2: string | undefined, p3: string | undefined) => {\n const tags = p2 ?? '';\n const pos = p3 ?? '';\n return `${p1}${tags} {\"position\":\"${pos}\"}`;\n });\n result = result.replace(twee2BadPosRe, '$1');\n return result;\n}\n","/**\n * Parse lexer items into Passage[].\n * Ported from storyload.go:loadTwee().\n */\nimport type { Passage, PassageMetadata, Diagnostic } from './types.js';\nimport { ItemType } from './types.js';\nimport { tweeLexer } from './lexer.js';\nimport { tweeUnescape } from './escape.js';\nimport { twee2ToV3 } from './twee2-compat.js';\n\nexport interface ParseOptions {\n /** Filename for diagnostics. */\n filename?: string;\n /** Trim whitespace from passage content. Default: true. */\n trim?: boolean;\n /** Enable Twee2 compatibility. Default: false. */\n twee2Compat?: boolean;\n}\n\nexport interface ParseResult {\n passages: Passage[];\n diagnostics: Diagnostic[];\n}\n\n/**\n * Parse Twee source text into passages.\n */\nexport function parseTwee(source: string, options: ParseOptions = {}): ParseResult {\n const { filename = '<inline>', trim = true, twee2Compat = false } = options;\n const diagnostics: Diagnostic[] = [];\n\n if (twee2Compat) {\n source = twee2ToV3(source);\n }\n\n const passages: Passage[] = [];\n let current: Passage | null = null;\n let pCount = 0;\n let lastType: ItemType = ItemType.EOF;\n\n for (const item of tweeLexer(source)) {\n switch (item.type) {\n case ItemType.Error:\n diagnostics.push({\n level: 'error',\n message: `line ${item.line}: Malformed twee source; ${item.val}.`,\n file: filename,\n line: item.line,\n });\n // Fatal: return what we have\n return { passages, diagnostics };\n\n case ItemType.EOF:\n if (pCount > 0 && current) {\n passages.push(current);\n }\n return { passages, diagnostics };\n\n case ItemType.Header:\n pCount++;\n if (pCount > 1 && current) {\n passages.push(current);\n }\n current = { name: '', tags: [], text: '' };\n break;\n\n case ItemType.Name: {\n if (!current) break;\n const name = tweeUnescape(item.val).trim();\n if (name.length === 0) {\n diagnostics.push({\n level: 'error',\n message: `line ${item.line}: Malformed twee source; passage with no name.`,\n file: filename,\n line: item.line,\n });\n return { passages, diagnostics };\n }\n current.name = name;\n break;\n }\n\n case ItemType.Tags: {\n if (!current) break;\n if (lastType !== ItemType.Name) {\n diagnostics.push({\n level: 'error',\n message: `line ${item.line}: Malformed twee source; optional tags block must immediately follow the passage name.`,\n file: filename,\n line: item.line,\n });\n return { passages, diagnostics };\n }\n // Strip the surrounding [ and ]\n const inner = item.val.slice(1, -1);\n current.tags = tweeUnescape(inner).split(/\\s+/).filter(Boolean);\n break;\n }\n\n case ItemType.Metadata: {\n if (!current) break;\n if (lastType !== ItemType.Name && lastType !== ItemType.Tags) {\n diagnostics.push({\n level: 'error',\n message: `line ${item.line}: Malformed twee source; optional metadata block must immediately follow the passage name or tags block.`,\n file: filename,\n line: item.line,\n });\n return { passages, diagnostics };\n }\n try {\n const raw: unknown = JSON.parse(item.val);\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n throw new Error('expected a JSON object');\n }\n const parsed = raw as Record<string, unknown>;\n const meta: PassageMetadata = {};\n for (const [key, value] of Object.entries(parsed)) {\n if (typeof value === 'string') {\n meta[key] = value;\n }\n }\n current.metadata = meta;\n } catch (e) {\n diagnostics.push({\n level: 'warning',\n message: `load ${filename}: line ${item.line}: Malformed twee source; could not decode metadata (reason: ${e instanceof Error ? e.message : String(e)}).`,\n file: filename,\n line: item.line,\n });\n }\n break;\n }\n\n case ItemType.Content: {\n if (!current) break;\n if (trim) {\n current.text = item.val.trim();\n } else {\n // Per spec: trailing blank lines MUST be stripped regardless of trim option\n current.text = item.val.replace(/\\n\\s*$/, '');\n }\n break;\n }\n\n default: {\n const _exhaustive: never = item.type;\n diagnostics.push({\n level: 'error',\n message: `line ${item.line}: Unhandled lexer item type: ${_exhaustive}.`,\n file: filename,\n line: item.line,\n });\n return { passages, diagnostics };\n }\n }\n\n lastType = item.type;\n }\n\n // Shouldn't reach here (EOF is always emitted), but just in case:\n if (pCount > 0 && current) {\n passages.push(current);\n }\n return { passages, diagnostics };\n}\n","/** Single source of truth for the twee-ts version. Update here when releasing. */\nexport const VERSION = '1.2.0';\n","/**\n * Twine 2 HTML and archive output.\n * Ported from storyout.go.\n */\nimport type { Story, StoryFormatInfo, Diagnostic } from './types.js';\nimport { attrEscape, htmlEscape, commentSanitize, htmlCommentSanitize } from './escape.js';\nimport { passageToPassagedata, hasTag, hasAnyTag } from './passage.js';\nimport { generateIFID } from './ifid.js';\nimport { readFormatSource } from './formats.js';\nimport { VERSION } from './version.js';\n\nconst CREATOR_NAME = 'Twee-ts';\n\nexport function toTwine2Archive(story: Story, startName: string, diagnostics: Diagnostic[]): string {\n return getTwine2DataChunk(story, startName, diagnostics) + '\\n';\n}\n\nexport function toTwine2HTML(\n story: Story,\n format: StoryFormatInfo,\n startName: string,\n diagnostics: Diagnostic[],\n): string {\n let template = readFormatSource(format);\n\n if (template.includes('{{STORY_NAME}}')) {\n template = template.replaceAll('{{STORY_NAME}}', htmlEscape(story.name));\n }\n if (template.includes('{{STORY_DATA}}')) {\n template = template.replace('{{STORY_DATA}}', getTwine2DataChunk(story, startName, diagnostics));\n }\n\n return template;\n}\n\nfunction getTwine2DataChunk(story: Story, startName: string, diagnostics: Diagnostic[]): string {\n // Check IFID status and generate if missing.\n ensureIFID(story, diagnostics);\n\n const parts: string[] = [];\n let startID = '';\n let pid = 0;\n\n // Gather script and stylesheet passages.\n const scripts: typeof story.passages = [];\n const stylesheets: typeof story.passages = [];\n for (const p of story.passages) {\n if (hasTag(p, 'Twine.private')) continue;\n if (hasTag(p, 'script')) scripts.push(p);\n else if (hasTag(p, 'stylesheet')) stylesheets.push(p);\n }\n\n // Style element\n let styleContent = '';\n if (stylesheets.length === 1) {\n styleContent = stylesheets[0]?.text ?? '';\n } else if (stylesheets.length > 1) {\n let pidS = 1;\n for (const p of stylesheets) {\n if (pidS > 1 && !styleContent.endsWith('\\n')) styleContent += '\\n';\n styleContent += `/* twine-user-stylesheet #${pidS}: \"${commentSanitize(p.name)}\" */\\n`;\n styleContent += p.text;\n pidS++;\n }\n }\n parts.push(`<style role=\"stylesheet\" id=\"twine-user-stylesheet\" type=\"text/twine-css\">${styleContent}</style>`);\n\n // Script element\n let scriptContent = '';\n if (scripts.length === 1) {\n scriptContent = scripts[0]?.text ?? '';\n } else if (scripts.length > 1) {\n let pidS = 1;\n for (const p of scripts) {\n if (pidS > 1 && !scriptContent.endsWith('\\n')) scriptContent += '\\n';\n scriptContent += `/* twine-user-script #${pidS}: \"${commentSanitize(p.name)}\" */\\n`;\n scriptContent += p.text;\n pidS++;\n }\n }\n parts.push(`<script role=\"script\" id=\"twine-user-script\" type=\"text/twine-javascript\">${scriptContent}</script>`);\n\n // Tag color elements (only spec-valid colors: 7 named colors or hex values)\n const validTagColors = new Set(['gray', 'red', 'orange', 'yellow', 'green', 'blue', 'purple']);\n const hexColorPattern = /^#[0-9a-fA-F]{3,8}$/;\n for (const [tag, color] of story.twine2.tagColors) {\n if (validTagColors.has(color) || hexColorPattern.test(color)) {\n parts.push(`<tw-tag name=\"${attrEscape(tag)}\" color=\"${attrEscape(color)}\"></tw-tag>`);\n }\n }\n\n // Normal passage elements\n pid = 1;\n for (const p of story.passages) {\n if (p.name === 'StoryTitle' || p.name === 'StoryData' || hasAnyTag(p, 'script', 'stylesheet', 'Twine.private')) {\n continue;\n }\n // Drop empty StorySettings\n if (p.name === 'StorySettings' && story.twine1.settings.size === 0) {\n continue;\n }\n\n parts.push(passageToPassagedata(p, pid));\n if (startName === p.name) {\n startID = String(pid);\n }\n pid++;\n }\n\n // Build options string\n const opts: string[] = [];\n for (const [opt, val] of story.twine2.options) {\n if (val) opts.push(opt);\n }\n const options = opts.join(' ');\n\n // Wrap in tw-storydata\n const zoom = String(story.twine2.zoom);\n\n const wrapper =\n `<!-- UUID://${htmlCommentSanitize(story.ifid)}// -->` +\n `<tw-storydata name=\"${attrEscape(story.name)}\" startnode=\"${attrEscape(startID)}\" ` +\n `creator=\"${attrEscape(CREATOR_NAME)}\" creator-version=\"${attrEscape(VERSION)}\" ` +\n `ifid=\"${attrEscape(story.ifid)}\" zoom=\"${attrEscape(zoom)}\" ` +\n `format=\"${attrEscape(story.twine2.format)}\" ` +\n `format-version=\"${attrEscape(story.twine2.formatVersion)}\" ` +\n `options=\"${attrEscape(options)}\" tags=\"${attrEscape(story.twine2.tags)}\" hidden>`;\n\n return wrapper + parts.join('') + '</tw-storydata>';\n}\n\nfunction ensureIFID(story: Story, diagnostics: Diagnostic[]): void {\n if (story.ifid !== '') return;\n\n if (story.legacyIFID !== '') {\n story.ifid = story.legacyIFID;\n diagnostics.push({\n level: 'warning',\n message: 'Story IFID not found; reusing \"ifid\" entry from the \"StorySettings\" special passage.',\n });\n } else {\n const ifid = generateIFID();\n story.ifid = ifid;\n diagnostics.push({\n level: 'error',\n message: `Story IFID not found. Add an IFID to your story: {\"ifid\":\"${ifid}\"}`,\n });\n }\n}\n","/**\n * Twine 1 HTML and archive output.\n * Ported from storyout.go.\n */\nimport { readFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport type { Story, StoryFormatInfo, Diagnostic } from './types.js';\nimport { hasTag, passageToTiddler } from './passage.js';\nimport { readFormatSource } from './formats.js';\nimport { jsStringEscape, htmlCommentSanitize } from './escape.js';\nimport { VERSION } from './version.js';\n\nconst CREATOR_NAME = 'twee-ts';\n\nexport function toTwine1Archive(story: Story, _startName: string): string {\n const { data, count } = getTwine1PassageChunk(story);\n return `<div id=\"storeArea\" data-size=\"${count}\">${data}</div>\\n`;\n}\n\nexport function toTwine1HTML(\n story: Story,\n format: StoryFormatInfo,\n startName: string,\n _diagnostics: Diagnostic[],\n): string {\n const formatDir = dirname(format.filename);\n const parentDir = dirname(formatDir);\n let template = readFormatSource(format);\n const { data, count } = getTwine1PassageChunk(story);\n\n // Component replacements\n template = tryReplaceComponent(template, '\"USER_LIB\"', join(formatDir, 'userlib.js'), false);\n template = tryReplaceComponent(template, '\"ENGINE\"', join(parentDir, 'engine.js'), true);\n template = tryReplaceComponent(template, '\"SUGARCANE\"', join(formatDir, 'code.js'), true);\n template = tryReplaceComponent(template, '\"JONAH\"', join(formatDir, 'code.js'), true);\n\n if (story.twine1.settings.get('jquery') === 'on') {\n template = tryReplaceComponent(template, '\"JQUERY\"', join(parentDir, 'jquery.js'), true);\n }\n if (story.twine1.settings.get('modernizr') === 'on') {\n template = tryReplaceComponent(template, '\"MODERNIZR\"', join(parentDir, 'modernizr.js'), true);\n }\n\n // Story instance replacements\n const displayStart = startName === 'Start' ? '' : startName;\n template = template.replace('\"VERSION\"', `Compiled with ${CREATOR_NAME}, ${VERSION}`);\n template = template.replace('\"TIME\"', `Built on ${new Date().toUTCString()}`);\n template = template.replace('\"START_AT\"', `\"${jsStringEscape(displayStart)}\"`);\n template = template.replace('\"STORY_SIZE\"', `\"${count}\"`);\n\n if (template.includes('\"STORY\"')) {\n template = template.replace('\"STORY\"', data);\n } else {\n // Pre-1.4 format: append data + footer\n let footer: string;\n try {\n footer = readFileSync(join(formatDir, 'footer.html'), 'utf-8');\n } catch {\n footer = '</div>\\n</body>\\n</html>\\n';\n }\n template += data + footer;\n }\n\n // IFID replacement\n if (story.ifid) {\n const safeIfid = htmlCommentSanitize(story.ifid);\n if (template.includes('<div id=\"store-area\"')) {\n template = template.replace('<div id=\"store-area\"', `<!-- UUID://${safeIfid}// --><div id=\"store-area\"`);\n } else {\n template = template.replace('<div id=\"storeArea\"', `<!-- UUID://${safeIfid}// --><div id=\"storeArea\"`);\n }\n }\n\n return template;\n}\n\nfunction getTwine1PassageChunk(story: Story): { data: string; count: number } {\n const obfuscateRot13 = story.twine1.settings.get('obfuscate') === 'rot13';\n let data = '';\n let count = 0;\n\n for (const p of story.passages) {\n if (hasTag(p, 'Twine.private')) continue;\n count++;\n data += passageToTiddler(p, count, obfuscateRot13);\n }\n\n return { data, count };\n}\n\nfunction tryReplaceComponent(template: string, placeholder: string, componentPath: string, required: boolean): string {\n if (!template.includes(placeholder)) return template;\n try {\n let content = readFileSync(componentPath, 'utf-8');\n if (content.charCodeAt(0) === 0xfeff) content = content.slice(1);\n return template.replace(placeholder, content);\n } catch (e) {\n if (required) {\n throw new Error(\n `Required format component not found: ${componentPath}: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n return template;\n }\n}\n","/**\n * Twee 3/1 decompile output.\n * Ported from storyout.go.\n */\nimport type { Story, OutputMode } from './types.js';\nimport { passageToTwee } from './passage.js';\n\nexport function toTwee(story: Story, outMode: OutputMode): string {\n let data = '';\n for (const p of story.passages) {\n data += passageToTwee(p, outMode);\n }\n return data;\n}\n","/**\n * Module/head injection into <head>.\n * Ported from module.go + io.go:modifyHead().\n */\nimport type { Diagnostic } from './types.js';\nimport { normalizedFileExt, mediaTypeFromExt, fontFormatHint, slugify } from './media-types.js';\nimport { readUTF8, readBase64, baseNameWithoutExt } from './util.js';\n\n/**\n * Load modules and return HTML tags to inject before </head>.\n */\nexport function loadModules(filenames: string[]): string {\n const processed = new Set<string>();\n const headTags: string[] = [];\n\n for (const filename of filenames) {\n if (processed.has(filename)) continue;\n\n const ext = normalizedFileExt(filename);\n let tag: string | null = null;\n\n switch (ext) {\n case 'css':\n tag = loadModuleTagged('style', filename);\n break;\n case 'js':\n tag = loadModuleTagged('script', filename);\n break;\n case 'otf':\n case 'ttf':\n case 'woff':\n case 'woff2':\n tag = loadModuleFont(filename);\n break;\n default:\n continue;\n }\n\n if (tag) headTags.push(tag);\n processed.add(filename);\n }\n\n return headTags.join('\\n');\n}\n\nfunction loadModuleTagged(tag: string, filename: string): string | null {\n const source = readUTF8(filename).trim();\n if (source.length === 0) return null;\n\n const family = baseNameWithoutExt(filename);\n const idSlug = `${tag}-module-${slugify(family)}`;\n const mimeType = tag === 'script' ? 'text/javascript' : 'text/css';\n\n return `<${tag} id=\"${idSlug}\" type=\"${mimeType}\">${source}</${tag}>`;\n}\n\nfunction loadModuleFont(filename: string): string | null {\n const source = readBase64(filename);\n const family = baseNameWithoutExt(filename);\n const idSlug = `style-module-${slugify(family)}`;\n const ext = normalizedFileExt(filename);\n const mediaType = mediaTypeFromExt(ext);\n const hint = fontFormatHint(ext);\n\n return `<style id=\"${idSlug}\" type=\"text/css\">@font-face {\\n\\tfont-family: \"${family}\";\\n\\tsrc: url(\"data:${mediaType};base64,${source}\") format(\"${hint}\");\\n}</style>`;\n}\n\n/**\n * Inject modules and head file content before </head>.\n */\nexport function modifyHead(html: string, modulePaths: string[], headFile?: string, diagnostics?: Diagnostic[]): string {\n const parts: string[] = [];\n\n if (modulePaths.length > 0) {\n const modules = loadModules(modulePaths).trim();\n if (modules.length > 0) parts.push(modules);\n }\n\n if (headFile) {\n try {\n const source = readUTF8(headFile).trim();\n if (source.length > 0) parts.push(source);\n } catch (e) {\n diagnostics?.push({\n level: 'warning',\n message: `Failed to read head file \"${headFile}\": ${e instanceof Error ? e.message : String(e)}`,\n });\n }\n }\n\n if (parts.length > 0) {\n parts.push('</head>');\n return html.replace('</head>', parts.join('\\n'));\n }\n return html;\n}\n","/**\n * Remote story format fetching, caching, and checksum verification.\n * Uses the Story Formats Archive (SFA) as the default source.\n */\nimport { mkdirSync, readFileSync, writeFileSync, existsSync, readdirSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { SFAIndex, SFAIndexEntry, StoryFormatInfo } from './types.js';\nimport { parseSemver, semverCompare, parseFormatJSON } from './formats.js';\n\nconst DEFAULT_SFA_INDICES = [\n 'https://videlais.github.io/story-formats-archive/official/index.json',\n 'https://videlais.github.io/story-formats-archive/unofficial/index.json',\n];\n\n/** Get the cache directory for downloaded story formats. */\nexport function getCacheDir(): string {\n const xdg = process.env['XDG_CACHE_HOME'];\n const base = xdg || join(homedir(), '.cache');\n return join(base, 'twee-ts', 'storyformats');\n}\n\n/** In-memory index cache, keyed by URL. Cleared each compile. */\nconst indexCache = new Map<string, SFAIndex>();\n\n/** Clear the in-memory index cache. */\nexport function clearIndexCache(): void {\n indexCache.clear();\n}\n\n/** Validate that a JSON value is a valid SFAIndexEntry. */\nfunction isValidEntry(val: unknown): val is SFAIndexEntry {\n if (typeof val !== 'object' || val === null || Array.isArray(val)) return false;\n const obj = val as Record<string, unknown>;\n return (\n typeof obj.name === 'string' &&\n typeof obj.version === 'string' &&\n typeof obj.checksums === 'object' &&\n obj.checksums !== null &&\n !Array.isArray(obj.checksums)\n );\n}\n\n/** Validate that a JSON value conforms to the SFAIndex shape. */\nfunction validateSFAIndex(json: unknown): SFAIndex {\n if (typeof json !== 'object' || json === null) {\n throw new Error('SFA index is not an object');\n }\n const obj = json as Record<string, unknown>;\n const twine1 = Array.isArray(obj['twine1']) ? (obj['twine1'] as unknown[]).filter(isValidEntry) : [];\n const twine2 = Array.isArray(obj['twine2']) ? (obj['twine2'] as unknown[]).filter(isValidEntry) : [];\n return { twine1, twine2 };\n}\n\n/** Generate a format ID from name and version. */\nfunction makeFormatId(name: string, version: string): string {\n const major = parseSemver(version)?.[0] ?? '0';\n return `${name.toLowerCase().replace(/\\s+/g, '-')}-${major}`;\n}\n\n/** Fetch and parse an SFA index.json, with in-memory caching. */\nexport async function fetchIndex(url: string): Promise<SFAIndex> {\n const cached = indexCache.get(url);\n if (cached) return cached;\n\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Failed to fetch format index from ${url}: ${res.status} ${res.statusText}`);\n }\n const data = validateSFAIndex(await res.json());\n indexCache.set(url, data);\n return data;\n}\n\ninterface FindEntryResult {\n entry: SFAIndexEntry;\n formatType: 'twine1' | 'twine2';\n}\n\n/**\n * Find the best matching entry in an SFA index.\n * Exact version preferred, then highest version with same major.\n */\nexport function findEntry(index: SFAIndex, name: string, version: string): FindEntryResult | undefined {\n const wanted = parseSemver(version);\n\n const searchArrays: Array<{ entries: SFAIndexEntry[]; formatType: 'twine1' | 'twine2' }> = [\n { entries: index.twine2 ?? [], formatType: 'twine2' },\n { entries: index.twine1 ?? [], formatType: 'twine1' },\n ];\n\n let bestResult: FindEntryResult | undefined;\n let bestVersion: [number, number, number] | null = null;\n\n for (const { entries, formatType } of searchArrays) {\n for (const entry of entries) {\n if (entry.name.toLowerCase() !== name.toLowerCase()) continue;\n const have = parseSemver(entry.version);\n if (!have) continue;\n\n // Exact match — return immediately\n if (wanted && semverCompare(have, wanted) === 0) return { entry, formatType };\n\n // Same-major, highest version\n if (wanted === null || (have[0] === wanted[0] && semverCompare(have, wanted) >= 0)) {\n if (!bestVersion || semverCompare(have, bestVersion) > 0) {\n bestVersion = have;\n bestResult = { entry, formatType };\n }\n }\n }\n }\n\n return bestResult;\n}\n\n/** Verify SHA-256 checksum using Web Crypto API (Node 22 built-in). */\nexport async function verifySHA256(content: Uint8Array<ArrayBuffer>, expectedHex: string): Promise<boolean> {\n const digest = await crypto.subtle.digest('SHA-256', content);\n const hex = Array.from(new Uint8Array(digest))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n return hex === expectedHex.toLowerCase();\n}\n\n/** Derive the download URL for a format.js from the index URL and entry. */\nfunction getDownloadUrl(indexUrl: string, entry: SFAIndexEntry, formatType: 'twine1' | 'twine2'): string {\n const base = indexUrl.replace(/\\/index\\.json$/, '');\n return `${base}/${formatType}/${entry.name}/${entry.version}/format.js`;\n}\n\n/** Download a format, verify its checksum, write to cache, and return StoryFormatInfo. */\nexport async function fetchAndCacheFormat(entry: SFAIndexEntry, downloadUrl: string): Promise<StoryFormatInfo> {\n const res = await fetch(downloadUrl);\n if (!res.ok) {\n throw new Error(`Failed to download format from ${downloadUrl}: ${res.status} ${res.statusText}`);\n }\n const text = await res.text();\n\n // Verify checksum if available\n const checksumKey = Object.keys(entry.checksums ?? {}).find((k) => k.endsWith('format.js'));\n if (checksumKey) {\n const expected = entry.checksums[checksumKey];\n if (!expected) throw new Error(`Missing checksum value for key \"${checksumKey}\"`);\n const encoder = new TextEncoder();\n const valid = await verifySHA256(encoder.encode(text), expected);\n if (!valid) {\n throw new Error(`Checksum verification failed for ${entry.name} ${entry.version}`);\n }\n }\n\n // Parse format JSON to extract name/version/source\n const id = makeFormatId(entry.name, entry.version);\n const data = parseFormatJSON(text, id);\n if (!data) {\n throw new Error(`Failed to parse format JSON from ${downloadUrl}`);\n }\n\n // Write to cache\n const cacheDir = getCacheDir();\n const formatDir = join(cacheDir, entry.name, entry.version);\n mkdirSync(formatDir, { recursive: true });\n const formatPath = join(formatDir, 'format.js');\n writeFileSync(formatPath, text, 'utf-8');\n\n return {\n id,\n filename: formatPath,\n isTwine2: true,\n name: data.name,\n version: data.version,\n proofing: data.proofing ?? false,\n };\n}\n\n/** Download a direct format.js URL, parse its JSON, cache it, and return StoryFormatInfo. */\nexport async function fetchDirectFormat(url: string): Promise<StoryFormatInfo> {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Failed to download format from ${url}: ${res.status} ${res.statusText}`);\n }\n const text = await res.text();\n\n const tempId = 'direct-url';\n const data = parseFormatJSON(text, tempId);\n if (!data) {\n throw new Error(`Failed to parse format JSON from ${url}`);\n }\n\n const id = makeFormatId(data.name, data.version);\n\n // Write to cache\n const cacheDir = getCacheDir();\n const formatDir = join(cacheDir, data.name, data.version);\n mkdirSync(formatDir, { recursive: true });\n const formatPath = join(formatDir, 'format.js');\n writeFileSync(formatPath, text, 'utf-8');\n\n return {\n id,\n filename: formatPath,\n isTwine2: true,\n name: data.name,\n version: data.version,\n proofing: data.proofing ?? false,\n };\n}\n\n/**\n * Try to resolve a remote story format by name and version.\n * 1. Try direct format URLs\n * 2. Try custom index URLs\n * 3. Try default SFA indices\n */\nexport async function resolveRemoteFormat(\n name: string,\n version: string,\n indices?: string[],\n urls?: string[],\n): Promise<StoryFormatInfo | undefined> {\n let lastError: Error | undefined;\n\n // 1. Try direct URLs — check if any match by name\n if (urls) {\n for (const url of urls) {\n try {\n const info = await fetchDirectFormat(url);\n if (info.name.toLowerCase() === name.toLowerCase()) {\n const wanted = parseSemver(version);\n const have = parseSemver(info.version);\n if (!wanted || (have && have[0] === wanted[0] && semverCompare(have, wanted) >= 0)) {\n return info;\n }\n }\n } catch (e) {\n lastError = e instanceof Error ? e : new Error(String(e));\n }\n }\n }\n\n // 2. Try custom indices, then default SFA indices\n const allIndices = [...(indices ?? []), ...DEFAULT_SFA_INDICES];\n for (const indexUrl of allIndices) {\n try {\n const index = await fetchIndex(indexUrl);\n const result = findEntry(index, name, version);\n if (result) {\n // Check cache first\n const cached = getCachedFormat(result.entry.name, result.entry.version);\n if (cached) return cached;\n\n const downloadUrl = getDownloadUrl(indexUrl, result.entry, result.formatType);\n return await fetchAndCacheFormat(result.entry, downloadUrl);\n }\n } catch (e) {\n lastError = e instanceof Error ? e : new Error(String(e));\n }\n }\n\n // If all sources failed with errors, propagate the last one\n if (lastError) throw lastError;\n return undefined;\n}\n\n/** Check if a format is already in the local cache. */\nfunction getCachedFormat(name: string, version: string): StoryFormatInfo | undefined {\n const formatPath = join(getCacheDir(), name, version, 'format.js');\n try {\n if (!existsSync(formatPath)) return undefined;\n const source = readFileSync(formatPath, 'utf-8');\n const id = makeFormatId(name, version);\n const data = parseFormatJSON(source, id);\n if (!data) return undefined;\n return {\n id,\n filename: formatPath,\n isTwine2: true,\n name: data.name,\n version: data.version,\n proofing: data.proofing ?? false,\n };\n } catch {\n return undefined;\n }\n}\n\n/** Discover all cached remote formats. Returns a Map like discoverFormats(). */\nexport function discoverCachedFormats(): Map<string, StoryFormatInfo> {\n const formats = new Map<string, StoryFormatInfo>();\n const cacheDir = getCacheDir();\n\n try {\n if (!existsSync(cacheDir)) return formats;\n } catch {\n return formats;\n }\n\n let names: string[];\n try {\n names = readdirSync(cacheDir);\n } catch {\n return formats;\n }\n\n for (const name of names) {\n const nameDir = join(cacheDir, name);\n try {\n if (!statSync(nameDir).isDirectory()) continue;\n } catch {\n continue;\n }\n\n let versions: string[];\n try {\n versions = readdirSync(nameDir);\n } catch {\n continue;\n }\n\n for (const version of versions) {\n const info = getCachedFormat(name, version);\n if (info) {\n formats.set(`${info.id}-${version}`, info);\n }\n }\n }\n\n return formats;\n}\n","/**\n * Story inspection utilities for unit testing.\n *\n * Extracts structural information from a compiled story:\n * passage names, tags, link graph, broken links, dead ends, orphans.\n *\n * Usage:\n * const result = await compile({ sources: ['./story'] });\n * const map = storyInspect(result.story);\n * expect(map.passages).toContain('Start');\n * expect(map.brokenLinks).toHaveLength(0);\n */\nimport type { Story } from './types.js';\nimport { isInfoPassage, isStoryPassage } from './passage.js';\n\nexport interface StoryMap {\n /** All passage names, in source order. */\n passages: string[];\n /** Only story passages (excludes StoryData, StoryTitle, scripts, stylesheets, etc.). */\n storyPassages: string[];\n /** Only info/special passages. */\n infoPassages: string[];\n /** All unique tags used across the story, sorted alphabetically. */\n tags: string[];\n /** Map of tag → passage names that carry that tag. */\n passagesByTag: Map<string, string[]>;\n /** Map of passage name → tags on that passage. */\n tagsByPassage: Map<string, string[]>;\n /**\n * Map of passage name → passage names it links to.\n * Parses `[[target]]`, `[[display->target]]`, `[[display|target]]`,\n * and SugarCube's `<<goto \"target\">>` / `<<link \"display\" \"target\">>`.\n */\n links: Map<string, string[]>;\n /** Broken links: `{ from, to }` pairs where `to` doesn't exist as a passage. */\n brokenLinks: BrokenLink[];\n /** Story passages with no outgoing links (potential dead ends). */\n deadEnds: string[];\n /** Story passages that no other passage links to (excluding the start passage). */\n orphans: string[];\n /** The configured start passage name, if any. */\n start: string;\n}\n\nexport interface BrokenLink {\n from: string;\n to: string;\n}\n\n/**\n * Extract all [[wiki-style links]] from passage text.\n *\n * Supported syntaxes:\n * - `[[PassageName]]`\n * - `[[Display Text->PassageName]]` (Twine 2 / SugarCube arrow)\n * - `[[Display Text|PassageName]]` (Twine 1 / Harlowe pipe)\n * - `<<goto \"PassageName\">>` (SugarCube macro)\n * - `<<link \"Display\" \"PassageName\">>` (SugarCube macro)\n */\nfunction extractLinksFromText(text: string): string[] {\n const targets = new Set<string>();\n\n // [[...]] links\n const wikiLinkRe = /\\[\\[([^\\]]+)\\]\\]/g;\n let m;\n while ((m = wikiLinkRe.exec(text)) !== null) {\n const content = m[1]!;\n\n // [[display->target]]\n const arrowIdx = content.indexOf('->');\n if (arrowIdx !== -1) {\n targets.add(content.slice(arrowIdx + 2).trim());\n continue;\n }\n\n // [[display|target]]\n const pipeIdx = content.indexOf('|');\n if (pipeIdx !== -1) {\n targets.add(content.slice(pipeIdx + 1).trim());\n continue;\n }\n\n // [[target]]\n targets.add(content.trim());\n }\n\n // <<goto \"target\">>\n const gotoRe = /<<goto\\s+[\"']([^\"']+)[\"']\\s*>>/g;\n while ((m = gotoRe.exec(text)) !== null) {\n targets.add(m[1]!);\n }\n\n // <<link \"display\" \"target\">> (second argument is the target passage)\n const linkMacroRe = /<<link\\s+[\"'][^\"']*[\"']\\s+[\"']([^\"']+)[\"']\\s*>>/g;\n while ((m = linkMacroRe.exec(text)) !== null) {\n targets.add(m[1]!);\n }\n\n return [...targets];\n}\n\n/**\n * Inspect a story and return its full structural map.\n *\n * Designed for story authors to use in unit tests:\n * ```ts\n * const result = await compile({ sources: ['./story'] });\n * const map = storyInspect(result.story);\n *\n * // Assert structure\n * expect(map.passages).toContain('Start');\n * expect(map.tags).toContain('location');\n * expect(map.passagesByTag.get('location')).toContain('Kitchen');\n * expect(map.brokenLinks).toEqual([]);\n * expect(map.deadEnds).not.toContain('Start');\n * ```\n */\nexport function storyInspect(story: Story): StoryMap {\n const allNames = new Set(story.passages.map((p) => p.name));\n\n const passages: string[] = [];\n const storyPassages: string[] = [];\n const infoPassages: string[] = [];\n const tagSet = new Set<string>();\n const passagesByTag = new Map<string, string[]>();\n const tagsByPassage = new Map<string, string[]>();\n const links = new Map<string, string[]>();\n\n for (const p of story.passages) {\n passages.push(p.name);\n\n if (isStoryPassage(p)) {\n storyPassages.push(p.name);\n }\n if (isInfoPassage(p)) {\n infoPassages.push(p.name);\n }\n\n // Tags\n tagsByPassage.set(p.name, [...p.tags]);\n for (const tag of p.tags) {\n tagSet.add(tag);\n let list = passagesByTag.get(tag);\n if (!list) {\n list = [];\n passagesByTag.set(tag, list);\n }\n list.push(p.name);\n }\n\n // Links\n const targets = extractLinksFromText(p.text);\n links.set(p.name, targets);\n }\n\n // Broken links: link targets that don't exist as passages\n const brokenLinks: BrokenLink[] = [];\n for (const [from, targets] of links) {\n for (const to of targets) {\n if (!allNames.has(to)) {\n brokenLinks.push({ from, to });\n }\n }\n }\n\n // Dead ends: story passages with no outgoing links\n const deadEnds: string[] = [];\n for (const name of storyPassages) {\n const targets = links.get(name);\n if (!targets || targets.length === 0) {\n deadEnds.push(name);\n }\n }\n\n // Orphans: story passages nobody links to (excluding start)\n const start = story.twine2.start || 'Start';\n const linkedTo = new Set<string>();\n for (const targets of links.values()) {\n for (const t of targets) {\n linkedTo.add(t);\n }\n }\n const orphans: string[] = [];\n for (const name of storyPassages) {\n if (name !== start && !linkedTo.has(name)) {\n orphans.push(name);\n }\n }\n\n return {\n passages,\n storyPassages,\n infoPassages,\n tags: [...tagSet].sort(),\n passagesByTag,\n tagsByPassage,\n links,\n brokenLinks,\n deadEnds,\n orphans,\n start,\n };\n}\n","/**\n * Config file loading and validation for twee-ts.\n */\nimport { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { TweeTsConfig, OutputMode } from './types.js';\n\nexport const CONFIG_FILENAME = 'twee-ts.config.json';\n\nconst VALID_OUTPUT_MODES: OutputMode[] = ['html', 'twee3', 'twee1', 'twine2-archive', 'twine1-archive', 'json'];\n\n/** Load a config file from the given directory (default: cwd). Returns null if not found. */\nexport function loadConfig(dir?: string): TweeTsConfig | null {\n const base = dir ?? process.cwd();\n const configPath = join(base, CONFIG_FILENAME);\n\n if (!existsSync(configPath)) return null;\n\n let raw: string;\n try {\n raw = readFileSync(configPath, 'utf-8');\n } catch {\n return null;\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (e) {\n throw new Error(`Invalid JSON in ${configPath}: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n const errors = validateConfig(data);\n if (errors.length > 0) {\n throw new Error(`Invalid config in ${configPath}:\\n ${errors.join('\\n ')}`);\n }\n\n return data as TweeTsConfig;\n}\n\n/** Load a config from a specific file path. */\nexport function loadConfigFile(filePath: string): TweeTsConfig {\n let raw: string;\n try {\n raw = readFileSync(filePath, 'utf-8');\n } catch (e) {\n throw new Error(`Cannot read config file ${filePath}: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (e) {\n throw new Error(`Invalid JSON in ${filePath}: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n const errors = validateConfig(data);\n if (errors.length > 0) {\n throw new Error(`Invalid config in ${filePath}:\\n ${errors.join('\\n ')}`);\n }\n\n return data as TweeTsConfig;\n}\n\n/** Validate a config object. Returns an array of error strings (empty = valid). */\nexport function validateConfig(data: unknown): string[] {\n const errors: string[] = [];\n\n if (typeof data !== 'object' || data === null || Array.isArray(data)) {\n errors.push('Config must be a JSON object.');\n return errors;\n }\n\n const obj = data as Record<string, unknown>;\n\n // String fields\n for (const key of ['output', 'formatId', 'startPassage', 'headFile'] as const) {\n if (key in obj && typeof obj[key] !== 'string') {\n errors.push(`\"${key}\" must be a string.`);\n }\n }\n\n // Boolean fields\n for (const key of ['useTweegoPath', 'trim', 'twee2Compat', 'testMode', 'noRemote'] as const) {\n if (key in obj && typeof obj[key] !== 'boolean') {\n errors.push(`\"${key}\" must be a boolean.`);\n }\n }\n\n // String array fields\n for (const key of ['sources', 'formatPaths', 'formatIndices', 'formatUrls', 'modules'] as const) {\n if (key in obj) {\n if (!Array.isArray(obj[key])) {\n errors.push(`\"${key}\" must be an array.`);\n } else if (!(obj[key] as unknown[]).every((v) => typeof v === 'string')) {\n errors.push(`\"${key}\" must be an array of strings.`);\n }\n }\n }\n\n // tagAliases validation\n if ('tagAliases' in obj) {\n if (typeof obj['tagAliases'] !== 'object' || obj['tagAliases'] === null || Array.isArray(obj['tagAliases'])) {\n errors.push('\"tagAliases\" must be an object.');\n } else {\n const aliases = obj['tagAliases'] as Record<string, unknown>;\n for (const [key, val] of Object.entries(aliases)) {\n if (typeof val !== 'string') {\n errors.push(`\"tagAliases.${key}\" must be a string.`);\n }\n }\n }\n }\n\n // OutputMode validation\n if ('outputMode' in obj) {\n if (typeof obj['outputMode'] !== 'string' || !VALID_OUTPUT_MODES.includes(obj['outputMode'] as OutputMode)) {\n errors.push(`\"outputMode\" must be one of: ${VALID_OUTPUT_MODES.join(', ')}.`);\n }\n }\n\n return errors;\n}\n\n/** Return a default config JSON string for --init scaffolding. */\nexport function scaffoldConfig(): string {\n const config: TweeTsConfig = {\n sources: ['src/'],\n output: 'story.html',\n };\n return JSON.stringify(config, null, 2) + '\\n';\n}\n"],"mappings":"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","names":["writeFileSync","readdirSync","statSync","join","statSync","readdirSync","join","quote","readFileSync","join","CREATOR_NAME","join","readFileSync","readFileSync","readdirSync","statSync","join","homedir","join","homedir","readFileSync","readdirSync","statSync","CREATOR_NAME","writeFileSync","readFileSync","existsSync","join"]}