github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/vue-1.0.24/src/parsers/template.js (about)

     1  import Cache from '../cache'
     2  import {
     3    inBrowser,
     4    trimNode,
     5    isTemplate,
     6    isFragment
     7  } from '../util/index'
     8  
     9  const templateCache = new Cache(1000)
    10  const idSelectorCache = new Cache(1000)
    11  
    12  const map = {
    13    efault: [0, '', ''],
    14    legend: [1, '<fieldset>', '</fieldset>'],
    15    tr: [2, '<table><tbody>', '</tbody></table>'],
    16    col: [
    17      2,
    18      '<table><tbody></tbody><colgroup>',
    19      '</colgroup></table>'
    20    ]
    21  }
    22  
    23  map.td =
    24  map.th = [
    25    3,
    26    '<table><tbody><tr>',
    27    '</tr></tbody></table>'
    28  ]
    29  
    30  map.option =
    31  map.optgroup = [
    32    1,
    33    '<select multiple="multiple">',
    34    '</select>'
    35  ]
    36  
    37  map.thead =
    38  map.tbody =
    39  map.colgroup =
    40  map.caption =
    41  map.tfoot = [1, '<table>', '</table>']
    42  
    43  map.g =
    44  map.defs =
    45  map.symbol =
    46  map.use =
    47  map.image =
    48  map.text =
    49  map.circle =
    50  map.ellipse =
    51  map.line =
    52  map.path =
    53  map.polygon =
    54  map.polyline =
    55  map.rect = [
    56    1,
    57    '<svg ' +
    58      'xmlns="http://www.w3.org/2000/svg" ' +
    59      'xmlns:xlink="http://www.w3.org/1999/xlink" ' +
    60      'xmlns:ev="http://www.w3.org/2001/xml-events"' +
    61      'version="1.1">',
    62    '</svg>'
    63  ]
    64  
    65  /**
    66   * Check if a node is a supported template node with a
    67   * DocumentFragment content.
    68   *
    69   * @param {Node} node
    70   * @return {Boolean}
    71   */
    72  
    73  function isRealTemplate (node) {
    74    return isTemplate(node) && isFragment(node.content)
    75  }
    76  
    77  const tagRE = /<([\w:-]+)/
    78  const entityRE = /&#?\w+?;/
    79  
    80  /**
    81   * Convert a string template to a DocumentFragment.
    82   * Determines correct wrapping by tag types. Wrapping
    83   * strategy found in jQuery & component/domify.
    84   *
    85   * @param {String} templateString
    86   * @param {Boolean} raw
    87   * @return {DocumentFragment}
    88   */
    89  
    90  function stringToFragment (templateString, raw) {
    91    // try a cache hit first
    92    var cacheKey = raw
    93      ? templateString
    94      : templateString.trim()
    95    var hit = templateCache.get(cacheKey)
    96    if (hit) {
    97      return hit
    98    }
    99  
   100    var frag = document.createDocumentFragment()
   101    var tagMatch = templateString.match(tagRE)
   102    var entityMatch = entityRE.test(templateString)
   103  
   104    if (!tagMatch && !entityMatch) {
   105      // text only, return a single text node.
   106      frag.appendChild(
   107        document.createTextNode(templateString)
   108      )
   109    } else {
   110      var tag = tagMatch && tagMatch[1]
   111      var wrap = map[tag] || map.efault
   112      var depth = wrap[0]
   113      var prefix = wrap[1]
   114      var suffix = wrap[2]
   115      var node = document.createElement('div')
   116  
   117      node.innerHTML = prefix + templateString + suffix
   118      while (depth--) {
   119        node = node.lastChild
   120      }
   121  
   122      var child
   123      /* eslint-disable no-cond-assign */
   124      while (child = node.firstChild) {
   125      /* eslint-enable no-cond-assign */
   126        frag.appendChild(child)
   127      }
   128    }
   129    if (!raw) {
   130      trimNode(frag)
   131    }
   132    templateCache.put(cacheKey, frag)
   133    return frag
   134  }
   135  
   136  /**
   137   * Convert a template node to a DocumentFragment.
   138   *
   139   * @param {Node} node
   140   * @return {DocumentFragment}
   141   */
   142  
   143  function nodeToFragment (node) {
   144    // if its a template tag and the browser supports it,
   145    // its content is already a document fragment. However, iOS Safari has
   146    // bug when using directly cloned template content with touch
   147    // events and can cause crashes when the nodes are removed from DOM, so we
   148    // have to treat template elements as string templates. (#2805)
   149    /* istanbul ignore if */
   150    if (isRealTemplate(node)) {
   151      return stringToFragment(node.innerHTML)
   152    }
   153    // script template
   154    if (node.tagName === 'SCRIPT') {
   155      return stringToFragment(node.textContent)
   156    }
   157    // normal node, clone it to avoid mutating the original
   158    var clonedNode = cloneNode(node)
   159    var frag = document.createDocumentFragment()
   160    var child
   161    /* eslint-disable no-cond-assign */
   162    while (child = clonedNode.firstChild) {
   163    /* eslint-enable no-cond-assign */
   164      frag.appendChild(child)
   165    }
   166    trimNode(frag)
   167    return frag
   168  }
   169  
   170  // Test for the presence of the Safari template cloning bug
   171  // https://bugs.webkit.org/showug.cgi?id=137755
   172  var hasBrokenTemplate = (function () {
   173    /* istanbul ignore else */
   174    if (inBrowser) {
   175      var a = document.createElement('div')
   176      a.innerHTML = '<template>1</template>'
   177      return !a.cloneNode(true).firstChild.innerHTML
   178    } else {
   179      return false
   180    }
   181  })()
   182  
   183  // Test for IE10/11 textarea placeholder clone bug
   184  var hasTextareaCloneBug = (function () {
   185    /* istanbul ignore else */
   186    if (inBrowser) {
   187      var t = document.createElement('textarea')
   188      t.placeholder = 't'
   189      return t.cloneNode(true).value === 't'
   190    } else {
   191      return false
   192    }
   193  })()
   194  
   195  /**
   196   * 1. Deal with Safari cloning nested <template> bug by
   197   *    manually cloning all template instances.
   198   * 2. Deal with IE10/11 textarea placeholder bug by setting
   199   *    the correct value after cloning.
   200   *
   201   * @param {Element|DocumentFragment} node
   202   * @return {Element|DocumentFragment}
   203   */
   204  
   205  export function cloneNode (node) {
   206    /* istanbul ignore if */
   207    if (!node.querySelectorAll) {
   208      return node.cloneNode()
   209    }
   210    var res = node.cloneNode(true)
   211    var i, original, cloned
   212    /* istanbul ignore if */
   213    if (hasBrokenTemplate) {
   214      var tempClone = res
   215      if (isRealTemplate(node)) {
   216        node = node.content
   217        tempClone = res.content
   218      }
   219      original = node.querySelectorAll('template')
   220      if (original.length) {
   221        cloned = tempClone.querySelectorAll('template')
   222        i = cloned.length
   223        while (i--) {
   224          cloned[i].parentNode.replaceChild(
   225            cloneNode(original[i]),
   226            cloned[i]
   227          )
   228        }
   229      }
   230    }
   231    /* istanbul ignore if */
   232    if (hasTextareaCloneBug) {
   233      if (node.tagName === 'TEXTAREA') {
   234        res.value = node.value
   235      } else {
   236        original = node.querySelectorAll('textarea')
   237        if (original.length) {
   238          cloned = res.querySelectorAll('textarea')
   239          i = cloned.length
   240          while (i--) {
   241            cloned[i].value = original[i].value
   242          }
   243        }
   244      }
   245    }
   246    return res
   247  }
   248  
   249  /**
   250   * Process the template option and normalizes it into a
   251   * a DocumentFragment that can be used as a partial or a
   252   * instance template.
   253   *
   254   * @param {*} template
   255   *        Possible values include:
   256   *        - DocumentFragment object
   257   *        - Node object of type Template
   258   *        - id selector: '#some-template-id'
   259   *        - template string: '<div><span>{{msg}}</span></div>'
   260   * @param {Boolean} shouldClone
   261   * @param {Boolean} raw
   262   *        inline HTML interpolation. Do not check for id
   263   *        selector and keep whitespace in the string.
   264   * @return {DocumentFragment|undefined}
   265   */
   266  
   267  export function parseTemplate (template, shouldClone, raw) {
   268    var node, frag
   269  
   270    // if the template is already a document fragment,
   271    // do nothing
   272    if (isFragment(template)) {
   273      trimNode(template)
   274      return shouldClone
   275        ? cloneNode(template)
   276        : template
   277    }
   278  
   279    if (typeof template === 'string') {
   280      // id selector
   281      if (!raw && template.charAt(0) === '#') {
   282        // id selector can be cached too
   283        frag = idSelectorCache.get(template)
   284        if (!frag) {
   285          node = document.getElementById(template.slice(1))
   286          if (node) {
   287            frag = nodeToFragment(node)
   288            // save selector to cache
   289            idSelectorCache.put(template, frag)
   290          }
   291        }
   292      } else {
   293        // normal string template
   294        frag = stringToFragment(template, raw)
   295      }
   296    } else if (template.nodeType) {
   297      // a direct node
   298      frag = nodeToFragment(template)
   299    }
   300  
   301    return frag && shouldClone
   302      ? cloneNode(frag)
   303      : frag
   304  }