UNPKG

carto

Version:

Mapnik Stylesheet Compiler

174 lines (157 loc) 6.27 kB
(function(tree) { var util = require('../util'), _ = require('lodash'); // a rule is a single property and value combination, or variable // name and value combination, like // polygon-opacity: 1.0; or @opacity: 1.0; tree.Rule = function Rule(ref, name, value, index, filename) { var parts = name.split('/'); this.name = parts.pop(); this.instance = parts.length ? parts[0] : '__default__'; this.value = (value instanceof tree.Value) ? value : new tree.Value([value]); this.index = index; this.symbolizer = ref.symbolizer(this.name); this.filename = filename; this.variable = (name.charAt(0) === '@'); }; tree.Rule.prototype.is = 'rule'; tree.Rule.prototype.clone = function() { var clone = Object.create(tree.Rule.prototype); clone.name = this.name; clone.value = this.value; clone.index = this.index; clone.instance = this.instance; clone.symbolizer = this.symbolizer; clone.filename = this.filename; clone.variable = this.variable; return clone; }; tree.Rule.prototype.updateID = function() { return this.id = this.zoom + '#' + this.instance + '#' + this.name; }; tree.Rule.prototype.toString = function() { return '[' + tree.Zoom.toString(this.zoom) + '] ' + this.name + ': ' + this.value; }; tree.Rule.prototype.validate = function (env) { var valid = true; if (!env.ref.validSelector(this.name)) { var mean = getMean(this.name, env.ref); var mean_message = '.'; if (!_.isNil(mean) && !_.isEmpty(mean)) { if (mean[0][1] < 3) { mean_message = '. Did you mean ' + mean[0][0] + '?'; } } valid = false; util.error(env, { message: "Unrecognized rule: " + this.name + mean_message, index: this.index, filename: this.filename }); } else { var selectorStatus = env.ref.selectorStatus(this.name); if (selectorStatus !== 'stable') { if (selectorStatus === 'deprecated') { util.warning(env, { message: this.name + ' is deprecated. It may be removed in the future.', filename: this.filename, index: this.index }); } else if (selectorStatus === 'unstable') { util.warning(env, { message: this.name + ' is unstable. It may change in the future.', filename: this.filename, index: this.index }); } else if (selectorStatus === 'experimental') { util.warning(env, { message: this.name + ' is experimental. It may change, be renamed or removed in the future.', filename: this.filename, index: this.index }); } } if ((this.value instanceof tree.Value) && !env.ref.validValue(env, this.name, this.value)) { if (!env.ref.selector(this.name)) { valid = false; util.error(env, { message: 'Unrecognized property: ' + this.name, index: this.index, filename: this.filename }); } else { var typename; if (env.ref.selector(this.name).validate) { typename = env.ref.selector(this.name).validate; } else if (typeof env.ref.selector(this.name).type === 'object') { typename = 'keyword (options: ' + env.ref.selector(this.name).type.join(', ') + ')'; } else { typename = env.ref.selector(this.name).type; } if (typename !== 'font' || (typename === 'font' && this.value.value[0].is !== 'string')) { valid = false; util.error(env, { message: 'Invalid value for ' + this.name + ', the type ' + typename + ' is expected. ' + this.value + ' (of type ' + this.value.value[0].is + ') was given.', index: this.index, filename: this.filename }); } else { valid = false; util.error(env, { message: 'The font \'' + this.value + '\' (specified as text-face-name) is not a known font on your system,' + ' please provide an existing font face name.', index: this.index, filename: this.filename }); } } } } return valid; } function getMean(name, ref) { return Object.keys(ref.selector_cache).map(function(f) { return [f, ref.editDistance(name, f)]; }).sort(function(a, b) { return a[1] - b[1]; }); } // second argument, if true, outputs the value of this // rule without the usual attribute="content" wrapping. Right // now this is just for the TextSymbolizer, but applies to other // properties in reference.json which specify serialization=content tree.Rule.prototype.toObject = function(env, content, sep) { if (this.validate(env)) { if (this.variable) { return {}; } else if (env.ref.isFont(this.name) && this.value.value.length > 1) { var f = tree._getFontSet(env, this.value.value); return _.set({}, 'fontset-name', f.name); } else if (content) { return this.value.toString(env, this.name, sep); } else { return _.set({}, env.ref.selectorName(this.name), this.value.toString(env, this.name)); } } return {}; }; // TODO: Rule ev chain should add fontsets to env.frames tree.Rule.prototype.ev = function(context) { return new tree.Rule(context.ref, this.name, this.value.ev(context), this.index, this.filename); }; })(require('../tree'));