eyeling 1.24.23 → 1.24.24

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
@@ -3733,7 +3733,7 @@ The output behavior also adapts to the kind of N3 program being run. In some cas
3733
3733
 
3734
3734
  For Markdown-oriented `log:outputString` examples, the output pane has two views: a rendered Markdown view and a Markdown source view. Those tabs appear only when the actual output looks like Markdown; Turtle or other plain output stays in the source editor without the Markdown toggle. The rendered view is selected by default for Markdown output, while the source view keeps the exact generated Markdown available for copying, inspection, or comparison.
3735
3735
 
3736
- Repository example reports often contain relative source links that are written for the checked-in files under `examples/output/*.md`. When such an example is loaded into the playground from a raw URL, the rendered Markdown view resolves those relative links against the corresponding static output page rather than against `/playground`, so links like `../name.n3` and `../input/name.trig` continue to point to the intended example files.
3736
+ Repository example reports often contain relative source links that are written for the checked-in files under `examples/output/*.md`. When such an example is loaded into the playground from a raw URL, or restored later from compact/Gist-backed state, the rendered Markdown view resolves those relative links against the corresponding static output page rather than against `/playground`, so links like `../name.n3` and `../input/name.trig` continue to point to the intended example files. The playground preserves this base in shared state when possible and can also recover it from the injected `@base <.../examples/name.n3>` line.
3737
3737
 
3738
3738
  ### I.4 Error handling and explainability
3739
3739
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.24.23",
3
+ "version": "1.24.24",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [
@@ -873,6 +873,11 @@ ${JSON.stringify(last, null, 2)}`);
873
873
  const outputStringProgram = `@prefix : <#> .
874
874
  @prefix log: <http://www.w3.org/2000/10/swap/log#> .
875
875
  :report log:outputString "## Hello from output string\n\nLine 2 with **bold** and [Eyeling](https://example.org/eyeling)\n" .
876
+ `;
877
+ const baseOnlyMarkdownProgram = `@base <https://raw.githubusercontent.com/eyereasoner/eyeling/refs/heads/main/examples/smoke-arithmetic.n3> .
878
+ @prefix : <#> .
879
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
880
+ :report log:outputString "# stateurl link base\n\n[N3 rules](../smoke-arithmetic.n3)\n[Input TriG](../input/smoke-arithmetic.trig)\n" .
876
881
  `;
877
882
  const logQueryTurtleProgram = `@prefix : <#> .
878
883
  @prefix log: <http://www.w3.org/2000/10/swap/log#> .
@@ -972,17 +977,45 @@ ${JSON.stringify(last, null, 2)}`);
972
977
  assert.equal(renderedAgain.renderedTabSelected, true, 'Expected Rendered tab to be selectable again');
973
978
  endTest();
974
979
 
975
- // 5) Normal editing should not keep rewriting the browser URL with raw N3 content.
980
+ // 5) Shared state files may only restore editor text. If that text came from a repository
981
+ // example, the injected @base line should still give Markdown links the static output-page base.
982
+ beginTest('playground resolves Markdown links from restored example base directives');
983
+ await setProgram(baseOnlyMarkdownProgram);
984
+ await clickRun();
985
+ const baseOnlyMarkdown = await waitForState(
986
+ 'base-only Markdown output completion',
987
+ (st) =>
988
+ String(st.status || '')
989
+ .trim()
990
+ .startsWith('Done') && /stateurl link base/i.test(String(st.output || '')),
991
+ 20000,
992
+ );
993
+ assert.match(
994
+ baseOnlyMarkdown.renderedHtml,
995
+ new RegExp('href="' + started.baseUrl.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '/examples/smoke-arithmetic\\.n3"'),
996
+ 'Expected restored-state Markdown source links to resolve against the static output page',
997
+ );
998
+ assert.match(
999
+ baseOnlyMarkdown.renderedHtml,
1000
+ new RegExp('href="' + started.baseUrl.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '/examples/input/smoke-arithmetic\\.trig"'),
1001
+ 'Expected restored-state Markdown TriG links to resolve against the static output page',
1002
+ );
1003
+ endTest();
1004
+
1005
+ // 6) Normal editing should not keep rewriting the browser URL with raw N3 content.
976
1006
  beginTest('playground keeps the live URL short and creates compact share links on demand');
977
- assert.doesNotMatch(renderedAgain.href, /[?&](?:edit|program)=/, 'Expected live URL to avoid raw editor content');
1007
+ await setProgram(outputStringProgram);
1008
+ const compactShareState = await getPlaygroundState();
1009
+ assert.doesNotMatch(compactShareState.href, /[?&](?:edit|program)=/, 'Expected live URL to avoid raw editor content');
978
1010
  const compactShareUrl = await makeShareUrlInPage();
1011
+ const rawEditorUrlLength = playgroundUrl.length + '?edit='.length + encodeURIComponent(outputStringProgram).length;
979
1012
  assert.match(compactShareUrl, /[?&]state=/, 'Expected an on-demand compact state parameter');
980
1013
  assert.doesNotMatch(compactShareUrl, /[?&](?:edit|program)=/, 'Expected share link to avoid raw edit/program params');
981
- assert.ok(compactShareUrl.length < playgroundUrl.length + encodeURIComponent(outputStringProgram).length, 'Expected compact share URL to be shorter than raw editor URL');
982
- assert.equal(renderedAgain.gistShareHidden, true, 'Expected ordinary compact share links to keep the Gist share option hidden');
1014
+ assert.ok(compactShareUrl.length < rawEditorUrlLength, 'Expected compact share URL to be shorter than raw editor URL');
1015
+ assert.equal(compactShareState.gistShareHidden, true, 'Expected ordinary compact share links to keep the Gist share option hidden');
983
1016
  endTest();
984
1017
 
985
- // 6) Very large edited programs should offer a Gist-backed share option instead of only a huge link.
1018
+ // 7) Very large edited programs should offer a Gist-backed share option instead of only a huge link.
986
1019
  beginTest('playground offers a Gist-backed option for oversized state links');
987
1020
  const longShareProgram = Array.from({ length: 1400 }, (_, i) => {
988
1021
  const n = String(i).padStart(4, '0');
@@ -1015,7 +1048,7 @@ ${JSON.stringify(last, null, 2)}`);
1015
1048
  assert.match(String(gistShare.seen.options.body || ''), /\\"e\\":/, 'Expected compact editor state in the Gist payload');
1016
1049
  endTest();
1017
1050
 
1018
- // 7) log:query can produce Turtle; that should stay in plain source output without Markdown tabs.
1051
+ // 8) log:query can produce Turtle; that should stay in plain source output without Markdown tabs.
1019
1052
  beginTest('playground hides markdown tabs for Turtle log:query output');
1020
1053
  await setProgram(logQueryTurtleProgram);
1021
1054
  await clickRun();
@@ -1035,7 +1068,7 @@ ${JSON.stringify(last, null, 2)}`);
1035
1068
  assert.equal(logQueryTurtle.sourceHidden, false, 'Expected Turtle log:query output to show source directly');
1036
1069
  endTest();
1037
1070
 
1038
- // 8) URL-loaded examples should auto-load matching examples/input/<stem>.trig and run in RDF/TriG mode.
1071
+ // 9) URL-loaded examples should auto-load matching examples/input/<stem>.trig and run in RDF/TriG mode.
1039
1072
  beginTest('playground auto-loads companion TriG sidecars and uses RDF/TriG mode');
1040
1073
  await loadUrlIntoEditor('https://raw.githubusercontent.com/eyereasoner/eyeling/refs/heads/main/examples/smoke-arithmetic.n3');
1041
1074
  const smokeLoaded = await waitForState(
@@ -1082,7 +1115,7 @@ ${JSON.stringify(last, null, 2)}`);
1082
1115
  assert.equal(smokeRenderedAgain.sourceHidden, true, 'Expected smoke-arithmetic source editor to hide again');
1083
1116
  endTest();
1084
1117
 
1085
- // 9) URL-loaded repository examples should auto-load matching examples/builtin/<stem>.js.
1118
+ // 10) URL-loaded repository examples should auto-load matching examples/builtin/<stem>.js.
1086
1119
  beginTest('playground auto-loads a companion example builtin for URL-loaded Sudoku');
1087
1120
  await loadUrlIntoEditor('https://raw.githubusercontent.com/eyereasoner/eyeling/refs/heads/main/examples/sudoku.n3');
1088
1121
  await waitForState(