UNPKG

@glimmer/syntax

Version:
1,867 lines (1,580 loc) 691 kB
define('@glimmer/syntax', ['exports', '@glimmer/env', '@glimmer/util', '@handlebars/parser', 'simple-html-tokenizer'], function (exports, env, util, parser, simpleHtmlTokenizer) { 'use strict'; var UNKNOWN_POSITION = Object.freeze({ line: 1, column: 0 }); var SYNTHETIC_LOCATION = Object.freeze({ source: '(synthetic)', start: UNKNOWN_POSITION, end: UNKNOWN_POSITION }); var TEMPORARY_LOCATION = Object.freeze({ source: '(temporary)', start: UNKNOWN_POSITION, end: UNKNOWN_POSITION }); var NON_EXISTENT_LOCATION = Object.freeze({ source: '(nonexistent)', start: UNKNOWN_POSITION, end: UNKNOWN_POSITION }); var BROKEN_LOCATION = Object.freeze({ source: '(broken)', start: UNKNOWN_POSITION, end: UNKNOWN_POSITION }); var SourceSlice = /*#__PURE__*/function () { function SourceSlice(options) { this.loc = options.loc; this.chars = options.chars; } SourceSlice.synthetic = function synthetic(chars) { var offsets = SourceSpan.synthetic(chars); return new SourceSlice({ loc: offsets, chars: chars }); }; SourceSlice.load = function load(source, slice) { return new SourceSlice({ loc: SourceSpan.load(source, slice[1]), chars: slice[0] }); }; var _proto = SourceSlice.prototype; _proto.getString = function getString() { return this.chars; }; _proto.serialize = function serialize() { return [this.chars, this.loc.serialize()]; }; return SourceSlice; }(); function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } it = o[Symbol.iterator](); return it.next.bind(it); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } /** * This file implements the DSL used by span and offset in places where they need to exhaustively * consider all combinations of states (Handlebars offsets, character offsets and invisible/broken * offsets). * * It's probably overkill, but it makes the code that uses it clear. It could be refactored or * removed. */ var MatchAny = 'MATCH_ANY'; var IsInvisible = 'IS_INVISIBLE'; var WhenList = /*#__PURE__*/function () { function WhenList(whens) { this._whens = whens; } var _proto = WhenList.prototype; _proto.first = function first(kind) { for (var _iterator = _createForOfIteratorHelperLoose(this._whens), _step; !(_step = _iterator()).done;) { var when = _step.value; var value = when.match(kind); if (util.isPresent(value)) { return value[0]; } } return null; }; return WhenList; }(); var When = /*#__PURE__*/function () { function When() { this._map = new Map(); } var _proto2 = When.prototype; _proto2.get = function get(pattern, or) { var value = this._map.get(pattern); if (value) { return value; } value = or(); this._map.set(pattern, value); return value; }; _proto2.add = function add(pattern, out) { this._map.set(pattern, out); }; _proto2.match = function match(kind) { var pattern = patternFor(kind); var out = []; var exact = this._map.get(pattern); var fallback = this._map.get(MatchAny); if (exact) { out.push(exact); } if (fallback) { out.push(fallback); } return out; }; return When; }(); function match(callback) { return callback(new Matcher()).check(); } var Matcher = /*#__PURE__*/function () { function Matcher() { this._whens = new When(); } /** * You didn't exhaustively match all possibilities. */ var _proto3 = Matcher.prototype; _proto3.check = function check() { var _this = this; return function (left, right) { return _this.matchFor(left.kind, right.kind)(left, right); }; }; _proto3.matchFor = function matchFor(left, right) { var nesteds = this._whens.match(left); var callback = new WhenList(nesteds).first(right); return callback; }; _proto3.when = function when(left, right, // eslint-disable-next-line @typescript-eslint/no-explicit-any callback) { this._whens.get(left, function () { return new When(); }).add(right, callback); return this; }; return Matcher; }(); function patternFor(kind) { switch (kind) { case "Broken" /* Broken */ : case "InternalsSynthetic" /* InternalsSynthetic */ : case "NonExistent" /* NonExistent */ : return IsInvisible; default: return kind; } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } /** * Used to indicate that an attempt to convert a `SourcePosition` to a character offset failed. It * is separate from `null` so that `null` can be used to indicate that the computation wasn't yet * attempted (and therefore to cache the failure) */ var BROKEN = 'BROKEN'; /** * A `SourceOffset` represents a single position in the source. * * There are three kinds of backing data for `SourceOffset` objects: * * - `CharPosition`, which contains a character offset into the raw source string * - `HbsPosition`, which contains a `SourcePosition` from the Handlebars AST, which can be * converted to a `CharPosition` on demand. * - `InvisiblePosition`, which represents a position not in source (@see {InvisiblePosition}) */ var SourceOffset = /*#__PURE__*/function () { function SourceOffset(data) { this.data = data; } /** * Create a `SourceOffset` from a Handlebars `SourcePosition`. It's stored as-is, and converted * into a character offset on demand, which avoids unnecessarily computing the offset of every * `SourceLocation`, but also means that broken `SourcePosition`s are not always detected. */ SourceOffset.forHbsPos = function forHbsPos(source, pos) { return new HbsPosition(source, pos, null).wrap(); } /** * Create a `SourceOffset` that corresponds to a broken `SourcePosition`. This means that the * calling code determined (or knows) that the `SourceLocation` doesn't correspond correctly to * any part of the source. */ ; SourceOffset.broken = function broken(pos) { if (pos === void 0) { pos = UNKNOWN_POSITION; } return new InvisiblePosition("Broken" /* Broken */ , pos).wrap(); } /** * Get the character offset for this `SourceOffset`, if possible. */ ; var _proto = SourceOffset.prototype; /** * Compare this offset with another one. * * If both offsets are `HbsPosition`s, they're equivalent as long as their lines and columns are * the same. This avoids computing offsets unnecessarily. * * Otherwise, two `SourceOffset`s are equivalent if their successfully computed character offsets * are the same. */ _proto.eql = function eql(right) { return _eql(this.data, right.data); } /** * Create a span that starts from this source offset and ends with another source offset. Avoid * computing character offsets if both `SourceOffset`s are still lazy. */ ; _proto.until = function until(other) { return span(this.data, other.data); } /** * Create a `SourceOffset` by moving the character position represented by this source offset * forward or backward (if `by` is negative), if possible. * * If this `SourceOffset` can't compute a valid character offset, `move` returns a broken offset. * * If the resulting character offset is less than 0 or greater than the size of the source, `move` * returns a broken offset. */ ; _proto.move = function move(by) { var charPos = this.data.toCharPos(); if (charPos === null) { return SourceOffset.broken(); } else { var result = charPos.offset + by; if (charPos.source.check(result)) { return new CharPosition(charPos.source, result).wrap(); } else { return SourceOffset.broken(); } } } /** * Create a new `SourceSpan` that represents a collapsed range at this source offset. Avoid * computing the character offset if it has not already been computed. */ ; _proto.collapsed = function collapsed() { return span(this.data, this.data); } /** * Convert this `SourceOffset` into a Handlebars {@see SourcePosition} for compatibility with * existing plugins. */ ; _proto.toJSON = function toJSON() { return this.data.toJSON(); }; _createClass(SourceOffset, [{ key: "offset", get: function get() { var charPos = this.data.toCharPos(); return charPos === null ? null : charPos.offset; } }]); return SourceOffset; }(); var CharPosition = /*#__PURE__*/function () { function CharPosition(source, charPos) { this.source = source; this.charPos = charPos; this.kind = "CharPosition" /* CharPosition */ ; /** Computed from char offset */ this._locPos = null; } /** * This is already a `CharPosition`. * * {@see HbsPosition} for the alternative. * * @implements {PositionData} */ var _proto2 = CharPosition.prototype; _proto2.toCharPos = function toCharPos() { return this; } /** * Produce a Handlebars {@see SourcePosition} for this `CharPosition`. If this `CharPosition` was * computed using {@see SourceOffset#move}, this will compute the `SourcePosition` for the offset. * * @implements {PositionData} */ ; _proto2.toJSON = function toJSON() { var hbs = this.toHbsPos(); return hbs === null ? UNKNOWN_POSITION : hbs.toJSON(); }; _proto2.wrap = function wrap() { return new SourceOffset(this); } /** * A `CharPosition` always has an offset it can produce without any additional computation. */ ; /** * Convert the current character offset to an `HbsPosition`, if it was not already computed. Once * a `CharPosition` has computed its `HbsPosition`, it will not need to do compute it again, and * the same `CharPosition` is retained when used as one of the ends of a `SourceSpan`, so * computing the `HbsPosition` should be a one-time operation. */ _proto2.toHbsPos = function toHbsPos() { var locPos = this._locPos; if (locPos === null) { var hbsPos = this.source.hbsPosFor(this.charPos); if (hbsPos === null) { this._locPos = locPos = BROKEN; } else { this._locPos = locPos = new HbsPosition(this.source, hbsPos, this.charPos); } } return locPos === BROKEN ? null : locPos; }; _createClass(CharPosition, [{ key: "offset", get: function get() { return this.charPos; } }]); return CharPosition; }(); var HbsPosition = /*#__PURE__*/function () { function HbsPosition(source, hbsPos, charPos) { if (charPos === void 0) { charPos = null; } this.source = source; this.hbsPos = hbsPos; this.kind = "HbsPosition" /* HbsPosition */ ; this._charPos = charPos === null ? null : new CharPosition(source, charPos); } /** * Lazily compute the character offset from the {@see SourcePosition}. Once an `HbsPosition` has * computed its `CharPosition`, it will not need to do compute it again, and the same * `HbsPosition` is retained when used as one of the ends of a `SourceSpan`, so computing the * `CharPosition` should be a one-time operation. * * @implements {PositionData} */ var _proto3 = HbsPosition.prototype; _proto3.toCharPos = function toCharPos() { var charPos = this._charPos; if (charPos === null) { var charPosNumber = this.source.charPosFor(this.hbsPos); if (charPosNumber === null) { this._charPos = charPos = BROKEN; } else { this._charPos = charPos = new CharPosition(this.source, charPosNumber); } } return charPos === BROKEN ? null : charPos; } /** * Return the {@see SourcePosition} that this `HbsPosition` was instantiated with. This operation * does not need to compute anything. * * @implements {PositionData} */ ; _proto3.toJSON = function toJSON() { return this.hbsPos; }; _proto3.wrap = function wrap() { return new SourceOffset(this); } /** * This is already an `HbsPosition`. * * {@see CharPosition} for the alternative. */ ; _proto3.toHbsPos = function toHbsPos() { return this; }; return HbsPosition; }(); var InvisiblePosition = /*#__PURE__*/function () { function InvisiblePosition(kind, // whatever was provided, possibly broken pos) { this.kind = kind; this.pos = pos; } /** * A broken position cannot be turned into a {@see CharacterPosition}. */ var _proto4 = InvisiblePosition.prototype; _proto4.toCharPos = function toCharPos() { return null; } /** * The serialization of an `InvisiblePosition is whatever Handlebars {@see SourcePosition} was * originally identified as broken, non-existent or synthetic. * * If an `InvisiblePosition` never had an source offset at all, this method returns * {@see UNKNOWN_POSITION} for compatibility. */ ; _proto4.toJSON = function toJSON() { return this.pos; }; _proto4.wrap = function wrap() { return new SourceOffset(this); }; _createClass(InvisiblePosition, [{ key: "offset", get: function get() { return null; } }]); return InvisiblePosition; }(); /** * Compare two {@see AnyPosition} and determine whether they are equal. * * @see {SourceOffset#eql} */ var _eql = match(function (m) { return m.when("HbsPosition" /* HbsPosition */ , "HbsPosition" /* HbsPosition */ , function (_ref, _ref2) { var left = _ref.hbsPos; var right = _ref2.hbsPos; return left.column === right.column && left.line === right.line; }).when("CharPosition" /* CharPosition */ , "CharPosition" /* CharPosition */ , function (_ref3, _ref4) { var left = _ref3.charPos; var right = _ref4.charPos; return left === right; }).when("CharPosition" /* CharPosition */ , "HbsPosition" /* HbsPosition */ , function (_ref5, right) { var left = _ref5.offset; var _a; return left === ((_a = right.toCharPos()) === null || _a === void 0 ? void 0 : _a.offset); }).when("HbsPosition" /* HbsPosition */ , "CharPosition" /* CharPosition */ , function (left, _ref6) { var right = _ref6.offset; var _a; return ((_a = left.toCharPos()) === null || _a === void 0 ? void 0 : _a.offset) === right; }).when(MatchAny, MatchAny, function () { return false; }); }); function _defineProperties$1(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass$1(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties$1(Constructor.prototype, protoProps); if (staticProps) _defineProperties$1(Constructor, staticProps); return Constructor; } /** * A `SourceSpan` object represents a span of characters inside of a template source. * * There are three kinds of `SourceSpan` objects: * * - `ConcreteSourceSpan`, which contains byte offsets * - `LazySourceSpan`, which contains `SourceLocation`s from the Handlebars AST, which can be * converted to byte offsets on demand. * - `InvisibleSourceSpan`, which represent source strings that aren't present in the source, * because: * - they were created synthetically * - their location is nonsensical (the span is broken) * - they represent nothing in the source (this currently happens only when a bug in the * upstream Handlebars parser fails to assign a location to empty blocks) * * At a high level, all `SourceSpan` objects provide: * * - byte offsets * - source in column and line format * * And you can do these operations on `SourceSpan`s: * * - collapse it to a `SourceSpan` representing its starting or ending position * - slice out some characters, optionally skipping some characters at the beginning or end * - create a new `SourceSpan` with a different starting or ending offset * * All SourceSpan objects implement `SourceLocation`, for compatibility. All SourceSpan * objects have a `toJSON` that emits `SourceLocation`, also for compatibility. * * For compatibility, subclasses of `AbstractSourceSpan` must implement `locDidUpdate`, which * happens when an AST plugin attempts to modify the `start` or `end` of a span directly. * * The goal is to avoid creating any problems for use-cases like AST Explorer. */ var SourceSpan = /*#__PURE__*/function () { function SourceSpan(data) { this.data = data; this.isInvisible = data.kind !== "CharPosition" /* CharPosition */ && data.kind !== "HbsPosition" /* HbsPosition */ ; } SourceSpan.load = function load(source, serialized) { if (typeof serialized === 'number') { return SourceSpan.forCharPositions(source, serialized, serialized); } else if (typeof serialized === 'string') { return SourceSpan.synthetic(serialized); } else if (Array.isArray(serialized)) { return SourceSpan.forCharPositions(source, serialized[0], serialized[1]); } else if (serialized === "NonExistent" /* NonExistent */ ) { return SourceSpan.NON_EXISTENT; } else if (serialized === "Broken" /* Broken */ ) { return SourceSpan.broken(BROKEN_LOCATION); } util.assertNever(serialized); }; SourceSpan.forHbsLoc = function forHbsLoc(source, loc) { var start = new HbsPosition(source, loc.start); var end = new HbsPosition(source, loc.end); return new HbsSpan(source, { start: start, end: end }, loc).wrap(); }; SourceSpan.forCharPositions = function forCharPositions(source, startPos, endPos) { var start = new CharPosition(source, startPos); var end = new CharPosition(source, endPos); return new CharPositionSpan(source, { start: start, end: end }).wrap(); }; SourceSpan.synthetic = function synthetic(chars) { return new InvisibleSpan("InternalsSynthetic" /* InternalsSynthetic */ , NON_EXISTENT_LOCATION, chars).wrap(); }; SourceSpan.broken = function broken(pos) { if (pos === void 0) { pos = BROKEN_LOCATION; } return new InvisibleSpan("Broken" /* Broken */ , pos).wrap(); }; var _proto = SourceSpan.prototype; _proto.getStart = function getStart() { return this.data.getStart().wrap(); }; _proto.getEnd = function getEnd() { return this.data.getEnd().wrap(); }; /** * Support converting ASTv1 nodes into a serialized format using JSON.stringify. */ _proto.toJSON = function toJSON() { return this.loc; } /** * Create a new span with the current span's end and a new beginning. */ ; _proto.withStart = function withStart(other) { return span(other.data, this.data.getEnd()); } /** * Create a new span with the current span's beginning and a new ending. */ ; _proto.withEnd = function withEnd(other) { return span(this.data.getStart(), other.data); }; _proto.asString = function asString() { return this.data.asString(); } /** * Convert this `SourceSpan` into a `SourceSlice`. In debug mode, this method optionally checks * that the byte offsets represented by this `SourceSpan` actually correspond to the expected * string. */ ; _proto.toSlice = function toSlice(expected) { var chars = this.data.asString(); if (env.DEBUG) { if (expected !== undefined && chars !== expected) { // eslint-disable-next-line no-console console.warn("unexpectedly found " + JSON.stringify(chars) + " when slicing source, but expected " + JSON.stringify(expected)); } } return new SourceSlice({ loc: this, chars: expected || chars }); } /** * For compatibility with SourceLocation in AST plugins * * @deprecated use startPosition instead */ ; _proto.collapse = function collapse(where) { switch (where) { case 'start': return this.getStart().collapsed(); case 'end': return this.getEnd().collapsed(); } }; _proto.extend = function extend(other) { return span(this.data.getStart(), other.data.getEnd()); }; _proto.serialize = function serialize() { return this.data.serialize(); }; _proto.slice = function slice(_ref) { var _ref$skipStart = _ref.skipStart, skipStart = _ref$skipStart === void 0 ? 0 : _ref$skipStart, _ref$skipEnd = _ref.skipEnd, skipEnd = _ref$skipEnd === void 0 ? 0 : _ref$skipEnd; return span(this.getStart().move(skipStart).data, this.getEnd().move(-skipEnd).data); }; _proto.sliceStartChars = function sliceStartChars(_ref2) { var _ref2$skipStart = _ref2.skipStart, skipStart = _ref2$skipStart === void 0 ? 0 : _ref2$skipStart, chars = _ref2.chars; return span(this.getStart().move(skipStart).data, this.getStart().move(skipStart + chars).data); }; _proto.sliceEndChars = function sliceEndChars(_ref3) { var _ref3$skipEnd = _ref3.skipEnd, skipEnd = _ref3$skipEnd === void 0 ? 0 : _ref3$skipEnd, chars = _ref3.chars; return span(this.getEnd().move(skipEnd - chars).data, this.getStart().move(-skipEnd).data); }; _createClass$1(SourceSpan, [{ key: "loc", get: function get() { var span = this.data.toHbsSpan(); return span === null ? BROKEN_LOCATION : span.toHbsLoc(); } }, { key: "module", get: function get() { return this.data.getModule(); } /** * Get the starting `SourcePosition` for this `SourceSpan`, lazily computing it if needed. */ }, { key: "startPosition", get: function get() { return this.loc.start; } /** * Get the ending `SourcePosition` for this `SourceSpan`, lazily computing it if needed. */ }, { key: "endPosition", get: function get() { return this.loc.end; } }, { key: "start", get: function get() { return this.loc.start; } /** * For compatibility with SourceLocation in AST plugins * * @deprecated use withStart instead */ , set: function set(position) { this.data.locDidUpdate({ start: position }); } /** * For compatibility with SourceLocation in AST plugins * * @deprecated use endPosition instead */ }, { key: "end", get: function get() { return this.loc.end; } /** * For compatibility with SourceLocation in AST plugins * * @deprecated use withEnd instead */ , set: function set(position) { this.data.locDidUpdate({ end: position }); } /** * For compatibility with SourceLocation in AST plugins * * @deprecated use module instead */ }, { key: "source", get: function get() { return this.module; } }], [{ key: "NON_EXISTENT", get: function get() { return new InvisibleSpan("NonExistent" /* NonExistent */ , NON_EXISTENT_LOCATION).wrap(); } }]); return SourceSpan; }(); var CharPositionSpan = /*#__PURE__*/function () { function CharPositionSpan(source, charPositions) { this.source = source; this.charPositions = charPositions; this.kind = "CharPosition" /* CharPosition */ ; this._locPosSpan = null; } var _proto2 = CharPositionSpan.prototype; _proto2.wrap = function wrap() { return new SourceSpan(this); }; _proto2.asString = function asString() { return this.source.slice(this.charPositions.start.charPos, this.charPositions.end.charPos); }; _proto2.getModule = function getModule() { return this.source.module; }; _proto2.getStart = function getStart() { return this.charPositions.start; }; _proto2.getEnd = function getEnd() { return this.charPositions.end; }; _proto2.locDidUpdate = function locDidUpdate() { }; _proto2.toHbsSpan = function toHbsSpan() { var locPosSpan = this._locPosSpan; if (locPosSpan === null) { var start = this.charPositions.start.toHbsPos(); var end = this.charPositions.end.toHbsPos(); if (start === null || end === null) { locPosSpan = this._locPosSpan = BROKEN; } else { locPosSpan = this._locPosSpan = new HbsSpan(this.source, { start: start, end: end }); } } return locPosSpan === BROKEN ? null : locPosSpan; }; _proto2.serialize = function serialize() { var _this$charPositions = this.charPositions, start = _this$charPositions.start.charPos, end = _this$charPositions.end.charPos; if (start === end) { return start; } else { return [start, end]; } }; _proto2.toCharPosSpan = function toCharPosSpan() { return this; }; return CharPositionSpan; }(); var HbsSpan = /*#__PURE__*/function () { function HbsSpan(source, hbsPositions, providedHbsLoc) { if (providedHbsLoc === void 0) { providedHbsLoc = null; } this.source = source; this.hbsPositions = hbsPositions; this.kind = "HbsPosition" /* HbsPosition */ ; this._charPosSpan = null; this._providedHbsLoc = providedHbsLoc; } var _proto3 = HbsSpan.prototype; _proto3.serialize = function serialize() { var charPos = this.toCharPosSpan(); return charPos === null ? "Broken" /* Broken */ : charPos.wrap().serialize(); }; _proto3.wrap = function wrap() { return new SourceSpan(this); }; _proto3.updateProvided = function updateProvided(pos, edge) { if (this._providedHbsLoc) { this._providedHbsLoc[edge] = pos; } // invalidate computed character offsets this._charPosSpan = null; this._providedHbsLoc = { start: pos, end: pos }; }; _proto3.locDidUpdate = function locDidUpdate(_ref4) { var start = _ref4.start, end = _ref4.end; if (start !== undefined) { this.updateProvided(start, 'start'); this.hbsPositions.start = new HbsPosition(this.source, start, null); } if (end !== undefined) { this.updateProvided(end, 'end'); this.hbsPositions.end = new HbsPosition(this.source, end, null); } }; _proto3.asString = function asString() { var span = this.toCharPosSpan(); return span === null ? '' : span.asString(); }; _proto3.getModule = function getModule() { return this.source.module; }; _proto3.getStart = function getStart() { return this.hbsPositions.start; }; _proto3.getEnd = function getEnd() { return this.hbsPositions.end; }; _proto3.toHbsLoc = function toHbsLoc() { return { start: this.hbsPositions.start.hbsPos, end: this.hbsPositions.end.hbsPos }; }; _proto3.toHbsSpan = function toHbsSpan() { return this; }; _proto3.toCharPosSpan = function toCharPosSpan() { var charPosSpan = this._charPosSpan; if (charPosSpan === null) { var start = this.hbsPositions.start.toCharPos(); var end = this.hbsPositions.end.toCharPos(); if (start && end) { charPosSpan = this._charPosSpan = new CharPositionSpan(this.source, { start: start, end: end }); } else { charPosSpan = this._charPosSpan = BROKEN; return null; } } return charPosSpan === BROKEN ? null : charPosSpan; }; return HbsSpan; }(); var InvisibleSpan = /*#__PURE__*/function () { function InvisibleSpan(kind, // whatever was provided, possibly broken loc, // if the span represents a synthetic string string) { if (string === void 0) { string = null; } this.kind = kind; this.loc = loc; this.string = string; } var _proto4 = InvisibleSpan.prototype; _proto4.serialize = function serialize() { switch (this.kind) { case "Broken" /* Broken */ : case "NonExistent" /* NonExistent */ : return this.kind; case "InternalsSynthetic" /* InternalsSynthetic */ : return this.string || ''; } }; _proto4.wrap = function wrap() { return new SourceSpan(this); }; _proto4.asString = function asString() { return this.string || ''; }; _proto4.locDidUpdate = function locDidUpdate(_ref5) { var start = _ref5.start, end = _ref5.end; if (start !== undefined) { this.loc.start = start; } if (end !== undefined) { this.loc.end = end; } }; _proto4.getModule = function getModule() { // TODO: Make this reflect the actual module this span originated from return 'an unknown module'; }; _proto4.getStart = function getStart() { return new InvisiblePosition(this.kind, this.loc.start); }; _proto4.getEnd = function getEnd() { return new InvisiblePosition(this.kind, this.loc.end); }; _proto4.toCharPosSpan = function toCharPosSpan() { return this; }; _proto4.toHbsSpan = function toHbsSpan() { return null; }; _proto4.toHbsLoc = function toHbsLoc() { return BROKEN_LOCATION; }; return InvisibleSpan; }(); var span = match(function (m) { return m.when("HbsPosition" /* HbsPosition */ , "HbsPosition" /* HbsPosition */ , function (left, right) { return new HbsSpan(left.source, { start: left, end: right }).wrap(); }).when("CharPosition" /* CharPosition */ , "CharPosition" /* CharPosition */ , function (left, right) { return new CharPositionSpan(left.source, { start: left, end: right }).wrap(); }).when("CharPosition" /* CharPosition */ , "HbsPosition" /* HbsPosition */ , function (left, right) { var rightCharPos = right.toCharPos(); if (rightCharPos === null) { return new InvisibleSpan("Broken" /* Broken */ , BROKEN_LOCATION).wrap(); } else { return span(left, rightCharPos); } }).when("HbsPosition" /* HbsPosition */ , "CharPosition" /* CharPosition */ , function (left, right) { var leftCharPos = left.toCharPos(); if (leftCharPos === null) { return new InvisibleSpan("Broken" /* Broken */ , BROKEN_LOCATION).wrap(); } else { return span(leftCharPos, right); } }).when(IsInvisible, MatchAny, function (left) { return new InvisibleSpan(left.kind, BROKEN_LOCATION).wrap(); }).when(MatchAny, IsInvisible, function (_, right) { return new InvisibleSpan(right.kind, BROKEN_LOCATION).wrap(); }); }); // eslint-disable-next-line import/no-extraneous-dependencies var Source = /*#__PURE__*/function () { function Source(source, module) { if (module === void 0) { module = 'an unknown module'; } this.source = source; this.module = module; } /** * Validate that the character offset represents a position in the source string. */ var _proto = Source.prototype; _proto.check = function check(offset) { return offset >= 0 && offset <= this.source.length; }; _proto.slice = function slice(start, end) { return this.source.slice(start, end); }; _proto.offsetFor = function offsetFor(line, column) { return SourceOffset.forHbsPos(this, { line: line, column: column }); }; _proto.spanFor = function spanFor(_ref) { var start = _ref.start, end = _ref.end; return SourceSpan.forHbsLoc(this, { start: { line: start.line, column: start.column }, end: { line: end.line, column: end.column } }); }; _proto.hbsPosFor = function hbsPosFor(offset) { var seenLines = 0; var seenChars = 0; if (offset > this.source.length) { return null; } while (true) { var nextLine = this.source.indexOf('\n', seenChars); if (offset <= nextLine || nextLine === -1) { return { line: seenLines + 1, column: offset - seenChars }; } else { seenLines += 1; seenChars = nextLine + 1; } } }; _proto.charPosFor = function charPosFor(position) { var line = position.line, column = position.column; var sourceString = this.source; var sourceLength = sourceString.length; var seenLines = 0; var seenChars = 0; while (true) { if (seenChars >= sourceLength) return sourceLength; var nextLine = this.source.indexOf('\n', seenChars); if (nextLine === -1) nextLine = this.source.length; if (seenLines === line - 1) { if (seenChars + column > nextLine) return nextLine; if (env.DEBUG) { var roundTrip = this.hbsPosFor(seenChars + column); } return seenChars + column; } else if (nextLine === -1) { return 0; } else { seenLines += 1; seenChars = nextLine + 1; } } }; return Source; }(); function _defineProperties$2(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass$2(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties$2(Constructor.prototype, protoProps); if (staticProps) _defineProperties$2(Constructor, staticProps); return Constructor; } var PathExpressionImplV1 = /*#__PURE__*/function () { function PathExpressionImplV1(original, head, tail, loc) { this.original = original; this.loc = loc; this.type = 'PathExpression'; this["this"] = false; this.data = false; // Cache for the head value. this._head = undefined; var parts = tail.slice(); if (head.type === 'ThisHead') { this["this"] = true; } else if (head.type === 'AtHead') { this.data = true; parts.unshift(head.name.slice(1)); } else { parts.unshift(head.name); } this.parts = parts; } _createClass$2(PathExpressionImplV1, [{ key: "head", get: function get() { if (this._head) { return this._head; } var firstPart; if (this["this"]) { firstPart = 'this'; } else if (this.data) { firstPart = "@" + this.parts[0]; } else { firstPart = this.parts[0]; } var firstPartLoc = this.loc.collapse('start').sliceStartChars({ chars: firstPart.length }).loc; return this._head = publicBuilder.head(firstPart, firstPartLoc); } }, { key: "tail", get: function get() { return this["this"] ? this.parts : this.parts.slice(1); } }]); return PathExpressionImplV1; }(); var _SOURCE; function SOURCE() { if (!_SOURCE) { _SOURCE = new Source('', '(synthetic)'); } return _SOURCE; } function buildMustache(path, params, hash, raw, loc, strip) { if (typeof path === 'string') { path = buildPath(path); } return { type: 'MustacheStatement', path: path, params: params || [], hash: hash || buildHash([]), escaped: !raw, trusting: !!raw, loc: buildLoc(loc || null), strip: strip || { open: false, close: false } }; } function buildBlock(path, params, hash, _defaultBlock, _elseBlock, loc, openStrip, inverseStrip, closeStrip) { var defaultBlock; var elseBlock; if (_defaultBlock.type === 'Template') { defaultBlock = util.assign({}, _defaultBlock, { type: 'Block' }); } else { defaultBlock = _defaultBlock; } if (_elseBlock !== undefined && _elseBlock !== null && _elseBlock.type === 'Template') { elseBlock = util.assign({}, _elseBlock, { type: 'Block' }); } else { elseBlock = _elseBlock; } return { type: 'BlockStatement', path: buildPath(path), params: params || [], hash: hash || buildHash([]), program: defaultBlock || null, inverse: elseBlock || null, loc: buildLoc(loc || null), openStrip: openStrip || { open: false, close: false }, inverseStrip: inverseStrip || { open: false, close: false }, closeStrip: closeStrip || { open: false, close: false } }; } function buildElementModifier(path, params, hash, loc) { return { type: 'ElementModifierStatement', path: buildPath(path), params: params || [], hash: hash || buildHash([]), loc: buildLoc(loc || null) }; } function buildPartial(name, params, hash, indent, loc) { return { type: 'PartialStatement', name: name, params: params || [], hash: hash || buildHash([]), indent: indent || '', strip: { open: false, close: false }, loc: buildLoc(loc || null) }; } function buildComment(value, loc) { return { type: 'CommentStatement', value: value, loc: buildLoc(loc || null) }; } function buildMustacheComment(value, loc) { return { type: 'MustacheCommentStatement', value: value, loc: buildLoc(loc || null) }; } function buildConcat(parts, loc) { if (!util.isPresent(parts)) { throw new Error("b.concat requires at least one part"); } return { type: 'ConcatStatement', parts: parts || [], loc: buildLoc(loc || null) }; } function buildElement(tag, options) { if (options === void 0) { options = {}; } var _options = options, attrs = _options.attrs, blockParams = _options.blockParams, modifiers = _options.modifiers, comments = _options.comments, children = _options.children, loc = _options.loc; var tagName; // this is used for backwards compat, prior to `selfClosing` being part of the ElementNode AST var selfClosing = false; if (typeof tag === 'object') { selfClosing = tag.selfClosing; tagName = tag.name; } else if (tag.slice(-1) === '/') { tagName = tag.slice(0, -1); selfClosing = true; } else { tagName = tag; } return { type: 'ElementNode', tag: tagName, selfClosing: selfClosing, attributes: attrs || [], blockParams: blockParams || [], modifiers: modifiers || [], comments: comments || [], children: children || [], loc: buildLoc(loc || null) }; } function buildAttr(name, value, loc) { return { type: 'AttrNode', name: name, value: value, loc: buildLoc(loc || null) }; } function buildText(chars, loc) { return { type: 'TextNode', chars: chars || '', loc: buildLoc(loc || null) }; } // Expressions function buildSexpr(path, params, hash, loc) { return { type: 'SubExpression', path: buildPath(path), params: params || [], hash: hash || buildHash([]), loc: buildLoc(loc || null) }; } function headToString(head) { switch (head.type) { case 'AtHead': return { original: head.name, parts: [head.name] }; case 'ThisHead': return { original: "this", parts: [] }; case 'VarHead': return { original: head.name, parts: [head.name] }; } } function buildHead(original, loc) { var _original$split = original.split('.'), head = _original$split[0], tail = _original$split.slice(1); var headNode; if (head === 'this') { headNode = { type: 'ThisHead', loc: buildLoc(loc || null) }; } else if (head[0] === '@') { headNode = { type: 'AtHead', name: head, loc: buildLoc(loc || null) }; } else { headNode = { type: 'VarHead', name: head, loc: buildLoc(loc || null) }; } return { head: headNode, tail: tail }; } function buildThis(loc) { return { type: 'ThisHead', loc: buildLoc(loc || null) }; } function buildAtName(name, loc) { return { type: 'AtHead', name: name, loc: buildLoc(loc || null) }; } function buildVar(name, loc) { return { type: 'VarHead', name: name, loc: buildLoc(loc || null) }; } function buildHeadFromString(head, loc) { if (head[0] === '@') { return buildAtName(head, loc); } else if (head === 'this') { return buildThis(loc); } else { return buildVar(head, loc); } } function buildNamedBlockName(name, loc) { return { type: 'NamedBlockName', name: name, loc: buildLoc(loc || null) }; } function buildCleanPath(head, tail, loc) { var _headToString = headToString(head), originalHead = _headToString.original, headParts = _headToString.parts; var parts = [].concat(headParts, tail); var original = [].concat(originalHead, parts).join('.'); return new PathExpressionImplV1(original, head, tail, buildLoc(loc || null)); } function buildPath(path, loc) { if (typeof path !== 'string') { if ('type' in path) { return path; } else { var _buildHead = buildHead(path.head, SourceSpan.broken()), _head = _buildHead.head, _tail = _buildHead.tail; var _headToString2 = headToString(_head), originalHead = _headToString2.original; return new PathExpressionImplV1([originalHead].concat(_tail).join('.'), _head, _tail, buildLoc(loc || null)); } } var _buildHead2 = buildHead(path, SourceSpan.broken()), head = _buildHead2.head, tail = _buildHead2.tail; return new PathExpressionImplV1(path, head, tail, buildLoc(loc || null)); } function buildLiteral(type, value, loc) { return { type: type, value: value, original: value, loc: buildLoc(loc || null) }; } // Miscellaneous function buildHash(pairs, loc) { return { type: 'Hash', pairs: pairs || [], loc: buildLoc(loc || null) }; } function buildPair(key, value, loc) { return { type: 'HashPair', key: key, value: value, loc: buildLoc(loc || null) }; } function buildProgram(body, blockParams, loc) { return { type: 'Template', body: body || [], blockParams: blockParams || [], loc: buildLoc(loc || null) }; } function buildBlockItself(body, blockParams, chained, loc) { if (chained === void 0) { chained = false; } return { type: 'Block', body: body || [], blockParams: blockParams || [], chained: chained, loc: buildLoc(loc || null) }; } function buildTemplate(body, blockParams, loc) { return { type: 'Template', body: body || [], blockParams: blockParams || [], loc: buildLoc(loc || null) }; } function buildPosition(line, column) { return { line: line, column: column }; } function buildLoc() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } if (args.length === 1) { var loc = args[0]; if (loc && typeof loc === 'object') { return SourceSpan.forHbsLoc(SOURCE(), loc); } else { return SourceSpan.forHbsLoc(SOURCE(), SYNTHETIC_LOCATION); } } else { var startLine = args[0], startColumn = args[1], endLine = args[2], endColumn = args[3], _source = args[4]; var source = _source ? new Source('', _source) : SOURCE(); return SourceSpan.forHbsLoc(source, { start: { line: startLine, column: startColumn }, end: { line: endLine, column: endColumn } }); } } var publicBuilder = { mustache: buildMustache, block: buildBlock, partial: buildPartial, comment: buildComment, mustacheComment: buildMustacheComment, element: buildElement, elementModifier: buildElementModifier, attr: buildAttr, text: buildText, sexpr: buildSexpr, concat: buildConcat, hash: buildHash, pair: buildPair, literal: buildLiteral, program: buildProgram, blockItself: buildBlockItself, template: buildTemplate, loc: buildLoc, pos: buildPosition, path: buildPath, fullPath: buildCleanPath, head: buildHeadFromString, at: buildAtName, "var": buildVar, "this": buildThis, blockName: buildNamedBlockName, string: literal('StringLiteral'), "boolean": literal('BooleanLiteral'), number: literal('NumberLiteral'), undefined: function (_undefined) { function undefined$1() { return _undefined.apply(this, arguments); } undefined$1.toString = function () { return _undefined.toString(); }; return undefined$1; }(function () { return buildLiteral('UndefinedLiteral', undefined); }), "null": function _null() { return buildLiteral('NullLiteral', null); } }; function literal(type) { return function (value, loc) { return buildLiteral(type, value, loc); }; } var api = /*#__PURE__*/Object.freeze({ __proto__: null }); /** * A free variable is resolved according to a resolution rule: * * 1. Strict resolution * 2. Namespaced resolution * 3. Fallback resolution */ /** * Strict resolution is used: * * 1. in a strict mode template * 2. in an unambiguous invocation with dot paths */ var StrictResolution = /*#__PURE__*/function () { function StrictResolution() { this.isAngleBracket = false; } var _proto = StrictResolution.prototype; _proto.resolution = function resolution() { return 31 /* GetStrictFree */ ; }; _proto.serialize = function serialize() { return 'Strict'; }; return StrictResolution; }(); var