@lithent/hmr-parser 0.2.2 → 0.2.3
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/dist/helper/calculator.d.cts +8 -0
- package/dist/helper/calculator.d.ts +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +5 -5
- package/dist/lithentHmrParser.mjs +4214 -4370
- package/dist/lithentHmrParser.mjs.map +1 -1
- package/dist/lithentHmrParser.umd.js +137 -216
- package/dist/lithentHmrParser.umd.js.map +1 -1
- package/dist/markerParse.d.cts +2 -0
- package/dist/markerParse.d.ts +1 -1
- package/dist/noMarkerParse.d.cts +2 -0
- package/dist/noMarkerParse.d.ts +1 -1
- package/dist/shared.d.cts +4 -0
- package/dist/shared.d.ts +1 -1
- package/dist/strings.d.cts +1 -0
- package/dist/strings.d.ts +1 -1
- package/dist/tests/bootstrap.test.d.cts +1 -0
- package/dist/tests/bootstrap.test.d.ts +1 -0
- package/dist/tests/mark.test.d.cts +1 -0
- package/dist/tests/nomark.test.d.cts +1 -0
- package/dist/transform/componentRegister.d.cts +3 -0
- package/dist/transform/componentRegister.d.ts +2 -2
- package/dist/transform/exportSnapshot.d.cts +3 -0
- package/dist/transform/exportSnapshot.d.ts +3 -0
- package/dist/transform/renderGuard.d.cts +3 -0
- package/dist/transform/renderGuard.d.ts +1 -1
- package/dist/types.d.cts +28 -0
- package/dist/utils/ast/componentCollector.d.cts +9 -0
- package/dist/utils/ast/componentCollector.d.ts +5 -4
- package/package.json +2 -2
- package/src/helper/calculator.ts +27 -7
- package/src/markerParse.ts +30 -14
- package/src/noMarkerParse.ts +16 -4
- package/src/shared.ts +8 -2
- package/src/strings.ts +105 -177
- package/src/tests/bootstrap.test.ts +312 -0
- package/src/tests/mark.test.ts +61 -181
- package/src/tests/nomark.test.tsx +110 -89
- package/src/transform/componentRegister.ts +13 -304
- package/src/transform/exportSnapshot.ts +77 -0
- package/src/transform/renderGuard.ts +59 -49
- package/src/utils/ast/componentCollector.ts +195 -96
package/dist/markerParse.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { MarkerTransformOptions, HmrTransformResult } from './types';
|
|
1
|
+
import { MarkerTransformOptions, HmrTransformResult } from './types.js';
|
|
2
2
|
export declare const transformWithMarker: (options: MarkerTransformOptions) => HmrTransformResult;
|
package/dist/noMarkerParse.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { BaseTransformOptions, HmrTransformResult } from './types';
|
|
1
|
+
import { BaseTransformOptions, HmrTransformResult } from './types.js';
|
|
2
2
|
export declare const transformWithoutMarker: (options: BaseTransformOptions) => HmrTransformResult;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { MarkerTransformOptions, BaseTransformOptions, MarkerAnalysisResult, BaseAnalysisResult } from './types.cjs';
|
|
2
|
+
export declare const analyzeMarker: (options: MarkerTransformOptions) => MarkerAnalysisResult;
|
|
3
|
+
export declare const analyzeNoMarker: (options: BaseTransformOptions) => BaseAnalysisResult;
|
|
4
|
+
export declare const shouldSkipTransform: (code: string) => boolean;
|
package/dist/shared.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MarkerTransformOptions, BaseTransformOptions, MarkerAnalysisResult, BaseAnalysisResult } from './types';
|
|
1
|
+
import { MarkerTransformOptions, BaseTransformOptions, MarkerAnalysisResult, BaseAnalysisResult } from './types.js';
|
|
2
2
|
export declare const analyzeMarker: (options: MarkerTransformOptions) => MarkerAnalysisResult;
|
|
3
3
|
export declare const analyzeNoMarker: (options: BaseTransformOptions) => BaseAnalysisResult;
|
|
4
4
|
export declare const shouldSkipTransform: (code: string) => boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const createHmrBootstrapBlock: (_targetExports: string[], componentNames: string[]) => string;
|
package/dist/strings.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const createHmrBootstrapBlock: (
|
|
1
|
+
export declare const createHmrBootstrapBlock: (_targetExports: string[], componentNames: string[]) => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { default as MagicString } from 'magic-string';
|
|
2
|
-
import { MountInfo } from '../utils/ast/componentCollector';
|
|
3
|
-
export declare const stitchComponentRegistration: (ms: MagicString, mounts: MountInfo[],
|
|
2
|
+
import { MountInfo } from '../utils/ast/componentCollector.js';
|
|
3
|
+
export declare const stitchComponentRegistration: (ms: MagicString, mounts: MountInfo[], _code: string, _importInsertionPos: number) => string;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { default as MagicString } from 'magic-string';
|
|
2
2
|
import { File } from '@babel/types';
|
|
3
|
-
export declare const wrapRenderCalls: (ms: MagicString, ast: File,
|
|
3
|
+
export declare const wrapRenderCalls: (ms: MagicString, ast: File, _code: string, importSpecifier?: string) => boolean;
|
package/dist/types.d.cts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { default as MagicString } from 'magic-string';
|
|
2
|
+
import { File } from '@babel/types';
|
|
3
|
+
export interface BaseTransformOptions {
|
|
4
|
+
code: string;
|
|
5
|
+
boundaryImportSpecifier: string;
|
|
6
|
+
tagFunctionImportSpecifier: string;
|
|
7
|
+
}
|
|
8
|
+
export interface MarkerTransformOptions extends BaseTransformOptions {
|
|
9
|
+
markerRegex: RegExp;
|
|
10
|
+
}
|
|
11
|
+
export interface BaseAnalysisResult {
|
|
12
|
+
targetExports: string[];
|
|
13
|
+
shouldTransform: boolean;
|
|
14
|
+
importInsertionPos: number;
|
|
15
|
+
blockInsertionPos: number;
|
|
16
|
+
headerSnippet: string;
|
|
17
|
+
ast: File;
|
|
18
|
+
}
|
|
19
|
+
export interface MarkerAnalysisResult extends BaseAnalysisResult {
|
|
20
|
+
match: RegExpExecArray | null;
|
|
21
|
+
}
|
|
22
|
+
export interface HmrTransformOptions extends MarkerTransformOptions {
|
|
23
|
+
}
|
|
24
|
+
export interface HmrTransformResult {
|
|
25
|
+
transformed: boolean;
|
|
26
|
+
code: string;
|
|
27
|
+
map: ReturnType<MagicString['generateMap']> | null;
|
|
28
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { File } from '@babel/types';
|
|
2
|
+
export type MountInfo = {
|
|
3
|
+
componentName: string;
|
|
4
|
+
declarationEnd: number;
|
|
5
|
+
start: number;
|
|
6
|
+
end: number;
|
|
7
|
+
declaration: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare const collectComponentMounts: (ast: File, _code: string, importSpecifier?: string) => MountInfo[];
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { File } from '@babel/types';
|
|
2
2
|
export type MountInfo = {
|
|
3
|
-
|
|
4
|
-
propsExpression: string;
|
|
5
|
-
componentName: string | null;
|
|
3
|
+
componentName: string;
|
|
6
4
|
declarationEnd: number;
|
|
5
|
+
start: number;
|
|
6
|
+
end: number;
|
|
7
|
+
declaration: boolean;
|
|
7
8
|
};
|
|
8
|
-
export declare const collectComponentMounts: (ast: File,
|
|
9
|
+
export declare const collectComponentMounts: (ast: File, _code: string, importSpecifier?: string) => MountInfo[];
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@lithent/hmr-parser",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.3",
|
|
5
5
|
"description": "Lithent HMR parser utilities for build tools",
|
|
6
6
|
"main": "./dist/lithentHmrParser.umd.js",
|
|
7
7
|
"module": "./dist/lithentHmrParser.mjs",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"vite-plugin-checker": "^0.8.0",
|
|
41
41
|
"vite-plugin-dts": "^4.2.1",
|
|
42
42
|
"vitest": "^2.1.5",
|
|
43
|
-
"lithent": "1.
|
|
43
|
+
"lithent": "1.25.0"
|
|
44
44
|
},
|
|
45
45
|
"volta": {
|
|
46
46
|
"node": "20.3.0",
|
package/src/helper/calculator.ts
CHANGED
|
@@ -49,7 +49,13 @@ export const collectExportNames = (ast: File): string[] => {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
export const detectLithentUsage = (ast: File): boolean => {
|
|
52
|
-
const watchedNames = new Set([
|
|
52
|
+
const watchedNames = new Set([
|
|
53
|
+
'render',
|
|
54
|
+
'mount',
|
|
55
|
+
'lmount',
|
|
56
|
+
'createApp',
|
|
57
|
+
'createRoot',
|
|
58
|
+
]);
|
|
53
59
|
|
|
54
60
|
for (const node of ast.program.body) {
|
|
55
61
|
if (node.type !== 'ImportDeclaration') continue;
|
|
@@ -86,12 +92,15 @@ export const collectHeaderInsert = (
|
|
|
86
92
|
ast: File,
|
|
87
93
|
sourceCode: string,
|
|
88
94
|
boundaryImportSpecifier: string,
|
|
89
|
-
|
|
95
|
+
tagFunctionImportSpecifier: string
|
|
90
96
|
) => {
|
|
91
|
-
const importsToPrepend: string[] = [
|
|
97
|
+
const importsToPrepend: string[] = [
|
|
98
|
+
`import { getComponentKey as __lithentGetComponentKey, mountCallback as __lithentMountCallback, componentMap as __lithentComponentMap } from '${tagFunctionImportSpecifier}';`,
|
|
99
|
+
];
|
|
92
100
|
let hasBoundaryImport = false;
|
|
93
101
|
let lastImportEnd = 0;
|
|
94
|
-
let directiveEnd =
|
|
102
|
+
let directiveEnd =
|
|
103
|
+
ast.program.directives.at(-1)?.end ?? ast.program.interpreter?.end ?? 0;
|
|
95
104
|
let firstImportStart: number | null = null;
|
|
96
105
|
|
|
97
106
|
for (const node of ast.program.body) {
|
|
@@ -101,8 +110,19 @@ export const collectHeaderInsert = (
|
|
|
101
110
|
firstImportStart = node.start ?? null;
|
|
102
111
|
}
|
|
103
112
|
|
|
104
|
-
if (
|
|
105
|
-
|
|
113
|
+
if (
|
|
114
|
+
node.source.value === boundaryImportSpecifier &&
|
|
115
|
+
node.importKind !== 'type'
|
|
116
|
+
) {
|
|
117
|
+
hasBoundaryImport =
|
|
118
|
+
node.specifiers.some(
|
|
119
|
+
specifier =>
|
|
120
|
+
specifier.type === 'ImportSpecifier' &&
|
|
121
|
+
specifier.importKind !== 'type' &&
|
|
122
|
+
specifier.imported.type === 'Identifier' &&
|
|
123
|
+
specifier.imported.name === 'createBoundary' &&
|
|
124
|
+
specifier.local.name === '__lithentCreateBoundary'
|
|
125
|
+
) || hasBoundaryImport;
|
|
106
126
|
}
|
|
107
127
|
|
|
108
128
|
continue;
|
|
@@ -126,7 +146,7 @@ export const collectHeaderInsert = (
|
|
|
126
146
|
|
|
127
147
|
if (!hasBoundaryImport) {
|
|
128
148
|
importsToPrepend.push(
|
|
129
|
-
`import { createBoundary } from '${boundaryImportSpecifier}';`
|
|
149
|
+
`import { createBoundary as __lithentCreateBoundary } from '${boundaryImportSpecifier}';`
|
|
130
150
|
);
|
|
131
151
|
}
|
|
132
152
|
|
package/src/markerParse.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { analyzeMarker } from './shared';
|
|
|
5
5
|
import { stitchComponentRegistration } from './transform/componentRegister';
|
|
6
6
|
import { wrapRenderCalls } from './transform/renderGuard';
|
|
7
7
|
import { collectComponentMounts } from './utils/ast/componentCollector';
|
|
8
|
+
import { createExportSnapshot } from './transform/exportSnapshot';
|
|
8
9
|
|
|
9
10
|
export const transformWithMarker = (
|
|
10
11
|
options: MarkerTransformOptions
|
|
@@ -15,6 +16,7 @@ export const transformWithMarker = (
|
|
|
15
16
|
targetExports,
|
|
16
17
|
shouldTransform,
|
|
17
18
|
importInsertionPos,
|
|
19
|
+
blockInsertionPos,
|
|
18
20
|
headerSnippet,
|
|
19
21
|
} = analysis;
|
|
20
22
|
|
|
@@ -22,7 +24,11 @@ export const transformWithMarker = (
|
|
|
22
24
|
return { transformed: false, code: options.code, map: null };
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
const mounts = collectComponentMounts(
|
|
27
|
+
const mounts = collectComponentMounts(
|
|
28
|
+
analysis.ast,
|
|
29
|
+
options.code,
|
|
30
|
+
options.tagFunctionImportSpecifier
|
|
31
|
+
);
|
|
26
32
|
const componentNames = Array.from(
|
|
27
33
|
new Set(
|
|
28
34
|
mounts
|
|
@@ -32,26 +38,36 @@ export const transformWithMarker = (
|
|
|
32
38
|
);
|
|
33
39
|
|
|
34
40
|
const ms = new MagicString(options.code);
|
|
35
|
-
|
|
41
|
+
if (mounts.length)
|
|
42
|
+
wrapRenderCalls(
|
|
43
|
+
ms,
|
|
44
|
+
analysis.ast,
|
|
45
|
+
options.code,
|
|
46
|
+
options.tagFunctionImportSpecifier
|
|
47
|
+
);
|
|
48
|
+
const hoisted = stitchComponentRegistration(
|
|
49
|
+
ms,
|
|
50
|
+
mounts,
|
|
51
|
+
options.code,
|
|
52
|
+
importInsertionPos
|
|
53
|
+
);
|
|
36
54
|
const transformBlock = createHmrBootstrapBlock(
|
|
37
55
|
targetExports,
|
|
38
56
|
componentNames
|
|
39
57
|
).trimStart();
|
|
40
58
|
|
|
41
|
-
|
|
59
|
+
const precedingChar =
|
|
60
|
+
blockInsertionPos > 0 ? options.code[blockInsertionPos - 1] : undefined;
|
|
61
|
+
const needsLeadingNewline = blockInsertionPos > 0 && precedingChar !== '\n';
|
|
62
|
+
const blockSnippet = `${needsLeadingNewline ? '\n' : ''}${transformBlock}\n${hoisted}\n\n`;
|
|
63
|
+
if (blockInsertionPos === importInsertionPos) {
|
|
64
|
+
ms.appendLeft(importInsertionPos, `${headerSnippet}${blockSnippet}`);
|
|
65
|
+
} else {
|
|
42
66
|
ms.appendLeft(importInsertionPos, headerSnippet);
|
|
67
|
+
ms.appendLeft(blockInsertionPos, blockSnippet);
|
|
43
68
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
match.index > 0 ? options.code[match.index - 1] : undefined;
|
|
47
|
-
const needsLeadingNewline = match.index > 0 && precedingChar !== '\n';
|
|
48
|
-
const followingChar = options.code[match.index + match[0].length] ?? null;
|
|
49
|
-
const trailingNewline = followingChar === '\n' ? '\n' : '\n\n';
|
|
50
|
-
const blockSnippet = `${needsLeadingNewline ? '\n' : ''}${transformBlock}${trailingNewline}`;
|
|
51
|
-
|
|
52
|
-
ms.overwrite(match.index, match.index + match[0].length, blockSnippet);
|
|
53
|
-
|
|
54
|
-
stitchComponentRegistration(ms, mounts, options.code, importInsertionPos);
|
|
69
|
+
ms.overwrite(match.index, match.index + match[0].length, '');
|
|
70
|
+
ms.append(createExportSnapshot(analysis.ast, mounts));
|
|
55
71
|
|
|
56
72
|
return {
|
|
57
73
|
transformed: true,
|
package/src/noMarkerParse.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { analyzeNoMarker } from './shared';
|
|
|
5
5
|
import { stitchComponentRegistration } from './transform/componentRegister';
|
|
6
6
|
import { wrapRenderCalls } from './transform/renderGuard';
|
|
7
7
|
import { collectComponentMounts } from './utils/ast/componentCollector';
|
|
8
|
+
import { createExportSnapshot } from './transform/exportSnapshot';
|
|
8
9
|
|
|
9
10
|
export const transformWithoutMarker = (
|
|
10
11
|
options: BaseTransformOptions
|
|
@@ -23,7 +24,11 @@ export const transformWithoutMarker = (
|
|
|
23
24
|
return { transformed: false, code: options.code, map: null };
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
const mounts = collectComponentMounts(
|
|
27
|
+
const mounts = collectComponentMounts(
|
|
28
|
+
ast,
|
|
29
|
+
options.code,
|
|
30
|
+
options.tagFunctionImportSpecifier
|
|
31
|
+
);
|
|
27
32
|
const componentNames = Array.from(
|
|
28
33
|
new Set(
|
|
29
34
|
mounts
|
|
@@ -33,7 +38,14 @@ export const transformWithoutMarker = (
|
|
|
33
38
|
);
|
|
34
39
|
|
|
35
40
|
const ms = new MagicString(options.code);
|
|
36
|
-
|
|
41
|
+
if (mounts.length)
|
|
42
|
+
wrapRenderCalls(ms, ast, options.code, options.tagFunctionImportSpecifier);
|
|
43
|
+
const hoisted = stitchComponentRegistration(
|
|
44
|
+
ms,
|
|
45
|
+
mounts,
|
|
46
|
+
options.code,
|
|
47
|
+
importInsertionPos
|
|
48
|
+
);
|
|
37
49
|
const transformBlock = createHmrBootstrapBlock(
|
|
38
50
|
targetExports,
|
|
39
51
|
componentNames
|
|
@@ -43,7 +55,7 @@ export const transformWithoutMarker = (
|
|
|
43
55
|
blockInsertionPos > 0 ? options.code[blockInsertionPos - 1] : undefined;
|
|
44
56
|
const needsLeadingNewlineForBlock =
|
|
45
57
|
blockInsertionPos > 0 && blockPrecedingChar !== '\n';
|
|
46
|
-
const blockSnippet = `${needsLeadingNewlineForBlock ? '\n' : ''}${transformBlock}\n\n`;
|
|
58
|
+
const blockSnippet = `${needsLeadingNewlineForBlock ? '\n' : ''}${transformBlock}\n${hoisted}\n\n`;
|
|
47
59
|
|
|
48
60
|
if (!headerSnippet && !blockSnippet.trim().length) {
|
|
49
61
|
return { transformed: false, code: options.code, map: null };
|
|
@@ -60,7 +72,7 @@ export const transformWithoutMarker = (
|
|
|
60
72
|
ms.appendLeft(blockInsertionPos, blockSnippet);
|
|
61
73
|
}
|
|
62
74
|
|
|
63
|
-
|
|
75
|
+
ms.append(createExportSnapshot(ast, mounts));
|
|
64
76
|
|
|
65
77
|
return {
|
|
66
78
|
transformed: true,
|
package/src/shared.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parse } from '@babel/parser';
|
|
2
|
+
import { collectComponentMounts } from './utils/ast/componentCollector';
|
|
2
3
|
import type { File } from '@babel/types';
|
|
3
4
|
import type {
|
|
4
5
|
MarkerTransformOptions,
|
|
@@ -73,7 +74,10 @@ export const analyzeMarker = (
|
|
|
73
74
|
|
|
74
75
|
return {
|
|
75
76
|
targetExports: finalTargets,
|
|
76
|
-
shouldTransform:
|
|
77
|
+
shouldTransform:
|
|
78
|
+
!!match ||
|
|
79
|
+
detectLithentUsage(ast) ||
|
|
80
|
+
collectComponentMounts(ast, code, tagFunctionImportSpecifier).length > 0,
|
|
77
81
|
importInsertionPos,
|
|
78
82
|
blockInsertionPos,
|
|
79
83
|
headerSnippet,
|
|
@@ -97,7 +101,9 @@ export const analyzeNoMarker = (
|
|
|
97
101
|
|
|
98
102
|
return {
|
|
99
103
|
targetExports,
|
|
100
|
-
shouldTransform:
|
|
104
|
+
shouldTransform:
|
|
105
|
+
detectLithentUsage(ast) ||
|
|
106
|
+
collectComponentMounts(ast, code, tagFunctionImportSpecifier).length > 0,
|
|
101
107
|
importInsertionPos,
|
|
102
108
|
blockInsertionPos,
|
|
103
109
|
headerSnippet,
|