fix(HtmlParser): consider <ng-container> when adding required parents

This commit is contained in:
Victor Berchet
2016-06-15 09:37:33 -07:00
parent 9cbd8f7afc
commit 9ba400d7d5
5 changed files with 94 additions and 30 deletions

View File

@ -1,11 +1,7 @@
import {Injectable} from '@angular/core';
import {isPresent, isBlank,} from '../src/facade/lang';
import {ListWrapper} from '../src/facade/collection';
import {HtmlAst, HtmlAttrAst, HtmlTextAst, HtmlCommentAst, HtmlElementAst, HtmlExpansionAst, HtmlExpansionCaseAst} from './html_ast';
import {HtmlToken, HtmlTokenType, tokenizeHtml} from './html_lexer';
import {ParseError, ParseSourceSpan} from './parse_util';
import {getHtmlTagDefinition, getNsPrefix, mergeNsAndName} from './html_tags';
@ -267,18 +263,17 @@ class TreeBuilder {
}
}
var tagDef = getHtmlTagDefinition(el.name);
var parentEl = this._getParentElement();
if (tagDef.requireExtraParent(isPresent(parentEl) ? parentEl.name : null)) {
const tagDef = getHtmlTagDefinition(el.name);
const {parent, container} = this._getParentElementSkippingContainers();
if (tagDef.requireExtraParent(isPresent(parent) ? parent.name : null)) {
var newParent = new HtmlElementAst(
tagDef.parentToAdd, [], [el], el.sourceSpan, el.startSourceSpan, el.endSourceSpan);
this._addToParent(newParent);
this.elementStack.push(newParent);
this.elementStack.push(el);
} else {
this._addToParent(el);
this.elementStack.push(el);
tagDef.parentToAdd, [], [], el.sourceSpan, el.startSourceSpan, el.endSourceSpan);
this._insertBeforeContainer(parent, container, newParent);
}
this._addToParent(el);
this.elementStack.push(el);
}
private _consumeEndTag(endTagToken: HtmlToken) {
@ -330,6 +325,25 @@ class TreeBuilder {
return this.elementStack.length > 0 ? ListWrapper.last(this.elementStack) : null;
}
/**
* Returns the parent in the DOM and the container.
*
* `<ng-container>` elements are skipped as they are not rendered as DOM element.
*/
private _getParentElementSkippingContainers():
{parent: HtmlElementAst, container: HtmlElementAst} {
let container: HtmlElementAst = null;
for (let i = this.elementStack.length - 1; i >= 0; i--) {
if (this.elementStack[i].name !== 'ng-container') {
return { parent: this.elementStack[i], container }
}
container = this.elementStack[i];
}
return {parent: ListWrapper.last(this.elementStack), container};
}
private _addToParent(node: HtmlAst) {
var parent = this._getParentElement();
if (isPresent(parent)) {
@ -338,6 +352,31 @@ class TreeBuilder {
this.rootNodes.push(node);
}
}
/**
* Insert a node between the parent and the container.
* When no container is given, the node is appended as a child of the parent.
* Also updates the element stack accordingly.
*
* @internal
*/
private _insertBeforeContainer(
parent: HtmlElementAst, container: HtmlElementAst, node: HtmlElementAst) {
if (!container) {
this._addToParent(node);
this.elementStack.push(node);
} else {
if (parent) {
// replace the container with the new node in the children
let index = parent.children.indexOf(container);
parent.children[index] = node;
} else {
this.rootNodes.push(node);
}
node.children.push(container);
this.elementStack.splice(this.elementStack.indexOf(container), 0, node);
}
}
}
function getElementFullName(

View File

@ -1,21 +1,15 @@
import {StringMapWrapper} from './facade/collection';
import {IS_DART, Math, StringWrapper, isArray, isBlank, isPrimitive, isStrictStringMap} from './facade/lang';
import {IS_DART, StringWrapper, isArray, isBlank, isPrimitive, isStrictStringMap} from './facade/lang';
export var MODULE_SUFFIX = IS_DART ? '.dart' : '';
var CAMEL_CASE_REGEXP = /([A-Z])/g;
var DASH_CASE_REGEXP = /-([a-z])/g;
export function camelCaseToDashCase(input: string): string {
return StringWrapper.replaceAllMapped(
input, CAMEL_CASE_REGEXP, (m: string[]) => { return '-' + m[1].toLowerCase(); });
}
export function dashCaseToCamelCase(input: string): string {
return StringWrapper.replaceAllMapped(
input, DASH_CASE_REGEXP, (m: string[]) => { return m[1].toUpperCase(); });
}
export function splitAtColon(input: string, defaultValues: string[]): string[] {
var parts = StringWrapper.split(input.trim(), /\s*:\s*/g);
if (parts.length > 1) {