UNPKG

@itriton/webpack

Version:

[@itriton/webpack](http://itriton.icjs.ink/itriton/webpack/start/introduce.html),提供webpack相关插件

135 lines (131 loc) 4.84 kB
import { __awaiter } from 'tslib'; import * as fs from 'fs'; import * as path from 'path'; const cssbeautify = require("cssbeautify"); class DetachExcessStyles { /** * 创建DetachExcessStyles实例 * @param {DetachExcessStylesOptions} options - 插件 options. * @example * ``` typescript const path = require('path'); const { DetachExcessStyles } = require('@itriton/webpack'); const env = process.env.NODE_ENV === 'development' ? 'dev' : 'build'; const mainStylePath = path.join(__dirname, `unpackage/dist/${env}/mp-weixin/common/main.wxss`); const baseDir = path.join(__dirname, `unpackage/dist/${env}/mp-weixin`); let plugins = []; if (process.env.UNI_PLATFORM === 'mp-weixin') { plugins.push( new DetachExcessStyles({ mainStylePath, baseDir, startWithDir: ['pages'], // 支持多个起始目录 endWithFile: '.wxss', // 可选,默认为 '.wxss' fullMatch: false, // 可选,默认为 false,设置为 true 时全匹配起始目录文件夹名称 debug: true // 可选,默认为 false }) ) } module.exports = { configureWebpack: { plugins } } * ``` */ constructor(options) { this.mainStylePath = options.mainStylePath; this.baseDir = options.baseDir; this.startWithDir = Array.isArray(options.startWithDir) ? options.startWithDir : [options.startWithDir || "pages"]; this.endWithFile = options.endWithFile || ".wxss"; this.fullMatch = options.fullMatch || false; this.debug = options.debug || false; } apply(compiler) { compiler.hooks.done.tapPromise("DetachExcessStyles", (stats) => __awaiter(this, void 0, void 0, function* () { if (fs.existsSync(this.mainStylePath)) { let mainStyleContent = fs.readFileSync(this.mainStylePath, "utf-8"); mainStyleContent = this.formatCss(mainStyleContent); const xxssFiles = this.getAllXxssFiles(this.baseDir); if (this.debug) console.log(xxssFiles); for (const file of xxssFiles) { let content = fs.readFileSync(file, "utf-8"); content = this.formatCss(content); content = this.removeGlobalStyles(content, mainStyleContent); fs.writeFileSync(file, content); } fs.writeFileSync(this.mainStylePath, mainStyleContent); } })); } /** * Get all .xxss files in the specified directory. * @param {string} dir - The directory to search. * @param {boolean} [further=false] - Whether to continue searching deeper directories. * @returns {string[]} - An array of file paths. */ getAllXxssFiles(dir, further = false) { let results = []; const files = fs.readdirSync(dir); files.forEach((file) => { const filePath = path.join(dir, file); const stat = fs.statSync(filePath); if (stat.isDirectory()) { const shouldRecurse = this.startWithDir.some((startDir) => this.fullMatch ? file === startDir : file.startsWith(startDir)); if (shouldRecurse || further) { results = results.concat(this.getAllXxssFiles(filePath, true)); } } else if (stat.isFile() && file.endsWith(this.endWithFile)) { results.push(filePath); } }); return results; } /** * Remove global styles from the content. * @param {string} content - The content to process. * @param {string} mainStyleContent - The global styles to remove. * @returns {string} - The processed content. */ removeGlobalStyles(content, mainStyleContent) { const mainStyles = mainStyleContent.split("\n").map((line) => line.trim()).filter((line) => line); const mainStyleSet = new Set(mainStyles); const contentLines = content.split("\n"); const resultLines = []; let inRemoveBlock = false; for (const line of contentLines) { const trimmedLine = line.trim(); if (mainStyleSet.has(trimmedLine)) { if (trimmedLine.endsWith("{")) { inRemoveBlock = true; } continue; } if (inRemoveBlock) { if (trimmedLine.endsWith("}")) { inRemoveBlock = false; } continue; } resultLines.push(line); } return resultLines.join("\n"); } /** * Format CSS content. * @param {string} css - The CSS content to format. * @returns {string} - The formatted CSS content. */ formatCss(css) { css = css.replace(/\/\*[\s\S]*?\*\//g, ""); css = cssbeautify(css, { indent: " ", autosemicolon: true }); css = css.replace(/\{(\s*)/g, "{ ").replace(/\s+/g, " ").trim(); css = css.replace(/\}/g, "}\n"); return css; } } export { DetachExcessStyles };