TopoJSON Remapper

by Bart Kalisz

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
<p>
  This script takes a topojson and re-maps its geometries by given schema. <br />
  If schema contains any names that don't match geometries or not all geometries have been matched it will generate "missing matches" array.
</p>

Babel + JSX

const config = {
	srcTopoJsonUrl: "https://gist.githubusercontent.com/WunderBart/6a3c589643c1978fd5a9/raw/d5c98dc5be842e3b8272c96f13129ea8fbb6220e/world_by_iso_min_topo.json",
	remapSchemeUrl: "https://gist.githubusercontent.com/WunderBart/bbea0b1bae6e91ad73d43a4dc27137b2/raw/aa61edf04b0271f7385e72764abfc4fd44ad613d/country_forums_by_region.json",
	srcCollectionName: "worldByIso",
	newCollectionName: "countryForumsByRegions",
};

class TopoJsonRemapper {
	constructor(config) {
  	this.config = config;
  }

	go = () => {
  	if (!this.isDataReady()) {
			this.fetchData().then(this.handleRemap);
    } else {
			this.handleRemap();
    }
  };

	handleRemap = () => {
		const remappedTopoJson = this.remap();

    this.saveData({ remappedTopoJson });
		this.openJson(remappedTopoJson);

		console.log("Remapped TopoJson:",  remappedTopoJson);
    console.log("Missing matches:", this.data.missingMatches);

		return remappedTopoJson;
  };
  
	fetchSrcTopoJson = url => fetch(url || this.config.srcTopoJsonUrl)
   	.then(response => response.json())
    .then(json => { this.saveData({ srcTopoJson: json }) })
    .catch(error => console.log("fetchTopoJson error:", error));

	fetchRemapScheme = url => fetch(url || this.config.remapSchemeUrl)
  	.then(response => response.json())
    .then(json => { this.saveData({ remapScheme: json }) })    
    .catch(error => console.log("fetchRemapScheme error:", error));

	fetchData = () => Promise.all([this.fetchSrcTopoJson(), this.fetchRemapScheme()]);

	collectArcs = idArray => {
  	const { config, data } = this;
		const { geometries } = data.srcTopoJson.objects[config.srcCollectionName]

		let tmpArcs = [];
		let tmpIdArray = _.map(idArray, this.normalizeText)

		geometries.forEach(geo => {
    	const geoName = this.normalizeText(geo.properties.name);

			if (_.includes(tmpIdArray, geoName)) {
	    	tmpArcs = _.concat(tmpArcs, geo.type === "Polygon" ? [geo.arcs] : geo.arcs);
        tmpIdArray = _.pull(tmpIdArray, geoName);
			}
   ...