├── .gitignore
├── ADVANCED_USAGE.md
├── BUILDS.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── analyze.js
├── create-build-list.sh
├── demo
├── get-epsg-code.web.js
├── get-epsg-code.web.js.map
└── index.html
├── enums.js
├── hash.js
├── normalize
├── esriwkt.js
├── ogcwkt.js
├── proj4.js
├── rows.js
├── test.js
└── wkt.js
├── package.json
├── parse
├── proj4js.js
└── test.js
├── prebuild.js
├── setup.sh
├── src
├── get-proj-type.js
└── index.js
└── test
├── data
├── 3031.json
├── 32617.gml
├── 32617.json
├── 3857.json
├── 4326.json
└── setup.sh
├── test.html
└── test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
106 | lib
107 | *.csv
108 | *.dat
109 | *.esriwkt
110 | *.geoserver
111 | *.gml
112 | *.gz
113 | *.mapfile
114 | *.mapnik
115 | *.postgis
116 | *.proj4
117 | *.txt
118 | test/data/*.js
119 | *.wkt
120 | *.xml
121 |
122 | *.min.js
123 | *.zip
124 | pnpm-lock.yaml
125 | .parcel-cache
126 | log
127 | *bak*
128 |
--------------------------------------------------------------------------------
/ADVANCED_USAGE.md:
--------------------------------------------------------------------------------
1 | # Advanced Usage
2 |
3 | ## Builds
4 | The identification of the following formats are included in all the available builds.
5 | This is because it doesn't add any significant size to your bundle to identify the EPSG code for these formats:
6 | - GeoServer Config
7 | - Graphic Markup Language (GML)
8 | - Mapfile (MapServer Configuration)
9 | - Mapnik Configuration
10 | - Open Geospatial Consortium Well-Known Text (OGC WKT)
11 | - PostGIS Statement
12 | - Proj4js Definition Statement
13 | - Open Geospatial Consortium XML
14 |
15 | However, identifying ESRI WKT, Mapfiles, Mapnik Configurations, and Proj4 Strings require embedding a compressed data file of valid hashes.
16 | Therefore, trimmed builds are provided as well, noting which formats are excluded.
17 |
18 |
19 | ### Requiring Bundles
20 | You can require a specific build with the following code:
21 | ```js
22 | const getEPSGCode = require('get-epsg-code/dist/get-epsg-code-including-esriwkt-proj4.node.min.js');
23 | ```
24 | You can find a list of all of the builds and their file size at [BUILDS.md](https://github.com/DanielJDufour/get-epsg-code/blob/master/BUILDS.md)
25 |
26 | ### Requiring Un-Bundled Files
27 | You can require un-bundled NodeJS-compatabile JavaScript files inside the lib folder.
28 | ```js
29 | // lookup without mapfile support
30 | const getEPSGCode = require('get-epsg-code/lib/lookup-esriwkt-proj4.js');
31 | ```
--------------------------------------------------------------------------------
/BUILDS.md:
--------------------------------------------------------------------------------
1 | # Builds
2 | | name | file size |
3 | | ---- | --------- |
4 | | get-epsg-code-including-esriwkt-proj.node.min.js | 94K |
5 | | get-epsg-code-including-esriwkt-proj.web.min.js | 94K |
6 | | get-epsg-code-including-esriwkt-proj4.node.min.js | 94K |
7 | | get-epsg-code-including-esriwkt-proj4.web.min.js | 94K |
8 | | get-epsg-code.node.js | 142K |
9 | | get-epsg-code.node.min.js | 118K |
10 | | get-epsg-code.web.js | 145K |
11 | | get-epsg-code.web.min.js | 118K |
12 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | # Getting Set Up
4 | 1) Fork https://github.com/danieljdufour/get-epsg-code
5 | 2) Clone your fork
6 |
7 | # Install Dependencies
8 | ```bash
9 | npm install
10 | ```
11 |
12 | # Download Coordinate Reference System Data
13 | ```bash
14 | npm run download-csv
15 | ```
16 |
17 | # Download Test Data
18 | ```bash
19 | npm run setup
20 | ```
21 |
22 | # Build the Compressed Data File
23 | ```bash
24 | npm run prebuild
25 | ```
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Creative Commons Legal Code
2 |
3 | CC0 1.0 Universal
4 |
5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
12 | HEREUNDER.
13 |
14 | Statement of Purpose
15 |
16 | The laws of most jurisdictions throughout the world automatically confer
17 | exclusive Copyright and Related Rights (defined below) upon the creator
18 | and subsequent owner(s) (each and all, an "owner") of an original work of
19 | authorship and/or a database (each, a "Work").
20 |
21 | Certain owners wish to permanently relinquish those rights to a Work for
22 | the purpose of contributing to a commons of creative, cultural and
23 | scientific works ("Commons") that the public can reliably and without fear
24 | of later claims of infringement build upon, modify, incorporate in other
25 | works, reuse and redistribute as freely as possible in any form whatsoever
26 | and for any purposes, including without limitation commercial purposes.
27 | These owners may contribute to the Commons to promote the ideal of a free
28 | culture and the further production of creative, cultural and scientific
29 | works, or to gain reputation or greater distribution for their Work in
30 | part through the use and efforts of others.
31 |
32 | For these and/or other purposes and motivations, and without any
33 | expectation of additional consideration or compensation, the person
34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she
35 | is an owner of Copyright and Related Rights in the Work, voluntarily
36 | elects to apply CC0 to the Work and publicly distribute the Work under its
37 | terms, with knowledge of his or her Copyright and Related Rights in the
38 | Work and the meaning and intended legal effect of CC0 on those rights.
39 |
40 | 1. Copyright and Related Rights. A Work made available under CC0 may be
41 | protected by copyright and related or neighboring rights ("Copyright and
42 | Related Rights"). Copyright and Related Rights include, but are not
43 | limited to, the following:
44 |
45 | i. the right to reproduce, adapt, distribute, perform, display,
46 | communicate, and translate a Work;
47 | ii. moral rights retained by the original author(s) and/or performer(s);
48 | iii. publicity and privacy rights pertaining to a person's image or
49 | likeness depicted in a Work;
50 | iv. rights protecting against unfair competition in regards to a Work,
51 | subject to the limitations in paragraph 4(a), below;
52 | v. rights protecting the extraction, dissemination, use and reuse of data
53 | in a Work;
54 | vi. database rights (such as those arising under Directive 96/9/EC of the
55 | European Parliament and of the Council of 11 March 1996 on the legal
56 | protection of databases, and under any national implementation
57 | thereof, including any amended or successor version of such
58 | directive); and
59 | vii. other similar, equivalent or corresponding rights throughout the
60 | world based on applicable law or treaty, and any national
61 | implementations thereof.
62 |
63 | 2. Waiver. To the greatest extent permitted by, but not in contravention
64 | of, applicable law, Affirmer hereby overtly, fully, permanently,
65 | irrevocably and unconditionally waives, abandons, and surrenders all of
66 | Affirmer's Copyright and Related Rights and associated claims and causes
67 | of action, whether now known or unknown (including existing as well as
68 | future claims and causes of action), in the Work (i) in all territories
69 | worldwide, (ii) for the maximum duration provided by applicable law or
70 | treaty (including future time extensions), (iii) in any current or future
71 | medium and for any number of copies, and (iv) for any purpose whatsoever,
72 | including without limitation commercial, advertising or promotional
73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
74 | member of the public at large and to the detriment of Affirmer's heirs and
75 | successors, fully intending that such Waiver shall not be subject to
76 | revocation, rescission, cancellation, termination, or any other legal or
77 | equitable action to disrupt the quiet enjoyment of the Work by the public
78 | as contemplated by Affirmer's express Statement of Purpose.
79 |
80 | 3. Public License Fallback. Should any part of the Waiver for any reason
81 | be judged legally invalid or ineffective under applicable law, then the
82 | Waiver shall be preserved to the maximum extent permitted taking into
83 | account Affirmer's express Statement of Purpose. In addition, to the
84 | extent the Waiver is so judged Affirmer hereby grants to each affected
85 | person a royalty-free, non transferable, non sublicensable, non exclusive,
86 | irrevocable and unconditional license to exercise Affirmer's Copyright and
87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the
88 | maximum duration provided by applicable law or treaty (including future
89 | time extensions), (iii) in any current or future medium and for any number
90 | of copies, and (iv) for any purpose whatsoever, including without
91 | limitation commercial, advertising or promotional purposes (the
92 | "License"). The License shall be deemed effective as of the date CC0 was
93 | applied by Affirmer to the Work. Should any part of the License for any
94 | reason be judged legally invalid or ineffective under applicable law, such
95 | partial invalidity or ineffectiveness shall not invalidate the remainder
96 | of the License, and in such case Affirmer hereby affirms that he or she
97 | will not (i) exercise any of his or her remaining Copyright and Related
98 | Rights in the Work or (ii) assert any associated claims and causes of
99 | action with respect to the Work, in either case contrary to Affirmer's
100 | express Statement of Purpose.
101 |
102 | 4. Limitations and Disclaimers.
103 |
104 | a. No trademark or patent rights held by Affirmer are waived, abandoned,
105 | surrendered, licensed or otherwise affected by this document.
106 | b. Affirmer offers the Work as-is and makes no representations or
107 | warranties of any kind concerning the Work, express, implied,
108 | statutory or otherwise, including without limitation warranties of
109 | title, merchantability, fitness for a particular purpose, non
110 | infringement, or the absence of latent or other defects, accuracy, or
111 | the present or absence of errors, whether or not discoverable, all to
112 | the greatest extent permissible under applicable law.
113 | c. Affirmer disclaims responsibility for clearing rights of other persons
114 | that may apply to the Work or any use thereof, including without
115 | limitation any person's Copyright and Related Rights in the Work.
116 | Further, Affirmer disclaims responsibility for obtaining any necessary
117 | consents, permissions or other rights required for any use of the
118 | Work.
119 | d. Affirmer understands and acknowledges that Creative Commons is not a
120 | party to this document and has no duty or obligation with respect to
121 | this CC0 or use of the Work.
122 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # get-epsg-code: *beta*
2 | Gets the EPSG Code for Nearly All Coordinate Reference System Formats (including OGC WKT, WKT 2, ESRI WKT, GeoServer Config, Mapfile, Mapnik Config, PostGIS Statement, PROJJSON, PROJ String, and Proj4JS String)
3 | s
4 | # usage
5 | ```javascript
6 | const getEPSGCode = require("get-epsg-code");
7 |
8 | const proj4string = "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs";
9 |
10 | const epsgCode = getEPSGCode(proj4string);
11 | // 3857
12 | ```
13 |
14 | # purpose
15 | Get the EPSG code for input without the need for a remote server
16 |
17 | # algorithm
18 | Take a CSV of Coordinate Reference System formats, hash the columns and stores the result in a binary file.
19 |
20 | # limitations
21 | This package goes only one way. It only gets EPSG codes for a given input. It cannot provide coordinate information for an EPSG code.
22 |
23 | # advanced usage
24 | For advanced usage, see [ADVANCED_USAGE.md](https://github.com/DanielJDufour/get-epsg-code/blob/master/ADVANCED_USAGE.md)
25 |
26 | # contact
27 | Post an issue at https://github.com/danieljdufour/get-epsg-code/issues or email the package author at daniel.j.dufour@gmail.com
28 |
--------------------------------------------------------------------------------
/analyze.js:
--------------------------------------------------------------------------------
1 | const { readFileSync } = require("fs");
2 | const { parse } = require("papaparse");
3 | const normalize_rows = require("./normalize/rows.js");
4 |
5 | // first read all rows from original CSv
6 | const string = readFileSync("./crs.csv", "utf-8");
7 | const parsed = parse(string, { header: true, skipEmptyLines: true });
8 | const original_rows = parsed.data;
9 |
10 | // find dupes
11 | normalize_rows(original_rows);
12 |
13 | const hashed_rows = require("./lib/lookup-esriwkt-mapfile-proj4.js")._load_rows();
14 |
15 | const hash2code = {};
16 | hashed_rows.reduce((acc, { epsg_code, ...rest }) => {
17 | Object.entries(rest).forEach(([field, hash]) => {
18 | if (!hash2code[field]) hash2code[field] = {};
19 | if (!hash2code[field][hash]) hash2code[field][hash] = [];
20 | hash2code[field][hash].push(epsg_code);
21 | });
22 | }, {});
23 | // console.log("hash2code:", hash2code);
24 |
25 | let collisions = 0;
26 |
27 | // remove uniques
28 | for (let fieldName in hash2code) {
29 | for (let hash in hash2code[fieldName]) {
30 | if (hash2code[fieldName][hash].length == 1) {
31 | delete hash2code[fieldName][hash];
32 | } else {
33 | const inputs = hash2code[fieldName][hash].map(code => {
34 | return original_rows.find(r => r.code == code)[fieldName];
35 | });
36 | if (new Set(inputs).size > 1) {
37 | // only collision if inputs aren't the same
38 | collisions++;
39 | // throw new Error("collision for field " + fieldName + " hash " + hash + " for codes " + hash2code[fieldName][hash]);
40 | }
41 | }
42 | }
43 | }
44 |
45 | console.log("collisions:", collisions);
46 |
47 | if (collisions > 0) {
48 | throw Error("there are collisions");
49 | }
50 |
--------------------------------------------------------------------------------
/create-build-list.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | echo "starting create-build-list.sh"
4 |
5 | echo '# Builds' > BUILDS.md
6 |
7 | echo '| name | file size |' >> BUILDS.md
8 |
9 | echo '| ---- | --------- |' >> BUILDS.md
10 |
11 | ls -alsh dist | grep 'get-epsg-code' | awk 'BEGIN { OFS = " | " }{ print "| "$10,$6" |" }' | grep '.js ' >> BUILDS.md
12 |
--------------------------------------------------------------------------------
/demo/get-epsg-code.web.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://get-epsg-code/./enums.js","webpack://get-epsg-code/./lib/enums.js","webpack://get-epsg-code/./lib/get-proj-type.js","webpack://get-epsg-code/./lib/hash.js","webpack://get-epsg-code/./lib/lookup-esriwkt-mapfile-proj4.js","webpack://get-epsg-code/./lib/normalize/esriwkt.js","webpack://get-epsg-code/./lib/normalize/proj4.js","webpack://get-epsg-code/./node_modules/.pnpm/b64ab@0.0.1/node_modules/b64ab/b64ab.js","webpack://get-epsg-code/./node_modules/.pnpm/is-wkt@0.1.0/node_modules/is-wkt/is-wkt.js","webpack://get-epsg-code/./node_modules/.pnpm/utm-utils@0.5.0/node_modules/utm-utils/src/getCodeFromEsriWKT.js","webpack://get-epsg-code/./node_modules/.pnpm/utm-utils@0.5.0/node_modules/utm-utils/src/getCodeFromProjString.js","webpack://get-epsg-code/./node_modules/.pnpm/wkt-parser@1.3.3/node_modules/wkt-parser/index.js","webpack://get-epsg-code/./node_modules/.pnpm/wkt-parser@1.3.3/node_modules/wkt-parser/parser.js","webpack://get-epsg-code/./node_modules/.pnpm/wkt-parser@1.3.3/node_modules/wkt-parser/process.js","webpack://get-epsg-code/./node_modules/.pnpm/xml-utils@1.7.0/node_modules/xml-utils/count-substring.js","webpack://get-epsg-code/./node_modules/.pnpm/xml-utils@1.7.0/node_modules/xml-utils/find-tag-by-name.js","webpack://get-epsg-code/./node_modules/.pnpm/xml-utils@1.7.0/node_modules/xml-utils/find-tag-by-path.js","webpack://get-epsg-code/./node_modules/.pnpm/xml-utils@1.7.0/node_modules/xml-utils/find-tags-by-name.js","webpack://get-epsg-code/./node_modules/.pnpm/xml-utils@1.7.0/node_modules/xml-utils/find-tags-by-path.js","webpack://get-epsg-code/./node_modules/.pnpm/xml-utils@1.7.0/node_modules/xml-utils/get-attribute.js","webpack://get-epsg-code/./node_modules/.pnpm/xml-utils@1.7.0/node_modules/xml-utils/index-of-match-end.js","webpack://get-epsg-code/./node_modules/.pnpm/xml-utils@1.7.0/node_modules/xml-utils/index-of-match.js","webpack://get-epsg-code/webpack/bootstrap","webpack://get-epsg-code/webpack/runtime/define property getters","webpack://get-epsg-code/webpack/runtime/hasOwnProperty shorthand","webpack://get-epsg-code/webpack/runtime/make namespace object","webpack://get-epsg-code/webpack/runtime/node module decorator","webpack://get-epsg-code/webpack/startup"],"names":[],"mappings":";;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;;;;;;;;;;AChBA,cAAc,mBAAO,CAAC,+EAAQ;;AAE9B,OAAO,UAAU,GAAG,mBAAO,CAAC,+BAAa;;AAEzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA,yBAAyB;AACzB;AACA,GAAG;AACH;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,GAAG;AACH;AACA;AACA,KAAK;AACL;AACA;AACA,GAAG;AACH;AACA,GAAG;AACH;AACA,GAAG,eAAe,IAAI;AACtB;AACA,GAAG;AACH;AACA,GAAG;AACH;AACA,GAAG;AACH;AACA,GAAG;AACH;AACA;AACA;;AAEA;AACA,sBAAsB;;;;;;;;;;;ACrDtB;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa,mBAAmB;AAChC;AACA;AACA,cAAc;AACd;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA,sBAAsB;;;;;;;;;;;AClCtB,cAAc,mBAAO,CAAC,2EAAO;AAC7B,sBAAsB,mBAAO,CAAC,mHAA4B;AAC1D,sBAAsB,mBAAO,CAAC,mHAA4B;AAC1D,qBAAqB,mBAAO,CAAC,6GAAyB;AACtD,iBAAiB,mBAAO,CAAC,0FAAY;AACrC,2BAA2B,mBAAO,CAAC,kIAAqC;AACxE,8BAA8B,mBAAO,CAAC,wIAAwC;;AAE9E,aAAa,mBAAO,CAAC,gCAAW;AAChC,sBAAsB,iGAAmD;AACzE,oBAAoB,2FAA+C;AACnE,oBAAoB,mBAAO,CAAC,kDAAoB;AAChD,OAAO,UAAU,GAAG,mBAAO,CAAC,kCAAY;;AAExC,aAAa,mBAAO,CAAC,gFAAmC;;AAExD;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA,uBAAuB,cAAc;AACrC;AACA,2BAA2B,gBAAgB;AAC3C;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA,iBAAiB,mBAAmB;AACpC;AACA;;AAEA;AACA;AACA,GAAG;AACH,2EAA2E,QAAQ;AACnF;AACA,GAAG;AACH,+EAA+E,QAAQ;AACvF,GAAG;AACH,gCAAgC,QAAQ;AACxC;;AAEA;AACA;AACA,KAAK;AACL;AACA;AACA,GAAG;AACH;AACA,GAAG;AACH,mCAAmC,IAAI;AACvC,GAAG;AACH;AACA,gDAAgD,KAAK;AACrD,KAAK;AACL,iCAAiC,IAAI;AACrC;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,GAAG;AACH;AACA,+CAA+C;AAC/C;AACA,GAAG;AACH;AACA;AACA;;AAEA,IAAI,KAA6B;AACjC;AACA;AACA;AACA;AACA,CAAC;AACD,oCAAoC;AACpC;;;;;;;;;;;;ACpIA;AACA;;AAEA;AACA,oCAAoC,IAAI;;AAExC;AACA;AACA,aAAa,kBAAkB;;AAE/B;AACA,kBAAkB;;AAElB,IAAI,IAA0C;AAC9C,IAAI,mCAAO,YAAY,SAAS,qBAAqB,EAAE;AAAA,kGAAC;AACxD,C;;;;;;;;;;ACfA;AACA;AACA,WAAW,OAAO;AAClB,aAAa,OAAO;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,KAAK;AACN;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA,kBAAkB;;;;;;;;;;;ACjClB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,0BAA0B,QAAQ;AAClC;AACA;AACA;AACA;AACA,iBAAiB,UAAU;AAC3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,eAAe;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,IAAI,IAA0C;AAC9C,EAAE,mCAAO,YAAY,eAAe;AAAA,kGAAC;AACrC;;AAEA,IAAI,IAA0B;AAC9B;AACA;;;;;;;;;;;ACxEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,mBAAmB,qBAAqB;AACxC;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;;AAEA,IAAI,IAA0C;AAC9C,EAAE,mCAAO;AACT;AACA,GAAG;AAAA,kGAAC;AACJ;;AAEA,IAAI,IAA0B;AAC9B;AACA,EAAE,sBAAsB;AACxB;AACA;AACA;;;;;;;;;;;AC1CA;AACA;AACA;AACA;AACA;AACA,wCAAwC,IAAI;AAC5C;AACA;AACA;AACA;AACA,GAAG,4CAA4C,IAAI;AACnD;AACA;AACA;AACA;AACA;;AAEA,IAAI,IAA0C;AAC9C;AACA;AACA;AACA;;AAEA,IAAI,IAA0B;AAC9B;AACA,EAAE,sBAAsB;AACxB;;;;;;;;;;;AC1BA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;;AAEA,IAAI,IAA0C;AAC9C;AACA;AACA;AACA;;AAEA,IAAI,IAA0B;AAC9B;AACA,EAAE,sBAAsB;AACxB;;;;;;;;;;;;;;;;;;AC5BA;AAC8B;AACE;;;;AAIhC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA,GAAG;AACH;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,yCAAyC,QAAQ;AACjD;AACA;AACA;AACA,OAAO;AACP;AACA,OAAO;AACP;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA,6BAAe,oCAAS;AACxB,aAAa,gDAAM;AACnB;AACA;AACA;AACA;AACA;AACA,EAAE,+CAAK;AACP;AACA;AACA;;;;;;;;;;;;;;;;AC5MA,iEAAe,WAAW,EAAC;;AAE3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;ACtKA;AACA;AACA;AACA;AACA;AACA,sBAAsB;;AAEtB;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;;AAEO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;AChHA;AACA;AACA;AACA;AACA;;AAEA;AACA,sBAAsB;;;;;;;;;;;ACPtB,qBAAqB,mBAAO,CAAC,0GAAqB;AAClD,wBAAwB,mBAAO,CAAC,kHAAyB;AACzD,uBAAuB,mBAAO,CAAC,4GAAsB;;AAErD;AACA;AACA;;AAEA;;AAEA;;AAEA,uCAAuC,QAAQ;AAC/C;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,GAAG;AACH;AACA;;AAEA,UAAU;AACV;;AAEA;AACA,sBAAsB;;;;;;;;;;;AC5DtB,uBAAuB,mBAAO,CAAC,gHAAwB;;AAEvD;AACA;AACA,2CAA2C,6BAA6B;AACxE;AACA;AACA;AACA;AACA,sBAAsB;;;;;;;;;;;ACTtB,sBAAsB,mBAAO,CAAC,8GAAuB;;AAErD;AACA;AACA;AACA;AACA;AACA;AACA,6CAA6C,oBAAoB;AACjE;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,sBAAsB;;;;;;;;;;;ACrBtB,uBAAuB,mBAAO,CAAC,gHAAwB;;AAEvD;AACA;AACA;AACA,gDAAgD,uBAAuB;AACvE;AACA,yBAAyB,yBAAyB;AAClD;AACA;AACA;AACA,0BAA0B,wBAAwB;AAClD;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,sBAAsB;;;;;;;;;;;AChCtB;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA,iBAAiB,uBAAuB;AACxC;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,sBAAsB;;;;;;;;;;;ACvBtB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,sBAAsB;;;;;;;;;;;ACRtB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,sBAAsB;;;;;;;UCRtB;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;;;;WCzBA;WACA;WACA;WACA;WACA,wCAAwC,yCAAyC;WACjF;WACA;WACA,E;;;;;WCPA,wF;;;;;WCAA;WACA;WACA;WACA,sDAAsD,kBAAkB;WACxE;WACA,+CAA+C,cAAc;WAC7D,E;;;;;WCNA;WACA;WACA;WACA;WACA,E;;;;;UCJA;UACA;UACA;UACA","file":"./get-epsg-code.web.js","sourcesContent":["const FORMATS = {\n ESRI_WKT: 'esriwkt',\n GEOSERVER: 'geoserver',\n MAPFILE: 'mapfile',\n MAPNIK: 'mapnik',\n OGC_GML: 'gml',\n OGC_XML: 'xml',\n OGC_WKT: 'wkt',\n POSTGIS: 'postgis',\n PROJ_4: 'proj4',\n PROJ_4_JS: 'js',\n PROJJSON: 'PROJJSON'\n};\n\nmodule.exports = {\n FORMATS\n};\n","const FORMATS = {\n ESRI_WKT: 'esriwkt',\n GEOSERVER: 'geoserver',\n MAPFILE: 'mapfile',\n MAPNIK: 'mapnik',\n OGC_GML: 'gml',\n OGC_XML: 'xml',\n OGC_WKT: 'wkt',\n POSTGIS: 'postgis',\n PROJ_4: 'proj4',\n PROJ_4_JS: 'js',\n PROJJSON: 'PROJJSON'\n};\n\nmodule.exports = {\n FORMATS\n};\n","const isWKT = require(\"is-wkt\");\n\nconst { FORMATS } = require('../enums.js');\n\nconst {\n ESRI_WKT,\n GEOSERVER,\n MAPFILE,\n MAPNIK,\n OGC_GML,\n OGC_XML,\n OGC_WKT,\n POSTGIS,\n PROJ_4,\n PROJ_4_JS,\n PROJJSON\n} = FORMATS;\n\nfunction getProjType(input) {\n // check WKT\n if (input.startsWith(\"{\") && input.includes(\"projjson\")) {\n return PROJJSON;\n } else if (isWKT(input)) {\n if (input.includes(\"AUTHORITY\")) {\n return OGC_WKT;\n } else {\n // appears to be ESRI WKT\n return ESRI_WKT;\n }\n } else if (input.includes(\"gml:ProjectedCRS\") || input.includes(\"gml:GeodeticCRS\") || input.includes(\"gml:GeographicCRS\")) {\n if (input.includes(\"gml:srsID\")) {\n return OGC_XML;\n } else {\n return OGC_GML;\n }\n } else if (input.startsWith(\"+proj=\")) {\n return PROJ_4;\n } else if (input.startsWith(`proj4.defs(\"EPSG:`)) {\n return PROJ_4_JS;\n } else if (/^\\d{1,6}\\=(PROJCS|GEOGCS)/.test(input)) {\n return GEOSERVER;\n } else if (input.startsWith(\"PROJECTION\") && input.endsWith(\"END\")) {\n return MAPFILE;\n } else if (input.endsWith('')) {\n return MAPNIK;\n } else if (input.startsWith('INSERT')) {\n return POSTGIS;\n } else {\n return \"SOMETHING ELSE\";\n }\n}\n\nmodule.exports = getProjType;\nmodule.exports.default = getProjType;\n","function hash(string) {\n // sometimes might have extra space at end from epsg.io\n string = string.trim();\n\n // replace new lines with spaces\n string = string.replace(/\\n/g, ' ');\n\n // replace tabs with spaces\n string = string.replace(/\\t/g, ' ');\n\n // remove any extra spaces\n string = string.replace(/ +/g, ' ');\n\n if (string[0] === \"+\") {\n // if proj4, sort keys\n string = string.split(\" \").sort().join(\" \")\n }\n\n let hash = 0, i, chr;\n if (string.length === 0) return hash;\n const string_length = string.length;\n for (i = 0; i < string_length; i++) {\n chr = string.charCodeAt(i);\n hash = ((hash << 5) - hash) + chr;\n hash |= 0; // Convert to 32bit integer\n }\n\n // convert to 16-bit\n hash = Math.round(hash / Math.pow(2, 16));\n\n return hash;\n}\n\nmodule.exports = hash;\nmodule.exports.default = hash;\n","const b64ab = require(\"b64ab\");\nconst findTagByPath = require('xml-utils/find-tag-by-path');\nconst findTagByName = require('xml-utils/find-tag-by-name');\nconst getAttribute = require('xml-utils/get-attribute');\nconst parseWKT = require('wkt-parser');\nconst getCodeFromEsriWKT = require(\"utm-utils/src/getCodeFromEsriWKT.js\");\nconst getCodeFromProjString = require(\"utm-utils/src/getCodeFromProjString.js\");\n\nconst hash = require(\"./hash.js\")\nconst clean_esriwkt = require('./normalize/esriwkt.js').normalize_esriwkt;\nconst clean_proj4 = require('./normalize/proj4.js').normalize_proj4;\nconst getProjType = require('./get-proj-type.js');\nconst { FORMATS } = require(\"./enums.js\");\n\nconst data = require(\"./data/esriwkt-mapfile-proj4.json\");\n\nconst getDefault = fn => fn.default || fn;\n\nconst rows = []\n\nfunction lookup(input, dataType, debug=false) {\n if (rows.length === 0) {\n const decoded = b64ab.toArrayBuffer(data.data);\n const arr = new Int16Array(decoded);\n if (debug) console.log(\"arr:\", arr);\n \n const num_fields = data.properties.columns.length;\n const num_rows = arr.length / num_fields;\n \n for (let r = 0; r < num_rows; r++) {\n const row = {};\n for (let f = 0; f < num_fields; f++) {\n row[data.properties.columns[f]] = arr[r * num_fields + f];\n }\n rows.push(row);\n }\n if (debug) console.log(\"[get-epsg-code] rows:\", rows);\n }\n\n const hashed = hash(input);\n if (debug) console.log(\"[get-epsg-code] hashed:\", hashed);\n\n const found = rows.filter(row => row[dataType] === hashed);\n if (debug) console.log(\"[get-epsg-code] found:\", found);\n\n return found.map(row => row.epsg_code);\n}\n\nconst {\n ESRI_WKT,\n GEOSERVER,\n MAPFILE, \n MAPNIK,\n OGC_GML,\n OGC_XML,\n OGC_WKT,\n POSTGIS,\n PROJ_4,\n PROJ_4_JS\n} = FORMATS;\n\nfunction getEPSGCode(input, options) {\n //console.log(\"starting get-epsg-code with\", input, options);\n var debug = options && options.debug ? options.debug : false;\n\n const dataType = getProjType(input);\n if (debug) console.log(\"dataType:\", dataType);\n\n if (dataType === OGC_WKT) {\n const parsed = getDefault(parseWKT)(input);\n if (debug) console.log(\"parsed:\", parsed);\n if (parsed.AUTHORITY) {\n const authority = parsed.AUTHORITY;\n return Number(authority.epsg || authority.EPSG);\n }\n } else if (dataType == ESRI_WKT) {\n // try utm parsing\n console.log({getCodeFromEsriWKT})\n const code = getDefault(getCodeFromEsriWKT)(input);\n if (code) return code;\n\n input = clean_esriwkt(input);\n return lookup(input, ESRI_WKT, debug);\n } else if (dataType === OGC_GML) {\n const identifier = getDefault(findTagByName)(input, \"gml:identifier\", { debug }).inner;\n return Number(identifier.replace(\"urn:ogc:def:crs:EPSG::\", \"\"));\n } else if (dataType === OGC_XML) {\n return Number(getDefault(findTagByPath)(input, [\"gml:srsID\", \"gml:name\"], { debug }).inner);\n } else if (dataType === PROJ_4) {\n input = clean_proj4(input, { debug });\n console.log(\"cleaned to input:\", input);\n\n if (input.startsWith('+proj=utm')) {\n return getCodeFromProjString(input);\n } else {\n return lookup(input, PROJ_4, debug);\n }\n } else if (dataType === PROJ_4_JS) {\n return Number(input.substring(17, input.indexOf(`\"`, 17)));\n } else if (dataType === GEOSERVER) {\n return Number(input.match(/^\\d{1,6}/)[0]);\n } else if (dataType === MAPFILE) {\n if (input.includes('init=epsg:')) {\n return Number.parseInt(/(\"init\\=epsg:)(\\d{1,10})(\")/.exec(input)[2]);\n } else if (input.includes('\"proj=utm\"')) {\n const zone = /(\"zone\\=)(\\d{1,2})(\")/.exec(input)[2];\n const south = input.includes('\"south\"');\n if (input.includes(\"ellps=GRS80\") && south === false) {\n return Number.parseInt('269' + zone);\n } else {\n const hemisphere = south ? '7' : '6';\n return Number.parseInt('32' + hemisphere + zone);\n }\n } else {\n return lookup(input, MAPFILE, debug);\n }\n } else if (dataType === MAPNIK) {\n const map = findTagByName(input, 'Map');\n const srs = getAttribute(map.outer, 'srs'); // Proj.4 String\n return getEPSGCode(srs);\n } else if (dataType === POSTGIS) {\n return Number(input.substring(input.indexOf(\"values (\") + 8, input.indexOf(\"EPSG\") - 3).trim());\n }\n};\n\nif (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {\n module.exports = getEPSGCode;\n}\nif (typeof window !== 'undefined') {\n window['getEPSGCode'] = getEPSGCode;\n} else if (typeof self !== 'undefined') {\n self['getEPSGCode'] = getEPSGCode; // jshint ignore:line\n}\n","function normalize_esriwkt(esriwkt) {\n esriwkt = esriwkt.replace(`DATUM[\"D_`, `DATUM[\"`);\n \n // reduce precision of decimal numbers to 15 digits\n esriwkt = esriwkt.replace(/\\.\\d{16,}/g, n => n.substr(0, 16));\n \n return esriwkt;\n}\nconsole.log({normalize_esriwkt})\n\nconsole.log(\"module:\", module);\nmodule.exports = { normalize_esriwkt };\n\nif (typeof define === \"function\" && define.amd) {\n define(function() { return { normalize_esriwkt }; });\n}","/**\n * \n * @param {String} str - PROJ.4 string\n * @returns {String} normalized PROJ.4 string\n */\nfunction normalize_proj4(str, {\n debug = false,\n remove_k1 = true,\n remove_no_defs = true,\n remove_title = true,\n remove_init=true,\n remove_type=true\n} = {}) {\n // replace any accidental extra spaces\n str = str.replace(/ +/g, ' ');\n\n // sort params\n let parts = str.split(/ ?\\+/g).filter(it => it !== \"\").sort();\n\n // seems like k=1 is interpreted as default for example https://epsg.io/3031.proj4 dropped it\n if (remove_k1) parts = parts.filter(it => it !== \"k=1\");\n if (remove_no_defs) parts = parts.filter(it => it !== \"no_defs\");\n if (remove_type) parts = parts.filter(it => !it.startsWith(\"type\"));\n if (remove_init) parts = parts.filter(it => !it.startsWith(\"init\"));\n if (remove_title) parts = parts.filter(it => !it.startsWith(\"title\"));\n\n str = parts.map(it => \"+\" + it).join(\" \");\n\n if (debug) console.log('normalized proj4 string\\nfrom \"' + arguments[0] + '\"\\nto \"' + str + '\"');\n \n return str;\n}\n\nmodule.exports = { normalize_proj4 };\n","var b64ab = {};\n\nb64ab.char2bits = {\n 0: \"110100\", 1: \"110101\", 2: \"110110\", 3: \"110111\", 4: \"111000\",\n 5: \"111001\", 6: \"111010\", 7: \"111011\", 8: \"111100\", 9: \"111101\",\n A: \"000000\", Q: \"010000\", g: \"100000\", w: \"110000\", B: \"000001\",\n R: \"010001\", h: \"100001\", x: \"110001\", C: \"000010\", S: \"010010\",\n i: \"100010\", y: \"110010\", D: \"000011\", T: \"010011\", j: \"100011\",\n z: \"110011\", E: \"000100\", U: \"010100\", k: \"100100\", F: \"000101\",\n V: \"010101\", l: \"100101\", G: \"000110\", W: \"010110\", m: \"100110\",\n H: \"000111\", X: \"010111\", n: \"100111\", I: \"001000\", Y: \"011000\",\n o: \"101000\", J: \"001001\", Z: \"011001\", p: \"101001\", K: \"001010\",\n a: \"011010\", q: \"101010\", L: \"001011\", b: \"011011\", r: \"101011\",\n M: \"001100\", c: \"011100\", s: \"101100\", N: \"001101\", d: \"011101\",\n t: \"101101\", O: \"001110\", e: \"011110\", u: \"101110\", \"+\": \"111110\",\n P: \"001111\", f: \"011111\", v: \"101111\", \"/\": \"111111\"\n};\n\nb64ab.toArrayBuffer = function toArrayBuffer (b64) {\n var char2bits = b64ab.char2bits;\n var eqct = 0;\n for (let i = b64.length; i >= 0; i--) if (b64[i] === \"=\") eqct++;\n var slen = (b64.length - eqct);\n var l = Math.floor(.75 * slen);\n var u8 = new Uint8Array(l);\n var s = \"\";\n for (var i = 0; i < slen; i++) {\n var char = b64[i];\n if (char === \"=\") break;\n s += char2bits[char];\n if (s.length >= 8) {\n u8[Math.floor(.75 * i)] = parseInt(s.substring(0, 8), 2);\n s = s.substring(8);\n }\n }\n return u8.buffer;\n};\n\nb64ab.toBase64String = function toBase64String(ab) {\n if (!b64ab.bits2char) {\n b64ab.bits2char = {};\n for (let char in b64ab.char2bits) b64ab.bits2char[b64ab.char2bits[char]] = char;\n }\n var bits2char = b64ab.bits2char;\n var u8 = new Uint8Array(ab);\n var s = \"\";\n var b = \"\";\n for (var i = 0; i < u8.length; i++) {\n var n = u8[i].toString(2);\n while (n.length < 8) n = \"0\" + n;\n b += n;\n while (b.length >= 6) {\n s += bits2char[b.substring(0, 6)];\n b = b.substring(6);\n }\n }\n if (b.length > 0) {\n while (b.length < 6) b += \"0\";\n s += bits2char[b];\n }\n while (s.length % 4 !== 0) {\n s += \"=\"\n }\n return s;\n};\n\nif (typeof define === \"function\" && define.amd) {\n define(function() { return b64ab })\n}\n\nif (typeof module === \"object\") module.exports = b64ab;\nif (typeof window === \"object\") window.b64ab = b64ab;\nif (typeof self === \"object\") self.b64ab = b64ab;\n","// keywords are from proj4js\nconst keywords = [\n \"PROJECTEDCRS\",\n \"PROJCRS\",\n \"GEOGCS\",\n \"GEOCCS\",\n \"PROJCS\",\n \"LOCAL_CS\",\n \"GEODCRS\",\n \"GEODETICCRS\",\n \"GEODETICDATUM\",\n \"ENGCRS\",\n \"ENGINEERINGCRS\"\n];\n\nfunction isWKT(str) {\n // clean any blank spaces in beginning\n str = str.trim();\n\n if (str.startsWith(\"PROJCS[\") || str.startsWith(\"GEOGCS[\")) {\n for (let i = 0; i < keywords.length; i++) {\n const kw = keywords[i];\n if (str.indexOf(kw) !== -1) {\n return true;\n }\n }\n } else {\n return false;\n }\n}\n\nif (typeof define === \"function\" && define.amd) {\n define(function () {\n return isWKT;\n });\n}\n\nif (typeof module === \"object\") {\n module.exports = isWKT;\n module.exports.default = isWKT;\n}\nif (typeof self === \"object\") self.isWKT = isWKT;\nif (typeof window === \"object\") window.isWKT = isWKT;\n","function getCodeFromEsriWKT(esri_wkt) {\n if (!esri_wkt) return;\n const match = /PROJCS\\[\\\"([^\"]+)\\\"/.exec(esri_wkt);\n if (!match) return;\n const name = match[1];\n if (name.match(/^WGS_1984_UTM_Zone_\\d{1,2}(N|S)$/)) {\n const last_part = name.split(\"_\").pop();\n const zone = last_part.substring(0, last_part.length - 1);\n const hemisphere = last_part.substring(last_part.length - 1) == \"N\" ? 6 : 7;\n return Number.parseInt(\"32\" + hemisphere + zone);\n } else if (name.match(/^NAD_1983_UTM_Zone_\\d{1,2}N$/)) {\n const last_part = name.split(\"_\").pop();\n const zone = last_part.substring(0, last_part.length - 1);\n return Number.parseInt(\"269\" + zone);\n }\n}\n\nif (typeof define === \"function\" && define.amd) {\n return function () {\n return getCodeFromEsriWKT;\n };\n}\n\nif (typeof module === \"object\") {\n module.exports = getCodeFromEsriWKT;\n module.exports.default = getCodeFromEsriWKT;\n}\n","function getCodeFromProjString(proj) {\n if (proj.startsWith(\"+proj=utm\") && proj.includes(\"+zone=\")) {\n // replace any accidental double spaces\n const parts = proj.split(\" \");\n const zone = parts.find(part => part.startsWith(\"+zone=\")).split(\"=\")[1];\n const south = proj.includes(\"+south\");\n\n let ellps = parts.find(part => part.startsWith(\"+ellps=\"));\n if (ellps) ellps = ellps.split(\"=\")[1];\n\n if (ellps === \"GRS80\" && south === false) {\n return Number.parseInt(\"269\" + zone);\n } else {\n const hemisphere = south ? \"7\" : \"6\";\n return Number.parseInt(\"32\" + hemisphere + zone);\n }\n }\n}\n\nif (typeof define === \"function\" && define.amd) {\n return function () {\n return getCodeFromProjString;\n };\n}\n\nif (typeof module === \"object\") {\n module.exports = getCodeFromProjString;\n module.exports.default = getCodeFromProjString;\n}\n","var D2R = 0.01745329251994329577;\nimport parser from './parser';\nimport {sExpr} from './process';\n\n\n\nfunction rename(obj, params) {\n var outName = params[0];\n var inName = params[1];\n if (!(outName in obj) && (inName in obj)) {\n obj[outName] = obj[inName];\n if (params.length === 3) {\n obj[outName] = params[2](obj[outName]);\n }\n }\n}\n\nfunction d2r(input) {\n return input * D2R;\n}\n\nfunction cleanWKT(wkt) {\n if (wkt.type === 'GEOGCS') {\n wkt.projName = 'longlat';\n } else if (wkt.type === 'LOCAL_CS') {\n wkt.projName = 'identity';\n wkt.local = true;\n } else {\n if (typeof wkt.PROJECTION === 'object') {\n wkt.projName = Object.keys(wkt.PROJECTION)[0];\n } else {\n wkt.projName = wkt.PROJECTION;\n }\n }\n if (wkt.AXIS) {\n var axisOrder = '';\n for (var i = 0, ii = wkt.AXIS.length; i < ii; ++i) {\n var axis = [wkt.AXIS[i][0].toLowerCase(), wkt.AXIS[i][1].toLowerCase()];\n if (axis[0].indexOf('north') !== -1 || ((axis[0] === 'y' || axis[0] === 'lat') && axis[1] === 'north')) {\n axisOrder += 'n';\n } else if (axis[0].indexOf('south') !== -1 || ((axis[0] === 'y' || axis[0] === 'lat') && axis[1] === 'south')) {\n axisOrder += 's';\n } else if (axis[0].indexOf('east') !== -1 || ((axis[0] === 'x' || axis[0] === 'lon') && axis[1] === 'east')) {\n axisOrder += 'e';\n } else if (axis[0].indexOf('west') !== -1 || ((axis[0] === 'x' || axis[0] === 'lon') && axis[1] === 'west')) {\n axisOrder += 'w';\n }\n }\n if (axisOrder.length === 2) {\n axisOrder += 'u';\n }\n if (axisOrder.length === 3) {\n wkt.axis = axisOrder;\n }\n }\n if (wkt.UNIT) {\n wkt.units = wkt.UNIT.name.toLowerCase();\n if (wkt.units === 'metre') {\n wkt.units = 'meter';\n }\n if (wkt.UNIT.convert) {\n if (wkt.type === 'GEOGCS') {\n if (wkt.DATUM && wkt.DATUM.SPHEROID) {\n wkt.to_meter = wkt.UNIT.convert*wkt.DATUM.SPHEROID.a;\n }\n } else {\n wkt.to_meter = wkt.UNIT.convert;\n }\n }\n }\n var geogcs = wkt.GEOGCS;\n if (wkt.type === 'GEOGCS') {\n geogcs = wkt;\n }\n if (geogcs) {\n //if(wkt.GEOGCS.PRIMEM&&wkt.GEOGCS.PRIMEM.convert){\n // wkt.from_greenwich=wkt.GEOGCS.PRIMEM.convert*D2R;\n //}\n if (geogcs.DATUM) {\n wkt.datumCode = geogcs.DATUM.name.toLowerCase();\n } else {\n wkt.datumCode = geogcs.name.toLowerCase();\n }\n if (wkt.datumCode.slice(0, 2) === 'd_') {\n wkt.datumCode = wkt.datumCode.slice(2);\n }\n if (wkt.datumCode === 'new_zealand_geodetic_datum_1949' || wkt.datumCode === 'new_zealand_1949') {\n wkt.datumCode = 'nzgd49';\n }\n if (wkt.datumCode === 'wgs_1984' || wkt.datumCode === 'world_geodetic_system_1984') {\n if (wkt.PROJECTION === 'Mercator_Auxiliary_Sphere') {\n wkt.sphere = true;\n }\n wkt.datumCode = 'wgs84';\n }\n if (wkt.datumCode.slice(-6) === '_ferro') {\n wkt.datumCode = wkt.datumCode.slice(0, - 6);\n }\n if (wkt.datumCode.slice(-8) === '_jakarta') {\n wkt.datumCode = wkt.datumCode.slice(0, - 8);\n }\n if (~wkt.datumCode.indexOf('belge')) {\n wkt.datumCode = 'rnb72';\n }\n if (geogcs.DATUM && geogcs.DATUM.SPHEROID) {\n wkt.ellps = geogcs.DATUM.SPHEROID.name.replace('_19', '').replace(/[Cc]larke\\_18/, 'clrk');\n if (wkt.ellps.toLowerCase().slice(0, 13) === 'international') {\n wkt.ellps = 'intl';\n }\n\n wkt.a = geogcs.DATUM.SPHEROID.a;\n wkt.rf = parseFloat(geogcs.DATUM.SPHEROID.rf, 10);\n }\n\n if (geogcs.DATUM && geogcs.DATUM.TOWGS84) {\n wkt.datum_params = geogcs.DATUM.TOWGS84;\n }\n if (~wkt.datumCode.indexOf('osgb_1936')) {\n wkt.datumCode = 'osgb36';\n }\n if (~wkt.datumCode.indexOf('osni_1952')) {\n wkt.datumCode = 'osni52';\n }\n if (~wkt.datumCode.indexOf('tm65')\n || ~wkt.datumCode.indexOf('geodetic_datum_of_1965')) {\n wkt.datumCode = 'ire65';\n }\n if (wkt.datumCode === 'ch1903+') {\n wkt.datumCode = 'ch1903';\n }\n if (~wkt.datumCode.indexOf('israel')) {\n wkt.datumCode = 'isr93';\n }\n }\n if (wkt.b && !isFinite(wkt.b)) {\n wkt.b = wkt.a;\n }\n\n function toMeter(input) {\n var ratio = wkt.to_meter || 1;\n return input * ratio;\n }\n var renamer = function(a) {\n return rename(wkt, a);\n };\n var list = [\n ['standard_parallel_1', 'Standard_Parallel_1'],\n ['standard_parallel_1', 'Latitude of 1st standard parallel'],\n ['standard_parallel_2', 'Standard_Parallel_2'],\n ['standard_parallel_2', 'Latitude of 2nd standard parallel'],\n ['false_easting', 'False_Easting'],\n ['false_easting', 'False easting'],\n ['false-easting', 'Easting at false origin'],\n ['false_northing', 'False_Northing'],\n ['false_northing', 'False northing'],\n ['false_northing', 'Northing at false origin'],\n ['central_meridian', 'Central_Meridian'],\n ['central_meridian', 'Longitude of natural origin'],\n ['central_meridian', 'Longitude of false origin'],\n ['latitude_of_origin', 'Latitude_Of_Origin'],\n ['latitude_of_origin', 'Central_Parallel'],\n ['latitude_of_origin', 'Latitude of natural origin'],\n ['latitude_of_origin', 'Latitude of false origin'],\n ['scale_factor', 'Scale_Factor'],\n ['k0', 'scale_factor'],\n ['latitude_of_center', 'Latitude_Of_Center'],\n ['latitude_of_center', 'Latitude_of_center'],\n ['lat0', 'latitude_of_center', d2r],\n ['longitude_of_center', 'Longitude_Of_Center'],\n ['longitude_of_center', 'Longitude_of_center'],\n ['longc', 'longitude_of_center', d2r],\n ['x0', 'false_easting', toMeter],\n ['y0', 'false_northing', toMeter],\n ['long0', 'central_meridian', d2r],\n ['lat0', 'latitude_of_origin', d2r],\n ['lat0', 'standard_parallel_1', d2r],\n ['lat1', 'standard_parallel_1', d2r],\n ['lat2', 'standard_parallel_2', d2r],\n ['azimuth', 'Azimuth'],\n ['alpha', 'azimuth', d2r],\n ['srsCode', 'name']\n ];\n list.forEach(renamer);\n if (!wkt.long0 && wkt.longc && (wkt.projName === 'Albers_Conic_Equal_Area' || wkt.projName === 'Lambert_Azimuthal_Equal_Area')) {\n wkt.long0 = wkt.longc;\n }\n if (!wkt.lat_ts && wkt.lat1 && (wkt.projName === 'Stereographic_South_Pole' || wkt.projName === 'Polar Stereographic (variant B)')) {\n wkt.lat0 = d2r(wkt.lat1 > 0 ? 90 : -90);\n wkt.lat_ts = wkt.lat1;\n } else if (!wkt.lat_ts && wkt.lat0 && wkt.projName === 'Polar_Stereographic') {\n wkt.lat_ts = wkt.lat0;\n wkt.lat0 = d2r(wkt.lat0 > 0 ? 90 : -90);\n }\n}\nexport default function(wkt) {\n var lisp = parser(wkt);\n var type = lisp.shift();\n var name = lisp.shift();\n lisp.unshift(['name', name]);\n lisp.unshift(['type', type]);\n var obj = {};\n sExpr(lisp, obj);\n cleanWKT(obj);\n return obj;\n}\n","export default parseString;\n\nvar NEUTRAL = 1;\nvar KEYWORD = 2;\nvar NUMBER = 3;\nvar QUOTED = 4;\nvar AFTERQUOTE = 5;\nvar ENDED = -1;\nvar whitespace = /\\s/;\nvar latin = /[A-Za-z]/;\nvar keyword = /[A-Za-z84_]/;\nvar endThings = /[,\\]]/;\nvar digets = /[\\d\\.E\\-\\+]/;\n// const ignoredChar = /[\\s_\\-\\/\\(\\)]/g;\nfunction Parser(text) {\n if (typeof text !== 'string') {\n throw new Error('not a string');\n }\n this.text = text.trim();\n this.level = 0;\n this.place = 0;\n this.root = null;\n this.stack = [];\n this.currentObject = null;\n this.state = NEUTRAL;\n}\nParser.prototype.readCharicter = function() {\n var char = this.text[this.place++];\n if (this.state !== QUOTED) {\n while (whitespace.test(char)) {\n if (this.place >= this.text.length) {\n return;\n }\n char = this.text[this.place++];\n }\n }\n switch (this.state) {\n case NEUTRAL:\n return this.neutral(char);\n case KEYWORD:\n return this.keyword(char)\n case QUOTED:\n return this.quoted(char);\n case AFTERQUOTE:\n return this.afterquote(char);\n case NUMBER:\n return this.number(char);\n case ENDED:\n return;\n }\n};\nParser.prototype.afterquote = function(char) {\n if (char === '\"') {\n this.word += '\"';\n this.state = QUOTED;\n return;\n }\n if (endThings.test(char)) {\n this.word = this.word.trim();\n this.afterItem(char);\n return;\n }\n throw new Error('havn\\'t handled \"' +char + '\" in afterquote yet, index ' + this.place);\n};\nParser.prototype.afterItem = function(char) {\n if (char === ',') {\n if (this.word !== null) {\n this.currentObject.push(this.word);\n }\n this.word = null;\n this.state = NEUTRAL;\n return;\n }\n if (char === ']') {\n this.level--;\n if (this.word !== null) {\n this.currentObject.push(this.word);\n this.word = null;\n }\n this.state = NEUTRAL;\n this.currentObject = this.stack.pop();\n if (!this.currentObject) {\n this.state = ENDED;\n }\n\n return;\n }\n};\nParser.prototype.number = function(char) {\n if (digets.test(char)) {\n this.word += char;\n return;\n }\n if (endThings.test(char)) {\n this.word = parseFloat(this.word);\n this.afterItem(char);\n return;\n }\n throw new Error('havn\\'t handled \"' +char + '\" in number yet, index ' + this.place);\n};\nParser.prototype.quoted = function(char) {\n if (char === '\"') {\n this.state = AFTERQUOTE;\n return;\n }\n this.word += char;\n return;\n};\nParser.prototype.keyword = function(char) {\n if (keyword.test(char)) {\n this.word += char;\n return;\n }\n if (char === '[') {\n var newObjects = [];\n newObjects.push(this.word);\n this.level++;\n if (this.root === null) {\n this.root = newObjects;\n } else {\n this.currentObject.push(newObjects);\n }\n this.stack.push(this.currentObject);\n this.currentObject = newObjects;\n this.state = NEUTRAL;\n return;\n }\n if (endThings.test(char)) {\n this.afterItem(char);\n return;\n }\n throw new Error('havn\\'t handled \"' +char + '\" in keyword yet, index ' + this.place);\n};\nParser.prototype.neutral = function(char) {\n if (latin.test(char)) {\n this.word = char;\n this.state = KEYWORD;\n return;\n }\n if (char === '\"') {\n this.word = '';\n this.state = QUOTED;\n return;\n }\n if (digets.test(char)) {\n this.word = char;\n this.state = NUMBER;\n return;\n }\n if (endThings.test(char)) {\n this.afterItem(char);\n return;\n }\n throw new Error('havn\\'t handled \"' +char + '\" in neutral yet, index ' + this.place);\n};\nParser.prototype.output = function() {\n while (this.place < this.text.length) {\n this.readCharicter();\n }\n if (this.state === ENDED) {\n return this.root;\n }\n throw new Error('unable to parse string \"' +this.text + '\". State is ' + this.state);\n};\n\nfunction parseString(txt) {\n var parser = new Parser(txt);\n return parser.output();\n}\n","\n\nfunction mapit(obj, key, value) {\n if (Array.isArray(key)) {\n value.unshift(key);\n key = null;\n }\n var thing = key ? {} : obj;\n\n var out = value.reduce(function(newObj, item) {\n sExpr(item, newObj);\n return newObj\n }, thing);\n if (key) {\n obj[key] = out;\n }\n}\n\nexport function sExpr(v, obj) {\n if (!Array.isArray(v)) {\n obj[v] = true;\n return;\n }\n var key = v.shift();\n if (key === 'PARAMETER') {\n key = v.shift();\n }\n if (v.length === 1) {\n if (Array.isArray(v[0])) {\n obj[key] = {};\n sExpr(v[0], obj[key]);\n return;\n }\n obj[key] = v[0];\n return;\n }\n if (!v.length) {\n obj[key] = true;\n return;\n }\n if (key === 'TOWGS84') {\n obj[key] = v;\n return;\n }\n if (key === 'AXIS') {\n if (!(key in obj)) {\n obj[key] = [];\n }\n obj[key].push(v);\n return;\n }\n if (!Array.isArray(key)) {\n obj[key] = {};\n }\n\n var i;\n switch (key) {\n case 'UNIT':\n case 'PRIMEM':\n case 'VERT_DATUM':\n obj[key] = {\n name: v[0].toLowerCase(),\n convert: v[1]\n };\n if (v.length === 3) {\n sExpr(v[2], obj[key]);\n }\n return;\n case 'SPHEROID':\n case 'ELLIPSOID':\n obj[key] = {\n name: v[0],\n a: v[1],\n rf: v[2]\n };\n if (v.length === 4) {\n sExpr(v[3], obj[key]);\n }\n return;\n case 'PROJECTEDCRS':\n case 'PROJCRS':\n case 'GEOGCS':\n case 'GEOCCS':\n case 'PROJCS':\n case 'LOCAL_CS':\n case 'GEODCRS':\n case 'GEODETICCRS':\n case 'GEODETICDATUM':\n case 'EDATUM':\n case 'ENGINEERINGDATUM':\n case 'VERT_CS':\n case 'VERTCRS':\n case 'VERTICALCRS':\n case 'COMPD_CS':\n case 'COMPOUNDCRS':\n case 'ENGINEERINGCRS':\n case 'ENGCRS':\n case 'FITTED_CS':\n case 'LOCAL_DATUM':\n case 'DATUM':\n v[0] = ['name', v[0]];\n mapit(obj, key, v);\n return;\n default:\n i = -1;\n while (++i < v.length) {\n if (!Array.isArray(v[i])) {\n return sExpr(v, obj[key]);\n }\n }\n return mapit(obj, key, v);\n }\n}\n","function countSubstring(string, substring) {\n const pattern = new RegExp(substring, \"g\");\n const match = string.match(pattern);\n return match ? match.length : 0;\n}\n\nmodule.exports = countSubstring;\nmodule.exports.default = countSubstring;\n","const indexOfMatch = require(\"./index-of-match.js\");\nconst indexOfMatchEnd = require(\"./index-of-match-end.js\");\nconst countSubstring = require(\"./count-substring.js\");\n\nfunction findTagByName(xml, tagName, options) {\n const debug = (options && options.debug) || false;\n const nested = !(options && typeof options.nested === false);\n\n const startIndex = (options && options.startIndex) || 0;\n\n if (debug) console.log(\"[xml-utils] starting findTagByName with\", tagName, \" and \", options);\n\n const start = indexOfMatch(xml, `\\<${tagName}[ \\n\\>\\/]`, startIndex);\n if (debug) console.log(\"[xml-utils] start:\", start);\n if (start === -1) return undefined;\n\n const afterStart = xml.slice(start + tagName.length);\n\n let relativeEnd = indexOfMatchEnd(afterStart, \"^[^<]*[ /]>\", 0);\n\n const selfClosing = relativeEnd !== -1 && afterStart[relativeEnd - 1] === \"/\";\n if (debug) console.log(\"[xml-utils] selfClosing:\", selfClosing);\n\n if (selfClosing === false) {\n // check if tag has subtags with the same name\n if (nested) {\n let startIndex = 0;\n let openings = 1;\n let closings = 0;\n while ((relativeEnd = indexOfMatchEnd(afterStart, \"[ /]\" + tagName + \">\", startIndex)) !== -1) {\n const clip = afterStart.substring(startIndex, relativeEnd + 1);\n openings += countSubstring(clip, \"<\" + tagName + \"[ \\n\\t>]\");\n closings += countSubstring(clip, \"\" + tagName + \">\");\n // we can't have more openings than closings\n if (closings >= openings) break;\n startIndex = relativeEnd;\n }\n } else {\n relativeEnd = indexOfMatchEnd(afterStart, \"[ /]\" + tagName + \">\", 0);\n }\n }\n\n const end = start + tagName.length + relativeEnd + 1;\n if (debug) console.log(\"[xml-utils] end:\", end);\n if (end === -1) return undefined;\n\n const outer = xml.slice(start, end);\n // tag is like