X Tutup
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions modules/angular2/src/compiler/html_parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ class TreeBuilder {
if (this.peek.type === HtmlTokenType.TAG_OPEN_END_VOID) {
this._advance();
selfClosing = true;
if (namespacePrefix(fullName) == null && !getHtmlTagDefinition(fullName).isVoid) {
this.errors.push(HtmlTreeError.create(
fullName, startTagToken.sourceSpan.start,
`Only void and foreign elements can be self closed "${startTagToken.parts[1]}"`));
}
} else if (this.peek.type === HtmlTokenType.TAG_OPEN_END) {
this._advance();
selfClosing = false;
Expand Down Expand Up @@ -171,17 +176,14 @@ class TreeBuilder {
private _consumeEndTag(endTagToken: HtmlToken) {
var fullName =
getElementFullName(endTagToken.parts[0], endTagToken.parts[1], this._getParentElement());
if (!this._popElement(fullName)) {
let msg;

if (getHtmlTagDefinition(fullName).isVoid) {
msg =
`Void elements do not have end tags (they can not have content) "${endTagToken.parts[1]}"`;
} else {
msg = `Unexpected closing tag "${endTagToken.parts[1]}"`;
}

this.errors.push(HtmlTreeError.create(fullName, endTagToken.sourceSpan.start, msg));
if (getHtmlTagDefinition(fullName).isVoid) {
this.errors.push(
HtmlTreeError.create(fullName, endTagToken.sourceSpan.start,
`Void elements do not have end tags "${endTagToken.parts[1]}"`));
} else if (!this._popElement(fullName)) {
this.errors.push(HtmlTreeError.create(fullName, endTagToken.sourceSpan.start,
`Unexpected closing tag "${endTagToken.parts[1]}"`));
}
}

Expand Down
48 changes: 25 additions & 23 deletions modules/angular2/test/compiler/html_parser_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,6 @@ export function main() {
]);
});

it('should tolerate end tags for void elements when they have no content', () => {
expect(humanizeDom(parser.parse('<input></input>', 'TestComp')))
.toEqual([[HtmlElementAst, 'input', 0]]);
});

it('should support optional end tags', () => {
expect(humanizeDom(parser.parse('<div><p>1<p>2</div>', 'TestComp')))
.toEqual([
Expand Down Expand Up @@ -152,6 +147,16 @@ export function main() {
expect(humanizeDom(parser.parse('<DiV><P></p></dIv>', 'TestComp')))
.toEqual([[HtmlElementAst, 'DiV', 0], [HtmlElementAst, 'P', 1]]);
});

it('should support self closing void elements', () => {
expect(humanizeDom(parser.parse('<input />', 'TestComp')))
.toEqual([[HtmlElementAst, 'input', 0]]);
});

it('should support self closing foreign elements', () => {
expect(humanizeDom(parser.parse('<math />', 'TestComp')))
.toEqual([[HtmlElementAst, '@math:math', 0]]);
});
});

describe('attributes', () => {
Expand Down Expand Up @@ -180,8 +185,8 @@ export function main() {
});

it('should support mamespace', () => {
expect(humanizeDom(parser.parse('<use xlink:href="Port" />', 'TestComp')))
.toEqual([[HtmlElementAst, 'use', 0], [HtmlAttrAst, '@xlink:href', 'Port']]);
expect(humanizeDom(parser.parse('<svg:use xlink:href="Port" />', 'TestComp')))
.toEqual([[HtmlElementAst, '@svg:use', 0], [HtmlAttrAst, '@xlink:href', 'Port']]);
});
});

Expand Down Expand Up @@ -214,29 +219,26 @@ export function main() {
expect(humanizeErrors(errors)).toEqual([['p', 'Unexpected closing tag "p"', '0:5']]);
});

it('should report text content in void elements', () => {
let errors = parser.parse('<input>content</input>', 'TestComp').errors;
it('should report closing tag for void elements', () => {
let errors = parser.parse('<input></input>', 'TestComp').errors;
expect(errors.length).toEqual(1);
expect(humanizeErrors(errors))
.toEqual([
[
'input',
'Void elements do not have end tags (they can not have content) "input"',
'0:14'
]
]);
.toEqual([['input', 'Void elements do not have end tags "input"', '0:7']]);
});

it('should report self closing html element', () => {
let errors = parser.parse('<p />', 'TestComp').errors;
expect(errors.length).toEqual(1);
expect(humanizeErrors(errors))
.toEqual([['p', 'Only void and foreign elements can be self closed "p"', '0:0']]);
});

it('should report html content in void elements', () => {
let errors = parser.parse('<input><p></p></input>', 'TestComp').errors;
it('should report self closing custom element', () => {
let errors = parser.parse('<my-cmp />', 'TestComp').errors;
expect(errors.length).toEqual(1);
expect(humanizeErrors(errors))
.toEqual([
[
'input',
'Void elements do not have end tags (they can not have content) "input"',
'0:14'
]
['my-cmp', 'Only void and foreign elements can be self closed "my-cmp"', '0:0']
]);
});

Expand Down
5 changes: 2 additions & 3 deletions modules/angular2/test/compiler/template_normalizer_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ export function main() {
var template = normalizer.normalizeLoadedTemplate(
dirType,
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}),
'<link href="b" rel="a"></link>', 'package:some/module/');
'<link href="b" rel="a">', 'package:some/module/');
expect(template.styleUrls).toEqual([]);
}));

Expand All @@ -250,8 +250,7 @@ export function main() {
var template = normalizer.normalizeLoadedTemplate(
dirType,
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []}),
'<link href="http://some/external.css" rel="stylesheet"></link>',
'package:some/module/');
'<link href="http://some/external.css" rel="stylesheet">', 'package:some/module/');
expect(template.styleUrls).toEqual([]);
}));

Expand Down
21 changes: 9 additions & 12 deletions modules/angular2/test/compiler/template_parser_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -728,8 +728,8 @@ Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp@0:5 ("<div [
type: new CompileTypeMetadata({name: 'DirB'}),
template: new CompileTemplateMetadata({ngContentSelectors: []})
});
expect(() => parse('<div/>', [dirB, dirA])).toThrowError(`Template parse errors:
More than one component: DirB,DirA ("[ERROR ->]<div/>"): TestComp@0:0`);
expect(() => parse('<div>', [dirB, dirA])).toThrowError(`Template parse errors:
More than one component: DirB,DirA ("[ERROR ->]<div>"): TestComp@0:0`);
});

it('should not allow components or element bindings nor dom events on explicit embedded templates',
Expand Down Expand Up @@ -774,8 +774,7 @@ Property binding a not used by any directive on an embedded template ("[ERROR ->

it('should keep <link rel="stylesheet"> elements if they have an absolute non package: url',
() => {
expect(
humanizeTplAst(parse('<link rel="stylesheet" href="http://someurl"></link>a', [])))
expect(humanizeTplAst(parse('<link rel="stylesheet" href="http://someurl">a', [])))
.toEqual([
[ElementAst, 'link'],
[AttrAst, 'rel', 'stylesheet'],
Expand All @@ -785,22 +784,21 @@ Property binding a not used by any directive on an embedded template ("[ERROR ->
});

it('should keep <link rel="stylesheet"> elements if they have no uri', () => {
expect(humanizeTplAst(parse('<link rel="stylesheet"></link>a', [])))
expect(humanizeTplAst(parse('<link rel="stylesheet">a', [])))
.toEqual([[ElementAst, 'link'], [AttrAst, 'rel', 'stylesheet'], [TextAst, 'a']]);
expect(humanizeTplAst(parse('<link REL="stylesheet"></link>a', [])))
expect(humanizeTplAst(parse('<link REL="stylesheet">a', [])))
.toEqual([[ElementAst, 'link'], [AttrAst, 'REL', 'stylesheet'], [TextAst, 'a']]);
});

it('should ignore <link rel="stylesheet"> elements if they have a relative uri', () => {
expect(humanizeTplAst(parse('<link rel="stylesheet" href="./other.css"></link>a', [])))
expect(humanizeTplAst(parse('<link rel="stylesheet" href="./other.css">a', [])))
.toEqual([[TextAst, 'a']]);
expect(humanizeTplAst(parse('<link rel="stylesheet" HREF="./other.css"></link>a', [])))
expect(humanizeTplAst(parse('<link rel="stylesheet" HREF="./other.css">a', [])))
.toEqual([[TextAst, 'a']]);
});

it('should ignore <link rel="stylesheet"> elements if they have a package: uri', () => {
expect(humanizeTplAst(
parse('<link rel="stylesheet" href="package:somePackage"></link>a', [])))
expect(humanizeTplAst(parse('<link rel="stylesheet" href="package:somePackage">a', [])))
.toEqual([[TextAst, 'a']]);
});

Expand Down Expand Up @@ -835,8 +833,7 @@ Property binding a not used by any directive on an embedded template ("[ERROR ->

it('should ignore <link rel="stylesheet"> elements inside of elements with ng-non-bindable',
() => {
expect(humanizeTplAst(
parse('<div ng-non-bindable><link rel="stylesheet"></link>a</div>', [])))
expect(humanizeTplAst(parse('<div ng-non-bindable><link rel="stylesheet">a</div>', [])))
.toEqual([[ElementAst, 'div'], [AttrAst, 'ng-non-bindable', ''], [TextAst, 'a']]);
});

Expand Down
12 changes: 7 additions & 5 deletions modules/angular2/test/core/linker/integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,10 +578,12 @@ export function main() {
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new ViewMetadata({
template: '<p><child-cmp var-alice/><child-cmp var-bob/></p>',
directives: [ChildComp]
}))
tcb.overrideView(
MyComp, new ViewMetadata({
template:
'<p><child-cmp var-alice></child-cmp><child-cmp var-bob></child-cmp></p>',
directives: [ChildComp]
}))

.createAsync(MyComp)
.then((fixture) => {
Expand Down Expand Up @@ -1007,7 +1009,7 @@ export function main() {
tcb.overrideView(
MyComp, new ViewMetadata({
template:
'<input type="checkbox" listenerprevent></input><input type="checkbox" listenernoprevent></input>',
'<input type="checkbox" listenerprevent><input type="checkbox" listenernoprevent>',
directives: [
DirectiveListeningDomEventPrevent,
DirectiveListeningDomEventNoPrevent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,7 @@ export function main() {
it('should call actions on the element independent of the compilation',
inject([TestComponentBuilder, Renderer, AsyncTestCompleter],
(tcb: TestComponentBuilder, renderer: Renderer, async) => {
tcb.overrideView(MyComp,
new ViewMetadata({template: '<input [title]="y"></input>'}))
tcb.overrideView(MyComp, new ViewMetadata({template: '<input [title]="y">'}))
.createAsync(MyComp)
.then((fixture) => {
var elRef = fixture.debugElement.componentViewChildren[0].elementRef;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,8 @@ void allTests() {
});

it('should include platform directives.', () async {
fooComponentMeta.template = new CompileTemplateMetadata(template: '<bar/>');
fooComponentMeta.template = new CompileTemplateMetadata(
template: '<bar></bar>');
final viewAnnotation = new AnnotationModel()
..name = 'View'
..isView = true;
Expand All @@ -370,7 +371,8 @@ void allTests() {
});

it('should include platform directives when it it a list.', () async {
fooComponentMeta.template = new CompileTemplateMetadata(template: '<bar/>');
fooComponentMeta.template = new CompileTemplateMetadata(
template: '<bar></bar>');
final viewAnnotation = new AnnotationModel()
..name = 'View'
..isView = true;
Expand Down
X Tutup