csmall-theme
Version:
自用资源,不负责对外的使用解答
119 lines (109 loc) • 4.06 kB
JavaScript
const fs = require('fs');
const path = require('path');
const {ConcatSource} = require("webpack-sources");
const pluginName = 'ThemeSwitchPlugin';
let themePathPlace = '';
let themeDir = '';
let themeUriPath = '';
function SwitchTheme(config){
if(config.theme.exists){
themePathPlace = config.themePathPlace;
}
themeDir = config.publicPath + config.cssDir;
themeUriPath = themeDir.slice(1);
this.distPath = config.path.dist;
this.themeKey = config.theme.key;
this.version = config.version;
this.onlyBuildTheme = config.onlyBuildTheme;
this.cleanExpiredCompiled = config.cleanExpiredCompiled;
this.comitBlacklist = ['.htm', '.js'];
this.themeExists = config.theme.exists;
}
function rewriteCssLink(html, version){
const collected = [];
const cssFiles = [];
let matchCss;
const regCss = new RegExp('<link [^>]*href="/?' + themeUriPath + themePathPlace + '/([^>]*).css"[^>]*>', 'g');
while((matchCss = regCss.exec(html))){
collected.push(matchCss);
}
for(let l = collected.length, i = 0; i < l; i++){
let item = collected[i];
html = html.replace(item[0], '');
cssFiles.push(item[1].replace('-' + version, ''));
}
let headPos = html.indexOf('<title>');
return html.slice(0, headPos) + '<meta name="css-keys" path="' + themeUriPath.slice(0, -1) + '" keys="' + cssFiles.join(',') + '">' + html.slice(headPos);
}
//同步删除指定目录下的所前目录和文件,包括当前目录
function rmdirSync(targetPath){
try{
let files = [];
if(fs.existsSync(targetPath)){
files = fs.readdirSync(targetPath);
files.forEach(function(file){
let curPath = targetPath + "/" + file;
if(fs.statSync(curPath).isDirectory()){ // recurse
if(!rmdirSync(curPath)){
return false;
}
}else{ // delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(targetPath);
}
}catch(e){
console.error(" Remove director fail! path=" + targetPath + " errorMsg:" + e);
process.exit(1);
}
return true;
}
SwitchTheme.prototype = {
apply(compiler){
compiler.hooks.emit.tap(pluginName, compilation => {
if(this.onlyBuildTheme){
this.removeOtherAssets(compilation.assets);
}
if(this.themeExists){
this.rewriteAsyncLoadCssPath(compilation.assets);
}
//清除掉旧文件
if(this.cleanExpiredCompiled){
console.info('\n===clear old compiled===');
}else{
console.info('\n===clear old theme===');
}
rmdirSync(this.distPath + (this.cleanExpiredCompiled? '': '/' + themeDir + '/' + this.themeKey));
});
},
removeOtherAssets(assets){
Object.keys(assets).map(fn => {
if(this.comitBlacklist.includes(path.extname(fn))){
delete assets[fn];
}
});
},
rewriteAsyncLoadCssPath(assets){
Object.keys(assets).map(fn => {
switch(fn.slice(fn.lastIndexOf('.') + 1)){
case 'js':
let regExp = new RegExp('\/' + themePathPlace + '\/', 'g');
assets[fn] = new ConcatSource(
assets[fn].source().replace(regExp, '\/"+window[\'_THEME_PATH\']+"\/')
);
break;
case 'css':
let js = assets[fn];
delete assets[fn];
fn = fn.replace('/' + themePathPlace + '/', '/' + this.themeKey + '/');
assets[fn] = js;
break;
case 'htm':
assets[fn] = new ConcatSource(rewriteCssLink(assets[fn].source(), this.version));
break;
}
});
}
};
module.exports = SwitchTheme;