@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.
- package/dist/build_manifest.js +2 -2
- package/dist/compile_proxy/asset-manifest.json +2 -2
- package/dist/toolbar/asset-manifest.json +11 -11
- package/dist/toolbar/{toolbar.main2_6c1b3d82.js.map → toolbar.main_6c1b3d82.js.map} +0 -0
- package/dist/toolbar/{toolbar_04ba410c.html → toolbar_f7b8a263.html} +1 -1
- package/dist/toolbar_injector/asset-manifest.json +3 -3
- package/dist/toolbar_injector/{toolbar_injector_4a48bc53.js → toolbar_injector_49e4756e.js} +2 -2
- package/dist/toolbar_injector/{toolbar_injector_4a48bc53.js.map → toolbar_injector_49e4756e.js.map} +2 -2
- package/package.json +5 -4
- package/readme.md +3 -3
- package/src/buildProject.js +9 -0
- package/src/executeTestPlan.js +1 -1
- package/src/internal/building/rollup_plugin_jsenv.js +33 -22
- package/src/internal/building/url_versioning.js +34 -16
- package/src/jsenvServiceWorkerFinalizer.js +3 -9
package/dist/build_manifest.js
CHANGED
|
@@ -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/
|
|
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/
|
|
12
|
+
export const TOOLBAR_INJECTOR_BUILD_URL = new URL("toolbar_injector/toolbar_injector_49e4756e.js", import.meta.url).href
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"toolbar.html": "
|
|
12
|
-
"toolbar.
|
|
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
|
}
|
|
File without changes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"toolbar_injector.js": "
|
|
4
|
-
"toolbar_injector.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/
|
|
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=
|
|
973
|
+
//# sourceMappingURL=toolbar_injector_49e4756e.js.map
|
package/dist/toolbar_injector/{toolbar_injector_4a48bc53.js.map → toolbar_injector_49e4756e.js.map}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"file": "
|
|
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/
|
|
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.
|
|
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": ">=
|
|
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 [](https://www.npmjs.com/package/@jsenv/core) [](https://github.com/jsenv/jsenv-core/actions?workflow=main) [](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
|
-
|
|
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
|
|
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">`
|
package/src/buildProject.js
CHANGED
|
@@ -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,
|
package/src/executeTestPlan.js
CHANGED
|
@@ -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
|
|
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
|
-
//
|
|
186
|
-
let
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 "
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
: () =>
|
|
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]
|
|
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(
|
|
16
|
-
if (
|
|
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,
|