@glimmer/syntax
Version:
1,867 lines (1,580 loc) • 691 kB
JavaScript
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