{"version":3,"file":"ractive.mjs","sources":["../../../src/polyfills/Object.assign.js","../../../src/utils/object.js","../../../src/utils/is.js","../../../src/polyfills/array.find.js","../../../src/polyfills/node.contains.js","../../../src/polyfills/performance.now.js","../../../src/config/environment.js","../../../src/polyfills/Promise.js","../../../src/polyfills/requestAnimationFrame.js","../../../src/Ractive/config/defaults.js","../../../src/Ractive/static/easing.js","../../../src/utils/noop.js","../../../src/utils/log.js","../../../src/config/errors.js","../../../src/shared/registry.js","../../../src/shared/interpolate.js","../../../src/Ractive/static/interpolators.js","../../../src/shared/keypaths.js","../../../src/utils/array.js","../../../src/utils/bind.js","../../../src/model/ModelBase.js","../../../src/global/capture.js","../../../src/shared/methodCallers.js","../../../src/shared/rebind.js","../../../src/model/LinkModel.js","../../../src/parse/utils/createFunction.js","../../../src/shared/getFunction.js","../../../src/config/template.js","../../../src/parse/Parser.js","../../../src/config/types.js","../../../src/parse/converters/mustache/readDelimiterChange.js","../../../src/parse/converters/expressions/primary/literal/readRegexpLiteral.js","../../../src/utils/escapeRegExp.js","../../../src/parse/converters/utils/getLowestIndex.js","../../../src/utils/html.js","../../../src/parse/converters/expressions/shared/errors.js","../../../src/parse/converters/expressions/primary/literal/readNumberLiteral.js","../../../src/parse/converters/expressions/primary/literal/readBooleanLiteral.js","../../../src/parse/converters/expressions/primary/literal/stringLiteral/makeQuotedStringMatcher.js","../../../src/parse/converters/expressions/primary/literal/readStringLiteral.js","../../../src/parse/converters/expressions/primary/literal/readTemplateStringLiteral.js","../../../src/parse/converters/expressions/shared/patterns.js","../../../src/parse/converters/expressions/shared/readKey.js","../../../src/parse/converters/expressions/primary/literal/objectLiteral/keyValuePair.js","../../../src/parse/converters/expressions/primary/literal/objectLiteral/keyValuePairs.js","../../../src/parse/converters/expressions/primary/literal/readObjectLiteral.js","../../../src/parse/converters/expressions/primary/literal/readArrayLiteral.js","../../../src/parse/converters/expressions/primary/readLiteral.js","../../../src/parse/converters/expressions/primary/readReference.js","../../../src/parse/converters/expressions/primary/readBracketedExpression.js","../../../src/parse/converters/expressions/readPrimary.js","../../../src/parse/converters/expressions/shared/readRefinement.js","../../../src/parse/converters/expressions/readMemberOrInvocation.js","../../../src/parse/converters/expressions/readTypeof.js","../../../src/parse/converters/expressions/readLogicalOr.js","../../../src/parse/converters/expressions/readConditional.js","../../../src/parse/converters/readExpression.js","../../../src/parse/converters/expressions/shared/readExpressionList.js","../../../src/parse/converters/readExpressionOrReference.js","../../../src/parse/utils/flattenExpression.js","../../../src/parse/utils/refineExpression.js","../../../src/parse/converters/element/readAttribute.js","../../../src/parse/converters/readMustache.js","../../../src/parse/converters/mustache/readTriple.js","../../../src/parse/converters/mustache/readUnescaped.js","../../../src/parse/converters/mustache/readAliases.js","../../../src/parse/converters/mustache/readPartial.js","../../../src/parse/converters/mustache/readMustacheComment.js","../../../src/parse/converters/mustache/readInterpolator.js","../../../src/parse/converters/mustache/section/readClosing.js","../../../src/parse/converters/mustache/section/readInlineBlock.js","../../../src/parse/converters/mustache/handlebarsBlockCodes.js","../../../src/parse/converters/mustache/readSection.js","../../../src/parse/converters/readHtmlComment.js","../../../src/parse/utils/stripStandalones.js","../../../src/parse/utils/trimWhitespace.js","../../../src/parse/utils/cleanup.js","../../../src/parse/converters/element/readClosingTag.js","../../../src/utils/hyphenateCamel.js","../../../src/parse/converters/readElement.js","../../../src/parse/converters/readText.js","../../../src/parse/converters/readPartialDefinitionSection.js","../../../src/parse/converters/readTemplate.js","../../../src/parse/utils/insertExpressions.js","../../../src/Ractive/shared.js","../../../src/parse/_parse.js","../../../src/Ractive/config/runtime-parser.js","../../../src/Ractive/helpers/getComputationSignature.js","../../../src/global/TransitionManager.js","../../../src/global/runloop.js","../../../src/shared/Ticker.js","../../../src/model/helpers/getPrefixer.js","../../../src/model/Model.js","../../../src/model/specials/SharedModel.js","../../../src/view/resolvers/resolveReference.js","../../../src/shared/getRactiveContext.js","../../../src/shared/set.js","../../../src/Ractive/prototype/shared/add.js","../../../src/Ractive/prototype/add.js","../../../src/Ractive/prototype/animate.js","../../../src/events/eventStack.js","../../../src/events/fireEvent.js","../../../src/events/Hook.js","../../../src/shared/anchors.js","../../../src/Ractive/prototype/attachChild.js","../../../src/Ractive/prototype/compute.js","../../../src/Ractive/prototype/detach.js","../../../src/Ractive/prototype/detachChild.js","../../../src/Ractive/prototype/find.js","../../../src/Ractive/prototype/findAll.js","../../../src/Ractive/prototype/findAllComponents.js","../../../src/Ractive/prototype/findComponent.js","../../../src/Ractive/prototype/findContainer.js","../../../src/Ractive/prototype/findParent.js","../../../src/view/items/shared/findElement.js","../../../src/shared/getNewIndices.js","../../../src/Ractive/prototype/shared/makeArrayMethod.js","../../../src/Ractive/prototype/update.js","../../../src/shared/Context.js","../../../src/Ractive/prototype/fire.js","../../../src/Ractive/prototype/get.js","../../../src/Ractive/static/getContext.js","../../../src/Ractive/prototype/getContext.js","../../../src/config/namespaces.js","../../../src/utils/dom.js","../../../src/Ractive/prototype/insert.js","../../../src/Ractive/prototype/link.js","../../../src/Ractive/prototype/observe/Observer.js","../../../src/Ractive/prototype/observe/Pattern.js","../../../src/Ractive/prototype/observe/Array.js","../../../src/Ractive/prototype/observe.js","../../../src/Ractive/prototype/observeOnce.js","../../../src/Ractive/prototype/shared/trim.js","../../../src/Ractive/prototype/shared/notEmptyString.js","../../../src/Ractive/prototype/off.js","../../../src/Ractive/prototype/on.js","../../../src/Ractive/prototype/once.js","../../../src/Ractive/prototype/pop.js","../../../src/Ractive/prototype/push.js","../../../src/Ractive/prototype/readLink.js","../../../src/global/css.js","../../../src/Ractive/config/custom/adapt.js","../../../src/utils/cleanCss.js","../../../src/Ractive/config/custom/css/transform.js","../../../src/utils/id.js","../../../src/Ractive/static/styleSet.js","../../../src/model/specials/CSSModel.js","../../../src/Ractive/config/custom/css/css.js","../../../src/Ractive/config/custom/data.js","../../../src/Ractive/config/custom/template.js","../../../src/Ractive/config/registries.js","../../../src/Ractive/config/wrapPrototypeMethod.js","../../../src/Ractive/config/deprecate.js","../../../src/Ractive/config/config.js","../../../src/view/items/shared/Item.js","../../../src/model/ComputationChild.js","../../../src/model/Computation.js","../../../src/view/resolvers/ExpressionProxy.js","../../../src/view/resolvers/ReferenceExpressionProxy.js","../../../src/view/resolvers/resolve.js","../../../src/view/items/Alias.js","../../../src/view/helpers/specialAttrs.js","../../../src/view/items/element/attribute/getUpdateDelegate.js","../../../src/view/items/element/attribute/propertyNames.js","../../../src/view/items/element/ConditionalAttribute.js","../../../src/view/items/element/Attribute.js","../../../src/view/items/element/BindingFlag.js","../../../src/view/items/Comment.js","../../../src/Ractive/prototype/teardown.js","../../../src/model/specials/RactiveModel.js","../../../src/model/RootModel.js","../../../src/Ractive/helpers/subscribe.js","../../../src/Ractive/construct.js","../../../src/view/items/Component.js","../../../src/view/items/shared/directiveArgs.js","../../../src/view/items/element/Decorator.js","../../../src/view/items/Doctype.js","../../../src/view/items/element/binding/Binding.js","../../../src/view/items/element/binding/handleDomEvent.js","../../../src/view/items/element/binding/CheckboxBinding.js","../../../src/view/items/element/binding/getBindingGroup.js","../../../src/view/items/element/binding/CheckboxNameBinding.js","../../../src/view/items/element/binding/ContentEditableBinding.js","../../../src/view/items/element/binding/GenericBinding.js","../../../src/view/items/element/binding/FileBinding.js","../../../src/utils/getSelectedOptions.js","../../../src/view/items/element/binding/MultipleSelectBinding.js","../../../src/view/items/element/binding/NumericBinding.js","../../../src/view/items/element/binding/RadioBinding.js","../../../src/view/items/element/binding/RadioNameBinding.js","../../../src/view/items/element/binding/SingleSelectBinding.js","../../../src/view/items/element/binding/selectBinding.js","../../../src/view/items/Element.js","../../../src/view/items/element/specials/Form.js","../../../src/view/items/element/ElementEvents.js","../../../src/view/items/component/RactiveEvent.js","../../../src/view/items/shared/EventDirective.js","../../../src/view/items/shared/progressiveText.js","../../../src/view/items/shared/Mustache.js","../../../src/view/items/Interpolator.js","../../../src/view/items/element/specials/Input.js","../../../src/utils/parseJSON.js","../../../src/view/items/component/Mapping.js","../../../src/view/items/element/specials/Option.js","../../../src/view/items/partial/getPartialTemplate.js","../../../src/view/items/Partial.js","../../../src/model/specials/KeyModel.js","../../../src/view/RepeatedFragment.js","../../../src/view/items/Section.js","../../../src/view/items/element/specials/Select.js","../../../src/view/items/element/specials/Textarea.js","../../../src/view/items/Text.js","../../../src/config/visibility.js","../../../src/view/items/element/transitions/prefix.js","../../../src/view/items/element/transitions/hyphenate.js","../../../src/view/items/element/transitions/createTransitions.js","../../../src/view/items/element/Transition.js","../../../src/view/items/triple/insertHtml.js","../../../src/view/items/Triple.js","../../../src/view/items/component/getComponentConstructor.js","../../../src/view/items/asyncProxy.js","../../../src/view/items/Await.js","../../../src/view/items/createItem.js","../../../src/view/helpers/processItems.js","../../../src/view/Fragment.js","../../../src/Ractive/initialise.js","../../../src/Ractive/render.js","../../../src/Ractive/prototype/render.js","../../../src/Ractive/prototype/reset.js","../../../src/Ractive/prototype/resetPartial.js","../../../src/Ractive/prototype/resetTemplate.js","../../../src/Ractive/prototype/reverse.js","../../../src/Ractive/prototype/set.js","../../../src/Ractive/prototype/shift.js","../../../src/Ractive/prototype/sort.js","../../../src/Ractive/prototype/splice.js","../../../src/Ractive/prototype/subtract.js","../../../src/Ractive/prototype/toggle.js","../../../src/Ractive/prototype/toCSS.js","../../../src/Ractive/prototype/toHTML.js","../../../src/Ractive/prototype/toText.js","../../../src/Ractive/prototype/transition.js","../../../src/Ractive/prototype/unlink.js","../../../src/Ractive/prototype/unrender.js","../../../src/Ractive/prototype/unshift.js","../../../src/Ractive/prototype/updateModel.js","../../../src/Ractive/prototype/use.js","../../../src/Ractive/prototype.js","../../../src/Ractive/static/isInstance.js","../../../src/Ractive/static/styleGet.js","../../../src/Ractive/static/styles.js","../../../src/Ractive/static/sharedSet.js","../../../src/Ractive/static/sharedGet.js","../../../src/Ractive/static/use.js","../../../src/extend/_extend.js","../../../src/extend/_macro.js","../../../src/Ractive/static/keypaths.js","../../../src/Ractive/static/findPlugin.js","../../../src/Ractive.js"],"sourcesContent":["/* istanbul ignore if */\nif (!Object.assign) {\n Object.assign = function(target, ...sources) {\n if (target == null) throw new TypeError('Cannot convert undefined or null to object');\n\n const to = Object(target);\n const sourcesLength = sources.length;\n\n for (let index = 0; index < sourcesLength; index++) {\n const nextSource = sources[index];\n for (const nextKey in nextSource) {\n if (!Object.prototype.hasOwnProperty.call(nextSource, nextKey)) continue;\n to[nextKey] = nextSource[nextKey];\n }\n }\n\n return to;\n };\n}\n","export function hasOwn(obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\nexport function fillGaps(target, ...sources) {\n for (let i = 0; i < sources.length; i++) {\n const source = sources[i];\n for (const key in source) {\n // Source can be a prototype-less object.\n if (key in target || !hasOwn(source, key)) continue;\n target[key] = source[key];\n }\n }\n\n return target;\n}\n\nexport function toPairs(obj = {}) {\n const pairs = [];\n for (const key in obj) {\n // Source can be a prototype-less object.\n if (!hasOwn(obj, key)) continue;\n pairs.push([key, obj[key]]);\n }\n return pairs;\n}\n\nconst obj = Object;\n\nexport const assign = obj.assign;\n\nexport const create = obj.create;\n\nexport const defineProperty = obj.defineProperty;\n\nexport const defineProperties = obj.defineProperties;\n\nexport const keys = obj.keys;\n","const toString = Object.prototype.toString;\nconst arrayLikePattern = /^\\[object (?:Array|FileList)\\]$/;\n\nexport function isArrayLike(obj) {\n return arrayLikePattern.test(toString.call(obj));\n}\n\nexport const isArray = Array.isArray;\n\nexport function isEqual(a, b) {\n if (a === null && b === null) {\n return true;\n }\n\n if (isObjectType(a) || isObjectType(b)) {\n return false;\n }\n\n return a === b;\n}\n\n// http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric\nexport function isNumeric(thing) {\n return !isNaN(parseFloat(thing)) && isFinite(thing);\n}\n\nexport function isObject(thing) {\n return thing && toString.call(thing) === '[object Object]';\n}\n\nexport function isObjectLike(thing) {\n return !!(thing && (isObjectType(thing) || isFunction(thing)));\n}\n\nexport function isObjectType(thing) {\n return typeof thing === 'object';\n}\n\nexport function isFunction(thing) {\n return typeof thing === 'function';\n}\n\nexport function isString(thing) {\n return typeof thing === 'string';\n}\n\nexport function isNumber(thing) {\n return typeof thing === 'number';\n}\n","import { hasOwn, defineProperty } from 'utils/object';\nimport { isFunction } from 'utils/is';\n\n/* istanbul ignore if */\nif (!Array.prototype.find) {\n defineProperty(Array.prototype, 'find', {\n value(callback, thisArg) {\n if (this === null || this === undefined)\n throw new TypeError('Array.prototype.find called on null or undefined');\n\n if (!isFunction(callback)) throw new TypeError(`${callback} is not a function`);\n\n const array = Object(this);\n const arrayLength = array.length >>> 0;\n\n for (let index = 0; index < arrayLength; index++) {\n if (!hasOwn(array, index)) continue;\n if (!callback.call(thisArg, array[index], index, array)) continue;\n return array[index];\n }\n\n return undefined;\n },\n configurable: true,\n writable: true\n });\n}\n","// NOTE: Node doesn't exist in IE8. Nothing can be done.\n/* istanbul ignore if */\nif (\n typeof window !== 'undefined' &&\n window.Node &&\n window.Node.prototype &&\n !window.Node.prototype.contains\n) {\n Node.prototype.contains = function(node) {\n if (!node) throw new TypeError('node required');\n\n do {\n if (this === node) return true;\n } while ((node = node && node.parentNode));\n\n return false;\n };\n}\n","/* istanbul ignore if */\nif (typeof window !== 'undefined' && window.performance && !window.performance.now) {\n window.performance = window.performance || {};\n\n const nowOffset = Date.now();\n\n window.performance.now = function() {\n return Date.now() - nowOffset;\n };\n}\n","/* eslint no-console:\"off\" */\nimport { isFunction } from 'utils/is';\n\nconst win = typeof window !== 'undefined' ? window : null;\nconst doc = win ? document : null;\nconst isClient = !!doc;\nconst base = typeof global !== 'undefined' ? global : win;\nconst hasConsole =\n typeof console !== 'undefined' && isFunction(console.warn) && isFunction(console.warn.apply);\n\nconst svg = doc\n ? doc.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#BasicStructure', '1.1')\n : false;\n\nconst vendors = ['o', 'ms', 'moz', 'webkit'];\n\nexport { win, doc, isClient, hasConsole, svg, vendors, base };\n","import { isFunction, isObjectType } from 'utils/is';\nimport { base } from 'config/environment';\n\n/* istanbul ignore if */\nif (!base.Promise) {\n const PENDING = {};\n const FULFILLED = {};\n const REJECTED = {};\n\n const Promise = (base.Promise = function(callback) {\n const fulfilledHandlers = [];\n const rejectedHandlers = [];\n let state = PENDING;\n let result;\n let dispatchHandlers;\n\n const makeResolver = newState => {\n return function(value) {\n if (state !== PENDING) return;\n result = value;\n state = newState;\n dispatchHandlers = makeDispatcher(\n state === FULFILLED ? fulfilledHandlers : rejectedHandlers,\n result\n );\n wait(dispatchHandlers);\n };\n };\n\n const fulfill = makeResolver(FULFILLED);\n const reject = makeResolver(REJECTED);\n\n try {\n callback(fulfill, reject);\n } catch (err) {\n reject(err);\n }\n\n return {\n // `then()` returns a Promise - 2.2.7\n then(onFulfilled, onRejected) {\n const promise2 = new Promise((fulfill, reject) => {\n const processResolutionHandler = (handler, handlers, forward) => {\n if (isFunction(handler)) {\n handlers.push(p1result => {\n try {\n resolve(promise2, handler(p1result), fulfill, reject);\n } catch (err) {\n reject(err);\n }\n });\n } else {\n handlers.push(forward);\n }\n };\n\n processResolutionHandler(onFulfilled, fulfilledHandlers, fulfill);\n processResolutionHandler(onRejected, rejectedHandlers, reject);\n\n if (state !== PENDING) {\n wait(dispatchHandlers);\n }\n });\n return promise2;\n },\n catch(onRejected) {\n return this.then(null, onRejected);\n },\n finally(callback) {\n return this.then(\n v => {\n callback();\n return v;\n },\n e => {\n callback();\n throw e;\n }\n );\n }\n };\n });\n\n Promise.all = function(promises) {\n return new Promise((fulfill, reject) => {\n const result = [];\n let pending;\n let i;\n\n if (!promises.length) {\n fulfill(result);\n return;\n }\n\n const processPromise = (promise, i) => {\n if (promise && isFunction(promise.then)) {\n promise.then(value => {\n result[i] = value;\n --pending || fulfill(result);\n }, reject);\n } else {\n result[i] = promise;\n --pending || fulfill(result);\n }\n };\n\n pending = i = promises.length;\n\n while (i--) {\n processPromise(promises[i], i);\n }\n });\n };\n\n Promise.race = function(promises) {\n return new Promise((fulfill, reject) => {\n let pending = true;\n function ok(v) {\n if (!pending) return;\n pending = false;\n fulfill(v);\n }\n function fail(e) {\n if (!pending) return;\n pending = false;\n reject(e);\n }\n for (let i = 0; i < promises.length; i++) {\n if (promises[i] && isFunction(promises[i].then)) {\n promises[i].then(ok, fail);\n }\n }\n });\n };\n\n Promise.resolve = function(value) {\n if (value && isFunction(value.then)) return value;\n return new Promise(fulfill => {\n fulfill(value);\n });\n };\n\n Promise.reject = function(reason) {\n if (reason && isFunction(reason.then)) return reason;\n return new Promise((fulfill, reject) => {\n reject(reason);\n });\n };\n\n // TODO use MutationObservers or something to simulate setImmediate\n const wait = function(callback) {\n setTimeout(callback, 0);\n };\n\n const makeDispatcher = function(handlers, result) {\n return function() {\n for (let handler; (handler = handlers.shift()); ) {\n handler(result);\n }\n };\n };\n\n const resolve = function(promise, x, fulfil, reject) {\n let then;\n if (x === promise) {\n throw new TypeError(`A promise's fulfillment handler cannot return the same promise`);\n }\n if (x instanceof Promise) {\n x.then(fulfil, reject);\n } else if (x && (isObjectType(x) || isFunction(x))) {\n try {\n then = x.then;\n } catch (e) {\n reject(e);\n return;\n }\n if (isFunction(then)) {\n let called;\n\n const resolvePromise = function(y) {\n if (called) return;\n called = true;\n resolve(promise, y, fulfil, reject);\n };\n const rejectPromise = function(r) {\n if (called) return;\n called = true;\n reject(r);\n };\n\n try {\n then.call(x, resolvePromise, rejectPromise);\n } catch (e) {\n if (!called) {\n reject(e);\n called = true;\n return;\n }\n }\n } else {\n fulfil(x);\n }\n } else {\n fulfil(x);\n }\n };\n}\n","/* istanbul ignore if */\nif (\n typeof window !== 'undefined' &&\n !(window.requestAnimationFrame && window.cancelAnimationFrame)\n) {\n let lastTime = 0;\n window.requestAnimationFrame = function(callback) {\n const currentTime = Date.now();\n const timeToNextCall = Math.max(0, 16 - (currentTime - lastTime));\n const id = window.setTimeout(() => {\n callback(currentTime + timeToNextCall);\n }, timeToNextCall);\n lastTime = currentTime + timeToNextCall;\n return id;\n };\n window.cancelAnimationFrame = function(id) {\n clearTimeout(id);\n };\n}\n","import { create } from 'utils/object';\n\nexport default {\n // render placement:\n el: void 0,\n append: false,\n delegate: true,\n enhance: false,\n\n // template:\n template: null,\n\n // parse:\n allowExpressions: true,\n delimiters: ['{{', '}}'],\n tripleDelimiters: ['{{{', '}}}'],\n staticDelimiters: ['[[', ']]'],\n staticTripleDelimiters: ['[[[', ']]]'],\n csp: true,\n interpolate: false,\n preserveWhitespace: false,\n sanitize: false,\n stripComments: true,\n contextLines: 0,\n\n // data & binding:\n data: create(null),\n helpers: create(null),\n computed: create(null),\n syncComputedChildren: false,\n resolveInstanceMembers: false,\n warnAboutAmbiguity: false,\n adapt: [],\n isolated: true,\n twoway: true,\n lazy: false,\n\n // transitions:\n noIntro: false,\n noOutro: false,\n transitionsEnabled: true,\n complete: void 0,\n nestedTransitions: true,\n\n // css:\n css: null,\n noCSSTransform: false\n};\n","// These are a subset of the easing equations found at\n// https://raw.github.com/danro/easing-js - license info\n// follows:\n\n// --------------------------------------------------\n// easing.js v0.5.4\n// Generic set of easing functions with AMD support\n// https://github.com/danro/easing-js\n// This code may be freely distributed under the MIT license\n// http://danro.mit-license.org/\n// --------------------------------------------------\n// All functions adapted from Thomas Fuchs & Jeremy Kahn\n// Easing Equations (c) 2003 Robert Penner, BSD license\n// https://raw.github.com/danro/easing-js/master/LICENSE\n// --------------------------------------------------\n\n// In that library, the functions named easeIn, easeOut, and\n// easeInOut below are named easeInCubic, easeOutCubic, and\n// (you guessed it) easeInOutCubic.\n//\n// You can add additional easing functions to this list, and they\n// will be globally available.\n\nexport default {\n linear(pos) {\n return pos;\n },\n easeIn(pos) {\n /* istanbul ignore next */\n return Math.pow(pos, 3);\n },\n easeOut(pos) {\n return Math.pow(pos - 1, 3) + 1;\n },\n easeInOut(pos) {\n /* istanbul ignore next */\n if ((pos /= 0.5) < 1) {\n return 0.5 * Math.pow(pos, 3);\n }\n /* istanbul ignore next */\n return 0.5 * (Math.pow(pos - 2, 3) + 2);\n }\n};\n","export default function() {}\n","/* global console */\n/* eslint no-console:\"off\" */\n\nimport { hasConsole } from '../config/environment';\nimport Ractive from '../Ractive';\nimport noop from './noop';\nimport { isObjectType } from 'utils/is';\n\nconst alreadyWarned = {};\nlet log, printWarning, welcome;\n\nif (hasConsole) {\n const welcomeIntro = [\n `%cRactive.js %c1.2.3 %cin debug mode, %cmore...`,\n 'color: rgb(114, 157, 52); font-weight: normal;',\n 'color: rgb(85, 85, 85); font-weight: normal;',\n 'color: rgb(85, 85, 85); font-weight: normal;',\n 'color: rgb(82, 140, 224); font-weight: normal; text-decoration: underline;'\n ];\n const welcomeMessage = `You're running Ractive 1.2.3 in debug mode - messages will be printed to the console to help you fix problems and optimise your application.\n\nTo disable debug mode, add this line at the start of your app:\n Ractive.DEBUG = false;\n\nTo disable debug mode when your app is minified, add this snippet:\n Ractive.DEBUG = /unminified/.test(function(){/*unminified*/});\n\nGet help and support:\n http://ractive.js.org\n http://stackoverflow.com/questions/tagged/ractivejs\n http://groups.google.com/forum/#!forum/ractive-js\n http://twitter.com/ractivejs\n\nFound a bug? Raise an issue:\n https://github.com/ractivejs/ractive/issues\n\n`;\n\n welcome = () => {\n if (Ractive.WELCOME_MESSAGE === false) {\n welcome = noop;\n return;\n }\n const message = 'WELCOME_MESSAGE' in Ractive ? Ractive.WELCOME_MESSAGE : welcomeMessage;\n const hasGroup = !!console.groupCollapsed;\n if (hasGroup) console.groupCollapsed.apply(console, welcomeIntro);\n console.log(message);\n if (hasGroup) {\n console.groupEnd(welcomeIntro);\n }\n\n welcome = noop;\n };\n\n printWarning = (message, args) => {\n welcome();\n\n // extract information about the instance this message pertains to, if applicable\n if (isObjectType(args[args.length - 1])) {\n const options = args.pop();\n const ractive = options ? options.ractive : null;\n\n if (ractive) {\n // if this is an instance of a component that we know the name of, add\n // it to the message\n let name;\n if (ractive.component && (name = ractive.component.name)) {\n message = `<${name}> ${message}`;\n }\n\n let node;\n if (\n (node =\n options.node || (ractive.fragment && ractive.fragment.rendered && ractive.find('*')))\n ) {\n args.push(node);\n }\n }\n }\n\n console.warn.apply(\n console,\n ['%cRactive.js: %c' + message, 'color: rgb(114, 157, 52);', 'color: rgb(85, 85, 85);'].concat(\n args\n )\n );\n };\n\n log = function() {\n console.log.apply(console, arguments);\n };\n} else {\n printWarning = log = welcome = noop;\n}\n\nfunction format(message, args) {\n return message.replace(/%s/g, () => args.shift());\n}\n\nfunction fatal(message, ...args) {\n message = format(message, args);\n throw new Error(message);\n}\n\nfunction logIfDebug() {\n if (Ractive.DEBUG) {\n log.apply(null, arguments);\n }\n}\n\nfunction warn(message, ...args) {\n message = format(message, args);\n printWarning(message, args);\n}\n\nfunction warnOnce(message, ...args) {\n message = format(message, args);\n\n if (alreadyWarned[message]) {\n return;\n }\n\n alreadyWarned[message] = true;\n printWarning(message, args);\n}\n\nfunction warnIfDebug() {\n if (Ractive.DEBUG) {\n warn.apply(null, arguments);\n }\n}\n\nfunction warnOnceIfDebug() {\n if (Ractive.DEBUG) {\n warnOnce.apply(null, arguments);\n }\n}\n\nexport { fatal, log, logIfDebug, warn, warnOnce, warnIfDebug, warnOnceIfDebug, welcome };\n","// Error messages that are used (or could be) in multiple places\nexport const badArguments = 'Bad arguments';\nexport const noRegistryFunctionReturn =\n 'A function was specified for \"%s\" %s, but no %s was returned';\nexport const missingPlugin = (name, type) =>\n `Missing \"${name}\" ${type} plugin. You may need to download a plugin via http://ractive.js.org/integrations/#${type}s`;\n","export function findInViewHierarchy(registryName, ractive, name) {\n const instance = findInstance(registryName, ractive, name);\n return instance ? instance[registryName][name] : null;\n}\n\nexport function findInstance(registryName, ractive, name) {\n while (ractive) {\n if (name in ractive[registryName]) {\n return ractive;\n }\n\n if (ractive.isolated) {\n return null;\n }\n\n ractive = ractive.parent;\n }\n}\n","import { fatal } from 'utils/log';\nimport { missingPlugin } from 'config/errors';\nimport interpolators from '../Ractive/static/interpolators';\nimport { findInViewHierarchy } from './registry';\n\nexport default function interpolate(from, to, ractive, type) {\n if (from === to) return null;\n\n if (type) {\n const interpol = findInViewHierarchy('interpolators', ractive, type);\n if (interpol) return interpol(from, to) || null;\n\n fatal(missingPlugin(type, 'interpolator'));\n }\n\n return (\n interpolators.number(from, to) ||\n interpolators.array(from, to) ||\n interpolators.object(from, to) ||\n null\n );\n}\n","import { isArray, isObject, isNumeric } from 'utils/is';\nimport interpolate from 'shared/interpolate';\nimport { hasOwn } from 'utils/object';\n\nconst interpolators = {\n number(from, to) {\n if (!isNumeric(from) || !isNumeric(to)) {\n return null;\n }\n\n from = +from;\n to = +to;\n\n const delta = to - from;\n\n if (!delta) {\n return function() {\n return from;\n };\n }\n\n return function(t) {\n return from + t * delta;\n };\n },\n\n array(from, to) {\n let len, i;\n\n if (!isArray(from) || !isArray(to)) {\n return null;\n }\n\n const intermediate = [];\n const interpolators = [];\n\n i = len = Math.min(from.length, to.length);\n while (i--) {\n interpolators[i] = interpolate(from[i], to[i]);\n }\n\n // surplus values - don't interpolate, but don't exclude them either\n for (i = len; i < from.length; i += 1) {\n intermediate[i] = from[i];\n }\n\n for (i = len; i < to.length; i += 1) {\n intermediate[i] = to[i];\n }\n\n return function(t) {\n let i = len;\n\n while (i--) {\n intermediate[i] = interpolators[i](t);\n }\n\n return intermediate;\n };\n },\n\n object(from, to) {\n if (!isObject(from) || !isObject(to)) {\n return null;\n }\n\n const properties = [];\n const intermediate = {};\n const interpolators = {};\n\n for (const prop in from) {\n if (hasOwn(from, prop)) {\n if (hasOwn(to, prop)) {\n properties.push(prop);\n interpolators[prop] = interpolate(from[prop], to[prop]) || (() => to[prop]);\n } else {\n intermediate[prop] = from[prop];\n }\n }\n }\n\n for (const prop in to) {\n if (hasOwn(to, prop) && !hasOwn(from, prop)) {\n intermediate[prop] = to[prop];\n }\n }\n\n const len = properties.length;\n\n return function(t) {\n let i = len;\n\n while (i--) {\n const prop = properties[i];\n\n intermediate[prop] = interpolators[prop](t);\n }\n\n return intermediate;\n };\n }\n};\n\nexport default interpolators;\n","import { isString } from 'utils/is';\n\nconst refPattern = /\\[\\s*(\\*|[0-9]|[1-9][0-9]+)\\s*\\]/g;\nconst splitPattern = /([^\\\\](?:\\\\\\\\)*)\\./;\nconst escapeKeyPattern = /\\\\|\\./g;\nconst unescapeKeyPattern = /((?:\\\\)+)\\1|\\\\(\\.)/g;\n\nexport function escapeKey(key) {\n if (isString(key)) {\n return key.replace(escapeKeyPattern, '\\\\$&');\n }\n\n return key;\n}\n\nexport function normalise(ref) {\n return ref ? ref.replace(refPattern, '.$1') : '';\n}\n\nexport function splitKeypath(keypath) {\n const result = [];\n let match;\n\n keypath = normalise(keypath);\n\n while ((match = splitPattern.exec(keypath))) {\n const index = match.index + match[1].length;\n result.push(keypath.substr(0, index));\n keypath = keypath.substr(index + 1);\n }\n\n result.push(keypath);\n\n return result;\n}\n\nexport function unescapeKey(key) {\n if (isString(key)) {\n return key.replace(unescapeKeyPattern, '$1$2');\n }\n\n return key;\n}\n","import { isArray, isString } from './is';\n\nexport function addToArray(array, value) {\n const index = array.indexOf(value);\n\n if (index === -1) {\n array.push(value);\n }\n}\n\nexport function arrayContains(array, value) {\n for (let i = 0, c = array.length; i < c; i++) {\n if (array[i] == value) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function arrayContentsMatch(a, b) {\n let i;\n\n if (!isArray(a) || !isArray(b)) {\n return false;\n }\n\n if (a.length !== b.length) {\n return false;\n }\n\n i = a.length;\n while (i--) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function ensureArray(x) {\n if (isString(x)) {\n return [x];\n }\n\n if (x === undefined) {\n return [];\n }\n\n return x;\n}\n\nexport function lastItem(array) {\n return array[array.length - 1];\n}\n\nexport function removeFromArray(array, member) {\n if (!array) {\n return;\n }\n\n const index = array.indexOf(member);\n\n if (index !== -1) {\n array.splice(index, 1);\n }\n}\n\nexport function combine(...arrays) {\n const res = arrays.concat.apply([], arrays);\n let i = res.length;\n while (i--) {\n const idx = res.indexOf(res[i]);\n if (~idx && idx < i) res.splice(i, 1);\n }\n\n return res;\n}\n\nexport function toArray(arrayLike) {\n const array = [];\n let i = arrayLike.length;\n while (i--) {\n array[i] = arrayLike[i];\n }\n\n return array;\n}\n\nexport function findMap(array, fn) {\n const len = array.length;\n for (let i = 0; i < len; i++) {\n const result = fn(array[i]);\n if (result) return result;\n }\n}\n\nexport function buildNewIndices(one, two, comparator) {\n let oldArray = one;\n let newArray = two;\n if (comparator) {\n oldArray = oldArray.map(comparator);\n newArray = newArray.map(comparator);\n }\n\n const oldLength = oldArray.length;\n\n const usedIndices = {};\n let firstUnusedIndex = 0;\n\n return oldArray.map(item => {\n let index;\n let start = firstUnusedIndex;\n\n do {\n index = newArray.indexOf(item, start);\n\n if (index === -1) {\n return -1;\n }\n\n start = index + 1;\n } while (usedIndices[index] === true && start < oldLength);\n\n // keep track of the first unused index, so we don't search\n // the whole of newArray for each item in oldArray unnecessarily\n if (index === firstUnusedIndex) {\n firstUnusedIndex += 1;\n }\n // allow next instance of next \"equal\" to be found item\n usedIndices[index] = true;\n return index;\n });\n}\n","const fnBind = Function.prototype.bind;\n\nexport default function bind(fn, context) {\n if (!/this/.test(fn.toString())) return fn;\n\n const bound = fnBind.call(fn, context);\n for (const prop in fn) bound[prop] = fn[prop];\n\n return bound;\n}\n","import { escapeKey, unescapeKey } from 'shared/keypaths';\nimport { addToArray, removeFromArray } from 'utils/array';\nimport { isArray, isObject, isFunction } from 'utils/is';\nimport bind from 'utils/bind';\nimport { create, keys as objectKeys } from 'utils/object';\n\nconst shuffleTasks = { early: [], mark: [] };\nconst registerQueue = { early: [], mark: [] };\nexport const noVirtual = { virtual: false };\n\nexport default class ModelBase {\n constructor(parent) {\n this.deps = [];\n\n this.children = [];\n this.childByKey = {};\n this.links = [];\n\n this.bindings = [];\n\n if (parent) {\n this.parent = parent;\n this.root = parent.root;\n }\n }\n\n addShuffleTask(task, stage = 'early') {\n shuffleTasks[stage].push(task);\n }\n addShuffleRegister(item, stage = 'early') {\n registerQueue[stage].push({ model: this, item });\n }\n\n downstreamChanged() {}\n\n findMatches(keys) {\n const len = keys.length;\n\n let existingMatches = [this];\n let matches;\n let i;\n\n for (i = 0; i < len; i += 1) {\n const key = keys[i];\n\n if (key === '*') {\n matches = [];\n existingMatches.forEach(model => {\n matches.push.apply(matches, model.getValueChildren(model.get()));\n });\n } else {\n matches = existingMatches.map(model => model.joinKey(key));\n }\n\n existingMatches = matches;\n }\n\n return matches;\n }\n\n getKeypath(ractive) {\n if (ractive !== this.ractive && this._link) return this._link.target.getKeypath(ractive);\n\n if (!this.keypath) {\n const parent = this.parent && this.parent.getKeypath(ractive);\n this.keypath = parent\n ? `${this.parent.getKeypath(ractive)}.${escapeKey(this.key)}`\n : escapeKey(this.key);\n }\n\n return this.keypath;\n }\n\n getValueChildren(value) {\n let children;\n if (isArray(value)) {\n children = [];\n if ('length' in this && this.length !== value.length) {\n children.push(this.joinKey('length'));\n }\n value.forEach((m, i) => {\n children.push(this.joinKey(i));\n });\n } else if (isObject(value) || isFunction(value)) {\n children = objectKeys(value).map(key => this.joinKey(key));\n } else if (value != null) {\n children = [];\n }\n\n const computed = this.computed;\n if (computed) {\n children.push.apply(children, objectKeys(computed).map(k => this.joinKey(k)));\n }\n\n return children;\n }\n\n getVirtual(shouldCapture) {\n const value = this.get(shouldCapture, { virtual: false });\n if (isObject(value)) {\n const result = isArray(value) ? [] : create(null);\n\n let keys = objectKeys(value);\n let i = keys.length;\n while (i--) {\n const child = this.childByKey[keys[i]];\n if (!child) result[keys[i]] = value[keys[i]];\n else if (child._link) result[keys[i]] = child._link.getVirtual();\n else result[keys[i]] = child.getVirtual();\n }\n\n i = this.children.length;\n while (i--) {\n const child = this.children[i];\n if (!(child.key in result) && child._link) {\n result[child.key] = child._link.getVirtual();\n }\n }\n\n if (this.computed) {\n keys = objectKeys(this.computed);\n i = keys.length;\n while (i--) {\n result[keys[i]] = this.computed[keys[i]].get();\n }\n }\n\n return result;\n } else return value;\n }\n\n has(key) {\n if (this._link) return this._link.has(key);\n\n const value = this.get(false, noVirtual);\n if (!value) return false;\n\n key = unescapeKey(key);\n if ((isFunction(value) || isObject(value)) && key in value) return true;\n\n let computed = this.computed;\n if (computed && key in this.computed) return true;\n\n computed = this.root.ractive && this.root.ractive.computed;\n if (computed) {\n objectKeys(computed).forEach(k => {\n if (computed[k].pattern && computed[k].pattern.test(this.getKeypath())) return true;\n });\n }\n\n return false;\n }\n\n joinAll(keys, opts) {\n let model = this;\n for (let i = 0; i < keys.length; i += 1) {\n if (\n opts &&\n opts.lastLink === false &&\n i + 1 === keys.length &&\n model.childByKey[keys[i]] &&\n model.childByKey[keys[i]]._link\n )\n return model.childByKey[keys[i]];\n model = model.joinKey(keys[i], opts);\n }\n\n return model;\n }\n\n notifyUpstream(startPath) {\n let parent = this.parent;\n const path = startPath || [this.key];\n while (parent) {\n if (parent.patterns) parent.patterns.forEach(o => o.notify(path.slice()));\n path.unshift(parent.key);\n parent.links.forEach(l => l.notifiedUpstream(path, this.root));\n parent.deps.forEach(d => d.handleChange(path));\n parent.downstreamChanged(startPath);\n parent = parent.parent;\n }\n }\n\n rebind(next, previous, safe) {\n if (this._link) {\n this._link.rebind(next, previous, false);\n }\n\n // tell the deps to move to the new target\n let i = this.deps.length;\n while (i--) {\n if (this.deps[i].rebind) this.deps[i].rebind(next, previous, safe);\n }\n\n i = this.links.length;\n while (i--) {\n const link = this.links[i];\n // only relink the root of the link tree\n if (link.owner && link.owner._link) link.relinking(next, safe);\n }\n\n i = this.children.length;\n while (i--) {\n const child = this.children[i];\n child.rebind(next ? next.joinKey(child.key) : undefined, child, safe);\n }\n\n i = this.bindings.length;\n while (i--) {\n this.bindings[i].rebind(next, previous, safe);\n }\n }\n\n reference() {\n 'refs' in this ? this.refs++ : (this.refs = 1);\n }\n\n register(dep) {\n this.deps.push(dep);\n }\n\n registerLink(link) {\n addToArray(this.links, link);\n }\n\n registerPatternObserver(observer) {\n (this.patterns || (this.patterns = [])).push(observer);\n this.register(observer);\n }\n\n registerTwowayBinding(binding) {\n this.bindings.push(binding);\n }\n\n unreference() {\n if ('refs' in this) this.refs--;\n }\n\n unregister(dep) {\n removeFromArray(this.deps, dep);\n }\n\n unregisterLink(link) {\n removeFromArray(this.links, link);\n }\n\n unregisterPatternObserver(observer) {\n removeFromArray(this.patterns, observer);\n this.unregister(observer);\n }\n\n unregisterTwowayBinding(binding) {\n removeFromArray(this.bindings, binding);\n }\n\n updateFromBindings(cascade) {\n let i = this.bindings.length;\n while (i--) {\n const value = this.bindings[i].getValue();\n if (value !== this.value) this.set(value);\n }\n\n // check for one-way bindings if there are no two-ways\n if (!this.bindings.length) {\n const oneway = findBoundValue(this.deps);\n if (oneway && oneway.value !== this.value) this.set(oneway.value);\n }\n\n if (cascade) {\n this.children.forEach(updateFromBindings);\n this.links.forEach(updateFromBindings);\n if (this._link) this._link.updateFromBindings(cascade);\n }\n }\n}\n\n// TODO: this may be better handled by overriding `get` on models with a parent that isRoot\nexport function maybeBind(model, value, shouldBind) {\n if (shouldBind && isFunction(value) && model.parent && model.parent.isRoot) {\n if (!model.boundValue) {\n model.boundValue = bind(value._r_unbound || value, model.parent.ractive);\n }\n\n return model.boundValue;\n }\n\n return value;\n}\n\nfunction updateFromBindings(model) {\n model.updateFromBindings(true);\n}\n\nexport function findBoundValue(list) {\n let i = list.length;\n while (i--) {\n if (list[i].bound) {\n const owner = list[i].owner;\n if (owner) {\n const value = owner.name === 'checked' ? owner.node.checked : owner.node.value;\n return { value };\n }\n }\n }\n}\n\nexport function fireShuffleTasks(stage) {\n if (!stage) {\n fireShuffleTasks('early');\n fireShuffleTasks('mark');\n } else {\n const tasks = shuffleTasks[stage];\n shuffleTasks[stage] = [];\n let i = tasks.length;\n while (i--) tasks[i]();\n\n const register = registerQueue[stage];\n registerQueue[stage] = [];\n i = register.length;\n while (i--) register[i].model.register(register[i].item);\n }\n}\n\nexport function shuffle(model, newIndices, link, unsafe) {\n model.shuffling = true;\n\n let i = newIndices.length;\n while (i--) {\n const idx = newIndices[i];\n // nothing is actually changing, so move in the index and roll on\n if (i === idx) {\n continue;\n }\n\n // rebind the children on i to idx\n if (i in model.childByKey)\n model.childByKey[i].rebind(\n !~idx ? undefined : model.joinKey(idx),\n model.childByKey[i],\n !unsafe\n );\n }\n\n const upstream = model.source().length !== model.source().value.length;\n\n model.links.forEach(l => l.shuffle(newIndices));\n if (!link) fireShuffleTasks('early');\n\n i = model.deps.length;\n while (i--) {\n if (model.deps[i].shuffle) model.deps[i].shuffle(newIndices);\n }\n\n model[link ? 'marked' : 'mark']();\n if (!link) fireShuffleTasks('mark');\n\n if (upstream) model.notifyUpstream();\n\n model.shuffling = false;\n}\n","const stack = [];\nlet captureGroup;\n\nexport function startCapturing() {\n stack.push((captureGroup = []));\n}\n\nexport function stopCapturing() {\n const dependencies = stack.pop();\n captureGroup = stack[stack.length - 1];\n return dependencies;\n}\n\nexport function capture(model) {\n if (captureGroup) {\n captureGroup.push(model);\n }\n}\n","export function bind(x) {\n x.bind();\n}\nexport function cancel(x) {\n x.cancel();\n}\nexport function destroyed(x) {\n x.destroyed();\n}\nexport function handleChange(x) {\n x.handleChange();\n}\nexport function mark(x) {\n x.mark();\n}\nexport function markForce(x) {\n x.mark(true);\n}\nexport function marked(x) {\n x.marked();\n}\nexport function markedAll(x) {\n x.markedAll();\n}\nexport function render(x) {\n x.render();\n}\nexport function shuffled(x) {\n x.shuffled();\n}\nexport function teardown(x) {\n x.teardown();\n}\nexport function unbind(x) {\n x.unbind();\n}\nexport function unrender(x) {\n x.unrender();\n}\nexport function unrenderAndDestroy(x) {\n x.unrender(true);\n}\nexport function update(x) {\n x.update();\n}\nexport function toString(x) {\n return x.toString();\n}\nexport function toEscapedString(x) {\n return x.toString(true);\n}\n","import { splitKeypath } from './keypaths';\nimport { isString } from 'utils/is';\n\n// this is the dry method of checking to see if a rebind applies to\n// a particular keypath because in some cases, a dep may be bound\n// directly to a particular keypath e.g. foo.bars.0.baz and need\n// to avoid getting kicked to foo.bars.1.baz if foo.bars is unshifted\nexport function rebindMatch(template, next, previous, fragment) {\n const keypath = template.r || template;\n\n // no valid keypath, go with next\n if (!keypath || !isString(keypath)) return next;\n\n // completely contextual ref, go with next\n if (\n keypath === '.' ||\n keypath[0] === '@' ||\n (next || previous).isKey ||\n (next || previous).isKeypath\n )\n return next;\n\n const parts = keypath.split('/');\n let keys = splitKeypath(parts[parts.length - 1]);\n const last = keys[keys.length - 1];\n\n // check the keypath against the model keypath to see if it matches\n let model = next || previous;\n\n // check to see if this was an alias\n if (model && keys.length === 1 && last !== model.key && fragment) {\n keys = findAlias(last, fragment) || keys;\n }\n\n let i = keys.length;\n let match = true;\n let shuffling = false;\n\n while (model && i--) {\n if (model.shuffling) shuffling = true;\n // non-strict comparison to account for indices in keypaths\n if (keys[i] != model.key) match = false;\n model = model.parent;\n }\n\n // next is undefined, but keypath is shuffling and previous matches\n if (!next && match && shuffling) return previous;\n else if (next && !match && shuffling)\n // next is defined, but doesn't match the keypath\n return previous;\n else return next;\n}\n\nfunction findAlias(name, fragment) {\n while (fragment) {\n const z = fragment.aliases;\n if (z && z[name]) {\n const aliases = (fragment.owner.iterations ? fragment.owner : fragment).owner.template.z;\n for (let i = 0; i < aliases.length; i++) {\n if (aliases[i].n === name) {\n const alias = aliases[i].x;\n if (!alias.r) return false;\n const parts = alias.r.split('/');\n return splitKeypath(parts[parts.length - 1]);\n }\n }\n return;\n }\n\n fragment = fragment.componentParent || fragment.parent;\n }\n}\n","import ModelBase, { fireShuffleTasks, maybeBind, shuffle } from './ModelBase';\nimport { capture } from '../global/capture';\nimport { handleChange, marked, markedAll, teardown } from 'shared/methodCallers';\nimport { rebindMatch } from 'shared/rebind';\nimport resolveReference from 'src/view/resolvers/resolveReference';\nimport noop from 'utils/noop';\nimport { hasOwn } from 'utils/object';\n\n// temporary placeholder target for detached implicit links\nexport const Missing = {\n key: '@missing',\n animate: noop,\n applyValue: noop,\n get: noop,\n getKeypath() {\n return this.key;\n },\n joinAll() {\n return this;\n },\n joinKey() {\n return this;\n },\n mark: noop,\n registerLink: noop,\n shufle: noop,\n set: noop,\n unregisterLink: noop\n};\nMissing.parent = Missing;\n\nexport default class LinkModel extends ModelBase {\n constructor(parent, owner, target, key) {\n super(parent);\n\n this.owner = owner;\n this.target = target;\n this.key = key === undefined ? owner.key : key;\n if (owner && owner.isLink) this.sourcePath = `${owner.sourcePath}.${this.key}`;\n\n if (target) target.registerLink(this);\n\n if (parent) this.isReadonly = parent.isReadonly;\n\n this.isLink = true;\n }\n\n animate(from, to, options, interpolator) {\n return this.target.animate(from, to, options, interpolator);\n }\n\n applyValue(value) {\n if (this.boundValue) this.boundValue = null;\n this.target.applyValue(value);\n }\n\n attach(fragment) {\n const model = resolveReference(fragment, this.key);\n if (model) {\n this.relinking(model, false);\n } else {\n // if there is no link available, move everything here to real models\n this.owner.unlink();\n }\n }\n\n detach() {\n this.relinking(Missing, false);\n }\n\n get(shouldCapture, opts = {}) {\n if (shouldCapture) {\n capture(this);\n\n // may need to tell the target to unwrap\n opts.unwrap = 'unwrap' in opts ? opts.unwrap : true;\n }\n\n const bind = 'shouldBind' in opts ? opts.shouldBind : true;\n opts.shouldBind = this.mapping && this.target.parent && this.target.parent.isRoot;\n\n return maybeBind(this, this.target.get(false, opts), bind);\n }\n\n getKeypath(ractive) {\n if (ractive && ractive !== this.root.ractive) return this.target.getKeypath(ractive);\n\n return super.getKeypath(ractive);\n }\n\n handleChange() {\n this.deps.forEach(handleChange);\n this.links.forEach(handleChange);\n this.notifyUpstream();\n }\n\n isDetached() {\n return this.virtual && this.target === Missing;\n }\n\n joinKey(key) {\n // TODO: handle nested links\n if (key === undefined || key === '') return this;\n\n if (!hasOwn(this.childByKey, key)) {\n const child = new LinkModel(this, this, this.target.joinKey(key), key);\n this.children.push(child);\n this.childByKey[key] = child;\n }\n\n return this.childByKey[key];\n }\n\n mark(force) {\n this.target.mark(force);\n }\n\n marked() {\n if (this.boundValue) this.boundValue = null;\n\n this.links.forEach(marked);\n\n this.deps.forEach(handleChange);\n }\n\n markedAll() {\n this.children.forEach(markedAll);\n this.marked();\n }\n\n notifiedUpstream(startPath, root) {\n this.links.forEach(l => l.notifiedUpstream(startPath, this.root));\n this.deps.forEach(handleChange);\n if (startPath && this.rootLink && this.root !== root) {\n const path = startPath.slice(1);\n path.unshift(this.key);\n this.notifyUpstream(path);\n }\n }\n\n relinked() {\n this.target.registerLink(this);\n this.children.forEach(c => c.relinked());\n }\n\n relinking(target, safe) {\n if (this.rootLink && this.sourcePath)\n target = rebindMatch(this.sourcePath, target, this.target);\n if (!target || this.target === target) return;\n\n this.target && this.target.unregisterLink(this);\n\n this.target = target;\n this.children.forEach(c => {\n c.relinking(target.joinKey(c.key), safe);\n });\n\n if (this.rootLink)\n this.addShuffleTask(() => {\n this.relinked();\n if (!safe) {\n this.markedAll();\n this.notifyUpstream();\n }\n });\n }\n\n set(value) {\n if (this.boundValue) this.boundValue = null;\n this.target.set(value);\n }\n\n shuffle(newIndices) {\n // watch for extra shuffles caused by a shuffle in a downstream link\n if (this.shuffling) return;\n\n // let the real model handle firing off shuffles\n if (!this.target.shuffling) {\n if (this.target.shuffle) {\n this.target.shuffle(newIndices);\n } else {\n // the target is a computation, which can't shuffle\n this.target.mark();\n }\n } else {\n shuffle(this, newIndices, true);\n }\n }\n\n source() {\n if (this.target.source) return this.target.source();\n else return this.target;\n }\n\n teardown() {\n if (this._link) this._link.teardown();\n this.target.unregisterLink(this);\n this.children.forEach(teardown);\n }\n}\n\nModelBase.prototype.link = function link(model, keypath, options) {\n const lnk = this._link || new LinkModel(this.parent, this, model, this.key);\n lnk.implicit = options && options.implicit;\n lnk.mapping = options && options.mapping;\n lnk.sourcePath = keypath;\n lnk.rootLink = true;\n if (this._link) this._link.relinking(model, false);\n this.rebind(lnk, this, false);\n fireShuffleTasks();\n\n this._link = lnk;\n lnk.markedAll();\n\n this.notifyUpstream();\n return lnk;\n};\n\nModelBase.prototype.unlink = function unlink() {\n if (this._link) {\n const ln = this._link;\n this._link = undefined;\n ln.rebind(this, ln, false);\n fireShuffleTasks();\n ln.teardown();\n this.notifyUpstream();\n }\n};\n","export function fromExpression(body, length = 0) {\n const args = new Array(length);\n\n while (length--) {\n args[length] = `_${length}`;\n }\n\n // Functions created directly with new Function() look like this:\n // function anonymous (_0 /**/) { return _0*2 }\n //\n // With this workaround, we get a little more compact:\n // function (_0){return _0*2}\n return new Function([], `return function (${args.join(',')}){return(${body});};`)();\n}\n","import { createFunction } from '../Ractive/config/runtime-parser';\nimport { create, keys } from 'utils/object';\n\nconst functions = create(null);\n\nexport default function getFunction(str, i) {\n if (functions[str]) return functions[str];\n return (functions[str] = createFunction(str, i));\n}\n\nexport function addFunctions(template) {\n if (!template) return;\n\n const exp = template.e;\n\n if (!exp) return;\n\n keys(exp).forEach(str => {\n if (functions[str]) return;\n functions[str] = exp[str];\n });\n}\n","export const TEMPLATE_VERSION = 4;\n","import { warnIfDebug } from 'utils/log';\nimport { create, hasOwn } from 'utils/object';\n\nconst leadingWhitespace = /^\\s+/;\n\nconst ParseError = function(message) {\n this.name = 'ParseError';\n this.message = message;\n try {\n throw new Error(message);\n } catch (e) {\n this.stack = e.stack;\n }\n};\n\nParseError.prototype = Error.prototype;\n\nconst Parser = function(str, options) {\n let item;\n let lineStart = 0;\n\n this.str = str;\n this.options = options || {};\n this.pos = 0;\n\n this.lines = this.str.split('\\n');\n this.lineEnds = this.lines.map(line => {\n const lineEnd = lineStart + line.length + 1; // +1 for the newline\n\n lineStart = lineEnd;\n return lineEnd;\n }, 0);\n\n // Custom init logic\n if (this.init) this.init(str, options);\n\n const items = [];\n\n while (this.pos < this.str.length && (item = this.read())) {\n items.push(item);\n }\n\n this.leftover = this.remaining();\n this.result = this.postProcess ? this.postProcess(items, options) : items;\n};\n\nParser.prototype = {\n read(converters) {\n let i, item;\n\n if (!converters) converters = this.converters;\n\n const pos = this.pos;\n\n const len = converters.length;\n for (i = 0; i < len; i += 1) {\n this.pos = pos; // reset for each attempt\n\n if ((item = converters[i](this))) {\n return item;\n }\n }\n\n return null;\n },\n\n getContextMessage(pos, message) {\n const [lineNum, columnNum] = this.getLinePos(pos);\n if (this.options.contextLines === -1) {\n return [lineNum, columnNum, `${message} at line ${lineNum} character ${columnNum}`];\n }\n\n const line = this.lines[lineNum - 1];\n\n let contextUp = '';\n let contextDown = '';\n if (this.options.contextLines) {\n const start =\n lineNum - 1 - this.options.contextLines < 0 ? 0 : lineNum - 1 - this.options.contextLines;\n contextUp = this.lines\n .slice(start, lineNum - 1 - start)\n .join('\\n')\n .replace(/\\t/g, ' ');\n contextDown = this.lines\n .slice(lineNum, lineNum + this.options.contextLines)\n .join('\\n')\n .replace(/\\t/g, ' ');\n if (contextUp) {\n contextUp += '\\n';\n }\n if (contextDown) {\n contextDown = '\\n' + contextDown;\n }\n }\n\n let numTabs = 0;\n const annotation =\n contextUp +\n line.replace(/\\t/g, (match, char) => {\n if (char < columnNum) {\n numTabs += 1;\n }\n\n return ' ';\n }) +\n '\\n' +\n new Array(columnNum + numTabs).join(' ') +\n '^----' +\n contextDown;\n\n return [\n lineNum,\n columnNum,\n `${message} at line ${lineNum} character ${columnNum}:\\n${annotation}`\n ];\n },\n\n getLinePos(char) {\n let lineNum = 0;\n let lineStart = 0;\n\n while (char >= this.lineEnds[lineNum]) {\n lineStart = this.lineEnds[lineNum];\n lineNum += 1;\n }\n\n const columnNum = char - lineStart;\n return [lineNum + 1, columnNum + 1, char]; // line/col should be one-based, not zero-based!\n },\n\n error(message) {\n const [lineNum, columnNum, msg] = this.getContextMessage(this.pos, message);\n\n const error = new ParseError(msg);\n\n error.line = lineNum;\n error.character = columnNum;\n error.shortMessage = message;\n\n throw error;\n },\n\n matchString(string) {\n if (this.str.substr(this.pos, string.length) === string) {\n this.pos += string.length;\n return string;\n }\n },\n\n matchPattern(pattern) {\n let match;\n\n if ((match = pattern.exec(this.remaining()))) {\n this.pos += match[0].length;\n return match[1] || match[0];\n }\n },\n\n sp() {\n this.matchPattern(leadingWhitespace);\n },\n\n remaining() {\n return this.str.substring(this.pos);\n },\n\n nextChar() {\n return this.str.charAt(this.pos);\n },\n\n warn(message) {\n const msg = this.getContextMessage(this.pos, message)[2];\n\n warnIfDebug(msg);\n }\n};\n\nParser.extend = function(proto) {\n const Parent = this;\n const Child = function(str, options) {\n Parser.call(this, str, options);\n };\n\n Child.prototype = create(Parent.prototype);\n\n for (const key in proto) {\n if (hasOwn(proto, key)) {\n Child.prototype[key] = proto[key];\n }\n }\n\n Child.extend = Parser.extend;\n return Child;\n};\n\nexport default Parser;\n","export const TEXT = 1;\nexport const INTERPOLATOR = 2;\nexport const TRIPLE = 3;\nexport const SECTION = 4;\nexport const INVERTED = 5;\nexport const CLOSING = 6;\nexport const ELEMENT = 7;\nexport const PARTIAL = 8;\nexport const COMMENT = 9;\nexport const DELIMCHANGE = 10;\nexport const ANCHOR = 11;\nexport const ATTRIBUTE = 13;\nexport const CLOSING_TAG = 14;\nexport const COMPONENT = 15;\nexport const YIELDER = 16;\nexport const INLINE_PARTIAL = 17;\nexport const DOCTYPE = 18;\nexport const ALIAS = 19;\n\nexport const AWAIT = 55;\n\nexport const NUMBER_LITERAL = 20;\nexport const STRING_LITERAL = 21;\nexport const ARRAY_LITERAL = 22;\nexport const OBJECT_LITERAL = 23;\nexport const BOOLEAN_LITERAL = 24;\nexport const REGEXP_LITERAL = 25;\n\nexport const GLOBAL = 26;\nexport const KEY_VALUE_PAIR = 27;\n\nexport const REFERENCE = 30;\nexport const REFINEMENT = 31;\nexport const MEMBER = 32;\nexport const PREFIX_OPERATOR = 33;\nexport const BRACKETED = 34;\nexport const CONDITIONAL = 35;\nexport const INFIX_OPERATOR = 36;\n\nexport const INVOCATION = 40;\n\nexport const SECTION_IF = 50;\nexport const SECTION_UNLESS = 51;\nexport const SECTION_EACH = 52;\nexport const SECTION_WITH = 53;\nexport const SECTION_IF_WITH = 54;\n\nexport const ELSE = 60;\nexport const ELSEIF = 61;\nexport const THEN = 62;\nexport const CATCH = 63;\n\nexport const EVENT = 70;\nexport const DECORATOR = 71;\nexport const TRANSITION = 72;\nexport const BINDING_FLAG = 73;\nexport const DELEGATE_FLAG = 74;\n","const delimiterChangePattern = /^[^\\s=]+/;\nconst whitespacePattern = /^\\s+/;\n\nexport default function readDelimiterChange(parser) {\n if (!parser.matchString('=')) {\n return null;\n }\n\n const start = parser.pos;\n\n // allow whitespace before new opening delimiter\n parser.sp();\n\n const opening = parser.matchPattern(delimiterChangePattern);\n if (!opening) {\n parser.pos = start;\n return null;\n }\n\n // allow whitespace (in fact, it's necessary...)\n if (!parser.matchPattern(whitespacePattern)) {\n return null;\n }\n\n const closing = parser.matchPattern(delimiterChangePattern);\n if (!closing) {\n parser.pos = start;\n return null;\n }\n\n // allow whitespace before closing '='\n parser.sp();\n\n if (!parser.matchString('=')) {\n parser.pos = start;\n return null;\n }\n\n return [opening, closing];\n}\n","import { REGEXP_LITERAL } from '../../../../../config/types';\n\nconst regexpPattern = /^(\\/(?:[^\\n\\r\\u2028\\u2029/\\\\[]|\\\\.|\\[(?:[^\\n\\r\\u2028\\u2029\\]\\\\]|\\\\.)*])+\\/(?:([gimuy])(?![a-z]*\\2))*(?![a-zA-Z_$0-9]))/;\n\nexport default function readNumberLiteral(parser) {\n let result;\n\n if ((result = parser.matchPattern(regexpPattern))) {\n return {\n t: REGEXP_LITERAL,\n v: result\n };\n }\n\n return null;\n}\n","const pattern = /[-/\\\\^$*+?.()|[\\]{}]/g;\n\nexport default function escapeRegExp(str) {\n return str.replace(pattern, '\\\\$&');\n}\n","import escapeRegExp from 'utils/escapeRegExp';\n\nconst regExpCache = {};\n\nexport default function(haystack, needles) {\n return haystack.search(\n regExpCache[needles.join()] ||\n (regExpCache[needles.join()] = new RegExp(needles.map(escapeRegExp).join('|')))\n );\n}\n","import { keys } from 'utils/object';\nimport { isFunction } from 'utils/is';\n\n// https://github.com/kangax/html-minifier/issues/63#issuecomment-37763316\n//export const booleanAttributes = /^(allowFullscreen|async|autofocus|autoplay|checked|compact|controls|declare|default|defaultChecked|defaultMuted|defaultSelected|defer|disabled|enabled|formNoValidate|hidden|indeterminate|inert|isMap|itemScope|loop|multiple|muted|noHref|noResize|noShade|noValidate|noWrap|open|pauseOnExit|readOnly|required|reversed|scoped|seamless|selected|sortable|translate|trueSpeed|typeMustMatch|visible)$/i;\nexport const booleanAttributes = {\n allowfullscreen: 1,\n async: 1,\n autofocus: 1,\n autoplay: 1,\n checked: 1,\n compact: 1,\n controls: 1,\n declare: 1,\n default: 1,\n defaultchecked: 1,\n defaultmuted: 1,\n defaultselected: 1,\n defer: 1,\n disabled: 1,\n enabled: 1,\n formnovalidate: 1,\n hidden: 1,\n indeterminate: 1,\n inert: 1,\n ismap: 1,\n itemscope: 1,\n loop: 1,\n multiple: 1,\n muted: 1,\n nohref: 1,\n noresize: 1,\n noshade: 1,\n novalidate: 1,\n nowrap: 1,\n open: 1,\n pauseonexit: 1,\n readonly: 1,\n required: 1,\n reversed: 1,\n scoped: 1,\n seamless: 1,\n selected: 1,\n sortable: 1,\n translate: 1,\n truespeed: 1,\n typemustmatch: 1,\n visible: 1\n};\nexport const voidElements = {\n area: 1,\n base: 1,\n br: 1,\n col: 1,\n command: 1,\n doctype: 1,\n embed: 1,\n hr: 1,\n img: 1,\n input: 1,\n keygen: 1,\n link: 1,\n meta: 1,\n param: 1,\n source: 1,\n track: 1,\n wbr: 1\n};\n\nconst htmlEntities = {\n quot: 34,\n amp: 38,\n apos: 39,\n lt: 60,\n gt: 62,\n nbsp: 160,\n iexcl: 161,\n cent: 162,\n pound: 163,\n curren: 164,\n yen: 165,\n brvbar: 166,\n sect: 167,\n uml: 168,\n copy: 169,\n ordf: 170,\n laquo: 171,\n not: 172,\n shy: 173,\n reg: 174,\n macr: 175,\n deg: 176,\n plusmn: 177,\n sup2: 178,\n sup3: 179,\n acute: 180,\n micro: 181,\n para: 182,\n middot: 183,\n cedil: 184,\n sup1: 185,\n ordm: 186,\n raquo: 187,\n frac14: 188,\n frac12: 189,\n frac34: 190,\n iquest: 191,\n Agrave: 192,\n Aacute: 193,\n Acirc: 194,\n Atilde: 195,\n Auml: 196,\n Aring: 197,\n AElig: 198,\n Ccedil: 199,\n Egrave: 200,\n Eacute: 201,\n Ecirc: 202,\n Euml: 203,\n Igrave: 204,\n Iacute: 205,\n Icirc: 206,\n Iuml: 207,\n ETH: 208,\n Ntilde: 209,\n Ograve: 210,\n Oacute: 211,\n Ocirc: 212,\n Otilde: 213,\n Ouml: 214,\n times: 215,\n Oslash: 216,\n Ugrave: 217,\n Uacute: 218,\n Ucirc: 219,\n Uuml: 220,\n Yacute: 221,\n THORN: 222,\n szlig: 223,\n agrave: 224,\n aacute: 225,\n acirc: 226,\n atilde: 227,\n auml: 228,\n aring: 229,\n aelig: 230,\n ccedil: 231,\n egrave: 232,\n eacute: 233,\n ecirc: 234,\n euml: 235,\n igrave: 236,\n iacute: 237,\n icirc: 238,\n iuml: 239,\n eth: 240,\n ntilde: 241,\n ograve: 242,\n oacute: 243,\n ocirc: 244,\n otilde: 245,\n ouml: 246,\n divide: 247,\n oslash: 248,\n ugrave: 249,\n uacute: 250,\n ucirc: 251,\n uuml: 252,\n yacute: 253,\n thorn: 254,\n yuml: 255,\n OElig: 338,\n oelig: 339,\n Scaron: 352,\n scaron: 353,\n Yuml: 376,\n fnof: 402,\n circ: 710,\n tilde: 732,\n Alpha: 913,\n Beta: 914,\n Gamma: 915,\n Delta: 916,\n Epsilon: 917,\n Zeta: 918,\n Eta: 919,\n Theta: 920,\n Iota: 921,\n Kappa: 922,\n Lambda: 923,\n Mu: 924,\n Nu: 925,\n Xi: 926,\n Omicron: 927,\n Pi: 928,\n Rho: 929,\n Sigma: 931,\n Tau: 932,\n Upsilon: 933,\n Phi: 934,\n Chi: 935,\n Psi: 936,\n Omega: 937,\n alpha: 945,\n beta: 946,\n gamma: 947,\n delta: 948,\n epsilon: 949,\n zeta: 950,\n eta: 951,\n theta: 952,\n iota: 953,\n kappa: 954,\n lambda: 955,\n mu: 956,\n nu: 957,\n xi: 958,\n omicron: 959,\n pi: 960,\n rho: 961,\n sigmaf: 962,\n sigma: 963,\n tau: 964,\n upsilon: 965,\n phi: 966,\n chi: 967,\n psi: 968,\n omega: 969,\n thetasym: 977,\n upsih: 978,\n piv: 982,\n ensp: 8194,\n emsp: 8195,\n thinsp: 8201,\n zwnj: 8204,\n zwj: 8205,\n lrm: 8206,\n rlm: 8207,\n ndash: 8211,\n mdash: 8212,\n lsquo: 8216,\n rsquo: 8217,\n sbquo: 8218,\n ldquo: 8220,\n rdquo: 8221,\n bdquo: 8222,\n dagger: 8224,\n Dagger: 8225,\n bull: 8226,\n hellip: 8230,\n permil: 8240,\n prime: 8242,\n Prime: 8243,\n lsaquo: 8249,\n rsaquo: 8250,\n oline: 8254,\n frasl: 8260,\n euro: 8364,\n image: 8465,\n weierp: 8472,\n real: 8476,\n trade: 8482,\n alefsym: 8501,\n larr: 8592,\n uarr: 8593,\n rarr: 8594,\n darr: 8595,\n harr: 8596,\n crarr: 8629,\n lArr: 8656,\n uArr: 8657,\n rArr: 8658,\n dArr: 8659,\n hArr: 8660,\n forall: 8704,\n part: 8706,\n exist: 8707,\n empty: 8709,\n nabla: 8711,\n isin: 8712,\n notin: 8713,\n ni: 8715,\n prod: 8719,\n sum: 8721,\n minus: 8722,\n lowast: 8727,\n radic: 8730,\n prop: 8733,\n infin: 8734,\n ang: 8736,\n and: 8743,\n or: 8744,\n cap: 8745,\n cup: 8746,\n int: 8747,\n there4: 8756,\n sim: 8764,\n cong: 8773,\n asymp: 8776,\n ne: 8800,\n equiv: 8801,\n le: 8804,\n ge: 8805,\n sub: 8834,\n sup: 8835,\n nsub: 8836,\n sube: 8838,\n supe: 8839,\n oplus: 8853,\n otimes: 8855,\n perp: 8869,\n sdot: 8901,\n lceil: 8968,\n rceil: 8969,\n lfloor: 8970,\n rfloor: 8971,\n lang: 9001,\n rang: 9002,\n loz: 9674,\n spades: 9824,\n clubs: 9827,\n hearts: 9829,\n diams: 9830\n};\nconst controlCharacters = [\n 8364,\n 129,\n 8218,\n 402,\n 8222,\n 8230,\n 8224,\n 8225,\n 710,\n 8240,\n 352,\n 8249,\n 338,\n 141,\n 381,\n 143,\n 144,\n 8216,\n 8217,\n 8220,\n 8221,\n 8226,\n 8211,\n 8212,\n 732,\n 8482,\n 353,\n 8250,\n 339,\n 157,\n 382,\n 376\n];\nconst entityPattern = new RegExp(\n '&(#?(?:x[\\\\w\\\\d]+|\\\\d+|' + keys(htmlEntities).join('|') + '));?',\n 'g'\n);\nconst codePointSupport = isFunction(String.fromCodePoint);\nconst codeToChar = codePointSupport ? String.fromCodePoint : String.fromCharCode;\n\nexport function decodeCharacterReferences(html) {\n return html.replace(entityPattern, (match, entity) => {\n let code;\n\n // Handle named entities\n if (entity[0] !== '#') {\n code = htmlEntities[entity];\n } else if (entity[1] === 'x') {\n code = parseInt(entity.substring(2), 16);\n } else {\n code = parseInt(entity.substring(1), 10);\n }\n\n if (!code) {\n return match;\n }\n\n return codeToChar(validateCode(code));\n });\n}\n\nconst lessThan = //g;\nconst amp = /&/g;\nconst invalid = 65533;\n\nexport function escapeHtml(str) {\n return str\n .replace(amp, '&')\n .replace(lessThan, '<')\n .replace(greaterThan, '>');\n}\n\n// some code points are verboten. If we were inserting HTML, the browser would replace the illegal\n// code points with alternatives in some cases - since we're bypassing that mechanism, we need\n// to replace them ourselves\n//\n// Source: http://en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters\n/* istanbul ignore next */\nfunction validateCode(code) {\n if (!code) {\n return invalid;\n }\n\n // line feed becomes generic whitespace\n if (code === 10) {\n return 32;\n }\n\n // ASCII range. (Why someone would use HTML entities for ASCII characters I don't know, but...)\n if (code < 128) {\n return code;\n }\n\n // code points 128-159 are dealt with leniently by browsers, but they're incorrect. We need\n // to correct the mistake or we'll end up with missing € signs and so on\n if (code <= 159) {\n return controlCharacters[code - 128];\n }\n\n // basic multilingual plane\n if (code < 55296) {\n return code;\n }\n\n // UTF-16 surrogate halves\n if (code <= 57343) {\n return invalid;\n }\n\n // rest of the basic multilingual plane\n if (code <= 65535) {\n return code;\n } else if (!codePointSupport) {\n return invalid;\n }\n\n // supplementary multilingual plane 0x10000 - 0x1ffff\n if (code >= 65536 && code <= 131071) {\n return code;\n }\n\n // supplementary ideographic plane 0x20000 - 0x2ffff\n if (code >= 131072 && code <= 196607) {\n return code;\n }\n\n return invalid;\n}\n","export const expectedExpression = 'Expected a JavaScript expression';\nexport const expectedParen = 'Expected closing paren';\n","import { NUMBER_LITERAL } from '../../../../../config/types';\n\n// bulletproof number regex from https://gist.github.com/Rich-Harris/7544330\nconst numberPattern = /^(?:[+-]?)0*(?:(?:(?:[1-9]\\d*)?\\.\\d+)|(?:(?:0|[1-9]\\d*)\\.)|(?:0|[1-9]\\d*))(?:[eE][+-]?\\d+)?/;\n\nexport default function readNumberLiteral(parser) {\n let result;\n\n if ((result = parser.matchPattern(numberPattern))) {\n return {\n t: NUMBER_LITERAL,\n v: result\n };\n }\n\n return null;\n}\n","import { BOOLEAN_LITERAL } from '../../../../../config/types';\n\nexport default function readBooleanLiteral(parser) {\n const remaining = parser.remaining();\n\n if (remaining.substr(0, 4) === 'true') {\n parser.pos += 4;\n return {\n t: BOOLEAN_LITERAL,\n v: 'true'\n };\n }\n\n if (remaining.substr(0, 5) === 'false') {\n parser.pos += 5;\n return {\n t: BOOLEAN_LITERAL,\n v: 'false'\n };\n }\n\n return null;\n}\n","// Match one or more characters until: \", ', \\, or EOL/EOF.\n// EOL/EOF is written as (?!.) (meaning there's no non-newline char next).\nconst stringMiddlePattern = /^(?=.)[^\"'\\\\]+?(?:(?!.)|(?=[\"'\\\\]))/;\n\n// Match one escape sequence, including the backslash.\nexport const escapeSequencePattern = /^\\\\(?:[`'\"\\\\bfnrt]|0(?![0-9])|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|(?=.)[^ux0-9])/;\n\n// Match one ES5 line continuation (backslash + line terminator).\nexport const lineContinuationPattern = /^\\\\(?:\\r\\n|[\\u000A\\u000D\\u2028\\u2029])/;\n\n// Helper for defining getDoubleQuotedString and getSingleQuotedString.\nexport default function(okQuote) {\n return function(parser) {\n let literal = '\"';\n let done = false;\n let next;\n\n while (!done) {\n next =\n parser.matchPattern(stringMiddlePattern) ||\n parser.matchPattern(escapeSequencePattern) ||\n parser.matchString(okQuote);\n if (next) {\n if (next === `\"`) {\n literal += `\\\\\"`;\n } else if (next === `\\\\'`) {\n literal += `'`;\n } else {\n literal += next;\n }\n } else {\n next = parser.matchPattern(lineContinuationPattern);\n if (next) {\n // convert \\(newline-like) into a \\u escape, which is allowed in JSON\n literal += '\\\\u' + ('000' + next.charCodeAt(1).toString(16)).slice(-4);\n } else {\n done = true;\n }\n }\n }\n\n literal += '\"';\n\n // use JSON.parse to interpret escapes\n return JSON.parse(literal);\n };\n}\n","import { STRING_LITERAL } from '../../../../../config/types';\nimport makeQuotedStringMatcher from './stringLiteral/makeQuotedStringMatcher';\n\nconst singleMatcher = makeQuotedStringMatcher(`\"`);\nconst doubleMatcher = makeQuotedStringMatcher(`'`);\n\nexport default function(parser) {\n const start = parser.pos;\n const quote = parser.matchString(`'`) || parser.matchString(`\"`);\n\n if (quote) {\n const string = (quote === `'` ? singleMatcher : doubleMatcher)(parser);\n\n if (!parser.matchString(quote)) {\n parser.pos = start;\n return null;\n }\n\n return {\n t: STRING_LITERAL,\n v: string\n };\n }\n\n return null;\n}\n","import readExpression from '../../../readExpression';\nimport { STRING_LITERAL, BRACKETED, INFIX_OPERATOR } from '../../../../../config/types';\nimport {\n escapeSequencePattern,\n lineContinuationPattern\n} from './stringLiteral/makeQuotedStringMatcher';\n\n// Match one or more characters until: \", ', or \\\nconst stringMiddlePattern = /^[^`\"\\\\\\$]+?(?:(?=[`\"\\\\\\$]))/;\n\nconst escapes = /[\\r\\n\\t\\b\\f]/g;\nfunction getString(literal) {\n return JSON.parse(`\"${literal.replace(escapes, escapeChar)}\"`);\n}\n\nfunction escapeChar(c) {\n switch (c) {\n case '\\n':\n return '\\\\n';\n case '\\r':\n return '\\\\r';\n case '\\t':\n return '\\\\t';\n case '\\b':\n return '\\\\b';\n case '\\f':\n return '\\\\f';\n }\n}\n\nexport default function readTemplateStringLiteral(parser) {\n if (!parser.matchString('`')) return null;\n\n let literal = '';\n let done = false;\n let next;\n const parts = [];\n\n while (!done) {\n next =\n parser.matchPattern(stringMiddlePattern) ||\n parser.matchPattern(escapeSequencePattern) ||\n parser.matchString('$') ||\n parser.matchString('\"');\n if (next) {\n if (next === `\"`) {\n literal += `\\\\\"`;\n } else if (next === '\\\\`') {\n literal += '`';\n } else if (next === '$') {\n if (parser.matchString('{')) {\n parts.push({ t: STRING_LITERAL, v: getString(literal) });\n literal = '';\n\n parser.sp();\n const expr = readExpression(parser);\n\n if (!expr) parser.error('Expected valid expression');\n\n parts.push({ t: BRACKETED, x: expr });\n\n parser.sp();\n if (!parser.matchString('}'))\n parser.error(`Expected closing '}' after interpolated expression`);\n } else {\n literal += '$';\n }\n } else {\n literal += next;\n }\n } else {\n next = parser.matchPattern(lineContinuationPattern);\n if (next) {\n // convert \\(newline-like) into a \\u escape, which is allowed in JSON\n literal += '\\\\u' + ('000' + next.charCodeAt(1).toString(16)).slice(-4);\n } else {\n done = true;\n }\n }\n }\n\n if (literal.length) parts.push({ t: STRING_LITERAL, v: getString(literal) });\n\n if (!parser.matchString('`')) parser.error(\"Expected closing '`'\");\n\n if (parts.length === 1) {\n return parts[0];\n } else {\n let result = parts.pop();\n let part;\n\n while ((part = parts.pop())) {\n result = {\n t: INFIX_OPERATOR,\n s: '+',\n o: [part, result]\n };\n }\n\n return {\n t: BRACKETED,\n x: result\n };\n }\n}\n","export const name = /^[a-zA-Z_$][a-zA-Z_$0-9]*/;\nexport const spreadPattern = /^\\s*\\.{3}/;\nexport const legalReference = /^(?:[a-zA-Z$_0-9]|\\\\\\.)+(?:(?:\\.(?:[a-zA-Z$_0-9]|\\\\\\.)+)|(?:\\[[0-9]+\\]))*/;\nexport const relaxedName = /^[a-zA-Z_$][-\\/a-zA-Z_$0-9]*(?:\\.(?:[a-zA-Z_$][-\\/a-zA-Z_$0-9]*))*/;\n","import readStringLiteral from '../primary/literal/readStringLiteral';\nimport readNumberLiteral from '../primary/literal/readNumberLiteral';\nimport { name as namePattern } from './patterns';\n\nconst identifier = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;\n\n// http://mathiasbynens.be/notes/javascript-properties\n// can be any name, string literal, or number literal\nexport default function readKey(parser) {\n let token;\n\n if ((token = readStringLiteral(parser))) {\n return identifier.test(token.v) ? token.v : '\"' + token.v.replace(/\"/g, '\\\\\"') + '\"';\n }\n\n if ((token = readNumberLiteral(parser))) {\n return token.v;\n }\n\n if ((token = parser.matchPattern(namePattern))) {\n return token;\n }\n\n return null;\n}\n","import { KEY_VALUE_PAIR, REFERENCE } from 'src/config/types';\nimport readKey from '../../../shared/readKey';\nimport readExpression from '../../../../readExpression';\nimport { name as namePattern, spreadPattern } from '../../../shared/patterns';\n\nexport default function readKeyValuePair(parser) {\n let spread;\n const start = parser.pos;\n\n // allow whitespace between '{' and key\n parser.sp();\n\n const refKey = parser.nextChar() !== \"'\" && parser.nextChar() !== '\"';\n if (refKey) spread = parser.matchPattern(spreadPattern);\n\n const key = spread ? readExpression(parser) : readKey(parser);\n if (key === null) {\n parser.pos = start;\n return null;\n }\n\n // allow whitespace between key and ':'\n parser.sp();\n\n // es2015 shorthand property\n if (refKey && (parser.nextChar() === ',' || parser.nextChar() === '}')) {\n if (!spread && !namePattern.test(key)) {\n parser.error(`Expected a valid reference, but found '${key}' instead.`);\n }\n\n const pair = {\n t: KEY_VALUE_PAIR,\n k: key,\n v: {\n t: REFERENCE,\n n: key\n }\n };\n\n if (spread) {\n pair.p = true;\n }\n\n return pair;\n }\n\n // next character must be ':'\n if (!parser.matchString(':')) {\n parser.pos = start;\n return null;\n }\n\n // allow whitespace between ':' and value\n parser.sp();\n\n // next expression must be a, well... expression\n const value = readExpression(parser);\n if (value === null) {\n parser.pos = start;\n return null;\n }\n\n return {\n t: KEY_VALUE_PAIR,\n k: key,\n v: value\n };\n}\n","import getKeyValuePair from './keyValuePair';\n\nexport default function readKeyValuePairs(parser) {\n const start = parser.pos;\n\n const pair = getKeyValuePair(parser);\n if (pair === null) {\n return null;\n }\n\n const pairs = [pair];\n\n if (parser.matchString(',')) {\n const keyValuePairs = readKeyValuePairs(parser);\n\n if (!keyValuePairs) {\n parser.pos = start;\n return null;\n }\n\n return pairs.concat(keyValuePairs);\n }\n\n return pairs;\n}\n","import { OBJECT_LITERAL } from '../../../../../config/types';\nimport readKeyValuePairs from './objectLiteral/keyValuePairs';\n\nexport default function(parser) {\n const start = parser.pos;\n\n // allow whitespace\n parser.sp();\n\n if (!parser.matchString('{')) {\n parser.pos = start;\n return null;\n }\n\n const keyValuePairs = readKeyValuePairs(parser);\n\n // allow whitespace between final value and '}'\n parser.sp();\n\n if (!parser.matchString('}')) {\n parser.pos = start;\n return null;\n }\n\n return {\n t: OBJECT_LITERAL,\n m: keyValuePairs\n };\n}\n","import { ARRAY_LITERAL } from 'src/config/types';\nimport readExpressionList from '../../shared/readExpressionList';\n\nexport default function(parser) {\n const start = parser.pos;\n\n // allow whitespace before '['\n parser.sp();\n\n if (!parser.matchString('[')) {\n parser.pos = start;\n return null;\n }\n\n const expressionList = readExpressionList(parser, true);\n\n if (!parser.matchString(']')) {\n parser.pos = start;\n return null;\n }\n\n return {\n t: ARRAY_LITERAL,\n m: expressionList\n };\n}\n","import readNumberLiteral from './literal/readNumberLiteral';\nimport readBooleanLiteral from './literal/readBooleanLiteral';\nimport readStringLiteral from './literal/readStringLiteral';\nimport readTemplateStringLiteral from './literal/readTemplateStringLiteral';\nimport readObjectLiteral from './literal/readObjectLiteral';\nimport readArrayLiteral from './literal/readArrayLiteral';\nimport readRegexpLiteral from './literal/readRegexpLiteral';\n\nexport default function readLiteral(parser) {\n return (\n readNumberLiteral(parser) ||\n readBooleanLiteral(parser) ||\n readStringLiteral(parser) ||\n readTemplateStringLiteral(parser) ||\n readObjectLiteral(parser) ||\n readArrayLiteral(parser) ||\n readRegexpLiteral(parser)\n );\n}\n","import { BRACKETED, GLOBAL, REFERENCE } from 'src/config/types';\nimport { normalise } from 'src/shared/keypaths';\nimport { legalReference, relaxedName } from '../shared/patterns';\n\n// if a reference is a browser global, we don't deference it later, so it needs special treatment\nconst globals = /^(?:Array|console|Date|RegExp|decodeURIComponent|decodeURI|encodeURIComponent|encodeURI|isFinite|isNaN|parseFloat|parseInt|JSON|Math|NaN|undefined|null|Object|Number|String|Boolean)\\b/;\n\n// keywords are not valid references, with the exception of `this`\nconst keywords = /^(?:break|case|catch|continue|debugger|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|var|void|while|with)$/;\n\nconst prefixPattern = /^(?:\\@\\.|\\@|~\\/|(?:\\^\\^\\/(?:\\^\\^\\/)*(?:\\.\\.\\/)*)|(?:\\.\\.\\/)+|\\.\\/(?:\\.\\.\\/)*|\\.)/;\nconst specials = /^(key|index|keypath|rootpath|this|global|shared|context|event|node|local|style|helpers|last|macro)/;\n\nexport default function readReference(parser) {\n let prefix, name, global, reference, lastDotIndex;\n\n const startPos = parser.pos;\n\n prefix = parser.matchPattern(prefixPattern) || '';\n name =\n (!prefix && parser.relaxedNames && parser.matchPattern(relaxedName)) ||\n parser.matchPattern(legalReference);\n const actual = prefix.length + ((name && name.length) || 0);\n\n if (prefix === '@.') {\n prefix = '@';\n if (name) name = 'this.' + name;\n else name = 'this';\n }\n\n if (!name && prefix) {\n name = prefix;\n prefix = '';\n }\n\n if (!name) {\n return null;\n }\n\n if (prefix === '@') {\n if (!specials.test(name)) {\n parser.error(`Unrecognized special reference @${name}`);\n } else if ((!name.indexOf('event') || !name.indexOf('node')) && !parser.inEvent) {\n parser.error(`@event and @node are only valid references within an event directive`);\n } else if (~name.indexOf('context')) {\n parser.pos = parser.pos - (name.length - 7);\n return {\n t: BRACKETED,\n x: {\n t: REFERENCE,\n n: '@context'\n }\n };\n }\n }\n\n // bug out if it's a keyword (exception for ancestor/restricted refs - see https://github.com/ractivejs/ractive/issues/1497)\n if (!prefix && !parser.relaxedNames && keywords.test(name)) {\n parser.pos = startPos;\n return null;\n }\n\n // if this is a browser global, stop here\n if (!prefix && globals.test(name)) {\n global = globals.exec(name)[0];\n parser.pos = startPos + global.length;\n\n return {\n t: GLOBAL,\n v: global\n };\n }\n\n reference = (prefix || '') + normalise(name);\n\n if (parser.matchString('(')) {\n // if this is a method invocation (as opposed to a function) we need\n // to strip the method name from the reference combo, else the context\n // will be wrong\n // but only if the reference was actually a member and not a refinement\n lastDotIndex = reference.lastIndexOf('.');\n if (lastDotIndex !== -1 && name[name.length - 1] !== ']') {\n if (lastDotIndex === 0) {\n reference = '.';\n parser.pos = startPos;\n } else {\n const refLength = reference.length;\n reference = reference.substr(0, lastDotIndex);\n parser.pos = startPos + (actual - (refLength - lastDotIndex));\n }\n } else {\n parser.pos -= 1;\n }\n }\n\n return {\n t: REFERENCE,\n n: reference.replace(/^this\\./, './').replace(/^this$/, '.')\n };\n}\n","import { BRACKETED } from 'src/config/types';\nimport { expectedExpression, expectedParen } from '../shared/errors';\nimport readExpression from '../../readExpression';\n\nexport default function readBracketedExpression(parser) {\n if (!parser.matchString('(')) return null;\n\n parser.sp();\n\n const expr = readExpression(parser);\n\n if (!expr) parser.error(expectedExpression);\n\n parser.sp();\n\n if (!parser.matchString(')')) parser.error(expectedParen);\n\n return {\n t: BRACKETED,\n x: expr\n };\n}\n","import readLiteral from './primary/readLiteral';\nimport readReference from './primary/readReference';\nimport readBracketedExpression from './primary/readBracketedExpression';\n\nexport default function(parser) {\n return readLiteral(parser) || readReference(parser) || readBracketedExpression(parser);\n}\n","import { REFINEMENT } from 'config/types';\nimport { expectedExpression } from './errors';\nimport { name as namePattern } from './patterns';\nimport readExpression from '../../readExpression';\n\nexport default function readRefinement(parser) {\n // some things call for strict refinement (partial names), meaning no space between reference and refinement\n if (!parser.strictRefinement) {\n parser.sp();\n }\n\n // \".\" name\n if (parser.matchString('.')) {\n parser.sp();\n\n const name = parser.matchPattern(namePattern);\n if (name) {\n return {\n t: REFINEMENT,\n n: name\n };\n }\n\n parser.error('Expected a property name');\n }\n\n // \"[\" expression \"]\"\n if (parser.matchString('[')) {\n parser.sp();\n\n const expr = readExpression(parser);\n if (!expr) parser.error(expectedExpression);\n\n parser.sp();\n\n if (!parser.matchString(']')) parser.error(`Expected ']'`);\n\n return {\n t: REFINEMENT,\n x: expr\n };\n }\n\n return null;\n}\n","import { MEMBER, INVOCATION } from 'config/types';\nimport readPrimary from './readPrimary';\nimport readExpressionList from './shared/readExpressionList';\nimport readRefinement from './shared/readRefinement';\nimport { expectedParen } from './shared/errors';\n\nexport default function(parser) {\n let expression = readPrimary(parser);\n\n if (!expression) return null;\n\n while (expression) {\n const refinement = readRefinement(parser);\n if (refinement) {\n expression = {\n t: MEMBER,\n x: expression,\n r: refinement\n };\n } else if (parser.matchString('(')) {\n parser.sp();\n const expressionList = readExpressionList(parser, true);\n\n parser.sp();\n\n if (!parser.matchString(')')) {\n parser.error(expectedParen);\n }\n\n expression = {\n t: INVOCATION,\n x: expression\n };\n\n if (expressionList) expression.o = expressionList;\n } else {\n break;\n }\n }\n\n return expression;\n}\n","import { PREFIX_OPERATOR } from 'config/types';\nimport { expectedExpression } from './shared/errors';\nimport readMemberOrInvocation from './readMemberOrInvocation';\nimport readExpression from '../readExpression';\n\nlet readTypeOf;\n\nconst makePrefixSequenceMatcher = function(symbol, fallthrough) {\n return function(parser) {\n let expression;\n\n if ((expression = fallthrough(parser))) {\n return expression;\n }\n\n if (!parser.matchString(symbol)) {\n return null;\n }\n\n parser.sp();\n\n expression = readExpression(parser);\n if (!expression) {\n parser.error(expectedExpression);\n }\n\n return {\n s: symbol,\n o: expression,\n t: PREFIX_OPERATOR\n };\n };\n};\n\n// create all prefix sequence matchers, return readTypeOf\n(function() {\n let i, len, matcher, fallthrough;\n\n const prefixOperators = '! ~ + - typeof'.split(' ');\n\n fallthrough = readMemberOrInvocation;\n for (i = 0, len = prefixOperators.length; i < len; i += 1) {\n matcher = makePrefixSequenceMatcher(prefixOperators[i], fallthrough);\n fallthrough = matcher;\n }\n\n // typeof operator is higher precedence than multiplication, so provides the\n // fallthrough for the multiplication sequence matcher we're about to create\n // (we're skipping void and delete)\n readTypeOf = fallthrough;\n})();\n\nexport default readTypeOf;\n","import { INFIX_OPERATOR } from 'config/types';\nimport readTypeof from './readTypeof';\n\nlet readLogicalOr;\n\nconst makeInfixSequenceMatcher = function(symbol, fallthrough) {\n return function(parser) {\n // > and / have to be quoted\n if (parser.inUnquotedAttribute && (symbol === '>' || symbol === '/'))\n return fallthrough(parser);\n\n let start, left, right;\n\n left = fallthrough(parser);\n if (!left) {\n return null;\n }\n\n // Loop to handle left-recursion in a case like `a * b * c` and produce\n // left association, i.e. `(a * b) * c`. The matcher can't call itself\n // to parse `left` because that would be infinite regress.\n while (true) {\n start = parser.pos;\n\n parser.sp();\n\n if (!parser.matchString(symbol)) {\n parser.pos = start;\n return left;\n }\n\n // special case - in operator must not be followed by [a-zA-Z_$0-9]\n if (symbol === 'in' && /[a-zA-Z_$0-9]/.test(parser.remaining().charAt(0))) {\n parser.pos = start;\n return left;\n }\n\n parser.sp();\n\n // right operand must also consist of only higher-precedence operators\n right = fallthrough(parser);\n if (!right) {\n parser.pos = start;\n return left;\n }\n\n left = {\n t: INFIX_OPERATOR,\n s: symbol,\n o: [left, right]\n };\n\n // Loop back around. If we don't see another occurrence of the symbol,\n // we'll return left.\n }\n };\n};\n\n// create all infix sequence matchers, and return readLogicalOr\n(function() {\n let i, len, matcher, fallthrough;\n\n // All the infix operators on order of precedence (source: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Operator_Precedence)\n // Each sequence matcher will initially fall through to its higher precedence\n // neighbour, and only attempt to match if one of the higher precedence operators\n // (or, ultimately, a literal, reference, or bracketed expression) already matched\n const infixOperators = '* / % + - << >> >>> < <= > >= in instanceof == != === !== & ^ | && ||'.split(\n ' '\n );\n\n // A typeof operator is higher precedence than multiplication\n fallthrough = readTypeof;\n for (i = 0, len = infixOperators.length; i < len; i += 1) {\n matcher = makeInfixSequenceMatcher(infixOperators[i], fallthrough);\n fallthrough = matcher;\n }\n\n // Logical OR is the fallthrough for the conditional matcher\n readLogicalOr = fallthrough;\n})();\n\nexport default readLogicalOr;\n","import { CONDITIONAL } from 'config/types';\nimport readLogicalOr from './readLogicalOr';\nimport { expectedExpression } from './shared/errors';\nimport readExpression from '../readExpression';\n\n// The conditional operator is the lowest precedence operator, so we start here\nexport default function getConditional(parser) {\n const expression = readLogicalOr(parser);\n if (!expression) {\n return null;\n }\n\n const start = parser.pos;\n\n parser.sp();\n\n if (!parser.matchString('?')) {\n parser.pos = start;\n return expression;\n }\n\n parser.sp();\n\n const ifTrue = readExpression(parser);\n if (!ifTrue) {\n parser.error(expectedExpression);\n }\n\n parser.sp();\n\n if (!parser.matchString(':')) {\n parser.error('Expected \":\"');\n }\n\n parser.sp();\n\n const ifFalse = readExpression(parser);\n if (!ifFalse) {\n parser.error(expectedExpression);\n }\n\n return {\n t: CONDITIONAL,\n o: [expression, ifTrue, ifFalse]\n };\n}\n","import readConditional from './expressions/readConditional';\nimport readReference from './expressions/primary/readReference';\n\nexport default function readExpression(parser) {\n // if eval is false, no expressions\n if (parser.allowExpressions === false) {\n const ref = readReference(parser);\n parser.sp();\n return ref;\n }\n\n // The conditional operator is the lowest precedence operator (except yield,\n // assignment operators, and commas, none of which are supported), so we\n // start there. If it doesn't match, it 'falls through' to progressively\n // higher precedence operators, until it eventually matches (or fails to\n // match) a 'primary' - a literal or a reference. This way, the abstract syntax\n // tree has everything in its proper place, i.e. 2 + 3 * 4 === 14, not 20.\n return readConditional(parser);\n}\n","import { expectedExpression } from './errors';\nimport readExpression from '../../readExpression';\nimport { spreadPattern } from './patterns';\n\nexport default function readExpressionList(parser, spread) {\n let isSpread;\n const expressions = [];\n\n const pos = parser.pos;\n\n do {\n parser.sp();\n\n if (spread) {\n isSpread = parser.matchPattern(spreadPattern);\n }\n\n const expr = readExpression(parser);\n\n if (expr === null && expressions.length) {\n parser.error(expectedExpression);\n } else if (expr === null) {\n parser.pos = pos;\n return null;\n }\n\n if (isSpread) {\n expr.p = true;\n }\n\n expressions.push(expr);\n\n parser.sp();\n } while (parser.matchString(','));\n\n return expressions;\n}\n","import { REFERENCE } from 'config/types';\nimport readExpression from './readExpression';\nimport readReference from './expressions/primary/readReference';\n\nexport default function readExpressionOrReference(parser, expectedFollowers) {\n const start = parser.pos;\n const expression = readExpression(parser);\n\n if (!expression) {\n // valid reference but invalid expression e.g. `{{new}}`?\n const ref = parser.matchPattern(/^(\\w+)/);\n if (ref) {\n return {\n t: REFERENCE,\n n: ref\n };\n }\n\n return null;\n }\n\n for (let i = 0; i < expectedFollowers.length; i += 1) {\n if (parser.remaining().substr(0, expectedFollowers[i].length) === expectedFollowers[i]) {\n return expression;\n }\n }\n\n parser.pos = start;\n return readReference(parser);\n}\n","import {\n REFERENCE,\n BOOLEAN_LITERAL,\n GLOBAL,\n NUMBER_LITERAL,\n REGEXP_LITERAL,\n STRING_LITERAL,\n ARRAY_LITERAL,\n OBJECT_LITERAL,\n KEY_VALUE_PAIR,\n PREFIX_OPERATOR,\n INFIX_OPERATOR,\n INVOCATION,\n BRACKETED,\n MEMBER,\n REFINEMENT,\n CONDITIONAL\n} from 'config/types';\nimport { isObject, isString } from 'utils/is';\n\nexport default function flattenExpression(expression) {\n let refs;\n let count = 0;\n\n extractRefs(expression, (refs = []));\n const stringified = stringify(expression);\n\n return {\n r: refs,\n s: getVars(stringified)\n };\n\n function getVars(expr) {\n const vars = [];\n for (let i = count - 1; i >= 0; i--) {\n vars.push(`x$${i}`);\n }\n return vars.length ? `(function(){var ${vars.join(',')};return(${expr});})()` : expr;\n }\n\n function stringify(node) {\n if (isString(node)) {\n return node;\n }\n\n switch (node.t) {\n case BOOLEAN_LITERAL:\n case GLOBAL:\n case NUMBER_LITERAL:\n case REGEXP_LITERAL:\n return node.v;\n\n case STRING_LITERAL:\n return JSON.stringify(String(node.v));\n\n case ARRAY_LITERAL:\n if (node.m && hasSpread(node.m)) {\n return `[].concat(${makeSpread(node.m, '[', ']', stringify)})`;\n } else {\n return '[' + (node.m ? node.m.map(stringify).join(',') : '') + ']';\n }\n\n case OBJECT_LITERAL:\n if (node.m && hasSpread(node.m)) {\n return `Object.assign({},${makeSpread(node.m, '{', '}', stringifyPair)})`;\n } else {\n return '{' + (node.m ? node.m.map(n => `${n.k}:${stringify(n.v)}`).join(',') : '') + '}';\n }\n\n case PREFIX_OPERATOR:\n return (node.s === 'typeof' ? 'typeof ' : node.s) + stringify(node.o);\n\n case INFIX_OPERATOR:\n return (\n stringify(node.o[0]) +\n (node.s.substr(0, 2) === 'in' ? ' ' + node.s + ' ' : node.s) +\n stringify(node.o[1])\n );\n\n case INVOCATION:\n if (node.o && hasSpread(node.o)) {\n const id = count++;\n return `(x$${id}=${stringify(node.x)}).apply(x$${id},${stringify({\n t: ARRAY_LITERAL,\n m: node.o\n })})`;\n } else {\n return stringify(node.x) + '(' + (node.o ? node.o.map(stringify).join(',') : '') + ')';\n }\n\n case BRACKETED:\n return '(' + stringify(node.x) + ')';\n\n case MEMBER:\n return stringify(node.x) + stringify(node.r);\n\n case REFINEMENT:\n return node.n ? '.' + node.n : '[' + stringify(node.x) + ']';\n\n case CONDITIONAL:\n return stringify(node.o[0]) + '?' + stringify(node.o[1]) + ':' + stringify(node.o[2]);\n\n case REFERENCE:\n return '_' + refs.indexOf(node.n);\n\n default:\n throw new Error('Expected legal JavaScript');\n }\n }\n\n function stringifyPair(node) {\n return node.p ? stringify(node.k) : `${node.k}:${stringify(node.v)}`;\n }\n\n function makeSpread(list, open, close, fn) {\n const out = list.reduce(\n (a, c) => {\n if (c.p) {\n a.str += `${a.open ? close + ',' : a.str.length ? ',' : ''}${fn(c)}`;\n } else {\n a.str += `${!a.str.length ? open : !a.open ? ',' + open : ','}${fn(c)}`;\n }\n a.open = !c.p;\n return a;\n },\n { open: false, str: '' }\n );\n if (out.open) out.str += close;\n return out.str;\n }\n}\n\nfunction hasSpread(list) {\n for (let i = 0; i < list.length; i++) {\n if (list[i].p) return true;\n }\n\n return false;\n}\n\n// TODO maybe refactor this?\nfunction extractRefs(node, refs) {\n if (node.t === REFERENCE && isString(node.n)) {\n if (!~refs.indexOf(node.n)) {\n refs.unshift(node.n);\n }\n }\n\n const list = node.o || node.m;\n if (list) {\n if (isObject(list)) {\n extractRefs(list, refs);\n } else {\n let i = list.length;\n while (i--) {\n extractRefs(list[i], refs);\n }\n }\n }\n\n if (node.k && node.t === KEY_VALUE_PAIR && !isString(node.k)) {\n extractRefs(node.k, refs);\n }\n\n if (node.x) {\n extractRefs(node.x, refs);\n }\n\n if (node.r) {\n extractRefs(node.r, refs);\n }\n\n if (node.v) {\n extractRefs(node.v, refs);\n }\n}\n","import { REFERENCE, BRACKETED, MEMBER, REFINEMENT } from 'config/types';\nimport flattenExpression from './flattenExpression';\n\nexport default function refineExpression(expression, mustache) {\n let referenceExpression;\n\n if (expression) {\n while (expression.t === BRACKETED && expression.x) {\n expression = expression.x;\n }\n\n if (expression.t === REFERENCE) {\n const n = expression.n;\n if (!~n.indexOf('@context')) {\n mustache.r = expression.n;\n } else {\n mustache.x = flattenExpression(expression);\n }\n } else {\n if ((referenceExpression = getReferenceExpression(expression))) {\n mustache.rx = referenceExpression;\n } else {\n mustache.x = flattenExpression(expression);\n }\n }\n\n return mustache;\n }\n}\n\n// TODO refactor this! it's bewildering\nfunction getReferenceExpression(expression) {\n const members = [];\n let refinement;\n\n while (expression.t === MEMBER && expression.r.t === REFINEMENT) {\n refinement = expression.r;\n\n if (refinement.x) {\n if (refinement.x.t === REFERENCE) {\n members.unshift(refinement.x);\n } else {\n members.unshift(flattenExpression(refinement.x));\n }\n } else {\n members.unshift(refinement.n);\n }\n\n expression = expression.x;\n }\n\n if (expression.t !== REFERENCE) {\n return null;\n }\n\n return {\n r: expression.n,\n m: members\n };\n}\n","import {\n ARRAY_LITERAL,\n ATTRIBUTE,\n DECORATOR,\n DELEGATE_FLAG,\n BINDING_FLAG,\n INTERPOLATOR,\n TRANSITION,\n EVENT\n} from '../../../config/types';\nimport getLowestIndex from '../utils/getLowestIndex';\nimport readMustache from '../readMustache';\nimport { decodeCharacterReferences } from 'src/utils/html';\nimport readExpressionList from '../expressions/shared/readExpressionList';\nimport readExpressionOrReference from '../readExpressionOrReference';\nimport flattenExpression from 'parse/utils/flattenExpression';\nimport refineExpression from 'parse/utils/refineExpression';\nimport { isString } from 'utils/is';\n\nconst attributeNamePattern = /^[^\\s\"'>\\/=(]+/;\nconst onPattern = /^on/;\nconst eventPattern = /^on-([a-zA-Z\\*\\.$_]((?:[a-zA-Z\\*\\.$_0-9\\-]|\\\\-)+))$/;\nconst reservedEventNames = /^(?:change|reset|teardown|update|construct|config|init|render|complete|unrender|detach|insert|destruct|attachchild|detachchild)$/;\nconst decoratorPattern = /^as-([a-z-A-Z][-a-zA-Z_0-9]*)$/;\nconst transitionPattern = /^([a-zA-Z](?:(?!-in-out)[-a-zA-Z_0-9])*)-(in|out|in-out)$/;\nconst boundPattern = /^((bind|class)-(([-a-zA-Z0-9_])+))$/;\nconst directives = {\n lazy: { t: BINDING_FLAG, v: 'l' },\n twoway: { t: BINDING_FLAG, v: 't' },\n 'no-delegation': { t: DELEGATE_FLAG }\n};\nconst unquotedAttributeValueTextPattern = /^[^\\s\"'=<>\\/`]+/;\nconst proxyEvent = /^[^\\s\"'=<>@\\[\\]()]*/;\nconst whitespace = /^\\s+/;\n\nconst slashes = /\\\\/g;\nfunction splitEvent(str) {\n const result = [];\n let s = 0;\n\n for (let i = 0; i < str.length; i++) {\n if (str[i] === '-' && str[i - 1] !== '\\\\') {\n result.push(str.substring(s, i).replace(slashes, ''));\n s = i + 1;\n }\n }\n\n result.push(str.substring(s).replace(slashes, ''));\n\n return result;\n}\n\nexport default function readAttribute(parser) {\n let name, i, nearest, idx;\n\n parser.sp();\n\n name = parser.matchPattern(attributeNamePattern);\n if (!name) {\n return null;\n }\n\n // check for accidental delimiter consumption e.g. attrs}} />\n nearest = name.length;\n for (i = 0; i < parser.tags.length; i++) {\n if (~(idx = name.indexOf(parser.tags[i].open))) {\n if (idx < nearest) nearest = idx;\n }\n }\n if (nearest < name.length) {\n parser.pos -= name.length - nearest;\n name = name.substr(0, nearest);\n if (!name) return null;\n }\n\n return { n: name };\n}\n\nfunction readAttributeValue(parser) {\n const start = parser.pos;\n\n // next character must be `=`, `/`, `>` or whitespace\n if (!/[=\\/>\\s]/.test(parser.nextChar())) {\n parser.error('Expected `=`, `/`, `>` or whitespace');\n }\n\n parser.sp();\n\n if (!parser.matchString('=')) {\n parser.pos = start;\n return null;\n }\n\n parser.sp();\n\n const valueStart = parser.pos;\n const startDepth = parser.sectionDepth;\n\n const value =\n readQuotedAttributeValue(parser, `'`) ||\n readQuotedAttributeValue(parser, `\"`) ||\n readUnquotedAttributeValue(parser);\n\n if (value === null) {\n parser.error('Expected valid attribute value');\n }\n\n if (parser.sectionDepth !== startDepth) {\n parser.pos = valueStart;\n parser.error(\n 'An attribute value must contain as many opening section tags as closing section tags'\n );\n }\n\n if (!value.length) {\n return '';\n }\n\n if (value.length === 1 && isString(value[0])) {\n return decodeCharacterReferences(value[0]);\n }\n\n return value;\n}\n\nfunction readUnquotedAttributeValueToken(parser) {\n let text, index;\n\n const start = parser.pos;\n\n text = parser.matchPattern(unquotedAttributeValueTextPattern);\n\n if (!text) {\n return null;\n }\n\n const haystack = text;\n const needles = parser.tags.map(t => t.open); // TODO refactor... we do this in readText.js as well\n\n if ((index = getLowestIndex(haystack, needles)) !== -1) {\n text = text.substr(0, index);\n parser.pos = start + text.length;\n }\n\n return text;\n}\n\nfunction readUnquotedAttributeValue(parser) {\n parser.inAttribute = true;\n\n const tokens = [];\n\n let token = readMustache(parser) || readUnquotedAttributeValueToken(parser);\n while (token) {\n tokens.push(token);\n token = readMustache(parser) || readUnquotedAttributeValueToken(parser);\n }\n\n if (!tokens.length) {\n return null;\n }\n\n parser.inAttribute = false;\n return tokens;\n}\n\nfunction readQuotedAttributeValue(parser, quoteMark) {\n const start = parser.pos;\n\n if (!parser.matchString(quoteMark)) {\n return null;\n }\n\n parser.inAttribute = quoteMark;\n\n const tokens = [];\n\n let token = readMustache(parser) || readQuotedStringToken(parser, quoteMark);\n while (token !== null) {\n tokens.push(token);\n token = readMustache(parser) || readQuotedStringToken(parser, quoteMark);\n }\n\n if (!parser.matchString(quoteMark)) {\n parser.pos = start;\n return null;\n }\n\n parser.inAttribute = false;\n\n return tokens;\n}\n\nfunction readQuotedStringToken(parser, quoteMark) {\n const haystack = parser.remaining();\n\n const needles = parser.tags.map(t => t.open); // TODO refactor... we do this in readText.js as well\n needles.push(quoteMark);\n\n const index = getLowestIndex(haystack, needles);\n\n if (index === -1) {\n parser.error('Quoted attribute value must have a closing quote');\n }\n\n if (!index) {\n return null;\n }\n\n parser.pos += index;\n return haystack.substr(0, index);\n}\n\nexport function readAttributeOrDirective(parser) {\n let match, directive;\n\n const attribute = readAttribute(parser, false);\n\n if (!attribute) return null;\n\n // lazy, twoway\n if ((directive = directives[attribute.n])) {\n attribute.t = directive.t;\n if (directive.v) attribute.v = directive.v;\n delete attribute.n; // no name necessary\n parser.sp();\n if (parser.nextChar() === '=') attribute.f = readAttributeValue(parser);\n } else if ((match = decoratorPattern.exec(attribute.n))) {\n // decorators\n attribute.n = match[1];\n attribute.t = DECORATOR;\n readArguments(parser, attribute);\n } else if ((match = transitionPattern.exec(attribute.n))) {\n // transitions\n attribute.n = match[1];\n attribute.t = TRANSITION;\n readArguments(parser, attribute);\n attribute.v = match[2] === 'in-out' ? 't0' : match[2] === 'in' ? 't1' : 't2';\n } else if ((match = eventPattern.exec(attribute.n))) {\n // on-click etc\n attribute.n = splitEvent(match[1]);\n attribute.t = EVENT;\n\n if (parser.matchString('(')) {\n attribute.a = flattenExpression({\n t: ARRAY_LITERAL,\n m: readExpressionList(parser)\n });\n if (!parser.matchString(')')) parser.error(`Expected closing ')'`);\n }\n\n parser.inEvent = true;\n\n // check for a proxy event\n if (!readProxyEvent(parser, attribute)) {\n // otherwise, it's an expression\n readArguments(parser, attribute, true);\n } else if (reservedEventNames.test(attribute.f)) {\n parser.pos -= attribute.f.length;\n parser.error(\n 'Cannot use reserved event names (change, reset, teardown, update, construct, config, init, render, unrender, complete, detach, insert, destruct, attachchild, detachchild)'\n );\n }\n\n parser.inEvent = false;\n } else if ((match = boundPattern.exec(attribute.n))) {\n // bound directives\n const bind = match[2] === 'bind';\n attribute.n = bind ? match[3] : match[1];\n attribute.t = ATTRIBUTE;\n readArguments(parser, attribute, false, true);\n\n if (!attribute.f && bind) {\n attribute.f = [{ t: INTERPOLATOR, r: match[3] }];\n }\n } else {\n parser.sp();\n const value = parser.nextChar() === '=' ? readAttributeValue(parser) : null;\n attribute.f = value != null ? value : attribute.f;\n\n if (parser.sanitizeEventAttributes && onPattern.test(attribute.n)) {\n return { exclude: true };\n } else {\n attribute.f = attribute.f || (attribute.f === '' ? '' : 0);\n attribute.t = ATTRIBUTE;\n }\n }\n\n return attribute;\n}\n\nfunction readProxyEvent(parser, attribute) {\n const start = parser.pos;\n if (!parser.matchString('=')) parser.error(`Missing required directive arguments`);\n\n const quote = parser.matchString(`'`) || parser.matchString(`\"`);\n parser.sp();\n const proxy = parser.matchPattern(proxyEvent);\n\n if (proxy !== undefined) {\n if (quote) {\n parser.sp();\n if (!parser.matchString(quote)) parser.pos = start;\n else return (attribute.f = proxy) || true;\n } else if (!parser.matchPattern(whitespace)) {\n parser.pos = start;\n } else {\n return (attribute.f = proxy) || true;\n }\n } else {\n parser.pos = start;\n }\n}\n\nfunction readArguments(parser, attribute, required = false, single = false) {\n parser.sp();\n if (!parser.matchString('=')) {\n if (required) parser.error(`Missing required directive arguments`);\n return;\n }\n parser.sp();\n\n const quote = parser.matchString('\"') || parser.matchString(\"'\");\n const spread = parser.spreadArgs;\n parser.spreadArgs = true;\n parser.inUnquotedAttribute = !quote;\n const expr = single\n ? readExpressionOrReference(parser, [quote || ' ', '/', '>'])\n : { m: readExpressionList(parser), t: ARRAY_LITERAL };\n parser.inUnquotedAttribute = false;\n parser.spreadArgs = spread;\n\n if (quote) {\n parser.sp();\n if (parser.matchString(quote) !== quote) parser.error(`Expected matching quote '${quote}'`);\n }\n\n if (single) {\n const interpolator = { t: INTERPOLATOR };\n refineExpression(expr, interpolator);\n attribute.f = [interpolator];\n } else {\n attribute.f = flattenExpression(expr);\n }\n}\n","import { DELIMCHANGE } from 'config/types';\nimport readDelimiterChange from './mustache/readDelimiterChange';\nimport readRegexpLiteral from './expressions/primary/literal/readRegexpLiteral';\nimport { readAttributeOrDirective } from './element/readAttribute';\n\nconst delimiterChangeToken = { t: DELIMCHANGE, exclude: true };\n\nexport default function readMustache(parser) {\n let mustache, i;\n\n // If we're inside a