eyeling 1.23.3 → 1.23.4
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/HANDBOOK.md +3 -1
- package/dist/browser/eyeling.browser.js +19 -3
- package/eyeling.js +19 -3
- package/lib/engine.js +14 -3
- package/lib/entry.js +5 -0
- package/package.json +1 -1
- package/test/playground.test.js +45 -0
package/HANDBOOK.md
CHANGED
|
@@ -1902,6 +1902,8 @@ node eyeling.js --builtin examples/builtin/queens.js examples/queens.n3
|
|
|
1902
1902
|
|
|
1903
1903
|
Examples that do not need a custom builtin should not add a matching file under `examples/builtin/`. Examples that do need one should ship it there and let the examples test runner load it uniformly. For example, `examples/sudoku.n3` is paired with `examples/builtin/sudoku.js`, and `examples/queens.n3` is paired with `examples/builtin/queens.js`.
|
|
1904
1904
|
|
|
1905
|
+
The browser playground follows the same convention for URL-loaded repository examples: when a loaded URL looks like `.../examples/name.n3`, the playground tries to fetch `.../examples/builtin/name.js` and register it before reasoning. If no matching builtin file exists, the N3 program runs normally.
|
|
1906
|
+
|
|
1905
1907
|
### 14.2 The bundled Node CLI/runtime (`eyeling.js`)
|
|
1906
1908
|
|
|
1907
1909
|
The bundle contains the whole engine. The CLI path is the “canonical behavior”:
|
|
@@ -2392,7 +2394,7 @@ Run it explicitly like this:
|
|
|
2392
2394
|
eyeling --builtin examples/builtin/sudoku.js examples/sudoku.n3
|
|
2393
2395
|
```
|
|
2394
2396
|
|
|
2395
|
-
`npm run test:examples` uses the same convention automatically: when it sees `examples/builtin/sudoku.js` next to `examples/sudoku.n3`, it loads that module for the Sudoku example.
|
|
2397
|
+
`npm run test:examples` uses the same convention automatically: when it sees `examples/builtin/sudoku.js` next to `examples/sudoku.n3`, it loads that module for the Sudoku example. The browser playground uses the convention too for URL-loaded repository examples, so loading the raw `examples/sudoku.n3` URL also fetches and registers the matching `examples/builtin/sudoku.js` module.
|
|
2396
2398
|
|
|
2397
2399
|
That example is useful for two reasons:
|
|
2398
2400
|
|
|
@@ -8702,10 +8702,21 @@ ${triples.map((tr) => ` ${tripleToN3(tr, prefixes)}`).join('\n')}
|
|
|
8702
8702
|
deref.setEnforceHttpsEnabled(!!enforceHttps);
|
|
8703
8703
|
proofCommentsEnabled = !!proof;
|
|
8704
8704
|
|
|
8705
|
+
function registerBuiltinModuleOption(mod, index) {
|
|
8706
|
+
if (!mod) return;
|
|
8707
|
+
if (typeof mod === 'string') {
|
|
8708
|
+
loadBuiltinModule(mod);
|
|
8709
|
+
return;
|
|
8710
|
+
}
|
|
8711
|
+
registerBuiltinModule(mod, `<reasonStream builtinModules[${index}]>`);
|
|
8712
|
+
}
|
|
8713
|
+
|
|
8705
8714
|
if (Array.isArray(builtinModules)) {
|
|
8706
|
-
for (
|
|
8707
|
-
|
|
8708
|
-
|
|
8715
|
+
for (let i = 0; i < builtinModules.length; i += 1) {
|
|
8716
|
+
registerBuiltinModuleOption(builtinModules[i], i);
|
|
8717
|
+
}
|
|
8718
|
+
} else {
|
|
8719
|
+
registerBuiltinModuleOption(builtinModules, 0);
|
|
8709
8720
|
}
|
|
8710
8721
|
|
|
8711
8722
|
let prefixes, triples, frules, brules, logQueryRules;
|
|
@@ -8989,6 +9000,11 @@ ${triples.map((tr) => ` ${tripleToN3(tr, prefixes)}`).join('\n')}
|
|
|
8989
9000
|
tripleToN3: engine.tripleToN3,
|
|
8990
9001
|
collectOutputStringsFromFacts: engine.collectOutputStringsFromFacts,
|
|
8991
9002
|
prettyPrintQueryTriples: engine.prettyPrintQueryTriples,
|
|
9003
|
+
registerBuiltin: engine.registerBuiltin,
|
|
9004
|
+
unregisterBuiltin: engine.unregisterBuiltin,
|
|
9005
|
+
registerBuiltinModule: engine.registerBuiltinModule,
|
|
9006
|
+
loadBuiltinModule: engine.loadBuiltinModule,
|
|
9007
|
+
listBuiltinIris: engine.listBuiltinIris,
|
|
8992
9008
|
getEnforceHttpsEnabled: engine.getEnforceHttpsEnabled,
|
|
8993
9009
|
setEnforceHttpsEnabled: engine.setEnforceHttpsEnabled,
|
|
8994
9010
|
getProofCommentsEnabled: engine.getProofCommentsEnabled,
|
package/eyeling.js
CHANGED
|
@@ -8679,10 +8679,21 @@ function reasonStream(input, opts = {}) {
|
|
|
8679
8679
|
deref.setEnforceHttpsEnabled(!!enforceHttps);
|
|
8680
8680
|
proofCommentsEnabled = !!proof;
|
|
8681
8681
|
|
|
8682
|
+
function registerBuiltinModuleOption(mod, index) {
|
|
8683
|
+
if (!mod) return;
|
|
8684
|
+
if (typeof mod === 'string') {
|
|
8685
|
+
loadBuiltinModule(mod);
|
|
8686
|
+
return;
|
|
8687
|
+
}
|
|
8688
|
+
registerBuiltinModule(mod, `<reasonStream builtinModules[${index}]>`);
|
|
8689
|
+
}
|
|
8690
|
+
|
|
8682
8691
|
if (Array.isArray(builtinModules)) {
|
|
8683
|
-
for (
|
|
8684
|
-
|
|
8685
|
-
|
|
8692
|
+
for (let i = 0; i < builtinModules.length; i += 1) {
|
|
8693
|
+
registerBuiltinModuleOption(builtinModules[i], i);
|
|
8694
|
+
}
|
|
8695
|
+
} else {
|
|
8696
|
+
registerBuiltinModuleOption(builtinModules, 0);
|
|
8686
8697
|
}
|
|
8687
8698
|
|
|
8688
8699
|
let prefixes, triples, frules, brules, logQueryRules;
|
|
@@ -8967,6 +8978,11 @@ module.exports = {
|
|
|
8967
8978
|
tripleToN3: engine.tripleToN3,
|
|
8968
8979
|
collectOutputStringsFromFacts: engine.collectOutputStringsFromFacts,
|
|
8969
8980
|
prettyPrintQueryTriples: engine.prettyPrintQueryTriples,
|
|
8981
|
+
registerBuiltin: engine.registerBuiltin,
|
|
8982
|
+
unregisterBuiltin: engine.unregisterBuiltin,
|
|
8983
|
+
registerBuiltinModule: engine.registerBuiltinModule,
|
|
8984
|
+
loadBuiltinModule: engine.loadBuiltinModule,
|
|
8985
|
+
listBuiltinIris: engine.listBuiltinIris,
|
|
8970
8986
|
getEnforceHttpsEnabled: engine.getEnforceHttpsEnabled,
|
|
8971
8987
|
setEnforceHttpsEnabled: engine.setEnforceHttpsEnabled,
|
|
8972
8988
|
getProofCommentsEnabled: engine.getProofCommentsEnabled,
|
package/lib/engine.js
CHANGED
|
@@ -3384,10 +3384,21 @@ function reasonStream(input, opts = {}) {
|
|
|
3384
3384
|
deref.setEnforceHttpsEnabled(!!enforceHttps);
|
|
3385
3385
|
proofCommentsEnabled = !!proof;
|
|
3386
3386
|
|
|
3387
|
+
function registerBuiltinModuleOption(mod, index) {
|
|
3388
|
+
if (!mod) return;
|
|
3389
|
+
if (typeof mod === 'string') {
|
|
3390
|
+
loadBuiltinModule(mod);
|
|
3391
|
+
return;
|
|
3392
|
+
}
|
|
3393
|
+
registerBuiltinModule(mod, `<reasonStream builtinModules[${index}]>`);
|
|
3394
|
+
}
|
|
3395
|
+
|
|
3387
3396
|
if (Array.isArray(builtinModules)) {
|
|
3388
|
-
for (
|
|
3389
|
-
|
|
3390
|
-
|
|
3397
|
+
for (let i = 0; i < builtinModules.length; i += 1) {
|
|
3398
|
+
registerBuiltinModuleOption(builtinModules[i], i);
|
|
3399
|
+
}
|
|
3400
|
+
} else {
|
|
3401
|
+
registerBuiltinModuleOption(builtinModules, 0);
|
|
3391
3402
|
}
|
|
3392
3403
|
|
|
3393
3404
|
let prefixes, triples, frules, brules, logQueryRules;
|
package/lib/entry.js
CHANGED
|
@@ -34,6 +34,11 @@ module.exports = {
|
|
|
34
34
|
tripleToN3: engine.tripleToN3,
|
|
35
35
|
collectOutputStringsFromFacts: engine.collectOutputStringsFromFacts,
|
|
36
36
|
prettyPrintQueryTriples: engine.prettyPrintQueryTriples,
|
|
37
|
+
registerBuiltin: engine.registerBuiltin,
|
|
38
|
+
unregisterBuiltin: engine.unregisterBuiltin,
|
|
39
|
+
registerBuiltinModule: engine.registerBuiltinModule,
|
|
40
|
+
loadBuiltinModule: engine.loadBuiltinModule,
|
|
41
|
+
listBuiltinIris: engine.listBuiltinIris,
|
|
37
42
|
getEnforceHttpsEnabled: engine.getEnforceHttpsEnabled,
|
|
38
43
|
setEnforceHttpsEnabled: engine.setEnforceHttpsEnabled,
|
|
39
44
|
getProofCommentsEnabled: engine.getProofCommentsEnabled,
|
package/package.json
CHANGED
package/test/playground.test.js
CHANGED
|
@@ -488,6 +488,8 @@ async function main() {
|
|
|
488
488
|
// Intercept CodeMirror + remote GitHub raw URLs (keep test deterministic).
|
|
489
489
|
const localPkg = fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8');
|
|
490
490
|
const localEyeling = fs.readFileSync(path.join(ROOT, 'eyeling.js'), 'utf8');
|
|
491
|
+
const localSudoku = fs.readFileSync(path.join(ROOT, 'examples', 'sudoku.n3'), 'utf8');
|
|
492
|
+
const localSudokuBuiltin = fs.readFileSync(path.join(ROOT, 'examples', 'builtin', 'sudoku.js'), 'utf8');
|
|
491
493
|
|
|
492
494
|
const intercept = new Map([
|
|
493
495
|
// CodeMirror assets (CDN)
|
|
@@ -517,6 +519,14 @@ async function main() {
|
|
|
517
519
|
'https://raw.githubusercontent.com/eyereasoner/eyeling/refs/heads/main/eyeling.js',
|
|
518
520
|
{ ct: 'application/javascript', body: localEyeling },
|
|
519
521
|
],
|
|
522
|
+
[
|
|
523
|
+
'https://raw.githubusercontent.com/eyereasoner/eyeling/refs/heads/main/examples/sudoku.n3',
|
|
524
|
+
{ ct: 'text/plain', body: localSudoku },
|
|
525
|
+
],
|
|
526
|
+
[
|
|
527
|
+
'https://raw.githubusercontent.com/eyereasoner/eyeling/refs/heads/main/examples/builtin/sudoku.js',
|
|
528
|
+
{ ct: 'application/javascript', body: localSudokuBuiltin },
|
|
529
|
+
],
|
|
520
530
|
]);
|
|
521
531
|
|
|
522
532
|
await cdp.send(
|
|
@@ -641,6 +651,21 @@ async function main() {
|
|
|
641
651
|
})()`);
|
|
642
652
|
}
|
|
643
653
|
|
|
654
|
+
async function loadUrlIntoEditor(url) {
|
|
655
|
+
const payload = JSON.stringify(String(url));
|
|
656
|
+
await evalInPage(`(() => {
|
|
657
|
+
const input = document.getElementById('n3-uri');
|
|
658
|
+
const asBackground = document.getElementById('load-as-background');
|
|
659
|
+
const btn = document.getElementById('load-uri-btn');
|
|
660
|
+
if (!input) throw new Error('n3-uri input not found');
|
|
661
|
+
if (!btn) throw new Error('load-uri-btn not found');
|
|
662
|
+
input.value = ${payload};
|
|
663
|
+
if (asBackground) asBackground.checked = false;
|
|
664
|
+
btn.click();
|
|
665
|
+
return true;
|
|
666
|
+
})()`);
|
|
667
|
+
}
|
|
668
|
+
|
|
644
669
|
async function waitForState(label, predicate, timeoutMs = 60000) {
|
|
645
670
|
const deadline = Date.now() + timeoutMs;
|
|
646
671
|
let last = { status: '', output: '', highlighted: [] };
|
|
@@ -731,6 +756,26 @@ ${JSON.stringify(last, null, 2)}`);
|
|
|
731
756
|
);
|
|
732
757
|
ok('playground renders log:outputString cleanly in Output');
|
|
733
758
|
|
|
759
|
+
// 5) URL-loaded repository examples should auto-load matching examples/builtin/<stem>.js.
|
|
760
|
+
await loadUrlIntoEditor('https://raw.githubusercontent.com/eyereasoner/eyeling/refs/heads/main/examples/sudoku.n3');
|
|
761
|
+
await waitForState(
|
|
762
|
+
'sudoku URL loaded with companion builtin',
|
|
763
|
+
(st) => /loaded n3 into the editor and loaded its example builtin/i.test(String(st.status || '')),
|
|
764
|
+
20000,
|
|
765
|
+
);
|
|
766
|
+
await clickRun();
|
|
767
|
+
const sudoku = await waitForState(
|
|
768
|
+
'URL-loaded Sudoku example completion',
|
|
769
|
+
(st) =>
|
|
770
|
+
String(st.status || '')
|
|
771
|
+
.trim()
|
|
772
|
+
.startsWith('Done') && /The puzzle is solved/i.test(String(st.output || '')),
|
|
773
|
+
60000,
|
|
774
|
+
);
|
|
775
|
+
assert.match(sudoku.output, /Completed grid/i, 'Expected Sudoku rendered output');
|
|
776
|
+
assert.match(sudoku.output, /unique valid Sudoku solution/i, 'Expected Sudoku builtin-backed result');
|
|
777
|
+
ok('playground auto-loads a companion example builtin for URL-loaded Sudoku');
|
|
778
|
+
|
|
734
779
|
// Ensure no uncaught runtime exceptions.
|
|
735
780
|
assert.equal(exceptions.length, 0, `Uncaught exceptions in demo.html: ${JSON.stringify(exceptions[0] || {})}`);
|
|
736
781
|
|