@jarenjs/play 0.72.0 → 0.72.3
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/README.md +4 -1
- package/docs/PLAY-FORMAT.md +4 -0
- package/package.json +6 -6
- package/src/engines.js +17 -11
package/README.md
CHANGED
|
@@ -49,7 +49,10 @@ The datasets list length is the whole story: **0** → the engine takes no
|
|
|
49
49
|
data (markdown/mermaid); **1** → one dataset; **N** → a switcher that runs
|
|
50
50
|
the *same* source over each shape. Adding an engine is a descriptor plus
|
|
51
51
|
examples — the picker, panes and switcher all derive from the descriptor.
|
|
52
|
-
See [docs/PLAY-FORMAT.md](docs/PLAY-FORMAT.md)
|
|
52
|
+
See [docs/PLAY-FORMAT.md](docs/PLAY-FORMAT.md) for descriptors and results,
|
|
53
|
+
and [ARCHITECTURE.md](ARCHITECTURE.md) for the state, action and run-loop
|
|
54
|
+
contract an embedding host supplies. Query, JSLT, JTLT and XQuery expose
|
|
55
|
+
an editable JSON externals pane.
|
|
53
56
|
|
|
54
57
|
## Exports
|
|
55
58
|
|
package/docs/PLAY-FORMAT.md
CHANGED
|
@@ -21,6 +21,10 @@ EnginePane = { key: string, label: string, control?: 'code' | 'text' }
|
|
|
21
21
|
- `sourcePanes` are the engine's input(s): a JSONPath `selector`, a JSLT
|
|
22
22
|
`stylesheet`, a JSON `patch`, a query + its `externals`, a markdown
|
|
23
23
|
`source`. Editable in the playground.
|
|
24
|
+
Query, JSLT, JTLT and XQuery each expose an `externals` JSON pane; an
|
|
25
|
+
empty pane means `{}` and malformed JSON is attributed to that pane.
|
|
26
|
+
XQuery's Data pane supplies the declared `$doc` external and takes
|
|
27
|
+
precedence over an `externals.doc` member.
|
|
24
28
|
- `dataPanes` are the JSON the engine runs against: usually one `data`; a
|
|
25
29
|
patch's is its `target`; markdown / mermaid / charts have **none** — the
|
|
26
30
|
source is everything.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jarenjs/play",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.72.
|
|
4
|
+
"version": "0.72.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
7
|
"types": "./dist/types/index.d.ts",
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
"prepack": "npm run build:types"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@jarenjs/contract": "^0.72.
|
|
60
|
-
"@jarenjs/core": "^0.72.
|
|
61
|
-
"@jarenjs/josl": "^0.72.
|
|
62
|
-
"@jarenjs/json": "^0.72.
|
|
63
|
-
"@jarenjs/validate": "^0.72.
|
|
59
|
+
"@jarenjs/contract": "^0.72.3",
|
|
60
|
+
"@jarenjs/core": "^0.72.3",
|
|
61
|
+
"@jarenjs/josl": "^0.72.3",
|
|
62
|
+
"@jarenjs/json": "^0.72.3",
|
|
63
|
+
"@jarenjs/validate": "^0.72.3"
|
|
64
64
|
}
|
|
65
65
|
}
|
package/src/engines.js
CHANGED
|
@@ -44,6 +44,12 @@ function parseJson(text, pane, label = pane) {
|
|
|
44
44
|
catch (err) { return { error: `${label}: ${msg(err)}`, pane }; }
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
/** The optional JSON bindings pane shared by every engine accepting externals. */
|
|
48
|
+
function parseExternals(source) {
|
|
49
|
+
return source.externals === undefined || String(source.externals).trim() === ''
|
|
50
|
+
? { value: {} } : parseJson(source.externals, 'externals');
|
|
51
|
+
}
|
|
52
|
+
|
|
47
53
|
/** A single-`code`-panel Result — the shape most engines return. */
|
|
48
54
|
/** @returns {import('./index.js').PlayResult} */
|
|
49
55
|
const ok = (text, compileMs, runMs, deep) => okPanels([{ id: 'out', label: 'Output', kind: 'code', text }, ...(deep ?? [])], compileMs, runMs);
|
|
@@ -295,16 +301,13 @@ export const ENGINE_LIST = [
|
|
|
295
301
|
run(source, data, options) {
|
|
296
302
|
const d = parseJson(data.data, 'data'); if (d.error) return failParse(d);
|
|
297
303
|
const q = parseJson(source.query, 'query'); if (q.error) return failParse(q);
|
|
298
|
-
|
|
299
|
-
if (source.externals !== undefined && String(source.externals).trim() !== '') {
|
|
300
|
-
const e = parseJson(source.externals, 'externals'); if (e.error) return failParse(e); externals = e.value;
|
|
301
|
-
}
|
|
304
|
+
const e = parseExternals(source); if (e.error) return failParse(e);
|
|
302
305
|
let fn; const t0 = now();
|
|
303
306
|
try { fn = compileJsonQuery(q.value, compileOptions(options)); }
|
|
304
307
|
catch (err) { return fail(msg(err), code(err), locate(err, 'query')); }
|
|
305
308
|
const t1 = now();
|
|
306
309
|
let out;
|
|
307
|
-
try { out = fn(d.value,
|
|
310
|
+
try { out = fn(d.value, e.value); }
|
|
308
311
|
catch (err) { return fail(msg(err), code(err), locate(err, 'query')); }
|
|
309
312
|
const t2 = now();
|
|
310
313
|
const items = out === undefined ? 0 : Array.isArray(out) ? out.length : 1;
|
|
@@ -319,17 +322,18 @@ export const ENGINE_LIST = [
|
|
|
319
322
|
},
|
|
320
323
|
{
|
|
321
324
|
id: 'jslt', label: 'JSLT', lead: 'JSON stylesheet transform (registered operators included).',
|
|
322
|
-
sourcePanes: [{ key: 'stylesheet', label: 'Stylesheet', control: 'code' }],
|
|
325
|
+
sourcePanes: [{ key: 'stylesheet', label: 'Stylesheet', control: 'code' }, { key: 'externals', label: 'Externals', control: 'code' }],
|
|
323
326
|
dataPanes: [{ key: 'data', label: 'Data' }],
|
|
324
327
|
run(source, data, options) {
|
|
325
328
|
const d = parseJson(data.data, 'data'); if (d.error) return failParse(d);
|
|
326
329
|
const s = parseJson(source.stylesheet, 'stylesheet'); if (s.error) return failParse(s);
|
|
330
|
+
const e = parseExternals(source); if (e.error) return failParse(e);
|
|
327
331
|
let compiled; const t0 = now();
|
|
328
332
|
try { compiled = compileJsltStylesheet(s.value, compileOptions(options)); }
|
|
329
333
|
catch (err) { return fail(msg(err), code(err), locate(err, 'stylesheet')); }
|
|
330
334
|
const t1 = now();
|
|
331
335
|
let out;
|
|
332
|
-
try { out = compiled(d.value); }
|
|
336
|
+
try { out = compiled(d.value, e.value); }
|
|
333
337
|
catch (err) { return fail(msg(err), code(err), locate(err, 'stylesheet')); }
|
|
334
338
|
const t2 = now();
|
|
335
339
|
// the identity lesson: a rule that changes nothing hands the INPUT back
|
|
@@ -345,17 +349,18 @@ export const ENGINE_LIST = [
|
|
|
345
349
|
},
|
|
346
350
|
{
|
|
347
351
|
id: 'jtlt', label: 'JTLT', lead: 'JSLT\'s text front-end — render JSON as Markdown, XML or code.',
|
|
348
|
-
sourcePanes: [{ key: 'template', label: 'Template', control: 'code' }],
|
|
352
|
+
sourcePanes: [{ key: 'template', label: 'Template', control: 'code' }, { key: 'externals', label: 'Externals', control: 'code' }],
|
|
349
353
|
dataPanes: [{ key: 'data', label: 'Data' }],
|
|
350
354
|
run(source, data, options) {
|
|
351
355
|
const d = parseJson(data.data, 'data'); if (d.error) return failParse(d);
|
|
352
356
|
const t = parseJson(source.template, 'template'); if (t.error) return failParse(t);
|
|
357
|
+
const e = parseExternals(source); if (e.error) return failParse(e);
|
|
353
358
|
let render; const t0 = now();
|
|
354
359
|
try { render = compileJtltStylesheet(t.value, compileOptions(options)); }
|
|
355
360
|
catch (err) { return fail(msg(err), code(err), locate(err, 'template')); }
|
|
356
361
|
const t1 = now();
|
|
357
362
|
let out;
|
|
358
|
-
try { out = render(d.value); }
|
|
363
|
+
try { out = render(d.value, e.value); }
|
|
359
364
|
catch (err) { return fail(msg(err), code(err), locate(err, 'template')); }
|
|
360
365
|
const t2 = now();
|
|
361
366
|
// JTLT emits TEXT (markdown / xml / source) — show it verbatim, not fmt'd
|
|
@@ -367,11 +372,12 @@ export const ENGINE_LIST = [
|
|
|
367
372
|
},
|
|
368
373
|
{
|
|
369
374
|
id: 'xquery', label: 'XQuery', lead: 'The XQuery 3.1 text subset — parsed to a query document and run over $doc.',
|
|
370
|
-
sourcePanes: [{ key: 'text', label: 'XQuery', control: 'code' }],
|
|
375
|
+
sourcePanes: [{ key: 'text', label: 'XQuery', control: 'code' }, { key: 'externals', label: 'Externals', control: 'code' }],
|
|
371
376
|
dataPanes: [{ key: 'data', label: 'Data' }],
|
|
372
377
|
run(source, data, options) {
|
|
373
378
|
const d = parseJson(data.data, 'data'); if (d.error) return failParse(d);
|
|
374
379
|
let doc, fn; const t0 = now();
|
|
380
|
+
const e = parseExternals(source); if (e.error) return failParse(e);
|
|
375
381
|
// two phases: the text parses (a syntax error locates a position in
|
|
376
382
|
// the XQuery pane), then the GENERATED query document compiles and
|
|
377
383
|
// runs — a location in that document has no pane the learner typed
|
|
@@ -382,7 +388,7 @@ export const ENGINE_LIST = [
|
|
|
382
388
|
const t1 = now();
|
|
383
389
|
let out;
|
|
384
390
|
try {
|
|
385
|
-
const externals = fn.externals.includes('doc') ? { doc: d.value } :
|
|
391
|
+
const externals = fn.externals.includes('doc') ? { ...e.value, doc: d.value } : e.value;
|
|
386
392
|
out = fn(d.value, externals);
|
|
387
393
|
}
|
|
388
394
|
catch (err) { return fail(msg(err), code(err), locate(err)); }
|