@purview-dev/astroc4 1.0.0-prerelease.4 → 1.0.0-prerelease.6

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.
@@ -2,12 +2,12 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/grammar/source.ts", "../src/grammar/langium.ts", "../src/grammar/textmate.ts", "../src/expressive-code.ts"],
4
4
  "sourcesContent": [
5
- "// source.mjs\n// path: src/grammar/source.mjs\n// Resolves the LikeC4 grammar the site asked for: the Langium grammar from\n// likec4/likec4 at a branch, tag or commit, cached on disk, reduced to a\n// TextMate grammar by ./textmate.mjs.\n//\n// This runs from the site's `astro:config:setup`, so `astro dev`, `astro\n// build`, `astro check` and `astro sync` all go through it — a bad ref or an\n// unreadable grammar fails the command instead of quietly shipping\n// unhighlighted code.\n//\n// Network policy: strict by default (`onError: 'fail'`). A *bad ref* is user\n// error and always fails. A *network failure* may fall back to the cache from\n// the last successful fetch, and then to the bundled snapshot, but only when\n// `onError` says so.\n\nimport { createHash } from 'node:crypto';\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { parseLangium } from './langium.js';\nimport { buildTmLanguage, type TmGrammar } from './textmate.js';\n\n/** Upstream repository and the paths the grammar is read from. */\nexport const DEFAULT_REPO = 'likec4/likec4';\nexport const DEFAULT_REF = 'main';\nexport const LANGIUM_PATH = 'packages/language-server/src/like-c4.langium';\nexport const DEFAULT_BASE_URL = 'https://raw.githubusercontent.com';\n\n/** Shape of a cache file. Bump when the fields change. */\nconst CACHE_VERSION = 1;\n\nconst BUNDLED_GRAMMAR = new URL('./likec4.tmLanguage.json', import.meta.url);\nconst BUNDLED_LANGIUM = new URL('./like-c4.langium', import.meta.url);\n\n/** The refs a repository actually has: branches, tags, `a1b2c3d`. */\nconst REF_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._/-]*$/;\n\nexport type OnError = 'fail' | 'warn' | 'silent';\n\n/** Everything the resolver accepts. The site only ever sets a few of these. */\nexport interface GrammarSourceOptions {\n\t/** Repository to read from. Defaults to likec4/likec4. */\n\trepo?: string;\n\t/** Branch, tag or commit SHA. Defaults to `main`. */\n\tref?: string;\n\t/** Use the bundled snapshot, never the network. */\n\toffline?: boolean;\n\t/** What to do when the grammar cannot be fetched. */\n\tonError?: OnError;\n\t/** Seconds a cached fetch stays fresh. */\n\tcacheTtl?: number;\n\t/** Ignore the cache and refetch. */\n\trefresh?: boolean;\n\t/** Raw file host, for mirrors and proxies. */\n\tbaseUrl?: string;\n\t/** Request timeout in milliseconds. */\n\ttimeout?: number;\n\t/** Site root, for the default cache directory. */\n\troot?: string;\n\t/** Where to cache, overriding the default. */\n\tcacheDir?: string;\n\t/** Environment, for `ASTROC4_*` overrides. */\n\tenv?: NodeJS.ProcessEnv;\n\t/** Astro's logger. */\n\tlogger?: { info?: (message: string) => void; warn?: (message: string) => void };\n\t/** Injected in tests. */\n\tfetchImpl?: typeof fetch;\n\t/** Bundled Langium text, for tests. */\n\tbundledLangiumPath?: string;\n}\n\n/** Where a grammar came from, for logs and tests. */\nexport interface GrammarMeta {\n\trepo: string;\n\tref: string;\n\t/** Where it came from. */\n\tsource: 'network' | 'cache' | 'bundled';\n\tfetchedAt: number;\n\tetag?: string | undefined;\n\t/** Content hash of the Langium source. */\n\tsha: string;\n\t/** Why the bundled snapshot was used. */\n\treason?: string;\n}\n\nexport interface GrammarSource {\n\t/** The TextMate grammar for Shiki. */\n\tgrammar: TmGrammar;\n\t/** The Langium source it was derived from. */\n\tlangium: string;\n\t/** Where it came from, for logs and tests. */\n\tmeta: GrammarMeta;\n}\n\n/** A repo and ref, which is all a cache entry is keyed on. */\ninterface GrammarIdentity {\n\trepo: string;\n\tref: string;\n}\n\n/** Raised for a ref this repository cannot have — always a user error. */\nexport class GrammarRefError extends Error {\n\toverride name = 'GrammarRefError';\n}\n\n/** Raised when the grammar could not be fetched, or came back unusable. */\nexport class GrammarFetchError extends Error {\n\toverride name = 'GrammarFetchError';\n}\n\nexport async function resolveLikeC4Grammar(options: GrammarSourceOptions = {}): Promise<GrammarSource> {\n\tconst env = options.env ?? process.env;\n\tconst repo = options.repo ?? DEFAULT_REPO;\n\tconst ref = env.ASTROC4_REF || options.ref || DEFAULT_REF;\n\tconst offline = options.offline ?? isTruthy(env.ASTROC4_OFFLINE);\n\tconst onError = options.onError ?? 'fail';\n\tconst logger = options.logger;\n\n\tvalidateRef(ref);\n\n\tif (offline) {\n\t\treturn bundled('offline: true', options);\n\t}\n\n\tconst cache = await readCache(options, { repo, ref });\n\n\tif (cache?.fresh && !options.refresh) {\n\t\treturn derive(cache.langium, { repo, ref, source: 'cache', fetchedAt: cache.fetchedAt, etag: cache.etag });\n\t}\n\n\tlet fetched;\n\n\ttry {\n\t\tfetched = await fetchLangiumSource({ ...options, repo, ref, etag: cache?.etag });\n\t} catch (error) {\n\t\tif (!(error instanceof Error)) throw error;\n\n\t\t// A bad ref will fail the same way forever: never paper over it.\n\t\tif (error instanceof GrammarRefError) throw error;\n\n\t\tif (onError === 'fail') throw error;\n\n\t\tif (onError === 'warn') logger?.warn?.(`[astroc4] ${error.message}`);\n\n\t\tif (cache) {\n\t\t\tif (onError === 'warn') {\n\t\t\t\tlogger?.warn?.(`[astroc4] using the grammar cached at ${new Date(cache.fetchedAt).toISOString()}`);\n\t\t\t}\n\n\t\t\treturn derive(cache.langium, {\n\t\t\t\trepo,\n\t\t\t\tref,\n\t\t\t\tsource: 'cache',\n\t\t\t\tfetchedAt: cache.fetchedAt,\n\t\t\t\tetag: cache.etag,\n\t\t\t});\n\t\t}\n\n\t\treturn bundled(error.message, options);\n\t}\n\n\tif ('notModified' in fetched) {\n\t\tif (!cache) {\n\t\t\tthrow new GrammarFetchError(\n\t\t\t\t'the grammar host answered 304 for a grammar that is not cached — retry with `refresh: true`',\n\t\t\t);\n\t\t}\n\n\t\tawait writeCache(options, { repo, ref }, cache);\n\n\t\treturn derive(cache.langium, { repo, ref, source: 'cache', fetchedAt: cache.fetchedAt, etag: cache.etag });\n\t}\n\n\tconst result = derive(fetched.text, { repo, ref, source: 'network', etag: fetched.etag });\n\tawait writeCache(options, { repo, ref }, { langium: fetched.text, etag: fetched.etag });\n\n\treturn result;\n}\n\n/** Where a derivation came from, before it becomes `GrammarMeta`. */\ninterface DeriveInfo {\n\trepo: string;\n\tref: string;\n\tsource: 'network' | 'cache' | 'bundled';\n\tfetchedAt?: number;\n\tetag?: string | undefined;\n}\n\nfunction derive(langium: string, info: DeriveInfo): GrammarSource {\n\tlet vocabulary;\n\n\ttry {\n\t\tvocabulary = parseLangium(langium);\n\t} catch (cause) {\n\t\tthrow new GrammarFetchError(\n\t\t\t`${info.repo}@${info.ref}: the grammar could not be read — ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t{ cause },\n\t\t);\n\t}\n\n\tconst sha = grammarSha(langium);\n\n\treturn {\n\t\tgrammar: buildTmLanguage(vocabulary, { repo: info.repo, ref: info.ref, sha }),\n\t\tlangium,\n\t\tmeta: {\n\t\t\trepo: info.repo,\n\t\t\tref: info.ref,\n\t\t\tsource: info.source,\n\t\t\tfetchedAt: info.fetchedAt ?? Date.now(),\n\t\t\tetag: info.etag,\n\t\t\tsha,\n\t\t},\n\t};\n}\n\n/**\n * The snapshot shipped with this package, for `offline: true` and for falling\n * back when the network is down and `onError` allows it. It is derived from\n * the committed `like-c4.langium`, so it matches `likec4.tmLanguage.json` (the\n * snapshot test asserts exactly that). Its provenance is the snapshot's own,\n * not the ref that was asked for.\n * @param reason Why it is being used, surfaced in logs.\n */\nasync function bundled(reason: string, options: GrammarSourceOptions): Promise<GrammarSource> {\n\tconst path = options.bundledLangiumPath ?? fileURLToPath(BUNDLED_LANGIUM);\n\tconst snapshot = await bundledProvenance();\n\n\tconst source = derive(await readFile(path, 'utf8'), {\n\t\trepo: snapshot.repo ?? DEFAULT_REPO,\n\t\tref: snapshot.ref ?? DEFAULT_REF,\n\t\tsource: 'bundled',\n\t});\n\n\tsource.meta.reason = reason;\n\n\treturn source;\n}\n\n/** `$generated` from the shipped grammar, so logs name the real snapshot. */\nasync function bundledProvenance(): Promise<{ repo?: string; ref?: string }> {\n\ttry {\n\t\tconst { $generated } = JSON.parse(await readFile(fileURLToPath(BUNDLED_GRAMMAR), 'utf8'));\n\n\t\treturn { repo: $generated?.repo, ref: $generated?.ref };\n\t} catch {\n\t\treturn {};\n\t}\n}\n\n/** Short content hash — the identity that actually changes highlighting. */\nexport function grammarSha(source: string): string {\n\treturn createHash('sha256').update(source).digest('hex').slice(0, 12);\n}\n\n// region refs\n\n/**\n * Rejects anything that cannot name a ref, before it reaches the network.\n */\nexport function validateRef(ref: string): string {\n\tif (typeof ref !== 'string' || ref.length === 0) {\n\t\tthrow new GrammarRefError('the LikeC4 grammar `ref` must be a branch, tag or commit SHA');\n\t}\n\n\tif (!REF_PATTERN.test(ref) || ref.includes('..') || ref.endsWith('/') || ref.includes('//')) {\n\t\tthrow new GrammarRefError(\n\t\t\t`\"${ref}\" is not a usable LikeC4 grammar ref — expected a branch, tag or commit SHA such as \"main\" or \"v1.59.4\"`,\n\t\t);\n\t}\n\n\treturn ref;\n}\n\n\n// endregion\n\n// region fetch\n\n/** What a fetch returns: the text, or the news that the ETag still matches. */\nexport type FetchResult = { text: string; etag?: string | undefined } | { notModified: true };\n\nexport async function fetchLangiumSource(\n\toptions: GrammarSourceOptions & { repo: string; ref: string; etag?: string | undefined },\n): Promise<FetchResult> {\n\tconst repo = options.repo;\n\tconst ref = options.ref;\n\tconst baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\n\tconst url = `${baseUrl}/${repo}/${ref}/${LANGIUM_PATH}`;\n\tconst timeout = options.timeout ?? 15_000;\n\tconst request = options.fetchImpl ?? fetch;\n\n\tconst headers: Record<string, string> = { 'user-agent': 'astroc4', accept: 'text/plain' };\n\tif (options.etag) headers['if-none-match'] = options.etag;\n\n\tlet response;\n\n\ttry {\n\t\tresponse = await request(url, { headers, redirect: 'follow', signal: AbortSignal.timeout(timeout) });\n\t} catch (cause) {\n\t\tthrow new GrammarFetchError(\n\t\t\t`could not fetch the LikeC4 grammar from ${url} — ${cause instanceof Error ? cause.message : String(cause)}. ` +\n\t\t\t\t'Builds are strict by default: pass `highlighting: { offline: true }` to use the bundled grammar instead.',\n\t\t\t{ cause },\n\t\t);\n\t}\n\n\tif (response.status === 304) return { notModified: true };\n\n\tif (response.status === 404) {\n\t\tthrow new GrammarRefError(\n\t\t\t`${repo} has no \"${ref}\", or it no longer has ${LANGIUM_PATH} (${url}). ` +\n\t\t\t\t'Use a tag such as \"v1.59.4\", a commit SHA, or \"main\".',\n\t\t);\n\t}\n\n\tif (!response.ok) {\n\t\tthrow new GrammarFetchError(\n\t\t\t`${url} responded ${response.status} ${response.statusText} — set ` +\n\t\t\t\t'`highlighting: { onError: \"warn\" }` to fall back to the bundled grammar.',\n\t\t);\n\t}\n\n\tconst text = await response.text();\n\n\tif (text.trim().length === 0) {\n\t\tthrow new GrammarFetchError(`${url} returned an empty file — the grammar is not usable`);\n\t}\n\n\treturn { text, etag: response.headers.get('etag') ?? undefined };\n}\n\n// endregion\n\n// region cache\n\n/**\n * Cache location: `node_modules/.cache/astroc4`, which every Astro project\n * already ignores. One file per repo@ref, so switching `ref` never thrashes.\n */\nfunction cachePath(options: GrammarSourceOptions, identity: GrammarIdentity): string {\n\tconst dir =\n\t\toptions.cacheDir ?? join(options.root ?? process.cwd(), 'node_modules', '.cache', 'astroc4');\n\tconst key = createHash('sha256').update(`${identity.repo}@${identity.ref}`).digest('hex').slice(0, 16);\n\n\treturn join(dir, `grammar-${key}.json`);\n}\n\n/** What a cache file holds. */\ntype CacheWriteEntry = { langium: string; etag?: string | undefined };\n/** A cache entry, plus whether it is still inside its TTL. */\ninterface CacheEntry extends CacheWriteEntry {\n\tfetchedAt: number;\n}\ninterface FreshCacheEntry extends CacheEntry {\n\tfresh: boolean;\n}\n\nasync function readCache(\n\toptions: GrammarSourceOptions,\n\tidentity: GrammarIdentity,\n): Promise<FreshCacheEntry | undefined> {\n\tlet raw;\n\n\ttry {\n\t\traw = await readFile(cachePath(options, identity), 'utf8');\n\t} catch {\n\t\treturn undefined;\n\t}\n\n\ttry {\n\t\tconst entry = JSON.parse(raw);\n\n\t\tif (\n\t\t\tentry?.version !== CACHE_VERSION ||\n\t\t\tentry.repo !== identity.repo ||\n\t\t\tentry.ref !== identity.ref ||\n\t\t\ttypeof entry.langium !== 'string' ||\n\t\t\ttypeof entry.fetchedAt !== 'number'\n\t\t) {\n\t\t\t// A cache written by a different version of this package, or a\n\t\t\t// truncated file. Refetching is cheaper than debugging it.\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst ttl = options.cacheTtl ?? 3600;\n\n\t\treturn { ...entry, fresh: Date.now() - entry.fetchedAt < ttl * 1000 };\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Best effort: a read-only `node_modules` must not fail a build, it only means\n * the next one has to fetch again.\n */\nasync function writeCache(\n\toptions: GrammarSourceOptions,\n\tidentity: GrammarIdentity,\n\tentry: CacheWriteEntry,\n): Promise<void> {\n\tconst path = cachePath(options, identity);\n\tconst temporary = `${path}.${process.pid}.tmp`;\n\n\ttry {\n\t\tawait mkdir(join(path, '..'), { recursive: true });\n\t\tawait writeFile(\n\t\t\ttemporary,\n\t\t\tJSON.stringify({\n\t\t\t\tversion: CACHE_VERSION,\n\t\t\t\trepo: identity.repo,\n\t\t\t\tref: identity.ref,\n\t\t\t\tetag: entry.etag,\n\t\t\t\tfetchedAt: Date.now(),\n\t\t\t\tlangium: entry.langium,\n\t\t\t}),\n\t\t\t'utf8',\n\t\t);\n\t\t// Rename rather than write in place: two Astro processes can resolve the\n\t\t// same cache entry at once during `astro check && astro build`.\n\t\tawait rename(temporary, path);\n\t} catch (error) {\n\t\toptions.logger?.warn?.(\n\t\t\t`[astroc4] could not cache the LikeC4 grammar in ${path} — ${error instanceof Error ? error.message : String(error)}`,\n\t\t);\n\t}\n}\n\n// endregion\n\nfunction isTruthy(value: string | undefined): boolean {\n\treturn typeof value === 'string' && /^(1|true|yes|on)$/i.test(value.trim());\n}\n\nexport default resolveLikeC4Grammar;\n\n",
6
- "// langium.mjs\n// path: src/grammar/langium.mjs\n// Reduces the LikeC4 Langium grammar to the vocabulary a TextMate grammar\n// needs: which words open a block, which are plain keywords, which are\n// property names, which belong to a closed value domain (shapes, colours,\n// arrow heads…) and which tokens have to be matched structurally (comments,\n// strings, icon ids).\n//\n// The grammar is read from likec4/likec4 at a ref the site chooses:\n// `packages/language-server/src/like-c4.langium`. Deriving from it is what\n// keeps highlighting in step with the language — `ElementShape` gained `agent`\n// after v1.59.4, and the TextMate grammar upstream maintains by hand still\n// does not know about it.\n//\n// Deliberately no Langium dependency: this is a tolerant scanner over one\n// file, not a parser for the grammar language, and it has to survive upstream\n// reformatting. Anything it cannot classify is dropped rather than guessed.\n\n/** Rules that describe a closed set of values are named after what they hold. */\nconst NOT_VALUE_DOMAINS = /Id$/;\n\n/** Property names the grammar matches as `key='…'` assignments. */\nconst PROPERTY_SUPPLEMENTS = ['kind', 'tag'];\n\n/** A token produced by the scanner. */\nexport type TokenType = 'literal' | 'regex' | 'ident' | 'punct';\nexport interface Token {\n\ttype: TokenType;\n\tvalue: string;\n}\n\n/** A `terminal` rule, with its value as written. */\nexport interface Terminal {\n\thidden: boolean;\n\tkind: 'regex' | 'literal';\n\t/** Raw regex source (without slashes) or the literal. */\n\tvalue: string;\n}\n\n/** A parser rule, fragment or terminal, as the scanner reads it. */\nexport interface Rule {\n\tname: string;\n\tkind: 'rule' | 'fragment' | 'terminal';\n\thidden: boolean;\n\treturns?: string | undefined;\n\ttokens: Token[];\n}\n\n/** Everything the TextMate generator needs to know about the language. */\nexport interface Vocabulary {\n\t/** Keywords that open a `{ … }` block. */\n\tblocks: string[];\n\t/** Every remaining word-like literal. */\n\tkeywords: string[];\n\t/** Property names from `key='…'` assignments. */\n\tproperties: string[];\n\t/** Relationship connectors containing `->`. */\n\tarrows: string[];\n\t/** `returns string` value domains, by rule name. */\n\tenums: Record<string, string[]>;\n\t/** Icon packs from the `LIB_ICON` terminal. */\n\ticons: string[];\n\t/** Literals from the `BOOLEAN` terminal. */\n\tbooleans: string[];\n\t/** Parser rules seen — used for sanity checks. */\n\truleCount: number;\n}\n\nexport function parseLangium(source: string): Vocabulary {\n\t// `grammar LikeC4` is a header, not a rule, and it has no `;`: leaving it in\n\t// would glue it to the first real rule and hide that rule from the scanner.\n\tconst statements = splitStatements(\n\t\tstripComments(source).replace(/^[ \\t]*grammar[ \\t]+[A-Za-z_]\\w*[ \\t]*$/gm, ''),\n\t);\n\tconst rules = statements.map(readStatement).filter((rule) => rule !== undefined);\n\n\tconst parserRules = rules.filter((rule) => rule.kind === 'rule' || rule.kind === 'fragment');\n\n\tif (parserRules.length === 0) {\n\t\tthrow new Error(\n\t\t\t'the file contains no Langium parser rules — is this still `packages/language-server/src/like-c4.langium`?',\n\t\t);\n\t}\n\n\tconst enums = resolveEnums(parserRules);\n\tconst blocks = findBlocks(parserRules);\n\tconst properties = unique([...findProperties(parserRules), ...PROPERTY_SUPPLEMENTS]);\n\tconst arrows = findArrows(parserRules);\n\tconst literals = unique(\n\t\tparserRules.flatMap((rule) => rule.tokens.filter((t) => t.type === 'literal').map((t) => t.value)),\n\t);\n\n\tconst classified = new Set([...blocks, ...properties, ...Object.values(enums).flat()]);\n\tconst keywords = literals.filter(\n\t\t(value) => /^[A-Za-z_]\\w*$/.test(value) && !classified.has(value),\n\t);\n\n\tconst terminals = readTerminals(rules);\n\n\t// A grammar with parser rules but no structure at all is not a LikeC4\n\t// grammar — most likely the path now holds something else. A small grammar\n\t// can legitimately have no \"leftover\" keywords, so blocks and value domains\n\t// count too.\n\tif (keywords.length === 0 && blocks.length === 0 && Object.keys(enums).length === 0) {\n\t\tthrow new Error('the file contains no LikeC4 keywords — the Langium grammar could not be read');\n\t}\n\n\treturn {\n\t\tblocks,\n\t\tkeywords,\n\t\tproperties,\n\t\tarrows,\n\t\tenums,\n\t\ticons: terminalAlternatives(terminals.LIB_ICON),\n\t\tbooleans: terminalAlternatives(terminals.BOOLEAN),\n\t\truleCount: parserRules.length,\n\t};\n}\n\n// region scanning\n\n/**\n * Blank out `//` and block comments. String and regex literals are copied\n * verbatim, because a `//` inside `/https?:\\/\\//` is not a comment.\n */\nfunction stripComments(source: string): string {\n\tlet out = '';\n\tlet i = 0;\n\n\twhile (i < source.length) {\n\t\tconst char = source[i];\n\n\t\tif (char === '/' && source[i + 1] === '/') {\n\t\t\twhile (i < source.length && source[i] !== '\\n') i++;\n\t\t\tout += ' ';\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === '/' && source[i + 1] === '*') {\n\t\t\ti += 2;\n\t\t\twhile (i < source.length && !(source[i] === '*' && source[i + 1] === '/')) i++;\n\t\t\ti += 2;\n\t\t\tout += ' ';\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"'\" || char === '\"') {\n\t\t\tconst end = endOfString(source, i);\n\t\t\tout += source.slice(i, end);\n\t\t\ti = end;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === '/') {\n\t\t\tconst end = endOfRegex(source, i);\n\t\t\tout += source.slice(i, end);\n\t\t\ti = end;\n\t\t\tcontinue;\n\t\t}\n\n\t\tout += char;\n\t\ti++;\n\t}\n\n\treturn out;\n}\n\n/** Index just past the quoted literal that opens at `start`. */\nfunction endOfString(source: string, start: number): number {\n\tconst quote = source[start];\n\tlet i = start + 1;\n\n\twhile (i < source.length) {\n\t\tif (source[i] === '\\\\') {\n\t\t\ti += 2;\n\t\t\tcontinue;\n\t\t}\n\t\tif (source[i] === quote) return i + 1;\n\t\ti++;\n\t}\n\n\treturn source.length;\n}\n\n/** Index just past the regex literal that opens at `start`. */\nfunction endOfRegex(source: string, start: number): number {\n\tlet i = start + 1;\n\tlet inClass = false;\n\n\twhile (i < source.length) {\n\t\tconst char = source[i];\n\n\t\tif (char === '\\\\') {\n\t\t\ti += 2;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === '[') inClass = true;\n\t\telse if (char === ']') inClass = false;\n\t\telse if (char === '/' && !inClass) return i + 1;\n\n\t\ti++;\n\t}\n\n\treturn source.length;\n}\n\n/**\n * Split on the `;` that ends each rule, ignoring the ones inside strings,\n * regexes and `{ … }` — interfaces have fields, and rules have `{infer X}`\n * actions, both of which can contain semicolons.\n */\nfunction splitStatements(source: string): string[] {\n\tconst statements: string[] = [];\n\tlet depth = 0;\n\tlet start = 0;\n\tlet i = 0;\n\n\twhile (i < source.length) {\n\t\tconst char = source[i];\n\n\t\tif (char === \"'\" || char === '\"') {\n\t\t\ti = endOfString(source, i);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === '/') {\n\t\t\ti = endOfRegex(source, i);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === '{') depth++;\n\t\telse if (char === '}') depth = Math.max(0, depth - 1);\n\t\telse if (char === ';' && depth === 0) {\n\t\t\tstatements.push(source.slice(start, i));\n\t\t\tstart = i + 1;\n\t\t}\n\n\t\ti++;\n\t}\n\n\tconst tail = source.slice(start).trim();\n\tif (tail.length > 0) statements.push(tail);\n\n\treturn statements.filter((statement) => statement.trim().length > 0);\n}\n\nconst HEADERS: { kind: 'rule' | 'fragment' | 'terminal'; hidden: boolean; pattern: RegExp }[] = [\n\t// `hidden terminal WS: /[ \\t]+/`\n\t{ kind: 'terminal', hidden: true, pattern: /^\\s*hidden\\s+terminal\\s+([A-Za-z_]\\w*)\\s*(?:<[^>]*>)?\\s*:/ },\n\t// `terminal LIB_ICON: /…/`, `terminal fragment HASH: '#'`\n\t{\n\t\tkind: 'terminal',\n\t\thidden: false,\n\t\tpattern:\n\t\t\t/^\\s*terminal\\s+(?:fragment\\s+)?([A-Za-z_]\\w*)\\s*(?:<[^>]*>)?\\s*(?:returns\\s+[A-Za-z_]\\w*\\s*)?:/,\n\t},\n\t// `fragment RelationConnector:`\n\t{ kind: 'fragment', hidden: false, pattern: /^\\s*fragment\\s+([A-Za-z_]\\w*)\\s*:/ },\n\t// `Model:`, `ModelViews:`, `entry LikeC4Grammar:`, `Relation<isExplicit>:`\n\t{\n\t\tkind: 'rule',\n\t\thidden: false,\n\t\tpattern: /^\\s*(?:entry\\s+)?([A-Za-z_]\\w*)\\s*(?:<[^>]*>)?\\s*(?:returns\\s+([A-Za-z_]\\w*)\\s*)?:/,\n\t},\n];\n\nfunction readStatement(statement: string): Rule | undefined {\n\tfor (const header of HEADERS) {\n\t\tconst match = header.pattern.exec(statement);\n\t\tconst name = match?.[1];\n\t\tif (!match || !name) continue;\n\n\t\treturn {\n\t\t\tname,\n\t\t\tkind: header.kind,\n\t\t\thidden: header.hidden,\n\t\t\treturns: header.kind === 'rule' ? match[2] : undefined,\n\t\t\ttokens: tokenize(statement.slice(match[0].length)),\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\nfunction tokenize(body: string): Token[] {\n\tconst tokens: Token[] = [];\n\tlet i = 0;\n\n\twhile (i < body.length) {\n\t\tconst char = body.charAt(i);\n\n\t\tif (/\\s/.test(char)) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"'\" || char === '\"') {\n\t\t\tconst end = endOfString(body, i);\n\t\t\ttokens.push({ type: 'literal', value: unquote(body.slice(i, end)) });\n\t\t\ti = end;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === '/') {\n\t\t\tconst end = endOfRegex(body, i);\n\t\t\ttokens.push({ type: 'regex', value: body.slice(i + 1, end - 1) });\n\t\t\ti = end;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst identifier = /^[A-Za-z_]\\w*/.exec(body.slice(i));\n\t\tif (identifier) {\n\t\t\ttokens.push({ type: 'ident', value: identifier[0] });\n\t\t\ti += identifier[0].length;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Multi-character punctuation (`+=`, `?=`) is irrelevant: only `=`, `|`,\n\t\t// `(` and `)` are inspected, and per-character tokens give all four.\n\t\ttokens.push({ type: 'punct', value: char });\n\t\ti++;\n\t}\n\n\treturn tokens;\n}\n\n/** Strip the quotes and resolve the escapes Langium allows in literals. */\nfunction unquote(quoted: string): string {\n\tconst inner = quoted.slice(1, -1);\n\tlet out = '';\n\n\tfor (let i = 0; i < inner.length; i++) {\n\t\tif (inner[i] !== '\\\\') {\n\t\t\tout += inner[i];\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst escaped = inner[++i];\n\t\tif (escaped === 'n') out += '\\n';\n\t\telse if (escaped === 't') out += '\\t';\n\t\telse if (escaped === 'r') out += '\\r';\n\t\telse out += escaped ?? '';\n\t}\n\n\treturn out;\n}\n\n// endregion\n\n// region vocabulary\n\n/**\n * Rules of the shape `'specification' '{' …` or `name='model' '{' …` open a\n * block. The first literal of the rule is the keyword, and it only counts when\n * the rule reaches a `{` without branching first: `'element' kind=ElementKind\n * ('{' …)` has an optional body, so `element` stays a keyword.\n */\nfunction findBlocks(rules: Rule[]): string[] {\n\treturn unique(\n\t\trules.flatMap((rule) => {\n\t\t\tconst tokens = rule.tokens;\n\t\t\tconst first = tokens.findIndex((token) => token.type === 'literal');\n\t\t\tconst keyword = first === -1 ? undefined : tokens[first]?.value;\n\n\t\t\tif (!keyword || keyword === '{' || !/^[A-Za-z_]\\w*$/.test(keyword)) return [];\n\n\t\t\tfor (let i = first + 1; i < tokens.length; i++) {\n\t\t\t\tconst token = tokens[i];\n\t\t\t\tif (!token) break;\n\t\t\t\tif (token.value === '(' || token.value === '|') return [];\n\t\t\t\tif (token.type === 'literal' && token.value === '{') return [keyword];\n\t\t\t}\n\n\t\t\treturn [];\n\t\t}),\n\t);\n}\n\n/**\n * `key='title'` and `key=('head' | 'tail')` name a property. Positional\n * arguments (`props+=String`) and `name=` (block headers) are ignored.\n */\nfunction findProperties(rules: Rule[]): string[] {\n\tconst properties: string[] = [];\n\n\tfor (const rule of rules) {\n\t\tconst tokens = rule.tokens;\n\n\t\tfor (let i = 0; i < tokens.length; i++) {\n\t\t\tconst token = tokens[i];\n\t\t\tif (!token || token.type !== 'ident' || token.value !== 'key') continue;\n\n\t\t\tconst equals = equalsIndex(tokens, i);\n\t\t\tif (equals === -1) continue;\n\n\t\t\tlet j = equals + 1;\n\n\t\t\tif (tokens[j]?.value === '(') {\n\t\t\t\tfor (j++; j < tokens.length && tokens[j]?.value !== ')'; j++) {\n\t\t\t\t\tconst inner = tokens[j];\n\t\t\t\t\tif (inner?.type === 'literal') properties.push(inner.value);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst value = tokens[j];\n\t\t\tif (value?.type === 'literal') properties.push(value.value);\n\t\t}\n\t}\n\n\treturn properties.filter((value) => /^[A-Za-z_]\\w*$/.test(value));\n}\n\n/**\n * Index of the `=` that assigns `tokens[i]` (`key=`, `key?=`, `key+=`), or `-1`\n * when the identifier is not being assigned.\n */\nfunction equalsIndex(tokens: Token[], i: number): number {\n\tif (tokens[i]?.type !== 'ident') return -1;\n\n\tconst next = tokens[i + 1]?.value;\n\tif (next === '=') return i + 1;\n\tif ((next === '?' || next === '+') && tokens[i + 2]?.value === '=') return i + 2;\n\n\treturn -1;\n}\n\n/**\n * The connectors live in one fragment:\n * dotKind=RelationKindDotRef | '-[' kind=[RelationshipKind] (… '->') | … | '->'\n */\nfunction findArrows(rules: Rule[]): string[] {\n\tconst connector = rules.find((rule) => rule.name === 'RelationConnector');\n\tconst fromConnector = (connector?.tokens ?? [])\n\t\t.filter((token) => token.type === 'literal' && token.value.includes('->'))\n\t\t.map((token) => token.value);\n\n\t// Longest first: TextMate alternation is first-match, so `]->` has to be\n\t// tried before `->` at the same position.\n\treturn unique([...fromConnector, '->', '<->']).sort((a, b) => b.length - a.length || a.localeCompare(b));\n}\n\n/**\n * A `returns string` rule whose body is only literals, `|` and references to\n * other such rules is a closed value domain — `BorderStyleValue: LineOptions |\n * 'none'` inherits from `LineOptions` that way. Anything referencing a rule\n * that is not itself a value domain (e.g. `Id returns string`) resolves to\n * nothing and is dropped.\n */\nfunction resolveEnums(rules: Rule[]): Record<string, string[]> {\n\tconst candidates = new Map<string, string[]>();\n\n\tfor (const rule of rules) {\n\t\tif (rule.returns !== 'string' || NOT_VALUE_DOMAINS.test(rule.name)) continue;\n\n\t\tconst onlyValuesAndChoices = rule.tokens.every(\n\t\t\t(token) =>\n\t\t\t\ttoken.type === 'literal' ||\n\t\t\t\ttoken.type === 'ident' ||\n\t\t\t\t(token.type === 'punct' && (token.value === '|' || token.value === ';')),\n\t\t);\n\n\t\tif (onlyValuesAndChoices) candidates.set(rule.name, []);\n\t}\n\n\t// Fixpoint, because `BorderStyleValue` can only resolve once `LineOptions`\n\t// has. One pass per rule is enough for any acyclic grammar.\n\tfor (let pass = 0; pass < rules.length; pass++) {\n\t\tlet changed = false;\n\n\t\tfor (const rule of rules) {\n\t\t\tif (!candidates.has(rule.name)) continue;\n\n\t\t\tconst resolved: string[] = [];\n\t\t\tlet complete = true;\n\n\t\t\tfor (const token of rule.tokens) {\n\t\t\t\tif (token.type === 'literal') {\n\t\t\t\t\tresolved.push(token.value);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (token.type !== 'ident') continue;\n\n\t\t\t\tconst inherited = candidates.get(token.value);\n\t\t\t\tif (inherited === undefined) {\n\t\t\t\t\tcomplete = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tresolved.push(...inherited);\n\t\t\t}\n\n\t\t\tconst next = unique(resolved);\n\t\t\tif (!complete || next.length === 0) continue;\n\n\t\t\tif ((candidates.get(rule.name) ?? []).length !== next.length) {\n\t\t\t\tcandidates.set(rule.name, next);\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\n\t\tif (!changed) break;\n\t}\n\n\tconst enums: Record<string, string[]> = {};\n\tfor (const [name, values] of [...candidates].sort(([a], [b]) => a.localeCompare(b))) {\n\t\tif (values.length > 0) enums[name] = values;\n\t}\n\n\treturn enums;\n}\n\n/** Reads every `terminal` rule, keyed by name. */\nfunction readTerminals(rules: Rule[]): Record<string, Terminal> {\n\tconst terminals: Record<string, Terminal> = {};\n\n\tfor (const rule of rules) {\n\t\tif (rule.kind !== 'terminal') continue;\n\n\t\tconst token = rule.tokens.find((candidate) => candidate.type === 'regex' || candidate.type === 'literal');\n\t\tif (!token) continue;\n\n\t\tterminals[rule.name] = {\n\t\t\thidden: rule.hidden,\n\t\t\tkind: token.type === 'regex' ? 'regex' : 'literal',\n\t\t\tvalue: token.value,\n\t\t};\n\t}\n\n\treturn terminals;\n}\n\n/**\n * The alternatives of the first group in a terminal's regex:\n * `(aws|azure|bootstrap|gcp|md|tech):[-\\w]+` -> the icon packs.\n */\nfunction terminalAlternatives(terminal: Terminal | undefined): string[] {\n\tif (!terminal || terminal.kind !== 'regex') return [];\n\n\tconst group = /\\(([^()]*)\\)/.exec(terminal.value);\n\tif (!group) return [];\n\n\treturn unique((group[1] ?? '').split('|').map((value) => value.trim())).filter((value) =>\n\t\t/^[A-Za-z][\\w-]*$/.test(value),\n\t);\n}\n\nfunction unique(values: string[]): string[] {\n\treturn [...new Set(values)].sort((a, b) => a.localeCompare(b));\n}\n\n// endregion\n\nexport default parseLangium;\n\n",
7
- "// textmate.mjs\n// path: src/grammar/textmate.mjs\n// Builds the Shiki / TextMate grammar for LikeC4 out of the vocabulary read\n// from the live Langium grammar (./langium.mjs).\n//\n// Two layers:\n// - generated — every word list: blocks, keywords, property names and closed\n// value domains. These are exactly the lists that go stale when the\n// language grows (`agent` was added to `ElementShape` after v1.59.4).\n// - structural — how LikeC4 source is *shaped* rather than which words it\n// uses: comments, quoted and triple-quoted strings, `#tag` vs `#hex`,\n// `tech:astro` icons, `-[https]->` arrows, `element system` declarations.\n// These are curated here because a Langium rule does not say how a token\n// should look, only that it is one.\n//\n// The result must stay plain JSON: Expressive Code JSON-round-trips integration\n// options before the `<Code>` component renders them, and throws on functions\n// or RegExp instances.\n\nimport type { Vocabulary } from './langium.js';\n\n/** Scope name of the grammar, as upstream's VS Code extension uses it. */\nexport const SCOPE_NAME = 'source.likec4';\n\n/** Shiki language id, plus the short alias used by ` ```c4 ` fences. */\nexport const LANGUAGE_NAME = 'likec4';\nexport const LANGUAGE_ALIASES = ['c4'];\n\nconst TMLANGUAGE_SCHEMA =\n\t'https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json';\n\n/**\n * Closed value domains: they colour as values, not as keywords.\n * Anything the grammar adds under these names is picked up automatically.\n */\nconst VALUE_DOMAINS = [\n\t'BorderStyleValue',\n\t'DynamicViewDisplayVariantValue',\n\t'EdgeRoutingValue',\n\t'ElementShape',\n\t'IconPositionValue',\n\t'LineOptions',\n\t'ArrowType',\n\t'RankValue',\n\t'SizeValue',\n\t'SizingValue',\n\t'ThemeColor',\n\t'ViewLayoutDirection',\n];\n\n/** Control-flow keywords read as keywords, not as a value domain. */\nconst KEYWORD_DOMAINS = ['DynamicViewFlowKeyword'];\n\n/** `source` / `target` are the only value-like variables. */\nconst VARIABLE_DOMAINS = ['Participant'];\n\n/** Operators whose scope is a word, kept curated: they are not all literals. */\nconst OPERATOR_WORDS = ['and', 'or', 'not', 'is'];\n\n/** Used when the grammar cannot be read — never expected, never silent. */\nconst FALLBACK_ICON_PACKS = ['aws', 'azure', 'bootstrap', 'gcp', 'tech'];\n\n/** One TextMate pattern. `match`/`begin`/`end` are regex *source*, not `RegExp`. */\nexport interface TmPattern {\n\tname?: string;\n\tcomment?: string;\n\tinclude?: string;\n\tmatch?: string;\n\tbegin?: string;\n\tend?: string;\n\tcontentName?: string;\n\tcaptures?: Record<string, { name: string }>;\n\tbeginCaptures?: Record<string, { name: string }>;\n\tendCaptures?: Record<string, { name: string }>;\n\tpatterns?: TmPattern[];\n}\n\n/** A TextMate grammar: JSON all the way down, never a `RegExp`. */\nexport interface TmGrammar {\n\t$schema: string;\n\tname: string;\n\tdisplayName: string;\n\tscopeName: string;\n\tfileTypes: string[];\n\tpatterns: TmPattern[];\n\t// Each repository entry is a pattern group; the tests index into them.\n\trepository: Record<string, any>;\n\t$generated?: { repo: string; ref: string; sha?: string; by: string };\n}\n\n/** Where the grammar came from, written into the snapshot's `$generated`. */\nexport interface TmProvenance {\n\trepo?: string;\n\tref?: string;\n\tsha?: string;\n}\n\n/** Turns a vocabulary into a TextMate grammar, JSON-serialisable. */\nexport function buildTmLanguage(vocabulary: Vocabulary, meta: TmProvenance = {}): TmGrammar {\n\tconst control = uniqueDomain(vocabulary, KEYWORD_DOMAINS);\n\tconst variables = uniqueDomain(vocabulary, VARIABLE_DOMAINS);\n\tconst icons = vocabulary.icons.length > 0 ? vocabulary.icons : FALLBACK_ICON_PACKS;\n\n\t// Words that are always syntax, never the name of a kind: `deployed =\n\t// instanceOf a` must not paint `instanceOf` as a type.\n\tconst reserved = alternationOf([...vocabulary.keywords, ...vocabulary.blocks, ...control]);\n\n\tconst grammar: TmGrammar = {\n\t\t$schema: TMLANGUAGE_SCHEMA,\n\t\t...(meta.repo && meta.ref\n\t\t\t? {\n\t\t\t\t\t$generated: {\n\t\t\t\t\t\trepo: meta.repo,\n\t\t\t\t\t\tref: meta.ref,\n\t\t\t\t\t\t...(meta.sha ? { sha: meta.sha } : {}),\n\t\t\t\t\t\tby: 'astroc4/scripts/sync-grammar.ts',\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t\tname: LANGUAGE_NAME,\n\t\tdisplayName: 'LikeC4',\n\t\tscopeName: SCOPE_NAME,\n\t\tfileTypes: ['c4', 'likec4'],\n\t\tpatterns: [{ include: '#everything' }],\n\t\trepository: {\n\t\t\teverything: {\n\t\t\t\tpatterns: [\n\t\t\t\t\t'comments',\n\t\t\t\t\t'strings',\n\t\t\t\t\t'urls',\n\t\t\t\t\t'icons',\n\t\t\t\t\t'hex-colors',\n\t\t\t\t\t'tags',\n\t\t\t\t\t'typed-arrow',\n\t\t\t\t\t'declarations',\n\t\t\t\t\t'keywords',\n\t\t\t\t\t'numbers',\n\t\t\t\t\t'operators',\n\t\t\t\t\t'punctuation',\n\t\t\t\t].map((name) => ({ include: `#${name}` })),\n\t\t\t},\n\t\t\tcomments: comments(),\n\t\t\tstrings: strings(),\n\t\t\turls: urls(),\n\t\t\ticons: iconIds(icons),\n\t\t\t'hex-colors': hexColours(),\n\t\t\ttags: tags(),\n\t\t\t'typed-arrow': typedArrow(),\n\t\t\tdeclarations: declarations(reserved),\n\t\t\tkeywords: keywords({ ...vocabulary, control, variables }),\n\t\t\tnumbers: numbers(),\n\t\t\toperators: operators(vocabulary.arrows),\n\t\t\tpunctuation: punctuation(),\n\t\t},\n\t};\n\n\tif (meta.repo && meta.ref) {\n\t\tgrammar.$generated = {\n\t\t\trepo: meta.repo,\n\t\t\tref: meta.ref,\n\t\t\t...(meta.sha ? { sha: meta.sha } : {}),\n\t\t\tby: 'astroc4/scripts/sync-grammar.ts',\n\t\t};\n\t}\n\n\treturn grammar;\n}\n// region structural patterns\n\nfunction comments() {\n\treturn {\n\t\tpatterns: [\n\t\t\t{\n\t\t\t\tname: 'comment.block.likec4',\n\t\t\t\tbegin: '/\\\\*',\n\t\t\t\tend: '\\\\*/',\n\t\t\t\tcaptures: { 0: { name: 'punctuation.definition.comment.likec4' } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'comment.line.double-slash.likec4',\n\t\t\t\tmatch: '//.*$',\n\t\t\t\tcaptures: { 0: { name: 'punctuation.definition.comment.likec4' } },\n\t\t\t},\n\t\t],\n\t};\n}\n\n/**\n * `'…'`, `\"…\"`, and the markdown strings `''' … '''` / `\"\"\" … \"\"\"` that\n * LikeC4 uses for descriptions.\n */\nfunction strings() {\n\tconst triple = (quote: string): TmPattern => ({\n\t\tname: 'string.quoted.triple.likec4',\n\t\tbegin: quote.repeat(3),\n\t\tend: quote.repeat(3),\n\t\tbeginCaptures: { 0: { name: 'punctuation.definition.string.begin.likec4' } },\n\t\tendCaptures: { 0: { name: 'punctuation.definition.string.end.likec4' } },\n\t});\n\n\tconst single = (quote: string, name: string): TmPattern => ({\n\t\tname,\n\t\tbegin: quote,\n\t\tend: `${quote}|$`,\n\t\tbeginCaptures: { 0: { name: 'punctuation.definition.string.begin.likec4' } },\n\t\tendCaptures: { 0: { name: 'punctuation.definition.string.end.likec4' } },\n\t\tpatterns: [{ name: 'constant.character.escape.likec4', match: '\\\\\\\\.' }],\n\t});\n\n\treturn {\n\t\tpatterns: [\n\t\t\ttriple(\"'\"),\n\t\t\ttriple('\"'),\n\t\t\tsingle(\"'\", 'string.quoted.single.likec4'),\n\t\t\tsingle('\"', 'string.quoted.double.likec4'),\n\t\t],\n\t};\n}\n\nfunction urls() {\n\treturn { name: 'markup.underline.link.likec4', match: \"\\\\bhttps?://[^\\\\s'\\\"]+\" };\n}\n\n/**\n * Icon ids (`tech:astro`, `aws:lambda`). The packs come from the `LIB_ICON`\n * terminal, so a pack added upstream highlights without touching this package.\n */\nfunction iconIds(packs: string[]): TmPattern {\n\treturn {\n\t\tcomment: 'Bundled icon ids: `tech:nginx`, `aws:…`, `gcp:…`, …',\n\t\tmatch: `\\\\b(${alternationOf(packs)})(:)([\\\\w-]+)`,\n\t\tcaptures: {\n\t\t\t1: { name: 'support.constant.icon-pack.likec4' },\n\t\t\t2: { name: 'punctuation.separator.likec4' },\n\t\t\t3: { name: 'support.constant.icon.likec4' },\n\t\t},\n\t};\n}\n\n/** `#0046BE` is a colour, `#compute` is a tag — hex first, so it wins. */\nfunction hexColours() {\n\treturn {\n\t\tname: 'constant.other.color.rgb-value.hex.likec4',\n\t\tmatch: '#(?:[0-9A-Fa-f]{8}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})(?![\\\\w-])',\n\t};\n}\n\nfunction tags() {\n\treturn { name: 'entity.name.tag.likec4', match: '#[A-Za-z_][\\\\w-]*' };\n}\n\n/** `a -[https]-> b` — the relationship kind inside the connector. */\nfunction typedArrow() {\n\treturn {\n\t\tcomment: '`a -[https]-> b`',\n\t\tmatch: '(-\\\\[)\\\\s*([A-Za-z_][\\\\w-]*)\\\\s*(\\\\]->)',\n\t\tcaptures: {\n\t\t\t1: { name: 'keyword.operator.arrow.likec4' },\n\t\t\t2: { name: 'entity.name.type.relationship.likec4' },\n\t\t\t3: { name: 'keyword.operator.arrow.likec4' },\n\t\t},\n\t};\n}\n\n/**\n * Declarations: the name being introduced is scoped, the name only being\n * referred to is not. Runs before the keyword patterns so `element system`\n * reads as a declaration rather than as two keywords.\n *\n * `reserved` is the alternation of syntax words (`instanceOf`, `extend`, …), so\n * `deployed = instanceOf a` scopes `instanceOf` as a keyword rather than as the\n * element kind the name is being assigned.\n */\nfunction declarations(reserved: string): TmPattern {\n\tconst notReserved = reserved ? `(?!(?:${reserved})\\\\b)` : '';\n\n\treturn {\n\t\tpatterns: [\n\t\t\t{\n\t\t\t\tcomment:\n\t\t\t\t\t'`element system`, `deploymentNode region`, `tag tls`, `relationship https`. Not `where tag is #x`.',\n\t\t\t\tmatch: '\\\\b(element|deploymentNode|tag|relationship)\\\\s+(?!is\\\\b)([A-Za-z_][\\\\w-]*)(?=\\\\s*(?:\\\\{|$|//))',\n\t\t\t\tcaptures: {\n\t\t\t\t\t1: { name: 'storage.type.likec4' },\n\t\t\t\t\t2: { name: 'entity.name.type.likec4' },\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tcomment:\n\t\t\t\t\t'`color testingBlue #0046BE` declares; `color testingBlue` inside a style block only refers.',\n\t\t\t\tmatch: '\\\\b(color)\\\\s+([A-Za-z_][\\\\w-]*)(?=\\\\s+#)',\n\t\t\t\tcaptures: {\n\t\t\t\t\t1: { name: 'storage.type.likec4' },\n\t\t\t\t\t2: { name: 'entity.name.type.likec4' },\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tcomment: '`view index`, `dynamic view firstRequest`, `deployment view prod`, `view internals of site`',\n\t\t\t\tmatch: '\\\\b(?:(dynamic|deployment)\\\\s+)?(view)\\\\s+([A-Za-z_]\\\\w*)',\n\t\t\t\tcaptures: {\n\t\t\t\t\t1: { name: 'storage.modifier.likec4' },\n\t\t\t\t\t2: { name: 'storage.type.view.likec4' },\n\t\t\t\t\t3: { name: 'entity.name.function.view.likec4' },\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tcomment: \"`reader = actor 'Engineer'`\",\n\t\t\t\tmatch: `\\\\b([A-Za-z_]\\\\w*)\\\\s*(=)(?!=)\\\\s*${notReserved}([A-Za-z_]\\\\w*)?`,\n\t\t\t\tcaptures: {\n\t\t\t\t\t1: { name: 'variable.other.definition.likec4' },\n\t\t\t\t\t2: { name: 'keyword.operator.assignment.likec4' },\n\t\t\t\t\t3: { name: 'entity.name.type.likec4' },\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t};\n}\n\n// endregion\n\n// region generated keyword patterns\n\n/**\n * Order matters here: blocks before plain keywords (so `model {` is a block),\n * operator words before keywords (`is`, `not`), variables before value domains\n * (so `source`/`target` stay variables even though `RankValue` reuses `source`).\n *\n */\nfunction keywords(vocabulary: Vocabulary & { control: string[]; variables: string[] }): TmPattern {\n\tconst patterns: TmPattern[] = [];\n\n\tconst blocks = alternationOf(vocabulary.blocks);\n\tif (blocks) {\n\t\tpatterns.push({\n\t\t\tcomment: 'Keywords that open a block: `model { … }`.',\n\t\t\tname: 'keyword.control.block.likec4',\n\t\t\tmatch: `\\\\b(?:${blocks})\\\\b(?=\\\\s*\\\\{)`,\n\t\t});\n\t}\n\n\t// Blocks repeat in the keyword list on purpose: `predicateGroup mine { … }`\n\t// is not followed by `{`, and still has to colour as a keyword. The block\n\t// pattern above wins wherever the brace is there.\n\tconst control = alternationOf([...vocabulary.keywords, ...vocabulary.control, ...vocabulary.blocks]);\n\n\t// Word operators (`is`, `not`) come before the keyword list, which also\n\t// contains them: `where tag is #x` reads as an operator, not a keyword.\n\tpatterns.push({\n\t\tname: 'keyword.operator.word.likec4',\n\t\tmatch: `\\\\b(?:${alternationOf(OPERATOR_WORDS)})\\\\b`,\n\t});\n\n\tif (control) {\n\t\tpatterns.push({ name: 'keyword.control.likec4', match: `\\\\b(?:${control})\\\\b` });\n\t}\n\n\tconst variables = alternationOf(vocabulary.variables);\n\tif (variables) {\n\t\tpatterns.push({ name: 'variable.language.likec4', match: `\\\\b(?:${variables})\\\\b` });\n\t}\n\n\tconst properties = alternationOf(vocabulary.properties);\n\tif (properties) {\n\t\tpatterns.push({ name: 'support.type.property-name.likec4', match: `\\\\b(?:${properties})\\\\b` });\n\t}\n\n\tconst values = alternationOf(uniqueDomain(vocabulary, VALUE_DOMAINS));\n\tif (values) {\n\t\tpatterns.push({ name: 'constant.language.likec4', match: `\\\\b(?:${values})\\\\b` });\n\t}\n\n\treturn { patterns };\n}\n\nfunction numbers() {\n\treturn { name: 'constant.numeric.likec4', match: '\\\\b\\\\d+(?:\\\\.\\\\d+)?%?' };\n}\n\n/**\n * Relationship connectors, longest first so `]->` wins over `->`.\n */\nfunction operators(arrows: string[]): TmPattern {\n\tconst patterns: TmPattern[] = [];\n\n\tconst connectors = alternationOf(arrows);\n\tif (connectors) {\n\t\tpatterns.push({ name: 'keyword.operator.arrow.likec4', match: connectors });\n\t}\n\n\tpatterns.push({ name: 'keyword.operator.wildcard.likec4', match: '\\\\.\\\\*\\\\*|\\\\.\\\\*|\\\\*\\\\*|\\\\*' });\n\n\treturn { patterns };\n}\n\nfunction punctuation() {\n\treturn {\n\t\tpatterns: [\n\t\t\t{ name: 'punctuation.section.block.begin.likec4', match: '\\\\{' },\n\t\t\t{ name: 'punctuation.section.block.end.likec4', match: '\\\\}' },\n\t\t\t{ name: 'punctuation.separator.comma.likec4', match: ',' },\n\t\t\t{ name: 'punctuation.accessor.likec4', match: '\\\\.' },\n\t\t],\n\t};\n}\n\n// endregion\n\n// region helpers\n\n/**\n * Every value of the named domains, deduplicated and sorted. Missing domains\n * are skipped rather than failing: upstream is free to rename a rule, and a\n * renamed domain still reaches the grammar through `keywords`.\n */\nfunction uniqueDomain(vocabulary: Vocabulary, names: string[]): string[] {\n\tconst values = names.flatMap((name) => vocabulary.enums[name] ?? []);\n\n\treturn [...new Set(values)].sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * `['a', 'b']` -> `a|b`, escaped for a TextMate regex. Returns '' for an empty\n * list so callers can skip the pattern instead of emitting `\\b(?:)\\b`.\n */\nfunction alternationOf(values: string[]): string {\n\treturn values.map(escapeRegExp).join('|');\n}\n\nfunction escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n// endregion\n\nexport default buildTmLanguage;\n\n",
8
- "// expressive-code.ts\n// path: src/expressive-code.ts\n// LikeC4 syntax highlighting for Expressive Code (Starlight's code blocks).\n// Shiki ships no LikeC4 grammar, so without this .c4 source renders as plain\n// text.\n//\n// The Starlight plugin injects this language into the site's Expressive Code\n// options for you (see src/index.ts) resolved from the live Langium grammar.\n// The exports here cover the two cases the plugin cannot:\n//\n// - a site that already has an `ec.config.mjs`, which can add the bundled\n// grammar with one line:\n//\n// import { likec4Language } from '@purview-dev/astroc4/expressive-code';\n// export default defineEcConfig({ shiki: { langs: [likec4Language] } });\n//\n// - anything else that needs the grammar programmatically, e.g. a Markdown\n// pipeline of its own: `await loadLikeC4Language({ ref: 'v1.59.4' })`.\n//\n// `likec4Language` is the bundled snapshot, so it works without network\n// access; `loadLikeC4Language` fetches the ref you ask for.\n\nimport type { LanguageRegistration } from 'shiki';\n\nimport grammar from './grammar/likec4.tmLanguage.json' with { type: 'json' };\nimport { resolveLikeC4Grammar, type GrammarSourceOptions } from './grammar/source.js';\nimport { LANGUAGE_ALIASES, LANGUAGE_NAME, type TmGrammar } from './grammar/textmate.js';\n\n/**\n * The snapshot is a `TmGrammar` by construction — `buildTmLanguage` produced it\n * and the snapshot test asserts it — but Shiki wants `IRawRepository`, which\n * the generated `repository` (JSON, not `RegExp`) cannot satisfy structurally.\n * One cast here beats one at every call site.\n */\nfunction registration(grammar: TmGrammar): LanguageRegistration & { aliases: string[] } {\n\treturn {\n\t\t...grammar,\n\t\tname: LANGUAGE_NAME,\n\t\taliases: [...LANGUAGE_ALIASES],\n\t} as LanguageRegistration & { aliases: string[] };\n}\n\n/** Shiki registration for LikeC4, under `likec4` with a `c4` alias. */\nexport const likec4Language: LanguageRegistration & { aliases: string[] } = registration(\n\tgrammar as TmGrammar,\n);\n\n/**\n * Resolve the grammar from likec4/likec4 at the ref you ask for and return it\n * as a Shiki language registration.\n */\nexport async function loadLikeC4Language(\n\toptions?: GrammarSourceOptions,\n): Promise<LanguageRegistration & { aliases: string[] }> {\n\tconst { grammar: resolved } = await resolveLikeC4Grammar(options);\n\n\treturn registration(resolved);\n}\n\nexport default likec4Language;\n"
5
+ "// Runs from `astro:config:setup`, so a bad ref fails dev, build, check and sync\n// rather than shipping unhighlighted code. A bad ref always fails; a network\n// failure falls back to the cache, then the bundled snapshot, only when\n// `onError` allows it.\n\nimport { createHash } from 'node:crypto';\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { parseLangium } from './langium.ts';\nimport { buildTmLanguage, type TmGrammar } from './textmate.ts';\n\nexport const DEFAULT_REPO = 'likec4/likec4';\nexport const DEFAULT_REF = 'main';\nexport const LANGIUM_PATH = 'packages/language-server/src/like-c4.langium';\nexport const DEFAULT_BASE_URL = 'https://raw.githubusercontent.com';\n\n/** Shape of a cache file. Bump when the fields change. */\nconst CACHE_VERSION = 1;\n\nconst BUNDLED_GRAMMAR = new URL('./likec4.tmLanguage.json', import.meta.url);\nconst BUNDLED_LANGIUM = new URL('./like-c4.langium', import.meta.url);\n\n/** The refs a repository actually has: branches, tags, `a1b2c3d`. */\nconst REF_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._/-]*$/;\n\nexport type OnError = 'fail' | 'warn' | 'silent';\n\nexport interface GrammarSourceOptions {\n\t/** Repository to read from. Defaults to likec4/likec4. */\n\trepo?: string;\n\t/** Branch, tag or commit SHA. Defaults to `main`. */\n\tref?: string;\n\t/** Use the bundled snapshot, never the network. */\n\toffline?: boolean;\n\t/** What to do when the grammar cannot be fetched. */\n\tonError?: OnError;\n\t/** Seconds a cached fetch stays fresh. */\n\tcacheTtl?: number;\n\t/** Ignore the cache and refetch. */\n\trefresh?: boolean;\n\t/** Raw file host, for mirrors and proxies. */\n\tbaseUrl?: string;\n\t/** Request timeout in milliseconds. */\n\ttimeout?: number;\n\t/** Site root, for the default cache directory. */\n\troot?: string;\n\tcacheDir?: string;\n\t/** Environment, for `ASTROC4_*` overrides. */\n\tenv?: NodeJS.ProcessEnv;\n\tlogger?: { info?: (message: string) => void; warn?: (message: string) => void };\n\t/** Injected in tests. */\n\tfetchImpl?: typeof fetch;\n\t/** Bundled Langium text, for tests. */\n\tbundledLangiumPath?: string;\n}\n\nexport interface GrammarMeta {\n\trepo: string;\n\tref: string;\n\tsource: 'network' | 'cache' | 'bundled';\n\tfetchedAt: number;\n\tetag?: string | undefined;\n\t/** Content hash of the Langium source. */\n\tsha: string;\n\t/** Why the bundled snapshot was used. */\n\treason?: string;\n}\n\nexport interface GrammarSource {\n\tgrammar: TmGrammar;\n\tlangium: string;\n\tmeta: GrammarMeta;\n}\n\ninterface GrammarIdentity {\n\trepo: string;\n\tref: string;\n}\n\n/** Raised for a ref this repository cannot have — always a user error. */\nexport class GrammarRefError extends Error {\n\toverride name = 'GrammarRefError';\n}\n\n/** Raised when the grammar could not be fetched, or came back unusable. */\nexport class GrammarFetchError extends Error {\n\toverride name = 'GrammarFetchError';\n}\n\nexport async function resolveLikeC4Grammar(options: GrammarSourceOptions = {}): Promise<GrammarSource> {\n\tconst env = options.env ?? process.env;\n\tconst repo = options.repo ?? DEFAULT_REPO;\n\tconst ref = env.ASTROC4_REF || options.ref || DEFAULT_REF;\n\tconst offline = options.offline ?? isTruthy(env.ASTROC4_OFFLINE);\n\tconst onError = options.onError ?? 'fail';\n\tconst logger = options.logger;\n\n\tvalidateRef(ref);\n\n\tif (offline) {\n\t\treturn bundled('offline: true', options);\n\t}\n\n\tconst cache = await readCache(options, { repo, ref });\n\n\tif (cache?.fresh && !options.refresh) {\n\t\treturn derive(cache.langium, { repo, ref, source: 'cache', fetchedAt: cache.fetchedAt, etag: cache.etag });\n\t}\n\n\tlet fetched;\n\n\ttry {\n\t\tfetched = await fetchLangiumSource({ ...options, repo, ref, etag: cache?.etag });\n\t} catch (error) {\n\t\tif (!(error instanceof Error)) throw error;\n\n\t\t// A bad ref will fail the same way forever: never paper over it.\n\t\tif (error instanceof GrammarRefError) throw error;\n\n\t\tif (onError === 'fail') throw error;\n\n\t\tif (onError === 'warn') logger?.warn?.(`[astroc4] ${error.message}`);\n\n\t\tif (cache) {\n\t\t\tif (onError === 'warn') {\n\t\t\t\tlogger?.warn?.(`[astroc4] using the grammar cached at ${new Date(cache.fetchedAt).toISOString()}`);\n\t\t\t}\n\n\t\t\treturn derive(cache.langium, {\n\t\t\t\trepo,\n\t\t\t\tref,\n\t\t\t\tsource: 'cache',\n\t\t\t\tfetchedAt: cache.fetchedAt,\n\t\t\t\tetag: cache.etag,\n\t\t\t});\n\t\t}\n\n\t\treturn bundled(error.message, options);\n\t}\n\n\tif ('notModified' in fetched) {\n\t\tif (!cache) {\n\t\t\tthrow new GrammarFetchError(\n\t\t\t\t'the grammar host answered 304 for a grammar that is not cached — retry with `refresh: true`',\n\t\t\t);\n\t\t}\n\n\t\tawait writeCache(options, { repo, ref }, cache);\n\n\t\treturn derive(cache.langium, { repo, ref, source: 'cache', fetchedAt: cache.fetchedAt, etag: cache.etag });\n\t}\n\n\tconst result = derive(fetched.text, { repo, ref, source: 'network', etag: fetched.etag });\n\tawait writeCache(options, { repo, ref }, { langium: fetched.text, etag: fetched.etag });\n\n\treturn result;\n}\n\ninterface DeriveInfo {\n\trepo: string;\n\tref: string;\n\tsource: 'network' | 'cache' | 'bundled';\n\tfetchedAt?: number;\n\tetag?: string | undefined;\n}\n\nfunction derive(langium: string, info: DeriveInfo): GrammarSource {\n\tlet vocabulary;\n\n\ttry {\n\t\tvocabulary = parseLangium(langium);\n\t} catch (cause) {\n\t\tthrow new GrammarFetchError(\n\t\t\t`${info.repo}@${info.ref}: the grammar could not be read — ${cause instanceof Error ? cause.message : String(cause)}`,\n\t\t\t{ cause },\n\t\t);\n\t}\n\n\tconst sha = grammarSha(langium);\n\n\treturn {\n\t\tgrammar: buildTmLanguage(vocabulary, { repo: info.repo, ref: info.ref, sha }),\n\t\tlangium,\n\t\tmeta: {\n\t\t\trepo: info.repo,\n\t\t\tref: info.ref,\n\t\t\tsource: info.source,\n\t\t\tfetchedAt: info.fetchedAt ?? Date.now(),\n\t\t\tetag: info.etag,\n\t\t\tsha,\n\t\t},\n\t};\n}\n\n/**\n * Derived from the committed `like-c4.langium`; its provenance is the\n * snapshot's own, not the ref that was asked for.\n * @param reason Why it is being used, surfaced in logs.\n */\nasync function bundled(reason: string, options: GrammarSourceOptions): Promise<GrammarSource> {\n\tconst path = options.bundledLangiumPath ?? fileURLToPath(BUNDLED_LANGIUM);\n\tconst snapshot = await bundledProvenance();\n\n\tconst source = derive(await readFile(path, 'utf8'), {\n\t\trepo: snapshot.repo ?? DEFAULT_REPO,\n\t\tref: snapshot.ref ?? DEFAULT_REF,\n\t\tsource: 'bundled',\n\t});\n\n\tsource.meta.reason = reason;\n\n\treturn source;\n}\n\n/** `$generated` from the shipped grammar, so logs name the real snapshot. */\nasync function bundledProvenance(): Promise<{ repo?: string; ref?: string }> {\n\ttry {\n\t\tconst { $generated } = JSON.parse(await readFile(fileURLToPath(BUNDLED_GRAMMAR), 'utf8'));\n\n\t\treturn { repo: $generated?.repo, ref: $generated?.ref };\n\t} catch {\n\t\treturn {};\n\t}\n}\n\n/** Short content hash — the identity that actually changes highlighting. */\nexport function grammarSha(source: string): string {\n\treturn createHash('sha256').update(source).digest('hex').slice(0, 12);\n}\n\n// region refs\n\nexport function validateRef(ref: string): string {\n\tif (typeof ref !== 'string' || ref.length === 0) {\n\t\tthrow new GrammarRefError('the LikeC4 grammar `ref` must be a branch, tag or commit SHA');\n\t}\n\n\tif (!REF_PATTERN.test(ref) || ref.includes('..') || ref.endsWith('/') || ref.includes('//')) {\n\t\tthrow new GrammarRefError(\n\t\t\t`\"${ref}\" is not a usable LikeC4 grammar ref — expected a branch, tag or commit SHA such as \"main\" or \"v1.59.4\"`,\n\t\t);\n\t}\n\n\treturn ref;\n}\n\n\n// endregion\n\n// region fetch\n\n/** What a fetch returns: the text, or the news that the ETag still matches. */\nexport type FetchResult = { text: string; etag?: string | undefined } | { notModified: true };\n\nexport async function fetchLangiumSource(\n\toptions: GrammarSourceOptions & { repo: string; ref: string; etag?: string | undefined },\n): Promise<FetchResult> {\n\tconst repo = options.repo;\n\tconst ref = options.ref;\n\tconst baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\n\tconst url = `${baseUrl}/${repo}/${ref}/${LANGIUM_PATH}`;\n\tconst timeout = options.timeout ?? 15_000;\n\tconst request = options.fetchImpl ?? fetch;\n\n\tconst headers: Record<string, string> = { 'user-agent': 'astroc4', accept: 'text/plain' };\n\tif (options.etag) headers['if-none-match'] = options.etag;\n\n\tlet response;\n\n\ttry {\n\t\tresponse = await request(url, { headers, redirect: 'follow', signal: AbortSignal.timeout(timeout) });\n\t} catch (cause) {\n\t\tthrow new GrammarFetchError(\n\t\t\t`could not fetch the LikeC4 grammar from ${url} — ${cause instanceof Error ? cause.message : String(cause)}. ` +\n\t\t\t\t'Builds are strict by default: pass `highlighting: { offline: true }` to use the bundled grammar instead.',\n\t\t\t{ cause },\n\t\t);\n\t}\n\n\tif (response.status === 304) return { notModified: true };\n\n\tif (response.status === 404) {\n\t\tthrow new GrammarRefError(\n\t\t\t`${repo} has no \"${ref}\", or it no longer has ${LANGIUM_PATH} (${url}). ` +\n\t\t\t\t'Use a tag such as \"v1.59.4\", a commit SHA, or \"main\".',\n\t\t);\n\t}\n\n\tif (!response.ok) {\n\t\tthrow new GrammarFetchError(\n\t\t\t`${url} responded ${response.status} ${response.statusText} — set ` +\n\t\t\t\t'`highlighting: { onError: \"warn\" }` to fall back to the bundled grammar.',\n\t\t);\n\t}\n\n\tconst text = await response.text();\n\n\tif (text.trim().length === 0) {\n\t\tthrow new GrammarFetchError(`${url} returned an empty file — the grammar is not usable`);\n\t}\n\n\treturn { text, etag: response.headers.get('etag') ?? undefined };\n}\n\n// endregion\n\n// region cache\n\n/**\n * Cache location: `node_modules/.cache/astroc4`, which every Astro project\n * already ignores. One file per repo@ref, so switching `ref` never thrashes.\n */\nfunction cachePath(options: GrammarSourceOptions, identity: GrammarIdentity): string {\n\tconst dir =\n\t\toptions.cacheDir ?? join(options.root ?? process.cwd(), 'node_modules', '.cache', 'astroc4');\n\tconst key = createHash('sha256').update(`${identity.repo}@${identity.ref}`).digest('hex').slice(0, 16);\n\n\treturn join(dir, `grammar-${key}.json`);\n}\n\ntype CacheWriteEntry = { langium: string; etag?: string | undefined };\ninterface CacheEntry extends CacheWriteEntry {\n\tfetchedAt: number;\n}\ninterface FreshCacheEntry extends CacheEntry {\n\tfresh: boolean;\n}\n\nasync function readCache(\n\toptions: GrammarSourceOptions,\n\tidentity: GrammarIdentity,\n): Promise<FreshCacheEntry | undefined> {\n\tlet raw;\n\n\ttry {\n\t\traw = await readFile(cachePath(options, identity), 'utf8');\n\t} catch {\n\t\treturn undefined;\n\t}\n\n\ttry {\n\t\tconst entry = JSON.parse(raw);\n\n\t\tif (\n\t\t\tentry?.version !== CACHE_VERSION ||\n\t\t\tentry.repo !== identity.repo ||\n\t\t\tentry.ref !== identity.ref ||\n\t\t\ttypeof entry.langium !== 'string' ||\n\t\t\ttypeof entry.fetchedAt !== 'number'\n\t\t) {\n\t\t\t// Another package version's cache, or a truncated file: refetch.\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst ttl = options.cacheTtl ?? 3600;\n\n\t\treturn { ...entry, fresh: Date.now() - entry.fetchedAt < ttl * 1000 };\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Best effort: a read-only `node_modules` must not fail a build, it only means\n * the next one has to fetch again.\n */\nasync function writeCache(\n\toptions: GrammarSourceOptions,\n\tidentity: GrammarIdentity,\n\tentry: CacheWriteEntry,\n): Promise<void> {\n\tconst path = cachePath(options, identity);\n\tconst temporary = `${path}.${process.pid}.tmp`;\n\n\ttry {\n\t\tawait mkdir(join(path, '..'), { recursive: true });\n\t\tawait writeFile(\n\t\t\ttemporary,\n\t\t\tJSON.stringify({\n\t\t\t\tversion: CACHE_VERSION,\n\t\t\t\trepo: identity.repo,\n\t\t\t\tref: identity.ref,\n\t\t\t\tetag: entry.etag,\n\t\t\t\tfetchedAt: Date.now(),\n\t\t\t\tlangium: entry.langium,\n\t\t\t}),\n\t\t\t'utf8',\n\t\t);\n\t\t// Rename rather than write in place: two Astro processes can resolve the\n\t\t// same cache entry at once during `astro check && astro build`.\n\t\tawait rename(temporary, path);\n\t} catch (error) {\n\t\toptions.logger?.warn?.(\n\t\t\t`[astroc4] could not cache the LikeC4 grammar in ${path} — ${error instanceof Error ? error.message : String(error)}`,\n\t\t);\n\t}\n}\n\n// endregion\n\nfunction isTruthy(value: string | undefined): boolean {\n\treturn typeof value === 'string' && /^(1|true|yes|on)$/i.test(value.trim());\n}\n\nexport default resolveLikeC4Grammar;\n\n",
6
+ "// Reduces the LikeC4 Langium grammar to the vocabulary a TextMate grammar needs.\n// Deliberately no Langium dependency: a tolerant scanner that has to survive\n// upstream reformatting, so anything it cannot classify is dropped, not guessed.\n\n/** `…Id returns string` rules are identifiers, not closed value domains. */\nconst NOT_VALUE_DOMAINS = /Id$/;\n\n/** Property names the grammar matches as `key='…'` assignments. */\nconst PROPERTY_SUPPLEMENTS = ['kind', 'tag'];\n\nexport type TokenType = 'literal' | 'regex' | 'ident' | 'punct';\nexport interface Token {\n\ttype: TokenType;\n\tvalue: string;\n}\n\nexport interface Terminal {\n\thidden: boolean;\n\tkind: 'regex' | 'literal';\n\t/** Raw regex source (without slashes) or the literal. */\n\tvalue: string;\n}\n\nexport interface Rule {\n\tname: string;\n\tkind: 'rule' | 'fragment' | 'terminal';\n\thidden: boolean;\n\treturns?: string | undefined;\n\ttokens: Token[];\n}\n\nexport interface Vocabulary {\n\t/** Keywords that open a `{ … }` block. */\n\tblocks: string[];\n\t/** Every remaining word-like literal. */\n\tkeywords: string[];\n\t/** Property names from `key='…'` assignments. */\n\tproperties: string[];\n\t/** Relationship connectors containing `->`. */\n\tarrows: string[];\n\t/** `returns string` value domains, by rule name. */\n\tenums: Record<string, string[]>;\n\t/** Icon packs from the `LIB_ICON` terminal. */\n\ticons: string[];\n\t/** Literals from the `BOOLEAN` terminal. */\n\tbooleans: string[];\n\t/** Parser rules seen — used for sanity checks. */\n\truleCount: number;\n}\n\nexport function parseLangium(source: string): Vocabulary {\n\t// `grammar LikeC4` is a header, not a rule, and it has no `;`: leaving it in\n\t// would glue it to the first real rule and hide that rule from the scanner.\n\tconst statements = splitStatements(\n\t\tstripComments(source).replace(/^[ \\t]*grammar[ \\t]+[A-Za-z_]\\w*[ \\t]*$/gm, ''),\n\t);\n\tconst rules = statements.map(readStatement).filter((rule) => rule !== undefined);\n\n\tconst parserRules = rules.filter((rule) => rule.kind === 'rule' || rule.kind === 'fragment');\n\n\tif (parserRules.length === 0) {\n\t\tthrow new Error(\n\t\t\t'the file contains no Langium parser rules — is this still `packages/language-server/src/like-c4.langium`?',\n\t\t);\n\t}\n\n\tconst enums = resolveEnums(parserRules);\n\tconst blocks = findBlocks(parserRules);\n\tconst properties = unique([...findProperties(parserRules), ...PROPERTY_SUPPLEMENTS]);\n\tconst arrows = findArrows(parserRules);\n\tconst literals = unique(\n\t\tparserRules.flatMap((rule) => rule.tokens.filter((t) => t.type === 'literal').map((t) => t.value)),\n\t);\n\n\tconst classified = new Set([...blocks, ...properties, ...Object.values(enums).flat()]);\n\tconst keywords = literals.filter(\n\t\t(value) => /^[A-Za-z_]\\w*$/.test(value) && !classified.has(value),\n\t);\n\n\tconst terminals = readTerminals(rules);\n\n\t// A small grammar can legitimately have no leftover keywords, so blocks and\n\t// value domains count too.\n\tif (keywords.length === 0 && blocks.length === 0 && Object.keys(enums).length === 0) {\n\t\tthrow new Error('the file contains no LikeC4 keywords — the Langium grammar could not be read');\n\t}\n\n\treturn {\n\t\tblocks,\n\t\tkeywords,\n\t\tproperties,\n\t\tarrows,\n\t\tenums,\n\t\ticons: terminalAlternatives(terminals.LIB_ICON),\n\t\tbooleans: terminalAlternatives(terminals.BOOLEAN),\n\t\truleCount: parserRules.length,\n\t};\n}\n\n// region scanning\n\n/**\n * Blank out `//` and block comments. String and regex literals are copied\n * verbatim, because a `//` inside `/https?:\\/\\//` is not a comment.\n */\nfunction stripComments(source: string): string {\n\tlet out = '';\n\tlet i = 0;\n\n\twhile (i < source.length) {\n\t\tconst char = source[i];\n\n\t\tif (char === '/' && source[i + 1] === '/') {\n\t\t\twhile (i < source.length && source[i] !== '\\n') i++;\n\t\t\tout += ' ';\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === '/' && source[i + 1] === '*') {\n\t\t\ti += 2;\n\t\t\twhile (i < source.length && !(source[i] === '*' && source[i + 1] === '/')) i++;\n\t\t\ti += 2;\n\t\t\tout += ' ';\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"'\" || char === '\"') {\n\t\t\tconst end = endOfString(source, i);\n\t\t\tout += source.slice(i, end);\n\t\t\ti = end;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === '/') {\n\t\t\tconst end = endOfRegex(source, i);\n\t\t\tout += source.slice(i, end);\n\t\t\ti = end;\n\t\t\tcontinue;\n\t\t}\n\n\t\tout += char;\n\t\ti++;\n\t}\n\n\treturn out;\n}\n\n/** Index just past the quoted literal that opens at `start`. */\nfunction endOfString(source: string, start: number): number {\n\tconst quote = source[start];\n\tlet i = start + 1;\n\n\twhile (i < source.length) {\n\t\tif (source[i] === '\\\\') {\n\t\t\ti += 2;\n\t\t\tcontinue;\n\t\t}\n\t\tif (source[i] === quote) return i + 1;\n\t\ti++;\n\t}\n\n\treturn source.length;\n}\n\n/** Index just past the regex literal that opens at `start`. */\nfunction endOfRegex(source: string, start: number): number {\n\tlet i = start + 1;\n\tlet inClass = false;\n\n\twhile (i < source.length) {\n\t\tconst char = source[i];\n\n\t\tif (char === '\\\\') {\n\t\t\ti += 2;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === '[') inClass = true;\n\t\telse if (char === ']') inClass = false;\n\t\telse if (char === '/' && !inClass) return i + 1;\n\n\t\ti++;\n\t}\n\n\treturn source.length;\n}\n\n/**\n * Split on the `;` that ends each rule, ignoring the ones inside strings,\n * regexes and `{ … }` — interfaces have fields, and rules have `{infer X}`\n * actions, both of which can contain semicolons.\n */\nfunction splitStatements(source: string): string[] {\n\tconst statements: string[] = [];\n\tlet depth = 0;\n\tlet start = 0;\n\tlet i = 0;\n\n\twhile (i < source.length) {\n\t\tconst char = source[i];\n\n\t\tif (char === \"'\" || char === '\"') {\n\t\t\ti = endOfString(source, i);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === '/') {\n\t\t\ti = endOfRegex(source, i);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === '{') depth++;\n\t\telse if (char === '}') depth = Math.max(0, depth - 1);\n\t\telse if (char === ';' && depth === 0) {\n\t\t\tstatements.push(source.slice(start, i));\n\t\t\tstart = i + 1;\n\t\t}\n\n\t\ti++;\n\t}\n\n\tconst tail = source.slice(start).trim();\n\tif (tail.length > 0) statements.push(tail);\n\n\treturn statements.filter((statement) => statement.trim().length > 0);\n}\n\nconst HEADERS: { kind: 'rule' | 'fragment' | 'terminal'; hidden: boolean; pattern: RegExp }[] = [\n\t// `hidden terminal WS: /[ \\t]+/`\n\t{ kind: 'terminal', hidden: true, pattern: /^\\s*hidden\\s+terminal\\s+([A-Za-z_]\\w*)\\s*(?:<[^>]*>)?\\s*:/ },\n\t// `terminal LIB_ICON: /…/`, `terminal fragment HASH: '#'`\n\t{\n\t\tkind: 'terminal',\n\t\thidden: false,\n\t\tpattern:\n\t\t\t/^\\s*terminal\\s+(?:fragment\\s+)?([A-Za-z_]\\w*)\\s*(?:<[^>]*>)?\\s*(?:returns\\s+[A-Za-z_]\\w*\\s*)?:/,\n\t},\n\t// `fragment RelationConnector:`\n\t{ kind: 'fragment', hidden: false, pattern: /^\\s*fragment\\s+([A-Za-z_]\\w*)\\s*:/ },\n\t// `Model:`, `ModelViews:`, `entry LikeC4Grammar:`, `Relation<isExplicit>:`\n\t{\n\t\tkind: 'rule',\n\t\thidden: false,\n\t\tpattern: /^\\s*(?:entry\\s+)?([A-Za-z_]\\w*)\\s*(?:<[^>]*>)?\\s*(?:returns\\s+([A-Za-z_]\\w*)\\s*)?:/,\n\t},\n];\n\nfunction readStatement(statement: string): Rule | undefined {\n\tfor (const header of HEADERS) {\n\t\tconst match = header.pattern.exec(statement);\n\t\tconst name = match?.[1];\n\t\tif (!match || !name) continue;\n\n\t\treturn {\n\t\t\tname,\n\t\t\tkind: header.kind,\n\t\t\thidden: header.hidden,\n\t\t\treturns: header.kind === 'rule' ? match[2] : undefined,\n\t\t\ttokens: tokenize(statement.slice(match[0].length)),\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\nfunction tokenize(body: string): Token[] {\n\tconst tokens: Token[] = [];\n\tlet i = 0;\n\n\twhile (i < body.length) {\n\t\tconst char = body.charAt(i);\n\n\t\tif (/\\s/.test(char)) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"'\" || char === '\"') {\n\t\t\tconst end = endOfString(body, i);\n\t\t\ttokens.push({ type: 'literal', value: unquote(body.slice(i, end)) });\n\t\t\ti = end;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === '/') {\n\t\t\tconst end = endOfRegex(body, i);\n\t\t\ttokens.push({ type: 'regex', value: body.slice(i + 1, end - 1) });\n\t\t\ti = end;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst identifier = /^[A-Za-z_]\\w*/.exec(body.slice(i));\n\t\tif (identifier) {\n\t\t\ttokens.push({ type: 'ident', value: identifier[0] });\n\t\t\ti += identifier[0].length;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Multi-character punctuation (`+=`, `?=`) is irrelevant: only `=`, `|`,\n\t\t// `(` and `)` are inspected, and per-character tokens give all four.\n\t\ttokens.push({ type: 'punct', value: char });\n\t\ti++;\n\t}\n\n\treturn tokens;\n}\n\n/** Strip the quotes and resolve the escapes Langium allows in literals. */\nfunction unquote(quoted: string): string {\n\tconst inner = quoted.slice(1, -1);\n\tlet out = '';\n\n\tfor (let i = 0; i < inner.length; i++) {\n\t\tif (inner[i] !== '\\\\') {\n\t\t\tout += inner[i];\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst escaped = inner[++i];\n\t\tif (escaped === 'n') out += '\\n';\n\t\telse if (escaped === 't') out += '\\t';\n\t\telse if (escaped === 'r') out += '\\r';\n\t\telse out += escaped ?? '';\n\t}\n\n\treturn out;\n}\n\n// endregion\n\n// region vocabulary\n\n/**\n * Rules of the shape `'specification' '{' …` or `name='model' '{' …` open a\n * block. The first literal of the rule is the keyword, and it only counts when\n * the rule reaches a `{` without branching first: `'element' kind=ElementKind\n * ('{' …)` has an optional body, so `element` stays a keyword.\n */\nfunction findBlocks(rules: Rule[]): string[] {\n\treturn unique(\n\t\trules.flatMap((rule) => {\n\t\t\tconst tokens = rule.tokens;\n\t\t\tconst first = tokens.findIndex((token) => token.type === 'literal');\n\t\t\tconst keyword = first === -1 ? undefined : tokens[first]?.value;\n\n\t\t\tif (!keyword || keyword === '{' || !/^[A-Za-z_]\\w*$/.test(keyword)) return [];\n\n\t\t\tfor (let i = first + 1; i < tokens.length; i++) {\n\t\t\t\tconst token = tokens[i];\n\t\t\t\tif (!token) break;\n\t\t\t\tif (token.value === '(' || token.value === '|') return [];\n\t\t\t\tif (token.type === 'literal' && token.value === '{') return [keyword];\n\t\t\t}\n\n\t\t\treturn [];\n\t\t}),\n\t);\n}\n\n/**\n * `key='title'` and `key=('head' | 'tail')` name a property. Positional\n * arguments (`props+=String`) and `name=` (block headers) are ignored.\n */\nfunction findProperties(rules: Rule[]): string[] {\n\tconst properties: string[] = [];\n\n\tfor (const rule of rules) {\n\t\tconst tokens = rule.tokens;\n\n\t\tfor (let i = 0; i < tokens.length; i++) {\n\t\t\tconst token = tokens[i];\n\t\t\tif (!token || token.type !== 'ident' || token.value !== 'key') continue;\n\n\t\t\tconst equals = equalsIndex(tokens, i);\n\t\t\tif (equals === -1) continue;\n\n\t\t\tlet j = equals + 1;\n\n\t\t\tif (tokens[j]?.value === '(') {\n\t\t\t\tfor (j++; j < tokens.length && tokens[j]?.value !== ')'; j++) {\n\t\t\t\t\tconst inner = tokens[j];\n\t\t\t\t\tif (inner?.type === 'literal') properties.push(inner.value);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst value = tokens[j];\n\t\t\tif (value?.type === 'literal') properties.push(value.value);\n\t\t}\n\t}\n\n\treturn properties.filter((value) => /^[A-Za-z_]\\w*$/.test(value));\n}\n\n/**\n * Index of the `=` that assigns `tokens[i]` (`key=`, `key?=`, `key+=`), or `-1`\n * when the identifier is not being assigned.\n */\nfunction equalsIndex(tokens: Token[], i: number): number {\n\tif (tokens[i]?.type !== 'ident') return -1;\n\n\tconst next = tokens[i + 1]?.value;\n\tif (next === '=') return i + 1;\n\tif ((next === '?' || next === '+') && tokens[i + 2]?.value === '=') return i + 2;\n\n\treturn -1;\n}\n\n/**\n * The connectors live in one fragment:\n * dotKind=RelationKindDotRef | '-[' kind=[RelationshipKind] (… '->') | … | '->'\n */\nfunction findArrows(rules: Rule[]): string[] {\n\tconst connector = rules.find((rule) => rule.name === 'RelationConnector');\n\tconst fromConnector = (connector?.tokens ?? [])\n\t\t.filter((token) => token.type === 'literal' && token.value.includes('->'))\n\t\t.map((token) => token.value);\n\n\t// Longest first: TextMate alternation is first-match, so `]->` has to be\n\t// tried before `->` at the same position.\n\treturn unique([...fromConnector, '->', '<->']).sort((a, b) => b.length - a.length || a.localeCompare(b));\n}\n\n/**\n * A `returns string` rule whose body is only literals, `|` and references to\n * other such rules is a closed value domain — `BorderStyleValue: LineOptions |\n * 'none'` inherits from `LineOptions` that way. Anything referencing a rule\n * that is not itself a value domain (e.g. `Id returns string`) resolves to\n * nothing and is dropped.\n */\nfunction resolveEnums(rules: Rule[]): Record<string, string[]> {\n\tconst candidates = new Map<string, string[]>();\n\n\tfor (const rule of rules) {\n\t\tif (rule.returns !== 'string' || NOT_VALUE_DOMAINS.test(rule.name)) continue;\n\n\t\tconst onlyValuesAndChoices = rule.tokens.every(\n\t\t\t(token) =>\n\t\t\t\ttoken.type === 'literal' ||\n\t\t\t\ttoken.type === 'ident' ||\n\t\t\t\t(token.type === 'punct' && (token.value === '|' || token.value === ';')),\n\t\t);\n\n\t\tif (onlyValuesAndChoices) candidates.set(rule.name, []);\n\t}\n\n\t// Fixpoint, because `BorderStyleValue` can only resolve once `LineOptions`\n\t// has. One pass per rule is enough for any acyclic grammar.\n\tfor (let pass = 0; pass < rules.length; pass++) {\n\t\tlet changed = false;\n\n\t\tfor (const rule of rules) {\n\t\t\tif (!candidates.has(rule.name)) continue;\n\n\t\t\tconst resolved: string[] = [];\n\t\t\tlet complete = true;\n\n\t\t\tfor (const token of rule.tokens) {\n\t\t\t\tif (token.type === 'literal') {\n\t\t\t\t\tresolved.push(token.value);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (token.type !== 'ident') continue;\n\n\t\t\t\tconst inherited = candidates.get(token.value);\n\t\t\t\tif (inherited === undefined) {\n\t\t\t\t\tcomplete = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tresolved.push(...inherited);\n\t\t\t}\n\n\t\t\tconst next = unique(resolved);\n\t\t\tif (!complete || next.length === 0) continue;\n\n\t\t\tif ((candidates.get(rule.name) ?? []).length !== next.length) {\n\t\t\t\tcandidates.set(rule.name, next);\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\n\t\tif (!changed) break;\n\t}\n\n\tconst enums: Record<string, string[]> = {};\n\tfor (const [name, values] of [...candidates].sort(([a], [b]) => a.localeCompare(b))) {\n\t\tif (values.length > 0) enums[name] = values;\n\t}\n\n\treturn enums;\n}\n\nfunction readTerminals(rules: Rule[]): Record<string, Terminal> {\n\tconst terminals: Record<string, Terminal> = {};\n\n\tfor (const rule of rules) {\n\t\tif (rule.kind !== 'terminal') continue;\n\n\t\tconst token = rule.tokens.find((candidate) => candidate.type === 'regex' || candidate.type === 'literal');\n\t\tif (!token) continue;\n\n\t\tterminals[rule.name] = {\n\t\t\thidden: rule.hidden,\n\t\t\tkind: token.type === 'regex' ? 'regex' : 'literal',\n\t\t\tvalue: token.value,\n\t\t};\n\t}\n\n\treturn terminals;\n}\n\n/**\n * The alternatives of the first group in a terminal's regex:\n * `(aws|azure|bootstrap|gcp|md|tech):[-\\w]+` -> the icon packs.\n */\nfunction terminalAlternatives(terminal: Terminal | undefined): string[] {\n\tif (!terminal || terminal.kind !== 'regex') return [];\n\n\tconst group = /\\(([^()]*)\\)/.exec(terminal.value);\n\tif (!group) return [];\n\n\treturn unique((group[1] ?? '').split('|').map((value) => value.trim())).filter((value) =>\n\t\t/^[A-Za-z][\\w-]*$/.test(value),\n\t);\n}\n\nfunction unique(values: string[]): string[] {\n\treturn [...new Set(values)].sort((a, b) => a.localeCompare(b));\n}\n\n// endregion\n\nexport default parseLangium;\n\n",
7
+ "// Word lists are generated from the Langium vocabulary; the structural patterns\n// (strings, tags vs hex colours, icons, arrows, declarations) are curated,\n// because a Langium rule says a token exists, not how it looks.\n//\n// The result must stay plain JSON: Expressive Code JSON-round-trips integration\n// options and throws on functions or RegExp instances.\n\nimport type { Vocabulary } from './langium.ts';\n\n/** Scope name of the grammar, as upstream's VS Code extension uses it. */\nexport const SCOPE_NAME = 'source.likec4';\n\n/** Shiki language id, plus the short alias used by ` ```c4 ` fences. */\nexport const LANGUAGE_NAME = 'likec4';\nexport const LANGUAGE_ALIASES = ['c4'];\n\nconst TMLANGUAGE_SCHEMA =\n\t'https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json';\n\n/**\n * Closed value domains: they colour as values, not as keywords.\n * Anything the grammar adds under these names is picked up automatically.\n */\nconst VALUE_DOMAINS = [\n\t'BorderStyleValue',\n\t'DynamicViewDisplayVariantValue',\n\t'EdgeRoutingValue',\n\t'ElementShape',\n\t'IconPositionValue',\n\t'LineOptions',\n\t'ArrowType',\n\t'RankValue',\n\t'SizeValue',\n\t'SizingValue',\n\t'ThemeColor',\n\t'ViewLayoutDirection',\n];\n\n/** Control-flow keywords read as keywords, not as a value domain. */\nconst KEYWORD_DOMAINS = ['DynamicViewFlowKeyword'];\n\n/** `source` / `target` are the only value-like variables. */\nconst VARIABLE_DOMAINS = ['Participant'];\n\n/** Operators whose scope is a word, kept curated: they are not all literals. */\nconst OPERATOR_WORDS = ['and', 'or', 'not', 'is'];\n\n/** Used when the grammar has no `LIB_ICON` terminal. */\nconst FALLBACK_ICON_PACKS = ['aws', 'azure', 'bootstrap', 'gcp', 'tech'];\n\n/** One TextMate pattern. `match`/`begin`/`end` are regex *source*, not `RegExp`. */\nexport interface TmPattern {\n\tname?: string;\n\tcomment?: string;\n\tinclude?: string;\n\tmatch?: string;\n\tbegin?: string;\n\tend?: string;\n\tcontentName?: string;\n\tcaptures?: Record<string, { name: string }>;\n\tbeginCaptures?: Record<string, { name: string }>;\n\tendCaptures?: Record<string, { name: string }>;\n\tpatterns?: TmPattern[];\n}\n\nexport interface TmGrammar {\n\t$schema: string;\n\tname: string;\n\tdisplayName: string;\n\tscopeName: string;\n\tfileTypes: string[];\n\tpatterns: TmPattern[];\n\t// Each repository entry is a pattern group; the tests index into them.\n\trepository: Record<string, any>;\n\t$generated?: { repo: string; ref: string; sha?: string; by: string };\n}\n\n/** Where the grammar came from, written into the snapshot's `$generated`. */\nexport interface TmProvenance {\n\trepo?: string;\n\tref?: string;\n\tsha?: string;\n}\n\nexport function buildTmLanguage(vocabulary: Vocabulary, meta: TmProvenance = {}): TmGrammar {\n\tconst control = uniqueDomain(vocabulary, KEYWORD_DOMAINS);\n\tconst variables = uniqueDomain(vocabulary, VARIABLE_DOMAINS);\n\tconst icons = vocabulary.icons.length > 0 ? vocabulary.icons : FALLBACK_ICON_PACKS;\n\n\t// Words that are always syntax, never the name of a kind: `deployed =\n\t// instanceOf a` must not paint `instanceOf` as a type.\n\tconst reserved = alternationOf([...vocabulary.keywords, ...vocabulary.blocks, ...control]);\n\n\tconst grammar: TmGrammar = {\n\t\t$schema: TMLANGUAGE_SCHEMA,\n\t\t...(meta.repo && meta.ref\n\t\t\t? {\n\t\t\t\t\t$generated: {\n\t\t\t\t\t\trepo: meta.repo,\n\t\t\t\t\t\tref: meta.ref,\n\t\t\t\t\t\t...(meta.sha ? { sha: meta.sha } : {}),\n\t\t\t\t\t\tby: 'astroc4/scripts/sync-grammar.ts',\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t\tname: LANGUAGE_NAME,\n\t\tdisplayName: 'LikeC4',\n\t\tscopeName: SCOPE_NAME,\n\t\tfileTypes: ['c4', 'likec4'],\n\t\tpatterns: [{ include: '#everything' }],\n\t\trepository: {\n\t\t\teverything: {\n\t\t\t\tpatterns: [\n\t\t\t\t\t'comments',\n\t\t\t\t\t'strings',\n\t\t\t\t\t'urls',\n\t\t\t\t\t'icons',\n\t\t\t\t\t'hex-colors',\n\t\t\t\t\t'tags',\n\t\t\t\t\t'typed-arrow',\n\t\t\t\t\t'declarations',\n\t\t\t\t\t'keywords',\n\t\t\t\t\t'numbers',\n\t\t\t\t\t'operators',\n\t\t\t\t\t'punctuation',\n\t\t\t\t].map((name) => ({ include: `#${name}` })),\n\t\t\t},\n\t\t\tcomments: comments(),\n\t\t\tstrings: strings(),\n\t\t\turls: urls(),\n\t\t\ticons: iconIds(icons),\n\t\t\t'hex-colors': hexColours(),\n\t\t\ttags: tags(),\n\t\t\t'typed-arrow': typedArrow(),\n\t\t\tdeclarations: declarations(reserved),\n\t\t\tkeywords: keywords({ ...vocabulary, control, variables }),\n\t\t\tnumbers: numbers(),\n\t\t\toperators: operators(vocabulary.arrows),\n\t\t\tpunctuation: punctuation(),\n\t\t},\n\t};\n\n\tif (meta.repo && meta.ref) {\n\t\tgrammar.$generated = {\n\t\t\trepo: meta.repo,\n\t\t\tref: meta.ref,\n\t\t\t...(meta.sha ? { sha: meta.sha } : {}),\n\t\t\tby: 'astroc4/scripts/sync-grammar.ts',\n\t\t};\n\t}\n\n\treturn grammar;\n}\n// region structural patterns\n\nfunction comments() {\n\treturn {\n\t\tpatterns: [\n\t\t\t{\n\t\t\t\tname: 'comment.block.likec4',\n\t\t\t\tbegin: '/\\\\*',\n\t\t\t\tend: '\\\\*/',\n\t\t\t\tcaptures: { 0: { name: 'punctuation.definition.comment.likec4' } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'comment.line.double-slash.likec4',\n\t\t\t\tmatch: '//.*$',\n\t\t\t\tcaptures: { 0: { name: 'punctuation.definition.comment.likec4' } },\n\t\t\t},\n\t\t],\n\t};\n}\n\n/** Includes the triple-quoted markdown strings LikeC4 uses for descriptions. */\nfunction strings() {\n\tconst triple = (quote: string): TmPattern => ({\n\t\tname: 'string.quoted.triple.likec4',\n\t\tbegin: quote.repeat(3),\n\t\tend: quote.repeat(3),\n\t\tbeginCaptures: { 0: { name: 'punctuation.definition.string.begin.likec4' } },\n\t\tendCaptures: { 0: { name: 'punctuation.definition.string.end.likec4' } },\n\t});\n\n\tconst single = (quote: string, name: string): TmPattern => ({\n\t\tname,\n\t\tbegin: quote,\n\t\tend: `${quote}|$`,\n\t\tbeginCaptures: { 0: { name: 'punctuation.definition.string.begin.likec4' } },\n\t\tendCaptures: { 0: { name: 'punctuation.definition.string.end.likec4' } },\n\t\tpatterns: [{ name: 'constant.character.escape.likec4', match: '\\\\\\\\.' }],\n\t});\n\n\treturn {\n\t\tpatterns: [\n\t\t\ttriple(\"'\"),\n\t\t\ttriple('\"'),\n\t\t\tsingle(\"'\", 'string.quoted.single.likec4'),\n\t\t\tsingle('\"', 'string.quoted.double.likec4'),\n\t\t],\n\t};\n}\n\nfunction urls() {\n\treturn { name: 'markup.underline.link.likec4', match: \"\\\\bhttps?://[^\\\\s'\\\"]+\" };\n}\n\n/**\n * Icon ids (`tech:astro`, `aws:lambda`). The packs come from the `LIB_ICON`\n * terminal, so a pack added upstream highlights without touching this package.\n */\nfunction iconIds(packs: string[]): TmPattern {\n\treturn {\n\t\tcomment: 'Bundled icon ids: `tech:nginx`, `aws:…`, `gcp:…`, …',\n\t\tmatch: `\\\\b(${alternationOf(packs)})(:)([\\\\w-]+)`,\n\t\tcaptures: {\n\t\t\t1: { name: 'support.constant.icon-pack.likec4' },\n\t\t\t2: { name: 'punctuation.separator.likec4' },\n\t\t\t3: { name: 'support.constant.icon.likec4' },\n\t\t},\n\t};\n}\n\n/** `#0046BE` is a colour, `#compute` is a tag: hex is included first, so it wins. */\nfunction hexColours() {\n\treturn {\n\t\tname: 'constant.other.color.rgb-value.hex.likec4',\n\t\tmatch: '#(?:[0-9A-Fa-f]{8}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})(?![\\\\w-])',\n\t};\n}\n\nfunction tags() {\n\treturn { name: 'entity.name.tag.likec4', match: '#[A-Za-z_][\\\\w-]*' };\n}\n\nfunction typedArrow() {\n\treturn {\n\t\tcomment: '`a -[https]-> b`',\n\t\tmatch: '(-\\\\[)\\\\s*([A-Za-z_][\\\\w-]*)\\\\s*(\\\\]->)',\n\t\tcaptures: {\n\t\t\t1: { name: 'keyword.operator.arrow.likec4' },\n\t\t\t2: { name: 'entity.name.type.relationship.likec4' },\n\t\t\t3: { name: 'keyword.operator.arrow.likec4' },\n\t\t},\n\t};\n}\n\n/**\n * The name being introduced is scoped, a name only referred to is not. Runs\n * before the keyword patterns so `element system` reads as a declaration.\n */\nfunction declarations(reserved: string): TmPattern {\n\tconst notReserved = reserved ? `(?!(?:${reserved})\\\\b)` : '';\n\n\treturn {\n\t\tpatterns: [\n\t\t\t{\n\t\t\t\tcomment:\n\t\t\t\t\t'`element system`, `deploymentNode region`, `tag tls`, `relationship https`. Not `where tag is #x`.',\n\t\t\t\tmatch: '\\\\b(element|deploymentNode|tag|relationship)\\\\s+(?!is\\\\b)([A-Za-z_][\\\\w-]*)(?=\\\\s*(?:\\\\{|$|//))',\n\t\t\t\tcaptures: {\n\t\t\t\t\t1: { name: 'storage.type.likec4' },\n\t\t\t\t\t2: { name: 'entity.name.type.likec4' },\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tcomment:\n\t\t\t\t\t'`color testingBlue #0046BE` declares; `color testingBlue` inside a style block only refers.',\n\t\t\t\tmatch: '\\\\b(color)\\\\s+([A-Za-z_][\\\\w-]*)(?=\\\\s+#)',\n\t\t\t\tcaptures: {\n\t\t\t\t\t1: { name: 'storage.type.likec4' },\n\t\t\t\t\t2: { name: 'entity.name.type.likec4' },\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tcomment: '`view index`, `dynamic view firstRequest`, `deployment view prod`, `view internals of site`',\n\t\t\t\tmatch: '\\\\b(?:(dynamic|deployment)\\\\s+)?(view)\\\\s+([A-Za-z_]\\\\w*)',\n\t\t\t\tcaptures: {\n\t\t\t\t\t1: { name: 'storage.modifier.likec4' },\n\t\t\t\t\t2: { name: 'storage.type.view.likec4' },\n\t\t\t\t\t3: { name: 'entity.name.function.view.likec4' },\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tcomment: \"`reader = actor 'Engineer'`\",\n\t\t\t\tmatch: `\\\\b([A-Za-z_]\\\\w*)\\\\s*(=)(?!=)\\\\s*${notReserved}([A-Za-z_]\\\\w*)?`,\n\t\t\t\tcaptures: {\n\t\t\t\t\t1: { name: 'variable.other.definition.likec4' },\n\t\t\t\t\t2: { name: 'keyword.operator.assignment.likec4' },\n\t\t\t\t\t3: { name: 'entity.name.type.likec4' },\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t};\n}\n\n// endregion\n\n// region generated keyword patterns\n\n/**\n * Order matters here: blocks before plain keywords (so `model {` is a block),\n * operator words before keywords (`is`, `not`), variables before value domains\n * (so `source`/`target` stay variables even though `RankValue` reuses `source`).\n */\nfunction keywords(vocabulary: Vocabulary & { control: string[]; variables: string[] }): TmPattern {\n\tconst patterns: TmPattern[] = [];\n\n\tconst blocks = alternationOf(vocabulary.blocks);\n\tif (blocks) {\n\t\tpatterns.push({\n\t\t\tcomment: 'Keywords that open a block: `model { … }`.',\n\t\t\tname: 'keyword.control.block.likec4',\n\t\t\tmatch: `\\\\b(?:${blocks})\\\\b(?=\\\\s*\\\\{)`,\n\t\t});\n\t}\n\n\t// Blocks repeat in the keyword list on purpose: `predicateGroup mine { ... }`\n\t// is not followed by `{`, and still has to colour as a keyword. The block\n\t// pattern above wins wherever the brace is there.\n\tconst control = alternationOf([...vocabulary.keywords, ...vocabulary.control, ...vocabulary.blocks]);\n\n\t// Word operators (`is`, `not`) come before the keyword list, which also\n\t// contains them: `where tag is #x` reads as an operator, not a keyword.\n\tpatterns.push({\n\t\tname: 'keyword.operator.word.likec4',\n\t\tmatch: `\\\\b(?:${alternationOf(OPERATOR_WORDS)})\\\\b`,\n\t});\n\n\tif (control) {\n\t\tpatterns.push({ name: 'keyword.control.likec4', match: `\\\\b(?:${control})\\\\b` });\n\t}\n\n\tconst variables = alternationOf(vocabulary.variables);\n\tif (variables) {\n\t\tpatterns.push({ name: 'variable.language.likec4', match: `\\\\b(?:${variables})\\\\b` });\n\t}\n\n\tconst properties = alternationOf(vocabulary.properties);\n\tif (properties) {\n\t\tpatterns.push({ name: 'support.type.property-name.likec4', match: `\\\\b(?:${properties})\\\\b` });\n\t}\n\n\tconst values = alternationOf(uniqueDomain(vocabulary, VALUE_DOMAINS));\n\tif (values) {\n\t\tpatterns.push({ name: 'constant.language.likec4', match: `\\\\b(?:${values})\\\\b` });\n\t}\n\n\treturn { patterns };\n}\n\nfunction numbers() {\n\treturn { name: 'constant.numeric.likec4', match: '\\\\b\\\\d+(?:\\\\.\\\\d+)?%?' };\n}\n\n/** `arrows` must be longest first so `]->` wins over `->`. */\nfunction operators(arrows: string[]): TmPattern {\n\tconst patterns: TmPattern[] = [];\n\n\tconst connectors = alternationOf(arrows);\n\tif (connectors) {\n\t\tpatterns.push({ name: 'keyword.operator.arrow.likec4', match: connectors });\n\t}\n\n\tpatterns.push({ name: 'keyword.operator.wildcard.likec4', match: '\\\\.\\\\*\\\\*|\\\\.\\\\*|\\\\*\\\\*|\\\\*' });\n\n\treturn { patterns };\n}\n\nfunction punctuation() {\n\treturn {\n\t\tpatterns: [\n\t\t\t{ name: 'punctuation.section.block.begin.likec4', match: '\\\\{' },\n\t\t\t{ name: 'punctuation.section.block.end.likec4', match: '\\\\}' },\n\t\t\t{ name: 'punctuation.separator.comma.likec4', match: ',' },\n\t\t\t{ name: 'punctuation.accessor.likec4', match: '\\\\.' },\n\t\t],\n\t};\n}\n\n// endregion\n\n// region helpers\n\n/**\n * Every value of the named domains, deduplicated and sorted. Missing domains\n * are skipped rather than failing: upstream is free to rename a rule, and a\n * renamed domain still reaches the grammar through `keywords`.\n */\nfunction uniqueDomain(vocabulary: Vocabulary, names: string[]): string[] {\n\tconst values = names.flatMap((name) => vocabulary.enums[name] ?? []);\n\n\treturn [...new Set(values)].sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * `['a', 'b']` -> `a|b`, escaped for a TextMate regex. Returns '' for an empty\n * list so callers can skip the pattern instead of emitting `\\b(?:)\\b`.\n */\nfunction alternationOf(values: string[]): string {\n\treturn values.map(escapeRegExp).join('|');\n}\n\nfunction escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n// endregion\n\nexport default buildTmLanguage;\n\n",
8
+ "// For sites the plugin cannot inject into (an existing `ec.config.mjs`, a\n// Markdown pipeline of their own). `likec4Language` is the bundled snapshot and\n// needs no network; `loadLikeC4Language` fetches the ref asked for.\n\nimport type { LanguageRegistration } from 'shiki';\n\nimport grammar from './grammar/likec4.tmLanguage.json' with { type: 'json' };\nimport { resolveLikeC4Grammar, type GrammarSourceOptions } from './grammar/source.ts';\nimport { LANGUAGE_ALIASES, LANGUAGE_NAME, type TmGrammar } from './grammar/textmate.ts';\n\n/**\n * Shiki wants `IRawRepository`, which the JSON `repository` cannot satisfy\n * structurally, so the cast lives here rather than at every call site.\n */\nfunction registration(grammar: TmGrammar): LanguageRegistration & { aliases: string[] } {\n\treturn {\n\t\t...grammar,\n\t\tname: LANGUAGE_NAME,\n\t\taliases: [...LANGUAGE_ALIASES],\n\t} as LanguageRegistration & { aliases: string[] };\n}\n\n/** Shiki registration for LikeC4, under `likec4` with a `c4` alias. */\nexport const likec4Language: LanguageRegistration & { aliases: string[] } = registration(\n\tgrammar as TmGrammar,\n);\n\nexport async function loadLikeC4Language(\n\toptions?: GrammarSourceOptions,\n): Promise<LanguageRegistration & { aliases: string[] }> {\n\tconst { grammar: resolved } = await resolveLikeC4Grammar(options);\n\n\treturn registration(resolved);\n}\n\nexport default likec4Language;\n"
9
9
  ],
10
- "mappings": "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",
10
+ "mappings": "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",
11
11
  "debugId": "AA3350C3BE6D0C0664756E2164756E21",
12
12
  "names": []
13
13
  }
package/dist/fences.d.ts CHANGED
@@ -1,22 +1,14 @@
1
1
  import type { MdastPluginEntry } from 'satteri';
2
- /** The one thing this module needs from `likec4`'s Node API. */
3
2
  type LikeC4Api = typeof import('likec4').LikeC4;
4
3
  /**
5
- * Kick off (and await) the same lazy load `loadLikeC4()` uses, so a later
6
- * call inside Satteri's processing reuses the already-resolved promise
7
- * instead of issuing a fresh `import('likec4')`.
8
- *
9
- * `astro build` on Windows crashes mid-build ("Vite module runner has been
10
- * closed", followed by a native libuv assertion that kills the process) if
11
- * that first `import('likec4')` happens while Vite is tearing down the SSR
12
- * module runner used for the content layer — which is exactly when the first
13
- * page containing a ```likec4 fence is rendered. Finishing the import before
14
- * that point removes the race. src/index.mjs calls this from
15
- * `astro:config:setup` for builds only — the module-scope comment above
16
- * `loadLikeC4` explains why eager-loading it in dev is unsafe.
4
+ * Finishes loading LikeC4 before the first page renders, so the load cannot race
5
+ * the module runner's teardown. Called for builds only.
17
6
  */
18
7
  export declare function preloadLikeC4(): Promise<LikeC4Api>;
19
- /** The `key="value"` pairs a fence's meta string can carry. */
8
+ interface Layout {
9
+ dump: any;
10
+ viewIds: string[];
11
+ }
20
12
  export interface FenceMeta {
21
13
  title?: string;
22
14
  description?: string;
@@ -24,9 +16,46 @@ export interface FenceMeta {
24
16
  collapsible?: string;
25
17
  defaultOpen?: string;
26
18
  view?: string;
19
+ project?: string;
20
+ file?: string;
27
21
  [key: string]: string | undefined;
28
22
  }
29
- /** Parse `key="value"` / `key=value` pairs from the fence's meta string. */
23
+ /** Parse `key="value"` / `key='value'` / `key=value` pairs from the fence's meta string. */
30
24
  export declare function parseFenceMeta(meta: string | null | undefined): FenceMeta;
31
- export declare function likec4Fences(): MdastPluginEntry;
25
+ /** Compile and lay out LikeC4 source; shared by fences and `<LikeC4View file>`. */
26
+ export declare function layoutSource(source: string): Promise<Layout>;
27
+ export interface FenceReporter {
28
+ warn: (message: string) => void;
29
+ }
30
+ export interface FenceOptions {
31
+ /** @deprecated Unused since 1.0.0-prerelease.6. */
32
+ reporter?: FenceReporter;
33
+ /** @deprecated Unused since 1.0.0-prerelease.6. */
34
+ mdx?: boolean;
35
+ /** The site root. A fence's `file="…"` must stay inside it; without one, `file=` is refused. */
36
+ root?: string;
37
+ /**
38
+ * The project names a page may pass as `project`. When given, an empty fence's
39
+ * `project` is checked at build time; without it, only the browser can.
40
+ */
41
+ projects?: string[];
42
+ }
43
+ export declare function likec4Fences({ root, projects }?: FenceOptions): MdastPluginEntry;
44
+ export interface FencePlaceholder {
45
+ viewId: string;
46
+ /** The laid-out model of an inline or `file=` fence; absent for a project view. */
47
+ model?: unknown;
48
+ project?: string;
49
+ title?: string;
50
+ description?: string;
51
+ height?: number;
52
+ collapsible?: boolean;
53
+ defaultOpen?: boolean;
54
+ }
55
+ /**
56
+ * The HTML a .md fence becomes: the shell, and a sized frame carrying the view
57
+ * and model for `md-fences.tsx`. Everything is escaped — titles and model labels
58
+ * are author text.
59
+ */
60
+ export declare function fencePlaceholder({ viewId, model, project, title, description, height, collapsible, defaultOpen, }: FencePlaceholder): string;
32
61
  export default likec4Fences;
@@ -0,0 +1,4 @@
1
+ import type { Plugin as VitePlugin } from 'vite';
2
+ /** The import query `LikeC4View.astro` adds to a `.c4` file it renders. */
3
+ export declare const FILE_LAYOUT_QUERY = "?astroc4-layout";
4
+ export declare function fileLayoutPlugin(): VitePlugin;
@@ -1,17 +1,14 @@
1
- /** A token produced by the scanner. */
2
1
  export type TokenType = 'literal' | 'regex' | 'ident' | 'punct';
3
2
  export interface Token {
4
3
  type: TokenType;
5
4
  value: string;
6
5
  }
7
- /** A `terminal` rule, with its value as written. */
8
6
  export interface Terminal {
9
7
  hidden: boolean;
10
8
  kind: 'regex' | 'literal';
11
9
  /** Raw regex source (without slashes) or the literal. */
12
10
  value: string;
13
11
  }
14
- /** A parser rule, fragment or terminal, as the scanner reads it. */
15
12
  export interface Rule {
16
13
  name: string;
17
14
  kind: 'rule' | 'fragment' | 'terminal';
@@ -19,7 +16,6 @@ export interface Rule {
19
16
  returns?: string | undefined;
20
17
  tokens: Token[];
21
18
  }
22
- /** Everything the TextMate generator needs to know about the language. */
23
19
  export interface Vocabulary {
24
20
  /** Keywords that open a `{ … }` block. */
25
21
  blocks: string[];
@@ -1,11 +1,9 @@
1
1
  import { type TmGrammar } from './textmate.js';
2
- /** Upstream repository and the paths the grammar is read from. */
3
2
  export declare const DEFAULT_REPO = "likec4/likec4";
4
3
  export declare const DEFAULT_REF = "main";
5
4
  export declare const LANGIUM_PATH = "packages/language-server/src/like-c4.langium";
6
5
  export declare const DEFAULT_BASE_URL = "https://raw.githubusercontent.com";
7
6
  export type OnError = 'fail' | 'warn' | 'silent';
8
- /** Everything the resolver accepts. The site only ever sets a few of these. */
9
7
  export interface GrammarSourceOptions {
10
8
  /** Repository to read from. Defaults to likec4/likec4. */
11
9
  repo?: string;
@@ -25,11 +23,9 @@ export interface GrammarSourceOptions {
25
23
  timeout?: number;
26
24
  /** Site root, for the default cache directory. */
27
25
  root?: string;
28
- /** Where to cache, overriding the default. */
29
26
  cacheDir?: string;
30
27
  /** Environment, for `ASTROC4_*` overrides. */
31
28
  env?: NodeJS.ProcessEnv;
32
- /** Astro's logger. */
33
29
  logger?: {
34
30
  info?: (message: string) => void;
35
31
  warn?: (message: string) => void;
@@ -39,11 +35,9 @@ export interface GrammarSourceOptions {
39
35
  /** Bundled Langium text, for tests. */
40
36
  bundledLangiumPath?: string;
41
37
  }
42
- /** Where a grammar came from, for logs and tests. */
43
38
  export interface GrammarMeta {
44
39
  repo: string;
45
40
  ref: string;
46
- /** Where it came from. */
47
41
  source: 'network' | 'cache' | 'bundled';
48
42
  fetchedAt: number;
49
43
  etag?: string | undefined;
@@ -53,11 +47,8 @@ export interface GrammarMeta {
53
47
  reason?: string;
54
48
  }
55
49
  export interface GrammarSource {
56
- /** The TextMate grammar for Shiki. */
57
50
  grammar: TmGrammar;
58
- /** The Langium source it was derived from. */
59
51
  langium: string;
60
- /** Where it came from, for logs and tests. */
61
52
  meta: GrammarMeta;
62
53
  }
63
54
  /** Raised for a ref this repository cannot have — always a user error. */
@@ -71,9 +62,6 @@ export declare class GrammarFetchError extends Error {
71
62
  export declare function resolveLikeC4Grammar(options?: GrammarSourceOptions): Promise<GrammarSource>;
72
63
  /** Short content hash — the identity that actually changes highlighting. */
73
64
  export declare function grammarSha(source: string): string;
74
- /**
75
- * Rejects anything that cannot name a ref, before it reaches the network.
76
- */
77
65
  export declare function validateRef(ref: string): string;
78
66
  /** What a fetch returns: the text, or the news that the ETag still matches. */
79
67
  export type FetchResult = {
@@ -24,7 +24,6 @@ export interface TmPattern {
24
24
  }>;
25
25
  patterns?: TmPattern[];
26
26
  }
27
- /** A TextMate grammar: JSON all the way down, never a `RegExp`. */
28
27
  export interface TmGrammar {
29
28
  $schema: string;
30
29
  name: string;
@@ -46,6 +45,5 @@ export interface TmProvenance {
46
45
  ref?: string;
47
46
  sha?: string;
48
47
  }
49
- /** Turns a vocabulary into a TextMate grammar, JSON-serialisable. */
50
48
  export declare function buildTmLanguage(vocabulary: Vocabulary, meta?: TmProvenance): TmGrammar;
51
49
  export default buildTmLanguage;
@@ -0,0 +1,28 @@
1
+ import { type ResolvedProject } from './projects.js';
2
+ /** After Astro's `base`. */
3
+ export declare const ICON_ROUTE = "/_astroc4/";
4
+ export interface IconAsset {
5
+ /** With links resolved. */
6
+ file: string;
7
+ /** Including Astro's `base`. */
8
+ url: string;
9
+ projectName: string;
10
+ /** Under the site's `public/`: Astro serves and copies it, astroc4 does neither. */
11
+ public?: boolean;
12
+ }
13
+ export declare function iconAssetFor(project: ResolvedProject, fileUrl: string, base: string, siteRoot: string): IconAsset | null;
14
+ /**
15
+ * LikeC4 resolves relative icon paths and `imageAliases` lexically against the
16
+ * staging link it opened, so `resolve(link, x)` is mapped back to
17
+ * `resolve(project.folder, x)`.
18
+ */
19
+ export declare function unstage(fileUrl: string, project: ResolvedProject, stagingDir: string | undefined): string;
20
+ /**
21
+ * @throws Astroc4ConfigError for a missing icon, or two files that would be
22
+ * served at the same URL.
23
+ */
24
+ export declare function buildIconManifest(entries: Array<{
25
+ project: ResolvedProject;
26
+ fileUrl: string;
27
+ source: string;
28
+ }>, base: string, siteRoot: string): Map<string, IconAsset>;
@@ -0,0 +1,16 @@
1
+ import type { Plugin as VitePlugin } from 'vite';
2
+ import { type IconAsset } from './icon-assets.js';
3
+ import type { ResolvedProject } from './projects.js';
4
+ export interface IconPluginState {
5
+ projects: ResolvedProject[];
6
+ base: string;
7
+ /** The site root; files under its `public/` are left to Astro. */
8
+ siteRoot: string;
9
+ stagingDir?: string;
10
+ }
11
+ export type Astroc4IconPlugin = VitePlugin & {
12
+ /** Keyed by compiled `file://` URL. */
13
+ manifest(): Map<string, IconAsset>;
14
+ emit(outDir: string): Promise<void>;
15
+ };
16
+ export declare function astroc4IconPlugin(state: IconPluginState): Astroc4IconPlugin;