|
@@ -1,13 +1,11 @@
|
|
|
var _ = require('../util')
|
|
var _ = require('../util')
|
|
|
-var textParser = require('../parsers/text')
|
|
|
|
|
var propDef = require('../directives/internal/prop')
|
|
var propDef = require('../directives/internal/prop')
|
|
|
var propBindingModes = require('../config')._propBindingModes
|
|
var propBindingModes = require('../config')._propBindingModes
|
|
|
|
|
|
|
|
// regexes
|
|
// regexes
|
|
|
var identRE = require('../parsers/path').identRE
|
|
var identRE = require('../parsers/path').identRE
|
|
|
-var dataAttrRE = /^data-/
|
|
|
|
|
var settablePathRE = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*|\[[^\[\]]+\])*$/
|
|
var settablePathRE = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*|\[[^\[\]]+\])*$/
|
|
|
-var literalValueRE = /^(true|false)$|^\d.*/
|
|
|
|
|
|
|
+var literalValueRE = /^(true|false)$|^\d.*|^'[^']*'$|^"[^"]*"$/
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Compile props on a root element and return
|
|
* Compile props on a root element and return
|
|
@@ -18,13 +16,10 @@ var literalValueRE = /^(true|false)$|^\d.*/
|
|
|
* @return {Function} propsLinkFn
|
|
* @return {Function} propsLinkFn
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
-// TODO: 1.0.0 we can just loop through el.attributes and
|
|
|
|
|
-// check for prop- prefixes.
|
|
|
|
|
-
|
|
|
|
|
module.exports = function compileProps (el, propOptions) {
|
|
module.exports = function compileProps (el, propOptions) {
|
|
|
var props = []
|
|
var props = []
|
|
|
var i = propOptions.length
|
|
var i = propOptions.length
|
|
|
- var options, name, attr, value, path, prop, literal, single
|
|
|
|
|
|
|
+ var options, name, attr, value, path, prop
|
|
|
while (i--) {
|
|
while (i--) {
|
|
|
options = propOptions[i]
|
|
options = propOptions[i]
|
|
|
name = options.name
|
|
name = options.name
|
|
@@ -40,7 +35,7 @@ module.exports = function compileProps (el, propOptions) {
|
|
|
// props could contain dashes, which will be
|
|
// props could contain dashes, which will be
|
|
|
// interpreted as minus calculations by the parser
|
|
// interpreted as minus calculations by the parser
|
|
|
// so we need to camelize the path here
|
|
// so we need to camelize the path here
|
|
|
- path = _.camelize(name.replace(dataAttrRE, ''))
|
|
|
|
|
|
|
+ path = _.camelize(name)
|
|
|
if (!identRE.test(path)) {
|
|
if (!identRE.test(path)) {
|
|
|
process.env.NODE_ENV !== 'production' && _.warn(
|
|
process.env.NODE_ENV !== 'production' && _.warn(
|
|
|
'Invalid prop key: "' + name + '". Prop keys ' +
|
|
'Invalid prop key: "' + name + '". Prop keys ' +
|
|
@@ -48,20 +43,9 @@ module.exports = function compileProps (el, propOptions) {
|
|
|
)
|
|
)
|
|
|
continue
|
|
continue
|
|
|
}
|
|
}
|
|
|
- attr = _.hyphenate(name)
|
|
|
|
|
- value = el.getAttribute(attr)
|
|
|
|
|
|
|
|
|
|
- if (value === null) {
|
|
|
|
|
- value = el.getAttribute('data-' + attr)
|
|
|
|
|
- if (value !== null) {
|
|
|
|
|
- attr = 'data-' + attr
|
|
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
|
|
- _.deprecation.DATA_PROPS(attr, value)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // create a prop descriptor
|
|
|
|
|
|
|
+ attr = 'prop-' + _.hyphenate(name)
|
|
|
|
|
+ value = el.getAttribute(attr)
|
|
|
prop = {
|
|
prop = {
|
|
|
name: name,
|
|
name: name,
|
|
|
raw: value,
|
|
raw: value,
|
|
@@ -69,70 +53,36 @@ module.exports = function compileProps (el, propOptions) {
|
|
|
options: options,
|
|
options: options,
|
|
|
mode: propBindingModes.ONE_WAY
|
|
mode: propBindingModes.ONE_WAY
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
if (value !== null) {
|
|
if (value !== null) {
|
|
|
- // important so that this doesn't get compiled
|
|
|
|
|
- // again as a normal attribute binding
|
|
|
|
|
el.removeAttribute(attr)
|
|
el.removeAttribute(attr)
|
|
|
- var tokens = textParser.parse(value)
|
|
|
|
|
- if (tokens) {
|
|
|
|
|
-
|
|
|
|
|
- if (process.env.NODE_ENV !== 'production') {
|
|
|
|
|
- _.deprecation.PROPS(attr, value)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+ value = value.trim()
|
|
|
|
|
+ // check binding type
|
|
|
|
|
+ if (literalValueRE.test(value)) {
|
|
|
|
|
+ prop.mode = propBindingModes.ONE_TIME
|
|
|
|
|
+ } else {
|
|
|
prop.dynamic = true
|
|
prop.dynamic = true
|
|
|
- prop.parentPath = textParser.tokensToExp(tokens)
|
|
|
|
|
- // check prop binding type.
|
|
|
|
|
- single = tokens.length === 1
|
|
|
|
|
- literal = literalValueRE.test(prop.parentPath)
|
|
|
|
|
- // one time: {{* prop}}
|
|
|
|
|
- if (literal || (single && tokens[0].oneTime)) {
|
|
|
|
|
|
|
+ if (value.charAt(0) === '*') {
|
|
|
prop.mode = propBindingModes.ONE_TIME
|
|
prop.mode = propBindingModes.ONE_TIME
|
|
|
- } else if (
|
|
|
|
|
- !literal &&
|
|
|
|
|
- (single && tokens[0].twoWay)
|
|
|
|
|
- ) {
|
|
|
|
|
- if (settablePathRE.test(prop.parentPath)) {
|
|
|
|
|
|
|
+ value = value.slice(1).trim()
|
|
|
|
|
+ } else if (value.charAt(0) === '@') {
|
|
|
|
|
+ value = value.slice(1).trim()
|
|
|
|
|
+ if (settablePathRE.test(value)) {
|
|
|
prop.mode = propBindingModes.TWO_WAY
|
|
prop.mode = propBindingModes.TWO_WAY
|
|
|
} else {
|
|
} else {
|
|
|
process.env.NODE_ENV !== 'production' && _.warn(
|
|
process.env.NODE_ENV !== 'production' && _.warn(
|
|
|
'Cannot bind two-way prop with non-settable ' +
|
|
'Cannot bind two-way prop with non-settable ' +
|
|
|
- 'parent path: ' + prop.parentPath
|
|
|
|
|
|
|
+ 'parent path: ' + value
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- } else {
|
|
|
|
|
- // new syntax
|
|
|
|
|
- attr = 'bind-' + attr
|
|
|
|
|
- value = prop.raw = el.getAttribute(attr)
|
|
|
|
|
- if (value !== null) {
|
|
|
|
|
- // mark it so we know this is a bind
|
|
|
|
|
- prop.bindSyntax = true
|
|
|
|
|
- el.removeAttribute(attr)
|
|
|
|
|
- value = value.trim()
|
|
|
|
|
- // check binding type
|
|
|
|
|
- if (literalValueRE.test(value)) {
|
|
|
|
|
- prop.mode = propBindingModes.ONE_TIME
|
|
|
|
|
- } else {
|
|
|
|
|
- prop.dynamic = true
|
|
|
|
|
- if (value.charAt(0) === '*') {
|
|
|
|
|
- prop.mode = propBindingModes.ONE_TIME
|
|
|
|
|
- value = value.slice(1).trim()
|
|
|
|
|
- } else if (value.charAt(0) === '@') {
|
|
|
|
|
- value = value.slice(1).trim()
|
|
|
|
|
- if (settablePathRE.test(value)) {
|
|
|
|
|
- prop.mode = propBindingModes.TWO_WAY
|
|
|
|
|
- } else {
|
|
|
|
|
- process.env.NODE_ENV !== 'production' && _.warn(
|
|
|
|
|
- 'Cannot bind two-way prop with non-settable ' +
|
|
|
|
|
- 'parent path: ' + value
|
|
|
|
|
- )
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
prop.parentPath = value
|
|
prop.parentPath = value
|
|
|
|
|
+ } else if (options.required) {
|
|
|
|
|
+ // warn missing required
|
|
|
|
|
+ process.env.NODE_ENV !== 'production' && _.warn(
|
|
|
|
|
+ 'Missing required prop: ' + name
|
|
|
|
|
+ )
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// warn required two-way
|
|
// warn required two-way
|
|
@@ -146,13 +96,6 @@ module.exports = function compileProps (el, propOptions) {
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // warn missing required
|
|
|
|
|
- if (value === null && options && options.required) {
|
|
|
|
|
- process.env.NODE_ENV !== 'production' && _.warn(
|
|
|
|
|
- 'Missing required prop: ' + name
|
|
|
|
|
- )
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
// push prop
|
|
// push prop
|
|
|
props.push(prop)
|
|
props.push(prop)
|
|
|
}
|
|
}
|
|
@@ -200,19 +143,14 @@ function makePropsLinkFn (props) {
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
// literal, cast it and just set once
|
|
// literal, cast it and just set once
|
|
|
- var raw = prop.raw
|
|
|
|
|
- if (options.type === Boolean && raw === '') {
|
|
|
|
|
- value = true
|
|
|
|
|
- } else if (raw.trim()) {
|
|
|
|
|
- value = _.toBoolean(_.toNumber(raw))
|
|
|
|
|
- if (process.env.NODE_ENV !== 'production' &&
|
|
|
|
|
- !prop.bindSyntax &&
|
|
|
|
|
- value !== raw) {
|
|
|
|
|
- _.deprecation.PROP_CASTING(prop.name, prop.raw)
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- value = raw
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ var raw = _.stripQuotes(prop.raw) || prop.raw
|
|
|
|
|
+ value = options.type === Boolean && raw === ''
|
|
|
|
|
+ ? true
|
|
|
|
|
+ // do not cast emptry string.
|
|
|
|
|
+ // _.toNumber casts empty string to 0.
|
|
|
|
|
+ : raw.trim()
|
|
|
|
|
+ ? _.toBoolean(_.toNumber(raw))
|
|
|
|
|
+ : raw
|
|
|
_.initProp(vm, prop, value)
|
|
_.initProp(vm, prop, value)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|