提交 d07d1359 编写于 作者: fxy060608's avatar fxy060608

fix(mp-weixin): Components start with wx (#3451)

上级 4791a571
...@@ -10,6 +10,9 @@ import { ...@@ -10,6 +10,9 @@ import {
} from '../src/mp/usingComponents' } from '../src/mp/usingComponents'
const inputDir = '/usr/xxx/projects/test/src' const inputDir = '/usr/xxx/projects/test/src'
function normalizeComponentName(name: string) {
return name
}
async function resolve(id: string, importer?: string) { async function resolve(id: string, importer?: string) {
return { return {
id: importer ? path.resolve(path.dirname(importer), id) : id, id: importer ? path.resolve(path.dirname(importer), id) : id,
...@@ -44,6 +47,7 @@ export function createApp() { ...@@ -44,6 +47,7 @@ export function createApp() {
{ {
inputDir, inputDir,
resolve, resolve,
normalizeComponentName,
} }
) )
...@@ -88,6 +92,7 @@ export function createApp() { ...@@ -88,6 +92,7 @@ export function createApp() {
{ {
inputDir, inputDir,
resolve, resolve,
normalizeComponentName,
} }
) )
...@@ -118,7 +123,11 @@ export function createApp() { ...@@ -118,7 +123,11 @@ export function createApp() {
) { ) {
const ast = parseProgram(source, filename, {}) const ast = parseProgram(source, filename, {})
const { imports } = await parseMainDescriptor(filename, ast, resolve) const { imports } = await parseMainDescriptor(filename, ast, resolve)
updateMiniProgramComponentsByMainFilename(filename, inputDir) updateMiniProgramComponentsByMainFilename(
filename,
inputDir,
normalizeComponentName
)
expect(findUsingComponents('pages/index/index')).toMatchObject( expect(findUsingComponents('pages/index/index')).toMatchObject(
usingComponents usingComponents
) )
......
...@@ -53,6 +53,10 @@ export interface MiniProgramCompilerOptions { ...@@ -53,6 +53,10 @@ export interface MiniProgramCompilerOptions {
* 父组件 setData 后,子组件的 properties 是否可以同步获取,目前仅 mp-weixin,mp-qq,mp-alipay 支持 * 父组件 setData 后,子组件的 properties 是否可以同步获取,目前仅 mp-weixin,mp-qq,mp-alipay 支持
*/ */
getPropertySync?: boolean getPropertySync?: boolean
/**
* 格式化组件名称,比如 wx-btn => weixin-btn (微信不允许以 wx 命名自定义组件)
*/
normalizeName?: (name: string) => string
} }
directive: string directive: string
emitFile?: (emittedFile: EmittedAsset) => string emitFile?: (emittedFile: EmittedAsset) => string
......
...@@ -117,21 +117,31 @@ export async function parseMainDescriptor( ...@@ -117,21 +117,31 @@ export async function parseMainDescriptor(
export function updateMiniProgramComponentsByScriptFilename( export function updateMiniProgramComponentsByScriptFilename(
scriptFilename: string, scriptFilename: string,
inputDir: string inputDir: string,
normalizeComponentName: (name: string) => string
) { ) {
const mainFilename = findMainFilenameByScriptFilename(scriptFilename) const mainFilename = findMainFilenameByScriptFilename(scriptFilename)
if (mainFilename) { if (mainFilename) {
updateMiniProgramComponentsByMainFilename(mainFilename, inputDir) updateMiniProgramComponentsByMainFilename(
mainFilename,
inputDir,
normalizeComponentName
)
} }
} }
export function updateMiniProgramComponentsByTemplateFilename( export function updateMiniProgramComponentsByTemplateFilename(
templateFilename: string, templateFilename: string,
inputDir: string inputDir: string,
normalizeComponentName: (name: string) => string
) { ) {
const mainFilename = findMainFilenameByTemplateFilename(templateFilename) const mainFilename = findMainFilenameByTemplateFilename(templateFilename)
if (mainFilename) { if (mainFilename) {
updateMiniProgramComponentsByMainFilename(mainFilename, inputDir) updateMiniProgramComponentsByMainFilename(
mainFilename,
inputDir,
normalizeComponentName
)
} }
} }
...@@ -153,9 +163,11 @@ export async function updateMiniProgramGlobalComponents( ...@@ -153,9 +163,11 @@ export async function updateMiniProgramGlobalComponents(
{ {
inputDir, inputDir,
resolve, resolve,
normalizeComponentName,
}: { }: {
inputDir: string inputDir: string
resolve: ParseDescriptor['resolve'] resolve: ParseDescriptor['resolve']
normalizeComponentName: (name: string) => string
} }
) { ) {
const { bindingComponents, imports } = await parseGlobalDescriptor( const { bindingComponents, imports } = await parseGlobalDescriptor(
...@@ -165,7 +177,12 @@ export async function updateMiniProgramGlobalComponents( ...@@ -165,7 +177,12 @@ export async function updateMiniProgramGlobalComponents(
) )
addMiniProgramUsingComponents( addMiniProgramUsingComponents(
'app', 'app',
createUsingComponents(bindingComponents, imports, inputDir) createUsingComponents(
bindingComponents,
imports,
inputDir,
normalizeComponentName
)
) )
return { return {
imports, imports,
...@@ -175,7 +192,8 @@ export async function updateMiniProgramGlobalComponents( ...@@ -175,7 +192,8 @@ export async function updateMiniProgramGlobalComponents(
function createUsingComponents( function createUsingComponents(
bindingComponents: BindingComponents, bindingComponents: BindingComponents,
imports: ImportDeclaration[], imports: ImportDeclaration[],
inputDir: string inputDir: string,
normalizeComponentName: (name: string) => string
) { ) {
const usingComponents: Record<string, string> = {} const usingComponents: Record<string, string> = {}
imports.forEach(({ source: { value }, specifiers: [specifier] }) => { imports.forEach(({ source: { value }, specifiers: [specifier] }) => {
...@@ -183,7 +201,9 @@ function createUsingComponents( ...@@ -183,7 +201,9 @@ function createUsingComponents(
if (!bindingComponents[name]) { if (!bindingComponents[name]) {
return return
} }
const componentName = hyphenate(bindingComponents[name].tag) const componentName = normalizeComponentName(
hyphenate(bindingComponents[name].tag)
)
if (!usingComponents[componentName]) { if (!usingComponents[componentName]) {
usingComponents[componentName] = addLeadingSlash( usingComponents[componentName] = addLeadingSlash(
removeExt(normalizeMiniProgramFilename(value, inputDir)) removeExt(normalizeMiniProgramFilename(value, inputDir))
...@@ -195,7 +215,8 @@ function createUsingComponents( ...@@ -195,7 +215,8 @@ function createUsingComponents(
export function updateMiniProgramComponentsByMainFilename( export function updateMiniProgramComponentsByMainFilename(
mainFilename: string, mainFilename: string,
inputDir: string inputDir: string,
normalizeComponentName: (name: string) => string
) { ) {
const mainDescriptor = mainDescriptors.get(mainFilename) const mainDescriptor = mainDescriptors.get(mainFilename)
if (!mainDescriptor) { if (!mainDescriptor) {
...@@ -221,7 +242,12 @@ export function updateMiniProgramComponentsByMainFilename( ...@@ -221,7 +242,12 @@ export function updateMiniProgramComponentsByMainFilename(
addMiniProgramUsingComponents( addMiniProgramUsingComponents(
removeExt(normalizeMiniProgramFilename(mainFilename, inputDir)), removeExt(normalizeMiniProgramFilename(mainFilename, inputDir)),
createUsingComponents(bindingComponents, imports, inputDir) createUsingComponents(
bindingComponents,
imports,
inputDir,
normalizeComponentName
)
) )
} }
......
...@@ -335,6 +335,9 @@ function genElement(node: ElementNode, context: TemplateCodegenContext) { ...@@ -335,6 +335,9 @@ function genElement(node: ElementNode, context: TemplateCodegenContext) {
} }
if (isUserComponent(node, context)) { if (isUserComponent(node, context)) {
tag = hyphenate(tag) tag = hyphenate(tag)
if (context.component?.normalizeName) {
tag = context.component?.normalizeName(tag)
}
} }
const { push } = context const { push } = context
......
...@@ -22,11 +22,15 @@ export default (options: UniMiniProgramPluginOptions) => { ...@@ -22,11 +22,15 @@ export default (options: UniMiniProgramPluginOptions) => {
if (!options.app.plugins) { if (!options.app.plugins) {
delete process.env.UNI_MP_PLUGIN delete process.env.UNI_MP_PLUGIN
} }
const normalizeComponentName = options.template.component?.normalizeName
return [ return [
(options: { (options: {
vueOptions?: { script?: Partial<SFCScriptCompileOptions> } vueOptions?: { script?: Partial<SFCScriptCompileOptions> }
}) => { }) => {
return uniMainJsPlugin(options.vueOptions?.script) return uniMainJsPlugin({
normalizeComponentName,
babelParserPlugins: options.vueOptions?.script?.babelParserPlugins,
})
}, },
uniManifestJsonPlugin(options), uniManifestJsonPlugin(options),
uniPagesJsonPlugin(options), uniPagesJsonPlugin(options),
...@@ -38,7 +42,10 @@ export default (options: UniMiniProgramPluginOptions) => { ...@@ -38,7 +42,10 @@ export default (options: UniMiniProgramPluginOptions) => {
(options: { (options: {
vueOptions?: { script?: Partial<SFCScriptCompileOptions> } vueOptions?: { script?: Partial<SFCScriptCompileOptions> }
}) => { }) => {
return uniUsingComponentsPlugin(options.vueOptions?.script) return uniUsingComponentsPlugin({
normalizeComponentName,
babelParserPlugins: options.vueOptions?.script?.babelParserPlugins,
})
}, },
...(process.env.UNI_SUBPACKAGE ? [uniSubpackagePlugin(options)] : []), ...(process.env.UNI_SUBPACKAGE ? [uniSubpackagePlugin(options)] : []),
...(process.env.UNI_MP_PLUGIN ? [uniMiniProgramPluginPlugin(options)] : []), ...(process.env.UNI_MP_PLUGIN ? [uniMiniProgramPluginPlugin(options)] : []),
......
...@@ -10,8 +10,13 @@ import type { SFCScriptCompileOptions } from '@vue/compiler-sfc' ...@@ -10,8 +10,13 @@ import type { SFCScriptCompileOptions } from '@vue/compiler-sfc'
import { dynamicImport } from './usingComponents' import { dynamicImport } from './usingComponents'
export function uniMainJsPlugin( export function uniMainJsPlugin(
options: Partial<SFCScriptCompileOptions> = {} options: {
normalizeComponentName?: (name: string) => string
babelParserPlugins?: SFCScriptCompileOptions['babelParserPlugins']
} = {}
) { ) {
const normalizeComponentName =
options.normalizeComponentName || ((name: string) => name)
return defineUniMainJsPlugin((opts) => { return defineUniMainJsPlugin((opts) => {
return { return {
name: 'uni:mp-main-js', name: 'uni:mp-main-js',
...@@ -31,6 +36,7 @@ export function uniMainJsPlugin( ...@@ -31,6 +36,7 @@ export function uniMainJsPlugin(
{ {
inputDir, inputDir,
resolve: this.resolve, resolve: this.resolve,
normalizeComponentName,
} }
) )
const { code, map } = await transformDynamicImports(source, imports, { const { code, map } = await transformDynamicImports(source, imports, {
......
...@@ -18,8 +18,13 @@ import { ...@@ -18,8 +18,13 @@ import {
import { virtualComponentPath, virtualPagePath } from './entry' import { virtualComponentPath, virtualPagePath } from './entry'
export function uniUsingComponentsPlugin( export function uniUsingComponentsPlugin(
options: Partial<SFCScriptCompileOptions> = {} options: {
normalizeComponentName?: (name: string) => string
babelParserPlugins?: SFCScriptCompileOptions['babelParserPlugins']
} = {}
): Plugin { ): Plugin {
const normalizeComponentName =
options.normalizeComponentName || ((name: string) => name)
const parseAst = (source: string, id: string) => { const parseAst = (source: string, id: string) => {
return parseProgram(source, id, { return parseProgram(source, id, {
babelParserPlugins: options.babelParserPlugins, babelParserPlugins: options.babelParserPlugins,
...@@ -56,7 +61,11 @@ export function uniUsingComponentsPlugin( ...@@ -56,7 +61,11 @@ export function uniUsingComponentsPlugin(
isExternal: true, isExternal: true,
} }
) )
updateMiniProgramComponentsByScriptFilename(filename, inputDir) updateMiniProgramComponentsByScriptFilename(
filename,
inputDir,
normalizeComponentName
)
return transformDynamicImports( return transformDynamicImports(
source, source,
descriptor.imports, descriptor.imports,
...@@ -73,7 +82,11 @@ export function uniUsingComponentsPlugin( ...@@ -73,7 +82,11 @@ export function uniUsingComponentsPlugin(
isExternal: true, isExternal: true,
} }
) )
updateMiniProgramComponentsByTemplateFilename(filename, inputDir) updateMiniProgramComponentsByTemplateFilename(
filename,
inputDir,
normalizeComponentName
)
return transformDynamicImports( return transformDynamicImports(
source, source,
descriptor.imports, descriptor.imports,
...@@ -90,7 +103,11 @@ export function uniUsingComponentsPlugin( ...@@ -90,7 +103,11 @@ export function uniUsingComponentsPlugin(
const descriptor = await parseMainDescriptor(filename, ast, this.resolve) const descriptor = await parseMainDescriptor(filename, ast, this.resolve)
updateMiniProgramComponentsByMainFilename(filename, inputDir) updateMiniProgramComponentsByMainFilename(
filename,
inputDir,
normalizeComponentName
)
return transformDynamicImports( return transformDynamicImports(
source, source,
......
import { assert } from './testUtils' import { assert } from './testUtils'
import { customElements } from '../src/compiler/options' import { customElements } from '../src/compiler/options'
describe('mp-weixin: transform component', () => { describe('mp-weixin: transform component', () => {
test(`Components start with wx`, () => {
assert(
`<WxBtn/>`,
`<weixin-btn u-i="2a9ec0b0-0" bind:__l="__l"/>`,
`(_ctx, _cache) => {
return {}
}`
)
})
test(`component with v-show`, () => { test(`component with v-show`, () => {
assert( assert(
`<custom v-show="ok"/>`, `<custom v-show="ok"/>`,
......
...@@ -100,7 +100,8 @@ const miniProgram = { ...@@ -100,7 +100,8 @@ const miniProgram = {
component: { component: {
dir: COMPONENTS_DIR, dir: COMPONENTS_DIR,
vShow: uniCliShared.COMPONENT_CUSTOM_HIDDEN, vShow: uniCliShared.COMPONENT_CUSTOM_HIDDEN,
getPropertySync: false, // 为了避免 Setting data field "uP" to undefined is invalid 警告 getPropertySync: false,
normalizeName: (name) => name.startsWith('wx-') ? name.replace('wx-', 'weixin-') : name,
}, },
}; };
const projectConfigFilename = 'project.config.json'; const projectConfigFilename = 'project.config.json';
......
...@@ -57,6 +57,8 @@ export const miniProgram: MiniProgramCompilerOptions = { ...@@ -57,6 +57,8 @@ export const miniProgram: MiniProgramCompilerOptions = {
dir: COMPONENTS_DIR, dir: COMPONENTS_DIR,
vShow: COMPONENT_CUSTOM_HIDDEN, vShow: COMPONENT_CUSTOM_HIDDEN,
getPropertySync: false, // 为了避免 Setting data field "uP" to undefined is invalid 警告 getPropertySync: false, // 为了避免 Setting data field "uP" to undefined is invalid 警告
normalizeName: (name) =>
name.startsWith('wx-') ? name.replace('wx-', 'weixin-') : name,
}, },
} }
const projectConfigFilename = 'project.config.json' const projectConfigFilename = 'project.config.json'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册