txw/local-nodemodules/@gtff/tdesign-gt-vue/icon/plugin.js

177 lines
5.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const fs = require('fs');
const path = require('path');
const { icons } = require('./svg.json');
// 待替换图标名称,和目标替换图标名称,映射关系
const ICON_MAP = require('./icon-map');
const PLUGIN_NAME = 't-icon-replace-webpack-plugin';
class TIconReplaceWebpackPlugin {
constructor(options) {
this.options = {
name: PLUGIN_NAME,
staticPath: 'static',
debug: false,
rules: [
/**
* 替换按需加载的icon组件
*/
{
test: /tdesign-icons-vue\/(esm|lib)\/components\/.*\.js$/,
modify: (src, pathString) => {
let newData = src || '';
// 获取需要替换的icon组件
const fileNameObj = pathString.split('/');
const fileNameExt = fileNameObj[fileNameObj.length - 1];
const fileName = fileNameExt.split('.')[0];
const module = ICON_MAP[fileName];
// console.log('newData', newData);
if (module) {
newData = this.replace(src);
}
return newData;
},
},
/**
* 替换全量t-icon组件
*/
{
test: /tdesign-icons-vue\/(esm|dist)\/svg-sprite\/svg-sprite\.js$/,
modify: (src) => {
const str =
process.env.RUN_TYPE === 'demo'
? '//tencent-tdgv-1255000078.cos.zjywxc.csp.xc01.cloud.sat.tax/icon/svg.js'
: /**
* 本地开发模式会编译成绝对路径,如/dev/static/svg.js
* 做成物料包会编译成./static/svg.js
*/
`${process.env.NODE_ENV === 'production' ? '.' : process.env.VUE_APP_CDN_PATH}/${
this.options.staticPath
}/svg.js`;
// console.log('str', str);
return src.replace(/(CDN_ICONFONT_URL = ['|"]).*(['|"])/, `$1${str}$2`);
},
},
],
...options,
};
// 如果不是用于demo站点则把svg.js拷贝到工程目录去
if (
process.env.RUN_TYPE !== 'demo' &&
// 确保跑在vue-cli下
process.env.VUE_APP_ENV !== undefined &&
// 非lint模式
/vue-cli-service lint/.test(process.env.npm_lifecycle_script) !== true
) {
this.copyJs();
}
// return this.replacePlugin();
}
apply(compiler) {
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
const modifiedModules = [];
const { rules, debug } = this.options;
const tapCallback = (params, normalModule) => {
const userRequest = normalModule.userRequest || '';
const startIndex = userRequest.lastIndexOf('!') === -1 ? 0 : userRequest.lastIndexOf('!') + 1;
const moduleRequest = userRequest.substr(startIndex).replace(/\\/g, '/');
if (modifiedModules.includes(moduleRequest)) {
return;
}
rules.forEach((options, ruleIndex) => {
const { test, modify } = options;
const isMatched = (() => {
if (typeof test === 'function' && test(normalModule)) {
return true;
}
return test instanceof RegExp && test.test(moduleRequest);
})();
if (debug && isMatched) {
// eslint-disable-next-line no-console
console.log(`[${PLUGIN_NAME}] Add loader for module ${moduleRequest} at index ${ruleIndex}.`);
}
if (isMatched) {
normalModule.loaders.push({
loader: require.resolve('./loader.js'),
options: {
path: moduleRequest,
ruleIndex,
modify,
},
});
modifiedModules.push(moduleRequest);
}
});
};
compilation.hooks.normalModuleLoader.tap(PLUGIN_NAME, tapCallback);
});
}
/**
* 替换单个icon js文件的核心处理函数
* @param source
* @returns {*}
*/
replace(source = '') {
let newSource = source;
// let iconName = source.match(/-icon-([\w|-]+)/g)[0];
const iconNameMatch = /id:[ ]?'([\w|-]+)'/g.exec(source);
if (iconNameMatch && iconNameMatch.length > 1) {
const iconName = iconNameMatch[1];
const newIconName = ICON_MAP[iconName];
const newIconSvg = icons.find((t) => t.name === newIconName);
// 存在图标替换
if (newIconName && newIconSvg) {
// 匹配 svg / path 属性 进行替换
let attrs = newIconSvg.svgCode.match(/([\w-]+?=".*?")/g);
if (!attrs) {
console.warn('icon svgCode is not correct, it should like `<svg ...><path ...></path></svg>`');
return;
}
attrs = attrs.map((t) => {
const r = t.split('=');
return { key: r[0], value: r[1] };
});
// 不包含 value 的 svg 属性
const pureAttrs = attrs.map((t) => t.key);
const regExp = new RegExp(`"*(${pureAttrs.join('|')})"*: ".*?"`, 'g');
newSource = source.replace(regExp, (str) => {
for (let i = 0, len = attrs.length; i < len; i++) {
const { key, value } = attrs[i];
if (str.indexOf(key) !== -1) {
return `"${key}": ${value}`;
}
}
return str;
});
}
}
return newSource;
}
/**
* 拷贝全量svg到项目静态目录
*/
copyJs() {
fs.copyFileSync(
path.resolve(__dirname, 'svg.js'),
path.resolve(process.cwd(), `public/${this.options.staticPath}/svg.js`),
);
console.log('====>> 拷贝全量svg到项目静态目录成功');
}
}
module.exports = TIconReplaceWebpackPlugin;