@jsenv/core 25.0.0-alpha.2 → 25.0.1

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.
@@ -7,6 +7,6 @@ export const COMPILE_PROXY_BUILD_URL = new URL("compile_proxy/compile_proxy_7ad5
7
7
 
8
8
  export const EVENT_SOURCE_CLIENT_BUILD_URL = new URL("event_source_client/event_source_client_80644aee.js", import.meta.url).href
9
9
 
10
- export const TOOLBAR_BUILD_URL = new URL("toolbar/toolbar_04ba410c.html", import.meta.url).href
10
+ export const TOOLBAR_BUILD_URL = new URL("toolbar/toolbar_f7b8a263.html", import.meta.url).href
11
11
 
12
- export const TOOLBAR_INJECTOR_BUILD_URL = new URL("toolbar_injector/toolbar_injector_4a48bc53.js", import.meta.url).href
12
+ export const TOOLBAR_INJECTOR_BUILD_URL = new URL("toolbar_injector/toolbar_injector_49e4756e.js", import.meta.url).href
@@ -1,4 +1,4 @@
1
1
  {
2
- "compile_proxy_e3b0c442.js.map": "compile_proxy_e3b0c442_809f35f7.js.map",
3
- "compile_proxy.html": "compile_proxy_7ad5faa6.html"
2
+ "compile_proxy.html": "compile_proxy_7ad5faa6.html",
3
+ "compile_proxy_e3b0c442.js.map": "compile_proxy_e3b0c442_809f35f7.js.map"
4
4
  }
@@ -1,13 +1,13 @@
1
1
  {
2
- ".jsenv/build/best/src/internal/dev_server/toolbar/compilation/compilation.css.map": "assets/compilation.css_e37c747b.map",
3
- ".jsenv/build/best/src/internal/dev_server/toolbar/eventsource/eventsource.css.map": "assets/eventsource.css_c0c71e7b.map",
4
- ".jsenv/build/best/src/internal/dev_server/toolbar/execution/execution.css.map": "assets/execution.css_f3377c10.map",
5
- ".jsenv/build/best/src/internal/dev_server/toolbar/focus/focus.css.map": "assets/focus.css_896f3e45.map",
6
- ".jsenv/build/best/src/internal/dev_server/toolbar/responsive/overflow-menu.css.map": "assets/overflow-menu.css_2859d519.map",
7
- ".jsenv/build/best/src/internal/dev_server/toolbar/settings/settings.css.map": "assets/settings.css_61548139.map",
8
- ".jsenv/build/best/src/internal/dev_server/toolbar/theme/light-theme.css.map": "assets/light-theme.css_72a60fa3.map",
9
- ".jsenv/build/best/src/internal/dev_server/toolbar/tooltip/tooltip.css.map": "assets/tooltip.css_a94a8bdd.map",
10
- ".jsenv/build/best/src/internal/dev_server/toolbar/toolbar.main.css.map": "assets/toolbar.main.css_269d7ce2.map",
11
- "toolbar.html": "toolbar_04ba410c.html",
12
- "toolbar.main2.js.map": "toolbar.main2_6c1b3d82.js.map"
2
+ "assets/compilation.css.map": "assets/compilation.css_e37c747b.map",
3
+ "assets/eventsource.css.map": "assets/eventsource.css_c0c71e7b.map",
4
+ "assets/execution.css.map": "assets/execution.css_f3377c10.map",
5
+ "assets/focus.css.map": "assets/focus.css_896f3e45.map",
6
+ "assets/light-theme.css.map": "assets/light-theme.css_72a60fa3.map",
7
+ "assets/overflow-menu.css.map": "assets/overflow-menu.css_2859d519.map",
8
+ "assets/settings.css.map": "assets/settings.css_61548139.map",
9
+ "assets/toolbar.main.css.map": "assets/toolbar.main.css_269d7ce2.map",
10
+ "assets/tooltip.css.map": "assets/tooltip.css_a94a8bdd.map",
11
+ "toolbar.html": "toolbar_f7b8a263.html",
12
+ "toolbar.main.js.map": "toolbar.main_6c1b3d82.js.map"
13
13
  }
@@ -5010,7 +5010,7 @@ html[data-toolbar-visible] #toolbar-trigger {
5010
5010
  };
5011
5011
  });
5012
5012
 
5013
- //# sourceMappingURL=toolbar.main2_6c1b3d82.js.map</script>
5013
+ //# sourceMappingURL=toolbar.main_6c1b3d82.js.map</script>
5014
5014
 
5015
5015
 
5016
5016
  </body></html>
@@ -1,5 +1,5 @@
1
1
  {
2
- ".jsenv/build/best/src/internal/dev_server/toolbar/jsenv-logo.svg": "assets/jsenv-logo_188b9ca6.svg",
3
- "toolbar_injector.js": "toolbar_injector_4a48bc53.js",
4
- "toolbar_injector.js.map": "toolbar_injector_4a48bc53.js.map"
2
+ "assets/jsenv-logo.svg": "assets/jsenv-logo_188b9ca6.svg",
3
+ "toolbar_injector.js": "toolbar_injector_49e4756e.js",
4
+ "toolbar_injector.js.map": "toolbar_injector_49e4756e.js.map"
5
5
  }
@@ -746,7 +746,7 @@
746
746
  return then ? value.then(then) : value;
747
747
  }
748
748
 
749
- var TOOLBAR_BUILD_RELATIVE_URL = "dist/toolbar/toolbar_04ba410c.html";
749
+ var TOOLBAR_BUILD_RELATIVE_URL = "dist/toolbar/toolbar_f7b8a263.html";
750
750
 
751
751
  function _call(body, then, direct) {
752
752
  if (direct) {
@@ -970,4 +970,4 @@
970
970
 
971
971
  })();
972
972
 
973
- //# sourceMappingURL=toolbar_injector_4a48bc53.js.map
973
+ //# sourceMappingURL=toolbar_injector_49e4756e.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "file": "toolbar_injector_4a48bc53.js",
3
+ "file": "toolbar_injector_49e4756e.js",
4
4
  "sources": [
5
5
  "../../helpers/babel/typeof/typeof.js",
6
6
  "../../helpers/babel/defineProperty/defineProperty.js",
@@ -25,7 +25,7 @@
25
25
  "import { fetchUrl } from \"./fetch-browser.js\"\n\nexport const fetchJson = async (url, options = {}) => {\n const response = await fetchUrl(url, options)\n const object = await response.json()\n return object\n}\n",
26
26
  "import { fetchJson } from \"../../browser_utils/fetchJson.js\"\n\nexport const fetchExploringJson = async ({ signal } = {}) => {\n try {\n const exploringInfo = await fetchJson(\"/.jsenv/exploring.json\", {\n signal,\n })\n return exploringInfo\n } catch (e) {\n if (signal && signal.aborted && e.name === \"AbortError\") {\n throw e\n }\n throw new Error(\n `Cannot communicate with exploring server due to a network error\n--- error stack ---\n${e.stack}`,\n )\n }\n}\n",
27
27
  "export const updateIframeOverflowOnParentWindow = () => {\n if (!window.parent) {\n // can happen while parent iframe reloads\n return\n }\n\n const aTooltipIsOpened =\n document.querySelector(\"[data-tooltip-visible]\") ||\n document.querySelector(\"[data-tooltip-auto-visible]\")\n const settingsAreOpened = document.querySelector(\"#settings[data-active]\")\n\n if (aTooltipIsOpened || settingsAreOpened) {\n enableIframeOverflowOnParentWindow()\n } else {\n disableIframeOverflowOnParentWindow()\n }\n}\n\nlet iframeOverflowEnabled = false\nconst enableIframeOverflowOnParentWindow = () => {\n if (iframeOverflowEnabled) return\n iframeOverflowEnabled = true\n\n const iframe = getToolbarIframe()\n const transitionDuration = iframe.style.transitionDuration\n setStyles(iframe, { \"height\": \"100%\", \"transition-duration\": \"0ms\" })\n if (transitionDuration) {\n setTimeout(() => {\n setStyles(iframe, { \"transition-duration\": transitionDuration })\n })\n }\n}\n\nconst disableIframeOverflowOnParentWindow = () => {\n if (!iframeOverflowEnabled) return\n iframeOverflowEnabled = false\n\n const iframe = getToolbarIframe()\n const transitionDuration = iframe.style.transitionDuration\n setStyles(iframe, { \"height\": \"40px\", \"transition-duration\": \"0ms\" })\n if (transitionDuration) {\n setTimeout(() => {\n setStyles(iframe, { \"transition-duration\": transitionDuration })\n })\n }\n}\n\nexport const getToolbarIframe = () => {\n const iframes = Array.from(window.parent.document.querySelectorAll(\"iframe\"))\n return iframes.find((iframe) => iframe.contentWindow === window)\n}\n\nexport const forceHideElement = (element) => {\n element.setAttribute(\"data-force-hide\", \"\")\n}\n\nexport const removeForceHideElement = (element) => {\n element.removeAttribute(\"data-force-hide\")\n}\n\nexport const setStyles = (element, styles) => {\n const elementStyle = element.style\n const restoreStyles = Object.keys(styles).map((styleName) => {\n let restore\n if (styleName in elementStyle) {\n const currentStyle = elementStyle[styleName]\n restore = () => {\n elementStyle[styleName] = currentStyle\n }\n } else {\n restore = () => {\n delete elementStyle[styleName]\n }\n }\n\n elementStyle[styleName] = styles[styleName]\n\n return restore\n })\n return () => {\n restoreStyles.forEach((restore) => restore())\n }\n}\n\nexport const setAttributes = (element, attributes) => {\n Object.keys(attributes).forEach((name) => {\n element.setAttribute(name, attributes[name])\n })\n}\n\nexport const getDocumentScroll = () => {\n return {\n x: document.documentElement.scrollLeft,\n y: document.documentElement.scrollTop,\n }\n}\n\nexport const toolbarSectionIsActive = (element) => {\n return element.hasAttribute(\"data-active\")\n}\n\nexport const activateToolbarSection = (element) => {\n element.setAttribute(\"data-active\", \"\")\n}\n\nexport const deactivateToolbarSection = (element) => {\n element.removeAttribute(\"data-active\")\n}\n",
28
- "import { fetchExploringJson } from \"@jsenv/core/src/internal/dev_server/exploring/fetchExploringJson.js\"\nimport { setAttributes, setStyles } from \"./util/dom.js\"\n\n// eslint-disable-next-line no-undef\nconst TOOLBAR_BUILD_RELATIVE_URL = \"dist/toolbar/toolbar_04ba410c.html\"\nconst jsenvLogoSvgUrl = new URL(\"./jsenv-logo.svg\", import.meta.url)\n\nconst injectToolbar = async () => {\n await new Promise((resolve) => {\n if (window.requestIdleCallback) {\n window.requestIdleCallback(resolve)\n } else {\n window.requestAnimationFrame(resolve)\n }\n })\n\n const { jsenvDirectoryRelativeUrl } = await fetchExploringJson()\n const jsenvDirectoryServerUrl = resolveUrl(\n jsenvDirectoryRelativeUrl,\n document.location.origin,\n )\n\n const placeholder = getToolbarPlaceholder()\n\n const iframe = document.createElement(\"iframe\")\n setAttributes(iframe, {\n tabindex: -1,\n // sandbox: \"allow-forms allow-modals allow-pointer-lock allow-popups allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation\",\n // allow: \"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; microphone; midi; payment; vr\",\n allowtransparency: true,\n })\n setStyles(iframe, {\n \"position\": \"fixed\",\n \"zIndex\": 1000,\n \"bottom\": 0,\n \"left\": 0,\n \"width\": \"100%\",\n \"height\": 0,\n /* ensure toolbar children are not focusable when hidden */\n \"visibility\": \"hidden\",\n \"transition-duration\": \"300ms\",\n \"transition-property\": \"height, visibility\",\n \"border\": \"none\",\n })\n const iframeLoadedPromise = iframeToLoadedPromise(iframe)\n const jsenvToolbarHtmlServerUrl = resolveUrl(\n TOOLBAR_BUILD_RELATIVE_URL,\n jsenvDirectoryServerUrl,\n )\n // set iframe src BEFORE putting it into the DOM (prevent firefox adding an history entry)\n iframe.setAttribute(\"src\", jsenvToolbarHtmlServerUrl)\n placeholder.parentNode.replaceChild(iframe, placeholder)\n\n await iframeLoadedPromise\n iframe.removeAttribute(\"tabindex\")\n\n const div = document.createElement(\"div\")\n div.innerHTML = `\n<div id=\"jsenv-toolbar-trigger\">\n <svg id=\"jsenv-toolbar-trigger-icon\">\n <use xlink:href=\"${jsenvLogoSvgUrl}#jsenv-logo\"></use>\n </svg>\n <style>\n #jsenv-toolbar-trigger {\n display: block;\n overflow: hidden;\n position: fixed;\n z-index: 1000;\n bottom: -32px;\n right: 20px;\n height: 40px;\n width: 40px;\n padding: 0;\n margin: 0;\n border-radius: 5px 5px 0 0;\n border: 1px solid rgba(0, 0, 0, 0.33);\n border-bottom: none;\n box-shadow: 0px 0px 6px 2px rgba(0, 0, 0, 0.46);\n background: transparent;\n text-align: center;\n transition: 600ms;\n }\n\n #jsenv-toolbar-trigger:hover {\n cursor: pointer;\n }\n\n #jsenv-toolbar-trigger[data-expanded] {\n bottom: 0;\n }\n\n #jsenv-toolbar-trigger-icon {\n width: 35px;\n height: 35px;\n opacity: 0;\n transition: 600ms;\n }\n\n #jsenv-toolbar-trigger[data-expanded] #jsenv-toolbar-trigger-icon {\n opacity: 1;\n }\n </style>\n</div>`\n const toolbarTrigger = div.firstElementChild\n iframe.parentNode.appendChild(toolbarTrigger)\n\n let timer\n toolbarTrigger.onmouseenter = () => {\n toolbarTrigger.setAttribute(\"data-animate\", \"\")\n timer = setTimeout(expandToolbarTrigger, 500)\n }\n toolbarTrigger.onmouseleave = () => {\n clearTimeout(timer)\n collapseToolbarTrigger()\n }\n toolbarTrigger.onfocus = () => {\n toolbarTrigger.removeAttribute(\"data-animate\")\n expandToolbarTrigger()\n }\n toolbarTrigger.onblur = () => {\n toolbarTrigger.removeAttribute(\"data-animate\")\n clearTimeout(timer)\n collapseToolbarTrigger()\n }\n toolbarTrigger.onclick = () => {\n sendCommandToToolbar(iframe, \"showToolbar\")\n }\n\n const showToolbarTrigger = () => {\n toolbarTrigger.style.display = \"block\"\n }\n\n const hideToolbarTrigger = () => {\n toolbarTrigger.style.display = \"none\"\n }\n\n const expandToolbarTrigger = () => {\n toolbarTrigger.setAttribute(\"data-expanded\", \"\")\n }\n\n const collapseToolbarTrigger = () => {\n toolbarTrigger.removeAttribute(\"data-expanded\", \"\")\n }\n\n hideToolbarTrigger()\n addToolbarEventCallback(iframe, \"toolbar-visibility-change\", (visible) => {\n if (visible) {\n hideToolbarTrigger()\n } else {\n showToolbarTrigger()\n }\n })\n addToolbarEventCallback(iframe, \"toolbar_ready\", () => {\n sendCommandToToolbar(iframe, \"renderToolbar\")\n })\n\n return iframe\n}\n\nconst addToolbarEventCallback = (iframe, eventName, callback) => {\n const messageEventCallback = (messageEvent) => {\n const { data } = messageEvent\n if (typeof data !== \"object\") {\n return\n }\n const { __jsenv__ } = data\n if (!__jsenv__) {\n return\n }\n if (__jsenv__.event !== eventName) {\n return\n }\n callback(__jsenv__.data)\n }\n\n window.addEventListener(\"message\", messageEventCallback, false)\n return () => {\n window.removeEventListener(\"message\", messageEventCallback, false)\n }\n}\n\nconst sendCommandToToolbar = (iframe, command, ...args) => {\n iframe.contentWindow.postMessage(\n {\n __jsenv__: {\n command,\n args,\n },\n },\n window.origin,\n )\n}\n\nconst getToolbarPlaceholder = () => {\n const placeholder = queryPlaceholder()\n if (placeholder) {\n if (document.body.contains(placeholder)) {\n return placeholder\n }\n // otherwise iframe would not be visible because in <head>\n console.warn(\n \"element with [data-jsenv-toolbar-placeholder] must be inside document.body\",\n )\n return createTooolbarPlaceholder()\n }\n return createTooolbarPlaceholder()\n}\n\nconst queryPlaceholder = () => {\n return document.querySelector(\"[data-jsenv-toolbar-placeholder]\")\n}\n\nconst createTooolbarPlaceholder = () => {\n const placeholder = document.createElement(\"span\")\n document.body.appendChild(placeholder)\n return placeholder\n}\n\nconst iframeToLoadedPromise = (iframe) => {\n return new Promise((resolve) => {\n const onload = () => {\n iframe.removeEventListener(\"load\", onload, true)\n resolve()\n }\n iframe.addEventListener(\"load\", onload, true)\n })\n}\n\nconst resolveUrl = (url, baseUrl) => String(new URL(url, baseUrl))\n\nif (document.readyState === \"complete\") {\n injectToolbar()\n} else {\n window.addEventListener(\"load\", injectToolbar)\n}\n"
28
+ "import { fetchExploringJson } from \"@jsenv/core/src/internal/dev_server/exploring/fetchExploringJson.js\"\nimport { setAttributes, setStyles } from \"./util/dom.js\"\n\n// eslint-disable-next-line no-undef\nconst TOOLBAR_BUILD_RELATIVE_URL = \"dist/toolbar/toolbar_f7b8a263.html\"\nconst jsenvLogoSvgUrl = new URL(\"./jsenv-logo.svg\", import.meta.url)\n\nconst injectToolbar = async () => {\n await new Promise((resolve) => {\n if (window.requestIdleCallback) {\n window.requestIdleCallback(resolve)\n } else {\n window.requestAnimationFrame(resolve)\n }\n })\n\n const { jsenvDirectoryRelativeUrl } = await fetchExploringJson()\n const jsenvDirectoryServerUrl = resolveUrl(\n jsenvDirectoryRelativeUrl,\n document.location.origin,\n )\n\n const placeholder = getToolbarPlaceholder()\n\n const iframe = document.createElement(\"iframe\")\n setAttributes(iframe, {\n tabindex: -1,\n // sandbox: \"allow-forms allow-modals allow-pointer-lock allow-popups allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation\",\n // allow: \"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; microphone; midi; payment; vr\",\n allowtransparency: true,\n })\n setStyles(iframe, {\n \"position\": \"fixed\",\n \"zIndex\": 1000,\n \"bottom\": 0,\n \"left\": 0,\n \"width\": \"100%\",\n \"height\": 0,\n /* ensure toolbar children are not focusable when hidden */\n \"visibility\": \"hidden\",\n \"transition-duration\": \"300ms\",\n \"transition-property\": \"height, visibility\",\n \"border\": \"none\",\n })\n const iframeLoadedPromise = iframeToLoadedPromise(iframe)\n const jsenvToolbarHtmlServerUrl = resolveUrl(\n TOOLBAR_BUILD_RELATIVE_URL,\n jsenvDirectoryServerUrl,\n )\n // set iframe src BEFORE putting it into the DOM (prevent firefox adding an history entry)\n iframe.setAttribute(\"src\", jsenvToolbarHtmlServerUrl)\n placeholder.parentNode.replaceChild(iframe, placeholder)\n\n await iframeLoadedPromise\n iframe.removeAttribute(\"tabindex\")\n\n const div = document.createElement(\"div\")\n div.innerHTML = `\n<div id=\"jsenv-toolbar-trigger\">\n <svg id=\"jsenv-toolbar-trigger-icon\">\n <use xlink:href=\"${jsenvLogoSvgUrl}#jsenv-logo\"></use>\n </svg>\n <style>\n #jsenv-toolbar-trigger {\n display: block;\n overflow: hidden;\n position: fixed;\n z-index: 1000;\n bottom: -32px;\n right: 20px;\n height: 40px;\n width: 40px;\n padding: 0;\n margin: 0;\n border-radius: 5px 5px 0 0;\n border: 1px solid rgba(0, 0, 0, 0.33);\n border-bottom: none;\n box-shadow: 0px 0px 6px 2px rgba(0, 0, 0, 0.46);\n background: transparent;\n text-align: center;\n transition: 600ms;\n }\n\n #jsenv-toolbar-trigger:hover {\n cursor: pointer;\n }\n\n #jsenv-toolbar-trigger[data-expanded] {\n bottom: 0;\n }\n\n #jsenv-toolbar-trigger-icon {\n width: 35px;\n height: 35px;\n opacity: 0;\n transition: 600ms;\n }\n\n #jsenv-toolbar-trigger[data-expanded] #jsenv-toolbar-trigger-icon {\n opacity: 1;\n }\n </style>\n</div>`\n const toolbarTrigger = div.firstElementChild\n iframe.parentNode.appendChild(toolbarTrigger)\n\n let timer\n toolbarTrigger.onmouseenter = () => {\n toolbarTrigger.setAttribute(\"data-animate\", \"\")\n timer = setTimeout(expandToolbarTrigger, 500)\n }\n toolbarTrigger.onmouseleave = () => {\n clearTimeout(timer)\n collapseToolbarTrigger()\n }\n toolbarTrigger.onfocus = () => {\n toolbarTrigger.removeAttribute(\"data-animate\")\n expandToolbarTrigger()\n }\n toolbarTrigger.onblur = () => {\n toolbarTrigger.removeAttribute(\"data-animate\")\n clearTimeout(timer)\n collapseToolbarTrigger()\n }\n toolbarTrigger.onclick = () => {\n sendCommandToToolbar(iframe, \"showToolbar\")\n }\n\n const showToolbarTrigger = () => {\n toolbarTrigger.style.display = \"block\"\n }\n\n const hideToolbarTrigger = () => {\n toolbarTrigger.style.display = \"none\"\n }\n\n const expandToolbarTrigger = () => {\n toolbarTrigger.setAttribute(\"data-expanded\", \"\")\n }\n\n const collapseToolbarTrigger = () => {\n toolbarTrigger.removeAttribute(\"data-expanded\", \"\")\n }\n\n hideToolbarTrigger()\n addToolbarEventCallback(iframe, \"toolbar-visibility-change\", (visible) => {\n if (visible) {\n hideToolbarTrigger()\n } else {\n showToolbarTrigger()\n }\n })\n addToolbarEventCallback(iframe, \"toolbar_ready\", () => {\n sendCommandToToolbar(iframe, \"renderToolbar\")\n })\n\n return iframe\n}\n\nconst addToolbarEventCallback = (iframe, eventName, callback) => {\n const messageEventCallback = (messageEvent) => {\n const { data } = messageEvent\n if (typeof data !== \"object\") {\n return\n }\n const { __jsenv__ } = data\n if (!__jsenv__) {\n return\n }\n if (__jsenv__.event !== eventName) {\n return\n }\n callback(__jsenv__.data)\n }\n\n window.addEventListener(\"message\", messageEventCallback, false)\n return () => {\n window.removeEventListener(\"message\", messageEventCallback, false)\n }\n}\n\nconst sendCommandToToolbar = (iframe, command, ...args) => {\n iframe.contentWindow.postMessage(\n {\n __jsenv__: {\n command,\n args,\n },\n },\n window.origin,\n )\n}\n\nconst getToolbarPlaceholder = () => {\n const placeholder = queryPlaceholder()\n if (placeholder) {\n if (document.body.contains(placeholder)) {\n return placeholder\n }\n // otherwise iframe would not be visible because in <head>\n console.warn(\n \"element with [data-jsenv-toolbar-placeholder] must be inside document.body\",\n )\n return createTooolbarPlaceholder()\n }\n return createTooolbarPlaceholder()\n}\n\nconst queryPlaceholder = () => {\n return document.querySelector(\"[data-jsenv-toolbar-placeholder]\")\n}\n\nconst createTooolbarPlaceholder = () => {\n const placeholder = document.createElement(\"span\")\n document.body.appendChild(placeholder)\n return placeholder\n}\n\nconst iframeToLoadedPromise = (iframe) => {\n return new Promise((resolve) => {\n const onload = () => {\n iframe.removeEventListener(\"load\", onload, true)\n resolve()\n }\n iframe.addEventListener(\"load\", onload, true)\n })\n}\n\nconst resolveUrl = (url, baseUrl) => String(new URL(url, baseUrl))\n\nif (document.readyState === \"complete\") {\n injectToolbar()\n} else {\n window.addEventListener(\"load\", injectToolbar)\n}\n"
29
29
  ],
30
30
  "names": [
31
31
  "nativeTypeOf",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "25.0.0-alpha.2",
3
+ "version": "25.0.1",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -8,10 +8,11 @@
8
8
  "url": "https://github.com/jsenv/jsenv-core"
9
9
  },
10
10
  "engines": {
11
- "node": ">=14.9.0"
11
+ "node": ">=16.13.0"
12
12
  },
13
13
  "publishConfig": {
14
- "access": "public"
14
+ "access": "public",
15
+ "registry": "https://registry.npmjs.org"
15
16
  },
16
17
  "type": "module",
17
18
  "exports": {
@@ -137,4 +138,4 @@
137
138
  "redux": "4.1.2",
138
139
  "rollup-plugin-import-assert": "1.1.1"
139
140
  }
140
- }
141
+ }
package/readme.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # jsenv [![npm package](https://img.shields.io/npm/v/@jsenv/core.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/core) [![github main worflow](https://github.com/jsenv/jsenv-core/workflows/main/badge.svg)](https://github.com/jsenv/jsenv-core/actions?workflow=main) [![codecov coverage](https://codecov.io/gh/jsenv/jsenv-core/branch/master/graph/badge.svg)](https://codecov.io/gh/jsenv/jsenv-core)
2
2
 
3
- _@jsenv/core_ is a quick start pack to launch a js project.
3
+ _@jsenv/core_ is a quick start pack to launch a js project. It provides what you need from the beginning: a dev server, a build tool and a test "framework", all in one.
4
4
 
5
- You don't have to pick a JavaScript framework: jsenv integrates naturally with standard HTML, CSS and JS. It provides what you need from the beginning: a dev server, a build tool and a test "framework", all in one.
5
+ Jsenv integrates naturally with **standard** HTML, CSS and JS: you don't have to pick a JavaScript framework.
6
6
 
7
7
  # Test runner overview
8
8
 
@@ -253,7 +253,7 @@ Jsenv was first created to write tests that could be executed in different runti
253
253
  - A test runner to execute test files
254
254
  - A build tool to optimize files for production
255
255
 
256
- Jsenv relies on standard web features. Each standard listed below is potentially supported natively by the browser. When browser supports all of them, jsenv will use source files without modification. Otherwise, the files are compiled to be executable in the browser.
256
+ Jsenv relies on **standard web features**. Each standard listed below is potentially supported natively by the browser. When browser supports all of them, jsenv will use source files without modification. Otherwise, the files are compiled to be executable in the browser.
257
257
 
258
258
  - `<script type="module">`
259
259
  - `<script type="importmap">`
@@ -15,6 +15,15 @@ import {
15
15
  jsenvNodeRuntimeSupport,
16
16
  } from "./internal/generateGroupMap/jsenvRuntimeSupport.js"
17
17
 
18
+ /**
19
+ * Generate optimized version of source files into a directory
20
+ * @param {string|url} projectDirectoryUrl Root directory of the project
21
+ * @param {string|url} buildDirectoryRelativeUrl Directory where optimized files are written
22
+ * @param {object} entryPoints Describe entry point paths and control their names in the build directory
23
+ * @param {"esmodule" | "systemjs" | "commonjs" | "global"} format Code generated will use this module format
24
+ * @param {object} runtimeSupport Code generated will be compatible with these runtimes
25
+ * @param {boolean} [minify=false] Minify file content in the build directory (HTML, CSS, JS, JSON, SVG)
26
+ */
18
27
  export const buildProject = async ({
19
28
  signal = new AbortController().signal,
20
29
  handleSIGINT = true,
@@ -22,7 +22,7 @@ import { jsenvCoverageConfig } from "./jsenvCoverageConfig.js"
22
22
  /**
23
23
  * Execute a list of files and log how it goes
24
24
  * @param {object} testPlan Configure files to execute and their runtimes (browsers/node)
25
- * @param {string|url} projectDirectoryUrl Root directory of your files
25
+ * @param {string|url} projectDirectoryUrl Root directory of the project
26
26
  * @param {number} [maxExecutionsInParallel=1] Maximum amount of execution in parallel
27
27
  * @param {number} [defaultMsAllocatedPerExecution=30000] Milliseconds after which execution is aborted and considered as failed by timeout
28
28
  * @param {number} [cooldownBetweenExecutions=0] Millisecond to wait between each execution
@@ -182,14 +182,16 @@ export const createRollupPlugins = async ({
182
182
  projectDirectoryUrl,
183
183
  )
184
184
 
185
- // map build relative urls without hash (called "ressourceName") to real build relative urls
186
- let buildManifest = {}
185
+ // Object mapping project relative urls to build relative urls
186
+ let buildMappings = {}
187
+ // Object mapping ressource names to build relative urls
188
+ let ressourceMappings = {}
187
189
 
188
190
  const ressourcesReferencedByJs = []
189
191
  const createImportMapForFilesUsedInJs = () => {
190
192
  const topLevelMappings = {}
191
193
  ressourcesReferencedByJs.sort(comparePathnames).forEach((ressourceName) => {
192
- const buildRelativeUrl = buildManifest[ressourceName]
194
+ const buildRelativeUrl = ressourceMappings[ressourceName]
193
195
  if (
194
196
  ressourceName &&
195
197
  buildRelativeUrl &&
@@ -203,12 +205,6 @@ export const createRollupPlugins = async ({
203
205
  }
204
206
  }
205
207
 
206
- // an object where keys are build relative urls
207
- // and values rollup chunk or asset
208
- // we need this because we sometimes tell rollup
209
- // that a file.fileName is something while it's not really this
210
- // because of remapping
211
- let buildMappings = {}
212
208
  let rollupBuild
213
209
 
214
210
  const EMPTY_CHUNK_URL = resolveUrl("__empty__", projectDirectoryUrl)
@@ -1390,7 +1386,7 @@ export const createRollupPlugins = async ({
1390
1386
  buildMappings[originalProjectRelativeUrl] =
1391
1387
  jsRessource.buildRelativeUrl
1392
1388
  }
1393
- buildManifest[jsRessource.fileName] = jsRessource.buildRelativeUrl
1389
+ ressourceMappings[jsRessource.fileName] = jsRessource.buildRelativeUrl
1394
1390
  })
1395
1391
  // wait for asset build relative urls
1396
1392
  // to ensure the importmap will contain remappings for them
@@ -1402,7 +1398,7 @@ export const createRollupPlugins = async ({
1402
1398
  })
1403
1399
  if (ressource && !ressource.isJsModule) {
1404
1400
  await ressource.getReadyPromise()
1405
- buildManifest[ressourceName] = ressource.buildRelativeUrl
1401
+ ressourceMappings[ressourceName] = ressource.buildRelativeUrl
1406
1402
  }
1407
1403
  }),
1408
1404
  )
@@ -1456,7 +1452,7 @@ export const createRollupPlugins = async ({
1456
1452
  // in case sourcemap is mutated, we must not trust rollup but the asset builder source instead
1457
1453
  rollupFileInfo.source = assetRessource.bufferAfterBuild
1458
1454
  assetBuild[buildRelativeUrl] = rollupFileInfo
1459
- buildManifest[assetRessource.fileName] = buildRelativeUrl
1455
+ ressourceMappings[assetRessource.fileName] = buildRelativeUrl
1460
1456
  if (assetRessource.bufferBeforeBuild) {
1461
1457
  const originalProjectUrl = asOriginalUrl(assetRessource.url)
1462
1458
  const originalProjectRelativeUrl = urlToRelativeUrl(
@@ -1474,8 +1470,8 @@ export const createRollupPlugins = async ({
1474
1470
  }
1475
1471
  rollupBuild = sortObjectByPathnames(rollupBuild)
1476
1472
  // fill "buildFileContents", "buildInlineFilesContents"
1477
- // and update "buildManifest" and "buildMappings" in case some ressource where inlined
1478
- // by ressourceBuilder.rollupBuildEnd
1473
+ // and update "buildMappings"
1474
+ // in case some ressource where inlined by ressourceBuilder.rollupBuildEnd
1479
1475
  Object.keys(rollupBuild).forEach((buildRelativeUrl) => {
1480
1476
  const rollupFileInfo = rollupBuild[buildRelativeUrl]
1481
1477
  const ressource = ressourceBuilder.findRessource((ressource) => {
@@ -1488,7 +1484,6 @@ export const createRollupPlugins = async ({
1488
1484
  return false
1489
1485
  })
1490
1486
  if (ressource.isInline) {
1491
- delete buildManifest[ressource.fileName]
1492
1487
  if (ressource.isJsModule) {
1493
1488
  delete jsModuleBuild[buildRelativeUrl]
1494
1489
  } else {
@@ -1508,19 +1503,18 @@ export const createRollupPlugins = async ({
1508
1503
  }
1509
1504
  })
1510
1505
 
1506
+ ressourceMappings = sortObjectByPathnames(ressourceMappings)
1507
+ buildMappings = sortObjectByPathnames(buildMappings)
1511
1508
  await visitServiceWorkers({
1512
1509
  projectDirectoryUrl,
1513
1510
  serviceWorkerUrls,
1514
1511
  classicServiceWorkerUrls,
1515
1512
  serviceWorkerFinalizer,
1516
1513
  buildMappings,
1517
- buildManifest,
1514
+ ressourceMappings,
1518
1515
  buildFileContents,
1519
1516
  lineBreakNormalization,
1520
1517
  })
1521
-
1522
- buildManifest = sortObjectByPathnames(buildManifest)
1523
- buildMappings = sortObjectByPathnames(buildMappings)
1524
1518
  const buildDuration = Date.now() - buildStartMs
1525
1519
  buildStats = createBuildStats({
1526
1520
  buildFileContents,
@@ -1560,7 +1554,11 @@ export const createRollupPlugins = async ({
1560
1554
  rollupBuild,
1561
1555
  urlResponseBodyMap: urlLoader.getUrlResponseBodyMap(),
1562
1556
  buildMappings,
1563
- buildManifest,
1557
+ ressourceMappings,
1558
+ // Object mapping build relative urls without hash to build relative urls
1559
+ buildManifest: createBuildManifest({
1560
+ buildFileContents,
1561
+ }),
1564
1562
  buildImportMap: createImportMapForFilesUsedInJs(),
1565
1563
  buildFileContents,
1566
1564
  buildInlineFileContents,
@@ -1573,6 +1571,21 @@ export const createRollupPlugins = async ({
1573
1571
  }
1574
1572
  }
1575
1573
 
1574
+ const createBuildManifest = ({ buildFileContents }) => {
1575
+ const buildManifest = {}
1576
+ Object.keys(buildFileContents).forEach((buildRelativeUrl) => {
1577
+ const relativeUrlWithoutHash = asFileNameWithoutHash(buildRelativeUrl)
1578
+ buildManifest[relativeUrlWithoutHash] = buildRelativeUrl
1579
+ })
1580
+ return buildManifest
1581
+ }
1582
+
1583
+ const asFileNameWithoutHash = (fileName) => {
1584
+ return fileName.replace(/_[a-z0-9]{8,}(\..*?)?$/, (_, afterHash = "") => {
1585
+ return afterHash
1586
+ })
1587
+ }
1588
+
1576
1589
  const prepareEntryPoints = async (
1577
1590
  entryPoints,
1578
1591
  {
@@ -1718,7 +1731,6 @@ const visitServiceWorkers = async ({
1718
1731
  classicServiceWorkerUrls,
1719
1732
  serviceWorkerFinalizer,
1720
1733
  buildMappings,
1721
- buildManifest,
1722
1734
  buildFileContents,
1723
1735
  lineBreakNormalization,
1724
1736
  }) => {
@@ -1745,7 +1757,6 @@ const visitServiceWorkers = async ({
1745
1757
  let code = buildFileContents[serviceWorkerBuildRelativeUrl]
1746
1758
  code = await serviceWorkerFinalizer(code, {
1747
1759
  serviceWorkerBuildRelativeUrl,
1748
- buildManifest,
1749
1760
  buildFileContents,
1750
1761
  lineBreakNormalization,
1751
1762
  })
@@ -10,20 +10,7 @@ export const createUrlVersioner = ({
10
10
  asOriginalUrl,
11
11
  lineBreakNormalization,
12
12
  }) => {
13
- const names = []
14
- const getFreeName = (name) => {
15
- let nameCandidate = name
16
- let integer = 1
17
- // eslint-disable-next-line no-constant-condition
18
- while (true) {
19
- if (!names.includes(nameCandidate)) {
20
- names.push(nameCandidate)
21
- return nameCandidate
22
- }
23
- integer++
24
- nameCandidate = `${name}${integer}`
25
- }
26
- }
13
+ const availableNameGenerator = createAvailableNameGenerator()
27
14
 
28
15
  const computeBuildRelativeUrl = (ressource, precomputation) => {
29
16
  const pattern = getFilenamePattern({
@@ -40,7 +27,11 @@ export const createUrlVersioner = ({
40
27
  pattern,
41
28
  getName: precomputation
42
29
  ? () => urlToBasename(ressource.url)
43
- : () => getFreeName(urlToBasename(ressource.url)),
30
+ : () =>
31
+ availableNameGenerator.getAvailableNameForPattern(
32
+ urlToBasename(ressource.url),
33
+ pattern,
34
+ ),
44
35
  contentType: ressource.contentType,
45
36
  lineBreakNormalization,
46
37
  },
@@ -69,6 +60,33 @@ export const createUrlVersioner = ({
69
60
  }
70
61
  }
71
62
 
63
+ const createAvailableNameGenerator = () => {
64
+ const cache = {}
65
+ const getAvailableNameForPattern = (name, pattern) => {
66
+ let names = cache[pattern]
67
+ if (!names) {
68
+ names = []
69
+ cache[pattern] = names
70
+ }
71
+
72
+ let nameCandidate = name
73
+ let integer = 1
74
+ // eslint-disable-next-line no-constant-condition
75
+ while (true) {
76
+ if (!names.includes(nameCandidate)) {
77
+ names.push(nameCandidate)
78
+ return nameCandidate
79
+ }
80
+ integer++
81
+ nameCandidate = `${name}${integer}`
82
+ }
83
+ }
84
+
85
+ return {
86
+ getAvailableNameForPattern,
87
+ }
88
+ }
89
+
72
90
  const getFilenamePattern = ({
73
91
  ressource,
74
92
  entryPointUrls,
@@ -115,7 +133,7 @@ const getFilenamePattern = ({
115
133
  }
116
134
 
117
135
  if (ressource.isJsModule) {
118
- return "[name]_[hash][extname]"
136
+ return "[name]_[hash].js"
119
137
  }
120
138
 
121
139
  return ressource.urlVersioningDisabled
@@ -4,20 +4,14 @@ import { generateContentHash } from "./internal/building/url_versioning.js"
4
4
 
5
5
  export const jsenvServiceWorkerFinalizer = (
6
6
  code,
7
- {
8
- serviceWorkerBuildRelativeUrl,
9
- buildManifest,
10
- buildFileContents,
11
- lineBreakNormalization,
12
- },
7
+ { serviceWorkerBuildRelativeUrl, buildFileContents, lineBreakNormalization },
13
8
  ) => {
14
9
  const generatedUrlsConfig = {}
15
- Object.keys(buildManifest).forEach((projectRelativeUrl) => {
16
- if (projectRelativeUrl.endsWith(".map")) {
10
+ Object.keys(buildFileContents).forEach((buildRelativeUrl) => {
11
+ if (buildRelativeUrl.endsWith(".map")) {
17
12
  return
18
13
  }
19
14
 
20
- const buildRelativeUrl = buildManifest[projectRelativeUrl]
21
15
  const buildUrl = resolveUrl(buildRelativeUrl, "file://")
22
16
  const serviceWorkerBuildUrl = resolveUrl(
23
17
  serviceWorkerBuildRelativeUrl,