niucloud/uni-app/scripts/inject-addon-chunk-windi.cjs
wangchen14709853322 5ed9a0ba81 v2.0-beta-20260626
v2框架公测版测试流程请看v2.0-beta.md
2026-07-01 12:25:30 +08:00

186 lines
3.1 KiB
JavaScript

/**
* 将页面 chunk 用到的 Windi 工具类从 style.css 提取并内联注入,
* 避免仅依赖 style.css 外链导致 DevTools 中找不到 .h-[74rpx] 等规则。
*/
const fs = require('fs')
const path = require('path')
const { readWindiBlock, parseWindiRuleMap } = require('./generate-addon-windi-css.cjs')
const MARKER_PREFIX = '__addonChunkWindiInjected'
function extractClassTokens(code) {
const tokens = new Set()
const patterns = [
/class:\s*"([^"]+)"/g,
/class:\s*'([^']+)'/g,
/class:\s*`([^`$]+)`/g
]
for (const re of patterns) {
let m
while ((m = re.exec(code))) {
for (const t of m[1].split(/\s+/)) {
if (t) tokens.add(t)
}
}
}
return tokens
}
function buildChunkWindiCss(code, ruleMap) {
const tokenSet = extractClassTokens(code)
const used = []
const seen = new Set()
// 按 Windi 全局生成顺序输出,避免按 chunk 扫描顺序打乱 text-* / leading-* 优先级
for (const [token, rule] of ruleMap) {
if (!tokenSet.has(token) || seen.has(token)) continue
seen.add(token)
used.push(rule)
}
return used.join('')
}
function buildInjectSnippet(chunkName, css) {
if (!css) return ''
const id = chunkName.replace(/\.js$/, '').replace(/[^a-zA-Z0-9_-]/g, '_')
const cssLiteral = JSON.stringify(css)
return `/* ${MARKER_PREFIX}:${id} */(function(i,c){if(typeof document==="undefined"||!c)return;const k="adw-"+i;if(document.getElementById(k))return;const s=document.createElement("style");s.id=k;s.textContent=c;document.head.appendChild(s)})("${id}",${cssLiteral});\n`
}
function injectChunkWindiCss(addonDir) {
const windiCss = readWindiBlock(addonDir)
if (!windiCss) return { injected: 0, skipped: 0, reason: 'no windi block' }
const ruleMap = parseWindiRuleMap(windiCss)
if (!ruleMap.size) return { injected: 0, skipped: 0, reason: 'empty rule map' }
const assetsDir = path.join(addonDir, 'assets')
if (!fs.existsSync(assetsDir)) return { injected: 0, skipped: 0 }
let injected = 0
let skipped = 0
for (const name of fs.readdirSync(assetsDir)) {
if (!name.endsWith('.js')) continue
const filePath = path.join(assetsDir, name)
let code = fs.readFileSync(filePath, 'utf-8')
if (code.includes(MARKER_PREFIX)) {
skipped++
continue
}
const css = buildChunkWindiCss(code, ruleMap)
const snippet = buildInjectSnippet(name, css)
if (!snippet) continue
fs.writeFileSync(filePath, snippet + code, 'utf-8')
injected++
}
return { injected, skipped, rules: ruleMap.size }
}
module.exports = { injectChunkWindiCss, extractClassTokens, MARKER_PREFIX }
if (require.main === module) {
const dir = process.argv[2]
if (!dir) {
console.error('Usage: node inject-addon-chunk-windi.cjs <addon-dir>')
process.exit(1)
}
const r = injectChunkWindiCss(path.resolve(dir))
console.log('[inject-chunk-windi]', r)
}