import type { ComponentResolver, ComponentInfo } from './types'; export interface resolverOptions { // use commonjs lib & source css or scss for ssr ssr?: boolean; // 是否引入style importStyle?: boolean; // 组件名称 name?: string; } // 转换为驼峰 function kebabCase(key) { const result = key.replace(/([A-Z])/g, ' $1').trim(); return result.split(' ').join('-').toLowerCase(); } // 安装包路径 const pakPath = 'ivue-material-plus/dist/unplugin-vue-components'; // 颜色路径 const basePath = 'ivue-material-plus/dist/styles/base.css'; // 动画路径 const animationPath = 'ivue-material-plus/dist/styles/animation.css'; // 没有样式的组件 const noStylesComponents = [ 'ivue-content', 'ivue-carousel-item', 'ivue-bottom-nav-item', 'ivue-breadcrumb-item', 'ivue-checkbox-group', 'ivue-collapse-panel', 'ivue-count-down', 'ivue-count-up', 'ivue-radio-group', 'ivue-option', 'ivue-option-group', 'ivue-image-preview', 'ivue-relative-time', 'ivue-submenu', 'ivue-menu-group', 'ivue-menu-item', 'ivue-form-item', 'ivue-skeleton-item', ]; // 使用依赖组件 const useDependentComponents = [ // ivue-table { name: 'ivue-table', dependent: ['IvueTableColumn'], }, // ivue-tabs { name: 'ivue-tabs', dependent: ['IvueTabItem', 'IvueTab'], }, // ivue-form { name: 'ivue-form', dependent: ['IvueFormItem'], }, // ivue-select { name: 'ivue-select', dependent: ['IvueOption', 'IvueOptionGroup'], }, // ivue-steps { name: 'ivue-steps', dependent: ['IvueStep'], }, // ivue-skeleton { name: 'ivue-skeleton', dependent: ['IvueSkeletonItem'], }, ]; // 样式 const sideEffects = [ // ivue-page { name: 'ivue-page', sideEffects: ['ivue-select'], }, // ivue-modal { name: 'ivue-modal', sideEffects: ['ivue-button', 'ivue-spin'], }, // ivue-cascader { name: 'ivue-cascader', sideEffects: ['ivue-input', 'ivue-select', 'ivue-loading'], }, // ivue-auto-complete { name: 'ivue-auto-complete', sideEffects: ['ivue-loading', 'ivue-input', 'ivue-select'], }, // ivue-button { name: 'ivue-button', sideEffects: ['ivue-ripple'], }, // ivue-switch { name: 'ivue-switch', sideEffects: ['ivue-ripple'], }, // ivue-table { name: 'ivue-table', sideEffects: ['ivue-tooltip', 'ivue-checkbox', 'ivue-scrollbar'], }, ]; // 设置样式文件 function getSideEffects(componentsName: string, options) { // 没有样式文件 if (!options.importStyle) { return; } // 单文件引入 if (options.singleFile) { return [`${pakPath}/styles/${componentsName}.css`]; } let list = [ `${pakPath}/styles/reset.css`, `${pakPath}/styles/ivue-icon.css`, `${basePath}`, `${animationPath}`, `${pakPath}/styles/${componentsName}.css`, ]; sideEffects.forEach((item) => { if (item.name === componentsName) { item.sideEffects.forEach((sideEffectsItem) => { list.push(`${pakPath}/styles/${sideEffectsItem}.css`); }); } }); return list; } // 请求组件 const resolveComponent = ( componentsName: string, options: resolverOptions ): ComponentInfo | undefined => { // 使用依赖组件 let useDependentComponentsData: { name: string; from: string; } | null = null; useDependentComponents.forEach((item) => { item.dependent.forEach((dependent) => { // 转换为驼峰 const _kebabCase = kebabCase(dependent); // 匹配输入的组件是否符合 if (_kebabCase === componentsName) { useDependentComponentsData = { name: dependent, from: `${pakPath}/${options.ssr ? 'lib' : 'es'}`, }; } }); }); // 注册依赖的组件 if (useDependentComponentsData) { return useDependentComponentsData; } return { name: options.name, from: `${pakPath}/${options.ssr ? 'lib' : 'es'}`, sideEffects: getSideEffects(componentsName, options), }; }; // 请求指令 const resolveDirective = (name: string, options: resolverOptions) => { const directives = { // loading Loading: { name: 'IvueLoading', importName: 'ivue-loading', styleName: 'ivue-loading', importStyle: true, }, // 水波纹 Ripple: { name: 'Ripple', importName: 'ivue-ripple', styleName: 'ivue-ripple', importStyle: true, }, // 点击外层触发 ClickOutside: { name: 'ClickOutside', importName: 'ivue-click-outside', styleName: 'ivue-click-outside', importStyle: false, }, // 手指事件 Touch: { name: 'Touch', importName: 'ivue-touch', styleName: 'ivue-touch', importStyle: false, }, // 文本缩略 LineClamp: { name: 'LineClamp', importName: 'ivue-line-clamp', styleName: 'ivue-line-clamp', importStyle: true, // 单文件引入 singleFile: true, }, }; const directive = directives[name]; if (!directive) { return; } return { name: directive.name, from: `${pakPath}/${options.ssr ? 'lib' : 'es'}`, sideEffects: getSideEffects(directive.styleName, { importStyle: directive.importStyle, singleFile: directive.singleFile, }), }; }; export function IvueMaterialPlusResolver( options?: resolverOptions ): ComponentResolver[] { let optionsResolved = { ssr: false, ...options, }; return [ { type: 'component', resolve: (name: string) => { // 是否是 ivue组件 if (!name.match(/^Ivue[A-Z]/)) { return; } // 转换为驼峰 const _kebabCase = kebabCase(name); // 没有样式组件 if ([...noStylesComponents].includes(_kebabCase)) { return resolveComponent(_kebabCase, { name, importStyle: false, ...optionsResolved, }); } // 有样式组件 return resolveComponent(_kebabCase, { name, importStyle: true, ...optionsResolved, }); }, }, { type: 'directive', resolve: (name: string) => { return resolveDirective(name, optionsResolved); }, }, ]; }