fix(compiler): fix for element needing implicit parent placed in top-level ng-container

fixes #18314
This commit is contained in:
Victor Berchet 2017-07-26 14:53:59 -07:00 committed by Alex Rickabaugh
parent ebef5e697a
commit 381471d338
3 changed files with 285 additions and 281 deletions

View File

@ -230,14 +230,11 @@ class _TreeBuilder {
}
private _closeVoidElement(): void {
if (this._elementStack.length > 0) {
const el = this._elementStack[this._elementStack.length - 1];
if (this.getTagDefinition(el.name).isVoid) {
const el = this._getParentElement();
if (el && this.getTagDefinition(el.name).isVoid) {
this._elementStack.pop();
}
}
}
private _consumeStartTag(startTagToken: lex.Token) {
const prefix = startTagToken.parts[0];
@ -274,12 +271,11 @@ class _TreeBuilder {
}
private _pushElement(el: html.Element) {
if (this._elementStack.length > 0) {
const parentEl = this._elementStack[this._elementStack.length - 1];
if (this.getTagDefinition(parentEl.name).isClosedByChild(el.name)) {
const parentEl = this._getParentElement();
if (parentEl && this.getTagDefinition(parentEl.name).isClosedByChild(el.name)) {
this._elementStack.pop();
}
}
const tagDef = this.getTagDefinition(el.name);
const {parent, container} = this._getParentElementSkippingContainers();
@ -353,7 +349,7 @@ class _TreeBuilder {
* `<ng-container>` elements are skipped as they are not rendered as DOM element.
*/
private _getParentElementSkippingContainers():
{parent: html.Element, container: html.Element|null} {
{parent: html.Element | null, container: html.Element|null} {
let container: html.Element|null = null;
for (let i = this._elementStack.length - 1; i >= 0; i--) {
@ -363,7 +359,7 @@ class _TreeBuilder {
container = this._elementStack[i];
}
return {parent: this._elementStack[this._elementStack.length - 1], container};
return {parent: null, container};
}
private _addToParent(node: html.Node) {

View File

@ -56,24 +56,22 @@ export function isNgTemplate(tagName: string): boolean {
return splitNsName(tagName)[1] === 'ng-template';
}
export function getNsPrefix(fullName: string): string
export function getNsPrefix(fullName: string): string;
export function getNsPrefix(fullName: null): null;
export function getNsPrefix(fullName: string | null): string |
null {
export function getNsPrefix(fullName: string | null): string|null {
return fullName === null ? null : splitNsName(fullName)[0];
}
}
export function mergeNsAndName(prefix: string, localName: string):
string {
export function mergeNsAndName(prefix: string, localName: string): string {
return prefix ? `:${prefix}:${localName}` : localName;
}
}
// see http://www.w3.org/TR/html51/syntax.html#named-character-references
// see https://html.spec.whatwg.org/multipage/entities.json
// This list is not exhaustive to keep the compiler footprint low.
// The `&#123;` / `&#x1ab;` syntax should be used when the named character reference does not
// exist.
export const NAMED_ENTITIES: {[k: string]: string} = {
// see http://www.w3.org/TR/html51/syntax.html#named-character-references
// see https://html.spec.whatwg.org/multipage/entities.json
// This list is not exhaustive to keep the compiler footprint low.
// The `&#123;` / `&#x1ab;` syntax should be used when the named character reference does not
// exist.
export const NAMED_ENTITIES: {[k: string]: string} = {
'Aacute': '\u00C1',
'aacute': '\u00E1',
'Acirc': '\u00C2',
@ -326,4 +324,4 @@ export function getNsPrefix(fullName: null): null;
'zeta': '\u03B6',
'zwj': '\u200D',
'zwnj': '\u200C',
};
};

View File

@ -152,6 +152,16 @@ export function main() {
]);
});
it('should append the required parent considering top level ng-container', () => {
expect(humanizeDom(
parser.parse('<ng-container><tr></tr></ng-container><p></p>', 'TestComp')))
.toEqual([
[html.Element, 'ng-container', 0],
[html.Element, 'tr', 1],
[html.Element, 'p', 0],
]);
});
it('should special case ng-container when adding a required parent', () => {
expect(humanizeDom(parser.parse(
'<table><thead><ng-container><tr></tr></ng-container></thead></table>',