@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 +65 -136
- package/dist/index.d.ts +156 -2
- package/dist/index.js +65 -136
- package/dist/publish/index.d.ts +38 -9
- package/dist/publish/index.js +62 -130
- package/dist/qa.d.ts +25 -1
- package/dist/renderer.d.ts +1 -1
- package/dist/{spec.schema-BxXBTOn-.d.ts → spec.schema-DhAI-tE8.d.ts} +164 -20
- package/dist/spec.schema.d.ts +1 -1
- package/package.json +3 -2
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
|
-
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
|
112
|
-
endpoint,
|
|
113
|
-
{
|
|
74
|
+
const published = await withRetry(
|
|
75
|
+
() => github.request(endpoint, {
|
|
114
76
|
method,
|
|
115
|
-
body:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
77
|
+
body: payload,
|
|
78
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
79
|
+
}),
|
|
80
|
+
retry
|
|
119
81
|
);
|
|
120
82
|
return {
|
|
121
83
|
target: "gist",
|
|
122
|
-
gistId: published.
|
|
123
|
-
htmlUrl: published.
|
|
124
|
-
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
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
|
|
242
|
-
putPath,
|
|
243
|
-
{
|
|
176
|
+
const published = await withRetry2(
|
|
177
|
+
() => github2.request(putPath, {
|
|
244
178
|
method: "PUT",
|
|
245
|
-
body
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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.
|
|
254
|
-
...published.
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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-
|
|
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-
|
|
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 };
|