wx-shop/tools/strip-wxss-at-rules.js
2025-11-09 20:14:34 +08:00

90 lines
2.6 KiB
JavaScript

const fs = require('fs');
const path = require('path');
function walk(dir, cb) {
fs.readdirSync(dir, { withFileTypes: true }).forEach(d => {
const full = path.join(dir, d.name);
if (d.isDirectory()) walk(full, cb);
else cb(full);
});
}
function removeAtRuleBlocks(css, atRule) {
// Remove occurrences like @atRule ... { ... } with brace matching
let out = '';
let i = 0;
while (i < css.length) {
const idx = css.indexOf('@' + atRule, i);
if (idx === -1) {
out += css.slice(i);
break;
}
out += css.slice(i, idx);
let j = idx;
// advance past @atRule
while (j < css.length && css[j] !== '{' && css[j] !== ';') j++;
if (css[j] === ';') {
// simple at-rule with semicolon, skip it
i = j + 1;
continue;
}
if (css[j] !== '{') {
// can't find block start, bail out
i = j;
continue;
}
// now find matching closing brace
let brace = 0;
let k = j;
do {
if (css[k] === '{') brace++;
else if (css[k] === '}') brace--;
k++;
} while (k < css.length && brace > 0);
i = k; // skip whole block
}
return out;
}
function removeAtRuleLine(css, atRule) {
// remove simple at-rule lines like @layer name;
return css.replace(new RegExp('^\\s*@' + atRule + "\\s+[^;{]+;\\s*", 'gmi'), '');
}
function transformMediaRanges(css) {
// (width >= 40rem) -> (min-width: 40rem)
css = css.replace(/\(\s*width\s*>=\s*([^\)]+)\)/g, '(min-width: $1)');
css = css.replace(/\(\s*width\s*<=\s*([^\)]+)\)/g, '(max-width: $1)');
css = css.replace(/@media\s*\(\s*width\s*>\s*([^\)]+)\)/g, '@media (min-width: $1)');
css = css.replace(/@media\s*\(\s*width\s*<\s*([^\)]+)\)/g, '@media (max-width: $1)');
return css;
}
function processFile(file) {
if (!file.endsWith('.wxss')) return;
const orig = fs.readFileSync(file, 'utf8');
let css = orig;
// remove @supports blocks entirely (unsupported in WXSS)
css = removeAtRuleBlocks(css, 'supports');
// remove @layer lines and blocks
css = removeAtRuleLine(css, 'layer');
css = removeAtRuleBlocks(css, 'layer');
// convert range media queries to min/max equivalents
css = transformMediaRanges(css);
// remove @container blocks (not supported)
css = removeAtRuleBlocks(css, 'container');
if (css !== orig) {
fs.writeFileSync(file, css, 'utf8');
console.log('Fixed', file);
}
}
const target = path.join(__dirname, '..', 'unpackage', 'dist', 'dev', 'mp-weixin');
if (!fs.existsSync(target)) {
console.error('Target directory not found:', target);
process.exit(1);
}
walk(target, processFile);
console.log('Done');