@mcuste/pi-diagram 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +240 -0
- package/dist/artifacts.d.ts +59 -0
- package/dist/artifacts.d.ts.map +1 -0
- package/dist/artifacts.js +274 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/cache.d.ts +43 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +0 -0
- package/dist/cache.js.map +1 -0
- package/dist/d2/diagnostics.d.ts +25 -0
- package/dist/d2/diagnostics.d.ts.map +1 -0
- package/dist/d2/diagnostics.js +77 -0
- package/dist/d2/diagnostics.js.map +1 -0
- package/dist/d2/fonts.d.ts +23 -0
- package/dist/d2/fonts.d.ts.map +1 -0
- package/dist/d2/fonts.js +255 -0
- package/dist/d2/fonts.js.map +1 -0
- package/dist/d2/preflight.d.ts +20 -0
- package/dist/d2/preflight.d.ts.map +1 -0
- package/dist/d2/preflight.js +217 -0
- package/dist/d2/preflight.js.map +1 -0
- package/dist/d2/profiles.d.ts +34 -0
- package/dist/d2/profiles.d.ts.map +1 -0
- package/dist/d2/profiles.js +118 -0
- package/dist/d2/profiles.js.map +1 -0
- package/dist/d2/runner.d.ts +95 -0
- package/dist/d2/runner.d.ts.map +1 -0
- package/dist/d2/runner.js +350 -0
- package/dist/d2/runner.js.map +1 -0
- package/dist/display.d.ts +48 -0
- package/dist/display.d.ts.map +1 -0
- package/dist/display.js +120 -0
- package/dist/display.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/normalize.d.ts +23 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/normalize.js +83 -0
- package/dist/normalize.js.map +1 -0
- package/dist/process.d.ts +38 -0
- package/dist/process.d.ts.map +1 -0
- package/dist/process.js +87 -0
- package/dist/process.js.map +1 -0
- package/dist/raster.d.ts +40 -0
- package/dist/raster.d.ts.map +1 -0
- package/dist/raster.js +193 -0
- package/dist/raster.js.map +1 -0
- package/dist/render.d.ts +55 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +229 -0
- package/dist/render.js.map +1 -0
- package/dist/tools.d.ts +58 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +284 -0
- package/dist/tools.js.map +1 -0
- package/package.json +101 -0
- package/src/artifacts.ts +418 -0
- package/src/cache.ts +0 -0
- package/src/d2/diagnostics.ts +114 -0
- package/src/d2/fonts.ts +289 -0
- package/src/d2/preflight.ts +270 -0
- package/src/d2/profiles.ts +157 -0
- package/src/d2/runner.ts +513 -0
- package/src/display.ts +201 -0
- package/src/index.ts +5 -0
- package/src/normalize.ts +119 -0
- package/src/process.ts +134 -0
- package/src/raster.ts +258 -0
- package/src/render.ts +338 -0
- package/src/tools.ts +455 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { DiagramSourceError } from "./d2/diagnostics.js";
|
|
3
|
+
/** Byte-level enforcement of the schema's character limit in `tools.ts`. */
|
|
4
|
+
const MAX_SOURCE_BYTES = 20 * 1024;
|
|
5
|
+
const MAX_TITLE_LENGTH = 120;
|
|
6
|
+
const TAB = 0x09;
|
|
7
|
+
const LINE_FEED = 0x0a;
|
|
8
|
+
const FIRST_PRINTABLE = 0x20;
|
|
9
|
+
const DELETE = 0x7f;
|
|
10
|
+
const BYTE_ORDER_MARK = 0xfeff;
|
|
11
|
+
/** Characters a terminal would act on rather than print. */
|
|
12
|
+
function isControl(codePoint) {
|
|
13
|
+
if (codePoint === TAB || codePoint === LINE_FEED) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
return codePoint < FIRST_PRINTABLE || codePoint === DELETE;
|
|
17
|
+
}
|
|
18
|
+
function findControl(text) {
|
|
19
|
+
let offset = 0;
|
|
20
|
+
for (const character of text) {
|
|
21
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
22
|
+
if (isControl(codePoint)) {
|
|
23
|
+
return { offset, codePoint };
|
|
24
|
+
}
|
|
25
|
+
offset += character.length;
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
/** Runs before anything inspects or renders, so the scanner and D2 see the same bytes. */
|
|
30
|
+
export function normalizeSource(raw) {
|
|
31
|
+
if (typeof raw !== "string") {
|
|
32
|
+
throw new DiagramSourceError("Diagram source must be a string.", [
|
|
33
|
+
{ code: "D2_SOURCE", message: `Received ${raw === null ? "null" : typeof raw}.` },
|
|
34
|
+
]);
|
|
35
|
+
}
|
|
36
|
+
const text = stripByteOrderMark(raw).replace(/\r\n?/gu, "\n").trim();
|
|
37
|
+
if (text.length === 0) {
|
|
38
|
+
throw new DiagramSourceError("Diagram source is empty.", [
|
|
39
|
+
{ code: "D2_SOURCE", message: "Send D2 source such as `client -> gateway: request`." },
|
|
40
|
+
]);
|
|
41
|
+
}
|
|
42
|
+
const control = findControl(text);
|
|
43
|
+
if (control) {
|
|
44
|
+
const label = control.codePoint.toString(16).padStart(4, "0").toUpperCase();
|
|
45
|
+
throw new DiagramSourceError("Diagram source contains a control character.", [
|
|
46
|
+
{
|
|
47
|
+
code: "D2_SOURCE",
|
|
48
|
+
message: `U+${label} at offset ${control.offset} is not allowed in diagram source.`,
|
|
49
|
+
},
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
const bytes = Buffer.byteLength(text, "utf8");
|
|
53
|
+
if (bytes > MAX_SOURCE_BYTES) {
|
|
54
|
+
throw new DiagramSourceError("Diagram source is too large.", [
|
|
55
|
+
{
|
|
56
|
+
code: "D2_TOO_LARGE",
|
|
57
|
+
message: `${bytes} bytes is above the ${MAX_SOURCE_BYTES} byte limit.`,
|
|
58
|
+
hint: "Split it into smaller diagrams.",
|
|
59
|
+
},
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
text: text,
|
|
64
|
+
hash: createHash("sha256").update(text, "utf8").digest("hex"),
|
|
65
|
+
lineCount: text.split("\n").length,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export function parseTitle(raw) {
|
|
69
|
+
if (typeof raw !== "string") {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
const printable = Array.from(raw, (character) => isControl(character.codePointAt(0) ?? 0) ? " " : character).join("");
|
|
73
|
+
const title = printable.replace(/\s+/gu, " ").trim();
|
|
74
|
+
if (title.length === 0) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
const capped = title.length > MAX_TITLE_LENGTH ? `${title.slice(0, MAX_TITLE_LENGTH - 3)}...` : title;
|
|
78
|
+
return capped;
|
|
79
|
+
}
|
|
80
|
+
function stripByteOrderMark(raw) {
|
|
81
|
+
return raw.codePointAt(0) === BYTE_ORDER_MARK ? raw.slice(1) : raw;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface CommandResult {
|
|
2
|
+
readonly command: string;
|
|
3
|
+
readonly args: readonly string[];
|
|
4
|
+
readonly exitCode: number;
|
|
5
|
+
readonly stdout: string;
|
|
6
|
+
readonly stderr: string;
|
|
7
|
+
}
|
|
8
|
+
interface RunCommandOptions {
|
|
9
|
+
readonly cwd: string;
|
|
10
|
+
readonly signal?: AbortSignal | undefined;
|
|
11
|
+
readonly env?: NodeJS.ProcessEnv | undefined;
|
|
12
|
+
readonly timeoutMs?: number | undefined;
|
|
13
|
+
readonly maxOutputBytes?: number | undefined;
|
|
14
|
+
}
|
|
15
|
+
export type CommandRunner = (command: string, args: readonly string[], options: RunCommandOptions) => Promise<CommandResult>;
|
|
16
|
+
/** The command never started, which is what a missing D2 install looks like. */
|
|
17
|
+
export declare class CommandInvocationError extends Error {
|
|
18
|
+
readonly command: string;
|
|
19
|
+
readonly code: string | undefined;
|
|
20
|
+
constructor(command: string, message: string, code: string | undefined, options?: ErrorOptions);
|
|
21
|
+
}
|
|
22
|
+
export declare class CommandCancelledError extends Error {
|
|
23
|
+
constructor(command: string);
|
|
24
|
+
}
|
|
25
|
+
export declare class CommandTimeoutError extends Error {
|
|
26
|
+
readonly command: string;
|
|
27
|
+
readonly timeoutMs: number;
|
|
28
|
+
constructor(command: string, timeoutMs: number);
|
|
29
|
+
}
|
|
30
|
+
/** A `maxBuffer` kill is a size limit, not a broken executable, so it is not a spawn failure. */
|
|
31
|
+
export declare class CommandOutputLimitError extends Error {
|
|
32
|
+
readonly command: string;
|
|
33
|
+
readonly maxOutputBytes: number;
|
|
34
|
+
constructor(command: string, maxOutputBytes: number, options?: ErrorOptions);
|
|
35
|
+
}
|
|
36
|
+
export declare const runCommand: CommandRunner;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,iBAAiB;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9C;AAED,MAAM,MAAM,aAAa,GAAG,CAC1B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,iBAAiB,KACvB,OAAO,CAAC,aAAa,CAAC,CAAC;AAE5B,gFAAgF;AAChF,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAElC,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE,YAAY,EAK7F;CACF;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,YAAY,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAK7C;CACF;AAED,iGAAiG;AACjG,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAEhC,YAAY,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAO1E;CACF;AAED,eAAO,MAAM,UAAU,EAAE,aA4DxB,CAAC"}
|
package/dist/process.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
const DEFAULT_MAX_OUTPUT_BYTES = 1024 * 1024;
|
|
3
|
+
/** The command never started, which is what a missing D2 install looks like. */
|
|
4
|
+
export class CommandInvocationError extends Error {
|
|
5
|
+
command;
|
|
6
|
+
code;
|
|
7
|
+
constructor(command, message, code, options) {
|
|
8
|
+
super(message, options);
|
|
9
|
+
this.name = "CommandInvocationError";
|
|
10
|
+
this.command = command;
|
|
11
|
+
this.code = code;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class CommandCancelledError extends Error {
|
|
15
|
+
constructor(command) {
|
|
16
|
+
super(`${command} was cancelled.`);
|
|
17
|
+
this.name = "CommandCancelledError";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class CommandTimeoutError extends Error {
|
|
21
|
+
command;
|
|
22
|
+
timeoutMs;
|
|
23
|
+
constructor(command, timeoutMs) {
|
|
24
|
+
super(`${command} did not finish within ${timeoutMs} ms and was stopped.`);
|
|
25
|
+
this.name = "CommandTimeoutError";
|
|
26
|
+
this.command = command;
|
|
27
|
+
this.timeoutMs = timeoutMs;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** A `maxBuffer` kill is a size limit, not a broken executable, so it is not a spawn failure. */
|
|
31
|
+
export class CommandOutputLimitError extends Error {
|
|
32
|
+
command;
|
|
33
|
+
maxOutputBytes;
|
|
34
|
+
constructor(command, maxOutputBytes, options) {
|
|
35
|
+
super(`${command} produced more than ${maxOutputBytes} bytes of output and was stopped.`, {
|
|
36
|
+
...options,
|
|
37
|
+
});
|
|
38
|
+
this.name = "CommandOutputLimitError";
|
|
39
|
+
this.command = command;
|
|
40
|
+
this.maxOutputBytes = maxOutputBytes;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export const runCommand = (command, args, options) => {
|
|
44
|
+
if (options.signal?.aborted) {
|
|
45
|
+
return Promise.reject(new CommandCancelledError(command));
|
|
46
|
+
}
|
|
47
|
+
const maxOutputBytes = options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
|
|
48
|
+
const timeoutMs = options.timeoutMs ?? 0;
|
|
49
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
50
|
+
execFile(command, [...args], {
|
|
51
|
+
cwd: options.cwd,
|
|
52
|
+
encoding: "utf8",
|
|
53
|
+
maxBuffer: maxOutputBytes,
|
|
54
|
+
signal: options.signal,
|
|
55
|
+
timeout: timeoutMs,
|
|
56
|
+
env: options.env,
|
|
57
|
+
windowsHide: true,
|
|
58
|
+
}, (error, stdout, stderr) => {
|
|
59
|
+
if (options.signal?.aborted || error?.name === "AbortError") {
|
|
60
|
+
reject(new CommandCancelledError(command));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (error?.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER") {
|
|
64
|
+
reject(new CommandOutputLimitError(command, maxOutputBytes, { cause: error }));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// `timeout` kills the child with a signal, which arrives without a numeric exit code.
|
|
68
|
+
if (timeoutMs > 0 && error?.signal && typeof error.code !== "number") {
|
|
69
|
+
reject(new CommandTimeoutError(command, timeoutMs));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (error && typeof error.code !== "number") {
|
|
73
|
+
const detail = error.message.trim();
|
|
74
|
+
reject(new CommandInvocationError(command, `Unable to execute ${command}: ${detail}`, typeof error.code === "string" ? error.code : undefined, { cause: error }));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
resolve({
|
|
78
|
+
command,
|
|
79
|
+
args: [...args],
|
|
80
|
+
exitCode: typeof error?.code === "number" ? error.code : 0,
|
|
81
|
+
stdout,
|
|
82
|
+
stderr,
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
return promise;
|
|
86
|
+
};
|
|
87
|
+
//# sourceMappingURL=process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../src/process.ts"],"names":[],"mappings":"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"}
|
package/dist/raster.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type RenderCache } from "./cache.js";
|
|
2
|
+
import type { RenderedSvg } from "./d2/runner.js";
|
|
3
|
+
declare const renderedPngBrand: unique symbol;
|
|
4
|
+
/** Bytes that passed `parseRenderedPng`, so they really are a PNG of a known size. */
|
|
5
|
+
type RenderedPng = Uint8Array & {
|
|
6
|
+
readonly [renderedPngBrand]: true;
|
|
7
|
+
};
|
|
8
|
+
export interface RasterRequest {
|
|
9
|
+
readonly svg: RenderedSvg;
|
|
10
|
+
readonly signal: AbortSignal | undefined;
|
|
11
|
+
}
|
|
12
|
+
export interface RasterImage {
|
|
13
|
+
readonly png: RenderedPng;
|
|
14
|
+
readonly widthPx: number;
|
|
15
|
+
readonly heightPx: number;
|
|
16
|
+
/** True when the diagram's own font could not draw every label, so system fonts were added. */
|
|
17
|
+
readonly systemFonts: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface SvgRasterizer {
|
|
20
|
+
rasterize(request: RasterRequest): Promise<RasterImage>;
|
|
21
|
+
}
|
|
22
|
+
/** The diagram is fine and only the image failed, so the caller shows text rather than failing. */
|
|
23
|
+
export declare class ImageRenderUnavailableError extends Error {
|
|
24
|
+
constructor(message: string, options?: ErrorOptions);
|
|
25
|
+
}
|
|
26
|
+
/** resvg reporting success is not proof the bytes are a usable PNG of the size asked for. */
|
|
27
|
+
export declare function parseRenderedPng(bytes: Uint8Array, expectedWidthPx: number): RasterImage;
|
|
28
|
+
/** Enough resolution to scale down cleanly, never a pathological canvas. */
|
|
29
|
+
export declare function parseTargetWidth(naturalWidthPx: number, naturalHeightPx: number): number;
|
|
30
|
+
/** Parsed again on the way out, so a corrupt entry is drawn again rather than displayed. */
|
|
31
|
+
export declare function parseCachedImage(entry: string): RasterImage;
|
|
32
|
+
export declare class ResvgRasterizer implements SvgRasterizer {
|
|
33
|
+
private readonly cache;
|
|
34
|
+
constructor(dependencies?: {
|
|
35
|
+
readonly cache?: RenderCache;
|
|
36
|
+
});
|
|
37
|
+
rasterize(request: RasterRequest): Promise<RasterImage>;
|
|
38
|
+
}
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=raster.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raster.d.ts","sourceRoot":"","sources":["../src/raster.ts"],"names":[],"mappings":"AAIA,OAAO,EAAyB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAOrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA4BlD,OAAO,CAAC,MAAM,gBAAgB,EAAE,OAAO,MAAM,CAAC;AAE9C,sFAAsF;AACtF,KAAK,WAAW,GAAG,UAAU,GAAG;IAAE,QAAQ,CAAC,CAAC,gBAAgB,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAEtE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;CAC1C;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,+FAA+F;IAC/F,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACzD;AAED,mGAAmG;AACnG,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAGlD;CACF;AAED,6FAA6F;AAC7F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,GAAG,WAAW,CA6BxF;AAED,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAgBxF;AAQD,4FAA4F;AAC5F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAkB3D;AAqBD,qBAAa,eAAgB,YAAW,aAAa;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IAEpC,YAAY,YAAY,GAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAA;KAAO,EAE9D;IAEK,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAoB5D;CACF"}
|
package/dist/raster.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { cacheKeyOf, FileCache } from "./cache.js";
|
|
6
|
+
import { missingCodePoints, parseEmbeddedFonts, textCodePoints, } from "./d2/fonts.js";
|
|
7
|
+
import { CommandCancelledError } from "./process.js";
|
|
8
|
+
/**
|
|
9
|
+
* Draws a D2 SVG as a PNG. D2's own PNG export drives a headless browser it downloads on first
|
|
10
|
+
* use; resvg needs no browser and no network.
|
|
11
|
+
*/
|
|
12
|
+
/** Twice the natural size keeps labels readable once the terminal scales the image to cells. */
|
|
13
|
+
const SCALE = 2;
|
|
14
|
+
const MIN_WIDTH_PX = 480;
|
|
15
|
+
const MAX_WIDTH_PX = 1600;
|
|
16
|
+
const MAX_HEIGHT_PX = 2400;
|
|
17
|
+
const MAX_PNG_BYTES = 4 * 1024 * 1024;
|
|
18
|
+
const DEFAULT_FONT_FAMILY = "Source Sans Pro";
|
|
19
|
+
/** Everything besides the SVG and resvg itself that decides the picture. */
|
|
20
|
+
const IMAGE_POLICY = [
|
|
21
|
+
"png",
|
|
22
|
+
String(SCALE),
|
|
23
|
+
String(MIN_WIDTH_PX),
|
|
24
|
+
String(MAX_WIDTH_PX),
|
|
25
|
+
String(MAX_HEIGHT_PX),
|
|
26
|
+
DEFAULT_FONT_FAMILY,
|
|
27
|
+
];
|
|
28
|
+
const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
29
|
+
/** The diagram is fine and only the image failed, so the caller shows text rather than failing. */
|
|
30
|
+
export class ImageRenderUnavailableError extends Error {
|
|
31
|
+
constructor(message, options) {
|
|
32
|
+
super(message, options);
|
|
33
|
+
this.name = "ImageRenderUnavailableError";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** resvg reporting success is not proof the bytes are a usable PNG of the size asked for. */
|
|
37
|
+
export function parseRenderedPng(bytes, expectedWidthPx) {
|
|
38
|
+
if (bytes.length > MAX_PNG_BYTES) {
|
|
39
|
+
throw new ImageRenderUnavailableError(`The image is ${bytes.length} bytes, past the ${MAX_PNG_BYTES} byte limit.`);
|
|
40
|
+
}
|
|
41
|
+
const buffer = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
42
|
+
if (buffer.length < 24 || !buffer.subarray(0, 8).equals(PNG_SIGNATURE)) {
|
|
43
|
+
throw new ImageRenderUnavailableError("The renderer did not return a PNG.");
|
|
44
|
+
}
|
|
45
|
+
if (buffer.toString("ascii", 12, 16) !== "IHDR") {
|
|
46
|
+
throw new ImageRenderUnavailableError("The PNG does not start with an image header.");
|
|
47
|
+
}
|
|
48
|
+
if (buffer.toString("ascii", buffer.length - 8, buffer.length - 4) !== "IEND") {
|
|
49
|
+
throw new ImageRenderUnavailableError("The PNG is truncated.");
|
|
50
|
+
}
|
|
51
|
+
const widthPx = buffer.readUInt32BE(16);
|
|
52
|
+
const heightPx = buffer.readUInt32BE(20);
|
|
53
|
+
if (widthPx === 0 || heightPx === 0) {
|
|
54
|
+
throw new ImageRenderUnavailableError("The PNG has no area.");
|
|
55
|
+
}
|
|
56
|
+
// A silently ignored size option would otherwise reach the terminal as an unreadable image.
|
|
57
|
+
if (Math.abs(widthPx - expectedWidthPx) > 1) {
|
|
58
|
+
throw new ImageRenderUnavailableError(`The PNG is ${widthPx} pixels wide, not the ${expectedWidthPx} that were asked for.`);
|
|
59
|
+
}
|
|
60
|
+
return { png: bytes, widthPx, heightPx, systemFonts: false };
|
|
61
|
+
}
|
|
62
|
+
/** Enough resolution to scale down cleanly, never a pathological canvas. */
|
|
63
|
+
export function parseTargetWidth(naturalWidthPx, naturalHeightPx) {
|
|
64
|
+
if (!Number.isFinite(naturalWidthPx) ||
|
|
65
|
+
!Number.isFinite(naturalHeightPx) ||
|
|
66
|
+
naturalWidthPx < 1 ||
|
|
67
|
+
naturalHeightPx < 1) {
|
|
68
|
+
throw new ImageRenderUnavailableError(`The SVG reports a ${naturalWidthPx} by ${naturalHeightPx} canvas.`);
|
|
69
|
+
}
|
|
70
|
+
// The limits come last, so a tall diagram is drawn smaller rather than past the canvas bound.
|
|
71
|
+
const byHeight = (MAX_HEIGHT_PX / naturalHeightPx) * naturalWidthPx;
|
|
72
|
+
const wanted = Math.max(naturalWidthPx * SCALE, MIN_WIDTH_PX);
|
|
73
|
+
return Math.max(1, Math.round(Math.min(wanted, MAX_WIDTH_PX, byHeight)));
|
|
74
|
+
}
|
|
75
|
+
/** The store holds text, so an image travels as base64 behind the sizes it was drawn at. */
|
|
76
|
+
function formatCachedImage(image) {
|
|
77
|
+
const drawn = `${image.widthPx} ${image.heightPx} ${image.systemFonts ? 1 : 0}`;
|
|
78
|
+
return `${drawn}\n${Buffer.from(image.png).toString("base64")}`;
|
|
79
|
+
}
|
|
80
|
+
/** Parsed again on the way out, so a corrupt entry is drawn again rather than displayed. */
|
|
81
|
+
export function parseCachedImage(entry) {
|
|
82
|
+
const split = entry.indexOf("\n");
|
|
83
|
+
const [width, height, fonts] = entry.slice(0, Math.max(split, 0)).split(" ");
|
|
84
|
+
const widthPx = Number(width);
|
|
85
|
+
const heightPx = Number(height);
|
|
86
|
+
const sized = Number.isSafeInteger(widthPx) && widthPx > 0 && Number.isSafeInteger(heightPx) && heightPx > 0;
|
|
87
|
+
if (split === -1 || !sized || (fonts !== "0" && fonts !== "1")) {
|
|
88
|
+
throw new ImageRenderUnavailableError("The stored image does not say how it was drawn.");
|
|
89
|
+
}
|
|
90
|
+
const image = parseRenderedPng(Buffer.from(entry.slice(split + 1), "base64"), widthPx);
|
|
91
|
+
if (image.heightPx !== heightPx) {
|
|
92
|
+
throw new ImageRenderUnavailableError(`The stored image is ${image.heightPx} pixels tall, not the ${heightPx} it was drawn at.`);
|
|
93
|
+
}
|
|
94
|
+
return { ...image, systemFonts: fonts === "1" };
|
|
95
|
+
}
|
|
96
|
+
let loaded;
|
|
97
|
+
let installed;
|
|
98
|
+
/** A native binary per platform, loaded lazily so an unsupported one cannot break text diagrams. */
|
|
99
|
+
async function load() {
|
|
100
|
+
loaded ??= import("@resvg/resvg-js");
|
|
101
|
+
try {
|
|
102
|
+
return await loaded;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
loaded = undefined;
|
|
106
|
+
throw new ImageRenderUnavailableError(`The SVG rasterizer could not be loaded: ${error.message}`, { cause: error });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
export class ResvgRasterizer {
|
|
110
|
+
cache;
|
|
111
|
+
constructor(dependencies = {}) {
|
|
112
|
+
this.cache = dependencies.cache ?? new FileCache();
|
|
113
|
+
}
|
|
114
|
+
async rasterize(request) {
|
|
115
|
+
if (request.signal?.aborted === true) {
|
|
116
|
+
throw new CommandCancelledError("Drawing the diagram");
|
|
117
|
+
}
|
|
118
|
+
const key = await imageKey(request.svg);
|
|
119
|
+
const stored = key === undefined ? undefined : await this.cache.read(key);
|
|
120
|
+
if (stored !== undefined) {
|
|
121
|
+
try {
|
|
122
|
+
return parseCachedImage(stored);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// An entry this build cannot read is no better than a missing one.
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const image = await draw(request.svg);
|
|
129
|
+
if (key !== undefined) {
|
|
130
|
+
await this.cache.write(key, formatCachedImage(image));
|
|
131
|
+
}
|
|
132
|
+
return image;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/** Undefined when the version is unknown, which keeps that image out of the store. */
|
|
136
|
+
async function imageKey(svg) {
|
|
137
|
+
const version = await resvgVersion();
|
|
138
|
+
return version === undefined ? undefined : cacheKeyOf([...IMAGE_POLICY, version, svg]);
|
|
139
|
+
}
|
|
140
|
+
/** resvg draws differently between versions, so a stored image belongs to the one that drew it. */
|
|
141
|
+
async function resvgVersion() {
|
|
142
|
+
installed ??= (async () => {
|
|
143
|
+
try {
|
|
144
|
+
const manifest = createRequire(import.meta.url).resolve("@resvg/resvg-js/package.json");
|
|
145
|
+
const parsed = JSON.parse(await readFile(manifest, "utf8"));
|
|
146
|
+
const found = parsed.version;
|
|
147
|
+
return typeof found === "string" ? found : undefined;
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
})();
|
|
153
|
+
return installed;
|
|
154
|
+
}
|
|
155
|
+
async function draw(svg) {
|
|
156
|
+
const { Resvg } = await load();
|
|
157
|
+
const fonts = parseEmbeddedFonts(svg);
|
|
158
|
+
const missing = missingCodePoints(fonts, textCodePoints(svg));
|
|
159
|
+
const directory = await mkdtemp(join(tmpdir(), "pi-diagram-fonts-"));
|
|
160
|
+
try {
|
|
161
|
+
const fontFiles = await writeFonts(directory, fonts);
|
|
162
|
+
const font = {
|
|
163
|
+
fontFiles,
|
|
164
|
+
// Labels the diagram's own font cannot draw would otherwise be empty boxes.
|
|
165
|
+
loadSystemFonts: missing.length > 0,
|
|
166
|
+
defaultFontFamily: DEFAULT_FONT_FAMILY,
|
|
167
|
+
};
|
|
168
|
+
const probe = new Resvg(svg, { font });
|
|
169
|
+
const widthPx = parseTargetWidth(probe.width, probe.height);
|
|
170
|
+
const drawn = new Resvg(svg, { font, fitTo: { mode: "width", value: widthPx } });
|
|
171
|
+
const image = parseRenderedPng(drawn.render().asPng(), widthPx);
|
|
172
|
+
return { ...image, systemFonts: missing.length > 0 };
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
if (error instanceof ImageRenderUnavailableError || error instanceof CommandCancelledError) {
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
throw new ImageRenderUnavailableError(`The SVG could not be drawn as an image: ${error.message}`, { cause: error });
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
await rm(directory, { recursive: true, force: true });
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
async function writeFonts(directory, fonts) {
|
|
185
|
+
const paths = [];
|
|
186
|
+
for (const [index, font] of fonts.entries()) {
|
|
187
|
+
const path = join(directory, `face-${index}.ttf`);
|
|
188
|
+
await writeFile(path, font.bytes, { mode: 0o600 });
|
|
189
|
+
paths.push(path);
|
|
190
|
+
}
|
|
191
|
+
return paths;
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=raster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raster.js","sourceRoot":"","sources":["../src/raster.ts"],"names":[],"mappings":"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"}
|
package/dist/render.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type WrittenArtifact } from "./artifacts.js";
|
|
2
|
+
import { type Diagnostic } from "./d2/diagnostics.js";
|
|
3
|
+
import { type ProfileName } from "./d2/profiles.js";
|
|
4
|
+
import { type D2Renderer, type SupportedD2Version } from "./d2/runner.js";
|
|
5
|
+
import { type SafeTitle } from "./normalize.js";
|
|
6
|
+
import { type SvgRasterizer } from "./raster.js";
|
|
7
|
+
/**
|
|
8
|
+
* D2's text renderer is beta, so a diagram it cannot draw has to fail in a way the user can
|
|
9
|
+
* understand rather than turning into broken box art or a different graph.
|
|
10
|
+
*/
|
|
11
|
+
/** How the diagram is drawn as text. */
|
|
12
|
+
export type Representation = "unicode" | "ascii" | "source";
|
|
13
|
+
export interface DiagramRequest {
|
|
14
|
+
readonly source: unknown;
|
|
15
|
+
readonly title?: unknown;
|
|
16
|
+
readonly profile?: unknown;
|
|
17
|
+
readonly render?: unknown;
|
|
18
|
+
readonly formats?: unknown;
|
|
19
|
+
readonly save?: unknown;
|
|
20
|
+
readonly cwd?: unknown;
|
|
21
|
+
/** Whether the host can display an image at all. Only `true` enables the raster path. */
|
|
22
|
+
readonly images?: unknown;
|
|
23
|
+
readonly signal?: AbortSignal | undefined;
|
|
24
|
+
}
|
|
25
|
+
interface DiagramImage {
|
|
26
|
+
/** Absolute path in the temp store. */
|
|
27
|
+
readonly path: string;
|
|
28
|
+
readonly widthPx: number;
|
|
29
|
+
readonly heightPx: number;
|
|
30
|
+
}
|
|
31
|
+
export interface DiagramRendering {
|
|
32
|
+
readonly profile: ProfileName;
|
|
33
|
+
readonly renderedAs: Representation;
|
|
34
|
+
readonly text: string;
|
|
35
|
+
/** The D2 source that was drawn, for the expanded view. */
|
|
36
|
+
readonly source: string;
|
|
37
|
+
/** Why the text came out the way it did. Empty when nothing went wrong. */
|
|
38
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
39
|
+
readonly image: DiagramImage | undefined;
|
|
40
|
+
readonly title: SafeTitle | undefined;
|
|
41
|
+
readonly sourceHash: string;
|
|
42
|
+
readonly lineCount: number;
|
|
43
|
+
readonly widthCells: number;
|
|
44
|
+
readonly d2Version: SupportedD2Version | undefined;
|
|
45
|
+
readonly saved: readonly WrittenArtifact[];
|
|
46
|
+
readonly notes: readonly string[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* `image` and `auto` choose the text that goes with the image. Whether a terminal can show one is
|
|
50
|
+
* only decided when the result is displayed, so both are always prepared.
|
|
51
|
+
*/
|
|
52
|
+
export declare function parseRepresentation(requested: unknown): Representation;
|
|
53
|
+
export declare function renderDiagram(request: DiagramRequest, renderer: D2Renderer, rasterizer?: SvgRasterizer): Promise<DiagramRendering>;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,UAAU,EAAsB,MAAM,qBAAqB,CAAC;AAE1E,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,kBAAkB,EAExB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAErB;;;GAGG;AAEH,wCAAwC;AACxC,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAO5D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,yFAAyF;IACzF,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAC3C;AAED,UAAU,YAAY;IACpB,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,SAAS,UAAU,EAAE,CAAC;IAC5C,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACnD,QAAQ,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAC3C,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,OAAO,GAAG,cAAc,CAoBtE;AAUD,wBAAsB,aAAa,CACjC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,UAAU,EACpB,UAAU,GAAE,aAAqC,GAChD,OAAO,CAAC,gBAAgB,CAAC,CAiH3B"}
|