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  }