Permalink
Browse files

Add regex filter, tests, clean up code more. Fixes #66

  • Loading branch information...
1 parent 9960cd2 commit 262ef7e722e545ff1b2501779b7e9cfb98789b8e @tmcw tmcw committed May 8, 2012
View
@@ -438,16 +438,15 @@ carto.Parser = function Parser(env) {
// "milky way" 'he\'s the one!'
//
quoted: function() {
- var str;
if (input.charAt(i) !== '"' && input.charAt(i) !== "'") return;
-
- if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) {
+ var str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/);
+ if (str) {
return new tree.Quoted(str[0], str[1] || str[2]);
}
},
comparison: function() {
- var str = $(/^=|!=|<=|>=|<|>/);
+ var str = $(/^=~|=|!=|<=|>=|<|>/);
if (str) {
return str;
}
@@ -25,9 +25,15 @@ tree.Directive.prototype = {
env.frames.shift();
return this;
},
- variable: function(name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) },
- find: function() { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) },
- rulesets: function() { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }
+ variable: function(name) {
+ return tree.Ruleset.prototype.variable.call(this.ruleset, name);
+ },
+ find: function() {
+ return tree.Ruleset.prototype.find.apply(this.ruleset, arguments);
+ },
+ rulesets: function() {
+ return tree.Ruleset.prototype.rulesets.apply(this.ruleset);
+ }
};
})(require('../tree'));
@@ -1,6 +1,8 @@
(function(tree) {
-tree.Expression = function Expression(value) { this.value = value };
+tree.Expression = function Expression(value) {
+ this.value = value;
+};
tree.Expression.prototype = {
eval: function(env) {
if (this.value.length > 1) {
View
@@ -19,26 +19,27 @@ tree.Filter = function Filter(key, op, val, index, filename) {
this.val = val;
}
- if (this.op !== '=' && this.op !== '!=') {
+ if (ops[this.op][1]) {
this.val = 1 * this.val;
}
this.id = this.key + this.op + this.val;
};
-// XML-safe versions of comparators
-var opXML = {
- '<': '&lt;',
- '>': '&gt;',
- '=': '=',
- '!=': '!=',
- '<=': '&lt;=',
- '>=': '&gt;='
+// xmlsafe, numeric, suffix
+var ops = {
+ '<': [' &lt; ', true],
+ '>': [' &gt; ', true],
+ '=': [' = ', false],
+ '!=': [' != ', false],
+ '<=': [' &lt;= ', true],
+ '>=': [' &gt;= ', true],
+ '=~': ['.match(', false, ')']
};
tree.Filter.prototype.toXML = function(env) {
- if (this.op !== '=' && this.op !== '!=' && isNaN(this.val)) {
+ if (ops[this.op][1] && isNaN(this.val)) {
env.error({
message: 'Cannot use operator "' + this.op + '" with value ' + this.val,
index: this.index,
@@ -50,7 +51,7 @@ tree.Filter.prototype.toXML = function(env) {
if (this._key) var key = this._key.toString(false);
if (this._val) var val = this._val.toString(this._val.is == 'string');
- return '[' + (key || this.key) + '] ' + opXML[this.op] + ' ' + (val || this.val);
+ return '[' + (key || this.key) + ']' + ops[this.op][0] + '' + (val || this.val) + (ops[this.op][2] || '');
};
tree.Filter.prototype.toString = function() {
@@ -66,12 +66,14 @@ Object.defineProperty(tree.Filterset.prototype, 'cloneWith', {
// We can add the rules that are already present without going through the
// add function as a Filterset is always in it's simplest canonical form.
- for (var id in this)
+ for (var id in this) {
clone[id] = this[id];
+ }
// Only add new filters that actually change the filter.
- while (id = additions.shift())
+ while (id = additions.shift()) {
clone.add(id);
+ }
return clone;
}
@@ -98,12 +100,10 @@ Object.defineProperty(tree.Filterset.prototype, 'addable', {
case '!=':
if (key + '=' in this) return (this[key + '='].val == value) ? false : null;
if (key + '!=' + value in this) return null;
-
if (key + '>' in this && this[key + '>'].val >= value) return null;
if (key + '<' in this && this[key + '<'].val <= value) return null;
if (key + '>=' in this && this[key + '>='].val > value) return null;
if (key + '<=' in this && this[key + '<='].val < value) return null;
-
return true;
case '>':
@@ -151,27 +151,40 @@ Object.defineProperty(tree.Filterset.prototype, 'add', {
switch (filter.op) {
case '=':
- for (var id in this)
- if (this[id].key == key)
+ for (var id in this) {
+ if (this[id].key == key) {
delete this[id];
+ }
+ }
this[key + '='] = filter;
break;
case '!=':
this[key + '!=' + filter.val] = filter;
break;
+ case '=~':
+ this[key + '=~' + filter.val] = filter;
+ break;
+
case '>':
- for (var id in this)
- if (this[id].key == key && this[id].val <= filter.val)
+ // If there are other filters that are also >
+ // but are less than this one, they don't matter, so
+ // remove them.
+ for (var id in this) {
+ if (this[id].key == key && this[id].val <= filter.val) {
delete this[id];
+ }
+ }
this[key + '>'] = filter;
break;
case '>=':
- for (var id in this)
- if (this[id].key == key && this[id].val < filter.val)
+ for (var id in this) {
+ if (this[id].key == key && this[id].val < filter.val) {
delete this[id];
+ }
+ }
if (key + '!=' + filter.val in this) {
delete this[key + '!=' + filter.val];
filter.op = '>';
@@ -183,16 +196,20 @@ Object.defineProperty(tree.Filterset.prototype, 'add', {
break;
case '<':
- for (var id in this)
- if (this[id].key == key && this[id].val >= filter.val)
+ for (var id in this) {
+ if (this[id].key == key && this[id].val >= filter.val) {
delete this[id];
+ }
+ }
this[key + '<'] = filter;
break;
case '<=':
- for (var id in this)
- if (this[id].key == key && this[id].val > filter.val)
+ for (var id in this) {
+ if (this[id].key == key && this[id].val > filter.val) {
delete this[id];
+ }
+ }
if (key + '!=' + filter.val in this) {
delete this[key + '!=' + filter.val];
filter.op = '<';
View
@@ -26,13 +26,13 @@ tree.FontSet = function FontSet(env, fonts) {
};
tree.FontSet.prototype.toXML = function(env) {
- return '<FontSet name="'
- + this.name
- + '">\n'
- + this.fonts.map(function(f) {
+ return '<FontSet name="' +
+ this.name +
+ '">\n' +
+ this.fonts.map(function(f) {
return ' <Font face-name="' + f +'"/>';
- }).join('\n')
- + '\n</FontSet>'
+ }).join('\n') +
+ '\n</FontSet>';
};
})(require('../tree'));
@@ -10,8 +10,8 @@ tree.Keyword = function Keyword(value) {
this.is = special[value] ? special[value] : 'keyword';
};
tree.Keyword.prototype = {
- eval: function() { return this },
- toString: function() { return this.value }
+ eval: function() { return this; },
+ toString: function() { return this.value; }
};
})(require('../tree'));
View
@@ -4,11 +4,11 @@ var tree = require('../tree');
// and stores them as bit-sequences so that they can be combined,
// inverted, and compared quickly.
tree.Zoom = function(op, value, index) {
- value = parseInt(value);
+ value = parseInt(value, 10);
if (value > tree.Zoom.maxZoom || value < 0) {
throw {
- message: 'Only zoom levels between 0 and '
- + tree.Zoom.maxZoom + ' supported.',
+ message: 'Only zoom levels between 0 and ' +
+ tree.Zoom.maxZoom + ' supported.',
index: index
};
}
@@ -81,14 +81,14 @@ tree.Zoom.toXML = function(zoom) {
var start = null, end = null;
for (var i = 0; i <= tree.Zoom.maxZoom; i++) {
if (zoom & (1 << i)) {
- if (start == null) start = i;
+ if (start === null) start = i;
end = i;
}
}
- if (start > 0) conditions.push(' <MaxScaleDenominator>'
- + tree.Zoom.ranges[start] + '</MaxScaleDenominator>\n');
- if (end < 22) conditions.push(' <MinScaleDenominator>'
- + tree.Zoom.ranges[end + 1] + '</MinScaleDenominator>\n');
+ if (start > 0) conditions.push(' <MaxScaleDenominator>' +
+ tree.Zoom.ranges[start] + '</MaxScaleDenominator>\n');
+ if (end < 22) conditions.push(' <MinScaleDenominator>' +
+ tree.Zoom.ranges[end + 1] + '</MinScaleDenominator>\n');
}
return conditions;
};
View
@@ -0,0 +1,14 @@
+{
+ "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over",
+ "Stylesheet": [
+ "regex.mss"
+ ],
+ "Layer": [{
+ "name": "world",
+ "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over",
+ "Datasource": {
+ "file": "http://tilemill-data.s3.amazonaws.com/test_data/shape_demo.zip",
+ "type": "shape"
+ }
+ }]
+}
View
@@ -0,0 +1,5 @@
+#world[ISO =~ "U*"] {
+ polygon-fill: #FFF;
+ line-color:#F00;
+ line-width: 0.5;
+}
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE Map[]>
+<Map srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over" maximum-extent="-20037508.34,-20037508.34,20037508.34,20037508.34">
+
+
+<Style name="world" filter-mode="first">
+ <Rule>
+ <Filter>([ISO].match('U*'))</Filter>
+ <PolygonSymbolizer fill="#ffffff" />
+ <LineSymbolizer stroke="#ff0000" stroke-width="0.5" />
+ </Rule>
+</Style>
+<Layer name="world"
+ srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over">
+ <StyleName>world</StyleName>
+ <Datasource>
+ <Parameter name="file"><![CDATA[[absolute path]]]></Parameter>
+ <Parameter name="type"><![CDATA[shape]]></Parameter>
+ </Datasource>
+ </Layer>
+
+</Map>

0 comments on commit 262ef7e

Please sign in to comment.