文件
shanghaipeiwan/server/tests/miniapp-script-syntax.spec.ts

74 行
2.8 KiB
TypeScript

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

// 已读取AGENTS.md
import * as fs from 'fs';
import * as path from 'path';
/**
* 第九十七批:小程序 Vue 单文件不得混入 TypeScript 语法。
* 背景:hall.vue 的 `<script setup>` 未声明 lang="ts",却写了 `(cls: string)`,
* 导致 HBuilderX/Vite 编译直接失败,只能在人工编译时发现。
*/
describe('第九十七批小程序脚本语法闸门', () => {
const root = path.resolve(__dirname, '../../pwuniapp');
const walk = (dir: string, out: string[]): string[] => {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
if (entry.name === 'node_modules' || entry.name === 'unpackage' || entry.name.startsWith('.')) continue;
const full = path.join(dir, entry.name);
if (entry.isDirectory()) walk(full, out);
else if (entry.name.endsWith('.vue')) out.push(full);
}
return out;
};
it('未声明 lang="ts" 的 <script> 中不得出现 TS 类型标注', () => {
const problems: string[] = [];
const typeAnno = /\(\s*[A-Za-z_$][\w$]*\s*:\s*(string|number|boolean|any|unknown|void|Record|Array)\b/;
for (const file of walk(root, [])) {
const src = fs.readFileSync(file, 'utf-8');
const scriptMatch = src.match(/<script([^>]*)>([\s\S]*?)<\/script>/);
if (!scriptMatch) continue;
const attrs = scriptMatch[1] || '';
if (/lang\s*=\s*["']ts["']/.test(attrs)) continue;
if (typeAnno.test(scriptMatch[2])) {
problems.push(path.relative(root, file));
}
}
expect(problems).toEqual([]);
});
it('未声明 lang="scss" 的 <style> 中不得出现嵌套选择器,杜绝微信 WXSS unexpected { 编译报错', () => {
const problems: string[] = [];
for (const file of walk(root, [])) {
const src = fs.readFileSync(file, 'utf-8');
const styleMatches = src.matchAll(/<style([^>]*)>([\s\S]*?)<\/style>/g);
for (const m of styleMatches) {
const attrs = m[1] || '';
if (/lang\s*=\s*["']scss["']/.test(attrs)) continue;
const body = m[2];
const lines = body.split('\n');
let depth = 0;
let inAtRule = false;
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (line.startsWith('@keyframes') || line.startsWith('@media')) {
inAtRule = true;
}
for (const ch of line) {
if (ch === '{') {
depth++;
if (depth > 1 && !inAtRule) {
problems.push(`${path.relative(root, file)}: line ${i + 1}`);
break;
}
} else if (ch === '}') {
depth = Math.max(0, depth - 1);
if (depth === 0) inAtRule = false;
}
}
}
}
}
expect(problems).toEqual([]);
});
});