2024-05-20 23:25:44 +08:00

137 lines
3.0 KiB
TypeScript

export interface VantResolverOptions {
/**
* Whether to automatically import the corresponding styles of the components.
*
* @default true
*/
importStyle?:
| boolean
| 'css'
/** Compatible with Vant 2.x / 3.x */
| 'less';
/**
* Set the referenced module type.
*
* @default 'esm'
*/
module?: 'esm' | 'cjs';
/**
* @deprecated Please use `module` option instead.
*/
ssr?: boolean;
}
export type VantImportsOptions = Pick<VantResolverOptions, 'module' | 'ssr'>;
/**
* Button->button; ButtonGroup->button-group
*/
function kebabCase(key: string) {
const result = key.replace(/([A-Z])/g, ' $1').trim();
return result.split(' ').join('-').toLowerCase();
}
function getModuleType(options: VantResolverOptions): string {
const { ssr, module = 'esm' } = options;
// compatible with the deprecated `ssr` option
if (ssr !== undefined) {
return ssr ? 'lib' : 'es';
}
return module === 'cjs' ? 'lib' : 'es';
}
function getSideEffects(dirName: string, options: VantResolverOptions) {
const { importStyle = true } = options;
if (!importStyle) {
return;
}
const moduleType = getModuleType(options);
if (importStyle === 'less') return `vant/${moduleType}/${dirName}/style/less`;
return `vant/${moduleType}/${dirName}/style/index`;
}
function getAPIMap() {
const apiMap = new Map<string, string>();
const api = {
dialog: [
'showDialog',
'closeDialog',
'showConfirmDialog',
'setDialogDefaultOptions',
'resetDialogDefaultOptions',
],
imagePreview: ['showImagePreview'],
notify: [
'showNotify',
'closeNotify',
'setNotifyDefaultOptions',
'resetNotifyDefaultOptions',
],
toast: [
'showToast',
'closeToast',
'showFailToast',
'showLoadingToast',
'showSuccessToast',
'allowMultipleToast',
'setToastDefaultOptions',
'resetToastDefaultOptions',
],
};
Object.entries(api).forEach(([importName, apiList]) => {
apiList.forEach((api) => {
apiMap.set(api, importName);
});
});
return apiMap;
}
export function VantResolver(options: VantResolverOptions = {}) {
const moduleType = getModuleType(options);
const apiMap = getAPIMap();
return {
type: 'component' as const,
resolve: (name: string) => {
if (name.startsWith('Van')) {
const partialName = name.slice(3);
return {
name: partialName,
from: `vant/${moduleType}`,
sideEffects: getSideEffects(kebabCase(partialName), options),
};
}
// import API
if (apiMap.has(name)) {
const partialName = apiMap.get(name)!;
return {
name,
from: `vant/${moduleType}`,
sideEffects: getSideEffects(kebabCase(partialName), options),
};
}
},
};
}
export function VantImports(options: VantImportsOptions = {}) {
const moduleType = getModuleType(options);
return {
[`vant/${moduleType}`]: [...getAPIMap().keys()],
};
}