carto/bin/cartox
2011-02-07 19:01:34 -05:00

161 lines
4.3 KiB
JavaScript
Executable File

#!/usr/bin/env node
var sax = require('sax'),
fs = require('fs'),
_ = require('underscore')._,
path = require('path'),
sys = require('sys');
require.paths.unshift(path.join(__dirname, '../lib'), path.join(__dirname, '../lib/node'));
var mess = require('carto'),
args = process.argv.slice(1);
var options = {
silent: false,
json: false
};
xml2tree = function(xml, callback) {
var parser = sax.parser(true);
var tree = [ {} ];
parser.onopentag = function(node) {
if (!(node.name in tree[0])) tree[0][node.name] = [];
tree[0][node.name].push(node.attributes);
tree.unshift(node.attributes);
};
parser.onclosetag = function() {
tree.shift();
if (tree.length === 1) callback(tree[0]);
};
parser.ontext = parser.oncdata = function(text) {
if (text.trim()) tree[0].text = (tree[0].text || '') + text;
};
parser.write(xml.toString());
}
args = args.filter(function (arg) {
var match;
if (match = arg.match(/^--?([a-z][0-9a-z-]*)$/i)) { arg = match[1] }
else { return arg }
switch (arg) {
case 'h':
case 'help':
sys.puts("Usage: cartox source");
process.exit(0);
break;
}
});
var input = args[1];
if (input && input[0] != '/') {
input = path.join(process.cwd(), input);
}
var output = args[2];
if (output && output[0] != '/') {
output = path.join(process.cwd(), output);
}
function upStyle(s) {
this.name = s.name;
this.rules = [];
}
upStyle.prototype.toMSS = function() {
return '.' + this.name
+ ' {\n'
+ this.rules.join('\n')
+ '\n}';
}
function upRule(xmlRule) {
this.filters = xmlRule.Filter ? this.upFilter(xmlRule.Filter) : [];
this.rules = this.upSymbolizers(xmlRule);
}
upRule.prototype.upFilter = function(xmlFilter) {
var xmlFilters = xmlFilter[0].text.match(/(\(.*?\))/g);
return _.flatten(xmlFilters.map(function(f) {
return f.replace(/\[(\w+)\]/, "$1").replace(/\)|\(/g, "");
}));
};
upRule.prototype.upSymbolizers = function(xmlRule) {
var css_rules = [];
var symnames = _.map(_.keys(mess.tree.Reference.data.symbolizers), function(symbolizer) {
return [symbolizer.charAt(0).toUpperCase() +
symbolizer.slice(1).replace(/\-./, function(str) {
return str[1].toUpperCase();
}) + 'Symbolizer', mess.tree.Reference.data.symbolizers[symbolizer]];
});
var symmap = _.reduce(symnames, function(memo, s) {
memo[s[0]] = s[1];
return memo;
}, {});
var cssmap = function(symbolizer, name) {
return symmap[symbolizer][name].css;
}
for (var i in xmlRule) {
if (i in symmap) {
for (var j in xmlRule[i][0]) {
if (symmap[i][j].type == 'uri') {
css_rules.push(cssmap(i, j) + ': url("' + xmlRule[i][0][j] + '");');
} else {
css_rules.push(cssmap(i, j) + ': "' + xmlRule[i][0][j] + '";');
}
}
}
}
return css_rules;
};
upRule.prototype.toMSS = function() {
return ' ' + this.filters.map(function(f) {
return '[' + f + ']';
}).join('')
+ ' {\n '
+ this.rules.join('\n ')
+ '\n }';
}
function upDatasource(ds) {
var params = {};
ds[0].Parameter.forEach(function(param) {
params[param.name] = param.text;
});
return params;
}
fs.readFile(input, 'utf-8', function (e, data) {
var styles = [];
var document = {};
var layers = [];
xml2tree(data, function(mapnik_xml) {
mapnik_xml.Map[0].Style.forEach(function(s) {
var newStyle = new upStyle(s);
s.Rule.forEach(function(r) {
newStyle.rules.push((new upRule(r)).toMSS());
});
styles.push(newStyle.toMSS());
});
mapnik_xml.Map[0].Layer.forEach(function(l) {
var newLayer = {
name: l.name,
class: l.name + '_style',
srs: l.srs
};
newLayer.Datasource = upDatasource(l.Datasource);
layers.push(newLayer);
});
document.Stylesheet = [{ id: 'gen', data: styles.join('') }];
document.Layer = layers;
console.log(JSON.stringify(document));
});
});