@jsenv/core 25.1.0 → 25.1.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/package.json +1 -1
- package/readme.md +10 -5
- package/src/executeTestPlan.js +11 -0
- package/src/internal/building/html/parseHtmlRessource.js +17 -23
- package/src/internal/compiling/compileHtml.js +15 -28
- package/src/internal/compiling/html_source_file_service.js +9 -10
- package/src/internal/compiling/jsenvCompilerForHtml.js +5 -11
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
_@jsenv/core_ is a quick start pack to launch a js project. It provides what you need from the beginning: develoment, testing and building all in one.
|
|
4
4
|
|
|
5
|
-
Jsenv
|
|
5
|
+
Jsenv integrates naturally with standard HTML, CSS and JS: you don't have to pick a JavaScript framework.
|
|
6
6
|
|
|
7
7
|
# Overview
|
|
8
8
|
|
|
@@ -276,7 +276,7 @@ Jsenv relies on **standard web features**. Each standard listed below is potenti
|
|
|
276
276
|
|
|
277
277
|
Amongst other use cases, the ease of use and flexibility of jsenv makes it a great tool to start and learn web development.
|
|
278
278
|
|
|
279
|
-
First because jsenv is a tool that was built to run raw js, html and css. It starts from the **simplest form of coding
|
|
279
|
+
First because jsenv is a tool that was built to run raw js, html and css. It starts from the **simplest form of coding**. If a browser can run your code, so can jsenv without configuration or things to learn. There is no magic that will bite you right away or later. Jsenv can be configured to add more stuff later, on demand.
|
|
280
280
|
|
|
281
281
|
Second because jsenv is compatible with the latest standards. Even some that are not yet mature in the js ecosystem, such as import maps. This will makes you at ease with technologies that will be part of the ecosystem once you are confortable with coding.
|
|
282
282
|
|
|
@@ -357,9 +357,12 @@ This file helps to see jsenv configuration quickly and share it between files. T
|
|
|
357
357
|
|
|
358
358
|
## babel.config.cjs
|
|
359
359
|
|
|
360
|
-
|
|
360
|
+
You need a babel config file when:
|
|
361
361
|
|
|
362
|
-
|
|
362
|
+
- Your code use non standard concepts. Examples: JSX, TypeScript.
|
|
363
|
+
- You need to be compatible with browsers where some features used by your codebase are not available. Examples: `async/await`, destructuring.
|
|
364
|
+
|
|
365
|
+
It's recommended to start with the following _babel.config.cjs_
|
|
363
366
|
|
|
364
367
|
```js
|
|
365
368
|
/*
|
|
@@ -374,14 +377,16 @@ module.exports = {
|
|
|
374
377
|
}
|
|
375
378
|
```
|
|
376
379
|
|
|
380
|
+
This babel config file will be used as explained in [Browser support](./docs/config/browser_support.md). It can also be used to enable [JSX](./docs/config/react.md#Using-JSX) and [TypeScript](./docs/config/typescript.md).
|
|
381
|
+
|
|
377
382
|
# See also
|
|
378
383
|
|
|
379
384
|
| Link | Description |
|
|
380
385
|
| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- |
|
|
381
386
|
| [Browser support](./docs/config/browser_support.md) | Document how to configure browser support |
|
|
382
387
|
| [Web workers](./docs/config/web_workers.md) | Document how to use web workers |
|
|
388
|
+
| [NPM package](./docs/config/npm_package.md) | Document how to use a NPM package |
|
|
383
389
|
| [React](./docs/config/react.md) | Document how to enable react/preact and JSX |
|
|
384
|
-
| [CommonJS modules](./docs/config/commonjs.md) | Document how to use code written in CommonJS |
|
|
385
390
|
| [TypeScript (Experimental)](./docs/config/typescript.md) | Document how to enable TypeScript |
|
|
386
391
|
| [@jsenv/template-pwa](https://github.com/jsenv/jsenv-template-pwa) | GitHub repository template for a progressive web application |
|
|
387
392
|
| [@jsenv/template-node-package](https://github.com/jsenv/jsenv-template-node-package) | GitHub repository template for a node package |
|
package/src/executeTestPlan.js
CHANGED
|
@@ -254,6 +254,17 @@ export const executeTestPlan = async ({
|
|
|
254
254
|
await Promise.all(promises)
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
+
// Sometimes on windows test plan scripts never ends
|
|
258
|
+
// I suspect it's some node process keeping the process alive
|
|
259
|
+
// because not properly killed for some reason.
|
|
260
|
+
// (It can be reproduced on @jsenv/importmap-node-module where playwright is not involved)
|
|
261
|
+
// The hotfix for now is to manually call process.exit() in on windows
|
|
262
|
+
if (process.platform === "win32") {
|
|
263
|
+
setTimeout(() => {
|
|
264
|
+
process.exit()
|
|
265
|
+
}, 2000).unref()
|
|
266
|
+
}
|
|
267
|
+
|
|
257
268
|
return {
|
|
258
269
|
testPlanAborted: result.aborted,
|
|
259
270
|
testPlanSummary: result.planSummary,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
replaceHtmlNode,
|
|
25
25
|
getHtmlNodeAttributeByName,
|
|
26
26
|
stringifyHtmlAst,
|
|
27
|
-
|
|
27
|
+
getIdForInlineHtmlNode,
|
|
28
28
|
removeHtmlNodeAttribute,
|
|
29
29
|
setHtmlNodeText,
|
|
30
30
|
getHtmlNodeTextNode,
|
|
@@ -234,11 +234,10 @@ const regularScriptTextNodeVisitor = (
|
|
|
234
234
|
return null
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
)
|
|
237
|
+
const scriptId = getIdForInlineHtmlNode(script, scripts)
|
|
238
|
+
const ressourceSpecifier = `${urlToFilename(
|
|
239
|
+
htmlRessource.url,
|
|
240
|
+
)}__inline__${scriptId}.js`
|
|
242
241
|
const jsReference = notifyReferenceFound({
|
|
243
242
|
referenceLabel: "html inline script",
|
|
244
243
|
contentTypeExpected: "application/javascript",
|
|
@@ -333,11 +332,10 @@ const moduleScriptTextNodeVisitor = (
|
|
|
333
332
|
return null
|
|
334
333
|
}
|
|
335
334
|
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
)
|
|
335
|
+
const scriptId = getIdForInlineHtmlNode(script, scripts)
|
|
336
|
+
const ressourceSpecifier = `${urlToFilename(
|
|
337
|
+
htmlRessource.url,
|
|
338
|
+
)}__inline__${scriptId}.js`
|
|
341
339
|
const jsReference = notifyReferenceFound({
|
|
342
340
|
referenceLabel: "html inline module script",
|
|
343
341
|
contentTypeExpected: "application/javascript",
|
|
@@ -445,16 +443,14 @@ const importmapScriptTextNodeVisitor = (
|
|
|
445
443
|
return null
|
|
446
444
|
}
|
|
447
445
|
|
|
446
|
+
const importmapScriptId = getIdForInlineHtmlNode(script, scripts)
|
|
448
447
|
const importmapReference = notifyReferenceFound({
|
|
449
448
|
referenceLabel: "html inline importmap",
|
|
450
449
|
contentTypeExpected: "application/importmap+json",
|
|
451
|
-
ressourceSpecifier:
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
`${urlToFilename(htmlRessource.url)}__inline__[id].importmap`,
|
|
455
|
-
),
|
|
450
|
+
ressourceSpecifier: `${urlToFilename(
|
|
451
|
+
htmlRessource.url,
|
|
452
|
+
)}__inline__${importmapScriptId}.importmap`,
|
|
456
453
|
...referenceLocationFromHtmlNode(script),
|
|
457
|
-
|
|
458
454
|
contentType: "application/importmap+json",
|
|
459
455
|
bufferBeforeBuild: Buffer.from(textNode.value),
|
|
460
456
|
isInline: true,
|
|
@@ -648,16 +644,14 @@ const styleTextNodeVisitor = (
|
|
|
648
644
|
return null
|
|
649
645
|
}
|
|
650
646
|
|
|
647
|
+
const styleId = getIdForInlineHtmlNode(style, styles)
|
|
651
648
|
const inlineStyleReference = notifyReferenceFound({
|
|
652
649
|
referenceLabel: "html style",
|
|
653
650
|
contentTypeExpected: "text/css",
|
|
654
|
-
ressourceSpecifier:
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
`${urlToFilename(htmlRessource.url)}__inline__[id].css`,
|
|
658
|
-
),
|
|
651
|
+
ressourceSpecifier: `${urlToFilename(
|
|
652
|
+
htmlRessource.url,
|
|
653
|
+
)}__inline__${styleId}.css`,
|
|
659
654
|
...referenceLocationFromHtmlNode(style),
|
|
660
|
-
|
|
661
655
|
contentType: "text/css",
|
|
662
656
|
bufferBeforeBuild: Buffer.from(textNode.value),
|
|
663
657
|
isInline: true,
|
|
@@ -495,35 +495,22 @@ export const createInlineScriptHash = (script) => {
|
|
|
495
495
|
return hash.digest("hex").slice(0, 8)
|
|
496
496
|
}
|
|
497
497
|
|
|
498
|
-
export const
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
const htmlNodeLocation = getHtmlNodeLocation(nodeCandidate)
|
|
510
|
-
if (!htmlNodeLocation) return false
|
|
511
|
-
return htmlNodeLocation.line === line
|
|
512
|
-
})
|
|
513
|
-
if (lineTaken) {
|
|
514
|
-
return `${line}.${column}`
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
return line
|
|
518
|
-
},
|
|
519
|
-
})
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
const renderNamePattern = (pattern, replacements) => {
|
|
523
|
-
return pattern.replace(/\[(\w+)\]/g, (_match, type) => {
|
|
524
|
-
const replacement = replacements[type]()
|
|
525
|
-
return replacement
|
|
498
|
+
export const getIdForInlineHtmlNode = (node, nodes) => {
|
|
499
|
+
const idAttribute = getHtmlNodeAttributeByName(node, "id")
|
|
500
|
+
if (idAttribute) {
|
|
501
|
+
return idAttribute.value
|
|
502
|
+
}
|
|
503
|
+
const { line, column } = getHtmlNodeLocation(node) || {}
|
|
504
|
+
const lineTaken = nodes.some((nodeCandidate) => {
|
|
505
|
+
if (nodeCandidate === node) return false
|
|
506
|
+
const htmlNodeLocation = getHtmlNodeLocation(nodeCandidate)
|
|
507
|
+
if (!htmlNodeLocation) return false
|
|
508
|
+
return htmlNodeLocation.line === line
|
|
526
509
|
})
|
|
510
|
+
if (lineTaken) {
|
|
511
|
+
return `${line}.${column}`
|
|
512
|
+
}
|
|
513
|
+
return line
|
|
527
514
|
}
|
|
528
515
|
|
|
529
516
|
const parseHtmlAsSingleElement = (html) => {
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
removeHtmlNodeAttribute,
|
|
42
42
|
getHtmlNodeTextNode,
|
|
43
43
|
setHtmlNodeText,
|
|
44
|
-
|
|
44
|
+
getIdForInlineHtmlNode,
|
|
45
45
|
} from "./compileHtml.js"
|
|
46
46
|
import { jsenvCoreDirectoryUrl } from "../jsenvCoreDirectoryUrl.js"
|
|
47
47
|
|
|
@@ -121,8 +121,8 @@ export const createTransformHtmlSourceFileService = ({
|
|
|
121
121
|
jsenvScriptInjection,
|
|
122
122
|
jsenvEventSourceClientInjection,
|
|
123
123
|
jsenvToolbarInjection,
|
|
124
|
-
onInlineModuleScript: ({ scriptContent,
|
|
125
|
-
const inlineScriptUrl = resolveUrl(
|
|
124
|
+
onInlineModuleScript: ({ scriptContent, scriptSpecifier }) => {
|
|
125
|
+
const inlineScriptUrl = resolveUrl(scriptSpecifier, fileUrl)
|
|
126
126
|
htmlInlineScriptMap.set(inlineScriptUrl, {
|
|
127
127
|
htmlFileUrl: fileUrl,
|
|
128
128
|
scriptContent,
|
|
@@ -248,19 +248,18 @@ const transformHTMLSourceFile = async ({
|
|
|
248
248
|
// inline
|
|
249
249
|
const textNode = getHtmlNodeTextNode(script)
|
|
250
250
|
if (typeAttribute && typeAttribute.value === "module" && textNode) {
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
)
|
|
251
|
+
const scriptId = getIdForInlineHtmlNode(script, scripts)
|
|
252
|
+
const scriptSpecifier = `${urlToFilename(
|
|
253
|
+
fileUrl,
|
|
254
|
+
)}__inline__${scriptId}.js`
|
|
256
255
|
onInlineModuleScript({
|
|
257
256
|
scriptContent: textNode.value,
|
|
258
|
-
|
|
257
|
+
scriptSpecifier,
|
|
259
258
|
})
|
|
260
259
|
setHtmlNodeText(
|
|
261
260
|
script,
|
|
262
261
|
`window.__jsenv__.executeFileUsingDynamicImport(${JSON.stringify(
|
|
263
|
-
`./${
|
|
262
|
+
`./${scriptSpecifier}`,
|
|
264
263
|
)})`,
|
|
265
264
|
)
|
|
266
265
|
return
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
stringifyHtmlAst,
|
|
31
31
|
getHtmlNodeAttributeByName,
|
|
32
32
|
getHtmlNodeTextNode,
|
|
33
|
-
|
|
33
|
+
getIdForInlineHtmlNode,
|
|
34
34
|
removeHtmlNodeAttribute,
|
|
35
35
|
setHtmlNodeText,
|
|
36
36
|
visitHtmlAst,
|
|
@@ -365,11 +365,8 @@ const visitScripts = async ({
|
|
|
365
365
|
return
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
scripts,
|
|
371
|
-
`[id].js`,
|
|
372
|
-
)
|
|
368
|
+
const scriptId = getIdForInlineHtmlNode(script, scripts)
|
|
369
|
+
const inlineScriptName = `${scriptId}.js`
|
|
373
370
|
const scriptOriginalUrl = resolveUrl(inlineScriptName, url)
|
|
374
371
|
const scriptCompiledUrl = generateCompiledFileAssetUrl(
|
|
375
372
|
compiledUrl,
|
|
@@ -482,11 +479,8 @@ const visitScripts = async ({
|
|
|
482
479
|
})
|
|
483
480
|
return
|
|
484
481
|
}
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
scripts,
|
|
488
|
-
`[id].js`,
|
|
489
|
-
)
|
|
482
|
+
const scriptId = getIdForInlineHtmlNode(script, scripts)
|
|
483
|
+
const inlineScriptName = `${scriptId}.js`
|
|
490
484
|
const scriptOriginalUrl = resolveUrl(inlineScriptName, url)
|
|
491
485
|
const scriptCompiledUrl = generateCompiledFileAssetUrl(
|
|
492
486
|
compiledUrl,
|