|
1 |
| -import { ComponentResolver } from '../../types' |
| 1 | +import { join, normalize } from 'path' |
| 2 | +import { ComponentResolver, SideEffectsInfo } from '../../types' |
| 3 | +import { kebabCase, camelCase, pascalCase } from '../utils' |
| 4 | + |
| 5 | +interface VeuiPeerConfig { |
| 6 | + /** |
| 7 | + * The package name of the peer module. |
| 8 | + */ |
| 9 | + package: string |
| 10 | + |
| 11 | + /** |
| 12 | + * The directory path of the peer module. |
| 13 | + * @default 'components' |
| 14 | + */ |
| 15 | + path?: string |
| 16 | + |
| 17 | + /** |
| 18 | + * The file name template for the peer module. |
| 19 | + * @default '{module}.css' |
| 20 | + */ |
| 21 | + fileName?: `${string}{module}${string}` |
| 22 | + |
| 23 | + /** |
| 24 | + * The text transform to be applied to the '{module}' part of the file name. |
| 25 | + * @default 'kebab-case' |
| 26 | + */ |
| 27 | + transform?: 'kebab-case' | 'camelCase' | 'PascalCase' | false |
| 28 | +} |
| 29 | + |
| 30 | +type SupportedLocale = 'en-US' | 'zh-Hans' |
| 31 | + |
| 32 | +export interface VeuiResolverOptions { |
| 33 | + /** |
| 34 | + * The alias of 'veui` package. |
| 35 | + * @default 'veui' |
| 36 | + */ |
| 37 | + alias?: string |
| 38 | + |
| 39 | + /** |
| 40 | + * Peer modules to be injected. |
| 41 | + */ |
| 42 | + modules?: VeuiPeerConfig[] |
| 43 | + |
| 44 | + /** |
| 45 | + * Locale modules to be injected. |
| 46 | + * @default 'zh-Hans' |
| 47 | + */ |
| 48 | + locale?: SupportedLocale | SupportedLocale[] | false |
| 49 | + |
| 50 | + /** |
| 51 | + * Global modules to be injected to all components. |
| 52 | + * @default [] |
| 53 | + */ |
| 54 | + global?: string[] |
| 55 | +} |
| 56 | + |
| 57 | +interface ComponentInfo { |
| 58 | + name: string |
| 59 | + path: string |
| 60 | +} |
| 61 | + |
| 62 | +const VEUI_PACKAGE_NAME = 'veui' |
| 63 | +let components: Set<string> | undefined |
2 | 64 |
|
3 | 65 | /**
|
4 | 66 | * Resolver for VEUI
|
5 | 67 | *
|
6 | 68 | * @link https://github.com/ecomfe/veui
|
7 | 69 | */
|
8 |
| -export function VeuiResolver(): ComponentResolver { |
| 70 | +export function VeuiResolver(options: VeuiResolverOptions): ComponentResolver { |
| 71 | + const { alias = VEUI_PACKAGE_NAME } = options |
| 72 | + |
| 73 | + if (!components) { |
| 74 | + try { |
| 75 | + /* eslint-disable @typescript-eslint/no-var-requires */ |
| 76 | + const componentsData = require(`${alias}/components.json`) as ComponentInfo[] |
| 77 | + |
| 78 | + components = new Set(componentsData.map(({ name }) => name)) |
| 79 | + } |
| 80 | + catch (e) { |
| 81 | + throw new Error('[unplugin-vue-components:veui] VEUI is not installed') |
| 82 | + } |
| 83 | + } |
| 84 | + |
9 | 85 | return (name: string) => {
|
10 |
| - if (name.match(/^Veui[A-Z]/)) |
11 |
| - return { importName: name.slice(4), path: 'veui' } |
| 86 | + if (name.match(/^Veui[A-Z]/)) { |
| 87 | + const componentName = name.slice(4) |
| 88 | + |
| 89 | + if (!components!.has(componentName)) return |
| 90 | + |
| 91 | + const sideEffects = getSideEffects(componentName, options) |
| 92 | + |
| 93 | + return { importName: componentName, path: alias, sideEffects } |
| 94 | + } |
| 95 | + } |
| 96 | +} |
| 97 | + |
| 98 | +const formatters = { |
| 99 | + 'kebab-case': kebabCase, |
| 100 | + 'camelCase': camelCase, |
| 101 | + 'PascalCase': pascalCase, |
| 102 | +} |
| 103 | + |
| 104 | +const peerPaths = new Map<string, boolean>() |
| 105 | + |
| 106 | +function assertPeerPath(peerPath: string) { |
| 107 | + if (!peerPaths.has(peerPath)) { |
| 108 | + try { |
| 109 | + require.resolve(peerPath) |
| 110 | + peerPaths.set(peerPath, true) |
| 111 | + } |
| 112 | + catch (e) { |
| 113 | + peerPaths.set(peerPath, false) |
| 114 | + } |
12 | 115 | }
|
| 116 | + |
| 117 | + return peerPaths.get(peerPath) as boolean |
| 118 | +} |
| 119 | + |
| 120 | +function getSideEffects( |
| 121 | + name: string, |
| 122 | + { |
| 123 | + alias = VEUI_PACKAGE_NAME, |
| 124 | + modules = [], |
| 125 | + locale = 'zh-Hans', |
| 126 | + global = [], |
| 127 | + }: VeuiResolverOptions, |
| 128 | +): SideEffectsInfo { |
| 129 | + const localeModules = (locale |
| 130 | + ? Array.isArray(locale) |
| 131 | + ? locale |
| 132 | + : [locale] |
| 133 | + : [] |
| 134 | + ).map(locale => `${alias}/locale/${locale}/${name}.js`) |
| 135 | + |
| 136 | + const peerModules = modules.map( |
| 137 | + ({ |
| 138 | + package: pack, |
| 139 | + path = 'components', |
| 140 | + fileName = '{module}.css', |
| 141 | + transform = 'kebab-case', |
| 142 | + }) => { |
| 143 | + const peer = transform ? formatters[transform](name) : name |
| 144 | + const file = fileName.replace(/\$?\{module\}/g, peer) |
| 145 | + return normalize(join(pack, path, file)) |
| 146 | + }, |
| 147 | + ) |
| 148 | + |
| 149 | + return [...localeModules, ...global, ...peerModules].filter(assertPeerPath) |
13 | 150 | }
|
0 commit comments