diff --git a/hsp/compiler/parser.js b/hsp/compiler/parser.js
index 657ba23..5d4e629 100644
--- a/hsp/compiler/parser.js
+++ b/hsp/compiler/parser.js
@@ -6,6 +6,30 @@ var blockParser = PEG.buildParser(grammar, {
trackLineAndColumn : true
});
+//http://www.w3.org/TR/html-markup/syntax.html#syntax-elements
+var VOID_HTML_ELEMENTS = {
+ "area": true,
+ "base": true,
+ "br": true,
+ "col": true,
+ "command": true,
+ "embed": true,
+ "hr": true,
+ "img": true,
+ "input": true,
+ "keygen": true,
+ "link": true,
+ "meta": true,
+ "param": true,
+ "source": true,
+ "track": true,
+ "wbr": true
+};
+
+function isVoidElement(elName) {
+ return VOID_HTML_ELEMENTS.hasOwnProperty(elName.toLowerCase());
+}
+
/**
* Return the list of instruction blocks that compose a template file at this stage the template AST is not complete -
* cf. parse() function to get the complete syntax tree Note: this function is exposed for unit test purposes and should
@@ -403,6 +427,10 @@ var SyntaxTree = klass({
* Element block management
*/
_element : function (idx, blocks, out) {
+ var b = blocks[idx];
+ if (isVoidElement(b.name)) {
+ b.closed=true;
+ }
return this._elementOrComponent("element", idx, blocks, out);
},
@@ -600,7 +628,11 @@ var SyntaxTree = klass({
_endelement : function (idx, blocks, out) {
// only called in case of error
var b = blocks[idx], nm = b.name;
- this._logError("End element " + nm + "> does not match any <" + nm + "> element", b);
+ if (isVoidElement(nm)) {
+ this._logError("The end element " + nm + "> was rejected as <" + nm + "> is a void HTML element and can't have a closing element", b);
+ } else {
+ this._logError("End element " + nm + "> does not match any <" + nm + "> element", b);
+ }
return idx;
},
diff --git a/public/test/compiler/errsamples/voidelement.txt b/public/test/compiler/errsamples/voidelement.txt
new file mode 100644
index 0000000..c0d95b0
--- /dev/null
+++ b/public/test/compiler/errsamples/voidelement.txt
@@ -0,0 +1,13 @@
+##### Template:
+# template test
+ Hello
World
+# /template
+
+##### Errors:
+[
+ {
+ "description": "The end element was rejected as
is a void HTML element and can't have a closing element",
+ "line": 2,
+ "column": 19
+ }
+]
diff --git a/public/test/compiler/errtests.js b/public/test/compiler/errtests.js
index 3ca9f40..552dc0b 100644
--- a/public/test/compiler/errtests.js
+++ b/public/test/compiler/errtests.js
@@ -23,8 +23,8 @@ describe('Template compilation errors: ', function () {
var samples = ["text1", "text2", "text3", "if1", "if2", "if3", "if4", "if5", "if6", "if7", "foreach1", "foreach2",
"foreach3", "element1", "element2", "element3", "element4", "element5", "element6", "element7", "element8",
"insert", "template1", "template2", "template3", "template4", "template5", "template6", "template7",
- "jsexpression1", "jsexpression2", "component1", "component2"];
- //samples=["component2"];
+ "jsexpression1", "jsexpression2", "component1", "component2", "voidelement"];
+ //samples=["voidelement"];
for (var i = 0, sz = samples.length; sz > i; i++) {
// create one test for each sample
it('tests error sample ('+samples[i]+')', testFn.bind({
diff --git a/public/test/compiler/samples/voidelement.txt b/public/test/compiler/samples/voidelement.txt
new file mode 100644
index 0000000..ab7ff71
--- /dev/null
+++ b/public/test/compiler/samples/voidelement.txt
@@ -0,0 +1,75 @@
+##### Template:
+# template test
+ Hello
World
+
+