magic-comments-loader 2.0.5 → 2.1.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/README.md +13 -0
- package/dist/cjs/formatter.cjs +37 -12
- package/dist/cjs/loader.cjs +2 -0
- package/dist/cjs/parser.cjs +5 -5
- package/dist/cjs/schema.cjs +18 -3
- package/dist/formatter.js +37 -12
- package/dist/loader.js +2 -0
- package/dist/parser.js +5 -5
- package/dist/schema.js +16 -0
- package/package.json +25 -18
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@ The `webpackChunkName` comment is added by default when registering the loader.
|
|
|
46
46
|
* [`verbose`](#verbose)
|
|
47
47
|
* [`mode`](#mode)
|
|
48
48
|
* [`match`](#match)
|
|
49
|
+
* [`comments`](#comments)
|
|
49
50
|
* `[magicCommentName: string]: MagicCommentValue` see `magic-comments` [options](https://github.com/morganney/magic-comments#options) for details
|
|
50
51
|
|
|
51
52
|
### `verbose`
|
|
@@ -75,6 +76,18 @@ Sets how the loader finds dynamic import expressions in your source code, either
|
|
|
75
76
|
|
|
76
77
|
Sets how globs are matched, either the module file path, or the `import()` specifier.
|
|
77
78
|
|
|
79
|
+
### `comments`
|
|
80
|
+
**type**
|
|
81
|
+
```ts
|
|
82
|
+
'ignore' | 'prepend' | 'append' | 'replace'
|
|
83
|
+
| (cmts: Array<{ start: number; end: number; text: string }>, magicComment: string) => string
|
|
84
|
+
```
|
|
85
|
+
**default** `'ignore'`
|
|
86
|
+
|
|
87
|
+
_Note, this option only considers block comments that precede the dynamic imports specifier, and any comments coming after are ignored and left intact._
|
|
88
|
+
|
|
89
|
+
Sets how dynamic imports with block comments are handled. If `ignore` is used, then it will be skipped and no magic comments from your configuration will be applied. If `replace` is used, then all found comments will be replaced with the magic comments. `append` and `prepend` add the magic comments before, or after the found comments, respectively. If a function is used it will be passed the found comments, and the magic comment string that is to be applied. The return value has the same effect as `replace`.
|
|
90
|
+
|
|
78
91
|
## Examples
|
|
79
92
|
|
|
80
93
|
Below are examples for some of the supported magic comments. Consult the [loader specification](https://github.com/morganney/magic-comments-loader/blob/main/__tests__/loader.spec.js) for a comprehensive usage example.
|
package/dist/cjs/formatter.cjs
CHANGED
|
@@ -10,24 +10,21 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
10
10
|
const format = ({
|
|
11
11
|
match,
|
|
12
12
|
source,
|
|
13
|
-
filepath,
|
|
14
13
|
comments,
|
|
14
|
+
filepath,
|
|
15
|
+
astComments,
|
|
15
16
|
magicCommentOptions,
|
|
16
17
|
importExpressionNodes
|
|
17
18
|
}) => {
|
|
18
19
|
const magicImports = [];
|
|
19
|
-
const cmts = [...comments];
|
|
20
20
|
const src = new _magicString.default(source);
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (wasFound) {
|
|
25
|
-
cmts.splice(idx, 1);
|
|
26
|
-
}
|
|
27
|
-
return wasFound;
|
|
21
|
+
const getComments = node => {
|
|
22
|
+
// This ignores comments that come after the imports specifier.
|
|
23
|
+
return astComments.filter(cmt => cmt.start > node.start && cmt.end < node.end && cmt.start < node.source.end);
|
|
28
24
|
};
|
|
29
25
|
for (const node of importExpressionNodes) {
|
|
30
|
-
|
|
26
|
+
const cmts = getComments(node);
|
|
27
|
+
if (!cmts.length || comments !== 'ignore') {
|
|
31
28
|
const specifier = source.substring(node.source.start, node.source.end);
|
|
32
29
|
const magicComment = (0, _magicComments.getMagicComment)({
|
|
33
30
|
match,
|
|
@@ -36,8 +33,36 @@ const format = ({
|
|
|
36
33
|
options: magicCommentOptions
|
|
37
34
|
});
|
|
38
35
|
if (magicComment) {
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
const clone = src.snip(node.start, node.end);
|
|
37
|
+
if (!cmts.length) {
|
|
38
|
+
magicImports.push(clone.toString().replace(specifier, `${magicComment} ${specifier}`));
|
|
39
|
+
src.appendLeft(node.source.start, `${magicComment} `);
|
|
40
|
+
} else {
|
|
41
|
+
/**
|
|
42
|
+
* Get the minimum start and maximum end.
|
|
43
|
+
* Assumption is that comment nodes are sorted
|
|
44
|
+
* in ascending order of `node.start`.
|
|
45
|
+
*/
|
|
46
|
+
const minStart = cmts[0].start;
|
|
47
|
+
const maxEnd = cmts[cmts.length - 1].end;
|
|
48
|
+
if (comments === 'replace') {
|
|
49
|
+
magicImports.push(clone.overwrite(minStart, maxEnd, magicComment).toString());
|
|
50
|
+
src.overwrite(minStart, maxEnd, magicComment);
|
|
51
|
+
} else if (comments === 'append') {
|
|
52
|
+
magicImports.push(clone.appendRight(maxEnd, ` ${magicComment}`).toString());
|
|
53
|
+
src.appendRight(maxEnd, ` ${magicComment}`);
|
|
54
|
+
} else if (comments === 'prepend') {
|
|
55
|
+
magicImports.push(clone.prependLeft(minStart, `${magicComment} `).toString());
|
|
56
|
+
src.prependLeft(minStart, `${magicComment} `);
|
|
57
|
+
} else {
|
|
58
|
+
// Has to be a function or the schema validator is broken
|
|
59
|
+
const replacement = comments(cmts, magicComment);
|
|
60
|
+
if (typeof replacement === 'string') {
|
|
61
|
+
magicImports.push(clone.overwrite(minStart, maxEnd, replacement).toString());
|
|
62
|
+
src.overwrite(minStart, maxEnd, replacement);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
41
66
|
}
|
|
42
67
|
}
|
|
43
68
|
}
|
package/dist/cjs/loader.cjs
CHANGED
|
@@ -20,6 +20,7 @@ const loader = function (source) {
|
|
|
20
20
|
const {
|
|
21
21
|
mode = 'parser',
|
|
22
22
|
match = 'module',
|
|
23
|
+
comments = 'ignore',
|
|
23
24
|
verbose = false,
|
|
24
25
|
...rest
|
|
25
26
|
} = options;
|
|
@@ -32,6 +33,7 @@ const loader = function (source) {
|
|
|
32
33
|
...(0, _parser.parse)(source),
|
|
33
34
|
match,
|
|
34
35
|
filepath,
|
|
36
|
+
comments,
|
|
35
37
|
magicCommentOptions
|
|
36
38
|
});
|
|
37
39
|
if (verbose) {
|
package/dist/cjs/parser.cjs
CHANGED
|
@@ -21,7 +21,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
21
21
|
(0, _acornJsxWalk.extend)(_acornWalk.base);
|
|
22
22
|
const jsxParser = _acorn.Parser.extend((0, _acornJsx.default)());
|
|
23
23
|
const parse = source => {
|
|
24
|
-
const
|
|
24
|
+
const astComments = [];
|
|
25
25
|
const importExpressionNodes = [];
|
|
26
26
|
const ast = jsxParser.parse(source, {
|
|
27
27
|
locations: false,
|
|
@@ -30,12 +30,12 @@ const parse = source => {
|
|
|
30
30
|
allowAwaitOutsideFunction: true,
|
|
31
31
|
allowReturnOutsideFunction: true,
|
|
32
32
|
allowImportExportEverywhere: true,
|
|
33
|
-
onComment: (isBlock,
|
|
33
|
+
onComment: (isBlock, text, start, end) => {
|
|
34
34
|
if (isBlock) {
|
|
35
|
-
|
|
35
|
+
astComments.push({
|
|
36
36
|
start,
|
|
37
37
|
end,
|
|
38
|
-
|
|
38
|
+
text
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -47,7 +47,7 @@ const parse = source => {
|
|
|
47
47
|
});
|
|
48
48
|
return {
|
|
49
49
|
ast,
|
|
50
|
-
|
|
50
|
+
astComments,
|
|
51
51
|
importExpressionNodes,
|
|
52
52
|
source
|
|
53
53
|
};
|
package/dist/cjs/schema.cjs
CHANGED
|
@@ -5,14 +5,29 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.schema = void 0;
|
|
7
7
|
var _magicComments = require("magic-comments");
|
|
8
|
-
const schema = {
|
|
8
|
+
const schema = exports.schema = {
|
|
9
9
|
type: 'object',
|
|
10
10
|
properties: {
|
|
11
11
|
..._magicComments.schema.properties,
|
|
12
12
|
mode: {
|
|
13
13
|
enum: ['parser', 'regexp']
|
|
14
|
+
},
|
|
15
|
+
comments: {
|
|
16
|
+
/**
|
|
17
|
+
* How to apply magic comments when the dynamic import already includes a block-level comment.
|
|
18
|
+
*
|
|
19
|
+
* - ignore: Default. Skip adding magic comments.
|
|
20
|
+
* - replace: Replace the found comment with any applied magic commments.
|
|
21
|
+
* - append: Add any applied magic comments after the comment.
|
|
22
|
+
* - preprend: Add any applied magic comments before the comment.
|
|
23
|
+
* - Function: (cmts: {}[], magicComment: string) => string
|
|
24
|
+
*/
|
|
25
|
+
oneOf: [{
|
|
26
|
+
enum: ['ignore', 'replace', 'prepend', 'append']
|
|
27
|
+
}, {
|
|
28
|
+
instanceof: 'Function'
|
|
29
|
+
}]
|
|
14
30
|
}
|
|
15
31
|
},
|
|
16
32
|
additionalProperties: false
|
|
17
|
-
};
|
|
18
|
-
exports.schema = schema;
|
|
33
|
+
};
|
package/dist/formatter.js
CHANGED
|
@@ -3,24 +3,21 @@ import MagicString from 'magic-string';
|
|
|
3
3
|
const format = ({
|
|
4
4
|
match,
|
|
5
5
|
source,
|
|
6
|
-
filepath,
|
|
7
6
|
comments,
|
|
7
|
+
filepath,
|
|
8
|
+
astComments,
|
|
8
9
|
magicCommentOptions,
|
|
9
10
|
importExpressionNodes
|
|
10
11
|
}) => {
|
|
11
12
|
const magicImports = [];
|
|
12
|
-
const cmts = [...comments];
|
|
13
13
|
const src = new MagicString(source);
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (wasFound) {
|
|
18
|
-
cmts.splice(idx, 1);
|
|
19
|
-
}
|
|
20
|
-
return wasFound;
|
|
14
|
+
const getComments = node => {
|
|
15
|
+
// This ignores comments that come after the imports specifier.
|
|
16
|
+
return astComments.filter(cmt => cmt.start > node.start && cmt.end < node.end && cmt.start < node.source.end);
|
|
21
17
|
};
|
|
22
18
|
for (const node of importExpressionNodes) {
|
|
23
|
-
|
|
19
|
+
const cmts = getComments(node);
|
|
20
|
+
if (!cmts.length || comments !== 'ignore') {
|
|
24
21
|
const specifier = source.substring(node.source.start, node.source.end);
|
|
25
22
|
const magicComment = getMagicComment({
|
|
26
23
|
match,
|
|
@@ -29,8 +26,36 @@ const format = ({
|
|
|
29
26
|
options: magicCommentOptions
|
|
30
27
|
});
|
|
31
28
|
if (magicComment) {
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
const clone = src.snip(node.start, node.end);
|
|
30
|
+
if (!cmts.length) {
|
|
31
|
+
magicImports.push(clone.toString().replace(specifier, `${magicComment} ${specifier}`));
|
|
32
|
+
src.appendLeft(node.source.start, `${magicComment} `);
|
|
33
|
+
} else {
|
|
34
|
+
/**
|
|
35
|
+
* Get the minimum start and maximum end.
|
|
36
|
+
* Assumption is that comment nodes are sorted
|
|
37
|
+
* in ascending order of `node.start`.
|
|
38
|
+
*/
|
|
39
|
+
const minStart = cmts[0].start;
|
|
40
|
+
const maxEnd = cmts[cmts.length - 1].end;
|
|
41
|
+
if (comments === 'replace') {
|
|
42
|
+
magicImports.push(clone.overwrite(minStart, maxEnd, magicComment).toString());
|
|
43
|
+
src.overwrite(minStart, maxEnd, magicComment);
|
|
44
|
+
} else if (comments === 'append') {
|
|
45
|
+
magicImports.push(clone.appendRight(maxEnd, ` ${magicComment}`).toString());
|
|
46
|
+
src.appendRight(maxEnd, ` ${magicComment}`);
|
|
47
|
+
} else if (comments === 'prepend') {
|
|
48
|
+
magicImports.push(clone.prependLeft(minStart, `${magicComment} `).toString());
|
|
49
|
+
src.prependLeft(minStart, `${magicComment} `);
|
|
50
|
+
} else {
|
|
51
|
+
// Has to be a function or the schema validator is broken
|
|
52
|
+
const replacement = comments(cmts, magicComment);
|
|
53
|
+
if (typeof replacement === 'string') {
|
|
54
|
+
magicImports.push(clone.overwrite(minStart, maxEnd, replacement).toString());
|
|
55
|
+
src.overwrite(minStart, maxEnd, replacement);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
34
59
|
}
|
|
35
60
|
}
|
|
36
61
|
}
|
package/dist/loader.js
CHANGED
|
@@ -14,6 +14,7 @@ const loader = function (source) {
|
|
|
14
14
|
const {
|
|
15
15
|
mode = 'parser',
|
|
16
16
|
match = 'module',
|
|
17
|
+
comments = 'ignore',
|
|
17
18
|
verbose = false,
|
|
18
19
|
...rest
|
|
19
20
|
} = options;
|
|
@@ -26,6 +27,7 @@ const loader = function (source) {
|
|
|
26
27
|
...parse(source),
|
|
27
28
|
match,
|
|
28
29
|
filepath,
|
|
30
|
+
comments,
|
|
29
31
|
magicCommentOptions
|
|
30
32
|
});
|
|
31
33
|
if (verbose) {
|
package/dist/parser.js
CHANGED
|
@@ -15,7 +15,7 @@ import jsx from 'acorn-jsx';
|
|
|
15
15
|
extend(base);
|
|
16
16
|
const jsxParser = Parser.extend(jsx());
|
|
17
17
|
const parse = source => {
|
|
18
|
-
const
|
|
18
|
+
const astComments = [];
|
|
19
19
|
const importExpressionNodes = [];
|
|
20
20
|
const ast = jsxParser.parse(source, {
|
|
21
21
|
locations: false,
|
|
@@ -24,12 +24,12 @@ const parse = source => {
|
|
|
24
24
|
allowAwaitOutsideFunction: true,
|
|
25
25
|
allowReturnOutsideFunction: true,
|
|
26
26
|
allowImportExportEverywhere: true,
|
|
27
|
-
onComment: (isBlock,
|
|
27
|
+
onComment: (isBlock, text, start, end) => {
|
|
28
28
|
if (isBlock) {
|
|
29
|
-
|
|
29
|
+
astComments.push({
|
|
30
30
|
start,
|
|
31
31
|
end,
|
|
32
|
-
|
|
32
|
+
text
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -41,7 +41,7 @@ const parse = source => {
|
|
|
41
41
|
});
|
|
42
42
|
return {
|
|
43
43
|
ast,
|
|
44
|
-
|
|
44
|
+
astComments,
|
|
45
45
|
importExpressionNodes,
|
|
46
46
|
source
|
|
47
47
|
};
|
package/dist/schema.js
CHANGED
|
@@ -5,6 +5,22 @@ const schema = {
|
|
|
5
5
|
...magicSchema.properties,
|
|
6
6
|
mode: {
|
|
7
7
|
enum: ['parser', 'regexp']
|
|
8
|
+
},
|
|
9
|
+
comments: {
|
|
10
|
+
/**
|
|
11
|
+
* How to apply magic comments when the dynamic import already includes a block-level comment.
|
|
12
|
+
*
|
|
13
|
+
* - ignore: Default. Skip adding magic comments.
|
|
14
|
+
* - replace: Replace the found comment with any applied magic commments.
|
|
15
|
+
* - append: Add any applied magic comments after the comment.
|
|
16
|
+
* - preprend: Add any applied magic comments before the comment.
|
|
17
|
+
* - Function: (cmts: {}[], magicComment: string) => string
|
|
18
|
+
*/
|
|
19
|
+
oneOf: [{
|
|
20
|
+
enum: ['ignore', 'replace', 'prepend', 'append']
|
|
21
|
+
}, {
|
|
22
|
+
instanceof: 'Function'
|
|
23
|
+
}]
|
|
8
24
|
}
|
|
9
25
|
},
|
|
10
26
|
additionalProperties: false
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "magic-comments-loader",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Add webpack magic comments to your dynamic imports at build time.",
|
|
5
5
|
"main": "dist",
|
|
6
6
|
"type": "module",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"prepack": "npm run build",
|
|
27
27
|
"build": "babel-dual-package src --out-dir dist",
|
|
28
28
|
"lint": "eslint . src __tests__ --ext .js,.cjs",
|
|
29
|
-
"
|
|
29
|
+
"prettier": "prettier src __tests__ -w",
|
|
30
30
|
"test:unit": "node --experimental-vm-modules --no-warnings ./node_modules/.bin/jest",
|
|
31
31
|
"test:spec": "NODE_OPTIONS='--loader=babel-register-esm --no-warnings' BABEL_ENV=test jest -c jest.config.spec.js",
|
|
32
32
|
"test": "npm run test:unit && npm run test:spec"
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"webpack",
|
|
36
36
|
"magic comments",
|
|
37
37
|
"loader",
|
|
38
|
-
"dynamic",
|
|
39
|
-
"
|
|
38
|
+
"dynamic import",
|
|
39
|
+
"webpackChunkName",
|
|
40
40
|
"build",
|
|
41
41
|
"config"
|
|
42
42
|
],
|
|
@@ -46,21 +46,18 @@
|
|
|
46
46
|
"dist"
|
|
47
47
|
],
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@babel/cli": "^7.
|
|
50
|
-
"@babel/core": "^7.
|
|
51
|
-
"@babel/eslint-parser": "^7.
|
|
52
|
-
"@babel/preset-env": "^7.
|
|
53
|
-
"babel-dual-package": "^1.
|
|
49
|
+
"@babel/cli": "^7.23.9",
|
|
50
|
+
"@babel/core": "^7.23.9",
|
|
51
|
+
"@babel/eslint-parser": "^7.23.9",
|
|
52
|
+
"@babel/preset-env": "^7.23.9",
|
|
53
|
+
"babel-dual-package": "^1.1.3",
|
|
54
54
|
"babel-register-esm": "^1.2.4",
|
|
55
|
-
"codecov": "^4.0.0-0",
|
|
56
55
|
"eslint": "^8.42.0",
|
|
57
|
-
"eslint-config-prettier": "^8.8.0",
|
|
58
56
|
"eslint-plugin-jest": "^27.2.1",
|
|
59
|
-
"
|
|
60
|
-
"jest": "^
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"prettier": "^2.8.8",
|
|
57
|
+
"jest": "^29.7.0",
|
|
58
|
+
"jest-light-runner": "^0.6.0",
|
|
59
|
+
"memfs": "^4.6.0",
|
|
60
|
+
"prettier": "^3.2.4",
|
|
64
61
|
"webpack": "^5.87.0"
|
|
65
62
|
},
|
|
66
63
|
"dependencies": {
|
|
@@ -68,9 +65,19 @@
|
|
|
68
65
|
"acorn-jsx": "^5.3.2",
|
|
69
66
|
"acorn-jsx-walk": "^2.0.0",
|
|
70
67
|
"acorn-walk": "^8.2.0",
|
|
71
|
-
"magic-comments": "^2.1.
|
|
68
|
+
"magic-comments": "^2.1.12",
|
|
72
69
|
"magic-string": "^0.30.0",
|
|
73
70
|
"micromatch": "^4.0.4",
|
|
74
|
-
"schema-utils": "^4.
|
|
71
|
+
"schema-utils": "^4.2.0"
|
|
72
|
+
},
|
|
73
|
+
"prettier": {
|
|
74
|
+
"printWidth": 90,
|
|
75
|
+
"tabWidth": 2,
|
|
76
|
+
"useTabs": false,
|
|
77
|
+
"semi": false,
|
|
78
|
+
"singleQuote": true,
|
|
79
|
+
"trailingComma": "none",
|
|
80
|
+
"bracketSpacing": true,
|
|
81
|
+
"arrowParens": "avoid"
|
|
75
82
|
}
|
|
76
83
|
}
|