|
|
@@ -1,11 +1,6 @@
|
|
|
-var utils = require('./utils'),
|
|
|
- dirId = 1,
|
|
|
-
|
|
|
- // match up to the first single pipe, ignore those within quotes.
|
|
|
- KEY_RE = /^(?:['"](?:\\.|[^'"])*['"]|\\.|[^\|]|\|\|)+/,
|
|
|
- ARG_RE = /^([\w-$ ]+):(.+)$/,
|
|
|
- FILTERS_RE = /\|[^\|]+/g,
|
|
|
- FILTER_TOKEN_RE = /[^\s']+|'[^']+'|[^\s"]+|"[^"]+"/g,
|
|
|
+var dirId = 1,
|
|
|
+ ARG_RE = /^[\w-]+$/,
|
|
|
+ FILTER_TOKEN_RE = /[^\s'"]+|'[^']+'|"[^"]+"/g,
|
|
|
NESTING_RE = /^\$(parent|root)\./,
|
|
|
SINGLE_VAR_RE = /^[\w\.$]+$/,
|
|
|
QUOTE_RE = /"/g
|
|
|
@@ -14,16 +9,19 @@ var utils = require('./utils'),
|
|
|
* Directive class
|
|
|
* represents a single directive instance in the DOM
|
|
|
*/
|
|
|
-function Directive (dirname, definition, expression, rawKey, compiler, node) {
|
|
|
+function Directive (name, ast, definition, compiler, el) {
|
|
|
|
|
|
this.id = dirId++
|
|
|
- this.name = dirname
|
|
|
+ this.name = name
|
|
|
this.compiler = compiler
|
|
|
this.vm = compiler.vm
|
|
|
- this.el = node
|
|
|
+ this.el = el
|
|
|
this.computeFilters = false
|
|
|
+ this.key = ast.key
|
|
|
+ this.arg = ast.arg
|
|
|
+ this.expression = ast.expression
|
|
|
|
|
|
- var isEmpty = expression === ''
|
|
|
+ var isEmpty = this.expression === ''
|
|
|
|
|
|
// mix in properties from the directive definition
|
|
|
if (typeof definition === 'function') {
|
|
|
@@ -46,15 +44,11 @@ function Directive (dirname, definition, expression, rawKey, compiler, node) {
|
|
|
|
|
|
this.expression = (
|
|
|
this.isLiteral
|
|
|
- ? compiler.eval(expression)
|
|
|
- : expression
|
|
|
+ ? compiler.eval(this.expression)
|
|
|
+ : this.expression
|
|
|
).trim()
|
|
|
-
|
|
|
- var parsed = Directive.parseArg(rawKey)
|
|
|
- this.key = parsed.key
|
|
|
- this.arg = parsed.arg
|
|
|
-
|
|
|
- var filters = Directive.parseFilters(this.expression.slice(rawKey.length)),
|
|
|
+
|
|
|
+ var filters = ast.filters,
|
|
|
filter, fn, i, l, computed
|
|
|
if (filters) {
|
|
|
this.filters = []
|
|
|
@@ -133,8 +127,8 @@ DirProto.unbind = function () {
|
|
|
// Exposed static methods -----------------------------------------------------
|
|
|
|
|
|
/**
|
|
|
- * split a unquoted-comma separated expression into
|
|
|
- * multiple clauses
|
|
|
+ * Parse a directive string into an Array of
|
|
|
+ * AST-like objects representing directives
|
|
|
*/
|
|
|
Directive.parse = function (str) {
|
|
|
|
|
|
@@ -147,7 +141,8 @@ Directive.parse = function (str) {
|
|
|
argIndex = 0,
|
|
|
dirs = [],
|
|
|
dir = {},
|
|
|
- lastFilterIndex = 0
|
|
|
+ lastFilterIndex = 0,
|
|
|
+ arg
|
|
|
|
|
|
for (var c, i = 0, l = str.length; i < l; i++) {
|
|
|
c = str.charAt(i)
|
|
|
@@ -165,12 +160,15 @@ Directive.parse = function (str) {
|
|
|
begin = argIndex = lastFilterIndex = i + 1
|
|
|
} else if (c === ':' && !dir.key && !dir.arg) {
|
|
|
// argument
|
|
|
- argIndex = i + 1
|
|
|
- dir.arg = str.slice(begin, i).trim()
|
|
|
+ arg = str.slice(begin, i).trim()
|
|
|
+ if (ARG_RE.test(arg)) {
|
|
|
+ argIndex = i + 1
|
|
|
+ dir.arg = str.slice(begin, i).trim()
|
|
|
+ }
|
|
|
} else if (c === '|' && str.charAt(i + 1) !== '|') {
|
|
|
- if (!dir.key) {
|
|
|
+ if (dir.key === undefined) {
|
|
|
// first filter, end of key
|
|
|
- lastFilterIndex = i
|
|
|
+ lastFilterIndex = i + 1
|
|
|
dir.key = str.slice(argIndex, i).trim()
|
|
|
} else {
|
|
|
// already has filter
|
|
|
@@ -194,127 +192,40 @@ Directive.parse = function (str) {
|
|
|
curly--
|
|
|
}
|
|
|
}
|
|
|
- if (begin !== i) {
|
|
|
+ if (i === 0 || begin !== i) {
|
|
|
pushDir()
|
|
|
}
|
|
|
|
|
|
function pushDir () {
|
|
|
dir.expression = str.slice(begin, i).trim()
|
|
|
- if (!dir.key) {
|
|
|
+ if (dir.key === undefined) {
|
|
|
dir.key = str.slice(argIndex, i).trim()
|
|
|
} else if (lastFilterIndex !== begin) {
|
|
|
pushFilter()
|
|
|
}
|
|
|
- dirs.push(dir)
|
|
|
+ if (i === 0 || dir.key) {
|
|
|
+ dirs.push(dir)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
function pushFilter () {
|
|
|
- (dir.filters = dir.filters || [])
|
|
|
- .push(str.slice(lastFilterIndex + 1, i).trim())
|
|
|
+ var exp = str.slice(lastFilterIndex, i).trim(),
|
|
|
+ filter
|
|
|
+ if (exp) {
|
|
|
+ filter = {}
|
|
|
+ var tokens = exp.match(FILTER_TOKEN_RE)
|
|
|
+ filter.name = tokens[0]
|
|
|
+ filter.args = tokens.length > 1 ? tokens.slice(1) : null
|
|
|
+ }
|
|
|
+ if (filter) {
|
|
|
+ (dir.filters = dir.filters || []).push(filter)
|
|
|
+ }
|
|
|
lastFilterIndex = i + 1
|
|
|
}
|
|
|
|
|
|
return dirs
|
|
|
}
|
|
|
|
|
|
-// function split (str) {
|
|
|
-// var inSingle = false,
|
|
|
-// inDouble = false,
|
|
|
-// curly = 0,
|
|
|
-// square = 0,
|
|
|
-// paren = 0,
|
|
|
-// begin = 0,
|
|
|
-// end = 0,
|
|
|
-// res = []
|
|
|
-// for (var c, i = 0, l = str.length; i < l; i++) {
|
|
|
-// c = str.charAt(i)
|
|
|
-// if (inSingle) {
|
|
|
-// if (c === "'") {
|
|
|
-// inSingle = !inSingle
|
|
|
-// }
|
|
|
-// end++
|
|
|
-// } else if (inDouble) {
|
|
|
-// if (c === '"') {
|
|
|
-// inDouble = !inDouble
|
|
|
-// }
|
|
|
-// end++
|
|
|
-// } else if (c === ',' && !paren && !curly && !square) {
|
|
|
-// res.push(str.slice(begin, end))
|
|
|
-// begin = end = i + 1
|
|
|
-// } else {
|
|
|
-// if (c === '"') {
|
|
|
-// inDouble = true
|
|
|
-// } else if (c === "'") {
|
|
|
-// inSingle = true
|
|
|
-// } else if (c === '(') {
|
|
|
-// paren++
|
|
|
-// } else if (c === ')') {
|
|
|
-// paren--
|
|
|
-// } else if (c === '[') {
|
|
|
-// square++
|
|
|
-// } else if (c === ']') {
|
|
|
-// square--
|
|
|
-// } else if (c === '{') {
|
|
|
-// curly++
|
|
|
-// } else if (c === '}') {
|
|
|
-// curly--
|
|
|
-// }
|
|
|
-// end++
|
|
|
-// }
|
|
|
-// }
|
|
|
-// if (begin !== end) {
|
|
|
-// res.push(str.slice(begin, end))
|
|
|
-// }
|
|
|
-// return res
|
|
|
-// }
|
|
|
-
|
|
|
-// /**
|
|
|
-// * parse a key, extract argument
|
|
|
-// */
|
|
|
-// Directive.parseArg = function (rawKey) {
|
|
|
-// var key = rawKey,
|
|
|
-// arg = null
|
|
|
-// if (rawKey.indexOf(':') > -1) {
|
|
|
-// var argMatch = rawKey.match(ARG_RE)
|
|
|
-// key = argMatch
|
|
|
-// ? argMatch[2].trim()
|
|
|
-// : key
|
|
|
-// arg = argMatch
|
|
|
-// ? argMatch[1].trim()
|
|
|
-// : arg
|
|
|
-// }
|
|
|
-// return {
|
|
|
-// key: key,
|
|
|
-// arg: arg
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
-// /**
|
|
|
-// * parse a the filters
|
|
|
-// */
|
|
|
-// Directive.parseFilters = function (exp) {
|
|
|
-// if (exp.indexOf('|') < 0) {
|
|
|
-// return
|
|
|
-// }
|
|
|
-// var filters = exp.match(FILTERS_RE),
|
|
|
-// res, i, l, tokens
|
|
|
-// if (filters) {
|
|
|
-// res = []
|
|
|
-// for (i = 0, l = filters.length; i < l; i++) {
|
|
|
-// tokens = filters[i].slice(1).match(FILTER_TOKEN_RE)
|
|
|
-// if (tokens) {
|
|
|
-// res.push({
|
|
|
-// name: tokens[0],
|
|
|
-// args: tokens.length > 1
|
|
|
-// ? tokens.slice(1)
|
|
|
-// : null
|
|
|
-// })
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-// return res
|
|
|
-// }
|
|
|
-
|
|
|
/**
|
|
|
* Inline computed filters so they become part
|
|
|
* of the expression
|
|
|
@@ -345,36 +256,4 @@ function escapeQuote (v) {
|
|
|
: v
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * Parse the key from a directive raw expression
|
|
|
- */
|
|
|
-Directive.parseKey = function (expression) {
|
|
|
- if (expression.indexOf('|') > -1) {
|
|
|
- var keyMatch = expression.match(KEY_RE)
|
|
|
- if (keyMatch) {
|
|
|
- return keyMatch[0].trim()
|
|
|
- }
|
|
|
- } else {
|
|
|
- return expression.trim()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * make sure the directive and expression is valid
|
|
|
- * before we create an instance
|
|
|
- */
|
|
|
-Directive.build = function (dirname, expression, compiler, node) {
|
|
|
-
|
|
|
- var dir = compiler.getOption('directives', dirname)
|
|
|
- if (!dir) return
|
|
|
-
|
|
|
- var rawKey = Directive.parseKey(expression)
|
|
|
- // have a valid raw key, or be an empty directive
|
|
|
- if (rawKey || expression === '') {
|
|
|
- return new Directive(dirname, dir, expression, rawKey, compiler, node)
|
|
|
- } else {
|
|
|
- utils.warn('Invalid directive expression: ' + expression)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
module.exports = Directive
|