Files
crawler-plugin/frontend-vue/tests/ep-imperative-style.test.ts
T
huangzd1997 86c05e71a2 fix(web): 补齐命令式调用的 EP 按需样式,修拦截弹窗贴到文档左上角
Element Plus 走按需引入,只有模板里用到的组件才会注入样式;ElMessage /
ElMessageBox 都是 import 后函数式调用,构建产物里一条 .el-message-box 规则都没有,
弹窗因此没有定位与遮罩,渲染成普通块元素压在页头文字上(ElMessage 提示条同样受影响)。
入口显式引入两个样式模块,并加测试钉住「显式 import 的 EP 组件必须有样式引入」。
2026-09-14 11:21:08 +08:00

58 lines
2.4 KiB
TypeScript

import { test } from 'node:test'
import assert from 'node:assert/strict'
import { readFileSync, readdirSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import { resolve, dirname } from 'node:path'
const here = dirname(fileURLToPath(import.meta.url))
const repoRoot = resolve(here, '..')
/**
* Element Plus 组件名 → 按需样式目录(ElMessageBox → message-box)。
* 与 element-plus/es/components/<目录>/style/css 的目录名一致。
*/
function styleDirOf(component: string) {
return component.replace(/^El/, '').replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
}
/** 扫 src 下所有「显式 from 'element-plus' 具名导入的 El* 组件」及其出处 */
function explicitElementPlusImports(): Map<string, string[]> {
const used = new Map<string, string[]>()
for (const file of readdirSync(resolve(repoRoot, 'src'), { recursive: true }) as string[]) {
if (!/\.(ts|vue)$/.test(file)) continue
const source = readFileSync(resolve(repoRoot, 'src', file), 'utf-8')
for (const match of source.matchAll(/import\s+(?!type\b)\{([^}]*)\}\s*from\s*['"]element-plus['"]/g)) {
for (const raw of match[1].split(',')) {
const name = raw.trim().split(/\s+as\s+/)[0].trim()
if (!/^El[A-Z]/.test(name)) continue
const files = used.get(name) || []
if (!files.includes(file)) files.push(file)
used.set(name, files)
}
}
}
return used
}
/**
* 显式 import 的 EP 组件不会被 ElementPlusResolver 注入样式(resolver 只处理
* 模板里未解析的组件和自动导入的标识符),漏在入口引入样式就会出现
* 「弹窗跑到文档左上角、和页头文字叠在一起」这类无定位样式的故障。
*/
test('test_element_plus_explicit_imports_have_on_demand_style', () => {
const entry = readFileSync(resolve(repoRoot, 'src/main.ts'), 'utf-8')
// 锚定行首:注释掉的 import 不算数
const styleDirs = [
...entry.matchAll(/^import\s+['"]element-plus\/es\/components\/([\w-]+)\/style\/css['"]/gm),
].map((match) => match[1])
for (const [component, files] of explicitElementPlusImports()) {
const dir = styleDirOf(component)
assert.ok(
styleDirs.includes(dir),
`${component}${files.join('、')} 被显式 import,按需样式不会自动注入;` +
`请在 src/main.ts 增加 import 'element-plus/es/components/${dir}/style/css'`,
)
}
})