UNPKG

@loaders.gl/wkt

Version:

Loader and Writer for the WKT (Well Known Text) Format

150 lines (123 loc) 3.57 kB
// loaders.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors // parse-wkt-crs was forked from https://github.com/DanielJDufour/wkt-crs under Creative Commons CC0 1.0 license. /* eslint-disable no-console */ // TODO switch to options.log export type ParseWKTCRSOptions = { sort?: boolean; keywords?: string[]; raw?: boolean; debug?: boolean; }; export type WKTCRS = any; /** * * @param wkt * @param options * @returns */ export function parseWKTCRS(wkt: string, options?: ParseWKTCRSOptions): WKTCRS { if (options?.debug) { console.log('[wktcrs] parse starting with\n', wkt); } // move all keywords into first array item slot // from PARAM[12345, 67890] to ["PARAM", 12345, 67890] wkt = wkt.replace(/[A-Z][A-Z\d_]+\[/gi, (match) => `["${match.substr(0, match.length - 1)}",`); // wrap variables in strings // from [...,NORTH] to [...,"NORTH"] wkt = wkt.replace(/, ?([A-Z][A-Z\d_]+[,\]])/gi, (match, p1) => { const varname = p1.substr(0, p1.length - 1); return ',' + `"${options?.raw ? 'raw:' : ''}${varname}"${p1[p1.length - 1]}`; }); if (options?.raw) { // replace all numbers with strings wkt = wkt.replace(/, {0,2}(-?[\.\d]+)(?=,|\])/g, function (match, p1) { return ',' + `"${options?.raw ? 'raw:' : ''}${p1}"`; }); } // str should now be valid JSON if (options?.debug) { console.log(`[wktcrs] json'd wkt: '${wkt}'`); } let data; try { data = JSON.parse(wkt); } catch (error) { console.error(`[wktcrs] failed to parse '${wkt}'`); throw error; } if (options?.debug) { console.log(`[wktcrs] json parsed: '${wkt}'`); } function process(data, parent) { const kw = data[0]; // after removing the first element with .shift() // data is now just an array of attributes data.forEach(function (it) { if (Array.isArray(it)) { process(it, data); } }); const kwarr = `MULTIPLE_${kw}`; if (kwarr in parent) { parent[kwarr].push(data); } else if (kw in parent) { parent[kwarr] = [parent[kw], data]; delete parent[kw]; } else { parent[kw] = data; } return parent; } const result = process(data, [data]); if (options?.debug) { console.log('[wktcrs] parse returning', result); } if (options?.sort) { sort(result, options); } return result; } function sort(data: string[], options?: {keywords?: string[]}) { const keys = Object.keys(data).filter((k) => !/\d+/.test(k)); const keywords: string[] = options?.keywords || []; if (!options?.keywords) { // try to find multiples const counts = {}; if (Array.isArray(data)) { data.forEach((it) => { if (Array.isArray(it) && it.length >= 2 && typeof it[1] === 'string') { const k = it[0]; if (!counts[k]) counts[k] = 0; counts[k]++; } }); for (const k in counts) { if (counts[k] > 0) keywords.push(k); } } } keys.forEach((key) => { data[key] = sort(data[key]); }); keywords.forEach((key) => { const indices: number[] = []; const params: string[] = []; data.forEach((item, i) => { if (Array.isArray(item) && item[0] === key) { indices.push(i); params.push(item); } }); params.sort((a, b) => { a = a[1].toString(); b = b[1].toString(); return a < b ? -1 : a > b ? 1 : 0; }); // replace in order params.forEach((param, i) => { data[indices[i]] = param; }); }); return data; }