yourjs-box 1.3.1 → 1.4.0

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/README.md CHANGED
@@ -24,7 +24,8 @@ should be loaded into the console inside of the script tag:
24
24
  </div>
25
25
  ```
26
26
 
27
- The console fills its container. The script is also available from unpkg at
27
+ The console fills its container (and is never less than 150px tall). The
28
+ script is also available from unpkg at
28
29
  `https://unpkg.com/yourjs-box@1/dist/yourjs-box.min.js`.
29
30
 
30
31
  ### Code Blocks
@@ -140,6 +141,43 @@ up in the output as a collapsed block labelled with whatever came after the
140
141
  prefix (and optional colon), or "Hidden code" if nothing did. Clicking the
141
142
  label shows or hides the code.
142
143
 
144
+ ### JavaScript API
145
+
146
+ Loading the script also provides `YourJSBox` for creating consoles from
147
+ JavaScript (eg. in React, Vue or any page that adds content dynamically). A
148
+ script tag in the `<head>` only provides the API, while one in the `<body>` is
149
+ also replaced by a console (with the code inside of it) as usual.
150
+
151
+ ```html
152
+ <script src="https://cdn.jsdelivr.net/npm/yourjs-box@1/dist/yourjs-box.min.js"></script>
153
+ ```
154
+
155
+ ```js
156
+ const box = YourJSBox.create({
157
+ target: '#lesson',
158
+ code: "// Say hello \\\\\nconsole.log('Hello!');",
159
+ theme: 'dark',
160
+ });
161
+
162
+ // Later (eg. when a component is removed):
163
+ box.destroy();
164
+ ```
165
+
166
+ `YourJSBox.create(options)` returns `{element, destroy}` where `element` is the
167
+ console's IFRAME and `destroy()` removes it, stops its code and closes its
168
+ pop-out window (in window mode it also restores the page's `console`
169
+ functions). The options are:
170
+
171
+ | Option | Description |
172
+ | --- | --- |
173
+ | `target` | Required. The element (or a CSS selector for it) that the console is placed relative to. |
174
+ | `placement` | Where the console goes: `"fill"` (default) replaces the target's contents, `"append"` and `"prepend"` add it inside of the target, `"replace"` replaces the target itself and `"before"` and `"after"` add it next to the target. |
175
+ | `height` | The CSS height of the console (a number is treated as pixels). Defaults to `"100%"` so the console fills its container. It is never less than 150px. |
176
+ | `code` | The code that the console starts with. |
177
+ | `runner`, `blockType`, `showResults`, `hidePrefix`, `dividerOrient`, `theme`, `librariesUrl` | The same as the `data-*` attributes above. |
178
+
179
+ `YourJSBox.version` is the version of JS Box that was loaded.
180
+
143
181
  ### Where Code Runs
144
182
 
145
183
  The console's interface is always in an IFRAME so that its styles and the
@@ -1,4 +1,4 @@
1
- /*! yourjs-box v1.3.1 | (c) 2023-present Christopher West | MIT License | https://github.com/westc/yourjs-box */
1
+ /*! yourjs-box v1.4.0 | (c) 2023-present Christopher West | MIT License | https://github.com/westc/yourjs-box */
2
2
  (() => {
3
3
  /**
4
4
  * Viewer IFRAME's CSS code
@@ -9,7 +9,7 @@
9
9
  * Information about this package (eg. its version).
10
10
  * @type {{name: string, version: string, homepage: string, repoUrl: string, bugsUrl: string}}
11
11
  */
12
- const PACKAGE_INFO = {"name":"yourjs-box","version":"1.3.1","homepage":"https://westc.github.io/yourjs-box/","repoUrl":"https://github.com/westc/yourjs-box","bugsUrl":"https://github.com/westc/yourjs-box/issues"};
12
+ const PACKAGE_INFO = {"name":"yourjs-box","version":"1.4.0","homepage":"https://westc.github.io/yourjs-box/","repoUrl":"https://github.com/westc/yourjs-box","bugsUrl":"https://github.com/westc/yourjs-box/issues"};
13
13
  /**
14
14
  * Viewer IFRAME's HTML code
15
15
  * @type {string}
@@ -130,6 +130,9 @@
130
130
  const RESULT_KEY = `yourjs-box.result.${Math.random().toString(36).slice(2)}`;
131
131
  globalThis[Symbol.for(RESULT_KEY)] = reportResult;
132
132
 
133
+ // The console functions that were replaced so that they can be restored.
134
+ const consoleWrappers = [];
135
+
133
136
  // Overrides for console functions. In window mode this also captures
134
137
  // anything else that the page logs, just like the browser's console.
135
138
  for (const key of [
@@ -139,12 +142,14 @@
139
142
  ]) {
140
143
  const original = console[key];
141
144
  if ('function' !== typeof original) continue;
142
- console[key] = function(...args) {
145
+ const wrapper = function(...args) {
143
146
  handleConsoleCall(key, args);
144
147
 
145
148
  // Calls and returns the original console function.
146
149
  return original.apply(this, arguments);
147
150
  };
151
+ console[key] = wrapper;
152
+ consoleWrappers.push({key, original, wrapper});
148
153
  }
149
154
 
150
155
  /**
@@ -251,13 +256,29 @@
251
256
  if (value !== undefined) addLog('result', [value], {}, 'string' === typeof value ? 1 : 0);
252
257
  }
253
258
 
254
- addEventListener('error', evt => {
259
+ function onError(evt) {
255
260
  reportUncaught(evt.error !== undefined ? evt.error : evt.message);
256
- });
257
-
258
- addEventListener('unhandledrejection', evt => {
261
+ }
262
+ function onUnhandledRejection(evt) {
259
263
  reportUncaught(evt.reason, true);
260
- });
264
+ }
265
+ addEventListener('error', onError);
266
+ addEventListener('unhandledrejection', onUnhandledRejection);
267
+
268
+ /**
269
+ * Stops capturing what is logged (used when a console in window mode is
270
+ * destroyed). Each console function is restored unless something else has
271
+ * replaced it since.
272
+ */
273
+ function destroy() {
274
+ removeEventListener('error', onError);
275
+ removeEventListener('unhandledrejection', onUnhandledRejection);
276
+ delete globalThis[Symbol.for(RESULT_KEY)];
277
+ for (const {key, original, wrapper} of consoleWrappers) {
278
+ if (console[key] === wrapper) console[key] = original;
279
+ }
280
+ clearLogs();
281
+ }
261
282
 
262
283
  /**
263
284
  * @param {*} error
@@ -780,7 +801,7 @@
780
801
  groupIds = [];
781
802
  }
782
803
 
783
- return {clearLogs, runCode, sendDescriptionFor};
804
+ return {clearLogs, destroy, runCode, sendDescriptionFor};
784
805
  }
785
806
 
786
807
 
@@ -850,6 +871,10 @@
850
871
  start();
851
872
 
852
873
  return {
874
+ destroy() {
875
+ worker.terminate();
876
+ if (blobUrl) URL.revokeObjectURL(blobUrl);
877
+ },
853
878
  apply(func, args) {
854
879
  if (func === 'reset') {
855
880
  worker.terminate();
@@ -873,6 +898,9 @@
873
898
  function createWindowRunner(onMessage) {
874
899
  const runner = createRunner(onMessage, {mode: 'window', ownUrl: OWN_URL});
875
900
  return {
901
+ destroy() {
902
+ runner.destroy();
903
+ },
876
904
  apply(func, args) {
877
905
  // Anything the code defined stays defined so a reset can only forget
878
906
  // the logged values.
@@ -883,13 +911,20 @@
883
911
  }
884
912
 
885
913
  /**
886
- * Function executed when the script is included in a document.
887
- * @param {HTMLScriptElement} script
888
- * This is the current script but also the placeholder for where the
889
- * console will be inserted into the DOM.
914
+ * Creates a console.
915
+ * @param {Object} options
916
+ * @param {string} options.code
917
+ * The code that the console starts with.
918
+ * @param {{[name: string]: string}} options.dataset
919
+ * The options for the console in the same form as the data attributes of
920
+ * a script tag (eg. `{runner: 'window', hidePrefix: 'HIDE'}`).
921
+ * @param {string=} options.height
922
+ * Optional, defaults to `"100%"`. The CSS height of the console.
923
+ * @param {(element: HTMLIFrameElement) => void} options.insert
924
+ * Puts the console's element into the page.
925
+ * @returns {{element: HTMLIFrameElement, destroy: () => void}}
890
926
  */
891
- function main(script) {
892
- const dataset = JSON.parse(JSON.stringify(script.dataset));
927
+ function createConsole({code, dataset, height, insert}) {
893
928
  const runnerMode = dataset.runner === 'window' ? 'window' : 'worker';
894
929
  const blockType = dataset.blockType === 'module' ? 'module' : 'classic';
895
930
  const showResults = dataset.showResults !== 'false';
@@ -993,7 +1028,8 @@
993
1028
  };
994
1029
 
995
1030
  // The pop-out window can't work without this page so it is closed too.
996
- addEventListener('pagehide', () => popOutWindow?.close());
1031
+ const closePopOut = () => popOutWindow?.close();
1032
+ addEventListener('pagehide', closePopOut);
997
1033
 
998
1034
  /**
999
1035
  * @param {Window=} targetWindow
@@ -2478,7 +2514,7 @@
2478
2514
  async onReady() {
2479
2515
  // The dataset is passed as is so that the viewer knows which options
2480
2516
  // were actually specified (eg. when copying the console as HTML).
2481
- this.call('init', script.textContent, dataset, {
2517
+ this.call('init', code, dataset, {
2482
2518
  runnerMode,
2483
2519
  blockType,
2484
2520
  showResults,
@@ -2491,7 +2527,10 @@
2491
2527
  body: VIEWER_IFRAME_HTML,
2492
2528
  style: {
2493
2529
  width: '100%',
2494
- height: '100%',
2530
+ // Fills its container unless a height is given but is never
2531
+ // squashed smaller than the default height of an IFRAME.
2532
+ height: height || '100%',
2533
+ minHeight: '150px',
2495
2534
  border: 0,
2496
2535
  display: 'block',
2497
2536
  },
@@ -2499,9 +2538,123 @@
2499
2538
  }
2500
2539
 
2501
2540
  inlineViewer = activeViewer = createViewer();
2502
- script.parentNode.insertBefore(inlineViewer.iframe, script);
2541
+ insert(inlineViewer.iframe);
2542
+
2543
+ let isDestroyed = false;
2544
+ return {
2545
+ element: inlineViewer.iframe,
2546
+ /**
2547
+ * Removes the console, stops its code and closes its pop-out window.
2548
+ */
2549
+ destroy() {
2550
+ if (isDestroyed) return;
2551
+ isDestroyed = true;
2552
+ if (popOutWindow) {
2553
+ clearInterval(popOutWatcher);
2554
+ popOutViewer.dispose();
2555
+ popOutWindow.close();
2556
+ popOutWindow = null;
2557
+ }
2558
+ removeEventListener('pagehide', closePopOut);
2559
+ runner.destroy();
2560
+ inlineViewer.dispose();
2561
+ inlineViewer.iframe.remove();
2562
+ },
2563
+ };
2564
+ }
2565
+
2566
+ /**
2567
+ * Creates a console in place of a script tag using its code and data
2568
+ * attributes.
2569
+ * @param {HTMLScriptElement} script
2570
+ */
2571
+ function createConsoleFromScript(script) {
2572
+ return createConsole({
2573
+ code: script.textContent,
2574
+ dataset: JSON.parse(JSON.stringify(script.dataset)),
2575
+ insert: element => script.parentNode.insertBefore(element, script),
2576
+ });
2503
2577
  }
2504
2578
 
2579
+ /**
2580
+ * Where YourJSBox.create() can put a console relative to its target.
2581
+ */
2582
+ const PLACEMENTS = {
2583
+ fill: (target, element) => target.replaceChildren(element),
2584
+ append: (target, element) => target.append(element),
2585
+ prepend: (target, element) => target.prepend(element),
2586
+ replace: (target, element) => target.replaceWith(element),
2587
+ before: (target, element) => target.before(element),
2588
+ after: (target, element) => target.after(element),
2589
+ };
2590
+
2591
+ /**
2592
+ * The options of YourJSBox.create() which are the same as the data
2593
+ * attributes of a script tag.
2594
+ */
2595
+ const CONSOLE_OPTION_NAMES = ['blockType', 'dividerOrient', 'hidePrefix', 'librariesUrl', 'runner', 'showResults', 'theme'];
2596
+
2597
+ /**
2598
+ * The JavaScript API for creating consoles (available as window.YourJSBox).
2599
+ */
2600
+ const YourJSBox = Object.freeze({
2601
+ version: PACKAGE_INFO.version,
2602
+
2603
+ /**
2604
+ * Creates a console.
2605
+ * @param {Object} options
2606
+ * @param {string|Element} options.target
2607
+ * The element (or a CSS selector for it) that the console is placed
2608
+ * relative to.
2609
+ * @param {"fill"|"append"|"prepend"|"replace"|"before"|"after"=} options.placement
2610
+ * Optional, defaults to `"fill"`. Where the console goes: "fill"
2611
+ * replaces the target's contents, "append" and "prepend" add it inside
2612
+ * of the target, "replace" replaces the target itself and "before" and
2613
+ * "after" add it next to the target.
2614
+ * @param {(string|number)=} options.height
2615
+ * Optional, defaults to `"100%"`. The CSS height of the console (a
2616
+ * number is treated as pixels). It is never less than 150px.
2617
+ * @param {string=} options.code
2618
+ * Optional. The code that the console starts with.
2619
+ * @param {string=} options.runner
2620
+ * @param {string=} options.blockType
2621
+ * @param {(boolean|string)=} options.showResults
2622
+ * @param {string=} options.hidePrefix
2623
+ * @param {string=} options.dividerOrient
2624
+ * @param {string=} options.theme
2625
+ * @param {string=} options.librariesUrl
2626
+ * The same as the data attributes of a script tag.
2627
+ * @returns {{element: HTMLIFrameElement, destroy: () => void}}
2628
+ */
2629
+ create(options) {
2630
+ options = Object(options);
2631
+ const {target, placement = 'fill', height, code = ''} = options;
2632
+ const targetElement = 'string' === typeof target ? document.querySelector(target) : target;
2633
+ if (targetElement?.nodeType !== 1) {
2634
+ throw new TypeError(
2635
+ 'string' === typeof target
2636
+ ? `YourJSBox.create(): no element matches the target ${JSON.stringify(target)}.`
2637
+ : 'YourJSBox.create(): target must be an element or a CSS selector.'
2638
+ );
2639
+ }
2640
+ if (!Object.hasOwn(PLACEMENTS, placement)) {
2641
+ throw new TypeError(`YourJSBox.create(): placement must be one of ${Object.keys(PLACEMENTS).join(', ')}.`);
2642
+ }
2643
+
2644
+ const dataset = {};
2645
+ for (const name of CONSOLE_OPTION_NAMES) {
2646
+ if (options[name] != null) dataset[name] = `${options[name]}`;
2647
+ }
2648
+
2649
+ return createConsole({
2650
+ code: `${code}`,
2651
+ dataset,
2652
+ height: 'number' === typeof height ? `${height}px` : height != null ? `${height}` : undefined,
2653
+ insert: element => PLACEMENTS[placement](targetElement, element),
2654
+ });
2655
+ },
2656
+ });
2657
+
2505
2658
  // NOTE: This solution was intentionally written without using newer JS
2506
2659
  // features to make the minified version even smaller.
2507
2660
  var createCallableFrame = (function () {
@@ -2789,5 +2942,13 @@
2789
2942
  return createCallableFrame;
2790
2943
  })();
2791
2944
 
2792
- main(document.currentScript);
2945
+ // The first copy of this script that is loaded provides the API.
2946
+ if (!window.YourJSBox) window.YourJSBox = YourJSBox;
2947
+
2948
+ // A script in the body is replaced by a console while a script in the head
2949
+ // only provides the API.
2950
+ const currentScript = document.currentScript;
2951
+ if (currentScript && !document.head?.contains(currentScript)) {
2952
+ createConsoleFromScript(currentScript);
2953
+ }
2793
2954
  })();
@@ -1,4 +1,4 @@
1
- /*! yourjs-box v1.3.1 | (c) 2023-present Christopher West | MIT License | https://github.com/westc/yourjs-box */
1
+ /*! yourjs-box v1.4.0 | (c) 2023-present Christopher West | MIT License | https://github.com/westc/yourjs-box */
2
2
  (() => {
3
3
  /**
4
4
  * Viewer IFRAME's CSS code
@@ -9,7 +9,7 @@
9
9
  * Information about this package (eg. its version).
10
10
  * @type {{name: string, version: string, homepage: string, repoUrl: string, bugsUrl: string}}
11
11
  */
12
- const PACKAGE_INFO = {"name":"yourjs-box","version":"1.3.1","homepage":"https://westc.github.io/yourjs-box/","repoUrl":"https://github.com/westc/yourjs-box","bugsUrl":"https://github.com/westc/yourjs-box/issues"};
12
+ const PACKAGE_INFO = {"name":"yourjs-box","version":"1.4.0","homepage":"https://westc.github.io/yourjs-box/","repoUrl":"https://github.com/westc/yourjs-box","bugsUrl":"https://github.com/westc/yourjs-box/issues"};
13
13
  /**
14
14
  * Viewer IFRAME's HTML code
15
15
  * @type {string}
@@ -91,7 +91,7 @@
91
91
  }
92
92
  }
93
93
 
94
- function createRunner(e,t){const{mode:n}=t,r=t.ownUrl||("worker"===n?self.location.href:""),o={};let s=0,i=0,c=!0,a;const l={},u={},f={};let p=[],d=0;const g=`yourjs-box.result.${Math.random().toString(36).slice(2)}`;globalThis[Symbol.for(g)]=y;for(const e of["assert","clear","count","countReset","debug","dir","dirxml","error","group","groupCollapsed","groupEnd","info","log","table","time","timeEnd","timeLog","trace","warn"]){const t=console[e];"function"==typeof t&&(console[e]=function(...n){return h(e,n),t.apply(this,arguments)})}function h(t,n){const r=n.length&&void 0!==n[0]?`${n[0]}`:"default";if("clear"===t)U(),p=[],e({target:"viewer",func:"clearDisplays",args:[!0]});else if("assert"===t){if(n[0])return;const e=n.slice(1);m("assert",e.length?"string"==typeof e[0]?["Assertion failed: "+e[0],...e.slice(1)]:["Assertion failed:",...e]:["Assertion failed: console.assert"])}else if("count"===t)u[r]=(u[r]||0)+1,m("count",[`${r}: ${u[r]}`]);else if("countReset"===t)Object.hasOwn(u,r)?u[r]=0:m("warn",[`Count for '${r}' does not exist`]);else if("time"===t)Object.hasOwn(f,r)?m("warn",[`Timer '${r}' already exists`]):f[r]=performance.now();else if("timeLog"===t||"timeEnd"===t){if(!Object.hasOwn(f,r))return void m("warn",[`Timer '${r}' does not exist`]);const e=performance.now()-f[r];"timeEnd"===t&&delete f[r],m(t,[`${r}: ${+e.toFixed(3)} ms`,..."timeLog"===t?n.slice(1):[]])}else if("trace"===t){const e=$((new Error).stack??"").split("\n").slice(1).join("\n");m("trace",n.length?n:["console.trace"],{stack:e})}else if("group"===t||"groupCollapsed"===t){const e=""+ ++d;m(t,n.length?n:["console.group"],{groupId:e,isCollapsed:"groupCollapsed"===t}),p.push(e)}else if("groupEnd"===t)p.pop();else{const e="table"===t?x(n[0],n[1]):null;m(t,e?n.slice(0,1):n,{table:e})}}function m(t,n,r,i=0){const c=""+ ++s;o[c]=n.map((e=>({...N(e,i),value:e}))),e({target:"viewer",func:"appendLog",args:[{logId:c,key:t,descriptions:o[c].map(v(["value"])),groupIds:p.slice(),...r}]})}function y(e){void 0!==e&&m("result",[e],{},"string"==typeof e?1:0)}function b(t,n){const r="classic"===a&&"SyntaxError"===t?.name&&/\bawait\b/.test(t.message)?'\n(To use top-level await, add data-block-type="module" to the script tag.)':"";e({target:"viewer",func:"appendError",args:[{message:(n?"Uncaught (in promise) ":"Uncaught ")+$(t?.stack??`${t?.message??t}`)+r}]})}function $(e){return`${e}`.split("\n").filter((e=>!(r&&/^\s*at\b/.test(e)&&e.includes(r)))).join("\n").replace(/(snippet-\d+\.js):(\d+):(\d+)/g,((e,t,n,r)=>{const o=l[t];return o&&+n===o.line&&+r>o.column?`${t}:${n}:${Math.max(o.column,r-o.shift)}`:e}))}function v(e,t){if(!t)return t=>v(e,t);const n={...t};for(const t of e)delete n[t];return n}function x(e,t){if(null===e||"object"!=typeof e)return null;const n="Value",r=[];let o=!1;const s=Object.keys(e).map((t=>{const n=e[t],s={index:t,values:{},hasValue:!1};if(null===n||"object"!=typeof n&&"function"!=typeof n)o=!0,s.hasValue=!0,s.value=n;else for(const e of Object.keys(n))r.includes(e)||r.push(e),s.values[e]=n[e];return s})),i=Array.isArray(t)?t.map((e=>`${e}`)):r,c=o&&!Array.isArray(t);return{headers:["(index)",...i,...c?[n]:[]],rows:s.map((({index:e,values:t,hasValue:n,value:r})=>({index:e,cells:[...i.map((e=>Object.hasOwn(t,e)?N(t[e],2):null)),...c?[n?N(r,2):null]:[]]})))}}function j(e){if(null==e)return""+e;const t=typeof e;return"object"===t||"undefined"===t?Object.prototype.toString.call(e).slice(8,-1):t}function O(e,t){try{const t=Object.getPrototypeOf(e)?.constructor?.name;if(t&&"string"==typeof t)return t}catch(e){}return t}addEventListener("error",(e=>{b(void 0!==e.error?e.error:e.message)})),addEventListener("unhandledrejection",(e=>{b(e.reason,!0)}));const w=5,E=100;function N(e,t=0,n=!1){const r=j(e),o="function"!==r&&r===r.toLowerCase(),s=undefined;return{typeName:r,isPrimitive:o,parts:n?[["text","Object"!==r?r:O(e,r)]]:k(e,t,r)}}function k(e,t,n=j(e)){if("string"===n)return t?(t>1&&e.length>100&&(e=e.slice(0,99)+"\u2026"),[["string",A(e)]]):[["text",e]];if("number"===n)return[["number",Object.is(e,-0)?"-0":""+e]];if("bigint"===n)return[["number",e+"n"]];if("boolean"===n)return[["number",""+e]];if("null"===n||"undefined"===n)return[["null",n]];if("symbol"===n)return[["symbol",e.toString()]];if("function"===n)return S(e,t);try{return L(e,t,n)}catch(e){return[["text",n]]}}function A(e){const t=JSON.stringify(e);return e.includes("'")?t:`'${t.slice(1,-1).replace(/\\"/g,'"')}'`}function S(e,t){let n="";try{n=Function.prototype.toString.call(e)}catch(e){}const r=/^class\b/.test(n);return t?t>1?[["function","\u0192"]]:[["function",r?`class ${e.name}`:`\u0192 ${e.name}()`]]:[["text",r?n:n.replace(/^(async\s+)?function\b\s*/,"$1\u0192 ")]]}function L(e,t,n){const r=O(e,n),o=/^Array(?:[^a-z]|$)|[^A-Z]Array$/.test(n);if("Date"===n)return[["text",isNaN(e)?"Invalid Date":Date.prototype.toString.call(e)]];if("RegExp"===n)return[["regexp",""+e]];if("Promise"===n)return[["text",`${r} {\u2026}`]];if("undefined"!=typeof Node&&e instanceof Node)return e.nodeType===Node.ELEMENT_NODE?[["node",e.localName+(e.id?"#"+e.id:"")+[...e.classList].map((e=>"."+e)).join("")]]:e.nodeType===Node.TEXT_NODE?[["string",A(e.data)]]:[["node",e.nodeName]];if(e instanceof Error)return[["text",t?`${e.name}: ${e.message}`:$(e.stack??`${e}`)]];if(t>1)return o?[["text",`${r}(${e.length})`]]:"Map"===n||"Set"===n?[["text",`${r}(${e.size})`]]:[["text","Object"===r?"{\u2026}":r]];const s=[],i=(e,t,n)=>{e.forEach(((e,t)=>{t&&s.push(["text",", "]),n(e)})),t>e.length&&s.push(["text",(e.length?", ":"")+"\u2026"])};if(o){const t=e.length;s.push(["text","Array"===n&&"Array"===r?`(${t}) [`:`${r}(${t}) [`]),i(Array.from({length:Math.min(t,E)},((e,t)=>t)),t,(t=>s.push(...t in e?k(e[t],2):[["null","empty"]]))),s.push(["text","]"])}else if("Map"===n||"Set"===n){const t=[...e].slice(0,E);s.push(["text",`${r}(${e.size}) {`]),i(t,e.size,(e=>{"Map"===n?s.push(...k(e[0],2),["text"," => "],...k(e[1],2)):s.push(...k(e,2))})),s.push(["text","}"])}else{const t=Object.keys(e);"Object"!==r&&s.push(["text",r+" "]),"Number"===n||"String"===n||"Boolean"===n?s.push(["text","{"],...k(e.valueOf(),2),["text","}"]):(s.push(["text","{"]),i(t.slice(0,w),t.length,(t=>{const n=Object.getOwnPropertyDescriptor(e,t);s.push(["key",t],["text",": "],..."value"in n?k(n.value,2):[["text","(\u2026)"]])})),s.push(["text","}"]))}return s}function R(e,t=e){const n=j(e),r=[],o=[],s=[],i=[];if(null!==e&&("object"==typeof e||"function"==typeof e)){let c=!1;try{if("Map"===n){for(const[t,n]of[...e])r.push([k(t,2).map((e=>e[1])).join(""),N(n,1)]),o.push({value:n});c=!0}else if("Array"!==n&&"function"!==n&&"function"==typeof e[Symbol.iterator]){let t=0;for(const n of e)r.push([""+t,N(n,1)]),o.push({value:n}),++t;c=!0}}catch(e){r.length=o.length=0}if(!c)for(const n of Object.getOwnPropertyNames(e))try{const s=Object.getOwnPropertyDescriptor(e,n),i="value"in s?s.value:Reflect.get(e,n,t);r.push([n,N(i,1),s.enumerable]),o.push({value:i})}catch(e){}const a=Object.getPrototypeOf(e);null!==a&&(s.push(["[[Prototype]]",N(a,1,!0)]),i.push({value:a,receiver:t}))}return{entries:r,protoEntries:s,$entries:o,$protoEntries:i}}async function C(t,r){const{blockType:o,resultRange:s}=Object(r),c=`snippet-${++i}.js`;if(Array.isArray(s)){const[e,n]=s,r=`globalThis[Symbol.for(${JSON.stringify(g)})]((`,o=t.slice(0,e).split("\n");l[c]={line:o.length,column:o[o.length-1].length+1,shift:r.length},t=t.slice(0,e)+r+t.slice(e,n)+"))"+t.slice(n)}const u=`${t}\n//# sourceURL=${c}`;a="module"===o?"module":"classic";try{if("module"===o)await import("data:text/javascript;charset=utf-8,"+encodeURIComponent(u));else if("worker"===n)T(u);else{const e=document.createElement("script");e.textContent=u,document.head.appendChild(e),e.remove()}}catch(e){b(e)}a=void 0,e({target:"viewer",func:"onCodeRan",args:[]})}function T(e){if(c)try{return void importScripts("data:text/javascript;charset=utf-8,"+encodeURIComponent(e))}catch(e){if("NetworkError"!==e?.name)throw e;c=!1}const t=URL.createObjectURL(new Blob([e],{type:"text/javascript"}));try{importScripts(t)}finally{URL.revokeObjectURL(t)}}function D(t){let n=o,r=0;for(let e of t)r&&r%2==0&&(e="$"+e),n=n?.[e],r++;if(!n)return;const s=R(n.value,"receiver"in n?n.receiver:n.value);Object.assign(n,s),e({target:"viewer",func:"updateDescriptionFor",args:[t,v(["$entries","$protoEntries"],s)]})}function U(){for(const e of Object.keys(o))delete o[e];p=[]}return{clearLogs:U,runCode:C,sendDescriptionFor:D}}
94
+ function createRunner(e,t){const{mode:n}=t,r=t.ownUrl||("worker"===n?self.location.href:""),o={};let s=0,i=0,c=!0,a;const l={},u={},f={};let p=[],d=0;const g=`yourjs-box.result.${Math.random().toString(36).slice(2)}`;globalThis[Symbol.for(g)]=b;const h=[];for(const e of["assert","clear","count","countReset","debug","dir","dirxml","error","group","groupCollapsed","groupEnd","info","log","table","time","timeEnd","timeLog","trace","warn"]){const t=console[e];if("function"!=typeof t)continue;const n=function(...n){return m(e,n),t.apply(this,arguments)};console[e]=n,h.push({key:e,original:t,wrapper:n})}function m(t,n){const r=n.length&&void 0!==n[0]?`${n[0]}`:"default";if("clear"===t)z(),p=[],e({target:"viewer",func:"clearDisplays",args:[!0]});else if("assert"===t){if(n[0])return;const e=n.slice(1);y("assert",e.length?"string"==typeof e[0]?["Assertion failed: "+e[0],...e.slice(1)]:["Assertion failed:",...e]:["Assertion failed: console.assert"])}else if("count"===t)u[r]=(u[r]||0)+1,y("count",[`${r}: ${u[r]}`]);else if("countReset"===t)Object.hasOwn(u,r)?u[r]=0:y("warn",[`Count for '${r}' does not exist`]);else if("time"===t)Object.hasOwn(f,r)?y("warn",[`Timer '${r}' already exists`]):f[r]=performance.now();else if("timeLog"===t||"timeEnd"===t){if(!Object.hasOwn(f,r))return void y("warn",[`Timer '${r}' does not exist`]);const e=performance.now()-f[r];"timeEnd"===t&&delete f[r],y(t,[`${r}: ${+e.toFixed(3)} ms`,..."timeLog"===t?n.slice(1):[]])}else if("trace"===t){const e=O((new Error).stack??"").split("\n").slice(1).join("\n");y("trace",n.length?n:["console.trace"],{stack:e})}else if("group"===t||"groupCollapsed"===t){const e=""+ ++d;y(t,n.length?n:["console.group"],{groupId:e,isCollapsed:"groupCollapsed"===t}),p.push(e)}else if("groupEnd"===t)p.pop();else{const e="table"===t?E(n[0],n[1]):null;y(t,e?n.slice(0,1):n,{table:e})}}function y(t,n,r,i=0){const c=""+ ++s;o[c]=n.map((e=>({...A(e,i),value:e}))),e({target:"viewer",func:"appendLog",args:[{logId:c,key:t,descriptions:o[c].map(w(["value"])),groupIds:p.slice(),...r}]})}function b(e){void 0!==e&&y("result",[e],{},"string"==typeof e?1:0)}function v(e){j(void 0!==e.error?e.error:e.message)}function $(e){j(e.reason,!0)}function x(){removeEventListener("error",v),removeEventListener("unhandledrejection",$),delete globalThis[Symbol.for(g)];for(const{key:e,original:t,wrapper:n}of h)console[e]===n&&(console[e]=t);z()}function j(t,n){const r="classic"===a&&"SyntaxError"===t?.name&&/\bawait\b/.test(t.message)?'\n(To use top-level await, add data-block-type="module" to the script tag.)':"";e({target:"viewer",func:"appendError",args:[{message:(n?"Uncaught (in promise) ":"Uncaught ")+O(t?.stack??`${t?.message??t}`)+r}]})}function O(e){return`${e}`.split("\n").filter((e=>!(r&&/^\s*at\b/.test(e)&&e.includes(r)))).join("\n").replace(/(snippet-\d+\.js):(\d+):(\d+)/g,((e,t,n,r)=>{const o=l[t];return o&&+n===o.line&&+r>o.column?`${t}:${n}:${Math.max(o.column,r-o.shift)}`:e}))}function w(e,t){if(!t)return t=>w(e,t);const n={...t};for(const t of e)delete n[t];return n}function E(e,t){if(null===e||"object"!=typeof e)return null;const n="Value",r=[];let o=!1;const s=Object.keys(e).map((t=>{const n=e[t],s={index:t,values:{},hasValue:!1};if(null===n||"object"!=typeof n&&"function"!=typeof n)o=!0,s.hasValue=!0,s.value=n;else for(const e of Object.keys(n))r.includes(e)||r.push(e),s.values[e]=n[e];return s})),i=Array.isArray(t)?t.map((e=>`${e}`)):r,c=o&&!Array.isArray(t);return{headers:["(index)",...i,...c?[n]:[]],rows:s.map((({index:e,values:t,hasValue:n,value:r})=>({index:e,cells:[...i.map((e=>Object.hasOwn(t,e)?A(t[e],2):null)),...c?[n?A(r,2):null]:[]]})))}}function k(e){if(null==e)return""+e;const t=typeof e;return"object"===t||"undefined"===t?Object.prototype.toString.call(e).slice(8,-1):t}function L(e,t){try{const t=Object.getPrototypeOf(e)?.constructor?.name;if(t&&"string"==typeof t)return t}catch(e){}return t}addEventListener("error",v),addEventListener("unhandledrejection",$);const N=5,S=100;function A(e,t=0,n=!1){const r=k(e),o="function"!==r&&r===r.toLowerCase(),s=undefined;return{typeName:r,isPrimitive:o,parts:n?[["text","Object"!==r?r:L(e,r)]]:R(e,t,r)}}function R(e,t,n=k(e)){if("string"===n)return t?(t>1&&e.length>100&&(e=e.slice(0,99)+"\u2026"),[["string",C(e)]]):[["text",e]];if("number"===n)return[["number",Object.is(e,-0)?"-0":""+e]];if("bigint"===n)return[["number",e+"n"]];if("boolean"===n)return[["number",""+e]];if("null"===n||"undefined"===n)return[["null",n]];if("symbol"===n)return[["symbol",e.toString()]];if("function"===n)return T(e,t);try{return D(e,t,n)}catch(e){return[["text",n]]}}function C(e){const t=JSON.stringify(e);return e.includes("'")?t:`'${t.slice(1,-1).replace(/\\"/g,'"')}'`}function T(e,t){let n="";try{n=Function.prototype.toString.call(e)}catch(e){}const r=/^class\b/.test(n);return t?t>1?[["function","\u0192"]]:[["function",r?`class ${e.name}`:`\u0192 ${e.name}()`]]:[["text",r?n:n.replace(/^(async\s+)?function\b\s*/,"$1\u0192 ")]]}function D(e,t,n){const r=L(e,n),o=/^Array(?:[^a-z]|$)|[^A-Z]Array$/.test(n);if("Date"===n)return[["text",isNaN(e)?"Invalid Date":Date.prototype.toString.call(e)]];if("RegExp"===n)return[["regexp",""+e]];if("Promise"===n)return[["text",`${r} {\u2026}`]];if("undefined"!=typeof Node&&e instanceof Node)return e.nodeType===Node.ELEMENT_NODE?[["node",e.localName+(e.id?"#"+e.id:"")+[...e.classList].map((e=>"."+e)).join("")]]:e.nodeType===Node.TEXT_NODE?[["string",C(e.data)]]:[["node",e.nodeName]];if(e instanceof Error)return[["text",t?`${e.name}: ${e.message}`:O(e.stack??`${e}`)]];if(t>1)return o?[["text",`${r}(${e.length})`]]:"Map"===n||"Set"===n?[["text",`${r}(${e.size})`]]:[["text","Object"===r?"{\u2026}":r]];const s=[],i=(e,t,n)=>{e.forEach(((e,t)=>{t&&s.push(["text",", "]),n(e)})),t>e.length&&s.push(["text",(e.length?", ":"")+"\u2026"])};if(o){const t=e.length;s.push(["text","Array"===n&&"Array"===r?`(${t}) [`:`${r}(${t}) [`]),i(Array.from({length:Math.min(t,S)},((e,t)=>t)),t,(t=>s.push(...t in e?R(e[t],2):[["null","empty"]]))),s.push(["text","]"])}else if("Map"===n||"Set"===n){const t=[...e].slice(0,S);s.push(["text",`${r}(${e.size}) {`]),i(t,e.size,(e=>{"Map"===n?s.push(...R(e[0],2),["text"," => "],...R(e[1],2)):s.push(...R(e,2))})),s.push(["text","}"])}else{const t=Object.keys(e);"Object"!==r&&s.push(["text",r+" "]),"Number"===n||"String"===n||"Boolean"===n?s.push(["text","{"],...R(e.valueOf(),2),["text","}"]):(s.push(["text","{"]),i(t.slice(0,N),t.length,(t=>{const n=Object.getOwnPropertyDescriptor(e,t);s.push(["key",t],["text",": "],..."value"in n?R(n.value,2):[["text","(\u2026)"]])})),s.push(["text","}"]))}return s}function U(e,t=e){const n=k(e),r=[],o=[],s=[],i=[];if(null!==e&&("object"==typeof e||"function"==typeof e)){let c=!1;try{if("Map"===n){for(const[t,n]of[...e])r.push([R(t,2).map((e=>e[1])).join(""),A(n,1)]),o.push({value:n});c=!0}else if("Array"!==n&&"function"!==n&&"function"==typeof e[Symbol.iterator]){let t=0;for(const n of e)r.push([""+t,A(n,1)]),o.push({value:n}),++t;c=!0}}catch(e){r.length=o.length=0}if(!c)for(const n of Object.getOwnPropertyNames(e))try{const s=Object.getOwnPropertyDescriptor(e,n),i="value"in s?s.value:Reflect.get(e,n,t);r.push([n,A(i,1),s.enumerable]),o.push({value:i})}catch(e){}const a=Object.getPrototypeOf(e);null!==a&&(s.push(["[[Prototype]]",A(a,1,!0)]),i.push({value:a,receiver:t}))}return{entries:r,protoEntries:s,$entries:o,$protoEntries:i}}async function M(t,r){const{blockType:o,resultRange:s}=Object(r),c=`snippet-${++i}.js`;if(Array.isArray(s)){const[e,n]=s,r=`globalThis[Symbol.for(${JSON.stringify(g)})]((`,o=t.slice(0,e).split("\n");l[c]={line:o.length,column:o[o.length-1].length+1,shift:r.length},t=t.slice(0,e)+r+t.slice(e,n)+"))"+t.slice(n)}const u=`${t}\n//# sourceURL=${c}`;a="module"===o?"module":"classic";try{if("module"===o)await import("data:text/javascript;charset=utf-8,"+encodeURIComponent(u));else if("worker"===n)P(u);else{const e=document.createElement("script");e.textContent=u,document.head.appendChild(e),e.remove()}}catch(e){j(e)}a=void 0,e({target:"viewer",func:"onCodeRan",args:[]})}function P(e){if(c)try{return void importScripts("data:text/javascript;charset=utf-8,"+encodeURIComponent(e))}catch(e){if("NetworkError"!==e?.name)throw e;c=!1}const t=URL.createObjectURL(new Blob([e],{type:"text/javascript"}));try{importScripts(t)}finally{URL.revokeObjectURL(t)}}function I(t){let n=o,r=0;for(let e of t)r&&r%2==0&&(e="$"+e),n=n?.[e],r++;if(!n)return;const s=U(n.value,"receiver"in n?n.receiver:n.value);Object.assign(n,s),e({target:"viewer",func:"updateDescriptionFor",args:[t,w(["$entries","$protoEntries"],s)]})}function z(){for(const e of Object.keys(o))delete o[e];p=[]}return{clearLogs:z,destroy:x,runCode:M,sendDescriptionFor:I}}
95
95
 
96
96
  /**
97
97
  * Runs the user's code in a Web Worker. The worker can be terminated which
@@ -159,6 +159,10 @@
159
159
  start();
160
160
 
161
161
  return {
162
+ destroy() {
163
+ worker.terminate();
164
+ if (blobUrl) URL.revokeObjectURL(blobUrl);
165
+ },
162
166
  apply(func, args) {
163
167
  if (func === 'reset') {
164
168
  worker.terminate();
@@ -182,6 +186,9 @@
182
186
  function createWindowRunner(onMessage) {
183
187
  const runner = createRunner(onMessage, {mode: 'window', ownUrl: OWN_URL});
184
188
  return {
189
+ destroy() {
190
+ runner.destroy();
191
+ },
185
192
  apply(func, args) {
186
193
  // Anything the code defined stays defined so a reset can only forget
187
194
  // the logged values.
@@ -192,13 +199,20 @@
192
199
  }
193
200
 
194
201
  /**
195
- * Function executed when the script is included in a document.
196
- * @param {HTMLScriptElement} script
197
- * This is the current script but also the placeholder for where the
198
- * console will be inserted into the DOM.
202
+ * Creates a console.
203
+ * @param {Object} options
204
+ * @param {string} options.code
205
+ * The code that the console starts with.
206
+ * @param {{[name: string]: string}} options.dataset
207
+ * The options for the console in the same form as the data attributes of
208
+ * a script tag (eg. `{runner: 'window', hidePrefix: 'HIDE'}`).
209
+ * @param {string=} options.height
210
+ * Optional, defaults to `"100%"`. The CSS height of the console.
211
+ * @param {(element: HTMLIFrameElement) => void} options.insert
212
+ * Puts the console's element into the page.
213
+ * @returns {{element: HTMLIFrameElement, destroy: () => void}}
199
214
  */
200
- function main(script) {
201
- const dataset = JSON.parse(JSON.stringify(script.dataset));
215
+ function createConsole({code, dataset, height, insert}) {
202
216
  const runnerMode = dataset.runner === 'window' ? 'window' : 'worker';
203
217
  const blockType = dataset.blockType === 'module' ? 'module' : 'classic';
204
218
  const showResults = dataset.showResults !== 'false';
@@ -302,7 +316,8 @@
302
316
  };
303
317
 
304
318
  // The pop-out window can't work without this page so it is closed too.
305
- addEventListener('pagehide', () => popOutWindow?.close());
319
+ const closePopOut = () => popOutWindow?.close();
320
+ addEventListener('pagehide', closePopOut);
306
321
 
307
322
  /**
308
323
  * @param {Window=} targetWindow
@@ -343,7 +358,7 @@
343
358
  async onReady() {
344
359
  // The dataset is passed as is so that the viewer knows which options
345
360
  // were actually specified (eg. when copying the console as HTML).
346
- this.call('init', script.textContent, dataset, {
361
+ this.call('init', code, dataset, {
347
362
  runnerMode,
348
363
  blockType,
349
364
  showResults,
@@ -356,7 +371,10 @@
356
371
  body: VIEWER_IFRAME_HTML,
357
372
  style: {
358
373
  width: '100%',
359
- height: '100%',
374
+ // Fills its container unless a height is given but is never
375
+ // squashed smaller than the default height of an IFRAME.
376
+ height: height || '100%',
377
+ minHeight: '150px',
360
378
  border: 0,
361
379
  display: 'block',
362
380
  },
@@ -364,9 +382,123 @@
364
382
  }
365
383
 
366
384
  inlineViewer = activeViewer = createViewer();
367
- script.parentNode.insertBefore(inlineViewer.iframe, script);
385
+ insert(inlineViewer.iframe);
386
+
387
+ let isDestroyed = false;
388
+ return {
389
+ element: inlineViewer.iframe,
390
+ /**
391
+ * Removes the console, stops its code and closes its pop-out window.
392
+ */
393
+ destroy() {
394
+ if (isDestroyed) return;
395
+ isDestroyed = true;
396
+ if (popOutWindow) {
397
+ clearInterval(popOutWatcher);
398
+ popOutViewer.dispose();
399
+ popOutWindow.close();
400
+ popOutWindow = null;
401
+ }
402
+ removeEventListener('pagehide', closePopOut);
403
+ runner.destroy();
404
+ inlineViewer.dispose();
405
+ inlineViewer.iframe.remove();
406
+ },
407
+ };
368
408
  }
369
409
 
410
+ /**
411
+ * Creates a console in place of a script tag using its code and data
412
+ * attributes.
413
+ * @param {HTMLScriptElement} script
414
+ */
415
+ function createConsoleFromScript(script) {
416
+ return createConsole({
417
+ code: script.textContent,
418
+ dataset: JSON.parse(JSON.stringify(script.dataset)),
419
+ insert: element => script.parentNode.insertBefore(element, script),
420
+ });
421
+ }
422
+
423
+ /**
424
+ * Where YourJSBox.create() can put a console relative to its target.
425
+ */
426
+ const PLACEMENTS = {
427
+ fill: (target, element) => target.replaceChildren(element),
428
+ append: (target, element) => target.append(element),
429
+ prepend: (target, element) => target.prepend(element),
430
+ replace: (target, element) => target.replaceWith(element),
431
+ before: (target, element) => target.before(element),
432
+ after: (target, element) => target.after(element),
433
+ };
434
+
435
+ /**
436
+ * The options of YourJSBox.create() which are the same as the data
437
+ * attributes of a script tag.
438
+ */
439
+ const CONSOLE_OPTION_NAMES = ['blockType', 'dividerOrient', 'hidePrefix', 'librariesUrl', 'runner', 'showResults', 'theme'];
440
+
441
+ /**
442
+ * The JavaScript API for creating consoles (available as window.YourJSBox).
443
+ */
444
+ const YourJSBox = Object.freeze({
445
+ version: PACKAGE_INFO.version,
446
+
447
+ /**
448
+ * Creates a console.
449
+ * @param {Object} options
450
+ * @param {string|Element} options.target
451
+ * The element (or a CSS selector for it) that the console is placed
452
+ * relative to.
453
+ * @param {"fill"|"append"|"prepend"|"replace"|"before"|"after"=} options.placement
454
+ * Optional, defaults to `"fill"`. Where the console goes: "fill"
455
+ * replaces the target's contents, "append" and "prepend" add it inside
456
+ * of the target, "replace" replaces the target itself and "before" and
457
+ * "after" add it next to the target.
458
+ * @param {(string|number)=} options.height
459
+ * Optional, defaults to `"100%"`. The CSS height of the console (a
460
+ * number is treated as pixels). It is never less than 150px.
461
+ * @param {string=} options.code
462
+ * Optional. The code that the console starts with.
463
+ * @param {string=} options.runner
464
+ * @param {string=} options.blockType
465
+ * @param {(boolean|string)=} options.showResults
466
+ * @param {string=} options.hidePrefix
467
+ * @param {string=} options.dividerOrient
468
+ * @param {string=} options.theme
469
+ * @param {string=} options.librariesUrl
470
+ * The same as the data attributes of a script tag.
471
+ * @returns {{element: HTMLIFrameElement, destroy: () => void}}
472
+ */
473
+ create(options) {
474
+ options = Object(options);
475
+ const {target, placement = 'fill', height, code = ''} = options;
476
+ const targetElement = 'string' === typeof target ? document.querySelector(target) : target;
477
+ if (targetElement?.nodeType !== 1) {
478
+ throw new TypeError(
479
+ 'string' === typeof target
480
+ ? `YourJSBox.create(): no element matches the target ${JSON.stringify(target)}.`
481
+ : 'YourJSBox.create(): target must be an element or a CSS selector.'
482
+ );
483
+ }
484
+ if (!Object.hasOwn(PLACEMENTS, placement)) {
485
+ throw new TypeError(`YourJSBox.create(): placement must be one of ${Object.keys(PLACEMENTS).join(', ')}.`);
486
+ }
487
+
488
+ const dataset = {};
489
+ for (const name of CONSOLE_OPTION_NAMES) {
490
+ if (options[name] != null) dataset[name] = `${options[name]}`;
491
+ }
492
+
493
+ return createConsole({
494
+ code: `${code}`,
495
+ dataset,
496
+ height: 'number' === typeof height ? `${height}px` : height != null ? `${height}` : undefined,
497
+ insert: element => PLACEMENTS[placement](targetElement, element),
498
+ });
499
+ },
500
+ });
501
+
370
502
  // NOTE: This solution was intentionally written without using newer JS
371
503
  // features to make the minified version even smaller.
372
504
  var createCallableFrame = (function () {
@@ -654,5 +786,13 @@
654
786
  return createCallableFrame;
655
787
  })();
656
788
 
657
- main(document.currentScript);
789
+ // The first copy of this script that is loaded provides the API.
790
+ if (!window.YourJSBox) window.YourJSBox = YourJSBox;
791
+
792
+ // A script in the body is replaced by a console while a script in the head
793
+ // only provides the API.
794
+ const currentScript = document.currentScript;
795
+ if (currentScript && !document.head?.contains(currentScript)) {
796
+ createConsoleFromScript(currentScript);
797
+ }
658
798
  })();
@@ -1,7 +1,7 @@
1
- /*! yourjs-box v1.3.1 | (c) 2023-present Christopher West | MIT License | https://github.com/westc/yourjs-box */
2
- (()=>{const VIEWER_IFRAME_CSS="[v-cloak]{display:none}body,html{height:100%;margin:0}body{background-color:var(--console-bg);font-family:system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif}#vueApp{display:flex;flex-direction:column;inset:0;position:fixed}#main{display:grid;flex-grow:1;gap:0;min-height:0;position:relative}#main.is-moving-divider{-webkit-user-select:none;user-select:none}#main.col-orient.is-moving-divider{cursor:col-resize}#main.row-orient.is-moving-divider{cursor:row-resize}#main.is-moving-divider::after{background-color:var(--accent);content:'';position:absolute;z-index:99}#main.col-orient.is-moving-divider::after{bottom:0;left:calc(100% - var(--temp-editor-pct) - var(--divider-size)/ 2 - 1px);top:0;width:2px}#main.row-orient.is-moving-divider::after{height:2px;left:0;right:0;top:calc(100% - var(--temp-editor-pct) - var(--divider-size)/ 2 - 1px)}#main.col-orient{grid-template-columns:1fr var(--divider-size) calc(var(--editor-pct) - var(--divider-size)/ 2);grid-template-rows:1fr}#main.row-orient{grid-template-columns:1fr;grid-template-rows:1fr var(--divider-size) calc(var(--editor-pct) - var(--divider-size)/ 2)}.divider{background-color:var(--divider-bg);box-sizing:border-box;position:relative;transition:background-color .15s}#main.col-orient .divider{border-left:1px solid var(--toolbar-border);border-right:1px solid var(--toolbar-border);cursor:col-resize}#main.row-orient .divider{border-bottom:1px solid var(--toolbar-border);border-top:1px solid var(--toolbar-border);cursor:row-resize}.divider::after{background-color:var(--divider-grip);border-radius:2px;content:'';left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);transition:background-color .15s}#main.col-orient .divider::after{height:32px;width:2px}#main.row-orient .divider::after{height:2px;width:32px}#main.is-moving-divider .divider,.divider:hover{background-color:var(--divider-hover-bg)}#main.is-moving-divider .divider::after,.divider:hover::after{background-color:var(--accent)}#displays{position:relative}#displays>div{position:absolute;inset:0;overflow:auto}#bottomNav{align-items:center;background-color:var(--toolbar-bg);border-top:1px solid var(--toolbar-border);color:var(--toolbar-text);display:flex;flex:0 0 auto;font-size:12px;gap:8px;height:32px;padding:0 6px 0 8px;-webkit-user-select:none;user-select:none}#bottomNav>.brand{align-items:center;display:flex;flex-grow:1;gap:8px}.runner-badge{border:1px solid var(--toolbar-border);border-radius:999px;color:var(--muted-text);font-size:10px;letter-spacing:.04em;line-height:15px;padding:0 6px;text-transform:uppercase}#bottomNav>.buttons{align-items:center;display:flex;gap:2px}#bottomNav .separator{background-color:var(--toolbar-border);height:16px;margin:0 4px;width:1px}#bottomNav button{align-items:center;background:0 0;border:0;border-radius:4px;color:inherit;cursor:pointer;display:inline-flex;font:inherit;gap:5px;height:24px;justify-content:center;min-width:26px;padding:0 6px}#bottomNav button>span:not(.label){display:inline-flex;font-size:14px}#bottomNav button svg:not(.spin){transform:none!important}#bottomNav button:hover:not(:disabled){background-color:var(--button-hover)}#bottomNav button:disabled{cursor:not-allowed;opacity:.45}#bottomNav button.primary{background-color:var(--accent);color:var(--accent-text);font-weight:600;margin-left:2px;padding:0 10px 0 8px}#bottomNav button.primary>span:not(.label){font-size:11px}#bottomNav button.primary:hover:not(:disabled){background-color:var(--accent-hover)}#bottomNav button:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.spin{animation:spin .8s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.logo{align-items:center;color:var(--toolbar-text);display:inline-flex;font-weight:700;gap:5px;letter-spacing:-.01em;line-height:1}.logo-mark{align-items:flex-end;background-color:#f7df1e;border-radius:3px;box-sizing:border-box;color:#1a1a1a;display:inline-flex;font-size:9.5px;font-weight:800;height:18px;justify-content:flex-end;letter-spacing:-.02em;padding:0 2px 2px 0;width:18px}.logo-text{font-size:14px}.logo-large{gap:12px}.logo-large>.logo-mark{border-radius:10px;box-shadow:0 8px 24px rgb(0 0 0 / .18);font-size:24px;height:56px;padding:0 6px 5px 0;width:56px}.logo-large>.logo-text{font-size:36px}#splash{align-items:center;background-color:var(--console-bg);display:flex;inset:0;justify-content:center;position:fixed;transition:opacity .35s ease,visibility .35s;z-index:1000}#splash.hidden{opacity:0;visibility:hidden}.splash-content{align-items:center;animation:splash-in .4s ease-out both;display:flex;flex-direction:column;gap:24px}.splash-progress{background-color:var(--toolbar-border);border-radius:3px;height:3px;overflow:hidden;width:140px}.splash-progress>div{animation:splash-progress 1.1s ease-in-out infinite;background-color:var(--accent);border-radius:inherit;height:100%;width:40%}@keyframes splash-in{from{opacity:0;transform:translateY(6px)}}@keyframes splash-progress{from{transform:translateX(-100%)}to{transform:translateX(250%)}}.dialog-backdrop{align-items:center;animation:fade-in .12s ease-out;background-color:var(--backdrop);display:flex;inset:0;justify-content:center;position:fixed;z-index:900}.dialog{animation:dialog-in .15s ease-out;background-color:var(--dialog-bg);border:1px solid var(--toolbar-border);border-radius:8px;box-shadow:0 12px 40px rgb(0 0 0 / .3);color:var(--console-text);font-size:13px;padding:16px;width:min(360px,calc(100% - 32px))}.dialog-title{font-size:14px;font-weight:600;margin-bottom:6px}.dialog-message{color:var(--muted-text);line-height:1.45}.dialog-buttons{display:flex;gap:8px;justify-content:flex-end;margin-top:16px}.dialog-button{background:0 0;border:1px solid var(--toolbar-border);border-radius:4px;color:inherit;cursor:pointer;font:inherit;height:28px;padding:0 12px}.dialog-button:hover{background-color:var(--button-hover)}.dialog-button.primary{background-color:var(--accent);border-color:var(--accent);color:var(--accent-text);font-weight:600}.dialog-button.primary:hover{background-color:var(--accent-hover)}.dialog-button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}#bottomNav button.logo-button{margin-left:-4px;padding:0 4px}.about-dialog{display:flex;flex-direction:column;max-height:calc(100% - 24px);padding:0;width:min(620px,calc(100% - 24px))}.about-dialog.is-export{height:min(560px,calc(100% - 24px))}.about-header{align-items:center;border-bottom:1px solid var(--toolbar-border);display:flex;flex:0 0 auto;padding:0 8px 0 12px}.tabs{display:flex;flex-grow:1;gap:4px}.tab{background:0 0;border:0;border-bottom:2px solid transparent;color:var(--muted-text);cursor:pointer;font:inherit;font-weight:600;padding:10px 8px 8px}.tab:hover{color:var(--console-text)}.tab.active{border-bottom-color:var(--accent);color:var(--console-text)}.close-button{align-items:center;background:0 0;border:0;border-radius:4px;color:var(--muted-text);cursor:pointer;display:inline-flex;font-size:16px;height:28px;justify-content:center;width:28px}.close-button:hover{background-color:var(--button-hover);color:var(--console-text)}.close-button:focus-visible,.segmented>button:focus-visible,.tab:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.about-body{flex:1 1 auto;min-height:0;overflow:auto;padding:16px}.about-title{align-items:center;display:flex;gap:12px}.logo-medium>.logo-mark{border-radius:7px;font-size:16px;height:40px;padding:0 4px 4px 0;width:40px}.logo-medium>.logo-text{display:none}.about-name{font-size:17px;font-weight:700}.about-aka{color:var(--muted-text);font-size:13px;font-weight:400;margin-left:4px}.about-version{color:var(--muted-text);font-size:12px}.about-description{line-height:1.5;margin:12px 0}.about-links{display:flex;flex-wrap:wrap;gap:6px 16px}.about-links a{color:var(--accent);font-weight:600;text-decoration:none}.about-links a:hover{text-decoration:underline}.about-body h3{color:var(--muted-text);font-size:11px;letter-spacing:.05em;margin:18px 0 6px;text-transform:uppercase}.about-details{display:grid;gap:4px 16px;grid-template-columns:max-content 1fr;margin:0}.about-details dt{color:var(--muted-text)}.about-details dd{margin:0}.about-details kbd{background-color:var(--toolbar-bg);border:1px solid var(--toolbar-border);border-bottom-width:2px;border-radius:4px;font-family:inherit;font-size:11px;padding:0 4px}.about-footer{border-top:1px solid var(--toolbar-border);color:var(--muted-text);font-size:12px;margin-top:18px;padding-top:12px}.export-body{display:flex;flex-direction:column;gap:10px}.export-options{display:flex;flex-wrap:wrap;gap:8px;justify-content:space-between}.segmented{border:1px solid var(--toolbar-border);border-radius:6px;display:inline-flex;overflow:hidden}.segmented>button{background:0 0;border:0;color:var(--muted-text);cursor:pointer;font:inherit;font-size:12px;font-weight:600;padding:5px 10px}.segmented>button+button{border-left:1px solid var(--toolbar-border)}.segmented>button:hover{background-color:var(--button-hover)}.segmented>button.active{background-color:var(--accent);color:var(--accent-text)}.export-note{color:var(--muted-text);font-size:12px}.export-preview{border:1px solid var(--toolbar-border);border-radius:6px;flex:1 1 auto;min-height:120px;overflow:hidden}.export-actions{display:flex;gap:8px;justify-content:flex-end}.more-menu{background-color:var(--dialog-bg);border:1px solid var(--toolbar-border);border-radius:8px;bottom:38px;box-shadow:0 8px 28px rgb(0 0 0 / .25);color:var(--console-text);font-size:13px;max-height:calc(100% - 48px);min-width:236px;overflow:auto;padding:4px;position:absolute;right:6px;z-index:800}.menu-item{align-items:center;background:0 0;border:0;border-radius:5px;color:inherit;cursor:pointer;display:flex;font:inherit;gap:8px;padding:6px 8px;text-align:left;width:100%}.menu-item:focus-visible,.menu-item:hover:not(:disabled){background-color:var(--button-hover);outline:0}.menu-item:disabled{cursor:not-allowed;opacity:.4}.menu-icon{color:var(--muted-text);display:inline-flex;font-size:14px;justify-content:center;width:16px}.menu-icon svg{transform:none!important}.menu-row{align-items:center;display:flex;gap:2px;padding:2px 2px 2px 8px}.menu-row-label{flex-grow:1}.menu-step{font-weight:600;justify-content:center;width:auto}.menu-percent{color:var(--muted-text);font-variant-numeric:tabular-nums;font-weight:400;min-width:52px}.menu-separator{background-color:var(--toolbar-border);height:1px;margin:4px 0}.popped-out{align-items:center;background-color:var(--console-bg);color:var(--console-text);display:flex;inset:0;justify-content:center;position:fixed;z-index:950}.popped-out-content{align-items:center;display:flex;flex-direction:column;gap:8px;padding:16px;text-align:center}.popped-out-title{font-size:15px;font-weight:600;margin-top:8px}.popped-out-text{color:var(--muted-text);font-size:13px}@keyframes fade-in{from{opacity:0}}@keyframes dialog-in{from{opacity:0;transform:scale(.96)}}.rotated-90deg{transform:rotate(90deg)}.align-top{vertical-align:top!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.no-select{-webkit-user-select:none;user-select:none}:root{color-scheme:light;--console-font:ui-monospace,Menlo,Monaco,Consolas,'Liberation Mono','Courier New',monospace;--console-bg:#fff;--console-text:#1f1f1f;--row-border:#f0f0f0;--arrow:#727272;--chevron:#9aa0a6;--entry-key:#881391;--preview-key:#5f6368;--string:#c41a16;--number:#1a1aa6;--null:#80868b;--header-bg:#f1f3f4;--header-text:#3c4043;--warn-bg:#fffbe5;--warn-border:#fff5c2;--warn-text:#5c3c00;--warn-icon:#e8a600;--error-bg:#fff0f0;--error-border:#ffd6d6;--error-text:#dc362e;--error-icon:#dc362e;--table-header-bg:#f3f3f3;--table-border:#d0d0d0;--toolbar-bg:#f3f3f3;--toolbar-border:#d6d6d6;--toolbar-text:#333;--muted-text:#5f6368;--button-hover:rgb(0 0 0 / 0.08);--accent:#1a73e8;--accent-hover:#1765cc;--accent-text:#fff;--divider-bg:#f3f3f3;--divider-hover-bg:#e8eaed;--divider-grip:#b0b0b0;--dialog-bg:#fff;--backdrop:rgb(0 0 0 / 0.25)}:root[data-theme=dark]{color-scheme:dark;--console-bg:#242424;--console-text:#e3e3e3;--row-border:#3a3a3a;--arrow:#9aa0a6;--chevron:#80868b;--entry-key:#5db0d7;--preview-key:#9aa0a6;--string:#f28b54;--number:#9980ff;--null:#8e8e8e;--header-bg:#2d2e30;--header-text:#c4c7c5;--warn-bg:#332b00;--warn-border:#665500;--warn-text:#ffd17a;--warn-icon:#ffd17a;--error-bg:#290000;--error-border:#5c0000;--error-text:#ff8080;--error-icon:#ff6b6b;--table-header-bg:#2e2e2e;--table-border:#4a4a4a;--toolbar-bg:#2b2b2b;--toolbar-border:#474747;--toolbar-text:#e3e3e3;--muted-text:#9aa0a6;--button-hover:rgb(255 255 255 / 0.1);--accent:#8ab4f8;--accent-hover:#aecbfa;--accent-text:#202124;--divider-bg:#2b2b2b;--divider-hover-bg:#333;--divider-grip:#6b6b6b;--dialog-bg:#2d2e30;--backdrop:rgb(0 0 0 / 0.5)}#displays{background-color:var(--console-bg);color:var(--console-text)}#displays>div{font-family:var(--console-font);font-size:calc(12px * var(--text-scale, 1));line-height:calc(16px * var(--text-scale, 1))}.console-row{border-bottom:1px solid var(--row-border);padding:2px 8px 2px 24px;position:relative;white-space:pre-wrap;word-break:break-word}.console-row>.row-icon{left:6px;line-height:0;position:absolute;top:4px}.log-error,.log-warn{margin-top:-1px}.log-warn{background-color:var(--warn-bg);border-bottom-color:var(--warn-border);border-top:1px solid var(--warn-border);color:var(--warn-text)}.log-warn>.row-icon{color:var(--warn-icon)}.log-error{background-color:var(--error-bg);border-bottom-color:var(--error-border);border-top:1px solid var(--error-border);color:var(--error-text)}.log-error>.row-icon{color:var(--error-icon)}.console-row{padding-left:calc(24px + var(--depth,0) * 16px)}.console-row>.row-icon{left:calc(6px + var(--depth,0) * 16px)}.group-header{cursor:pointer;font-weight:700}.group-header>.row-icon.arrow{top:5px}.log-assert{background-color:var(--error-bg);border-bottom-color:var(--error-border);border-top:1px solid var(--error-border);color:var(--error-text);margin-top:-1px}.log-assert>.row-icon{color:var(--error-icon)}.log-result>.row-icon{color:var(--chevron)}.trace-stack{color:var(--null);padding-left:1ch}.splash-message{color:var(--muted-text);font-size:13px;max-width:280px;text-align:center}.splash-slow{animation:show-after-delay 0s 10s both}@keyframes show-after-delay{from{visibility:hidden}to{visibility:visible}}#splash.failed .splash-progress,#splash.failed .splash-slow,.splash-error{display:none}#splash.failed .splash-error{display:block}.code-header{background-color:var(--header-bg);border-bottom:1px solid var(--row-border);color:var(--header-text);font-weight:700;padding:2px 8px;white-space:pre-wrap}.code-header.toggleable{cursor:pointer}.code-row .copy-to-editor-button{align-items:center;background-color:var(--console-bg);border:1px solid var(--toolbar-border);border-radius:4px;color:var(--toolbar-text);cursor:pointer;display:inline-flex;height:22px;justify-content:center;opacity:0;padding:0;position:absolute;right:6px;top:2px;transition:opacity .15s;width:22px}.code-row .copy-to-editor-button:focus-visible,.code-row:hover .copy-to-editor-button{opacity:1}.code-row .copy-to-editor-button:hover{background-color:var(--toolbar-bg)}@media (hover:none){.code-row .copy-to-editor-button{opacity:.8}}.notice{color:var(--null);font-style:italic}.code-row>.row-icon{color:var(--chevron)}.code-row code,.code-row pre{background:0 0!important;font-family:var(--console-font)!important;font-size:calc(12px * var(--text-scale, 1))!important;line-height:calc(16px * var(--text-scale, 1))!important;padding:0!important;text-shadow:none!important}.js-value{max-width:100%;vertical-align:top}.row-content>.js-value+.js-value{margin-left:1ch}.js-value-header.expandable{cursor:default}.js-value .expansion{padding-left:12px}.js-value .loading{color:var(--null);padding-left:12px}.arrow{display:inline-block;height:10px;position:relative;width:12px}.arrow.expandable::before{border-color:transparent transparent transparent var(--arrow);border-style:solid;border-width:4px 0 4px 6px;content:'';left:2px;position:absolute;top:1px;transform-origin:3px 4px;transition:transform .1s}.arrow.expandable.expanded::before{transform:rotate(90deg)}.entry-key{color:var(--entry-key)}.entry-key.dim{opacity:.6}.t-key{color:var(--preview-key)}.t-regexp,.t-string,.t-symbol{color:var(--string)}.t-number{color:var(--number)}.t-null{color:var(--null)}.t-function{font-style:italic}.t-node{color:var(--entry-key)}.console-table{border:1px solid var(--table-border);border-collapse:collapse;margin:2px 0 4px;white-space:nowrap}.console-table td,.console-table th{border-left:1px solid var(--table-border);max-width:300px;overflow:hidden;padding:1px 4px;text-align:left;text-overflow:ellipsis}.console-table th{background-color:var(--table-header-bg);border-bottom:1px solid var(--table-border);font-weight:400}",PACKAGE_INFO={name:"yourjs-box",version:"1.3.1",homepage:"https://westc.github.io/yourjs-box/",repoUrl:"https://github.com/westc/yourjs-box",bugsUrl:"https://github.com/westc/yourjs-box/issues"},VIEWER_IFRAME_HTML='<div id="splash" aria-label="Loading"><div class="splash-content"><span class="logo logo-large"><span class="logo-mark">JS</span><span class="logo-text">Box</span></span><div class="splash-progress"><div></div></div><div class="splash-message splash-slow">Still loading&hellip;</div><div class="splash-message splash-error">JS Box couldn&rsquo;t load. Please check your connection and reload the page.</div></div></div><div id="vueApp" v-cloak><div id="main" ref="main" :class="mainElemClassNames" :style="mainElemStyles" @mousedown="onMainElemMouseDown"><div id="displays"><div ref="displaysScroller" @scroll="onDisplaysScroll"><template v-for="display in displays"><div v-if="display.type === \'prism\'"><div v-if="display.isHidden" class="code-header toggleable no-select" @click="display.isCodeShown = !display.isCodeShown" :title="display.isCodeShown ? \'Hide Code\' : \'Show Code\'"><span :class="[\'arrow\', \'expandable\', display.isCodeShown ? \'expanded\' : \'\']"></span>{{ display.header || \'Hidden code\' }}</div><div v-else-if="display.header" class="code-header">{{ display.header }}</div><div v-if="display.isCodeShown" class="console-row code-row"><span class="row-icon"><icon name="chevron"></icon></span><prism language="javascript" :code="display.value" :is-dark="theme === \'dark\'" match-braces></prism><button class="copy-to-editor-button" title="Copy to editor" @click="copyToEditor(display.value)"><icon name="copyToEditor"></icon></button></div></div><div v-if="display.type === \'log\' &amp;&amp; !isInCollapsedGroup(display)" :class="[\'console-row\', \'log-\' + display.key, display.groupId ? \'group-header\' : \'\']" :style="{\'--depth\': display.groupIds.length}" :title="display.name" @click="onLogRowClick(display, $event)"><span v-if="display.key === \'error\' || display.key === \'assert\'" class="row-icon"><icon name="consoleError"></icon></span><span v-else-if="display.key === \'warn\'" class="row-icon"><icon name="consoleWarning"></icon></span><span v-else-if="display.key === \'result\'" class="row-icon"><icon name="result"></icon></span><span v-else-if="display.groupId" :class="[\'row-icon\', \'arrow\', \'expandable\', display.isCollapsed ? \'\' : \'expanded\']"></span><div class="row-content"><table v-if="display.table" class="console-table"><thead><tr><th v-for="header in display.table.headers">{{ header }}</th></tr></thead><tbody><tr v-for="row in display.table.rows"><td>{{ row.index }}</td><td v-for="cell in row.cells"><template v-if="cell"><span v-for="part in cell.parts" :class="\'t-\' + part[0]">{{ part[1] }}</span></template></td></tr></tbody></table><js-value v-for="(description, index) in display.descriptions" :description="description" :path="[display.logId, index]"></js-value><div v-if="display.stack" class="trace-stack">{{ display.stack }}</div></div></div><div v-if="display.type === \'notice\'" class="console-row notice">{{ display.message }}</div><div v-if="display.type === \'error\'" class="console-row log-error"><span class="row-icon"><icon name="consoleError"></icon></span><div class="row-content">{{ display.message }}</div></div></template></div></div><div class="divider" ref="mainDivider"></div><div id="editor"><ace-editor v-model="jsCode" language="javascript" :theme="theme" :font-size="Math.round(12 * textScale)" @key-combo="onEditorKeyCombo" height="100%"></ace-editor></div></div><div id="bottomNav"><div class="brand"><button class="logo-button" title="About JS Box" @click="openAbout(\'about\')"><span class="logo"><span class="logo-mark">JS</span><span class="logo-text">Box</span></span></button> <span class="runner-badge" :title="runnerMode === \'window\' ? \'Code runs directly in this page\' : \'Code runs in a Web Worker (no DOM access)\'">{{ runnerMode === \'window\' ? \'Window\' : \'Worker\' }}</span></div><div class="buttons"><template v-for="bottomButton in bottomButtons"><span v-if="bottomButton.isSeparator" class="separator"></span> <button v-else :class="bottomButton.className" @click="bottomButton.callback.call(this, $event)" :title="bottomButton.title" :disabled="bottomButton.disableIf &amp;&amp; bottomButton.disableIf.call(this)"><icon :name="bottomButton.iconName"></icon><span v-if="bottomButton.label" class="label">{{ bottomButton.label }}</span></button></template></div></div><div v-if="isMenuOpen" class="more-menu" role="menu" aria-label="More" ref="moreMenu" @keydown="onMenuKeyDown"><div class="menu-row" role="group" aria-label="Text size"><span class="menu-row-label">Text size</span> <button class="menu-item menu-step" role="menuitem" title="Smaller text" aria-label="Smaller text" :disabled="!canShrinkText" @click="changeTextScale(-1)">A&minus;</button> <button class="menu-item menu-step menu-percent" role="menuitem" title="Reset the text size" aria-label="Reset the text size" @click="setTextScale(1)">{{ Math.round(textScale * 100) }}%</button> <button class="menu-item menu-step" role="menuitem" title="Bigger text" aria-label="Bigger text" :disabled="!canGrowText" @click="changeTextScale(1)">A+</button></div><div class="menu-separator"></div><button v-if="isPopOut" class="menu-item" role="menuitem" @click="closeMenu(); bringBack()"><span class="menu-icon"><icon name="popIn"></icon></span>Bring back into the page</button> <button v-else class="menu-item" role="menuitem" @click="popOut()"><span class="menu-icon"><icon name="popOut"></icon></span>Pop out into a window</button> <button class="menu-item" role="menuitem" @click="closeMenu(); openAbout(\'html\')"><span class="menu-icon"><icon name="code"></icon></span>Copy as HTML&hellip;</button> <button class="menu-item" role="menuitem" @click="closeMenu(); resetConsole()"><span class="menu-icon"><icon name="refresh"></icon></span>Reset&hellip;</button><div class="menu-separator"></div><button class="menu-item" role="menuitem" @click="closeMenu(); openAbout(\'about\')"><span class="menu-icon"><icon name="info"></icon></span>About JS Box</button></div><div v-if="isPoppedOut" class="popped-out"><div class="popped-out-content"><span class="logo logo-medium"><span class="logo-mark">JS</span><span class="logo-text">Box</span></span><div class="popped-out-title">This console is open in a separate window</div><div class="popped-out-text">Its code still runs in this page.</div><div class="dialog-buttons"><button class="dialog-button" @click="focusPopOut">Show the window</button> <button class="dialog-button primary" @click="requestPopIn">Bring it back</button></div></div></div><div v-if="isAboutOpen" class="dialog-backdrop" @mousedown.self="closeAbout" @keydown.esc="closeAbout"><div :class="[\'dialog\', \'about-dialog\', aboutTab === \'html\' ? \'is-export\' : \'\']" role="dialog" aria-modal="true" aria-label="About JS Box"><div class="about-header"><div class="tabs" role="tablist"><button role="tab" :aria-selected="aboutTab === \'about\'" :class="[\'tab\', aboutTab === \'about\' ? \'active\' : \'\']" @click="aboutTab = \'about\'">About</button> <button role="tab" :aria-selected="aboutTab === \'html\'" :class="[\'tab\', aboutTab === \'html\' ? \'active\' : \'\']" @click="aboutTab = \'html\'">Copy as HTML</button></div><button class="close-button" ref="aboutCloseButton" title="Close" @click="closeAbout"><icon name="close"></icon></button></div><div v-if="aboutTab === \'about\'" class="about-body"><div class="about-title"><span class="logo logo-medium"><span class="logo-mark">JS</span><span class="logo-text">Box</span></span><div><div class="about-name">YourJS Box <span class="about-aka">aka JS Box</span></div><div class="about-version">Version {{ packageInfo.version }}</div></div></div><p class="about-description">An interactive JavaScript console that can be embedded in any web page with a single script tag.</p><div class="about-links"><a :href="packageInfo.homepage" target="_blank" rel="noopener">Website</a> <a :href="packageInfo.repoUrl" target="_blank" rel="noopener">GitHub</a> <a :href="packageInfo.repoUrl + \'#readme\'" target="_blank" rel="noopener">Documentation</a> <a :href="packageInfo.bugsUrl" target="_blank" rel="noopener">Report an issue</a></div><h3>This console</h3><dl class="about-details"><dt>Code runs in</dt><dd>{{ runnerDescription }}</dd><dt>Theme</dt><dd>{{ themeDescription }}</dd><dt>Code blocks run as</dt><dd>{{ blockTypeDescription }}</dd><dt>Results</dt><dd>{{ showResults ? \'The value of the last expression is shown\' : \'Not shown\' }}</dd><dt>Layout</dt><dd>{{ layoutDescription }}</dd></dl><h3>Keyboard shortcuts</h3><dl class="about-details"><dt><kbd>{{ modKey }}</kbd> + <kbd>Enter</kbd></dt><dd>Run the next block of code</dd><dt><kbd>Esc</kbd></dt><dd>Close this window, the menu or full screen</dd></dl><div class="about-footer">MIT License &copy; 2023-present Christopher West &middot; Built with Vue {{ libraryVersions.vue }}, Ace {{ libraryVersions[\'ace-builds\'] }}, Prism {{ libraryVersions.prismjs }} and Acorn {{ libraryVersions.acorn }}</div></div><div v-else class="about-body export-body"><div class="export-options"><div class="segmented" role="radiogroup" aria-label="Code"><button v-for="option in exportCodeOptions" role="radio" :aria-checked="exportCode === option.value" :class="exportCode === option.value ? \'active\' : \'\'" @click="exportCode = option.value">{{ option.label }}</button></div><div class="segmented" role="radiogroup" aria-label="Format"><button v-for="option in exportFormatOptions" role="radio" :aria-checked="exportFormat === option.value" :class="exportFormat === option.value ? \'active\' : \'\'" @click="exportFormat = option.value">{{ option.label }}</button></div></div><div class="export-note">{{ exportNote }}</div><div class="export-preview"><ace-editor :model-value="exportHtml" language="html" :theme="theme" height="100%" :read-only="true"></ace-editor></div><div class="export-actions"><button class="dialog-button" @click="downloadExport">Download page</button> <button class="dialog-button primary" @click="copyExport">{{ copyLabel }}</button></div></div></div></div><div v-if="dialog" class="dialog-backdrop" @mousedown.self="closeDialog(false)" @keydown.esc="closeDialog(false)"><div class="dialog" role="alertdialog" aria-modal="true" :aria-label="dialog.title"><div class="dialog-title">{{ dialog.title }}</div><div class="dialog-message">{{ dialog.message }}</div><div class="dialog-buttons"><button class="dialog-button" @click="closeDialog(false)">Cancel</button> <button class="dialog-button primary" ref="dialogConfirmButton" @click="closeDialog(true)">{{ dialog.confirmText }}</button></div></div></div></div>',OWN_URL=document.currentScript?.src??"",ORIGINAL_CONSOLE=window[Symbol.for("yourjs-box.originalConsole")]??={...console},LIBRARY_VERSIONS={"ace-builds":"1.44.0",acorn:"8.18.0","prism-themes":"1.9.0",prismjs:"1.30.0",vue:"3.5.43"},DEFAULT_LIBRARIES_URL="https://unpkg.com/{name}@{version}/";function getLibraryFileUrl(librariesUrl,name,path){var librariesUrl=librariesUrl.replace(/\{(name|version)\}/g,(_,key)=>"name"===key?name:LIBRARY_VERSIONS[name]).replace(/\/?$/,"/");return new URL(librariesUrl+path,document.baseURI).href}const RELAYABLE_FUNCS={viewer:["appendLog","appendError","clearDisplays","onCodeRan","updateDescriptionFor"],runner:["clearLogs","reset","runCode","sendDescriptionFor"],host:["focusPopOut","popIn","popOut","requestPopIn","setMaximized"]};function relayMessage(data,targets){var{target,func,args}=Object(data),targets=targets[target];targets&&RELAYABLE_FUNCS[target].includes(func)&&Array.isArray(args)?targets.apply(func,args):ORIGINAL_CONSOLE.error("Unhandled message sent to main handler:",data)}function createRunner(e,t){const{mode:n}=t,r=t.ownUrl||("worker"===n?self.location.href:""),o={};let s=0,i=0,c=!0,a;const l={},u={},f={};let p=[],d=0;const g="yourjs-box.result."+Math.random().toString(36).slice(2);globalThis[Symbol.for(g)]=y;for(const e of["assert","clear","count","countReset","debug","dir","dirxml","error","group","groupCollapsed","groupEnd","info","log","table","time","timeEnd","timeLog","trace","warn"]){const t=console[e];"function"==typeof t&&(console[e]=function(...n){return h(e,n),t.apply(this,arguments)})}function h(t,n){var r=n.length&&void 0!==n[0]?""+n[0]:"default";if("clear"===t)U(),p=[],e({target:"viewer",func:"clearDisplays",args:[!0]});else if("assert"===t){if(!n[0]){const e=n.slice(1);m("assert",e.length?"string"==typeof e[0]?["Assertion failed: "+e[0],...e.slice(1)]:["Assertion failed:",...e]:["Assertion failed: console.assert"])}}else if("count"===t)u[r]=(u[r]||0)+1,m("count",[r+": "+u[r]]);else if("countReset"===t)Object.hasOwn(u,r)?u[r]=0:m("warn",[`Count for '${r}' does not exist`]);else if("time"===t)Object.hasOwn(f,r)?m("warn",[`Timer '${r}' already exists`]):f[r]=performance.now();else if("timeLog"===t||"timeEnd"===t){if(!Object.hasOwn(f,r))return m("warn",[`Timer '${r}' does not exist`]);const e=performance.now()-f[r];"timeEnd"===t&&delete f[r],m(t,[r+`: ${+e.toFixed(3)} ms`,..."timeLog"===t?n.slice(1):[]])}else if("trace"===t){const e=$((new Error).stack??"").split("\n").slice(1).join("\n");m("trace",n.length?n:["console.trace"],{stack:e})}else if("group"===t||"groupCollapsed"===t){const e=""+ ++d;m(t,n.length?n:["console.group"],{groupId:e,isCollapsed:"groupCollapsed"===t}),p.push(e)}else if("groupEnd"===t)p.pop();else{const e="table"===t?x(n[0],n[1]):null;m(t,e?n.slice(0,1):n,{table:e})}}function m(t,n,r,i=0){var c=""+ ++s;o[c]=n.map(e=>({...N(e,i),value:e})),e({target:"viewer",func:"appendLog",args:[{logId:c,key:t,descriptions:o[c].map(v(["value"])),groupIds:p.slice(),...r}]})}function y(e){void 0!==e&&m("result",[e],{},"string"==typeof e?1:0)}function b(t,n){var r="classic"===a&&"SyntaxError"===t?.name&&/\bawait\b/.test(t.message)?'\n(To use top-level await, add data-block-type="module" to the script tag.)':"";e({target:"viewer",func:"appendError",args:[{message:(n?"Uncaught (in promise) ":"Uncaught ")+$(t?.stack??""+(t?.message??t))+r}]})}function $(e){return(""+e).split("\n").filter(e=>!(r&&/^\s*at\b/.test(e)&&e.includes(r))).join("\n").replace(/(snippet-\d+\.js):(\d+):(\d+)/g,(e,t,n,r)=>{var o=l[t];return o&&+n===o.line&&+r>o.column?t+`:${n}:`+Math.max(o.column,r-o.shift):e})}function v(e,t){if(!t)return t=>v(e,t);var n={...t};for(const t of e)delete n[t];return n}function x(e,t){if(null===e||"object"!=typeof e)return null;const n="Value",r=[];let o=!1;const s=Object.keys(e).map(t=>{var n=e[t],s={index:t,values:{},hasValue:!1};if(null===n||"object"!=typeof n&&"function"!=typeof n)o=!0,s.hasValue=!0,s.value=n;else for(const e of Object.keys(n))r.includes(e)||r.push(e),s.values[e]=n[e];return s}),i=Array.isArray(t)?t.map(e=>""+e):r,c=o&&!Array.isArray(t);return{headers:["(index)",...i,...c?[n]:[]],rows:s.map(({index:e,values:t,hasValue:n,value:r})=>({index:e,cells:[...i.map(e=>Object.hasOwn(t,e)?N(t[e],2):null),...c?[n?N(r,2):null]:[]]}))}}function j(e){var t;return null==e?""+e:"object"==(t=typeof e)||"undefined"==t?Object.prototype.toString.call(e).slice(8,-1):t}function O(e,t){try{const t=Object.getPrototypeOf(e)?.constructor?.name;if(t&&"string"==typeof t)return t}catch(e){}return t}addEventListener("error",e=>{b(void 0!==e.error?e.error:e.message)}),addEventListener("unhandledrejection",e=>{b(e.reason,!0)});const w=5,E=100;function N(e,t=0,n=!1){var r=j(e),o="function"!==r&&r===r.toLowerCase(),s=void 0;return{typeName:r,isPrimitive:o,parts:n?[["text","Object"!==r?r:O(e,r)]]:k(e,t,r)}}function k(e,t,n=j(e)){if("string"===n)return t?[["string",A(e=1<t&&100<e.length?e.slice(0,99)+"\u2026":e)]]:[["text",e]];if("number"===n)return[["number",Object.is(e,-0)?"-0":""+e]];if("bigint"===n)return[["number",e+"n"]];if("boolean"===n)return[["number",""+e]];if("null"===n||"undefined"===n)return[["null",n]];if("symbol"===n)return[["symbol",e.toString()]];if("function"===n)return S(e,t);try{return L(e,t,n)}catch(e){return[["text",n]]}}function A(e){var t=JSON.stringify(e);return e.includes("'")?t:`'${t.slice(1,-1).replace(/\\"/g,'"')}'`}function S(e,t){let n="";try{n=Function.prototype.toString.call(e)}catch(e){}var r=/^class\b/.test(n);return t?1<t?[["function","\u0192"]]:[["function",r?"class "+e.name:`\u0192 ${e.name}()`]]:[["text",r?n:n.replace(/^(async\s+)?function\b\s*/,"$1\u0192 ")]]}function L(e,t,n){var r=O(e,n),o=/^Array(?:[^a-z]|$)|[^A-Z]Array$/.test(n);if("Date"===n)return[["text",isNaN(e)?"Invalid Date":Date.prototype.toString.call(e)]];if("RegExp"===n)return[["regexp",""+e]];if("Promise"===n)return[["text",r+" {\u2026}"]];if("undefined"!=typeof Node&&e instanceof Node)return e.nodeType===Node.ELEMENT_NODE?[["node",e.localName+(e.id?"#"+e.id:"")+[...e.classList].map(e=>"."+e).join("")]]:e.nodeType===Node.TEXT_NODE?[["string",A(e.data)]]:[["node",e.nodeName]];if(e instanceof Error)return[["text",t?e.name+": "+e.message:$(e.stack??""+e)]];if(1<t)return o?[["text",`${r}(${e.length})`]]:"Map"===n||"Set"===n?[["text",`${r}(${e.size})`]]:[["text","Object"===r?"{\u2026}":r]];const s=[],i=(e,t,n)=>{e.forEach((e,t)=>{t&&s.push(["text",", "]),n(e)}),t>e.length&&s.push(["text",(e.length?", ":"")+"\u2026"])};if(o){const t=e.length;s.push(["text","Array"===n&&"Array"===r?`(${t}) [`:`${r}(${t}) [`]),i(Array.from({length:Math.min(t,E)},(e,t)=>t),t,t=>s.push(...t in e?k(e[t],2):[["null","empty"]])),s.push(["text","]"])}else if("Map"===n||"Set"===n){const t=[...e].slice(0,E);s.push(["text",`${r}(${e.size}) {`]),i(t,e.size,e=>{"Map"===n?s.push(...k(e[0],2),["text"," => "],...k(e[1],2)):s.push(...k(e,2))}),s.push(["text","}"])}else{const t=Object.keys(e);"Object"!==r&&s.push(["text",r+" "]),"Number"===n||"String"===n||"Boolean"===n?s.push(["text","{"],...k(e.valueOf(),2),["text","}"]):(s.push(["text","{"]),i(t.slice(0,w),t.length,t=>{var n=Object.getOwnPropertyDescriptor(e,t);s.push(["key",t],["text",": "],..."value"in n?k(n.value,2):[["text","(\u2026)"]])}),s.push(["text","}"]))}return s}function R(e,t=e){const n=j(e),r=[],o=[],s=[],i=[];if(null!==e&&("object"==typeof e||"function"==typeof e)){let c=!1;try{if("Map"===n){for(const[t,n]of[...e])r.push([k(t,2).map(e=>e[1]).join(""),N(n,1)]),o.push({value:n});c=!0}else if("Array"!==n&&"function"!==n&&"function"==typeof e[Symbol.iterator]){let t=0;for(const n of e)r.push([""+t,N(n,1)]),o.push({value:n}),++t;c=!0}}catch(e){r.length=o.length=0}if(!c)for(const n of Object.getOwnPropertyNames(e))try{const s=Object.getOwnPropertyDescriptor(e,n),i="value"in s?s.value:Reflect.get(e,n,t);r.push([n,N(i,1),s.enumerable]),o.push({value:i})}catch(e){}var a=Object.getPrototypeOf(e);null!==a&&(s.push(["[[Prototype]]",N(a,1,!0)]),i.push({value:a,receiver:t}))}return{entries:r,protoEntries:s,$entries:o,$protoEntries:i}}async function C(t,r){const{blockType:o,resultRange:s}=Object(r),c=`snippet-${++i}.js`;if(Array.isArray(s)){const[e,n]=s,r=`globalThis[Symbol.for(${JSON.stringify(g)})]((`,o=t.slice(0,e).split("\n");l[c]={line:o.length,column:o[o.length-1].length+1,shift:r.length},t=t.slice(0,e)+r+t.slice(e,n)+"))"+t.slice(n)}var r=t+`
3
- //# sourceURL=`+c;a="module"===o?"module":"classic";try{if("module"===o)await import("data:text/javascript;charset=utf-8,"+encodeURIComponent(r));else if("worker"===n)T(r);else{const e=document.createElement("script");e.textContent=r,document.head.appendChild(e),e.remove()}}catch(e){b(e)}a=void 0,e({target:"viewer",func:"onCodeRan",args:[]})}function T(e){if(c)try{return importScripts("data:text/javascript;charset=utf-8,"+encodeURIComponent(e))}catch(e){if("NetworkError"!==e?.name)throw e;c=!1}var t=URL.createObjectURL(new Blob([e],{type:"text/javascript"}));try{importScripts(t)}finally{URL.revokeObjectURL(t)}}function D(t){let n=o,r=0;for(let e of t)r&&r%2==0&&(e="$"+e),n=n?.[e],r++;var s;n&&(s=R(n.value,"receiver"in n?n.receiver:n.value),Object.assign(n,s),e({target:"viewer",func:"updateDescriptionFor",args:[t,v(["$entries","$protoEntries"],s)]}))}function U(){for(const e of Object.keys(o))delete o[e];p=[]}return{clearLogs:U,runCode:C,sendDescriptionFor:D}}function createWorkerRunner(onMessage){const WORKER_SOURCE="(function(){var runner = ("+createRunner+')(function(m) { postMessage(m); }, {mode: "worker"});onmessage = function(e) {var d = e.data;if (d && Object.prototype.hasOwnProperty.call(runner, d.func) && Array.isArray(d.args)) {runner[d.func].apply(null, d.args);}};postMessage({target: "main", func: "ready"});})();';let canUseDataUrl=!0,blobUrl,worker,isReady,pendingMessages;function start(){isReady=!1,pendingMessages=[];var url=canUseDataUrl?"data:text/javascript;charset=utf-8,"+encodeURIComponent(WORKER_SOURCE):blobUrl??=URL.createObjectURL(new Blob([WORKER_SOURCE],{type:"text/javascript"}));try{worker=new Worker(url)}catch(e){if(canUseDataUrl)return canUseDataUrl=!1,start();throw e}const thisWorker=worker;worker.onmessage=e=>{if(thisWorker===worker)if("main"===e.data?.target&&"ready"===e.data.func){isReady=!0;for(const message of pendingMessages.splice(0))worker.postMessage(message)}else onMessage(e.data)},worker.onerror=e=>{var e;thisWorker===worker&&!isReady&&canUseDataUrl&&(e.preventDefault(),canUseDataUrl=!1,e=pendingMessages,worker.terminate(),start(),pendingMessages.push(...e))}}return start(),{apply(func,args){"reset"===func?(worker.terminate(),start()):isReady?worker.postMessage({func:func,args:args}):pendingMessages.push({func:func,args:args})}}}function createWindowRunner(onMessage){const runner=createRunner(onMessage,{mode:"window",ownUrl:OWN_URL});return{apply(func,args){"reset"===func?runner.clearLogs():runner[func](...args)}}}function main(script){const dataset=JSON.parse(JSON.stringify(script.dataset)),runnerMode="window"===dataset.runner?"window":"worker",blockType="module"===dataset.blockType?"module":"classic",showResults="false"!==dataset.showResults,libraryUrl=getLibraryFileUrl.bind(null,dataset.librariesUrl||DEFAULT_LIBRARIES_URL);let inlineViewer,popOutViewer=null,popOutWindow=null,popOutWatcher,activeViewer;var sendToViewer=data=>relayMessage(data,{viewer:activeViewer});const runner=("window"==runnerMode?createWindowRunner:createWorkerRunner)(sendToViewer),theme=/^(light|dark)$/.test(dataset.theme)?dataset.theme:matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light",hostFuncs={setMaximized(isMaximized){var{style}=inlineViewer.iframe;isMaximized?(inlineViewer.normalCssText??=style.cssText,Object.assign(style,{position:"fixed",inset:"0",width:"100%",height:"100%",zIndex:"2147483647"})):null!=inlineViewer.normalCssText&&(style.cssText=inlineViewer.normalCssText,inlineViewer.normalCssText=null)},popOut(state){if(popOutWindow)popOutWindow.focus();else{var rect=inlineViewer.iframe.getBoundingClientRect(),width=Math.max(820,Math.round(rect.width)),rect=Math.max(560,Math.round(rect.height));const newWindow=open("","_blank",`popup,width=${width},height=`+rect);newWindow?(popOutWindow=newWindow,popOutViewer=createViewer(newWindow,state),newWindow.yourjsBoxPopIn=state=>newWindow===popOutWindow&&hostFuncs.popIn(state),activeViewer=popOutViewer,inlineViewer.call("setPoppedOut",!0),popOutWatcher=setInterval(()=>{newWindow.closed&&setTimeout(()=>newWindow===popOutWindow&&hostFuncs.popIn(null),300)},500)):inlineViewer.call("onPopOutFailed")}},popIn(state){var oldWindow=popOutWindow;oldWindow&&(clearInterval(popOutWatcher),popOutWindow=null,popOutViewer.dispose(),popOutViewer=null,(activeViewer=inlineViewer).call("setPoppedOut",!1,state),oldWindow.closed||oldWindow.close())},requestPopIn(){popOutViewer&&popOutViewer.call("popIn")},focusPopOut(){popOutWindow?.focus()}};function createViewer(targetWindow,state){return createCallableFrame({jsCode(){let mountedApp;const IS_MISSING_LIBRARIES=!window.Vue||!window.ace||!window.Prism,Prism=(IS_MISSING_LIBRARIES&&document.querySelector("#splash").classList.add("failed"),window.Prism),MIN_LOADING_TIME=(delete window.Prism,Prism?.plugins.autoloader.loadLanguages("javascript"),1e3),POP_IN_FUNCTION_NAME="yourjsBoxPopIn",TEXT_SCALES=[.75,.9,1,1.15,1.3,1.5,1.75,2],TEXT_SCALE_STORAGE_KEY="yourjs-box.textScale";function loadTextScale(){try{var e=+localStorage.getItem("yourjs-box.textScale");return TEXT_SCALES.includes(e)?e:1}catch(e){return 1}}const NARROW_WIDTH=600;function getAutoDividerOrient(){return innerWidth<600?"horizontal":"vertical"}function init(e,t,i){if(!IS_MISSING_LIBRARIES){const s=t.hidePrefix??"",n=matchMedia("(prefers-color-scheme: dark)"),o=unindentMin(e),{visibleCode:r,hiddenGroups:a}=extractHiddenGroups(o,s),l=/Mac|iPhone|iPad/.test(navigator.platform),d=()=>a.map(e=>({...e}));mountedApp=Vue.createApp({data:()=>({displays:[],hidePrefix:s,hiddenGroups:d(),runnerMode:i.runnerMode,blockType:i.blockType,showResults:i.showResults,packageInfo:i.packageInfo,libraryVersions:i.libraryVersions,runHistory:[],isAboutOpen:!1,aboutTab:"about",exportCode:"current",exportFormat:"snippet",copyLabel:"Copy",runningCount:0,dialog:null,isDisplaysScrolledToBottom:!0,forcedTheme:/^(light|dark)$/.test(t.theme)?t.theme:null,prefersDark:n.matches,runCount:0,jsCode:r,isDividerOrientAuto:!/^(horizontal|vertical)$/.test(t.dividerOrient),dividerOrient:/^(horizontal|vertical)$/.test(t.dividerOrient)?t.dividerOrient:getAutoDividerOrient(),isMovingDivider:!1,dividerPct:"50%",dividerSize:"8px",tempDividerPct:null,isMenuOpen:!1,textScale:loadTextScale(),isFullscreen:!1,isMaximized:!1,isPopOut:i.isPopOut,isPoppedOut:!1,...i.popOutState??{}}),computed:{theme(){return this.forcedTheme??(this.prefersDark?"dark":"light")},modKey:()=>l?"\u2318":"Ctrl",runnerDescription(){return"window"===this.runnerMode?"This page (it can use the page's globals and DOM)":"A Web Worker (isolated from the page, no DOM)"},themeDescription(){return`${"dark"===this.theme?"Dark":"Light"} (${this.forcedTheme?"set by data-theme":"follows your system"})`},blockTypeDescription(){return"module"===this.blockType?"Modules (top-level await and imports work, declarations stay in each block)":"Classic scripts (top-level declarations are shared between blocks)"},collapsedGroupIds(){return new Set(this.displays.filter(e=>e.groupId&&e.isCollapsed).map(e=>e.groupId))},layoutDescription(){return("vertical"===this.dividerOrient?"Editor beside the console":"Editor below the console")+(this.isDividerOrientAuto?" (automatic)":"")},exportCodeOptions:()=>[{value:"current",label:"Current code",note:"The code that already ran followed by the code in the editor."},{value:"original",label:"Original code",note:"The code this console started with."},{value:"blank",label:"Blank",note:"An empty console with the same settings."}],exportFormatOptions:()=>[{value:"snippet",label:"Embed snippet"},{value:"page",label:"Full page"}],exportNote(){return this.exportCodeOptions.find(e=>e.value===this.exportCode).note},exportJsCode(){if("original"===this.exportCode)return o;if("blank"===this.exportCode)return"";const e=this.runHistory.slice(),t=this.hiddenGroups.slice();let i=this.runCount;var s=()=>{for(;t.length&&t[0].runCount<=i;)e.push(t.shift().allLines)};s();for(const t of parseJSCodeGroups(this.jsCode))t.allLines.trim()&&(e.push(t.allLines),i++,s());return e.push(...t.map(e=>e.allLines)),joinCodeBlocks(e)},exportDataset(){const{librariesUrl:e,...i}=t;return i},exportHtml(){return buildConsoleHtml({code:this.exportJsCode,dataset:this.exportDataset,packageInfo:this.packageInfo,isFullPage:"page"===this.exportFormat})},bottomButtons(){var e=this.isFullscreen||this.isMaximized;return[{iconName:"clear",title:"Clear console",callback(){this.clearConsole()}},{iconName:"horizontalView",title:"Show the editor below the console",callback(){this.setDividerOrient("horizontal")},showIf(){return"horizontal"!==this.dividerOrient}},{iconName:"verticalView",title:"Show the editor beside the console",callback(){this.setDividerOrient("vertical")},showIf(){return"vertical"!==this.dividerOrient}},{iconName:e?"exitFullscreen":"fullscreen",title:e?"Exit full screen":"Full screen",callback(){this.toggleFullscreen()}},{iconName:"more",title:"More",className:"more-button",callback(){this.toggleMenu()}},{iconName:this.runningCount?"spinner":"play",label:"Run",className:"primary",title:`Run the next block of code (${l?"\u2318":"Ctrl+"}Enter)`,callback(){this.runCode()},disableIf(){return!this.canRunCode}}].filter(e=>!e.showIf||e.showIf.call(this))},canShrinkText(){return this.textScale>TEXT_SCALES[0]},canGrowText(){return this.textScale<TEXT_SCALES[TEXT_SCALES.length-1]},canRunCode(){return this.jsCode.trim()},mainElemClassNames(){return["vertical"===this.dividerOrient?"col-orient":"row-orient",this.isMovingDivider?"is-moving-divider":""].join(" ")},mainElemStyles(){return{"--divider-size":this.dividerSize,"--editor-pct":this.dividerPct,"--temp-editor-pct":this.tempDividerPct}}},methods:{onEditorKeyCombo(e){(e.ctrlKey||e.metaKey)&&"Enter"===e.key&&this.canRunCode&&this.runCode()},runCode(){this.isDisplaysScrolledToBottom=!0;var[e,...t]=parseJSCodeGroups(this.jsCode);this.runGroup(e),this.jsCode=t.map(e=>e.allLines).join("\n"),this.runCount++},runHiddenGroups(){var{hiddenGroups:e}=this;e.length&&e[0].runCount<=this.runCount&&this.runGroup(e.shift())},runGroup(e){var{header:t,isHidden:i}=parseGroupHeader(e.headerLines,this.hidePrefix);this.displays.push({type:"prism",header:t,isHidden:i,isCodeShown:!i,value:e.lines}),this.runningCount++,this.runHistory.push(e.allLines),messageParent({target:"runner",func:"runCode",args:[e.lines,{blockType:this.blockType,resultRange:this.showResults&&!i?findLastExpression(e.lines,this.blockType):null}]})},clearConsole(){this.displays=[],messageParent({target:"runner",func:"clearLogs",args:[]})},async resetConsole(){await this.confirm({title:"Reset the console?",message:"The output will be cleared and the editor will go back to the original code."+("window"===this.runnerMode?" Anything the code already defined on the page will stay defined.":""),confirmText:"Reset"})&&(this.displays=[],this.jsCode=r,this.hiddenGroups=d(),this.runCount=0,this.runningCount=0,this.runHistory=[],messageParent({target:"runner",func:"reset",args:[]}),this.runHiddenGroups())},async copyToEditor(e){this.jsCode.trim()&&this.jsCode!==e&&!await this.confirm({title:"Replace the code in the editor?",message:"The code that is currently in the editor will be replaced with a copy of the code you selected.",confirmText:"Replace"})||(this.jsCode=e)},confirm(e){return this.dialog?.resolve(!1),new Promise(t=>{this.dialog={...e,resolve:t},this.$nextTick(()=>this.$refs.dialogConfirmButton?.focus())})},openAbout(e){this.aboutTab=e,this.isAboutOpen=!0,this.$nextTick(()=>this.$refs.aboutCloseButton?.focus())},closeAbout(){this.isAboutOpen=!1},async copyExport(){var e=this.exportHtml;try{await navigator.clipboard.writeText(e)}catch(t){var e=Object.assign(document.createElement("textarea"),{value:e});document.body.appendChild(e),e.select(),document.execCommand("copy"),e.remove()}this.copyLabel="Copied!",clearTimeout(this.copyLabelTimeout),this.copyLabelTimeout=setTimeout(()=>this.copyLabel="Copy",1600)},downloadExport(){const e=buildConsoleHtml({code:this.exportJsCode,dataset:this.exportDataset,packageInfo:this.packageInfo,isFullPage:!0}),t=URL.createObjectURL(new Blob([e],{type:"text/html"}));Object.assign(document.createElement("a"),{href:t,download:"js-box.html"}).click(),setTimeout(()=>URL.revokeObjectURL(t),1e3)},onLogRowClick(e,t){e.groupId&&!t.target.closest(".js-value-header.expandable")&&(e.isCollapsed=!e.isCollapsed)},isInCollapsedGroup(e){const{collapsedGroupIds:t}=this;return!!t.size&&!!e.groupIds?.some(e=>t.has(e))},getState(){return JSON.parse(JSON.stringify({displays:this.displays,jsCode:this.jsCode,runHistory:this.runHistory,hiddenGroups:this.hiddenGroups,runCount:this.runCount,runningCount:this.runningCount,dividerOrient:this.dividerOrient,isDividerOrientAuto:this.isDividerOrientAuto,dividerPct:this.dividerPct}))},restoreState(e){Object.assign(this,e),this.isDisplaysScrolledToBottom=!0},toggleMenu(){this.isMenuOpen?this.closeMenu():(this.isMenuOpen=!0,this.$nextTick(()=>this.$refs.moreMenu?.querySelector(".menu-item:not(:disabled)")?.focus()))},closeMenu(e){this.isMenuOpen=!1,e&&document.querySelector("#bottomNav .more-button")?.focus()},onMenuKeyDown(e){var t,i,s;"Escape"===e.key?(e.stopPropagation(),this.closeMenu(!0)):"ArrowDown"!==e.key&&"ArrowUp"!==e.key||(e.preventDefault(),i=(t=[...this.$refs.moreMenu.querySelectorAll(".menu-item:not(:disabled)")]).indexOf(document.activeElement),t[(i+("ArrowDown"===e.key?1:t.length-1))%t.length]?.focus())},changeTextScale(e){var e=TEXT_SCALES.indexOf(this.textScale)+e;0<=e&&e<TEXT_SCALES.length&&this.setTextScale(TEXT_SCALES[e])},setTextScale(e){this.textScale=e;try{localStorage.setItem("yourjs-box.textScale",""+e)}catch(e){}},async toggleFullscreen(){if(this.isMaximized)this.setMaximized(!1);else if(document.fullscreenElement)await document.exitFullscreen();else try{await document.documentElement.requestFullscreen()}catch(e){this.isPopOut||this.setMaximized(!0)}},setMaximized(e){this.isMaximized=e,messageParent({target:"host",func:"setMaximized",args:[e]})},popOut(){this.closeMenu(),this.isMaximized&&this.setMaximized(!1),messageParent({target:"host",func:"popOut",args:[this.getState()]})},bringBack(){this.hasSentState=!0;var e=window.yourjsBoxPopIn;"function"==typeof e?e(this.getState()):messageParent({target:"host",func:"popIn",args:[this.getState()]})},focusPopOut(){messageParent({target:"host",func:"focusPopOut",args:[]})},requestPopIn(){messageParent({target:"host",func:"requestPopIn",args:[]})},onWindowMouseDown(e){this.isMenuOpen&&!e.target.closest(".more-menu, .more-button")&&this.closeMenu()},onWindowKeyDown(e){"Escape"!==e.key||!this.isMaximized||this.isMenuOpen||this.dialog||this.isAboutOpen||this.setMaximized(!1)},closeDialog(e){var{dialog:t}=this;this.dialog=null,t?.resolve(e)},setDividerOrient(e){this.isDividerOrientAuto=!1,this.dividerOrient=e},onWindowResize(){this.isDividerOrientAuto&&(this.dividerOrient=getAutoDividerOrient())},onDisplaysScroll(){var{scrollTop:e,scrollHeight:t,clientHeight:i}=this.$refs.displaysScroller;this.isDisplaysScrolledToBottom=t-e-i<8},getEditorPct(e){var t=this.$refs.main.getBoundingClientRect(),{dividerOrient:i}=this,s=e.pageX-t.left,e=e.pageY-t.top,o=t.width,t=t.height;return 100-100*Math.min(Math.max(.2,"vertical"===i?s/o:e/t),.8)+"%"},onMainElemMouseDown(e){e.target===this.$refs.mainDivider&&(this.isMovingDivider=!0,this.tempDividerPct=this.getEditorPct(e))},onWindowMouseMove(e){this.isMovingDivider&&(this.tempDividerPct=this.getEditorPct(e))},onWindowMouseUp(e){this.isMovingDivider&&(this.isMovingDivider=!1,this.dividerPct=this.getEditorPct(e))},onWindowError(e){this.displays.push({type:"error",message:e.error?.stack??e.message??e.error?.message??""+e.error,line:e.lineno,column:e.colno})}},watch:{textScale:{handler(e){document.documentElement.style.setProperty("--text-scale",e)},immediate:!0},theme:{handler(e){document.documentElement.dataset.theme=e},immediate:!0},"displays.length"(){this.isDisplaysScrolledToBottom&&this.$nextTick(()=>{var e=this.$refs.displaysScroller;e.scrollTop=e.scrollHeight})}},mounted(){addEventListener("mousemove",this.onWindowMouseMove),addEventListener("mousedown",this.onWindowMouseDown),addEventListener("keydown",this.onWindowKeyDown),addEventListener("resize",this.onWindowResize),addEventListener("mouseup",this.onWindowMouseUp),addEventListener("error",this.onWindowError),n.addEventListener("change",e=>this.prefersDark=e.matches),document.addEventListener("fullscreenchange",()=>this.isFullscreen=!!document.fullscreenElement),this.isPopOut&&addEventListener("pagehide",()=>this.hasSentState||this.bringBack()),this.runningCount||this.runHiddenGroups(),setTimeout(()=>document.querySelector("#splash").classList.add("hidden"),Math.max(0,(this.isPopOut?0:1e3)-performance.now()))}}).component("ace-editor",getAceComponentProps()).component("prism",getPrismComponentProps()).component("icon",getIconComponentProps()).component("js-value",getJSValueComponentProps()).mount(document.querySelector("#vueApp"))}}function getAceComponentProps(){return{data:()=>({annotations:[]}),props:["fontSize","height","keybinding","language","modelValue","readOnly","theme","width"],computed:{infoNotes(){return this.annotations.filter(({type:e})=>"info"===e)},warningNotes(){return this.annotations.filter(({type:e})=>"warning"===e)},errorNotes(){return this.annotations.filter(({type:e})=>"error"===e)},style(){return{height:null!=this.height?"number"==typeof this.height?this.height+"px":this.height:"150px",width:null!=this.width?"number"==typeof this.width?this.width+"px":this.width:"100%"}},modeSig(){return"ace/mode/"+(this.language??"text")},themeSig(){return"ace/theme/"+(""+(this.theme??"light")).replace(/^light$|(^dark$)/i,(e,t)=>"cloud_editor"+(t?"_dark":""))}},watch:{themeSig(e){this.editor.setTheme(e)},fontSize(e){e&&this.editor.setFontSize(e)},modelValue(e){e!==this.editor.getValue()&&this.editor.setValue(e,-1)}},async mounted(){const e=ace.edit(this.$refs.editor,{value:this.modelValue,mode:this.modeSig,theme:this.themeSig});this.editor=e,this.fontSize&&e.setFontSize(this.fontSize),this.readOnly&&(e.setReadOnly(!0),e.setHighlightActiveLine(!1),e.session.setUseWorker(!1)),e.setKeyboardHandler("ace/keyboard/vscode"),e.commands.removeCommand("addLineAfter"),e.commands.removeCommand("addLineBefore"),e.on("change",()=>this.$emit("update:modelValue",e.getValue())),e.session.on("changeAnnotation",()=>{var t=JSON.stringify(this.errorNotes),i=JSON.stringify(this.infoNotes),s=JSON.stringify(this.warningNotes),{errorNotes:n,infoNotes:o,warningNotes:r}=(this.annotations=e.getSession().getAnnotations(),this);t!==JSON.stringify(n)&&this.$emit("changeErrorNotes",n),i!==JSON.stringify(o)&&this.$emit("changeInfoNotes",o),s!==JSON.stringify(r)&&this.$emit("changeWarningNotes",r)}),e.textInput.getElement().addEventListener("keydown",e=>{16!==e.keyCode&&17!==e.keyCode&&18!==e.keyCode&&91!==e.keyCode&&92!==e.keyCode&&93!==e.keyCode&&(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey&&1<(e.key??"").length)&&this.$emit("keyCombo",e)})},template:'<div ref="editor" :style="style"></div>'}}function getPrismComponentProps(){return{data:()=>({annotations:[]}),props:["code","isDark","language","lineNumbers","matchBraces"],computed:{html(){},preStyle(){return{filter:!1!==(this.isDark??!1)?"none":"invert(1) hue-rotate(180deg) brightness(1.1)",margin:0,paddingTop:"0.5em",paddingBottom:"0.5em"}}},watch:{code(){this.redraw()},language(){this.redraw()},lineNumbers(){this.redraw()},matchBraces(){this.redraw()}},methods:{async redraw(){const e=this.$refs.pre,t=this.$refs.code;t.textContent=this.code,t.className="language-javascript",e.className="";for(const t of["lineNumbers","matchBraces"]){var i;null!=this[t]&&(i=t.replace(/[A-Z]+/g,"-$&").toLowerCase(),e.className+=" "+i)}Prism.highlightElement(t)}},async mounted(){await this.redraw()},template:'<pre ref="pre" :style="preStyle"><code ref="code"></code></pre>'}}function getIconComponentProps(){return{props:["name"],computed:{svgCode(){var e={missing:'<svg viewBox="0 0 32 32"><circle cx="16" cy="22.5" r="1.5" fill="currentColor"/><path fill="currentColor" d="M17 19h-2v-4h2c1.103 0 2-.897 2-2s-.897-2-2-2h-2c-1.103 0-2 .897-2 2v.5h-2V13c0-2.206 1.794-4 4-4h2c2.206 0 4 1.794 4 4s-1.794 4-4 4z"/><path fill="currentColor" d="M29.391 14.527L17.473 2.609A2.078 2.078 0 0 0 16 2c-.533 0-1.067.203-1.473.609L2.609 14.527C2.203 14.933 2 15.466 2 16s.203 1.067.609 1.473L14.526 29.39c.407.407.941.61 1.474.61s1.067-.203 1.473-.609L29.39 17.474c.407-.407.61-.94.61-1.474s-.203-1.067-.609-1.473M16 28.036L3.965 16L16 3.964L28.036 16z"/></svg>',trash:'<svg viewBox="0 0 15 15"><path fill="currentColor" fill-rule="evenodd" d="M5.5 1a.5.5 0 0 0 0 1h4a.5.5 0 0 0 0-1zM3 3.5a.5.5 0 0 1 .5-.5h8a.5.5 0 0 1 0 1H11v8a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V4h-.5a.5.5 0 0 1-.5-.5M5 4h5v8H5z" clip-rule="evenodd"/></svg>',play:'<svg viewBox="0 0 16 16"><path fill="currentColor" d="M2 1v14l12-7z"/></svg>',refresh:'<svg viewBox="0 0 15 15"><path fill="currentColor" fill-rule="evenodd" d="M1.903 7.297c0 3.044 2.207 5.118 4.686 5.547a.521.521 0 1 1-.178 1.027C3.5 13.367.861 10.913.861 7.297c0-1.537.699-2.745 1.515-3.663c.585-.658 1.254-1.193 1.792-1.602H2.532a.5.5 0 0 1 0-1h3a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-1 0V2.686l-.001.002c-.572.43-1.27.957-1.875 1.638c-.715.804-1.253 1.776-1.253 2.97m11.108.406c0-3.012-2.16-5.073-4.607-5.533a.521.521 0 1 1 .192-1.024c2.874.54 5.457 2.98 5.457 6.557c0 1.537-.699 2.744-1.515 3.663c-.585.658-1.254 1.193-1.792 1.602h1.636a.5.5 0 1 1 0 1h-3a.5.5 0 0 1-.5-.5v-3a.5.5 0 1 1 1 0v1.845h.002c.571-.432 1.27-.958 1.874-1.64c.715-.803 1.253-1.775 1.253-2.97" clip-rule="evenodd"/></svg>',horizontalView:'<svg viewBox="0 0 15 15"><path fill="currentColor" fill-rule="evenodd" d="M1.5 2h12a.5.5 0 0 1 .5.5V7H1V2.5a.5.5 0 0 1 .5-.5M1 8v4.5a.5.5 0 0 0 .5.5h12a.5.5 0 0 0 .5-.5V8zM0 2.5A1.5 1.5 0 0 1 1.5 1h12A1.5 1.5 0 0 1 15 2.5v10a1.5 1.5 0 0 1-1.5 1.5h-12A1.5 1.5 0 0 1 0 12.5z" clip-rule="evenodd"/></svg>',verticalView:'<svg viewBox="0 0 15 15"><path fill="currentColor" fill-rule="evenodd" d="M8 2h5.5a.5.5 0 0 1 .5.5v10a.5.5 0 0 1-.5.5H8zM7 2H1.5a.5.5 0 0 0-.5.5v10a.5.5 0 0 0 .5.5H7zm-7 .5A1.5 1.5 0 0 1 1.5 1h12A1.5 1.5 0 0 1 15 2.5v10a1.5 1.5 0 0 1-1.5 1.5h-12A1.5 1.5 0 0 1 0 12.5z" clip-rule="evenodd"/></svg>',error:'<svg viewBox="0 0 24 24"><path fill="currentColor" d="M11 15h2v2h-2zm0-8h2v6h-2zm1-5C6.47 2 2 6.5 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 18a8 8 0 0 1-8-8a8 8 0 0 1 8-8a8 8 0 0 1 8 8a8 8 0 0 1-8 8"/></svg>',fullscreen:'<svg viewBox="0 0 16 16"><path d="M2.5 6V2.5H6M10 2.5h3.5V6M13.5 10v3.5H10M6 13.5H2.5V10" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',exitFullscreen:'<svg viewBox="0 0 16 16"><path d="M6 2.5V6H2.5M13.5 6H10V2.5M10 13.5V10h3.5M2.5 10H6v3.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',more:'<svg viewBox="0 0 16 16"><circle cx="3.5" cy="8" r="1.4" fill="currentColor"/><circle cx="8" cy="8" r="1.4" fill="currentColor"/><circle cx="12.5" cy="8" r="1.4" fill="currentColor"/></svg>',popOut:'<svg viewBox="0 0 16 16"><path d="M9.5 2.5h4v4M13.5 2.5L8 8M12 9.5v3a1 1 0 0 1-1 1H3.5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h3" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',popIn:'<svg viewBox="0 0 16 16"><path d="M12 8.5H8V4.5M8 8.5l5.5-5.5M12 10.5v2a1 1 0 0 1-1 1H3.5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h2" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',code:'<svg viewBox="0 0 16 16"><path d="M5.5 4.5L2 8l3.5 3.5M10.5 4.5L14 8l-3.5 3.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',info:'<svg viewBox="0 0 16 16"><circle cx="8" cy="8" r="6.25" fill="none" stroke="currentColor" stroke-width="1.5"/><path d="M8 7.25v4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/><circle cx="8" cy="5" r="1" fill="currentColor"/></svg>',result:'<svg viewBox="0 0 16 16"><path d="M9 4.5L5.5 8 9 11.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><circle cx="12" cy="8" r="1.1" fill="currentColor"/></svg>',close:'<svg viewBox="0 0 16 16"><path d="M4 4l8 8m0-8l-8 8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>',clear:'<svg viewBox="0 0 16 16"><circle cx="8" cy="8" r="6" fill="none" stroke="currentColor" stroke-width="1.5"/><path d="M3.75 12.25l8.5-8.5" stroke="currentColor" stroke-width="1.5"/></svg>',copyToEditor:'<svg viewBox="0 0 16 16"><path d="M6 3.5L2.5 7 6 10.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 7h6.5a4 4 0 0 1 4 4v1.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',spinner:'<svg viewBox="0 0 16 16" class="spin"><path d="M8 1.75a6.25 6.25 0 1 1-6.25 6.25" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"/></svg>',chevron:'<svg viewBox="0 0 16 16"><path d="M6 4l4 4-4 4" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',consoleError:'<svg viewBox="0 0 16 16"><circle cx="8" cy="8" r="7" fill="currentColor"/><path d="M5.5 5.5l5 5m0-5l-5 5" stroke="#fff" stroke-width="1.75" stroke-linecap="round"/></svg>',consoleWarning:'<svg viewBox="0 0 16 16"><path d="M8 1.75L14.75 14H1.25z" fill="currentColor" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/><path d="M8 6v3.5" stroke="#202124" stroke-width="1.75" stroke-linecap="round"/><circle cx="8" cy="11.75" r="1" fill="#202124"/></svg>'};return(e[this.name]??e.missing).replace("<svg",'$& xmlns="http://www.w3.org/2000/svg" style="height: 1em; width: 1em; display: inline-block; transform: translateY(0.1em);"')}},template:'<span v-html="svgCode"></span>'}}function getJSValueComponentProps(){return{props:["description","path","name","isDimName"],data:()=>({isExpanded:!1,hasBeenExpanded:!1}),watch:{isExpanded(e){e&&!this.hasBeenExpanded&&(this.hasBeenExpanded=e)}},computed:{isPartialDescription(){return void 0===this.description.entries},isExpandable(){return!this.description.isPrimitive},isEntry(){return null!=this.name},classNames(){return["js-value",this.isEntry||this.isExpandable&&this.isExpanded?"d-block":"d-inline-block",this.isExpanded?"expanded":""]},entryGroups:()=>[{key:"entries",isDim:e=>!1===e[2]},{key:"protoEntries",isDim:()=>!0}]},methods:{toggleExpanded(){this.isExpandable&&(this.isExpanded=!this.isExpanded,this.isExpanded)&&this.isPartialDescription&&messageParent({target:"runner",func:"sendDescriptionFor",args:[this.path]})}},template:'\n <div :class="classNames">\n <div :class="[\'js-value-header\', isExpandable ? \'expandable\' : \'\']" @click="toggleExpanded"><span\n v-if="isExpandable || isEntry" :class="[\'arrow\', isExpandable ? \'expandable\' : \'\', isExpanded ? \'expanded\' : \'\']"></span><template\n v-if="isEntry"><span :class="[\'entry-key\', isDimName ? \'dim\' : \'\']">{{ name }}</span>: </template><span\n v-for="part in description.parts" :class="\'t-\' + part[0]">{{ part[1] }}</span></div>\n <div v-if="hasBeenExpanded" v-show="isExpanded" class="expansion">\n <div v-if="isPartialDescription" class="loading">Loading&hellip;</div>\n <template v-else>\n <template v-for="group in entryGroups">\n <js-value\n v-for="(entry, entryIndex) in description[group.key]"\n :name="entry[0]"\n :is-dim-name="group.isDim(entry)"\n :description="entry[1]"\n :path="path.concat([group.key, entryIndex])">\n </js-value>\n </template>\n </template>\n </div>\n </div>\n '}}function parseJSCodeGroups(e){return e.split(/\r\n|\r|\n/).reduce((e,t)=>{var i=e[e.length-1],s=/^\/\/[^]*\\\\$/.test(t),n=s?t.replace(/^\/+\s*|\s*\\+$/g,""):t;return!e.length||s&&!i.canAppendHeader?e.push({headerLines:s?[n]:[],lines:s?[]:[t],allLines:[t],canAppendHeader:s}):(s?i.headerLines.push(n):(i.canAppendHeader=!1,i.lines.push(t)),i.allLines.push(t)),e},[]).reduce((e,t)=>(t.canAppendHeader||(delete t.canAppendHeader,t.headerLines=t.headerLines.join("\n").trimEnd(),t.lines=t.lines.join("\n"),t.allLines=t.allLines.join("\n"),e.push(t)),e),[])}function parseGroupHeader(e,t){var i=!!t&&e.startsWith(t);return{header:i?e.slice(t.length).replace(/^\s*:?\s*/,""):e,isHidden:i}}function extractHiddenGroups(e,t){var i=[],s=[];for(const n of parseJSCodeGroups(e))parseGroupHeader(n.headerLines,t).isHidden?s.push({...n,runCount:i.length}):i.push(n);return{visibleCode:i.map(e=>e.allLines).join("\n"),hiddenGroups:s}}function findLastExpression(e,t){if(window.acorn)try{var{body:i}=acorn.parse(e,{ecmaVersion:"latest",sourceType:"module"===t?"module":"script",allowHashBang:!0}),s=i[i.length-1];if("ExpressionStatement"===s?.type&&!s.directive)return[s.expression.start,s.expression.end]}catch(e){}return null}function joinCodeBlocks(e){return e.map(e=>e.replace(/^(\s*[\r\n])+|\s+$/g,"")).filter(Boolean).map((e,t)=>{var i=e.split(/\r\n|\r|\n/)[0];return t&&!/^\/\/[^]*\\\\$/.test(i)?`// \\\\
1
+ /*! yourjs-box v1.4.0 | (c) 2023-present Christopher West | MIT License | https://github.com/westc/yourjs-box */
2
+ (()=>{const VIEWER_IFRAME_CSS="[v-cloak]{display:none}body,html{height:100%;margin:0}body{background-color:var(--console-bg);font-family:system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif}#vueApp{display:flex;flex-direction:column;inset:0;position:fixed}#main{display:grid;flex-grow:1;gap:0;min-height:0;position:relative}#main.is-moving-divider{-webkit-user-select:none;user-select:none}#main.col-orient.is-moving-divider{cursor:col-resize}#main.row-orient.is-moving-divider{cursor:row-resize}#main.is-moving-divider::after{background-color:var(--accent);content:'';position:absolute;z-index:99}#main.col-orient.is-moving-divider::after{bottom:0;left:calc(100% - var(--temp-editor-pct) - var(--divider-size)/ 2 - 1px);top:0;width:2px}#main.row-orient.is-moving-divider::after{height:2px;left:0;right:0;top:calc(100% - var(--temp-editor-pct) - var(--divider-size)/ 2 - 1px)}#main.col-orient{grid-template-columns:1fr var(--divider-size) calc(var(--editor-pct) - var(--divider-size)/ 2);grid-template-rows:1fr}#main.row-orient{grid-template-columns:1fr;grid-template-rows:1fr var(--divider-size) calc(var(--editor-pct) - var(--divider-size)/ 2)}.divider{background-color:var(--divider-bg);box-sizing:border-box;position:relative;transition:background-color .15s}#main.col-orient .divider{border-left:1px solid var(--toolbar-border);border-right:1px solid var(--toolbar-border);cursor:col-resize}#main.row-orient .divider{border-bottom:1px solid var(--toolbar-border);border-top:1px solid var(--toolbar-border);cursor:row-resize}.divider::after{background-color:var(--divider-grip);border-radius:2px;content:'';left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);transition:background-color .15s}#main.col-orient .divider::after{height:32px;width:2px}#main.row-orient .divider::after{height:2px;width:32px}#main.is-moving-divider .divider,.divider:hover{background-color:var(--divider-hover-bg)}#main.is-moving-divider .divider::after,.divider:hover::after{background-color:var(--accent)}#displays{position:relative}#displays>div{position:absolute;inset:0;overflow:auto}#bottomNav{align-items:center;background-color:var(--toolbar-bg);border-top:1px solid var(--toolbar-border);color:var(--toolbar-text);display:flex;flex:0 0 auto;font-size:12px;gap:8px;height:32px;padding:0 6px 0 8px;-webkit-user-select:none;user-select:none}#bottomNav>.brand{align-items:center;display:flex;flex-grow:1;gap:8px}.runner-badge{border:1px solid var(--toolbar-border);border-radius:999px;color:var(--muted-text);font-size:10px;letter-spacing:.04em;line-height:15px;padding:0 6px;text-transform:uppercase}#bottomNav>.buttons{align-items:center;display:flex;gap:2px}#bottomNav .separator{background-color:var(--toolbar-border);height:16px;margin:0 4px;width:1px}#bottomNav button{align-items:center;background:0 0;border:0;border-radius:4px;color:inherit;cursor:pointer;display:inline-flex;font:inherit;gap:5px;height:24px;justify-content:center;min-width:26px;padding:0 6px}#bottomNav button>span:not(.label){display:inline-flex;font-size:14px}#bottomNav button svg:not(.spin){transform:none!important}#bottomNav button:hover:not(:disabled){background-color:var(--button-hover)}#bottomNav button:disabled{cursor:not-allowed;opacity:.45}#bottomNav button.primary{background-color:var(--accent);color:var(--accent-text);font-weight:600;margin-left:2px;padding:0 10px 0 8px}#bottomNav button.primary>span:not(.label){font-size:11px}#bottomNav button.primary:hover:not(:disabled){background-color:var(--accent-hover)}#bottomNav button:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.spin{animation:spin .8s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.logo{align-items:center;color:var(--toolbar-text);display:inline-flex;font-weight:700;gap:5px;letter-spacing:-.01em;line-height:1}.logo-mark{align-items:flex-end;background-color:#f7df1e;border-radius:3px;box-sizing:border-box;color:#1a1a1a;display:inline-flex;font-size:9.5px;font-weight:800;height:18px;justify-content:flex-end;letter-spacing:-.02em;padding:0 2px 2px 0;width:18px}.logo-text{font-size:14px}.logo-large{gap:12px}.logo-large>.logo-mark{border-radius:10px;box-shadow:0 8px 24px rgb(0 0 0 / .18);font-size:24px;height:56px;padding:0 6px 5px 0;width:56px}.logo-large>.logo-text{font-size:36px}#splash{align-items:center;background-color:var(--console-bg);display:flex;inset:0;justify-content:center;position:fixed;transition:opacity .35s ease,visibility .35s;z-index:1000}#splash.hidden{opacity:0;visibility:hidden}.splash-content{align-items:center;animation:splash-in .4s ease-out both;display:flex;flex-direction:column;gap:24px}.splash-progress{background-color:var(--toolbar-border);border-radius:3px;height:3px;overflow:hidden;width:140px}.splash-progress>div{animation:splash-progress 1.1s ease-in-out infinite;background-color:var(--accent);border-radius:inherit;height:100%;width:40%}@keyframes splash-in{from{opacity:0;transform:translateY(6px)}}@keyframes splash-progress{from{transform:translateX(-100%)}to{transform:translateX(250%)}}.dialog-backdrop{align-items:center;animation:fade-in .12s ease-out;background-color:var(--backdrop);display:flex;inset:0;justify-content:center;position:fixed;z-index:900}.dialog{animation:dialog-in .15s ease-out;background-color:var(--dialog-bg);border:1px solid var(--toolbar-border);border-radius:8px;box-shadow:0 12px 40px rgb(0 0 0 / .3);color:var(--console-text);font-size:13px;padding:16px;width:min(360px,calc(100% - 32px))}.dialog-title{font-size:14px;font-weight:600;margin-bottom:6px}.dialog-message{color:var(--muted-text);line-height:1.45}.dialog-buttons{display:flex;gap:8px;justify-content:flex-end;margin-top:16px}.dialog-button{background:0 0;border:1px solid var(--toolbar-border);border-radius:4px;color:inherit;cursor:pointer;font:inherit;height:28px;padding:0 12px}.dialog-button:hover{background-color:var(--button-hover)}.dialog-button.primary{background-color:var(--accent);border-color:var(--accent);color:var(--accent-text);font-weight:600}.dialog-button.primary:hover{background-color:var(--accent-hover)}.dialog-button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}#bottomNav button.logo-button{margin-left:-4px;padding:0 4px}.about-dialog{display:flex;flex-direction:column;max-height:calc(100% - 24px);padding:0;width:min(620px,calc(100% - 24px))}.about-dialog.is-export{height:min(560px,calc(100% - 24px))}.about-header{align-items:center;border-bottom:1px solid var(--toolbar-border);display:flex;flex:0 0 auto;padding:0 8px 0 12px}.tabs{display:flex;flex-grow:1;gap:4px}.tab{background:0 0;border:0;border-bottom:2px solid transparent;color:var(--muted-text);cursor:pointer;font:inherit;font-weight:600;padding:10px 8px 8px}.tab:hover{color:var(--console-text)}.tab.active{border-bottom-color:var(--accent);color:var(--console-text)}.close-button{align-items:center;background:0 0;border:0;border-radius:4px;color:var(--muted-text);cursor:pointer;display:inline-flex;font-size:16px;height:28px;justify-content:center;width:28px}.close-button:hover{background-color:var(--button-hover);color:var(--console-text)}.close-button:focus-visible,.segmented>button:focus-visible,.tab:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.about-body{flex:1 1 auto;min-height:0;overflow:auto;padding:16px}.about-title{align-items:center;display:flex;gap:12px}.logo-medium>.logo-mark{border-radius:7px;font-size:16px;height:40px;padding:0 4px 4px 0;width:40px}.logo-medium>.logo-text{display:none}.about-name{font-size:17px;font-weight:700}.about-aka{color:var(--muted-text);font-size:13px;font-weight:400;margin-left:4px}.about-version{color:var(--muted-text);font-size:12px}.about-description{line-height:1.5;margin:12px 0}.about-links{display:flex;flex-wrap:wrap;gap:6px 16px}.about-links a{color:var(--accent);font-weight:600;text-decoration:none}.about-links a:hover{text-decoration:underline}.about-body h3{color:var(--muted-text);font-size:11px;letter-spacing:.05em;margin:18px 0 6px;text-transform:uppercase}.about-details{display:grid;gap:4px 16px;grid-template-columns:max-content 1fr;margin:0}.about-details dt{color:var(--muted-text)}.about-details dd{margin:0}.about-details kbd{background-color:var(--toolbar-bg);border:1px solid var(--toolbar-border);border-bottom-width:2px;border-radius:4px;font-family:inherit;font-size:11px;padding:0 4px}.about-footer{border-top:1px solid var(--toolbar-border);color:var(--muted-text);font-size:12px;margin-top:18px;padding-top:12px}.export-body{display:flex;flex-direction:column;gap:10px}.export-options{display:flex;flex-wrap:wrap;gap:8px;justify-content:space-between}.segmented{border:1px solid var(--toolbar-border);border-radius:6px;display:inline-flex;overflow:hidden}.segmented>button{background:0 0;border:0;color:var(--muted-text);cursor:pointer;font:inherit;font-size:12px;font-weight:600;padding:5px 10px}.segmented>button+button{border-left:1px solid var(--toolbar-border)}.segmented>button:hover{background-color:var(--button-hover)}.segmented>button.active{background-color:var(--accent);color:var(--accent-text)}.export-note{color:var(--muted-text);font-size:12px}.export-preview{border:1px solid var(--toolbar-border);border-radius:6px;flex:1 1 auto;min-height:120px;overflow:hidden}.export-actions{display:flex;gap:8px;justify-content:flex-end}.more-menu{background-color:var(--dialog-bg);border:1px solid var(--toolbar-border);border-radius:8px;bottom:38px;box-shadow:0 8px 28px rgb(0 0 0 / .25);color:var(--console-text);font-size:13px;max-height:calc(100% - 48px);min-width:236px;overflow:auto;padding:4px;position:absolute;right:6px;z-index:800}.menu-item{align-items:center;background:0 0;border:0;border-radius:5px;color:inherit;cursor:pointer;display:flex;font:inherit;gap:8px;padding:6px 8px;text-align:left;width:100%}.menu-item:focus-visible,.menu-item:hover:not(:disabled){background-color:var(--button-hover);outline:0}.menu-item:disabled{cursor:not-allowed;opacity:.4}.menu-icon{color:var(--muted-text);display:inline-flex;font-size:14px;justify-content:center;width:16px}.menu-icon svg{transform:none!important}.menu-row{align-items:center;display:flex;gap:2px;padding:2px 2px 2px 8px}.menu-row-label{flex-grow:1}.menu-step{font-weight:600;justify-content:center;width:auto}.menu-percent{color:var(--muted-text);font-variant-numeric:tabular-nums;font-weight:400;min-width:52px}.menu-separator{background-color:var(--toolbar-border);height:1px;margin:4px 0}.popped-out{align-items:center;background-color:var(--console-bg);color:var(--console-text);display:flex;inset:0;justify-content:center;position:fixed;z-index:950}.popped-out-content{align-items:center;display:flex;flex-direction:column;gap:8px;padding:16px;text-align:center}.popped-out-title{font-size:15px;font-weight:600;margin-top:8px}.popped-out-text{color:var(--muted-text);font-size:13px}@keyframes fade-in{from{opacity:0}}@keyframes dialog-in{from{opacity:0;transform:scale(.96)}}.rotated-90deg{transform:rotate(90deg)}.align-top{vertical-align:top!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.no-select{-webkit-user-select:none;user-select:none}:root{color-scheme:light;--console-font:ui-monospace,Menlo,Monaco,Consolas,'Liberation Mono','Courier New',monospace;--console-bg:#fff;--console-text:#1f1f1f;--row-border:#f0f0f0;--arrow:#727272;--chevron:#9aa0a6;--entry-key:#881391;--preview-key:#5f6368;--string:#c41a16;--number:#1a1aa6;--null:#80868b;--header-bg:#f1f3f4;--header-text:#3c4043;--warn-bg:#fffbe5;--warn-border:#fff5c2;--warn-text:#5c3c00;--warn-icon:#e8a600;--error-bg:#fff0f0;--error-border:#ffd6d6;--error-text:#dc362e;--error-icon:#dc362e;--table-header-bg:#f3f3f3;--table-border:#d0d0d0;--toolbar-bg:#f3f3f3;--toolbar-border:#d6d6d6;--toolbar-text:#333;--muted-text:#5f6368;--button-hover:rgb(0 0 0 / 0.08);--accent:#1a73e8;--accent-hover:#1765cc;--accent-text:#fff;--divider-bg:#f3f3f3;--divider-hover-bg:#e8eaed;--divider-grip:#b0b0b0;--dialog-bg:#fff;--backdrop:rgb(0 0 0 / 0.25)}:root[data-theme=dark]{color-scheme:dark;--console-bg:#242424;--console-text:#e3e3e3;--row-border:#3a3a3a;--arrow:#9aa0a6;--chevron:#80868b;--entry-key:#5db0d7;--preview-key:#9aa0a6;--string:#f28b54;--number:#9980ff;--null:#8e8e8e;--header-bg:#2d2e30;--header-text:#c4c7c5;--warn-bg:#332b00;--warn-border:#665500;--warn-text:#ffd17a;--warn-icon:#ffd17a;--error-bg:#290000;--error-border:#5c0000;--error-text:#ff8080;--error-icon:#ff6b6b;--table-header-bg:#2e2e2e;--table-border:#4a4a4a;--toolbar-bg:#2b2b2b;--toolbar-border:#474747;--toolbar-text:#e3e3e3;--muted-text:#9aa0a6;--button-hover:rgb(255 255 255 / 0.1);--accent:#8ab4f8;--accent-hover:#aecbfa;--accent-text:#202124;--divider-bg:#2b2b2b;--divider-hover-bg:#333;--divider-grip:#6b6b6b;--dialog-bg:#2d2e30;--backdrop:rgb(0 0 0 / 0.5)}#displays{background-color:var(--console-bg);color:var(--console-text)}#displays>div{font-family:var(--console-font);font-size:calc(12px * var(--text-scale, 1));line-height:calc(16px * var(--text-scale, 1))}.console-row{border-bottom:1px solid var(--row-border);padding:2px 8px 2px 24px;position:relative;white-space:pre-wrap;word-break:break-word}.console-row>.row-icon{left:6px;line-height:0;position:absolute;top:4px}.log-error,.log-warn{margin-top:-1px}.log-warn{background-color:var(--warn-bg);border-bottom-color:var(--warn-border);border-top:1px solid var(--warn-border);color:var(--warn-text)}.log-warn>.row-icon{color:var(--warn-icon)}.log-error{background-color:var(--error-bg);border-bottom-color:var(--error-border);border-top:1px solid var(--error-border);color:var(--error-text)}.log-error>.row-icon{color:var(--error-icon)}.console-row{padding-left:calc(24px + var(--depth,0) * 16px)}.console-row>.row-icon{left:calc(6px + var(--depth,0) * 16px)}.group-header{cursor:pointer;font-weight:700}.group-header>.row-icon.arrow{top:5px}.log-assert{background-color:var(--error-bg);border-bottom-color:var(--error-border);border-top:1px solid var(--error-border);color:var(--error-text);margin-top:-1px}.log-assert>.row-icon{color:var(--error-icon)}.log-result>.row-icon{color:var(--chevron)}.trace-stack{color:var(--null);padding-left:1ch}.splash-message{color:var(--muted-text);font-size:13px;max-width:280px;text-align:center}.splash-slow{animation:show-after-delay 0s 10s both}@keyframes show-after-delay{from{visibility:hidden}to{visibility:visible}}#splash.failed .splash-progress,#splash.failed .splash-slow,.splash-error{display:none}#splash.failed .splash-error{display:block}.code-header{background-color:var(--header-bg);border-bottom:1px solid var(--row-border);color:var(--header-text);font-weight:700;padding:2px 8px;white-space:pre-wrap}.code-header.toggleable{cursor:pointer}.code-row .copy-to-editor-button{align-items:center;background-color:var(--console-bg);border:1px solid var(--toolbar-border);border-radius:4px;color:var(--toolbar-text);cursor:pointer;display:inline-flex;height:22px;justify-content:center;opacity:0;padding:0;position:absolute;right:6px;top:2px;transition:opacity .15s;width:22px}.code-row .copy-to-editor-button:focus-visible,.code-row:hover .copy-to-editor-button{opacity:1}.code-row .copy-to-editor-button:hover{background-color:var(--toolbar-bg)}@media (hover:none){.code-row .copy-to-editor-button{opacity:.8}}.notice{color:var(--null);font-style:italic}.code-row>.row-icon{color:var(--chevron)}.code-row code,.code-row pre{background:0 0!important;font-family:var(--console-font)!important;font-size:calc(12px * var(--text-scale, 1))!important;line-height:calc(16px * var(--text-scale, 1))!important;padding:0!important;text-shadow:none!important}.js-value{max-width:100%;vertical-align:top}.row-content>.js-value+.js-value{margin-left:1ch}.js-value-header.expandable{cursor:default}.js-value .expansion{padding-left:12px}.js-value .loading{color:var(--null);padding-left:12px}.arrow{display:inline-block;height:10px;position:relative;width:12px}.arrow.expandable::before{border-color:transparent transparent transparent var(--arrow);border-style:solid;border-width:4px 0 4px 6px;content:'';left:2px;position:absolute;top:1px;transform-origin:3px 4px;transition:transform .1s}.arrow.expandable.expanded::before{transform:rotate(90deg)}.entry-key{color:var(--entry-key)}.entry-key.dim{opacity:.6}.t-key{color:var(--preview-key)}.t-regexp,.t-string,.t-symbol{color:var(--string)}.t-number{color:var(--number)}.t-null{color:var(--null)}.t-function{font-style:italic}.t-node{color:var(--entry-key)}.console-table{border:1px solid var(--table-border);border-collapse:collapse;margin:2px 0 4px;white-space:nowrap}.console-table td,.console-table th{border-left:1px solid var(--table-border);max-width:300px;overflow:hidden;padding:1px 4px;text-align:left;text-overflow:ellipsis}.console-table th{background-color:var(--table-header-bg);border-bottom:1px solid var(--table-border);font-weight:400}",PACKAGE_INFO={name:"yourjs-box",version:"1.4.0",homepage:"https://westc.github.io/yourjs-box/",repoUrl:"https://github.com/westc/yourjs-box",bugsUrl:"https://github.com/westc/yourjs-box/issues"},VIEWER_IFRAME_HTML='<div id="splash" aria-label="Loading"><div class="splash-content"><span class="logo logo-large"><span class="logo-mark">JS</span><span class="logo-text">Box</span></span><div class="splash-progress"><div></div></div><div class="splash-message splash-slow">Still loading&hellip;</div><div class="splash-message splash-error">JS Box couldn&rsquo;t load. Please check your connection and reload the page.</div></div></div><div id="vueApp" v-cloak><div id="main" ref="main" :class="mainElemClassNames" :style="mainElemStyles" @mousedown="onMainElemMouseDown"><div id="displays"><div ref="displaysScroller" @scroll="onDisplaysScroll"><template v-for="display in displays"><div v-if="display.type === \'prism\'"><div v-if="display.isHidden" class="code-header toggleable no-select" @click="display.isCodeShown = !display.isCodeShown" :title="display.isCodeShown ? \'Hide Code\' : \'Show Code\'"><span :class="[\'arrow\', \'expandable\', display.isCodeShown ? \'expanded\' : \'\']"></span>{{ display.header || \'Hidden code\' }}</div><div v-else-if="display.header" class="code-header">{{ display.header }}</div><div v-if="display.isCodeShown" class="console-row code-row"><span class="row-icon"><icon name="chevron"></icon></span><prism language="javascript" :code="display.value" :is-dark="theme === \'dark\'" match-braces></prism><button class="copy-to-editor-button" title="Copy to editor" @click="copyToEditor(display.value)"><icon name="copyToEditor"></icon></button></div></div><div v-if="display.type === \'log\' &amp;&amp; !isInCollapsedGroup(display)" :class="[\'console-row\', \'log-\' + display.key, display.groupId ? \'group-header\' : \'\']" :style="{\'--depth\': display.groupIds.length}" :title="display.name" @click="onLogRowClick(display, $event)"><span v-if="display.key === \'error\' || display.key === \'assert\'" class="row-icon"><icon name="consoleError"></icon></span><span v-else-if="display.key === \'warn\'" class="row-icon"><icon name="consoleWarning"></icon></span><span v-else-if="display.key === \'result\'" class="row-icon"><icon name="result"></icon></span><span v-else-if="display.groupId" :class="[\'row-icon\', \'arrow\', \'expandable\', display.isCollapsed ? \'\' : \'expanded\']"></span><div class="row-content"><table v-if="display.table" class="console-table"><thead><tr><th v-for="header in display.table.headers">{{ header }}</th></tr></thead><tbody><tr v-for="row in display.table.rows"><td>{{ row.index }}</td><td v-for="cell in row.cells"><template v-if="cell"><span v-for="part in cell.parts" :class="\'t-\' + part[0]">{{ part[1] }}</span></template></td></tr></tbody></table><js-value v-for="(description, index) in display.descriptions" :description="description" :path="[display.logId, index]"></js-value><div v-if="display.stack" class="trace-stack">{{ display.stack }}</div></div></div><div v-if="display.type === \'notice\'" class="console-row notice">{{ display.message }}</div><div v-if="display.type === \'error\'" class="console-row log-error"><span class="row-icon"><icon name="consoleError"></icon></span><div class="row-content">{{ display.message }}</div></div></template></div></div><div class="divider" ref="mainDivider"></div><div id="editor"><ace-editor v-model="jsCode" language="javascript" :theme="theme" :font-size="Math.round(12 * textScale)" @key-combo="onEditorKeyCombo" height="100%"></ace-editor></div></div><div id="bottomNav"><div class="brand"><button class="logo-button" title="About JS Box" @click="openAbout(\'about\')"><span class="logo"><span class="logo-mark">JS</span><span class="logo-text">Box</span></span></button> <span class="runner-badge" :title="runnerMode === \'window\' ? \'Code runs directly in this page\' : \'Code runs in a Web Worker (no DOM access)\'">{{ runnerMode === \'window\' ? \'Window\' : \'Worker\' }}</span></div><div class="buttons"><template v-for="bottomButton in bottomButtons"><span v-if="bottomButton.isSeparator" class="separator"></span> <button v-else :class="bottomButton.className" @click="bottomButton.callback.call(this, $event)" :title="bottomButton.title" :disabled="bottomButton.disableIf &amp;&amp; bottomButton.disableIf.call(this)"><icon :name="bottomButton.iconName"></icon><span v-if="bottomButton.label" class="label">{{ bottomButton.label }}</span></button></template></div></div><div v-if="isMenuOpen" class="more-menu" role="menu" aria-label="More" ref="moreMenu" @keydown="onMenuKeyDown"><div class="menu-row" role="group" aria-label="Text size"><span class="menu-row-label">Text size</span> <button class="menu-item menu-step" role="menuitem" title="Smaller text" aria-label="Smaller text" :disabled="!canShrinkText" @click="changeTextScale(-1)">A&minus;</button> <button class="menu-item menu-step menu-percent" role="menuitem" title="Reset the text size" aria-label="Reset the text size" @click="setTextScale(1)">{{ Math.round(textScale * 100) }}%</button> <button class="menu-item menu-step" role="menuitem" title="Bigger text" aria-label="Bigger text" :disabled="!canGrowText" @click="changeTextScale(1)">A+</button></div><div class="menu-separator"></div><button v-if="isPopOut" class="menu-item" role="menuitem" @click="closeMenu(); bringBack()"><span class="menu-icon"><icon name="popIn"></icon></span>Bring back into the page</button> <button v-else class="menu-item" role="menuitem" @click="popOut()"><span class="menu-icon"><icon name="popOut"></icon></span>Pop out into a window</button> <button class="menu-item" role="menuitem" @click="closeMenu(); openAbout(\'html\')"><span class="menu-icon"><icon name="code"></icon></span>Copy as HTML&hellip;</button> <button class="menu-item" role="menuitem" @click="closeMenu(); resetConsole()"><span class="menu-icon"><icon name="refresh"></icon></span>Reset&hellip;</button><div class="menu-separator"></div><button class="menu-item" role="menuitem" @click="closeMenu(); openAbout(\'about\')"><span class="menu-icon"><icon name="info"></icon></span>About JS Box</button></div><div v-if="isPoppedOut" class="popped-out"><div class="popped-out-content"><span class="logo logo-medium"><span class="logo-mark">JS</span><span class="logo-text">Box</span></span><div class="popped-out-title">This console is open in a separate window</div><div class="popped-out-text">Its code still runs in this page.</div><div class="dialog-buttons"><button class="dialog-button" @click="focusPopOut">Show the window</button> <button class="dialog-button primary" @click="requestPopIn">Bring it back</button></div></div></div><div v-if="isAboutOpen" class="dialog-backdrop" @mousedown.self="closeAbout" @keydown.esc="closeAbout"><div :class="[\'dialog\', \'about-dialog\', aboutTab === \'html\' ? \'is-export\' : \'\']" role="dialog" aria-modal="true" aria-label="About JS Box"><div class="about-header"><div class="tabs" role="tablist"><button role="tab" :aria-selected="aboutTab === \'about\'" :class="[\'tab\', aboutTab === \'about\' ? \'active\' : \'\']" @click="aboutTab = \'about\'">About</button> <button role="tab" :aria-selected="aboutTab === \'html\'" :class="[\'tab\', aboutTab === \'html\' ? \'active\' : \'\']" @click="aboutTab = \'html\'">Copy as HTML</button></div><button class="close-button" ref="aboutCloseButton" title="Close" @click="closeAbout"><icon name="close"></icon></button></div><div v-if="aboutTab === \'about\'" class="about-body"><div class="about-title"><span class="logo logo-medium"><span class="logo-mark">JS</span><span class="logo-text">Box</span></span><div><div class="about-name">YourJS Box <span class="about-aka">aka JS Box</span></div><div class="about-version">Version {{ packageInfo.version }}</div></div></div><p class="about-description">An interactive JavaScript console that can be embedded in any web page with a single script tag.</p><div class="about-links"><a :href="packageInfo.homepage" target="_blank" rel="noopener">Website</a> <a :href="packageInfo.repoUrl" target="_blank" rel="noopener">GitHub</a> <a :href="packageInfo.repoUrl + \'#readme\'" target="_blank" rel="noopener">Documentation</a> <a :href="packageInfo.bugsUrl" target="_blank" rel="noopener">Report an issue</a></div><h3>This console</h3><dl class="about-details"><dt>Code runs in</dt><dd>{{ runnerDescription }}</dd><dt>Theme</dt><dd>{{ themeDescription }}</dd><dt>Code blocks run as</dt><dd>{{ blockTypeDescription }}</dd><dt>Results</dt><dd>{{ showResults ? \'The value of the last expression is shown\' : \'Not shown\' }}</dd><dt>Layout</dt><dd>{{ layoutDescription }}</dd></dl><h3>Keyboard shortcuts</h3><dl class="about-details"><dt><kbd>{{ modKey }}</kbd> + <kbd>Enter</kbd></dt><dd>Run the next block of code</dd><dt><kbd>Esc</kbd></dt><dd>Close this window, the menu or full screen</dd></dl><div class="about-footer">MIT License &copy; 2023-present Christopher West &middot; Built with Vue {{ libraryVersions.vue }}, Ace {{ libraryVersions[\'ace-builds\'] }}, Prism {{ libraryVersions.prismjs }} and Acorn {{ libraryVersions.acorn }}</div></div><div v-else class="about-body export-body"><div class="export-options"><div class="segmented" role="radiogroup" aria-label="Code"><button v-for="option in exportCodeOptions" role="radio" :aria-checked="exportCode === option.value" :class="exportCode === option.value ? \'active\' : \'\'" @click="exportCode = option.value">{{ option.label }}</button></div><div class="segmented" role="radiogroup" aria-label="Format"><button v-for="option in exportFormatOptions" role="radio" :aria-checked="exportFormat === option.value" :class="exportFormat === option.value ? \'active\' : \'\'" @click="exportFormat = option.value">{{ option.label }}</button></div></div><div class="export-note">{{ exportNote }}</div><div class="export-preview"><ace-editor :model-value="exportHtml" language="html" :theme="theme" height="100%" :read-only="true"></ace-editor></div><div class="export-actions"><button class="dialog-button" @click="downloadExport">Download page</button> <button class="dialog-button primary" @click="copyExport">{{ copyLabel }}</button></div></div></div></div><div v-if="dialog" class="dialog-backdrop" @mousedown.self="closeDialog(false)" @keydown.esc="closeDialog(false)"><div class="dialog" role="alertdialog" aria-modal="true" :aria-label="dialog.title"><div class="dialog-title">{{ dialog.title }}</div><div class="dialog-message">{{ dialog.message }}</div><div class="dialog-buttons"><button class="dialog-button" @click="closeDialog(false)">Cancel</button> <button class="dialog-button primary" ref="dialogConfirmButton" @click="closeDialog(true)">{{ dialog.confirmText }}</button></div></div></div></div>',OWN_URL=document.currentScript?.src??"",ORIGINAL_CONSOLE=window[Symbol.for("yourjs-box.originalConsole")]??={...console},LIBRARY_VERSIONS={"ace-builds":"1.44.0",acorn:"8.18.0","prism-themes":"1.9.0",prismjs:"1.30.0",vue:"3.5.43"},DEFAULT_LIBRARIES_URL="https://unpkg.com/{name}@{version}/";function getLibraryFileUrl(librariesUrl,name,path){var librariesUrl=librariesUrl.replace(/\{(name|version)\}/g,(_,key)=>"name"===key?name:LIBRARY_VERSIONS[name]).replace(/\/?$/,"/");return new URL(librariesUrl+path,document.baseURI).href}const RELAYABLE_FUNCS={viewer:["appendLog","appendError","clearDisplays","onCodeRan","updateDescriptionFor"],runner:["clearLogs","reset","runCode","sendDescriptionFor"],host:["focusPopOut","popIn","popOut","requestPopIn","setMaximized"]};function relayMessage(data,targets){var{target,func,args}=Object(data),targets=targets[target];targets&&RELAYABLE_FUNCS[target].includes(func)&&Array.isArray(args)?targets.apply(func,args):ORIGINAL_CONSOLE.error("Unhandled message sent to main handler:",data)}function createRunner(e,t){const{mode:n}=t,r=t.ownUrl||("worker"===n?self.location.href:""),o={};let s=0,i=0,c=!0,a;const l={},u={},f={};let p=[],d=0;const g="yourjs-box.result."+Math.random().toString(36).slice(2),h=(globalThis[Symbol.for(g)]=b,[]);for(const e of["assert","clear","count","countReset","debug","dir","dirxml","error","group","groupCollapsed","groupEnd","info","log","table","time","timeEnd","timeLog","trace","warn"]){const t=console[e];if("function"==typeof t){const n=function(...n){return m(e,n),t.apply(this,arguments)};console[e]=n,h.push({key:e,original:t,wrapper:n})}}function m(t,n){var r=n.length&&void 0!==n[0]?""+n[0]:"default";if("clear"===t)z(),p=[],e({target:"viewer",func:"clearDisplays",args:[!0]});else if("assert"===t){if(!n[0]){const e=n.slice(1);y("assert",e.length?"string"==typeof e[0]?["Assertion failed: "+e[0],...e.slice(1)]:["Assertion failed:",...e]:["Assertion failed: console.assert"])}}else if("count"===t)u[r]=(u[r]||0)+1,y("count",[r+": "+u[r]]);else if("countReset"===t)Object.hasOwn(u,r)?u[r]=0:y("warn",[`Count for '${r}' does not exist`]);else if("time"===t)Object.hasOwn(f,r)?y("warn",[`Timer '${r}' already exists`]):f[r]=performance.now();else if("timeLog"===t||"timeEnd"===t){if(!Object.hasOwn(f,r))return y("warn",[`Timer '${r}' does not exist`]);const e=performance.now()-f[r];"timeEnd"===t&&delete f[r],y(t,[r+`: ${+e.toFixed(3)} ms`,..."timeLog"===t?n.slice(1):[]])}else if("trace"===t){const e=O((new Error).stack??"").split("\n").slice(1).join("\n");y("trace",n.length?n:["console.trace"],{stack:e})}else if("group"===t||"groupCollapsed"===t){const e=""+ ++d;y(t,n.length?n:["console.group"],{groupId:e,isCollapsed:"groupCollapsed"===t}),p.push(e)}else if("groupEnd"===t)p.pop();else{const e="table"===t?E(n[0],n[1]):null;y(t,e?n.slice(0,1):n,{table:e})}}function y(t,n,r,i=0){var c=""+ ++s;o[c]=n.map(e=>({...A(e,i),value:e})),e({target:"viewer",func:"appendLog",args:[{logId:c,key:t,descriptions:o[c].map(w(["value"])),groupIds:p.slice(),...r}]})}function b(e){void 0!==e&&y("result",[e],{},"string"==typeof e?1:0)}function v(e){j(void 0!==e.error?e.error:e.message)}function $(e){j(e.reason,!0)}function x(){removeEventListener("error",v),removeEventListener("unhandledrejection",$),delete globalThis[Symbol.for(g)];for(var{key:e,original:t,wrapper:n}of h)console[e]===n&&(console[e]=t);z()}function j(t,n){var r="classic"===a&&"SyntaxError"===t?.name&&/\bawait\b/.test(t.message)?'\n(To use top-level await, add data-block-type="module" to the script tag.)':"";e({target:"viewer",func:"appendError",args:[{message:(n?"Uncaught (in promise) ":"Uncaught ")+O(t?.stack??""+(t?.message??t))+r}]})}function O(e){return(""+e).split("\n").filter(e=>!(r&&/^\s*at\b/.test(e)&&e.includes(r))).join("\n").replace(/(snippet-\d+\.js):(\d+):(\d+)/g,(e,t,n,r)=>{var o=l[t];return o&&+n===o.line&&+r>o.column?t+`:${n}:`+Math.max(o.column,r-o.shift):e})}function w(e,t){if(!t)return t=>w(e,t);var n={...t};for(const t of e)delete n[t];return n}function E(e,t){if(null===e||"object"!=typeof e)return null;const n="Value",r=[];let o=!1;const s=Object.keys(e).map(t=>{var n=e[t],s={index:t,values:{},hasValue:!1};if(null===n||"object"!=typeof n&&"function"!=typeof n)o=!0,s.hasValue=!0,s.value=n;else for(const e of Object.keys(n))r.includes(e)||r.push(e),s.values[e]=n[e];return s}),i=Array.isArray(t)?t.map(e=>""+e):r,c=o&&!Array.isArray(t);return{headers:["(index)",...i,...c?[n]:[]],rows:s.map(({index:e,values:t,hasValue:n,value:r})=>({index:e,cells:[...i.map(e=>Object.hasOwn(t,e)?A(t[e],2):null),...c?[n?A(r,2):null]:[]]}))}}function k(e){var t;return null==e?""+e:"object"==(t=typeof e)||"undefined"==t?Object.prototype.toString.call(e).slice(8,-1):t}function L(e,t){try{const t=Object.getPrototypeOf(e)?.constructor?.name;if(t&&"string"==typeof t)return t}catch(e){}return t}addEventListener("error",v),addEventListener("unhandledrejection",$);const N=5,S=100;function A(e,t=0,n=!1){var r=k(e),o="function"!==r&&r===r.toLowerCase(),s=void 0;return{typeName:r,isPrimitive:o,parts:n?[["text","Object"!==r?r:L(e,r)]]:R(e,t,r)}}function R(e,t,n=k(e)){if("string"===n)return t?[["string",C(e=1<t&&100<e.length?e.slice(0,99)+"\u2026":e)]]:[["text",e]];if("number"===n)return[["number",Object.is(e,-0)?"-0":""+e]];if("bigint"===n)return[["number",e+"n"]];if("boolean"===n)return[["number",""+e]];if("null"===n||"undefined"===n)return[["null",n]];if("symbol"===n)return[["symbol",e.toString()]];if("function"===n)return T(e,t);try{return D(e,t,n)}catch(e){return[["text",n]]}}function C(e){var t=JSON.stringify(e);return e.includes("'")?t:`'${t.slice(1,-1).replace(/\\"/g,'"')}'`}function T(e,t){let n="";try{n=Function.prototype.toString.call(e)}catch(e){}var r=/^class\b/.test(n);return t?1<t?[["function","\u0192"]]:[["function",r?"class "+e.name:`\u0192 ${e.name}()`]]:[["text",r?n:n.replace(/^(async\s+)?function\b\s*/,"$1\u0192 ")]]}function D(e,t,n){var r=L(e,n),o=/^Array(?:[^a-z]|$)|[^A-Z]Array$/.test(n);if("Date"===n)return[["text",isNaN(e)?"Invalid Date":Date.prototype.toString.call(e)]];if("RegExp"===n)return[["regexp",""+e]];if("Promise"===n)return[["text",r+" {\u2026}"]];if("undefined"!=typeof Node&&e instanceof Node)return e.nodeType===Node.ELEMENT_NODE?[["node",e.localName+(e.id?"#"+e.id:"")+[...e.classList].map(e=>"."+e).join("")]]:e.nodeType===Node.TEXT_NODE?[["string",C(e.data)]]:[["node",e.nodeName]];if(e instanceof Error)return[["text",t?e.name+": "+e.message:O(e.stack??""+e)]];if(1<t)return o?[["text",`${r}(${e.length})`]]:"Map"===n||"Set"===n?[["text",`${r}(${e.size})`]]:[["text","Object"===r?"{\u2026}":r]];const s=[],i=(e,t,n)=>{e.forEach((e,t)=>{t&&s.push(["text",", "]),n(e)}),t>e.length&&s.push(["text",(e.length?", ":"")+"\u2026"])};if(o){const t=e.length;s.push(["text","Array"===n&&"Array"===r?`(${t}) [`:`${r}(${t}) [`]),i(Array.from({length:Math.min(t,S)},(e,t)=>t),t,t=>s.push(...t in e?R(e[t],2):[["null","empty"]])),s.push(["text","]"])}else if("Map"===n||"Set"===n){const t=[...e].slice(0,S);s.push(["text",`${r}(${e.size}) {`]),i(t,e.size,e=>{"Map"===n?s.push(...R(e[0],2),["text"," => "],...R(e[1],2)):s.push(...R(e,2))}),s.push(["text","}"])}else{const t=Object.keys(e);"Object"!==r&&s.push(["text",r+" "]),"Number"===n||"String"===n||"Boolean"===n?s.push(["text","{"],...R(e.valueOf(),2),["text","}"]):(s.push(["text","{"]),i(t.slice(0,N),t.length,t=>{var n=Object.getOwnPropertyDescriptor(e,t);s.push(["key",t],["text",": "],..."value"in n?R(n.value,2):[["text","(\u2026)"]])}),s.push(["text","}"]))}return s}function U(e,t=e){const n=k(e),r=[],o=[],s=[],i=[];if(null!==e&&("object"==typeof e||"function"==typeof e)){let c=!1;try{if("Map"===n){for(const[t,n]of[...e])r.push([R(t,2).map(e=>e[1]).join(""),A(n,1)]),o.push({value:n});c=!0}else if("Array"!==n&&"function"!==n&&"function"==typeof e[Symbol.iterator]){let t=0;for(const n of e)r.push([""+t,A(n,1)]),o.push({value:n}),++t;c=!0}}catch(e){r.length=o.length=0}if(!c)for(const n of Object.getOwnPropertyNames(e))try{const s=Object.getOwnPropertyDescriptor(e,n),i="value"in s?s.value:Reflect.get(e,n,t);r.push([n,A(i,1),s.enumerable]),o.push({value:i})}catch(e){}var a=Object.getPrototypeOf(e);null!==a&&(s.push(["[[Prototype]]",A(a,1,!0)]),i.push({value:a,receiver:t}))}return{entries:r,protoEntries:s,$entries:o,$protoEntries:i}}async function M(t,r){const{blockType:o,resultRange:s}=Object(r),c=`snippet-${++i}.js`;if(Array.isArray(s)){const[e,n]=s,r=`globalThis[Symbol.for(${JSON.stringify(g)})]((`,o=t.slice(0,e).split("\n");l[c]={line:o.length,column:o[o.length-1].length+1,shift:r.length},t=t.slice(0,e)+r+t.slice(e,n)+"))"+t.slice(n)}var r=t+`
3
+ //# sourceURL=`+c;a="module"===o?"module":"classic";try{if("module"===o)await import("data:text/javascript;charset=utf-8,"+encodeURIComponent(r));else if("worker"===n)P(r);else{const e=document.createElement("script");e.textContent=r,document.head.appendChild(e),e.remove()}}catch(e){j(e)}a=void 0,e({target:"viewer",func:"onCodeRan",args:[]})}function P(e){if(c)try{return importScripts("data:text/javascript;charset=utf-8,"+encodeURIComponent(e))}catch(e){if("NetworkError"!==e?.name)throw e;c=!1}var t=URL.createObjectURL(new Blob([e],{type:"text/javascript"}));try{importScripts(t)}finally{URL.revokeObjectURL(t)}}function I(t){let n=o,r=0;for(let e of t)r&&r%2==0&&(e="$"+e),n=n?.[e],r++;var s;n&&(s=U(n.value,"receiver"in n?n.receiver:n.value),Object.assign(n,s),e({target:"viewer",func:"updateDescriptionFor",args:[t,w(["$entries","$protoEntries"],s)]}))}function z(){for(const e of Object.keys(o))delete o[e];p=[]}return{clearLogs:z,destroy:x,runCode:M,sendDescriptionFor:I}}function createWorkerRunner(onMessage){const WORKER_SOURCE="(function(){var runner = ("+createRunner+')(function(m) { postMessage(m); }, {mode: "worker"});onmessage = function(e) {var d = e.data;if (d && Object.prototype.hasOwnProperty.call(runner, d.func) && Array.isArray(d.args)) {runner[d.func].apply(null, d.args);}};postMessage({target: "main", func: "ready"});})();';let canUseDataUrl=!0,blobUrl,worker,isReady,pendingMessages;function start(){isReady=!1,pendingMessages=[];var url=canUseDataUrl?"data:text/javascript;charset=utf-8,"+encodeURIComponent(WORKER_SOURCE):blobUrl??=URL.createObjectURL(new Blob([WORKER_SOURCE],{type:"text/javascript"}));try{worker=new Worker(url)}catch(e){if(canUseDataUrl)return canUseDataUrl=!1,start();throw e}const thisWorker=worker;worker.onmessage=e=>{if(thisWorker===worker)if("main"===e.data?.target&&"ready"===e.data.func){isReady=!0;for(const message of pendingMessages.splice(0))worker.postMessage(message)}else onMessage(e.data)},worker.onerror=e=>{var e;thisWorker===worker&&!isReady&&canUseDataUrl&&(e.preventDefault(),canUseDataUrl=!1,e=pendingMessages,worker.terminate(),start(),pendingMessages.push(...e))}}return start(),{destroy(){worker.terminate(),blobUrl&&URL.revokeObjectURL(blobUrl)},apply(func,args){"reset"===func?(worker.terminate(),start()):isReady?worker.postMessage({func:func,args:args}):pendingMessages.push({func:func,args:args})}}}function createWindowRunner(onMessage){const runner=createRunner(onMessage,{mode:"window",ownUrl:OWN_URL});return{destroy(){runner.destroy()},apply(func,args){"reset"===func?runner.clearLogs():runner[func](...args)}}}function createConsole({code,dataset,height,insert}){const runnerMode="window"===dataset.runner?"window":"worker",blockType="module"===dataset.blockType?"module":"classic",showResults="false"!==dataset.showResults,libraryUrl=getLibraryFileUrl.bind(null,dataset.librariesUrl||DEFAULT_LIBRARIES_URL);let inlineViewer,popOutViewer=null,popOutWindow=null,popOutWatcher,activeViewer;var sendToViewer=data=>relayMessage(data,{viewer:activeViewer});const runner=("window"==runnerMode?createWindowRunner:createWorkerRunner)(sendToViewer),theme=/^(light|dark)$/.test(dataset.theme)?dataset.theme:matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light",hostFuncs={setMaximized(isMaximized){var{style}=inlineViewer.iframe;isMaximized?(inlineViewer.normalCssText??=style.cssText,Object.assign(style,{position:"fixed",inset:"0",width:"100%",height:"100%",zIndex:"2147483647"})):null!=inlineViewer.normalCssText&&(style.cssText=inlineViewer.normalCssText,inlineViewer.normalCssText=null)},popOut(state){if(popOutWindow)popOutWindow.focus();else{var rect=inlineViewer.iframe.getBoundingClientRect(),width=Math.max(820,Math.round(rect.width)),rect=Math.max(560,Math.round(rect.height));const newWindow=open("","_blank",`popup,width=${width},height=`+rect);newWindow?(popOutWindow=newWindow,popOutViewer=createViewer(newWindow,state),newWindow.yourjsBoxPopIn=state=>newWindow===popOutWindow&&hostFuncs.popIn(state),activeViewer=popOutViewer,inlineViewer.call("setPoppedOut",!0),popOutWatcher=setInterval(()=>{newWindow.closed&&setTimeout(()=>newWindow===popOutWindow&&hostFuncs.popIn(null),300)},500)):inlineViewer.call("onPopOutFailed")}},popIn(state){var oldWindow=popOutWindow;oldWindow&&(clearInterval(popOutWatcher),popOutWindow=null,popOutViewer.dispose(),popOutViewer=null,(activeViewer=inlineViewer).call("setPoppedOut",!1,state),oldWindow.closed||oldWindow.close())},requestPopIn(){popOutViewer&&popOutViewer.call("popIn")},focusPopOut(){popOutWindow?.focus()}},closePopOut=()=>popOutWindow?.close();function createViewer(targetWindow,state){return createCallableFrame({jsCode(){let mountedApp;const IS_MISSING_LIBRARIES=!window.Vue||!window.ace||!window.Prism,Prism=(IS_MISSING_LIBRARIES&&document.querySelector("#splash").classList.add("failed"),window.Prism),MIN_LOADING_TIME=(delete window.Prism,Prism?.plugins.autoloader.loadLanguages("javascript"),1e3),POP_IN_FUNCTION_NAME="yourjsBoxPopIn",TEXT_SCALES=[.75,.9,1,1.15,1.3,1.5,1.75,2],TEXT_SCALE_STORAGE_KEY="yourjs-box.textScale";function loadTextScale(){try{var e=+localStorage.getItem("yourjs-box.textScale");return TEXT_SCALES.includes(e)?e:1}catch(e){return 1}}const NARROW_WIDTH=600;function getAutoDividerOrient(){return innerWidth<600?"horizontal":"vertical"}function init(e,t,i){if(!IS_MISSING_LIBRARIES){const s=t.hidePrefix??"",n=matchMedia("(prefers-color-scheme: dark)"),o=unindentMin(e),{visibleCode:r,hiddenGroups:a}=extractHiddenGroups(o,s),l=/Mac|iPhone|iPad/.test(navigator.platform),d=()=>a.map(e=>({...e}));mountedApp=Vue.createApp({data:()=>({displays:[],hidePrefix:s,hiddenGroups:d(),runnerMode:i.runnerMode,blockType:i.blockType,showResults:i.showResults,packageInfo:i.packageInfo,libraryVersions:i.libraryVersions,runHistory:[],isAboutOpen:!1,aboutTab:"about",exportCode:"current",exportFormat:"snippet",copyLabel:"Copy",runningCount:0,dialog:null,isDisplaysScrolledToBottom:!0,forcedTheme:/^(light|dark)$/.test(t.theme)?t.theme:null,prefersDark:n.matches,runCount:0,jsCode:r,isDividerOrientAuto:!/^(horizontal|vertical)$/.test(t.dividerOrient),dividerOrient:/^(horizontal|vertical)$/.test(t.dividerOrient)?t.dividerOrient:getAutoDividerOrient(),isMovingDivider:!1,dividerPct:"50%",dividerSize:"8px",tempDividerPct:null,isMenuOpen:!1,textScale:loadTextScale(),isFullscreen:!1,isMaximized:!1,isPopOut:i.isPopOut,isPoppedOut:!1,...i.popOutState??{}}),computed:{theme(){return this.forcedTheme??(this.prefersDark?"dark":"light")},modKey:()=>l?"\u2318":"Ctrl",runnerDescription(){return"window"===this.runnerMode?"This page (it can use the page's globals and DOM)":"A Web Worker (isolated from the page, no DOM)"},themeDescription(){return`${"dark"===this.theme?"Dark":"Light"} (${this.forcedTheme?"set by data-theme":"follows your system"})`},blockTypeDescription(){return"module"===this.blockType?"Modules (top-level await and imports work, declarations stay in each block)":"Classic scripts (top-level declarations are shared between blocks)"},collapsedGroupIds(){return new Set(this.displays.filter(e=>e.groupId&&e.isCollapsed).map(e=>e.groupId))},layoutDescription(){return("vertical"===this.dividerOrient?"Editor beside the console":"Editor below the console")+(this.isDividerOrientAuto?" (automatic)":"")},exportCodeOptions:()=>[{value:"current",label:"Current code",note:"The code that already ran followed by the code in the editor."},{value:"original",label:"Original code",note:"The code this console started with."},{value:"blank",label:"Blank",note:"An empty console with the same settings."}],exportFormatOptions:()=>[{value:"snippet",label:"Embed snippet"},{value:"page",label:"Full page"}],exportNote(){return this.exportCodeOptions.find(e=>e.value===this.exportCode).note},exportJsCode(){if("original"===this.exportCode)return o;if("blank"===this.exportCode)return"";const e=this.runHistory.slice(),t=this.hiddenGroups.slice();let i=this.runCount;var s=()=>{for(;t.length&&t[0].runCount<=i;)e.push(t.shift().allLines)};s();for(const t of parseJSCodeGroups(this.jsCode))t.allLines.trim()&&(e.push(t.allLines),i++,s());return e.push(...t.map(e=>e.allLines)),joinCodeBlocks(e)},exportDataset(){const{librariesUrl:e,...i}=t;return i},exportHtml(){return buildConsoleHtml({code:this.exportJsCode,dataset:this.exportDataset,packageInfo:this.packageInfo,isFullPage:"page"===this.exportFormat})},bottomButtons(){var e=this.isFullscreen||this.isMaximized;return[{iconName:"clear",title:"Clear console",callback(){this.clearConsole()}},{iconName:"horizontalView",title:"Show the editor below the console",callback(){this.setDividerOrient("horizontal")},showIf(){return"horizontal"!==this.dividerOrient}},{iconName:"verticalView",title:"Show the editor beside the console",callback(){this.setDividerOrient("vertical")},showIf(){return"vertical"!==this.dividerOrient}},{iconName:e?"exitFullscreen":"fullscreen",title:e?"Exit full screen":"Full screen",callback(){this.toggleFullscreen()}},{iconName:"more",title:"More",className:"more-button",callback(){this.toggleMenu()}},{iconName:this.runningCount?"spinner":"play",label:"Run",className:"primary",title:`Run the next block of code (${l?"\u2318":"Ctrl+"}Enter)`,callback(){this.runCode()},disableIf(){return!this.canRunCode}}].filter(e=>!e.showIf||e.showIf.call(this))},canShrinkText(){return this.textScale>TEXT_SCALES[0]},canGrowText(){return this.textScale<TEXT_SCALES[TEXT_SCALES.length-1]},canRunCode(){return this.jsCode.trim()},mainElemClassNames(){return["vertical"===this.dividerOrient?"col-orient":"row-orient",this.isMovingDivider?"is-moving-divider":""].join(" ")},mainElemStyles(){return{"--divider-size":this.dividerSize,"--editor-pct":this.dividerPct,"--temp-editor-pct":this.tempDividerPct}}},methods:{onEditorKeyCombo(e){(e.ctrlKey||e.metaKey)&&"Enter"===e.key&&this.canRunCode&&this.runCode()},runCode(){this.isDisplaysScrolledToBottom=!0;var[e,...t]=parseJSCodeGroups(this.jsCode);this.runGroup(e),this.jsCode=t.map(e=>e.allLines).join("\n"),this.runCount++},runHiddenGroups(){var{hiddenGroups:e}=this;e.length&&e[0].runCount<=this.runCount&&this.runGroup(e.shift())},runGroup(e){var{header:t,isHidden:i}=parseGroupHeader(e.headerLines,this.hidePrefix);this.displays.push({type:"prism",header:t,isHidden:i,isCodeShown:!i,value:e.lines}),this.runningCount++,this.runHistory.push(e.allLines),messageParent({target:"runner",func:"runCode",args:[e.lines,{blockType:this.blockType,resultRange:this.showResults&&!i?findLastExpression(e.lines,this.blockType):null}]})},clearConsole(){this.displays=[],messageParent({target:"runner",func:"clearLogs",args:[]})},async resetConsole(){await this.confirm({title:"Reset the console?",message:"The output will be cleared and the editor will go back to the original code."+("window"===this.runnerMode?" Anything the code already defined on the page will stay defined.":""),confirmText:"Reset"})&&(this.displays=[],this.jsCode=r,this.hiddenGroups=d(),this.runCount=0,this.runningCount=0,this.runHistory=[],messageParent({target:"runner",func:"reset",args:[]}),this.runHiddenGroups())},async copyToEditor(e){this.jsCode.trim()&&this.jsCode!==e&&!await this.confirm({title:"Replace the code in the editor?",message:"The code that is currently in the editor will be replaced with a copy of the code you selected.",confirmText:"Replace"})||(this.jsCode=e)},confirm(e){return this.dialog?.resolve(!1),new Promise(t=>{this.dialog={...e,resolve:t},this.$nextTick(()=>this.$refs.dialogConfirmButton?.focus())})},openAbout(e){this.aboutTab=e,this.isAboutOpen=!0,this.$nextTick(()=>this.$refs.aboutCloseButton?.focus())},closeAbout(){this.isAboutOpen=!1},async copyExport(){var e=this.exportHtml;try{await navigator.clipboard.writeText(e)}catch(t){var e=Object.assign(document.createElement("textarea"),{value:e});document.body.appendChild(e),e.select(),document.execCommand("copy"),e.remove()}this.copyLabel="Copied!",clearTimeout(this.copyLabelTimeout),this.copyLabelTimeout=setTimeout(()=>this.copyLabel="Copy",1600)},downloadExport(){const e=buildConsoleHtml({code:this.exportJsCode,dataset:this.exportDataset,packageInfo:this.packageInfo,isFullPage:!0}),t=URL.createObjectURL(new Blob([e],{type:"text/html"}));Object.assign(document.createElement("a"),{href:t,download:"js-box.html"}).click(),setTimeout(()=>URL.revokeObjectURL(t),1e3)},onLogRowClick(e,t){e.groupId&&!t.target.closest(".js-value-header.expandable")&&(e.isCollapsed=!e.isCollapsed)},isInCollapsedGroup(e){const{collapsedGroupIds:t}=this;return!!t.size&&!!e.groupIds?.some(e=>t.has(e))},getState(){return JSON.parse(JSON.stringify({displays:this.displays,jsCode:this.jsCode,runHistory:this.runHistory,hiddenGroups:this.hiddenGroups,runCount:this.runCount,runningCount:this.runningCount,dividerOrient:this.dividerOrient,isDividerOrientAuto:this.isDividerOrientAuto,dividerPct:this.dividerPct}))},restoreState(e){Object.assign(this,e),this.isDisplaysScrolledToBottom=!0},toggleMenu(){this.isMenuOpen?this.closeMenu():(this.isMenuOpen=!0,this.$nextTick(()=>this.$refs.moreMenu?.querySelector(".menu-item:not(:disabled)")?.focus()))},closeMenu(e){this.isMenuOpen=!1,e&&document.querySelector("#bottomNav .more-button")?.focus()},onMenuKeyDown(e){var t,i,s;"Escape"===e.key?(e.stopPropagation(),this.closeMenu(!0)):"ArrowDown"!==e.key&&"ArrowUp"!==e.key||(e.preventDefault(),i=(t=[...this.$refs.moreMenu.querySelectorAll(".menu-item:not(:disabled)")]).indexOf(document.activeElement),t[(i+("ArrowDown"===e.key?1:t.length-1))%t.length]?.focus())},changeTextScale(e){var e=TEXT_SCALES.indexOf(this.textScale)+e;0<=e&&e<TEXT_SCALES.length&&this.setTextScale(TEXT_SCALES[e])},setTextScale(e){this.textScale=e;try{localStorage.setItem("yourjs-box.textScale",""+e)}catch(e){}},async toggleFullscreen(){if(this.isMaximized)this.setMaximized(!1);else if(document.fullscreenElement)await document.exitFullscreen();else try{await document.documentElement.requestFullscreen()}catch(e){this.isPopOut||this.setMaximized(!0)}},setMaximized(e){this.isMaximized=e,messageParent({target:"host",func:"setMaximized",args:[e]})},popOut(){this.closeMenu(),this.isMaximized&&this.setMaximized(!1),messageParent({target:"host",func:"popOut",args:[this.getState()]})},bringBack(){this.hasSentState=!0;var e=window.yourjsBoxPopIn;"function"==typeof e?e(this.getState()):messageParent({target:"host",func:"popIn",args:[this.getState()]})},focusPopOut(){messageParent({target:"host",func:"focusPopOut",args:[]})},requestPopIn(){messageParent({target:"host",func:"requestPopIn",args:[]})},onWindowMouseDown(e){this.isMenuOpen&&!e.target.closest(".more-menu, .more-button")&&this.closeMenu()},onWindowKeyDown(e){"Escape"!==e.key||!this.isMaximized||this.isMenuOpen||this.dialog||this.isAboutOpen||this.setMaximized(!1)},closeDialog(e){var{dialog:t}=this;this.dialog=null,t?.resolve(e)},setDividerOrient(e){this.isDividerOrientAuto=!1,this.dividerOrient=e},onWindowResize(){this.isDividerOrientAuto&&(this.dividerOrient=getAutoDividerOrient())},onDisplaysScroll(){var{scrollTop:e,scrollHeight:t,clientHeight:i}=this.$refs.displaysScroller;this.isDisplaysScrolledToBottom=t-e-i<8},getEditorPct(e){var t=this.$refs.main.getBoundingClientRect(),{dividerOrient:i}=this,s=e.pageX-t.left,e=e.pageY-t.top,o=t.width,t=t.height;return 100-100*Math.min(Math.max(.2,"vertical"===i?s/o:e/t),.8)+"%"},onMainElemMouseDown(e){e.target===this.$refs.mainDivider&&(this.isMovingDivider=!0,this.tempDividerPct=this.getEditorPct(e))},onWindowMouseMove(e){this.isMovingDivider&&(this.tempDividerPct=this.getEditorPct(e))},onWindowMouseUp(e){this.isMovingDivider&&(this.isMovingDivider=!1,this.dividerPct=this.getEditorPct(e))},onWindowError(e){this.displays.push({type:"error",message:e.error?.stack??e.message??e.error?.message??""+e.error,line:e.lineno,column:e.colno})}},watch:{textScale:{handler(e){document.documentElement.style.setProperty("--text-scale",e)},immediate:!0},theme:{handler(e){document.documentElement.dataset.theme=e},immediate:!0},"displays.length"(){this.isDisplaysScrolledToBottom&&this.$nextTick(()=>{var e=this.$refs.displaysScroller;e.scrollTop=e.scrollHeight})}},mounted(){addEventListener("mousemove",this.onWindowMouseMove),addEventListener("mousedown",this.onWindowMouseDown),addEventListener("keydown",this.onWindowKeyDown),addEventListener("resize",this.onWindowResize),addEventListener("mouseup",this.onWindowMouseUp),addEventListener("error",this.onWindowError),n.addEventListener("change",e=>this.prefersDark=e.matches),document.addEventListener("fullscreenchange",()=>this.isFullscreen=!!document.fullscreenElement),this.isPopOut&&addEventListener("pagehide",()=>this.hasSentState||this.bringBack()),this.runningCount||this.runHiddenGroups(),setTimeout(()=>document.querySelector("#splash").classList.add("hidden"),Math.max(0,(this.isPopOut?0:1e3)-performance.now()))}}).component("ace-editor",getAceComponentProps()).component("prism",getPrismComponentProps()).component("icon",getIconComponentProps()).component("js-value",getJSValueComponentProps()).mount(document.querySelector("#vueApp"))}}function getAceComponentProps(){return{data:()=>({annotations:[]}),props:["fontSize","height","keybinding","language","modelValue","readOnly","theme","width"],computed:{infoNotes(){return this.annotations.filter(({type:e})=>"info"===e)},warningNotes(){return this.annotations.filter(({type:e})=>"warning"===e)},errorNotes(){return this.annotations.filter(({type:e})=>"error"===e)},style(){return{height:null!=this.height?"number"==typeof this.height?this.height+"px":this.height:"150px",width:null!=this.width?"number"==typeof this.width?this.width+"px":this.width:"100%"}},modeSig(){return"ace/mode/"+(this.language??"text")},themeSig(){return"ace/theme/"+(""+(this.theme??"light")).replace(/^light$|(^dark$)/i,(e,t)=>"cloud_editor"+(t?"_dark":""))}},watch:{themeSig(e){this.editor.setTheme(e)},fontSize(e){e&&this.editor.setFontSize(e)},modelValue(e){e!==this.editor.getValue()&&this.editor.setValue(e,-1)}},async mounted(){const e=ace.edit(this.$refs.editor,{value:this.modelValue,mode:this.modeSig,theme:this.themeSig});this.editor=e,this.fontSize&&e.setFontSize(this.fontSize),this.readOnly&&(e.setReadOnly(!0),e.setHighlightActiveLine(!1),e.session.setUseWorker(!1)),e.setKeyboardHandler("ace/keyboard/vscode"),e.commands.removeCommand("addLineAfter"),e.commands.removeCommand("addLineBefore"),e.on("change",()=>this.$emit("update:modelValue",e.getValue())),e.session.on("changeAnnotation",()=>{var t=JSON.stringify(this.errorNotes),i=JSON.stringify(this.infoNotes),s=JSON.stringify(this.warningNotes),{errorNotes:n,infoNotes:o,warningNotes:r}=(this.annotations=e.getSession().getAnnotations(),this);t!==JSON.stringify(n)&&this.$emit("changeErrorNotes",n),i!==JSON.stringify(o)&&this.$emit("changeInfoNotes",o),s!==JSON.stringify(r)&&this.$emit("changeWarningNotes",r)}),e.textInput.getElement().addEventListener("keydown",e=>{16!==e.keyCode&&17!==e.keyCode&&18!==e.keyCode&&91!==e.keyCode&&92!==e.keyCode&&93!==e.keyCode&&(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey&&1<(e.key??"").length)&&this.$emit("keyCombo",e)})},template:'<div ref="editor" :style="style"></div>'}}function getPrismComponentProps(){return{data:()=>({annotations:[]}),props:["code","isDark","language","lineNumbers","matchBraces"],computed:{html(){},preStyle(){return{filter:!1!==(this.isDark??!1)?"none":"invert(1) hue-rotate(180deg) brightness(1.1)",margin:0,paddingTop:"0.5em",paddingBottom:"0.5em"}}},watch:{code(){this.redraw()},language(){this.redraw()},lineNumbers(){this.redraw()},matchBraces(){this.redraw()}},methods:{async redraw(){const e=this.$refs.pre,t=this.$refs.code;t.textContent=this.code,t.className="language-javascript",e.className="";for(const t of["lineNumbers","matchBraces"]){var i;null!=this[t]&&(i=t.replace(/[A-Z]+/g,"-$&").toLowerCase(),e.className+=" "+i)}Prism.highlightElement(t)}},async mounted(){await this.redraw()},template:'<pre ref="pre" :style="preStyle"><code ref="code"></code></pre>'}}function getIconComponentProps(){return{props:["name"],computed:{svgCode(){var e={missing:'<svg viewBox="0 0 32 32"><circle cx="16" cy="22.5" r="1.5" fill="currentColor"/><path fill="currentColor" d="M17 19h-2v-4h2c1.103 0 2-.897 2-2s-.897-2-2-2h-2c-1.103 0-2 .897-2 2v.5h-2V13c0-2.206 1.794-4 4-4h2c2.206 0 4 1.794 4 4s-1.794 4-4 4z"/><path fill="currentColor" d="M29.391 14.527L17.473 2.609A2.078 2.078 0 0 0 16 2c-.533 0-1.067.203-1.473.609L2.609 14.527C2.203 14.933 2 15.466 2 16s.203 1.067.609 1.473L14.526 29.39c.407.407.941.61 1.474.61s1.067-.203 1.473-.609L29.39 17.474c.407-.407.61-.94.61-1.474s-.203-1.067-.609-1.473M16 28.036L3.965 16L16 3.964L28.036 16z"/></svg>',trash:'<svg viewBox="0 0 15 15"><path fill="currentColor" fill-rule="evenodd" d="M5.5 1a.5.5 0 0 0 0 1h4a.5.5 0 0 0 0-1zM3 3.5a.5.5 0 0 1 .5-.5h8a.5.5 0 0 1 0 1H11v8a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V4h-.5a.5.5 0 0 1-.5-.5M5 4h5v8H5z" clip-rule="evenodd"/></svg>',play:'<svg viewBox="0 0 16 16"><path fill="currentColor" d="M2 1v14l12-7z"/></svg>',refresh:'<svg viewBox="0 0 15 15"><path fill="currentColor" fill-rule="evenodd" d="M1.903 7.297c0 3.044 2.207 5.118 4.686 5.547a.521.521 0 1 1-.178 1.027C3.5 13.367.861 10.913.861 7.297c0-1.537.699-2.745 1.515-3.663c.585-.658 1.254-1.193 1.792-1.602H2.532a.5.5 0 0 1 0-1h3a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-1 0V2.686l-.001.002c-.572.43-1.27.957-1.875 1.638c-.715.804-1.253 1.776-1.253 2.97m11.108.406c0-3.012-2.16-5.073-4.607-5.533a.521.521 0 1 1 .192-1.024c2.874.54 5.457 2.98 5.457 6.557c0 1.537-.699 2.744-1.515 3.663c-.585.658-1.254 1.193-1.792 1.602h1.636a.5.5 0 1 1 0 1h-3a.5.5 0 0 1-.5-.5v-3a.5.5 0 1 1 1 0v1.845h.002c.571-.432 1.27-.958 1.874-1.64c.715-.803 1.253-1.775 1.253-2.97" clip-rule="evenodd"/></svg>',horizontalView:'<svg viewBox="0 0 15 15"><path fill="currentColor" fill-rule="evenodd" d="M1.5 2h12a.5.5 0 0 1 .5.5V7H1V2.5a.5.5 0 0 1 .5-.5M1 8v4.5a.5.5 0 0 0 .5.5h12a.5.5 0 0 0 .5-.5V8zM0 2.5A1.5 1.5 0 0 1 1.5 1h12A1.5 1.5 0 0 1 15 2.5v10a1.5 1.5 0 0 1-1.5 1.5h-12A1.5 1.5 0 0 1 0 12.5z" clip-rule="evenodd"/></svg>',verticalView:'<svg viewBox="0 0 15 15"><path fill="currentColor" fill-rule="evenodd" d="M8 2h5.5a.5.5 0 0 1 .5.5v10a.5.5 0 0 1-.5.5H8zM7 2H1.5a.5.5 0 0 0-.5.5v10a.5.5 0 0 0 .5.5H7zm-7 .5A1.5 1.5 0 0 1 1.5 1h12A1.5 1.5 0 0 1 15 2.5v10a1.5 1.5 0 0 1-1.5 1.5h-12A1.5 1.5 0 0 1 0 12.5z" clip-rule="evenodd"/></svg>',error:'<svg viewBox="0 0 24 24"><path fill="currentColor" d="M11 15h2v2h-2zm0-8h2v6h-2zm1-5C6.47 2 2 6.5 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 18a8 8 0 0 1-8-8a8 8 0 0 1 8-8a8 8 0 0 1 8 8a8 8 0 0 1-8 8"/></svg>',fullscreen:'<svg viewBox="0 0 16 16"><path d="M2.5 6V2.5H6M10 2.5h3.5V6M13.5 10v3.5H10M6 13.5H2.5V10" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',exitFullscreen:'<svg viewBox="0 0 16 16"><path d="M6 2.5V6H2.5M13.5 6H10V2.5M10 13.5V10h3.5M2.5 10H6v3.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',more:'<svg viewBox="0 0 16 16"><circle cx="3.5" cy="8" r="1.4" fill="currentColor"/><circle cx="8" cy="8" r="1.4" fill="currentColor"/><circle cx="12.5" cy="8" r="1.4" fill="currentColor"/></svg>',popOut:'<svg viewBox="0 0 16 16"><path d="M9.5 2.5h4v4M13.5 2.5L8 8M12 9.5v3a1 1 0 0 1-1 1H3.5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h3" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',popIn:'<svg viewBox="0 0 16 16"><path d="M12 8.5H8V4.5M8 8.5l5.5-5.5M12 10.5v2a1 1 0 0 1-1 1H3.5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h2" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',code:'<svg viewBox="0 0 16 16"><path d="M5.5 4.5L2 8l3.5 3.5M10.5 4.5L14 8l-3.5 3.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',info:'<svg viewBox="0 0 16 16"><circle cx="8" cy="8" r="6.25" fill="none" stroke="currentColor" stroke-width="1.5"/><path d="M8 7.25v4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/><circle cx="8" cy="5" r="1" fill="currentColor"/></svg>',result:'<svg viewBox="0 0 16 16"><path d="M9 4.5L5.5 8 9 11.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><circle cx="12" cy="8" r="1.1" fill="currentColor"/></svg>',close:'<svg viewBox="0 0 16 16"><path d="M4 4l8 8m0-8l-8 8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>',clear:'<svg viewBox="0 0 16 16"><circle cx="8" cy="8" r="6" fill="none" stroke="currentColor" stroke-width="1.5"/><path d="M3.75 12.25l8.5-8.5" stroke="currentColor" stroke-width="1.5"/></svg>',copyToEditor:'<svg viewBox="0 0 16 16"><path d="M6 3.5L2.5 7 6 10.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 7h6.5a4 4 0 0 1 4 4v1.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',spinner:'<svg viewBox="0 0 16 16" class="spin"><path d="M8 1.75a6.25 6.25 0 1 1-6.25 6.25" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"/></svg>',chevron:'<svg viewBox="0 0 16 16"><path d="M6 4l4 4-4 4" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',consoleError:'<svg viewBox="0 0 16 16"><circle cx="8" cy="8" r="7" fill="currentColor"/><path d="M5.5 5.5l5 5m0-5l-5 5" stroke="#fff" stroke-width="1.75" stroke-linecap="round"/></svg>',consoleWarning:'<svg viewBox="0 0 16 16"><path d="M8 1.75L14.75 14H1.25z" fill="currentColor" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/><path d="M8 6v3.5" stroke="#202124" stroke-width="1.75" stroke-linecap="round"/><circle cx="8" cy="11.75" r="1" fill="#202124"/></svg>'};return(e[this.name]??e.missing).replace("<svg",'$& xmlns="http://www.w3.org/2000/svg" style="height: 1em; width: 1em; display: inline-block; transform: translateY(0.1em);"')}},template:'<span v-html="svgCode"></span>'}}function getJSValueComponentProps(){return{props:["description","path","name","isDimName"],data:()=>({isExpanded:!1,hasBeenExpanded:!1}),watch:{isExpanded(e){e&&!this.hasBeenExpanded&&(this.hasBeenExpanded=e)}},computed:{isPartialDescription(){return void 0===this.description.entries},isExpandable(){return!this.description.isPrimitive},isEntry(){return null!=this.name},classNames(){return["js-value",this.isEntry||this.isExpandable&&this.isExpanded?"d-block":"d-inline-block",this.isExpanded?"expanded":""]},entryGroups:()=>[{key:"entries",isDim:e=>!1===e[2]},{key:"protoEntries",isDim:()=>!0}]},methods:{toggleExpanded(){this.isExpandable&&(this.isExpanded=!this.isExpanded,this.isExpanded)&&this.isPartialDescription&&messageParent({target:"runner",func:"sendDescriptionFor",args:[this.path]})}},template:'\n <div :class="classNames">\n <div :class="[\'js-value-header\', isExpandable ? \'expandable\' : \'\']" @click="toggleExpanded"><span\n v-if="isExpandable || isEntry" :class="[\'arrow\', isExpandable ? \'expandable\' : \'\', isExpanded ? \'expanded\' : \'\']"></span><template\n v-if="isEntry"><span :class="[\'entry-key\', isDimName ? \'dim\' : \'\']">{{ name }}</span>: </template><span\n v-for="part in description.parts" :class="\'t-\' + part[0]">{{ part[1] }}</span></div>\n <div v-if="hasBeenExpanded" v-show="isExpanded" class="expansion">\n <div v-if="isPartialDescription" class="loading">Loading&hellip;</div>\n <template v-else>\n <template v-for="group in entryGroups">\n <js-value\n v-for="(entry, entryIndex) in description[group.key]"\n :name="entry[0]"\n :is-dim-name="group.isDim(entry)"\n :description="entry[1]"\n :path="path.concat([group.key, entryIndex])">\n </js-value>\n </template>\n </template>\n </div>\n </div>\n '}}function parseJSCodeGroups(e){return e.split(/\r\n|\r|\n/).reduce((e,t)=>{var i=e[e.length-1],s=/^\/\/[^]*\\\\$/.test(t),n=s?t.replace(/^\/+\s*|\s*\\+$/g,""):t;return!e.length||s&&!i.canAppendHeader?e.push({headerLines:s?[n]:[],lines:s?[]:[t],allLines:[t],canAppendHeader:s}):(s?i.headerLines.push(n):(i.canAppendHeader=!1,i.lines.push(t)),i.allLines.push(t)),e},[]).reduce((e,t)=>(t.canAppendHeader||(delete t.canAppendHeader,t.headerLines=t.headerLines.join("\n").trimEnd(),t.lines=t.lines.join("\n"),t.allLines=t.allLines.join("\n"),e.push(t)),e),[])}function parseGroupHeader(e,t){var i=!!t&&e.startsWith(t);return{header:i?e.slice(t.length).replace(/^\s*:?\s*/,""):e,isHidden:i}}function extractHiddenGroups(e,t){var i=[],s=[];for(const n of parseJSCodeGroups(e))parseGroupHeader(n.headerLines,t).isHidden?s.push({...n,runCount:i.length}):i.push(n);return{visibleCode:i.map(e=>e.allLines).join("\n"),hiddenGroups:s}}function findLastExpression(e,t){if(window.acorn)try{var{body:i}=acorn.parse(e,{ecmaVersion:"latest",sourceType:"module"===t?"module":"script",allowHashBang:!0}),s=i[i.length-1];if("ExpressionStatement"===s?.type&&!s.directive)return[s.expression.start,s.expression.end]}catch(e){}return null}function joinCodeBlocks(e){return e.map(e=>e.replace(/^(\s*[\r\n])+|\s+$/g,"")).filter(Boolean).map((e,t)=>{var i=e.split(/\r\n|\r|\n/)[0];return t&&!/^\/\/[^]*\\\\$/.test(i)?`// \\\\
4
4
  `+e:e}).join("\n\n")}function buildConsoleHtml({code:e,dataset:t,packageInfo:i,isFullPage:s}){const{name:n,version:o}=i,r=`https://cdn.jsdelivr.net/npm/${n}@${o.split(".")[0]}/dist/${n}.min.js`,a=Object.entries(t).map(([e,t])=>` data-${e.replace(/[A-Z]/g,e=>"-"+e.toLowerCase())}="${escapeHtmlAttribute(t)}"`).join(""),l=s?" ":" ",d=e.replace(/<\/(script)/gi,"<\\/$1").replace(/<!--/g,"<\\!--"),c=(d.trim()?[`<script src="${r}"${a}>`,...d.split("\n").map(e=>e.trim()?" "+e:""),"<\/script>"]:[`<script src="${r}"${a}></script>`]).map(e=>e&&l+e).join("\n");return s?["<!DOCTYPE html>",'<html lang="en">'," <head>",' <meta charset="utf-8">',' <meta name="viewport" content="width=device-width, initial-scale=1">'," <title>JS Box</title>"," <style>"," html, body { height: 100%; margin: 0; }"," </style>"," </head>"," <body>",c," </body>","</html>",""].join("\n"):`<div style="height: 400px;">
5
5
  ${c}
6
6
  </div>
7
- `}function escapeHtmlAttribute(e){return(""+e).replace(/[&"<>]/g,e=>`&#${e.charCodeAt(0)};`)}function unindentMin(e,t){var i=(t=Object(t)).tabSize??4,t=t.trim??!0;if(e=e.replace(/\t/g," ".repeat(i)),!/(^|[\r\n])\S/.test(e)){const t=/(^|[\r\n])((?:(?!\r|\n)\s)+)(?=(\S)?)/g;let i=1/0;for(let s;s=t.exec(e);)s[3]&&(i=Math.min(i,s[2].length));e=e.replace(t,(e,t,s)=>t+s.slice(i))}return t?e.replace(/^(\s*[\r\n]+)+|\s+$/g,""):e}function sanitizeDescription(e){return{typeName:""+(e=Object(e)).typeName,isPrimitive:!!e.isPrimitive,parts:Array.from(e.parts??[],e=>[/^[a-z]+$/.test(Object(e)[0])?e[0]:"text",""+Object(e)[1]]),...sanitizeEntries(e)}}function sanitizeEntries(e){e=Object(e);var t={};for(const i of["entries","protoEntries"])Array.isArray(e[i])&&(t[i]=e[i].map(e=>[""+Object(e)[0],sanitizeDescription(Object(e)[1]),!1!==Object(e)[2]]));return t}function appendLog({logId:e,key:t,descriptions:i,table:s,groupIds:n,groupId:o,isCollapsed:r,stack:a}){t=""+t,mountedApp.displays.push({type:"log",key:t,name:"result"===t?"Result":"console."+t,descriptions:Array.from(i,sanitizeDescription),table:s?{headers:Array.from(s.headers,e=>""+e),rows:Array.from(s.rows,e=>({index:""+e.index,cells:Array.from(e.cells,e=>e&&sanitizeDescription(e))}))}:null,groupIds:Array.from(n??[],e=>""+e),groupId:null!=o?""+o:null,isCollapsed:!!r,stack:null!=a?""+a:null,logId:""+e})}function appendError({message:e,line:t,column:i}){mountedApp.displays.push({type:"error",message:""+e,line:+t,column:+i})}function updateDescriptionFor(e,t){const i=(e=Array.from(e)).shift(),s=mountedApp.displays.find(e=>"log"===e.type&&e.logId===i);let n=s?.descriptions[toIndex(e.shift())];for(let t=0;n&&t<e.length;t+=2){const i=e[t];if("entries"!==i&&"protoEntries"!==i)return;n=n[i]?.[toIndex(e[t+1])]?.[1]}n&&Object.assign(n,sanitizeEntries(t))}function onCodeRan(){mountedApp.runningCount=Math.max(0,mountedApp.runningCount-1),mountedApp.runHiddenGroups()}function setPoppedOut(e,t){mountedApp.isPoppedOut=e,t&&mountedApp.restoreState(t)}function popIn(){mountedApp.bringBack()}function onPopOutFailed(){mountedApp.displays.push({type:"notice",message:"The pop-out window was blocked by the browser. Allow pop-ups for this site and try again."})}function clearDisplays(){mountedApp.displays=[{type:"notice",message:"Console was cleared"}]}function toIndex(e){return Number.isInteger(e)&&0<=e?e:void 0}},jsUrls:[libraryUrl("vue","dist/vue.global.prod.js"),libraryUrl("ace-builds","src-noconflict/ace.js"),libraryUrl("prismjs","components/prism-core.min.js"),libraryUrl("prismjs","plugins/autoloader/prism-autoloader.min.js"),libraryUrl("prismjs","plugins/match-braces/prism-match-braces.min.js"),...showResults?[libraryUrl("acorn","dist/acorn.js")]:[]],cssUrls:["data:text/css,"+encodeURIComponent(VIEWER_IFRAME_CSS),libraryUrl("prism-themes","themes/prism-vsc-dark-plus.min.css"),libraryUrl("prismjs","plugins/match-braces/prism-match-braces.min.css")],head:targetWindow?'<meta charset="utf-8"><title>JS Box</title>':"",htmlAttributes:'data-theme="'+theme+'"',targetWindow:targetWindow,onMessage(message){relayMessage(message.data,{runner:runner,host:{apply:(func,args)=>hostFuncs[func](...args)}})},async onReady(){this.call("init",script.textContent,dataset,{runnerMode:runnerMode,blockType:blockType,showResults:showResults,packageInfo:PACKAGE_INFO,libraryVersions:LIBRARY_VERSIONS,isPopOut:!!targetWindow,popOutState:state??null})},body:VIEWER_IFRAME_HTML,style:{width:"100%",height:"100%",border:0,display:"block"}})}addEventListener("pagehide",()=>popOutWindow?.close()),inlineViewer=activeViewer=createViewer(),script.parentNode.insertBefore(inlineViewer.iframe,script)}var createCallableFrame=function(){var IFRAME_SCRIPT_MESSAGE_CODE=parseFunction(function(){var HOST_WINDOW=window.opener||window.parent;function messageParent(message){HOST_WINDOW.postMessage(message,"*")}window.addEventListener("message",function(e){var data=e.data,func;e.source===HOST_WINDOW&&data&&/^[A-Za-z_$][\w$]*$/.test(data.funcName)&&Array.isArray(data.args)&&(func=eval(data.funcName),"function"==typeof func)&&func.apply(e,data.args)})}).body;function createCallableFrame(options){var jsCode=options.jsCode,onMessage=options.onMessage,onReady=options.onReady,style=options.style,isReady,READY_ID=Math.random()+""+Math.random(),jsCode=["(function(){",IFRAME_SCRIPT_MESSAGE_CODE,"var applyParent, callParent;","(function(READY_ID){",parseFunction(function(){applyParent=function(funcName,args){HOST_WINDOW.postMessage({funcName:funcName,args:args,id:READY_ID},"*")},callParent=function(funcName){HOST_WINDOW.postMessage({funcName:funcName,args:Array.prototype.slice.call(arguments,1),id:READY_ID},"*")};var interval=setInterval(function(){/^(complete|interactive)$/.test(document.readyState)&&(clearInterval(interval),messageParent(READY_ID))},100)}).body,"})("+JSON.stringify(READY_ID)+");","function"!=typeof jsCode?jsCode||"":parseFunction(jsCode).body,"})();"].join("\n").replace(/<(?=\/script|!--)/gi,"\\x3C"),TARGET_WINDOW=options.targetWindow,IFRAME=TARGET_WINDOW?null:document.createElement("iframe");function getFrameWindow(){return TARGET_WINDOW||IFRAME.contentWindow}var jsCode=["<!DOCTYPE html>","<html "+(options.htmlAttributes||"")+">","<head>",options.head||"",(options.cssUrls||[]).map(function(cssUrl){return'<link href="'+cssUrl+'" rel="stylesheet">'}).join("\n"),"</head>","<body>",options.body||"",(options.jsUrls||[]).map(function(jsUrl){return'<script src="'+jsUrl+'"><\/script>'}).join("\n"),"<script>"+jsCode+"<\/script>","</body>","</html>"].join("\n");if(TARGET_WINDOW?(TARGET_WINDOW.document.open(),TARGET_WINDOW.document.write(jsCode),TARGET_WINDOW.document.close()):(IFRAME.srcdoc=jsCode,IFRAME.setAttribute("allow","fullscreen")),style&&IFRAME)if("string"==typeof style)IFRAME.style.cssText=style;else for(var styleKey in style)hasOwn(style,styleKey)&&(IFRAME.style[styleKey]=style[styleKey]);function onWindowMessage(e){if(e.source===getFrameWindow()){var data=e.data,dataIsReadyId=READY_ID===data;if(isReady&&!dataIsReadyId)options.functions&&data.id===READY_ID&&hasOwn(options.functions,data.funcName)?options.functions[data.funcName].apply(callableFrame,data.args):"function"==typeof onMessage?onMessage.call(callableFrame,e):console.warn("Message sent from callable frame but no listener was set up.",e);else if(dataIsReadyId)for(isReady=!0,"function"==typeof onReady&&onReady.call(callableFrame,e);queuedMessages.length;)postToFrame(queuedMessages.shift());else console.warn("Message sent from callable frame prematurely:",e)}}addEventListener("message",onWindowMessage);var queuedMessages=[];function postToFrame(message){isReady?getFrameWindow().postMessage(message,"*"):queuedMessages.push(message)}var callableFrame={apply:function(funcName,args){postToFrame({funcName:funcName,args:args})},call:function(funcName){postToFrame({funcName:funcName,args:Array.prototype.slice.call(arguments,1)})},iframe:IFRAME,window:TARGET_WINDOW,dispose:function(){removeEventListener("message",onWindowMessage)}};return callableFrame}var hasOwn=atob.call.bind({}.hasOwnProperty);function parseFunction(input){for(var strFunc=input+"",m;m=/\/\*[^]*?\*\/|\/\/.*/g.exec(strFunc);){var STR_BEFORE=strFunc.slice(0,m.index);if(/[\{"'`]/.test(STR_BEFORE))break;strFunc=STR_BEFORE+" "+strFunc.slice(m.index+m[0].length)}var input=/^\s*async\b/.test(strFunc),IS_GENERATOR=(input&&(strFunc=strFunc.replace("async","")),/^\s*(?:function\s*)?\*/.test(strFunc)),ARROW_MATCH=(IS_GENERATOR&&(strFunc=strFunc.replace(/(?:\bfunction\s*)?\*/,"")),/\s*=>\s*/.exec(strFunc)),INDEX_OF_FUNC_START=strFunc.search(/\)\s*\{/),INDEX_OF_FUNC_START=ARROW_MATCH&&(ARROW_MATCH.index<INDEX_OF_FUNC_START||INDEX_OF_FUNC_START<0),parameters,ARROW_MATCH,STR_BEFORE,ARROW_MATCH,parameters,ARROW_MATCH;return ARROW_MATCH=INDEX_OF_FUNC_START?(STR_BEFORE=strFunc.slice(0,ARROW_MATCH.index),ARROW_MATCH=strFunc.slice(ARROW_MATCH.index+ARROW_MATCH[0].length),parameters=(/\S+(?:\s*,\s*\S+)*/.exec(STR_BEFORE.replace(/[()]/g," "))??[])[0],/^\{/.test(ARROW_MATCH)?ARROW_MATCH.replace(/^\{|\}\s*$/g,""):"return "+ARROW_MATCH):(parameters=(/\(([^\)]*)\)/.exec(strFunc)??[])[1],(/\{([^]*)\}/.exec(strFunc)??[])[1]),{isAsync:input,isGenerator:IS_GENERATOR,isArrow:INDEX_OF_FUNC_START,parameters:parameters,body:ARROW_MATCH}}return createCallableFrame.parseFunction=parseFunction,createCallableFrame}();main(document.currentScript)})();
7
+ `}function escapeHtmlAttribute(e){return(""+e).replace(/[&"<>]/g,e=>`&#${e.charCodeAt(0)};`)}function unindentMin(e,t){var i=(t=Object(t)).tabSize??4,t=t.trim??!0;if(e=e.replace(/\t/g," ".repeat(i)),!/(^|[\r\n])\S/.test(e)){const t=/(^|[\r\n])((?:(?!\r|\n)\s)+)(?=(\S)?)/g;let i=1/0;for(let s;s=t.exec(e);)s[3]&&(i=Math.min(i,s[2].length));e=e.replace(t,(e,t,s)=>t+s.slice(i))}return t?e.replace(/^(\s*[\r\n]+)+|\s+$/g,""):e}function sanitizeDescription(e){return{typeName:""+(e=Object(e)).typeName,isPrimitive:!!e.isPrimitive,parts:Array.from(e.parts??[],e=>[/^[a-z]+$/.test(Object(e)[0])?e[0]:"text",""+Object(e)[1]]),...sanitizeEntries(e)}}function sanitizeEntries(e){e=Object(e);var t={};for(const i of["entries","protoEntries"])Array.isArray(e[i])&&(t[i]=e[i].map(e=>[""+Object(e)[0],sanitizeDescription(Object(e)[1]),!1!==Object(e)[2]]));return t}function appendLog({logId:e,key:t,descriptions:i,table:s,groupIds:n,groupId:o,isCollapsed:r,stack:a}){t=""+t,mountedApp.displays.push({type:"log",key:t,name:"result"===t?"Result":"console."+t,descriptions:Array.from(i,sanitizeDescription),table:s?{headers:Array.from(s.headers,e=>""+e),rows:Array.from(s.rows,e=>({index:""+e.index,cells:Array.from(e.cells,e=>e&&sanitizeDescription(e))}))}:null,groupIds:Array.from(n??[],e=>""+e),groupId:null!=o?""+o:null,isCollapsed:!!r,stack:null!=a?""+a:null,logId:""+e})}function appendError({message:e,line:t,column:i}){mountedApp.displays.push({type:"error",message:""+e,line:+t,column:+i})}function updateDescriptionFor(e,t){const i=(e=Array.from(e)).shift(),s=mountedApp.displays.find(e=>"log"===e.type&&e.logId===i);let n=s?.descriptions[toIndex(e.shift())];for(let t=0;n&&t<e.length;t+=2){const i=e[t];if("entries"!==i&&"protoEntries"!==i)return;n=n[i]?.[toIndex(e[t+1])]?.[1]}n&&Object.assign(n,sanitizeEntries(t))}function onCodeRan(){mountedApp.runningCount=Math.max(0,mountedApp.runningCount-1),mountedApp.runHiddenGroups()}function setPoppedOut(e,t){mountedApp.isPoppedOut=e,t&&mountedApp.restoreState(t)}function popIn(){mountedApp.bringBack()}function onPopOutFailed(){mountedApp.displays.push({type:"notice",message:"The pop-out window was blocked by the browser. Allow pop-ups for this site and try again."})}function clearDisplays(){mountedApp.displays=[{type:"notice",message:"Console was cleared"}]}function toIndex(e){return Number.isInteger(e)&&0<=e?e:void 0}},jsUrls:[libraryUrl("vue","dist/vue.global.prod.js"),libraryUrl("ace-builds","src-noconflict/ace.js"),libraryUrl("prismjs","components/prism-core.min.js"),libraryUrl("prismjs","plugins/autoloader/prism-autoloader.min.js"),libraryUrl("prismjs","plugins/match-braces/prism-match-braces.min.js"),...showResults?[libraryUrl("acorn","dist/acorn.js")]:[]],cssUrls:["data:text/css,"+encodeURIComponent(VIEWER_IFRAME_CSS),libraryUrl("prism-themes","themes/prism-vsc-dark-plus.min.css"),libraryUrl("prismjs","plugins/match-braces/prism-match-braces.min.css")],head:targetWindow?'<meta charset="utf-8"><title>JS Box</title>':"",htmlAttributes:'data-theme="'+theme+'"',targetWindow:targetWindow,onMessage(message){relayMessage(message.data,{runner:runner,host:{apply:(func,args)=>hostFuncs[func](...args)}})},async onReady(){this.call("init",code,dataset,{runnerMode:runnerMode,blockType:blockType,showResults:showResults,packageInfo:PACKAGE_INFO,libraryVersions:LIBRARY_VERSIONS,isPopOut:!!targetWindow,popOutState:state??null})},body:VIEWER_IFRAME_HTML,style:{width:"100%",height:height||"100%",minHeight:"150px",border:0,display:"block"}})}addEventListener("pagehide",closePopOut),insert((inlineViewer=activeViewer=createViewer()).iframe);let isDestroyed=!1;return{element:inlineViewer.iframe,destroy(){isDestroyed||(isDestroyed=!0,popOutWindow&&(clearInterval(popOutWatcher),popOutViewer.dispose(),popOutWindow.close(),popOutWindow=null),removeEventListener("pagehide",closePopOut),runner.destroy(),inlineViewer.dispose(),inlineViewer.iframe.remove())}}}function createConsoleFromScript(script){createConsole({code:script.textContent,dataset:JSON.parse(JSON.stringify(script.dataset)),insert:element=>script.parentNode.insertBefore(element,script)})}const PLACEMENTS={fill:(target,element)=>target.replaceChildren(element),append:(target,element)=>target.append(element),prepend:(target,element)=>target.prepend(element),replace:(target,element)=>target.replaceWith(element),before:(target,element)=>target.before(element),after:(target,element)=>target.after(element)},CONSOLE_OPTION_NAMES=["blockType","dividerOrient","hidePrefix","librariesUrl","runner","showResults","theme"],YourJSBox=Object.freeze({version:PACKAGE_INFO.version,create(options){const{target,placement="fill",height,code=""}=options=Object(options),targetElement="string"==typeof target?document.querySelector(target):target;if(1!==targetElement?.nodeType)throw new TypeError("string"==typeof target?`YourJSBox.create(): no element matches the target ${JSON.stringify(target)}.`:"YourJSBox.create(): target must be an element or a CSS selector.");if(!Object.hasOwn(PLACEMENTS,placement))throw new TypeError(`YourJSBox.create(): placement must be one of ${Object.keys(PLACEMENTS).join(", ")}.`);var dataset={};for(const name of CONSOLE_OPTION_NAMES)null!=options[name]&&(dataset[name]=""+options[name]);return createConsole({code:""+code,dataset:dataset,height:"number"==typeof height?height+"px":null!=height?""+height:void 0,insert:element=>PLACEMENTS[placement](targetElement,element)})}});var createCallableFrame=function(){var IFRAME_SCRIPT_MESSAGE_CODE=parseFunction(function(){var HOST_WINDOW=window.opener||window.parent;function messageParent(message){HOST_WINDOW.postMessage(message,"*")}window.addEventListener("message",function(e){var data=e.data,func;e.source===HOST_WINDOW&&data&&/^[A-Za-z_$][\w$]*$/.test(data.funcName)&&Array.isArray(data.args)&&(func=eval(data.funcName),"function"==typeof func)&&func.apply(e,data.args)})}).body;function createCallableFrame(options){var jsCode=options.jsCode,onMessage=options.onMessage,onReady=options.onReady,style=options.style,isReady,READY_ID=Math.random()+""+Math.random(),jsCode=["(function(){",IFRAME_SCRIPT_MESSAGE_CODE,"var applyParent, callParent;","(function(READY_ID){",parseFunction(function(){applyParent=function(funcName,args){HOST_WINDOW.postMessage({funcName:funcName,args:args,id:READY_ID},"*")},callParent=function(funcName){HOST_WINDOW.postMessage({funcName:funcName,args:Array.prototype.slice.call(arguments,1),id:READY_ID},"*")};var interval=setInterval(function(){/^(complete|interactive)$/.test(document.readyState)&&(clearInterval(interval),messageParent(READY_ID))},100)}).body,"})("+JSON.stringify(READY_ID)+");","function"!=typeof jsCode?jsCode||"":parseFunction(jsCode).body,"})();"].join("\n").replace(/<(?=\/script|!--)/gi,"\\x3C"),TARGET_WINDOW=options.targetWindow,IFRAME=TARGET_WINDOW?null:document.createElement("iframe");function getFrameWindow(){return TARGET_WINDOW||IFRAME.contentWindow}var jsCode=["<!DOCTYPE html>","<html "+(options.htmlAttributes||"")+">","<head>",options.head||"",(options.cssUrls||[]).map(function(cssUrl){return'<link href="'+cssUrl+'" rel="stylesheet">'}).join("\n"),"</head>","<body>",options.body||"",(options.jsUrls||[]).map(function(jsUrl){return'<script src="'+jsUrl+'"><\/script>'}).join("\n"),"<script>"+jsCode+"<\/script>","</body>","</html>"].join("\n");if(TARGET_WINDOW?(TARGET_WINDOW.document.open(),TARGET_WINDOW.document.write(jsCode),TARGET_WINDOW.document.close()):(IFRAME.srcdoc=jsCode,IFRAME.setAttribute("allow","fullscreen")),style&&IFRAME)if("string"==typeof style)IFRAME.style.cssText=style;else for(var styleKey in style)hasOwn(style,styleKey)&&(IFRAME.style[styleKey]=style[styleKey]);function onWindowMessage(e){if(e.source===getFrameWindow()){var data=e.data,dataIsReadyId=READY_ID===data;if(isReady&&!dataIsReadyId)options.functions&&data.id===READY_ID&&hasOwn(options.functions,data.funcName)?options.functions[data.funcName].apply(callableFrame,data.args):"function"==typeof onMessage?onMessage.call(callableFrame,e):console.warn("Message sent from callable frame but no listener was set up.",e);else if(dataIsReadyId)for(isReady=!0,"function"==typeof onReady&&onReady.call(callableFrame,e);queuedMessages.length;)postToFrame(queuedMessages.shift());else console.warn("Message sent from callable frame prematurely:",e)}}addEventListener("message",onWindowMessage);var queuedMessages=[];function postToFrame(message){isReady?getFrameWindow().postMessage(message,"*"):queuedMessages.push(message)}var callableFrame={apply:function(funcName,args){postToFrame({funcName:funcName,args:args})},call:function(funcName){postToFrame({funcName:funcName,args:Array.prototype.slice.call(arguments,1)})},iframe:IFRAME,window:TARGET_WINDOW,dispose:function(){removeEventListener("message",onWindowMessage)}};return callableFrame}var hasOwn=atob.call.bind({}.hasOwnProperty);function parseFunction(input){for(var strFunc=input+"",m;m=/\/\*[^]*?\*\/|\/\/.*/g.exec(strFunc);){var STR_BEFORE=strFunc.slice(0,m.index);if(/[\{"'`]/.test(STR_BEFORE))break;strFunc=STR_BEFORE+" "+strFunc.slice(m.index+m[0].length)}var input=/^\s*async\b/.test(strFunc),IS_GENERATOR=(input&&(strFunc=strFunc.replace("async","")),/^\s*(?:function\s*)?\*/.test(strFunc)),ARROW_MATCH=(IS_GENERATOR&&(strFunc=strFunc.replace(/(?:\bfunction\s*)?\*/,"")),/\s*=>\s*/.exec(strFunc)),INDEX_OF_FUNC_START=strFunc.search(/\)\s*\{/),INDEX_OF_FUNC_START=ARROW_MATCH&&(ARROW_MATCH.index<INDEX_OF_FUNC_START||INDEX_OF_FUNC_START<0),parameters,ARROW_MATCH,STR_BEFORE,ARROW_MATCH,parameters,ARROW_MATCH;return ARROW_MATCH=INDEX_OF_FUNC_START?(STR_BEFORE=strFunc.slice(0,ARROW_MATCH.index),ARROW_MATCH=strFunc.slice(ARROW_MATCH.index+ARROW_MATCH[0].length),parameters=(/\S+(?:\s*,\s*\S+)*/.exec(STR_BEFORE.replace(/[()]/g," "))??[])[0],/^\{/.test(ARROW_MATCH)?ARROW_MATCH.replace(/^\{|\}\s*$/g,""):"return "+ARROW_MATCH):(parameters=(/\(([^\)]*)\)/.exec(strFunc)??[])[1],(/\{([^]*)\}/.exec(strFunc)??[])[1]),{isAsync:input,isGenerator:IS_GENERATOR,isArrow:INDEX_OF_FUNC_START,parameters:parameters,body:ARROW_MATCH}}return createCallableFrame.parseFunction=parseFunction,createCallableFrame}();window.YourJSBox||(window.YourJSBox=YourJSBox);const currentScript=document.currentScript;currentScript&&!document.head?.contains(currentScript)&&createConsoleFromScript(currentScript)})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yourjs-box",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "A simple way to embed a JavaScript console on your website.",
5
5
  "unpkg": "dist/yourjs-box.min.js",
6
6
  "jsdelivr": "dist/yourjs-box.min.js",