Adding make doc command, making renderer docs better for docco, writing some docs.
This commit is contained in:
parent
10088c473f
commit
490b51c6fd
3
Makefile
3
Makefile
@ -10,4 +10,7 @@ test:
|
||||
bin/expresso -I lib test/${only}.test.js
|
||||
endif
|
||||
|
||||
doc:
|
||||
docco lib/mess/*.js
|
||||
|
||||
.PHONY: test
|
||||
|
@ -311,10 +311,8 @@ mess.Parser = function Parser(env) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of Ruleset objects, flattened
|
||||
* and sorted according to specificitySort
|
||||
*/
|
||||
// Get an array of Ruleset objects, flattened
|
||||
// and sorted according to specificitySort
|
||||
root.toList = (function() {
|
||||
var line, lines, column, _ = require('underscore')._;
|
||||
return function(env) {
|
||||
@ -336,15 +334,13 @@ mess.Parser = function Parser(env) {
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Sort rules by specificity: this function expects selectors to be
|
||||
* split already.
|
||||
*
|
||||
* Written to be used as a .sort(Function);
|
||||
* argument.
|
||||
*
|
||||
* [1, 0, 0, 467] > [0, 0, 1, 520]
|
||||
*/
|
||||
// Sort rules by specificity: this function expects selectors to be
|
||||
// split already.
|
||||
//
|
||||
// Written to be used as a .sort(Function);
|
||||
// argument.
|
||||
//
|
||||
// [1, 0, 0, 467] > [0, 0, 1, 520]
|
||||
var specificitySort = function(a, b) {
|
||||
var as = a.selector.specificity();
|
||||
var bs = b.selector.specificity();
|
||||
|
@ -9,12 +9,8 @@ var path = require('path'),
|
||||
|
||||
require.paths.unshift(path.join(__dirname, '..', 'lib'));
|
||||
|
||||
/**
|
||||
* Rendering circuitry for JSON map manifests.
|
||||
*
|
||||
* This is node-only for the time being.
|
||||
*/
|
||||
|
||||
// Rendering circuitry for JSON map manifests.
|
||||
// This is node-only for the time being.
|
||||
mess.Renderer = function Renderer(env) {
|
||||
env = _.extend({}, env);
|
||||
if (!env.debug) env.debug = false;
|
||||
@ -23,19 +19,15 @@ mess.Renderer = function Renderer(env) {
|
||||
if (!env.validation_data) env.validation_data = false;
|
||||
|
||||
return {
|
||||
/**
|
||||
* Keep a copy of passed-in environment variables
|
||||
*/
|
||||
// Keep a copy of passed-in environment variables
|
||||
env: env,
|
||||
|
||||
/**
|
||||
* Ensure that map layers have a populated SRS value and attempt to
|
||||
* autodetect SRS if missing. Requires that node-srs is available and
|
||||
* that any remote datasources have been localized.
|
||||
*
|
||||
* @param {Object} m map object.
|
||||
* @param {Function} callback
|
||||
*/
|
||||
// Ensure that map layers have a populated SRS value and attempt to
|
||||
// autodetect SRS if missing. Requires that node-srs is available and
|
||||
// that any remote datasources have been localized.
|
||||
//
|
||||
// - @param {Object} m map object.
|
||||
// - @param {Function} callback
|
||||
ensureSRS: function(m, callback) {
|
||||
Step(
|
||||
function autodetectSRS() {
|
||||
@ -48,6 +40,8 @@ mess.Renderer = function Renderer(env) {
|
||||
fs.readdir(path.dirname(l.Datasource.file), this);
|
||||
},
|
||||
function(err, files) {
|
||||
// Confirm that layers have .prj files
|
||||
// in line with the .shp and .dbf, etc files.
|
||||
var prj = _.detect(files, function(f) {
|
||||
return path.extname(f).toLowerCase() == '.prj';
|
||||
});
|
||||
@ -78,15 +72,13 @@ mess.Renderer = function Renderer(env) {
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Download any file-based remote datsources.
|
||||
*
|
||||
* Usable as an entry point: does not expect any modification to
|
||||
* the map object beyond JSON parsing.
|
||||
*
|
||||
* @param {Object} m map object.
|
||||
* @param {Function} callback
|
||||
*/
|
||||
// Download any file-based remote datsources.
|
||||
//
|
||||
// Usable as an entry point: does not expect any modification to
|
||||
// the map object beyond JSON parsing.
|
||||
//
|
||||
// - @param {Object} m map object.
|
||||
// - @param {Function} callback
|
||||
localizeExternals: function(m, callback) {
|
||||
var that = this;
|
||||
if (env.only_validate === true) {
|
||||
@ -130,12 +122,10 @@ mess.Renderer = function Renderer(env) {
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Download any remote stylesheets
|
||||
*
|
||||
* @param {Object} m map object.
|
||||
* @param {Function} callback
|
||||
*/
|
||||
// Download any remote stylesheets
|
||||
//
|
||||
// - @param {Object} m map object.
|
||||
// - @param {Function} callback
|
||||
localizeStyle: function(m, callback) {
|
||||
var that = this;
|
||||
Step(
|
||||
@ -144,6 +134,8 @@ mess.Renderer = function Renderer(env) {
|
||||
m.Stylesheet.forEach(function(s, k) {
|
||||
if (!s.id) {
|
||||
var next = group();
|
||||
// TODO: handle stylesheet externals
|
||||
// that fail.
|
||||
new External(that.env, s)
|
||||
.on('complete', function(external) {
|
||||
m.Stylesheet[k] = external.path();
|
||||
@ -159,16 +151,14 @@ mess.Renderer = function Renderer(env) {
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Compile (already downloaded) styles with mess.js,
|
||||
* calling callback with an array of [map object, [stylesheet objects]]
|
||||
*
|
||||
* Called with the results of localizeStyle or localizeExternals:
|
||||
* expects not to handle downloading.
|
||||
*
|
||||
* @param {Object} m map object.
|
||||
* @param {Function} callback
|
||||
*/
|
||||
// Compile (already downloaded) styles with mess.js,
|
||||
// calling callback with an array of [map object, [stylesheet objects]]
|
||||
//
|
||||
// Called with the results of localizeStyle or localizeExternals:
|
||||
// expects not to handle downloading.
|
||||
//
|
||||
// - @param {Object} m map object.
|
||||
// - @param {Function} callback
|
||||
style: function(m, callback) {
|
||||
var that = this;
|
||||
Step(
|
||||
@ -176,8 +166,13 @@ mess.Renderer = function Renderer(env) {
|
||||
var group = this.group();
|
||||
m.Stylesheet.forEach(function(s) {
|
||||
var next = group();
|
||||
// If a stylesheet is an object with an id
|
||||
// property, it will have a .data property
|
||||
// as well which can be parsed directly
|
||||
if (s.id) {
|
||||
next(null, [s.id, s.data]);
|
||||
// Otherwise the value is assumed to be a
|
||||
// string and is read from the filesystem
|
||||
} else {
|
||||
fs.readFile(s, 'utf-8', function(err, data) {
|
||||
next(err, [s, data]);
|
||||
@ -191,6 +186,9 @@ mess.Renderer = function Renderer(env) {
|
||||
results.forEach(function(result) {
|
||||
var next = group();
|
||||
var parsingTime = +new Date;
|
||||
// Maintain a parsing environment from
|
||||
// stylesheet to stylesheet, so that frames
|
||||
// and effects are maintained.
|
||||
var parse_env = _.extend(
|
||||
_.extend(
|
||||
that.env,
|
||||
@ -219,17 +217,18 @@ mess.Renderer = function Renderer(env) {
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Split definitions into sub-lists of definitions
|
||||
* containing rules pertaining to only one
|
||||
* symbolizer each
|
||||
*/
|
||||
// Split definitions into sub-lists of definitions
|
||||
// containing rules pertaining to only one
|
||||
// symbolizer each
|
||||
splitSymbolizers: function(definitions) {
|
||||
var splitTime = +new Date;
|
||||
var bySymbolizer = {};
|
||||
for (var i = 0; i < definitions.length; i++) {
|
||||
definitions[i].symbolizers().forEach(function(sym) {
|
||||
var index = sym + (definitions[i].selector.attachment ? '/' + definitions[i].selector.attachment : '');
|
||||
// Maintain attachments
|
||||
var index = sym + (definitions[i].selector.attachment ?
|
||||
'/' + definitions[i].selector.attachment :
|
||||
'');
|
||||
if(!bySymbolizer[index]) {
|
||||
bySymbolizer[index] = [];
|
||||
}
|
||||
@ -237,15 +236,14 @@ mess.Renderer = function Renderer(env) {
|
||||
definitions[i].filterSymbolizer(sym));
|
||||
});
|
||||
}
|
||||
if (env.debug) console.warn('Splitting symbolizers: ' + ((new Date - splitTime)) + 'ms');
|
||||
if (env.debug) console.warn('Splitting symbolizers: '
|
||||
+ ((new Date - splitTime)) + 'ms');
|
||||
return bySymbolizer;
|
||||
},
|
||||
|
||||
/**
|
||||
* Pick the 'winners' - all elements that select
|
||||
* properly. Apply inherited styles from their
|
||||
* ancestors to them.
|
||||
*/
|
||||
// Pick the 'winners' - all elements that select
|
||||
// properly. Apply inherited styles from their
|
||||
// ancestors to them.
|
||||
processChain: function(definitions) {
|
||||
var processTime = +new Date();
|
||||
// definitions are ordered in specificity,
|
||||
@ -261,8 +259,8 @@ mess.Renderer = function Renderer(env) {
|
||||
}
|
||||
}
|
||||
|
||||
if (env.debug) console.warn('Processing time: ' + ((new Date - processTime)) + 'ms');
|
||||
|
||||
if (env.debug) console.warn('Processing time: '
|
||||
+ ((new Date - processTime)) + 'ms');
|
||||
return definitions;
|
||||
},
|
||||
|
||||
@ -294,9 +292,14 @@ mess.Renderer = function Renderer(env) {
|
||||
var filters;
|
||||
for (var id1 in byFilter) {
|
||||
for (var id2 in byFilter) {
|
||||
// If selectors are identical, they can't be merged.
|
||||
if (id1 === id2) continue;
|
||||
// If selectors don't cover the exact same zoom range,
|
||||
// they can't be merged.
|
||||
if (byFilter[id1].zoom != byFilter[id2].zoom) continue;
|
||||
if (filters = tree.Filter.mergable(byFilter[id1].filters, byFilter[id2].filters)) {
|
||||
if (filters = tree.Filter.mergable(
|
||||
byFilter[id1].filters,
|
||||
byFilter[id2].filters)) {
|
||||
byFilter[id1].filters = filters;
|
||||
delete byFilter[id2];
|
||||
}
|
||||
@ -310,6 +313,10 @@ mess.Renderer = function Renderer(env) {
|
||||
return result;
|
||||
},
|
||||
|
||||
// Resolve conditions: with the current state of Mapnik
|
||||
// and the goal of CSS-like behavior, it is necessary to
|
||||
// ensure that only one Rule, and thus only one Filter,
|
||||
// is applied out of a Style.
|
||||
resolveConditions: function(definitions) {
|
||||
var renderer = this;
|
||||
var resolvingTime = +new Date;
|
||||
@ -364,20 +371,18 @@ mess.Renderer = function Renderer(env) {
|
||||
input = next;
|
||||
}
|
||||
|
||||
if (env.debug) console.warn('Resolving time: ' + ((new Date - resolvingTime)) + 'ms');
|
||||
// process.exit();
|
||||
if (env.debug) console.warn('Resolving time: '
|
||||
+ ((new Date - resolvingTime)) + 'ms');
|
||||
return rules;
|
||||
},
|
||||
|
||||
/**
|
||||
* Find a rule like Map { background-color: #fff; },
|
||||
* if any, and return a list of properties to be inserted
|
||||
* into the <Map element of the resulting XML.
|
||||
*
|
||||
* @param {Array} rulesets the output of toList.
|
||||
* @param {Object} env.
|
||||
* @return {String} rendered properties.
|
||||
*/
|
||||
// Find a rule like Map { background-color: #fff; },
|
||||
// if any, and return a list of properties to be inserted
|
||||
// into the <Map element of the resulting XML.
|
||||
//
|
||||
// - @param {Array} rulesets the output of toList.
|
||||
// - @param {Object} env.
|
||||
// - @return {String} rendered properties.
|
||||
getMapProperties: function(rulesets, env) {
|
||||
var properties = [];
|
||||
rulesets.filter(function(r) {
|
||||
@ -391,13 +396,11 @@ mess.Renderer = function Renderer(env) {
|
||||
return properties.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepare full XML map output. Called with the results
|
||||
* of this.style
|
||||
*
|
||||
* @param {Array} res array of [map object, stylesheets].
|
||||
* @param {Function} callback
|
||||
*/
|
||||
// Prepare full XML map output. Called with the results
|
||||
// of this.style
|
||||
//
|
||||
// - @param {Array} res array of [map object, stylesheets].
|
||||
// - @param {Function} callback
|
||||
template: function(err, m, stylesheets, callback) {
|
||||
// frames is a container for variables and other less.js
|
||||
// constructs.
|
||||
@ -425,8 +428,12 @@ mess.Renderer = function Renderer(env) {
|
||||
return rulesets[1].toList(env);
|
||||
}));
|
||||
|
||||
// Iterate through layers and create styles custom-built
|
||||
// for each of them, and apply those styles to the layers.
|
||||
m.Layer.forEach(function(l) {
|
||||
l.styles = [];
|
||||
// Classes are given as space-separated alphanumeric
|
||||
// strings.
|
||||
var classes = (l['class'] || '').split(/\s+/g);
|
||||
|
||||
var matching = rulesets.filter(function(ruleset) {
|
||||
@ -464,7 +471,11 @@ mess.Renderer = function Renderer(env) {
|
||||
function() {
|
||||
var group = this.group();
|
||||
var map_properties = that.getMapProperties(rulesets, env);
|
||||
if (env.only_validate !== true && env.deferred_externals.length) {
|
||||
// The only_validate flag can be set to prevent
|
||||
// any externals from being downloaded - for instance,
|
||||
// when only validation is needed.
|
||||
if (env.only_validate !== true &&
|
||||
env.deferred_externals.length) {
|
||||
env.deferred_externals.forEach(function(def) {
|
||||
var next = group();
|
||||
new External(that.env, def)
|
||||
@ -501,18 +512,20 @@ mess.Renderer = function Renderer(env) {
|
||||
}
|
||||
});
|
||||
|
||||
callback(env.errors.length ? env.errors : null, output.join('\n'));
|
||||
callback(env.errors.length ?
|
||||
env.errors :
|
||||
null,
|
||||
output.join('\n'));
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepare a JML document (given as a string) into a
|
||||
* fully-localized XML file ready for Mapnik2 consumption
|
||||
*
|
||||
* @param {String} str the JSON file as a string.
|
||||
* @param {Function} callback to be called with err, XML representation.
|
||||
*/
|
||||
// Prepare a MML document (given as a string) into a
|
||||
// fully-localized XML file ready for Mapnik2 consumption
|
||||
//
|
||||
// - @param {String} str the JSON file as a string.
|
||||
// - @param {Function} callback to be called with err,
|
||||
// XML representation.
|
||||
render: function(str, callback) {
|
||||
var m = (typeof str == "string") ? JSON.parse(str) : str,
|
||||
that = this;
|
||||
@ -521,11 +534,13 @@ mess.Renderer = function Renderer(env) {
|
||||
this.localizeExternals(m, function(err, res) {
|
||||
that.ensureSRS(res, function(err, res) {
|
||||
that.localizeStyle(res, function(err, res) {
|
||||
if (env.debug) console.warn('Localizing time: ' + ((new Date - localizingTime)) + 'ms');
|
||||
if (env.debug) console.warn('Localizing time: '
|
||||
+ ((new Date - localizingTime)) + 'ms');
|
||||
that.style(res, function(err, m, res) {
|
||||
var compilingTime = +new Date;
|
||||
that.template(err, m, res, function(err, res) {
|
||||
if (env.debug) console.warn('COMPILING TIME: ' + ((new Date - compilingTime)) + 'ms');
|
||||
if (env.debug) console.warn('COMPILING TIME: '
|
||||
+ ((new Date - compilingTime)) + 'ms');
|
||||
callback(err, res);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user