@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "25.1.0",
3
+ "version": "25.1.1",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "repository": {
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 **integrates naturally with standard** HTML, CSS and JS: you don't have to pick a JavaScript framework.
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** in JavaScript. 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.
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
- When code needs to be transformed, the project must contain a [babel config file](https://babeljs.io/docs/en/config-files).
360
+ You need a babel config file when:
361
361
 
362
- It's recommended to use the following _babel.config.cjs_
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 |
@@ -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
- getUniqueNameForInlineHtmlNode,
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 ressourceSpecifier = getUniqueNameForInlineHtmlNode(
238
- script,
239
- scripts,
240
- `${urlToFilename(htmlRessource.url)}__inline__[id].js`,
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 ressourceSpecifier = getUniqueNameForInlineHtmlNode(
337
- script,
338
- scripts,
339
- `${urlToFilename(htmlRessource.url)}__inline__[id].js`,
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: getUniqueNameForInlineHtmlNode(
452
- script,
453
- scripts,
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: getUniqueNameForInlineHtmlNode(
655
- style,
656
- styles,
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 getUniqueNameForInlineHtmlNode = (node, nodes, pattern) => {
499
- return renderNamePattern(pattern, {
500
- id: () => {
501
- const idAttribute = getHtmlNodeAttributeByName(node, "id")
502
- if (idAttribute) {
503
- return idAttribute.value
504
- }
505
-
506
- const { line, column } = getHtmlNodeLocation(node) || {}
507
- const lineTaken = nodes.some((nodeCandidate) => {
508
- if (nodeCandidate === node) return false
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
- getUniqueNameForInlineHtmlNode,
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, scriptIdentifier }) => {
125
- const inlineScriptUrl = resolveUrl(scriptIdentifier, fileUrl)
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 scriptIdentifier = getUniqueNameForInlineHtmlNode(
252
- script,
253
- scripts,
254
- `${urlToFilename(fileUrl)}__inline__[id].js`,
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
- scriptIdentifier,
257
+ scriptSpecifier,
259
258
  })
260
259
  setHtmlNodeText(
261
260
  script,
262
261
  `window.__jsenv__.executeFileUsingDynamicImport(${JSON.stringify(
263
- `./${scriptIdentifier}`,
262
+ `./${scriptSpecifier}`,
264
263
  )})`,
265
264
  )
266
265
  return
@@ -30,7 +30,7 @@ import {
30
30
  stringifyHtmlAst,
31
31
  getHtmlNodeAttributeByName,
32
32
  getHtmlNodeTextNode,
33
- getUniqueNameForInlineHtmlNode,
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 inlineScriptName = getUniqueNameForInlineHtmlNode(
369
- script,
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 inlineScriptName = getUniqueNameForInlineHtmlNode(
486
- script,
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,