diff --git a/src/core/resolvers/antdv.ts b/src/core/resolvers/antdv.ts index e3386628..239861c3 100644 --- a/src/core/resolvers/antdv.ts +++ b/src/core/resolvers/antdv.ts @@ -85,11 +85,14 @@ const matchComponents: IMatcher[] = [ pattern: /^Layout/, styleDir: 'layout', }, + { + pattern: /^Message/, + styleDir: 'message', + }, { pattern: /^Menu|^SubMenu/, styleDir: 'menu', }, - { pattern: /^Table/, styleDir: 'table', @@ -237,7 +240,7 @@ function getSideEffects(compName: string, options: AntDesignVueResolverOptions): return `${packageName}/${lib}/${styleDir}/style/css` } } -const primitiveNames = ['Affix', 'Anchor', 'AnchorLink', 'AutoComplete', 'AutoCompleteOptGroup', 'AutoCompleteOption', 'Alert', 'Avatar', 'AvatarGroup', 'BackTop', 'Badge', 'BadgeRibbon', 'Breadcrumb', 'BreadcrumbItem', 'BreadcrumbSeparator', 'Button', 'ButtonGroup', 'Calendar', 'Card', 'CardGrid', 'CardMeta', 'Collapse', 'CollapsePanel', 'Carousel', 'Cascader', 'Checkbox', 'CheckboxGroup', 'Col', 'Comment', 'ConfigProvider', 'DatePicker', 'MonthPicker', 'WeekPicker', 'RangePicker', 'QuarterPicker', 'Descriptions', 'DescriptionsItem', 'Divider', 'Dropdown', 'DropdownButton', 'Drawer', 'Empty', 'Form', 'FormItem', 'FormItemRest', 'Grid', 'Input', 'InputGroup', 'InputPassword', 'InputSearch', 'Textarea', 'Image', 'ImagePreviewGroup', 'InputNumber', 'Layout', 'LayoutHeader', 'LayoutSider', 'LayoutFooter', 'LayoutContent', 'List', 'ListItem', 'ListItemMeta', 'Menu', 'MenuDivider', 'MenuItem', 'MenuItemGroup', 'SubMenu', 'Mentions', 'MentionsOption', 'Modal', 'Statistic', 'StatisticCountdown', 'PageHeader', 'Pagination', 'Popconfirm', 'Popover', 'Progress', 'Radio', 'RadioButton', 'RadioGroup', 'Rate', 'Result', 'Row', 'Select', 'SelectOptGroup', 'SelectOption', 'Skeleton', 'SkeletonButton', 'SkeletonAvatar', 'SkeletonInput', 'SkeletonImage', 'Slider', 'Space', 'Spin', 'Steps', 'Step', 'Switch', 'Table', 'TableColumn', 'TableColumnGroup', 'TableSummary', 'TableSummaryRow', 'TableSummaryCell', 'Transfer', 'Tree', 'TreeNode', 'DirectoryTree', 'TreeSelect', 'TreeSelectNode', 'Tabs', 'TabPane', 'Tag', 'CheckableTag', 'TimePicker', 'TimeRangePicker', 'Timeline', 'TimelineItem', 'Tooltip', 'Typography', 'TypographyLink', 'TypographyParagraph', 'TypographyText', 'TypographyTitle', 'Upload', 'UploadDragger', 'LocaleProvider'] +const primitiveNames = ['Affix', 'Anchor', 'AnchorLink', 'AutoComplete', 'AutoCompleteOptGroup', 'AutoCompleteOption', 'Alert', 'Avatar', 'AvatarGroup', 'BackTop', 'Badge', 'BadgeRibbon', 'Breadcrumb', 'BreadcrumbItem', 'BreadcrumbSeparator', 'Button', 'ButtonGroup', 'Calendar', 'Card', 'CardGrid', 'CardMeta', 'Collapse', 'CollapsePanel', 'Carousel', 'Cascader', 'Checkbox', 'CheckboxGroup', 'Col', 'Comment', 'ConfigProvider', 'DatePicker', 'MonthPicker', 'WeekPicker', 'RangePicker', 'QuarterPicker', 'Descriptions', 'DescriptionsItem', 'Divider', 'Dropdown', 'DropdownButton', 'Drawer', 'Empty', 'Form', 'FormItem', 'FormItemRest', 'Grid', 'Input', 'InputGroup', 'InputPassword', 'InputSearch', 'Textarea', 'Image', 'ImagePreviewGroup', 'InputNumber', 'Layout', 'LayoutHeader', 'LayoutSider', 'LayoutFooter', 'LayoutContent', 'List', 'ListItem', 'ListItemMeta', 'Menu', 'MenuDivider', 'MenuItem', 'MenuItemGroup', 'SubMenu', 'Mentions', 'MentionsOption', 'Modal', 'Statistic', 'StatisticCountdown', 'PageHeader', 'Pagination', 'Popconfirm', 'Popover', 'Progress', 'Radio', 'RadioButton', 'RadioGroup', 'Rate', 'Result', 'Row', 'Select', 'SelectOptGroup', 'SelectOption', 'Skeleton', 'SkeletonButton', 'SkeletonAvatar', 'SkeletonInput', 'SkeletonImage', 'Slider', 'Space', 'Spin', 'Steps', 'Step', 'Switch', 'Table', 'TableColumn', 'TableColumnGroup', 'TableSummary', 'TableSummaryRow', 'TableSummaryCell', 'Transfer', 'Tree', 'TreeNode', 'DirectoryTree', 'TreeSelect', 'TreeSelectNode', 'Tabs', 'TabPane', 'Tag', 'CheckableTag', 'TimePicker', 'TimeRangePicker', 'Timeline', 'TimelineItem', 'Tooltip', 'Typography', 'TypographyLink', 'TypographyParagraph', 'TypographyText', 'TypographyTitle', 'Upload', 'UploadDragger', 'LocaleProvider', 'Message'] const prefix = 'A' let antdvNames: Set diff --git a/src/core/transforms/component.ts b/src/core/transforms/component.ts index 9cd36b32..a92e54e9 100644 --- a/src/core/transforms/component.ts +++ b/src/core/transforms/component.ts @@ -1,6 +1,7 @@ +import { toArray } from '@antfu/utils' import Debug from 'debug' import type MagicString from 'magic-string' -import { pascalCase, stringifyComponentImport } from '../utils' +import { pascalCase, removeDuplicatesPrepend, stringifyComponentImport, stringifyImport } from '../utils' import type { Context } from '../context' import type { ResolveResult } from '../transformer' import type { SupportedTransformer } from '../..' @@ -45,9 +46,19 @@ const resolveVue3 = (code: string, s: MagicString) => { return results } +const componentUi = [{ + prefix: 'A', + name: 'ant-design-vue', +}, { + prefix: '', + name: 'element-plus', +}, { + prefix: '', + name: 'vant', +}] + export default async function transformComponent(code: string, transformer: SupportedTransformer, s: MagicString, ctx: Context, sfcPath: string) { let no = 0 - const results = transformer === 'vue2' ? resolveVue2(code, s) : resolveVue3(code, s) for (const { rawName, replace } of results) { @@ -57,11 +68,40 @@ export default async function transformComponent(code: string, transformer: Supp const component = await ctx.findComponent(name, 'component', [sfcPath]) if (component) { const varName = `__unplugin_components_${no}` - s.prepend(`${stringifyComponentImport({ ...component, as: varName }, ctx)};\n`) + removeDuplicatesPrepend(`${stringifyComponentImport({ ...component, as: varName }, ctx)}`, s) no += 1 replace(varName) } } + // Prevent templates and imports from being duplicated + const onlyStyle = onlyInjectStyle(code).filter(item => !results.some(({ rawName }) => rawName === item)) + for (const rawName of onlyStyle) { + const name = pascalCase(rawName) + ctx.updateUsageMap(sfcPath, [name]) + const component = await ctx.findComponent(name, 'component', [sfcPath]) + if (!component || !component.sideEffects) + continue + const sideEffects = toArray(component.sideEffects) + + removeDuplicatesPrepend(`${sideEffects.map(stringifyImport).join(';')}`, s) + } + debug(`^ (${no})`) } + +function onlyInjectStyle(code: string) { + const results: string[] = [] + for (const ui of componentUi) { + const { name, prefix } = ui + const ulReg = new RegExp(`import {(.*)} from ['"]${name}["']`) + const matcher = code.match(ulReg) + if (!matcher) + continue + results.push(...matcher[1].split(',').map((i) => { + i = i.trim() + return `${prefix}${i[0].toUpperCase() + i.slice(1)}` + })) + } + return results +} diff --git a/src/core/transforms/directive/index.ts b/src/core/transforms/directive/index.ts index 30c07d29..38ff2b20 100644 --- a/src/core/transforms/directive/index.ts +++ b/src/core/transforms/directive/index.ts @@ -1,6 +1,6 @@ import Debug from 'debug' import type MagicString from 'magic-string' -import { pascalCase, stringifyComponentImport } from '../../utils' +import { pascalCase, removeDuplicatesPrepend, stringifyComponentImport } from '../../utils' import type { Context } from '../../context' import type { SupportedTransformer } from '../../..' import { DIRECTIVE_IMPORT_PREFIX } from '../../constants' @@ -23,7 +23,7 @@ export default async function transformDirective(code: string, transformer: Supp continue const varName = `__unplugin_directives_${no}` - s.prepend(`${stringifyComponentImport({ ...directive, as: varName }, ctx)};\n`) + removeDuplicatesPrepend(`${stringifyComponentImport({ ...directive, as: varName }, ctx)}`, s) no += 1 replace(varName) } diff --git a/src/core/utils.ts b/src/core/utils.ts index 87f69866..f9e6b652 100644 --- a/src/core/utils.ts +++ b/src/core/utils.ts @@ -6,6 +6,7 @@ import { getPackageInfo, isPackageExists, } from 'local-pkg' +import type MagicString from 'magic-string' import type { ComponentInfo, ImportInfo, ImportInfoLegacy, Options, ResolvedOptions } from '../types' import type { Context } from './context' import { DISABLE_COMMENT } from './constants' @@ -225,3 +226,10 @@ export function resolveImportPath(importName: string): string | undefined { preserveSymlinks: false, }) } + +export function removeDuplicatesPrepend(content: string, s: MagicString) { + const r = !(s as any).intro + ? `${content};` + : `${content.split(';').filter(item => !(s as any).intro.includes(item)).join(';')};\n` + return s.prepend(r) +} diff --git a/test/__snapshots__/dts.test.ts.snap b/test/__snapshots__/dts.test.ts.snap index 99dc4c5f..8f35d023 100644 --- a/test/__snapshots__/dts.test.ts.snap +++ b/test/__snapshots__/dts.test.ts.snap @@ -1,4 +1,4 @@ -// Vitest Snapshot v1 +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`dts > components only 1`] = ` "/* eslint-disable */ diff --git a/test/__snapshots__/search.test.ts.snap b/test/__snapshots__/search.test.ts.snap index 27284a11..e635cc73 100644 --- a/test/__snapshots__/search.test.ts.snap +++ b/test/__snapshots__/search.test.ts.snap @@ -1,4 +1,4 @@ -// Vitest Snapshot v1 +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`search > should with namespace & collapse 1`] = ` [ diff --git a/test/__snapshots__/stringifyComponentImport.test.ts.snap b/test/__snapshots__/stringifyComponentImport.test.ts.snap index 002db3de..a6403cb5 100644 --- a/test/__snapshots__/stringifyComponentImport.test.ts.snap +++ b/test/__snapshots__/stringifyComponentImport.test.ts.snap @@ -1,4 +1,4 @@ -// Vitest Snapshot v1 +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`stringifyComponentImport > importName 1`] = `"import { a as Test } from 'test'"`; diff --git a/test/__snapshots__/transform.test.ts.snap b/test/__snapshots__/transform.test.ts.snap index 21f607f4..92147690 100644 --- a/test/__snapshots__/transform.test.ts.snap +++ b/test/__snapshots__/transform.test.ts.snap @@ -1,10 +1,9 @@ -// Vitest Snapshot v1 +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`Component and directive as same name > vue2 transform should work 1`] = ` { "code": "/* unplugin-vue-components disabled */import __unplugin_directives_0 from 'test/directive/Loading'; import __unplugin_components_0 from 'test/component/Loading'; - var render = function () { this.$options.directives[\\"loading\\"] = __unplugin_directives_0; var _vm = this @@ -27,7 +26,6 @@ exports[`Component and directive as same name > vue2.7 transform should work 1`] { "code": "/* unplugin-vue-components disabled */import __unplugin_directives_0 from 'test/directive/Loading'; import __unplugin_components_0 from 'test/component/Div'; - import { defineComponent as _defineComponent } from \\"vue\\"; const _sfc_main = /* @__PURE__ */ _defineComponent({ __name: \\"App\\", @@ -48,7 +46,6 @@ exports[`Component and directive as same name > vue3 transform should work 1`] = { "code": "/* unplugin-vue-components disabled */import __unplugin_directives_0 from 'test/directive/ElInfiniteScroll'; import __unplugin_components_0 from 'test/component/ElInfiniteScroll'; - const render = (_ctx, _cache) => { const _component_el_infinite_scroll = __unplugin_components_0 const _directive_el_infinite_scroll = __unplugin_directives_0 @@ -67,7 +64,6 @@ exports[`transform > vue2 transform should work 1`] = ` { "code": "/* unplugin-vue-components disabled */import __unplugin_directives_0 from 'test/directive/Loading'; import __unplugin_components_0 from 'test/component/TestComp'; - var render = function () { this.$options.directives[\\"loading\\"] = __unplugin_directives_0; var _vm = this @@ -89,7 +85,6 @@ this.$options.directives[\\"loading\\"] = __unplugin_directives_0; exports[`transform > vue2 transform with jsx should work 1`] = ` { "code": "/* unplugin-vue-components disabled */import __unplugin_components_0 from 'test/component/TestComp'; - export default { render(){ return h(__unplugin_components_0, { @@ -107,7 +102,6 @@ exports[`transform > vue3 transform should work 1`] = ` { "code": "/* unplugin-vue-components disabled */import __unplugin_directives_0 from 'test/directive/Loading'; import __unplugin_components_0 from 'test/component/TestComp'; - const render = (_ctx, _cache) => { const _component_test_comp = __unplugin_components_0 const _directive_loading = __unplugin_directives_0 diff --git a/test/resolvers/__snapshots__/ant-design-vue.test.ts.snap b/test/resolvers/__snapshots__/ant-design-vue.test.ts.snap new file mode 100644 index 00000000..35ce27f0 --- /dev/null +++ b/test/resolvers/__snapshots__/ant-design-vue.test.ts.snap @@ -0,0 +1,105 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Ant Design Vue Resolver > components and directives should be transformed 1`] = ` +{ + "code": "/* unplugin-vue-components disabled */import 'ant-design-vue/es/message/style/css'; +import { Button as __unplugin_components_0 } from 'ant-design-vue/es';import 'ant-design-vue/es/button/style/css'; + import { defineComponent as _defineComponent } from \\"vue\\"; +' + + 'import { message } from \\"ant-design-vue\\"; +' + + 'import { ElMessage } from \\"element-plus\\"; +' + + 'const _sfc_main = /* @__PURE__ */ _defineComponent({ +' + + ' __name: \\"App\\", +' + + ' setup(__props, { expose }) { +' + + ' expose(); +' + + ' const test1 = () => { +' + + ' ElMessage.success(\\"message\\"); +' + + ' }; +' + + ' const handleClick = () => { +' + + ' message.success(\\"\\\\u6D4B\\\\u8BD5 jsx \\\\u4F7F\\\\u7528 a-button \\\\u548C mesage\\"); +' + + ' }; +' + + ' const __returned__ = { test1, handleClick }; +' + + ' Object.defineProperty(__returned__, \\"__isScriptSetup\\", { enumerable: false, value: true }); +' + + ' return __returned__; +' + + ' } +' + + '}); +' + + 'import { createTextVNode as _createTextVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, createVNode as _createVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \\"vue\\"; +' + + 'const _withScopeId = (n) => (_pushScopeId(\\"data-v-7a7a37b1\\"), n = n(), _popScopeId(), n); +' + + 'const _hoisted_1 = { class: \\"block\\" }; +' + + 'function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { +' + + ' const _component_a_button = __unplugin_components_0; +' + + ' return _openBlock(), _createElementBlock(\\"div\\", _hoisted_1, [ +' + + ' _createVNode(_component_a_button, { onClick: $setup.handleClick }, { +' + + ' default: _withCtx(() => [ +' + + ' _createTextVNode(\\" \\\\u70B9\\\\u6211 \\") +' + + ' ]), +' + + ' _: 1 +' + + ' /* STABLE */ +' + + ' }) +' + + ' ]); +' + + '} +' + + 'import \\"/Users/hejian/Documents/Github/unplugin-vue-components/examples/vite-vue3/src/App.vue?vue&type=style&index=0&scoped=7a7a37b1&lang.css\\"; +' + + '_sfc_main.__hmrId = \\"7a7a37b1\\"; +' + + 'typeof __VUE_HMR_RUNTIME__ !== \\"undefined\\" && __VUE_HMR_RUNTIME__.createRecord(_sfc_main.__hmrId, _sfc_main); +' + + 'import.meta.hot.accept((mod) => { +' + + ' if (!mod) +' + + ' return; +' + + ' const { default: updated, _rerender_only } = mod; +' + + ' if (_rerender_only) { +' + + ' __VUE_HMR_RUNTIME__.rerender(updated.__hmrId, updated.render); +' + + ' } else { +' + + ' __VUE_HMR_RUNTIME__.reload(updated.__hmrId, updated); +' + + ' } +' + + '}); +' + + 'import _export_sfc from \\"\\\\0plugin-vue:export-helper\\"; +' + + 'export default /* @__PURE__ */ _export_sfc(_sfc_main, [[\\"render\\", _sfc_render], [\\"__scopeId\\", \\"data-v-7a7a37b1\\"], [\\"__file\\", \\"/Users/hejian/Documents/Github/unplugin-vue-components/examples/vite-vue3/src/App.vue\\"]]); + +", +} +`; diff --git a/test/resolvers/__snapshots__/element-plus.test.ts.snap b/test/resolvers/__snapshots__/element-plus.test.ts.snap index 9b448706..9b035d83 100644 --- a/test/resolvers/__snapshots__/element-plus.test.ts.snap +++ b/test/resolvers/__snapshots__/element-plus.test.ts.snap @@ -1,11 +1,103 @@ -// Vitest Snapshot v1 +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Element Plus Resolver > auto load dynamically created component styles 1`] = ` +{ + "code": "/* unplugin-vue-components disabled */import { ElLoadingDirective as __unplugin_directives_0 } from 'element-plus/es';import 'element-plus/es/components/loading/style/css'; +import 'element-plus/es/components/message-box/style/css'; +import 'element-plus/es/components/message/style/css'; +import { ElConfigProvider as __unplugin_components_1 } from 'element-plus/es';import 'element-plus/es/components/config-provider/style/css'; +import { ElButton as __unplugin_components_0 } from 'element-plus/es';import 'element-plus/es/components/base/style/css';import 'element-plus/es/components/button/style/css'; + import { ref } from 'vue' + import { ElMessage, ElMessageBox } from 'element-plus' + + const _sfc_main = { + __name: 'App', + setup(__props, { expose }) { + expose(); + + const loading = ref(true) + const test1 = (_) => { + ElMessage.success('message') + } + const test2 = (_) => { + ElMessageBox.confirm( + 'ElMessageBox', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + center: true, + }, + ) + } + + const __returned__ = { loading, test1, test2, ref, get ElMessage() { return ElMessage }, get ElMessageBox() { return ElMessageBox } } + Object.defineProperty(__returned__, '__isScriptSetup', { enumerable: false, value: true }) + return __returned__ + } + + } + import { createTextVNode as _createTextVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, createVNode as _createVNode, resolveDirective as _resolveDirective, openBlock as _openBlock, createBlock as _createBlock, withDirectives as _withDirectives, Fragment as _Fragment, createElementBlock as _createElementBlock } from \\"vue\\" + + function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { + const _component_el_button = __unplugin_components_0 + const _component_el_config_provider = __unplugin_components_1 + const _directive_loading = __unplugin_directives_0 + + return (_openBlock(), _createElementBlock(_Fragment, null, [ + _createVNode(_component_el_config_provider, { namespace: \\"ep\\" }, { + default: _withCtx(() => [ + _createVNode(_component_el_button, { onClick: $setup.test1 }, { + default: _withCtx(() => [ + _createTextVNode(\\" el-message \\") + ]), + _: 1 /* STABLE */ + }), + _createVNode(_component_el_button, { onClick: $setup.test2 }, { + default: _withCtx(() => [ + _createTextVNode(\\" el-messageBox \\") + ]), + _: 1 /* STABLE */ + }), + _withDirectives((_openBlock(), _createBlock(_component_el_button, null, { + default: _withCtx(() => [ + _createTextVNode(\\" loading... \\") + ]), + _: 1 /* STABLE */ + })), [ + [_directive_loading, $setup.loading] + ]) + ]), + _: 1 /* STABLE */ + }), + _createVNode($setup[\\"ElMessage\\"]) + ], 64 /* STABLE_FRAGMENT */)) + } + + + _sfc_main.__hmrId = \\"7a7a37b1\\" + typeof __VUE_HMR_RUNTIME__ !== 'undefined' && __VUE_HMR_RUNTIME__.createRecord(_sfc_main.__hmrId, _sfc_main) + import.meta.hot.accept(mod => { + if (!mod) return + const { default: updated, _rerender_only } = mod + if (_rerender_only) { + __VUE_HMR_RUNTIME__.rerender(updated.__hmrId, updated.render) + } else { + __VUE_HMR_RUNTIME__.reload(updated.__hmrId, updated) + } + }) + import _export_sfc from 'plugin-vue:export-helper' + export default /*#__PURE__*/_export_sfc(_sfc_main, [['render',_sfc_render],['__file',\\"/Users/hejian/Documents/Github/unplugin-vue-components/examples/vite-vue3/src/App.vue\\"]]) +", +} +`; exports[`Element Plus Resolver > components and directives should be transformed 1`] = ` { - "code": "/* unplugin-vue-components disabled */import { ElLoadingDirective as __unplugin_directives_0 } from 'element-plus/es';import 'element-plus/es/components/base/style/css';import 'element-plus/es/components/loading/style/css'; + "code": "/* unplugin-vue-components disabled */import { ElLoadingDirective as __unplugin_directives_0 } from 'element-plus/es';import 'element-plus/es/components/loading/style/css'; import { Apple as __unplugin_components_1 } from '@element-plus/icons-vue'; import { ElButton as __unplugin_components_0 } from 'element-plus/es';import 'element-plus/es/components/base/style/css';import 'element-plus/es/components/button/style/css'; - (_ctx, _cache) => { const _component_el_button = __unplugin_components_0 const _component_el_icon_apple = __unplugin_components_1 diff --git a/test/resolvers/ant-design-vue.test.ts b/test/resolvers/ant-design-vue.test.ts new file mode 100644 index 00000000..95299b54 --- /dev/null +++ b/test/resolvers/ant-design-vue.test.ts @@ -0,0 +1,66 @@ +import { describe, expect, it } from 'vitest' +import { AntDesignVueResolver } from '../../src/resolvers' +import { Context } from '../../src/core/context' + +describe('Ant Design Vue Resolver', () => { + it('components and directives should be transformed', async () => { + const code = ` + import { defineComponent as _defineComponent } from "vue";\n' + + 'import { message } from "ant-design-vue";\n' + + 'import { ElMessage } from "element-plus";\n' + + 'const _sfc_main = /* @__PURE__ */ _defineComponent({\n' + + ' __name: "App",\n' + + ' setup(__props, { expose }) {\n' + + ' expose();\n' + + ' const test1 = () => {\n' + + ' ElMessage.success("message");\n' + + ' };\n' + + ' const handleClick = () => {\n' + + ' message.success("\\u6D4B\\u8BD5 jsx \\u4F7F\\u7528 a-button \\u548C mesage");\n' + + ' };\n' + + ' const __returned__ = { test1, handleClick };\n' + + ' Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });\n' + + ' return __returned__;\n' + + ' }\n' + + '});\n' + + 'import { createTextVNode as _createTextVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, createVNode as _createVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from "vue";\n' + + 'const _withScopeId = (n) => (_pushScopeId("data-v-7a7a37b1"), n = n(), _popScopeId(), n);\n' + + 'const _hoisted_1 = { class: "block" };\n' + + 'function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {\n' + + ' const _component_a_button = _resolveComponent("a-button");\n' + + ' return _openBlock(), _createElementBlock("div", _hoisted_1, [\n' + + ' _createVNode(_component_a_button, { onClick: $setup.handleClick }, {\n' + + ' default: _withCtx(() => [\n' + + ' _createTextVNode(" \\u70B9\\u6211 ")\n' + + ' ]),\n' + + ' _: 1\n' + + ' /* STABLE */\n' + + ' })\n' + + ' ]);\n' + + '}\n' + + 'import "/Users/hejian/Documents/Github/unplugin-vue-components/examples/vite-vue3/src/App.vue?vue&type=style&index=0&scoped=7a7a37b1&lang.css";\n' + + '_sfc_main.__hmrId = "7a7a37b1";\n' + + 'typeof __VUE_HMR_RUNTIME__ !== "undefined" && __VUE_HMR_RUNTIME__.createRecord(_sfc_main.__hmrId, _sfc_main);\n' + + 'import.meta.hot.accept((mod) => {\n' + + ' if (!mod)\n' + + ' return;\n' + + ' const { default: updated, _rerender_only } = mod;\n' + + ' if (_rerender_only) {\n' + + ' __VUE_HMR_RUNTIME__.rerender(updated.__hmrId, updated.render);\n' + + ' } else {\n' + + ' __VUE_HMR_RUNTIME__.reload(updated.__hmrId, updated);\n' + + ' }\n' + + '});\n' + + 'import _export_sfc from "\\0plugin-vue:export-helper";\n' + + 'export default /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-7a7a37b1"], ["__file", "/Users/hejian/Documents/Github/unplugin-vue-components/examples/vite-vue3/src/App.vue"]]);\n +` + + const ctx = new Context({ + resolvers: [AntDesignVueResolver({})], + transformer: 'vue3', + directives: true, + }) + ctx.sourcemap = false + expect(await ctx.transform(code, '')).toMatchSnapshot() + }) +}) diff --git a/test/resolvers/element-plus.test.ts b/test/resolvers/element-plus.test.ts index a8ce6032..22476f08 100644 --- a/test/resolvers/element-plus.test.ts +++ b/test/resolvers/element-plus.test.ts @@ -28,4 +28,99 @@ describe('Element Plus Resolver', () => { ctx.sourcemap = false expect(await ctx.transform(code, '')).toMatchSnapshot() }) + + it('auto load dynamically created component styles', async () => { + const code = ` + import { ref } from 'vue' + import { ElMessage, ElMessageBox } from 'element-plus' + + const _sfc_main = { + __name: 'App', + setup(__props, { expose }) { + expose(); + + const loading = ref(true) + const test1 = (_) => { + ElMessage.success('message') + } + const test2 = (_) => { + ElMessageBox.confirm( + 'ElMessageBox', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + center: true, + }, + ) + } + + const __returned__ = { loading, test1, test2, ref, get ElMessage() { return ElMessage }, get ElMessageBox() { return ElMessageBox } } + Object.defineProperty(__returned__, '__isScriptSetup', { enumerable: false, value: true }) + return __returned__ + } + + } + import { createTextVNode as _createTextVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, createVNode as _createVNode, resolveDirective as _resolveDirective, openBlock as _openBlock, createBlock as _createBlock, withDirectives as _withDirectives, Fragment as _Fragment, createElementBlock as _createElementBlock } from "vue" + + function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { + const _component_el_button = _resolveComponent("el-button") + const _component_el_config_provider = _resolveComponent("el-config-provider") + const _directive_loading = _resolveDirective("loading") + + return (_openBlock(), _createElementBlock(_Fragment, null, [ + _createVNode(_component_el_config_provider, { namespace: "ep" }, { + default: _withCtx(() => [ + _createVNode(_component_el_button, { onClick: $setup.test1 }, { + default: _withCtx(() => [ + _createTextVNode(" el-message ") + ]), + _: 1 /* STABLE */ + }), + _createVNode(_component_el_button, { onClick: $setup.test2 }, { + default: _withCtx(() => [ + _createTextVNode(" el-messageBox ") + ]), + _: 1 /* STABLE */ + }), + _withDirectives((_openBlock(), _createBlock(_component_el_button, null, { + default: _withCtx(() => [ + _createTextVNode(" loading... ") + ]), + _: 1 /* STABLE */ + })), [ + [_directive_loading, $setup.loading] + ]) + ]), + _: 1 /* STABLE */ + }), + _createVNode($setup["ElMessage"]) + ], 64 /* STABLE_FRAGMENT */)) + } + + + _sfc_main.__hmrId = "7a7a37b1" + typeof __VUE_HMR_RUNTIME__ !== 'undefined' && __VUE_HMR_RUNTIME__.createRecord(_sfc_main.__hmrId, _sfc_main) + import.meta.hot.accept(mod => { + if (!mod) return + const { default: updated, _rerender_only } = mod + if (_rerender_only) { + __VUE_HMR_RUNTIME__.rerender(updated.__hmrId, updated.render) + } else { + __VUE_HMR_RUNTIME__.reload(updated.__hmrId, updated) + } + }) + import _export_sfc from 'plugin-vue:export-helper' + export default /*#__PURE__*/_export_sfc(_sfc_main, [['render',_sfc_render],['__file',"/Users/hejian/Documents/Github/unplugin-vue-components/examples/vite-vue3/src/App.vue"]]) +` + + const ctx = new Context({ + resolvers: [ElementPlusResolver({})], + transformer: 'vue3', + directives: true, + }) + ctx.sourcemap = false + expect(await ctx.transform(code, '')).toMatchSnapshot() + }) }) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy