yourjs-box 1.6.0 → 1.8.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 +96 -19
- package/dist/yourjs-box.full.js +243 -29
- package/dist/yourjs-box.js +58 -11
- package/dist/yourjs-box.min.js +8 -7
- package/package.json +2 -1
package/dist/yourjs-box.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! yourjs-box v1.
|
|
1
|
+
/*! yourjs-box v1.8.0 | (c) 2023-present Chris West | MIT License | https://github.com/westc/yourjs-box */
|
|
2
2
|
(() => {
|
|
3
3
|
/**
|
|
4
4
|
* Viewer IFRAME's CSS code
|
|
@@ -9,12 +9,12 @@
|
|
|
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.
|
|
12
|
+
const PACKAGE_INFO = {"name":"yourjs-box","version":"1.8.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}
|
|
16
16
|
*/
|
|
17
|
-
const 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…</div><div class=\"splash-message splash-error\">JS Box couldn’t load. Please check your connection and reload the page.</div></div></div><div id=\"vueApp\" v-cloak><input type=\"file\" ref=\"fileInput\" class=\"file-input\" accept=\".js,.mjs,.cjs,.txt,text/javascript,text/plain\" tabindex=\"-1\" aria-hidden=\"true\" @change=\"onFileChosen\"><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' && !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\" :key-path=\"[]\" :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 ref=\"editor\" v-model=\"jsCode\" language=\"javascript\" :theme=\"theme\" :font-size=\"Math.round(12 * textScale)\" @key-combo=\"onEditorKeyCombo\" @history-key=\"onEditorHistoryKey\" 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 && 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−</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 class=\"menu-item\" role=\"menuitem\" @click=\"openFile()\"><span class=\"menu-icon\"><icon name=\"open\"></icon></span>Open…</button> <button class=\"menu-item\" role=\"menuitem\" @click=\"saveFile()\"><span class=\"menu-icon\"><icon name=\"save\"></icon></span>Save…</button><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…</button> <button class=\"menu-item\" role=\"menuitem\" @click=\"closeMenu(); resetConsole()\"><span class=\"menu-icon\"><icon name=\"refresh\"></icon></span>Reset…</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=\"isHistoryOpen\" class=\"more-menu history-panel\" role=\"menu\" aria-label=\"History\" ref=\"historyPanel\" @keydown=\"onMenuKeyDown\"><div class=\"history-title\">History</div><div v-if=\"!historyEntries.length\" class=\"history-empty\">Code that you run will show up here.</div><button v-for=\"entry in historyEntries\" class=\"menu-item history-item\" role=\"menuitem\" :title=\"commandHistory[entry.index]\" @click=\"recallHistory(entry.index)\"><span class=\"history-label\">{{ entry.label }}</span> <span class=\"history-detail\">{{ entry.detail }}</span></button><div class=\"history-hint\">Tip: press ↑ at the start of the editor (or ↓ at the end) to go through the history.</div></div><div v-if=\"valueMenu\" class=\"more-menu value-menu\" role=\"menu\" aria-label=\"Value\" ref=\"valueMenu\" :style=\"{left: valueMenu.x + 'px', top: valueMenu.y + 'px'}\" @keydown=\"onMenuKeyDown\"><button class=\"menu-item\" role=\"menuitem\" @click=\"copyValueAsJson()\"><span class=\"menu-icon\"><icon name=\"copy\"></icon></span>Copy as JSON</button> <button class=\"menu-item\" role=\"menuitem\" @click=\"saveValueAsJson()\"><span class=\"menu-icon\"><icon name=\"save\"></icon></span>Save as JSON…</button> <button class=\"menu-item\" role=\"menuitem\" @click=\"storeValueAsGlobal()\"><span class=\"menu-icon\"><icon name=\"variable\"></icon></span>Store as global variable</button> <button v-if=\"valueMenu.propertyPath\" class=\"menu-item\" role=\"menuitem\" @click=\"copyPropertyPath()\"><span class=\"menu-icon\"><icon name=\"path\"></icon></span>Copy property path</button><template v-if=\"!valueMenu.isPrimitive\"><div class=\"menu-separator\"></div><button class=\"menu-item\" role=\"menuitem\" @click=\"refreshValue()\"><span class=\"menu-icon\"><icon name=\"refresh\"></icon></span>Refresh</button></template></div><div v-if=\"toast\" class=\"toast\" role=\"status\">{{ toast.message }}</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>Imports</dt><dd>{{ importsUrl ? 'Packages imported by name load from ' + importsUrl.replace('{specifier}', '\u2026') : 'Only URLs and paths can be imported' }}</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>↑</kbd> / <kbd>↓</kbd></dt><dd>Go through the code that was run (at the very start or end of the editor)</dd><dt><kbd>{{ modKey === 'Ctrl' ? 'Alt' : '⌥' }}</kbd> + <kbd>H</kbd></dt><dd>Show the history</dd><dt><kbd>Esc</kbd></dt><dd>Close this window, the menu or full screen</dd></dl><div class=\"about-footer\">MIT License © 2023-present Chris West · 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>";
|
|
17
|
+
const 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…</div><div class=\"splash-message splash-error\">JS Box couldn’t load. Please check your connection and reload the page.</div></div></div><div id=\"vueApp\" v-cloak><input type=\"file\" ref=\"fileInput\" class=\"file-input\" accept=\".js,.mjs,.cjs,.ts,.mts,.cts,.txt,text/javascript,text/plain\" tabindex=\"-1\" aria-hidden=\"true\" @change=\"onFileChosen\"><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=\"language\" :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' && !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\" :key-path=\"[]\" :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 ref=\"editor\" v-model=\"jsCode\" :language=\"language\" :theme=\"theme\" :font-size=\"Math.round(12 * textScale)\" @key-combo=\"onEditorKeyCombo\" @history-key=\"onEditorHistoryKey\" 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 && 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−</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 class=\"menu-item\" role=\"menuitem\" @click=\"openFile()\"><span class=\"menu-icon\"><icon name=\"open\"></icon></span>Open…</button> <button class=\"menu-item\" role=\"menuitem\" @click=\"saveFile()\"><span class=\"menu-icon\"><icon name=\"save\"></icon></span>Save…</button><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…</button> <button class=\"menu-item\" role=\"menuitem\" @click=\"closeMenu(); resetConsole()\"><span class=\"menu-icon\"><icon name=\"refresh\"></icon></span>Reset…</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=\"isHistoryOpen\" class=\"more-menu history-panel\" role=\"menu\" aria-label=\"History\" ref=\"historyPanel\" @keydown=\"onMenuKeyDown\"><div class=\"history-title\">History</div><div v-if=\"!historyEntries.length\" class=\"history-empty\">Code that you run will show up here.</div><button v-for=\"entry in historyEntries\" class=\"menu-item history-item\" role=\"menuitem\" :title=\"commandHistory[entry.index]\" @click=\"recallHistory(entry.index)\"><span class=\"history-label\">{{ entry.label }}</span> <span class=\"history-detail\">{{ entry.detail }}</span></button><div class=\"history-hint\">Tip: press ↑ at the start of the editor (or ↓ at the end) to go through the history.</div></div><div v-if=\"valueMenu\" class=\"more-menu value-menu\" role=\"menu\" aria-label=\"Value\" ref=\"valueMenu\" :style=\"{left: valueMenu.x + 'px', top: valueMenu.y + 'px'}\" @keydown=\"onMenuKeyDown\"><button class=\"menu-item\" role=\"menuitem\" @click=\"copyValueAsJson()\"><span class=\"menu-icon\"><icon name=\"copy\"></icon></span>Copy as JSON</button> <button class=\"menu-item\" role=\"menuitem\" @click=\"saveValueAsJson()\"><span class=\"menu-icon\"><icon name=\"save\"></icon></span>Save as JSON…</button> <button class=\"menu-item\" role=\"menuitem\" @click=\"storeValueAsGlobal()\"><span class=\"menu-icon\"><icon name=\"variable\"></icon></span>Store as global variable</button> <button v-if=\"valueMenu.propertyPath\" class=\"menu-item\" role=\"menuitem\" @click=\"copyPropertyPath()\"><span class=\"menu-icon\"><icon name=\"path\"></icon></span>Copy property path</button><template v-if=\"!valueMenu.isPrimitive\"><div class=\"menu-separator\"></div><button class=\"menu-item\" role=\"menuitem\" @click=\"refreshValue()\"><span class=\"menu-icon\"><icon name=\"refresh\"></icon></span>Refresh</button></template></div><div v-if=\"toast\" class=\"toast\" role=\"status\">{{ toast.message }}</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>Language</dt><dd>{{ isTypeScript ? 'TypeScript (types are removed by Babel, not checked)' : 'JavaScript' }}</dd><dt>Code blocks run as</dt><dd>{{ blockTypeDescription }}</dd><dt>Imports</dt><dd>{{ importsUrl ? 'Packages imported by name load from ' + importsUrl.replace('{specifier}', '\u2026') : 'Only URLs and paths can be imported' }}</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>↑</kbd> / <kbd>↓</kbd></dt><dd>Go through the code that was run (at the very start or end of the editor)</dd><dt><kbd>{{ modKey === 'Ctrl' ? 'Alt' : '⌥' }}</kbd> + <kbd>H</kbd></dt><dd>Show the history</dd><dt><kbd>Esc</kbd></dt><dd>Close this window, the menu or full screen</dd></dl><div class=\"about-footer\">MIT License © 2023-present Chris West · Built with {{ builtWith }}</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>";
|
|
18
18
|
/**
|
|
19
19
|
* The URL of this script which is used to remove this script's lines from the
|
|
20
20
|
* stack traces of errors in window mode.
|
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
* was tested with.
|
|
34
34
|
*/
|
|
35
35
|
const LIBRARY_VERSIONS = {
|
|
36
|
+
// Only loaded by TypeScript consoles.
|
|
37
|
+
'@babel/standalone': '7.29.9',
|
|
36
38
|
'ace-builds': '1.44.0',
|
|
37
39
|
'acorn': '8.18.0',
|
|
38
40
|
'prism-themes': '1.9.0',
|
|
@@ -112,7 +114,7 @@
|
|
|
112
114
|
}
|
|
113
115
|
}
|
|
114
116
|
|
|
115
|
-
function createRunner(e,t){const{mode:n}=t,r=t.ownUrl||("worker"===n?self.location.href:""),o={};let s=0,i=0,c=!0,l;const a={},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)_(),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=>({...L(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);_()}function j(t,n){const r="classic"===l&&"SyntaxError"===t?.name?/\bawait\b/.test(t.message)?"top-level await":/\bimport\b/.test(t.message)?"import statements":null:null,o=r?`\n(To use ${r}, 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}`)+o}]})}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=a[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)?L(t[e],2):null)),...c?[n?L(r,2):null]:[]]})))}}function S(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 A(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,k=100;function L(e,t=0,n=!1){const r=S(e),o="function"!==r&&r===r.toLowerCase(),s=undefined;return{typeName:r,isPrimitive:o,parts:n?[["text","Object"!==r?r:A(e,r)]]:T(e,t,r)}}function T(e,t,n=S(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 R(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 R(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=A(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,k)},((e,t)=>t)),t,(t=>s.push(...t in e?T(e[t],2):[["null","empty"]]))),s.push(["text","]"])}else if("Map"===n||"Set"===n){const t=[...e].slice(0,k);s.push(["text",`${r}(${e.size}) {`]),i(t,e.size,(e=>{"Map"===n?s.push(...T(e[0],2),["text"," => "],...T(e[1],2)):s.push(...T(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","{"],...T(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?T(n.value,2):[["text","(\u2026)"]])})),s.push(["text","}"]))}return s}function U(e,t=e){const n=S(e),r=[],o=[],s=[],i=[];let c=!1;if(null!==e&&("object"==typeof e||"function"==typeof e)){try{if("Map"===n){for(const[t,n]of[...e])r.push([T(t,2).map((e=>e[1])).join(""),L(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,L(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,L(i,1),s.enumerable]),o.push({value:i})}catch(e){}const l=Object.getPrototypeOf(e);null!==l&&(s.push(["[[Prototype]]",L(l,1,!0)]),i.push({value:l,receiver:t}))}return{entries:r,protoEntries:s,entriesArePropertyKeys:!c,$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");a[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}`;l="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)}l=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(e){V(e,!1)}function J(e){V(e,!0)}function V(t,n){const r=z(t);if(!r)return;const o=U(r.value,"receiver"in r?r.receiver:r.value);Object.assign(r,o);const s=n?L(r.value,t.length>2?1:0,"protoEntries"===t[t.length-2]):{};e({target:"viewer",func:"updateDescriptionFor",args:[t,{...w(["$entries","$protoEntries"],o),...s}]})}function z(e){let t=o;return e.forEach(((e,n)=>{t=t?.[n&&n%2==0?"$"+e:e]})),t}function F(t,n){const r=z(t);let o;try{o=r?B(r.value):{error:"The value is no longer available."}}catch(e){o={error:`The value couldn't be converted to JSON (${e?.message??e}).`}}e({target:"viewer",func:"onValueJson",args:[{requestId:n,...o}]})}function B(e){let t=0;const n=[],r=JSON.stringify(e,(function(e,r){for(;n.length&&n[n.length-1].converted!==this;)n.pop();if("bigint"==typeof r)return`${r}`;if(null!==r&&"object"==typeof r){const e=r;if(n.some((t=>t.original===e)))return void t++;(r instanceof Map||r instanceof Set)&&(r=[...r]),n.push({original:e,converted:r})}return r}),2);return void 0===r?{error:"This value can't be represented as JSON.",circularCount:t}:{json:r,circularCount:t}}function G(t){const n=z(t);if(!n)return;let r=1;for(;`temp${r}`in globalThis;)r++;globalThis[`temp${r}`]=n.value,e({target:"viewer",func:"onStoredAsGlobal",args:[`temp${r}`]})}function _(){for(const e of Object.keys(o))delete o[e];p=[]}return{clearLogs:_,destroy:x,getValueAsJson:F,refreshDescription:J,runCode:M,sendDescriptionFor:I,storeAsGlobal:G}}
|
|
117
|
+
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={},p={};let d=[],g=0;const h=`yourjs-box.result.${Math.random().toString(36).slice(2)}`;globalThis[Symbol.for(h)]=v;const m=[];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 y(e,n),t.apply(this,arguments)};console[e]=n,m.push({key:e,original:t,wrapper:n})}function y(t,n){const r=n.length&&void 0!==n[0]?`${n[0]}`:"default";if("clear"===t)K(),d=[],e({target:"viewer",func:"clearDisplays",args:[!0]});else if("assert"===t){if(n[0])return;const e=n.slice(1);b("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)f[r]=(f[r]||0)+1,b("count",[`${r}: ${f[r]}`]);else if("countReset"===t)Object.hasOwn(f,r)?f[r]=0:b("warn",[`Count for '${r}' does not exist`]);else if("time"===t)Object.hasOwn(p,r)?b("warn",[`Timer '${r}' already exists`]):p[r]=performance.now();else if("timeLog"===t||"timeEnd"===t){if(!Object.hasOwn(p,r))return void b("warn",[`Timer '${r}' does not exist`]);const e=performance.now()-p[r];"timeEnd"===t&&delete p[r],b(t,[`${r}: ${+e.toFixed(3)} ms`,..."timeLog"===t?n.slice(1):[]])}else if("trace"===t){const e=w((new Error).stack??"").split("\n").slice(1).join("\n");b("trace",n.length?n:["console.trace"],{stack:e})}else if("group"===t||"groupCollapsed"===t){const e=""+ ++g;b(t,n.length?n:["console.group"],{groupId:e,isCollapsed:"groupCollapsed"===t}),d.push(e)}else if("groupEnd"===t)d.pop();else{const e="table"===t?A(n[0],n[1]):null;b(t,e?n.slice(0,1):n,{table:e})}}function b(t,n,r,i=0){const c=""+ ++s;o[c]=n.map((e=>({...C(e,i),value:e}))),e({target:"viewer",func:"appendLog",args:[{logId:c,key:t,descriptions:o[c].map(S(["value"])),groupIds:d.slice(),...r}]})}function v(e){void 0!==e&&b("result",[e],{},"string"==typeof e?1:0)}function $(e){O(void 0!==e.error?e.error:e.message)}function x(e){O(e.reason,!0)}function j(){removeEventListener("error",$),removeEventListener("unhandledrejection",x),delete globalThis[Symbol.for(h)];for(const{key:e,original:t,wrapper:n}of m)console[e]===n&&(console[e]=t);K()}function O(t,n){const r="classic"===a&&"SyntaxError"===t?.name?/\bawait\b/.test(t.message)?"top-level await":/\bimport\b/.test(t.message)?"import statements":null:null,o=r?`\n(To use ${r}, add data-block-type="module" to the script tag.)`:"";e({target:"viewer",func:"appendError",args:[{message:(n?"Uncaught (in promise) ":"Uncaught ")+w(t?.stack??`${t?.message??t}`)+o}]})}function w(e){return`${e}`.split("\n").filter((e=>!(r&&/^\s*at\b/.test(e)&&e.includes(r)))).join("\n").replace(/(snippet-\d+\.[jt]s):(\d+):(\d+)/g,((e,t,n,r)=>{n=+n,r=+r;const o=l[t];return o&&n===o.line&&r>o.column&&(r=Math.max(o.column,r-o.shift)),[n,r]=E(u[t],n,r),`${t}:${n}:${r}`}))}function E(e,t,n){const r=e?.[t-1];let o;for(const e of r??[]){if(e[0]>n-1)break;o=e}return o?[o[1]+1,o[2]+1+(n-1-o[0])]:[t,n]}function S(e,t){if(!t)return t=>S(e,t);const n={...t};for(const t of e)delete n[t];return n}function A(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)?C(t[e],2):null)),...c?[n?C(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 N(e,t){try{const t=Object.getPrototypeOf(e)?.constructor?.name;if(t&&"string"==typeof t)return t}catch(e){}return t}addEventListener("error",$),addEventListener("unhandledrejection",x);const L=5,T=100;function C(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:N(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",D(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 M(e,t);try{return U(e,t,n)}catch(e){return[["text",n]]}}function D(e){const t=JSON.stringify(e);return e.includes("'")?t:`'${t.slice(1,-1).replace(/\\"/g,'"')}'`}function M(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 U(e,t,n){const r=N(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",D(e.data)]]:[["node",e.nodeName]];if(e instanceof Error)return[["text",t?`${e.name}: ${e.message}`:w(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,T)},((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,T);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,L),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 P(e,t=e){const n=k(e),r=[],o=[],s=[],i=[];let c=!1;if(null!==e&&("object"==typeof e||"function"==typeof e)){try{if("Map"===n){for(const[t,n]of[...e])r.push([R(t,2).map((e=>e[1])).join(""),C(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,C(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,C(i,1),s.enumerable]),o.push({value:i})}catch(e){}const a=Object.getPrototypeOf(e);null!==a&&(s.push(["[[Prototype]]",C(a,1,!0)]),i.push({value:a,receiver:t}))}return{entries:r,protoEntries:s,entriesArePropertyKeys:!c,$entries:o,$protoEntries:i}}async function I(t,r){const{blockType:o,resultRange:s,language:c,sourceMap:f,compileError:p}=Object(r),d=`snippet-${++i}.${"typescript"===c?"ts":"js"}`;if(Array.isArray(f)&&(u[d]=f),Array.isArray(s)){const[e,n]=s,r=`globalThis[Symbol.for(${JSON.stringify(h)})]((`,o=t.slice(0,e).split("\n");l[d]={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 g=`${t}\n//# sourceURL=${d}`;a="module"===o?"module":"classic";try{if(p){const{message:e,line:t,column:n}=p;O({name:"SyntaxError",message:`${e}`,stack:`SyntaxError: ${e}\n at ${d}:${+t}:${+n}`})}else if("module"===o)await import("data:text/javascript;charset=utf-8,"+encodeURIComponent(g));else if("worker"===n)J(g);else{const e=document.createElement("script");e.textContent=g,document.head.appendChild(e),e.remove()}}catch(e){O(e)}a=void 0,e({target:"viewer",func:"onCodeRan",args:[]})}function J(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 V(e){F(e,!1)}function z(e){F(e,!0)}function F(t,n){const r=B(t);if(!r)return;const o=P(r.value,"receiver"in r?r.receiver:r.value);Object.assign(r,o);const s=n?C(r.value,t.length>2?1:0,"protoEntries"===t[t.length-2]):{};e({target:"viewer",func:"updateDescriptionFor",args:[t,{...S(["$entries","$protoEntries"],o),...s}]})}function B(e){let t=o;return e.forEach(((e,n)=>{t=t?.[n&&n%2==0?"$"+e:e]})),t}function G(t,n){const r=B(t);let o;try{o=r?_(r.value):{error:"The value is no longer available."}}catch(e){o={error:`The value couldn't be converted to JSON (${e?.message??e}).`}}e({target:"viewer",func:"onValueJson",args:[{requestId:n,...o}]})}function _(e){let t=0;const n=[],r=JSON.stringify(e,(function(e,r){for(;n.length&&n[n.length-1].converted!==this;)n.pop();if("bigint"==typeof r)return`${r}`;if(null!==r&&"object"==typeof r){const e=r;if(n.some((t=>t.original===e)))return void t++;(r instanceof Map||r instanceof Set)&&(r=[...r]),n.push({original:e,converted:r})}return r}),2);return void 0===r?{error:"This value can't be represented as JSON.",circularCount:t}:{json:r,circularCount:t}}function q(t){const n=B(t);if(!n)return;let r=1;for(;`temp${r}`in globalThis;)r++;globalThis[`temp${r}`]=n.value,e({target:"viewer",func:"onStoredAsGlobal",args:[`temp${r}`]})}function K(){for(const e of Object.keys(o))delete o[e];d=[]}return{clearLogs:K,destroy:j,getValueAsJson:G,refreshDescription:z,runCode:I,sendDescriptionFor:V,storeAsGlobal:q}}
|
|
116
118
|
|
|
117
119
|
/**
|
|
118
120
|
* Runs the user's code in a Web Worker. The worker can be terminated which
|
|
@@ -236,6 +238,7 @@
|
|
|
236
238
|
function createConsole({code, dataset, height, insert}) {
|
|
237
239
|
const runnerMode = dataset.runner === 'window' ? 'window' : 'worker';
|
|
238
240
|
const blockType = dataset.blockType === 'module' ? 'module' : 'classic';
|
|
241
|
+
const language = dataset.language === 'typescript' ? 'typescript' : 'javascript';
|
|
239
242
|
const showResults = dataset.showResults !== 'false';
|
|
240
243
|
// An empty data-imports-url turns off loading packages by name.
|
|
241
244
|
const importsUrl = dataset.importsUrl == null
|
|
@@ -254,9 +257,8 @@
|
|
|
254
257
|
let popOutWatcher;
|
|
255
258
|
let activeViewer;
|
|
256
259
|
const sendToViewer = data => relayMessage(data, {viewer: activeViewer});
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
: createWorkerRunner(sendToViewer);
|
|
260
|
+
// Created once the console is loaded (see load()).
|
|
261
|
+
let runner = null;
|
|
260
262
|
|
|
261
263
|
// The theme is determined up front so that the loading screen uses it.
|
|
262
264
|
const theme = /^(light|dark)$/.test(dataset.theme)
|
|
@@ -353,8 +355,9 @@
|
|
|
353
355
|
*/
|
|
354
356
|
function createViewer(targetWindow, state) {
|
|
355
357
|
return createCallableFrame({
|
|
358
|
+
deferLoad: !targetWindow,
|
|
356
359
|
jsCode() {
|
|
357
|
-
let mountedApp;const IS_MISSING_LIBRARIES=!window.Vue||!window.ace||!window.Prism;IS_MISSING_LIBRARIES&&document.querySelector("#splash").classList.add("failed");const Prism=window.Prism;delete window.Prism,Prism?.plugins.autoloader.loadLanguages("javascript");const MIN_LOADING_TIME=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{const e=+localStorage.getItem(TEXT_SCALE_STORAGE_KEY);return TEXT_SCALES.includes(e)?e:1}catch(e){return 1}}const NARROW_WIDTH=600;function getAutoDividerOrient(){return innerWidth<NARROW_WIDTH?"horizontal":"vertical"}function init(e,t,i){if(IS_MISSING_LIBRARIES)return;const s=t.hidePrefix??"",o=matchMedia("(prefers-color-scheme: dark)"),r=unindentMin(e),{visibleCode:n,hiddenGroups:a}=extractHiddenGroups(r,s),l=/Mac|iPhone|iPad/.test(navigator.platform);mountedApp=Vue.createApp({data:()=>({displays:[],hidePrefix:s,hiddenGroups:a.map((e=>({...e}))),runnerMode:i.runnerMode,importsUrl:i.importsUrl,originalCode:r,fileName:null,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:o.matches,runCount:0,jsCode:n,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,isHistoryOpen:!1,commandHistory:[],historyIndex:null,historyDraft:null,valueMenu:null,toast:null,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},originalGroups(){return extractHiddenGroups(this.originalCode,this.hidePrefix)},exportJsCode(){return"original"===this.exportCode?this.originalCode:"blank"===this.exportCode?"":this.currentCode},currentCode(){const e=this.runHistory.slice(),t=this.hiddenGroups.slice();let i=this.runCount;const 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(){const e=this.isFullscreen||this.isMaximized;return[{iconName:"more",title:"More",className:"more-button",callback(){this.toggleMenu()}},{iconName:"clear",title:"Clear console",callback(){this.clearConsole()}},{iconName:"history",title:`History (${l?"\u2325":"Alt+"}H)`,className:"history-button",callback(){this.toggleHistory()}},{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: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)))},historyEntries(){return this.commandHistory.map(((e,t)=>{const[i]=parseJSCodeGroups(e),s=(i?.lines??e).split("\n").filter((e=>e.trim()));return{index:t,label:i?.headerLines||s[0]||"",detail:`${s.length} line${1===s.length?"":"s"}`}})).reverse()},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;const[e,...t]=parseJSCodeGroups(this.jsCode);this.runGroup(e);const i=t.map((e=>e.allLines)).join("\n");null!==this.historyIndex?(this.jsCode=[i,this.historyDraft].filter((e=>e.trim())).join("\n"),this.historyIndex=this.historyDraft=null):(this.jsCode=i,this.runCount++)},navigateHistory(e){const t=this.commandHistory;if(e<0)return!!t.length&&(null===this.historyIndex&&(this.historyDraft=this.jsCode,this.historyIndex=t.length),this.historyIndex>0&&this.showHistoryCode(this.historyIndex-1,"start"),!0);if(null===this.historyIndex)return!1;if(this.historyIndex<t.length-1)this.showHistoryCode(this.historyIndex+1,"end");else{const e=this.historyDraft;this.historyIndex=this.historyDraft=null,this.setEditorCode(e,"end")}return!0},showHistoryCode(e,t){null===this.historyIndex&&(this.historyDraft=this.jsCode),this.historyIndex=e,this.setEditorCode(this.commandHistory[e],t)},setEditorCode(e,t){this.jsCode=e,this.$nextTick((()=>{const e=this.$refs.editor?.editor;e&&("end"===t?e.navigateFileEnd():e.navigateFileStart())}))},onEditorHistoryKey(e){e.handled=this.navigateHistory(e.direction)},toggleHistory(){this.isHistoryOpen?this.isHistoryOpen=!1:(this.closeMenu(),this.closeValueMenu(),this.isHistoryOpen=!0,this.$nextTick((()=>this.$refs.historyPanel?.querySelector(".menu-item")?.focus())))},recallHistory(e){this.isHistoryOpen=!1,this.showHistoryCode(e,"start"),this.$nextTick((()=>this.$refs.editor?.editor.focus()))},stopNavigatingHistory(){this.historyIndex=this.historyDraft=null},runHiddenGroups(){const{hiddenGroups:e}=this;e.length&&e[0].runCount<=this.runCount&&this.runGroup(e.shift())},runGroup(e){const{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);const s=e.allLines.trim();!i&&s&&this.commandHistory[this.commandHistory.length-1]!==s&&(this.commandHistory.push(s),this.commandHistory.length>200&&this.commandHistory.shift());const{code:o,resultRange:r}=prepareCode(e.lines,{blockType:this.blockType,importsUrl:this.importsUrl,findResult:this.showResults&&!i});messageParent({target:"runner",func:"runCode",args:[o,{blockType:this.blockType,resultRange:r}]})},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.restart()},restart(){const{visibleCode:e,hiddenGroups:t}=this.originalGroups;this.displays=[],this.jsCode=e,this.hiddenGroups=t.map((e=>({...e}))),this.runCount=0,this.runningCount=0,this.runHistory=[],this.stopNavigatingHistory(),messageParent({target:"runner",func:"reset",args:[]}),this.runHiddenGroups()},openFile(){this.closeMenu();const{fileInput:e}=this.$refs;e.value="",e.click()},async onFileChosen(e){const t=e.target.files?.[0];if(!t)return;const i=unindentMin(await t.text());if(this.displays.length||this.jsCode.trim()){if(!await this.confirm({title:`Open ${t.name}?`,message:"The output will be cleared and the code in the editor will be replaced with the code in the file."+("window"===this.runnerMode?" Anything the code already defined on the page will stay defined.":""),confirmText:"Open"}))return}this.fileName=t.name,this.originalCode=i,this.restart()},async saveFile(){this.closeMenu();const e=this.currentCode+"\n",t=this.fileName||"js-box.js";if("function"==typeof window.showSaveFilePicker)try{const i=await showSaveFilePicker({suggestedName:t,types:[{description:"JavaScript",accept:{"text/javascript":[".js",".mjs"]}}]}),s=await i.createWritable();return await s.write(e),await s.close(),void(this.fileName=i.name)}catch(e){if("AbortError"===e?.name)return}const i=URL.createObjectURL(new Blob([e],{type:"text/javascript"}));Object.assign(document.createElement("a"),{href:i,download:t}).click(),setTimeout((()=>URL.revokeObjectURL(i)),1e3)},async copyToEditor(e){if(this.jsCode.trim()&&this.jsCode!==e){if(!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"}))return}this.stopNavigatingHistory(),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(){const e=this.exportHtml;try{await navigator.clipboard.writeText(e)}catch(t){const i=Object.assign(document.createElement("textarea"),{value:e});document.body.appendChild(i),i.select(),document.execCommand("copy"),i.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,originalCode:this.originalCode,fileName:this.fileName,commandHistory:this.commandHistory,historyIndex:this.historyIndex,historyDraft:this.historyDraft,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.isHistoryOpen=!1,this.closeValueMenu(),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){if("Escape"===e.key)e.stopPropagation(),this.closeMenu(this.isMenuOpen),this.closeValueMenu(),this.isHistoryOpen=!1;else if("ArrowDown"===e.key||"ArrowUp"===e.key){e.preventDefault();const t=[...e.currentTarget.querySelectorAll(".menu-item:not(:disabled)")],i=t.indexOf(document.activeElement),s=t[(i+("ArrowDown"===e.key?1:t.length-1))%t.length];s?.focus()}},changeTextScale(e){const t=TEXT_SCALES.indexOf(this.textScale)+e;t>=0&&t<TEXT_SCALES.length&&this.setTextScale(TEXT_SCALES[t])},setTextScale(e){this.textScale=e;try{localStorage.setItem(TEXT_SCALE_STORAGE_KEY,`${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;const 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(),this.valueMenu&&!e.target.closest(".value-menu")&&this.closeValueMenu(),this.isHistoryOpen&&!e.target.closest(".history-panel, .history-button")&&(this.isHistoryOpen=!1)},onWindowKeyDown(e){if(e.altKey&&!e.ctrlKey&&!e.metaKey&&"KeyH"===e.code)return e.preventDefault(),e.stopPropagation(),void this.toggleHistory();"Escape"===e.key&&this.valueMenu?this.closeValueMenu():"Escape"!==e.key||!this.isMaximized||this.isMenuOpen||this.dialog||this.isAboutOpen||this.setMaximized(!1)},openValueMenu(e,{path:t,keyPath:i,isPrimitive:s}){this.closeMenu(),this.valueMenu={x:e.clientX,y:e.clientY,path:t.slice(),propertyPath:i?.length?formatPropertyPath(i):null,fileName:i?.length&&/^[\w$-]+$/.test(i[i.length-1])?i[i.length-1]:"value",isPrimitive:s},this.$nextTick((()=>{const e=this.$refs.valueMenu;if(!e||!this.valueMenu)return;const{width:t,height:i}=e.getBoundingClientRect();this.valueMenu.x=Math.max(4,Math.min(this.valueMenu.x,innerWidth-t-4)),this.valueMenu.y=Math.max(4,Math.min(this.valueMenu.y,innerHeight-i-4)),e.querySelector(".menu-item")?.focus()}))},closeValueMenu(){this.valueMenu=null},requestValueJson(e){const t=`${Date.now()}-${Math.random()}`;return new Promise((i=>{jsonRequests.set(t,i),messageParent({target:"runner",func:"getValueAsJson",args:[e,t]})}))},showToast(e){clearTimeout(this.toastTimeout),this.toast={message:e},this.toastTimeout=setTimeout((()=>this.toast=null),3500)},showJsonToast({circularCount:e,error:t},i){this.showToast(t||i+(e?` (${e} circular reference${1===e?" was":"s were"} left out)`:""))},async copyValueAsJson(){const e=[...this.valueMenu.path];this.closeValueMenu();const t=this.requestValueJson(e);try{if(window.ClipboardItem&&navigator.clipboard?.write)await navigator.clipboard.write([new ClipboardItem({"text/plain":t.then((({json:e,error:t})=>{if(t)throw new Error(t);return new Blob([e],{type:"text/plain"})}))})]);else{const{json:e,error:i}=await t;if(i)throw new Error(i);await navigator.clipboard.writeText(e)}this.showJsonToast(await t,"Copied as JSON")}catch(e){const i=await t;this.showToast(i.error||"The value couldn't be copied. Your browser may not allow copying here.")}},async saveValueAsJson(){const{fileName:e}=this.valueMenu,t=[...this.valueMenu.path];this.closeValueMenu();const i=this.requestValueJson(t),s=`${e}.json`;let o;if("function"==typeof window.showSaveFilePicker)try{o=await showSaveFilePicker({suggestedName:s,types:[{description:"JSON",accept:{"application/json":[".json"]}}]})}catch(e){if("AbortError"===e?.name)return}const r=await i;if(r.error)return void this.showToast(r.error);const n=r.json+"\n";if(o){const e=await o.createWritable();await e.write(n),await e.close()}else{const e=URL.createObjectURL(new Blob([n],{type:"application/json"}));Object.assign(document.createElement("a"),{href:e,download:s}).click(),setTimeout((()=>URL.revokeObjectURL(e)),1e3)}this.showJsonToast(r,"Saved as JSON")},storeValueAsGlobal(){const e=[...this.valueMenu.path];this.closeValueMenu(),messageParent({target:"runner",func:"storeAsGlobal",args:[e]})},async copyPropertyPath(){const{propertyPath:e}=this.valueMenu;this.closeValueMenu();try{await navigator.clipboard.writeText(e),this.showToast(`Copied ${e}`)}catch(e){this.showToast("The property path couldn't be copied. Your browser may not allow copying here.")}},refreshValue(){const e=[...this.valueMenu.path];this.closeValueMenu(),messageParent({target:"runner",func:"refreshDescription",args:[e]})},closeDialog(e){const{dialog:t}=this;this.dialog=null,t?.resolve(e)},setDividerOrient(e){this.isDividerOrientAuto=!1,this.dividerOrient=e},onWindowResize(){this.isDividerOrientAuto&&(this.dividerOrient=getAutoDividerOrient())},onDisplaysScroll(){this.closeValueMenu();const{scrollTop:e,scrollHeight:t,clientHeight:i}=this.$refs.displaysScroller;this.isDisplaysScrolledToBottom=t-e-i<8},getEditorPct(e){const t=this.$refs.main.getBoundingClientRect(),{dividerOrient:i}=this,s=e.pageX-t.left,o=e.pageY-t.top,r=t.width,n=t.height;return 100-100*Math.min(Math.max(.2,"vertical"===i?s/r:o/n),.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((()=>{const e=this.$refs.displaysScroller;e.scrollTop=e.scrollHeight}))}},mounted(){addEventListener("mousemove",this.onWindowMouseMove),addEventListener("mousedown",this.onWindowMouseDown),addEventListener("keydown",this.onWindowKeyDown,!0),addEventListener("resize",this.onWindowResize),addEventListener("mouseup",this.onWindowMouseUp),addEventListener("error",this.onWindowError),o.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",(()=>{const t=JSON.stringify(this.errorNotes),i=JSON.stringify(this.infoNotes),s=JSON.stringify(this.warningNotes);this.annotations=e.getSession().getAnnotations();const{errorNotes:o,infoNotes:r,warningNotes:n}=this;t!==JSON.stringify(o)&&this.$emit("changeErrorNotes",o),i!==JSON.stringify(r)&&this.$emit("changeInfoNotes",r),s!==JSON.stringify(n)&&this.$emit("changeWarningNotes",n)})),this.$refs.editor.addEventListener("keydown",(t=>{const i="ArrowUp"===t.key;if(!i&&"ArrowDown"!==t.key)return;if(t.shiftKey||t.altKey||t.ctrlKey||t.metaKey||!e.selection.isEmpty())return;const{row:s,column:o}=e.getCursorPosition(),r=e.session.getLength()-1;if(!(i?0===s&&0===o:s===r&&o===e.session.getLine(r).length))return;const n={direction:i?-1:1,handled:!1};this.$emit("historyKey",n),n.handled&&(t.preventDefault(),t.stopPropagation())}),!0),e.textInput.getElement().addEventListener("keydown",(e=>{if(16===e.keyCode||17===e.keyCode||18===e.keyCode||91===e.keyCode||92===e.keyCode||93===e.keyCode)return;(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey&&(e.key??"").length>1)&&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"])if(null!=this[t]){const 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(){const 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 15 15"><path fill="currentColor" fill-rule="evenodd" d="M3.242 2.322a.5.5 0 0 1 .491-.014l9 4.75a.5.5 0 0 1 0 .884l-9 4.75A.5.5 0 0 1 3 12.25v-9.5a.5.5 0 0 1 .242-.428M4 3.579v7.842L11.429 7.5z" clip-rule="evenodd"/></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>',play:'<svg viewBox="0 0 16 16"><path fill="currentColor" d="M2 1v14l12-7z"/></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>',history:'<svg viewBox="0 0 16 16"><path d="M2.5 8a5.5 5.5 0 1 0 1.6-3.9" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M2.25 2.5v2.75H5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M8 5v3.25l2.25 1.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',copy:'<svg viewBox="0 0 16 16"><rect x="5.5" y="5.5" width="8" height="8" rx="1.25" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M10.5 3.5v-.75A1.25 1.25 0 0 0 9.25 1.5h-5A1.25 1.25 0 0 0 3 2.75v5A1.25 1.25 0 0 0 4.25 9h.75" fill="none" stroke="currentColor" stroke-width="1.4"/></svg>',variable:'<svg viewBox="0 0 16 16"><path d="M5 2.5c-1.5 1.5-2 3.5-2 5.5s.5 4 2 5.5M11 2.5c1.5 1.5 2 3.5 2 5.5s-.5 4-2 5.5M6.5 6l3 4M9.5 6l-3 4" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>',path:'<svg viewBox="0 0 16 16"><circle cx="3.5" cy="12.5" r="1.5" fill="currentColor"/><circle cx="12.5" cy="3.5" r="1.5" fill="currentColor"/><path d="M3.5 11V8a2 2 0 0 1 2-2h5a2 2 0 0 0 2-2" fill="none" stroke="currentColor" stroke-width="1.4"/></svg>',open:'<svg viewBox="0 0 16 16"><path d="M2 4.5a1 1 0 0 1 1-1h3.2l1.3 1.5H13a1 1 0 0 1 1 1V12a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1z" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"/></svg>',save:'<svg viewBox="0 0 16 16"><path d="M8 2.5v7M5 7l3 3 3-3M3 11.5v1.5h10v-1.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></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","keyPath"],data:()=>({isExpanded:!1,hasBeenExpanded:!1}),watch:{isExpanded(e){e&&!this.hasBeenExpanded&&(this.hasBeenExpanded=e)},isPartialDescription(e){e&&this.isExpanded&&this.requestDescription()}},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(){const{keyPath:e,description:t}=this;return[{key:"entries",isDim:e=>!1===e[2],getKeyPath:i=>e&&t.entriesArePropertyKeys?e.concat([i[0]]):null},{key:"protoEntries",isDim:()=>!0,getKeyPath:()=>e}]}},methods:{toggleExpanded(){this.isExpandable&&(this.isExpanded=!this.isExpanded,this.isExpanded&&this.isPartialDescription&&this.requestDescription())},requestDescription(){messageParent({target:"runner",func:"sendDescriptionFor",args:[this.path]})},openMenu(e){this.$root.openValueMenu(e,{path:this.path,keyPath:this.keyPath,isPrimitive:this.description.isPrimitive})}},template:'\n <div :class="classNames">\n <div :class="[\'js-value-header\', isExpandable ? \'expandable\' : \'\']" @click="toggleExpanded" @contextmenu.prevent.stop="openMenu"><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…</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 :key-path="group.getKeyPath(entry)"\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)=>{const i=e[e.length-1],s=/^\/\/[^]*\\\\$/.test(t),o=s?t.replace(/^\/+\s*|\s*\\+$/g,""):t;return!e.length||s&&!i.canAppendHeader?e.push({headerLines:s?[o]:[],lines:s?[]:[t],allLines:[t],canAppendHeader:s}):s?(i.headerLines.push(o),i.allLines.push(t)):(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){const i=!!t&&e.startsWith(t);return{header:i?e.slice(t.length).replace(/^\s*:?\s*/,""):e,isHidden:i}}function extractHiddenGroups(e,t){const i=[],s=[];for(const o of parseJSCodeGroups(e))parseGroupHeader(o.headerLines,t).isHidden?s.push({...o,runCount:i.length}):i.push(o);return{visibleCode:i.map((e=>e.allLines)).join("\n"),hiddenGroups:s}}function prepareCode(e,{blockType:t,importsUrl:i,findResult:s}){if(!window.acorn)return{code:e,resultRange:null};let o;try{o=acorn.parse(e,{ecmaVersion:"latest",sourceType:"module"===t?"module":"script",allowHashBang:!0})}catch(t){return{code:e,resultRange:null}}let r=null;if(s){const e=o.body[o.body.length-1];"ExpressionStatement"!==e?.type||e.directive||(r=[e.expression.start,e.expression.end])}const n=[];i&&walkAst(o,(e=>{const{source:t}=/^(Import(Declaration|Expression)|Export(All|Named)Declaration)$/.test(e.type)?e:{};"Literal"===t?.type&&"string"==typeof t.value&&isBareSpecifier(t.value)&&n.push({start:t.start,end:t.end,text:JSON.stringify(i.replace(/\{specifier\}/g,t.value))})})),n.sort(((e,t)=>t.start-e.start));for(const{start:t,end:i,text:s}of n){e=e.slice(0,t)+s+e.slice(i);const o=s.length-(i-t);r&&(r=r.map((e=>e>=i?e+o:e)))}return{code:e,resultRange:r}}function formatPropertyPath(e){return e.map(((e,t)=>/^(0|[1-9]\d*)$/.test(e)?`[${e}]`:/^[A-Za-z_$][\w$]*$/.test(e)?(t?".":"")+e:`[${JSON.stringify(e)}]`)).join("")}function isBareSpecifier(e){return!/^(\.{0,2}\/|#|[a-z][a-z\d+.-]*:)/i.test(e)}function walkAst(e,t){if(Array.isArray(e))for(const i of e)walkAst(i,t);else if(e&&"string"==typeof e.type){t(e);for(const i of Object.keys(e)){const s=e[i];s&&"object"==typeof s&&walkAst(s,t)}}}function joinCodeBlocks(e){return e.map((e=>e.replace(/^(\s*[\r\n])+|\s+$/g,""))).filter(Boolean).map(((e,t)=>{const i=e.split(/\r\n|\r|\n/)[0];return t&&!/^\/\/[^]*\\\\$/.test(i)?`// \\\\\n${e}`:e})).join("\n\n")}function buildConsoleHtml({code:e,dataset:t,packageInfo:i,isFullPage:s}){const{name:o,version:r}=i,n=`https://cdn.jsdelivr.net/npm/${o}@${r.split(".")[0]}/dist/${o}.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="${n}"${a}>`,...d.split("\n").map((e=>e.trim()?" "+e:"")),"<\/script>"]:[`<script src="${n}"${a}><\/script>`]).map((e=>e?l+e: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;">\n${c}\n</div>\n`}function escapeHtmlAttribute(e){return`${e}`.replace(/[&"<>]/g,(e=>`&#${e.charCodeAt(0)};`))}function unindentMin(e,t){const i=(t=Object(t)).tabSize??4,s=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 s?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),...null!=e.entriesArePropertyKeys?{entriesArePropertyKeys:!!e.entriesArePropertyKeys}:{}}}function sanitizeEntries(e){e=Object(e);const 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:o,groupId:r,isCollapsed:n,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(o??[],(e=>`${e}`)),groupId:null!=r?`${r}`:null,isCollapsed:!!n,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 o=s?.descriptions[toIndex(e.shift())];for(let t=0;o&&t<e.length;t+=2){const i=e[t];if("entries"!==i&&"protoEntries"!==i)return;o=o[i]?.[toIndex(e[t+1])]?.[1]}if(o&&(Object.assign(o,sanitizeEntries(t)),o.entriesArePropertyKeys=!!Object(t).entriesArePropertyKeys,Array.isArray(Object(t).parts))){const{typeName:e,isPrimitive:i,parts:s}=sanitizeDescription(t);Object.assign(o,{typeName:e,isPrimitive:i,parts:s})}}function onValueJson(e){const{requestId:t,json:i,circularCount:s,error:o}=Object(e),r=jsonRequests.get(`${t}`);r&&(jsonRequests.delete(`${t}`),r({json:null!=i?`${i}`:null,circularCount:+s||0,error:null!=o?`${o}`:null}))}const jsonRequests=new Map;function onStoredAsGlobal(e){mountedApp.displays.push({type:"notice",message:`Stored as the global variable ${e}`})}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)&&e>=0?e:void 0}
|
|
360
|
+
let mountedApp;const IS_MISSING_LIBRARIES=!window.Vue||!window.ace||!window.Prism;IS_MISSING_LIBRARIES&&document.querySelector("#splash").classList.add("failed");const Prism=window.Prism;delete window.Prism,Prism?.plugins.autoloader.loadLanguages("javascript");const MIN_LOADING_TIME=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{const e=+localStorage.getItem(TEXT_SCALE_STORAGE_KEY);return TEXT_SCALES.includes(e)?e:1}catch(e){return 1}}const NARROW_WIDTH=600;function getAutoDividerOrient(){return innerWidth<NARROW_WIDTH?"horizontal":"vertical"}function init(e,t,i){if(IS_MISSING_LIBRARIES)return;if("typescript"===i.language&&!window.Babel)return void document.querySelector("#splash").classList.add("failed");Prism.plugins.autoloader.loadLanguages(i.language);const s=t.hidePrefix??"",o=matchMedia("(prefers-color-scheme: dark)"),r=unindentMin(e),{visibleCode:n,hiddenGroups:a}=extractHiddenGroups(r,s),l=/Mac|iPhone|iPad/.test(navigator.platform);mountedApp=Vue.createApp({data:()=>({displays:[],hidePrefix:s,hiddenGroups:a.map((e=>({...e}))),runnerMode:i.runnerMode,importsUrl:i.importsUrl,originalCode:r,fileName:null,blockType:i.blockType,language:i.language,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:o.matches,runCount:0,jsCode:n,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,isHistoryOpen:!1,commandHistory:[],historyIndex:null,historyDraft:null,valueMenu:null,toast:null,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"})`},isTypeScript(){return"typescript"===this.language},builtWith(){const e=this.libraryVersions,t=[`Vue ${e.vue}`,`Ace ${e["ace-builds"]}`,`Prism ${e.prismjs}`,`Acorn ${e.acorn}`,...this.isTypeScript?[`Babel ${e["@babel/standalone"]}`]:[]];return t.slice(0,-1).join(", ")+" and "+t[t.length-1]},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},originalGroups(){return extractHiddenGroups(this.originalCode,this.hidePrefix)},exportJsCode(){return"original"===this.exportCode?this.originalCode:"blank"===this.exportCode?"":this.currentCode},currentCode(){const e=this.runHistory.slice(),t=this.hiddenGroups.slice();let i=this.runCount;const 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(){const e=this.isFullscreen||this.isMaximized;return[{iconName:"more",title:"More",className:"more-button",callback(){this.toggleMenu()}},{iconName:"clear",title:"Clear console",callback(){this.clearConsole()}},{iconName:"history",title:`History (${l?"\u2325":"Alt+"}H)`,className:"history-button",callback(){this.toggleHistory()}},{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: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)))},historyEntries(){return this.commandHistory.map(((e,t)=>{const[i]=parseJSCodeGroups(e),s=(i?.lines??e).split("\n").filter((e=>e.trim()));return{index:t,label:i?.headerLines||s[0]||"",detail:`${s.length} line${1===s.length?"":"s"}`}})).reverse()},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;const[e,...t]=parseJSCodeGroups(this.jsCode);this.runGroup(e);const i=t.map((e=>e.allLines)).join("\n");null!==this.historyIndex?(this.jsCode=[i,this.historyDraft].filter((e=>e.trim())).join("\n"),this.historyIndex=this.historyDraft=null):(this.jsCode=i,this.runCount++)},navigateHistory(e){const t=this.commandHistory;if(e<0)return!!t.length&&(null===this.historyIndex&&(this.historyDraft=this.jsCode,this.historyIndex=t.length),this.historyIndex>0&&this.showHistoryCode(this.historyIndex-1,"start"),!0);if(null===this.historyIndex)return!1;if(this.historyIndex<t.length-1)this.showHistoryCode(this.historyIndex+1,"end");else{const e=this.historyDraft;this.historyIndex=this.historyDraft=null,this.setEditorCode(e,"end")}return!0},showHistoryCode(e,t){null===this.historyIndex&&(this.historyDraft=this.jsCode),this.historyIndex=e,this.setEditorCode(this.commandHistory[e],t)},setEditorCode(e,t){this.jsCode=e,this.$nextTick((()=>{const e=this.$refs.editor?.editor;e&&("end"===t?e.navigateFileEnd():e.navigateFileStart())}))},onEditorHistoryKey(e){e.handled=this.navigateHistory(e.direction)},toggleHistory(){this.isHistoryOpen?this.isHistoryOpen=!1:(this.closeMenu(),this.closeValueMenu(),this.isHistoryOpen=!0,this.$nextTick((()=>this.$refs.historyPanel?.querySelector(".menu-item")?.focus())))},recallHistory(e){this.isHistoryOpen=!1,this.showHistoryCode(e,"start"),this.$nextTick((()=>this.$refs.editor?.editor.focus()))},stopNavigatingHistory(){this.historyIndex=this.historyDraft=null},runHiddenGroups(){const{hiddenGroups:e}=this;e.length&&e[0].runCount<=this.runCount&&this.runGroup(e.shift())},runGroup(e){const{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);const s=e.allLines.trim();!i&&s&&this.commandHistory[this.commandHistory.length-1]!==s&&(this.commandHistory.push(s),this.commandHistory.length>200&&this.commandHistory.shift());const{language:o,blockType:r}=this,n="typescript"===o?compileTypeScript(e.lines,{blockType:r}):{code:e.lines},{code:a,resultRange:l}=n.error?{code:"",resultRange:null}:prepareCode(n.code,{blockType:r,importsUrl:this.importsUrl,findResult:this.showResults&&!i});messageParent({target:"runner",func:"runCode",args:[a,{blockType:r,resultRange:l,language:o,sourceMap:n.sourceMap,compileError:n.error}]})},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.restart()},restart(){const{visibleCode:e,hiddenGroups:t}=this.originalGroups;this.displays=[],this.jsCode=e,this.hiddenGroups=t.map((e=>({...e}))),this.runCount=0,this.runningCount=0,this.runHistory=[],this.stopNavigatingHistory(),messageParent({target:"runner",func:"reset",args:[]}),this.runHiddenGroups()},openFile(){this.closeMenu();const{fileInput:e}=this.$refs;e.value="",e.click()},async onFileChosen(e){const t=e.target.files?.[0];if(!t)return;const i=unindentMin(await t.text());if(this.displays.length||this.jsCode.trim()){if(!await this.confirm({title:`Open ${t.name}?`,message:"The output will be cleared and the code in the editor will be replaced with the code in the file."+("window"===this.runnerMode?" Anything the code already defined on the page will stay defined.":""),confirmText:"Open"}))return}this.fileName=t.name,this.originalCode=i,this.restart()},async saveFile(){this.closeMenu();const e=this.currentCode+"\n",t=this.fileName||(this.isTypeScript?"js-box.ts":"js-box.js"),i=this.isTypeScript?{description:"TypeScript",accept:{"text/typescript":[".ts",".mts"]}}:{description:"JavaScript",accept:{"text/javascript":[".js",".mjs"]}};if("function"==typeof window.showSaveFilePicker)try{const s=await showSaveFilePicker({suggestedName:t,types:[i]}),o=await s.createWritable();return await o.write(e),await o.close(),void(this.fileName=s.name)}catch(e){if("AbortError"===e?.name)return}const s=URL.createObjectURL(new Blob([e],{type:Object.keys(i.accept)[0]}));Object.assign(document.createElement("a"),{href:s,download:t}).click(),setTimeout((()=>URL.revokeObjectURL(s)),1e3)},async copyToEditor(e){if(this.jsCode.trim()&&this.jsCode!==e){if(!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"}))return}this.stopNavigatingHistory(),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(){const e=this.exportHtml;try{await navigator.clipboard.writeText(e)}catch(t){const i=Object.assign(document.createElement("textarea"),{value:e});document.body.appendChild(i),i.select(),document.execCommand("copy"),i.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,originalCode:this.originalCode,fileName:this.fileName,commandHistory:this.commandHistory,historyIndex:this.historyIndex,historyDraft:this.historyDraft,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.isHistoryOpen=!1,this.closeValueMenu(),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){if("Escape"===e.key)e.stopPropagation(),this.closeMenu(this.isMenuOpen),this.closeValueMenu(),this.isHistoryOpen=!1;else if("ArrowDown"===e.key||"ArrowUp"===e.key){e.preventDefault();const t=[...e.currentTarget.querySelectorAll(".menu-item:not(:disabled)")],i=t.indexOf(document.activeElement),s=t[(i+("ArrowDown"===e.key?1:t.length-1))%t.length];s?.focus()}},changeTextScale(e){const t=TEXT_SCALES.indexOf(this.textScale)+e;t>=0&&t<TEXT_SCALES.length&&this.setTextScale(TEXT_SCALES[t])},setTextScale(e){this.textScale=e;try{localStorage.setItem(TEXT_SCALE_STORAGE_KEY,`${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;const 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(),this.valueMenu&&!e.target.closest(".value-menu")&&this.closeValueMenu(),this.isHistoryOpen&&!e.target.closest(".history-panel, .history-button")&&(this.isHistoryOpen=!1)},onWindowKeyDown(e){if(e.altKey&&!e.ctrlKey&&!e.metaKey&&"KeyH"===e.code)return e.preventDefault(),e.stopPropagation(),void this.toggleHistory();"Escape"===e.key&&this.valueMenu?this.closeValueMenu():"Escape"!==e.key||!this.isMaximized||this.isMenuOpen||this.dialog||this.isAboutOpen||this.setMaximized(!1)},openValueMenu(e,{path:t,keyPath:i,isPrimitive:s}){this.closeMenu(),this.valueMenu={x:e.clientX,y:e.clientY,path:t.slice(),propertyPath:i?.length?formatPropertyPath(i):null,fileName:i?.length&&/^[\w$-]+$/.test(i[i.length-1])?i[i.length-1]:"value",isPrimitive:s},this.$nextTick((()=>{const e=this.$refs.valueMenu;if(!e||!this.valueMenu)return;const{width:t,height:i}=e.getBoundingClientRect();this.valueMenu.x=Math.max(4,Math.min(this.valueMenu.x,innerWidth-t-4)),this.valueMenu.y=Math.max(4,Math.min(this.valueMenu.y,innerHeight-i-4)),e.querySelector(".menu-item")?.focus()}))},closeValueMenu(){this.valueMenu=null},requestValueJson(e){const t=`${Date.now()}-${Math.random()}`;return new Promise((i=>{jsonRequests.set(t,i),messageParent({target:"runner",func:"getValueAsJson",args:[e,t]})}))},showToast(e){clearTimeout(this.toastTimeout),this.toast={message:e},this.toastTimeout=setTimeout((()=>this.toast=null),3500)},showJsonToast({circularCount:e,error:t},i){this.showToast(t||i+(e?` (${e} circular reference${1===e?" was":"s were"} left out)`:""))},async copyValueAsJson(){const e=[...this.valueMenu.path];this.closeValueMenu();const t=this.requestValueJson(e);try{if(window.ClipboardItem&&navigator.clipboard?.write)await navigator.clipboard.write([new ClipboardItem({"text/plain":t.then((({json:e,error:t})=>{if(t)throw new Error(t);return new Blob([e],{type:"text/plain"})}))})]);else{const{json:e,error:i}=await t;if(i)throw new Error(i);await navigator.clipboard.writeText(e)}this.showJsonToast(await t,"Copied as JSON")}catch(e){const i=await t;this.showToast(i.error||"The value couldn't be copied. Your browser may not allow copying here.")}},async saveValueAsJson(){const{fileName:e}=this.valueMenu,t=[...this.valueMenu.path];this.closeValueMenu();const i=this.requestValueJson(t),s=`${e}.json`;let o;if("function"==typeof window.showSaveFilePicker)try{o=await showSaveFilePicker({suggestedName:s,types:[{description:"JSON",accept:{"application/json":[".json"]}}]})}catch(e){if("AbortError"===e?.name)return}const r=await i;if(r.error)return void this.showToast(r.error);const n=r.json+"\n";if(o){const e=await o.createWritable();await e.write(n),await e.close()}else{const e=URL.createObjectURL(new Blob([n],{type:"application/json"}));Object.assign(document.createElement("a"),{href:e,download:s}).click(),setTimeout((()=>URL.revokeObjectURL(e)),1e3)}this.showJsonToast(r,"Saved as JSON")},storeValueAsGlobal(){const e=[...this.valueMenu.path];this.closeValueMenu(),messageParent({target:"runner",func:"storeAsGlobal",args:[e]})},async copyPropertyPath(){const{propertyPath:e}=this.valueMenu;this.closeValueMenu();try{await navigator.clipboard.writeText(e),this.showToast(`Copied ${e}`)}catch(e){this.showToast("The property path couldn't be copied. Your browser may not allow copying here.")}},refreshValue(){const e=[...this.valueMenu.path];this.closeValueMenu(),messageParent({target:"runner",func:"refreshDescription",args:[e]})},closeDialog(e){const{dialog:t}=this;this.dialog=null,t?.resolve(e)},setDividerOrient(e){this.isDividerOrientAuto=!1,this.dividerOrient=e},onWindowResize(){this.isDividerOrientAuto&&(this.dividerOrient=getAutoDividerOrient())},onDisplaysScroll(){this.closeValueMenu();const{scrollTop:e,scrollHeight:t,clientHeight:i}=this.$refs.displaysScroller;this.isDisplaysScrolledToBottom=t-e-i<8},getEditorPct(e){const t=this.$refs.main.getBoundingClientRect(),{dividerOrient:i}=this,s=e.pageX-t.left,o=e.pageY-t.top,r=t.width,n=t.height;return 100-100*Math.min(Math.max(.2,"vertical"===i?s/r:o/n),.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((()=>{const e=this.$refs.displaysScroller;e.scrollTop=e.scrollHeight}))}},mounted(){addEventListener("mousemove",this.onWindowMouseMove),addEventListener("mousedown",this.onWindowMouseDown),addEventListener("keydown",this.onWindowKeyDown,!0),addEventListener("resize",this.onWindowResize),addEventListener("mouseup",this.onWindowMouseUp),addEventListener("error",this.onWindowError),o.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",(()=>{const t=JSON.stringify(this.errorNotes),i=JSON.stringify(this.infoNotes),s=JSON.stringify(this.warningNotes);this.annotations=e.getSession().getAnnotations();const{errorNotes:o,infoNotes:r,warningNotes:n}=this;t!==JSON.stringify(o)&&this.$emit("changeErrorNotes",o),i!==JSON.stringify(r)&&this.$emit("changeInfoNotes",r),s!==JSON.stringify(n)&&this.$emit("changeWarningNotes",n)})),this.$refs.editor.addEventListener("keydown",(t=>{const i="ArrowUp"===t.key;if(!i&&"ArrowDown"!==t.key)return;if(t.shiftKey||t.altKey||t.ctrlKey||t.metaKey||!e.selection.isEmpty())return;const{row:s,column:o}=e.getCursorPosition(),r=e.session.getLength()-1;if(!(i?0===s&&0===o:s===r&&o===e.session.getLine(r).length))return;const n={direction:i?-1:1,handled:!1};this.$emit("historyKey",n),n.handled&&(t.preventDefault(),t.stopPropagation())}),!0),e.textInput.getElement().addEventListener("keydown",(e=>{if(16===e.keyCode||17===e.keyCode||18===e.keyCode||91===e.keyCode||92===e.keyCode||93===e.keyCode)return;(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey&&(e.key??"").length>1)&&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-${this.language??"javascript"}`,e.className="";for(const t of["lineNumbers","matchBraces"])if(null!=this[t]){const 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(){const 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 15 15"><path fill="currentColor" fill-rule="evenodd" d="M3.242 2.322a.5.5 0 0 1 .491-.014l9 4.75a.5.5 0 0 1 0 .884l-9 4.75A.5.5 0 0 1 3 12.25v-9.5a.5.5 0 0 1 .242-.428M4 3.579v7.842L11.429 7.5z" clip-rule="evenodd"/></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>',play:'<svg viewBox="0 0 16 16"><path fill="currentColor" d="M2 1v14l12-7z"/></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>',history:'<svg viewBox="0 0 16 16"><path d="M2.5 8a5.5 5.5 0 1 0 1.6-3.9" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M2.25 2.5v2.75H5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M8 5v3.25l2.25 1.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',copy:'<svg viewBox="0 0 16 16"><rect x="5.5" y="5.5" width="8" height="8" rx="1.25" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M10.5 3.5v-.75A1.25 1.25 0 0 0 9.25 1.5h-5A1.25 1.25 0 0 0 3 2.75v5A1.25 1.25 0 0 0 4.25 9h.75" fill="none" stroke="currentColor" stroke-width="1.4"/></svg>',variable:'<svg viewBox="0 0 16 16"><path d="M5 2.5c-1.5 1.5-2 3.5-2 5.5s.5 4 2 5.5M11 2.5c1.5 1.5 2 3.5 2 5.5s-.5 4-2 5.5M6.5 6l3 4M9.5 6l-3 4" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>',path:'<svg viewBox="0 0 16 16"><circle cx="3.5" cy="12.5" r="1.5" fill="currentColor"/><circle cx="12.5" cy="3.5" r="1.5" fill="currentColor"/><path d="M3.5 11V8a2 2 0 0 1 2-2h5a2 2 0 0 0 2-2" fill="none" stroke="currentColor" stroke-width="1.4"/></svg>',open:'<svg viewBox="0 0 16 16"><path d="M2 4.5a1 1 0 0 1 1-1h3.2l1.3 1.5H13a1 1 0 0 1 1 1V12a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1z" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"/></svg>',save:'<svg viewBox="0 0 16 16"><path d="M8 2.5v7M5 7l3 3 3-3M3 11.5v1.5h10v-1.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></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","keyPath"],data:()=>({isExpanded:!1,hasBeenExpanded:!1}),watch:{isExpanded(e){e&&!this.hasBeenExpanded&&(this.hasBeenExpanded=e)},isPartialDescription(e){e&&this.isExpanded&&this.requestDescription()}},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(){const{keyPath:e,description:t}=this;return[{key:"entries",isDim:e=>!1===e[2],getKeyPath:i=>e&&t.entriesArePropertyKeys?e.concat([i[0]]):null},{key:"protoEntries",isDim:()=>!0,getKeyPath:()=>e}]}},methods:{toggleExpanded(){this.isExpandable&&(this.isExpanded=!this.isExpanded,this.isExpanded&&this.isPartialDescription&&this.requestDescription())},requestDescription(){messageParent({target:"runner",func:"sendDescriptionFor",args:[this.path]})},openMenu(e){this.$root.openValueMenu(e,{path:this.path,keyPath:this.keyPath,isPrimitive:this.description.isPrimitive})}},template:'\n <div :class="classNames">\n <div :class="[\'js-value-header\', isExpandable ? \'expandable\' : \'\']" @click="toggleExpanded" @contextmenu.prevent.stop="openMenu"><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…</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 :key-path="group.getKeyPath(entry)"\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)=>{const i=e[e.length-1],s=/^\/\/[^]*\\\\$/.test(t),o=s?t.replace(/^\/+\s*|\s*\\+$/g,""):t;return!e.length||s&&!i.canAppendHeader?e.push({headerLines:s?[o]:[],lines:s?[]:[t],allLines:[t],canAppendHeader:s}):s?(i.headerLines.push(o),i.allLines.push(t)):(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){const i=!!t&&e.startsWith(t);return{header:i?e.slice(t.length).replace(/^\s*:?\s*/,""):e,isHidden:i}}function extractHiddenGroups(e,t){const i=[],s=[];for(const o of parseJSCodeGroups(e))parseGroupHeader(o.headerLines,t).isHidden?s.push({...o,runCount:i.length}):i.push(o);return{visibleCode:i.map((e=>e.allLines)).join("\n"),hiddenGroups:s}}function compileTypeScript(e,{blockType:t}){try{const i=Babel.transform(e,{filename:"snippet.ts",presets:[["typescript",{allExtensions:!0,onlyRemoveTypeImports:!0}]],sourceType:"module"===t?"module":"script",parserOpts:{allowImportExportEverywhere:"module"!==t},retainLines:!0,sourceMaps:!0});return{code:i.code,sourceMap:decodeSourceMap(i.map.mappings)}}catch(t){if("SyntaxError"!==t?.name||!t.loc)throw t;return{code:e,error:{message:`${t.message}`.split("\n")[0].replace(/^\/?snippet\.ts:\s*/,"").replace(/\s*\(\d+:\d+\)$/,""),line:t.loc.line,column:t.loc.column+1}}}}function decodeSourceMap(e){const t=[0,0,0,0,0];return e.split(";").map((e=>{t[0]=0;const i=[];for(const s of e.split(",")){if(!s)continue;const e=[];let o=0,r=0;for(const t of s){const i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(t);o+=(31&i)<<r,32&i?r+=5:(e.push(1&o?-(o>>>1):o>>>1),o=r=0)}e.forEach(((e,i)=>t[i]+=e)),e.length>=4&&i.push([t[0],t[2],t[3]])}return i.sort(((e,t)=>e[0]-t[0]))}))}function prepareCode(e,{blockType:t,importsUrl:i,findResult:s}){if(!window.acorn)return{code:e,resultRange:null};let o;try{o=acorn.parse(e,{ecmaVersion:"latest",sourceType:"module"===t?"module":"script",allowHashBang:!0})}catch(t){return{code:e,resultRange:null}}let r=null;if(s){const e=o.body[o.body.length-1];"ExpressionStatement"!==e?.type||e.directive||(r=[e.expression.start,e.expression.end])}const n=[];i&&walkAst(o,(e=>{const{source:t}=/^(Import(Declaration|Expression)|Export(All|Named)Declaration)$/.test(e.type)?e:{};"Literal"===t?.type&&"string"==typeof t.value&&isBareSpecifier(t.value)&&n.push({start:t.start,end:t.end,text:JSON.stringify(i.replace(/\{specifier\}/g,t.value))})})),n.sort(((e,t)=>t.start-e.start));for(const{start:t,end:i,text:s}of n){e=e.slice(0,t)+s+e.slice(i);const o=s.length-(i-t);r&&(r=r.map((e=>e>=i?e+o:e)))}return{code:e,resultRange:r}}function formatPropertyPath(e){return e.map(((e,t)=>/^(0|[1-9]\d*)$/.test(e)?`[${e}]`:/^[A-Za-z_$][\w$]*$/.test(e)?(t?".":"")+e:`[${JSON.stringify(e)}]`)).join("")}function isBareSpecifier(e){return!/^(\.{0,2}\/|#|[a-z][a-z\d+.-]*:)/i.test(e)}function walkAst(e,t){if(Array.isArray(e))for(const i of e)walkAst(i,t);else if(e&&"string"==typeof e.type){t(e);for(const i of Object.keys(e)){const s=e[i];s&&"object"==typeof s&&walkAst(s,t)}}}function joinCodeBlocks(e){return e.map((e=>e.replace(/^(\s*[\r\n])+|\s+$/g,""))).filter(Boolean).map(((e,t)=>{const i=e.split(/\r\n|\r|\n/)[0];return t&&!/^\/\/[^]*\\\\$/.test(i)?`// \\\\\n${e}`:e})).join("\n\n")}function buildConsoleHtml({code:e,dataset:t,packageInfo:i,isFullPage:s}){const{name:o,version:r}=i,n=`https://cdn.jsdelivr.net/npm/${o}@${r.split(".")[0]}/dist/${o}.min.js`,a=Object.entries(t).map((([e,t])=>` data-${e.replace(/[A-Z]/g,(e=>"-"+e.toLowerCase()))}="${escapeHtmlAttribute(t)}"`)).join(""),l=s?" ":" ",c=e.replace(/<\/(script)/gi,"<\\/$1").replace(/<!--/g,"<\\!--"),d=(c.trim()?[`<script src="${n}"${a}>`,...c.split("\n").map((e=>e.trim()?" "+e:"")),"<\/script>"]:[`<script src="${n}"${a}><\/script>`]).map((e=>e?l+e: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>",d," </body>","</html>",""].join("\n"):`<div style="height: 400px;">\n${d}\n</div>\n`}function escapeHtmlAttribute(e){return`${e}`.replace(/[&"<>]/g,(e=>`&#${e.charCodeAt(0)};`))}function unindentMin(e,t){const i=(t=Object(t)).tabSize??4,s=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 s?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),...null!=e.entriesArePropertyKeys?{entriesArePropertyKeys:!!e.entriesArePropertyKeys}:{}}}function sanitizeEntries(e){e=Object(e);const 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:o,groupId:r,isCollapsed:n,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(o??[],(e=>`${e}`)),groupId:null!=r?`${r}`:null,isCollapsed:!!n,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 o=s?.descriptions[toIndex(e.shift())];for(let t=0;o&&t<e.length;t+=2){const i=e[t];if("entries"!==i&&"protoEntries"!==i)return;o=o[i]?.[toIndex(e[t+1])]?.[1]}if(o&&(Object.assign(o,sanitizeEntries(t)),o.entriesArePropertyKeys=!!Object(t).entriesArePropertyKeys,Array.isArray(Object(t).parts))){const{typeName:e,isPrimitive:i,parts:s}=sanitizeDescription(t);Object.assign(o,{typeName:e,isPrimitive:i,parts:s})}}function onValueJson(e){const{requestId:t,json:i,circularCount:s,error:o}=Object(e),r=jsonRequests.get(`${t}`);r&&(jsonRequests.delete(`${t}`),r({json:null!=i?`${i}`:null,circularCount:+s||0,error:null!=o?`${o}`:null}))}const jsonRequests=new Map;function onStoredAsGlobal(e){mountedApp.displays.push({type:"notice",message:`Stored as the global variable ${e}`})}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)&&e>=0?e:void 0}
|
|
358
361
|
},
|
|
359
362
|
// Exact versions are used so that a new release of a library can never
|
|
360
363
|
// change how an existing version of this console works. Ace and Prism
|
|
@@ -368,6 +371,8 @@
|
|
|
368
371
|
// Used to find the last expression in each block of code (so that its
|
|
369
372
|
// value can be shown) and the packages that it imports.
|
|
370
373
|
libraryUrl('acorn', 'dist/acorn.js'),
|
|
374
|
+
// Removes the types from TypeScript code before it is run.
|
|
375
|
+
...language === 'typescript' ? [libraryUrl('@babel/standalone', 'babel.min.js')] : [],
|
|
371
376
|
],
|
|
372
377
|
cssUrls: [
|
|
373
378
|
'data:text/css,' + encodeURIComponent(VIEWER_IFRAME_CSS),
|
|
@@ -386,6 +391,7 @@
|
|
|
386
391
|
this.call('init', code, dataset, {
|
|
387
392
|
runnerMode,
|
|
388
393
|
blockType,
|
|
394
|
+
language,
|
|
389
395
|
showResults,
|
|
390
396
|
importsUrl,
|
|
391
397
|
packageInfo: PACKAGE_INFO,
|
|
@@ -411,6 +417,37 @@
|
|
|
411
417
|
insert(inlineViewer.iframe);
|
|
412
418
|
|
|
413
419
|
let isDestroyed = false;
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Loads the viewer and starts the runner (which, in window mode, is when
|
|
423
|
+
* the page's console functions start being captured).
|
|
424
|
+
*/
|
|
425
|
+
function load() {
|
|
426
|
+
if (runner || isDestroyed) return;
|
|
427
|
+
runner = runnerMode === 'window'
|
|
428
|
+
? createWindowRunner(sendToViewer)
|
|
429
|
+
: createWorkerRunner(sendToViewer);
|
|
430
|
+
inlineViewer.load();
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Unless data-loading="eager" is given, nothing is loaded until the console
|
|
434
|
+
// is about to be scrolled into view (or a hidden console is shown).
|
|
435
|
+
/** @type {IntersectionObserver?} */
|
|
436
|
+
let loadObserver = null;
|
|
437
|
+
if (dataset.loading !== 'eager' && 'function' === typeof window.IntersectionObserver) {
|
|
438
|
+
loadObserver = new IntersectionObserver(entries => {
|
|
439
|
+
if (entries.some(entry => entry.isIntersecting)) {
|
|
440
|
+
loadObserver.disconnect();
|
|
441
|
+
loadObserver = null;
|
|
442
|
+
load();
|
|
443
|
+
}
|
|
444
|
+
}, {rootMargin: '200px'});
|
|
445
|
+
loadObserver.observe(inlineViewer.iframe);
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
load();
|
|
449
|
+
}
|
|
450
|
+
|
|
414
451
|
return {
|
|
415
452
|
element: inlineViewer.iframe,
|
|
416
453
|
/**
|
|
@@ -426,7 +463,8 @@
|
|
|
426
463
|
popOutWindow = null;
|
|
427
464
|
}
|
|
428
465
|
removeEventListener('pagehide', closePopOut);
|
|
429
|
-
|
|
466
|
+
loadObserver?.disconnect();
|
|
467
|
+
runner?.destroy();
|
|
430
468
|
inlineViewer.dispose();
|
|
431
469
|
inlineViewer.iframe.remove();
|
|
432
470
|
},
|
|
@@ -462,7 +500,7 @@
|
|
|
462
500
|
* The options of YourJSBox.create() which are the same as the data
|
|
463
501
|
* attributes of a script tag.
|
|
464
502
|
*/
|
|
465
|
-
const CONSOLE_OPTION_NAMES = ['blockType', 'dividerOrient', 'hidePrefix', 'importsUrl', 'librariesUrl', 'runner', 'showResults', 'theme'];
|
|
503
|
+
const CONSOLE_OPTION_NAMES = ['blockType', 'dividerOrient', 'hidePrefix', 'importsUrl', 'language', 'librariesUrl', 'loading', 'runner', 'showResults', 'theme'];
|
|
466
504
|
|
|
467
505
|
/**
|
|
468
506
|
* The JavaScript API for creating consoles (available as window.YourJSBox).
|
|
@@ -488,12 +526,14 @@
|
|
|
488
526
|
* Optional. The code that the console starts with.
|
|
489
527
|
* @param {string=} options.runner
|
|
490
528
|
* @param {string=} options.blockType
|
|
529
|
+
* @param {string=} options.language
|
|
491
530
|
* @param {(boolean|string)=} options.showResults
|
|
492
531
|
* @param {string=} options.hidePrefix
|
|
493
532
|
* @param {string=} options.dividerOrient
|
|
494
533
|
* @param {string=} options.theme
|
|
495
534
|
* @param {string=} options.librariesUrl
|
|
496
535
|
* @param {string=} options.importsUrl
|
|
536
|
+
* @param {string=} options.loading
|
|
497
537
|
* The same as the data attributes of a script tag.
|
|
498
538
|
* @returns {{element: HTMLIFrameElement, destroy: () => void}}
|
|
499
539
|
*/
|
|
@@ -578,6 +618,8 @@
|
|
|
578
618
|
* @param {Window=} options.targetWindow
|
|
579
619
|
* If given the page is written into this (same origin) window (eg. a
|
|
580
620
|
* pop-out window) instead of into a new IFRAME.
|
|
621
|
+
* @param {boolean=} options.deferLoad
|
|
622
|
+
* If true the IFRAME's page isn't loaded until `load()` is called.
|
|
581
623
|
* @param {((this: R, event: MessageEvent) => void)=} options.onMessage
|
|
582
624
|
* @param {((this: R, event: MessageEvent) => void)=} options.onReady
|
|
583
625
|
* @returns {R}
|
|
@@ -659,9 +701,9 @@
|
|
|
659
701
|
TARGET_WINDOW.document.close();
|
|
660
702
|
}
|
|
661
703
|
else {
|
|
662
|
-
IFRAME.srcdoc = HTML_CODE;
|
|
663
704
|
// Allows the console to go full screen.
|
|
664
705
|
IFRAME.setAttribute('allow', 'fullscreen');
|
|
706
|
+
if (!options.deferLoad) IFRAME.srcdoc = HTML_CODE;
|
|
665
707
|
}
|
|
666
708
|
|
|
667
709
|
// Set the style of the iframe.
|
|
@@ -723,6 +765,10 @@
|
|
|
723
765
|
},
|
|
724
766
|
iframe: IFRAME,
|
|
725
767
|
window: TARGET_WINDOW,
|
|
768
|
+
// Loads the IFRAME's page if it was deferred.
|
|
769
|
+
load: function() {
|
|
770
|
+
if (IFRAME && !IFRAME.srcdoc) IFRAME.srcdoc = HTML_CODE;
|
|
771
|
+
},
|
|
726
772
|
// Stops listening for messages from the frame.
|
|
727
773
|
dispose: function() {
|
|
728
774
|
removeEventListener('message', onWindowMessage);
|
|
@@ -736,6 +782,7 @@
|
|
|
736
782
|
* @property {(funcName: string, ...args: any[]) => void} call
|
|
737
783
|
* @property {HTMLIFrameElement?} iframe
|
|
738
784
|
* @property {Window=} window
|
|
785
|
+
* @property {() => void} load
|
|
739
786
|
* @property {() => void} dispose
|
|
740
787
|
*/
|
|
741
788
|
|