@danielsimonjr/sciengjs 0.0.0-stage → 0.1.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 +182 -3
- package/THIRD_PARTY_NOTICES.md +57 -0
- package/assets/fonts/LiberationSerif-Regular.LICENSE.txt +102 -0
- package/assets/fonts/LiberationSerif-Regular.ttf +0 -0
- package/assets/licenses/EPL-2.0.txt +278 -0
- package/assets/licenses/MPL-2.0.txt +374 -0
- package/dist/config.d.ts +28 -0
- package/dist/config.js +186 -0
- package/dist/config.js.map +1 -0
- package/dist/core.d.ts +10 -0
- package/dist/core.js +85 -0
- package/dist/core.js.map +1 -0
- package/dist/errors.d.ts +18 -0
- package/dist/errors.js +25 -0
- package/dist/errors.js.map +1 -0
- package/dist/graph/backend-png.d.ts +5 -0
- package/dist/graph/backend-png.js +57 -0
- package/dist/graph/backend-png.js.map +1 -0
- package/dist/graph/backend-svg.d.ts +3 -0
- package/dist/graph/backend-svg.js +12 -0
- package/dist/graph/backend-svg.js.map +1 -0
- package/dist/graph/dot.d.ts +12 -0
- package/dist/graph/dot.js +48 -0
- package/dist/graph/dot.js.map +1 -0
- package/dist/graph/image.d.ts +23 -0
- package/dist/graph/image.js +292 -0
- package/dist/graph/image.js.map +1 -0
- package/dist/graph/index.d.ts +3 -0
- package/dist/graph/index.js +3 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/pairs.d.ts +11 -0
- package/dist/pairs.js +43 -0
- package/dist/pairs.js.map +1 -0
- package/dist/raster/index.d.ts +18 -0
- package/dist/raster/index.js +77 -0
- package/dist/raster/index.js.map +1 -0
- package/dist/raster/warnings.d.ts +12 -0
- package/dist/raster/warnings.js +175 -0
- package/dist/raster/warnings.js.map +1 -0
- package/dist/registry.d.ts +13 -0
- package/dist/registry.js +17 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +48 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/dist/worker/entry.d.ts +1 -0
- package/dist/worker/entry.js +38 -0
- package/dist/worker/entry.js.map +1 -0
- package/dist/worker/protocol.d.ts +37 -0
- package/dist/worker/protocol.js +2 -0
- package/dist/worker/protocol.js.map +1 -0
- package/dist/worker/run.d.ts +30 -0
- package/dist/worker/run.js +90 -0
- package/dist/worker/run.js.map +1 -0
- package/package.json +71 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/graph/index.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SciengConfig } from "./config.ts";
|
|
2
|
+
import type { Capability, RenderRequest, RenderResult } from "./types.ts";
|
|
3
|
+
export { RenderError, RENDER_ERROR_CODES, type RenderErrorCode } from "./errors.ts";
|
|
4
|
+
export { loadConfig, type SciengConfig, type NetworkPolicy } from "./config.ts";
|
|
5
|
+
export { INPUT_TYPES, OUTPUT_FORMATS, type InputType, type OutputFormat, type RenderOptions, type RenderRequest, type RenderResult, type RenderAsset, type Capability, } from "./types.ts";
|
|
6
|
+
/** Renders one source to the requested format. Rejects with a RenderError. Never falls back to another format. */
|
|
7
|
+
export declare function render(req: RenderRequest, config?: Partial<SciengConfig>): Promise<RenderResult>;
|
|
8
|
+
/** Reports each supported pair, its stage and whether that stage is ready on this machine. */
|
|
9
|
+
export declare function capabilities(config?: Partial<SciengConfig>): Promise<Capability[]>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { capabilitiesWithRegistry, renderWithRegistry } from "./core.js";
|
|
2
|
+
import { DEFAULT_REGISTRY } from "./registry.js";
|
|
3
|
+
export { RenderError, RENDER_ERROR_CODES } from "./errors.js";
|
|
4
|
+
export { loadConfig } from "./config.js";
|
|
5
|
+
export { INPUT_TYPES, OUTPUT_FORMATS, } from "./types.js";
|
|
6
|
+
/** Renders one source to the requested format. Rejects with a RenderError. Never falls back to another format. */
|
|
7
|
+
export function render(req, config) {
|
|
8
|
+
return renderWithRegistry(req, config ?? {}, DEFAULT_REGISTRY);
|
|
9
|
+
}
|
|
10
|
+
/** Reports each supported pair, its stage and whether that stage is ready on this machine. */
|
|
11
|
+
export function capabilities(config) {
|
|
12
|
+
return capabilitiesWithRegistry(config ?? {}, DEFAULT_REGISTRY);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAIjD,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAwB,MAAM,aAAa,CAAC;AACpF,OAAO,EAAE,UAAU,EAAyC,MAAM,aAAa,CAAC;AAChF,OAAO,EACL,WAAW,EACX,cAAc,GAQf,MAAM,YAAY,CAAC;AAEpB,kHAAkH;AAClH,MAAM,UAAU,MAAM,CAAC,GAAkB,EAAE,MAA8B;IACvE,OAAO,kBAAkB,CAAC,GAAG,EAAE,MAAM,IAAI,EAAE,EAAE,gBAAgB,CAAC,CAAC;AACjE,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,YAAY,CAAC,MAA8B;IACzD,OAAO,wBAAwB,CAAC,MAAM,IAAI,EAAE,EAAE,gBAAgB,CAAC,CAAC;AAClE,CAAC"}
|
package/dist/pairs.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { InputType, OutputFormat } from "./types.ts";
|
|
2
|
+
/** One (input, output) pair of the design, with the stage that renders it. */
|
|
3
|
+
export interface PairSpec {
|
|
4
|
+
type: InputType;
|
|
5
|
+
format: OutputFormat;
|
|
6
|
+
stage: string;
|
|
7
|
+
}
|
|
8
|
+
/** The pairs of the design section "Scope". A pair missing here is unsupported. */
|
|
9
|
+
export declare const PAIRS: readonly PairSpec[];
|
|
10
|
+
/** Returns the pair of the table, or undefined when the design does not list it. */
|
|
11
|
+
export declare function findPair(type: InputType, format: OutputFormat): PairSpec | undefined;
|
package/dist/pairs.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** The pairs of the design section "Scope". A pair missing here is unsupported. */
|
|
2
|
+
export const PAIRS = [
|
|
3
|
+
{ type: "dot", format: "svg", stage: "graph" },
|
|
4
|
+
{ type: "dot", format: "png", stage: "graph" },
|
|
5
|
+
{ type: "dot", format: "pdf", stage: "browser" },
|
|
6
|
+
{ type: "mermaid", format: "svg", stage: "browser" },
|
|
7
|
+
{ type: "mermaid", format: "png", stage: "browser" },
|
|
8
|
+
{ type: "mermaid", format: "pdf", stage: "browser" },
|
|
9
|
+
{ type: "math", format: "svg", stage: "math" },
|
|
10
|
+
{ type: "math", format: "png", stage: "math" },
|
|
11
|
+
{ type: "math", format: "pdf", stage: "math" },
|
|
12
|
+
{ type: "tikz", format: "svg", stage: "tex" },
|
|
13
|
+
{ type: "tikz", format: "png", stage: "tex" },
|
|
14
|
+
{ type: "tikz", format: "pdf", stage: "tex" },
|
|
15
|
+
{ type: "plot", format: "svg", stage: "plot" },
|
|
16
|
+
{ type: "plot", format: "png", stage: "plot" },
|
|
17
|
+
{ type: "plot", format: "pdf", stage: "plot" },
|
|
18
|
+
{ type: "plot", format: "html", stage: "plot" },
|
|
19
|
+
{ type: "sysml", format: "svg", stage: "graph" },
|
|
20
|
+
{ type: "sysml", format: "png", stage: "graph" },
|
|
21
|
+
{ type: "sysml", format: "pdf", stage: "graph" },
|
|
22
|
+
{ type: "step", format: "html", stage: "mesh" },
|
|
23
|
+
{ type: "step", format: "png", stage: "browser" },
|
|
24
|
+
{ type: "step", format: "glb", stage: "mesh" },
|
|
25
|
+
{ type: "iges", format: "html", stage: "mesh" },
|
|
26
|
+
{ type: "iges", format: "png", stage: "browser" },
|
|
27
|
+
{ type: "iges", format: "glb", stage: "mesh" },
|
|
28
|
+
{ type: "brep", format: "html", stage: "mesh" },
|
|
29
|
+
{ type: "brep", format: "png", stage: "browser" },
|
|
30
|
+
{ type: "brep", format: "glb", stage: "mesh" },
|
|
31
|
+
{ type: "cad", format: "html", stage: "mesh" },
|
|
32
|
+
{ type: "cad", format: "png", stage: "browser" },
|
|
33
|
+
{ type: "cad", format: "glb", stage: "mesh" },
|
|
34
|
+
{ type: "cad", format: "stl", stage: "mesh" },
|
|
35
|
+
{ type: "html", format: "png", stage: "browser" },
|
|
36
|
+
{ type: "html", format: "pdf", stage: "browser" },
|
|
37
|
+
{ type: "html", format: "md", stage: "html" },
|
|
38
|
+
];
|
|
39
|
+
/** Returns the pair of the table, or undefined when the design does not list it. */
|
|
40
|
+
export function findPair(type, format) {
|
|
41
|
+
return PAIRS.find((p) => p.type === type && p.format === format);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=pairs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pairs.js","sourceRoot":"","sources":["../src/pairs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The most megabytes of RGBA pixels that one PNG render accepts. Measured: a render holds about two
|
|
3
|
+
* copies of the pixel buffer (the pixmap and the PNG encoder input), so the peak is 2.0 times the pixels
|
|
4
|
+
* (8000 by 8000 pixels peak at 536 MB, 16000 by 16000 at 1999 MB). WASM memory ends at 4 GiB.
|
|
5
|
+
*/
|
|
6
|
+
export declare const MAX_PNG_PIXEL_MB = 1024;
|
|
7
|
+
/** The options of one SVG to PNG render. */
|
|
8
|
+
export interface SvgToPngOptions {
|
|
9
|
+
scale: number;
|
|
10
|
+
maxMemoryMb: number;
|
|
11
|
+
font?: Uint8Array;
|
|
12
|
+
/** Replaces the reader of the resvg WASM file. Tests use it to fail the first start. */
|
|
13
|
+
readWasm?: () => Uint8Array;
|
|
14
|
+
}
|
|
15
|
+
/** Renders an SVG to PNG bytes with resvg. The scale multiplies the SVG size. A pixel buffer over maxMemoryMb or over MAX_PNG_PIXEL_MB rejects with E_LIMIT. */
|
|
16
|
+
export declare function svgToPng(svg: string, options: SvgToPngOptions): Promise<Uint8Array>;
|
|
17
|
+
/** Tells whether the bytes start with a TrueType, OpenType or Apple TrueType font signature. A collection (ttcf) is not a single font. */
|
|
18
|
+
export declare function isFontFile(bytes: Uint8Array): boolean;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { initWasm, Resvg } from "@resvg/resvg-wasm";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { RenderError } from "../errors.js";
|
|
5
|
+
/**
|
|
6
|
+
* The most megabytes of RGBA pixels that one PNG render accepts. Measured: a render holds about two
|
|
7
|
+
* copies of the pixel buffer (the pixmap and the PNG encoder input), so the peak is 2.0 times the pixels
|
|
8
|
+
* (8000 by 8000 pixels peak at 536 MB, 16000 by 16000 at 1999 MB). WASM memory ends at 4 GiB.
|
|
9
|
+
*/
|
|
10
|
+
export const MAX_PNG_PIXEL_MB = 1024;
|
|
11
|
+
let wasmPromise;
|
|
12
|
+
function defaultReadWasm() {
|
|
13
|
+
return readFileSync(createRequire(import.meta.url).resolve("@resvg/resvg-wasm/index_bg.wasm"));
|
|
14
|
+
}
|
|
15
|
+
// A failed start is not cached, so a later render can try again.
|
|
16
|
+
function ensureWasm(readWasm) {
|
|
17
|
+
if (wasmPromise === undefined) {
|
|
18
|
+
const started = (async () => {
|
|
19
|
+
await initWasm(readWasm());
|
|
20
|
+
})();
|
|
21
|
+
wasmPromise = started;
|
|
22
|
+
started.catch(() => {
|
|
23
|
+
if (wasmPromise === started) {
|
|
24
|
+
wasmPromise = undefined;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return wasmPromise;
|
|
29
|
+
}
|
|
30
|
+
/** Renders an SVG to PNG bytes with resvg. The scale multiplies the SVG size. A pixel buffer over maxMemoryMb or over MAX_PNG_PIXEL_MB rejects with E_LIMIT. */
|
|
31
|
+
export async function svgToPng(svg, options) {
|
|
32
|
+
await ensureWasm(options.readWasm ?? defaultReadWasm);
|
|
33
|
+
let resvg;
|
|
34
|
+
try {
|
|
35
|
+
resvg = new Resvg(svg, {
|
|
36
|
+
fitTo: { mode: "zoom", value: options.scale },
|
|
37
|
+
dpi: 72,
|
|
38
|
+
font: { loadSystemFonts: false, fontBuffers: options.font ? [options.font] : [] },
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
throw new RenderError("E_INPUT", "resvg cannot read the SVG: " + (err instanceof Error ? err.message : String(err)));
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const limitMb = Math.min(options.maxMemoryMb, MAX_PNG_PIXEL_MB);
|
|
46
|
+
const limitBytes = limitMb * 1048576;
|
|
47
|
+
const needed = Math.ceil(resvg.width * options.scale) * Math.ceil(resvg.height * options.scale) * 4;
|
|
48
|
+
if (needed > limitBytes) {
|
|
49
|
+
throw new RenderError("E_LIMIT", "the PNG needs " + needed + " bytes of pixels; the limit is " + limitBytes + " bytes");
|
|
50
|
+
}
|
|
51
|
+
return resvg.render().asPng();
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
resvg.free();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Tells whether the bytes start with a TrueType, OpenType or Apple TrueType font signature. A collection (ttcf) is not a single font. */
|
|
58
|
+
export function isFontFile(bytes) {
|
|
59
|
+
if (bytes.length < 4) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
const b0 = bytes[0];
|
|
63
|
+
const b1 = bytes[1];
|
|
64
|
+
const b2 = bytes[2];
|
|
65
|
+
const b3 = bytes[3];
|
|
66
|
+
if (b0 === 0x00 && b1 === 0x01 && b2 === 0x00 && b3 === 0x00) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
if (b0 === 0x4f && b1 === 0x54 && b2 === 0x54 && b3 === 0x4f) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
if (b0 === 0x74 && b1 === 0x72 && b2 === 0x75 && b3 === 0x65) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/raster/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Tells whether the font holds a glyph for a code point. */
|
|
2
|
+
export type CoverageTest = (codePoint: number) => boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Reads the Unicode character map of a TrueType or OpenType font (formats 4 and 12).
|
|
5
|
+
* Returns undefined when the font has no readable map, so the caller skips the check.
|
|
6
|
+
*/
|
|
7
|
+
export declare function fontCovers(font: Uint8Array): CoverageTest | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Lists what the raster font cannot draw in the text of an SVG. The font has one face, so bold and
|
|
10
|
+
* italic text draw in that face. A character without a glyph draws no pixel. Each kind gives one warning.
|
|
11
|
+
*/
|
|
12
|
+
export declare function rasterWarnings(svg: string, font: Uint8Array): string[];
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
function tableOf(view, tag) {
|
|
2
|
+
if (view.byteLength < 12) {
|
|
3
|
+
return undefined;
|
|
4
|
+
}
|
|
5
|
+
const count = view.getUint16(4);
|
|
6
|
+
for (let i = 0; i < count; i++) {
|
|
7
|
+
const entry = 12 + i * 16;
|
|
8
|
+
if (entry + 16 > view.byteLength) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
let name = "";
|
|
12
|
+
for (let k = 0; k < 4; k++) {
|
|
13
|
+
name += String.fromCharCode(view.getUint8(entry + k));
|
|
14
|
+
}
|
|
15
|
+
if (name === tag) {
|
|
16
|
+
return { offset: view.getUint32(entry + 8), length: view.getUint32(entry + 12) };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
function format4(view, start) {
|
|
22
|
+
const segments = view.getUint16(start + 6) / 2;
|
|
23
|
+
const ends = start + 14;
|
|
24
|
+
const starts = ends + segments * 2 + 2;
|
|
25
|
+
const deltas = starts + segments * 2;
|
|
26
|
+
const ranges = deltas + segments * 2;
|
|
27
|
+
return (cp) => {
|
|
28
|
+
if (cp > 0xffff) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
for (let s = 0; s < segments; s++) {
|
|
32
|
+
if (cp > view.getUint16(ends + s * 2)) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const first = view.getUint16(starts + s * 2);
|
|
36
|
+
if (cp < first) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
const offset = view.getUint16(ranges + s * 2);
|
|
40
|
+
let glyph;
|
|
41
|
+
if (offset === 0) {
|
|
42
|
+
glyph = (cp + view.getUint16(deltas + s * 2)) & 0xffff;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const at = ranges + s * 2 + offset + (cp - first) * 2;
|
|
46
|
+
if (at + 2 > view.byteLength) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
glyph = view.getUint16(at);
|
|
50
|
+
if (glyph !== 0) {
|
|
51
|
+
glyph = (glyph + view.getUint16(deltas + s * 2)) & 0xffff;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return glyph !== 0;
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function format12(view, start) {
|
|
60
|
+
const groups = view.getUint32(start + 12);
|
|
61
|
+
return (cp) => {
|
|
62
|
+
for (let g = 0; g < groups; g++) {
|
|
63
|
+
const at = start + 16 + g * 12;
|
|
64
|
+
if (at + 12 > view.byteLength) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
if (cp >= view.getUint32(at) && cp <= view.getUint32(at + 4)) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Reads the Unicode character map of a TrueType or OpenType font (formats 4 and 12).
|
|
76
|
+
* Returns undefined when the font has no readable map, so the caller skips the check.
|
|
77
|
+
*/
|
|
78
|
+
export function fontCovers(font) {
|
|
79
|
+
const view = new DataView(font.buffer, font.byteOffset, font.byteLength);
|
|
80
|
+
try {
|
|
81
|
+
const cmap = tableOf(view, "cmap");
|
|
82
|
+
if (cmap === undefined) {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
const tests = [];
|
|
86
|
+
const count = view.getUint16(cmap.offset + 2);
|
|
87
|
+
for (let i = 0; i < count; i++) {
|
|
88
|
+
const record = cmap.offset + 4 + i * 8;
|
|
89
|
+
const platform = view.getUint16(record);
|
|
90
|
+
const encoding = view.getUint16(record + 2);
|
|
91
|
+
const unicode = platform === 0 || (platform === 3 && (encoding === 1 || encoding === 10));
|
|
92
|
+
if (!unicode) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const sub = cmap.offset + view.getUint32(record + 4);
|
|
96
|
+
const format = view.getUint16(sub);
|
|
97
|
+
if (format === 4) {
|
|
98
|
+
tests.push(format4(view, sub));
|
|
99
|
+
}
|
|
100
|
+
else if (format === 12) {
|
|
101
|
+
tests.push(format12(view, sub));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (tests.length === 0) {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
return (cp) => tests.some((test) => test(cp));
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// A named entity of SVG (amp, lt, gt, quot, apos) stands for an ASCII character, which the check skips. Only a numeric reference can name a character that the font lacks.
|
|
114
|
+
function decodeEntities(text) {
|
|
115
|
+
return text.replace(/&#(x[0-9a-fA-F]+|[0-9]+);/g, (whole, body) => {
|
|
116
|
+
const value = body.startsWith("x") ? parseInt(body.slice(1), 16) : parseInt(body, 10);
|
|
117
|
+
return value <= 0x10ffff ? String.fromCodePoint(value) : whole;
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function isBold(weight) {
|
|
121
|
+
const value = weight.trim().toLowerCase();
|
|
122
|
+
return value === "bold" || value === "bolder" || (/^[0-9]+$/.test(value) && Number(value) >= 600);
|
|
123
|
+
}
|
|
124
|
+
/** The code point text of an SVG fragment: the markup removed and the entities read. */
|
|
125
|
+
function textOf(markup) {
|
|
126
|
+
return decodeEntities(markup.replace(/<[^>]*>/g, ""));
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Lists what the raster font cannot draw in the text of an SVG. The font has one face, so bold and
|
|
130
|
+
* italic text draw in that face. A character without a glyph draws no pixel. Each kind gives one warning.
|
|
131
|
+
*/
|
|
132
|
+
export function rasterWarnings(svg, font) {
|
|
133
|
+
const covers = fontCovers(font);
|
|
134
|
+
let bold = 0;
|
|
135
|
+
let italic = 0;
|
|
136
|
+
const missing = new Set();
|
|
137
|
+
for (const match of svg.matchAll(/<(?:text|tspan)\b([^>]*)>/g)) {
|
|
138
|
+
const attributes = match[1];
|
|
139
|
+
const weight = /\sfont-weight="([^"]*)"/.exec(attributes);
|
|
140
|
+
if (weight !== null && isBold(weight[1])) {
|
|
141
|
+
bold++;
|
|
142
|
+
}
|
|
143
|
+
const style = /\sfont-style="([^"]*)"/.exec(attributes);
|
|
144
|
+
if (style !== null && (style[1] === "italic" || style[1] === "oblique")) {
|
|
145
|
+
italic++;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (covers !== undefined) {
|
|
149
|
+
for (const match of svg.matchAll(/<text\b[^>]*>([\s\S]*?)<\/text>/g)) {
|
|
150
|
+
for (const ch of textOf(match[1])) {
|
|
151
|
+
const cp = ch.codePointAt(0);
|
|
152
|
+
if (cp > 0x20 && cp !== 0xa0 && !(cp >= 0x7f && cp < 0xa0) && !covers(cp)) {
|
|
153
|
+
missing.add(cp);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const warnings = [];
|
|
159
|
+
if (covers === undefined && /<text\b/.test(svg)) {
|
|
160
|
+
warnings.push("the raster font has no readable character map, so the render cannot check which characters it draws");
|
|
161
|
+
}
|
|
162
|
+
if (bold > 0) {
|
|
163
|
+
warnings.push(`${bold} bold text element(s) draw in the one face of the raster font`);
|
|
164
|
+
}
|
|
165
|
+
if (italic > 0) {
|
|
166
|
+
warnings.push(`${italic} italic text element(s) draw in the one face of the raster font`);
|
|
167
|
+
}
|
|
168
|
+
if (missing.size > 0) {
|
|
169
|
+
const first = [...missing][0];
|
|
170
|
+
const code = "U+" + first.toString(16).toUpperCase().padStart(4, "0");
|
|
171
|
+
warnings.push(`${missing.size} character(s) have no glyph in the raster font and draw blank (first: ${code})`);
|
|
172
|
+
}
|
|
173
|
+
return warnings;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=warnings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warnings.js","sourceRoot":"","sources":["../../src/raster/warnings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** One backend: the module that the worker loads for a (type, format) pair. */
|
|
2
|
+
export interface BackendEntry {
|
|
3
|
+
/** The backend name that a result reports, for example "graph/viz". */
|
|
4
|
+
backend: string;
|
|
5
|
+
/** An absolute file URL of a module that exports `render`. */
|
|
6
|
+
moduleUrl: string;
|
|
7
|
+
}
|
|
8
|
+
/** Maps "type:format" to a backend. A key is missing when no backend is built in. */
|
|
9
|
+
export type Registry = Record<string, BackendEntry>;
|
|
10
|
+
/** The backends of this build. */
|
|
11
|
+
export declare const DEFAULT_REGISTRY: Registry;
|
|
12
|
+
/** Builds the registry key of a pair. */
|
|
13
|
+
export declare function registryKey(type: string, format: string): string;
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { extname } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
/** The URL of a backend module of this package. The extension follows the build: .ts from src, .js from dist. */
|
|
4
|
+
function backendUrl(name) {
|
|
5
|
+
const extension = extname(fileURLToPath(import.meta.url));
|
|
6
|
+
return new URL(`./${name}${extension}`, import.meta.url).href;
|
|
7
|
+
}
|
|
8
|
+
/** The backends of this build. */
|
|
9
|
+
export const DEFAULT_REGISTRY = {
|
|
10
|
+
"dot:svg": { backend: "graph/viz", moduleUrl: backendUrl("graph/backend-svg") },
|
|
11
|
+
"dot:png": { backend: "graph/viz+raster/resvg", moduleUrl: backendUrl("graph/backend-png") },
|
|
12
|
+
};
|
|
13
|
+
/** Builds the registry key of a pair. */
|
|
14
|
+
export function registryKey(type, format) {
|
|
15
|
+
return `${type}:${format}`;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAazC,iHAAiH;AACjH,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,OAAO,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,SAAS,EAAE,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;AAChE,CAAC;AAED,kCAAkC;AAClC,MAAM,CAAC,MAAM,gBAAgB,GAAa;IACxC,SAAS,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,CAAC,mBAAmB,CAAC,EAAE;IAC/E,SAAS,EAAE,EAAE,OAAO,EAAE,wBAAwB,EAAE,SAAS,EAAE,UAAU,CAAC,mBAAmB,CAAC,EAAE;CAC7F,CAAC;AAEF,yCAAyC;AACzC,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,MAAc;IACtD,OAAO,GAAG,IAAI,IAAI,MAAM,EAAE,CAAC;AAC7B,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** The input types of the design. */
|
|
2
|
+
export declare const INPUT_TYPES: readonly ["dot", "mermaid", "math", "tikz", "plot", "sysml", "step", "iges", "brep", "cad", "html"];
|
|
3
|
+
/** One input type of the design. */
|
|
4
|
+
export type InputType = (typeof INPUT_TYPES)[number];
|
|
5
|
+
/** The output formats of the design. */
|
|
6
|
+
export declare const OUTPUT_FORMATS: readonly ["svg", "png", "pdf", "html", "md", "glb", "stl"];
|
|
7
|
+
/** One output format of the design. */
|
|
8
|
+
export type OutputFormat = (typeof OUTPUT_FORMATS)[number];
|
|
9
|
+
/** Input types whose source is bytes, not text. */
|
|
10
|
+
export declare const BINARY_INPUT_TYPES: readonly InputType[];
|
|
11
|
+
/** Per-type options. Each increment types its own keys. I0 keeps the bag open. */
|
|
12
|
+
export type RenderOptions = Record<string, unknown>;
|
|
13
|
+
/** One render request. The source is text, or bytes for the binary input types. */
|
|
14
|
+
export interface RenderRequest {
|
|
15
|
+
type: InputType;
|
|
16
|
+
/** Text for text formats, bytes for step, iges and brep. */
|
|
17
|
+
source: string | Uint8Array;
|
|
18
|
+
format: OutputFormat;
|
|
19
|
+
options?: RenderOptions;
|
|
20
|
+
}
|
|
21
|
+
/** One extracted asset, for example an image. */
|
|
22
|
+
export interface RenderAsset {
|
|
23
|
+
name: string;
|
|
24
|
+
bytes: Uint8Array;
|
|
25
|
+
mime: string;
|
|
26
|
+
}
|
|
27
|
+
/** The result of one render. */
|
|
28
|
+
export interface RenderResult {
|
|
29
|
+
bytes: Uint8Array;
|
|
30
|
+
mime: string;
|
|
31
|
+
/** The backend that rendered, for example "graph/viz". */
|
|
32
|
+
backend: string;
|
|
33
|
+
/** Each item names its source line when it has one. */
|
|
34
|
+
warnings: string[];
|
|
35
|
+
/** Extracted images, for example from an HTML to Markdown render. */
|
|
36
|
+
assets?: RenderAsset[];
|
|
37
|
+
}
|
|
38
|
+
/** One supported pair with its stage and its readiness. */
|
|
39
|
+
export interface Capability {
|
|
40
|
+
type: InputType;
|
|
41
|
+
format: OutputFormat;
|
|
42
|
+
/** The stage that the pair needs. */
|
|
43
|
+
stage: string;
|
|
44
|
+
/** True when the stage is ready on this machine. */
|
|
45
|
+
ready: boolean;
|
|
46
|
+
/** Why the pair is not ready, when it is not. */
|
|
47
|
+
reason?: string;
|
|
48
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** The input types of the design. */
|
|
2
|
+
export const INPUT_TYPES = [
|
|
3
|
+
"dot",
|
|
4
|
+
"mermaid",
|
|
5
|
+
"math",
|
|
6
|
+
"tikz",
|
|
7
|
+
"plot",
|
|
8
|
+
"sysml",
|
|
9
|
+
"step",
|
|
10
|
+
"iges",
|
|
11
|
+
"brep",
|
|
12
|
+
"cad",
|
|
13
|
+
"html",
|
|
14
|
+
];
|
|
15
|
+
/** The output formats of the design. */
|
|
16
|
+
export const OUTPUT_FORMATS = ["svg", "png", "pdf", "html", "md", "glb", "stl"];
|
|
17
|
+
/** Input types whose source is bytes, not text. */
|
|
18
|
+
export const BINARY_INPUT_TYPES = ["step", "iges", "brep"];
|
|
19
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,KAAK;IACL,SAAS;IACT,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;CACE,CAAC;AAKX,wCAAwC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAU,CAAC;AAKzF,mDAAmD;AACnD,MAAM,CAAC,MAAM,kBAAkB,GAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
import { parentPort, workerData } from "node:worker_threads";
|
|
10
|
+
import { RenderError, RENDER_ERROR_CODES } from "../errors.js";
|
|
11
|
+
/**
|
|
12
|
+
* The worker side of a render. The worker loads the backend module, runs one request and posts one message.
|
|
13
|
+
* A backend error that is a RenderError keeps its code. Any other error maps to E_INTERNAL.
|
|
14
|
+
*/
|
|
15
|
+
async function run(job) {
|
|
16
|
+
try {
|
|
17
|
+
const mod = (await import(__rewriteRelativeImportExtension(job.moduleUrl)));
|
|
18
|
+
if (typeof mod.render !== "function") {
|
|
19
|
+
throw new RenderError("E_INTERNAL", `backend module ${job.moduleUrl} exports no render function`);
|
|
20
|
+
}
|
|
21
|
+
const out = await mod.render(job.request);
|
|
22
|
+
return { ok: true, bytes: out.bytes, warnings: out.warnings ?? [] };
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
if (err instanceof RenderError) {
|
|
26
|
+
return { ok: false, code: err.code, message: err.message, line: err.line, column: err.column };
|
|
27
|
+
}
|
|
28
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
29
|
+
return { ok: false, code: "E_INTERNAL", message };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const job = workerData;
|
|
33
|
+
const message = await run(job);
|
|
34
|
+
if (!message.ok && !RENDER_ERROR_CODES.includes(message.code)) {
|
|
35
|
+
message.code = "E_INTERNAL";
|
|
36
|
+
}
|
|
37
|
+
parentPort?.postMessage(message);
|
|
38
|
+
//# sourceMappingURL=entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../../src/worker/entry.ts"],"names":[],"mappings":";;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAwB,MAAM,cAAc,CAAC;AAGrF;;;GAGG;AACH,KAAK,UAAU,GAAG,CAAC,GAAc;IAC/B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,kCAAC,GAAG,CAAC,SAAS,EAAC,CAAuF,CAAC;QAChI,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YACrC,MAAM,IAAI,WAAW,CAAC,YAAY,EAAE,kBAAkB,GAAG,CAAC,SAAS,6BAA6B,CAAC,CAAC;QACpG,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC1C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;IACtE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,WAAW,EAAE,CAAC;YAC/B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;QACjG,CAAC;QACD,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;IACpD,CAAC;AACH,CAAC;AAED,MAAM,GAAG,GAAG,UAAuB,CAAC;AACpC,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC;AAC/B,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,CAAE,kBAAwC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;IACrF,OAAO,CAAC,IAAI,GAAG,YAAsC,CAAC;AACxD,CAAC;AACD,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { InputType, OutputFormat, RenderOptions } from "../types.ts";
|
|
2
|
+
/** The configuration values that a backend reads. */
|
|
3
|
+
export interface BackendSettings {
|
|
4
|
+
/** The memory limit of one render, in megabytes. */
|
|
5
|
+
maxMemoryMb: number;
|
|
6
|
+
/** The path of the raster font that replaces the bundled font, or undefined for the bundled font. */
|
|
7
|
+
rasterFont: string | undefined;
|
|
8
|
+
}
|
|
9
|
+
/** What the worker receives: one render request and the backend module that serves it. */
|
|
10
|
+
export interface WorkerJob {
|
|
11
|
+
moduleUrl: string;
|
|
12
|
+
backend: string;
|
|
13
|
+
request: {
|
|
14
|
+
type: InputType;
|
|
15
|
+
format: OutputFormat;
|
|
16
|
+
source: string | Uint8Array;
|
|
17
|
+
options: RenderOptions;
|
|
18
|
+
settings: BackendSettings;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** The value that a backend module returns from `render`. */
|
|
22
|
+
export interface BackendOutput {
|
|
23
|
+
bytes: Uint8Array;
|
|
24
|
+
warnings?: string[];
|
|
25
|
+
}
|
|
26
|
+
/** The one message that a worker sends back. */
|
|
27
|
+
export type WorkerMessage = {
|
|
28
|
+
ok: true;
|
|
29
|
+
bytes: Uint8Array;
|
|
30
|
+
warnings: string[];
|
|
31
|
+
} | {
|
|
32
|
+
ok: false;
|
|
33
|
+
code: string;
|
|
34
|
+
message: string;
|
|
35
|
+
line?: number;
|
|
36
|
+
column?: number;
|
|
37
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/worker/protocol.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Worker } from "node:worker_threads";
|
|
2
|
+
import type { BackendOutput, WorkerJob } from "./protocol.ts";
|
|
3
|
+
/** The exit of one worker. The exit code is the code that `Worker.terminate` reports. */
|
|
4
|
+
export interface WorkerExit {
|
|
5
|
+
exitCode: number;
|
|
6
|
+
}
|
|
7
|
+
/** The limits of one worker render. */
|
|
8
|
+
export interface WorkerLimits {
|
|
9
|
+
/** The time limit of one render, in milliseconds. */
|
|
10
|
+
timeoutMs: number;
|
|
11
|
+
/**
|
|
12
|
+
* The heap limit of the worker, in megabytes. Node enforces it. Bun 1.4.4 accepts the option
|
|
13
|
+
* and does not enforce it, so the limit holds only under Node, the release runtime.
|
|
14
|
+
*/
|
|
15
|
+
maxMemoryMb: number;
|
|
16
|
+
/** Called once the worker has exited, before the render settles. Tests use it to prove the exit. */
|
|
17
|
+
onWorkerExit?: (exit: WorkerExit) => void;
|
|
18
|
+
/** The longest wait for the worker to stop after the render settles, in milliseconds. */
|
|
19
|
+
terminateWaitMs?: number;
|
|
20
|
+
/** Creates the worker. Tests replace it with a double. */
|
|
21
|
+
createWorker?: (entry: URL, data: WorkerJob, maxMemoryMb: number) => Worker;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Runs one render in a fresh worker. The worker ends at the first of: its message, its error,
|
|
25
|
+
* its exit, or the time limit. The promise settles only after the worker has exited.
|
|
26
|
+
*
|
|
27
|
+
* A heap exhaustion (`ERR_WORKER_OUT_OF_MEMORY`) maps to `E_LIMIT`. The design lists the heap
|
|
28
|
+
* limit as a resource limit of a source. A crash of any other kind maps to `E_INTERNAL`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function runInWorker(job: WorkerJob, limits: WorkerLimits): Promise<BackendOutput>;
|