@jsenv/ast 1.1.1 → 1.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/ast",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Parse and transform HTML,CSS and JS",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -9,8 +9,7 @@
9
9
  "directory": "packages/ast"
10
10
  },
11
11
  "publishConfig": {
12
- "access": "public",
13
- "registry": "https://registry.npmjs.org"
12
+ "access": "public"
14
13
  },
15
14
  "author": {
16
15
  "name": "dmail",
@@ -34,13 +33,13 @@
34
33
  "test": "node --conditions=development ./scripts/test.mjs"
35
34
  },
36
35
  "dependencies": {
37
- "@babel/parser": "7.18.5",
38
- "@parcel/css": "1.10.1",
39
- "acorn": "8.7.1",
36
+ "@babel/parser": "7.18.8",
37
+ "@parcel/css": "1.12.2",
38
+ "acorn": "8.8.0",
40
39
  "acorn-import-assertions": "1.8.0",
41
40
  "acorn-walk": "8.2.0",
42
41
  "parse5": "7.0.0",
43
42
  "postcss": "8.4.14",
44
43
  "postcss-value-parser": "4.2.0"
45
44
  }
46
- }
45
+ }
@@ -1,17 +1,80 @@
1
1
  import { getHtmlNodeAttribute } from "./html_node_attributes.js"
2
2
 
3
3
  export const analyzeScriptNode = (scriptNode) => {
4
- const type = getHtmlNodeAttribute(scriptNode, "type")
5
- if (type === undefined || type === "text/javascript") {
6
- return "classic"
4
+ const typeAttribute = getHtmlNodeAttribute(scriptNode, "type")
5
+ if (typeAttribute === undefined || typeAttribute === "text/javascript") {
6
+ return {
7
+ type: "js_classic",
8
+ contentType: "text/javascript",
9
+ }
10
+ }
11
+ if (typeAttribute === "module") {
12
+ return {
13
+ type: "js_module",
14
+ contentType: "text/javascript",
15
+ }
16
+ }
17
+ if (typeAttribute === "importmap") {
18
+ return {
19
+ type: "importmap",
20
+ contentType: "application/importmap+json",
21
+ }
22
+ }
23
+ // jsx
24
+ if (typeAttribute === "text/jsx") {
25
+ return {
26
+ type: "js_classic",
27
+ contentType: "text/javascript",
28
+ extension: ".jsx",
29
+ }
30
+ }
31
+ if (typeAttribute === "module/jsx") {
32
+ return {
33
+ type: "js_module",
34
+ contentType: "text/javascript",
35
+ extension: ".jsx",
36
+ }
7
37
  }
8
- if (type === "module") {
9
- return "module"
38
+ // typescript
39
+ if (typeAttribute === "text/ts") {
40
+ return {
41
+ type: "js_classic",
42
+ contentType: "text/javascript",
43
+ extension: ".ts",
44
+ }
10
45
  }
11
- if (type === "importmap") {
12
- return "importmap"
46
+ if (typeAttribute === "module/ts") {
47
+ return {
48
+ type: "js_module",
49
+ contentType: "text/javascript",
50
+ extension: ".ts",
51
+ }
52
+ }
53
+ // typescript and jsx
54
+ if (typeAttribute === "text/tsx") {
55
+ return {
56
+ type: "js_classic",
57
+ contentType: "text/javascript",
58
+ extension: ".tsx",
59
+ }
60
+ }
61
+ if (typeAttribute === "module/tsx") {
62
+ return {
63
+ type: "js_module",
64
+ contentType: "text/javascript",
65
+ extension: ".tsx",
66
+ }
67
+ }
68
+ // from MDN about [type] attribute:
69
+ // "Any other value: The embedded content is treated as a data block
70
+ // which won't be processed by the browser. Developers must use a valid MIME type
71
+ // that is not a JavaScript MIME type to denote data blocks.
72
+ // The src attribute will be ignored."
73
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type
74
+ return {
75
+ type: "text",
76
+ contentType: "text/plain",
13
77
  }
14
- return type
15
78
  }
16
79
 
17
80
  export const analyzeLinkNode = (linkNode) => {
@@ -21,7 +84,7 @@ export const analyzeLinkNode = (linkNode) => {
21
84
  isStylesheet: true,
22
85
  }
23
86
  }
24
- const isRessourceHint = [
87
+ const isResourceHint = [
25
88
  "preconnect",
26
89
  "dns-prefetch",
27
90
  "prefetch",
@@ -29,7 +92,7 @@ export const analyzeLinkNode = (linkNode) => {
29
92
  "modulepreload",
30
93
  ].includes(rel)
31
94
  return {
32
- isRessourceHint,
95
+ isResourceHint,
33
96
  rel,
34
97
  }
35
98
  }
@@ -7,7 +7,7 @@ import { setHtmlNodeText } from "./html_node_text.js"
7
7
  export const inlineScriptNode = (script, textContent) => {
8
8
  const src = getHtmlNodeAttribute(script, "src")
9
9
  setHtmlNodeAttributes(script, {
10
- "generated-from-src": src,
10
+ "inlined-from-src": src,
11
11
  "src": undefined,
12
12
  "crossorigin": undefined,
13
13
  "integrity": undefined,
@@ -18,7 +18,7 @@ export const inlineScriptNode = (script, textContent) => {
18
18
  export const inlineLinkStylesheetNode = (link, textContent) => {
19
19
  const href = getHtmlNodeAttribute(link, "href")
20
20
  setHtmlNodeAttributes(link, {
21
- "generated-from-href": href,
21
+ "inlined-from-href": href,
22
22
  "href": undefined,
23
23
  "rel": undefined,
24
24
  "type": undefined,
@@ -34,7 +34,7 @@ export const inlineLinkStylesheetNode = (link, textContent) => {
34
34
  export const inlineImgNode = (img, contentAsBase64) => {
35
35
  const src = getHtmlNodeAttribute(img, "src")
36
36
  setHtmlNodeAttributes(img, {
37
- "generated-from-src": src,
37
+ "inlined-from-src": src,
38
38
  "src": contentAsBase64,
39
39
  })
40
40
  }
@@ -1,9 +1,6 @@
1
1
  import { parseFragment } from "parse5"
2
2
 
3
- import {
4
- getHtmlNodeAttribute,
5
- setHtmlNodeAttributes,
6
- } from "./html_node_attributes.js"
3
+ import { setHtmlNodeAttributes } from "./html_node_attributes.js"
7
4
  import { findHtmlNode } from "./html_search.js"
8
5
  import { analyzeScriptNode } from "./html_analysis.js"
9
6
 
@@ -20,18 +17,20 @@ export const createHtmlNode = ({ tagName, textContent = "", ...rest }) => {
20
17
  return fragment.childNodes[0]
21
18
  }
22
19
 
23
- export const injectScriptNodeAsEarlyAsPossible = (htmlAst, scriptNode) => {
24
- const injectedBy = getHtmlNodeAttribute(scriptNode, "injected-by")
25
- if (injectedBy === undefined) {
26
- setHtmlNodeAttributes(scriptNode, {
27
- "injected-by": "jsenv",
28
- })
29
- }
30
- const isModule = analyzeScriptNode(scriptNode) === "module"
31
- if (isModule) {
20
+ export const injectScriptNodeAsEarlyAsPossible = (
21
+ htmlAst,
22
+ scriptNode,
23
+ jsenvPluginName = "jsenv",
24
+ ) => {
25
+ setHtmlNodeAttributes(scriptNode, {
26
+ "jsenv-plugin-owner": jsenvPluginName,
27
+ "jsenv-plugin-action": "injected",
28
+ })
29
+ const isJsModule = analyzeScriptNode(scriptNode).type === "js_module"
30
+ if (isJsModule) {
32
31
  const firstImportmapScript = findHtmlNode(htmlAst, (node) => {
33
32
  if (node.nodeName !== "script") return false
34
- return analyzeScriptNode(node) === "importmap"
33
+ return analyzeScriptNode(node).type === "importmap"
35
34
  })
36
35
  if (firstImportmapScript) {
37
36
  return insertAfter(
@@ -97,9 +97,9 @@ export const getHtmlNodeAttributePosition = (node, attributeName) => {
97
97
  }
98
98
  }
99
99
  const originalPositionAttributeName =
100
- attributeName === "generated-from-src"
100
+ attributeName === "inlined-from-src"
101
101
  ? "original-src-position"
102
- : attributeName === "generated-from-href"
102
+ : attributeName === "inlined-from-href"
103
103
  ? "original-href-position"
104
104
  : `original-${attributeName}-position`
105
105
  const originalPosition = getHtmlNodeAttribute(
@@ -66,10 +66,10 @@ export const stringifyHtmlAst = (
66
66
  "original-position": undefined,
67
67
  "original-src-position": undefined,
68
68
  "original-href-position": undefined,
69
- "injected-by": undefined,
70
- "generated-by": undefined,
71
- "generated-from-src": undefined,
72
- "generated-from-href": undefined,
69
+ "inlined-from-src": undefined,
70
+ "inlined-from-href": undefined,
71
+ "jsenv-plugin-owner": undefined,
72
+ "jsenv-plugin-action": undefined,
73
73
  })
74
74
  },
75
75
  })
@@ -31,6 +31,13 @@ export const analyzeNewUrlCall = (node, { isJsModule, onUrl }) => {
31
31
  const baseUrlType = analyzeUrlNodeType(secondArgNode, { isJsModule })
32
32
  if (baseUrlType) {
33
33
  // we can understand the second argument
34
+ if (
35
+ baseUrlType === "StringLiteral" &&
36
+ secondArgNode.value === "file:///"
37
+ ) {
38
+ // ignore new URL(specifier, "file:///")
39
+ return
40
+ }
34
41
  const urlType = analyzeUrlNodeType(firstArgNode, { isJsModule })
35
42
  if (urlType === "StringLiteral") {
36
43
  // we can understand the first argument