eyeling 1.24.19 → 1.24.23
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 -2
- package/package.json +1 -1
- package/test/playground.test.js +52 -22
package/HANDBOOK.md
CHANGED
|
@@ -3760,11 +3760,11 @@ 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
|
|
3763
|
+
If a generated embedded-state link is still very long, the playground reveals **Create Gist share**. That option asks for a GitHub token with gist permission, stores the compact playground state as a secret Gist JSON file, and copies a small `?stateurl=...` playground link that fetches the state file client-side. The token is stored only in that browser's `localStorage`, the Gist is created by a POST request with `referrerPolicy: "no-referrer"`, and the shared playground URL no longer contains the large encoded program.
|
|
3764
3764
|
|
|
3765
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.
|
|
3766
3766
|
|
|
3767
|
-
For compatibility, older `?edit=`, `?program=`, `?url=`, compact `?state=`, and hash-based links are
|
|
3767
|
+
For compatibility, older `?edit=`, `?program=`, `?url=`, compact `?state=`, `?stateurl=`, and hash-based links are accepted when opened. The old `/demo` entry point is also kept as a redirect to the canonical `/playground` page.
|
|
3768
3768
|
|
|
3769
3769
|
### I.6 What the playground is good for
|
|
3770
3770
|
|
package/package.json
CHANGED
package/test/playground.test.js
CHANGED
|
@@ -722,7 +722,8 @@ 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
|
-
|
|
725
|
+
gistShareHidden: document.getElementById('create-gist-share-btn') ? !!document.getElementById('create-gist-share-btn').hidden : true,
|
|
726
|
+
gistShareText: document.getElementById('create-gist-share-btn') ? String(document.getElementById('create-gist-share-btn').textContent || '').trim() : '',
|
|
726
727
|
backgroundStatus: document.getElementById('background-status') ? String(document.getElementById('background-status').textContent || '') : '',
|
|
727
728
|
href: String(window.location.href || ''),
|
|
728
729
|
highlighted,
|
|
@@ -783,21 +784,33 @@ async function main() {
|
|
|
783
784
|
return {
|
|
784
785
|
url,
|
|
785
786
|
length: url.length,
|
|
786
|
-
threshold: window.
|
|
787
|
-
|
|
788
|
-
|
|
787
|
+
threshold: window.__eyelingPlaygroundGistShareThreshold,
|
|
788
|
+
needsGistShare: window.__eyelingPlaygroundShouldOfferGistShare(url),
|
|
789
|
+
hasEmbeddedState: window.__eyelingPlaygroundShareUrlHasEmbeddedState(url),
|
|
790
|
+
stateUrlShare: window.__eyelingPlaygroundMakeShareUrlFromStateUrl('https://gist.githubusercontent.com/user/id/raw/eyeling-playground-state.json'),
|
|
789
791
|
};
|
|
790
792
|
})()`);
|
|
791
793
|
}
|
|
792
794
|
|
|
793
|
-
async function
|
|
794
|
-
const payload = JSON.stringify({
|
|
795
|
+
async function createGistBackedShareUrlWithStubInPage(token, response) {
|
|
796
|
+
const payload = JSON.stringify({ token: String(token), response });
|
|
795
797
|
return await evalInPage(`(async () => {
|
|
796
798
|
const args = ${payload};
|
|
797
799
|
const originalFetch = window.fetch;
|
|
798
800
|
let seen = null;
|
|
799
801
|
window.fetch = async (url, options) => {
|
|
800
|
-
|
|
802
|
+
options = options || {};
|
|
803
|
+
seen = {
|
|
804
|
+
url: String(url || ''),
|
|
805
|
+
options: {
|
|
806
|
+
method: options.method,
|
|
807
|
+
headers: options.headers,
|
|
808
|
+
body: options.body,
|
|
809
|
+
cache: options.cache,
|
|
810
|
+
referrerPolicy: options.referrerPolicy,
|
|
811
|
+
hasSignal: !!options.signal,
|
|
812
|
+
},
|
|
813
|
+
};
|
|
801
814
|
return {
|
|
802
815
|
ok: true,
|
|
803
816
|
status: 200,
|
|
@@ -805,8 +818,15 @@ async function main() {
|
|
|
805
818
|
};
|
|
806
819
|
};
|
|
807
820
|
try {
|
|
808
|
-
const
|
|
809
|
-
|
|
821
|
+
const state = {
|
|
822
|
+
edit: (window.__cmStubsById && window.__cmStubsById['n3-editor']) ? window.__cmStubsById['n3-editor'].getValue() : '',
|
|
823
|
+
url: '',
|
|
824
|
+
loadbg: false,
|
|
825
|
+
proofcomments: false,
|
|
826
|
+
httpsderef: true,
|
|
827
|
+
};
|
|
828
|
+
const shareUrl = await window.__eyelingPlaygroundCreateGistBackedShareUrl(state, args.token);
|
|
829
|
+
return { shareUrl, seen };
|
|
810
830
|
} finally {
|
|
811
831
|
window.fetch = originalFetch;
|
|
812
832
|
}
|
|
@@ -959,11 +979,11 @@ ${JSON.stringify(last, null, 2)}`);
|
|
|
959
979
|
assert.match(compactShareUrl, /[?&]state=/, 'Expected an on-demand compact state parameter');
|
|
960
980
|
assert.doesNotMatch(compactShareUrl, /[?&](?:edit|program)=/, 'Expected share link to avoid raw edit/program params');
|
|
961
981
|
assert.ok(compactShareUrl.length < playgroundUrl.length + encodeURIComponent(outputStringProgram).length, 'Expected compact share URL to be shorter than raw editor URL');
|
|
962
|
-
assert.equal(renderedAgain.
|
|
982
|
+
assert.equal(renderedAgain.gistShareHidden, true, 'Expected ordinary compact share links to keep the Gist share option hidden');
|
|
963
983
|
endTest();
|
|
964
984
|
|
|
965
|
-
// 6) Very large edited programs should offer a
|
|
966
|
-
beginTest('playground offers a
|
|
985
|
+
// 6) Very large edited programs should offer a Gist-backed share option instead of only a huge link.
|
|
986
|
+
beginTest('playground offers a Gist-backed option for oversized state links');
|
|
967
987
|
const longShareProgram = Array.from({ length: 1400 }, (_, i) => {
|
|
968
988
|
const n = String(i).padStart(4, '0');
|
|
969
989
|
const token = ((i * 2654435761) >>> 0).toString(36).padStart(7, '0');
|
|
@@ -972,17 +992,27 @@ ${JSON.stringify(last, null, 2)}`);
|
|
|
972
992
|
await setProgram(longShareProgram);
|
|
973
993
|
const longShare = await makeShareUrlDiagnosticsInPage();
|
|
974
994
|
assert.ok(longShare.length > longShare.threshold, `Expected test share URL to exceed threshold (${longShare.length} <= ${longShare.threshold})`);
|
|
975
|
-
assert.equal(longShare.
|
|
976
|
-
assert.
|
|
977
|
-
assert.
|
|
978
|
-
|
|
979
|
-
|
|
995
|
+
assert.equal(longShare.needsGistShare, true, 'Expected oversized embedded state to request a Gist-backed sharing option');
|
|
996
|
+
assert.equal(longShare.hasEmbeddedState, true, 'Expected oversized edited program to be an embedded state link');
|
|
997
|
+
assert.match(longShare.stateUrlShare, /[?&]stateurl=/, 'Expected stateurl= links to be supported for externally stored state');
|
|
998
|
+
assert.doesNotMatch(longShare.stateUrlShare, /[?&]state=/, 'Expected externally stored state links to avoid embedded state payloads');
|
|
999
|
+
const gistShare = await createGistBackedShareUrlWithStubInPage('github-gist-token-123', {
|
|
1000
|
+
files: {
|
|
1001
|
+
'eyeling-playground-state.json': {
|
|
1002
|
+
raw_url: 'https://gist.githubusercontent.com/user/id/raw/eyeling-playground-state.json',
|
|
1003
|
+
},
|
|
1004
|
+
},
|
|
980
1005
|
});
|
|
981
|
-
assert.
|
|
982
|
-
assert.
|
|
983
|
-
assert.
|
|
984
|
-
assert.equal(
|
|
985
|
-
assert.
|
|
1006
|
+
assert.match(gistShare.shareUrl, /[?&]stateurl=/, 'Expected Gist-backed share URL to use a compact stateurl parameter');
|
|
1007
|
+
assert.doesNotMatch(gistShare.shareUrl, /[?&]state=/, 'Expected Gist-backed share URL not to embed the compressed state');
|
|
1008
|
+
assert.ok(gistShare.shareUrl.length < 300, 'Expected Gist-backed share URL to stay small');
|
|
1009
|
+
assert.equal(gistShare.seen.url, 'https://api.github.com/gists', 'Expected GitHub Gist create endpoint');
|
|
1010
|
+
assert.equal(gistShare.seen.options.method, 'POST', 'Expected GitHub Gist API POST request');
|
|
1011
|
+
assert.equal(gistShare.seen.options.headers.Authorization, 'Bearer github-gist-token-123', 'Expected bearer token authorization');
|
|
1012
|
+
assert.equal(gistShare.seen.options.referrerPolicy, 'no-referrer', 'Expected GitHub Gist API request not to send a long Referer');
|
|
1013
|
+
assert.match(String(gistShare.seen.options.body || ''), /"public":false/, 'Expected a secret Gist, not a public Gist');
|
|
1014
|
+
assert.match(String(gistShare.seen.options.body || ''), /eyeling-playground-state\.json/, 'Expected shared state to be saved as JSON');
|
|
1015
|
+
assert.match(String(gistShare.seen.options.body || ''), /\\"e\\":/, 'Expected compact editor state in the Gist payload');
|
|
986
1016
|
endTest();
|
|
987
1017
|
|
|
988
1018
|
// 7) log:query can produce Turtle; that should stay in plain source output without Markdown tabs.
|