mirror of
https://github.com/motajs/template.git
synced 2026-11-10 04:24:30 +08:00
feat(09-22): strip replay decorators in both builds + content list filtering
This commit is contained in:
1 parent
9d291a6f80
commit
6015628d9b
7 files changed
+913
-150
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import { Plugin } from 'vite';
|
||||
import { ModuleInfo } from 'rollup';
|
||||
import ts from 'typescript';
|
||||
|
||||
/** 数据端构建中禁止出现的渲染端模块说明符,第一项为匹配规则,第二项为报错时的命中标记 */
|
||||
const SPECIFIER_BANS: ReadonlyArray<readonly [RegExp, string]> = [
|
||||
@@ -76,3 +77,91 @@ export function dataIsolationPlugin(): Plugin {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** 构建时需要删除的录像装饰器名称 */
|
||||
const REPLAY_DECORATORS: ReadonlyArray<string> = [
|
||||
'shouldReplay',
|
||||
'ignoreReplay'
|
||||
];
|
||||
/** 需要处理录像装饰器的源文件后缀 */
|
||||
const SCRIPT_EXTENSIONS: ReadonlyArray<string> = ['.ts', '.tsx'];
|
||||
/** 判定第三方依赖路径的 node_modules 片段 */
|
||||
const NODE_MODULES_SEGMENT = /[/\\]node_modules[/\\]/;
|
||||
|
||||
/**
|
||||
* 删除源码中所有录像装饰器的应用,只按装饰器节点的文本范围切片,不会误删字符串与注释。
|
||||
* @param code 源码文本
|
||||
* @param fileName 源码文件名,用于确定脚本种类
|
||||
*/
|
||||
export function removeReplayDecorators(code: string, fileName: string): string {
|
||||
const kind = fileName.endsWith('.tsx')
|
||||
? ts.ScriptKind.TSX
|
||||
: ts.ScriptKind.TS;
|
||||
const sourceFile = ts.createSourceFile(
|
||||
fileName,
|
||||
code,
|
||||
ts.ScriptTarget.Latest,
|
||||
true,
|
||||
kind
|
||||
);
|
||||
const ranges: Array<[number, number]> = [];
|
||||
const stack: ts.Node[] = [sourceFile];
|
||||
|
||||
while (stack.length > 0) {
|
||||
const node = stack.pop()!;
|
||||
if (ts.canHaveDecorators(node)) {
|
||||
const decorators = ts.getDecorators(node);
|
||||
if (decorators) {
|
||||
for (const decorator of decorators) {
|
||||
const expression = decorator.expression;
|
||||
const target = ts.isCallExpression(expression)
|
||||
? expression.expression
|
||||
: expression;
|
||||
if (
|
||||
ts.isIdentifier(target) &&
|
||||
REPLAY_DECORATORS.includes(target.text)
|
||||
) {
|
||||
ranges.push([
|
||||
decorator.getStart(sourceFile),
|
||||
decorator.getEnd()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ts.forEachChild(node, child => {
|
||||
stack.push(child);
|
||||
});
|
||||
}
|
||||
|
||||
if (ranges.length === 0) return code;
|
||||
|
||||
let result = code;
|
||||
ranges.sort((a, b) => b[0] - a[0]);
|
||||
for (const [start, end] of ranges) {
|
||||
result = result.slice(0, start) + result.slice(end);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建删除录像装饰器的构建插件,仅处理项目自身的 TypeScript 源码,跳过第三方依赖。
|
||||
*/
|
||||
export function replayDecoratorPlugin(): Plugin {
|
||||
return {
|
||||
name: 'mota-replay-decorator',
|
||||
enforce: 'pre',
|
||||
apply: 'build',
|
||||
transform(code, id) {
|
||||
const fileName = id.split('?')[0];
|
||||
if (NODE_MODULES_SEGMENT.test(fileName)) return null;
|
||||
const matched = SCRIPT_EXTENSIONS.some(extension =>
|
||||
fileName.endsWith(extension)
|
||||
);
|
||||
if (!matched) return null;
|
||||
const result = removeReplayDecorators(code, fileName);
|
||||
if (result === code) return null;
|
||||
return { code: result, map: null };
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user