@danielsimonjr/mathts-workbook 0.3.23 → 0.4.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/dist/{chunk-3KTM2DZC.js → chunk-M2K7SQG2.js} +28 -8
- package/dist/{chunk-UU537RJR.js → chunk-ZVCYWKM5.js} +2 -2
- package/dist/cli.js +16 -5
- package/dist/index.d.ts +20 -1
- package/dist/index.js +20 -2
- package/dist/run-worker.js +1 -1
- package/package.json +64 -64
|
@@ -4,6 +4,11 @@ var POLLUTION_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "proto
|
|
|
4
4
|
function parseYamlHardened(content) {
|
|
5
5
|
return parseYaml(content, { schema: "core", merge: false, logLevel: "silent" });
|
|
6
6
|
}
|
|
7
|
+
function parseYamlSafe(content) {
|
|
8
|
+
const value = parseYamlHardened(content);
|
|
9
|
+
assertNoPollution(value);
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
7
12
|
function isPlainObject(value) {
|
|
8
13
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
14
|
}
|
|
@@ -15,6 +20,10 @@ function findPollutionKeys(value, seen = /* @__PURE__ */ new WeakSet(), found =
|
|
|
15
20
|
for (const item of value) findPollutionKeys(item, seen, found);
|
|
16
21
|
return found;
|
|
17
22
|
}
|
|
23
|
+
const proto = Object.getPrototypeOf(value);
|
|
24
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
25
|
+
found.push("__proto__");
|
|
26
|
+
}
|
|
18
27
|
for (const key of Object.getOwnPropertyNames(value)) {
|
|
19
28
|
if (POLLUTION_KEYS.has(key)) {
|
|
20
29
|
found.push(key);
|
|
@@ -172,7 +181,14 @@ var IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
|
172
181
|
function isValidIdentifier(id) {
|
|
173
182
|
return typeof id === "string" && IDENTIFIER_RE.test(id);
|
|
174
183
|
}
|
|
175
|
-
var SUPPORTED_CELL_TYPES = [
|
|
184
|
+
var SUPPORTED_CELL_TYPES = [
|
|
185
|
+
"code",
|
|
186
|
+
"markdown",
|
|
187
|
+
"data",
|
|
188
|
+
"test",
|
|
189
|
+
"equation",
|
|
190
|
+
"visualization"
|
|
191
|
+
];
|
|
176
192
|
var EXECUTION_MODES = ["reactive", "sequential", "manual"];
|
|
177
193
|
function detectCellType(cell) {
|
|
178
194
|
for (const key of CELL_TYPE_KEYS) {
|
|
@@ -210,9 +226,7 @@ function mapCell(raw, index, errors) {
|
|
|
210
226
|
errors.push(`Cell at index ${index}: missing "id"`);
|
|
211
227
|
id = `#${index}`;
|
|
212
228
|
} else if (typeof rawId !== "string" || !IDENTIFIER_RE.test(rawId)) {
|
|
213
|
-
errors.push(
|
|
214
|
-
`Cell "${String(rawId)}": id must be a valid identifier ([A-Za-z_][A-Za-z0-9_]*)`
|
|
215
|
-
);
|
|
229
|
+
errors.push(`Cell "${String(rawId)}": id must be a valid identifier ([A-Za-z_][A-Za-z0-9_]*)`);
|
|
216
230
|
id = String(rawId);
|
|
217
231
|
} else {
|
|
218
232
|
id = rawId;
|
|
@@ -360,11 +374,18 @@ function importWorkbook(input) {
|
|
|
360
374
|
try {
|
|
361
375
|
obj = parseYamlHardened(input);
|
|
362
376
|
} catch (error) {
|
|
363
|
-
return {
|
|
377
|
+
return {
|
|
378
|
+
success: false,
|
|
379
|
+
errors: [`Invalid JSON/YAML: ${error instanceof Error ? error.message : String(error)}`]
|
|
380
|
+
};
|
|
364
381
|
}
|
|
365
382
|
if (!obj || typeof obj !== "object" || Array.isArray(obj)) {
|
|
366
383
|
return { success: false, errors: ['Input must be an object with a "cells" array'] };
|
|
367
384
|
}
|
|
385
|
+
const pollution = findPollutionKeys(obj);
|
|
386
|
+
if (pollution.length > 0) {
|
|
387
|
+
return { success: false, errors: [`Disallowed key "${pollution[0]}" (prototype pollution)`] };
|
|
388
|
+
}
|
|
368
389
|
const root = obj;
|
|
369
390
|
if (!Array.isArray(root.cells)) {
|
|
370
391
|
return { success: false, errors: ['Input must have a "cells" array'] };
|
|
@@ -556,8 +577,7 @@ var WorkbookExecutor = class {
|
|
|
556
577
|
* parser, so both YAML entry points are consistent.
|
|
557
578
|
*/
|
|
558
579
|
async executeData(cell) {
|
|
559
|
-
const value =
|
|
560
|
-
assertNoPollution(value);
|
|
580
|
+
const value = parseYamlSafe(cell.content);
|
|
561
581
|
return value;
|
|
562
582
|
}
|
|
563
583
|
/**
|
|
@@ -699,7 +719,7 @@ function formatResult(value) {
|
|
|
699
719
|
}
|
|
700
720
|
|
|
701
721
|
export {
|
|
702
|
-
|
|
722
|
+
parseYamlSafe,
|
|
703
723
|
buildDependencyGraph,
|
|
704
724
|
topologicalSort,
|
|
705
725
|
getDependents,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
isValidIdentifier,
|
|
9
9
|
parseWorkbook,
|
|
10
10
|
serializeWorkbook
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-M2K7SQG2.js";
|
|
12
12
|
|
|
13
13
|
// src/fs-atomic.ts
|
|
14
14
|
import { writeFileSync, renameSync, unlinkSync } from "fs";
|
|
@@ -321,7 +321,7 @@ var Session = class {
|
|
|
321
321
|
|
|
322
322
|
// src/contract.ts
|
|
323
323
|
var SCHEMA_VERSION = { major: 1, minor: 0 };
|
|
324
|
-
var VERSION = "0.
|
|
324
|
+
var VERSION = "0.4.0";
|
|
325
325
|
var COMMAND_NAMES = [
|
|
326
326
|
"run",
|
|
327
327
|
"describe",
|
package/dist/cli.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
runWorkbookWithTimeout,
|
|
16
16
|
setMetadata,
|
|
17
17
|
writeFileAtomic
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-ZVCYWKM5.js";
|
|
19
19
|
import {
|
|
20
20
|
buildDependencyGraph,
|
|
21
21
|
createExecutor,
|
|
@@ -23,14 +23,15 @@ import {
|
|
|
23
23
|
formatResult,
|
|
24
24
|
importWorkbook,
|
|
25
25
|
parseWorkbook,
|
|
26
|
-
|
|
26
|
+
parseYamlSafe,
|
|
27
27
|
serializeWorkbook,
|
|
28
28
|
stripOutputs,
|
|
29
29
|
toDOT,
|
|
30
30
|
toMermaid
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-M2K7SQG2.js";
|
|
32
32
|
|
|
33
33
|
// src/cli.ts
|
|
34
|
+
import { createHash } from "crypto";
|
|
34
35
|
import { readFileSync, writeFileSync, lstatSync, realpathSync } from "fs";
|
|
35
36
|
import { pathToFileURL } from "url";
|
|
36
37
|
import { basename } from "path";
|
|
@@ -599,6 +600,7 @@ mtsw - MathTS Workbook CLI
|
|
|
599
600
|
|
|
600
601
|
Usage:
|
|
601
602
|
mtsw run <file> [-c <id>] [-v] [--json] [--write] [--timeout <ms>]
|
|
603
|
+
[--expect-hash <sha256>]
|
|
602
604
|
Execute a workbook (or one cell + its
|
|
603
605
|
deps with -c/--cell). -v: events,
|
|
604
606
|
--json: machine output, --write: persist
|
|
@@ -607,6 +609,8 @@ Usage:
|
|
|
607
609
|
kills it (WorkbookTimeoutError) if it
|
|
608
610
|
exceeds the budget \u2014 a runaway cell can't
|
|
609
611
|
hang the process. Incompatible with -c/-v.
|
|
612
|
+
--expect-hash refuses to run unless the
|
|
613
|
+
file's SHA-256 matches (optimistic lock).
|
|
610
614
|
mtsw describe <file> [--json] Structured document model (cells, graph)
|
|
611
615
|
mtsw validate <file> [--json] Validate structure (ids, deps, cycles)
|
|
612
616
|
mtsw graph <file> [-f mermaid|dot] Print the dependency graph
|
|
@@ -790,6 +794,13 @@ async function runCommand(args) {
|
|
|
790
794
|
}
|
|
791
795
|
const read = readFile(file);
|
|
792
796
|
if (read.error) return fail([read.error]);
|
|
797
|
+
const expectHash = flagValue(args, "--expect-hash");
|
|
798
|
+
if (expectHash !== void 0) {
|
|
799
|
+
const actual = createHash("sha256").update(read.content, "utf8").digest("hex");
|
|
800
|
+
if (actual.toLowerCase() !== expectHash.toLowerCase()) {
|
|
801
|
+
return fail([`--expect-hash mismatch: file SHA-256 is ${actual}, expected ${expectHash}`]);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
793
804
|
const parsed = parseWorkbook(read.content);
|
|
794
805
|
if (!parsed.success) {
|
|
795
806
|
const problems2 = parsed.errors ?? [];
|
|
@@ -877,7 +888,7 @@ function validateChartSpecs(workbook) {
|
|
|
877
888
|
if (cell.type !== "visualization") continue;
|
|
878
889
|
let spec;
|
|
879
890
|
try {
|
|
880
|
-
spec =
|
|
891
|
+
spec = parseYamlSafe(cell.content);
|
|
881
892
|
} catch (error) {
|
|
882
893
|
problems.push(`Cell "${cell.id}": invalid chart spec (${errMessage(error)})`);
|
|
883
894
|
continue;
|
|
@@ -1087,7 +1098,7 @@ function buildRenderDoc(workbook, byId, format = "svg") {
|
|
|
1087
1098
|
if (c.type === "visualization") {
|
|
1088
1099
|
rc.type = "chart";
|
|
1089
1100
|
try {
|
|
1090
|
-
const spec =
|
|
1101
|
+
const spec = parseYamlSafe(c.content);
|
|
1091
1102
|
const rendered = renderChart(
|
|
1092
1103
|
{ type: spec?.type, title: spec?.title, xLabel: spec?.x?.label, yLabel: spec?.y?.label },
|
|
1093
1104
|
lookup(spec?.x?.data),
|
package/dist/index.d.ts
CHANGED
|
@@ -431,6 +431,25 @@ interface HandleResult {
|
|
|
431
431
|
}
|
|
432
432
|
declare function handleRequest(session: Session, request: JsonRpcRequest): Promise<HandleResult>;
|
|
433
433
|
|
|
434
|
+
/**
|
|
435
|
+
* MathML → SVG typesetting. Wraps a MathML fragment in an SVG document so
|
|
436
|
+
* rendered workbooks can emit SVG (browsers, rsvg, inkscape) instead of raw
|
|
437
|
+
* MathML. The glyph metrics are a conservative estimate — consumers that need
|
|
438
|
+
* pixel-perfect layout should typeset with a real engine; this is the
|
|
439
|
+
* no-dependency path the CLI/export uses.
|
|
440
|
+
*/
|
|
441
|
+
interface MathSvgOptions {
|
|
442
|
+
/** Display (`block`) or inline. Default `block`. */
|
|
443
|
+
display?: 'block' | 'inline';
|
|
444
|
+
/** Extra padding in CSS pixels. Default 4. */
|
|
445
|
+
padding?: number;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Wrap a MathML fragment (or a full `<math>` document) in an SVG with a
|
|
449
|
+
* `foreignObject` so the math remains selectable and scalable.
|
|
450
|
+
*/
|
|
451
|
+
declare function mathMLToSVG(mathml: string, options?: MathSvgOptions): string;
|
|
452
|
+
|
|
434
453
|
/**
|
|
435
454
|
* Shared message/result shapes between `timeout-runner.ts` (the coordinator,
|
|
436
455
|
* running on the caller's thread) and `run-worker.ts` (the `worker_threads`
|
|
@@ -480,4 +499,4 @@ declare class WorkbookTimeoutError extends Error {
|
|
|
480
499
|
*/
|
|
481
500
|
declare function runWorkbookWithTimeout(source: string, options: RunWorkbookWithTimeoutOptions): Promise<SerializedRunResult>;
|
|
482
501
|
|
|
483
|
-
export { type Cell, type CellPosition, type CellResult, type CellType, type ExecutionMode, type ParseResult, type RemoveResult, type RunResult, type RunWorkbookWithTimeoutOptions, type RuntimeConfig, SCHEMA_VERSION, type SerializedCellResult, type SerializedRunResult, Session, VERSION, type Workbook, type WorkbookEvent, WorkbookExecutor, type WorkbookMetadata, WorkbookTimeoutError, addCell, buildDependencyGraph, createExecutor, detectCellType, detectCycles, editCell, formatResult, getAncestors, getDependents, handleRequest, moveCell, parseWorkbook, removeCell, renameCell, runWorkbookWithTimeout, serializeWorkbook, setMetadata, stripOutputs, toMermaid, topologicalSort };
|
|
502
|
+
export { type Cell, type CellPosition, type CellResult, type CellType, type ExecutionMode, type MathSvgOptions, type ParseResult, type RemoveResult, type RunResult, type RunWorkbookWithTimeoutOptions, type RuntimeConfig, SCHEMA_VERSION, type SerializedCellResult, type SerializedRunResult, Session, VERSION, type Workbook, type WorkbookEvent, WorkbookExecutor, type WorkbookMetadata, WorkbookTimeoutError, addCell, buildDependencyGraph, createExecutor, detectCellType, detectCycles, editCell, formatResult, getAncestors, getDependents, handleRequest, mathMLToSVG, moveCell, parseWorkbook, removeCell, renameCell, runWorkbookWithTimeout, serializeWorkbook, setMetadata, stripOutputs, toMermaid, topologicalSort };
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
renameCell,
|
|
12
12
|
runWorkbookWithTimeout,
|
|
13
13
|
setMetadata
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-ZVCYWKM5.js";
|
|
15
15
|
import {
|
|
16
16
|
WorkbookExecutor,
|
|
17
17
|
buildDependencyGraph,
|
|
@@ -26,7 +26,24 @@ import {
|
|
|
26
26
|
stripOutputs,
|
|
27
27
|
toMermaid,
|
|
28
28
|
topologicalSort
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-M2K7SQG2.js";
|
|
30
|
+
|
|
31
|
+
// src/svg-math.ts
|
|
32
|
+
function mathMLToSVG(mathml, options = {}) {
|
|
33
|
+
const display = options.display ?? "block";
|
|
34
|
+
const pad = options.padding ?? 4;
|
|
35
|
+
const inner = mathml.includes("<math") ? mathml : `<math xmlns="http://www.w3.org/1998/Math/MathML" display="${display}">${mathml}</math>`;
|
|
36
|
+
const text = inner.replace(/<[^>]+>/g, "");
|
|
37
|
+
const width = Math.max(24, text.length * 10 + pad * 2);
|
|
38
|
+
const height = display === "block" ? 36 + pad * 2 : 20 + pad * 2;
|
|
39
|
+
return [
|
|
40
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">`,
|
|
41
|
+
`<foreignObject x="${pad}" y="${pad}" width="${width - pad * 2}" height="${height - pad * 2}">`,
|
|
42
|
+
inner,
|
|
43
|
+
`</foreignObject>`,
|
|
44
|
+
`</svg>`
|
|
45
|
+
].join("");
|
|
46
|
+
}
|
|
30
47
|
export {
|
|
31
48
|
SCHEMA_VERSION,
|
|
32
49
|
Session,
|
|
@@ -43,6 +60,7 @@ export {
|
|
|
43
60
|
getAncestors,
|
|
44
61
|
getDependents,
|
|
45
62
|
handleRequest,
|
|
63
|
+
mathMLToSVG,
|
|
46
64
|
moveCell,
|
|
47
65
|
parseWorkbook,
|
|
48
66
|
removeCell,
|
package/dist/run-worker.js
CHANGED
package/package.json
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@danielsimonjr/mathts-workbook",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Scientific workbook runtime for MathTS (.mtsw format)",
|
|
5
|
-
"author": "Daniel Simon Jr.",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"main": "./dist/index.js",
|
|
9
|
-
"module": "./dist/index.js",
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
|
-
"bin": {
|
|
12
|
-
"mtsw": "dist/cli.js"
|
|
13
|
-
},
|
|
14
|
-
"exports": {
|
|
15
|
-
".": {
|
|
16
|
-
"import": "./dist/index.js",
|
|
17
|
-
"types": "./dist/index.d.ts"
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
"files": [
|
|
21
|
-
"dist",
|
|
22
|
-
"README.md"
|
|
23
|
-
],
|
|
24
|
-
"scripts": {
|
|
25
|
-
"build": "tsup",
|
|
26
|
-
"dev": "tsup --watch",
|
|
27
|
-
"test": "vitest run",
|
|
28
|
-
"test:watch": "vitest",
|
|
29
|
-
"test:coverage": "vitest run --coverage",
|
|
30
|
-
"typecheck": "tsc --noEmit",
|
|
31
|
-
"lint": "eslint src --ext .ts",
|
|
32
|
-
"lint:fix": "eslint src --ext .ts --fix",
|
|
33
|
-
"clean": "rm -rf dist",
|
|
34
|
-
"build:prod": "tsup --minify --treeshake"
|
|
35
|
-
},
|
|
36
|
-
"dependencies": {
|
|
37
|
-
"@danielsimonjr/mathts-core": "^0.14.
|
|
38
|
-
"@danielsimonjr/mathts-expression": "^0.7.
|
|
39
|
-
"@danielsimonjr/mathts-functions": "^0.
|
|
40
|
-
"@danielsimonjr/mathts-plot": "^0.4.
|
|
41
|
-
"yaml": "^2.3.0"
|
|
42
|
-
},
|
|
43
|
-
"devDependencies": {
|
|
44
|
-
"@types/node": "^
|
|
45
|
-
"tsup": "^8.0.0",
|
|
46
|
-
"typescript": "^5.3.0",
|
|
47
|
-
"vitest": "^4.1.
|
|
48
|
-
},
|
|
49
|
-
"publishConfig": {
|
|
50
|
-
"access": "public"
|
|
51
|
-
},
|
|
52
|
-
"repository": {
|
|
53
|
-
"type": "git",
|
|
54
|
-
"url": "git+https://github.com/danielsimonjr/MathTS.git",
|
|
55
|
-
"directory": "workbook"
|
|
56
|
-
},
|
|
57
|
-
"keywords": [
|
|
58
|
-
"notebook",
|
|
59
|
-
"workbook",
|
|
60
|
-
"scientific-computing",
|
|
61
|
-
"reactive",
|
|
62
|
-
"yaml"
|
|
63
|
-
]
|
|
64
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@danielsimonjr/mathts-workbook",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Scientific workbook runtime for MathTS (.mtsw format)",
|
|
5
|
+
"author": "Daniel Simon Jr.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"bin": {
|
|
12
|
+
"mtsw": "dist/cli.js"
|
|
13
|
+
},
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"dev": "tsup --watch",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"test:watch": "vitest",
|
|
29
|
+
"test:coverage": "vitest run --coverage",
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"lint": "eslint src --ext .ts",
|
|
32
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
33
|
+
"clean": "rm -rf dist",
|
|
34
|
+
"build:prod": "tsup --minify --treeshake"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@danielsimonjr/mathts-core": "^0.14.1",
|
|
38
|
+
"@danielsimonjr/mathts-expression": "^0.7.1",
|
|
39
|
+
"@danielsimonjr/mathts-functions": "^0.64.0",
|
|
40
|
+
"@danielsimonjr/mathts-plot": "^0.4.2",
|
|
41
|
+
"yaml": "^2.3.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "^26.2.0",
|
|
45
|
+
"tsup": "^8.0.0",
|
|
46
|
+
"typescript": "^5.3.0",
|
|
47
|
+
"vitest": "^4.1.10"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"repository": {
|
|
53
|
+
"type": "git",
|
|
54
|
+
"url": "git+https://github.com/danielsimonjr/MathTS.git",
|
|
55
|
+
"directory": "workbook"
|
|
56
|
+
},
|
|
57
|
+
"keywords": [
|
|
58
|
+
"notebook",
|
|
59
|
+
"workbook",
|
|
60
|
+
"scientific-computing",
|
|
61
|
+
"reactive",
|
|
62
|
+
"yaml"
|
|
63
|
+
]
|
|
64
|
+
}
|