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 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 (const spec of builtinModules) loadBuiltinModule(spec);
8707
- } else if (typeof builtinModules === 'string' && builtinModules) {
8708
- loadBuiltinModule(builtinModules);
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 (const spec of builtinModules) loadBuiltinModule(spec);
8684
- } else if (typeof builtinModules === 'string' && builtinModules) {
8685
- loadBuiltinModule(builtinModules);
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 (const spec of builtinModules) loadBuiltinModule(spec);
3389
- } else if (typeof builtinModules === 'string' && builtinModules) {
3390
- loadBuiltinModule(builtinModules);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.23.3",
3
+ "version": "1.23.4",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [
@@ -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