UNPKG

csmall-theme

Version:

自用资源,不负责对外的使用解答

222 lines (190 loc) 6.87 kB
/** 加载不同的主题样式 如果是当前主题中的样式,不做特殊处理 如果是主题路径下的文件,替换为当前主题的文件 如果是第三方样式: 首先查看在当前主题下是否有此文件,如有则在之后插入当前主题下的文件 如没有则再查看custom下是否有,如有则在之后插入 **/ const path = require('path'); const fs = require('fs'); let options = {}, resolve = {alias: {}, aliasKeys: []}, sourcePath = path.resolve(process.cwd(), './src'); const defaultOptions = { styleLibrary: 'style', customLibrary: 'custom', themeLibrary: 'theme', sourcePath: sourcePath, third: [] }; let stylePath, themePath, customPath, themeLibrary; const pathDelimiterRegExp = /[\/\\]/; let addNormalizedDependency; function loadThemeSource(file, desc){ //console.log('Load style ' + desc + ': ' + file); return fs.readFileSync(file, 'utf-8');// + "\n/** Theme-loader insert **/\n" + source; } function replaceThirdLibrary(file){ if(file.slice(-4) === '.vue'){ return ''; } for(let i = 0, l = options.third.length; i < l; i++){ if(file.indexOf(options.third[i]) === 0){ let themeFile = path.resolve(themePath, file.slice(options.third[i].length + 1)); themeFile = appendFileExt(themeFile); if(themeFile){ return themeFile; } themeFile = path.resolve(customPath, file.slice(options.third[i].length + 1)); themeFile = appendFileExt(themeFile); if(themeFile){ return themeFile; } return ''; } } } function isFile(file){ try{ return fs.statSync(file).isFile(); }catch(e){ return false; } } function appendFileExt(file){ if(isFile(file)){ return file; } if(path.basename(file).charAt(0) !== '_'){ let f = path.resolve(path.dirname(file), '_' + path.basename(file)); if(isFile(f)){ return f; } } if(!path.extname(file)){ file += '.scss'; if(isFile(file)){ return file; }else{ file = path.resolve(path.dirname(file), '_' + path.basename(file)); if(isFile(file)){ return file; } } } return ''; } function replaceThemeFile(file, prev){ if(file.indexOf(themeLibrary) === 0 && file.indexOf(themePath) !== 0){ let fileSuffix = file.slice(themeLibrary.length + 1); const pathPart = fileSuffix.split(pathDelimiterRegExp); if(pathPart.length >= 2){ pathPart.shift(); file = path.resolve(themePath, pathPart.join('/')); let currentFile = appendFileExt(file); if(currentFile){ return currentFile; }else{ console.warn('>>>Please edit ' + file + ' for: ' + prev); } } } return ''; } function applyTheme(file, source, map){ let themeFile = replaceThemeFile(file, 'entry'); if(themeFile){//加载当前主题的样式 return [themeFile, loadThemeSource(themeFile, 'current[entry]'), map]; } //看是否是第三方库的样式,尝试替换为自有样式 let thirdFile = replaceThirdLibrary(file); if(thirdFile){ return [thirdFile, loadThemeSource(thirdFile, 'replace from third[entry]'), map]; } return [file, source, map]; } function convertUrlToFile(url, prev){ let replaceEnable = true; if(url.charAt(0) === '~'){ url = url.slice(1); let dir = url.split(pathDelimiterRegExp)[0]; if(resolve.alias[dir]){ url = url.slice(dir.length + 1); prev = resolve.alias[dir]; }else{ prev = path.resolve(path.dirname(sourcePath), resolve.modules[0]); replaceEnable = false; } }else{ prev = path.dirname(prev); } return [path.resolve(prev, url), replaceEnable]; } function addSassLoaderHook(sassLoader){ if(!sassLoader.options){ sassLoader.options = {}; } if(!sassLoader.options.sassOptions){ sassLoader.options.sassOptions = {}; } sassLoader.options.sassOptions.importer = function(url, prev, done){ let [file, replaceAble] = convertUrlToFile(url, prev); if(!replaceAble){//强制加载第三方库样式,为避免循环引入,不允许替换 let fullFile = appendFileExt(file); addNormalizedDependency(file); return {file: fullFile, contents: loadThemeSource(fullFile, 'not allow replace')}; } let fullFile = replaceThemeFile(file, prev); if(fullFile){//加载当前主题样式 addNormalizedDependency(file); return {file: fullFile, contents: loadThemeSource(fullFile, 'current')}; } let source = ''; let thirdFile = replaceThirdLibrary(file);//看是否是第三方库的样式,尝试替换为自有样式 if(thirdFile){//将第三方样式替换为自有样式 source = loadThemeSource(thirdFile, 'replace from third'); file = thirdFile; }else{//直接加载 fullFile = appendFileExt(file); if(fullFile){ source = loadThemeSource(fullFile, 'fallback'); }else{ console.warn('Theme file not exists: ' + file + ' for: ' + prev); } } addNormalizedDependency(file); return {file: file, contents: source}; }; } function processOptions(loader){ options = loader.options || {}; Object.keys(defaultOptions).map(key => { if(!options[key]){ options[key] = defaultOptions[key]; } }); if(!options.theme){ console.warn('The theme-loader\'s option "theme" not defined'); } sourcePath = path.resolve(options['sourcePath'], './'); stylePath = path.resolve(sourcePath + '/' + options.styleLibrary, './'); themeLibrary = path.resolve(stylePath + '/' + options.themeLibrary, './'); themePath = path.resolve(themeLibrary + '/' + options.theme, './'); customPath = path.resolve(stylePath + '/' + options.customLibrary, './'); } module.exports = function(source, map){ const processed = applyTheme(this.resourcePath, source, map); this.resourcePath = processed[0]; this.callback(null, processed[1], processed[2]); }; module.exports.pitch = function(){ resolve = this._compiler.options.resolve; resolve.aliasKeys = Object.keys(resolve.alias); addNormalizedDependency = file => { // node-sass returns POSIX paths this.dependency(path.normalize(file)); }; processOptions(this.loaders[this.loaderIndex]); addSassLoaderHook(this.loaders[this.loaderIndex - 1]); };