Document tree items as well, fix up a few of their documentations

This commit is contained in:
Tom MacWright 2011-02-02 16:47:33 -05:00
parent 3a57822e7d
commit 90fdaab9d7
5 changed files with 51 additions and 32 deletions

View File

@ -11,6 +11,6 @@ test:
endif endif
doc: doc:
docco lib/mess/*.js docco lib/mess/*.js lib/mess/tree/*.js
.PHONY: test .PHONY: test

View File

@ -12,11 +12,9 @@ tree.Definition.prototype.clone = function() {
return obj; return obj;
}; };
/** // Return a copy of this ruleset with only
* Return a copy of this ruleset with only // rules related to a specific symbolizer, but otherwise identical
* rules related to a specific symbolizer, but otherwise identical // selectors.
* selectors.
*/
tree.Definition.prototype.filterSymbolizer = function(symbolizer) { tree.Definition.prototype.filterSymbolizer = function(symbolizer) {
var newDefinition = this.clone(); var newDefinition = this.clone();
newDefinition.rules = newDefinition.rules.filter(function(rule) { newDefinition.rules = newDefinition.rules.filter(function(rule) {
@ -25,6 +23,9 @@ tree.Definition.prototype.filterSymbolizer = function(symbolizer) {
return newDefinition; return newDefinition;
}; };
// Get a list of all of the symbolizer types
// that this definition will affect as a result of
// its rules.
tree.Definition.prototype.symbolizers = function() { tree.Definition.prototype.symbolizers = function() {
// reduce used to make the result of this // reduce used to make the result of this
// an array of unique values. // an array of unique values.
@ -36,10 +37,8 @@ tree.Definition.prototype.symbolizers = function() {
}, []); }, []);
}; };
/** // Find a rule by name within this ruleset,
* Find a rule by name within this ruleset, // returning it if possible. Otherwise not returning.
* returning it if possible. Otherwise not returning.
*/
tree.Definition.prototype.hasRule = function(name) { tree.Definition.prototype.hasRule = function(name) {
this.rules_cache = (!this.dirty && this.rules_cache) this.rules_cache = (!this.dirty && this.rules_cache)
? this.rules_cache ? this.rules_cache
@ -50,6 +49,9 @@ tree.Definition.prototype.hasRule = function(name) {
return this.rules_cache[name]; return this.rules_cache[name];
}; };
// Take all of the rules from a given definition that
// this definition doesn't have already, and add them to this
// definition.
tree.Definition.prototype.inheritFrom = function(definition) { tree.Definition.prototype.inheritFrom = function(definition) {
for (var i = 0; i < definition.rules.length; i++) { for (var i = 0; i < definition.rules.length; i++) {
if (!this.hasRule(definition.rules[i].name)) { if (!this.hasRule(definition.rules[i].name)) {
@ -59,6 +61,9 @@ tree.Definition.prototype.inheritFrom = function(definition) {
} }
}; };
// Get all of the unique rules in this definition, in
// specificity order. Mapnik doesn't allow multiple attributes
// in Symbolizers.
tree.Definition.prototype.unique_rules = function() { tree.Definition.prototype.unique_rules = function() {
if (this.unique_rules_cache) return this.unique_rules_cache; if (this.unique_rules_cache) return this.unique_rules_cache;
var rules = {}, var rules = {},
@ -73,6 +78,7 @@ tree.Definition.prototype.unique_rules = function() {
}; };
tree.Definition.prototype.toXML = function(env) { tree.Definition.prototype.toXML = function(env) {
// Return a cached compilation if one is available.
if (this._xml) return this._xml; if (this._xml) return this._xml;
var sym = this.symbolizers(); var sym = this.symbolizers();
@ -86,17 +92,25 @@ tree.Definition.prototype.toXML = function(env) {
} }
if (sym) { if (sym) {
// Some Mapnik symbolizers, like TextSymbolizer, don't
// have defaults for all properties and will fail if they
// aren't given. Thus, at the last minute check that these
// are satisfied.
if (reqfail = tree.Reference.requiredProperties( if (reqfail = tree.Reference.requiredProperties(
sym, sym,
this.unique_rules())) { this.unique_rules())) {
env.error({ env.error({
message: reqfail, message: reqfail,
index: this.unique_rules()[0] && this.unique_rules()[0].index, index: this.unique_rules()[0] &&
index: this.unique_rules()[0] && this.unique_rules()[0].filename this.unique_rules()[0].index,
index: this.unique_rules()[0] &&
this.unique_rules()[0].filename
}); });
} }
} }
// Come up with a symbolizer name based on the name from
// Reference.
var symname = sym ? sym.charAt(0).toUpperCase() var symname = sym ? sym.charAt(0).toUpperCase()
+ sym.slice(1).replace(/\-./, function(str) { + sym.slice(1).replace(/\-./, function(str) {
return str[1].toUpperCase(); return str[1].toUpperCase();

View File

@ -1,13 +1,12 @@
(function(tree) { (function(tree) {
// An element is an id or class selector
tree.Element = function Element(value) { tree.Element = function Element(value) {
this.value = value.trim(); this.value = value.trim();
}; };
/** // Determine the 'specificity matrix' of this
* Determine the 'specificity matrix' of this // specific selector
* specific selector
*/
tree.Element.prototype.specificity = function() { tree.Element.prototype.specificity = function() {
return [ return [
(this.value[0] == '#') ? 1 : 0, // a (this.value[0] == '#') ? 1 : 0, // a
@ -19,14 +18,12 @@ tree.Element.prototype.toString = function() {
return this.value; return this.value;
}; };
/** // Determine whether this element matches an id or classes.
* Determine whether this element matches an id or classes. // An element is a single id or class, or check whether the given
* An element is a single id or class, or check whether the given // array of classes contains this, or the id is equal to this.
* array of classes contains this, or the id is equal to this. //
* // Takes a plain string for id and plain strings in the array of
* Takes a plain string for id and plain strings in the array of // classes.
* classes.
*/
tree.Element.prototype.matches = function(id, classes) { tree.Element.prototype.matches = function(id, classes) {
return (classes.indexOf(this.value.replace(/^\./, '')) !== -1) || return (classes.indexOf(this.value.replace(/^\./, '')) !== -1) ||
(this.value.replace(/^#/, '') == id); (this.value.replace(/^#/, '') == id);

View File

@ -17,6 +17,7 @@ tree.Filter = function Filter(key, op, val, index) {
}; };
// XML-safe versions of comparators
var opXML = { var opXML = {
'<': '&lt;', '<': '&lt;',
'>': '&gt;', '>': '&gt;',
@ -26,6 +27,7 @@ var opXML = {
'>=': '&gt;=' '>=': '&gt;='
}; };
// inverses of comparators
var opNegate = { var opNegate = {
'<': '>=', '<': '>=',
'<=': '>', '<=': '>',
@ -49,10 +51,8 @@ tree.Filter.prototype.toString = function() {
return '[' + this.id + ']'; return '[' + this.id + ']';
}; };
/** // Negate this filter: warning - this changes
* Negate this filter: warning - this changes // the filter itself.
* the filter itself.
*/
tree.Filter.prototype.negate = function() { tree.Filter.prototype.negate = function() {
return new tree.Filter(this.key, opNegate[this.op], this.val); return new tree.Filter(this.key, opNegate[this.op], this.val);
}; };
@ -245,6 +245,8 @@ tree.Filter.simplify = function(filters) {
return filters; return filters;
}; };
// Test two rules to decide whether one can be merged into the other.
// returns the rule that the other rule can be merged into.
tree.Filter.mergable = function(f1, f2) { tree.Filter.mergable = function(f1, f2) {
var filters1 = Object.keys(f1); var filters1 = Object.keys(f1);
var filters2 = Object.keys(f2); var filters2 = Object.keys(f2);

View File

@ -1,10 +1,14 @@
var tree = require('mess/tree'); var tree = require('mess/tree');
// Storage for zoom ranges. Only supports continuous ranges,
// and stores them as bit-sequences so that they can be combined,
// inverted, and compared quickly.
tree.Zoom = function(op, value, index) { tree.Zoom = function(op, value, index) {
value = parseInt(value); value = parseInt(value);
if (value > tree.Zoom.maxZoom || value < 0) { if (value > tree.Zoom.maxZoom || value < 0) {
throw { 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 index: index
}; };
} }
@ -57,7 +61,7 @@ tree.Zoom.ranges = {
23: 50 23: 50
}; };
// Only works for single range zooms. [XXX....XXXXX.........] is invalid. // Only works for single range zooms. `[XXX....XXXXX.........]` is invalid.
tree.Zoom.toXML = function(zoom) { tree.Zoom.toXML = function(zoom) {
var conditions = []; var conditions = [];
if (zoom != tree.Zoom.all) { if (zoom != tree.Zoom.all) {
@ -68,8 +72,10 @@ tree.Zoom.toXML = function(zoom) {
end = i; end = i;
} }
} }
if (start > 0) conditions.push('<MaxScaleDenominator>' + tree.Zoom.ranges[start] + '</MaxScaleDenominator>'); if (start > 0) conditions.push('<MaxScaleDenominator>'
if (end < 22) conditions.push('<MinScaleDenominator>' + tree.Zoom.ranges[end + 1] + '</MinScaleDenominator>'); + tree.Zoom.ranges[start] + '</MaxScaleDenominator>');
if (end < 22) conditions.push('<MinScaleDenominator>'
+ tree.Zoom.ranges[end + 1] + '</MinScaleDenominator>');
} }
return conditions; return conditions;
}; };