@jsenv/core 29.9.1 → 30.0.0-alpha.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.
@@ -1,424 +0,0 @@
1
- import { pathToFileURL } from "node:url"
2
-
3
- import { URL_META } from "@jsenv/url-meta"
4
- import { isFileSystemPath } from "@jsenv/urls"
5
- import { createDetailedMessage } from "@jsenv/log"
6
- import { babelHelperNameFromUrl } from "@jsenv/babel-plugins"
7
- import { sourcemapConverter } from "@jsenv/sourcemap"
8
-
9
- import { fileUrlConverter } from "@jsenv/core/src/kitchen/file_url_converter.js"
10
-
11
- const globalThisClientFileUrl = new URL(
12
- "../../transpilation/babel/global_this/client/global_this.js",
13
- import.meta.url,
14
- ).href
15
- const newStylesheetClientFileUrl = new URL(
16
- "../../transpilation/babel/new_stylesheet/client/new_stylesheet.js",
17
- import.meta.url,
18
- ).href
19
- const regeneratorRuntimeClientFileUrl = new URL(
20
- "../../transpilation/babel/regenerator_runtime/client/regenerator_runtime.js",
21
- import.meta.url,
22
- ).href
23
-
24
- export const bundleJsModules = async ({
25
- jsModuleUrlInfos,
26
- context,
27
- options,
28
- }) => {
29
- const {
30
- signal,
31
- logger,
32
- rootDirectoryUrl,
33
- buildDirectoryUrl,
34
- assetsDirectory,
35
- urlGraph,
36
- runtimeCompat,
37
- sourcemaps,
38
- } = context
39
- const {
40
- babelHelpersChunk = true,
41
- include,
42
- preserveDynamicImport = false,
43
- strictExports = false,
44
- } = options
45
- const { jsModuleBundleUrlInfos } = await buildWithRollup({
46
- signal,
47
- logger,
48
- rootDirectoryUrl,
49
- buildDirectoryUrl,
50
- assetsDirectory,
51
- urlGraph,
52
- jsModuleUrlInfos,
53
-
54
- runtimeCompat,
55
- sourcemaps,
56
-
57
- include,
58
- babelHelpersChunk,
59
- preserveDynamicImport,
60
- strictExports,
61
- })
62
- return jsModuleBundleUrlInfos
63
- }
64
-
65
- const rollupPluginJsenv = ({
66
- // logger,
67
- rootDirectoryUrl,
68
- buildDirectoryUrl,
69
- assetsDirectory,
70
- urlGraph,
71
- jsModuleUrlInfos,
72
- sourcemaps,
73
-
74
- include,
75
- babelHelpersChunk,
76
- preserveDynamicImport,
77
- strictExports,
78
-
79
- resultRef,
80
- }) => {
81
- let _rollupEmitFile = () => {
82
- throw new Error("not implemented")
83
- }
84
- const format = jsModuleUrlInfos.some((jsModuleUrlInfo) =>
85
- jsModuleUrlInfo.filename.endsWith(".cjs"),
86
- )
87
- ? "cjs"
88
- : "esm"
89
- const emitChunk = (chunk) => {
90
- return _rollupEmitFile({
91
- type: "chunk",
92
- ...chunk,
93
- })
94
- }
95
- let importCanBeBundled = () => true
96
- if (include) {
97
- const associations = URL_META.resolveAssociations(
98
- { bundle: include },
99
- rootDirectoryUrl,
100
- )
101
- importCanBeBundled = (url) => {
102
- return URL_META.applyAssociations({ url, associations }).bundle
103
- }
104
- }
105
- const urlImporters = {}
106
-
107
- return {
108
- name: "jsenv",
109
- async buildStart() {
110
- _rollupEmitFile = (...args) => this.emitFile(...args)
111
- let previousNonEntryPointModuleId
112
- jsModuleUrlInfos.forEach((jsModuleUrlInfo) => {
113
- const id = jsModuleUrlInfo.url
114
- if (jsModuleUrlInfo.isEntryPoint) {
115
- emitChunk({
116
- id,
117
- })
118
- return
119
- }
120
- emitChunk({
121
- id,
122
- implicitlyLoadedAfterOneOf: previousNonEntryPointModuleId
123
- ? [previousNonEntryPointModuleId]
124
- : null,
125
- preserveSignature: strictExports
126
- ? "strict"
127
- : jsModuleUrlInfo.dependents.size < 2
128
- ? "allow-extension"
129
- : "strict",
130
- })
131
- previousNonEntryPointModuleId = id
132
- })
133
- },
134
- async generateBundle(outputOptions, rollupResult) {
135
- _rollupEmitFile = (...args) => this.emitFile(...args)
136
-
137
- const jsModuleBundleUrlInfos = {}
138
- Object.keys(rollupResult).forEach((fileName) => {
139
- const rollupFileInfo = rollupResult[fileName]
140
- // there is 3 types of file: "placeholder", "asset", "chunk"
141
- if (rollupFileInfo.type === "chunk") {
142
- const sourceUrls = Object.keys(rollupFileInfo.modules).map((id) =>
143
- fileUrlConverter.asFileUrl(id),
144
- )
145
-
146
- let url
147
- let originalUrl
148
- if (rollupFileInfo.facadeModuleId) {
149
- url = fileUrlConverter.asFileUrl(rollupFileInfo.facadeModuleId)
150
- originalUrl = url
151
- } else {
152
- url = new URL(rollupFileInfo.fileName, buildDirectoryUrl).href
153
- if (rollupFileInfo.isDynamicEntry) {
154
- originalUrl = sourceUrls[sourceUrls.length - 1]
155
- } else {
156
- originalUrl = url
157
- }
158
- }
159
-
160
- const jsModuleBundleUrlInfo = {
161
- url,
162
- originalUrl,
163
- type: format === "esm" ? "js_module" : "common_js",
164
- data: {
165
- bundlerName: "rollup",
166
- bundleRelativeUrl: rollupFileInfo.fileName,
167
- usesImport:
168
- rollupFileInfo.imports.length > 0 ||
169
- rollupFileInfo.dynamicImports.length > 0,
170
- isDynamicEntry: rollupFileInfo.isDynamicEntry,
171
- },
172
- sourceUrls,
173
- contentType: "text/javascript",
174
- content: rollupFileInfo.code,
175
- sourcemap: rollupFileInfo.map,
176
- }
177
- jsModuleBundleUrlInfos[url] = jsModuleBundleUrlInfo
178
- }
179
- })
180
- resultRef.current = {
181
- jsModuleBundleUrlInfos,
182
- }
183
- },
184
- outputOptions: (outputOptions) => {
185
- // const sourcemapFile = buildDirectoryUrl
186
- Object.assign(outputOptions, {
187
- format,
188
- dir: fileUrlConverter.asFilePath(buildDirectoryUrl),
189
- sourcemap: sourcemaps === "file" || sourcemaps === "inline",
190
- // sourcemapFile,
191
- sourcemapPathTransform: (relativePath) => {
192
- return new URL(relativePath, buildDirectoryUrl).href
193
- },
194
- entryFileNames: () => {
195
- return `[name].js`
196
- },
197
- chunkFileNames: (chunkInfo) => {
198
- const insideJs = willBeInsideJsDirectory({
199
- chunkInfo,
200
- fileUrlConverter,
201
- jsModuleUrlInfos,
202
- })
203
- let nameFromUrlInfo
204
- if (chunkInfo.facadeModuleId) {
205
- const url = fileUrlConverter.asFileUrl(chunkInfo.facadeModuleId)
206
- const urlInfo = jsModuleUrlInfos.find(
207
- (jsModuleUrlInfo) => jsModuleUrlInfo.url === url,
208
- )
209
- if (urlInfo) {
210
- nameFromUrlInfo = urlInfo.filename
211
- }
212
- }
213
- const name = nameFromUrlInfo || `${chunkInfo.name}.js`
214
- return insideJs ? `${assetsDirectory}js/${name}` : `${name}`
215
- },
216
- manualChunks: (id) => {
217
- if (babelHelpersChunk) {
218
- const fileUrl = fileUrlConverter.asFileUrl(id)
219
- if (
220
- fileUrl.endsWith(
221
- "babel-plugin-transform-async-to-promises/helpers.mjs",
222
- )
223
- ) {
224
- return "babel_helpers"
225
- }
226
- if (babelHelperNameFromUrl(fileUrl)) {
227
- return "babel_helpers"
228
- }
229
- if (fileUrl === globalThisClientFileUrl) {
230
- return "babel_helpers"
231
- }
232
- if (fileUrl === newStylesheetClientFileUrl) {
233
- return "babel_helpers"
234
- }
235
- if (fileUrl === regeneratorRuntimeClientFileUrl) {
236
- return "babel_helpers"
237
- }
238
- }
239
- return null
240
- },
241
- // https://rollupjs.org/guide/en/#outputpaths
242
- // paths: (id) => {
243
- // return id
244
- // },
245
- })
246
- },
247
- // https://rollupjs.org/guide/en/#resolvedynamicimport
248
- resolveDynamicImport: (specifier, importer) => {
249
- if (preserveDynamicImport) {
250
- let urlObject
251
- if (specifier[0] === "/") {
252
- urlObject = new URL(specifier.slice(1), rootDirectoryUrl)
253
- } else {
254
- if (isFileSystemPath(importer)) {
255
- importer = fileUrlConverter.asFileUrl(importer)
256
- }
257
- urlObject = new URL(specifier, importer)
258
- }
259
- urlObject.searchParams.set("as_js_classic_library", "")
260
- return { external: true, id: urlObject.href }
261
- }
262
- return null
263
- },
264
- resolveId: (specifier, importer = rootDirectoryUrl) => {
265
- if (isFileSystemPath(importer)) {
266
- importer = fileUrlConverter.asFileUrl(importer)
267
- }
268
- let url
269
- if (specifier[0] === "/") {
270
- url = new URL(specifier.slice(1), rootDirectoryUrl).href
271
- } else {
272
- url = new URL(specifier, importer).href
273
- }
274
- const existingImporter = urlImporters[url]
275
- if (!existingImporter) {
276
- urlImporters[url] = importer
277
- }
278
- if (!url.startsWith("file:")) {
279
- return { id: url, external: true }
280
- }
281
- if (!importCanBeBundled(url)) {
282
- return { id: url, external: true }
283
- }
284
- const urlInfo = urlGraph.getUrlInfo(url)
285
- if (!urlInfo) {
286
- // happen when excluded by urlAnalysis.include
287
- return { id: url, external: true }
288
- }
289
- if (!urlInfo.shouldHandle) {
290
- return { id: url, external: true }
291
- }
292
- const filePath = fileUrlConverter.asFilePath(url)
293
- return filePath
294
- },
295
- async load(rollupId) {
296
- const fileUrl = fileUrlConverter.asFileUrl(rollupId)
297
- const urlInfo = urlGraph.getUrlInfo(fileUrl)
298
- return {
299
- code: urlInfo.content,
300
- map:
301
- (sourcemaps === "file" || sourcemaps === "inline") &&
302
- urlInfo.sourcemap
303
- ? sourcemapConverter.toFilePaths(urlInfo.sourcemap)
304
- : null,
305
- }
306
- },
307
- }
308
- }
309
-
310
- const buildWithRollup = async ({
311
- signal,
312
- logger,
313
- rootDirectoryUrl,
314
- buildDirectoryUrl,
315
- assetsDirectory,
316
- urlGraph,
317
- jsModuleUrlInfos,
318
-
319
- runtimeCompat,
320
- sourcemaps,
321
-
322
- include,
323
- babelHelpersChunk,
324
- preserveDynamicImport,
325
- }) => {
326
- const resultRef = { current: null }
327
- try {
328
- await applyRollupPlugins({
329
- rollupPlugins: [
330
- rollupPluginJsenv({
331
- signal,
332
- logger,
333
- rootDirectoryUrl,
334
- buildDirectoryUrl,
335
- assetsDirectory,
336
- urlGraph,
337
- jsModuleUrlInfos,
338
-
339
- runtimeCompat,
340
- sourcemaps,
341
- include,
342
- babelHelpersChunk,
343
- preserveDynamicImport,
344
- resultRef,
345
- }),
346
- ],
347
- inputOptions: {
348
- input: [],
349
- onwarn: (warning) => {
350
- if (warning.code === "CIRCULAR_DEPENDENCY") {
351
- return
352
- }
353
- if (
354
- warning.code === "THIS_IS_UNDEFINED" &&
355
- pathToFileURL(warning.id).href === globalThisClientFileUrl
356
- ) {
357
- return
358
- }
359
- if (warning.code === "EVAL") {
360
- // ideally we should disable only for jsenv files
361
- return
362
- }
363
- logger.warn(String(warning))
364
- },
365
- },
366
- })
367
- return resultRef.current
368
- } catch (e) {
369
- if (e.code === "MISSING_EXPORT") {
370
- const detailedMessage = createDetailedMessage(e.message, {
371
- frame: e.frame,
372
- })
373
- throw new Error(detailedMessage, { cause: e })
374
- }
375
- throw e
376
- }
377
- }
378
-
379
- const applyRollupPlugins = async ({
380
- rollupPlugins,
381
- inputOptions = {},
382
- outputOptions = {},
383
- }) => {
384
- const { rollup } = await import("rollup")
385
- const { importAssertions } = await import("acorn-import-assertions")
386
- const rollupReturnValue = await rollup({
387
- ...inputOptions,
388
- plugins: rollupPlugins,
389
- acornInjectPlugins: [
390
- importAssertions,
391
- ...(inputOptions.acornInjectPlugins || []),
392
- ],
393
- })
394
- const rollupOutputArray = await rollupReturnValue.generate(outputOptions)
395
- return rollupOutputArray
396
- }
397
-
398
- const willBeInsideJsDirectory = ({
399
- chunkInfo,
400
- fileUrlConverter,
401
- jsModuleUrlInfos,
402
- }) => {
403
- // if the chunk is generated dynamically by rollup
404
- // for an entry point jsenv will put that file inside js/ directory
405
- // if it's generated dynamically for a file already in js/ directory
406
- // both will be inside the js/ directory
407
- if (!chunkInfo.facadeModuleId) {
408
- // generated by rollup
409
- return true
410
- }
411
- const url = fileUrlConverter.asFileUrl(chunkInfo.facadeModuleId)
412
- const jsModuleUrlInfo = jsModuleUrlInfos.find(
413
- (jsModuleUrlInfo) => jsModuleUrlInfo.url === url,
414
- )
415
- if (!jsModuleUrlInfo) {
416
- // generated by rollup
417
- return true
418
- }
419
- if (!jsModuleUrlInfo.isEntryPoint) {
420
- // not an entry point, jsenv will put it inside js/ directory
421
- return true
422
- }
423
- return false
424
- }
@@ -1,52 +0,0 @@
1
- import { bundleCss } from "./css/bundle_css.js"
2
- import { bundleJsClassicWorkers } from "./js_classic_workers/bundle_js_classic_workers.js"
3
- import { bundleJsModules } from "./js_module/bundle_js_modules.js"
4
-
5
- export const jsenvPluginBundling = (bundling) => {
6
- if (typeof bundling === "boolean") {
7
- bundling = {
8
- css: bundling,
9
- js_classic_workers: bundling,
10
- js_module: bundling,
11
- }
12
- } else if (typeof bundling !== "object") {
13
- throw new Error(`bundling must be a boolean or an object, got ${bundling}`)
14
- }
15
- Object.keys(bundling).forEach((key) => {
16
- if (bundling[key] === true) bundling[key] = {}
17
- })
18
-
19
- return {
20
- name: "jsenv:bundling",
21
- appliesDuring: "build",
22
- bundle: {
23
- css: bundling.css
24
- ? (cssUrlInfos, context) => {
25
- return bundleCss({
26
- cssUrlInfos,
27
- context,
28
- options: bundling.css,
29
- })
30
- }
31
- : undefined,
32
- js_classic: bundling.js_classic
33
- ? (jsClassicUrlInfos, context) => {
34
- return bundleJsClassicWorkers({
35
- jsClassicUrlInfos,
36
- context,
37
- options: bundling.js_classic_workers,
38
- })
39
- }
40
- : undefined,
41
- js_module: bundling.js_module
42
- ? (jsModuleUrlInfos, context) => {
43
- return bundleJsModules({
44
- jsModuleUrlInfos,
45
- context,
46
- options: bundling.js_module,
47
- })
48
- }
49
- : undefined,
50
- },
51
- }
52
- }
@@ -1,9 +0,0 @@
1
- import { minifyWithParcel } from "@jsenv/ast"
2
-
3
- export const minifyCss = ({ cssUrlInfo, context }) => {
4
- const { code, map } = minifyWithParcel(cssUrlInfo, context)
5
- return {
6
- content: String(code),
7
- sourcemap: map,
8
- }
9
- }
@@ -1,13 +0,0 @@
1
- import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
2
-
3
- // https://github.com/kangax/html-minifier#options-quick-reference
4
- export const minifyHtml = ({ htmlUrlInfo, options } = {}) => {
5
- const { collapseWhitespace = true, removeComments = true } = options
6
-
7
- const { minify } = requireFromJsenv("html-minifier")
8
- const htmlMinified = minify(htmlUrlInfo.content, {
9
- collapseWhitespace,
10
- removeComments,
11
- })
12
- return htmlMinified
13
- }
@@ -1,31 +0,0 @@
1
- // https://github.com/terser-js/terser#minify-options
2
-
3
- export const minifyJs = async ({ jsUrlInfo, options }) => {
4
- const url = jsUrlInfo.url
5
- const content = jsUrlInfo.content
6
- const sourcemap = jsUrlInfo.sourcemap
7
- const isJsModule = jsUrlInfo.type === "js_module"
8
-
9
- const { minify } = await import("terser")
10
- const terserResult = await minify(
11
- {
12
- [url]: content,
13
- },
14
- {
15
- sourceMap: {
16
- ...(sourcemap ? { content: JSON.stringify(sourcemap) } : {}),
17
- asObject: true,
18
- includeSources: true,
19
- },
20
- module: isJsModule,
21
- // We need to preserve "new InlineContent()" calls to be able to recognize them
22
- // after minification in order to version urls inside inline content text
23
- keep_fnames: /InlineContent/,
24
- ...options,
25
- },
26
- )
27
- return {
28
- content: terserResult.code,
29
- sourcemap: terserResult.map,
30
- }
31
- }
@@ -1,79 +0,0 @@
1
- import { minifyHtml } from "./html/minify_html.js"
2
- import { minifyCss } from "./css/minify_css.js"
3
- import { minifyJs } from "./js/minify_js.js"
4
- import { minifyJson } from "./json/minify_json.js"
5
-
6
- export const jsenvPluginMinification = (minification) => {
7
- if (typeof minification === "boolean") {
8
- minification = {
9
- html: minification,
10
- css: minification,
11
- js_classic: minification,
12
- js_module: minification,
13
- json: minification,
14
- svg: minification,
15
- }
16
- } else if (typeof minification !== "object") {
17
- throw new Error(
18
- `minification must be a boolean or an object, got ${minification}`,
19
- )
20
- }
21
- Object.keys(minification).forEach((key) => {
22
- if (minification[key] === true) minification[key] = {}
23
- })
24
- const htmlOptimizer = minification.html
25
- ? (urlInfo, context) =>
26
- minifyHtml({
27
- htmlUrlInfo: urlInfo,
28
- context,
29
- options: minification.html,
30
- })
31
- : null
32
- const jsonOptimizer = minification.json
33
- ? (urlInfo, context) =>
34
- minifyJson({
35
- jsonUrlInfo: urlInfo,
36
- context,
37
- options: minification.json,
38
- })
39
- : null
40
- const cssOptimizer = minification.css
41
- ? (urlInfo, context) =>
42
- minifyCss({
43
- cssUrlInfo: urlInfo,
44
- context,
45
- options: minification.css,
46
- })
47
- : null
48
- const jsClassicOptimizer = minification.js_classic
49
- ? (urlInfo, context) =>
50
- minifyJs({
51
- jsUrlInfo: urlInfo,
52
- context,
53
- options: minification.js_classic,
54
- })
55
- : null
56
- const jsModuleOptimizer = minification.js_module
57
- ? (urlInfo, context) =>
58
- minifyJs({
59
- jsUrlInfo: urlInfo,
60
- context,
61
- options: minification.js_module,
62
- })
63
- : null
64
-
65
- return {
66
- name: "jsenv:minification",
67
- appliesDuring: "build",
68
- optimizeUrlContent: {
69
- html: htmlOptimizer,
70
- svg: htmlOptimizer,
71
- css: cssOptimizer,
72
- js_classic: jsClassicOptimizer,
73
- js_module: jsModuleOptimizer,
74
- json: jsonOptimizer,
75
- importmap: jsonOptimizer,
76
- webmanifest: jsonOptimizer,
77
- },
78
- }
79
- }
@@ -1,8 +0,0 @@
1
- export const minifyJson = ({ jsonUrlInfo }) => {
2
- const { content } = jsonUrlInfo
3
- if (content.startsWith("{\n")) {
4
- const jsonWithoutWhitespaces = JSON.stringify(JSON.parse(content))
5
- return jsonWithoutWhitespaces
6
- }
7
- return null
8
- }