Fixes #35 Add support for <compiler-options> tag

This commit is contained in:
Phillip Gates-Idem 2015-02-17 18:57:00 -05:00
parent d2956f1787
commit c9b062da45
8 changed files with 87 additions and 23 deletions

View File

@ -1154,7 +1154,17 @@ World</textarea</div>
The following options are available to control whitespace removal:
__Option 1)__ Disable whitespace removal using the `c-whitespace` attribute:
__Option 1)__ Disable whitespace removal using the `compiler-options` tag:
```html
<compiler-options whitespace="preserve" />
<div>
<img src="foo.jpg">
<img src="foo.jpg">
</div>
```
__Option 2)__ Disable whitespace removal using the `c-whitespace` attribute:
```html
<div c-whitespace="preserve">
@ -1163,13 +1173,13 @@ __Option 1)__ Disable whitespace removal using the `c-whitespace` attribute:
</div>
```
__Option 2)__ Disable _all_ whitespace removal by changing a compiler option
__Option 3)__ Disable _all_ whitespace removal by changing a compiler option
```javascript
require('marko/compiler').defaultOptions.preserveWhitespace = true;
```
__Option 3)__ Control whitespace removal for specific tags
__Option 4)__ Control whitespace removal for specific tags
```javascript
require('marko/compiler').defaultOptions.preserveWhitespace = {
@ -1179,7 +1189,7 @@ require('marko/compiler').defaultOptions.preserveWhitespace = {
};
```
__Option 4)__ Configured a custom tag to preserve whitespace
__Option 5)__ Configured a custom tag to preserve whitespace
Adding the `"preserve-whitespace": true` property to a tag definition will result in the Marko compiler preserving whitespace wherever that tag is encountered in a template.

View File

@ -44,8 +44,17 @@ function ParseTreeBuilder(taglibs) {
this.charProps = null;
this.nsStack = [];
this.compilerOptions = undefined;
}
var COMPILER_ATTRIBUTE_HANDLERS = {
'whitespace': function(attr, compilerOptions) {
if (attr.value === 'preserve') {
compilerOptions.preserveWhitespace = true;
}
}
};
ParseTreeBuilder.prototype = {
createPos: function(line, column) {
if (arguments.length === 1) {
@ -76,6 +85,10 @@ ParseTreeBuilder.prototype = {
this.parentNode = null;
this.nsStack = [];
// Put the compiler options into the rootNode so that
// TemplateCompiler has access to these
rootNode.compilerOptions = this.compilerOptions;
return rootNode;
},
@ -94,6 +107,24 @@ ParseTreeBuilder.prototype = {
},
handleStartElement: function(el, attributes) {
var self = this;
if (el.localName === 'compiler-options') {
attributes.forEach(function (attr) {
var attrLocalName = attr.localName;
var attrPrefix = attr.prefix;
var handler;
if (attrPrefix || ((handler = COMPILER_ATTRIBUTE_HANDLERS[attrLocalName]) === undefined)) {
var attrName = attrPrefix;
attrName = (attrName) ? attrName + ':' + attrLocalName : attrLocalName;
throw new Error('Invalid Marko compiler option: ' + attrName + ', Allowed: ' + Object.keys(COMPILER_ATTRIBUTE_HANDLERS));
}
handler(attr, self.compilerOptions || (self.compilerOptions = {}));
}, this);
return;
}
this.prevTextNode = null;
var namespaceMappings = this.nsStack.length ? Object.create(this.nsStack[this.nsStack.length-1]) : {};
@ -153,7 +184,11 @@ ParseTreeBuilder.prototype = {
this.parentNode = elementNode;
},
handleEndElement: function() {
handleEndElement: function(elementName) {
if (elementName === 'compiler-options') {
return;
}
this.prevTextNode = null;
this.parentNode = this.parentNode.parentNode;
this.nsStack.pop();

View File

@ -89,7 +89,7 @@ ParseTreeBuilderHtml.prototype = {
_this.handleCharacters(decodeEntities(text));
},
onclosetag: function(name){
_this.handleEndElement();
_this.handleEndElement(name);
}
}, parserOptions);
parser.write(src);

View File

@ -74,8 +74,8 @@ ParseTreeBuilderXml.prototype = {
onclosetag: function () {
_this.handleEndElement();
onclosetag: function (name) {
_this.handleEndElement(name);
},
oncomment: function (comment) {

View File

@ -25,6 +25,7 @@ var ok = require('assert').ok;
var attributeParser = require('./attribute-parser');
var expressionParser = require('./expression-parser');
var inherit = require('raptor-util/inherit');
var extend = require('raptor-util/extend');
var _Node = require('./Node');
var ElementNode = require('./ElementNode');
var TextNode = require('./TextNode');
@ -115,6 +116,12 @@ TemplateCompiler.prototype = {
* First build the parse tree for the tempate
*/
rootNode = parser.parse(src, filePath, this.taglibs);
if (rootNode.compilerOptions) {
// compiler options were set in the template so use those here
this.options = extend(extend({}, this.options), rootNode.compilerOptions);
}
//Build a parse tree from the input XML
templateBuilder = new TemplateBuilder(this, filePath, rootNode);
//The templateBuilder object is need to manage the compiled JavaScript output

View File

@ -147,6 +147,10 @@ describe('marko/marko' , function() {
testRender("test-project/html-templates/whitespace3.marko", {}, done);
});
it("should preserve whitespace using <compiler-options>", function(done) {
testRender("test-project/html-templates/whitespace4.marko", {}, done);
});
it("should handle whitespace correctly for mixed text and element children", function(done) {
testRender("test-project/html-templates/whitespace-inline-elements.marko", {}, done);
});

View File

@ -0,0 +1,4 @@
<compiler-options whitespace="preserve" />
A
B
C

View File

@ -0,0 +1,4 @@
A
B
C