requirejs-esm 4.1.0 → 4.3.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": "requirejs-esm",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "A RequireJS plugin converting JavaScript modules from ESM to AMD.",
5
5
  "author": "Ferdinand Prantl <prantlf@gmail.com>",
6
6
  "license": "MIT",
@@ -41,7 +41,7 @@
41
41
  "demo:local": "npm run optimize:local && npm run minify:local",
42
42
  "optimize:local": "r.js -o demo-local/build.config.js",
43
43
  "minify:local": "terser -cm --ecma 2018 --comments false --source-map content=demo-local/main-built.js.map --source-map includeSources --source-map url=main-built.min.js.map -o demo-local/main-built.min.js demo-local/main-built.js",
44
- "lint": "eslint src bin perf/*.js bin test/*.js",
44
+ "lint": "biome lint src bin perf/*.js bin test/*.js",
45
45
  "fix": "npm run lint -- --fix",
46
46
  "check": "tehanu test/*.js",
47
47
  "cover": "c8 node test && c8 --no-clean ./bin/esm2requirejs.js && c8 --no-clean ./bin/esm2requirejs.js test/input/esm-import-all.js && c8 --no-clean ./bin/esm2requirejs.js dummy || c8 report -r text -r lcov | grep -Ev '(\\.\\.\\.)|(index.mjs)|(source-map.js)|(base64-vlq.js)|(base64.js)|(binary-search.js)|(mapping-list.js)|(read-wasm-browser.js)|(url-browser.js)|(wasm.js)|(regexes.js)|(public-api.js)|(All files)' && c8 check-coverage",
@@ -71,27 +71,25 @@
71
71
  "@prantlf/convert-source-map": "^3.0.2",
72
72
  "astring": "^1.9.0",
73
73
  "charcodes": "^0.2.1",
74
- "commander": "^14.0.2",
75
- "meriyah": "^7.0.0",
74
+ "commander": "^14.0.3",
75
+ "meriyah": "^7.1.0",
76
76
  "punycode": "^2.3.1",
77
77
  "source-map": "^0.8.0-beta.0",
78
78
  "tiny-glob": "^0.2.9"
79
79
  },
80
80
  "devDependencies": {
81
- "@eslint/js": "^9.39.1",
81
+ "@biomejs/biome": "^2.4.14",
82
82
  "@prantlf/requirejs": "^3.3.1",
83
- "@rollup/plugin-commonjs": "^29.0.0",
83
+ "@rollup/plugin-commonjs": "^29.0.2",
84
84
  "@rollup/plugin-json": "^6.1.0",
85
85
  "@rollup/plugin-node-resolve": "^16.0.3",
86
- "c8": "^10.1.3",
87
- "eslint": "^9.39.1",
88
- "globals": "^16.5.0",
86
+ "c8": "^11.0.0",
89
87
  "lit-html": "^1",
90
- "rollup": "^4.53.3",
88
+ "rollup": "^4.60.2",
91
89
  "tehanu": "^1.0.1",
92
90
  "tehanu-repo-coco": "^1.0.1",
93
91
  "tehanu-teru": "^1.0.1",
94
- "terser": "^5.44.1"
92
+ "terser": "^5.46.2"
95
93
  },
96
94
  "keywords": [
97
95
  "requirejs-plugin",
package/src/api.d.ts CHANGED
@@ -26,7 +26,9 @@ type OnAfterUpdate = (options: AmdOptions) => boolean
26
26
  interface TransformAstOptions {
27
27
  pluginName?: string /*= 'esm'' */
28
28
  resolvePath?: ResolvePath
29
+ skipIfNoImportExport?: boolean /*= false */
29
30
  useStrict?: boolean /*= true */
31
+ sourceMap?: boolean /*= false */
30
32
  onBeforeTransform?: OnBeforeTransform
31
33
  onAfterTransform?: OnAfterTransform
32
34
  onBeforeUpdate?: OnBeforeUpdate
package/src/api.js CHANGED
@@ -1,3 +1,8 @@
1
1
  export { resolvePath } from './resolve-path'
2
2
  export { default as transform } from './transform'
3
- export { transformAst, detectDefinesOrRequires, detectImportsAndExports } from './transformer'
3
+ export {
4
+ transformAst,
5
+ detectDefinesOrRequires,
6
+ detectImportsAndExports,
7
+ processOrSkipByComment
8
+ } from './transformer'
package/src/fetch-text.js CHANGED
@@ -21,7 +21,7 @@ if (typeof window !== 'undefined' && window.navigator && window.document) {
21
21
  xhr.send(null)
22
22
  }
23
23
  } else {
24
- const { readFileSync } = require.nodeRequire ? require.nodeRequire('fs') : require('fs')
24
+ const { readFileSync } = require.nodeRequire ? require.nodeRequire('fs') : require('node:fs')
25
25
  fetchText = (path, callback) => {
26
26
  // Asynchronous reading is not possible during the build in the optimizer.
27
27
  try {
package/src/plugin.js CHANGED
@@ -16,6 +16,8 @@ const {
16
16
  onlyAmd,
17
17
  // List of module names not to check and transform.
18
18
  skipModules = [],
19
+ // Assume AMD/UMD if there're no import or export statements.
20
+ skipIfNoImportExport,
19
21
  // Method to update paths of module dependencies, to prefix JavaScript module
20
22
  // name with `esm!`, above all.
21
23
  resolvePath,
@@ -112,6 +114,7 @@ export default {
112
114
  resolvePath,
113
115
  /*ecmaVersion,*/
114
116
  useStrict,
117
+ skipIfNoImportExport,
115
118
  // Always produce the source maps when transpiling in the browser, otherwise
116
119
  // the debugging would me impossible. When building and bundling, check if
117
120
  // the source maps were enabled for the output.
@@ -156,7 +159,7 @@ export default {
156
159
  // compiled with esm refer it with that name and this stub will simplify
157
160
  // the module loading by skipping the plugin evaluation.
158
161
  write.asModule(`${pluginName}!${moduleName}`,
159
- '\ndefine([\'' + moduleName + '\'], res => res);\n')
162
+ `\ndefine(['${moduleName}'], res => res);\n`)
160
163
  }
161
164
  //>>excludeEnd('excludeEsm')
162
165
  }
@@ -71,7 +71,7 @@ export function resolvePath (sourcePath, currentFile, { pluginName, needsResolve
71
71
  // mapped there using the `paths` of `map` configuration properties.
72
72
  if ((sourcePath.charAt(0) === '.' && (sourcePath.charAt(1) === '/' ||
73
73
  sourcePath.charAt(1) === '.' && sourcePath.charAt(2) === '/')) &&
74
- !(needsResolve && needsResolve(sourcePath, currentFile))) {
74
+ !(needsResolve?.(sourcePath, currentFile))) {
75
75
  sourcePath = joinPath(parentDir(currentFile), sourcePath)
76
76
  if (sourcePath.endsWith('.js')) sourcePath = sourcePath.substring(0, sourcePath.length - 3)
77
77
  }
package/src/transform.js CHANGED
@@ -4,7 +4,7 @@ import { parseModule } from 'meriyah'
4
4
  import { generate } from 'astring'
5
5
  import { SourceMapGenerator } from 'source-map'
6
6
  import convert from '@prantlf/convert-source-map'
7
- import { transformAst } from './transformer'
7
+ import { transformAst, processOrSkipByComment } from './transformer'
8
8
 
9
9
  export default function transform(text, file, {
10
10
  // Allow using a different plugin alias than `esm` in the source code.
@@ -12,6 +12,8 @@ export default function transform(text, file, {
12
12
  // Method to update paths of module dependencies, to prefix JavaScript module
13
13
  // name with `esm!`, above all.
14
14
  resolvePath = originalResolvePath,
15
+ // Assume AMD/UMD if there're no import or export statements.
16
+ skipIfNoImportExport,
15
17
  // ecmaVersion = 2020,
16
18
  // Do not insert `"use strict"` expression to the AMD modules. You'd set it
17
19
  // to `false` if your bundler inserts `"use strict"` to the outer scope.
@@ -26,8 +28,15 @@ export default function transform(text, file, {
26
28
  onBeforeUpdate,
27
29
  onAfterUpdate
28
30
  } = {}) {
31
+ const processOrSkip = processOrSkipByComment(text)
32
+ if (processOrSkip === false) {
33
+ return { code: text, map: null, updated: false }
34
+ } else if (processOrSkip === true) {
35
+ skipIfNoImportExport = undefined;
36
+ }
37
+
29
38
  // const ast = parse(text, { ecmaVersion, sourceType: 'module', locations: true })
30
- let ast = parseModule(text, { next: true, loc: true })
39
+ const ast = parseModule(text, { next: true, loc: true })
31
40
 
32
41
  const options = {
33
42
  sourceFileName: file,
@@ -35,6 +44,7 @@ export default function transform(text, file, {
35
44
  resolvePath,
36
45
  originalResolvePath,
37
46
  useStrict,
47
+ skipIfNoImportExport,
38
48
  onBeforeTransform,
39
49
  onAfterTransform,
40
50
  onBeforeUpdate,
@@ -153,17 +153,25 @@ export function detectDefinesOrRequires(program) {
153
153
 
154
154
  // Updates dependency paths to be prefixed by `esm!` or otherwise updated.
155
155
  export function updateAmdDeps(amd, options) {
156
- options.onBeforeUpdate?.(amd)
156
+ let updated = options.onBeforeUpdate?.({
157
+ ...options,
158
+ amd
159
+ })
157
160
 
158
161
  const { deps } = amd
159
- if (!deps) return
162
+ if (!deps) {
163
+ afterUpdate()
164
+ return updated
165
+ }
160
166
 
161
167
  const { sourceFileName: parentName } = options
162
168
  const { elements } = deps
163
- if (!elements.length) return
169
+ if (!elements.length) {
170
+ afterUpdate()
171
+ return updated
172
+ }
164
173
 
165
174
  const { resolvePath } = options
166
- let updated
167
175
  for (const element of elements) {
168
176
  if (element.type === 'Literal') {
169
177
  const moduleName = element.value
@@ -175,7 +183,25 @@ export function updateAmdDeps(amd, options) {
175
183
  }
176
184
  }
177
185
 
178
- updated ||= options.onAfterUpdate?.(amd)
186
+ afterUpdate()
179
187
 
180
188
  return updated
189
+
190
+ function afterUpdate() {
191
+ const updatedNow = options.onAfterUpdate?.({
192
+ ...options,
193
+ amd
194
+ })
195
+ updated ||= updatedNow
196
+ }
197
+ }
198
+
199
+ export function callAmdUpdateHooks(amd, options) {
200
+ options = {
201
+ ...options,
202
+ amd
203
+ }
204
+ const updatedBefore = options.onBeforeUpdate?.(options)
205
+ const updatedAfter = options.onAfterUpdate?.(options)
206
+ return updatedBefore || updatedAfter
181
207
  }
@@ -0,0 +1,16 @@
1
+ // Check if one of the first 10 lines shorter than 100 characters contains
2
+ // "// requirejs-esm-skip-file" or // requirejs-esm-process-file".
3
+ export function processOrSkipByComment(text) {
4
+ for (let start = 0, i = 0; i < 10; ++i) {
5
+ const endLine = text.indexOf('\n', start)
6
+ if (endLine < 0 || endLine > 100) break
7
+ const line = text.substring(start, endLine)
8
+ const comment = /^\s*\/\//.test(line)
9
+ if (!comment) break
10
+ const directive = /^\s*\/\/\s*requirejs-esm-(skip|process)-file\s*$/.exec(line)
11
+ if (directive) {
12
+ return directive[1] === 'process'
13
+ }
14
+ start = endLine + 1
15
+ }
16
+ }
@@ -5,7 +5,7 @@ import { isValidIdentifier } from './validators'
5
5
  import { isIdentifierChar } from './identifier'
6
6
 
7
7
  export function toIdentifier(input) {
8
- input = input + ''
8
+ input = `${input}`
9
9
 
10
10
  let name = ''
11
11
  for (const c of input) {
@@ -14,9 +14,7 @@ export function toIdentifier(input) {
14
14
 
15
15
  name = name.replace(/^[-0-9]+/, '')
16
16
 
17
- name = name.replace(/[-\s]+(.)?/g, function (match, c) {
18
- return c ? c.toUpperCase() : ''
19
- })
17
+ name = name.replace(/[-\s]+(.)?/g, (_match, c) => c ? c.toUpperCase() : '')
20
18
 
21
19
  if (!isValidIdentifier(name)) {
22
20
  name = `_${name}`
@@ -149,7 +149,7 @@ export function transformEsmToAmd(program, options) {
149
149
  // expression after keyword default
150
150
  const { declaration } = statement
151
151
  let exportValue = declaration
152
- let needExportExpression = true
152
+ const needExportExpression = true
153
153
 
154
154
  if (declaration.type === 'FunctionDeclaration') {
155
155
  exportValue = toExpression(exportValue)
@@ -244,7 +244,7 @@ export function transformEsmToAmd(program, options) {
244
244
  const importVar = generateUidIdentifier(exportSource.value, program)
245
245
  importVars.push(importVar)
246
246
 
247
- for (let specifier of specifiers) {
247
+ for (const specifier of specifiers) {
248
248
  const { exported, local } = specifier
249
249
  const { name } = local
250
250
  let localName
@@ -318,6 +318,17 @@ export function transformEsmToAmd(program, options) {
318
318
  }
319
319
  }
320
320
 
321
+ // no imports and exports, do not wrap to AMD module, if AMD/UMD should be assumed
322
+ if (options.skipIfNoImportExport && !(importPaths.length || hasExport)) {
323
+ options.onAfterTransform?.({
324
+ ...options,
325
+ updated: false,
326
+ program,
327
+ callbackBody: body
328
+ })
329
+ return false
330
+ }
331
+
321
332
  // adding define wrapper
322
333
  if (hasExport && needReturnExport) {
323
334
  let returnStat
@@ -350,10 +361,13 @@ export function transformEsmToAmd(program, options) {
350
361
 
351
362
  options.onAfterTransform?.({
352
363
  ...options,
364
+ updated: true,
353
365
  program,
354
366
  callbackBody: body
355
367
  })
356
368
 
369
+ return true
370
+
357
371
  function addExportStatement({ exported, local }) {
358
372
  const asName = exported.name
359
373
  if (asName !== 'default') {
@@ -1,5 +1,6 @@
1
- import { detectDefinesOrRequires, updateAmdDeps } from './amd'
1
+ import { detectDefinesOrRequires, updateAmdDeps, callAmdUpdateHooks } from './amd'
2
2
  import { detectImportsAndExports, transformEsmToAmd } from './esm'
3
+ import { processOrSkipByComment } from './comments'
3
4
 
4
5
  export function transformAst(program, options = {}) {
5
6
  const amds = detectDefinesOrRequires(program)
@@ -7,16 +8,16 @@ export function transformAst(program, options = {}) {
7
8
  const result = {}
8
9
  if (length) {
9
10
  result.amd = true
10
- if (options.resolvePath) {
11
- for (const amd of amds) {
12
- result.updated ||= updateAmdDeps(amd, options)
13
- }
11
+ for (const amd of amds) {
12
+ const updated = options.resolvePath
13
+ ? updateAmdDeps(amd, options)
14
+ : callAmdUpdateHooks(amd, options)
15
+ result.updated ||= updated
14
16
  }
15
17
  } else {
16
- transformEsmToAmd(program, options)
17
- result.updated = true
18
+ result.updated = transformEsmToAmd(program, options)
18
19
  }
19
20
  return result
20
21
  }
21
22
 
22
- export { detectDefinesOrRequires, detectImportsAndExports }
23
+ export { detectDefinesOrRequires, detectImportsAndExports, processOrSkipByComment }
package/src/write-text.js CHANGED
@@ -5,8 +5,8 @@ let writeText
5
5
  // Initialise the writeText variable with a function to write to a file.
6
6
  /* istanbul ignore if */
7
7
  if (!(typeof window !== 'undefined' && window.navigator && window.document)) {
8
- const { writeFileSync, mkdirSync } = require.nodeRequire ? require.nodeRequire('fs') : require('fs')
9
- const { dirname } = require.nodeRequire ? require.nodeRequire('path') : require('path')
8
+ const { writeFileSync, mkdirSync } = require.nodeRequire ? require.nodeRequire('fs') : require('node:fs')
9
+ const { dirname } = require.nodeRequire ? require.nodeRequire('path') : require('node:path')
10
10
  writeText = (path, content) => {
11
11
  mkdirSync(dirname(path), { recursive: true })
12
12
  writeFileSync(path, content)