@spectratools/graphic-designer-cli 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -10,38 +10,8 @@ import { Cli, z as z3 } from "incur";
10
10
  // src/publish/gist.ts
11
11
  import { readFile } from "fs/promises";
12
12
  import { basename } from "path";
13
-
14
- // src/utils/retry.ts
15
- var DEFAULT_RETRY_POLICY = {
16
- maxRetries: 3,
17
- baseMs: 500,
18
- maxMs: 4e3
19
- };
20
- function sleep(ms) {
21
- return new Promise((resolve5) => setTimeout(resolve5, ms));
22
- }
23
- async function withRetry(operation, policy = DEFAULT_RETRY_POLICY) {
24
- let attempt = 0;
25
- let lastError;
26
- while (attempt <= policy.maxRetries) {
27
- try {
28
- const value = await operation();
29
- return { value, attempts: attempt + 1 };
30
- } catch (error) {
31
- lastError = error;
32
- if (attempt >= policy.maxRetries) {
33
- break;
34
- }
35
- const backoff = Math.min(policy.baseMs * 2 ** attempt, policy.maxMs);
36
- const jitter = Math.floor(Math.random() * 125);
37
- await sleep(backoff + jitter);
38
- attempt += 1;
39
- }
40
- }
41
- throw lastError;
42
- }
43
-
44
- // src/publish/gist.ts
13
+ import { withRetry } from "@spectratools/cli-shared/middleware";
14
+ import { createHttpClient } from "@spectratools/cli-shared/utils";
45
15
  function requireGitHubToken(token) {
46
16
  const resolved = token ?? process.env.GITHUB_TOKEN;
47
17
  if (!resolved) {
@@ -49,28 +19,21 @@ function requireGitHubToken(token) {
49
19
  }
50
20
  return resolved;
51
21
  }
52
- async function gistJson(path, init, token, retryPolicy) {
53
- return withRetry(async () => {
54
- const response = await fetch(`https://api.github.com${path}`, {
55
- ...init,
56
- headers: {
57
- Accept: "application/vnd.github+json",
58
- Authorization: `Bearer ${token}`,
59
- "User-Agent": "spectratools-graphic-designer",
60
- ...init.headers
61
- }
62
- });
63
- if (!response.ok) {
64
- const text = await response.text();
65
- throw new Error(
66
- `GitHub Gist API ${path} failed (${response.status}): ${text || response.statusText}`
67
- );
68
- }
69
- return await response.json();
70
- }, retryPolicy);
71
- }
22
+ var DEFAULT_RETRY = {
23
+ maxRetries: 3,
24
+ baseMs: 500,
25
+ maxMs: 4e3
26
+ };
27
+ var github = createHttpClient({
28
+ baseUrl: "https://api.github.com",
29
+ defaultHeaders: {
30
+ Accept: "application/vnd.github+json",
31
+ "User-Agent": "spectratools-graphic-designer"
32
+ }
33
+ });
72
34
  async function publishToGist(options) {
73
35
  const token = requireGitHubToken(options.token);
36
+ const retry = options.retryPolicy ?? DEFAULT_RETRY;
74
37
  const [imageBuffer, metadataBuffer] = await Promise.all([
75
38
  readFile(options.imagePath),
76
39
  readFile(options.metadataPath)
@@ -108,27 +71,27 @@ async function publishToGist(options) {
108
71
  };
109
72
  const endpoint = options.gistId ? `/gists/${options.gistId}` : "/gists";
110
73
  const method = options.gistId ? "PATCH" : "POST";
111
- const published = await gistJson(
112
- endpoint,
113
- {
74
+ const published = await withRetry(
75
+ () => github.request(endpoint, {
114
76
  method,
115
- body: JSON.stringify(payload)
116
- },
117
- token,
118
- options.retryPolicy
77
+ body: payload,
78
+ headers: { Authorization: `Bearer ${token}` }
79
+ }),
80
+ retry
119
81
  );
120
82
  return {
121
83
  target: "gist",
122
- gistId: published.value.id,
123
- htmlUrl: published.value.html_url,
124
- attempts: published.attempts,
125
- files: Object.keys(published.value.files ?? payload.files)
84
+ gistId: published.id,
85
+ htmlUrl: published.html_url,
86
+ files: Object.keys(published.files ?? payload.files)
126
87
  };
127
88
  }
128
89
 
129
90
  // src/publish/github.ts
130
91
  import { readFile as readFile2 } from "fs/promises";
131
92
  import { basename as basename2, posix } from "path";
93
+ import { withRetry as withRetry2 } from "@spectratools/cli-shared/middleware";
94
+ import { HttpError, createHttpClient as createHttpClient2 } from "@spectratools/cli-shared/utils";
132
95
  function requireGitHubToken2(token) {
133
96
  const resolved = token ?? process.env.GITHUB_TOKEN;
134
97
  if (!resolved) {
@@ -136,56 +99,18 @@ function requireGitHubToken2(token) {
136
99
  }
137
100
  return resolved;
138
101
  }
139
- async function githubJson(path, init, token, retryPolicy) {
140
- return withRetry(async () => {
141
- const response = await fetch(`https://api.github.com${path}`, {
142
- ...init,
143
- headers: {
144
- Accept: "application/vnd.github+json",
145
- Authorization: `Bearer ${token}`,
146
- "User-Agent": "spectratools-graphic-designer",
147
- ...init.headers
148
- }
149
- });
150
- if (!response.ok) {
151
- const text = await response.text();
152
- throw new Error(
153
- `GitHub API ${path} failed (${response.status}): ${text || response.statusText}`
154
- );
155
- }
156
- return await response.json();
157
- }, retryPolicy);
158
- }
159
- async function githubJsonMaybe(path, token, retryPolicy) {
160
- const { value, attempts } = await withRetry(async () => {
161
- const response = await fetch(`https://api.github.com${path}`, {
162
- headers: {
163
- Accept: "application/vnd.github+json",
164
- Authorization: `Bearer ${token}`,
165
- "User-Agent": "spectratools-graphic-designer"
166
- }
167
- });
168
- if (response.status === 404) {
169
- return { found: false };
170
- }
171
- if (!response.ok) {
172
- const text = await response.text();
173
- throw new Error(
174
- `GitHub API ${path} failed (${response.status}): ${text || response.statusText}`
175
- );
176
- }
177
- const json = await response.json();
178
- return { found: true, value: json };
179
- }, retryPolicy);
180
- if (!value.found) {
181
- return { found: false, attempts };
102
+ var DEFAULT_RETRY2 = {
103
+ maxRetries: 3,
104
+ baseMs: 500,
105
+ maxMs: 4e3
106
+ };
107
+ var github2 = createHttpClient2({
108
+ baseUrl: "https://api.github.com",
109
+ defaultHeaders: {
110
+ Accept: "application/vnd.github+json",
111
+ "User-Agent": "spectratools-graphic-designer"
182
112
  }
183
- return {
184
- found: true,
185
- value: value.value,
186
- attempts
187
- };
188
- }
113
+ });
189
114
  function parseRepo(repo) {
190
115
  const [owner, name] = repo.split("/");
191
116
  if (!owner || !name) {
@@ -201,9 +126,25 @@ function normalizePath(pathPrefix, filename) {
201
126
  const trimmed = (pathPrefix ?? "artifacts").replace(/^\/+|\/+$/gu, "");
202
127
  return posix.join(trimmed, filename);
203
128
  }
129
+ async function githubJsonMaybe(path, token, retry) {
130
+ return withRetry2(async () => {
131
+ try {
132
+ const value = await github2.request(path, {
133
+ headers: { Authorization: `Bearer ${token}` }
134
+ });
135
+ return { found: true, value };
136
+ } catch (err) {
137
+ if (err instanceof HttpError && err.status === 404) {
138
+ return { found: false };
139
+ }
140
+ throw err;
141
+ }
142
+ }, retry);
143
+ }
204
144
  async function publishToGitHub(options) {
205
145
  const token = requireGitHubToken2(options.token);
206
146
  const branch = options.branch ?? "main";
147
+ const retry = options.retryPolicy ?? DEFAULT_RETRY2;
207
148
  const commitMessage = options.commitMessage ?? "chore(graphic-designer): publish deterministic artifacts";
208
149
  const [imageBuffer, metadataBuffer] = await Promise.all([
209
150
  readFile2(options.imagePath),
@@ -221,16 +162,10 @@ async function publishToGitHub(options) {
221
162
  content: metadataBuffer.toString("base64")
222
163
  }
223
164
  ];
224
- let totalAttempts = 0;
225
165
  const files = [];
226
166
  for (const upload of uploads) {
227
167
  const existingPath = `${toApiContentPath(options.repo, upload.destination)}?ref=${encodeURIComponent(branch)}`;
228
- const existing = await githubJsonMaybe(
229
- existingPath,
230
- token,
231
- options.retryPolicy
232
- );
233
- totalAttempts += existing.attempts;
168
+ const existing = await githubJsonMaybe(existingPath, token, retry);
234
169
  const body = {
235
170
  message: `${commitMessage} (${basename2(upload.sourcePath)})`,
236
171
  content: upload.content,
@@ -238,27 +173,24 @@ async function publishToGitHub(options) {
238
173
  sha: existing.value?.sha
239
174
  };
240
175
  const putPath = toApiContentPath(options.repo, upload.destination);
241
- const published = await githubJson(
242
- putPath,
243
- {
176
+ const published = await withRetry2(
177
+ () => github2.request(putPath, {
244
178
  method: "PUT",
245
- body: JSON.stringify(body)
246
- },
247
- token,
248
- options.retryPolicy
179
+ body,
180
+ headers: { Authorization: `Bearer ${token}` }
181
+ }),
182
+ retry
249
183
  );
250
- totalAttempts += published.attempts;
251
184
  files.push({
252
185
  path: upload.destination,
253
- ...published.value.content?.sha ? { sha: published.value.content.sha } : {},
254
- ...published.value.content?.html_url ? { htmlUrl: published.value.content.html_url } : {}
186
+ ...published.content?.sha ? { sha: published.content.sha } : {},
187
+ ...published.content?.html_url ? { htmlUrl: published.content.html_url } : {}
255
188
  });
256
189
  }
257
190
  return {
258
191
  target: "github",
259
192
  repo: options.repo,
260
193
  branch,
261
- attempts: totalAttempts,
262
194
  files
263
195
  };
264
196
  }
@@ -4814,7 +4746,6 @@ cli.command("publish", {
4814
4746
  issueCount: z3.number()
4815
4747
  }),
4816
4748
  publish: z3.object({
4817
- attempts: z3.number(),
4818
4749
  summary: z3.string(),
4819
4750
  url: z3.string().optional()
4820
4751
  })
@@ -4867,7 +4798,6 @@ cli.command("publish", {
4867
4798
  issueCount: qa.issues.length
4868
4799
  },
4869
4800
  publish: {
4870
- attempts: gist.attempts,
4871
4801
  summary: `Published ${gist.files.length} files to gist ${gist.gistId}.`,
4872
4802
  url: gist.htmlUrl
4873
4803
  }
@@ -4880,7 +4810,7 @@ cli.command("publish", {
4880
4810
  retryable: false
4881
4811
  });
4882
4812
  }
4883
- const github = await publishToGitHub({
4813
+ const github3 = await publishToGitHub({
4884
4814
  imagePath,
4885
4815
  metadataPath,
4886
4816
  repo: c.options.repo,
@@ -4888,7 +4818,7 @@ cli.command("publish", {
4888
4818
  ...c.options.pathPrefix ? { pathPrefix: c.options.pathPrefix } : {},
4889
4819
  ...c.options.description ? { commitMessage: c.options.description } : {}
4890
4820
  });
4891
- const url = github.files.find((file) => file.htmlUrl)?.htmlUrl;
4821
+ const url = github3.files.find((file) => file.htmlUrl)?.htmlUrl;
4892
4822
  return c.ok({
4893
4823
  target: "github",
4894
4824
  qa: {
@@ -4896,8 +4826,7 @@ cli.command("publish", {
4896
4826
  issueCount: qa.issues.length
4897
4827
  },
4898
4828
  publish: {
4899
- attempts: github.attempts,
4900
- summary: `Published ${github.files.length} files to ${github.repo}@${github.branch}.`,
4829
+ summary: `Published ${github3.files.length} files to ${github3.repo}@${github3.branch}.`,
4901
4830
  url
4902
4831
  }
4903
4832
  });
package/dist/index.d.ts CHANGED
@@ -1,17 +1,42 @@
1
1
  import { Cli } from 'incur';
2
- import { T as ThemeInput, D as DesignSpec, a as Rect, b as DrawCommand, c as Theme, d as RenderedElement } from './spec.schema-BxXBTOn-.js';
3
- export { A as AutoLayoutConfig, B as BuiltInTheme, C as CardElement, e as CodeBlockElement, f as ConnectionElement, g as ConstraintSpec, h as DEFAULT_GENERATOR_VERSION, i as DEFAULT_RAINBOW_COLORS, j as Decorator, k as DesignSafeFrame, l as DrawBadge, m as DrawBezier, n as DrawCircle, o as DrawFontFamily, p as DrawGradientRect, q as DrawLine, r as DrawPath, s as DrawPoint, t as DrawRect, u as DrawText, E as Element, F as FlowNodeElement, G as Gradient, v as GradientOverlayDecorator, w as GradientSpec, x as GradientStop, y as GridLayoutConfig, I as ImageElement, L as LayoutConfig, z as LayoutSnapshot, M as ManualLayoutConfig, H as RainbowRuleDecorator, R as RenderMetadata, J as RenderResult, S as ShapeElement, K as StackLayoutConfig, N as TerminalElement, O as TextElement, P as ThemeInput, V as VignetteDecorator, W as WrittenArtifacts, Q as builtInThemeBackgrounds, U as builtInThemes, X as computeSpecHash, Y as defaultAutoLayout, Z as defaultCanvas, _ as defaultConstraints, $ as defaultGridLayout, a0 as defaultLayout, a1 as defaultStackLayout, a2 as defaultTheme, a3 as deriveSafeFrame, a4 as designSpecSchema, a5 as drawGradientRect, a6 as drawRainbowRule, a7 as drawVignette, a8 as inferLayout, a9 as inferSidecarPath, aa as parseDesignSpec, ab as renderDesign, ac as resolveTheme, ad as writeRenderArtifacts } from './spec.schema-BxXBTOn-.js';
2
+ import { T as ThemeInput, D as DesignSpec, a as Rect, b as DrawCommand, c as Theme, d as RenderedElement } from './spec.schema-DhAI-tE8.js';
3
+ export { A as AutoLayoutConfig, B as BuiltInTheme, C as CardElement, e as CodeBlockElement, f as ConnectionElement, g as ConstraintSpec, h as DEFAULT_GENERATOR_VERSION, i as DEFAULT_RAINBOW_COLORS, j as Decorator, k as DesignSafeFrame, l as DrawBadge, m as DrawBezier, n as DrawCircle, o as DrawFontFamily, p as DrawGradientRect, q as DrawLine, r as DrawPath, s as DrawPoint, t as DrawRect, u as DrawText, E as Element, F as FlowNodeElement, G as Gradient, v as GradientOverlayDecorator, w as GradientSpec, x as GradientStop, y as GridLayoutConfig, I as ImageElement, L as LayoutConfig, z as LayoutSnapshot, M as ManualLayoutConfig, H as RainbowRuleDecorator, R as RenderMetadata, J as RenderResult, S as ShapeElement, K as StackLayoutConfig, N as TerminalElement, O as TextElement, P as ThemeInput, V as VignetteDecorator, W as WrittenArtifacts, Q as builtInThemeBackgrounds, U as builtInThemes, X as computeSpecHash, Y as defaultAutoLayout, Z as defaultCanvas, _ as defaultConstraints, $ as defaultGridLayout, a0 as defaultLayout, a1 as defaultStackLayout, a2 as defaultTheme, a3 as deriveSafeFrame, a4 as designSpecSchema, a5 as drawGradientRect, a6 as drawRainbowRule, a7 as drawVignette, a8 as inferLayout, a9 as inferSidecarPath, aa as parseDesignSpec, ab as renderDesign, ac as resolveTheme, ad as writeRenderArtifacts } from './spec.schema-DhAI-tE8.js';
4
4
  import { SKRSContext2D } from '@napi-rs/canvas';
5
5
  export { QaIssue, QaReport, QaSeverity, readMetadata, runQa } from './qa.js';
6
6
  import { Highlighter } from 'shiki';
7
7
  export { GistPublishOptions, GistPublishResult, GitHubPublishOptions, GitHubPublishResult, publishToGist, publishToGitHub } from './publish/index.js';
8
8
  import 'zod';
9
+ import '@spectratools/cli-shared/middleware';
9
10
 
10
11
  declare const cli: Cli.Cli<{}, undefined, undefined>;
11
12
 
12
13
  declare const themeToShikiMap: Record<string, string>;
13
14
  declare function resolveShikiTheme(theme: ThemeInput): string;
14
15
 
16
+ /**
17
+ * Build a validated {@link DesignSpec} for a flowchart diagram.
18
+ *
19
+ * Accepts plain-text node and edge definitions and converts them into
20
+ * `flow-node` and `connection` elements with automatic ELK-based layout.
21
+ *
22
+ * Node tokens use the format `"Label"` or `"Label:shape"` (e.g.
23
+ * `"Start:pill"`). Edge tokens use `"From->To"` or `"From->To:label"`.
24
+ *
25
+ * @param options - Flowchart configuration.
26
+ * @param options.nodes - Array of node token strings to create.
27
+ * @param options.edges - Array of edge token strings defining connections.
28
+ * @param options.title - Optional header title displayed above the flowchart.
29
+ * @param options.direction - ELK layout direction. Defaults to `"TB"`.
30
+ * @param options.algorithm - ELK layout algorithm. Defaults to `"layered"`.
31
+ * @param options.theme - Built-in theme name. Defaults to `"dark"`.
32
+ * @param options.nodeShape - Default node shape when not specified per-node.
33
+ * Defaults to `"rounded-box"`.
34
+ * @param options.width - Canvas width override in pixels.
35
+ * @param options.height - Canvas height override in pixels.
36
+ * @returns A fully validated and parsed {@link DesignSpec}.
37
+ * @throws When a node token is empty, duplicated, or an edge references an
38
+ * unknown node.
39
+ */
15
40
  declare function buildFlowchartSpec(options: {
16
41
  nodes: string[];
17
42
  edges: string[];
@@ -26,6 +51,31 @@ declare function buildFlowchartSpec(options: {
26
51
 
27
52
  type WindowControls = 'macos' | 'bw' | 'none';
28
53
 
54
+ /**
55
+ * Build a validated {@link DesignSpec} for a Carbon-style code screenshot.
56
+ *
57
+ * Wraps a code snippet in a single `code-block` element with macOS-style window
58
+ * chrome, drop shadow, and syntax highlighting. The resulting spec uses a
59
+ * vertical stack layout.
60
+ *
61
+ * @param options - Code screenshot configuration.
62
+ * @param options.code - The source code string to display.
63
+ * @param options.language - Programming language for syntax highlighting (e.g.
64
+ * `"typescript"`).
65
+ * @param options.title - Optional title shown in the window title bar.
66
+ * @param options.theme - Built-in theme name. Defaults to `"dark"`.
67
+ * @param options.showLineNumbers - Whether to render line numbers. Defaults to
68
+ * `false`.
69
+ * @param options.highlightLines - Array of 1-based line numbers to highlight.
70
+ * @param options.startLine - Starting line number for display. Defaults to `1`.
71
+ * @param options.width - Canvas width in pixels. Defaults to `800`.
72
+ * @param options.height - Canvas height in pixels. Defaults to `500`.
73
+ * @param options.surroundColor - Background colour behind the code window.
74
+ * @param options.windowControls - Window control style (`"macos"`, `"bw"`, or
75
+ * `"none"`). Defaults to `"macos"`.
76
+ * @param options.scale - Render scale multiplier. Defaults to `2`.
77
+ * @returns A fully validated and parsed {@link DesignSpec}.
78
+ */
29
79
  declare function buildCodeSpec(options: {
30
80
  code: string;
31
81
  language: string;
@@ -41,6 +91,31 @@ declare function buildCodeSpec(options: {
41
91
  scale?: number;
42
92
  }): DesignSpec;
43
93
 
94
+ /**
95
+ * Build a validated {@link DesignSpec} for a terminal screenshot.
96
+ *
97
+ * Accepts either raw terminal content or a command/output pair and wraps it in
98
+ * a single `terminal` element with macOS-style window chrome and a drop shadow.
99
+ * At least one of `content`, `command`, or `output` must be provided.
100
+ *
101
+ * @param options - Terminal screenshot configuration.
102
+ * @param options.command - Shell command to display (prepended with the prompt).
103
+ * @param options.output - Command output text.
104
+ * @param options.content - Raw terminal content — takes precedence over
105
+ * `command`/`output` when provided.
106
+ * @param options.title - Optional window title bar text.
107
+ * @param options.prompt - Prompt prefix used when rendering `command`. Defaults
108
+ * to `"$ "`.
109
+ * @param options.theme - Built-in theme name. Defaults to `"dark"`.
110
+ * @param options.width - Canvas width in pixels. Defaults to `800`.
111
+ * @param options.height - Canvas height in pixels. Defaults to `400`.
112
+ * @param options.surroundColor - Background colour behind the terminal window.
113
+ * @param options.windowControls - Window control style (`"macos"`, `"bw"`, or
114
+ * `"none"`). Defaults to `"macos"`.
115
+ * @param options.scale - Render scale multiplier. Defaults to `2`.
116
+ * @returns A fully validated and parsed {@link DesignSpec}.
117
+ * @throws When none of `content`, `command`, or `output` is provided.
118
+ */
44
119
  declare function buildTerminalSpec(options: {
45
120
  command?: string;
46
121
  output?: string;
@@ -55,6 +130,26 @@ declare function buildTerminalSpec(options: {
55
130
  scale?: number;
56
131
  }): DesignSpec;
57
132
 
133
+ /**
134
+ * Build a validated {@link DesignSpec} for a card grid layout.
135
+ *
136
+ * Converts an array of card data into `card` elements arranged in a grid. The
137
+ * number of columns is inferred from the card count when not specified
138
+ * explicitly.
139
+ *
140
+ * @param options - Card grid configuration.
141
+ * @param options.cards - Array of card data objects. Each must include `title`
142
+ * and `body`; `badge`, `metric`, and `tone` are optional.
143
+ * @param options.title - Optional header title displayed above the card grid.
144
+ * @param options.subtitle - Optional header subtitle (only rendered when
145
+ * `title` is also set).
146
+ * @param options.columns - Number of grid columns. When omitted, a heuristic
147
+ * chooses based on card count (1–4 columns).
148
+ * @param options.theme - Built-in theme name. Defaults to `"dark"`.
149
+ * @param options.width - Canvas width override in pixels.
150
+ * @param options.height - Canvas height override in pixels.
151
+ * @returns A fully validated and parsed {@link DesignSpec}.
152
+ */
58
153
  declare function buildCardsSpec(options: {
59
154
  cards: Array<{
60
155
  title: string;
@@ -88,10 +183,46 @@ type ElkLayoutResult = LayoutResult & {
88
183
  edgeRoutes?: Map<string, EdgeRoute>;
89
184
  };
90
185
 
186
+ /**
187
+ * Render an array of freestyle draw commands onto a canvas context.
188
+ *
189
+ * Supports eight command types: `rect`, `circle`, `text`, `line`, `bezier`,
190
+ * `path`, `badge`, and `gradient-rect`. Each command is rendered in order and
191
+ * produces a corresponding {@link RenderedElement} with computed bounds for
192
+ * downstream QA checks.
193
+ *
194
+ * @param ctx - The `@napi-rs/canvas` 2D rendering context to draw into.
195
+ * @param commands - Array of {@link DrawCommand} objects from the design spec's
196
+ * `draw` field.
197
+ * @param theme - The resolved {@link Theme} used for font resolution and
198
+ * default colours.
199
+ * @returns An array of {@link RenderedElement} entries describing each drawn
200
+ * command's bounding box and colours.
201
+ */
91
202
  declare function renderDrawCommands(ctx: SKRSContext2D, commands: DrawCommand[], theme: Theme): RenderedElement[];
92
203
 
204
+ /**
205
+ * Register the bundled font families (Inter, JetBrains Mono, Space Grotesk)
206
+ * with the global `@napi-rs/canvas` font registry.
207
+ *
208
+ * **Must be called before {@link renderDesign}.** Without registered fonts the
209
+ * canvas will fall back to system defaults, producing inconsistent output across
210
+ * environments. {@link renderDesign} calls this internally, but consumers using
211
+ * lower-level APIs (e.g. `renderDrawCommands`) should call it explicitly.
212
+ *
213
+ * This function is idempotent — subsequent calls after the first are no-ops.
214
+ */
93
215
  declare function loadFonts(): void;
94
216
 
217
+ /**
218
+ * Initialise (or return the existing) shiki syntax highlighter singleton.
219
+ *
220
+ * Loads all bundled themes and languages on first call. Subsequent calls return
221
+ * the cached instance immediately. Must be called (or allowed to be called
222
+ * implicitly via {@link highlightCode}) before any syntax highlighting work.
223
+ *
224
+ * @returns The shared shiki {@link Highlighter} instance.
225
+ */
95
226
  declare function initHighlighter(): Promise<Highlighter>;
96
227
  type HighlightedLine = {
97
228
  tokens: Array<{
@@ -99,7 +230,30 @@ type HighlightedLine = {
99
230
  color: string;
100
231
  }>;
101
232
  };
233
+ /**
234
+ * Tokenise and syntax-highlight a code string.
235
+ *
236
+ * Lazily initialises the highlighter via {@link initHighlighter} if it has not
237
+ * been created yet. Language aliases (e.g. `"ts"` → `"typescript"`) are
238
+ * resolved automatically.
239
+ *
240
+ * @param code - The source code string to highlight.
241
+ * @param language - Programming language identifier or alias (e.g.
242
+ * `"typescript"`, `"ts"`, `"python"`).
243
+ * @param themeName - Shiki theme name to use for colouring (e.g.
244
+ * `"github-dark"`).
245
+ * @returns An array of {@link HighlightedLine} objects, one per line, each
246
+ * containing an array of coloured text tokens.
247
+ * @throws When the language or theme is not among the bundled set.
248
+ */
102
249
  declare function highlightCode(code: string, language: string, themeName: string): Promise<HighlightedLine[]>;
250
+ /**
251
+ * Dispose the shared shiki highlighter instance and release its resources.
252
+ *
253
+ * After disposal, the next call to {@link initHighlighter} or
254
+ * {@link highlightCode} will create a fresh instance. Safe to call even when no
255
+ * highlighter has been initialised (no-op in that case).
256
+ */
103
257
  declare function disposeHighlighter(): void;
104
258
 
105
259
  export { DesignSpec, DrawCommand, type EdgeRoute, type ElkLayoutResult, type HighlightedLine, type LayoutResult, Rect, RenderedElement, Theme, buildCardsSpec, buildCodeSpec, buildFlowchartSpec, buildTerminalSpec, cli, disposeHighlighter, highlightCode, initHighlighter, loadFonts, renderDrawCommands, resolveShikiTheme, themeToShikiMap };