55 lines
2.7 KiB
JavaScript
55 lines
2.7 KiB
JavaScript
const fs = require('node:fs')
|
||
const path = require('node:path')
|
||
const { spawnSync } = require('node:child_process')
|
||
const runner = require.resolve('@tarojs/webpack5-runner')
|
||
const postcss = require(require.resolve('postcss', { paths: [runner] }))
|
||
const parseSelector = require(require.resolve('postcss-selector-parser', { paths: [runner] }))
|
||
const dist = path.resolve(__dirname, '../dist')
|
||
|
||
function collect(folder) {
|
||
return fs.readdirSync(folder, { withFileTypes: true }).flatMap(entry => {
|
||
const file = path.join(folder, entry.name)
|
||
return entry.isDirectory() ? collect(file) : file.endsWith('.wxss') ? [file] : []
|
||
})
|
||
}
|
||
|
||
function validateWxss(css, label) {
|
||
postcss.parse(css).walkRules(rule => {
|
||
if (rule.parent.type === 'atrule' && /keyframes$/i.test(rule.parent.name)) return
|
||
parseSelector(selectors => selectors.walkUniversals(() => {
|
||
throw new Error(`${label}:WXSS 不支持通配选择器 ${rule.selector}`)
|
||
})).processSync(rule.selector)
|
||
parseSelector(selectors => selectors.walkPseudos(pseudo => {
|
||
if (/^:(?:first|last|nth|only)-(?:child|of-type)$/.test(pseudo.value)
|
||
&& (!pseudo.prev() || pseudo.prev().type === 'combinator')) {
|
||
throw new Error(`${label}:WXSS 结构伪类前需明确元素或类名 ${rule.selector}`)
|
||
}
|
||
})).processSync(rule.selector)
|
||
})
|
||
}
|
||
|
||
function main() {
|
||
if (!fs.existsSync(path.join(dist, 'app.wxss'))) throw new Error('请先构建微信小程序')
|
||
const files = collect(dist)
|
||
for (const file of files) validateWxss(fs.readFileSync(file, 'utf8'), path.relative(dist, file))
|
||
console.log(`WXSS 选择器兼容检查通过:${files.length} 个文件`)
|
||
|
||
const compiler = process.env.WECHAT_WXSS_COMPILER
|
||
|| '/Applications/wechatwebdevtools.app/Contents/Resources/app.asar.unpacked/node_modules/wcc-exec/wcsc'
|
||
if (!fs.existsSync(compiler)) {
|
||
if (process.env.WECHAT_WXSS_COMPILER) throw new Error('指定的微信 WXSS 编译器不存在')
|
||
console.warn('未找到微信原生 WXSS 编译器:本次仅完成静态检查,仍需开发者工具编译验收。可设置 WECHAT_WXSS_COMPILER。')
|
||
} else {
|
||
// The native compiler resolves @import from its supplied file collection.
|
||
const result = spawnSync(compiler, ['-lc', '-pc', String(files.length), ...files.map(file => `./${path.relative(dist, file)}`)], {
|
||
cwd: dist, encoding: 'utf8', maxBuffer: 16 * 1024 * 1024
|
||
})
|
||
if (result.error) throw result.error
|
||
if (result.status !== 0) throw new Error(`微信原生编译失败:${result.stderr.slice(0, 3000)}`)
|
||
console.log(`微信原生 WXSS 编译通过:${files.length} 个文件`)
|
||
}
|
||
}
|
||
|
||
module.exports = { validateWxss }
|
||
if (require.main === module) main()
|