@jsenv/core 35.0.5 → 36.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/README.md +1 -1
- package/dist/js/inline_content.js +5 -4
- package/dist/jsenv_core.js +1127 -1497
- package/package.json +8 -8
- package/src/build/build.js +49 -41
- package/src/dev/file_service.js +7 -17
- package/src/dev/start_dev_server.js +12 -7
- package/src/kitchen/kitchen.js +38 -19
- package/src/kitchen/url_graph.js +1 -1
- package/src/plugins/autoreload/jsenv_plugin_hmr.js +2 -2
- package/src/plugins/file_urls/jsenv_plugin_file_urls.js +4 -4
- package/src/plugins/http_urls/jsenv_plugin_http_urls.js +1 -1
- package/src/plugins/importmap/jsenv_plugin_importmap.js +1 -1
- package/src/plugins/inlining/jsenv_plugin_inlining.js +1 -1
- package/src/plugins/inlining/jsenv_plugin_inlining_as_data_url.js +13 -2
- package/src/plugins/plugin_controller.js +19 -10
- package/src/plugins/plugins.js +21 -25
- package/src/plugins/{url_analysis/css/css_urls.js → reference_analysis/css/jsenv_plugin_css_reference_analysis.js} +11 -1
- package/src/plugins/{inline_content_analysis/jsenv_plugin_data_urls.js → reference_analysis/data_urls/jsenv_plugin_data_urls_analysis.js} +19 -19
- package/src/plugins/reference_analysis/directory/jsenv_plugin_directory_reference_analysis.js +51 -0
- package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +429 -0
- package/src/plugins/reference_analysis/inline_content.js +7 -0
- package/src/plugins/reference_analysis/js/jsenv_plugin_js_reference_analysis.js +161 -0
- package/src/plugins/reference_analysis/jsenv_plugin_reference_analysis.js +120 -0
- package/src/plugins/{url_analysis → reference_analysis}/jsenv_plugin_reference_expected_types.js +19 -12
- package/src/plugins/{url_analysis/webmanifest/webmanifest_urls.js → reference_analysis/webmanifest/jsenv_plugin_webmanifest_reference_analysis.js} +13 -1
- package/src/plugins/resolution_node_esm/jsenv_plugin_node_esm_resolution.js +74 -0
- package/src/plugins/{url_resolution → resolution_node_esm}/node_esm_resolver.js +8 -0
- package/src/plugins/resolution_web/jsenv_plugin_web_resolution.js +45 -0
- package/src/plugins/transpilation/as_js_module/jsenv_plugin_as_js_module.js +1 -1
- package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +1 -1
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +4 -6
- package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_conversion.js +1 -1
- package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_inside_html.js +4 -6
- package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_on_workers.js +1 -1
- package/src/plugins/url_type_from_reference.js +13 -0
- package/src/plugins/{url_version/jsenv_plugin_url_version.js → version_search_param/jsenv_plugin_version_search_param.js} +4 -4
- package/dist/html/explorer.html +0 -559
- package/dist/other/jsenv.png +0 -0
- package/src/plugins/explorer/client/explorer.html +0 -608
- package/src/plugins/explorer/client/jsenv.png +0 -0
- package/src/plugins/explorer/jsenv_plugin_explorer.js +0 -86
- package/src/plugins/inline_content_analysis/client/inline_content.js +0 -6
- package/src/plugins/inline_content_analysis/jsenv_plugin_html_inline_content_analysis.js +0 -206
- package/src/plugins/inline_content_analysis/jsenv_plugin_inline_content_analysis.js +0 -34
- package/src/plugins/inline_content_analysis/jsenv_plugin_js_inline_content_analysis.js +0 -314
- package/src/plugins/url_analysis/html/html_urls.js +0 -313
- package/src/plugins/url_analysis/js/js_urls.js +0 -65
- package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +0 -116
- package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +0 -140
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* This plugin ensure content inlined inside HTML is cooked (inline <script> for instance)
|
|
3
|
-
* For <script hot-accept> the script content will be moved to a virtual file
|
|
4
|
-
* to enable hot reloading
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { generateInlineContentUrl } from "@jsenv/urls";
|
|
8
|
-
import {
|
|
9
|
-
parseHtmlString,
|
|
10
|
-
stringifyHtmlAst,
|
|
11
|
-
visitHtmlNodes,
|
|
12
|
-
getHtmlNodeText,
|
|
13
|
-
getHtmlNodePosition,
|
|
14
|
-
analyzeScriptNode,
|
|
15
|
-
setHtmlNodeAttributes,
|
|
16
|
-
setHtmlNodeText,
|
|
17
|
-
removeHtmlNodeText,
|
|
18
|
-
getHtmlNodeAttribute,
|
|
19
|
-
} from "@jsenv/ast";
|
|
20
|
-
import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js";
|
|
21
|
-
|
|
22
|
-
export const jsenvPluginHtmlInlineContentAnalysis = ({
|
|
23
|
-
analyzeConvertedScripts,
|
|
24
|
-
}) => {
|
|
25
|
-
const cookInlineContent = async ({
|
|
26
|
-
context,
|
|
27
|
-
inlineContentUrlInfo,
|
|
28
|
-
inlineContentReference,
|
|
29
|
-
}) => {
|
|
30
|
-
try {
|
|
31
|
-
await context.cook(inlineContentUrlInfo, {
|
|
32
|
-
reference: inlineContentReference,
|
|
33
|
-
});
|
|
34
|
-
} catch (e) {
|
|
35
|
-
if (e.code === "PARSE_ERROR") {
|
|
36
|
-
// When something like <style> or <script> contains syntax error
|
|
37
|
-
// the HTML in itself it still valid
|
|
38
|
-
// keep the syntax error and continue with the HTML
|
|
39
|
-
const messageStart =
|
|
40
|
-
inlineContentUrlInfo.type === "css"
|
|
41
|
-
? `Syntax error on css declared inside <style>`
|
|
42
|
-
: `Syntax error on js declared inside <script>`;
|
|
43
|
-
|
|
44
|
-
context.logger.error(`${messageStart}: ${e.cause.reasonCode}
|
|
45
|
-
${e.traceMessage}`);
|
|
46
|
-
} else {
|
|
47
|
-
throw e;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
name: "jsenv:html_inline_content_analysis",
|
|
54
|
-
appliesDuring: "*",
|
|
55
|
-
transformUrlContent: {
|
|
56
|
-
html: async (urlInfo, context) => {
|
|
57
|
-
const htmlAst = parseHtmlString(urlInfo.content);
|
|
58
|
-
const mutations = [];
|
|
59
|
-
const actions = [];
|
|
60
|
-
visitHtmlNodes(htmlAst, {
|
|
61
|
-
style: (styleNode) => {
|
|
62
|
-
const styleNodeText = getHtmlNodeText(styleNode);
|
|
63
|
-
if (!styleNodeText) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
const { line, column, lineEnd, columnEnd, isOriginal } =
|
|
67
|
-
getHtmlNodePosition(styleNode, {
|
|
68
|
-
preferOriginal: true,
|
|
69
|
-
});
|
|
70
|
-
const inlineStyleUrl = generateInlineContentUrl({
|
|
71
|
-
url: urlInfo.url,
|
|
72
|
-
extension: ".css",
|
|
73
|
-
line,
|
|
74
|
-
column,
|
|
75
|
-
lineEnd,
|
|
76
|
-
columnEnd,
|
|
77
|
-
});
|
|
78
|
-
const debug =
|
|
79
|
-
getHtmlNodeAttribute(styleNode, "jsenv-debug") !== undefined;
|
|
80
|
-
const [inlineStyleReference, inlineStyleUrlInfo] =
|
|
81
|
-
context.referenceUtils.foundInline({
|
|
82
|
-
node: styleNode,
|
|
83
|
-
type: "style",
|
|
84
|
-
expectedType: "css",
|
|
85
|
-
isOriginalPosition: isOriginal,
|
|
86
|
-
// we remove 1 to the line because imagine the following html:
|
|
87
|
-
// <style>body { color: red; }</style>
|
|
88
|
-
// -> content starts same line as <style>
|
|
89
|
-
specifierLine: line - 1,
|
|
90
|
-
specifierColumn: column,
|
|
91
|
-
specifier: inlineStyleUrl,
|
|
92
|
-
contentType: "text/css",
|
|
93
|
-
content: styleNodeText,
|
|
94
|
-
debug,
|
|
95
|
-
});
|
|
96
|
-
actions.push(async () => {
|
|
97
|
-
await cookInlineContent({
|
|
98
|
-
context,
|
|
99
|
-
inlineContentUrlInfo: inlineStyleUrlInfo,
|
|
100
|
-
inlineContentReference: inlineStyleReference,
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
mutations.push(() => {
|
|
104
|
-
setHtmlNodeText(styleNode, inlineStyleUrlInfo.content, {
|
|
105
|
-
indentation: false, // indentation would decrease strack trace precision
|
|
106
|
-
});
|
|
107
|
-
setHtmlNodeAttributes(styleNode, {
|
|
108
|
-
"jsenv-cooked-by": "jsenv:html_inline_content_analysis",
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
},
|
|
112
|
-
script: (scriptNode) => {
|
|
113
|
-
const scriptNodeText = getHtmlNodeText(scriptNode);
|
|
114
|
-
if (!scriptNodeText) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
// If the inline script was already handled by an other plugin, ignore it
|
|
118
|
-
// - we want to preserve inline scripts generated by html supervisor during dev
|
|
119
|
-
// - we want to avoid cooking twice a script during build
|
|
120
|
-
if (
|
|
121
|
-
!analyzeConvertedScripts &&
|
|
122
|
-
getHtmlNodeAttribute(scriptNode, "jsenv-injected-by") ===
|
|
123
|
-
"jsenv:js_module_fallback"
|
|
124
|
-
) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const hotAccept =
|
|
129
|
-
getHtmlNodeAttribute(scriptNode, "hot-accept") !== undefined;
|
|
130
|
-
const { type, contentType, extension } =
|
|
131
|
-
analyzeScriptNode(scriptNode);
|
|
132
|
-
const { line, column, lineEnd, columnEnd, isOriginal } =
|
|
133
|
-
getHtmlNodePosition(scriptNode, {
|
|
134
|
-
preferOriginal: true,
|
|
135
|
-
});
|
|
136
|
-
let inlineScriptUrl = generateInlineContentUrl({
|
|
137
|
-
url: urlInfo.url,
|
|
138
|
-
extension: extension || CONTENT_TYPE.asFileExtension(contentType),
|
|
139
|
-
line,
|
|
140
|
-
column,
|
|
141
|
-
lineEnd,
|
|
142
|
-
columnEnd,
|
|
143
|
-
});
|
|
144
|
-
const debug =
|
|
145
|
-
getHtmlNodeAttribute(scriptNode, "jsenv-debug") !== undefined;
|
|
146
|
-
const [inlineScriptReference, inlineScriptUrlInfo] =
|
|
147
|
-
context.referenceUtils.foundInline({
|
|
148
|
-
node: scriptNode,
|
|
149
|
-
type: "script",
|
|
150
|
-
expectedType: type,
|
|
151
|
-
// we remove 1 to the line because imagine the following html:
|
|
152
|
-
// <script>console.log('ok')</script>
|
|
153
|
-
// -> content starts same line as <script>
|
|
154
|
-
specifierLine: line - 1,
|
|
155
|
-
specifierColumn: column,
|
|
156
|
-
isOriginalPosition: isOriginal,
|
|
157
|
-
specifier: inlineScriptUrl,
|
|
158
|
-
contentType,
|
|
159
|
-
content: scriptNodeText,
|
|
160
|
-
debug,
|
|
161
|
-
});
|
|
162
|
-
actions.push(async () => {
|
|
163
|
-
await cookInlineContent({
|
|
164
|
-
context,
|
|
165
|
-
inlineContentUrlInfo: inlineScriptUrlInfo,
|
|
166
|
-
inlineContentReference: inlineScriptReference,
|
|
167
|
-
});
|
|
168
|
-
mutations.push(() => {
|
|
169
|
-
const attributes = {
|
|
170
|
-
"jsenv-cooked-by": "jsenv:html_inline_content_analysis",
|
|
171
|
-
// 1. <script type="jsx"> becomes <script>
|
|
172
|
-
// 2. <script type="module/jsx"> becomes <script type="module">
|
|
173
|
-
...(extension
|
|
174
|
-
? { type: type === "js_module" ? "module" : undefined }
|
|
175
|
-
: {}),
|
|
176
|
-
};
|
|
177
|
-
if (hotAccept) {
|
|
178
|
-
removeHtmlNodeText(scriptNode);
|
|
179
|
-
setHtmlNodeAttributes(scriptNode, {
|
|
180
|
-
...attributes,
|
|
181
|
-
});
|
|
182
|
-
} else {
|
|
183
|
-
setHtmlNodeText(scriptNode, inlineScriptUrlInfo.content, {
|
|
184
|
-
indentation: false, // indentation would decrease stack trace precision
|
|
185
|
-
});
|
|
186
|
-
setHtmlNodeAttributes(scriptNode, {
|
|
187
|
-
...attributes,
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
},
|
|
193
|
-
});
|
|
194
|
-
if (actions.length > 0) {
|
|
195
|
-
await Promise.all(actions.map((action) => action()));
|
|
196
|
-
}
|
|
197
|
-
if (mutations.length === 0) {
|
|
198
|
-
return null;
|
|
199
|
-
}
|
|
200
|
-
mutations.forEach((mutation) => mutation());
|
|
201
|
-
const htmlModified = stringifyHtmlAst(htmlAst);
|
|
202
|
-
return htmlModified;
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
};
|
|
206
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { jsenvPluginHtmlInlineContentAnalysis } from "./jsenv_plugin_html_inline_content_analysis.js";
|
|
2
|
-
import { jsenvPluginJsInlineContentAnalysis } from "./jsenv_plugin_js_inline_content_analysis.js";
|
|
3
|
-
import { jsenvPluginDataUrls } from "./jsenv_plugin_data_urls.js";
|
|
4
|
-
|
|
5
|
-
export const jsenvPluginInlineContentAnalysis = ({
|
|
6
|
-
fetchInlineUrls = true,
|
|
7
|
-
analyzeConvertedScripts = false,
|
|
8
|
-
allowEscapeForVersioning = false,
|
|
9
|
-
} = {}) => {
|
|
10
|
-
return [
|
|
11
|
-
...(fetchInlineUrls ? [jsenvPluginInlineContentFetcher()] : []),
|
|
12
|
-
jsenvPluginHtmlInlineContentAnalysis({ analyzeConvertedScripts }),
|
|
13
|
-
jsenvPluginJsInlineContentAnalysis({ allowEscapeForVersioning }),
|
|
14
|
-
jsenvPluginDataUrls(),
|
|
15
|
-
];
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const jsenvPluginInlineContentFetcher = () => {
|
|
19
|
-
return {
|
|
20
|
-
name: "jsenv:inline_content_fetcher",
|
|
21
|
-
appliesDuring: "*",
|
|
22
|
-
fetchUrlContent: (urlInfo) => {
|
|
23
|
-
if (!urlInfo.isInline) {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
return {
|
|
27
|
-
// we want to fetch the original content otherwise we might re-cook
|
|
28
|
-
// content already cooked
|
|
29
|
-
content: urlInfo.originalContent,
|
|
30
|
-
contentType: urlInfo.contentType,
|
|
31
|
-
};
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
};
|
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
import { generateInlineContentUrl } from "@jsenv/urls";
|
|
2
|
-
import { createMagicSource } from "@jsenv/sourcemap";
|
|
3
|
-
import { applyBabelPlugins } from "@jsenv/ast";
|
|
4
|
-
import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js";
|
|
5
|
-
import { JS_QUOTES } from "@jsenv/utils/src/string/js_quotes.js";
|
|
6
|
-
|
|
7
|
-
export const jsenvPluginJsInlineContentAnalysis = ({
|
|
8
|
-
allowEscapeForVersioning,
|
|
9
|
-
}) => {
|
|
10
|
-
const parseAndTransformInlineContentCalls = async (urlInfo, context) => {
|
|
11
|
-
const inlineContentInfos = await parseJsInlineContentInfos({
|
|
12
|
-
js: urlInfo.content,
|
|
13
|
-
url: urlInfo.originalUrl,
|
|
14
|
-
isJsModule: urlInfo.type === "js_module",
|
|
15
|
-
});
|
|
16
|
-
if (inlineContentInfos.length === 0) {
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
const magicSource = createMagicSource(urlInfo.content);
|
|
20
|
-
await inlineContentInfos.reduce(async (previous, inlineContentInfo) => {
|
|
21
|
-
await previous;
|
|
22
|
-
const inlineUrl = generateInlineContentUrl({
|
|
23
|
-
url: urlInfo.url,
|
|
24
|
-
extension: CONTENT_TYPE.asFileExtension(inlineContentInfo.contentType),
|
|
25
|
-
line: inlineContentInfo.line,
|
|
26
|
-
column: inlineContentInfo.column,
|
|
27
|
-
lineEnd: inlineContentInfo.lineEnd,
|
|
28
|
-
columnEnd: inlineContentInfo.columnEnd,
|
|
29
|
-
});
|
|
30
|
-
let { quote } = inlineContentInfo;
|
|
31
|
-
if (
|
|
32
|
-
quote === "`" &&
|
|
33
|
-
!context.isSupportedOnCurrentClients("template_literals")
|
|
34
|
-
) {
|
|
35
|
-
// if quote is "`" and template literals are not supported
|
|
36
|
-
// we'll use a regular string (single or double quote)
|
|
37
|
-
// when rendering the string
|
|
38
|
-
quote = JS_QUOTES.pickBest(inlineContentInfo.content);
|
|
39
|
-
}
|
|
40
|
-
const [inlineReference, inlineUrlInfo] =
|
|
41
|
-
context.referenceUtils.foundInline({
|
|
42
|
-
type: "js_inline_content",
|
|
43
|
-
subtype: inlineContentInfo.type, // "new_blob_first_arg", "new_inline_content_first_arg", "json_parse_first_arg"
|
|
44
|
-
isOriginalPosition: urlInfo.content === urlInfo.originalContent,
|
|
45
|
-
specifierLine: inlineContentInfo.line,
|
|
46
|
-
specifierColumn: inlineContentInfo.column,
|
|
47
|
-
specifier: inlineUrl,
|
|
48
|
-
contentType: inlineContentInfo.contentType,
|
|
49
|
-
content: inlineContentInfo.content,
|
|
50
|
-
});
|
|
51
|
-
inlineUrlInfo.jsQuote = quote;
|
|
52
|
-
inlineReference.escape = (value) =>
|
|
53
|
-
JS_QUOTES.escapeSpecialChars(value.slice(1, -1), { quote });
|
|
54
|
-
await context.cook(inlineUrlInfo, { reference: inlineReference });
|
|
55
|
-
magicSource.replace({
|
|
56
|
-
start: inlineContentInfo.start,
|
|
57
|
-
end: inlineContentInfo.end,
|
|
58
|
-
replacement: JS_QUOTES.escapeSpecialChars(inlineUrlInfo.content, {
|
|
59
|
-
quote,
|
|
60
|
-
allowEscapeForVersioning,
|
|
61
|
-
}),
|
|
62
|
-
});
|
|
63
|
-
}, Promise.resolve());
|
|
64
|
-
return magicSource.toContentAndSourcemap();
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
name: "jsenv:js_inline_content_analysis",
|
|
69
|
-
appliesDuring: "*",
|
|
70
|
-
transformUrlContent: {
|
|
71
|
-
js_classic: parseAndTransformInlineContentCalls,
|
|
72
|
-
js_module: parseAndTransformInlineContentCalls,
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const parseJsInlineContentInfos = async ({ js, url, isJsModule }) => {
|
|
78
|
-
if (
|
|
79
|
-
!js.includes("InlineContent") &&
|
|
80
|
-
!js.includes("new Blob(") &&
|
|
81
|
-
!js.includes("JSON.parse(")
|
|
82
|
-
) {
|
|
83
|
-
return [];
|
|
84
|
-
}
|
|
85
|
-
const { metadata } = await applyBabelPlugins({
|
|
86
|
-
babelPlugins: [babelPluginMetadataInlineContents],
|
|
87
|
-
urlInfo: {
|
|
88
|
-
originalUrl: url,
|
|
89
|
-
type: isJsModule ? "js_module" : "js_classic",
|
|
90
|
-
content: js,
|
|
91
|
-
},
|
|
92
|
-
});
|
|
93
|
-
return metadata.inlineContentInfos;
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
const babelPluginMetadataInlineContents = () => {
|
|
97
|
-
return {
|
|
98
|
-
name: "metadata-inline-contents",
|
|
99
|
-
visitor: {
|
|
100
|
-
Program: (programPath, state) => {
|
|
101
|
-
const inlineContentInfos = [];
|
|
102
|
-
const onInlineContentInfo = (inlineContentInfo) => {
|
|
103
|
-
inlineContentInfos.push(inlineContentInfo);
|
|
104
|
-
};
|
|
105
|
-
programPath.traverse({
|
|
106
|
-
NewExpression: (path) => {
|
|
107
|
-
if (isNewInlineContentCall(path)) {
|
|
108
|
-
analyzeNewInlineContentCall(path.node, {
|
|
109
|
-
onInlineContentInfo,
|
|
110
|
-
});
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
if (isNewBlobCall(path.node)) {
|
|
114
|
-
analyzeNewBlobCall(path.node, {
|
|
115
|
-
onInlineContentInfo,
|
|
116
|
-
});
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
CallExpression: (path) => {
|
|
121
|
-
const node = path.node;
|
|
122
|
-
if (isJSONParseCall(node)) {
|
|
123
|
-
analyzeJsonParseCall(node, {
|
|
124
|
-
onInlineContentInfo,
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
},
|
|
128
|
-
});
|
|
129
|
-
state.file.metadata.inlineContentInfos = inlineContentInfos;
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
};
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
const isNewInlineContentCall = (path) => {
|
|
136
|
-
const node = path.node;
|
|
137
|
-
if (node.callee.type === "Identifier") {
|
|
138
|
-
// terser rename import to use a shorter name
|
|
139
|
-
const name = getOriginalName(path, node.callee.name);
|
|
140
|
-
return name === "InlineContent";
|
|
141
|
-
}
|
|
142
|
-
if (node.callee.id && node.callee.id.type === "Identifier") {
|
|
143
|
-
const name = getOriginalName(path, node.callee.id.name);
|
|
144
|
-
return name === "InlineContent";
|
|
145
|
-
}
|
|
146
|
-
return false;
|
|
147
|
-
};
|
|
148
|
-
const analyzeNewInlineContentCall = (node, { onInlineContentInfo }) => {
|
|
149
|
-
analyzeArguments({
|
|
150
|
-
node,
|
|
151
|
-
onInlineContentInfo,
|
|
152
|
-
nodeHoldingContent: node.arguments[0],
|
|
153
|
-
type: "new_inline_content_first_arg",
|
|
154
|
-
});
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
const isNewBlobCall = (node) => {
|
|
158
|
-
return node.callee.type === "Identifier" && node.callee.name === "Blob";
|
|
159
|
-
};
|
|
160
|
-
const analyzeNewBlobCall = (node, { onInlineContentInfo }) => {
|
|
161
|
-
const firstArg = node.arguments[0];
|
|
162
|
-
if (!firstArg) {
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
if (firstArg.type !== "ArrayExpression") {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
if (firstArg.elements.length !== 1) {
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
analyzeArguments({
|
|
172
|
-
node,
|
|
173
|
-
onInlineContentInfo,
|
|
174
|
-
nodeHoldingContent: firstArg.elements[0],
|
|
175
|
-
type: "new_blob_first_arg",
|
|
176
|
-
});
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
const analyzeArguments = ({
|
|
180
|
-
node,
|
|
181
|
-
onInlineContentInfo,
|
|
182
|
-
nodeHoldingContent,
|
|
183
|
-
type,
|
|
184
|
-
}) => {
|
|
185
|
-
if (node.arguments.length !== 2) {
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
const [, secondArg] = node.arguments;
|
|
189
|
-
const typePropertyNode = getTypePropertyNode(secondArg);
|
|
190
|
-
if (!typePropertyNode) {
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
const typePropertyValueNode = typePropertyNode.value;
|
|
194
|
-
if (typePropertyValueNode.type !== "StringLiteral") {
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
const contentType = typePropertyValueNode.value;
|
|
198
|
-
const contentDetails = extractContentDetails(nodeHoldingContent);
|
|
199
|
-
if (contentDetails) {
|
|
200
|
-
onInlineContentInfo({
|
|
201
|
-
node: nodeHoldingContent,
|
|
202
|
-
...getNodePosition(nodeHoldingContent),
|
|
203
|
-
type,
|
|
204
|
-
contentType,
|
|
205
|
-
...contentDetails,
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
const extractContentDetails = (node) => {
|
|
210
|
-
if (node.type === "StringLiteral") {
|
|
211
|
-
return {
|
|
212
|
-
nodeType: "StringLiteral",
|
|
213
|
-
quote: node.extra.raw[0],
|
|
214
|
-
content: node.value,
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
if (node.type === "TemplateLiteral") {
|
|
218
|
-
const quasis = node.quasis;
|
|
219
|
-
if (quasis.length !== 1) {
|
|
220
|
-
return null;
|
|
221
|
-
}
|
|
222
|
-
const templateElementNode = quasis[0];
|
|
223
|
-
return {
|
|
224
|
-
nodeType: "TemplateLiteral",
|
|
225
|
-
quote: "`",
|
|
226
|
-
content: templateElementNode.value.cooked,
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
return null;
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
const isJSONParseCall = (node) => {
|
|
233
|
-
const callee = node.callee;
|
|
234
|
-
return (
|
|
235
|
-
callee.type === "MemberExpression" &&
|
|
236
|
-
callee.object.type === "Identifier" &&
|
|
237
|
-
callee.object.name === "JSON" &&
|
|
238
|
-
callee.property.type === "Identifier" &&
|
|
239
|
-
callee.property.name === "parse"
|
|
240
|
-
);
|
|
241
|
-
};
|
|
242
|
-
const analyzeJsonParseCall = (node, { onInlineContentInfo }) => {
|
|
243
|
-
const firstArgNode = node.arguments[0];
|
|
244
|
-
const contentDetails = extractContentDetails(firstArgNode);
|
|
245
|
-
if (contentDetails) {
|
|
246
|
-
onInlineContentInfo({
|
|
247
|
-
node: firstArgNode,
|
|
248
|
-
...getNodePosition(firstArgNode),
|
|
249
|
-
type: "json_parse_first_arg",
|
|
250
|
-
contentType: "application/json",
|
|
251
|
-
...contentDetails,
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
const getNodePosition = (node) => {
|
|
257
|
-
return {
|
|
258
|
-
start: node.start,
|
|
259
|
-
end: node.end,
|
|
260
|
-
line: node.loc.start.line,
|
|
261
|
-
column: node.loc.start.column,
|
|
262
|
-
lineEnd: node.loc.end.line,
|
|
263
|
-
columnEnd: node.loc.end.column,
|
|
264
|
-
};
|
|
265
|
-
};
|
|
266
|
-
const getOriginalName = (path, name) => {
|
|
267
|
-
const binding = path.scope.getBinding(name);
|
|
268
|
-
if (!binding) {
|
|
269
|
-
return name;
|
|
270
|
-
}
|
|
271
|
-
if (binding.path.type === "ImportSpecifier") {
|
|
272
|
-
const importedName = binding.path.node.imported.name;
|
|
273
|
-
if (name === importedName) {
|
|
274
|
-
return name;
|
|
275
|
-
}
|
|
276
|
-
return getOriginalName(path, importedName);
|
|
277
|
-
}
|
|
278
|
-
if (binding.path.type === "VariableDeclarator") {
|
|
279
|
-
const { node } = binding.path;
|
|
280
|
-
const { init } = node;
|
|
281
|
-
if (init && init.type === "Identifier") {
|
|
282
|
-
const previousName = init.name;
|
|
283
|
-
return getOriginalName(path, previousName);
|
|
284
|
-
}
|
|
285
|
-
if (node.id && node.id.type === "Identifier") {
|
|
286
|
-
const { constantViolations } = binding;
|
|
287
|
-
if (constantViolations && constantViolations.length > 0) {
|
|
288
|
-
const lastViolation = constantViolations[constantViolations.length - 1];
|
|
289
|
-
if (
|
|
290
|
-
lastViolation &&
|
|
291
|
-
lastViolation.node.type === "AssignmentExpression" &&
|
|
292
|
-
lastViolation.node.right.type === "MemberExpression" &&
|
|
293
|
-
lastViolation.node.right.property.type === "Identifier"
|
|
294
|
-
) {
|
|
295
|
-
return lastViolation.node.right.property.name;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
return name;
|
|
301
|
-
};
|
|
302
|
-
const getTypePropertyNode = (node) => {
|
|
303
|
-
if (node.type !== "ObjectExpression") {
|
|
304
|
-
return null;
|
|
305
|
-
}
|
|
306
|
-
const { properties } = node;
|
|
307
|
-
return properties.find((property) => {
|
|
308
|
-
return (
|
|
309
|
-
property.type === "ObjectProperty" &&
|
|
310
|
-
property.key.type === "Identifier" &&
|
|
311
|
-
property.key.name === "type"
|
|
312
|
-
);
|
|
313
|
-
});
|
|
314
|
-
};
|