Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Commit

Permalink
renderer returns output and error/warning objects, do only throw on p…
Browse files Browse the repository at this point in the history
…rogram failure, warn when layer has no associated styles, warn when styles do not match correspondig layer selector, ref #29
  • Loading branch information
nebulon42 committed May 28, 2017
1 parent 4831472 commit 9f8bfad
Show file tree
Hide file tree
Showing 63 changed files with 691 additions and 480 deletions.
24 changes: 23 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
## Changelog
# Changelog

## 1.0.0 (unreleased)

* Documentation is now available on https://cartocss.readthedocs.io. ([#473](https://github.com/mapbox/carto/issues/473))
* Warnings are emitted if properties are used that are `deprecated`, `unstable` or `experimental`.
There is a new command line / API switch (`-q / --quiet` / `quiet`) to suppress those warnings. ([#474](https://github.com/mapbox/carto/issues/474))
* Warnings are emitted if a layer has no associated styles or styles do not match a corresponding layer selector. ([#29](https://github.com/mapbox/carto/issues/29))

### Breaking changes

#### Stylesheets

* The deprecated `name` attribute for layers is no longer supported. Use `id` instead.
* The deprecated color functions `husl` and `husla` are no longer supported. Use `hsluv` and `hsluva` instead.

#### API

* `carto.Renderer.render` and `carto.Renderer.renderMSS` now return an object `{ msg: Array, data: String }` instead of just a
string. `data` contains the output as before and `msg` now contains an array of error or warning objects.
In case of errors `data` is `null`.
* carto now only throws errors in case of program failures. All other style processing
related errors can be found in the `msg` property (see above).

## 0.18.0

Expand Down
39 changes: 27 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,34 @@ The `Renderer` interface is the main API for developers, and it takes an MML fil
var data = fs.readFileSync(input, 'utf-8');
var mml = new carto.MML();
mml.load(path.dirname(input), data, function (err, data) {
if (err) throw err;
var output = new carto.Renderer({
filename: input,
local_data_dir: path.dirname(input),
}).render(data);
console.log(output);
var output = {};

if (!err) {
output = new carto.Renderer({
filename: input,
local_data_dir: path.dirname(input),
}).render(data);
}

if (output.msg) {
output.msg.forEach(function (v) {
if (v.type === 'error') {
console.error(carto.Util.getMessageToPrint(v));
}
else if (v.type === 'warning') {
console.warn(carto.Util.getMessageToPrint(v));
}
});
}

// output content (if no errors)
if (output.data) {
console.log(output.data);
}
});
} catch(err) {
if (Array.isArray(err)) {
err.forEach(function(e) {
carto.writeError(e, options);
});
} else { throw err; }
} catch (err) {
// program failures
...
}

If you want to use CartoCSS within the browser you should not use MML loading via `carto.MML.load`.
Expand Down
25 changes: 23 additions & 2 deletions bin/carto
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ var path = require('path'),
carto = require('../lib/carto'),
semver = require('semver'),
url = require('url'),
_ = require('lodash');
_ = require('lodash'),
util = require('../lib/carto/util');

var existsSync = require('fs').existsSync || require('path').existsSync

Expand Down Expand Up @@ -103,6 +104,24 @@ function compile(err, data) {
} else if (ext === '.mss') {
output = renderer.renderMSS(data);
}

if (_.has(output, 'msg') && _.isArray(output.msg) &&
output.msg.length > 0) {
var hasError = false;
_.forEach(output.msg, function (v) {
if (v.type === 'error') {
console.error(util.getMessageToPrint(v));
hasError = true;
}
else if (v.type === 'warning') {
console.warn(util.getMessageToPrint(v));
}
});

if (hasError) {
process.exit(1);
}
}
} catch (e) {
if (e.stack) {
console.error(e.stack);
Expand All @@ -115,7 +134,9 @@ function compile(err, data) {
process.exit(1);
}
if (!options.benchmark) {
console.log(output);
if (!_.isNil(output.data)) {
console.log(output.data);
}
} else {
var duration = (+new Date) - start;
console.log('TOTAL: ' + (duration) + 'ms');
Expand Down
39 changes: 27 additions & 12 deletions docs/installation_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,34 @@ and it takes an MML file as a string as input. ::
var data = fs.readFileSync(input, 'utf-8');
var mml = new carto.MML();
mml.load(path.dirname(input), data, function (err, data) {
if (err) throw err;
var output = new carto.Renderer({
filename: input,
local_data_dir: path.dirname(input),
}).render(data);
console.log(output);
var output = {};

if (!err) {
output = new carto.Renderer({
filename: input,
local_data_dir: path.dirname(input),
}).render(data);
}

if (output.msg) {
output.msg.forEach(function (v) {
if (v.type === 'error') {
console.error(carto.Util.getMessageToPrint(v));
}
else if (v.type === 'warning') {
console.warn(carto.Util.getMessageToPrint(v));
}
});
}

// output content (if no errors)
if (output.data) {
console.log(output.data);
}
});
} catch(err) {
if (Array.isArray(err)) {
err.forEach(function(e) {
carto.writeError(e, options);
});
} else { throw err; }
} catch (err) {
// program failures
...
}

.. note:: If you want to use Carto within the browser you should not use MML loading via ``carto.MML.load``.
Expand Down
1 change: 1 addition & 0 deletions lib/carto/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ var carto = {
Renderer: require('./renderer').Renderer,
MML: require('./mml').MML,
tree: require('./tree'),
Util: require('./util'),

// @TODO
writeError: function(ctx, options) {
Expand Down
37 changes: 28 additions & 9 deletions lib/carto/mml.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
var path = require('path'),
fs = require('fs'),
_ = require('lodash'),
yaml = require('js-yaml');

var carto = require('./index');
yaml = require('js-yaml'),
carto = require('./index'),
util = require('./util');

carto.MML = function MML(options) {
this.options = options || {};
Expand All @@ -18,12 +18,17 @@ carto.MML = function MML(options) {
*/
carto.MML.prototype.load = function load(basedir, data, callback) {
var mml = '',
that = this;
that = this,
env = {};

try {
mml = yaml.safeLoad(data);
} catch (err) {
return callback("carto: " + err.message.replace(/^[A-Z]+, /, ''), null);
env = {};
util.error(env, {
message: 'carto: ' + err.message.replace(/^[A-Z]+, /, '')
});
return callback(env.msg, null);
}

if (this.options.localize) {
Expand All @@ -32,7 +37,11 @@ carto.MML.prototype.load = function load(basedir, data, callback) {
require.resolve('millstone');
millstone = require('millstone');
} catch (err) {
return callback('carto: Millstone not found, required if localizing stylesheet resources. ' + err.message.replace(/^[A-Z]+, /, ''), null);
env = {};
util.error(env, {
message: 'carto: Millstone not found, required if localizing stylesheet resources. ' + err.message.replace(/^[A-Z]+, /, '')
});
return callback(env.msg, null);
}
millstone.resolve({
mml: mml,
Expand All @@ -45,7 +54,9 @@ carto.MML.prototype.load = function load(basedir, data, callback) {
if (that.options.localize && millstone.drainPool) {
millstone.drainPool(function() {});
}
return callback(err, data);
env = {};
util.error(env, err);
return callback(env.msg, data);
});
} else {
if (_.has(mml, 'Stylesheet') && !_.isNil(mml.Stylesheet)) {
Expand All @@ -61,14 +72,22 @@ carto.MML.prototype.load = function load(basedir, data, callback) {
try {
mss = fs.readFileSync(file, 'utf-8');
} catch (err) {
return callback('Failed to load file ' + file + ".\n", null);
env = {};
util.error(env, {
message: 'Failed to load file ' + file + '.'
});
return callback(env.msg, null);
}
mml.Stylesheet[i] = { id: stylesheet, data: mss };
}
return callback(null, mml);
}
else {
return callback("Expecting a Stylesheet property containing an (array of) stylesheet object(s) of the form { id: 'x', 'data': 'y' }.\n", null);
env = {};
util.error(env, {
message: "Expecting a Stylesheet property containing an (array of) stylesheet object(s) of the form { id: 'x', 'data': 'y' }."
});
return callback(env.msg, null);
}
}
};
Expand Down
13 changes: 8 additions & 5 deletions lib/carto/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ carto.Parser = function Parser(env) {
if (level !== 0) {
error = {
index: i - 1,
type: 'Parse',
message: (level > 0) ? "missing closing `}`" : "missing opening `{`",
filename: env.filename
};
Expand All @@ -194,7 +193,8 @@ carto.Parser = function Parser(env) {
})([[]]);

if (error) {
throw util.error(env, error);
util.error(env, error);
throw new Error('N/A');
}

// Start with the primary rule.
Expand Down Expand Up @@ -511,19 +511,21 @@ carto.Parser = function Parser(env) {
} else if (f) {
var err = filters.add(f);
if (err) {
throw util.error(env, {
util.error(env, {
message: err,
index: i - 1,
filename: env.filename
});
throw new Error('N/A');
}
conditions++;
} else if (attachment) {
throw util.error(env, {
util.error(env, {
message: 'Encountered second attachment name.\n',
index: i - 1,
filename: env.filename
});
throw new Error('N/A');
} else {
attachment = a;
}
Expand Down Expand Up @@ -560,11 +562,12 @@ carto.Parser = function Parser(env) {
$(this.entities.keyword) ||
$(this.entities.field))) {
if (! $(']')) {
throw util.error(env, {
util.error(env, {
message: 'Missing closing ] of filter.',
index: memo - 1,
filename: env.filename
});
throw new Error('N/A');
}
if (!key.is) key = new tree.Field(key);
return new tree.Filter(key, op, val, memo, env.filename);
Expand Down
Loading

0 comments on commit 9f8bfad

Please sign in to comment.