@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.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +240 -0
  3. package/dist/artifacts.d.ts +59 -0
  4. package/dist/artifacts.d.ts.map +1 -0
  5. package/dist/artifacts.js +274 -0
  6. package/dist/artifacts.js.map +1 -0
  7. package/dist/cache.d.ts +43 -0
  8. package/dist/cache.d.ts.map +1 -0
  9. package/dist/cache.js +0 -0
  10. package/dist/cache.js.map +1 -0
  11. package/dist/d2/diagnostics.d.ts +25 -0
  12. package/dist/d2/diagnostics.d.ts.map +1 -0
  13. package/dist/d2/diagnostics.js +77 -0
  14. package/dist/d2/diagnostics.js.map +1 -0
  15. package/dist/d2/fonts.d.ts +23 -0
  16. package/dist/d2/fonts.d.ts.map +1 -0
  17. package/dist/d2/fonts.js +255 -0
  18. package/dist/d2/fonts.js.map +1 -0
  19. package/dist/d2/preflight.d.ts +20 -0
  20. package/dist/d2/preflight.d.ts.map +1 -0
  21. package/dist/d2/preflight.js +217 -0
  22. package/dist/d2/preflight.js.map +1 -0
  23. package/dist/d2/profiles.d.ts +34 -0
  24. package/dist/d2/profiles.d.ts.map +1 -0
  25. package/dist/d2/profiles.js +118 -0
  26. package/dist/d2/profiles.js.map +1 -0
  27. package/dist/d2/runner.d.ts +95 -0
  28. package/dist/d2/runner.d.ts.map +1 -0
  29. package/dist/d2/runner.js +350 -0
  30. package/dist/d2/runner.js.map +1 -0
  31. package/dist/display.d.ts +48 -0
  32. package/dist/display.d.ts.map +1 -0
  33. package/dist/display.js +120 -0
  34. package/dist/display.js.map +1 -0
  35. package/dist/index.d.ts +3 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +5 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/normalize.d.ts +23 -0
  40. package/dist/normalize.d.ts.map +1 -0
  41. package/dist/normalize.js +83 -0
  42. package/dist/normalize.js.map +1 -0
  43. package/dist/process.d.ts +38 -0
  44. package/dist/process.d.ts.map +1 -0
  45. package/dist/process.js +87 -0
  46. package/dist/process.js.map +1 -0
  47. package/dist/raster.d.ts +40 -0
  48. package/dist/raster.d.ts.map +1 -0
  49. package/dist/raster.js +193 -0
  50. package/dist/raster.js.map +1 -0
  51. package/dist/render.d.ts +55 -0
  52. package/dist/render.d.ts.map +1 -0
  53. package/dist/render.js +229 -0
  54. package/dist/render.js.map +1 -0
  55. package/dist/tools.d.ts +58 -0
  56. package/dist/tools.d.ts.map +1 -0
  57. package/dist/tools.js +284 -0
  58. package/dist/tools.js.map +1 -0
  59. package/package.json +101 -0
  60. package/src/artifacts.ts +418 -0
  61. package/src/cache.ts +0 -0
  62. package/src/d2/diagnostics.ts +114 -0
  63. package/src/d2/fonts.ts +289 -0
  64. package/src/d2/preflight.ts +270 -0
  65. package/src/d2/profiles.ts +157 -0
  66. package/src/d2/runner.ts +513 -0
  67. package/src/display.ts +201 -0
  68. package/src/index.ts +5 -0
  69. package/src/normalize.ts +119 -0
  70. package/src/process.ts +134 -0
  71. package/src/raster.ts +258 -0
  72. package/src/render.ts +338 -0
  73. package/src/tools.ts +455 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * One vocabulary for every refusal, including D2's own errors, so a policy rejection and a
3
+ * syntax error read the same way and the model has one thing to correct.
4
+ */
5
+ export type DiagnosticCode = "D2_SOURCE" | "D2_TOO_LARGE" | "D2_TIMEOUT" | "D2_IMPORT" | "D2_ICON" | "D2_LINK" | "D2_IMAGE_SHAPE" | "D2_UNKNOWN_SHAPE" | "D2_BLOCK_STRING" | "D2_CONFIG" | "D2_UNTERMINATED" | "D2_SYNTAX" | "D2_RENDER";
6
+ export interface Diagnostic {
7
+ readonly code: DiagnosticCode;
8
+ readonly message: string;
9
+ readonly line?: number;
10
+ readonly column?: number;
11
+ readonly hint?: string;
12
+ }
13
+ /** A refusal the model can fix by editing its source. What it cannot fix gets another type. */
14
+ export declare class DiagramSourceError extends Error {
15
+ readonly diagnostics: readonly Diagnostic[];
16
+ constructor(summary: string, diagnostics: readonly Diagnostic[]);
17
+ }
18
+ /** One line, indented, the way it reads inside a refusal message. */
19
+ export declare function formatDiagnostic(diagnostic: Diagnostic): string;
20
+ /**
21
+ * `secretPaths` are absolute paths from the isolated render directory. D2 puts them in render
22
+ * errors, and they must not reach the model or the transcript.
23
+ */
24
+ export declare function parseD2Diagnostics(stderr: string, code: DiagnosticCode, secretPaths: readonly string[]): readonly Diagnostic[];
25
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/d2/diagnostics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,MAAM,cAAc,GACtB,WAAW,GACX,cAAc,GACd,YAAY,GACZ,WAAW,GACX,SAAS,GACT,SAAS,GACT,gBAAgB,GAChB,kBAAkB,GAClB,iBAAiB,GACjB,WAAW,GACX,iBAAiB,GACjB,WAAW,GACX,WAAW,CAAC;AAEhB,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,+FAA+F;AAC/F,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,WAAW,EAAE,SAAS,UAAU,EAAE,CAAC;IAE5C,YAAY,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,UAAU,EAAE,EAK9D;CACF;AAMD,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAS/D;AAOD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,cAAc,EACpB,WAAW,EAAE,SAAS,MAAM,EAAE,GAC7B,SAAS,UAAU,EAAE,CAwBvB"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * One vocabulary for every refusal, including D2's own errors, so a policy rejection and a
3
+ * syntax error read the same way and the model has one thing to correct.
4
+ */
5
+ const MAX_DIAGNOSTICS = 10;
6
+ const MAX_MESSAGE_LENGTH = 200;
7
+ /** A refusal the model can fix by editing its source. What it cannot fix gets another type. */
8
+ export class DiagramSourceError extends Error {
9
+ diagnostics;
10
+ constructor(summary, diagnostics) {
11
+ const capped = diagnostics.slice(0, MAX_DIAGNOSTICS);
12
+ super(capped.length > 0 ? `${summary}\n${formatDiagnostics(capped)}` : summary);
13
+ this.name = "DiagramSourceError";
14
+ this.diagnostics = capped;
15
+ }
16
+ }
17
+ function formatDiagnostics(diagnostics) {
18
+ return diagnostics.map(formatDiagnostic).join("\n");
19
+ }
20
+ /** One line, indented, the way it reads inside a refusal message. */
21
+ export function formatDiagnostic(diagnostic) {
22
+ const at = diagnostic.line === undefined
23
+ ? ""
24
+ : diagnostic.column === undefined
25
+ ? `line ${diagnostic.line}: `
26
+ : `line ${diagnostic.line}, column ${diagnostic.column}: `;
27
+ const hint = diagnostic.hint === undefined ? "" : ` ${diagnostic.hint}`;
28
+ return ` ${at}${diagnostic.message}${hint} [${diagnostic.code}]`;
29
+ }
30
+ /** Prefixes D2 adds that do not help the model fix its source. */
31
+ const NOISE_PREFIXES = [/^err:\s*/u, /^failed to compile [^:]*:\s*/u, /^github\.com\/\S+:\s*/u];
32
+ const LOCATION = /(\d+):(\d+):\s*(.+)$/u;
33
+ /**
34
+ * `secretPaths` are absolute paths from the isolated render directory. D2 puts them in render
35
+ * errors, and they must not reach the model or the transcript.
36
+ */
37
+ export function parseD2Diagnostics(stderr, code, secretPaths) {
38
+ const diagnostics = [];
39
+ for (const rawLine of stderr.split("\n")) {
40
+ if (diagnostics.length >= MAX_DIAGNOSTICS) {
41
+ break;
42
+ }
43
+ const scrubbed = scrub(rawLine, secretPaths);
44
+ if (scrubbed.length === 0) {
45
+ continue;
46
+ }
47
+ const location = LOCATION.exec(scrubbed);
48
+ if (location) {
49
+ const [, line, column, message] = location;
50
+ diagnostics.push({
51
+ code,
52
+ message: cap(message ?? scrubbed),
53
+ line: Number(line),
54
+ column: Number(column),
55
+ });
56
+ continue;
57
+ }
58
+ diagnostics.push({ code, message: cap(scrubbed) });
59
+ }
60
+ return diagnostics;
61
+ }
62
+ function scrub(line, secretPaths) {
63
+ let text = line.trim();
64
+ for (const prefix of NOISE_PREFIXES) {
65
+ text = text.replace(prefix, "").trim();
66
+ }
67
+ for (const secret of secretPaths) {
68
+ // Strip the directory before the file name so `<dir>/input.d2:2:6:` leaves `2:6:`.
69
+ text = text.split(`${secret}/`).join("").split(secret).join("");
70
+ }
71
+ return text.replace(/^input\.d2:/u, "").trim();
72
+ }
73
+ function cap(message) {
74
+ const text = message.trim();
75
+ return text.length > MAX_MESSAGE_LENGTH ? `${text.slice(0, MAX_MESSAGE_LENGTH - 1)}...` : text;
76
+ }
77
+ //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/d2/diagnostics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { RenderedSvg } from "./runner.js";
2
+ declare const sfntBrand: unique symbol;
3
+ /** A font rebuilt from a WOFF container, with a table directory this module checked. */
4
+ type SfntFont = Uint8Array & {
5
+ readonly [sfntBrand]: true;
6
+ };
7
+ export interface EmbeddedFont {
8
+ readonly family: string;
9
+ readonly bytes: SfntFont;
10
+ /** Code points the face can draw, or `undefined` when its cmap is not one this module reads. */
11
+ readonly coverage: ReadonlySet<number> | undefined;
12
+ }
13
+ /**
14
+ * Faces that could be rebuilt and understood. One that could not is left out rather than guessed
15
+ * at, and reported through its missing coverage instead.
16
+ */
17
+ export declare function parseEmbeddedFonts(svg: RenderedSvg): readonly EmbeddedFont[];
18
+ /** Code points that have to be drawable, taken from the SVG's own text elements. */
19
+ export declare function textCodePoints(svg: RenderedSvg): ReadonlySet<number>;
20
+ /** Code points no embedded face can draw. */
21
+ export declare function missingCodePoints(fonts: readonly EmbeddedFont[], needed: ReadonlySet<number>): readonly number[];
22
+ export {};
23
+ //# sourceMappingURL=fonts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../../src/d2/fonts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAmB/C,OAAO,CAAC,MAAM,SAAS,EAAE,OAAO,MAAM,CAAC;AAEvC,wFAAwF;AACxF,KAAK,QAAQ,GAAG,UAAU,GAAG;IAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAE5D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,gGAAgG;IAChG,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;CACpD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,WAAW,GAAG,SAAS,YAAY,EAAE,CAuB5E;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,CAgBpE;AAED,6CAA6C;AAC7C,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,GAC1B,SAAS,MAAM,EAAE,CASnB"}
@@ -0,0 +1,255 @@
1
+ import { inflateSync } from "node:zlib";
2
+ /**
3
+ * Recovers the fonts D2 embeds in its SVG. D2 sizes every box around the label it measured in
4
+ * those faces, so drawing the image with any other font makes labels overflow.
5
+ */
6
+ const MAX_FACES = 8;
7
+ const MAX_FACE_BYTES = 4 * 1024 * 1024;
8
+ const MAX_TABLES = 64;
9
+ /** A subset face covers a handful of glyphs; this only stops a malformed cmap looping. */
10
+ const MAX_COVERAGE = 65_536;
11
+ const FACE_BLOCK = /@font-face\s*\{([^}]*)\}/gu;
12
+ const FACE_FAMILY = /font-family:\s*([\w-]+)/u;
13
+ const FACE_WOFF = /url\(\s*["']?data:application\/font-woff;base64,([A-Za-z0-9+/=]+)/u;
14
+ const TEXT_ELEMENT = /<text\b[^>]*>([\s\S]*?)<\/text>/giu;
15
+ const INNER_TAG = /<[^>]*>/gu;
16
+ /**
17
+ * Faces that could be rebuilt and understood. One that could not is left out rather than guessed
18
+ * at, and reported through its missing coverage instead.
19
+ */
20
+ export function parseEmbeddedFonts(svg) {
21
+ const fonts = [];
22
+ for (const block of svg.matchAll(FACE_BLOCK)) {
23
+ if (fonts.length >= MAX_FACES) {
24
+ break;
25
+ }
26
+ const declarations = block[1];
27
+ if (declarations === undefined) {
28
+ continue;
29
+ }
30
+ const family = FACE_FAMILY.exec(declarations)?.[1];
31
+ const encoded = FACE_WOFF.exec(declarations)?.[1];
32
+ if (family === undefined || encoded === undefined || encoded.length > MAX_FACE_BYTES) {
33
+ continue;
34
+ }
35
+ try {
36
+ const bytes = rebuild(Buffer.from(encoded, "base64"));
37
+ fonts.push({ family, bytes, coverage: readCoverage(bytes) });
38
+ }
39
+ catch {
40
+ // A face that cannot be rebuilt is left out rather than reported.
41
+ }
42
+ }
43
+ return fonts;
44
+ }
45
+ /** Code points that have to be drawable, taken from the SVG's own text elements. */
46
+ export function textCodePoints(svg) {
47
+ const needed = new Set();
48
+ for (const element of svg.matchAll(TEXT_ELEMENT)) {
49
+ const content = element[1];
50
+ if (content === undefined) {
51
+ continue;
52
+ }
53
+ for (const char of decodeEntities(content.replace(INNER_TAG, ""))) {
54
+ const code = char.codePointAt(0);
55
+ // Whitespace needs no glyph, and a missing space would report a false gap on every label.
56
+ if (code !== undefined && !/\s/u.test(char)) {
57
+ needed.add(code);
58
+ }
59
+ }
60
+ }
61
+ return needed;
62
+ }
63
+ /** Code points no embedded face can draw. */
64
+ export function missingCodePoints(fonts, needed) {
65
+ if (fonts.length === 0) {
66
+ return [...needed];
67
+ }
68
+ if (fonts.some((font) => font.coverage === undefined)) {
69
+ // One unreadable cmap makes the whole answer a guess, so nothing is claimed to be missing.
70
+ return [];
71
+ }
72
+ return [...needed].filter((code) => !fonts.some((font) => font.coverage?.has(code) === true));
73
+ }
74
+ function decodeEntities(text) {
75
+ return text.replace(/&(#x[0-9a-f]+|#\d+|[a-z]+);/giu, (entity, body) => {
76
+ const named = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'" };
77
+ if (body.startsWith("#")) {
78
+ const code = Number.parseInt(body.slice(body.startsWith("#x") || body.startsWith("#X") ? 2 : 1), body.startsWith("#x") || body.startsWith("#X") ? 16 : 10);
79
+ return Number.isSafeInteger(code) && code > 0 && code <= 0x10ffff
80
+ ? String.fromCodePoint(code)
81
+ : entity;
82
+ }
83
+ return named[body.toLowerCase()] ?? entity;
84
+ });
85
+ }
86
+ /** Every offset is checked against the buffer: the container is only as trustworthy as its SVG. */
87
+ function rebuild(woff) {
88
+ if (woff.length < 44 || woff.toString("ascii", 0, 4) !== "wOFF") {
89
+ throw new Error("Not a WOFF container.");
90
+ }
91
+ const numTables = woff.readUInt16BE(12);
92
+ if (numTables === 0 || numTables > MAX_TABLES || 44 + numTables * 20 > woff.length) {
93
+ throw new Error(`WOFF declares ${numTables} tables.`);
94
+ }
95
+ const tables = [];
96
+ let decompressed = 0;
97
+ for (let index = 0; index < numTables; index += 1) {
98
+ const record = 44 + index * 20;
99
+ const offset = woff.readUInt32BE(record + 4);
100
+ const compressed = woff.readUInt32BE(record + 8);
101
+ const original = woff.readUInt32BE(record + 12);
102
+ decompressed += original;
103
+ if (offset + compressed > woff.length || original > MAX_FACE_BYTES) {
104
+ throw new Error("WOFF table lies outside the container.");
105
+ }
106
+ if (decompressed > MAX_FACE_BYTES) {
107
+ throw new Error("WOFF tables decompress past the size limit.");
108
+ }
109
+ const raw = woff.subarray(offset, offset + compressed);
110
+ const data = compressed === original ? raw : inflateSync(raw);
111
+ if (data.length !== original) {
112
+ throw new Error("WOFF table does not decompress to its declared length.");
113
+ }
114
+ tables.push({
115
+ tag: woff.toString("ascii", record, record + 4),
116
+ checksum: woff.readUInt32BE(record + 16),
117
+ data,
118
+ });
119
+ }
120
+ tables.sort((left, right) => (left.tag < right.tag ? -1 : 1));
121
+ const header = Buffer.alloc(12 + numTables * 16);
122
+ header.writeUInt32BE(woff.readUInt32BE(4), 0);
123
+ header.writeUInt16BE(numTables, 4);
124
+ const highest = 2 ** Math.floor(Math.log2(numTables));
125
+ header.writeUInt16BE(highest * 16, 6);
126
+ header.writeUInt16BE(Math.log2(highest), 8);
127
+ header.writeUInt16BE(numTables * 16 - highest * 16, 10);
128
+ let position = header.length;
129
+ const body = [];
130
+ tables.forEach((table, index) => {
131
+ const record = 12 + index * 16;
132
+ header.write(table.tag, record, 4, "ascii");
133
+ header.writeUInt32BE(table.checksum, record + 4);
134
+ header.writeUInt32BE(position, record + 8);
135
+ header.writeUInt32BE(table.data.length, record + 12);
136
+ const padding = (4 - (table.data.length % 4)) % 4;
137
+ body.push(table.data, Buffer.alloc(padding));
138
+ position += table.data.length + padding;
139
+ });
140
+ return Buffer.concat([header, ...body]);
141
+ }
142
+ /** `undefined` when the face carries no cmap subtable in a format this module reads. */
143
+ function readCoverage(font) {
144
+ const view = Buffer.from(font.buffer, font.byteOffset, font.byteLength);
145
+ const cmap = findTable(view, "cmap");
146
+ if (cmap === undefined || cmap + 4 > view.length) {
147
+ return undefined;
148
+ }
149
+ const subtables = view.readUInt16BE(cmap + 2);
150
+ let best;
151
+ for (let index = 0; index < subtables; index += 1) {
152
+ const record = cmap + 4 + index * 8;
153
+ if (record + 8 > view.length) {
154
+ return undefined;
155
+ }
156
+ const offset = cmap + view.readUInt32BE(record + 4);
157
+ if (offset + 2 > view.length) {
158
+ return undefined;
159
+ }
160
+ const format = view.readUInt16BE(offset);
161
+ // Format 12 reaches beyond the BMP, so it wins when a face offers both.
162
+ if (format === 12 || (format === 4 && best === undefined)) {
163
+ best = { format, offset };
164
+ }
165
+ }
166
+ if (best === undefined) {
167
+ return undefined;
168
+ }
169
+ return best.format === 12 ? readFormat12(view, best.offset) : readFormat4(view, best.offset);
170
+ }
171
+ function findTable(font, tag) {
172
+ if (font.length < 12) {
173
+ return undefined;
174
+ }
175
+ const numTables = font.readUInt16BE(4);
176
+ if (12 + numTables * 16 > font.length) {
177
+ return undefined;
178
+ }
179
+ for (let index = 0; index < numTables; index += 1) {
180
+ const record = 12 + index * 16;
181
+ if (font.toString("ascii", record, record + 4) === tag) {
182
+ return font.readUInt32BE(record + 8);
183
+ }
184
+ }
185
+ return undefined;
186
+ }
187
+ /** Windows BMP segment mapping, which is what D2's subset faces carry. */
188
+ function readFormat4(font, offset) {
189
+ if (offset + 14 > font.length) {
190
+ return undefined;
191
+ }
192
+ const segments = font.readUInt16BE(offset + 6) / 2;
193
+ const endCodes = offset + 14;
194
+ const startCodes = endCodes + segments * 2 + 2;
195
+ const deltas = startCodes + segments * 2;
196
+ const rangeOffsets = deltas + segments * 2;
197
+ if (!Number.isSafeInteger(segments) || rangeOffsets + segments * 2 > font.length) {
198
+ return undefined;
199
+ }
200
+ const covered = new Set();
201
+ for (let segment = 0; segment < segments; segment += 1) {
202
+ const end = font.readUInt16BE(endCodes + segment * 2);
203
+ const start = font.readUInt16BE(startCodes + segment * 2);
204
+ const delta = font.readInt16BE(deltas + segment * 2);
205
+ const rangeOffset = font.readUInt16BE(rangeOffsets + segment * 2);
206
+ if (start > end || covered.size + (end - start) > MAX_COVERAGE) {
207
+ return undefined;
208
+ }
209
+ for (let code = start; code <= end && code !== 0xffff; code += 1) {
210
+ let glyph;
211
+ if (rangeOffset === 0) {
212
+ glyph = (code + delta) & 0xffff;
213
+ }
214
+ else {
215
+ const at = rangeOffsets + segment * 2 + rangeOffset + (code - start) * 2;
216
+ if (at + 2 > font.length) {
217
+ return undefined;
218
+ }
219
+ const found = font.readUInt16BE(at);
220
+ glyph = found === 0 ? 0 : (found + delta) & 0xffff;
221
+ }
222
+ if (glyph !== 0) {
223
+ covered.add(code);
224
+ }
225
+ }
226
+ }
227
+ return covered;
228
+ }
229
+ function readFormat12(font, offset) {
230
+ if (offset + 16 > font.length) {
231
+ return undefined;
232
+ }
233
+ const groups = font.readUInt32BE(offset + 12);
234
+ if (offset + 16 + groups * 12 > font.length) {
235
+ return undefined;
236
+ }
237
+ const covered = new Set();
238
+ for (let index = 0; index < groups; index += 1) {
239
+ const record = offset + 16 + index * 12;
240
+ const start = font.readUInt32BE(record);
241
+ const end = font.readUInt32BE(record + 4);
242
+ const glyph = font.readUInt32BE(record + 8);
243
+ if (start > end || end > 0x10ffff || covered.size + (end - start) > MAX_COVERAGE) {
244
+ return undefined;
245
+ }
246
+ if (glyph === 0) {
247
+ continue;
248
+ }
249
+ for (let code = start; code <= end; code += 1) {
250
+ covered.add(code);
251
+ }
252
+ }
253
+ return covered;
254
+ }
255
+ //# sourceMappingURL=fonts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fonts.js","sourceRoot":"","sources":["../../src/d2/fonts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { NormalizedD2Source } from "../normalize.js";
2
+ import { type Diagnostic } from "./diagnostics.js";
3
+ /**
4
+ * The safe D2 subset. `@` imports read files, `icon` loads local paths and remote URLs, and
5
+ * source can override the layout engine. A relative import was verified against d2 0.8.1 to
6
+ * read a sibling file and draw its contents, so this is a live file-read channel.
7
+ *
8
+ * Anything ambiguous is refused rather than guessed at. See docs/safety.md for the full policy.
9
+ */
10
+ declare const safeSourceBrand: unique symbol;
11
+ /** The renderer accepts nothing else, so unchecked source cannot reach D2. */
12
+ export type SafeD2Source = NormalizedD2Source & {
13
+ readonly [safeSourceBrand]: true;
14
+ };
15
+ /** Throws with one diagnostic per problem found, rather than at the first. */
16
+ export declare function parseSafeSource(source: NormalizedD2Source): SafeD2Source;
17
+ /** Exported so tests can read the diagnostics without catching the error. */
18
+ export declare function inspect(source: NormalizedD2Source): readonly Diagnostic[];
19
+ export {};
20
+ //# sourceMappingURL=preflight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../../src/d2/preflight.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,KAAK,UAAU,EAAsB,MAAM,kBAAkB,CAAC;AAEvE;;;;;;GAMG;AAEH,OAAO,CAAC,MAAM,eAAe,EAAE,OAAO,MAAM,CAAC;AAE7C,8EAA8E;AAC9E,MAAM,MAAM,YAAY,GAAG,kBAAkB,GAAG;IAAE,QAAQ,CAAC,CAAC,eAAe,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAwCrF,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CASxE;AAED,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,MAAM,EAAE,kBAAkB,GAAG,SAAS,UAAU,EAAE,CASzE"}