import type { ComponentInfo, ComponentResolver, SideEffectsInfo } from '../../types' const matchComponents = [ { pattern: /^LayAvatarList$/, styleDir: 'avatar', }, { pattern: /^LayBreadcrumbItem$/, styleDir: 'breadcrumb', }, { pattern: /^(LayCarouselItem)$/, styleDir: 'carousel', }, { pattern: /^(LayCheckboxGroup)$/, styleDir: 'checkbox', }, { pattern: /^LayCol$/, styleDir: 'row', }, { pattern: /^(LayCollapseItem)$/, styleDir: 'collapse', }, { pattern: /^LayConfigProvider$/, styleDir: undefined, }, { pattern: /^LayCountUp$/, styleDir: undefined, }, { pattern: /^(LayDropdownMenu|LayDropdownMenuItem|LayDropdownSubMenu)$/, styleDir: 'dropdown', }, { pattern: /^(LayFormItem)$/, styleDir: 'form', }, { pattern: /^(LayMenuItem|LaySubMenu)$/, styleDir: 'menu', }, { pattern: /^(LayRadioGroup)$/, styleDir: 'radio', }, { pattern: /^LaySelectOption$/, styleDir: 'select', }, { pattern: /^LaySkeletonItem$/, styleDir: 'skeleton', }, { pattern: /^LaySplitPanelItem$/, styleDir: 'splitPanel', }, { pattern: /^LayStepItem$/, styleDir: 'step', }, { pattern: /^(LayTabItem)$/, styleDir: 'tab', }, { pattern: /^LayTimelineItem$/, styleDir: 'timeline', }, ] export interface LayuiVueResolverOptions { /** * import style along with components * * @default 'css' */ importStyle?: boolean | 'css' /** * resolve '@layui/layui-vue' icons * requires package `@layui/icons-vue` * * @default false */ resolveIcons?: boolean /** * exclude components that do not require automatic import * */ exclude?: Array<string | RegExp> } const layuiRE = /^Lay[A-Z]/ const layerRE = /^(layer|LayLayer)$/ const iconsRE = /^([A-Z][\w]+Icon|LayIcon)$/ let libName = '@layui/layui-vue' function lowerCamelCase(str: string) { return str.charAt(0).toLowerCase() + str.slice(1) } function getSideEffects(importName: string, options: LayuiVueResolverOptions): SideEffectsInfo | undefined { const { importStyle = 'css' } = options if (!importStyle) return undefined if (libName !== '@layui/layui-vue') return `${libName}/lib/index.css` let styleDir: string | undefined = lowerCamelCase(importName.slice(3)) // LayBackTop -> backTop for (const item of matchComponents) { if (item.pattern.test(importName)) { styleDir = item.styleDir break } } if (importStyle === 'css' || importStyle) { return styleDir ? [`@layui/layui-vue/es/${styleDir}/index.css`, '@layui/layui-vue/es/index/index.css'] : undefined } } function resolveComponent(importName: string, options: LayuiVueResolverOptions): ComponentInfo | undefined { let name: string | undefined if (options.exclude && isExclude(importName, options.exclude)) return undefined if (options.resolveIcons && importName.match(iconsRE)) { name = importName libName = '@layui/icons-vue' } else if (importName.match(layerRE)) { name = importName libName = '@layui/layer-vue' } else if (importName.match(layuiRE) && !importName.match(iconsRE)) { name = importName libName = '@layui/layui-vue' } return name ? { name, from: libName, sideEffects: getSideEffects(name, options) } : undefined } function isExclude(name: string, exclude: Array<string | RegExp>): boolean { for (const item of exclude) { if (name === item || name.match(item)) return true } return false } /** * Resolver for layui-vue * * @link http://www.layui-vue.com/ for layui-vue * */ export function LayuiVueResolver( options: LayuiVueResolverOptions = {}, ): ComponentResolver { return { type: 'component', resolve: (name: string) => { return resolveComponent(name, options) }, } }