| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- #!/usr/bin/env node
- /**
- * D34: 修复「import 落在 </script> 之后」的历史残留
- * C 批脚本把品牌色 import 追加到了 </script> 与 <style> 之间 -> 模块作用域外,运行期标识符未定义。
- * 处理:把这段的 import 行搬回 <script> 内;已存在同路径 import 则合并去重。
- */
- const fs = require('fs');
- const path = require('path');
- const DRY = process.argv.includes('--dry');
- const ROOT = path.resolve(__dirname, '..');
- const SKIP = new Set(['components/mp-html/node/node.vue']); // mp-html 自带多 script 结构
- function walk(dir, out = []) {
- for (const name of fs.readdirSync(dir)) {
- if (['node_modules', 'dist', 'unpackage', '.git', 'scripts', '.tmp_equiv'].includes(name)) continue;
- const p = path.join(dir, name);
- const st = fs.statSync(p);
- if (st.isDirectory()) walk(p, out);
- else if (name.endsWith('.vue')) out.push(p);
- }
- return out;
- }
- function parseNames(imp) {
- const m = imp.match(/import\s*\{([^}]*)\}\s*from\s*(['"][^'"]+['"])/);
- if (!m) return null;
- return {
- names: m[1].split(',').map(s => s.trim()).filter(Boolean),
- from: m[2],
- };
- }
- let fixedFiles = 0;
- let movedImports = 0;
- for (const abs of walk(ROOT)) {
- const rel = path.relative(ROOT, abs).split(path.sep).join('/');
- if (SKIP.has(rel)) continue;
- let src = fs.readFileSync(abs, 'utf8');
- const open = src.match(/<script[^>]*>/);
- const closeIdx = src.indexOf('</script>');
- const styleIdx = src.search(/<style/);
- if (!open || closeIdx === -1) continue;
- const endRegion = styleIdx === -1 ? src.length : styleIdx;
- if (endRegion <= closeIdx) continue;
- const after = src.slice(closeIdx + 9, endRegion);
- const importLines = after.match(/^\s*import\s[^\n]*$/gm);
- if (!importLines) continue;
- // 从尾部区域删除这些 import 行
- let newAfter = after;
- for (const line of importLines) newAfter = newAfter.replace(line + '\n', '').replace(line + '\r\n', '').replace(line, '');
- const eol = src.includes('\r\n') ? '\r\n' : '\n';
- // 逐个搬回 script 内
- const openIdx = src.indexOf(open[0]);
- let scriptBodyStart = openIdx + open[0].length;
- let scriptBody = src.slice(scriptBodyStart, closeIdx);
- for (const line of importLines) {
- const parsed = parseNames(line);
- if (!parsed) continue;
- const escFrom = parsed.from.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
- const existingRe = new RegExp("import\\s*\\{([^}]*)\\}\\s*from\\s*" + escFrom + ';?');
- const ex = scriptBody.match(existingRe);
- if (ex) {
- const merged = [...new Set([...ex[1].split(',').map(s => s.trim()).filter(Boolean), ...parsed.names])];
- scriptBody = scriptBody.replace(ex[0], 'import { ' + merged.join(', ') + ' } from ' + parsed.from);
- } else {
- const lead = (scriptBody.match(/^\r?\n/) || [''])[0];
- scriptBody = lead + 'import { ' + parsed.names.join(', ') + ' } from ' + parsed.from + eol + scriptBody.slice(lead.length);
- }
- movedImports++;
- }
- const out = src.slice(0, scriptBodyStart) + scriptBody + src.slice(closeIdx, closeIdx + 9) + newAfter + src.slice(endRegion);
- if (!DRY) fs.writeFileSync(abs, out, 'utf8');
- fixedFiles++;
- console.log((DRY ? '[DRY] ' : '') + rel + ' imports:' + importLines.length);
- }
- console.log('文件:', fixedFiles, '搬移 import:', movedImports);
|