@jsenv/ast 6.10.3 → 6.10.5
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": "6.10.
|
|
3
|
+
"version": "6.10.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Parse and transform HTML, CSS and JS",
|
|
6
6
|
"repository": {
|
|
@@ -29,14 +29,14 @@
|
|
|
29
29
|
"@babel/core": "8.0.1",
|
|
30
30
|
"@babel/helper-module-imports": "8.0.0",
|
|
31
31
|
"@babel/parser": "8.0.4",
|
|
32
|
-
"@jsenv/humanize": "1.8.
|
|
33
|
-
"@jsenv/urls": "2.9.
|
|
32
|
+
"@jsenv/humanize": "1.8.2",
|
|
33
|
+
"@jsenv/urls": "2.9.13",
|
|
34
34
|
"@jsenv/utils": "2.3.1",
|
|
35
35
|
"acorn": "8.18.0",
|
|
36
36
|
"acorn-import-attributes": "1.9.5",
|
|
37
37
|
"acorn-walk": "8.3.5",
|
|
38
38
|
"parse5": "8.0.1",
|
|
39
|
-
"postcss": "8.5.
|
|
39
|
+
"postcss": "8.5.28",
|
|
40
40
|
"postcss-value-parser": "4.2.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
@@ -10,11 +10,21 @@
|
|
|
10
10
|
|
|
11
11
|
const PLACEHOLDER = (index) => `var(--jsenv-css-substitution-${index})`;
|
|
12
12
|
|
|
13
|
+
// A css comment an author writes in a template that cannot be made readable,
|
|
14
|
+
// to say so and stop being told. Kept as plain css: it costs nothing when the
|
|
15
|
+
// template does become readable, the css pipeline strips it like any comment.
|
|
16
|
+
const OPAQUE_DIRECTIVE = "jsenv-css-opaque";
|
|
17
|
+
|
|
18
|
+
export const hasCssOpaqueDirective = (templateSource) => {
|
|
19
|
+
return templateSource.includes(OPAQUE_DIRECTIVE);
|
|
20
|
+
};
|
|
21
|
+
|
|
13
22
|
/**
|
|
14
23
|
* @param {Object} templateLiteralNode a TemplateLiteral acorn node
|
|
15
24
|
* @param {string} js the source the node comes from
|
|
16
|
-
* @returns {{ content: string, substitutions: Array<{placeholder: string, expression: string}> }
|
|
17
|
-
*
|
|
25
|
+
* @returns {{ content: string, substitutions: Array<{placeholder: string, expression: string}> }
|
|
26
|
+
* | { opaque: { reason: string } }}
|
|
27
|
+
* "opaque" when the css cannot be read: the template is left alone
|
|
18
28
|
*/
|
|
19
29
|
export const buildCssTemplateSubstitutions = (templateLiteralNode, js) => {
|
|
20
30
|
const { quasis, expressions } = templateLiteralNode;
|
|
@@ -22,8 +32,12 @@ export const buildCssTemplateSubstitutions = (templateLiteralNode, js) => {
|
|
|
22
32
|
for (const quasi of quasis) {
|
|
23
33
|
const { cooked } = quasi.value;
|
|
24
34
|
if (cooked === undefined) {
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
return {
|
|
36
|
+
opaque: {
|
|
37
|
+
reason:
|
|
38
|
+
"an escape sequence cannot be cooked into the css it stands for",
|
|
39
|
+
},
|
|
40
|
+
};
|
|
27
41
|
}
|
|
28
42
|
parts.push(cooked);
|
|
29
43
|
}
|
|
@@ -39,9 +53,14 @@ export const buildCssTemplateSubstitutions = (templateLiteralNode, js) => {
|
|
|
39
53
|
});
|
|
40
54
|
content += placeholder + parts[i + 1];
|
|
41
55
|
}
|
|
42
|
-
for (
|
|
43
|
-
|
|
44
|
-
|
|
56
|
+
for (let i = 0; i < positions.length; i++) {
|
|
57
|
+
const nonValuePosition = readNonValuePosition(content, positions[i]);
|
|
58
|
+
if (nonValuePosition) {
|
|
59
|
+
return {
|
|
60
|
+
opaque: {
|
|
61
|
+
reason: `"\${${substitutions[i].expression}}" stands in ${nonValuePosition}`,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
45
64
|
}
|
|
46
65
|
}
|
|
47
66
|
return { content, substitutions };
|
|
@@ -49,7 +68,8 @@ export const buildCssTemplateSubstitutions = (templateLiteralNode, js) => {
|
|
|
49
68
|
|
|
50
69
|
// Reads the css from its start up to "position", keeping just enough state to
|
|
51
70
|
// tell what the placeholder sitting there would be part of.
|
|
52
|
-
|
|
71
|
+
// Returns what it is part of when that is not a value, null when it is one.
|
|
72
|
+
const readNonValuePosition = (css, position) => {
|
|
53
73
|
let braceDepth = 0;
|
|
54
74
|
let stringQuote = null;
|
|
55
75
|
let inComment = false;
|
|
@@ -130,29 +150,32 @@ const isCssValuePosition = (css, position) => {
|
|
|
130
150
|
}
|
|
131
151
|
i++;
|
|
132
152
|
}
|
|
133
|
-
if (inComment
|
|
134
|
-
return
|
|
153
|
+
if (inComment) {
|
|
154
|
+
return "a comment";
|
|
155
|
+
}
|
|
156
|
+
if (stringQuote) {
|
|
157
|
+
return "a string";
|
|
135
158
|
}
|
|
136
159
|
if (braceDepth === 0) {
|
|
137
|
-
|
|
138
|
-
return false;
|
|
160
|
+
return "a selector, or an at-rule prelude";
|
|
139
161
|
}
|
|
140
162
|
if (!colonSeen) {
|
|
141
|
-
|
|
142
|
-
return false;
|
|
163
|
+
return "a property name, or a nested selector";
|
|
143
164
|
}
|
|
144
165
|
if (css.slice(statementStart, position).trimStart().startsWith("@")) {
|
|
145
|
-
|
|
146
|
-
return false;
|
|
166
|
+
return "a nested at-rule prelude";
|
|
147
167
|
}
|
|
148
168
|
if (functionStack[functionStack.length - 1] === "url") {
|
|
149
169
|
// url() takes an url, and an url built at runtime is not one the build
|
|
150
170
|
// can follow to a file
|
|
151
|
-
return
|
|
171
|
+
return "url()";
|
|
152
172
|
}
|
|
153
173
|
// A ":" also opens a pseudo class, so what looks like a value here can still
|
|
154
174
|
// be the end of a nested selector; that is settled by what closes it.
|
|
155
|
-
|
|
175
|
+
if (!closedByDeclarationEnd(css, position)) {
|
|
176
|
+
return "a nested selector";
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
156
179
|
};
|
|
157
180
|
|
|
158
181
|
const readFunctionNameBefore = (css, parenthesisIndex) => {
|
|
@@ -12,7 +12,7 @@ export const isImportMetaCssAssignment = (node) => {
|
|
|
12
12
|
|
|
13
13
|
export const analyzeImportMetaCssAssignment = (
|
|
14
14
|
node,
|
|
15
|
-
{ js, ast, ancestors, onInlineContent },
|
|
15
|
+
{ js, ast, ancestors, onInlineContent, onOpaqueContent },
|
|
16
16
|
) => {
|
|
17
17
|
// "import.meta.css = [css, url]": the array form a pre-built file ships
|
|
18
18
|
// (see jsenv:import_meta_css); the css is the first element.
|
|
@@ -21,6 +21,9 @@ export const analyzeImportMetaCssAssignment = (
|
|
|
21
21
|
if (!assignedNode) {
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
|
+
// a pre-built package ships "[css, url]": its css was written in a source
|
|
25
|
+
// this build does not have, so this build is not where it can be fixed
|
|
26
|
+
const alreadyBuilt = node.right.type === "ArrayExpression";
|
|
24
27
|
// "const css = `...`; import.meta.css = css;" — the css is where the constant
|
|
25
28
|
// is declared, and that is where it is read and rewritten.
|
|
26
29
|
const nodeHoldingContent =
|
|
@@ -58,7 +61,16 @@ export const analyzeImportMetaCssAssignment = (
|
|
|
58
61
|
nodeHoldingContent,
|
|
59
62
|
js,
|
|
60
63
|
);
|
|
61
|
-
if (
|
|
64
|
+
if (substitutionInfo.opaque) {
|
|
65
|
+
onOpaqueContent({
|
|
66
|
+
...position,
|
|
67
|
+
...substitutionInfo.opaque,
|
|
68
|
+
alreadyBuilt,
|
|
69
|
+
templateSource: js.slice(
|
|
70
|
+
nodeHoldingContent.start,
|
|
71
|
+
nodeHoldingContent.end,
|
|
72
|
+
),
|
|
73
|
+
});
|
|
62
74
|
return;
|
|
63
75
|
}
|
|
64
76
|
onInlineContent({
|
|
@@ -69,6 +81,7 @@ export const analyzeImportMetaCssAssignment = (
|
|
|
69
81
|
quote: "`",
|
|
70
82
|
content: substitutionInfo.content,
|
|
71
83
|
substitutions: substitutionInfo.substitutions,
|
|
84
|
+
alreadyBuilt,
|
|
72
85
|
astInfo: { node: nodeHoldingContent },
|
|
73
86
|
});
|
|
74
87
|
};
|
package/src/js/parse_js_urls.js
CHANGED
|
@@ -78,6 +78,13 @@ export const parseJsUrls = ({
|
|
|
78
78
|
...inlineContentInfo,
|
|
79
79
|
});
|
|
80
80
|
};
|
|
81
|
+
// css the build cannot read: no url info comes out of it, only a way to tell
|
|
82
|
+
const onOpaqueContent = (opaqueContentInfo) => {
|
|
83
|
+
jsUrls.push({
|
|
84
|
+
isOpaqueCss: true,
|
|
85
|
+
...opaqueContentInfo,
|
|
86
|
+
});
|
|
87
|
+
};
|
|
81
88
|
|
|
82
89
|
const getCommentBeforeClosingParenthesis = (
|
|
83
90
|
// either new InlineContent() or JSON.parse() for instance
|
|
@@ -141,6 +148,7 @@ export const parseJsUrls = ({
|
|
|
141
148
|
ast,
|
|
142
149
|
ancestors,
|
|
143
150
|
onInlineContent,
|
|
151
|
+
onOpaqueContent,
|
|
144
152
|
});
|
|
145
153
|
}
|
|
146
154
|
},
|
package/src/main.js
CHANGED
|
@@ -59,6 +59,9 @@ export { visitJsAstUntil } from "./js/visit_js_ast_until.js";
|
|
|
59
59
|
export { visitJsAst } from "./js/visit_js_ast.js";
|
|
60
60
|
export { getImportMetaPropertyName } from "./js/import_meta.js";
|
|
61
61
|
export { getUrlForContentInsideJs } from "./js/js_inline_content_url.js";
|
|
62
|
-
export {
|
|
62
|
+
export {
|
|
63
|
+
hasCssOpaqueDirective,
|
|
64
|
+
renderCssTemplateLiteral,
|
|
65
|
+
} from "./js/js_static_analysis/css_template_substitutions.js";
|
|
63
66
|
|
|
64
67
|
export { generateUrlForInlineContent } from "./inline_content_url.js";
|