eyeling 1.24.17 → 1.24.18
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 +2 -0
- package/package.json +1 -1
- package/test/playground.test.js +35 -5
package/HANDBOOK.md
CHANGED
|
@@ -3760,6 +3760,8 @@ When a user does want a portable link, the **Copy share link** button creates on
|
|
|
3760
3760
|
- edited programs are shared with a compact compressed `?state=...` payload,
|
|
3761
3761
|
- default option values are omitted from that payload to keep links small.
|
|
3762
3762
|
|
|
3763
|
+
If a generated compact share link is still very long, the playground reveals an **Open shortener** option. The threshold is intentionally conservative, and the shortener handoff is explicit rather than automatic: the browser opens a TinyURL creation page with the generated share URL only after the user chooses that option. This avoids silently sending encoded editor content to a third-party service.
|
|
3764
|
+
|
|
3763
3765
|
This keeps everyday use pleasant while preserving the important tutorial and issue-reporting workflow: a link can still capture the imported resource, the local editable overlay, background-knowledge mode, proof-comments mode, and HTTPS-dereferencing mode.
|
|
3764
3766
|
|
|
3765
3767
|
For compatibility, older `?edit=`, `?program=`, `?url=`, compact `?state=`, and hash-based links are still accepted when opened. The old `/demo` entry point is also kept as a redirect to the canonical `/playground` page.
|
package/package.json
CHANGED
package/test/playground.test.js
CHANGED
|
@@ -722,6 +722,7 @@ async function main() {
|
|
|
722
722
|
renderedTabSelected: renderedTab ? renderedTab.getAttribute('aria-selected') === 'true' : false,
|
|
723
723
|
sourceTabSelected: sourceTab ? sourceTab.getAttribute('aria-selected') === 'true' : false,
|
|
724
724
|
shareStatus: document.getElementById('share-status') ? String(document.getElementById('share-status').textContent || '') : '',
|
|
725
|
+
shortenerHidden: document.getElementById('open-shortener-btn') ? !!document.getElementById('open-shortener-btn').hidden : true,
|
|
725
726
|
backgroundStatus: document.getElementById('background-status') ? String(document.getElementById('background-status').textContent || '') : '',
|
|
726
727
|
href: String(window.location.href || ''),
|
|
727
728
|
highlighted,
|
|
@@ -776,6 +777,19 @@ async function main() {
|
|
|
776
777
|
return await evalInPage(`window.__eyelingPlaygroundMakeShareUrl()`);
|
|
777
778
|
}
|
|
778
779
|
|
|
780
|
+
async function makeShareUrlDiagnosticsInPage() {
|
|
781
|
+
return await evalInPage(`(async () => {
|
|
782
|
+
const url = await window.__eyelingPlaygroundMakeShareUrl();
|
|
783
|
+
return {
|
|
784
|
+
url,
|
|
785
|
+
length: url.length,
|
|
786
|
+
threshold: window.__eyelingPlaygroundShareUrlShortenerThreshold,
|
|
787
|
+
needsShortener: window.__eyelingPlaygroundShouldOfferShortener(url),
|
|
788
|
+
shortenerUrl: window.__eyelingPlaygroundMakeShareUrlShortenerUrl(url),
|
|
789
|
+
};
|
|
790
|
+
})()`);
|
|
791
|
+
}
|
|
792
|
+
|
|
779
793
|
async function loadUrlIntoEditor(url) {
|
|
780
794
|
const payload = JSON.stringify(String(url));
|
|
781
795
|
await evalInPage(`(() => {
|
|
@@ -922,9 +936,25 @@ ${JSON.stringify(last, null, 2)}`);
|
|
|
922
936
|
assert.match(compactShareUrl, /[?&]state=/, 'Expected an on-demand compact state parameter');
|
|
923
937
|
assert.doesNotMatch(compactShareUrl, /[?&](?:edit|program)=/, 'Expected share link to avoid raw edit/program params');
|
|
924
938
|
assert.ok(compactShareUrl.length < playgroundUrl.length + encodeURIComponent(outputStringProgram).length, 'Expected compact share URL to be shorter than raw editor URL');
|
|
939
|
+
assert.equal(renderedAgain.shortenerHidden, true, 'Expected ordinary compact share links to keep the shortener option hidden');
|
|
940
|
+
endTest();
|
|
941
|
+
|
|
942
|
+
// 6) Very large edited programs should offer a URL shortener handoff instead of only a huge link.
|
|
943
|
+
beginTest('playground offers a URL shortener option for oversized share links');
|
|
944
|
+
const longShareProgram = Array.from({ length: 1400 }, (_, i) => {
|
|
945
|
+
const n = String(i).padStart(4, '0');
|
|
946
|
+
const token = ((i * 2654435761) >>> 0).toString(36).padStart(7, '0');
|
|
947
|
+
return `:s${n}_${token} :p${token}_${n} "literal-${n}-${token}-${i * 9973}" .`;
|
|
948
|
+
}).join('\n');
|
|
949
|
+
await setProgram(longShareProgram);
|
|
950
|
+
const longShare = await makeShareUrlDiagnosticsInPage();
|
|
951
|
+
assert.ok(longShare.length > longShare.threshold, `Expected test share URL to exceed threshold (${longShare.length} <= ${longShare.threshold})`);
|
|
952
|
+
assert.equal(longShare.needsShortener, true, 'Expected oversized share URL to request a shortener option');
|
|
953
|
+
assert.match(longShare.shortenerUrl, /^https:\/\/tinyurl\.com\/create\.php\?url=/, 'Expected TinyURL create URL handoff');
|
|
954
|
+
assert.ok(longShare.shortenerUrl.includes(encodeURIComponent(longShare.url).slice(0, 40)), 'Expected shortener URL to carry the generated share URL');
|
|
925
955
|
endTest();
|
|
926
956
|
|
|
927
|
-
//
|
|
957
|
+
// 7) log:query can produce Turtle; that should stay in plain source output without Markdown tabs.
|
|
928
958
|
beginTest('playground hides markdown tabs for Turtle log:query output');
|
|
929
959
|
await setProgram(logQueryTurtleProgram);
|
|
930
960
|
await clickRun();
|
|
@@ -944,7 +974,7 @@ ${JSON.stringify(last, null, 2)}`);
|
|
|
944
974
|
assert.equal(logQueryTurtle.sourceHidden, false, 'Expected Turtle log:query output to show source directly');
|
|
945
975
|
endTest();
|
|
946
976
|
|
|
947
|
-
//
|
|
977
|
+
// 8) URL-loaded examples should auto-load matching examples/input/<stem>.trig and run in RDF/TriG mode.
|
|
948
978
|
beginTest('playground auto-loads companion TriG sidecars and uses RDF/TriG mode');
|
|
949
979
|
await loadUrlIntoEditor('https://raw.githubusercontent.com/eyereasoner/eyeling/refs/heads/main/examples/smoke-arithmetic.n3');
|
|
950
980
|
const smokeLoaded = await waitForState(
|
|
@@ -991,7 +1021,7 @@ ${JSON.stringify(last, null, 2)}`);
|
|
|
991
1021
|
assert.equal(smokeRenderedAgain.sourceHidden, true, 'Expected smoke-arithmetic source editor to hide again');
|
|
992
1022
|
endTest();
|
|
993
1023
|
|
|
994
|
-
//
|
|
1024
|
+
// 9) URL-loaded repository examples should auto-load matching examples/builtin/<stem>.js.
|
|
995
1025
|
beginTest('playground auto-loads a companion example builtin for URL-loaded Sudoku');
|
|
996
1026
|
await loadUrlIntoEditor('https://raw.githubusercontent.com/eyereasoner/eyeling/refs/heads/main/examples/sudoku.n3');
|
|
997
1027
|
await waitForState(
|
|
@@ -1015,12 +1045,12 @@ ${JSON.stringify(last, null, 2)}`);
|
|
|
1015
1045
|
assert.match(sudoku.output, /unique valid Sudoku solution/i, 'Expected Sudoku builtin-backed result');
|
|
1016
1046
|
endTest();
|
|
1017
1047
|
|
|
1018
|
-
//
|
|
1048
|
+
// 10) Ensure no uncaught runtime exceptions.
|
|
1019
1049
|
beginTest('playground has no uncaught runtime exceptions');
|
|
1020
1050
|
assert.equal(exceptions.length, 0, `Uncaught exceptions in playground.html: ${JSON.stringify(exceptions[0] || {})}`);
|
|
1021
1051
|
endTest();
|
|
1022
1052
|
|
|
1023
|
-
//
|
|
1053
|
+
// 11) Console errors are noisy and often indicate a broken UI.
|
|
1024
1054
|
// (We suppress known noise like /favicon.ico on the server.)
|
|
1025
1055
|
beginTest('playground has no console errors');
|
|
1026
1056
|
assert.equal(consoleErrors.length, 0, `Console errors in playground.html: ${JSON.stringify(consoleErrors[0] || {})}`);
|