mirror of
https://gitee.com/vuejs/vue.git
synced 2024-12-04 21:17:55 +08:00
feat(compiler/watch): allow unicode characters in component names and watch paths (#8666)
close #8564
This commit is contained in:
parent
325fc7693c
commit
9c718522ba
@ -11,12 +11,11 @@
|
||||
|
||||
import { makeMap, no } from 'shared/util'
|
||||
import { isNonPhrasingTag } from 'web/compiler/util'
|
||||
import { unicodeLetters } from 'core/util/lang'
|
||||
|
||||
// Regular Expressions for parsing tags and attributes
|
||||
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
|
||||
// could use https://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-QName
|
||||
// but for Vue templates we can enforce a simple charset
|
||||
const ncname = '[a-zA-Z_][\\w\\-\\.]*'
|
||||
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z${unicodeLetters}]*`
|
||||
const qnameCapture = `((?:${ncname}\\:)?${ncname})`
|
||||
const startTagOpen = new RegExp(`^<${qnameCapture}`)
|
||||
const startTagClose = /^\s*(\/?)>/
|
||||
|
@ -1,5 +1,12 @@
|
||||
/* @flow */
|
||||
|
||||
/**
|
||||
* unicode letters used for parsing html tags, component names and property paths.
|
||||
* using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname
|
||||
* skipping \u10000-\uEFFFF due to it freezing up PhantomJS
|
||||
*/
|
||||
export const unicodeLetters = 'a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD'
|
||||
|
||||
/**
|
||||
* Check if a string starts with $ or _
|
||||
*/
|
||||
@ -23,7 +30,7 @@ export function def (obj: Object, key: string, val: any, enumerable?: boolean) {
|
||||
/**
|
||||
* Parse simple path.
|
||||
*/
|
||||
const bailRE = /[^\w.$]/
|
||||
const bailRE = new RegExp(`[^${unicodeLetters}.$]`)
|
||||
export function parsePath (path: string): any {
|
||||
if (bailRE.test(path)) {
|
||||
return
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
import config from '../config'
|
||||
import { warn } from './debug'
|
||||
import { nativeWatch } from './env'
|
||||
import { set } from '../observer/index'
|
||||
import { hasSymbol } from '../util/index'
|
||||
import { unicodeLetters } from './lang'
|
||||
import { nativeWatch, hasSymbol } from './env'
|
||||
|
||||
import {
|
||||
ASSET_TYPES,
|
||||
@ -264,11 +264,10 @@ function checkComponents (options: Object) {
|
||||
}
|
||||
|
||||
export function validateComponentName (name: string) {
|
||||
if (!/^[a-zA-Z][\w-]*$/.test(name)) {
|
||||
if (!new RegExp(`^[a-zA-Z][\\-\\.0-9_${unicodeLetters}]*$`).test(name)) {
|
||||
warn(
|
||||
'Invalid component name: "' + name + '". Component names ' +
|
||||
'can only contain alphanumeric characters and the hyphen, ' +
|
||||
'and must start with a letter.'
|
||||
'should conform to valid custom element name in html5 specification.'
|
||||
)
|
||||
}
|
||||
if (isBuiltInTag(name) || config.isReservedTag(name)) {
|
||||
|
@ -26,6 +26,9 @@ describe('Instance methods data', () => {
|
||||
data: {
|
||||
a: {
|
||||
b: 1
|
||||
},
|
||||
유니코드: {
|
||||
なまえ: 'ok'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -108,6 +111,15 @@ describe('Instance methods data', () => {
|
||||
expect(spy).toHaveBeenCalledWith(1)
|
||||
})
|
||||
|
||||
it('handler option in string', () => {
|
||||
vm.$watch('유니코드.なまえ', {
|
||||
handler: 'foo',
|
||||
immediate: true
|
||||
})
|
||||
expect(spy.calls.count()).toBe(1)
|
||||
expect(spy).toHaveBeenCalledWith('ok')
|
||||
})
|
||||
|
||||
it('warn expression', () => {
|
||||
vm.$watch('a + b', spy)
|
||||
expect('Watcher only accepts simple dot-delimited paths').toHaveBeenWarned()
|
||||
|
@ -15,7 +15,7 @@ describe('Options name', () => {
|
||||
})
|
||||
|
||||
/* eslint-disable */
|
||||
expect(`Invalid component name: "Hyper*Vue". Component names can only contain alphanumeric characters and the hyphen, and must start with a letter.`)
|
||||
expect(`Invalid component name: "Hyper*Vue".`)
|
||||
.toHaveBeenWarned()
|
||||
/* eslint-enable */
|
||||
|
||||
@ -24,7 +24,7 @@ describe('Options name', () => {
|
||||
})
|
||||
|
||||
/* eslint-disable */
|
||||
expect(`Invalid component name: "2Cool2BValid". Component names can only contain alphanumeric characters and the hyphen, and must start with a letter.`)
|
||||
expect(`Invalid component name: "2Cool2BValid".`)
|
||||
.toHaveBeenWarned()
|
||||
/* eslint-enable */
|
||||
})
|
||||
@ -37,4 +37,12 @@ describe('Options name', () => {
|
||||
expect(SuperComponent.options.components['SuperVue']).toEqual(SuperComponent)
|
||||
expect(SuperComponent.options.components['super-component']).toEqual(SuperComponent)
|
||||
})
|
||||
|
||||
it('should allow all potential custom element name for component name including non-alphanumeric characters', () => {
|
||||
Vue.extend({
|
||||
name: 'my-컴포넌트'
|
||||
})
|
||||
|
||||
expect(`Invalid component name`).not.toHaveBeenWarned()
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user