PageSourceSearch

https://www.jhrl.com/sites/all/libraries/riotjs/riot.js?tlse4v

js jhrl.com collected 2026-10-06 13:17:40 UTC 69,364 bytes, 2,536 lines download raw bytes

1/* Riot v2.3.17, @license MIT */
2
3;(function(window, undefined) {
4  'use strict';
5var riot = { version: 'v2.3.17', settings: {} },
6  // be aware, internal usage
7  // ATTENTION: prefix the global dynamic variables with `__`
8
9  // counter to give a unique id to all the Tag instances
10  __uid = 0,
11  // tags instances cache
12  __virtualDom = [],
13  // tags implementation cache
14  __tagImpl = {},
15
16  /**
17   * Const
18   */
19  GLOBAL_MIXIN = '__global_mixin',
20
21  // riot specific prefixes
22  RIOT_PREFIX = 'riot-',
23  RIOT_TAG = RIOT_PREFIX + 'tag',
24  RIOT_TAG_IS = 'data-is',
25
26  // for typeof == '' comparisons
27  T_STRING = 'string',
28  T_OBJECT = 'object',
29  T_UNDEF  = 'undefined',
30  T_BOOL   = 'boolean',
31  T_FUNCTION = 'function',
32  // special native tags that cannot be treated like the others
33  SPECIAL_TAGS_REGEX = /^(?:t(?:body|head|foot|[rhd])|caption|col(?:group)?|opt(?:ion|group))$/,
34  RESERVED_WORDS_BLACKLIST = ['_item', '_id', '_parent', 'update', 'root', 'mount', 'unmount', 'mixin', 'isMounted', 'isLoop', 'tags', 'parent', 'opts', 'trigger', 'on', 'off', 'one'],
35
36  // version# for IE 8-11, 0 for others
37  IE_VERSION = (window && window.document || {}).documentMode | 0
38/* istanbul ignore next */
39riot.observable = function(el) {
40
41  /**
42   * Extend the original object or create a new empty one
43   * @type { Object }
44   */
45
46  el = el || {}
47
48  /**
49   * Private variables and methods
50   */
51  var callbacks = {},
52    slice = Array.prototype.slice,
53    onEachEvent = function(e, fn) { e.replace(/\S+/g, fn) }
54
55  // extend the object adding the observable methods
56  Object.defineProperties(el, {
57    /**
58     * Listen to the given space separated list of `events` and execute the `callback` each time an event is triggered.
59     * @param  { String } events - events ids
60     * @param  { Function } fn - callback function
61     * @returns { Object } el
62     */
63    on: {
64      value: function(events, fn) {
65        if (typeof fn != 'function')  return el
66
67        onEachEvent(events, function(name, pos) {
68          (callbacks[name] = callbacks[name] || []).push(fn)
69          fn.typed = pos > 0
70        })
71
72        return el
73      },
74      enumerable: false,
75      writable: false,
76      configurable: false
77    },
78
79    /**
80     * Removes the given space separated list of `events` listeners
81     * @param   { String } events - events ids
82     * @param   { Function } fn - callback function
83     * @returns { Object } el
84     */
85    off: {
86      value: function(events, fn) {
87        if (events == '*' && !fn) callbacks = {}
88        else {
89          onEachEvent(events, function(name) {
90            if (fn) {
91              var arr = callbacks[name]
92              for (var i = 0, cb; cb = arr && arr[i]; ++i) {
93                if (cb == fn) arr.splice(i--, 1)
94              }
95            } else delete callbacks[name]
96          })
97        }
98        return el
99      },
100      enumerable: false,
101      writable: false,
102      configurable: false
103    },
104
105    /**
106     * Listen to the given space separated list of `events` and execute the `callback` at most once
107     * @param   { String } events - events ids
108     * @param   { Function } fn - callback function
109     * @returns { Object } el
110     */
111    one: {
112      value: function(events, fn) {
113        function on() {
114          el.off(events, on)
115          fn.apply(el, arguments)
116        }
117        return el.on(events, on)
118      },
119      enumerable: false,
120      writable: false,
121      configurable: false
122    },
123
124    /**
125     * Execute all callback functions that listen to the given space separated list of `events`
126     * @param   { String } events - events ids
127     * @returns { Object } el
128     */
129    trigger: {
130      value: function(events) {
131
132        // getting the arguments
133        var arglen = arguments.length - 1,
134          args = new Array(arglen),
135          fns
136
137        for (var i = 0; i < arglen; i++) {
138          args[i] = arguments[i + 1] // skip first argument
139        }
140
141        onEachEvent(events, function(name) {
142
143          fns = slice.call(callbacks[name] || [], 0)
144
145          for (var i = 0, fn; fn = fns[i]; ++i) {
146            if (fn.busy) return
147            fn.busy = 1
148            fn.apply(el, fn.typed ? [name].concat(args) : args)
149            if (fns[i] !== fn) { i-- }
150            fn.busy = 0
151          }
152
153          if (callbacks['*'] && name != '*')
154            el.trigger.apply(el, ['*', name].concat(args))
155
156        })
157
158        return el
159      },
160      enumerable: false,
161      writable: false,
162      configurable: false
163    }
164  })
165
166  return el
167
168}
169/* istanbul ignore next */
170;(function(riot) {
171
172/**
173 * Simple client-side router
174 * @module riot-route
175 */
176
177
178var RE_ORIGIN = /^.+?\/+[^\/]+/,
179  EVENT_LISTENER = 'EventListener',
180  REMOVE_EVENT_LISTENER = 'remove' + EVENT_LISTENER,
181  ADD_EVENT_LISTENER = 'add' + EVENT_LISTENER,
182  HAS_ATTRIBUTE = 'hasAttribute',
183  REPLACE = 'replace',
184  POPSTATE = 'popstate',
185  HASHCHANGE = 'hashchange',
186  TRIGGER = 'trigger',
187  MAX_EMIT_STACK_LEVEL = 3,
188  win = typeof window != 'undefined' && window,
189  doc = typeof document != 'undefined' && document,
190  hist = win && history,
191  loc = win && (hist.location || win.location), // see html5-history-api
192  prot = Router.prototype, // to minify more
193  clickEvent = doc && doc.ontouchstart ? 'touchstart' : 'click',
194  started = false,
195  central = riot.observable(),
196  routeFound = false,
197  debouncedEmit,
198  base, current, parser, secondParser, emitStack = [], emitStackLevel = 0
199
200/**
201 * Default parser. You can replace it via router.parser method.
202 * @param {string} path - current path (normalized)
203 * @returns {array} array
204 */
205function DEFAULT_PARSER(path) {
206  return path.split(/[/?#]/)
207}
208
209/**
210 * Default parser (second). You can replace it via router.parser method.
211 * @param {string} path - current path (normalized)
212 * @param {string} filter - filter string (normalized)
213 * @returns {array} array
214 */
215function DEFAULT_SECOND_PARSER(path, filter) {
216  var re = new RegExp('^' + filter[REPLACE](/\*/g, '([^/?#]+?)')[REPLACE](/\.\./, '.*') + '$'),
217    args = path.match(re)
218
219  if (args) return args.slice(1)
220}
221
222/**
223 * Simple/cheap debounce implementation
224 * @param   {function} fn - callback
225 * @param   {number} delay - delay in seconds
226 * @returns {function} debounced function
227 */
228function debounce(fn, delay) {
229  var t
230  return function () {
231    clearTimeout(t)
232    t = setTimeout(fn, delay)
233  }
234}
235
236/**
237 * Set the window listeners to trigger the routes
238 * @param {boolean} autoExec - see route.start
239 */
240function start(autoExec) {
241  debouncedEmit = debounce(emit, 1)
242  win[ADD_EVENT_LISTENER](POPSTATE, debouncedEmit)
243  win[ADD_EVENT_LISTENER](HASHCHANGE, debouncedEmit)
244  doc[ADD_EVENT_LISTENER](clickEvent, click)
245  if (autoExec) emit(true)
246}
247
248/**
249 * Router class
250 */
251function Router() {
252  this.$ = []
253  riot.observable(this) // make it observable
254  central.on('stop', this.s.bind(this))
255  central.on('emit', this.e.bind(this))
256}
257
258function normalize(path) {
259  return path[REPLACE](/^\/|\/$/, '')
260}
261
262function isString(str) {
263  return typeof str == 'string'
264}
265
266/**
267 * Get the part after domain name
268 * @param {string} href - fullpath
269 * @returns {string} path from root
270 */
271function getPathFromRoot(href) {
272  return (href || loc.href || '')[REPLACE](RE_ORIGIN, '')
273}
274
275/**
276 * Get the part after base
277 * @param {string} href - fullpath
278 * @returns {string} path from base
279 */
280function getPathFromBase(href) {
281  return base[0] == '#'
282    ? (href || loc.href || '').split(base)[1] || ''
283    : getPathFromRoot(href)[REPLACE](base, '')
284}
285
286function emit(force) {
287  // the stack is needed for redirections
288  var isRoot = emitStackLevel == 0
289  if (MAX_EMIT_STACK_LEVEL <= emitStackLevel) return
290
291  emitStackLevel++
292  emitStack.push(function() {
293    var path = getPathFromBase()
294    if (force || path != current) {
295      central[TRIGGER]('emit', path)
296      current = path
297    }
298  })
299  if (isRoot) {
300    while (emitStack.length) {
301      emitStack[0]()
302      emitStack.shift()
303    }
304    emitStackLevel = 0
305  }
306}
307
308function click(e) {
309  if (
310    e.which != 1 // not left click
311    || e.metaKey || e.ctrlKey || e.shiftKey // or meta keys
312    || e.defaultPrevented // or default prevented
313  ) return
314
315  var el = e.target
316  while (el && el.nodeName != 'A') el = el.parentNode
317  if (
318    !el || el.nodeName != 'A' // not A tag
319    || el[HAS_ATTRIBUTE]('download') // has download attr
320    || !el[HAS_ATTRIBUTE]('href') // has no href attr
321    || el.target && el.target != '_self' // another window or frame
322    || el.href.indexOf(loc.href.match(RE_ORIGIN)[0]) == -1 // cross origin
323  ) return
324
325  if (el.href != loc.href) {
326    if (
327      el.href.split('#')[0] == loc.href.split('#')[0] // internal jump
328      || base != '#' && getPathFromRoot(el.href).indexOf(base) !== 0 // outside of base
329      || !go(getPathFromBase(el.href), el.title || doc.title) // route not found
330    ) return
331  }
332
333  e.preventDefault()
334}
335
336/**
337 * Go to the path
338 * @param {string} path - destination path
339 * @param {string} title - page title
340 * @param {boolean} shouldReplace - use replaceState or pushState
341 * @returns {boolean} - route not found flag
342 */
343function go(path, title, shouldReplace) {
344  if (hist) { // if a browser
345    path = base + normalize(path)
346    title = title || doc.title
347    // browsers ignores the second parameter `title`
348    shouldReplace
349      ? hist.replaceState(null, title, path)
350      : hist.pushState(null, title, path)
351    // so we need to set it manually
352    doc.title = title
353    routeFound = false
354    emit()
355    return routeFound
356  }
357
358  // Server-side usage: directly execute handlers for the path
359  return central[TRIGGER]('emit', getPathFromBase(path))
360}
361
362/**
363 * Go to path or set action
364 * a single string:                go there
365 * two strings:                    go there with setting a title
366 * two strings and boolean:        replace history with setting a title
367 * a single function:              set an action on the default route
368 * a string/RegExp and a function: set an action on the route
369 * @param {(string|function)} first - path / action / filter
370 * @param {(string|RegExp|function)} second - title / action
371 * @param {boolean} third - replace flag
372 */
373prot.m = function(first, second, third) {
374  if (isString(first) && (!second || isString(second))) go(first, second, third || false)
375  else if (second) this.r(first, second)
376  else this.r('@', first)
377}
378
379/**
380 * Stop routing
381 */
382prot.s = function() {
383  this.off('*')
384  this.$ = []
385}
386
387/**
388 * Emit
389 * @param {string} path - path
390 */
391prot.e = function(path) {
392  this.$.concat('@').some(function(filter) {
393    var args = (filter == '@' ? parser : secondParser)(normalize(path), normalize(filter))
394    if (typeof args != 'undefined') {
395      this[TRIGGER].apply(null, [filter].concat(args))
396      return routeFound = true // exit from loop
397    }
398  }, this)
399}
400
401/**
402 * Register route
403 * @param {string} filter - filter for matching to url
404 * @param {function} action - action to register
405 */
406prot.r = function(filter, action) {
407  if (filter != '@') {
408    filter = '/' + normalize(filter)
409    this.$.push(filter)
410  }
411  this.on(filter, action)
412}
413
414var mainRouter = new Router()
415var route = mainRouter.m.bind(mainRouter)
416
417/**
418 * Create a sub router
419 * @returns {function} the method of a new Router object
420 */
421route.create = function() {
422  var newSubRouter = new Router()
423  // stop only this sub-router
424  newSubRouter.m.stop = newSubRouter.s.bind(newSubRouter)
425  // return sub-router's main method
426  return newSubRouter.m.bind(newSubRouter)
427}
428
429/**
430 * Set the base of url
431 * @param {(str|RegExp)} arg - a new base or '#' or '#!'
432 */
433route.base = function(arg) {
434  base = arg || '#'
435  current = getPathFromBase() // recalculate current path
436}
437
438/** Exec routing right now **/
439route.exec = function() {
440  emit(true)
441}
442
443/**
444 * Replace the default router to yours
445 * @param {function} fn - your parser function
446 * @param {function} fn2 - your secondParser function
447 */
448route.parser = function(fn, fn2) {
449  if (!fn && !fn2) {
450    // reset parser for testing...
451    parser = DEFAULT_PARSER
452    secondParser = DEFAULT_SECOND_PARSER
453  }
454  if (fn) parser = fn
455  if (fn2) secondParser = fn2
456}
457
458/**
459 * Helper function to get url query as an object
460 * @returns {object} parsed query
461 */
462route.query = function() {
463  var q = {}
464  var href = loc.href || current
465  href[REPLACE](/[?&](.+?)=([^&]*)/g, function(_, k, v) { q[k] = v })
466  return q
467}
468
469/** Stop routing **/
470route.stop = function () {
471  if (started) {
472    if (win) {
473      win[REMOVE_EVENT_LISTENER](POPSTATE, debouncedEmit)
474      win[REMOVE_EVENT_LISTENER](HASHCHANGE, debouncedEmit)
475      doc[REMOVE_EVENT_LISTENER](clickEvent, click)
476    }
477    central[TRIGGER]('stop')
478    started = false
479  }
480}
481
482/**
483 * Start routing
484 * @param {boolean} autoExec - automatically exec after starting if true
485 */
486route.start = function (autoExec) {
487  if (!started) {
488    if (win) {
489      if (document.readyState == 'complete') start(autoExec)
490      // the timeout is needed to solve
491      // a weird safari bug https://github.com/riot/route/issues/33
492      else win[ADD_EVENT_LISTENER]('load', function() {
493        setTimeout(function() { start(autoExec) }, 1)
494      })
495    }
496    started = true
497  }
498}
499
500/** Prepare the router **/
501route.base()
502route.parser()
503
504riot.route = route
505})(riot)
506/* istanbul ignore next */
507
508/**
509 * The riot template engine
510 * @version v2.3.21
511 */
512
513/**
514 * riot.util.brackets
515 *
516 * - `brackets    ` - Returns a string or regex based on its parameter
517 * - `brackets.set` - Change the current riot brackets
518 *
519 * @module
520 */
521
522var brackets = (function (UNDEF) {
523
524  var
525    REGLOB = 'g',
526
527    R_MLCOMMS = /\/\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//g,
528
529    R_STRINGS = /"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'/g,
530
531    S_QBLOCKS = R_STRINGS.source + '|' +
532      /(?:\breturn\s+|(?:[$\w\)\]]|\+\+|--)\s*(\/)(?![*\/]))/.source + '|' +
533      /\/(?=[^*\/])[^[\/\\]*(?:(?:\[(?:\\.|[^\]\\]*)*\]|\\.)[^[\/\\]*)*?(\/)[gim]*/.source,
534
535    FINDBRACES = {
536      '(': RegExp('([()])|'   + S_QBLOCKS, REGLOB),
537      '[': RegExp('([[\\]])|' + S_QBLOCKS, REGLOB),
538      '{': RegExp('([{}])|'   + S_QBLOCKS, REGLOB)
539    },
540
541    DEFAULT = '{ }'
542
543  var _pairs = [
544    '{', '}',
545    '{', '}',
546    /{[^}]*}/,
547    /\\([{}])/g,
548    /\\({)|{/g,
549    RegExp('\\\\(})|([[({])|(})|' + S_QBLOCKS, REGLOB),
550    DEFAULT,
551    /^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/,
552    /(^|[^\\]){=[\S\s]*?}/
553  ]
554
555  var
556    cachedBrackets = UNDEF,
557    _regex,
558    _cache = [],
559    _settings
560
561  function _loopback (re) { return re }
562
563  function _rewrite (re, bp) {
564    if (!bp) bp = _cache
565    return new RegExp(
566      re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : ''
567    )
568  }
569
570  function _create (pair) {
571    if (pair === DEFAULT) return _pairs
572
573    var arr = pair.split(' ')
574
575    if (arr.length !== 2 || /[\x00-\x1F<>a-zA-Z0-9'",;\\]/.test(pair)) {
576      throw new Error('Unsupported brackets "' + pair + '"')
577    }
578    arr = arr.concat(pair.replace(/(?=[[\]()*+?.^$|])/g, '\\').split(' '))
579
580    arr[4] = _rewrite(arr[1].length > 1 ? /{[\S\s]*?}/ : _pairs[4], arr)
581    arr[5] = _rewrite(pair.length > 3 ? /\\({|})/g : _pairs[5], arr)
582    arr[6] = _rewrite(_pairs[6], arr)
583    arr[7] = RegExp('\\\\(' + arr[3] + ')|([[({])|(' + arr[3] + ')|' + S_QBLOCKS, REGLOB)
584    arr[8] = pair
585    return arr
586  }
587
588  function _brackets (reOrIdx) {
589    return reOrIdx instanceof RegExp ? _regex(reOrIdx) : _cache[reOrIdx]
590  }
591
592  _brackets.split = function split (str, tmpl, _bp) {
593    // istanbul ignore next: _bp is for the compiler
594    if (!_bp) _bp = _cache
595
596    var
597      parts = [],
598      match,
599      isexpr,
600      start,
601      pos,
602      re = _bp[6]
603
604    isexpr = start = re.lastIndex = 0
605
606    while (match = re.exec(str)) {
607
608      pos = match.index
609
610      if (isexpr) {
611
612        if (match[2]) {
613          re.lastIndex = skipBraces(str, match[2], re.lastIndex)
614          continue
615        }
616        if (!match[3])
617          continue
618      }
619
620      if (!match[1]) {
621        unescapeStr(str.slice(start, pos))
622        start = re.lastIndex
623        re = _bp[6 + (isexpr ^= 1)]
624        re.lastIndex = start
625      }
626    }
627
628    if (str && start < str.length) {
629      unescapeStr(str.slice(start))
630    }
631
632    return parts
633
634    function unescapeStr (s) {
635      if (tmpl || isexpr)
636        parts.push(s && s.replace(_bp[5], '$1'))
637      else
638        parts.push(s)
639    }
640
641    function skipBraces (s, ch, ix) {
642      var
643        match,
644        recch = FINDBRACES[ch]
645
646      recch.lastIndex = ix
647      ix = 1
648      while (match = recch.exec(s)) {
649        if (match[1] &&
650          !(match[1] === ch ? ++ix : --ix)) break
651      }
652      return ix ? s.length : recch.lastIndex
653    }
654  }
655
656  _brackets.hasExpr = function hasExpr (str) {
657    return _cache[4].test(str)
658  }
659
660  _brackets.loopKeys = function loopKeys (expr) {
661    var m = expr.match(_cache[9])
662    return m
663      ? { key: m[1], pos: m[2], val: _cache[0] + m[3].trim() + _cache[1] }
664      : { val: expr.trim() }
665  }
666
667  _brackets.hasRaw = function (src) {
668    return _cache[10].test(src)
669  }
670
671  _brackets.array = function array (pair) {
672    return pair ? _create(pair) : _cache
673  }
674
675  function _reset (pair) {
676    if ((pair || (pair = DEFAULT)) !== _cache[8]) {
677      _cache = _create(pair)
678      _regex = pair === DEFAULT ? _loopback : _rewrite
679      _cache[9] = _regex(_pairs[9])
680      _cache[10] = _regex(_pairs[10])
681    }
682    cachedBrackets = pair
683  }
684
685  function _setSettings (o) {
686    var b
687    o = o || {}
688    b = o.brackets
689    Object.defineProperty(o, 'brackets', {
690      set: _reset,
691      get: function () { return cachedBrackets },
692      enumerable: true
693    })
694    _settings = o
695    _reset(b)
696  }
697
698  Object.defineProperty(_brackets, 'settings', {
699    set: _setSettings,
700    get: function () { return _settings }
701  })
702
703  /* istanbul ignore next: in the browser riot is always in the scope */
704  _brackets.settings = typeof riot !== 'undefined' && riot.settings || {}
705  _brackets.set = _reset
706
707  _brackets.R_STRINGS = R_STRINGS
708  _brackets.R_MLCOMMS = R_MLCOMMS
709  _brackets.S_QBLOCKS = S_QBLOCKS
710
711  return _brackets
712
713})()
714
715/**
716 * @module tmpl
717 *
718 * tmpl          - Root function, returns the template value, render with data
719 * tmpl.hasExpr  - Test the existence of a expression inside a string
720 * tmpl.loopKeys - Get the keys for an 'each' loop (used by `_each`)
721 */
722
723var tmpl = (function () {
724
725  var _cache = {}
726
727  function _tmpl (str, data) {
728    if (!str) return str
729
730    return (_cache[str] || (_cache[str] = _create(str))).call(data, _logErr)
731  }
732
733  _tmpl.haveRaw = brackets.hasRaw
734
735  _tmpl.hasExpr = brackets.hasExpr
736
737  _tmpl.loopKeys = brackets.loopKeys
738
739  _tmpl.errorHandler = null
740
741  function _logErr (err, ctx) {
742
743    if (_tmpl.errorHandler) {
744
745      err.riotData = {
746        tagName: ctx && ctx.root && ctx.root.tagName,
747        _riot_id: ctx && ctx._riot_id  //eslint-disable-line camelcase
748      }
749      _tmpl.errorHandler(err)
750    }
751  }
752
753  function _create (str) {
754
755    var expr = _getTmpl(str)
756    if (expr.slice(0, 11) !== 'try{return ') expr = 'return ' + expr
757
758    return new Function('E', expr + ';')
759  }
760
761  var
762    RE_QBLOCK = RegExp(brackets.S_QBLOCKS, 'g'),
763    RE_QBMARK = /\x01(\d+)~/g
764
765  function _getTmpl (str) {
766    var
767      qstr = [],
768      expr,
769      parts = brackets.split(str.replace(/\u2057/g, '"'), 1)
770
771    if (parts.length > 2 || parts[0]) {
772      var i, j, list = []
773
774      for (i = j = 0; i < parts.length; ++i) {
775
776        expr = parts[i]
777
778        if (expr && (expr = i & 1 ?
779
780              _parseExpr(expr, 1, qstr) :
781
782              '"' + expr
783                .replace(/\\/g, '\\\\')
784                .replace(/\r\n?|\n/g, '\\n')
785                .replace(/"/g, '\\"') +
786              '"'
787
788          )) list[j++] = expr
789
790      }
791
792      expr = j < 2 ? list[0] :
793             '[' + list.join(',') + '].join("")'
794
795    } else {
796
797      expr = _parseExpr(parts[1], 0, qstr)
798    }
799
800    if (qstr[0])
801      expr = expr.replace(RE_QBMARK, function (_, pos) {
802        return qstr[pos]
803          .replace(/\r/g, '\\r')
804          .replace(/\n/g, '\\n')
805      })
806
807    return expr
808  }
809
810  var
811    RE_BREND = {
812      '(': /[()]/g,
813      '[': /[[\]]/g,
814      '{': /[{}]/g
815    },
816    CS_IDENT = /^(?:(-?[_A-Za-z\xA0-\xFF][-\w\xA0-\xFF]*)|\x01(\d+)~):/
817
818  function _parseExpr (expr, asText, qstr) {
819
820    if (expr[0] === '=') expr = expr.slice(1)
821
822    expr = expr
823          .replace(RE_QBLOCK, function (s, div) {
824            return s.length > 2 && !div ? '\x01' + (qstr.push(s) - 1) + '~' : s
825          })
826          .replace(/\s+/g, ' ').trim()
827          .replace(/\ ?([[\({},?\.:])\ ?/g, '$1')
828
829    if (expr) {
830      var
831        list = [],
832        cnt = 0,
833        match
834
835      while (expr &&
836            (match = expr.match(CS_IDENT)) &&
837            !match.index
838        ) {
839        var
840          key,
841          jsb,
842          re = /,|([[{(])|$/g
843
844        expr = RegExp.rightContext
845        key  = match[2] ? qstr[match[2]].slice(1, -1).trim().replace(/\s+/g, ' ') : match[1]
846
847        while (jsb = (match = re.exec(expr))[1]) skipBraces(jsb, re)
848
849        jsb  = expr.slice(0, match.index)
850        expr = RegExp.rightContext
851
852        list[cnt++] = _wrapExpr(jsb, 1, key)
853      }
854
855      expr = !cnt ? _wrapExpr(expr, asText) :
856          cnt > 1 ? '[' + list.join(',') + '].join(" ").trim()' : list[0]
857    }
858    return expr
859
860    function skipBraces (ch, re) {
861      var
862        mm,
863        lv = 1,
864        ir = RE_BREND[ch]
865
866      ir.lastIndex = re.lastIndex
867      while (mm = ir.exec(expr)) {
868        if (mm[0] === ch) ++lv
869        else if (!--lv) break
870      }
871      re.lastIndex = lv ? expr.length : ir.lastIndex
872    }
873  }
874
875  // istanbul ignore next: not both
876  var
877    JS_CONTEXT = '"in this?this:' + (typeof window !== 'object' ? 'global' : 'window') + ').',
878    JS_VARNAME = /[,{][$\w]+:|(^ *|[^$\w\.])(?!(?:typeof|true|false|null|undefined|in|instanceof|is(?:Finite|NaN)|void|NaN|new|Date|RegExp|Math)(?![$\w]))([$_A-Za-z][$\w]*)/g,
879    JS_NOPROPS = /^(?=(\.[$\w]+))\1(?:[^.[(]|$)/
880
881  function _wrapExpr (expr, asText, key) {
882    var tb
883
884    expr = expr.replace(JS_VARNAME, function (match, p, mvar, pos, s) {
885      if (mvar) {
886        pos = tb ? 0 : pos + match.length
887
888        if (mvar !== 'this' && mvar !== 'global' && mvar !== 'window') {
889          match = p + '("' + mvar + JS_CONTEXT + mvar
890          if (pos) tb = (s = s[pos]) === '.' || s === '(' || s === '['
891        } else if (pos) {
892          tb = !JS_NOPROPS.test(s.slice(pos))
893        }
894      }
895      return match
896    })
897
898    if (tb) {
899      expr = 'try{return ' + expr + '}catch(e){E(e,this)}'
900    }
901
902    if (key) {
903
904      expr = (tb ?
905          'function(){' + expr + '}.call(this)' : '(' + expr + ')'
906        ) + '?"' + key + '":""'
907
908    } else if (asText) {
909
910      expr = 'function(v){' + (tb ?
911          expr.replace('return ', 'v=') : 'v=(' + expr + ')'
912        ) + ';return v||v===0?v:""}.call(this)'
913    }
914
915    return expr
916  }
917
918  // istanbul ignore next: compatibility fix for beta versions
919  _tmpl.parse = function (s) { return s }
920
921  _tmpl.version = brackets.version = 'v2.3.21'
922
923  return _tmpl
924
925})()
926
927/*
928  lib/browser/tag/mkdom.js
929
930  Includes hacks needed for the Internet Explorer version 9 and below
931  See: http://kangax.github.io/compat-table/es5/#ie8
932       http://codeplanet.io/dropping-ie8/
933*/
934var mkdom = (function _mkdom() {
935  var
936    reHasYield  = /<yield\b/i,
937    reYieldAll  = /<yield\s*(?:\/>|>([\S\s]*?)<\/yield\s*>)/ig,
938    reYieldSrc  = /<yield\s+to=['"]([^'">]*)['"]\s*>([\S\s]*?)<\/yield\s*>/ig,
939    reYieldDest = /<yield\s+from=['"]?([-\w]+)['"]?\s*(?:\/>|>([\S\s]*?)<\/yield\s*>)/ig
940  var
941    rootEls = { tr: 'tbody', th: 'tr', td: 'tr', col: 'colgroup' },
942    tblTags = IE_VERSION && IE_VERSION < 10
943      ? SPECIAL_TAGS_REGEX : /^(?:t(?:body|head|foot|[rhd])|caption|col(?:group)?)$/
944
945  /**
946   * Creates a DOM element to wrap the given content. Normally an `DIV`, but can be
947   * also a `TABLE`, `SELECT`, `TBODY`, `TR`, or `COLGROUP` element.
948   *
949   * @param   {string} templ  - The template coming from the custom tag definition
950   * @param   {string} [html] - HTML content that comes from the DOM element where you
951   *           will mount the tag, mostly the original tag in the page
952   * @returns {HTMLElement} DOM element with _templ_ merged through `YIELD` with the _html_.
953   */
954  function _mkdom(templ, html) {
955    var
956      match   = templ && templ.match(/^\s*<([-\w]+)/),
957      tagName = match && match[1].toLowerCase(),
958      el = mkEl('div')
959
960    // replace all the yield tags with the tag inner html
961    templ = replaceYield(templ, html)
962
963    /* istanbul ignore next */
964    if (tblTags.test(tagName))
965      el = specialTags(el, templ, tagName)
966    else
967      el.innerHTML = templ
968
969    el.stub = true
970
971    return el
972  }
973
974  /*
975    Creates the root element for table or select child elements:
976    tr/th/td/thead/tfoot/tbody/caption/col/colgroup/option/optgroup
977  */
978  function specialTags(el, templ, tagName) {
979    var
980      select = tagName[0] === 'o',
981      parent = select ? 'select>' : 'table>'
982
983    // trim() is important here, this ensures we don't have artifacts,
984    // so we can check if we have only one element inside the parent
985    el.innerHTML = '<' + parent + templ.trim() + '</' + parent
986    parent = el.firstChild
987
988    // returns the immediate parent if tr/th/td/col is the only element, if not
989    // returns the whole tree, as this can include additional elements
990    if (select) {
991      parent.selectedIndex = -1  // for IE9, compatible w/current riot behavior
992    } else {
993      // avoids insertion of cointainer inside container (ex: tbody inside tbody)
994      var tname = rootEls[tagName]
995      if (tname && parent.childElementCount === 1) parent = $(tname, parent)
996    }
997    return parent
998  }
999
1000  /*
1001    Replace the yield tag from any tag template with the innerHTML of the
1002    original tag in the page
1003  */
1004  function replaceYield(templ, html) {
1005    // do nothing if no yield
1006    if (!reHasYield.test(templ)) return templ
1007
1008    // be careful with #1343 - string on the source having `$1`
1009    var src = {}
1010
1011    html = html && html.replace(reYieldSrc, function (_, ref, text) {
1012      src[ref] = src[ref] || text   // preserve first definition
1013      return ''
1014    }).trim()
1015
1016    return templ
1017      .replace(reYieldDest, function (_, ref, def) {  // yield with from - to attrs
1018        return src[ref] || def || ''
1019      })
1020      .replace(reYieldAll, function (_, def) {        // yield without any "from"
1021        return html || def || ''
1022      })
1023  }
1024
1025  return _mkdom
1026
1027})()
1028
1029/**
1030 * Convert the item looped into an object used to extend the child tag properties
1031 * @param   { Object } expr - object containing the keys used to extend the children tags
1032 * @param   { * } key - value to assign to the new object returned
1033 * @param   { * } val - value containing the position of the item in the array
1034 * @returns { Object } - new object containing the values of the original item
1035 *
1036 * The variables 'key' and 'val' are arbitrary.
1037 * They depend on the collection type looped (Array, Object)
1038 * and on the expression used on the each tag
1039 *
1040 */
1041function mkitem(expr, key, val) {
1042  var item = {}
1043  item[expr.key] = key
1044  if (expr.pos) item[expr.pos] = val
1045  return item
1046}
1047
1048/**
1049 * Unmount the redundant tags
1050 * @param   { Array } items - array containing the current items to loop
1051 * @param   { Array } tags - array containing all the children tags
1052 */
1053function unmountRedundant(items, tags) {
1054
1055  var i = tags.length,
1056    j = items.length,
1057    t
1058
1059  while (i > j) {
1060    t = tags[--i]
1061    tags.splice(i, 1)
1062    t.unmount()
1063  }
1064}
1065
1066/**
1067 * Move the nested custom tags in non custom loop tags
1068 * @param   { Object } child - non custom loop tag
1069 * @param   { Number } i - current position of the loop tag
1070 */
1071function moveNestedTags(child, i) {
1072  Object.keys(child.tags).forEach(function(tagName) {
1073    var tag = child.tags[tagName]
1074    if (isArray(tag))
1075      each(tag, function (t) {
1076        moveChildTag(t, tagName, i)
1077      })
1078    else
1079      moveChildTag(tag, tagName, i)
1080  })
1081}
1082
1083/**
1084 * Adds the elements for a virtual tag
1085 * @param { Tag } tag - the tag whose root's children will be inserted or appended
1086 * @param { Node } src - the node that will do the inserting or appending
1087 * @param { Tag } target - only if inserting, insert before this tag's first child
1088 */
1089function addVirtual(tag, src, target) {
1090  var el = tag._root, sib
1091  tag._virts = []
1092  while (el) {
1093    sib = el.nextSibling
1094    if (target)
1095      src.insertBefore(el, target._root)
1096    else
1097      src.appendChild(el)
1098
1099    tag._virts.push(el) // hold for unmounting
1100    el = sib
1101  }
1102}
1103
1104/**
1105 * Move virtual tag and all child nodes
1106 * @param { Tag } tag - first child reference used to start move
1107 * @param { Node } src  - the node that will do the inserting
1108 * @param { Tag } target - insert before this tag's first child
1109 * @param { Number } len - how many child nodes to move
1110 */
1111function moveVirtual(tag, src, target, len) {
1112  var el = tag._root, sib, i = 0
1113  for (; i < len; i++) {
1114    sib = el.nextSibling
1115    src.insertBefore(el, target._root)
1116    el = sib
1117  }
1118}
1119
1120
1121/**
1122 * Manage tags having the 'each'
1123 * @param   { Object } dom - DOM node we need to loop
1124 * @param   { Tag } parent - parent tag instance where the dom node is contained
1125 * @param   { String } expr - string contained in the 'each' attribute
1126 */
1127function _each(dom, parent, expr) {
1128
1129  // remove the each property from the original tag
1130  remAttr(dom, 'each')
1131
1132  var mustReorder = typeof getAttr(dom, 'no-reorder') !== T_STRING || remAttr(dom, 'no-reorder'),
1133    tagName = getTagName(dom),
1134    impl = __tagImpl[tagName] || { tmpl: dom.outerHTML },
1135    useRoot = SPECIAL_TAGS_REGEX.test(tagName),
1136    root = dom.parentNode,
1137    ref = document.createTextNode(''),
1138    child = getTag(dom),
1139    isOption = tagName.toLowerCase() === 'option', // the option tags must be treated differently
1140    tags = [],
1141    oldItems = [],
1142    hasKeys,
1143    isVirtual = dom.tagName == 'VIRTUAL'
1144
1145  // parse the each expression
1146  expr = tmpl.loopKeys(expr)
1147
1148  // insert a marked where the loop tags will be injected
1149  root.insertBefore(ref, dom)
1150
1151  // clean template code
1152  parent.one('before-mount', function () {
1153
1154    // remove the original DOM node
1155    dom.parentNode.removeChild(dom)
1156    if (root.stub) root = parent.root
1157
1158  }).on('update', function () {
1159    // get the new items collection
1160    var items = tmpl(expr.val, parent),
1161      // create a fragment to hold the new DOM nodes to inject in the parent tag
1162      frag = document.createDocumentFragment()
1163
1164    // object loop. any changes cause full redraw
1165    if (!isArray(items)) {
1166      hasKeys = items || false
1167      items = hasKeys ?
1168        Object.keys(items).map(function (key) {
1169          return mkitem(expr, key, items[key])
1170        }) : []
1171    }
1172
1173    // loop all the new items
1174    var i = 0,
1175      itemsLength = items.length
1176
1177    for (; i < itemsLength; i++) {
1178      // reorder only if the items are objects
1179      var
1180        item = items[i],
1181        _mustReorder = mustReorder && item instanceof Object && !hasKeys,
1182        oldPos = oldItems.indexOf(item),
1183        pos = ~oldPos && _mustReorder ? oldPos : i,
1184        // does a tag exist in this position?
1185        tag = tags[pos]
1186
1187      item = !hasKeys && expr.key ? mkitem(expr, item, i) : item
1188
1189      // new tag
1190      if (
1191        !_mustReorder && !tag // with no-reorder we just update the old tags
1192        ||
1193        _mustReorder && !~oldPos || !tag // by default we always try to reorder the DOM elements
1194      ) {
1195
1196        tag = new Tag(impl, {
1197          parent: parent,
1198          isLoop: true,
1199          hasImpl: !!__tagImpl[tagName],
1200          root: useRoot ? root : dom.cloneNode(),
1201          item: item
1202        }, dom.innerHTML)
1203
1204        tag.mount()
1205
1206        if (isVirtual) tag._root = tag.root.firstChild // save reference for further moves or inserts
1207        // this tag must be appended
1208        if (i == tags.length || !tags[i]) { // fix 1581
1209          if (isVirtual)
1210            addVirtual(tag, frag)
1211          else frag.appendChild(tag.root)
1212        }
1213        // this tag must be insert
1214        else {
1215          if (isVirtual)
1216            addVirtual(tag, root, tags[i])
1217          else root.insertBefore(tag.root, tags[i].root) // #1374 some browsers reset selected here
1218          oldItems.splice(i, 0, item)
1219        }
1220
1221        tags.splice(i, 0, tag)
1222        pos = i // handled here so no move
1223      } else tag.update(item, true)
1224
1225      // reorder the tag if it's not located in its previous position
1226      if (
1227        pos !== i && _mustReorder &&
1228        tags[i] // fix 1581 unable to reproduce it in a test!
1229      ) {
1230        // update the DOM
1231        if (isVirtual)
1232          moveVirtual(tag, root, tags[i], dom.childNodes.length)
1233        else root.insertBefore(tag.root, tags[i].root)
1234        // update the position attribute if it exists
1235        if (expr.pos)
1236          tag[expr.pos] = i
1237        // move the old tag instance
1238        tags.splice(i, 0, tags.splice(pos, 1)[0])
1239        // move the old item
1240        oldItems.splice(i, 0, oldItems.splice(pos, 1)[0])
1241        // if the loop tags are not custom
1242        // we need to move all their custom tags into the right position
1243        if (!child && tag.tags) moveNestedTags(tag, i)
1244      }
1245
1246      // cache the original item to use it in the events bound to this node
1247      // and its children
1248      tag._item = item
1249      // cache the real parent tag internally
1250      defineProperty(tag, '_parent', parent)
1251    }
1252
1253    // remove the redundant tags
1254    unmountRedundant(items, tags)
1255
1256    // insert the new nodes
1257    if (isOption) {
1258      root.appendChild(frag)
1259
1260      // #1374 <select> <option selected={true}> </select>
1261      if (root.length) {
1262        var si, op = root.options
1263
1264        root.selectedIndex = si = -1
1265        for (i = 0; i < op.length; i++) {
1266          if (op[i].selected = op[i].__selected) {
1267            if (si < 0) root.selectedIndex = si = i
1268          }
1269        }
1270      }
1271    }
1272    else root.insertBefore(frag, ref)
1273
1274    // set the 'tags' property of the parent tag
1275    // if child is 'undefined' it means that we don't need to set this property
1276    // for example:
1277    // we don't need store the `myTag.tags['div']` property if we are looping a div tag
1278    // but we need to track the `myTag.tags['child']` property looping a custom child node named `child`
1279    if (child) parent.tags[tagName] = tags
1280
1281    // clone the items array
1282    oldItems = items.slice()
1283
1284  })
1285
1286}
1287/**
1288 * Object that will be used to inject and manage the css of every tag instance
1289 */
1290var styleManager = (function(_riot) {
1291
1292  if (!window) return { // skip injection on the server
1293    add: function () {},
1294    inject: function () {}
1295  }
1296
1297  var styleNode = (function () {
1298    // create a new style element with the correct type
1299    var newNode = mkEl('style')
1300    setAttr(newNode, 'type', 'text/css')
1301
1302    // replace any user node or insert the new one into the head
1303    var userNode = $('style[type=riot]')
1304    if (userNode) {
1305      if (userNode.id) newNode.id = userNode.id
1306      userNode.parentNode.replaceChild(newNode, userNode)
1307    }
1308    else document.getElementsByTagName('head')[0].appendChild(newNode)
1309
1310    return newNode
1311  })()
1312
1313  // Create cache and shortcut to the correct property
1314  var cssTextProp = styleNode.styleSheet,
1315    stylesToInject = ''
1316
1317  // Expose the style node in a non-modificable property
1318  Object.defineProperty(_riot, 'styleNode', {
1319    value: styleNode,
1320    writable: true
1321  })
1322
1323  /**
1324   * Public api
1325   */
1326  return {
1327    /**
1328     * Save a tag style to be later injected into DOM
1329     * @param   { String } css [description]
1330     */
1331    add: function(css) {
1332      stylesToInject += css
1333    },
1334    /**
1335     * Inject all previously saved tag styles into DOM
1336     * innerHTML seems slow: http://jsperf.com/riot-insert-style
1337     */
1338    inject: function() {
1339      if (stylesToInject) {
1340        if (cssTextProp) cssTextProp.cssText += stylesToInject
1341        else styleNode.innerHTML += stylesToInject
1342        stylesToInject = ''
1343      }
1344    }
1345  }
1346
1347})(riot)
1348
1349
1350function parseNamedElements(root, tag, childTags, forceParsingNamed) {
1351
1352  walk(root, function(dom) {
1353    if (dom.nodeType == 1) {
1354      dom.isLoop = dom.isLoop ||
1355                  (dom.parentNode && dom.parentNode.isLoop || getAttr(dom, 'each'))
1356                    ? 1 : 0
1357
1358      // custom child tag
1359      if (childTags) {
1360        var child = getTag(dom)
1361
1362        if (child && !dom.isLoop)
1363          childTags.push(initChildTag(child, {root: dom, parent: tag}, dom.innerHTML, tag))
1364      }
1365
1366      if (!dom.isLoop || forceParsingNamed)
1367        setNamed(dom, tag, [])
1368    }
1369
1370  })
1371
1372}
1373
1374function parseExpressions(root, tag, expressions) {
1375
1376  function addExpr(dom, val, extra) {
1377    if (tmpl.hasExpr(val)) {
1378      expressions.push(extend({ dom: dom, expr: val }, extra))
1379    }
1380  }
1381
1382  walk(root, function(dom) {
1383    var type = dom.nodeType,
1384      attr
1385
1386    // text node
1387    if (type == 3 && dom.parentNode.tagName != 'STYLE') addExpr(dom, dom.nodeValue)
1388    if (type != 1) return
1389
1390    /* element */
1391
1392    // loop
1393    attr = getAttr(dom, 'each')
1394
1395    if (attr) { _each(dom, tag, attr); return false }
1396
1397    // attribute expressions
1398    each(dom.attributes, function(attr) {
1399      var name = attr.name,
1400        bool = name.split('__')[1]
1401
1402      addExpr(dom, attr.value, { attr: bool || name, bool: bool })
1403      if (bool) { remAttr(dom, name); return false }
1404
1405    })
1406
1407    // skip custom tags
1408    if (getTag(dom)) return false
1409
1410  })
1411
1412}
1413function Tag(impl, conf, innerHTML) {
1414
1415  var self = riot.observable(this),
1416    opts = inherit(conf.opts) || {},
1417    parent = conf.parent,
1418    isLoop = conf.isLoop,
1419    hasImpl = conf.hasImpl,
1420    item = cleanUpData(conf.item),
1421    expressions = [],
1422    childTags = [],
1423    root = conf.root,
1424    tagName = root.tagName.toLowerCase(),
1425    attr = {},
1426    implAttr = {},
1427    propsInSyncWithParent = [],
1428    dom
1429
1430  // only call unmount if we have a valid __tagImpl (has name property)
1431  if (impl.name && root._tag) root._tag.unmount(true)
1432
1433  // not yet mounted
1434  this.isMounted = false
1435  root.isLoop = isLoop
1436
1437  // keep a reference to the tag just created
1438  // so we will be able to mount this tag multiple times
1439  root._tag = this
1440
1441  // create a unique id to this tag
1442  // it could be handy to use it also to improve the virtual dom rendering speed
1443  defineProperty(this, '_riot_id', ++__uid) // base 1 allows test !t._riot_id
1444
1445  extend(this, { parent: parent, root: root, opts: opts, tags: {} }, item)
1446
1447  // grab attributes
1448  each(root.attributes, function(el) {
1449    var val = el.value
1450    // remember attributes with expressions only
1451    if (tmpl.hasExpr(val)) attr[el.name] = val
1452  })
1453
1454  dom = mkdom(impl.tmpl, innerHTML)
1455
1456  // options
1457  function updateOpts() {
1458    var ctx = hasImpl && isLoop ? self : parent || self
1459
1460    // update opts from current DOM attributes
1461    each(root.attributes, function(el) {
1462      var val = el.value
1463      opts[toCamel(el.name)] = tmpl.hasExpr(val) ? tmpl(val, ctx) : val
1464    })
1465    // recover those with expressions
1466    each(Object.keys(attr), function(name) {
1467      opts[toCamel(name)] = tmpl(attr[name], ctx)
1468    })
1469  }
1470
1471  function normalizeData(data) {
1472    for (var key in item) {
1473      if (typeof self[key] !== T_UNDEF && isWritable(self, key))
1474        self[key] = data[key]
1475    }
1476  }
1477
1478  function inheritFromParent () {
1479    if (!self.parent || !isLoop) return
1480    each(Object.keys(self.parent), function(k) {
1481      // some properties must be always in sync with the parent tag
1482      var mustSync = !contains(RESERVED_WORDS_BLACKLIST, k) && contains(propsInSyncWithParent, k)
1483      if (typeof self[k] === T_UNDEF || mustSync) {
1484        // track the property to keep in sync
1485        // so we can keep it updated
1486        if (!mustSync) propsInSyncWithParent.push(k)
1487        self[k] = self.parent[k]
1488      }
1489    })
1490  }
1491
1492  /**
1493   * Update the tag expressions and options
1494   * @param   { * }  data - data we want to use to extend the tag properties
1495   * @param   { Boolean } isInherited - is this update coming from a parent tag?
1496   * @returns { self }
1497   */
1498  defineProperty(this, 'update', function(data, isInherited) {
1499
1500    // make sure the data passed will not override
1501    // the component core methods
1502    data = cleanUpData(data)
1503    // inherit properties from the parent
1504    inheritFromParent()
1505    // normalize the tag properties in case an item object was initially passed
1506    if (data && isObject(item)) {
1507      normalizeData(data)
1508      item = data
1509    }
1510    extend(self, data)
1511    updateOpts()
1512    self.trigger('update', data)
1513    update(expressions, self)
1514
1515    // the updated event will be triggered
1516    // once the DOM will be ready and all the re-flows are completed
1517    // this is useful if you want to get the "real" root properties
1518    // 4 ex: root.offsetWidth ...
1519    if (isInherited && self.parent)
1520      // closes #1599
1521      self.parent.one('updated', function() { self.trigger('updated') })
1522    else rAF(function() { self.trigger('updated') })
1523
1524    return this
1525  })
1526
1527  defineProperty(this, 'mixin', function() {
1528    each(arguments, function(mix) {
1529      var instance
1530
1531      mix = typeof mix === T_STRING ? riot.mixin(mix) : mix
1532
1533      // check if the mixin is a function
1534      if (isFunction(mix)) {
1535        // create the new mixin instance
1536        instance = new mix()
1537        // save the prototype to loop it afterwards
1538        mix = mix.prototype
1539      } else instance = mix
1540
1541      // loop the keys in the function prototype or the all object keys
1542      each(Object.getOwnPropertyNames(mix), function(key) {
1543        // bind methods to self
1544        if (key != 'init')
1545          self[key] = isFunction(instance[key]) ?
1546                        instance[key].bind(self) :
1547                        instance[key]
1548      })
1549
1550      // init method will be called automatically
1551      if (instance.init) instance.init.bind(self)()
1552    })
1553    return this
1554  })
1555
1556  defineProperty(this, 'mount', function() {
1557
1558    updateOpts()
1559
1560    // add global mixin
1561    var globalMixin = riot.mixin(GLOBAL_MIXIN)
1562    if (globalMixin) self.mixin(globalMixin)
1563
1564    // initialiation
1565    if (impl.fn) impl.fn.call(self, opts)
1566
1567    // parse layout after init. fn may calculate args for nested custom tags
1568    parseExpressions(dom, self, expressions)
1569
1570    // mount the child tags
1571    toggle(true)
1572
1573    // update the root adding custom attributes coming from the compiler
1574    // it fixes also #1087
1575    if (impl.attrs)
1576      walkAttributes(impl.attrs, function (k, v) { setAttr(root, k, v) })
1577    if (impl.attrs || hasImpl)
1578      parseExpressions(self.root, self, expressions)
1579
1580    if (!self.parent || isLoop) self.update(item)
1581
1582    // internal use only, fixes #403
1583    self.trigger('before-mount')
1584
1585    if (isLoop && !hasImpl) {
1586      // update the root attribute for the looped elements
1587      root = dom.firstChild
1588    } else {
1589      while (dom.firstChild) root.appendChild(dom.firstChild)
1590      if (root.stub) root = parent.root
1591    }
1592
1593    defineProperty(self, 'root', root)
1594
1595    // parse the named dom nodes in the looped child
1596    // adding them to the parent as well
1597    if (isLoop)
1598      parseNamedElements(self.root, self.parent, null, true)
1599
1600    // if it's not a child tag we can trigger its mount event
1601    if (!self.parent || self.parent.isMounted) {
1602      self.isMounted = true
1603      self.trigger('mount')
1604    }
1605    // otherwise we need to wait that the parent event gets triggered
1606    else self.parent.one('mount', function() {
1607      // avoid to trigger the `mount` event for the tags
1608      // not visible included in an if statement
1609      if (!isInStub(self.root)) {
1610        self.parent.isMounted = self.isMounted = true
1611        self.trigger('mount')
1612      }
1613    })
1614  })
1615
1616
1617  defineProperty(this, 'unmount', function(keepRootTag) {
1618    var el = root,
1619      p = el.parentNode,
1620      ptag,
1621      tagIndex = __virtualDom.indexOf(self)
1622
1623    self.trigger('before-unmount')
1624
1625    // remove this tag instance from the global virtualDom variable
1626    if (~tagIndex)
1627      __virtualDom.splice(tagIndex, 1)
1628
1629    if (this._virts) {
1630      each(this._virts, function(v) {
1631        if (v.parentNode) v.parentNode.removeChild(v)
1632      })
1633    }
1634
1635    if (p) {
1636
1637      if (parent) {
1638        ptag = getImmediateCustomParentTag(parent)
1639        // remove this tag from the parent tags object
1640        // if there are multiple nested tags with same name..
1641        // remove this element form the array
1642        if (isArray(ptag.tags[tagName]))
1643          each(ptag.tags[tagName], function(tag, i) {
1644            if (tag._riot_id == self._riot_id)
1645              ptag.tags[tagName].splice(i, 1)
1646          })
1647        else
1648          // otherwise just delete the tag instance
1649          ptag.tags[tagName] = undefined
1650      }
1651
1652      else
1653        while (el.firstChild) el.removeChild(el.firstChild)
1654
1655      if (!keepRootTag)
1656        p.removeChild(el)
1657      else
1658        // the riot-tag attribute isn't needed anymore, remove it
1659        remAttr(p, 'riot-tag')
1660    }
1661
1662
1663    self.trigger('unmount')
1664    toggle()
1665    self.off('*')
1666    self.isMounted = false
1667    delete root._tag
1668
1669  })
1670
1671  // proxy function to bind updates
1672  // dispatched from a parent tag
1673  function onChildUpdate(data) { self.update(data, true) }
1674
1675  function toggle(isMount) {
1676
1677    // mount/unmount children
1678    each(childTags, function(child) { child[isMount ? 'mount' : 'unmount']() })
1679
1680    // listen/unlisten parent (events flow one way from parent to children)
1681    if (!parent) return
1682    var evt = isMount ? 'on' : 'off'
1683
1684    // the loop tags will be always in sync with the parent automatically
1685    if (isLoop)
1686      parent[evt]('unmount', self.unmount)
1687    else {
1688      parent[evt]('update', onChildUpdate)[evt]('unmount', self.unmount)
1689    }
1690  }
1691
1692
1693  // named elements available for fn
1694  parseNamedElements(dom, this, childTags)
1695
1696}
1697/**
1698 * Attach an event to a DOM node
1699 * @param { String } name - event name
1700 * @param { Function } handler - event callback
1701 * @param { Object } dom - dom node
1702 * @param { Tag } tag - tag instance
1703 */
1704function setEventHandler(name, handler, dom, tag) {
1705
1706  dom[name] = function(e) {
1707
1708    var ptag = tag._parent,
1709      item = tag._item,
1710      el
1711
1712    if (!item)
1713      while (ptag && !item) {
1714        item = ptag._item
1715        ptag = ptag._parent
1716      }
1717
1718    // cross browser event fix
1719    e = e || window.event
1720
1721    // override the event properties
1722    if (isWritable(e, 'currentTarget')) e.currentTarget = dom
1723    if (isWritable(e, 'target')) e.target = e.srcElement
1724    if (isWritable(e, 'which')) e.which = e.charCode || e.keyCode
1725
1726    e.item = item
1727
1728    // prevent default behaviour (by default)
1729    if (handler.call(tag, e) !== true && !/radio|check/.test(dom.type)) {
1730      if (e.preventDefault) e.preventDefault()
1731      e.returnValue = false
1732    }
1733
1734    if (!e.preventUpdate) {
1735      el = item ? getImmediateCustomParentTag(ptag) : tag
1736      el.update()
1737    }
1738
1739  }
1740
1741}
1742
1743
1744/**
1745 * Insert a DOM node replacing another one (used by if- attribute)
1746 * @param   { Object } root - parent node
1747 * @param   { Object } node - node replaced
1748 * @param   { Object } before - node added
1749 */
1750function insertTo(root, node, before) {
1751  if (!root) return
1752  root.insertBefore(before, node)
1753  root.removeChild(node)
1754}
1755
1756/**
1757 * Update the expressions in a Tag instance
1758 * @param   { Array } expressions - expression that must be re evaluated
1759 * @param   { Tag } tag - tag instance
1760 */
1761function update(expressions, tag) {
1762
1763  each(expressions, function(expr, i) {
1764
1765    var dom = expr.dom,
1766      attrName = expr.attr,
1767      value = tmpl(expr.expr, tag),
1768      parent = expr.dom.parentNode
1769
1770    if (expr.bool) {
1771      value = !!value
1772      if (attrName === 'selected') dom.__selected = value   // #1374
1773    }
1774    else if (value == null)
1775      value = ''
1776
1777    // #1638: regression of #1612, update the dom only if the value of the
1778    // expression was changed
1779    if (expr.value === value) {
1780      return
1781    }
1782    expr.value = value
1783
1784    // textarea and text nodes has no attribute name
1785    if (!attrName) {
1786      // about #815 w/o replace: the browser converts the value to a string,
1787      // the comparison by "==" does too, but not in the server
1788      value += ''
1789      // test for parent avoids error with invalid assignment to nodeValue
1790      if (parent) {
1791        if (parent.tagName === 'TEXTAREA') {
1792          parent.value = value                    // #1113
1793          if (!IE_VERSION) dom.nodeValue = value  // #1625 IE throws here, nodeValue
1794        }                                         // will be available on 'updated'
1795        else dom.nodeValue = value
1796      }
1797      return
1798    }
1799
1800    // ~~#1612: look for changes in dom.value when updating the value~~
1801    if (attrName === 'value') {
1802      dom.value = value
1803      return
1804    }
1805
1806    // remove original attribute
1807    remAttr(dom, attrName)
1808
1809    // event handler
1810    if (isFunction(value)) {
1811      setEventHandler(attrName, value, dom, tag)
1812
1813    // if- conditional
1814    } else if (attrName == 'if') {
1815      var stub = expr.stub,
1816        add = function() { insertTo(stub.parentNode, stub, dom) },
1817        remove = function() { insertTo(dom.parentNode, dom, stub) }
1818
1819      // add to DOM
1820      if (value) {
1821        if (stub) {
1822          add()
1823          dom.inStub = false
1824          // avoid to trigger the mount event if the tags is not visible yet
1825          // maybe we can optimize this avoiding to mount the tag at all
1826          if (!isInStub(dom)) {
1827            walk(dom, function(el) {
1828              if (el._tag && !el._tag.isMounted)
1829                el._tag.isMounted = !!el._tag.trigger('mount')
1830            })
1831          }
1832        }
1833      // remove from DOM
1834      } else {
1835        stub = expr.stub = stub || document.createTextNode('')
1836        // if the parentNode is defined we can easily replace the tag
1837        if (dom.parentNode)
1838          remove()
1839        // otherwise we need to wait the updated event
1840        else (tag.parent || tag).one('updated', remove)
1841
1842        dom.inStub = true
1843      }
1844    // show / hide
1845    } else if (attrName === 'show') {
1846      dom.style.display = value ? '' : 'none'
1847
1848    } else if (attrName === 'hide') {
1849      dom.style.display = value ? 'none' : ''
1850
1851    } else if (expr.bool) {
1852      dom[attrName] = value
1853      if (value) setAttr(dom, attrName, attrName)
1854
1855    } else if (value === 0 || value && typeof value !== T_OBJECT) {
1856      // <img src="{ expr }">
1857      if (startsWith(attrName, RIOT_PREFIX) && attrName != RIOT_TAG) {
1858        attrName = attrName.slice(RIOT_PREFIX.length)
1859      }
1860      setAttr(dom, attrName, value)
1861    }
1862
1863  })
1864
1865}
1866/**
1867 * Specialized function for looping an array-like collection with `each={}`
1868 * @param   { Array } els - collection of items
1869 * @param   {Function} fn - callback function
1870 * @returns { Array } the array looped
1871 */
1872function each(els, fn) {
1873  var len = els ? els.length : 0
1874
1875  for (var i = 0, el; i < len; i++) {
1876    el = els[i]
1877    // return false -> current item was removed by fn during the loop
1878    if (el != null && fn(el, i) === false) i--
1879  }
1880  return els
1881}
1882
1883/**
1884 * Detect if the argument passed is a function
1885 * @param   { * } v - whatever you want to pass to this function
1886 * @returns { Boolean } -
1887 */
1888function isFunction(v) {
1889  return typeof v === T_FUNCTION || false   // avoid IE problems
1890}
1891
1892/**
1893 * Detect if the argument passed is an object, exclude null.
1894 * NOTE: Use isObject(x) && !isArray(x) to excludes arrays.
1895 * @param   { * } v - whatever you want to pass to this function
1896 * @returns { Boolean } -
1897 */
1898function isObject(v) {
1899  return v && typeof v === T_OBJECT         // typeof null is 'object'
1900}
1901
1902/**
1903 * Remove any DOM attribute from a node
1904 * @param   { Object } dom - DOM node we want to update
1905 * @param   { String } name - name of the property we want to remove
1906 */
1907function remAttr(dom, name) {
1908  dom.removeAttribute(name)
1909}
1910
1911/**
1912 * Convert a string containing dashes to camel case
1913 * @param   { String } string - input string
1914 * @returns { String } my-string -> myString
1915 */
1916function toCamel(string) {
1917  return string.replace(/-(\w)/g, function(_, c) {
1918    return c.toUpperCase()
1919  })
1920}
1921
1922/**
1923 * Get the value of any DOM attribute on a node
1924 * @param   { Object } dom - DOM node we want to parse
1925 * @param   { String } name - name of the attribute we want to get
1926 * @returns { String | undefined } name of the node attribute whether it exists
1927 */
1928function getAttr(dom, name) {
1929  return dom.getAttribute(name)
1930}
1931
1932/**
1933 * Set any DOM attribute
1934 * @param { Object } dom - DOM node we want to update
1935 * @param { String } name - name of the property we want to set
1936 * @param { String } val - value of the property we want to set
1937 */
1938function setAttr(dom, name, val) {
1939  dom.setAttribute(name, val)
1940}
1941
1942/**
1943 * Detect the tag implementation by a DOM node
1944 * @param   { Object } dom - DOM node we need to parse to get its tag implementation
1945 * @returns { Object }
1945 it returns an object containing the implementation of a custom tag (template and boot function)
1946 */
1947function getTag(dom) {
1948  return dom.tagName && __tagImpl[getAttr(dom, RIOT_TAG_IS) ||
1949    getAttr(dom, RIOT_TAG) || dom.tagName.toLowerCase()]
1950}
1951/**
1952 * Add a child tag to its parent into the `tags` object
1953 * @param   { Object } tag - child tag instance
1954 * @param   { String } tagName - key where the new tag will be stored
1955 * @param   { Object } parent - tag instance where the new child tag will be included
1956 */
1957function addChildTag(tag, tagName, parent) {
1958  var cachedTag = parent.tags[tagName]
1959
1960  // if there are multiple children tags having the same name
1961  if (cachedTag) {
1962    // if the parent tags property is not yet an array
1963    // create it adding the first cached tag
1964    if (!isArray(cachedTag))
1965      // don't add the same tag twice
1966      if (cachedTag !== tag)
1967        parent.tags[tagName] = [cachedTag]
1968    // add the new nested tag to the array
1969    if (!contains(parent.tags[tagName], tag))
1970      parent.tags[tagName].push(tag)
1971  } else {
1972    parent.tags[tagName] = tag
1973  }
1974}
1975
1976/**
1977 * Move the position of a custom tag in its parent tag
1978 * @param   { Object } tag - child tag instance
1979 * @param   { String } tagName - key where the tag was stored
1980 * @param   { Number } newPos - index where the new tag will be stored
1981 */
1982function moveChildTag(tag, tagName, newPos) {
1983  var parent = tag.parent,
1984    tags
1985  // no parent no move
1986  if (!parent) return
1987
1988  tags = parent.tags[tagName]
1989
1990  if (isArray(tags))
1991    tags.splice(newPos, 0, tags.splice(tags.indexOf(tag), 1)[0])
1992  else addChildTag(tag, tagName, parent)
1993}
1994
1995/**
1996 * Create a new child tag including it correctly into its parent
1997 * @param   { Object } child - child tag implementation
1998 * @param   { Object } opts - tag options containing the DOM node where the tag will be mounted
1999 * @param   { String } innerHTML - inner html of the child node
2000 * @param   { Object } parent - instance of the parent tag including the child custom tag
2001 * @returns { Object } instance of the new child tag just created
2002 */
2003function initChildTag(child, opts, innerHTML, parent) {
2004  var tag = new Tag(child, opts, innerHTML),
2005    tagName = getTagName(opts.root),
2006    ptag = getImmediateCustomParentTag(parent)
2007  // fix for the parent attribute in the looped elements
2008  tag.parent = ptag
2009  // store the real parent tag
2010  // in some cases this could be different from the custom parent tag
2011  // for example in nested loops
2012  tag._parent = parent
2013
2014  // add this tag to the custom parent tag
2015  addChildTag(tag, tagName, ptag)
2016  // and also to the real parent tag
2017  if (ptag !== parent)
2018    addChildTag(tag, tagName, parent)
2019  // empty the child node once we got its template
2020  // to avoid that its children get compiled multiple times
2021  opts.root.innerHTML = ''
2022
2023  return tag
2024}
2025
2026/**
2027 * Loop backward all the parents tree to detect the first custom parent tag
2028 * @param   { Object } tag - a Tag instance
2029 * @returns { Object } the instance of the first custom parent tag found
2030 */
2031function getImmediateCustomParentTag(tag) {
2032  var ptag = tag
2033  while (!getTag(ptag.root)) {
2034    if (!ptag.parent) break
2035    ptag = ptag.parent
2036  }
2037  return ptag
2038}
2039
2040/**
2041 * Helper function to set an immutable property
2042 * @param   { Object } el - object where the new property will be set
2043 * @param   { String } key - object key where the new property will be stored
2044 * @param   { * } value - value of the new property
2045* @param   { Object } options - set the propery overriding the default options
2046 * @returns { Object } - the initial object
2047 */
2048function defineProperty(el, key, value, options) {
2049  Object.defineProperty(el, key, extend({
2050    value: value,
2051    enumerable: false,
2052    writable: false,
2053    configurable: false
2054  }, options))
2055  return el
2056}
2057
2058/**
2059 * Get the tag name of any DOM node
2060 * @param   { Object } dom - DOM node we want to parse
2061 * @returns { String } name to identify this dom node in riot
2062 */
2063function getTagName(dom) {
2064  var child = getTag(dom),
2065    namedTag = getAttr(dom, 'name'),
2066    tagName = namedTag && !tmpl.hasExpr(namedTag) ?
2067                namedTag :
2068              child ? child.name : dom.tagName.toLowerCase()
2069
2070  return tagName
2071}
2072
2073/**
2074 * Extend any object with other properties
2075 * @param   { Object } src - source object
2076 * @returns { Object } the resulting extended object
2077 *
2078 * var obj = { foo: 'baz' }
2079 * extend(obj, {bar: 'bar', foo: 'bar'})
2080 * console.log(obj) => {bar: 'bar', foo: 'bar'}
2081 *
2082 */
2083function extend(src) {
2084  var obj, args = arguments
2085  for (var i = 1; i < args.length; ++i) {
2086    if (obj = args[i]) {
2087      for (var key in obj) {
2088        // check if this property of the source object could be overridden
2089        if (isWritable(src, key))
2090          src[key] = obj[key]
2091      }
2092    }
2093  }
2094  return src
2095}
2096
2097/**
2098 * Check whether an array contains an item
2099 * @param   { Array } arr - target array
2100 * @param   { * } item - item to test
2101 * @returns { Boolean } Does 'arr' contain 'item'?
2102 */
2103function contains(arr, item) {
2104  return ~arr.indexOf(item)
2105}
2106
2107/**
2108 * Check whether an object is a kind of array
2109 * @param   { * } a - anything
2110 * @returns {Boolean} is 'a' an array?
2111 */
2112function isArray(a) { return Array.isArray(a) || a instanceof Array }
2113
2114/**
2115 * Detect whether a property of an object could be overridden
2116 * @param   { Object }  obj - source object
2117 * @param   { String }  key - object property
2118 * @returns { Boolean } is this property writable?
2119 */
2120function isWritable(obj, key) {
2121  var props = Object.getOwnPropertyDescriptor(obj, key)
2122  return typeof obj[key] === T_UNDEF || props && props.writable
2123}
2124
2125
2126/**
2127 * With this function we avoid that the internal Tag methods get overridden
2128 * @param   { Object } data - options we want to use to extend the tag instance
2129 * @returns { Object } clean object without containing the riot internal reserved words
2130 */
2131function cleanUpData(data) {
2132  if (!(data instanceof Tag) && !(data && typeof data.trigger == T_FUNCTION))
2133    return data
2134
2135  var o = {}
2136  for (var key in data) {
2137    if (!contains(RESERVED_WORDS_BLACKLIST, key))
2138      o[key] = data[key]
2139  }
2140  return o
2141}
2142
2143/**
2144 * Walk down recursively all the children tags starting dom node
2145 * @param   { Object }   dom - starting node where we will start the recursion
2146 * @param   { Function } fn - callback to transform the child node just found
2147 */
2148function walk(dom, fn) {
2149  if (dom) {
2150    // stop the recursion
2151    if (fn(dom) === false) return
2152    else {
2153      dom = dom.firstChild
2154
2155      while (dom) {
2156        walk(dom, fn)
2157        dom = dom.nextSibling
2158      }
2159    }
2160  }
2161}
2162
2163/**
2164 * Minimize risk: only zero or one _space_ between attr & value
2165 * @param   { String }   html - html string we want to parse
2166 * @param   { Function } fn - callback function to apply on any attribute found
2167 */
2168function walkAttributes(html, fn) {
2169  var m,
2170    re = /([-\w]+) ?= ?(?:"([^"]*)|'([^']*)|({[^}]*}))/g
2171
2172  while (m = re.exec(html)) {
2173    fn(m[1].toLowerCase(), m[2] || m[3] || m[4])
2174  }
2175}
2176
2177/**
2178 * Check whether a DOM node is in stub mode, useful for the riot 'if' directive
2179 * @param   { Object }  dom - DOM node we want to parse
2180 * @returns { Boolean } -
2181 */
2182function isInStub(dom) {
2183  while (dom) {
2184    if (dom.inStub) return true
2185    dom = dom.parentNode
2186  }
2187  return false
2188}
2189
2190/**
2191 * Create a generic DOM node
2192 * @param   { String } name - name of the DOM node we want to create
2193 * @returns { Object } DOM node just created
2194 */
2195function mkEl(name) {
2196  return document.createElement(name)
2197}
2198
2199/**
2200 * Shorter and fast way to select multiple nodes in the DOM
2201 * @param   { String } selector - DOM selector
2202 * @param   { Object } ctx - DOM node where the targets of our search will is located
2203 * @returns { Object } dom nodes found
2204 */
2205function $$(selector, ctx) {
2206  return (ctx || document).querySelectorAll(selector)
2207}
2208
2209/**
2210 * Shorter and fast way to select a single node in the DOM
2211 * @param   { String } selector - unique dom selector
2212 * @param   { Object } ctx - DOM node where the target of our search will is located
2213 * @returns { Object } dom node found
2214 */
2215function $(selector, ctx) {
2216  return (ctx || document).querySelector(selector)
2217}
2218
2219/**
2220 * Simple object prototypal inheritance
2221 * @param   { Object } parent - parent object
2222 * @returns { Object } child instance
2223 */
2224function inherit(parent) {
2225  function Child() {}
2226  Child.prototype = parent
2227  return new Child()
2228}
2229
2230/**
2231 * Get the name property needed to identify a DOM node in riot
2232 * @param   { Object } dom - DOM node we need to parse
2233 * @returns { String | undefined } give us back a string to identify this dom node
2234 */
2235function getNamedKey(dom) {
2236  return getAttr(dom, 'id') || getAttr(dom, 'name')
2237}
2238
2239/**
2240 * Set the named properties of a tag element
2241 * @param { Object } dom - DOM node we need to parse
2242 * @param { Object } parent - tag instance where the named dom element will be eventually added
2243 * @param { Array } keys - list of all the tag instance properties
2244 */
2245function setNamed(dom, parent, keys) {
2246  // get the key value we want to add to the tag instance
2247  var key = getNamedKey(dom),
2248    isArr,
2249    // add the node detected to a tag instance using the named property
2250    add = function(value) {
2251      // avoid to override the tag properties already set
2252      if (contains(keys, key)) return
2253      // check whether this value is an array
2254      isArr = isArray(value)
2255      // if the key was never set
2256      if (!value)
2257        // set it once on the tag instance
2258        parent[key] = dom
2259      // if it was an array and not yet set
2260      else if (!isArr || isArr && !contains(value, dom)) {
2261        // add the dom node into the array
2262        if (isArr)
2263          value.push(dom)
2264        else
2265          parent[key] = [value, dom]
2266      }
2267    }
2268
2269  // skip the elements with no named properties
2270  if (!key) return
2271
2272  // check whether this key has been already evaluated
2273  if (tmpl.hasExpr(key))
2274    // wait the first updated event only once
2275    parent.one('mount', function() {
2276      key = getNamedKey(dom)
2277      add(parent[key])
2278    })
2279  else
2280    add(parent[key])
2281
2282}
2283
2284/**
2285 * Faster String startsWith alternative
2286 * @param   { String } src - source string
2287 * @param   { String } str - test string
2288 * @returns { Boolean } -
2289 */
2290function startsWith(src, str) {
2291  return src.slice(0, str.length) === str
2292}
2293
2294/**
2295 * requestAnimationFrame function
2296 * Adapted from https://gist.github.com/paulirish/1579671, license MIT
2297 */
2298var rAF = (function (w) {
2299  var raf = w.requestAnimationFrame    ||
2300            w.mozRequestAnimationFrame || w.webkitRequestAnimationFrame
2301
2302  if (!raf || /iP(ad|hone|od).*OS 6/.test(w.navigator.userAgent)) {  // buggy iOS6
2303    var lastTime = 0
2304
2305    raf = function (cb) {
2306      var nowtime = Date.now(), timeout = Math.max(16 - (nowtime - lastTime), 0)
2307      setTimeout(function () { cb(lastTime = nowtime + timeout) }, timeout)
2308    }
2309  }
2310  return raf
2311
2312})(window || {})
2313
2314/**
2315 * Mount a tag creating new Tag instance
2316 * @param   { Object } root - dom node where the tag will be mounted
2317 * @param   { String } tagName - name of the riot tag we want to mount
2318 * @param   { Object } opts - options to pass to the Tag instance
2319 * @returns { Tag } a new Tag instance
2320 */
2321function mountTo(root, tagName, opts) {
2322  var tag = __tagImpl[tagName],
2323    // cache the inner HTML to fix #855
2324    innerHTML = root._innerHTML = root._innerHTML || root.innerHTML
2325
2326  // clear the inner html
2327  root.innerHTML = ''
2328
2329  if (tag && root) tag = new Tag(tag, { root: root, opts: opts }, innerHTML)
2330
2331  if (tag && tag.mount) {
2332    tag.mount()
2333    // add this tag to the virtualDom variable
2334    if (!contains(__virtualDom, tag)) __virtualDom.push(tag)
2335  }
2336
2337  return tag
2338}
2339/**
2340 * Riot public api
2341 */
2342
2343// share methods for other riot parts, e.g. compiler
2344riot.util = { brackets: brackets, tmpl: tmpl }
2345
2346/**
2347 * Create a mixin that could be globally shared across all the tags
2348 */
2349riot.mixin = (function() {
2350  var mixins = {}
2351
2352  /**
2353   * Create/Return a mixin by its name
2354   * @param   { String } name - mixin name (global mixin if missing)
2355   * @param   { Object } mixin - mixin logic
2356   * @returns { Object } the mixin logic
2357   */
2358  return function(name, mixin) {
2359    if (isObject(name)) {
2360      mixin = name
2361      mixins[GLOBAL_MIXIN] = extend(mixins[GLOBAL_MIXIN] || {}, mixin)
2362      return
2363    }
2364
2365    if (!mixin) return mixins[name]
2366    mixins[name] = mixin
2367  }
2368
2369})()
2370
2371/**
2372 * Create a new riot tag implementation
2373 * @param   { String }   name - name/id of the new riot tag
2374 * @param   { String }   html - tag template
2375 * @param   { String }   css - custom tag css
2376 * @param   { String }   attrs - root tag attributes
2377 * @param   { Function } fn - user function
2378 * @returns { String } name/id of the tag just created
2379 */
2380riot.tag = function(name, html, css, attrs, fn) {
2381  if (isFunction(attrs)) {
2382    fn = attrs
2383    if (/^[\w\-]+\s?=/.test(css)) {
2384      attrs = css
2385      css = ''
2386    } else attrs = ''
2387  }
2388  if (css) {
2389    if (isFunction(css)) fn = css
2390    else styleManager.add(css)
2391  }
2392  name = name.toLowerCase()
2393  __tagImpl[name] = { name: name, tmpl: html, attrs: attrs, fn: fn }
2394  return name
2395}
2396
2397/**
2398 * Create a new riot tag implementation (for use by the compiler)
2399 * @param   { String }   name - name/id of the new riot tag
2400 * @param   { String }   html - tag template
2401 * @param   { String }   css - custom tag css
2402 * @param   { String }   attrs - root tag attributes
2403 * @param   { Function } fn - user function
2404 * @returns { String } name/id of the tag just created
2405 */
2406riot.tag2 = function(name, html, css, attrs, fn) {
2407  if (css) styleManager.add(css)
2408  //if (bpair) riot.settings.brackets = bpair
2409  __tagImpl[name] = { name: name, tmpl: html, attrs: attrs, fn: fn }
2410  return name
2411}
2412
2413/**
2414 * Mount a tag using a specific tag implementation
2415 * @param   { String } selector - tag DOM selector
2416 * @param   { String } tagName - tag implementation name
2417 * @param   { Object } opts - tag logic
2418 * @returns { Array } new tags instances
2419 */
2420riot.mount = function(selector, tagName, opts) {
2421
2422  var els,
2423    allTags,
2424    tags = []
2425
2426  // helper functions
2427
2428  function addRiotTags(arr) {
2429    var list = ''
2430    each(arr, function (e) {
2431      if (!/[^-\w]/.test(e)) {
2432        e = e.trim().toLowerCase()
2433        list += ',[' + RIOT_TAG_IS + '="' + e + '"],[' + RIOT_TAG + '="' + e + '"]'
2434      }
2435    })
2436    return list
2437  }
2438
2439  function selectAllTags() {
2440    var keys = Object.keys(__tagImpl)
2441    return keys + addRiotTags(keys)
2442  }
2443
2444  function pushTags(root) {
2445    if (root.tagName) {
2446      var riotTag = getAttr(root, RIOT_TAG_IS) || getAttr(root, RIOT_TAG)
2447
2448      // have tagName? force riot-tag to be the same
2449      if (tagName && riotTag !== tagName) {
2450        riotTag = tagName
2451        setAttr(root, RIOT_TAG_IS, tagName)
2452      }
2453      var tag = mountTo(root, riotTag || root.tagName.toLowerCase(), opts)
2454
2455      if (tag) tags.push(tag)
2456    } else if (root.length) {
2457      each(root, pushTags)   // assume nodeList
2458    }
2459  }
2460
2461  // ----- mount code -----
2462
2463  // inject styles into DOM
2464  styleManager.inject()
2465
2466  if (isObject(tagName)) {
2467    opts = tagName
2468    tagName = 0
2469  }
2470
2471  // crawl the DOM to find the tag
2472  if (typeof selector === T_STRING) {
2473    if (selector === '*')
2474      // select all the tags registered
2475      // and also the tags found with the riot-tag attribute set
2476      selector = allTags = selectAllTags()
2477    else
2478      // or just the ones named like the selector
2479      selector += addRiotTags(selector.split(/, */))
2480
2481    // make sure to pass always a selector
2482    // to the querySelectorAll function
2483    els = selector ? $$(selector) : []
2484  }
2485  else
2486    // probably you have passed already a tag or a NodeList
2487    els = selector
2488
2489  // select all the registered and mount them inside their root elements
2490  if (tagName === '*') {
2491    // get all custom tags
2492    tagName = allTags || selectAllTags()
2493    // if the root els it's just a single tag
2494    if (els.tagName)
2495      els = $$(tagName, els)
2496    else {
2497      // select all the children for all the different root elements
2498      var nodeList = []
2499      each(els, function (_el) {
2500        nodeList.push($$(tagName, _el))
2501      })
2502      els = nodeList
2503    }
2504    // get rid of the tagName
2505    tagName = 0
2506  }
2507
2508  pushTags(els)
2509
2510  return tags
2511}
2512
2513/**
2514 * Update all the tags instances created
2515 * @returns { Array } all the tags instances
2516 */
2517riot.update = function() {
2518  return each(__virtualDom, function(tag) {
2519    tag.update()
2520  })
2521}
2522
2523/**
2524 * Export the Tag constructor
2525 */
2526riot.Tag = Tag
2527  // support CommonJS, AMD & browser
2528  /* istanbul ignore next */
2529  if (typeof exports === T_OBJECT)
2530    module.exports = riot
2531  else if (typeof define === T_FUNCTION && typeof define.amd !== T_UNDEF)
2532    define(function() { return riot })
2533  else
2534    window.riot = riot
2535
2536})(typeof window != 'undefined' ? window : void 0);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.