github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/vue-1.0.24/src/parsers/directive.js (about) 1 import { toNumber, stripQuotes } from '../util/index' 2 import Cache from '../cache' 3 4 const cache = new Cache(1000) 5 const filterTokenRE = /[^\s'"]+|'[^']*'|"[^"]*"/g 6 const reservedArgRE = /^in$|^-?\d+/ 7 8 /** 9 * Parser state 10 */ 11 12 var str, dir 13 var c, prev, i, l, lastFilterIndex 14 var inSingle, inDouble, curly, square, paren 15 16 /** 17 * Push a filter to the current directive object 18 */ 19 20 function pushFilter () { 21 var exp = str.slice(lastFilterIndex, i).trim() 22 var filter 23 if (exp) { 24 filter = {} 25 var tokens = exp.match(filterTokenRE) 26 filter.name = tokens[0] 27 if (tokens.length > 1) { 28 filter.args = tokens.slice(1).map(processFilterArg) 29 } 30 } 31 if (filter) { 32 (dir.filters = dir.filters || []).push(filter) 33 } 34 lastFilterIndex = i + 1 35 } 36 37 /** 38 * Check if an argument is dynamic and strip quotes. 39 * 40 * @param {String} arg 41 * @return {Object} 42 */ 43 44 function processFilterArg (arg) { 45 if (reservedArgRE.test(arg)) { 46 return { 47 value: toNumber(arg), 48 dynamic: false 49 } 50 } else { 51 var stripped = stripQuotes(arg) 52 var dynamic = stripped === arg 53 return { 54 value: dynamic ? arg : stripped, 55 dynamic: dynamic 56 } 57 } 58 } 59 60 /** 61 * Parse a directive value and extract the expression 62 * and its filters into a descriptor. 63 * 64 * Example: 65 * 66 * "a + 1 | uppercase" will yield: 67 * { 68 * expression: 'a + 1', 69 * filters: [ 70 * { name: 'uppercase', args: null } 71 * ] 72 * } 73 * 74 * @param {String} s 75 * @return {Object} 76 */ 77 78 export function parseDirective (s) { 79 var hit = cache.get(s) 80 if (hit) { 81 return hit 82 } 83 84 // reset parser state 85 str = s 86 inSingle = inDouble = false 87 curly = square = paren = 0 88 lastFilterIndex = 0 89 dir = {} 90 91 for (i = 0, l = str.length; i < l; i++) { 92 prev = c 93 c = str.charCodeAt(i) 94 if (inSingle) { 95 // check single quote 96 if (c === 0x27 && prev !== 0x5C) inSingle = !inSingle 97 } else if (inDouble) { 98 // check double quote 99 if (c === 0x22 && prev !== 0x5C) inDouble = !inDouble 100 } else if ( 101 c === 0x7C && // pipe 102 str.charCodeAt(i + 1) !== 0x7C && 103 str.charCodeAt(i - 1) !== 0x7C 104 ) { 105 if (dir.expression == null) { 106 // first filter, end of expression 107 lastFilterIndex = i + 1 108 dir.expression = str.slice(0, i).trim() 109 } else { 110 // already has filter 111 pushFilter() 112 } 113 } else { 114 switch (c) { 115 case 0x22: inDouble = true; break // " 116 case 0x27: inSingle = true; break // ' 117 case 0x28: paren++; break // ( 118 case 0x29: paren--; break // ) 119 case 0x5B: square++; break // [ 120 case 0x5D: square--; break // ] 121 case 0x7B: curly++; break // { 122 case 0x7D: curly--; break // } 123 } 124 } 125 } 126 127 if (dir.expression == null) { 128 dir.expression = str.slice(0, i).trim() 129 } else if (lastFilterIndex !== 0) { 130 pushFilter() 131 } 132 133 cache.put(s, dir) 134 return dir 135 }