UNPKG

angular2

Version:

Angular 2 - a web framework for modern web apps

228 lines 10.2 kB
'use strict';var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc); switch (arguments.length) { case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target); case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0); case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc); } }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var lang_1 = require('angular2/src/facade/lang'); var collection_1 = require('angular2/src/facade/collection'); var html_ast_1 = require('./html_ast'); var di_1 = require('angular2/src/core/di'); var html_lexer_1 = require('./html_lexer'); var parse_util_1 = require('./parse_util'); var html_tags_1 = require('./html_tags'); var HtmlTreeError = (function (_super) { __extends(HtmlTreeError, _super); function HtmlTreeError(elementName, location, msg) { _super.call(this, location, msg); this.elementName = elementName; } HtmlTreeError.create = function (elementName, location, msg) { return new HtmlTreeError(elementName, location, msg); }; return HtmlTreeError; })(parse_util_1.ParseError); exports.HtmlTreeError = HtmlTreeError; var HtmlParseTreeResult = (function () { function HtmlParseTreeResult(rootNodes, errors) { this.rootNodes = rootNodes; this.errors = errors; } return HtmlParseTreeResult; })(); exports.HtmlParseTreeResult = HtmlParseTreeResult; var HtmlParser = (function () { function HtmlParser() { } HtmlParser.prototype.parse = function (sourceContent, sourceUrl) { var tokensAndErrors = html_lexer_1.tokenizeHtml(sourceContent, sourceUrl); var treeAndErrors = new TreeBuilder(tokensAndErrors.tokens).build(); return new HtmlParseTreeResult(treeAndErrors.rootNodes, tokensAndErrors.errors .concat(treeAndErrors.errors)); }; HtmlParser = __decorate([ di_1.Injectable(), __metadata('design:paramtypes', []) ], HtmlParser); return HtmlParser; })(); exports.HtmlParser = HtmlParser; var TreeBuilder = (function () { function TreeBuilder(tokens) { this.tokens = tokens; this.index = -1; this.rootNodes = []; this.errors = []; this.elementStack = []; this._advance(); } TreeBuilder.prototype.build = function () { while (this.peek.type !== html_lexer_1.HtmlTokenType.EOF) { if (this.peek.type === html_lexer_1.HtmlTokenType.TAG_OPEN_START) { this._consumeStartTag(this._advance()); } else if (this.peek.type === html_lexer_1.HtmlTokenType.TAG_CLOSE) { this._consumeEndTag(this._advance()); } else if (this.peek.type === html_lexer_1.HtmlTokenType.CDATA_START) { this._consumeCdata(this._advance()); } else if (this.peek.type === html_lexer_1.HtmlTokenType.COMMENT_START) { this._consumeComment(this._advance()); } else if (this.peek.type === html_lexer_1.HtmlTokenType.TEXT || this.peek.type === html_lexer_1.HtmlTokenType.RAW_TEXT || this.peek.type === html_lexer_1.HtmlTokenType.ESCAPABLE_RAW_TEXT) { this._consumeText(this._advance()); } else { // Skip all other tokens... this._advance(); } } return new HtmlParseTreeResult(this.rootNodes, this.errors); }; TreeBuilder.prototype._advance = function () { var prev = this.peek; if (this.index < this.tokens.length - 1) { // Note: there is always an EOF token at the end this.index++; } this.peek = this.tokens[this.index]; return prev; }; TreeBuilder.prototype._advanceIf = function (type) { if (this.peek.type === type) { return this._advance(); } return null; }; TreeBuilder.prototype._consumeCdata = function (startToken) { this._consumeText(this._advance()); this._advanceIf(html_lexer_1.HtmlTokenType.CDATA_END); }; TreeBuilder.prototype._consumeComment = function (startToken) { this._advanceIf(html_lexer_1.HtmlTokenType.RAW_TEXT); this._advanceIf(html_lexer_1.HtmlTokenType.COMMENT_END); }; TreeBuilder.prototype._consumeText = function (token) { this._addToParent(new html_ast_1.HtmlTextAst(token.parts[0], token.sourceSpan)); }; TreeBuilder.prototype._consumeStartTag = function (startTagToken) { var prefix = startTagToken.parts[0]; var name = startTagToken.parts[1]; var attrs = []; while (this.peek.type === html_lexer_1.HtmlTokenType.ATTR_NAME) { attrs.push(this._consumeAttr(this._advance())); } var fullName = getElementFullName(prefix, name, this._getParentElement()); var voidElement = false; // Note: There could have been a tokenizer error // so that we don't get a token for the end tag... if (this.peek.type === html_lexer_1.HtmlTokenType.TAG_OPEN_END_VOID) { this._advance(); voidElement = true; } else if (this.peek.type === html_lexer_1.HtmlTokenType.TAG_OPEN_END) { this._advance(); voidElement = false; } var end = this.peek.sourceSpan.start; var el = new html_ast_1.HtmlElementAst(fullName, attrs, [], new parse_util_1.ParseSourceSpan(startTagToken.sourceSpan.start, end)); this._pushElement(el); if (voidElement) { this._popElement(fullName); } }; TreeBuilder.prototype._pushElement = function (el) { if (this.elementStack.length > 0) { var parentEl = collection_1.ListWrapper.last(this.elementStack); if (html_tags_1.getHtmlTagDefinition(parentEl.name).isClosedByChild(el.name)) { this.elementStack.pop(); } } var tagDef = html_tags_1.getHtmlTagDefinition(el.name); var parentEl = this._getParentElement(); if (tagDef.requireExtraParent(lang_1.isPresent(parentEl) ? parentEl.name : null)) { var newParent = new html_ast_1.HtmlElementAst(tagDef.requiredParent, [], [el], el.sourceSpan); this._addToParent(newParent); this.elementStack.push(newParent); this.elementStack.push(el); } else { this._addToParent(el); this.elementStack.push(el); } }; TreeBuilder.prototype._consumeEndTag = function (endTagToken) { var fullName = getElementFullName(endTagToken.parts[0], endTagToken.parts[1], this._getParentElement()); if (!this._popElement(fullName)) { this.errors.push(HtmlTreeError.create(fullName, endTagToken.sourceSpan.start, "Unexpected closing tag \"" + endTagToken.parts[1] + "\"")); } }; TreeBuilder.prototype._popElement = function (fullName) { for (var stackIndex = this.elementStack.length - 1; stackIndex >= 0; stackIndex--) { var el = this.elementStack[stackIndex]; if (el.name.toLowerCase() == fullName.toLowerCase()) { collection_1.ListWrapper.splice(this.elementStack, stackIndex, this.elementStack.length - stackIndex); return true; } if (!html_tags_1.getHtmlTagDefinition(el.name).closedByParent) { return false; } } return false; }; TreeBuilder.prototype._consumeAttr = function (attrName) { var fullName = mergeNsAndName(attrName.parts[0], attrName.parts[1]); var end = attrName.sourceSpan.end; var value = ''; if (this.peek.type === html_lexer_1.HtmlTokenType.ATTR_VALUE) { var valueToken = this._advance(); value = valueToken.parts[0]; end = valueToken.sourceSpan.end; } return new html_ast_1.HtmlAttrAst(fullName, value, new parse_util_1.ParseSourceSpan(attrName.sourceSpan.start, end)); }; TreeBuilder.prototype._getParentElement = function () { return this.elementStack.length > 0 ? collection_1.ListWrapper.last(this.elementStack) : null; }; TreeBuilder.prototype._addToParent = function (node) { var parent = this._getParentElement(); if (lang_1.isPresent(parent)) { parent.children.push(node); } else { this.rootNodes.push(node); } }; return TreeBuilder; })(); function mergeNsAndName(prefix, localName) { return lang_1.isPresent(prefix) ? "@" + prefix + ":" + localName : localName; } function getElementFullName(prefix, localName, parentElement) { if (lang_1.isBlank(prefix)) { prefix = html_tags_1.getHtmlTagDefinition(localName).implicitNamespacePrefix; if (lang_1.isBlank(prefix) && lang_1.isPresent(parentElement)) { prefix = namespacePrefix(parentElement.name); } } return mergeNsAndName(prefix, localName); } var NS_PREFIX_RE = /^@([^:]+)/g; function namespacePrefix(elementName) { var match = lang_1.RegExpWrapper.firstMatch(NS_PREFIX_RE, elementName); return lang_1.isBlank(match) ? null : match[1]; } //# sourceMappingURL=html_parser.js.map