Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

carto

Package Overview
Dependencies
Maintainers
6
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

carto - npm Package Compare versions

Comparing version 0.4.10 to 0.6.0

.travis.yml

12

CHANGELOG.md
## Changelog
### 0.6.0
* Bump `mapnik-reference` dependency to 1.0.0 to allow for using `buffer-size` in the
`Map` element.
### 0.5.0
* Now uses the [mapnik-reference](https://github.com/mapnik/mapnik-reference) npm module
instead of copying `reference.json` when it's updated
* Adds a second parameter to `carto.Renderer` - an object which has a key `mapnik_version`
that specifies the version of Mapnik this stylesheet should target.
### 0.4.10

@@ -4,0 +16,0 @@

24

lib/carto/functions.js

@@ -8,4 +8,4 @@ (function (tree) {

rgba: function (r, g, b, a) {
var rgb = [r, g, b].map(function (c) { return number(c); }),
a = number(a);
var rgb = [r, g, b].map(function (c) { return number(c); });
a = number(a);
return new tree.Color(rgb, a);

@@ -121,5 +121,2 @@ },

},
e: function (str) {
return new tree.Anonymous(str instanceof tree.JavaScript ? str.evaluated : str);
},
'%': function (quoted /* arg, arg, ...*/) {

@@ -138,2 +135,19 @@ var args = Array.prototype.slice.call(arguments, 1),

var image_filter_functors = [
'emboss', 'blur', 'gray', 'sobel', 'edge-detect',
'x-gradient', 'y-gradient', 'sharpen'];
for (var i = 0; i < image_filter_functors.length; i++) {
var f = image_filter_functors[i];
tree.functions[f] = (function(f) {
return function() {
return new tree.ImageFilter(f);
};
})(f);
}
tree.functions['agg-stack-blur'] = function(x, y) {
return new tree.ImageFilter('agg-stack-blur', [x, y]);
};
function hsla(hsla) {

@@ -140,0 +154,0 @@ return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a);

@@ -53,5 +53,5 @@ var util = require('util');

[ 'alpha', 'anonymous', 'call', 'color', 'comment', 'definition', 'dimension',
[ 'anonymous', 'call', 'color', 'comment', 'definition', 'dimension',
'directive', 'element', 'expression', 'filterset', 'filter',
'keyword', 'layer', 'mixin', 'operation', 'quoted',
'keyword', 'layer', 'operation', 'quoted', 'imagefilter',
'reference', 'rule', 'ruleset', 'selector', 'style', 'url', 'value',

@@ -58,0 +58,0 @@ 'variable', 'zoom', 'invalid', 'fontset'

@@ -12,3 +12,3 @@ var carto, tree, _;

}
//
// carto.js - parser

@@ -44,4 +44,3 @@ //

// It also takes care of moving all the indices forwards.
//
//
carto.Parser = function Parser(env) {

@@ -140,5 +139,4 @@ var input, // LeSS input string

// grammar is mostly white-space insensitive.
//
if (match) {
mem = i += length;
var mem = i += length;
endIndex = i + chunks[j].length - length;

@@ -184,2 +182,4 @@

function makeError(err) {
var einput;
_(err).defaults({

@@ -203,3 +203,3 @@ index: furthest,

}
return new Error(_('<%=filename%>:<%=line%>:<%=column%> <%=message%>').template(err));
return new Error(_('<%=filename%>:<%=line%>:<%=column%> <%=message%>').template(err));
}

@@ -211,5 +211,3 @@

//
// The Parser
//
return parser = {

@@ -286,8 +284,8 @@

throw makeError({
message:'Missing closing `}`',
index:i
message: 'Missing closing `}`',
index: i
});
}
return chunks.map(function(c) { return c.join('') });
return chunks.map(function(c) { return c.join(''); });
})([[]]);

@@ -363,20 +361,2 @@

//
// Here's some LESS code:
//
// .class {
// color: #fff;
// border: 1px solid #000;
// width: @w + 4px;
// > .child {...}
// }
//
// And here's what the parse tree might look like:
//
// Ruleset (Selector '.class', [
// Rule ("color", Value ([Expression [Color #fff]]))
// Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]]))
// Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]]))
// Ruleset (Selector [Element '>', '.child'], [...])
// ])
//
// In general, most rules will try to parse a token with the `$()` function, and if the return

@@ -405,5 +385,5 @@ // value is truly, will return a new node, of the relevant type. Sometimes, we need to check

while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) ||
$(this.mixin.call) || $(this.comment))
|| $(/^[\s\n]+/) || (node = $(this.invalid))) {
while ((node = $(this.rule) || $(this.ruleset) ||
$(this.comment)) ||
$(/^[\s\n]+/) || (node = $(this.invalid))) {
node && root.push(node);

@@ -415,6 +395,6 @@ }

invalid: function () {
var chunk;
var chunk = $(/^[^;\n]*[;\n]/);
// To fail gracefully, match everything until a semicolon or linebreak.
if (chunk = $(/^[^;\n]*[;\n]/)) {
if (chunk) {
return new(tree.Invalid)(chunk, memo);

@@ -449,6 +429,5 @@ }

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]);

@@ -459,4 +438,4 @@ }

comparison: function() {
var str;
if (str = $(/^=|!=|<=|>=|<|>/)) {
var str = $(/^=~|=|!=|<=|>=|<|>/);
if (str) {
return str;

@@ -466,16 +445,13 @@ }

//
// A catch-all word, such as:
//
// hard_light
// hard-light
//
// These can start with either a letter or a dash (-),
// and then contain numbers, underscores, and letters.
//
keyword: function() {
var k;
if (k = $(/^[A-Za-z-]+[A-Za-z-0-9_]*/)) { return new tree.Keyword(k) }
var k = $(/^[A-Za-z-]+[A-Za-z-0-9_]*/);
if (k) { return new tree.Keyword(k); }
},
//
// A function call

@@ -486,3 +462,2 @@ //

// The arguments are parsed with the `entities.arguments` parser.
//
call: function() {

@@ -495,10 +470,15 @@ var name, args;

if (name === 'url') { return null }
else { i += name.length + 1 }
if (name === 'url') {
return null;
} else {
i += name.length + 1;
}
args = $(this.entities.arguments);
if (! $(')')) return;
if (!$(')')) return;
if (name) { return new tree.Call(name, args, i) }
if (name) {
return new tree.Call(name, args, i);
}
},

@@ -510,3 +490,3 @@ arguments: function() {

args.push(arg);
if (! $(',')) { break }
if (! $(',')) { break; }
}

@@ -521,3 +501,2 @@ return args;

//
// Parse url() tokens

@@ -528,3 +507,2 @@ //

// to be enclosed within a string, so it can't be parsed as an Expression.
//
url: function() {

@@ -535,12 +513,11 @@ var value;

value = $(this.entities.quoted) || $(this.entities.variable) ||
$(/^[-\w%@$\/.&=:;#+?~]+/) || '';
$(/^[\-\w%@$\/.&=:;#+?~]+/) || '';
if (! $(')')) {
return new tree.Invalid(value, memo, 'Missing closing ) in URL.');
} else {
return new tree.URL((value.value || value.data || value instanceof tree.Variable)
? value : new tree.Anonymous(value), imports.paths);
return new tree.URL((value.value || value instanceof tree.Variable) ?
value : new tree.Anonymous(value), imports.paths);
}
},
//
// A Variable entity, such as `@fink`, in

@@ -552,3 +529,2 @@ //

// see `parsers.variable`.
//
variable: function() {

@@ -562,3 +538,2 @@ var name, index = i;

//
// A Hexadecimal color

@@ -569,3 +544,2 @@ //

// `rgb` and `hsl` colors are parsed through the `entities.call` parser.
//
color: function() {

@@ -584,134 +558,26 @@ var rgb;

// A Dimension, that is, a number and a unit. The only
// unit that has an effect is %
//
// A Dimension, that is, a number and a unit
//
// 0.5em 95%
//
dimension: function() {
var value, c = input.charCodeAt(i);
var c = input.charCodeAt(i);
if ((c > 57 || c < 45) || c === 47) return;
if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) {
var value = $(/^(-?\d*\.?\d+)(\%|\w+)?/);
if (value) {
return new tree.Dimension(value[1], value[2], memo);
}
},
//
// JavaScript code to be evaluated
//
// `window.location.href`
//
javascript: function() {
var str;
if (input.charAt(i) !== '`') { return }
if (str = $(/^`([^`]*)`/)) {
return new tree.JavaScript(str[1], i);
}
}
},
//
// The variable part of a variable definition. Used in the `rule` parser
//
// @fink:
//
variable: function() {
var name;
if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] }
if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1]; }
},
//
// Mixins
//
mixin: {
//
// A Mixin call, with an optional argument list
//
// #mixins > .square(#fff);
// .rounded(4px, black);
// .button;
//
// The `while` loop is there because mixins can be
// namespaced, but we only support the child and descendant
// selector for now.
//
call: function() {
var elements = [], e, c, args, index = i, s = input.charAt(i);
if (s !== '.' && s !== '#') { return }
while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) {
elements.push(new tree.Element(c, e));
c = $('>');
}
$('(') && (args = $(this.entities.arguments)) && $(')');
if (elements.length > 0 && ($(';') || peek('}'))) {
throw new Error('Calls are not yet supported.');
return new tree.mixin.Call(elements, args, index);
}
},
//
// A Mixin definition, with a list of parameters
//
// .rounded (@radius: 2px, @color) {
// ...
// }
//
// Until we have a finer grained state-machine, we have to
// do a look-ahead, to make sure we don't have a mixin call.
// See the `rule` function for more information.
//
// We start by matching `.rounded (`, and then proceed on to
// the argument list, which has optional default values.
// We store the parameters in `params`, with a `value` key,
// if there is a value, such as in the case of `@radius`.
//
// Once we've got our params list, and a closing `)`, we parse
// the `{...}` block.
//
definition: function() {
var name, params = [], match, ruleset, param, value;
if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') ||
peek(/^[^{]*(;|})/)) return;
if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)[\s,]*\(/)) {
name = match[1];
while (param = $(this.entities.variable) || $(this.entities.literal)
|| $(this.entities.keyword)) {
// Variable
if (param instanceof tree.Variable) {
if ($(':')) {
if (value = $(this.expression)) {
params.push({ name: param.name, value: value });
} else {
throw new Error('Expected value.');
}
} else {
params.push({ name: param.name });
}
} else {
params.push({ value: param });
}
if (! $(',')) { break }
}
if (! $(')')) throw new Error('Expected )');
ruleset = $(this.block);
if (ruleset) {
throw new Error('Definitions should not exist here.');
return new tree.mixin.Definition(name, params, ruleset);
}
}
}
},
//
// Entities are the smallest recognized token,

@@ -722,3 +588,3 @@ // and can be found inside a rule's value.

return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) ||
$(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript);
$(this.entities.call) || $(this.entities.keyword);
},

@@ -735,40 +601,17 @@

//
// A Selector Element
//
// div
// .classname
// #socks
// input[type="text"]
//
// Elements are the building blocks for Selectors. They consist of
// an element name, such as a tag a class, or `*`.
//
element: function() {
var e;
if (e = $(/^(?:[.#][\w-]+|\*|Map)/)) {
return new tree.Element(e);
}
var e = $(/^(?:[.#][\w\-]+|\*|Map)/);
if (e) return new tree.Element(e);
},
//
// Attachments allow adding multiple lines, polygons etc. to an
// object. There can only be one attachment per selector.
//
attachment: function() {
var s;
if (s = $(/^::([\w-]+(?:\/[\w-]+)*)/)) {
// There's no object for attachment names.
return s[1];
}
var s = $(/^::([\w\-]+(?:\/[\w\-]+)*)/);
if (s) return s[1];
},
//
// A CSS Selector
//
// .class > div + h1
// li a:hover
//
// Selectors are made out of one or more Elements, see above.
//
selector: function() {

@@ -806,3 +649,3 @@ var a, attachment;

var c = input.charAt(i);
if (c === '{' || c === '}' || c === ';' || c === ',') { break }
if (c === '{' || c === '}' || c === ';' || c === ',') { break; }
}

@@ -819,5 +662,5 @@

if (! $('[')) return;
if (key = $(/^[a-zA-Z0-9-_]+/) || $(this.entities.quoted) || $(this.entities.variable)) {
if (key = $(/^[a-zA-Z0-9\-_]+/) || $(this.entities.quoted) || $(this.entities.variable)) {
if ((op = $(this.entities.comparison)) &&
(val = $(this.entities.quoted) || $(this.entities.variable) || $(/^[\w-\.]+/))) {
(val = $(this.entities.quoted) || $(this.entities.variable) || $(/^[\w\-\.]+/))) {
if (! $(']')) return;

@@ -898,7 +741,8 @@ return new tree.Filter(key, op, val, memo, env.filename);

font: function() {
var value = [], expression = [], weight, shorthand, font, e;
var value = [], expression = [], weight, font, e;
while (e = $(this.shorthand) || $(this.entity)) {
while (e = $(this.entity)) {
expression.push(e);
}
value.push(new tree.Expression(expression));

@@ -909,3 +753,3 @@

value.push(e);
if (! $(',')) { break }
if (! $(',')) { break; }
}

@@ -916,10 +760,5 @@ }

//
// A Value is a comma-delimited list of Expressions
//
// font-family: Baskerville, Georgia, serif;
//
// In a Rule, a Value represents everything after the `:`,
// and before the `;`.
//
value: function() {

@@ -930,3 +769,3 @@ var e, expressions = [];

expressions.push(e);
if (! $(',')) { break }
if (! $(',')) { break; }
}

@@ -965,6 +804,4 @@

//
// An operand is anything that can be part of an operation,
// such as a Color, or a Variable
//
operand: function() {

@@ -976,3 +813,2 @@ return $(this.sub) || $(this.entities.dimension) ||

//
// Expressions either represent mathematical operations,

@@ -983,3 +819,2 @@ // or white-space delimited Entities.

// @var * 2
//
expression: function() {

@@ -996,7 +831,4 @@ var e, delim, entities = [], d;

property: function() {
var name;
if (name = $(/^(([a-z][-a-z_0-9]*\/)?\*?-?[-a-z_0-9]+)\s*:/)) {
return name[1];
}
var name = $(/^(([a-z][-a-z_0-9]*\/)?\*?-?[-a-z_0-9]+)\s*:/);
if (name) return name[1];
}

@@ -1003,0 +835,0 @@ }

@@ -5,4 +5,6 @@ var _ = require('underscore');

carto.Renderer = function Renderer(env) {
carto.Renderer = function Renderer(env, options) {
this.env = env || {};
this.options = options || {};
this.options.mapnik_version = this.options.mapnik_version || 'latest';
};

@@ -18,3 +20,3 @@

// are limited to FontSets.
env = _(this.env).defaults({
var env = _(this.env).defaults({
benchmark: false,

@@ -25,2 +27,4 @@ validation_data: false,

tree.Reference.setVersion(this.options.mapnik_version);
var output = [];

@@ -39,3 +43,3 @@

if (env.benchmark)
console.warn('Parsing time: ' + ((new Date() - time)) + 'ms');
console.warn('Parsing time: ' + (new Date() - time) + 'ms');
return root.toList(env);

@@ -56,3 +60,3 @@ })

var rules = inheritRules(matching, env);
sorted = sortStyles(rules, env);
var sorted = sortStyles(rules, env);
_(sorted).each(function(rule) {

@@ -76,4 +80,5 @@ var style = new tree.Style(l.name, rule.attachment, rule);

var map_properties;
try {
var map_properties = getMapProperties(m, rulesets, env);
map_properties = getMapProperties(m, rulesets, env);
} catch (err) {

@@ -131,3 +136,3 @@ env.error(err);

'<!DOCTYPE Map[]>\n' +
'<Map' + properties + '>\n');
'<Map' + properties + ' maximum-extent="-20037508.34,-20037508.34,20037508.34,20037508.34">\n');
output.push('</Map>');

@@ -134,0 +139,0 @@ return callback(null, output.join('\n'));

@@ -9,2 +9,3 @@ (function(tree) {

this.args = args;
this.is = 'call';
this.index = index;

@@ -57,6 +58,2 @@ };

}
},
toString: function(env) {
return this.eval(env).toString();
}

@@ -63,0 +60,0 @@ };

@@ -26,6 +26,6 @@ (function(tree) {

};
tree.Color.prototype = {
eval: function() { return this; },
//
// If we have some transparency, the only way to represent it

@@ -35,3 +35,2 @@ // is via `rgba`. Otherwise, we use the hex representation,

// Values are capped between `0` and `255`, rounded and zero-padded.
//
toString: function() {

@@ -51,3 +50,2 @@ if (this.alpha < 1.0) {

//
// Operations have to be done per-channel, if not,

@@ -57,3 +55,2 @@ // channels will spill onto each other. Once we have

// we create a new Color node to hold the result.
//
operate: function(op, other) {

@@ -60,0 +57,0 @@ var result = [];

@@ -71,3 +71,3 @@ (function(tree) {

xml += this.filters.toXML(env);
// Sort symbolizers by the index of their first property definition

@@ -92,5 +92,11 @@ var sym_order = [], indexes = [];

for (var i = 0; i < sym_order.length; i++) {
attributes = symbolizers[sym_order[i]];
var attributes = symbolizers[sym_order[i]];
var symbolizer = sym_order[i].split('/').pop();
if (fail = tree.Reference.requiredProperties(symbolizer, attributes)) {
// Skip the magical * symbolizer which is used for universal properties
// which are bubbled up to Style elements intead of Symbolizer elements.
if (symbolizer === '*') continue;
var fail = tree.Reference.requiredProperties(symbolizer, attributes);
if (fail) {
var rule = attributes[Object.keys(attributes).shift()];

@@ -112,2 +118,7 @@ env.error({

for (var key in attributes) {
if (symbolizer === 'map') env.error({
message: 'Map properties are not permitted in other rules',
index: attributes[key].index,
filename: attributes[key].filename
});
var x = tree.Reference.selector(attributes[key].name);

@@ -114,0 +125,0 @@ if (x && x.serialization && x.serialization === 'content') {

@@ -28,7 +28,13 @@ (function(tree) {

},
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'));
(function(tree) {
tree.Expression = function Expression(value) { this.value = value };
tree.Expression = function Expression(value) {
this.value = value;
};
tree.Expression.prototype = {

@@ -5,0 +7,0 @@ eval: function(env) {

@@ -22,3 +22,3 @@ (function(tree) {

if (this.op !== '=' && this.op !== '!=') {
if (ops[this.op][1] == 'numeric') {
this.val = 1 * this.val;

@@ -31,14 +31,23 @@ }

// XML-safe versions of comparators
var opXML = {
'<': '&lt;',
'>': '&gt;',
'=': '=',
'!=': '!=',
'<=': '&lt;=',
'>=': '&gt;='
// xmlsafe, numeric, suffix
var ops = {
'<': [' &lt; ', 'numeric'],
'>': [' &gt; ', 'numeric'],
'=': [' = ', 'both'],
'!=': [' != ', 'both'],
'<=': [' &lt;= ', 'numeric'],
'>=': [' &gt;= ', 'numeric'],
'=~': ['.match(', 'string', ')']
};
tree.Filter.prototype.toXML = function(env) {
if (this.op !== '=' && this.op !== '!=' && isNaN(this.val)) {
if (this.val.eval) this._val = this.val.eval(env);
if (this.key.eval) this._key = this.key.eval(env);
if (this._key) var key = this._key.toString(false);
if (this._val) var val = this._val.toString(this._val.is == 'string');
if (
(ops[this.op][1] == 'numeric' && isNaN(this.val)) ||
(ops[this.op][1] == 'string' && (val || this.val)[0] != "'")
) {
env.error({

@@ -50,8 +59,4 @@ message: 'Cannot use operator "' + this.op + '" with value ' + this.val,

}
if (this.val.eval) this._val = this.val.eval(env);
if (this.key.eval) this._key = this.key.eval(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] || '');
};

@@ -58,0 +63,0 @@

@@ -69,8 +69,10 @@ var tree = require('../tree');

// 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);
}

@@ -102,3 +104,2 @@ return clone;

if (key + '!=' + value in this) return null;
if (key + '>' in this && this[key + '>'].val >= value) return null;

@@ -108,3 +109,2 @@ if (key + '<' in this && this[key + '<'].val <= value) return null;

if (key + '<=' in this && this[key + '<='].val < value) return null;
return true;

@@ -157,5 +157,7 @@

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;

@@ -168,6 +170,15 @@ 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;

@@ -177,5 +188,7 @@ 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) {

@@ -192,5 +205,7 @@ delete this[key + '!=' + filter.val];

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;

@@ -200,5 +215,7 @@ 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) {

@@ -205,0 +222,0 @@ delete this[key + '!=' + filter.val];

@@ -29,11 +29,11 @@ (function(tree) {

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'));

@@ -13,6 +13,6 @@ (function(tree) {

tree.Keyword.prototype = {
eval: function() { return this },
toString: function() { return this.value }
eval: function() { return this; },
toString: function() { return this.value; }
};
})(require('../tree'));

@@ -38,3 +38,3 @@ (function(tree) {

type: 'runtime',
filename: this.filename,
filename: this.filename
});

@@ -41,0 +41,0 @@ return {

@@ -10,5 +10,6 @@ (function(tree) {

toString: function(quotes) {
return (quotes === true) ? "'" + this.value + "'" : this.value;
var xmlvalue = this.value.replace(/\'/g, '&apos;');
return (quotes === true) ? "'" + xmlvalue + "'" : this.value;
},
eval: function() {
'eval': function() {
return this;

@@ -15,0 +16,0 @@ }

(function(tree) {
var fs = require('fs');
var mapnik_reference = require('mapnik-reference');
tree.Reference = {
data: JSON.parse(fs.readFileSync(__dirname + '/reference.json'))
data: mapnik_reference.version.latest
};
tree.Reference.setVersion = function(version) {
tree.Reference.data = mapnik_reference.version[version];
};
tree.Reference.required_prop_list_cache = {};

@@ -71,6 +76,6 @@

var req = tree.Reference.requiredPropertyList(symbolizer_name);
for (i in req) {
for (var i in req) {
if (!(req[i] in rules)) {
return 'Property ' + req[i] + ' required for defining '
+ symbolizer_name + ' styles.';
return 'Property ' + req[i] + ' required for defining ' +
symbolizer_name + ' styles.';
}

@@ -95,5 +100,6 @@ }

return tree.Reference.selector(selector).validate == 'font';
}
};
tree.Reference.validValue = function(env, selector, value) {
var i, j;
if (value[0]) {

@@ -103,3 +109,5 @@ return tree.Reference.selector(selector).type == value[0].is;

// TODO: handle in reusable way
if (value.value[0].is == 'keyword') {
if (!tree.Reference.selector(selector)) {
return false;
} else if (value.value[0].is == 'keyword') {
return tree.Reference

@@ -119,6 +127,15 @@ .selector(selector).type

return true;
} else if (tree.Reference.selector(selector).type == 'imagefilters') {
for (i in value.value) {
for (j in value.value[i].value) {
if (value.value[i].value[j].is !== 'imagefilter') {
return false;
}
}
}
return true;
} else {
if (tree.Reference.selector(selector).validate) {
var valid = false;
for (var i = 0; i < value.value.length; i++) {
for (i = 0; i < value.value.length; i++) {
if (tree.Reference.selector(selector).type == value.value[i].is &&

@@ -138,4 +155,4 @@ tree.Reference

}
}
};
})(require('../tree'));

@@ -16,3 +16,3 @@ (function(tree) {

var clone = Object.create(tree.Rule.prototype);
clone.name = this.name
clone.name = this.name;
clone.value = this.value;

@@ -51,14 +51,24 @@ clone.index = this.index;

!tree.Reference.validValue(env, this.name, this.value)) {
return env.error({
message: 'Invalid value for ' +
this.name +
', a valid ' +
(tree.Reference.selector(this.name).validate ||
tree.Reference.selector(this.name).type) +
' is expected. ' + this.value +
' was given.',
index: this.index,
type: 'syntax',
filename: this.filename
});
if (!tree.Reference.selector(this.name)) {
return env.error({
message: 'Unrecognized property: ' +
this.name,
index: this.index,
type: 'syntax',
filename: this.filename
});
} else {
return env.error({
message: 'Invalid value for ' +
this.name +
', a valid ' +
(tree.Reference.selector(this.name).validate ||
tree.Reference.selector(this.name).type) +
' is expected. ' + this.value +
' was given.',
index: this.index,
type: 'syntax',
filename: this.filename
});
}
}

@@ -84,5 +94,5 @@

*/
tree.Rule.prototype.eval = function(context) {
tree.Rule.prototype['eval'] = function(context) {
return new tree.Rule(this.name,
this.value.eval(context),
this.value['eval'](context),
this.index,

@@ -101,5 +111,5 @@ this.filename);

},
eval: function() { return this }
'eval': function() { return this; }
};
})(require('../tree'));

@@ -61,3 +61,3 @@ (function(tree) {

variables: function() {
if (this._variables) { return this._variables }
if (this._variables) { return this._variables; }
else {

@@ -84,3 +84,3 @@ return this._variables = this.rules.reduce(function(hash, r) {

rulesets: function() {
if (this._rulesets) { return this._rulesets }
if (this._rulesets) { return this._rulesets; }
else {

@@ -97,3 +97,3 @@ return this._rulesets = this.rules.filter(function(r) {

if (key in this._lookups) { return this._lookups[key] }
if (key in this._lookups) { return this._lookups[key]; }

@@ -119,3 +119,3 @@ this.rulesets().forEach(function(rule) {

var selectors = [];
if (this.selectors.length == 0) {
if (this.selectors.length === 0) {
env.frames = env.frames.concat(this.rules);

@@ -122,0 +122,0 @@ }

(function(tree) {
var _ = require('underscore');

@@ -11,2 +12,15 @@ tree.Style = function Style(name, attachment, definitions) {

var existing = {};
// TODO :add filters and comp op
var image_filters = _.flatten(this.definitions.map(function(definition) {
return definition.rules.filter(function(rule) {
return (rule.name === 'image-filters');
});
}));
var comp_op = _.flatten(this.definitions.map(function(definition) {
return definition.rules.filter(function(rule) {
return (rule.name === 'composite-operation');
});
}));
var rules = this.definitions.map(function(definition) {

@@ -16,5 +30,18 @@ return definition.toXML(env, existing);

return '<Style name="' + this.name + '" filter-mode="first">\n' + rules.join('') + '</Style>';
var image_filters_xml = '',
comp_op_xml = '';
if (image_filters.length) {
image_filters_xml = 'image-filters="' + image_filters.map(function(f) {
return f.value.eval(env).toString(env, null, ';');
}).join(',') + '"';
}
if (comp_op.length) {
comp_op_xml = 'comp-op="' + comp_op[0].value.eval(env).toString() + '"';
}
return '<Style name="' + this.name + '" filter-mode="first" ' + image_filters_xml + ' ' + comp_op_xml + '>\n' + rules.join('') + '</Style>';
};
})(require('../tree'));
(function(tree) {
tree.URL = function URL(val, paths) {
if (val.data) {
this.attrs = val;
} else {
// Add the base path if the URL is relative and we are in the browser
if (!/^(?:https?:\/|file:\/)?\//.test(val.value) && paths.length > 0 && typeof(process) === 'undefined') {
val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value);
}
this.value = val;
this.paths = paths;
this.is = 'uri';
}
this.value = val;
this.paths = paths;
this.is = 'uri';
};

@@ -21,5 +13,3 @@ tree.URL.prototype = {

eval: function(ctx) {
return this.attrs ? this : new tree.URL(this.value.eval(ctx), this.paths);
// URL case no longer supported.
// @TODO: throw an error?
return new tree.URL(this.value.eval(ctx), this.paths);
}

@@ -26,0 +16,0 @@ };

@@ -17,6 +17,6 @@ (function(tree) {

},
toString: function(env, selector) {
toString: function(env, selector, sep) {
return this.value.map(function(e) {
return e.toString(env);
}).join(', ');
}).join(sep || ', ');
},

@@ -23,0 +23,0 @@ clone: function() {

@@ -27,3 +27,3 @@ (function(tree) {

type: 'runtime',
filename: this.filename,
filename: this.filename
});

@@ -30,0 +30,0 @@ return {

@@ -7,7 +7,7 @@ var tree = require('../tree');

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

@@ -24,3 +24,2 @@ };

return 1 << value;
break;
case '>':

@@ -86,10 +85,10 @@ start = value + 1;

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');
}

@@ -96,0 +95,0 @@ return conditions;

{
"name": "carto",
"version": "0.6.0",
"description": "Mapnik Stylesheet Compiler",

@@ -25,3 +26,2 @@ "url": "https://github.com/mapbox/carto",

],
"version": "0.4.10",
"licenses": [{

@@ -40,6 +40,7 @@ "type": "Apache"

"underscore": "~1.3.3",
"mapnik-reference": "~1.0.0",
"xml2js": "~0.1.13"
},
"devDependencies": {
"expresso": "0.9.x",
"mocha": "1.0.x",
"docco": "0.3.x",

@@ -51,4 +52,4 @@ "jshint": "0.2.x",

"pretest": "npm install --dev",
"test": "expresso"
"test": "mocha"
}
}
# carto
Is a stylesheet renderer for Mapnik. It's an evolution of the [Cascadenik](https://github.com/mapnik/Cascadenik) idea and language, with an emphasis on speed and flexibility.
[![Build Status](https://secure.travis-ci.org/mapbox/carto.png)](http://travis-ci.org/mapbox/carto)
## Installation
Is a stylesheet renderer for Mapnik. It's an evolution of the
[Cascadenik](https://github.com/mapnik/Cascadenik) idea and language,
with an emphasis on speed and flexibility.
npm install carto
## Reference Documentation
* [mapbox.com/carto](http://mapbox.com/carto/)
## MML
_incompatibility_
* MML files are assumed to be JSON, not XML. The files are near-identical to the XML files accepted by Cascadenik, just translated into JSON.
* Carto will not embed files or download URLs for you. Stylesheets should be embedded directly into your MML JSON and any datasources should be paths (relative or absolute) that would be acceptable in Mapnik XML.
* MML files are assumed to be JSON, not XML. The files are near-identical
to the XML files accepted by Cascadenik, just translated into JSON.
* Carto will not embed files or download URLs for you. Stylesheets should
be embedded directly into your MML JSON and any datasources should be
paths (relative or absolute) that would be acceptable in Mapnik XML.
The [millstone project](https://github.com/mapbox/millstone) aims to fill this need.

@@ -206,7 +213,44 @@

## Filters
## Usage
Carto supports a variety of filter styles:
#### Using the binary
Numeric comparisons:
```
#world[population > 100]
#world[population < 100]
#world[population >= 100]
#world[population <= 100]
```
General comparisons:
```
#world[population = 100]
#world[population != 100]
```
String comparisons:
```
/* a regular expression over name */
#world[name =~ "A.*"]
```
## Developers
#### Installation
If you're using [TileMill](http://mapbox.com/tilemill/), you're already
using Carto and don't need to do a thing.
If you're a developer-type and want to use the `carto` binary with
`node.js` (and you have [npm](http://npmjs.org/) installed),
npm install carto
#### From the binary
Install `millstone` to enable support for localizing external resources (URLs and local files) referenced in your mml file.

@@ -217,3 +261,3 @@

#### Using the code
#### From code

@@ -243,15 +287,2 @@ Currently `carto.js` is designed to be invoked from [node.js](http://nodejs.org/).

## Syntax Highlighting
There's a TextMate and vim bundle that offers syntax highlighting for `.mss` and `.mml` files in the `build` directory.
### TextMate bundle
To install, download or clone this repository, then double-click on the `carto.tmbundle` icon in that folder.
The TextMate bundle **requires** [node-mapnik](https://github.com/mapnik/node-mapnik) and Carto installed globally - the versions that are installed locally in TileMill or other tools can't be automatically discovered.
npm install mapnik -g
npm install carto -g
### Vim

@@ -272,3 +303,3 @@

* [expresso](https://github.com/visionmedia/expresso)
* [mocha](https://github.com/visionmedia/mocha)
* [sax-js](https://github.com/isaacs/sax-js/)

@@ -281,2 +312,2 @@

* AJ Ashton (ajashton)
* Dane Springmeyer (springmeyer)
* Dane Springmeyer (springmeyer)

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc