@lucidkiln/language-server 0.0.0-stage → 1.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","names":["KEYWORDS","docs","KEYWORDS"],"sources":["../src/builtins.ts","../src/context.ts","../src/calls.ts","../src/docs.json","../src/docs.ts","../src/html.ts","../src/typescript-6.ts","../src/typescript-7.ts","../src/typescript.ts","../src/project.ts","../src/scopes.ts","../src/types.ts","../src/features.ts","../src/server.ts","../src/main.ts"],"sourcesContent":["/** A built-in filter, function or test: how to call it, for completions and hover. What it does comes from `docs.json`. */\nexport type BuiltinDoc = { signature: string };\n\n/** A tag: the snippet that completes it after `{%`. `$0` marks where the cursor ends. What it does comes from `docs.json`. */\nexport type TagDoc = { snippet: string };\n\nconst block = (name: string, header: string) =>\n\t`${name}${header} %}\\n\\t$0\\n{% end${name} %}`;\n\nexport const TAGS: Record<string, TagDoc> = {\n\tif: {\n\t\tsnippet: block(\"if\", \" ${1:condition}\"),\n\t},\n\telseif: {\n\t\tsnippet: \"elseif ${1:condition} %}\",\n\t},\n\telse: {\n\t\tsnippet: \"else %}\",\n\t},\n\tfor: {\n\t\tsnippet: block(\"for\", \" ${1:item} in ${2:items}\"),\n\t},\n\tset: {\n\t\tsnippet: \"set ${1:name} = ${2:value} %}\",\n\t},\n\tprops: {\n\t\tsnippet: \"props ${1:name} %}\",\n\t},\n\textends: {\n\t\tsnippet: 'extends \"${1:layouts/base}\" %}',\n\t},\n\tblock: {\n\t\tsnippet: block(\"block\", \" ${1:name}\"),\n\t},\n\tinclude: {\n\t\tsnippet: 'include \"${1}\" %}',\n\t},\n\tcomponent: {\n\t\tsnippet: 'component \"${1}\" with { $2 } %}\\n\\t$0\\n{% endcomponent %}',\n\t},\n\tisland: {\n\t\tsnippet: 'island \"${1}\" with { $2 } %}\\n\\t$0\\n{% endisland %}',\n\t},\n\tfill: {\n\t\tsnippet: block(\"fill\", ' \"${1:name}\"'),\n\t},\n\tslot: {\n\t\tsnippet: \"slot %}$0{% endslot %}\",\n\t},\n\tmacro: {\n\t\tsnippet: block(\"macro\", \" ${1:name}(${2})\"),\n\t},\n\timport: {\n\t\tsnippet: 'import \"${1}\" as ${2:name} %}',\n\t},\n\tfrom: {\n\t\tsnippet: 'from \"${1}\" import ${2:name} %}',\n\t},\n\twith: {\n\t\tsnippet: block(\"with\", \" { ${1} }\"),\n\t},\n\tcache: {\n\t\tsnippet: block(\"cache\", ' \"${1:key}\" for ${2:600}'),\n\t},\n\toutlet: {\n\t\tsnippet: 'outlet \"${1:head}\" %}',\n\t},\n\tadd: {\n\t\tsnippet: block(\"add\", ' to \"${1:head}\"'),\n\t},\n\tflush: {\n\t\tsnippet: \"flush %}\",\n\t},\n\tapply: {\n\t\tsnippet: block(\"apply\", \" ${1:filter}\"),\n\t},\n\tautoescape: {\n\t\tsnippet: block(\"autoescape\", ' \"${1:html}\"'),\n\t},\n\tverbatim: {\n\t\tsnippet: \"verbatim %}\\n$0\\n{% endverbatim %}\",\n\t},\n};\n\n/** Tags that have a body and an end tag. */\nexport const BLOCK_TAGS = new Set([\n\t\"if\",\n\t\"for\",\n\t\"set\",\n\t\"block\",\n\t\"component\",\n\t\"island\",\n\t\"fill\",\n\t\"slot\",\n\t\"macro\",\n\t\"with\",\n\t\"cache\",\n\t\"add\",\n\t\"apply\",\n\t\"autoescape\",\n\t\"verbatim\",\n]);\n\nexport const FILTERS: Record<string, BuiltinDoc> = {\n\tupper: { signature: \"upper\" },\n\tlower: { signature: \"lower\" },\n\tcapitalize: {\n\t\tsignature: \"capitalize\",\n\t},\n\ttitle: {\n\t\tsignature: \"title\",\n\t},\n\ttrim: {\n\t\tsignature: \"trim(characters?, side?)\",\n\t},\n\treplace: {\n\t\tsignature: \"replace(search, replacement)\",\n\t},\n\tsplit: {\n\t\tsignature: \"split(separator, limit?)\",\n\t},\n\ttruncate: {\n\t\tsignature: \"truncate(length, ellipsis?)\",\n\t},\n\tstripTags: {\n\t\tsignature: \"stripTags\",\n\t},\n\tnl2br: {\n\t\tsignature: \"nl2br\",\n\t},\n\turlEncode: {\n\t\tsignature: \"urlEncode\",\n\t},\n\tjson: {\n\t\tsignature: \"json(indent?)\",\n\t},\n\tescape: {\n\t\tsignature: \"escape(strategy?)\",\n\t},\n\traw: {\n\t\tsignature: \"raw\",\n\t},\n\tdefault: {\n\t\tsignature: \"default(fallback)\",\n\t},\n\tlength: {\n\t\tsignature: \"length\",\n\t},\n\tfirst: {\n\t\tsignature: \"first\",\n\t},\n\tlast: {\n\t\tsignature: \"last\",\n\t},\n\tslice: {\n\t\tsignature: \"slice(start, end?)\",\n\t},\n\tjoin: {\n\t\tsignature: \"join(glue?, lastGlue?)\",\n\t},\n\tkeys: {\n\t\tsignature: \"keys\",\n\t},\n\tmerge: {\n\t\tsignature: \"merge(...values)\",\n\t},\n\treverse: {\n\t\tsignature: \"reverse\",\n\t},\n\tsort: {\n\t\tsignature: \"sort(by?)\",\n\t},\n\tmap: {\n\t\tsignature: \"map((value, key) => ...)\",\n\t},\n\tfilter: {\n\t\tsignature: \"filter((value, key) => ...)\",\n\t},\n\treduce: {\n\t\tsignature: \"reduce((total, value, key) => ..., initial)\",\n\t},\n\tfind: {\n\t\tsignature: \"find((value, key) => ...)\",\n\t},\n\tcolumn: {\n\t\tsignature: \"column(name)\",\n\t},\n\tbatch: {\n\t\tsignature: \"batch(size, fill?)\",\n\t},\n\tabs: {\n\t\tsignature: \"abs\",\n\t},\n\tround: {\n\t\tsignature: \"round(precision?, method?)\",\n\t},\n\tformatNumber: {\n\t\tsignature: \"formatNumber(...options)\",\n\t},\n\tplural: {\n\t\tsignature: \"plural(one, other, ...forms)\",\n\t},\n\tformatDate: {\n\t\tsignature: \"formatDate(...options)\",\n\t},\n};\n\nexport const FUNCTIONS: Record<string, BuiltinDoc> = {\n\trange: {\n\t\tsignature: \"range(start, end, step?)\",\n\t},\n\tmax: {\n\t\tsignature: \"max(...values)\",\n\t},\n\tmin: {\n\t\tsignature: \"min(...values)\",\n\t},\n\tcycle: {\n\t\tsignature: \"cycle(values, position)\",\n\t},\n\tdate: {\n\t\tsignature: \"date(value?)\",\n\t},\n\tattrs: {\n\t\tsignature: \"attrs(attributes)\",\n\t},\n\tdump: {\n\t\tsignature: \"dump(...values)\",\n\t},\n\tparent: {\n\t\tsignature: \"parent()\",\n\t},\n\tblock: {\n\t\tsignature: \"block(name)\",\n\t},\n};\n\nexport const TESTS: Record<string, BuiltinDoc> = {\n\tdefined: {\n\t\tsignature: \"defined\",\n\t},\n\tnull: {\n\t\tsignature: \"null\",\n\t},\n\tempty: {\n\t\tsignature: \"empty\",\n\t},\n\teven: { signature: \"even\" },\n\todd: { signature: \"odd\" },\n\titerable: {\n\t\tsignature: \"iterable\",\n\t},\n\t\"divisible by\": {\n\t\tsignature: \"divisible by(divisor)\",\n\t},\n};\n\nexport const LOOP_PROPERTIES: Record<string, string> = {\n\tindex: \"Position, starting at 1.\",\n\tindex0: \"Position, starting at 0.\",\n\trevIndex: \"Items left, ending at 1.\",\n\trevIndex0: \"Items left, ending at 0.\",\n\tfirst: \"`true` on the first item.\",\n\tlast: \"`true` on the last item.\",\n\tlength: \"Total number of items.\",\n};\n\nexport const KEYWORDS = [\n\t\"true\",\n\t\"false\",\n\t\"null\",\n\t\"and\",\n\t\"or\",\n\t\"not\",\n\t\"in\",\n\t\"is\",\n];\n","import { BLOCK_TAGS } from \"./builtins.js\";\n\n/**\n * What the text before the cursor is in the middle of, for completions. `start` is where the word being typed starts.\n *\n * - `tag`: a tag's name, just after `{%`. `end` is where an existing `%}` on the line ends, so a snippet can replace it.\n * - `template`: a template name in the string after `extends`, `include`, `component`, `island`, `import` or `from`.\n * - `filter`, `test`: a name after `|`, or after `is` or `is not`.\n * - `loop`: a property after `loop.`.\n * - `prop`: a key in the `with { }` hash of an `include`, `component` or `island` of `template`.\n * - `member`: a property name after a dot, such as `page.title`.\n * - `expression`: a variable or function name.\n */\nexport type CursorContext =\n\t| { kind: \"tag\"; start: number; end: number | null; open: string | null }\n\t| { kind: \"template\"; start: number; prefix: string }\n\t| {\n\t\t\tkind: \"filter\" | \"test\" | \"loop\" | \"member\" | \"expression\";\n\t\t\tstart: number;\n\t }\n\t| { kind: \"prop\"; start: number; template: string };\n\n/** Where the output or tag around `offset` opens, and its kind. Null outside one, or inside a comment. */\nexport const enclosingDelimiter = (\n\ttext: string,\n\toffset: number,\n): { start: number; kind: \"output\" | \"tag\" } | null => {\n\tconst before = text.slice(0, offset);\n\tconst output = before.lastIndexOf(\"{{\");\n\tconst tag = before.lastIndexOf(\"{%\");\n\tconst comment = before.lastIndexOf(\"{#\");\n\tif (comment !== -1 && before.indexOf(\"#}\", comment) === -1) return null;\n\tconst start = Math.max(output, tag);\n\tif (start === -1 || start < comment) return null;\n\tconst kind = start === tag ? \"tag\" : \"output\";\n\tif (before.indexOf(kind === \"tag\" ? \"%}\" : \"}}\", start) !== -1) return null;\n\treturn { start, kind };\n};\n\n/** The block tags open at `offset`, innermost last, from the tags before it. */\nexport const openBlocks = (text: string, offset: number): string[] => {\n\tconst stack: string[] = [];\n\tconst tags = /\\{%-?\\s*(\\w+)([^%]*)%\\}/g;\n\tfor (const match of text.slice(0, offset).matchAll(tags)) {\n\t\tconst name = match[1] as string;\n\t\tconst rest = match[2] as string;\n\t\tif (BLOCK_TAGS.has(name)) {\n\t\t\tif (name === \"set\" && rest.includes(\"=\")) continue;\n\t\t\tif (name === \"block\" && rest.trim().includes(\" \")) continue;\n\t\t\tstack.push(name);\n\t\t} else if (name.startsWith(\"end\")) {\n\t\t\tconst index = stack.lastIndexOf(name.slice(3));\n\t\t\tif (index !== -1) stack.length = index;\n\t\t}\n\t}\n\treturn stack;\n};\n\nconst WORD_END = /[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport const cursorContext = (\n\ttext: string,\n\toffset: number,\n): CursorContext | null => {\n\tconst delimiter = enclosingDelimiter(text, offset);\n\tif (!delimiter) return null;\n\tconst inner = text.slice(delimiter.start + 2, offset).replace(/^-/, \"\");\n\tconst word = WORD_END.exec(inner)?.[0] ?? \"\";\n\tconst start = offset - word.length;\n\tconst head = inner.slice(0, inner.length - word.length);\n\n\tif (delimiter.kind === \"tag\" && /^\\s*$/.test(head)) {\n\t\tconst after = /^\\w*(\\s*-?%\\})/.exec(\n\t\t\ttext.slice(offset).split(\"\\n\")[0] ?? \"\",\n\t\t);\n\t\tconst blocks = openBlocks(text, delimiter.start);\n\t\treturn {\n\t\t\tkind: \"tag\",\n\t\t\tstart,\n\t\t\tend: after ? offset + (after[0] as string).length : null,\n\t\t\topen: blocks.at(-1) ?? null,\n\t\t};\n\t}\n\n\tconst template =\n\t\t/\\b(?:extends|include|component|island|import|from)\\s+([\"'])([^\"']*)$/.exec(\n\t\t\tinner,\n\t\t);\n\tif (template) {\n\t\tconst prefix = template[2] as string;\n\t\treturn { kind: \"template\", start: offset - prefix.length, prefix };\n\t}\n\tif (/\\bloop\\.$/.test(head)) return { kind: \"loop\", start };\n\tif (/(?:^|[^|])\\|\\s*$/.test(head)) return { kind: \"filter\", start };\n\tif (/\\bis\\s+(?:not\\s+)?$/.test(head)) return { kind: \"test\", start };\n\n\tconst props =\n\t\t/\\b(?:include|component|island)\\s+([\"'])([^\"']+)\\1\\s+with\\s+\\{([^{}]*)$/.exec(\n\t\t\thead,\n\t\t);\n\tif (props && /(?:^|,)\\s*$/.test(props[3] as string)) {\n\t\treturn { kind: \"prop\", start, template: props[2] as string };\n\t}\n\t// A dot after a name, `]` or `)`, but not a decimal point.\n\tif (/[\\w\\])]\\??\\.$/.test(head) && !/(?:^|[^\\w$])\\d+\\.$/.test(head)) {\n\t\treturn { kind: \"member\", start };\n\t}\n\tif (/[.\\w]$/.test(head) || /[\"']$/.test(head)) return null;\n\treturn { kind: \"expression\", start };\n};\n\n/** The name under the cursor, and what it names, for hover and go to definition. */\nexport type CursorSymbol = {\n\tkind:\n\t\t| \"tag\"\n\t\t| \"filter\"\n\t\t| \"test\"\n\t\t| \"function\"\n\t\t| \"loop\"\n\t\t| \"variable\"\n\t\t| \"template\";\n\tname: string;\n\tstart: number;\n\tend: number;\n};\n\n/** Every template name written as a string after `extends`, `include`, `component`, `island`, `import` or `from`, with the name's offsets. */\nexport const templateStrings = (\n\ttext: string,\n): { name: string; start: number; end: number }[] => {\n\tconst found: { name: string; start: number; end: number }[] = [];\n\tconst pattern =\n\t\t/\\{%-?\\s*(?:extends|include|component|island|import|from)\\s+([\"'])([^\"'\\n]*)\\1/g;\n\tfor (const match of text.matchAll(pattern)) {\n\t\tconst name = match[2] as string;\n\t\tconst end = (match.index as number) + match[0].length - 1;\n\t\tfound.push({ name, start: end - name.length, end });\n\t}\n\treturn found;\n};\n\nexport const symbolAt = (text: string, offset: number): CursorSymbol | null => {\n\tconst string = templateStrings(text).find(\n\t\t(found) => offset >= found.start && offset <= found.end,\n\t);\n\tif (string) return { kind: \"template\", ...string };\n\n\tconst delimiter = enclosingDelimiter(text, offset);\n\tif (!delimiter) return null;\n\tlet start = offset;\n\tlet end = offset;\n\twhile (start > 0 && /\\w/.test(text[start - 1] as string)) start--;\n\twhile (end < text.length && /\\w/.test(text[end] as string)) end++;\n\tif (start === end || !/^[A-Za-z_]/.test(text.slice(start))) return null;\n\tlet name = text.slice(start, end);\n\tconst head = text.slice(delimiter.start + 2, start);\n\tconst tail = text.slice(end, end + 40);\n\n\tif (delimiter.kind === \"tag\" && /^-?\\s*$/.test(head)) {\n\t\treturn { kind: \"tag\", name, start, end };\n\t}\n\tif (/\\|\\s*$/.test(head)) return { kind: \"filter\", name, start, end };\n\tif (/\\bis\\s+(?:not\\s+)?$/.test(head)) {\n\t\tif (name === \"divisible\" && /^\\s+by\\b/.test(tail)) name = \"divisible by\";\n\t\treturn { kind: \"test\", name, start, end };\n\t}\n\tif (name === \"by\" && /\\bis\\s+(?:not\\s+)?divisible\\s+$/.test(head)) {\n\t\treturn { kind: \"test\", name: \"divisible by\", start, end };\n\t}\n\tif (/\\bloop\\.$/.test(head)) return { kind: \"loop\", name, start, end };\n\tif (/[.\\w]$/.test(head)) return null;\n\tif (/^\\s*\\(/.test(tail)) return { kind: \"function\", name, start, end };\n\treturn { kind: \"variable\", name, start, end };\n};\n","import { enclosingDelimiter } from \"./context.js\";\n\n/**\n * The function or filter call whose arguments the cursor is in. Read from the text, because a half-typed call such as\n * `testPages(\"tags\", ` doesn't parse.\n *\n * - `index`: the positional argument the cursor is on, counting from 0.\n * - `named`: the named argument the cursor is in, as in `limit: ‸`, or null.\n * - `sawNamed`: whether a named argument came before the cursor. Named arguments are gathered into the last parameter.\n * - `namePosition`: whether the cursor is where an argument starts, so a name such as `limit:` could go there. `start`\n * is where the word being typed starts.\n */\nexport type CallContext = {\n\tkind: \"function\" | \"filter\";\n\tname: string;\n\tindex: number;\n\tnamed: string | null;\n\tsawNamed: boolean;\n\tnamePosition: boolean;\n\tstart: number;\n};\n\nconst CLOSERS: Record<string, string> = { \"(\": \")\", \"[\": \"]\", \"{\": \"}\" };\n\ntype Frame = {\n\tchar: string;\n\t/** For `(`: the function or filter it calls, or null for grouping brackets and method calls. */\n\tcallee: { kind: \"function\" | \"filter\"; name: string } | null;\n\tcommas: number;\n\t/** Where the current argument starts. */\n\tsegment: number;\n\tsawNamed: boolean;\n};\n\n/** Words before `(` that aren't calls, as in `not (a or b)`. */\nconst KEYWORDS = new Set([\"and\", \"or\", \"not\", \"in\", \"is\", \"if\", \"else\"]);\n\nconst NAMED = /^\\s*([A-Za-z_]\\w*)\\s*:(?!:)/;\n\nexport const callContext = (\n\ttext: string,\n\toffset: number,\n): CallContext | null => {\n\tconst delimiter = enclosingDelimiter(text, offset);\n\tif (!delimiter) return null;\n\tconst stack: Frame[] = [];\n\tlet quote: string | null = null;\n\tfor (let index = delimiter.start + 2; index < offset; index++) {\n\t\tconst char = text[index] as string;\n\t\tif (quote) {\n\t\t\tif (char === \"\\\\\") index++;\n\t\t\telse if (char === quote) quote = null;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === '\"' || char === \"'\") quote = char;\n\t\telse if (char in CLOSERS) {\n\t\t\tlet callee: Frame[\"callee\"] = null;\n\t\t\tif (char === \"(\") {\n\t\t\t\tconst match = /(\\|\\s*|\\.\\s*)?([A-Za-z_]\\w*)\\s*$/.exec(\n\t\t\t\t\ttext.slice(delimiter.start + 2, index),\n\t\t\t\t);\n\t\t\t\tconst name = match?.[2];\n\t\t\t\tif (name && !KEYWORDS.has(name) && !match[1]?.startsWith(\".\")) {\n\t\t\t\t\tcallee = { kind: match[1] ? \"filter\" : \"function\", name };\n\t\t\t\t}\n\t\t\t}\n\t\t\tstack.push({\n\t\t\t\tchar,\n\t\t\t\tcallee,\n\t\t\t\tcommas: 0,\n\t\t\t\tsegment: index + 1,\n\t\t\t\tsawNamed: false,\n\t\t\t});\n\t\t} else if (char === \")\" || char === \"]\" || char === \"}\") {\n\t\t\tstack.pop();\n\t\t} else if (char === \",\") {\n\t\t\tconst frame = stack.at(-1);\n\t\t\tif (frame) {\n\t\t\t\tif (NAMED.test(text.slice(frame.segment, index))) frame.sawNamed = true;\n\t\t\t\tframe.commas++;\n\t\t\t\tframe.segment = index + 1;\n\t\t\t}\n\t\t}\n\t}\n\tconst frame = stack.at(-1);\n\tif (frame?.char !== \"(\" || !frame.callee) return null;\n\tconst segment = text.slice(frame.segment, offset);\n\tconst word = /[A-Za-z_]\\w*$/.exec(segment)?.[0] ?? \"\";\n\treturn {\n\t\t...frame.callee,\n\t\tindex: frame.commas,\n\t\tnamed: NAMED.exec(segment)?.[1] ?? null,\n\t\tsawNamed: frame.sawNamed,\n\t\tnamePosition: /^\\s*[A-Za-z_]?\\w*$/.test(segment),\n\t\tstart: offset - word.length,\n\t};\n};\n\n/**\n * Splits a parameter list, such as `a: string, b?: { c: number }`, at its top-level commas. Each part keeps its\n * offsets, so a signature can point at the parameter it's on.\n */\nexport const splitParameters = (\n\tlist: string,\n): { text: string; start: number; end: number }[] => {\n\tconst parts: { text: string; start: number; end: number }[] = [];\n\tlet depth = 0;\n\tlet start = 0;\n\tconst push = (end: number) => {\n\t\tconst raw = list.slice(start, end);\n\t\tconst leading = raw.length - raw.trimStart().length;\n\t\tconst text = raw.trim();\n\t\tif (text)\n\t\t\tparts.push({\n\t\t\t\ttext,\n\t\t\t\tstart: start + leading,\n\t\t\t\tend: start + leading + text.length,\n\t\t\t});\n\t};\n\tfor (let index = 0; index < list.length; index++) {\n\t\tconst char = list[index] as string;\n\t\tif (\"([{<\".includes(char)) depth++;\n\t\telse if (\")]}\".includes(char) || (char === \">\" && list[index - 1] !== \"=\"))\n\t\t\tdepth--;\n\t\telse if (char === \",\" && depth === 0) {\n\t\t\tpush(index);\n\t\t\tstart = index + 1;\n\t\t}\n\t}\n\tpush(list.length);\n\treturn parts;\n};\n","","import docs from \"./docs.json\" with { type: \"json\" };\n\n/** The kinds of built-in that have docs. */\nexport type DocKind = \"tags\" | \"filters\" | \"functions\" | \"tests\";\n\n/**\n * What each built-in does, from its section of the docs site, up to the end of its first example. The docs build writes\n * `docs.json`; see `apps/documentation/src/editor-docs.ts`.\n */\nconst DOCS: Record<\n\tDocKind,\n\tRecord<string, { markdown: string; url: string }>\n> = docs;\n\n/** A built-in's docs as Markdown, ending with a link to its section on the docs site. Null for names without docs. */\nexport const docsFor = (kind: DocKind, name: string): string | null => {\n\tconst doc = DOCS[kind][name];\n\treturn doc ? `${doc.markdown}\\n\\n---\\n\\n[Kiln docs](${doc.url})` : null;\n};\n","import { templateText } from \"@lucidkiln/core\";\nimport { getLanguageService } from \"vscode-html-languageservice\";\nimport type { CompletionItem, Hover } from \"vscode-languageserver\";\nimport { TextDocument } from \"vscode-languageserver-textdocument\";\n\nconst service = getLanguageService();\n\n/** The template as an HTML document, with Kiln syntax blanked out so the HTML service only sees the markup. */\nconst htmlOf = (document: TextDocument) => {\n\tconst html = TextDocument.create(\n\t\tdocument.uri,\n\t\t\"html\",\n\t\tdocument.version,\n\t\ttemplateText(document.getText()),\n\t);\n\treturn { html, parsed: service.parseHTMLDocument(html) };\n};\n\n/** HTML elements, attributes and attribute values at `offset`, outside Kiln syntax. */\nexport const htmlCompletions = (\n\tdocument: TextDocument,\n\toffset: number,\n): CompletionItem[] => {\n\tconst { html, parsed } = htmlOf(document);\n\treturn service.doComplete(html, document.positionAt(offset), parsed).items;\n};\n\n/** MDN's description of the HTML element or attribute at `offset`, outside Kiln syntax. */\nexport const htmlHover = (\n\tdocument: TextDocument,\n\toffset: number,\n): Hover | null => {\n\tconst { html, parsed } = htmlOf(document);\n\treturn service.doHover(html, document.positionAt(offset), parsed);\n};\n","import { dirname } from \"node:path\";\nimport type * as TS from \"typescript-6\";\nimport {\n\ttype Member,\n\tsamePath,\n\ttype TypeScriptProject,\n\tvirtualPath,\n} from \"./typescript.js\";\n\n/** A project checked by TypeScript 6's classic API, in this process. */\nexport const openTypeScript6 = (\n\tts: typeof TS,\n\tconfigPath: string,\n): TypeScriptProject => {\n\tconst parseConfig = () => {\n\t\tconst parsed = ts.getParsedCommandLineOfConfigFile(\n\t\t\tconfigPath,\n\t\t\t{},\n\t\t\t{ ...ts.sys, onUnRecoverableConfigFileDiagnostic: () => {} },\n\t\t);\n\t\tif (!parsed) throw new Error(`can't read ${configPath}`);\n\t\treturn parsed;\n\t};\n\tlet config = parseConfig();\n\tconst virtual = virtualPath(configPath, config.fileNames);\n\tlet text = \"\";\n\t/** Bumped when a file changes, so the language service reads it again. */\n\tconst versions = new Map<string, number>();\n\tconst version = (path: string) => versions.get(path) ?? 0;\n\tlet fileNames = [...config.fileNames, virtual];\n\n\tconst read = (path: string) =>\n\t\tsamePath(path, virtual) ? text : ts.sys.readFile(path);\n\tconst service = ts.createLanguageService(\n\t\t{\n\t\t\tgetCompilationSettings: () => config.options,\n\t\t\tgetScriptFileNames: () => fileNames,\n\t\t\tgetScriptVersion: (path) => String(version(path)),\n\t\t\tgetScriptSnapshot: (path) => {\n\t\t\t\tconst content = read(path);\n\t\t\t\treturn content === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: ts.ScriptSnapshot.fromString(content);\n\t\t\t},\n\t\t\tgetCurrentDirectory: () => dirname(configPath),\n\t\t\tgetDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options),\n\t\t\tfileExists: (path) => samePath(path, virtual) || ts.sys.fileExists(path),\n\t\t\treadFile: read,\n\t\t\treadDirectory: (...args) => ts.sys.readDirectory(...args),\n\t\t\tdirectoryExists: (path) => ts.sys.directoryExists(path),\n\t\t\tgetDirectories: (path) => ts.sys.getDirectories(path),\n\t\t},\n\t\tts.createDocumentRegistry(),\n\t);\n\n\treturn {\n\t\tquery(source, use) {\n\t\t\tif (source !== text) {\n\t\t\t\ttext = source;\n\t\t\t\tversions.set(virtual, version(virtual) + 1);\n\t\t\t}\n\t\t\tconst program = service.getProgram();\n\t\t\tconst file = program?.getSourceFile(virtual);\n\t\t\tif (!program || !file) return null;\n\t\t\tconst checker = program.getTypeChecker();\n\t\t\tconst typeOf = (alias: string) => {\n\t\t\t\tconst declaration = file.statements.find(\n\t\t\t\t\t(statement): statement is TS.TypeAliasDeclaration =>\n\t\t\t\t\t\tts.isTypeAliasDeclaration(statement) &&\n\t\t\t\t\t\tstatement.name.text === alias,\n\t\t\t\t);\n\t\t\t\treturn declaration\n\t\t\t\t\t? checker.getTypeAtLocation(declaration.name)\n\t\t\t\t\t: undefined;\n\t\t\t};\n\t\t\treturn use({\n\t\t\t\tdescribe: (alias) => {\n\t\t\t\t\tconst type = typeOf(alias);\n\t\t\t\t\treturn type\n\t\t\t\t\t\t? checker.typeToString(\n\t\t\t\t\t\t\t\ttype,\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\tts.TypeFormatFlags.NoTruncation,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: null;\n\t\t\t\t},\n\t\t\t\tmembers: (alias) => {\n\t\t\t\t\tconst type = typeOf(alias);\n\t\t\t\t\tif (!type) return [];\n\t\t\t\t\treturn checker.getPropertiesOfType(type).map((symbol): Member => {\n\t\t\t\t\t\tconst node = symbol.declarations?.[0];\n\t\t\t\t\t\tconst declaredIn = node?.getSourceFile();\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tname: symbol.name,\n\t\t\t\t\t\t\toptional: (symbol.flags & ts.SymbolFlags.Optional) !== 0,\n\t\t\t\t\t\t\ttype: checker.typeToString(\n\t\t\t\t\t\t\t\tchecker.getTypeOfSymbolAtLocation(symbol, file),\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\tts.TypeFormatFlags.NoTruncation,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tdocs: ts.displayPartsToString(\n\t\t\t\t\t\t\t\tsymbol.getDocumentationComment(checker),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\ttags: symbol.getJsDocTags(checker).map((tag) => ({\n\t\t\t\t\t\t\t\tname: tag.name,\n\t\t\t\t\t\t\t\ttext: ts.displayPartsToString(tag.text),\n\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t\tlocation:\n\t\t\t\t\t\t\t\tnode && declaredIn\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\tpath: declaredIn.fileName,\n\t\t\t\t\t\t\t\t\t\t\t...declaredIn.getLineAndCharacterOfPosition(\n\t\t\t\t\t\t\t\t\t\t\t\tnode.getStart(declaredIn),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t};\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tchanged(changes) {\n\t\t\tfor (const change of changes) {\n\t\t\t\tversions.set(change.path, version(change.path) + 1);\n\t\t\t}\n\t\t\t// A new or deleted file can change which files the config includes.\n\t\t\tif (changes.some((change) => change.kind !== \"changed\")) {\n\t\t\t\tconfig = parseConfig();\n\t\t\t\tfileNames = [...config.fileNames, virtual];\n\t\t\t}\n\t\t},\n\t\tclose() {\n\t\t\tservice.dispose();\n\t\t},\n\t};\n};\n","import { basename, dirname } from \"node:path\";\nimport type * as Sync from \"typescript/unstable/sync\";\nimport {\n\tentriesWith,\n\tlineAndCharacter,\n\ttype Member,\n\tsamePath,\n\ttype TypeScriptProject,\n\tvirtualPath,\n} from \"./typescript.js\";\n\n/** `TypeFormatFlags.NoTruncation`, so long types are written in full. */\nconst NO_TRUNCATION = 1;\n\n/** A project checked by TypeScript 7's API, which runs the native compiler in its own process. */\nexport const openTypeScript7 = (\n\tsync: Pick<typeof Sync, \"API\" | \"SymbolFlags\">,\n\tconfigPath: string,\n): TypeScriptProject => {\n\tlet virtual = \"\";\n\tlet text = \"\";\n\tconst api = new sync.API({\n\t\tcwd: dirname(configPath),\n\t\tfs: {\n\t\t\treadFile: (path) => (samePath(path, virtual) ? text : undefined),\n\t\t\tfileExists: (path) => (samePath(path, virtual) ? true : undefined),\n\t\t\tgetAccessibleEntries: (folder) =>\n\t\t\t\tvirtual && samePath(folder, dirname(virtual))\n\t\t\t\t\t? entriesWith(folder, basename(virtual))\n\t\t\t\t\t: undefined,\n\t\t},\n\t});\n\tvirtual = virtualPath(configPath, api.parseConfigFile(configPath).fileNames);\n\tlet snapshot = api.updateSnapshot({ openProjects: [configPath] });\n\tconst update = (changes: Parameters<typeof api.updateSnapshot>[0]) => {\n\t\tsnapshot.dispose();\n\t\tsnapshot = api.updateSnapshot(changes);\n\t};\n\n\treturn {\n\t\tquery(source, use) {\n\t\t\tif (source !== text) {\n\t\t\t\ttext = source;\n\t\t\t\tupdate({ fileChanges: { changed: [virtual] } });\n\t\t\t}\n\t\t\tconst project = snapshot.getProject(configPath);\n\t\t\tif (!project?.program.getSourceFile(virtual)) return null;\n\t\t\tconst { checker } = project;\n\t\t\tconst typeOf = (alias: string) => {\n\t\t\t\tconst at = text.indexOf(`type ${alias} =`);\n\t\t\t\treturn at === -1\n\t\t\t\t\t? undefined\n\t\t\t\t\t: checker.getTypeAtPosition(virtual, at + \"type \".length);\n\t\t\t};\n\t\t\treturn use({\n\t\t\t\tdescribe: (alias) => {\n\t\t\t\t\tconst type = typeOf(alias);\n\t\t\t\t\treturn type\n\t\t\t\t\t\t? checker.typeToString(type, undefined, NO_TRUNCATION)\n\t\t\t\t\t\t: null;\n\t\t\t\t},\n\t\t\t\tmembers: (alias) => {\n\t\t\t\t\tconst type = typeOf(alias);\n\t\t\t\t\tif (!type) return [];\n\t\t\t\t\treturn checker.getPropertiesOfType(type).map((symbol): Member => {\n\t\t\t\t\t\tconst node = symbol.declarations[0]?.resolve(project);\n\t\t\t\t\t\tconst file = node?.getSourceFile();\n\t\t\t\t\t\tconst memberType = checker.getTypeOfSymbol(symbol);\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tname: symbol.name,\n\t\t\t\t\t\t\toptional: (symbol.flags & sync.SymbolFlags.Optional) !== 0,\n\t\t\t\t\t\t\ttype: memberType\n\t\t\t\t\t\t\t\t? checker.typeToString(memberType, undefined, NO_TRUNCATION)\n\t\t\t\t\t\t\t\t: \"unknown\",\n\t\t\t\t\t\t\tdocs: checker.getDocumentationCommentOfSymbol(symbol),\n\t\t\t\t\t\t\ttags: checker\n\t\t\t\t\t\t\t\t.getJsDocTagsOfSymbol(symbol)\n\t\t\t\t\t\t\t\t.map((tag) => ({ name: tag.name, text: tag.text ?? \"\" })),\n\t\t\t\t\t\t\tlocation:\n\t\t\t\t\t\t\t\tnode && file\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\tpath: file.fileName,\n\t\t\t\t\t\t\t\t\t\t\t...lineAndCharacter(file.text, node.getStart(file)),\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: null,\n\t\t\t\t\t\t};\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tchanged(changes) {\n\t\t\tconst paths = (kind: string) =>\n\t\t\t\tchanges\n\t\t\t\t\t.filter((change) => change.kind === kind)\n\t\t\t\t\t.map((change) => change.path);\n\t\t\tupdate({\n\t\t\t\tfileChanges: {\n\t\t\t\t\tcreated: paths(\"created\"),\n\t\t\t\t\tchanged: paths(\"changed\"),\n\t\t\t\t\tdeleted: paths(\"deleted\"),\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tclose() {\n\t\t\tsnapshot.dispose();\n\t\t\tapi.close();\n\t\t},\n\t};\n};\n","import { readdirSync, readFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join, relative, sep } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { openTypeScript6 } from \"./typescript-6.js\";\nimport { openTypeScript7 } from \"./typescript-7.js\";\n\n/** A place in a TypeScript file. `line` and `character` are zero-based, as in the Language Server Protocol. */\nexport type SourceLocation = { path: string; line: number; character: number };\n\n/** A property of a TypeScript type, with what an editor shows for it. */\nexport type Member = {\n\tname: string;\n\toptional: boolean;\n\t/** The property's type, written out. */\n\ttype: string;\n\t/** Its doc comment, without tags. */\n\tdocs: string;\n\ttags: { name: string; text: string }[];\n\tlocation: SourceLocation | null;\n};\n\n/** Reads the type aliases of the file passed to `TypeScriptProject.query`. */\nexport type TypeQuery = {\n\t/** The alias's type, written out. Null when the alias isn't in the file. */\n\tdescribe(alias: string): string | null;\n\t/** The properties of the alias's type. */\n\tmembers(alias: string): Member[];\n};\n\n/** A file that changed on disk. */\nexport type FileChange = {\n\tpath: string;\n\tkind: \"created\" | \"changed\" | \"deleted\";\n};\n\n/**\n * A project's own TypeScript, loaded from its `tsconfig.json`. The language server asks it about types by checking a\n * generated file of type aliases, which lives in the project's first source folder so it sees the same modules and\n * declarations as the project's own code.\n */\nexport type TypeScriptProject = {\n\t/** Checks `source` as a file in the project and reads it with `use`. Null when TypeScript can't check the file. */\n\tquery<T>(source: string, use: (query: TypeQuery) => T): T | null;\n\t/** Tells TypeScript which files changed on disk. */\n\tchanged(changes: FileChange[]): void;\n\tclose(): void;\n};\n\n/** The generated file's name. Nothing in the project should use it. */\nconst VIRTUAL_NAME = \"__kiln_types__.ts\";\n\n/** Where the generated file goes: the folder of the project's first TypeScript source file, or the config's folder. */\nexport const virtualPath = (\n\tconfigPath: string,\n\tfileNames: readonly string[],\n) => {\n\tconst root = dirname(configPath);\n\tconst source = fileNames.find((name) => {\n\t\tconst path = relative(root, name);\n\t\treturn (\n\t\t\t/\\.[cm]?tsx?$/.test(name) &&\n\t\t\t!/\\.d\\.[cm]?ts$/.test(name) &&\n\t\t\t!path.startsWith(\"..\") &&\n\t\t\t!path.split(sep).includes(\"node_modules\")\n\t\t);\n\t});\n\treturn join(source ? dirname(source) : root, VIRTUAL_NAME);\n};\n\n/** Whether two paths are the same file. TypeScript may change a path's case on case-insensitive file systems. */\nexport const samePath = (a: string, b: string) =>\n\ta === b || a.toLowerCase() === b.toLowerCase();\n\n/** A folder's entries with the generated file added, for TypeScript's include globs. */\nexport const entriesWith = (folder: string, name: string) => {\n\tconst entries = readdirSync(folder, { withFileTypes: true });\n\treturn {\n\t\tfiles: [\n\t\t\t...entries.filter((entry) => entry.isFile()).map((entry) => entry.name),\n\t\t\tname,\n\t\t],\n\t\tdirectories: entries\n\t\t\t.filter((entry) => entry.isDirectory())\n\t\t\t.map((entry) => entry.name),\n\t};\n};\n\n/** The zero-based line and character of an offset in `text`. */\nexport const lineAndCharacter = (text: string, offset: number) => {\n\tconst lines = text.slice(0, offset).split(\"\\n\");\n\treturn { line: lines.length - 1, character: (lines.at(-1) as string).length };\n};\n\n/** The nearest `tsconfig.json` in `folder` or a folder above it. */\nconst findConfig = (folder: string): string | null => {\n\tfor (let current = folder; ; current = dirname(current)) {\n\t\tconst candidate = join(current, \"tsconfig.json\");\n\t\ttry {\n\t\t\treadFileSync(candidate);\n\t\t\treturn candidate;\n\t\t} catch {\n\t\t\t// Keep looking.\n\t\t}\n\t\tif (dirname(current) === current) return null;\n\t}\n};\n\n/**\n * Loads the TypeScript installed for the project in `folder`, with the nearest `tsconfig.json`. Null when either is\n * missing or the version is older than 6. Version 7 and later use TypeScript's new API; version 6 uses the classic one.\n */\nexport const openTypeScript = async (\n\tfolder: string,\n\twarn: (message: string) => void,\n): Promise<TypeScriptProject | null> => {\n\tconst configPath = findConfig(folder);\n\tif (!configPath) return null;\n\tconst require = createRequire(join(folder, \"kiln.json\"));\n\tlet major: number;\n\ttry {\n\t\tconst pkg = JSON.parse(\n\t\t\treadFileSync(require.resolve(\"typescript/package.json\"), \"utf8\"),\n\t\t) as { version: string };\n\t\tmajor = Number(pkg.version.split(\".\")[0]);\n\t} catch {\n\t\treturn null;\n\t}\n\ttry {\n\t\tif (major >= 7) {\n\t\t\tconst sync = (await import(\n\t\t\t\tpathToFileURL(require.resolve(\"typescript/unstable/sync\")).href\n\t\t\t)) as Parameters<typeof openTypeScript7>[0];\n\t\t\treturn openTypeScript7(sync, configPath);\n\t\t}\n\t\tif (major === 6) {\n\t\t\treturn openTypeScript6(\n\t\t\t\trequire(\"typescript\") as Parameters<typeof openTypeScript6>[0],\n\t\t\t\tconfigPath,\n\t\t\t);\n\t\t}\n\t} catch (error) {\n\t\twarn(`Kiln: couldn't load TypeScript. ${(error as Error).message}`);\n\t}\n\treturn null;\n};\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { dirname, join, relative, sep } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport * as bundledKiln from \"@lucidkiln/core\";\nimport type { Diagnostic, Kiln, KilnManifest } from \"@lucidkiln/core\";\nimport * as bundledFormat from \"@lucidkiln/core/format\";\nimport {\n\ttype FileChange,\n\topenTypeScript,\n\ttype TypeScriptProject,\n} from \"./typescript.js\";\n\ntype KilnModule = Pick<typeof bundledKiln, \"createKiln\">;\ntype FormatModule = Pick<\n\ttypeof bundledFormat,\n\t\"formatEdits\" | \"KilnFormatError\"\n>;\n\n/** Diagnostics that need to know the project's names and templates, so they are dropped without a `kiln.json`. */\nconst NEEDS_MANIFEST = new Set([\n\t\"unknown-function\",\n\t\"unknown-filter\",\n\t\"unknown-test\",\n\t\"unknown-type\",\n\t\"missing-template\",\n]);\n\n/**\n * The templates under one `kiln.json`, or a workspace folder without one, and a Kiln environment that checks them.\n *\n * Template names are paths relative to `root`, such as `pages/home.kiln`, as Kiln resolves them.\n */\nexport type Project = {\n\t/** The `kiln.json` file, or null without one. */\n\tmanifestPath: string | null;\n\tmanifest: KilnManifest | null;\n\troot: string;\n\tkiln: Kiln;\n\tformat: FormatModule;\n\t/** Unsaved text of open templates, by name. The loader reads these before the disk. */\n\toverlay: Map<string, string>;\n\t/**\n\t * The project's own TypeScript, started the first time it's needed. Null without `kiln.json`, a `tsconfig.json`, or\n\t * TypeScript 6 or later.\n\t */\n\ttypescript: () => Promise<TypeScriptProject | null>;\n\t/** Tells the project's TypeScript, if it started, which TypeScript files changed on disk. */\n\ttypescriptChanged: (changes: FileChange[]) => void;\n\t/** Stops the project's TypeScript, if it started. */\n\tclose: () => void;\n};\n\n/**\n * Resolves a template name as Kiln does: relative to `from` when it starts with `./` or `../`, with `.kiln` added when the last part has no extension. Null when the name is invalid.\n */\nexport const resolveName = (name: string, from?: string): string | null => {\n\tconst relativeName = name.startsWith(\"./\") || name.startsWith(\"../\");\n\tconst segments =\n\t\trelativeName && from ? from.split(\"/\").slice(0, -1) : ([] as string[]);\n\tfor (const segment of name.split(\"/\")) {\n\t\tif (segment === \"\" || segment === \".\") continue;\n\t\tif (segment === \"..\") {\n\t\t\tif (segments.length === 0) return null;\n\t\t\tsegments.pop();\n\t\t} else segments.push(segment);\n\t}\n\tconst last = segments.at(-1);\n\tif (last === undefined || name.startsWith(\"/\")) return null;\n\tif (!last.includes(\".\")) segments[segments.length - 1] = `${last}.kiln`;\n\treturn segments.join(\"/\");\n};\n\n/** The template name for a file, or null when it is outside the project's root. */\nexport const nameOf = (project: Project, path: string): string | null => {\n\tconst name = relative(project.root, path);\n\tif (name.startsWith(\"..\") || name.startsWith(sep) || name === \"\") return null;\n\treturn name.split(sep).join(\"/\");\n};\n\nexport const pathOf = (project: Project, name: string): string =>\n\tjoin(project.root, ...name.split(\"/\"));\n\n/** Every template under the root, skipping dot folders and node_modules. */\nexport const listTemplates = async (project: Project): Promise<string[]> => {\n\tconst names: string[] = [];\n\tconst visit = async (folder: string, from: string): Promise<void> => {\n\t\t// An unreadable folder should not hide templates found elsewhere in the project.\n\t\tconst entries = await readdir(folder, { withFileTypes: true }).catch(\n\t\t\t() => [],\n\t\t);\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n\t\t\tconst name = from + entry.name;\n\t\t\tif (entry.isDirectory())\n\t\t\t\tawait visit(join(folder, entry.name), name + \"/\");\n\t\t\telse if (entry.isFile() && name.endsWith(\".kiln\")) names.push(name);\n\t\t}\n\t};\n\tawait visit(project.root, \"\");\n\treturn names.sort();\n};\n\n/** The nearest `kiln.json` in `folder` or above it, stopping at `stop` when given. */\nexport const findManifest = async (\n\tfolder: string,\n\tstop: string | null,\n): Promise<string | null> => {\n\tfor (let current = folder; ; current = dirname(current)) {\n\t\tconst candidate = join(current, \"kiln.json\");\n\t\ttry {\n\t\t\tawait readFile(candidate, \"utf8\");\n\t\t\treturn candidate;\n\t\t} catch {\n\t\t\t// Keep looking.\n\t\t}\n\t\tif (current === stop || dirname(current) === current) return null;\n\t}\n};\n\n/** Reads `kiln.json`, filling in defaults. Throws when it isn't valid. */\nexport const readManifest = async (path: string): Promise<KilnManifest> => {\n\tconst data: unknown = JSON.parse(await readFile(path, \"utf8\"));\n\tif (typeof data !== \"object\" || data === null || Array.isArray(data)) {\n\t\tthrow new Error(\"kiln.json must hold an object\");\n\t}\n\tconst field = (key: keyof KilnManifest): string[] => {\n\t\tconst value = (data as Record<string, unknown>)[key];\n\t\tif (value === undefined) return [];\n\t\tif (\n\t\t\t!Array.isArray(value) ||\n\t\t\tvalue.some((item) => typeof item !== \"string\")\n\t\t) {\n\t\t\tthrow new Error(`\"${key}\" in kiln.json must be a list of names`);\n\t\t}\n\t\treturn value;\n\t};\n\tconst {\n\t\troot = \".\",\n\t\tstrict = true,\n\t\thtmlChecks = true,\n\t} = data as Partial<KilnManifest>;\n\tif (typeof root !== \"string\")\n\t\tthrow new Error('\"root\" in kiln.json must be a string');\n\tif (typeof strict !== \"boolean\") {\n\t\tthrow new Error('\"strict\" in kiln.json must be true or false');\n\t}\n\t// createKiln checks the levels inside.\n\tif (\n\t\ttypeof htmlChecks !== \"boolean\" &&\n\t\t(typeof htmlChecks !== \"object\" ||\n\t\t\thtmlChecks === null ||\n\t\t\tArray.isArray(htmlChecks))\n\t) {\n\t\tthrow new Error(\n\t\t\t'\"htmlChecks\" in kiln.json must be true, false or an object',\n\t\t);\n\t}\n\treturn {\n\t\troot,\n\t\tstrict,\n\t\thtmlChecks,\n\t\tfunctions: field(\"functions\"),\n\t\tfilters: field(\"filters\"),\n\t\ttests: field(\"tests\"),\n\t\tglobals: field(\"globals\"),\n\t\ttypes: field(\"types\"),\n\t};\n};\n\n/** Imports an entry point of the copy of Kiln installed in a project, or returns null. */\nconst importInstalled = async <T>(\n\tfrom: string,\n\tentry: \".\" | \"./format\",\n): Promise<T | null> => {\n\tfor (let current = from; ; current = dirname(current)) {\n\t\tconst folder = join(current, \"node_modules\", \"@lucidkiln\", \"core\");\n\t\ttry {\n\t\t\tconst pkg = JSON.parse(\n\t\t\t\tawait readFile(join(folder, \"package.json\"), \"utf8\"),\n\t\t\t) as { exports?: Record<string, { import?: string } | undefined> };\n\t\t\tconst file = pkg.exports?.[entry]?.import;\n\t\t\treturn file\n\t\t\t\t? ((await import(pathToFileURL(join(folder, file)).href)) as T)\n\t\t\t\t: null;\n\t\t} catch {\n\t\t\t// Not installed here, or too old for this entry point.\n\t\t}\n\t\tif (dirname(current) === current) return null;\n\t}\n};\n\nconst stubs = <T>(names: readonly string[], value: T) =>\n\tObject.fromEntries(names.map((name) => [name, value]));\n\n/**\n * Opens the project for a template folder: the nearest `kiln.json`, or `fallbackRoot` without one. Prefers the project's own copy of Kiln, so errors match how it renders.\n *\n * A broken `kiln.json` is reported through `warn`, and the project is opened as if it had none.\n */\nexport const openProject = async (\n\tmanifestPath: string | null,\n\tfallbackRoot: string,\n\twarn: (message: string) => void,\n): Promise<Project> => {\n\tlet manifest: KilnManifest | null = null;\n\tif (manifestPath) {\n\t\ttry {\n\t\t\tmanifest = await readManifest(manifestPath);\n\t\t} catch (error) {\n\t\t\twarn(`Kiln: ignoring ${manifestPath}. ${(error as Error).message}`);\n\t\t}\n\t}\n\tconst root =\n\t\tmanifestPath && manifest\n\t\t\t? join(dirname(manifestPath), manifest.root)\n\t\t\t: fallbackRoot;\n\tconst base = manifestPath ? dirname(manifestPath) : fallbackRoot;\n\tconst { createKiln } =\n\t\t(await importInstalled<KilnModule>(base, \".\")) ?? bundledKiln;\n\tconst format =\n\t\t(await importInstalled<FormatModule>(base, \"./format\")) ?? bundledFormat;\n\n\tconst overlay = new Map<string, string>();\n\tconst options = {\n\t\tloader: {\n\t\t\tload: async (name: string) => {\n\t\t\t\tconst open = overlay.get(name);\n\t\t\t\tif (open !== undefined) return open;\n\t\t\t\tif (!manifest) return null;\n\t\t\t\ttry {\n\t\t\t\t\treturn await readFile(join(root, ...name.split(\"/\")), \"utf8\");\n\t\t\t\t} catch {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t};\n\tlet kiln: Kiln;\n\ttry {\n\t\tkiln = manifest\n\t\t\t? createKiln({\n\t\t\t\t\t...options,\n\t\t\t\t\tfunctions: stubs(manifest.functions, () => null),\n\t\t\t\t\tfilters: stubs(manifest.filters, () => null),\n\t\t\t\t\ttests: stubs(manifest.tests, () => true),\n\t\t\t\t\tglobals: stubs(manifest.globals, null),\n\t\t\t\t\ttypes: stubs(manifest.types, () => true),\n\t\t\t\t\tstrict: manifest.strict,\n\t\t\t\t\thtmlChecks: manifest.htmlChecks,\n\t\t\t\t})\n\t\t\t: createKiln(options);\n\t} catch (error) {\n\t\twarn(`Kiln: ignoring ${manifestPath}. ${(error as Error).message}`);\n\t\tmanifest = null;\n\t\tkiln = createKiln(options);\n\t}\n\tlet typescript: Promise<TypeScriptProject | null> | undefined;\n\tconst folder = manifestPath && manifest ? dirname(manifestPath) : null;\n\treturn {\n\t\tmanifestPath,\n\t\tmanifest,\n\t\troot,\n\t\tkiln,\n\t\tformat,\n\t\toverlay,\n\t\ttypescript: () =>\n\t\t\t(typescript ??= folder\n\t\t\t\t? openTypeScript(folder, warn)\n\t\t\t\t: Promise.resolve(null)),\n\t\ttypescriptChanged: (changes) =>\n\t\t\tvoid typescript?.then((opened) => opened?.changed(changes)),\n\t\tclose: () => void typescript?.then((opened) => opened?.close()),\n\t};\n};\n\n/** Checks a template's text and returns its own diagnostics. */\nexport const diagnose = async (\n\tproject: Project,\n\tname: string,\n\ttext: string,\n): Promise<Diagnostic[]> => {\n\tconst diagnostics = await project.kiln.check(name, text);\n\treturn diagnostics.filter(\n\t\t(diagnostic) =>\n\t\t\tdiagnostic.template === name &&\n\t\t\t(project.manifest !== null || !NEEDS_MANIFEST.has(diagnostic.code)),\n\t);\n};\n","import {\n\ttype Argument,\n\ttype Expression,\n\ttype HashEntry,\n\ttype PropType,\n\tparse,\n\ttype Span,\n\ttype Statement,\n\ttype TemplateNode,\n} from \"@lucidkiln/core/syntax\";\n\n/**\n * Where a variable's value comes from, so its type can be worked out.\n *\n * - `prop`: a `props` entry, or `rest` for `...attributes`.\n * - `set`: `set name = value`. `capture` is a `set` block, which holds markup.\n * - `item`, `key`: a `for` loop's value or key.\n * - `arrow`: an arrow function's parameter, `index` counting from 0, passed to `filter` with `input` before the `|`.\n * - `with`: a key of the hash a `with` tag passes.\n * - `param`, `import`: a macro argument, or a name brought in with `import` or `from`. Their types are unknown.\n */\nexport type BindingSource =\n\t| { kind: \"prop\"; type: PropType[] | null; optional: boolean }\n\t| { kind: \"rest\" }\n\t| { kind: \"set\"; value: Expression }\n\t| { kind: \"capture\" }\n\t| { kind: \"item\" | \"key\"; iterable: Expression }\n\t| { kind: \"arrow\"; filter: string; input: Expression; index: number }\n\t| { kind: \"with\"; value: Expression; key: string }\n\t| { kind: \"param\" | \"import\" };\n\n/** A variable a template brings into scope: where its name is written, and the range of text that can see it. */\nexport type Binding = {\n\tname: string;\n\tsource: BindingSource;\n\t/** The name where it's declared. */\n\tdefinition: Span;\n\t/** The scope it lives in. */\n\tscope: Span;\n\t/** It can be used from here to the end of `scope`. */\n\tfrom: number;\n};\n\nexport type TemplateScopes = { ast: TemplateNode; bindings: Binding[] };\n\n/** Whether a variable can be used at `offset`. A scope's end is exclusive, except at the end of the template. */\nconst sees = (binding: Binding, offset: number, length: number) =>\n\toffset >= binding.from &&\n\t(offset < binding.scope.end || binding.scope.end === length);\n\n/** The offset of `name` as a whole word in `text`, searching `span` from `after`. Falls back to the span's start. */\nconst nameIn = (text: string, span: Span, name: string, after = span.start) => {\n\tconst pattern = new RegExp(`(?<![\\\\w$])${name}(?![\\\\w$])`, \"g\");\n\tpattern.lastIndex = after;\n\tconst match = pattern.exec(text.slice(0, span.end));\n\tconst start = match ? match.index : span.start;\n\treturn { start, end: start + name.length };\n};\n\n/** The expressions directly inside an expression. */\nconst childExpressions = (expression: Expression): Expression[] => {\n\tconst ofArgs = (args: Argument[]) => args.map((arg) => arg.value);\n\tswitch (expression.type) {\n\t\tcase \"Interpolation\":\n\t\t\treturn expression.parts;\n\t\tcase \"Array\":\n\t\t\treturn expression.elements.map((element) =>\n\t\t\t\telement.type === \"Spread\" ? element.value : element,\n\t\t\t);\n\t\tcase \"Hash\":\n\t\t\treturn expression.entries.flatMap((entry: HashEntry) =>\n\t\t\t\tentry.type === \"Spread\" ? [entry.value] : [entry.key, entry.value],\n\t\t\t);\n\t\tcase \"Unary\":\n\t\t\treturn [expression.operand];\n\t\tcase \"Binary\":\n\t\t\treturn [expression.left, expression.right];\n\t\tcase \"Conditional\":\n\t\t\treturn [\n\t\t\t\texpression.test,\n\t\t\t\texpression.consequent,\n\t\t\t\t...(expression.alternate ? [expression.alternate] : []),\n\t\t\t];\n\t\tcase \"Member\":\n\t\t\treturn [expression.object, expression.property];\n\t\tcase \"Call\":\n\t\t\treturn [expression.callee, ...ofArgs(expression.args)];\n\t\tcase \"Filter\":\n\t\tcase \"Test\":\n\t\t\treturn [expression.input, ...ofArgs(expression.args)];\n\t\tcase \"Arrow\":\n\t\t\treturn [expression.body];\n\t\tcase \"OptionalChain\":\n\t\t\treturn [expression.expression];\n\t\tdefault:\n\t\t\treturn [];\n\t}\n};\n\n/** The expressions a statement holds itself, not those in nested statements. */\nconst statementExpressions = (statement: Statement): Expression[] => {\n\tswitch (statement.type) {\n\t\tcase \"Output\":\n\t\t\treturn [statement.expression];\n\t\tcase \"If\":\n\t\t\treturn statement.branches.map((branch) => branch.test);\n\t\tcase \"For\":\n\t\t\treturn [statement.iterable];\n\t\tcase \"Set\":\n\t\t\treturn [statement.value];\n\t\tcase \"Props\":\n\t\t\treturn statement.props.flatMap((prop) =>\n\t\t\t\tprop.default ? [prop.default] : [],\n\t\t\t);\n\t\tcase \"Extends\":\n\t\t\treturn [statement.template];\n\t\tcase \"Include\":\n\t\tcase \"Component\":\n\t\tcase \"Island\":\n\t\t\treturn [statement.template, ...(statement.with ? [statement.with] : [])];\n\t\tcase \"Macro\":\n\t\t\treturn statement.params.flatMap((param) =>\n\t\t\t\tparam.default ? [param.default] : [],\n\t\t\t);\n\t\tcase \"With\":\n\t\t\treturn [statement.value];\n\t\tcase \"Cache\":\n\t\t\treturn [statement.key, ...(statement.seconds ? [statement.seconds] : [])];\n\t\tcase \"Apply\":\n\t\t\treturn statement.filters.flatMap((filter) =>\n\t\t\t\tfilter.args.map((arg) => arg.value),\n\t\t\t);\n\t\tdefault:\n\t\t\treturn [];\n\t}\n};\n\n/** The statement lists inside a statement, and whether each starts a new scope. */\nconst childBodies = (\n\tstatement: Statement,\n): { body: Statement[]; scoped: boolean }[] => {\n\tswitch (statement.type) {\n\t\tcase \"If\":\n\t\t\treturn [\n\t\t\t\t...statement.branches.map((branch) => ({\n\t\t\t\t\tbody: branch.body,\n\t\t\t\t\tscoped: false,\n\t\t\t\t})),\n\t\t\t\t...(statement.alternate\n\t\t\t\t\t? [{ body: statement.alternate, scoped: false }]\n\t\t\t\t\t: []),\n\t\t\t];\n\t\tcase \"For\":\n\t\t\treturn [\n\t\t\t\t{ body: statement.body, scoped: true },\n\t\t\t\t...(statement.alternate\n\t\t\t\t\t? [{ body: statement.alternate, scoped: false }]\n\t\t\t\t\t: []),\n\t\t\t];\n\t\tcase \"Component\":\n\t\t\treturn [\n\t\t\t\t{ body: statement.body, scoped: true },\n\t\t\t\t...statement.fills.map((fill) => ({ body: fill.body, scoped: true })),\n\t\t\t];\n\t\tcase \"SetBlock\":\n\t\tcase \"Add\":\n\t\tcase \"Cache\":\n\t\tcase \"Apply\":\n\t\tcase \"Autoescape\":\n\t\tcase \"Island\":\n\t\tcase \"Slot\":\n\t\t\treturn [{ body: statement.body, scoped: false }];\n\t\tcase \"Block\":\n\t\tcase \"Macro\":\n\t\tcase \"With\":\n\t\t\treturn [{ body: statement.body, scoped: true }];\n\t\tdefault:\n\t\t\treturn [];\n\t}\n};\n\n/** Every expression in a list of statements, including nested ones, outermost first. */\nexport function* expressionsIn(statements: Statement[]): Generator<Expression> {\n\tconst visit = function* (expression: Expression): Generator<Expression> {\n\t\tyield expression;\n\t\tfor (const child of childExpressions(expression)) yield* visit(child);\n\t};\n\tfor (const statement of statements) {\n\t\tfor (const expression of statementExpressions(statement))\n\t\t\tyield* visit(expression);\n\t\tfor (const { body } of childBodies(statement)) yield* expressionsIn(body);\n\t}\n}\n\n/** The innermost expression whose span holds `offset`, and the expressions around it, outermost first. */\nexport const expressionPathAt = (\n\tast: TemplateNode,\n\toffset: number,\n): Expression[] => {\n\tconst path: Expression[] = [];\n\tconst visit = (expression: Expression): boolean => {\n\t\tif (offset < expression.span.start || offset > expression.span.end)\n\t\t\treturn false;\n\t\tpath.push(expression);\n\t\tfor (const child of childExpressions(expression)) {\n\t\t\tif (visit(child)) return true;\n\t\t}\n\t\treturn true;\n\t};\n\tfor (const expression of expressionsIn(ast.body)) {\n\t\tif (visit(expression)) break;\n\t}\n\treturn path;\n};\n\n/**\n * Parses a template and finds every variable it brings into scope, following Kiln's rules: `for`, `with`, `block`,\n * `macro`, `component` and `fill` start a scope, and `set` updates a variable that is already visible or creates one in\n * the current scope.\n */\nexport const templateScopes = (\n\ttext: string,\n\tisTest: (name: string) => boolean,\n): TemplateScopes => {\n\tconst { ast } = parse(text, { isTest });\n\tconst bindings: Binding[] = [];\n\n\tconst visible = (name: string, offset: number) =>\n\t\tbindings.some(\n\t\t\t(binding) => binding.name === name && sees(binding, offset, text.length),\n\t\t);\n\n\tconst arrows = (expression: Expression) => {\n\t\tfor (const node of expressionsIn([\n\t\t\t{ type: \"Output\", expression, span: expression.span },\n\t\t])) {\n\t\t\tif (node.type !== \"Filter\") continue;\n\t\t\tfor (const arg of node.args) {\n\t\t\t\tif (arg.value.type !== \"Arrow\") continue;\n\t\t\t\tconst arrow = arg.value;\n\t\t\t\tconst head = text.slice(arrow.span.start, arrow.body.span.start);\n\t\t\t\tarrow.params.forEach((name, index) => {\n\t\t\t\t\tconst at = nameIn(head, { start: 0, end: head.length }, name);\n\t\t\t\t\tbindings.push({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tsource: {\n\t\t\t\t\t\t\tkind: \"arrow\",\n\t\t\t\t\t\t\tfilter: node.name,\n\t\t\t\t\t\t\tinput: node.input,\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefinition: {\n\t\t\t\t\t\t\tstart: arrow.span.start + at.start,\n\t\t\t\t\t\t\tend: arrow.span.start + at.end,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tscope: arrow.span,\n\t\t\t\t\t\tfrom: arrow.span.start,\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n\n\tconst walk = (statements: Statement[], scope: Span) => {\n\t\tfor (const statement of statements) {\n\t\t\tfor (const expression of statementExpressions(statement))\n\t\t\t\tarrows(expression);\n\t\t\tconst add = (\n\t\t\t\tname: string,\n\t\t\t\tsource: BindingSource,\n\t\t\t\tdefinition: Span,\n\t\t\t\tinner: Span = scope,\n\t\t\t\tfrom = statement.span.end,\n\t\t\t) => bindings.push({ name, source, definition, scope: inner, from });\n\n\t\t\tswitch (statement.type) {\n\t\t\t\tcase \"Props\":\n\t\t\t\t\tfor (const prop of statement.props) {\n\t\t\t\t\t\tadd(\n\t\t\t\t\t\t\tprop.name,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkind: \"prop\",\n\t\t\t\t\t\t\t\ttype: prop.type,\n\t\t\t\t\t\t\t\toptional: prop.default !== null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tstart: prop.span.start,\n\t\t\t\t\t\t\t\tend: prop.span.start + prop.name.length,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tscope,\n\t\t\t\t\t\t\tscope.start,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (statement.rest) {\n\t\t\t\t\t\tconst rest = statement.rest;\n\t\t\t\t\t\tadd(\n\t\t\t\t\t\t\trest,\n\t\t\t\t\t\t\t{ kind: \"rest\" },\n\t\t\t\t\t\t\tnameIn(text, statement.span, rest),\n\t\t\t\t\t\t\tscope,\n\t\t\t\t\t\t\tscope.start,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Set\":\n\t\t\t\tcase \"SetBlock\":\n\t\t\t\t\tif (!visible(statement.name, statement.span.start)) {\n\t\t\t\t\t\tconst after = text.indexOf(\"set\", statement.span.start) + 3;\n\t\t\t\t\t\tadd(\n\t\t\t\t\t\t\tstatement.name,\n\t\t\t\t\t\t\tstatement.type === \"Set\"\n\t\t\t\t\t\t\t\t? { kind: \"set\", value: statement.value }\n\t\t\t\t\t\t\t\t: { kind: \"capture\" },\n\t\t\t\t\t\t\tnameIn(text, statement.span, statement.name, after),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"For\": {\n\t\t\t\t\tconst after = text.indexOf(\"for\", statement.span.start) + 3;\n\t\t\t\t\tconst from = statement.iterable.span.end;\n\t\t\t\t\tif (statement.keyName) {\n\t\t\t\t\t\tadd(\n\t\t\t\t\t\t\tstatement.keyName,\n\t\t\t\t\t\t\t{ kind: \"key\", iterable: statement.iterable },\n\t\t\t\t\t\t\tnameIn(text, statement.span, statement.keyName, after),\n\t\t\t\t\t\t\tstatement.span,\n\t\t\t\t\t\t\tfrom,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tadd(\n\t\t\t\t\t\tstatement.valueName,\n\t\t\t\t\t\t{ kind: \"item\", iterable: statement.iterable },\n\t\t\t\t\t\tnameIn(\n\t\t\t\t\t\t\ttext,\n\t\t\t\t\t\t\tstatement.span,\n\t\t\t\t\t\t\tstatement.valueName,\n\t\t\t\t\t\t\tstatement.keyName\n\t\t\t\t\t\t\t\t? nameIn(text, statement.span, statement.keyName, after).end\n\t\t\t\t\t\t\t\t: after,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tstatement.span,\n\t\t\t\t\t\tfrom,\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"Macro\":\n\t\t\t\t\tfor (const param of statement.params) {\n\t\t\t\t\t\tadd(\n\t\t\t\t\t\t\tparam.name,\n\t\t\t\t\t\t\t{ kind: \"param\" },\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tstart: param.span.start,\n\t\t\t\t\t\t\t\tend: param.span.start + param.name.length,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tstatement.span,\n\t\t\t\t\t\t\tparam.span.end,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"With\":\n\t\t\t\t\tif (statement.value.type === \"Hash\") {\n\t\t\t\t\t\tfor (const entry of statement.value.entries) {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tentry.type !== \"Property\" ||\n\t\t\t\t\t\t\t\tentry.key.type !== \"Literal\" ||\n\t\t\t\t\t\t\t\ttypeof entry.key.value !== \"string\"\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\tadd(\n\t\t\t\t\t\t\t\tentry.key.value,\n\t\t\t\t\t\t\t\t{ kind: \"with\", value: statement.value, key: entry.key.value },\n\t\t\t\t\t\t\t\tentry.key.span,\n\t\t\t\t\t\t\t\tstatement.span,\n\t\t\t\t\t\t\t\tstatement.value.span.end,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"Import\": {\n\t\t\t\t\tconst after = text.lastIndexOf(\" as \", statement.span.end);\n\t\t\t\t\tadd(\n\t\t\t\t\t\tstatement.alias,\n\t\t\t\t\t\t{ kind: \"import\" },\n\t\t\t\t\t\tnameIn(text, statement.span, statement.alias, Math.max(after, 0)),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"FromImport\":\n\t\t\t\t\tfor (const item of statement.names) {\n\t\t\t\t\t\tadd(\n\t\t\t\t\t\t\titem.alias,\n\t\t\t\t\t\t\t{ kind: \"import\" },\n\t\t\t\t\t\t\tnameIn(text, item.span, item.alias, item.span.start),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tfor (const { body, scoped } of childBodies(statement)) {\n\t\t\t\twalk(body, scoped ? statement.span : scope);\n\t\t\t}\n\t\t}\n\t};\n\n\twalk(ast.body, ast.span);\n\treturn { ast, bindings };\n};\n\n/** The variable `name` refers to at `offset`: the one in the innermost scope that can see it there. */\nexport const bindingAt = (\n\tscopes: TemplateScopes,\n\tname: string,\n\toffset: number,\n): Binding | null => {\n\tlet found: Binding | null = null;\n\tfor (const binding of scopes.bindings) {\n\t\tif (binding.name !== name || !sees(binding, offset, scopes.ast.span.end))\n\t\t\tcontinue;\n\t\tif (\n\t\t\t!found ||\n\t\t\tbinding.scope.end - binding.scope.start <\n\t\t\t\tfound.scope.end - found.scope.start\n\t\t) {\n\t\t\tfound = binding;\n\t\t}\n\t}\n\treturn found;\n};\n\n/** Every variable visible at `offset`, innermost first, one per name. */\nexport const bindingsAt = (scopes: TemplateScopes, offset: number) => {\n\tconst names = new Set(scopes.bindings.map((binding) => binding.name));\n\treturn [...names].flatMap((name) => {\n\t\tconst binding = bindingAt(scopes, name, offset);\n\t\treturn binding ? [binding] : [];\n\t});\n};\n","import type { Argument, Expression, PropType } from \"@lucidkiln/core/syntax\";\nimport { splitParameters } from \"./calls.js\";\nimport {\n\ttype BindingSource,\n\tbindingAt,\n\ttype TemplateScopes,\n} from \"./scopes.js\";\nimport type { Member, TypeScriptProject } from \"./typescript.js\";\n\n/**\n * Kiln's rules for values, written as TypeScript helper types. Each Kiln expression becomes a type built from these,\n * and the project's own TypeScript works out what it is.\n *\n * - `Get`: `a.b` and `a[0]`, reading a property, a map's value or a list's item.\n * - `Item`, `Key`: what `for` gives for each pass.\n * - `Result`: what a call gives once Kiln waits for it. `Params` and `Returns` describe the function for hover.\n * - `Members`: the values whose properties a template can read, so lists, maps and primitives complete nothing.\n * - `Last`: a function's last parameter, which named arguments are gathered into.\n * - `Fits`, `NamedFit`: whether an argument fits its parameter. Unknown types always fit, so the editor never guesses.\n */\nconst PRELUDE = `import type { KilnFilters, KilnFunctions, KilnGlobals, KilnTests, KilnTypes, Markup, RenderAware } from \"@lucidkiln/core\";\ntype Named<N extends string> = N extends keyof KilnTypes ? KilnTypes[N] : unknown;\ntype Get<V, K> = NonNullable<V> extends infer O ? O extends ReadonlyMap<unknown, infer M> ? M : O extends readonly (infer I)[] ? (K extends number ? I : unknown) : K extends keyof O ? O[K] : unknown : never;\ntype Item<V> = NonNullable<V> extends infer O ? O extends string ? unknown : O extends readonly (infer I)[] ? I : O extends ReadonlyMap<unknown, infer M> ? M : O extends ReadonlySet<infer S> ? S : O extends Iterable<infer I> ? I : O extends object ? O[keyof O] : unknown : never;\ntype Key<V> = NonNullable<V> extends infer O ? O extends string ? unknown : O extends readonly unknown[] | ReadonlySet<unknown> ? number : O extends ReadonlyMap<infer K, unknown> ? K : O extends object ? keyof O & string : unknown : never;\ntype Returns<F> = F extends RenderAware<any, any, infer R> ? R : F extends (...args: any) => infer R ? R : unknown;\ntype Result<F> = Awaited<Returns<F>>;\ntype Params<F> = F extends RenderAware<any, infer A, any> ? A : F extends (...args: infer A) => any ? A : never;\ntype Tail<A> = A extends readonly [unknown?, ...infer R] ? R : A;\ntype Last<A> = Required<A> extends readonly [...unknown[], infer L] ? L : A extends readonly (infer E)[] ? E : unknown;\ntype Fits<A, P> = [P] extends [never] ? true : unknown extends P ? true : unknown extends A ? true : [Exclude<A, Markup>] extends [P] ? true : false;\ntype NamedFit<L, K, A> = unknown extends L ? \"ok\" : [L] extends [never] ? \"ok\" : NonNullable<L> extends infer O ? string extends keyof O ? \"ok\" : K extends keyof O ? Fits<A, Exclude<O[K], undefined>> extends true ? \"ok\" : \"mismatch\" : \"missing\" : \"ok\";\ntype Members<V> = NonNullable<V> extends infer O ? O extends string | number | boolean | bigint | symbol | Function | Date | Markup | readonly unknown[] | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown> ? never : O : never;\n`;\n\nconst BUILTIN_TYPES: Record<string, string> = {\n\tnull: \"null\",\n\tboolean: \"boolean\",\n\tnumber: \"number\",\n\tstring: \"string | Markup\",\n\tarray: \"readonly unknown[]\",\n\thash: \"Readonly<Record<string, unknown>> | ReadonlyMap<string, unknown>\",\n\tset: \"ReadonlySet<unknown>\",\n\tdate: \"Date\",\n\tmarkup: \"Markup\",\n\tobject: \"object\",\n};\n\n/** A prop's declared type as TypeScript, the same way `generateTypes` writes it. */\nexport const propType = (type: readonly PropType[] | null): string => {\n\tif (type === null) return \"unknown\";\n\tif (type.length === 0) return \"never\";\n\treturn type\n\t\t.map((member): string => {\n\t\t\tif (typeof member === \"string\") return BUILTIN_TYPES[member] ?? \"unknown\";\n\t\t\tif (\"literal\" in member) return JSON.stringify(member.literal);\n\t\t\tif (\"named\" in member) return `Named<${JSON.stringify(member.named)}>`;\n\t\t\tif (\"list\" in member) return `readonly (${propType(member.list)})[]`;\n\t\t\tif (member.shape.length === 0) return \"object\";\n\t\t\tconst keys = member.shape.map(\n\t\t\t\t(key) =>\n\t\t\t\t\t`${JSON.stringify(key.name)}${key.optional ? \"?\" : \"\"}: ${propType(key.type)}`,\n\t\t\t);\n\t\t\treturn `{ ${keys.join(\"; \")} }`;\n\t\t})\n\t\t.join(\" | \");\n};\n\nconst BUILTIN_FUNCTIONS: Record<string, string> = {\n\trange: \"number[]\",\n\tmax: \"number\",\n\tmin: \"number\",\n\tcycle: \"unknown\",\n\tdate: \"Date\",\n\tattrs: \"Markup\",\n\tdump: \"Markup\",\n\tparent: \"Markup\",\n\tblock: \"Markup\",\n};\n\n/** What each built-in filter gives, from the type of the value before the `|` and the types of its arguments. */\nconst BUILTIN_FILTERS: Record<\n\tstring,\n\t(input: string, args: string[]) => string\n> = {\n\tupper: () => \"string\",\n\tlower: () => \"string\",\n\tcapitalize: () => \"string\",\n\ttitle: () => \"string\",\n\ttrim: () => \"string\",\n\treplace: () => \"string\",\n\tsplit: () => \"string[]\",\n\ttruncate: () => \"string\",\n\tstripTags: () => \"string\",\n\turlEncode: () => \"string\",\n\tjson: () => \"Markup\",\n\tescape: () => \"Markup\",\n\traw: () => \"Markup\",\n\tdefault: (input, [fallback = \"string\"]) =>\n\t\t`NonNullable<${input}> | ${fallback}`,\n\tlength: () => \"number\",\n\tfirst: (input) => `Item<${input}>`,\n\tlast: (input) => `Item<${input}>`,\n\tslice: (input) => input,\n\tjoin: () => \"string\",\n\tkeys: (input) => `Key<${input}>[]`,\n\tmerge: (input) => input,\n\treverse: (input) => input,\n\tsort: (input) => input,\n\tmap: () => \"unknown[]\",\n\tfilter: (input) => input,\n\treduce: () => \"unknown\",\n\tfind: (input) => `Item<${input}> | null`,\n\tcolumn: () => \"unknown[]\",\n\tbatch: (input) => `Item<${input}>[][]`,\n\tabs: () => \"number\",\n\tround: () => \"number\",\n\tformatNumber: () => \"string\",\n\tplural: () => \"string\",\n\tformatDate: () => \"string\",\n};\n\n/** The list item an arrow function's parameter gets, by filter: which parameter it is. */\nconst ITEM_PARAMS: Record<string, readonly number[]> = {\n\tmap: [0],\n\tfilter: [0],\n\tfind: [0],\n\tsort: [0, 1],\n\treduce: [1],\n};\n\n/** What a template knows besides its own variables: which names the project registers. */\nexport type TypeContext = {\n\tscopes: TemplateScopes;\n\t/** Function and filter names the project registers, from `kiln.json`. A registered name replaces a built-in. */\n\tfunctions: readonly string[];\n\tfilters: readonly string[];\n\t/** Macros the template defines or imports. Calling one gives markup. */\n\tmacros: ReadonlySet<string>;\n};\n\nconst MAX_DEPTH = 32;\n\n/** The TypeScript type of a variable, from where its value comes from. */\nexport const bindingType = (\n\tsource: BindingSource,\n\tcontext: TypeContext,\n\tdepth = 0,\n): string => {\n\tconst of = (expression: Expression) =>\n\t\texpressionType(expression, context, depth + 1);\n\tswitch (source.kind) {\n\t\tcase \"prop\":\n\t\t\treturn propType(source.type);\n\t\tcase \"rest\":\n\t\t\treturn \"Readonly<Record<string, unknown>>\";\n\t\tcase \"set\":\n\t\t\treturn of(source.value);\n\t\tcase \"capture\":\n\t\t\treturn \"Markup\";\n\t\tcase \"item\":\n\t\t\treturn `Item<${of(source.iterable)}>`;\n\t\tcase \"key\":\n\t\t\treturn `Key<${of(source.iterable)}>`;\n\t\tcase \"arrow\":\n\t\t\treturn ITEM_PARAMS[source.filter]?.includes(source.index)\n\t\t\t\t? `Item<${of(source.input)}>`\n\t\t\t\t: \"unknown\";\n\t\tcase \"with\":\n\t\t\treturn `Get<${of(source.value)}, ${JSON.stringify(source.key)}>`;\n\t\tdefault:\n\t\t\treturn \"unknown\";\n\t}\n};\n\nconst union = (types: string[]) =>\n\ttypes.length === 0 ? \"never\" : [...new Set(types)].join(\" | \");\n\nconst literalKey = (expression: Expression) =>\n\texpression.type === \"Literal\" &&\n\t(typeof expression.value === \"string\" || typeof expression.value === \"number\")\n\t\t? JSON.stringify(expression.value)\n\t\t: null;\n\n/** Writes the TypeScript type of a Kiln expression, using the helper types in `PRELUDE`. */\nexport const expressionType = (\n\texpression: Expression,\n\tcontext: TypeContext,\n\tdepth = 0,\n): string => {\n\tif (depth > MAX_DEPTH) return \"unknown\";\n\tconst of = (inner: Expression) => expressionType(inner, context, depth + 1);\n\tconst args = (list: Argument[]) =>\n\t\tlist.map((arg) => (arg.type === \"Spread\" ? \"unknown\" : of(arg.value)));\n\n\tswitch (expression.type) {\n\t\tcase \"Literal\":\n\t\t\treturn expression.value === null ? \"null\" : typeof expression.value;\n\t\tcase \"Interpolation\":\n\t\t\treturn \"string\";\n\t\tcase \"Array\":\n\t\t\treturn `(${union(\n\t\t\t\texpression.elements.map((element) =>\n\t\t\t\t\telement.type === \"Spread\"\n\t\t\t\t\t\t? `Item<${of(element.value)}>`\n\t\t\t\t\t\t: of(element),\n\t\t\t\t),\n\t\t\t)})[]`;\n\t\tcase \"Hash\": {\n\t\t\tconst keys = expression.entries.flatMap((entry) => {\n\t\t\t\tif (entry.type === \"Spread\") return [];\n\t\t\t\tconst key =\n\t\t\t\t\tentry.key.type === \"Name\"\n\t\t\t\t\t\t? JSON.stringify(entry.key.name)\n\t\t\t\t\t\t: literalKey(entry.key);\n\t\t\t\treturn key ? [`${key}: ${of(entry.value)}`] : [];\n\t\t\t});\n\t\t\treturn `{ ${keys.join(\"; \")} }`;\n\t\t}\n\t\tcase \"Unary\":\n\t\t\treturn expression.operator === \"not\" ? \"boolean\" : \"number\";\n\t\tcase \"Binary\":\n\t\t\tswitch (expression.operator) {\n\t\t\t\tcase \"??\":\n\t\t\t\tcase \"?:\":\n\t\t\t\t\treturn `NonNullable<${of(expression.left)}> | ${of(expression.right)}`;\n\t\t\t\tcase \"~\":\n\t\t\t\t\treturn \"string\";\n\t\t\t\tcase \"..\":\n\t\t\t\t\treturn \"number[]\";\n\t\t\t\tcase \"+\":\n\t\t\t\tcase \"-\":\n\t\t\t\tcase \"*\":\n\t\t\t\tcase \"/\":\n\t\t\t\tcase \"//\":\n\t\t\t\tcase \"%\":\n\t\t\t\tcase \"**\":\n\t\t\t\t\treturn \"number\";\n\t\t\t\tdefault:\n\t\t\t\t\treturn \"boolean\";\n\t\t\t}\n\t\tcase \"Conditional\":\n\t\t\treturn union([\n\t\t\t\tof(expression.consequent),\n\t\t\t\texpression.alternate ? of(expression.alternate) : \"null\",\n\t\t\t]);\n\t\tcase \"Member\": {\n\t\t\tconst key = literalKey(expression.property) ?? \"string\";\n\t\t\treturn `Get<${of(expression.object)}, ${key}>`;\n\t\t}\n\t\tcase \"Call\": {\n\t\t\tconst { callee } = expression;\n\t\t\tif (callee.type === \"Member\") {\n\t\t\t\tconst key = literalKey(callee.property) ?? \"string\";\n\t\t\t\treturn `Result<Get<${of(callee.object)}, ${key}>>`;\n\t\t\t}\n\t\t\tif (callee.type !== \"Name\") return \"unknown\";\n\t\t\tconst name = callee.name;\n\t\t\tif (context.macros.has(name)) return \"Markup\";\n\t\t\tconst builtin = BUILTIN_FUNCTIONS[name];\n\t\t\tif (builtin && !context.functions.includes(name)) return builtin;\n\t\t\treturn `Result<Get<KilnFunctions, ${JSON.stringify(name)}>>`;\n\t\t}\n\t\tcase \"Filter\": {\n\t\t\tconst input = of(expression.input);\n\t\t\tconst builtin = BUILTIN_FILTERS[expression.name];\n\t\t\tif (!builtin || context.filters.includes(expression.name)) {\n\t\t\t\treturn `Result<Get<KilnFilters, ${JSON.stringify(expression.name)}>>`;\n\t\t\t}\n\t\t\tconst arrow = expression.args[0]?.value;\n\t\t\tif (expression.name === \"map\" && arrow?.type === \"Arrow\") {\n\t\t\t\treturn `(${of(arrow.body)})[]`;\n\t\t\t}\n\t\t\treturn builtin(input, args(expression.args));\n\t\t}\n\t\tcase \"Test\":\n\t\t\treturn \"boolean\";\n\t\tcase \"OptionalChain\":\n\t\t\treturn of(expression.expression);\n\t\tcase \"Name\": {\n\t\t\tif (expression.name === \"loop\") return \"unknown\";\n\t\t\tconst binding = bindingAt(\n\t\t\t\tcontext.scopes,\n\t\t\t\texpression.name,\n\t\t\t\texpression.span.start,\n\t\t\t);\n\t\t\tif (binding) return bindingType(binding.source, context, depth + 1);\n\t\t\treturn `Get<KilnGlobals, ${JSON.stringify(expression.name)}>`;\n\t\t}\n\t\tdefault:\n\t\t\treturn \"unknown\";\n\t}\n};\n\n/** The registries a project describes in TypeScript, by the kind of name the language server looks up. */\nexport const REGISTRIES = {\n\tfunction: \"KilnFunctions\",\n\tfilter: \"KilnFilters\",\n\ttest: \"KilnTests\",\n\tglobal: \"KilnGlobals\",\n} as const;\n\n/** Checks a file of `type name = type` aliases with the project's TypeScript, and reads it with `use`. */\nexport const withTypes = <T>(\n\ttypescript: TypeScriptProject,\n\taliases: Record<string, string>,\n\tuse: (read: {\n\t\tdescribe: (alias: string) => string | null;\n\t\tmembers: (alias: string) => Member[];\n\t}) => T,\n): T | null => {\n\tconst source =\n\t\tPRELUDE +\n\t\tObject.entries(aliases)\n\t\t\t.map(([name, type]) => `type ${name} = ${type};\\n`)\n\t\t\t.join(\"\");\n\treturn typescript.query(source, use);\n};\n\n/** The TypeScript type of a registered function, filter or test, by kind and name. */\nconst callableType = (kind: keyof typeof REGISTRIES, name: string) =>\n\t`Get<${REGISTRIES[kind]}, ${JSON.stringify(name)}>`;\n\n/** Its parameters as a tuple: a filter's first parameter is the value before the `|`, so `withInput` keeps it. */\nexport const parametersType = (\n\tkind: \"function\" | \"filter\" | \"test\",\n\tname: string,\n\twithInput = false,\n) => {\n\tconst params = `Params<${callableType(kind, name)}>`;\n\treturn kind === \"function\" || withInput ? params : `Tail<${params}>`;\n};\n\n/** A described function, filter or test: its signature and where each parameter sits in it. */\nexport type Signature = {\n\tlabel: string;\n\tparameters: { name: string; start: number; end: number }[];\n\tmember: Member;\n};\n\n/** A host function, filter or test as hover shows it, such as `documents(collection: string): Promise<Page[]>`. */\nexport const describeCallable = (\n\ttypescript: TypeScriptProject,\n\tkind: \"function\" | \"filter\" | \"test\",\n\tname: string,\n): Signature | null =>\n\twithTypes(\n\t\ttypescript,\n\t\t{\n\t\t\tRegistry: REGISTRIES[kind],\n\t\t\tParameters: parametersType(kind, name),\n\t\t\tReturn: `Returns<${callableType(kind, name)}>`,\n\t\t},\n\t\t(read) => {\n\t\t\tconst member = read\n\t\t\t\t.members(\"Registry\")\n\t\t\t\t.find((item) => item.name === name);\n\t\t\tconst parameters = read.describe(\"Parameters\");\n\t\t\tconst result = read.describe(\"Return\");\n\t\t\tif (!member || !parameters || !result) return null;\n\t\t\tconst list = parameters.replace(/^\\[|\\]$/g, \"\");\n\t\t\tconst prefix = `${kind === \"filter\" ? \"|\" : kind === \"test\" ? \"is \" : \"\"}${name}(`;\n\t\t\treturn {\n\t\t\t\tlabel: `${prefix}${list}): ${result}`,\n\t\t\t\tparameters: splitParameters(list).map((part) => ({\n\t\t\t\t\tname: /^(?:\\.\\.\\.)?([\\w$]+)/.exec(part.text)?.[1] ?? part.text,\n\t\t\t\t\tstart: prefix.length + part.start,\n\t\t\t\t\tend: prefix.length + part.end,\n\t\t\t\t})),\n\t\t\t\tmember,\n\t\t\t};\n\t\t},\n\t);\n\n/** The names a function or filter takes as named arguments: the properties of its last parameter. */\nexport const namedOptions = (\n\ttypescript: TypeScriptProject,\n\tkind: \"function\" | \"filter\",\n\tname: string,\n): Member[] =>\n\twithTypes(\n\t\ttypescript,\n\t\t{ Options: `Members<Last<${parametersType(kind, name)}>>` },\n\t\t(read) => read.members(\"Options\"),\n\t) ?? [];\n\n/** One argument to check: its type, and the parameter it goes to, by position or by name. */\nexport type ArgumentCheck = {\n\ttype: string;\n\tparameters: string;\n} & ({ index: number } | { name: string });\n\n/** What's wrong with an argument, with the types to show: `missing` is a named argument the function doesn't take. */\nexport type ArgumentProblem =\n\t| { kind: \"mismatch\"; expected: string; actual: string }\n\t| { kind: \"missing\" };\n\n/** Checks arguments against their parameters with one TypeScript query. Null for an argument that fits. */\nexport const checkArguments = (\n\ttypescript: TypeScriptProject,\n\tchecks: ArgumentCheck[],\n): (ArgumentProblem | null)[] => {\n\tif (checks.length === 0) return [];\n\tconst aliases: Record<string, string> = {};\n\tchecks.forEach((check, index) => {\n\t\tconst expected =\n\t\t\t\"index\" in check\n\t\t\t\t? `Required<${check.parameters}>[${check.index}]`\n\t\t\t\t: `Exclude<Get<Last<${check.parameters}>, ${JSON.stringify(check.name)}>, undefined>`;\n\t\taliases[`Fit${index}`] =\n\t\t\t\"index\" in check\n\t\t\t\t? `Fits<${check.type}, ${expected}> extends true ? \"ok\" : \"mismatch\"`\n\t\t\t\t: `NamedFit<Last<${check.parameters}>, ${JSON.stringify(check.name)}, ${check.type}>`;\n\t\taliases[`Expected${index}`] = expected;\n\t\taliases[`Actual${index}`] = check.type;\n\t});\n\treturn (\n\t\twithTypes(typescript, aliases, (read) =>\n\t\t\tchecks.map((_, index): ArgumentProblem | null => {\n\t\t\t\tconst fit = read.describe(`Fit${index}`);\n\t\t\t\tif (fit === '\"missing\"') return { kind: \"missing\" };\n\t\t\t\tif (fit !== '\"mismatch\"') return null;\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"mismatch\",\n\t\t\t\t\texpected: read.describe(`Expected${index}`) ?? \"unknown\",\n\t\t\t\t\tactual: read.describe(`Actual${index}`) ?? \"unknown\",\n\t\t\t\t};\n\t\t\t}),\n\t\t) ?? checks.map(() => null)\n\t);\n};\n","import { readFile } from \"node:fs/promises\";\nimport { pathToFileURL } from \"node:url\";\nimport type { AnalysedProp, Analysis, PropType } from \"@lucidkiln/core\";\nimport type { Expression, Span } from \"@lucidkiln/core/syntax\";\nimport {\n\ttype CompletionItem,\n\tCompletionItemKind,\n\ttype DocumentLink,\n\ttype DocumentSymbol,\n\ttype Hover,\n\tInsertTextFormat,\n\tInsertTextMode,\n\ttype LocationLink,\n\tMarkupKind,\n\ttype SignatureHelp,\n\tSymbolKind,\n} from \"vscode-languageserver\";\nimport type { TextDocument } from \"vscode-languageserver-textdocument\";\nimport {\n\ttype BuiltinDoc,\n\tFILTERS,\n\tFUNCTIONS,\n\tKEYWORDS,\n\tLOOP_PROPERTIES,\n\tTAGS,\n\tTESTS,\n} from \"./builtins.js\";\nimport { callContext, splitParameters } from \"./calls.js\";\nimport {\n\tcursorContext,\n\tenclosingDelimiter,\n\tsymbolAt,\n\ttemplateStrings,\n} from \"./context.js\";\nimport { type DocKind, docsFor } from \"./docs.js\";\nimport { htmlCompletions, htmlHover } from \"./html.js\";\nimport { listTemplates, pathOf, type Project, resolveName } from \"./project.js\";\nimport {\n\ttype Binding,\n\tbindingAt,\n\tbindingsAt,\n\texpressionPathAt,\n\texpressionsIn,\n\ttype TemplateScopes,\n\ttemplateScopes,\n} from \"./scopes.js\";\nimport {\n\ttype ArgumentCheck,\n\tbindingType,\n\tcheckArguments,\n\tdescribeCallable,\n\texpressionType,\n\tnamedOptions,\n\tparametersType,\n\tREGISTRIES,\n\ttype TypeContext,\n\twithTypes,\n} from \"./types.js\";\nimport type { Member, SourceLocation } from \"./typescript.js\";\n\n/** A template open in the editor, with its project and template name. */\nexport type OpenTemplate = {\n\tdocument: TextDocument;\n\tproject: Project;\n\t/** Null when the file is outside the project's root. */\n\tname: string | null;\n};\n\nconst analyse = async (\n\tproject: Project,\n\tname: string,\n\ttext?: string,\n): Promise<Analysis | null> => {\n\ttry {\n\t\treturn await project.kiln.analyze(name, text);\n\t} catch {\n\t\treturn null;\n\t}\n};\n\n/** Writes a prop type as it appears in `props`, such as `\"a\" | \"b\"` or `{ url?: string }[]`. */\nexport const describeType = (type: readonly PropType[] | null): string => {\n\tif (type === null) return \"any\";\n\treturn type\n\t\t.map((member): string => {\n\t\t\tif (typeof member === \"string\") return member;\n\t\t\tif (\"literal\" in member) return JSON.stringify(member.literal);\n\t\t\tif (\"named\" in member) return member.named;\n\t\t\tif (\"list\" in member) {\n\t\t\t\tconst inner = describeType(member.list);\n\t\t\t\treturn member.list.length > 1 ? `(${inner})[]` : `${inner}[]`;\n\t\t\t}\n\t\t\tconst keys = member.shape.map(\n\t\t\t\t(key) =>\n\t\t\t\t\t`${key.name}${key.optional ? \"?\" : \"\"}: ${describeType(key.type)}`,\n\t\t\t);\n\t\t\treturn `{ ${keys.join(\", \")} }`;\n\t\t})\n\t\t.join(\" | \");\n};\n\nconst describeProp = (prop: AnalysedProp) =>\n\t`${prop.name}${prop.required ? \"\" : \"?\"}: ${describeType(prop.type)}`;\n\nconst markdown = (value: string) => ({ kind: MarkupKind.Markdown, value });\n\n/** Markdown for an item's docs, or nothing when it has none. */\nconst documentation = (kind: DocKind, name: string) => {\n\tconst docs = docsFor(kind, name);\n\treturn docs ? markdown(docs) : undefined;\n};\n\nconst builtinItems = (\n\tbuiltins: Record<string, BuiltinDoc>,\n\tdocKind: DocKind,\n\tkind: CompletionItemKind,\n\textra: readonly string[],\n): CompletionItem[] => [\n\t...Object.entries(builtins).map(([label, doc]) => ({\n\t\tlabel,\n\t\tkind,\n\t\tdetail: doc.signature,\n\t\tdocumentation: documentation(docKind, label),\n\t})),\n\t...extra\n\t\t.filter((name) => !(name in builtins))\n\t\t.map((label) => ({ label, kind, detail: \"From your project\" })),\n];\n\n/** Parses a template and finds its variables, with what `expressionType` needs to work out their types. */\nconst templateTypes = (\n\topen: OpenTemplate,\n\ttext: string,\n): { scopes: TemplateScopes; context: TypeContext } => {\n\tconst manifest = open.project.manifest;\n\tconst scopes = templateScopes(\n\t\ttext,\n\t\t(name) => name in TESTS || (manifest?.tests.includes(name) ?? false),\n\t);\n\tconst macros = new Set([\n\t\t...macrosIn(text).keys(),\n\t\t...scopes.bindings\n\t\t\t.filter((binding) => binding.source.kind === \"import\")\n\t\t\t.map((binding) => binding.name),\n\t]);\n\treturn {\n\t\tscopes,\n\t\tcontext: {\n\t\t\tscopes,\n\t\t\tfunctions: manifest?.functions ?? [],\n\t\t\tfilters: manifest?.filters ?? [],\n\t\t\tmacros,\n\t\t},\n\t};\n};\n\n/** The property under the cursor in `a.b`, with the expression it's read from. */\nconst propertyAt = (\n\tscopes: TemplateScopes,\n\ttext: string,\n\toffset: number,\n): { name: string; object: Expression; span: Span } | null => {\n\tconst path = expressionPathAt(scopes.ast, offset);\n\tfor (let index = path.length - 1; index >= 0; index--) {\n\t\tconst node = path[index] as Expression;\n\t\tif (node.type !== \"Member\") continue;\n\t\tconst { property } = node;\n\t\tif (\n\t\t\tproperty.type === \"Literal\" &&\n\t\t\ttypeof property.value === \"string\" &&\n\t\t\toffset >= property.span.start &&\n\t\t\toffset <= property.span.end &&\n\t\t\ttext[property.span.start - 1] === \".\"\n\t\t) {\n\t\t\treturn { name: property.value, object: node.object, span: property.span };\n\t\t}\n\t}\n\treturn null;\n};\n\n/** A member's doc comment and tags, as Markdown. */\nconst memberDocs = (member: Member) =>\n\t[\n\t\tmember.docs,\n\t\t...member.tags.map((tag) => `*@${tag.name}* ${tag.text}`.trim()),\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\"\\n\\n\");\n\n/** The properties TypeScript finds on the value of `object`. Empty without TypeScript. */\nconst membersOf = async (\n\topen: OpenTemplate,\n\tobject: Expression,\n\tcontext: TypeContext,\n): Promise<Member[]> => {\n\tconst typescript = await open.project.typescript();\n\tif (!typescript) return [];\n\tconst type = expressionType(object, context);\n\treturn (\n\t\twithTypes(typescript, { Value: `Members<${type}>` }, (read) =>\n\t\t\tread.members(\"Value\"),\n\t\t) ?? []\n\t);\n};\n\n/** A function, filter, test or global the project describes in TypeScript. */\nconst registered = async (\n\topen: OpenTemplate,\n\tkind: keyof typeof REGISTRIES,\n\tname: string,\n): Promise<Member | null> => {\n\tconst typescript = await open.project.typescript();\n\tif (!typescript) return null;\n\treturn (\n\t\twithTypes(typescript, { Registry: REGISTRIES[kind] }, (read) =>\n\t\t\tread.members(\"Registry\").find((member) => member.name === name),\n\t\t) ?? null\n\t);\n};\n\nconst BINDING_NOTES: Record<Binding[\"source\"][\"kind\"], string> = {\n\tprop: \"A prop of this template.\",\n\trest: \"The variables passed to this template that it doesn't declare.\",\n\tset: \"Set in this template.\",\n\tcapture: \"Set in this template, from a `set` block.\",\n\titem: \"A loop variable.\",\n\tkey: \"A loop variable.\",\n\tarrow: \"An arrow function's parameter.\",\n\twith: \"From the `with` tag.\",\n\tparam: \"A macro argument.\",\n\timport: \"Imported macros.\",\n};\n\nexport const complete = async (\n\topen: OpenTemplate,\n\toffset: number,\n): Promise<CompletionItem[]> => {\n\tconst { document, project, name } = open;\n\tconst text = document.getText();\n\tconst context = cursorContext(text, offset);\n\tif (!context) {\n\t\treturn enclosingDelimiter(text, offset)\n\t\t\t? []\n\t\t\t: htmlCompletions(document, offset);\n\t}\n\tconst replace = (end = offset) => ({\n\t\tstart: document.positionAt(context.start),\n\t\tend: document.positionAt(end),\n\t});\n\tconst manifest = project.manifest;\n\n\tswitch (context.kind) {\n\t\tcase \"tag\": {\n\t\t\tconst items: CompletionItem[] = Object.entries(TAGS).map(\n\t\t\t\t([label, tag]) => ({\n\t\t\t\t\tlabel,\n\t\t\t\t\tkind: CompletionItemKind.Keyword,\n\t\t\t\t\tdocumentation: documentation(\"tags\", label),\n\t\t\t\t\tinsertTextFormat: InsertTextFormat.Snippet,\n\t\t\t\t\tinsertTextMode: InsertTextMode.adjustIndentation,\n\t\t\t\t\t// Replaces a `%}` already on the line, since the snippet brings its own.\n\t\t\t\t\ttextEdit: {\n\t\t\t\t\t\trange: replace(context.end ?? offset),\n\t\t\t\t\t\tnewText: tag.snippet,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (context.open) {\n\t\t\t\tconst label = `end${context.open}`;\n\t\t\t\titems.unshift({\n\t\t\t\t\tlabel,\n\t\t\t\t\tkind: CompletionItemKind.Keyword,\n\t\t\t\t\tdetail: `Closes the open ${context.open}`,\n\t\t\t\t\tsortText: \"0\",\n\t\t\t\t\ttextEdit: {\n\t\t\t\t\t\trange: replace(context.end ?? offset),\n\t\t\t\t\t\tnewText: `${label} %}`,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn items;\n\t\t}\n\t\tcase \"template\": {\n\t\t\tconst templates = await listTemplates(project);\n\t\t\treturn templates.map((template) => {\n\t\t\t\tconst label = template.replace(/\\.kiln$/, \"\");\n\t\t\t\treturn {\n\t\t\t\t\tlabel,\n\t\t\t\t\tkind: CompletionItemKind.File,\n\t\t\t\t\ttextEdit: { range: replace(), newText: label },\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\t\tcase \"filter\":\n\t\t\treturn builtinItems(\n\t\t\t\tFILTERS,\n\t\t\t\t\"filters\",\n\t\t\t\tCompletionItemKind.Function,\n\t\t\t\tmanifest?.filters ?? [],\n\t\t\t);\n\t\tcase \"test\":\n\t\t\treturn builtinItems(\n\t\t\t\tTESTS,\n\t\t\t\t\"tests\",\n\t\t\t\tCompletionItemKind.Function,\n\t\t\t\tmanifest?.tests ?? [],\n\t\t\t);\n\t\tcase \"member\": {\n\t\t\t// A placeholder name lets the template parse while nothing follows the dot yet.\n\t\t\tconst patched =\n\t\t\t\tcontext.start === offset\n\t\t\t\t\t? `${text.slice(0, offset)}__kiln__${text.slice(offset)}`\n\t\t\t\t\t: text;\n\t\t\tconst types = templateTypes(open, patched);\n\t\t\tconst property = propertyAt(types.scopes, patched, context.start);\n\t\t\tif (!property) return [];\n\t\t\tconst members = await membersOf(open, property.object, types.context);\n\t\t\treturn members.map((member) => ({\n\t\t\t\tlabel: member.name,\n\t\t\t\tkind: CompletionItemKind.Property,\n\t\t\t\tdetail: `${member.name}${member.optional ? \"?\" : \"\"}: ${member.type}`,\n\t\t\t\tdocumentation: memberDocs(member)\n\t\t\t\t\t? markdown(memberDocs(member))\n\t\t\t\t\t: undefined,\n\t\t\t\ttextEdit: { range: replace(), newText: member.name },\n\t\t\t}));\n\t\t}\n\t\tcase \"loop\":\n\t\t\treturn Object.entries(LOOP_PROPERTIES).map(([label, description]) => ({\n\t\t\t\tlabel,\n\t\t\t\tkind: CompletionItemKind.Property,\n\t\t\t\tdocumentation: markdown(description),\n\t\t\t}));\n\t\tcase \"prop\": {\n\t\t\tconst target = resolveName(context.template, name ?? undefined);\n\t\t\tconst analysis = target ? await analyse(project, target) : null;\n\t\t\treturn (analysis?.props ?? []).map((prop) => ({\n\t\t\t\tlabel: prop.name,\n\t\t\t\tkind: CompletionItemKind.Field,\n\t\t\t\tdetail: describeProp(prop),\n\t\t\t\tinsertText: `${prop.name}: `,\n\t\t\t}));\n\t\t}\n\t\tcase \"expression\": {\n\t\t\tconst analysis = name ? await analyse(project, name, text) : null;\n\t\t\tconst { scopes } = templateTypes(open, text);\n\t\t\tconst variables = new Set([\n\t\t\t\t...(analysis?.props.map((prop) => prop.name) ?? []),\n\t\t\t\t...(analysis?.rest ? [analysis.rest] : []),\n\t\t\t\t...bindingsAt(scopes, offset).map((binding) => binding.name),\n\t\t\t\t...macrosIn(text).keys(),\n\t\t\t\t...(manifest?.globals ?? []),\n\t\t\t]);\n\t\t\tconst props = new Map(analysis?.props.map((prop) => [prop.name, prop]));\n\t\t\tconst named = await namedArgumentItems(open, text, offset);\n\t\t\treturn [\n\t\t\t\t...named,\n\t\t\t\t...[...variables].map((label) => {\n\t\t\t\t\tconst prop = props.get(label);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tlabel,\n\t\t\t\t\t\tkind: CompletionItemKind.Variable,\n\t\t\t\t\t\tdetail: prop ? describeProp(prop) : undefined,\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t\t...builtinItems(\n\t\t\t\t\tFUNCTIONS,\n\t\t\t\t\t\"functions\",\n\t\t\t\t\tCompletionItemKind.Function,\n\t\t\t\t\tmanifest?.functions ?? [],\n\t\t\t\t),\n\t\t\t\t...KEYWORDS.map((label) => ({\n\t\t\t\t\tlabel,\n\t\t\t\t\tkind: CompletionItemKind.Keyword,\n\t\t\t\t})),\n\t\t\t];\n\t\t}\n\t}\n};\n\n/** The `{% macro name(params) %}` definitions in a template, by name. */\nconst macrosIn = (text: string) =>\n\tnew Map(\n\t\t[...text.matchAll(/\\{%-?\\s*macro\\s+(\\w+)\\s*\\(([^)]*)\\)/g)].map((match) => [\n\t\t\tmatch[1] as string,\n\t\t\t{ params: (match[2] as string).trim(), start: match.index as number },\n\t\t]),\n\t);\n\nconst codeBlock = (code: string, language = \"kiln\") =>\n\t`\\`\\`\\`${language}\\n${code}\\n\\`\\`\\``;\n\n/** A hover's parts, such as a signature and its docs, with a rule between each. Missing parts are left out. */\nconst sections = (...parts: (string | null | undefined)[]) =>\n\tparts.filter(Boolean).join(\"\\n\\n---\\n\\n\");\n\n/** A tag's syntax, from its completion snippet: named placeholders become their names, and the rest become `…`. */\nconst tagSyntax = (snippet: string) =>\n\t`{% ${snippet.replace(/\\$\\{\\d+:([^}]*)\\}/g, \"$1\").replace(/\\$\\{?\\d+\\}?/g, \"…\")}`;\n\n/** A registered function, filter or test as the project's TypeScript describes it: its signature, then its docs. */\nconst describedCallable = async (\n\topen: OpenTemplate,\n\tkind: \"function\" | \"filter\" | \"test\",\n\tname: string,\n) => {\n\tconst typescript = await open.project.typescript();\n\tconst described = typescript\n\t\t? describeCallable(typescript, kind, name)\n\t\t: null;\n\treturn described\n\t\t? sections(codeBlock(described.label, \"ts\"), memberDocs(described.member))\n\t\t: null;\n};\n\n/** The variable a name refers to: the one it declares when the cursor is on a declaration, or the one in scope. */\nconst bindingFor = (\n\tscopes: TemplateScopes,\n\tsymbol: { name: string; start: number },\n) =>\n\tscopes.bindings.find(\n\t\t(binding) =>\n\t\t\tbinding.name === symbol.name &&\n\t\t\tsymbol.start >= binding.definition.start &&\n\t\t\tsymbol.start < binding.definition.end,\n\t) ?? bindingAt(scopes, symbol.name, symbol.start);\n\n/** The property under the cursor in `a.b`, and what TypeScript knows about it. */\nconst memberAt = async (open: OpenTemplate, text: string, offset: number) => {\n\tconst types = templateTypes(open, text);\n\tconst property = propertyAt(types.scopes, text, offset);\n\tif (!property) return null;\n\tconst members = await membersOf(open, property.object, types.context);\n\tconst member = members.find((item) => item.name === property.name);\n\treturn member ? { member, span: property.span } : null;\n};\n\nexport const hover = async (\n\topen: OpenTemplate,\n\toffset: number,\n): Promise<Hover | null> => {\n\tconst { document, project, name } = open;\n\tconst text = document.getText();\n\tconst symbol = symbolAt(text, offset);\n\tconst rangeOf = (span: Span) => ({\n\t\tstart: document.positionAt(span.start),\n\t\tend: document.positionAt(span.end),\n\t});\n\tif (!symbol) {\n\t\tif (!enclosingDelimiter(text, offset)) return htmlHover(document, offset);\n\t\tconst found = await memberAt(open, text, offset);\n\t\tif (!found) return null;\n\t\tconst { member } = found;\n\t\treturn {\n\t\t\tcontents: markdown(\n\t\t\t\tsections(\n\t\t\t\t\tcodeBlock(\n\t\t\t\t\t\t`${member.name}${member.optional ? \"?\" : \"\"}: ${member.type}`,\n\t\t\t\t\t\t\"ts\",\n\t\t\t\t\t),\n\t\t\t\t\tmemberDocs(member),\n\t\t\t\t),\n\t\t\t),\n\t\t\trange: rangeOf(found.span),\n\t\t};\n\t}\n\tconst fromProject = (names: readonly string[] | undefined, what: string) =>\n\t\tnames?.includes(symbol.name) ? `A ${what} your project registers.` : null;\n\t/** Whether the project registers a name, which replaces a built-in with the same name. */\n\tconst registers = (names: readonly string[] | undefined) =>\n\t\tnames?.includes(symbol.name) ?? false;\n\tlet value: string | null = null;\n\n\t/** A built-in's signature, then its docs. */\n\tconst builtin = (signature: string, kind: DocKind) =>\n\t\tsections(codeBlock(signature), docsFor(kind, symbol.name));\n\n\tswitch (symbol.kind) {\n\t\tcase \"tag\": {\n\t\t\t// An end tag, such as `endfor`, shows the docs of the tag it closes.\n\t\t\tconst tag =\n\t\t\t\tsymbol.name in TAGS ? symbol.name : symbol.name.replace(/^end/, \"\");\n\t\t\tconst doc = TAGS[tag];\n\t\t\tvalue = sections(\n\t\t\t\tdoc && codeBlock(tagSyntax(doc.snippet)),\n\t\t\t\tdocsFor(\"tags\", tag),\n\t\t\t);\n\t\t\tbreak;\n\t\t}\n\t\tcase \"filter\": {\n\t\t\tconst doc = FILTERS[symbol.name];\n\t\t\tvalue =\n\t\t\t\tdoc && !registers(project.manifest?.filters)\n\t\t\t\t\t? builtin(`|${doc.signature}`, \"filters\")\n\t\t\t\t\t: ((await describedCallable(open, \"filter\", symbol.name)) ??\n\t\t\t\t\t\tfromProject(project.manifest?.filters, \"filter\"));\n\t\t\tbreak;\n\t\t}\n\t\tcase \"test\": {\n\t\t\tconst doc = TESTS[symbol.name];\n\t\t\tvalue =\n\t\t\t\tdoc && !registers(project.manifest?.tests)\n\t\t\t\t\t? builtin(`is ${doc.signature}`, \"tests\")\n\t\t\t\t\t: ((await describedCallable(open, \"test\", symbol.name)) ??\n\t\t\t\t\t\tfromProject(project.manifest?.tests, \"test\"));\n\t\t\tbreak;\n\t\t}\n\t\tcase \"loop\": {\n\t\t\tconst description = LOOP_PROPERTIES[symbol.name];\n\t\t\tvalue = description\n\t\t\t\t? sections(codeBlock(`loop.${symbol.name}`), description)\n\t\t\t\t: null;\n\t\t\tbreak;\n\t\t}\n\t\tcase \"function\": {\n\t\t\tconst macro = macrosIn(text).get(symbol.name);\n\t\t\tconst doc = FUNCTIONS[symbol.name];\n\t\t\tif (macro) value = codeBlock(`macro ${symbol.name}(${macro.params})`);\n\t\t\telse if (doc && !registers(project.manifest?.functions))\n\t\t\t\tvalue = builtin(doc.signature, \"functions\");\n\t\t\telse\n\t\t\t\tvalue =\n\t\t\t\t\t(await describedCallable(open, \"function\", symbol.name)) ??\n\t\t\t\t\tfromProject(project.manifest?.functions, \"function\");\n\t\t\tbreak;\n\t\t}\n\t\tcase \"variable\": {\n\t\t\tconst types = templateTypes(open, text);\n\t\t\tconst binding = bindingFor(types.scopes, symbol);\n\t\t\tif (binding?.source.kind === \"prop\" || binding?.source.kind === \"rest\") {\n\t\t\t\tconst analysis = name ? await analyse(project, name, text) : null;\n\t\t\t\tconst prop = analysis?.props.find((item) => item.name === symbol.name);\n\t\t\t\tvalue = sections(\n\t\t\t\t\tcodeBlock(prop ? describeProp(prop) : `...${symbol.name}`),\n\t\t\t\t\tBINDING_NOTES[binding.source.kind],\n\t\t\t\t);\n\t\t\t} else if (binding) {\n\t\t\t\tconst typescript = await project.typescript();\n\t\t\t\tconst type = typescript\n\t\t\t\t\t? withTypes(\n\t\t\t\t\t\t\ttypescript,\n\t\t\t\t\t\t\t{ Value: bindingType(binding.source, types.context) },\n\t\t\t\t\t\t\t(read) => read.describe(\"Value\"),\n\t\t\t\t\t\t)\n\t\t\t\t\t: null;\n\t\t\t\tvalue = sections(\n\t\t\t\t\tcodeBlock(\n\t\t\t\t\t\ttype && type !== \"unknown\"\n\t\t\t\t\t\t\t? `${symbol.name}: ${type}`\n\t\t\t\t\t\t\t: symbol.name,\n\t\t\t\t\t\t\"ts\",\n\t\t\t\t\t),\n\t\t\t\t\tBINDING_NOTES[binding.source.kind],\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst global = await registered(open, \"global\", symbol.name);\n\t\t\t\tvalue = global\n\t\t\t\t\t? sections(\n\t\t\t\t\t\t\tcodeBlock(`${symbol.name}: ${global.type}`, \"ts\"),\n\t\t\t\t\t\t\tmemberDocs(global),\n\t\t\t\t\t\t)\n\t\t\t\t\t: project.manifest?.globals.includes(symbol.name)\n\t\t\t\t\t\t? \"A global your project provides.\"\n\t\t\t\t\t\t: null;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase \"template\": {\n\t\t\tconst target = resolveName(symbol.name, name ?? undefined);\n\t\t\tconst analysis = target ? await analyse(project, target) : null;\n\t\t\tif (!target || !analysis) {\n\t\t\t\tvalue = project.manifest\n\t\t\t\t\t? `Template \\`${symbol.name}\\` was not found.`\n\t\t\t\t\t: null;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tconst lines = [`**${target}**`];\n\t\t\tif (analysis.props.length > 0 || analysis.rest) {\n\t\t\t\tconst props = analysis.props.map(describeProp);\n\t\t\t\tif (analysis.rest) props.push(`...${analysis.rest}`);\n\t\t\t\tlines.push(codeBlock(`props ${props.join(\", \")}`));\n\t\t\t}\n\t\t\tif (analysis.blocks.length > 0) {\n\t\t\t\tlines.push(\n\t\t\t\t\t`Blocks: ${analysis.blocks.map((block) => `\\`${block}\\``).join(\", \")}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tvalue = lines.join(\"\\n\\n\");\n\t\t}\n\t}\n\treturn value ? { contents: markdown(value), range: rangeOf(symbol) } : null;\n};\n\nconst point = (line: number, character: number) => {\n\tconst position = { line, character };\n\treturn { start: position, end: position };\n};\n\n/** The line and column of an offset in another template's text. */\nconst positionIn = (text: string, offset: number) => {\n\tconst lines = text.slice(0, offset).split(\"\\n\");\n\treturn { line: lines.length - 1, character: (lines.at(-1) as string).length };\n};\n\n/**\n * Where the name under the cursor is defined. The link's origin is the whole name, so editors underline all of\n * `\"layouts/base\"` rather than one word of it.\n *\n * Variables go to where the template declares them. Without `kiln.json`, template names have no root, so nothing in\n * other templates is found. With the project's TypeScript, its functions, filters, tests, globals and the properties of\n * typed values go to their TypeScript source.\n */\nexport const definition = async (\n\topen: OpenTemplate,\n\toffset: number,\n): Promise<LocationLink | null> => {\n\tconst { document, project, name } = open;\n\tconst text = document.getText();\n\tconst link = (\n\t\torigin: Span,\n\t\turi: string,\n\t\trange: LocationLink[\"targetRange\"],\n\t): LocationLink => ({\n\t\toriginSelectionRange: {\n\t\t\tstart: document.positionAt(origin.start),\n\t\t\tend: document.positionAt(origin.end),\n\t\t},\n\t\ttargetUri: uri,\n\t\ttargetRange: range,\n\t\ttargetSelectionRange: range,\n\t});\n\tconst inSource = (origin: Span, location: SourceLocation) =>\n\t\tlink(\n\t\t\torigin,\n\t\t\tpathToFileURL(location.path).href,\n\t\t\tpoint(location.line, location.character),\n\t\t);\n\tconst symbol = symbolAt(text, offset);\n\tif (!symbol) {\n\t\tif (!enclosingDelimiter(text, offset)) return null;\n\t\tconst found = await memberAt(open, text, offset);\n\t\treturn found?.member.location\n\t\t\t? inSource(found.span, found.member.location)\n\t\t\t: null;\n\t}\n\tconst inTemplate = (template: string, line = 0, character = 0) =>\n\t\tlink(\n\t\t\tsymbol,\n\t\t\tpathToFileURL(pathOf(project, template)).href,\n\t\t\tpoint(line, character),\n\t\t);\n\tconst load = (template: string) =>\n\t\tproject.overlay.get(template) ?? readTemplate(project, template);\n\t/** Goes to a function, filter, test or global in the project's TypeScript. */\n\tconst inTypeScript = async (kind: keyof typeof REGISTRIES) => {\n\t\tconst member = await registered(open, kind, symbol.name);\n\t\treturn member?.location ? inSource(symbol, member.location) : null;\n\t};\n\n\t// A block name goes to the same block in the layout this template extends.\n\tconst blockName =\n\t\tsymbol.kind === \"variable\" &&\n\t\t/\\{%-?\\s*block\\s+$/.test(\n\t\t\ttext.slice(Math.max(0, symbol.start - 40), symbol.start),\n\t\t);\n\n\tif (symbol.kind === \"variable\" && !blockName) {\n\t\tconst binding = bindingFor(templateTypes(open, text).scopes, symbol);\n\t\tif (binding) {\n\t\t\treturn link(symbol, document.uri, {\n\t\t\t\tstart: document.positionAt(binding.definition.start),\n\t\t\t\tend: document.positionAt(binding.definition.end),\n\t\t\t});\n\t\t}\n\t\treturn inTypeScript(\"global\");\n\t}\n\tif (symbol.kind === \"function\") {\n\t\tconst local = macrosIn(text).get(symbol.name);\n\t\tif (local) {\n\t\t\tconst position = document.positionAt(local.start);\n\t\t\treturn link(\n\t\t\t\tsymbol,\n\t\t\t\tdocument.uri,\n\t\t\t\tpoint(position.line, position.character),\n\t\t\t);\n\t\t}\n\t}\n\tif (!project.manifest) return null;\n\n\tif (symbol.kind === \"template\") {\n\t\tconst target = resolveName(symbol.name, name ?? undefined);\n\t\treturn target ? inTemplate(target) : null;\n\t}\n\tif (symbol.kind === \"filter\" || symbol.kind === \"test\") {\n\t\treturn inTypeScript(symbol.kind);\n\t}\n\n\tif (symbol.kind === \"function\") {\n\t\t// A macro brought in with `from \"x\" import name`.\n\t\tfor (const match of text.matchAll(\n\t\t\t/\\{%-?\\s*from\\s+([\"'])([^\"']*)\\1\\s+import\\s+([^%]*)%\\}/g,\n\t\t)) {\n\t\t\tfor (const part of (match[3] as string).split(\",\")) {\n\t\t\t\tconst [original, alias = original] = part.trim().split(/\\s+as\\s+/);\n\t\t\t\tif (alias !== symbol.name || !original) continue;\n\t\t\t\tconst target = resolveName(match[2] as string, name ?? undefined);\n\t\t\t\tconst source = target ? await load(target) : null;\n\t\t\t\tconst macro = source ? macrosIn(source).get(original) : null;\n\t\t\t\tif (target && source && macro) {\n\t\t\t\t\tconst position = positionIn(source, macro.start);\n\t\t\t\t\treturn inTemplate(target, position.line, position.character);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn inTypeScript(\"function\");\n\t}\n\n\tif (blockName && name) {\n\t\tlet current = name;\n\t\tfor (let depth = 0; depth < 20; depth++) {\n\t\t\tconst analysis = await analyse(\n\t\t\t\tproject,\n\t\t\t\tcurrent,\n\t\t\t\tcurrent === name ? text : undefined,\n\t\t\t);\n\t\t\tconst parent = analysis?.templates.find(\n\t\t\t\t(ref) => ref.kind === \"extends\",\n\t\t\t)?.name;\n\t\t\tif (!parent) return null;\n\t\t\tconst source = await load(parent);\n\t\t\tconst block = source\n\t\t\t\t? new RegExp(`\\\\{%-?\\\\s*block\\\\s+${symbol.name}\\\\b`).exec(source)\n\t\t\t\t: null;\n\t\t\tif (source && block) {\n\t\t\t\tconst position = positionIn(source, block.index);\n\t\t\t\treturn inTemplate(parent, position.line, position.character);\n\t\t\t}\n\t\t\tcurrent = parent;\n\t\t}\n\t}\n\treturn null;\n};\n\nconst readTemplate = async (project: Project, name: string) => {\n\ttry {\n\t\treturn await readFile(pathOf(project, name), \"utf8\");\n\t} catch {\n\t\treturn null;\n\t}\n};\n\nexport const links = (open: OpenTemplate): DocumentLink[] => {\n\tconst { document, project, name } = open;\n\tif (!project.manifest) return [];\n\treturn templateStrings(document.getText()).flatMap((found) => {\n\t\tconst target = resolveName(found.name, name ?? undefined);\n\t\tif (!target) return [];\n\t\treturn [\n\t\t\t{\n\t\t\t\trange: {\n\t\t\t\t\tstart: document.positionAt(found.start),\n\t\t\t\t\tend: document.positionAt(found.end),\n\t\t\t\t},\n\t\t\t\ttarget: pathToFileURL(pathOf(project, target)).href,\n\t\t\t},\n\t\t];\n\t});\n};\n\nconst SYMBOL_KINDS: Record<string, SymbolKind> = {\n\tblock: SymbolKind.Module,\n\tmacro: SymbolKind.Function,\n\tslot: SymbolKind.Field,\n\tfill: SymbolKind.Field,\n};\n\nexport const symbols = (document: TextDocument): DocumentSymbol[] => {\n\tconst text = document.getText();\n\tconst found: DocumentSymbol[] = [];\n\tfor (const match of text.matchAll(\n\t\t/\\{%-?\\s*(block|macro|slot|fill)\\b\\s*([\"']?)([\\w-]*)\\2[^%]*%\\}/g,\n\t)) {\n\t\tconst kind = match[1] as string;\n\t\tconst range = {\n\t\t\tstart: document.positionAt(match.index as number),\n\t\t\tend: document.positionAt((match.index as number) + match[0].length),\n\t\t};\n\t\tfound.push({\n\t\t\tname: match[3] || (kind === \"slot\" ? \"default\" : kind),\n\t\t\tdetail: kind,\n\t\t\tkind: SYMBOL_KINDS[kind] ?? SymbolKind.Field,\n\t\t\trange,\n\t\t\tselectionRange: range,\n\t\t});\n\t}\n\treturn found;\n};\n\n/** Whether the project registers a function or filter, which replaces a built-in with the same name. */\nconst isRegistered = (\n\tproject: Project,\n\tkind: \"function\" | \"filter\",\n\tname: string,\n) =>\n\t(kind === \"function\"\n\t\t? project.manifest?.functions\n\t\t: project.manifest?.filters\n\t)?.includes(name) ?? false;\n\n/** A built-in's documented signature, such as `round(precision?, method?)`, when it takes arguments. */\nconst builtinSignature = (kind: \"function\" | \"filter\", name: string) => {\n\tconst doc = (kind === \"function\" ? FUNCTIONS : FILTERS)[name];\n\tif (!doc?.signature.includes(\"(\")) return null;\n\tconst label = `${kind === \"filter\" ? \"|\" : \"\"}${doc.signature}`;\n\tconst open = label.indexOf(\"(\") + 1;\n\tconst list = label.slice(open, label.lastIndexOf(\")\"));\n\treturn {\n\t\tlabel,\n\t\tparameters: splitParameters(list).map((part) => ({\n\t\t\tname: /^(?:\\.\\.\\.)?(\\w+)/.exec(part.text)?.[1] ?? part.text,\n\t\t\tstart: open + part.start,\n\t\t\tend: open + part.end,\n\t\t})),\n\t};\n};\n\n/** Named arguments the function or filter at the cursor takes, such as `limit:`, when an argument could start there. */\nconst namedArgumentItems = async (\n\topen: OpenTemplate,\n\ttext: string,\n\toffset: number,\n): Promise<CompletionItem[]> => {\n\tconst call = callContext(text, offset);\n\tif (!call?.namePosition) return [];\n\tconst range = {\n\t\tstart: open.document.positionAt(call.start),\n\t\tend: open.document.positionAt(offset),\n\t};\n\tconst item = (label: string, detail?: string, docs?: string) => ({\n\t\tlabel: `${label}:`,\n\t\tkind: CompletionItemKind.Field,\n\t\tdetail,\n\t\tdocumentation: docs ? markdown(docs) : undefined,\n\t\tsortText: `0${label}`,\n\t\ttextEdit: { range, newText: `${label}: ` },\n\t});\n\tconst builtin = isRegistered(open.project, call.kind, call.name)\n\t\t? null\n\t\t: builtinSignature(call.kind, call.name);\n\tif (builtin) return builtin.parameters.map((param) => item(param.name));\n\tif (call.kind === \"function\" && macrosIn(text).has(call.name)) return [];\n\tconst typescript = await open.project.typescript();\n\tif (!typescript) return [];\n\treturn namedOptions(typescript, call.kind, call.name).map((member) =>\n\t\titem(\n\t\t\tmember.name,\n\t\t\t`${member.name}${member.optional ? \"?\" : \"\"}: ${member.type}`,\n\t\t\tmemberDocs(member),\n\t\t),\n\t);\n};\n\n/**\n * The parameters of the function or filter whose arguments the cursor is in, with the one it's on active. Named\n * arguments are gathered into the last parameter, so a named argument makes that one active and shows its own type.\n */\nexport const signatureHelp = async (\n\topen: OpenTemplate,\n\toffset: number,\n): Promise<SignatureHelp | null> => {\n\tconst text = open.document.getText();\n\tconst call = callContext(text, offset);\n\tif (!call) return null;\n\tlet signature: {\n\t\tlabel: string;\n\t\tparameters: { name: string; start: number; end: number }[];\n\t\tdocs?: string | null;\n\t\tparamDocs?: Map<string, string>;\n\t} | null = null;\n\tconst macro = call.kind === \"function\" ? macrosIn(text).get(call.name) : null;\n\tif (macro) {\n\t\tconst label = `${call.name}(${macro.params})`;\n\t\tsignature = {\n\t\t\tlabel,\n\t\t\tparameters: splitParameters(macro.params).map((part) => ({\n\t\t\t\tname: /^\\w+/.exec(part.text)?.[0] ?? part.text,\n\t\t\t\tstart: call.name.length + 1 + part.start,\n\t\t\t\tend: call.name.length + 1 + part.end,\n\t\t\t})),\n\t\t};\n\t} else if (!isRegistered(open.project, call.kind, call.name)) {\n\t\tconst builtin = builtinSignature(call.kind, call.name);\n\t\tif (builtin) {\n\t\t\tsignature = {\n\t\t\t\t...builtin,\n\t\t\t\tdocs: docsFor(\n\t\t\t\t\tcall.kind === \"function\" ? \"functions\" : \"filters\",\n\t\t\t\t\tcall.name,\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\t}\n\tconst typescript = signature ? null : await open.project.typescript();\n\tif (typescript) {\n\t\tconst described = describeCallable(typescript, call.kind, call.name);\n\t\tif (described) {\n\t\t\tconst params = new Map(\n\t\t\t\tdescribed.member.tags.flatMap((tag) => {\n\t\t\t\t\tconst match = /^(\\w+)\\s*(.*)$/s.exec(tag.text);\n\t\t\t\t\treturn tag.name === \"param\" && match\n\t\t\t\t\t\t? [[match[1] as string, match[2] as string] as const]\n\t\t\t\t\t\t: [];\n\t\t\t\t}),\n\t\t\t);\n\t\t\tsignature = {\n\t\t\t\tlabel: described.label,\n\t\t\t\tparameters: described.parameters,\n\t\t\t\tdocs: described.member.docs,\n\t\t\t\tparamDocs: params,\n\t\t\t};\n\t\t}\n\t}\n\tif (!signature || signature.parameters.length === 0) return null;\n\tconst last = signature.parameters.length - 1;\n\tconst active =\n\t\tcall.named || call.sawNamed ? last : Math.min(call.index, last);\n\tlet namedDocs: string | null = null;\n\tif (call.named && typescript) {\n\t\tconst option = namedOptions(typescript, call.kind, call.name).find(\n\t\t\t(member) => member.name === call.named,\n\t\t);\n\t\tif (option) {\n\t\t\tnamedDocs = sections(\n\t\t\t\tcodeBlock(\n\t\t\t\t\t`${option.name}${option.optional ? \"?\" : \"\"}: ${option.type}`,\n\t\t\t\t\t\"ts\",\n\t\t\t\t),\n\t\t\t\tmemberDocs(option),\n\t\t\t);\n\t\t}\n\t}\n\tconst found = signature;\n\treturn {\n\t\tsignatures: [\n\t\t\t{\n\t\t\t\tlabel: found.label,\n\t\t\t\tdocumentation: found.docs ? markdown(found.docs) : undefined,\n\t\t\t\tparameters: found.parameters.map((param, index) => {\n\t\t\t\t\tconst docs =\n\t\t\t\t\t\tindex === active && namedDocs\n\t\t\t\t\t\t\t? namedDocs\n\t\t\t\t\t\t\t: found.paramDocs?.get(param.name);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tlabel: [param.start, param.end] as [number, number],\n\t\t\t\t\t\tdocumentation: docs ? markdown(docs) : undefined,\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t},\n\t\t],\n\t\tactiveSignature: 0,\n\t\tactiveParameter: active,\n\t};\n};\n\n/** A warning about an argument, with its offsets in the template. */\nexport type ArgumentWarning = {\n\tstart: number;\n\tend: number;\n\tcode: \"argument-type\" | \"unknown-argument\";\n\tmessage: string;\n};\n\n/**\n * Checks the arguments of calls to the project's own functions and filters against their TypeScript types. A filter's\n * value before the `|` is its first argument. Calls with `...` spreads, and arguments whose type is unknown, aren't\n * checked.\n */\nexport const argumentWarnings = async (\n\topen: OpenTemplate,\n): Promise<ArgumentWarning[]> => {\n\tconst typescript = await open.project.typescript();\n\tif (!typescript) return [];\n\tconst text = open.document.getText();\n\tconst { scopes, context } = templateTypes(open, text);\n\t/**\n\t * Each check, with what it's for: a filter's input, a positional or a named argument. A wrong type is reported on\n\t * the value, and a named argument the function doesn't take on its name.\n\t */\n\tconst checks: (ArgumentCheck & {\n\t\tspan: Span;\n\t\tnameSpan?: Span;\n\t\tcallee: string;\n\t\trole: \"input\" | \"positional\" | \"named\";\n\t})[] = [];\n\tfor (const node of expressionsIn(scopes.ast.body)) {\n\t\tlet kind: \"function\" | \"filter\";\n\t\tlet name: string;\n\t\tif (node.type === \"Call\" && node.callee.type === \"Name\") {\n\t\t\tkind = \"function\";\n\t\t\tname = node.callee.name;\n\t\t\tif (context.macros.has(name)) continue;\n\t\t} else if (node.type === \"Filter\") {\n\t\t\tkind = \"filter\";\n\t\t\tname = node.name;\n\t\t} else continue;\n\t\tconst builtins = kind === \"function\" ? FUNCTIONS : FILTERS;\n\t\tif (builtins[name] && !isRegistered(open.project, kind, name)) continue;\n\t\tif (node.args.some((arg) => arg.type === \"Spread\")) continue;\n\t\tconst parameters = parametersType(kind, name, true);\n\t\tconst positional = [\n\t\t\t...(node.type === \"Filter\" ? [node.input] : []),\n\t\t\t...node.args.flatMap((arg) =>\n\t\t\t\targ.type === \"Positional\" ? [arg.value] : [],\n\t\t\t),\n\t\t];\n\t\tpositional.forEach((value, index) => {\n\t\t\tchecks.push({\n\t\t\t\ttype: expressionType(value, context),\n\t\t\t\tparameters,\n\t\t\t\tindex,\n\t\t\t\tspan: value.span,\n\t\t\t\tcallee: name,\n\t\t\t\trole: node.type === \"Filter\" && index === 0 ? \"input\" : \"positional\",\n\t\t\t});\n\t\t});\n\t\tfor (const arg of node.args) {\n\t\t\tif (arg.type !== \"Named\") continue;\n\t\t\tchecks.push({\n\t\t\t\ttype: expressionType(arg.value, context),\n\t\t\t\tparameters,\n\t\t\t\tname: arg.name,\n\t\t\t\tspan: arg.value.span,\n\t\t\t\tnameSpan: {\n\t\t\t\t\tstart: arg.span.start,\n\t\t\t\t\tend: arg.span.start + arg.name.length,\n\t\t\t\t},\n\t\t\t\tcallee: name,\n\t\t\t\trole: \"named\",\n\t\t\t});\n\t\t}\n\t}\n\treturn checkArguments(typescript, checks).flatMap(\n\t\t(problem, index): ArgumentWarning[] => {\n\t\t\tconst check = checks[index];\n\t\t\tif (!problem || !check) return [];\n\t\t\tif (problem.kind === \"missing\") {\n\t\t\t\tconst option = \"name\" in check ? check.name : \"\";\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\t...(check.nameSpan ?? check.span),\n\t\t\t\t\t\tcode: \"unknown-argument\",\n\t\t\t\t\t\tmessage: `\\`${check.callee}\\` doesn't take \\`${option}\\`.`,\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t}\n\t\t\tconst expected = `\\`${problem.expected}\\``;\n\t\t\tconst actual = `not \\`${problem.actual}\\``;\n\t\t\tconst message =\n\t\t\t\tcheck.role === \"input\"\n\t\t\t\t\t? `\\`${check.callee}\\` needs ${expected} before the \\`|\\`, ${actual}.`\n\t\t\t\t\t: check.role === \"named\" && \"name\" in check\n\t\t\t\t\t\t? `\\`${check.name}\\` should be ${expected}, ${actual}.`\n\t\t\t\t\t\t: `This argument should be ${expected}, ${actual}.`;\n\t\t\treturn [{ ...check.span, code: \"argument-type\", message }];\n\t\t},\n\t);\n};\n","import { dirname, isAbsolute, relative, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { TextDocument } from \"vscode-languageserver-textdocument\";\nimport {\n\ttype Connection,\n\tDiagnosticSeverity,\n\tDidChangeWatchedFilesNotification,\n\tFileChangeType,\n\ttype TextEdit,\n\tTextDocuments,\n\tTextDocumentSyncKind,\n} from \"vscode-languageserver/node\";\nimport {\n\targumentWarnings,\n\tcomplete,\n\tdefinition,\n\thover,\n\tlinks,\n\ttype OpenTemplate,\n\tsignatureHelp,\n\tsymbols,\n} from \"./features.js\";\nimport {\n\tdiagnose,\n\tfindManifest,\n\tnameOf,\n\topenProject,\n\ttype Project,\n} from \"./project.js\";\n\n/** Serves Kiln templates over a language server connection. */\nexport const startServer = (connection: Connection): void => {\n\tconst documents = new TextDocuments(TextDocument);\n\n\tlet workspaceFolders: string[] = [];\n\tlet canWatchFiles = false;\n\t/** Whether the client takes `LocationLink`s from go to definition. Plain locations lose the clicked range. */\n\tlet definitionLinks = false;\n\t/** Open projects, by the path of their `kiln.json`, or their folder when they have none. */\n\tconst projects = new Map<string, Promise<Project>>();\n\n\tconnection.onInitialize((params) => {\n\t\tworkspaceFolders = (params.workspaceFolders ?? [])\n\t\t\t.map((folder) => folder.uri)\n\t\t\t.concat(\n\t\t\t\tparams.rootUri && !params.workspaceFolders ? [params.rootUri] : [],\n\t\t\t)\n\t\t\t.filter((uri) => uri.startsWith(\"file:\"))\n\t\t\t.map((uri) => fileURLToPath(uri));\n\t\tcanWatchFiles =\n\t\t\tparams.capabilities.workspace?.didChangeWatchedFiles\n\t\t\t\t?.dynamicRegistration === true;\n\t\tdefinitionLinks =\n\t\t\tparams.capabilities.textDocument?.definition?.linkSupport === true;\n\t\treturn {\n\t\t\tcapabilities: {\n\t\t\t\ttextDocumentSync: TextDocumentSyncKind.Incremental,\n\t\t\t\tcompletionProvider: {\n\t\t\t\t\t// `<` and `=` start HTML element and attribute value completions.\n\t\t\t\t\ttriggerCharacters: [\n\t\t\t\t\t\t\"|\",\n\t\t\t\t\t\t\".\",\n\t\t\t\t\t\t\"%\",\n\t\t\t\t\t\t'\"',\n\t\t\t\t\t\t\"'\",\n\t\t\t\t\t\t\"/\",\n\t\t\t\t\t\t\" \",\n\t\t\t\t\t\t\"{\",\n\t\t\t\t\t\t\",\",\n\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\"=\",\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\thoverProvider: true,\n\t\t\t\tsignatureHelpProvider: {\n\t\t\t\t\ttriggerCharacters: [\"(\", \",\"],\n\t\t\t\t\tretriggerCharacters: [\":\", \" \"],\n\t\t\t\t},\n\t\t\t\tdefinitionProvider: true,\n\t\t\t\tdocumentLinkProvider: { resolveProvider: false },\n\t\t\t\tdocumentSymbolProvider: true,\n\t\t\t\tdocumentFormattingProvider: true,\n\t\t\t\tdocumentRangeFormattingProvider: true,\n\t\t\t},\n\t\t\tserverInfo: { name: \"kiln-language-server\" },\n\t\t};\n\t});\n\n\tconnection.onInitialized(() => {\n\t\tif (!canWatchFiles) return;\n\t\tvoid connection.client.register(DidChangeWatchedFilesNotification.type, {\n\t\t\twatchers: [\n\t\t\t\t{ globPattern: \"**/*.kiln\" },\n\t\t\t\t{ globPattern: \"**/kiln.json\" },\n\t\t\t\t{ globPattern: \"**/*.{ts,tsx,mts,cts}\" },\n\t\t\t\t{ globPattern: \"**/tsconfig*.json\" },\n\t\t\t],\n\t\t});\n\t});\n\n\t/** The project a file belongs to: the nearest `kiln.json` inside its workspace folder, or the folder itself. */\n\tconst projectFor = async (path: string): Promise<Project> => {\n\t\tconst folder =\n\t\t\tworkspaceFolders\n\t\t\t\t.filter((candidate) => {\n\t\t\t\t\tconst name = relative(candidate, path);\n\t\t\t\t\treturn (\n\t\t\t\t\t\tname !== \"..\" && !name.startsWith(\"..\" + sep) && !isAbsolute(name)\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t\t.sort((a, b) => b.length - a.length)[0] ?? null;\n\t\tconst manifestPath = await findManifest(dirname(path), folder);\n\t\tconst fallbackRoot = folder ?? dirname(path);\n\t\tconst key = manifestPath ?? fallbackRoot;\n\t\tlet project = projects.get(key);\n\t\tif (!project) {\n\t\t\tproject = openProject(manifestPath, fallbackRoot, (message) =>\n\t\t\t\tconnection.window.showWarningMessage(message),\n\t\t\t);\n\t\t\tprojects.set(key, project);\n\t\t}\n\t\treturn project;\n\t};\n\n\tconst openTemplate = async (\n\t\tdocument: TextDocument,\n\t): Promise<OpenTemplate | null> => {\n\t\tif (!document.uri.startsWith(\"file:\")) return null;\n\t\tconst path = fileURLToPath(document.uri);\n\t\tconst project = await projectFor(path);\n\t\treturn { document, project, name: nameOf(project, path) };\n\t};\n\n\tconst pending = new Map<string, ReturnType<typeof setTimeout>>();\n\n\t/** Checks a template shortly after its last change, and publishes its diagnostics. */\n\tconst scheduleCheck = (document: TextDocument) => {\n\t\tclearTimeout(pending.get(document.uri));\n\t\tpending.set(\n\t\t\tdocument.uri,\n\t\t\tsetTimeout(() => {\n\t\t\t\tpending.delete(document.uri);\n\t\t\t\tvoid check(document);\n\t\t\t}, 150),\n\t\t);\n\t};\n\n\tconst check = async (document: TextDocument) => {\n\t\tconst open = await openTemplate(document);\n\t\tif (!open?.name) return;\n\t\tconst { project, name } = open;\n\t\tconst version = document.version;\n\t\tconst diagnostics = await diagnose(project, name, document.getText()).catch(\n\t\t\t() => [],\n\t\t);\n\t\tconst warnings = await argumentWarnings(open).catch(() => []);\n\t\tif (documents.get(document.uri)?.version !== version) return;\n\t\tvoid connection.sendDiagnostics({\n\t\t\turi: document.uri,\n\t\t\tversion,\n\t\t\tdiagnostics: diagnostics\n\t\t\t\t.map((diagnostic) => ({\n\t\t\t\t\trange: {\n\t\t\t\t\t\tstart: document.positionAt(diagnostic.start.offset),\n\t\t\t\t\t\tend: document.positionAt(diagnostic.end.offset),\n\t\t\t\t\t},\n\t\t\t\t\tseverity:\n\t\t\t\t\t\tdiagnostic.severity === \"error\"\n\t\t\t\t\t\t\t? DiagnosticSeverity.Error\n\t\t\t\t\t\t\t: DiagnosticSeverity.Warning,\n\t\t\t\t\tcode: diagnostic.code,\n\t\t\t\t\tsource: \"kiln\",\n\t\t\t\t\tmessage: diagnostic.message,\n\t\t\t\t}))\n\t\t\t\t.concat(\n\t\t\t\t\twarnings.map((warning) => ({\n\t\t\t\t\t\trange: {\n\t\t\t\t\t\t\tstart: document.positionAt(warning.start),\n\t\t\t\t\t\t\tend: document.positionAt(warning.end),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tseverity: DiagnosticSeverity.Warning,\n\t\t\t\t\t\tcode: warning.code,\n\t\t\t\t\t\tsource: \"kiln\",\n\t\t\t\t\t\tmessage: warning.message,\n\t\t\t\t\t})),\n\t\t\t\t),\n\t\t});\n\t};\n\n\t/** Every open template in a project sees an edit to any of them, since one template's props can break another. */\n\tconst checkProject = async (project: Project) => {\n\t\tfor (const document of documents.all()) {\n\t\t\tconst open = await openTemplate(document);\n\t\t\tif (open?.project === project) scheduleCheck(document);\n\t\t}\n\t};\n\n\tdocuments.onDidChangeContent(async ({ document }) => {\n\t\tconst open = await openTemplate(document);\n\t\tif (!open?.name) return;\n\t\topen.project.overlay.set(open.name, document.getText());\n\t\topen.project.kiln.invalidate(open.name);\n\t\tawait checkProject(open.project);\n\t});\n\n\tdocuments.onDidClose(async ({ document }) => {\n\t\tclearTimeout(pending.get(document.uri));\n\t\tvoid connection.sendDiagnostics({ uri: document.uri, diagnostics: [] });\n\t\tconst open = await openTemplate(document);\n\t\tif (!open?.name) return;\n\t\topen.project.overlay.delete(open.name);\n\t\topen.project.kiln.invalidate(open.name);\n\t\tawait checkProject(open.project);\n\t});\n\n\t/** Closes every open project, so the next request opens them again from their settings. */\n\tconst closeProjects = async () => {\n\t\tconst open = [...projects.values()];\n\t\tprojects.clear();\n\t\tfor (const project of open) (await project).close();\n\t};\n\n\tconnection.onShutdown(closeProjects);\n\n\tconnection.onDidChangeWatchedFiles(async ({ changes }) => {\n\t\tconst isSettings = (uri: string) =>\n\t\t\turi.endsWith(\"/kiln.json\") || /\\/tsconfig[^/]*\\.json$/.test(uri);\n\t\tconst typescriptChanges = changes.flatMap((change) =>\n\t\t\tchange.uri.startsWith(\"file:\") && /\\.[cm]?tsx?$/.test(change.uri)\n\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: fileURLToPath(change.uri),\n\t\t\t\t\t\t\tkind:\n\t\t\t\t\t\t\t\tchange.type === FileChangeType.Created\n\t\t\t\t\t\t\t\t\t? (\"created\" as const)\n\t\t\t\t\t\t\t\t\t: change.type === FileChangeType.Deleted\n\t\t\t\t\t\t\t\t\t\t? (\"deleted\" as const)\n\t\t\t\t\t\t\t\t\t\t: (\"changed\" as const),\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t: [],\n\t\t);\n\t\tif (typescriptChanges.length > 0) {\n\t\t\tfor (const project of projects.values()) {\n\t\t\t\t(await project).typescriptChanged(typescriptChanges);\n\t\t\t}\n\t\t}\n\t\tif (changes.some((change) => isSettings(change.uri))) {\n\t\t\tawait closeProjects();\n\t\t\t// Populate every new project before checking callers, so cross-template checks see all unsaved text.\n\t\t\tfor (const document of documents.all()) {\n\t\t\t\tconst open = await openTemplate(document);\n\t\t\t\tif (open?.name) {\n\t\t\t\t\topen.project.overlay.set(open.name, document.getText());\n\t\t\t\t\topen.project.kiln.invalidate(open.name);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (const change of changes) {\n\t\t\t\tif (!change.uri.startsWith(\"file:\") || !change.uri.endsWith(\".kiln\"))\n\t\t\t\t\tcontinue;\n\t\t\t\tconst path = fileURLToPath(change.uri);\n\t\t\t\tconst project = await projectFor(path);\n\t\t\t\tconst name = nameOf(project, path);\n\t\t\t\tif (name) project.kiln.invalidate(name);\n\t\t\t}\n\t\t}\n\t\tfor (const document of documents.all()) scheduleCheck(document);\n\t});\n\n\t/** Runs a handler with the open template for a request, or returns `fallback` when there is none. */\n\tconst withTemplate =\n\t\t<P extends { textDocument: { uri: string } }, R>(\n\t\t\tfallback: R,\n\t\t\thandler: (open: OpenTemplate, params: P) => R | Promise<R>,\n\t\t) =>\n\t\tasync (params: P): Promise<R> => {\n\t\t\tconst document = documents.get(params.textDocument.uri);\n\t\t\tconst open = document ? await openTemplate(document) : null;\n\t\t\treturn open ? handler(open, params) : fallback;\n\t\t};\n\n\tconnection.onCompletion(\n\t\twithTemplate([], (open, params) =>\n\t\t\tcomplete(open, open.document.offsetAt(params.position)),\n\t\t),\n\t);\n\tconnection.onHover(\n\t\twithTemplate(null, (open, params) =>\n\t\t\thover(open, open.document.offsetAt(params.position)),\n\t\t),\n\t);\n\tconnection.onSignatureHelp(\n\t\twithTemplate(null, (open, params) =>\n\t\t\tsignatureHelp(open, open.document.offsetAt(params.position)),\n\t\t),\n\t);\n\tconnection.onDefinition(\n\t\twithTemplate(null, async (open, params) => {\n\t\t\tconst link = await definition(\n\t\t\t\topen,\n\t\t\t\topen.document.offsetAt(params.position),\n\t\t\t);\n\t\t\tif (!link || definitionLinks) return link && [link];\n\t\t\treturn { uri: link.targetUri, range: link.targetSelectionRange };\n\t\t}),\n\t);\n\tconnection.onDocumentLinks(withTemplate([], (open) => links(open)));\n\tconnection.onDocumentSymbol(\n\t\twithTemplate([], (open) => symbols(open.document)),\n\t);\n\n\t/** Formats a template, or part of one, as edits. Templates with syntax errors are left alone. */\n\tconst formatTemplate = (\n\t\topen: OpenTemplate,\n\t\toptions: { tabSize: number; insertSpaces: boolean },\n\t\trange?: { start: number; end: number },\n\t): TextEdit[] => {\n\t\tconst { document, project } = open;\n\t\ttry {\n\t\t\treturn project.format\n\t\t\t\t.formatEdits(document.getText(), {\n\t\t\t\t\tuseTabs: !options.insertSpaces,\n\t\t\t\t\ttabWidth: options.tabSize,\n\t\t\t\t\trange,\n\t\t\t\t})\n\t\t\t\t.map((edit) => ({\n\t\t\t\t\trange: {\n\t\t\t\t\t\tstart: document.positionAt(edit.start),\n\t\t\t\t\t\tend: document.positionAt(edit.end),\n\t\t\t\t\t},\n\t\t\t\t\tnewText: edit.text,\n\t\t\t\t}));\n\t\t} catch (error) {\n\t\t\tif (error instanceof project.format.KilnFormatError) {\n\t\t\t\tconnection.window.showErrorMessage(error.message);\n\t\t\t}\n\t\t\treturn [];\n\t\t}\n\t};\n\n\tconnection.onDocumentFormatting(\n\t\twithTemplate([], (open, params) => formatTemplate(open, params.options)),\n\t);\n\tconnection.onDocumentRangeFormatting(\n\t\twithTemplate([], (open, params) =>\n\t\t\tformatTemplate(open, params.options, {\n\t\t\t\tstart: open.document.offsetAt(params.range.start),\n\t\t\t\tend: open.document.offsetAt(params.range.end),\n\t\t\t}),\n\t\t),\n\t);\n\n\tdocuments.listen(connection);\n\tconnection.listen();\n};\n","#!/usr/bin/env node\nimport { createConnection, ProposedFeatures } from \"vscode-languageserver/node\";\nimport { startServer } from \"./server.js\";\n\nstartServer(createConnection(ProposedFeatures.all));\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,49 @@
1
1
  {
2
- "name": "@lucidkiln/language-server",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
2
+ "name": "@lucidkiln/language-server",
3
+ "version": "1.1.0",
4
+ "description": "Language server for Kiln templates: errors as you type, formatting, completions, hover and go to definition.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/buildlucid/kiln.git",
8
+ "directory": "packages/language-server"
9
+ },
10
+ "type": "module",
11
+ "bin": {
12
+ "kiln-language-server": "./dist/main.js"
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "dev": "vp pack --watch",
19
+ "prepack": "vp run build"
20
+ },
21
+ "keywords": [
22
+ "kiln",
23
+ "language server",
24
+ "lsp",
25
+ "template"
26
+ ],
27
+ "dependencies": {
28
+ "@lucidkiln/core": "^1.1.0",
29
+ "vscode-html-languageservice": "5.6.2",
30
+ "vscode-languageserver": "10.1.2",
31
+ "vscode-languageserver-textdocument": "1.0.15"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^24.19.2",
35
+ "typescript": "^7.0.2",
36
+ "typescript-6": "npm:typescript@^6.0.3",
37
+ "vite-plus": "1.2.0"
38
+ },
39
+ "volta": {
40
+ "node": "24.22.0"
41
+ },
42
+ "engines": {
43
+ "node": "^24.0.0"
44
+ },
45
+ "license": "MIT",
46
+ "publishConfig": {
47
+ "access": "public"
48
+ }
49
+ }