2020-01-28 13:08:03 +08:00
|
|
|
"use strict";
|
|
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
|
|
value: true
|
|
|
|
});
|
|
|
|
exports.default = void 0;
|
|
|
|
|
|
|
|
var _xhtml = _interopRequireDefault(require("./xhtml"));
|
|
|
|
|
|
|
|
var _types = require("../../tokenizer/types");
|
|
|
|
|
|
|
|
var _context = require("../../tokenizer/context");
|
|
|
|
|
|
|
|
var N = _interopRequireWildcard(require("../../types"));
|
|
|
|
|
|
|
|
var _identifier = require("../../util/identifier");
|
|
|
|
|
|
|
|
var _whitespace = require("../../util/whitespace");
|
|
|
|
|
2020-03-22 05:13:25 +08:00
|
|
|
var _location = require("../../parser/location");
|
|
|
|
|
2020-01-28 13:08:03 +08:00
|
|
|
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
|
|
|
|
|
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
|
|
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
|
|
|
|
const HEX_NUMBER = /^[\da-fA-F]+$/;
|
|
|
|
const DECIMAL_NUMBER = /^\d+$/;
|
2020-03-22 05:13:25 +08:00
|
|
|
const JsxErrors = Object.freeze({
|
|
|
|
AttributeIsEmpty: "JSX attributes must only be assigned a non-empty expression",
|
|
|
|
MissingClosingTagFragment: "Expected corresponding JSX closing tag for <>",
|
|
|
|
MissingClosingTagElement: "Expected corresponding JSX closing tag for <%0>",
|
|
|
|
UnsupportedJsxValue: "JSX value should be either an expression or a quoted JSX text",
|
|
|
|
UnterminatedJsxContent: "Unterminated JSX contents",
|
|
|
|
UnwrappedAdjacentJSXElements: "Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>?"
|
|
|
|
});
|
2020-01-28 13:08:03 +08:00
|
|
|
_context.types.j_oTag = new _context.TokContext("<tag", false);
|
|
|
|
_context.types.j_cTag = new _context.TokContext("</tag", false);
|
|
|
|
_context.types.j_expr = new _context.TokContext("<tag>...</tag>", true, true);
|
|
|
|
_types.types.jsxName = new _types.TokenType("jsxName");
|
|
|
|
_types.types.jsxText = new _types.TokenType("jsxText", {
|
|
|
|
beforeExpr: true
|
|
|
|
});
|
|
|
|
_types.types.jsxTagStart = new _types.TokenType("jsxTagStart", {
|
|
|
|
startsExpr: true
|
|
|
|
});
|
|
|
|
_types.types.jsxTagEnd = new _types.TokenType("jsxTagEnd");
|
|
|
|
|
|
|
|
_types.types.jsxTagStart.updateContext = function () {
|
|
|
|
this.state.context.push(_context.types.j_expr);
|
|
|
|
this.state.context.push(_context.types.j_oTag);
|
|
|
|
this.state.exprAllowed = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
_types.types.jsxTagEnd.updateContext = function (prevType) {
|
|
|
|
const out = this.state.context.pop();
|
|
|
|
|
|
|
|
if (out === _context.types.j_oTag && prevType === _types.types.slash || out === _context.types.j_cTag) {
|
|
|
|
this.state.context.pop();
|
|
|
|
this.state.exprAllowed = this.curContext() === _context.types.j_expr;
|
|
|
|
} else {
|
|
|
|
this.state.exprAllowed = true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
function isFragment(object) {
|
|
|
|
return object ? object.type === "JSXOpeningFragment" || object.type === "JSXClosingFragment" : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getQualifiedJSXName(object) {
|
|
|
|
if (object.type === "JSXIdentifier") {
|
|
|
|
return object.name;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (object.type === "JSXNamespacedName") {
|
|
|
|
return object.namespace.name + ":" + object.name.name;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (object.type === "JSXMemberExpression") {
|
|
|
|
return getQualifiedJSXName(object.object) + "." + getQualifiedJSXName(object.property);
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Error("Node had unexpected type: " + object.type);
|
|
|
|
}
|
|
|
|
|
|
|
|
var _default = superClass => class extends superClass {
|
|
|
|
jsxReadToken() {
|
|
|
|
let out = "";
|
|
|
|
let chunkStart = this.state.pos;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
if (this.state.pos >= this.length) {
|
2020-03-22 05:13:25 +08:00
|
|
|
throw this.raise(this.state.start, JsxErrors.UnterminatedJsxContent);
|
2020-01-28 13:08:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const ch = this.input.charCodeAt(this.state.pos);
|
|
|
|
|
|
|
|
switch (ch) {
|
|
|
|
case 60:
|
|
|
|
case 123:
|
|
|
|
if (this.state.pos === this.state.start) {
|
|
|
|
if (ch === 60 && this.state.exprAllowed) {
|
|
|
|
++this.state.pos;
|
|
|
|
return this.finishToken(_types.types.jsxTagStart);
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.getTokenFromCode(ch);
|
|
|
|
}
|
|
|
|
|
|
|
|
out += this.input.slice(chunkStart, this.state.pos);
|
|
|
|
return this.finishToken(_types.types.jsxText, out);
|
|
|
|
|
|
|
|
case 38:
|
|
|
|
out += this.input.slice(chunkStart, this.state.pos);
|
|
|
|
out += this.jsxReadEntity();
|
|
|
|
chunkStart = this.state.pos;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if ((0, _whitespace.isNewLine)(ch)) {
|
|
|
|
out += this.input.slice(chunkStart, this.state.pos);
|
|
|
|
out += this.jsxReadNewLine(true);
|
|
|
|
chunkStart = this.state.pos;
|
|
|
|
} else {
|
|
|
|
++this.state.pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxReadNewLine(normalizeCRLF) {
|
|
|
|
const ch = this.input.charCodeAt(this.state.pos);
|
|
|
|
let out;
|
|
|
|
++this.state.pos;
|
|
|
|
|
|
|
|
if (ch === 13 && this.input.charCodeAt(this.state.pos) === 10) {
|
|
|
|
++this.state.pos;
|
|
|
|
out = normalizeCRLF ? "\n" : "\r\n";
|
|
|
|
} else {
|
|
|
|
out = String.fromCharCode(ch);
|
|
|
|
}
|
|
|
|
|
|
|
|
++this.state.curLine;
|
|
|
|
this.state.lineStart = this.state.pos;
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxReadString(quote) {
|
|
|
|
let out = "";
|
|
|
|
let chunkStart = ++this.state.pos;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
if (this.state.pos >= this.length) {
|
2020-03-22 05:13:25 +08:00
|
|
|
throw this.raise(this.state.start, _location.Errors.UnterminatedString);
|
2020-01-28 13:08:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const ch = this.input.charCodeAt(this.state.pos);
|
|
|
|
if (ch === quote) break;
|
|
|
|
|
|
|
|
if (ch === 38) {
|
|
|
|
out += this.input.slice(chunkStart, this.state.pos);
|
|
|
|
out += this.jsxReadEntity();
|
|
|
|
chunkStart = this.state.pos;
|
|
|
|
} else if ((0, _whitespace.isNewLine)(ch)) {
|
|
|
|
out += this.input.slice(chunkStart, this.state.pos);
|
|
|
|
out += this.jsxReadNewLine(false);
|
|
|
|
chunkStart = this.state.pos;
|
|
|
|
} else {
|
|
|
|
++this.state.pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out += this.input.slice(chunkStart, this.state.pos++);
|
|
|
|
return this.finishToken(_types.types.string, out);
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxReadEntity() {
|
|
|
|
let str = "";
|
|
|
|
let count = 0;
|
|
|
|
let entity;
|
|
|
|
let ch = this.input[this.state.pos];
|
|
|
|
const startPos = ++this.state.pos;
|
|
|
|
|
|
|
|
while (this.state.pos < this.length && count++ < 10) {
|
|
|
|
ch = this.input[this.state.pos++];
|
|
|
|
|
|
|
|
if (ch === ";") {
|
|
|
|
if (str[0] === "#") {
|
|
|
|
if (str[1] === "x") {
|
|
|
|
str = str.substr(2);
|
|
|
|
|
|
|
|
if (HEX_NUMBER.test(str)) {
|
|
|
|
entity = String.fromCodePoint(parseInt(str, 16));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
str = str.substr(1);
|
|
|
|
|
|
|
|
if (DECIMAL_NUMBER.test(str)) {
|
|
|
|
entity = String.fromCodePoint(parseInt(str, 10));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
entity = _xhtml.default[str];
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
str += ch;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!entity) {
|
|
|
|
this.state.pos = startPos;
|
|
|
|
return "&";
|
|
|
|
}
|
|
|
|
|
|
|
|
return entity;
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxReadWord() {
|
|
|
|
let ch;
|
|
|
|
const start = this.state.pos;
|
|
|
|
|
|
|
|
do {
|
|
|
|
ch = this.input.charCodeAt(++this.state.pos);
|
|
|
|
} while ((0, _identifier.isIdentifierChar)(ch) || ch === 45);
|
|
|
|
|
|
|
|
return this.finishToken(_types.types.jsxName, this.input.slice(start, this.state.pos));
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxParseIdentifier() {
|
|
|
|
const node = this.startNode();
|
|
|
|
|
|
|
|
if (this.match(_types.types.jsxName)) {
|
|
|
|
node.name = this.state.value;
|
|
|
|
} else if (this.state.type.keyword) {
|
|
|
|
node.name = this.state.type.keyword;
|
|
|
|
} else {
|
|
|
|
this.unexpected();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.next();
|
|
|
|
return this.finishNode(node, "JSXIdentifier");
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxParseNamespacedName() {
|
|
|
|
const startPos = this.state.start;
|
|
|
|
const startLoc = this.state.startLoc;
|
|
|
|
const name = this.jsxParseIdentifier();
|
|
|
|
if (!this.eat(_types.types.colon)) return name;
|
|
|
|
const node = this.startNodeAt(startPos, startLoc);
|
|
|
|
node.namespace = name;
|
|
|
|
node.name = this.jsxParseIdentifier();
|
|
|
|
return this.finishNode(node, "JSXNamespacedName");
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxParseElementName() {
|
|
|
|
const startPos = this.state.start;
|
|
|
|
const startLoc = this.state.startLoc;
|
|
|
|
let node = this.jsxParseNamespacedName();
|
|
|
|
|
|
|
|
if (node.type === "JSXNamespacedName") {
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (this.eat(_types.types.dot)) {
|
|
|
|
const newNode = this.startNodeAt(startPos, startLoc);
|
|
|
|
newNode.object = node;
|
|
|
|
newNode.property = this.jsxParseIdentifier();
|
|
|
|
node = this.finishNode(newNode, "JSXMemberExpression");
|
|
|
|
}
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxParseAttributeValue() {
|
|
|
|
let node;
|
|
|
|
|
|
|
|
switch (this.state.type) {
|
|
|
|
case _types.types.braceL:
|
|
|
|
node = this.startNode();
|
|
|
|
this.next();
|
|
|
|
node = this.jsxParseExpressionContainer(node);
|
|
|
|
|
|
|
|
if (node.expression.type === "JSXEmptyExpression") {
|
2020-03-22 05:13:25 +08:00
|
|
|
this.raise(node.start, JsxErrors.AttributeIsEmpty);
|
2020-01-28 13:08:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return node;
|
|
|
|
|
|
|
|
case _types.types.jsxTagStart:
|
|
|
|
case _types.types.string:
|
|
|
|
return this.parseExprAtom();
|
|
|
|
|
|
|
|
default:
|
2020-03-22 05:13:25 +08:00
|
|
|
throw this.raise(this.state.start, JsxErrors.UnsupportedJsxValue);
|
2020-01-28 13:08:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxParseEmptyExpression() {
|
|
|
|
const node = this.startNodeAt(this.state.lastTokEnd, this.state.lastTokEndLoc);
|
|
|
|
return this.finishNodeAt(node, "JSXEmptyExpression", this.state.start, this.state.startLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxParseSpreadChild(node) {
|
|
|
|
this.next();
|
|
|
|
node.expression = this.parseExpression();
|
|
|
|
this.expect(_types.types.braceR);
|
|
|
|
return this.finishNode(node, "JSXSpreadChild");
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxParseExpressionContainer(node) {
|
|
|
|
if (this.match(_types.types.braceR)) {
|
|
|
|
node.expression = this.jsxParseEmptyExpression();
|
|
|
|
} else {
|
|
|
|
node.expression = this.parseExpression();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.expect(_types.types.braceR);
|
|
|
|
return this.finishNode(node, "JSXExpressionContainer");
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxParseAttribute() {
|
|
|
|
const node = this.startNode();
|
|
|
|
|
|
|
|
if (this.eat(_types.types.braceL)) {
|
|
|
|
this.expect(_types.types.ellipsis);
|
|
|
|
node.argument = this.parseMaybeAssign();
|
|
|
|
this.expect(_types.types.braceR);
|
|
|
|
return this.finishNode(node, "JSXSpreadAttribute");
|
|
|
|
}
|
|
|
|
|
|
|
|
node.name = this.jsxParseNamespacedName();
|
|
|
|
node.value = this.eat(_types.types.eq) ? this.jsxParseAttributeValue() : null;
|
|
|
|
return this.finishNode(node, "JSXAttribute");
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxParseOpeningElementAt(startPos, startLoc) {
|
|
|
|
const node = this.startNodeAt(startPos, startLoc);
|
|
|
|
|
|
|
|
if (this.match(_types.types.jsxTagEnd)) {
|
|
|
|
this.expect(_types.types.jsxTagEnd);
|
|
|
|
return this.finishNode(node, "JSXOpeningFragment");
|
|
|
|
}
|
|
|
|
|
|
|
|
node.name = this.jsxParseElementName();
|
|
|
|
return this.jsxParseOpeningElementAfterName(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxParseOpeningElementAfterName(node) {
|
|
|
|
const attributes = [];
|
|
|
|
|
|
|
|
while (!this.match(_types.types.slash) && !this.match(_types.types.jsxTagEnd)) {
|
|
|
|
attributes.push(this.jsxParseAttribute());
|
|
|
|
}
|
|
|
|
|
|
|
|
node.attributes = attributes;
|
|
|
|
node.selfClosing = this.eat(_types.types.slash);
|
|
|
|
this.expect(_types.types.jsxTagEnd);
|
|
|
|
return this.finishNode(node, "JSXOpeningElement");
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxParseClosingElementAt(startPos, startLoc) {
|
|
|
|
const node = this.startNodeAt(startPos, startLoc);
|
|
|
|
|
|
|
|
if (this.match(_types.types.jsxTagEnd)) {
|
|
|
|
this.expect(_types.types.jsxTagEnd);
|
|
|
|
return this.finishNode(node, "JSXClosingFragment");
|
|
|
|
}
|
|
|
|
|
|
|
|
node.name = this.jsxParseElementName();
|
|
|
|
this.expect(_types.types.jsxTagEnd);
|
|
|
|
return this.finishNode(node, "JSXClosingElement");
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxParseElementAt(startPos, startLoc) {
|
|
|
|
const node = this.startNodeAt(startPos, startLoc);
|
|
|
|
const children = [];
|
|
|
|
const openingElement = this.jsxParseOpeningElementAt(startPos, startLoc);
|
|
|
|
let closingElement = null;
|
|
|
|
|
|
|
|
if (!openingElement.selfClosing) {
|
|
|
|
contents: for (;;) {
|
|
|
|
switch (this.state.type) {
|
|
|
|
case _types.types.jsxTagStart:
|
|
|
|
startPos = this.state.start;
|
|
|
|
startLoc = this.state.startLoc;
|
|
|
|
this.next();
|
|
|
|
|
|
|
|
if (this.eat(_types.types.slash)) {
|
|
|
|
closingElement = this.jsxParseClosingElementAt(startPos, startLoc);
|
|
|
|
break contents;
|
|
|
|
}
|
|
|
|
|
|
|
|
children.push(this.jsxParseElementAt(startPos, startLoc));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case _types.types.jsxText:
|
|
|
|
children.push(this.parseExprAtom());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case _types.types.braceL:
|
|
|
|
{
|
|
|
|
const node = this.startNode();
|
|
|
|
this.next();
|
|
|
|
|
|
|
|
if (this.match(_types.types.ellipsis)) {
|
|
|
|
children.push(this.jsxParseSpreadChild(node));
|
|
|
|
} else {
|
|
|
|
children.push(this.jsxParseExpressionContainer(node));
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw this.unexpected();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isFragment(openingElement) && !isFragment(closingElement)) {
|
2020-03-22 05:13:25 +08:00
|
|
|
this.raise(closingElement.start, JsxErrors.MissingClosingTagFragment);
|
2020-01-28 13:08:03 +08:00
|
|
|
} else if (!isFragment(openingElement) && isFragment(closingElement)) {
|
2020-03-22 05:13:25 +08:00
|
|
|
this.raise(closingElement.start, JsxErrors.MissingClosingTagElement, getQualifiedJSXName(openingElement.name));
|
2020-01-28 13:08:03 +08:00
|
|
|
} else if (!isFragment(openingElement) && !isFragment(closingElement)) {
|
|
|
|
if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) {
|
2020-03-22 05:13:25 +08:00
|
|
|
this.raise(closingElement.start, JsxErrors.MissingClosingTagElement, getQualifiedJSXName(openingElement.name));
|
2020-01-28 13:08:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isFragment(openingElement)) {
|
|
|
|
node.openingFragment = openingElement;
|
|
|
|
node.closingFragment = closingElement;
|
|
|
|
} else {
|
|
|
|
node.openingElement = openingElement;
|
|
|
|
node.closingElement = closingElement;
|
|
|
|
}
|
|
|
|
|
|
|
|
node.children = children;
|
|
|
|
|
|
|
|
if (this.isRelational("<")) {
|
2020-03-22 05:13:25 +08:00
|
|
|
throw this.raise(this.state.start, JsxErrors.UnwrappedAdjacentJSXElements);
|
2020-01-28 13:08:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return isFragment(openingElement) ? this.finishNode(node, "JSXFragment") : this.finishNode(node, "JSXElement");
|
|
|
|
}
|
|
|
|
|
|
|
|
jsxParseElement() {
|
|
|
|
const startPos = this.state.start;
|
|
|
|
const startLoc = this.state.startLoc;
|
|
|
|
this.next();
|
|
|
|
return this.jsxParseElementAt(startPos, startLoc);
|
|
|
|
}
|
|
|
|
|
2020-03-22 05:13:25 +08:00
|
|
|
parseExprAtom(refExpressionErrors) {
|
2020-01-28 13:08:03 +08:00
|
|
|
if (this.match(_types.types.jsxText)) {
|
|
|
|
return this.parseLiteral(this.state.value, "JSXText");
|
|
|
|
} else if (this.match(_types.types.jsxTagStart)) {
|
|
|
|
return this.jsxParseElement();
|
|
|
|
} else if (this.isRelational("<") && this.input.charCodeAt(this.state.pos) !== 33) {
|
|
|
|
this.finishToken(_types.types.jsxTagStart);
|
|
|
|
return this.jsxParseElement();
|
|
|
|
} else {
|
2020-03-22 05:13:25 +08:00
|
|
|
return super.parseExprAtom(refExpressionErrors);
|
2020-01-28 13:08:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
getTokenFromCode(code) {
|
|
|
|
if (this.state.inPropertyName) return super.getTokenFromCode(code);
|
|
|
|
const context = this.curContext();
|
|
|
|
|
|
|
|
if (context === _context.types.j_expr) {
|
|
|
|
return this.jsxReadToken();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (context === _context.types.j_oTag || context === _context.types.j_cTag) {
|
|
|
|
if ((0, _identifier.isIdentifierStart)(code)) {
|
|
|
|
return this.jsxReadWord();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (code === 62) {
|
|
|
|
++this.state.pos;
|
|
|
|
return this.finishToken(_types.types.jsxTagEnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((code === 34 || code === 39) && context === _context.types.j_oTag) {
|
|
|
|
return this.jsxReadString(code);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (code === 60 && this.state.exprAllowed && this.input.charCodeAt(this.state.pos + 1) !== 33) {
|
|
|
|
++this.state.pos;
|
|
|
|
return this.finishToken(_types.types.jsxTagStart);
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.getTokenFromCode(code);
|
|
|
|
}
|
|
|
|
|
|
|
|
updateContext(prevType) {
|
|
|
|
if (this.match(_types.types.braceL)) {
|
|
|
|
const curContext = this.curContext();
|
|
|
|
|
|
|
|
if (curContext === _context.types.j_oTag) {
|
|
|
|
this.state.context.push(_context.types.braceExpression);
|
|
|
|
} else if (curContext === _context.types.j_expr) {
|
|
|
|
this.state.context.push(_context.types.templateQuasi);
|
|
|
|
} else {
|
|
|
|
super.updateContext(prevType);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.state.exprAllowed = true;
|
|
|
|
} else if (this.match(_types.types.slash) && prevType === _types.types.jsxTagStart) {
|
|
|
|
this.state.context.length -= 2;
|
|
|
|
this.state.context.push(_context.types.j_cTag);
|
|
|
|
this.state.exprAllowed = false;
|
|
|
|
} else {
|
|
|
|
return super.updateContext(prevType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.default = _default;
|