├── .deepsource.toml
├── .eslintrc.js
├── .gitattributes
├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── .husky
└── pre-commit
├── CHANGELOG.md
├── CNAME
├── LICENSE
├── README.md
├── docs
├── .nojekyll
├── CNAME
├── assets
│ ├── highlight.css
│ ├── icons.css
│ ├── icons.png
│ ├── icons@2x.png
│ ├── main.js
│ ├── search.js
│ ├── style.css
│ ├── widgets.png
│ └── widgets@2x.png
├── classes
│ └── HintError.html
├── index.html
├── interfaces
│ └── HintIssue.html
└── modules.html
├── lib
├── array_is_numbers.ts
├── check_duplicate_keys.ts
├── enforce_bbox.ts
├── enforce_position.ts
├── enforce_position_array.ts
├── enforce_same_position.ts
├── errors.ts
├── forbid_confusing_properties.ts
├── get_array.ts
├── get_member_value.ts
├── get_object.ts
├── get_type.ts
├── index.ts
└── types.ts
├── mise.toml
├── package.json
├── pnpm-lock.yaml
├── test
├── bad.test.ts
├── fixture
│ ├── bad
│ │ ├── bad-duplicate-properties.cli-output-json
│ │ ├── bad-duplicate-properties.geojson
│ │ ├── bad-featurelist.cli-output-json
│ │ ├── bad-featurelist.geojson
│ │ ├── bad-json.cli-output-json
│ │ ├── bad-json.geojson
│ │ ├── bad-object-type.cli-output-json
│ │ ├── bad-object-type.geojson
│ │ ├── bad-polygonloop.cli-output-json
│ │ ├── bad-polygonloop.geojson
│ │ ├── bad-properties-as-array.cli-output-json
│ │ ├── bad-properties-as-array.geojson
│ │ ├── badcoord.cli-output-json
│ │ ├── badcoord.geojson
│ │ ├── badcoordtype.cli-output-json
│ │ ├── badcoordtype.geojson
│ │ ├── badfeature-no-properties.geojson
│ │ ├── badfeature.cli-output-json
│ │ ├── badfeature.geojson
│ │ ├── badfeatureid.cli-output-json
│ │ ├── badfeatureid.geojson
│ │ ├── bbox-4or6elements.geojson
│ │ ├── bbox-contains-string.geojson
│ │ ├── bbox-string.geojson
│ │ ├── different-first-last.geojson
│ │ ├── different-first-size.geojson
│ │ ├── expected_object.geojson
│ │ ├── false.geojson
│ │ ├── feature_changed_semantics.geojson
│ │ ├── featurecollection-obj.geojson
│ │ ├── featurecollection-type-case.geojson
│ │ ├── featurecollection.geojson
│ │ ├── featurecollection_changed_semantics.geojson
│ │ ├── geometry_changed_semantics.geojson
│ │ ├── geometrycollection_nested.geojson
│ │ ├── multiple_problems.geojson
│ │ ├── multipoint-multidimension.geojson
│ │ ├── multipoint-nocoordinates.geojson
│ │ ├── multipoint-nondimension.geojson
│ │ ├── nofeaturetype.geojson
│ │ ├── notype.geojson
│ │ ├── point-labeled-as-a-multipolygon.geojson
│ │ ├── point-string.geojson
│ │ ├── point-toofew.geojson
│ │ ├── point-toomany.geojson
│ │ ├── point.geojson
│ │ ├── rootstring.geojson
│ │ ├── short-line.geojson
│ │ ├── short-linearring.geojson
│ │ ├── short-multilinestring.geojson
│ │ ├── stringcoord.geojson
│ │ └── unknowntype.geojson
│ └── good
│ │ ├── good-feature-with-id.geojson
│ │ ├── good-feature-with-string-id.geojson
│ │ ├── good-feature.geojson
│ │ ├── good-featurecollection-bbox.geojson
│ │ ├── good-featurecollection-bbox3d.geojson
│ │ ├── good-featurecollection-extensions.geojson
│ │ ├── good-featurecollection.geojson
│ │ ├── good-geometrycollection.geojson
│ │ ├── good-linestring.geojson
│ │ ├── good-multilinestring.geojson
│ │ ├── good-multipoint.geojson
│ │ ├── good-point-3d.geojson
│ │ ├── good-point.geojson
│ │ ├── good-polygon.geojson
│ │ ├── multipolygon.geojson
│ │ ├── nullgeometry.geojson
│ │ └── nullproperties.geojson
├── good.test.ts
└── scavenge.test.ts
├── tsconfig.json
├── typedoc.json
└── types
└── momoa.d.ts
/.deepsource.toml:
--------------------------------------------------------------------------------
1 | version = 1
2 |
3 | test_patterns = [
4 | "**.test.ts",
5 | "**.test.tsx"
6 | ]
7 |
8 | exclude_patterns = ["db/migrations/**"]
9 |
10 | [[analyzers]]
11 | name = "javascript"
12 | enabled = true
13 |
14 | [analyzers.meta]
15 | plugins = ["react"]
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | browser: true,
4 | es2021: true,
5 | },
6 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
7 | parser: '@typescript-eslint/parser',
8 | parserOptions: {
9 | ecmaVersion: 13,
10 | sourceType: 'module',
11 | },
12 | plugins: ['@typescript-eslint'],
13 | rules: {},
14 | ignorePatterns: [
15 | 'docs/*',
16 | 'dist/*.js',
17 | 'dist/*.ts',
18 | '.eslintrc.js',
19 | 'jest.config.js',
20 | ],
21 | };
22 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | docs/* linguist-generated
2 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | on: [push]
2 |
3 | jobs:
4 | test:
5 | uses: "placemark/workflows/.github/workflows/vitest.yml@v3"
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | .DS_Store
3 | node_modules
4 | dist
5 | coverage
6 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | pnpm test run
5 | pnpm lint
6 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4 |
5 | ### [0.1.11](https://github.com/placemark/check-geojson/compare/v0.1.10...v0.1.11) (2022-04-28)
6 |
7 | ### [0.1.10](https://github.com/placemark/check-geojson/compare/v0.1.9...v0.1.10) (2022-04-13)
8 |
9 |
10 | ### Bug Fixes
11 |
12 | * correct module entry point ([455081a](https://github.com/placemark/check-geojson/commit/455081ae6cd482d873b348ecd7d1b5cffb1d20be))
13 |
14 | ### [0.1.9](https://github.com/placemark/check-geojson/compare/v0.1.8...v0.1.9) (2022-03-19)
15 |
16 |
17 | ### Bug Fixes
18 |
19 | * Avoid downlevel iteration ([48dc9f3](https://github.com/placemark/check-geojson/commit/48dc9f3b9a6419eee8125390bf7905916a40f969))
20 |
--------------------------------------------------------------------------------
/CNAME:
--------------------------------------------------------------------------------
1 | check-geojson.docs.placemark.io
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Tom MacWright
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # check-geojson
2 |
3 | A spiritual successor to [geojsonhint](https://github.com/mapbox/geojsonhint), which is no longer maintained.
4 |
5 | check-geojson is a parser and validator for GeoJSON strings. It is tailored to the use cases of validating user-generated GeoJSON content, or troubleshooting GeoJSON that you've received.
6 |
7 | _Note: the API is not yet stable._
8 |
9 | ## [📕 API Documentation](http://check-geojson.docs.placemark.io/)
10 |
11 | ### Main differences from geojsonhint
12 |
13 | - Actively maintained
14 | - Written in TypeScript and includes types
15 | - Uses [momoa](https://github.com/humanwhocodes/momoa) to parse JSON instead of a homemade
16 | parser. This is probably the biggest one. jsonlint-lines was a hack, which I created
17 | because I could not find a single parser that actually parsed JSON and gave line numbers
18 | for values. momoa is much better than that hack, and using it makes line-level errors
19 | much cleaner.
20 |
21 | Unlike geojsonhint, this checker _only_ produces errors, not warnings. So things
22 | that geojsonhint would warn about, like:
23 |
24 | - excessive coordinate precision
25 | - right-hand rule compliance
26 |
27 | This does not check for. Additionally, the `crs` member is ignored by this tool: as of
28 | the latest GeoJSON specification, this is [not used](https://datatracker.ietf.org/doc/html/rfc7946#appendix-B.1).
29 |
30 | We're using the same test fixtures as geojsonhint as a starter.
31 |
32 | ### Install
33 |
34 | ```shell
35 | pnpm add @placemarkio/check-geojson
36 | yarn add @placemarkio/check-geojson
37 | ```
38 |
39 | ### Usage
40 |
41 | ```ts
42 | import { check } from "@placemarkio/check-geojson"
43 |
44 | let geojsonObject;
45 | try {
46 | geojsonObject = check('… geojson string …')
47 | } catch (e) {
48 | /// e.issues
49 | }
50 | ```
51 |
52 | If your GeoJSON is already an object, you will need to convert it to a string first. geojson-check will re-parse it. You should consider the performance penalty of this.
53 |
54 | ```ts
55 | const issues = getIssues(JSON.stringify(geojsonObject));
56 | if (issues.length > 0) {
57 | // ...
58 | }
59 | ```
60 |
61 | ---
62 |
63 | [](https://codeclimate.com/repos/60a64f6aa449b13bc40002bd/maintainability) [](https://codeclimate.com/repos/60a64f6aa449b13bc40002bd/test_coverage)
64 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false.
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | check-geojson.docs.placemark.io
2 |
--------------------------------------------------------------------------------
/docs/assets/highlight.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --light-hl-0: #AF00DB;
3 | --dark-hl-0: #C586C0;
4 | --light-hl-1: #000000;
5 | --dark-hl-1: #D4D4D4;
6 | --light-hl-2: #001080;
7 | --dark-hl-2: #9CDCFE;
8 | --light-hl-3: #A31515;
9 | --dark-hl-3: #CE9178;
10 | --light-hl-4: #0000FF;
11 | --dark-hl-4: #569CD6;
12 | --light-hl-5: #0070C1;
13 | --dark-hl-5: #4FC1FF;
14 | --light-hl-6: #795E26;
15 | --dark-hl-6: #DCDCAA;
16 | --light-hl-7: #008000;
17 | --dark-hl-7: #6A9955;
18 | --light-code-background: #F5F5F5;
19 | --dark-code-background: #1E1E1E;
20 | }
21 |
22 | @media (prefers-color-scheme: light) { :root {
23 | --hl-0: var(--light-hl-0);
24 | --hl-1: var(--light-hl-1);
25 | --hl-2: var(--light-hl-2);
26 | --hl-3: var(--light-hl-3);
27 | --hl-4: var(--light-hl-4);
28 | --hl-5: var(--light-hl-5);
29 | --hl-6: var(--light-hl-6);
30 | --hl-7: var(--light-hl-7);
31 | --code-background: var(--light-code-background);
32 | } }
33 |
34 | @media (prefers-color-scheme: dark) { :root {
35 | --hl-0: var(--dark-hl-0);
36 | --hl-1: var(--dark-hl-1);
37 | --hl-2: var(--dark-hl-2);
38 | --hl-3: var(--dark-hl-3);
39 | --hl-4: var(--dark-hl-4);
40 | --hl-5: var(--dark-hl-5);
41 | --hl-6: var(--dark-hl-6);
42 | --hl-7: var(--dark-hl-7);
43 | --code-background: var(--dark-code-background);
44 | } }
45 |
46 | body.light {
47 | --hl-0: var(--light-hl-0);
48 | --hl-1: var(--light-hl-1);
49 | --hl-2: var(--light-hl-2);
50 | --hl-3: var(--light-hl-3);
51 | --hl-4: var(--light-hl-4);
52 | --hl-5: var(--light-hl-5);
53 | --hl-6: var(--light-hl-6);
54 | --hl-7: var(--light-hl-7);
55 | --code-background: var(--light-code-background);
56 | }
57 |
58 | body.dark {
59 | --hl-0: var(--dark-hl-0);
60 | --hl-1: var(--dark-hl-1);
61 | --hl-2: var(--dark-hl-2);
62 | --hl-3: var(--dark-hl-3);
63 | --hl-4: var(--dark-hl-4);
64 | --hl-5: var(--dark-hl-5);
65 | --hl-6: var(--dark-hl-6);
66 | --hl-7: var(--dark-hl-7);
67 | --code-background: var(--dark-code-background);
68 | }
69 |
70 | .hl-0 { color: var(--hl-0); }
71 | .hl-1 { color: var(--hl-1); }
72 | .hl-2 { color: var(--hl-2); }
73 | .hl-3 { color: var(--hl-3); }
74 | .hl-4 { color: var(--hl-4); }
75 | .hl-5 { color: var(--hl-5); }
76 | .hl-6 { color: var(--hl-6); }
77 | .hl-7 { color: var(--hl-7); }
78 | pre, code { background: var(--code-background); }
79 |
--------------------------------------------------------------------------------
/docs/assets/icons.css:
--------------------------------------------------------------------------------
1 | .tsd-kind-icon {
2 | display: block;
3 | position: relative;
4 | padding-left: 20px;
5 | text-indent: -20px;
6 | }
7 | .tsd-kind-icon:before {
8 | content: "";
9 | display: inline-block;
10 | vertical-align: middle;
11 | width: 17px;
12 | height: 17px;
13 | margin: 0 3px 2px 0;
14 | background-image: url(./icons.png);
15 | }
16 | @media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 144dpi) {
17 | .tsd-kind-icon:before {
18 | background-image: url(./icons@2x.png);
19 | background-size: 238px 204px;
20 | }
21 | }
22 |
23 | .tsd-signature.tsd-kind-icon:before {
24 | background-position: 0 -153px;
25 | }
26 |
27 | .tsd-kind-object-literal > .tsd-kind-icon:before {
28 | background-position: 0px -17px;
29 | }
30 | .tsd-kind-object-literal.tsd-is-protected > .tsd-kind-icon:before {
31 | background-position: -17px -17px;
32 | }
33 | .tsd-kind-object-literal.tsd-is-private > .tsd-kind-icon:before {
34 | background-position: -34px -17px;
35 | }
36 |
37 | .tsd-kind-class > .tsd-kind-icon:before {
38 | background-position: 0px -34px;
39 | }
40 | .tsd-kind-class.tsd-is-protected > .tsd-kind-icon:before {
41 | background-position: -17px -34px;
42 | }
43 | .tsd-kind-class.tsd-is-private > .tsd-kind-icon:before {
44 | background-position: -34px -34px;
45 | }
46 |
47 | .tsd-kind-class.tsd-has-type-parameter > .tsd-kind-icon:before {
48 | background-position: 0px -51px;
49 | }
50 | .tsd-kind-class.tsd-has-type-parameter.tsd-is-protected
51 | > .tsd-kind-icon:before {
52 | background-position: -17px -51px;
53 | }
54 | .tsd-kind-class.tsd-has-type-parameter.tsd-is-private > .tsd-kind-icon:before {
55 | background-position: -34px -51px;
56 | }
57 |
58 | .tsd-kind-interface > .tsd-kind-icon:before {
59 | background-position: 0px -68px;
60 | }
61 | .tsd-kind-interface.tsd-is-protected > .tsd-kind-icon:before {
62 | background-position: -17px -68px;
63 | }
64 | .tsd-kind-interface.tsd-is-private > .tsd-kind-icon:before {
65 | background-position: -34px -68px;
66 | }
67 |
68 | .tsd-kind-interface.tsd-has-type-parameter > .tsd-kind-icon:before {
69 | background-position: 0px -85px;
70 | }
71 | .tsd-kind-interface.tsd-has-type-parameter.tsd-is-protected
72 | > .tsd-kind-icon:before {
73 | background-position: -17px -85px;
74 | }
75 | .tsd-kind-interface.tsd-has-type-parameter.tsd-is-private
76 | > .tsd-kind-icon:before {
77 | background-position: -34px -85px;
78 | }
79 |
80 | .tsd-kind-namespace > .tsd-kind-icon:before {
81 | background-position: 0px -102px;
82 | }
83 | .tsd-kind-namespace.tsd-is-protected > .tsd-kind-icon:before {
84 | background-position: -17px -102px;
85 | }
86 | .tsd-kind-namespace.tsd-is-private > .tsd-kind-icon:before {
87 | background-position: -34px -102px;
88 | }
89 |
90 | .tsd-kind-module > .tsd-kind-icon:before {
91 | background-position: 0px -102px;
92 | }
93 | .tsd-kind-module.tsd-is-protected > .tsd-kind-icon:before {
94 | background-position: -17px -102px;
95 | }
96 | .tsd-kind-module.tsd-is-private > .tsd-kind-icon:before {
97 | background-position: -34px -102px;
98 | }
99 |
100 | .tsd-kind-enum > .tsd-kind-icon:before {
101 | background-position: 0px -119px;
102 | }
103 | .tsd-kind-enum.tsd-is-protected > .tsd-kind-icon:before {
104 | background-position: -17px -119px;
105 | }
106 | .tsd-kind-enum.tsd-is-private > .tsd-kind-icon:before {
107 | background-position: -34px -119px;
108 | }
109 |
110 | .tsd-kind-enum-member > .tsd-kind-icon:before {
111 | background-position: 0px -136px;
112 | }
113 | .tsd-kind-enum-member.tsd-is-protected > .tsd-kind-icon:before {
114 | background-position: -17px -136px;
115 | }
116 | .tsd-kind-enum-member.tsd-is-private > .tsd-kind-icon:before {
117 | background-position: -34px -136px;
118 | }
119 |
120 | .tsd-kind-signature > .tsd-kind-icon:before {
121 | background-position: 0px -153px;
122 | }
123 | .tsd-kind-signature.tsd-is-protected > .tsd-kind-icon:before {
124 | background-position: -17px -153px;
125 | }
126 | .tsd-kind-signature.tsd-is-private > .tsd-kind-icon:before {
127 | background-position: -34px -153px;
128 | }
129 |
130 | .tsd-kind-type-alias > .tsd-kind-icon:before {
131 | background-position: 0px -170px;
132 | }
133 | .tsd-kind-type-alias.tsd-is-protected > .tsd-kind-icon:before {
134 | background-position: -17px -170px;
135 | }
136 | .tsd-kind-type-alias.tsd-is-private > .tsd-kind-icon:before {
137 | background-position: -34px -170px;
138 | }
139 |
140 | .tsd-kind-type-alias.tsd-has-type-parameter > .tsd-kind-icon:before {
141 | background-position: 0px -187px;
142 | }
143 | .tsd-kind-type-alias.tsd-has-type-parameter.tsd-is-protected
144 | > .tsd-kind-icon:before {
145 | background-position: -17px -187px;
146 | }
147 | .tsd-kind-type-alias.tsd-has-type-parameter.tsd-is-private
148 | > .tsd-kind-icon:before {
149 | background-position: -34px -187px;
150 | }
151 |
152 | .tsd-kind-variable > .tsd-kind-icon:before {
153 | background-position: -136px -0px;
154 | }
155 | .tsd-kind-variable.tsd-is-protected > .tsd-kind-icon:before {
156 | background-position: -153px -0px;
157 | }
158 | .tsd-kind-variable.tsd-is-private > .tsd-kind-icon:before {
159 | background-position: -119px -0px;
160 | }
161 | .tsd-kind-variable.tsd-parent-kind-class > .tsd-kind-icon:before {
162 | background-position: -51px -0px;
163 | }
164 | .tsd-kind-variable.tsd-parent-kind-class.tsd-is-inherited
165 | > .tsd-kind-icon:before {
166 | background-position: -68px -0px;
167 | }
168 | .tsd-kind-variable.tsd-parent-kind-class.tsd-is-protected
169 | > .tsd-kind-icon:before {
170 | background-position: -85px -0px;
171 | }
172 | .tsd-kind-variable.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
173 | > .tsd-kind-icon:before {
174 | background-position: -102px -0px;
175 | }
176 | .tsd-kind-variable.tsd-parent-kind-class.tsd-is-private
177 | > .tsd-kind-icon:before {
178 | background-position: -119px -0px;
179 | }
180 | .tsd-kind-variable.tsd-parent-kind-enum > .tsd-kind-icon:before {
181 | background-position: -170px -0px;
182 | }
183 | .tsd-kind-variable.tsd-parent-kind-enum.tsd-is-protected
184 | > .tsd-kind-icon:before {
185 | background-position: -187px -0px;
186 | }
187 | .tsd-kind-variable.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before {
188 | background-position: -119px -0px;
189 | }
190 | .tsd-kind-variable.tsd-parent-kind-interface > .tsd-kind-icon:before {
191 | background-position: -204px -0px;
192 | }
193 | .tsd-kind-variable.tsd-parent-kind-interface.tsd-is-inherited
194 | > .tsd-kind-icon:before {
195 | background-position: -221px -0px;
196 | }
197 |
198 | .tsd-kind-property > .tsd-kind-icon:before {
199 | background-position: -136px -0px;
200 | }
201 | .tsd-kind-property.tsd-is-protected > .tsd-kind-icon:before {
202 | background-position: -153px -0px;
203 | }
204 | .tsd-kind-property.tsd-is-private > .tsd-kind-icon:before {
205 | background-position: -119px -0px;
206 | }
207 | .tsd-kind-property.tsd-parent-kind-class > .tsd-kind-icon:before {
208 | background-position: -51px -0px;
209 | }
210 | .tsd-kind-property.tsd-parent-kind-class.tsd-is-inherited
211 | > .tsd-kind-icon:before {
212 | background-position: -68px -0px;
213 | }
214 | .tsd-kind-property.tsd-parent-kind-class.tsd-is-protected
215 | > .tsd-kind-icon:before {
216 | background-position: -85px -0px;
217 | }
218 | .tsd-kind-property.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
219 | > .tsd-kind-icon:before {
220 | background-position: -102px -0px;
221 | }
222 | .tsd-kind-property.tsd-parent-kind-class.tsd-is-private
223 | > .tsd-kind-icon:before {
224 | background-position: -119px -0px;
225 | }
226 | .tsd-kind-property.tsd-parent-kind-enum > .tsd-kind-icon:before {
227 | background-position: -170px -0px;
228 | }
229 | .tsd-kind-property.tsd-parent-kind-enum.tsd-is-protected
230 | > .tsd-kind-icon:before {
231 | background-position: -187px -0px;
232 | }
233 | .tsd-kind-property.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before {
234 | background-position: -119px -0px;
235 | }
236 | .tsd-kind-property.tsd-parent-kind-interface > .tsd-kind-icon:before {
237 | background-position: -204px -0px;
238 | }
239 | .tsd-kind-property.tsd-parent-kind-interface.tsd-is-inherited
240 | > .tsd-kind-icon:before {
241 | background-position: -221px -0px;
242 | }
243 |
244 | .tsd-kind-get-signature > .tsd-kind-icon:before {
245 | background-position: -136px -17px;
246 | }
247 | .tsd-kind-get-signature.tsd-is-protected > .tsd-kind-icon:before {
248 | background-position: -153px -17px;
249 | }
250 | .tsd-kind-get-signature.tsd-is-private > .tsd-kind-icon:before {
251 | background-position: -119px -17px;
252 | }
253 | .tsd-kind-get-signature.tsd-parent-kind-class > .tsd-kind-icon:before {
254 | background-position: -51px -17px;
255 | }
256 | .tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-inherited
257 | > .tsd-kind-icon:before {
258 | background-position: -68px -17px;
259 | }
260 | .tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-protected
261 | > .tsd-kind-icon:before {
262 | background-position: -85px -17px;
263 | }
264 | .tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
265 | > .tsd-kind-icon:before {
266 | background-position: -102px -17px;
267 | }
268 | .tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-private
269 | > .tsd-kind-icon:before {
270 | background-position: -119px -17px;
271 | }
272 | .tsd-kind-get-signature.tsd-parent-kind-enum > .tsd-kind-icon:before {
273 | background-position: -170px -17px;
274 | }
275 | .tsd-kind-get-signature.tsd-parent-kind-enum.tsd-is-protected
276 | > .tsd-kind-icon:before {
277 | background-position: -187px -17px;
278 | }
279 | .tsd-kind-get-signature.tsd-parent-kind-enum.tsd-is-private
280 | > .tsd-kind-icon:before {
281 | background-position: -119px -17px;
282 | }
283 | .tsd-kind-get-signature.tsd-parent-kind-interface > .tsd-kind-icon:before {
284 | background-position: -204px -17px;
285 | }
286 | .tsd-kind-get-signature.tsd-parent-kind-interface.tsd-is-inherited
287 | > .tsd-kind-icon:before {
288 | background-position: -221px -17px;
289 | }
290 |
291 | .tsd-kind-set-signature > .tsd-kind-icon:before {
292 | background-position: -136px -34px;
293 | }
294 | .tsd-kind-set-signature.tsd-is-protected > .tsd-kind-icon:before {
295 | background-position: -153px -34px;
296 | }
297 | .tsd-kind-set-signature.tsd-is-private > .tsd-kind-icon:before {
298 | background-position: -119px -34px;
299 | }
300 | .tsd-kind-set-signature.tsd-parent-kind-class > .tsd-kind-icon:before {
301 | background-position: -51px -34px;
302 | }
303 | .tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-inherited
304 | > .tsd-kind-icon:before {
305 | background-position: -68px -34px;
306 | }
307 | .tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-protected
308 | > .tsd-kind-icon:before {
309 | background-position: -85px -34px;
310 | }
311 | .tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
312 | > .tsd-kind-icon:before {
313 | background-position: -102px -34px;
314 | }
315 | .tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-private
316 | > .tsd-kind-icon:before {
317 | background-position: -119px -34px;
318 | }
319 | .tsd-kind-set-signature.tsd-parent-kind-enum > .tsd-kind-icon:before {
320 | background-position: -170px -34px;
321 | }
322 | .tsd-kind-set-signature.tsd-parent-kind-enum.tsd-is-protected
323 | > .tsd-kind-icon:before {
324 | background-position: -187px -34px;
325 | }
326 | .tsd-kind-set-signature.tsd-parent-kind-enum.tsd-is-private
327 | > .tsd-kind-icon:before {
328 | background-position: -119px -34px;
329 | }
330 | .tsd-kind-set-signature.tsd-parent-kind-interface > .tsd-kind-icon:before {
331 | background-position: -204px -34px;
332 | }
333 | .tsd-kind-set-signature.tsd-parent-kind-interface.tsd-is-inherited
334 | > .tsd-kind-icon:before {
335 | background-position: -221px -34px;
336 | }
337 |
338 | .tsd-kind-accessor > .tsd-kind-icon:before {
339 | background-position: -136px -51px;
340 | }
341 | .tsd-kind-accessor.tsd-is-protected > .tsd-kind-icon:before {
342 | background-position: -153px -51px;
343 | }
344 | .tsd-kind-accessor.tsd-is-private > .tsd-kind-icon:before {
345 | background-position: -119px -51px;
346 | }
347 | .tsd-kind-accessor.tsd-parent-kind-class > .tsd-kind-icon:before {
348 | background-position: -51px -51px;
349 | }
350 | .tsd-kind-accessor.tsd-parent-kind-class.tsd-is-inherited
351 | > .tsd-kind-icon:before {
352 | background-position: -68px -51px;
353 | }
354 | .tsd-kind-accessor.tsd-parent-kind-class.tsd-is-protected
355 | > .tsd-kind-icon:before {
356 | background-position: -85px -51px;
357 | }
358 | .tsd-kind-accessor.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
359 | > .tsd-kind-icon:before {
360 | background-position: -102px -51px;
361 | }
362 | .tsd-kind-accessor.tsd-parent-kind-class.tsd-is-private
363 | > .tsd-kind-icon:before {
364 | background-position: -119px -51px;
365 | }
366 | .tsd-kind-accessor.tsd-parent-kind-enum > .tsd-kind-icon:before {
367 | background-position: -170px -51px;
368 | }
369 | .tsd-kind-accessor.tsd-parent-kind-enum.tsd-is-protected
370 | > .tsd-kind-icon:before {
371 | background-position: -187px -51px;
372 | }
373 | .tsd-kind-accessor.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before {
374 | background-position: -119px -51px;
375 | }
376 | .tsd-kind-accessor.tsd-parent-kind-interface > .tsd-kind-icon:before {
377 | background-position: -204px -51px;
378 | }
379 | .tsd-kind-accessor.tsd-parent-kind-interface.tsd-is-inherited
380 | > .tsd-kind-icon:before {
381 | background-position: -221px -51px;
382 | }
383 |
384 | .tsd-kind-function > .tsd-kind-icon:before {
385 | background-position: -136px -68px;
386 | }
387 | .tsd-kind-function.tsd-is-protected > .tsd-kind-icon:before {
388 | background-position: -153px -68px;
389 | }
390 | .tsd-kind-function.tsd-is-private > .tsd-kind-icon:before {
391 | background-position: -119px -68px;
392 | }
393 | .tsd-kind-function.tsd-parent-kind-class > .tsd-kind-icon:before {
394 | background-position: -51px -68px;
395 | }
396 | .tsd-kind-function.tsd-parent-kind-class.tsd-is-inherited
397 | > .tsd-kind-icon:before {
398 | background-position: -68px -68px;
399 | }
400 | .tsd-kind-function.tsd-parent-kind-class.tsd-is-protected
401 | > .tsd-kind-icon:before {
402 | background-position: -85px -68px;
403 | }
404 | .tsd-kind-function.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
405 | > .tsd-kind-icon:before {
406 | background-position: -102px -68px;
407 | }
408 | .tsd-kind-function.tsd-parent-kind-class.tsd-is-private
409 | > .tsd-kind-icon:before {
410 | background-position: -119px -68px;
411 | }
412 | .tsd-kind-function.tsd-parent-kind-enum > .tsd-kind-icon:before {
413 | background-position: -170px -68px;
414 | }
415 | .tsd-kind-function.tsd-parent-kind-enum.tsd-is-protected
416 | > .tsd-kind-icon:before {
417 | background-position: -187px -68px;
418 | }
419 | .tsd-kind-function.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before {
420 | background-position: -119px -68px;
421 | }
422 | .tsd-kind-function.tsd-parent-kind-interface > .tsd-kind-icon:before {
423 | background-position: -204px -68px;
424 | }
425 | .tsd-kind-function.tsd-parent-kind-interface.tsd-is-inherited
426 | > .tsd-kind-icon:before {
427 | background-position: -221px -68px;
428 | }
429 |
430 | .tsd-kind-method > .tsd-kind-icon:before {
431 | background-position: -136px -68px;
432 | }
433 | .tsd-kind-method.tsd-is-protected > .tsd-kind-icon:before {
434 | background-position: -153px -68px;
435 | }
436 | .tsd-kind-method.tsd-is-private > .tsd-kind-icon:before {
437 | background-position: -119px -68px;
438 | }
439 | .tsd-kind-method.tsd-parent-kind-class > .tsd-kind-icon:before {
440 | background-position: -51px -68px;
441 | }
442 | .tsd-kind-method.tsd-parent-kind-class.tsd-is-inherited
443 | > .tsd-kind-icon:before {
444 | background-position: -68px -68px;
445 | }
446 | .tsd-kind-method.tsd-parent-kind-class.tsd-is-protected
447 | > .tsd-kind-icon:before {
448 | background-position: -85px -68px;
449 | }
450 | .tsd-kind-method.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
451 | > .tsd-kind-icon:before {
452 | background-position: -102px -68px;
453 | }
454 | .tsd-kind-method.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before {
455 | background-position: -119px -68px;
456 | }
457 | .tsd-kind-method.tsd-parent-kind-enum > .tsd-kind-icon:before {
458 | background-position: -170px -68px;
459 | }
460 | .tsd-kind-method.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before {
461 | background-position: -187px -68px;
462 | }
463 | .tsd-kind-method.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before {
464 | background-position: -119px -68px;
465 | }
466 | .tsd-kind-method.tsd-parent-kind-interface > .tsd-kind-icon:before {
467 | background-position: -204px -68px;
468 | }
469 | .tsd-kind-method.tsd-parent-kind-interface.tsd-is-inherited
470 | > .tsd-kind-icon:before {
471 | background-position: -221px -68px;
472 | }
473 |
474 | .tsd-kind-call-signature > .tsd-kind-icon:before {
475 | background-position: -136px -68px;
476 | }
477 | .tsd-kind-call-signature.tsd-is-protected > .tsd-kind-icon:before {
478 | background-position: -153px -68px;
479 | }
480 | .tsd-kind-call-signature.tsd-is-private > .tsd-kind-icon:before {
481 | background-position: -119px -68px;
482 | }
483 | .tsd-kind-call-signature.tsd-parent-kind-class > .tsd-kind-icon:before {
484 | background-position: -51px -68px;
485 | }
486 | .tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-inherited
487 | > .tsd-kind-icon:before {
488 | background-position: -68px -68px;
489 | }
490 | .tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected
491 | > .tsd-kind-icon:before {
492 | background-position: -85px -68px;
493 | }
494 | .tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
495 | > .tsd-kind-icon:before {
496 | background-position: -102px -68px;
497 | }
498 | .tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-private
499 | > .tsd-kind-icon:before {
500 | background-position: -119px -68px;
501 | }
502 | .tsd-kind-call-signature.tsd-parent-kind-enum > .tsd-kind-icon:before {
503 | background-position: -170px -68px;
504 | }
505 | .tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-protected
506 | > .tsd-kind-icon:before {
507 | background-position: -187px -68px;
508 | }
509 | .tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-private
510 | > .tsd-kind-icon:before {
511 | background-position: -119px -68px;
512 | }
513 | .tsd-kind-call-signature.tsd-parent-kind-interface > .tsd-kind-icon:before {
514 | background-position: -204px -68px;
515 | }
516 | .tsd-kind-call-signature.tsd-parent-kind-interface.tsd-is-inherited
517 | > .tsd-kind-icon:before {
518 | background-position: -221px -68px;
519 | }
520 |
521 | .tsd-kind-function.tsd-has-type-parameter > .tsd-kind-icon:before {
522 | background-position: -136px -85px;
523 | }
524 | .tsd-kind-function.tsd-has-type-parameter.tsd-is-protected
525 | > .tsd-kind-icon:before {
526 | background-position: -153px -85px;
527 | }
528 | .tsd-kind-function.tsd-has-type-parameter.tsd-is-private
529 | > .tsd-kind-icon:before {
530 | background-position: -119px -85px;
531 | }
532 | .tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class
533 | > .tsd-kind-icon:before {
534 | background-position: -51px -85px;
535 | }
536 | .tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-inherited
537 | > .tsd-kind-icon:before {
538 | background-position: -68px -85px;
539 | }
540 | .tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected
541 | > .tsd-kind-icon:before {
542 | background-position: -85px -85px;
543 | }
544 | .tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
545 | > .tsd-kind-icon:before {
546 | background-position: -102px -85px;
547 | }
548 | .tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-private
549 | > .tsd-kind-icon:before {
550 | background-position: -119px -85px;
551 | }
552 | .tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum
553 | > .tsd-kind-icon:before {
554 | background-position: -170px -85px;
555 | }
556 | .tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-protected
557 | > .tsd-kind-icon:before {
558 | background-position: -187px -85px;
559 | }
560 | .tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-private
561 | > .tsd-kind-icon:before {
562 | background-position: -119px -85px;
563 | }
564 | .tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-interface
565 | > .tsd-kind-icon:before {
566 | background-position: -204px -85px;
567 | }
568 | .tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-interface.tsd-is-inherited
569 | > .tsd-kind-icon:before {
570 | background-position: -221px -85px;
571 | }
572 |
573 | .tsd-kind-method.tsd-has-type-parameter > .tsd-kind-icon:before {
574 | background-position: -136px -85px;
575 | }
576 | .tsd-kind-method.tsd-has-type-parameter.tsd-is-protected
577 | > .tsd-kind-icon:before {
578 | background-position: -153px -85px;
579 | }
580 | .tsd-kind-method.tsd-has-type-parameter.tsd-is-private > .tsd-kind-icon:before {
581 | background-position: -119px -85px;
582 | }
583 | .tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class
584 | > .tsd-kind-icon:before {
585 | background-position: -51px -85px;
586 | }
587 | .tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-inherited
588 | > .tsd-kind-icon:before {
589 | background-position: -68px -85px;
590 | }
591 | .tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected
592 | > .tsd-kind-icon:before {
593 | background-position: -85px -85px;
594 | }
595 | .tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
596 | > .tsd-kind-icon:before {
597 | background-position: -102px -85px;
598 | }
599 | .tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-private
600 | > .tsd-kind-icon:before {
601 | background-position: -119px -85px;
602 | }
603 | .tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum
604 | > .tsd-kind-icon:before {
605 | background-position: -170px -85px;
606 | }
607 | .tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-protected
608 | > .tsd-kind-icon:before {
609 | background-position: -187px -85px;
610 | }
611 | .tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-private
612 | > .tsd-kind-icon:before {
613 | background-position: -119px -85px;
614 | }
615 | .tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-interface
616 | > .tsd-kind-icon:before {
617 | background-position: -204px -85px;
618 | }
619 | .tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-interface.tsd-is-inherited
620 | > .tsd-kind-icon:before {
621 | background-position: -221px -85px;
622 | }
623 |
624 | .tsd-kind-constructor > .tsd-kind-icon:before {
625 | background-position: -136px -102px;
626 | }
627 | .tsd-kind-constructor.tsd-is-protected > .tsd-kind-icon:before {
628 | background-position: -153px -102px;
629 | }
630 | .tsd-kind-constructor.tsd-is-private > .tsd-kind-icon:before {
631 | background-position: -119px -102px;
632 | }
633 | .tsd-kind-constructor.tsd-parent-kind-class > .tsd-kind-icon:before {
634 | background-position: -51px -102px;
635 | }
636 | .tsd-kind-constructor.tsd-parent-kind-class.tsd-is-inherited
637 | > .tsd-kind-icon:before {
638 | background-position: -68px -102px;
639 | }
640 | .tsd-kind-constructor.tsd-parent-kind-class.tsd-is-protected
641 | > .tsd-kind-icon:before {
642 | background-position: -85px -102px;
643 | }
644 | .tsd-kind-constructor.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
645 | > .tsd-kind-icon:before {
646 | background-position: -102px -102px;
647 | }
648 | .tsd-kind-constructor.tsd-parent-kind-class.tsd-is-private
649 | > .tsd-kind-icon:before {
650 | background-position: -119px -102px;
651 | }
652 | .tsd-kind-constructor.tsd-parent-kind-enum > .tsd-kind-icon:before {
653 | background-position: -170px -102px;
654 | }
655 | .tsd-kind-constructor.tsd-parent-kind-enum.tsd-is-protected
656 | > .tsd-kind-icon:before {
657 | background-position: -187px -102px;
658 | }
659 | .tsd-kind-constructor.tsd-parent-kind-enum.tsd-is-private
660 | > .tsd-kind-icon:before {
661 | background-position: -119px -102px;
662 | }
663 | .tsd-kind-constructor.tsd-parent-kind-interface > .tsd-kind-icon:before {
664 | background-position: -204px -102px;
665 | }
666 | .tsd-kind-constructor.tsd-parent-kind-interface.tsd-is-inherited
667 | > .tsd-kind-icon:before {
668 | background-position: -221px -102px;
669 | }
670 |
671 | .tsd-kind-constructor-signature > .tsd-kind-icon:before {
672 | background-position: -136px -102px;
673 | }
674 | .tsd-kind-constructor-signature.tsd-is-protected > .tsd-kind-icon:before {
675 | background-position: -153px -102px;
676 | }
677 | .tsd-kind-constructor-signature.tsd-is-private > .tsd-kind-icon:before {
678 | background-position: -119px -102px;
679 | }
680 | .tsd-kind-constructor-signature.tsd-parent-kind-class > .tsd-kind-icon:before {
681 | background-position: -51px -102px;
682 | }
683 | .tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-inherited
684 | > .tsd-kind-icon:before {
685 | background-position: -68px -102px;
686 | }
687 | .tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-protected
688 | > .tsd-kind-icon:before {
689 | background-position: -85px -102px;
690 | }
691 | .tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
692 | > .tsd-kind-icon:before {
693 | background-position: -102px -102px;
694 | }
695 | .tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-private
696 | > .tsd-kind-icon:before {
697 | background-position: -119px -102px;
698 | }
699 | .tsd-kind-constructor-signature.tsd-parent-kind-enum > .tsd-kind-icon:before {
700 | background-position: -170px -102px;
701 | }
702 | .tsd-kind-constructor-signature.tsd-parent-kind-enum.tsd-is-protected
703 | > .tsd-kind-icon:before {
704 | background-position: -187px -102px;
705 | }
706 | .tsd-kind-constructor-signature.tsd-parent-kind-enum.tsd-is-private
707 | > .tsd-kind-icon:before {
708 | background-position: -119px -102px;
709 | }
710 | .tsd-kind-constructor-signature.tsd-parent-kind-interface
711 | > .tsd-kind-icon:before {
712 | background-position: -204px -102px;
713 | }
714 | .tsd-kind-constructor-signature.tsd-parent-kind-interface.tsd-is-inherited
715 | > .tsd-kind-icon:before {
716 | background-position: -221px -102px;
717 | }
718 |
719 | .tsd-kind-index-signature > .tsd-kind-icon:before {
720 | background-position: -136px -119px;
721 | }
722 | .tsd-kind-index-signature.tsd-is-protected > .tsd-kind-icon:before {
723 | background-position: -153px -119px;
724 | }
725 | .tsd-kind-index-signature.tsd-is-private > .tsd-kind-icon:before {
726 | background-position: -119px -119px;
727 | }
728 | .tsd-kind-index-signature.tsd-parent-kind-class > .tsd-kind-icon:before {
729 | background-position: -51px -119px;
730 | }
731 | .tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-inherited
732 | > .tsd-kind-icon:before {
733 | background-position: -68px -119px;
734 | }
735 | .tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-protected
736 | > .tsd-kind-icon:before {
737 | background-position: -85px -119px;
738 | }
739 | .tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
740 | > .tsd-kind-icon:before {
741 | background-position: -102px -119px;
742 | }
743 | .tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-private
744 | > .tsd-kind-icon:before {
745 | background-position: -119px -119px;
746 | }
747 | .tsd-kind-index-signature.tsd-parent-kind-enum > .tsd-kind-icon:before {
748 | background-position: -170px -119px;
749 | }
750 | .tsd-kind-index-signature.tsd-parent-kind-enum.tsd-is-protected
751 | > .tsd-kind-icon:before {
752 | background-position: -187px -119px;
753 | }
754 | .tsd-kind-index-signature.tsd-parent-kind-enum.tsd-is-private
755 | > .tsd-kind-icon:before {
756 | background-position: -119px -119px;
757 | }
758 | .tsd-kind-index-signature.tsd-parent-kind-interface > .tsd-kind-icon:before {
759 | background-position: -204px -119px;
760 | }
761 | .tsd-kind-index-signature.tsd-parent-kind-interface.tsd-is-inherited
762 | > .tsd-kind-icon:before {
763 | background-position: -221px -119px;
764 | }
765 |
766 | .tsd-kind-event > .tsd-kind-icon:before {
767 | background-position: -136px -136px;
768 | }
769 | .tsd-kind-event.tsd-is-protected > .tsd-kind-icon:before {
770 | background-position: -153px -136px;
771 | }
772 | .tsd-kind-event.tsd-is-private > .tsd-kind-icon:before {
773 | background-position: -119px -136px;
774 | }
775 | .tsd-kind-event.tsd-parent-kind-class > .tsd-kind-icon:before {
776 | background-position: -51px -136px;
777 | }
778 | .tsd-kind-event.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before {
779 | background-position: -68px -136px;
780 | }
781 | .tsd-kind-event.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before {
782 | background-position: -85px -136px;
783 | }
784 | .tsd-kind-event.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
785 | > .tsd-kind-icon:before {
786 | background-position: -102px -136px;
787 | }
788 | .tsd-kind-event.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before {
789 | background-position: -119px -136px;
790 | }
791 | .tsd-kind-event.tsd-parent-kind-enum > .tsd-kind-icon:before {
792 | background-position: -170px -136px;
793 | }
794 | .tsd-kind-event.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before {
795 | background-position: -187px -136px;
796 | }
797 | .tsd-kind-event.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before {
798 | background-position: -119px -136px;
799 | }
800 | .tsd-kind-event.tsd-parent-kind-interface > .tsd-kind-icon:before {
801 | background-position: -204px -136px;
802 | }
803 | .tsd-kind-event.tsd-parent-kind-interface.tsd-is-inherited
804 | > .tsd-kind-icon:before {
805 | background-position: -221px -136px;
806 | }
807 |
808 | .tsd-is-static > .tsd-kind-icon:before {
809 | background-position: -136px -153px;
810 | }
811 | .tsd-is-static.tsd-is-protected > .tsd-kind-icon:before {
812 | background-position: -153px -153px;
813 | }
814 | .tsd-is-static.tsd-is-private > .tsd-kind-icon:before {
815 | background-position: -119px -153px;
816 | }
817 | .tsd-is-static.tsd-parent-kind-class > .tsd-kind-icon:before {
818 | background-position: -51px -153px;
819 | }
820 | .tsd-is-static.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before {
821 | background-position: -68px -153px;
822 | }
823 | .tsd-is-static.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before {
824 | background-position: -85px -153px;
825 | }
826 | .tsd-is-static.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
827 | > .tsd-kind-icon:before {
828 | background-position: -102px -153px;
829 | }
830 | .tsd-is-static.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before {
831 | background-position: -119px -153px;
832 | }
833 | .tsd-is-static.tsd-parent-kind-enum > .tsd-kind-icon:before {
834 | background-position: -170px -153px;
835 | }
836 | .tsd-is-static.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before {
837 | background-position: -187px -153px;
838 | }
839 | .tsd-is-static.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before {
840 | background-position: -119px -153px;
841 | }
842 | .tsd-is-static.tsd-parent-kind-interface > .tsd-kind-icon:before {
843 | background-position: -204px -153px;
844 | }
845 | .tsd-is-static.tsd-parent-kind-interface.tsd-is-inherited
846 | > .tsd-kind-icon:before {
847 | background-position: -221px -153px;
848 | }
849 |
850 | .tsd-is-static.tsd-kind-function > .tsd-kind-icon:before {
851 | background-position: -136px -170px;
852 | }
853 | .tsd-is-static.tsd-kind-function.tsd-is-protected > .tsd-kind-icon:before {
854 | background-position: -153px -170px;
855 | }
856 | .tsd-is-static.tsd-kind-function.tsd-is-private > .tsd-kind-icon:before {
857 | background-position: -119px -170px;
858 | }
859 | .tsd-is-static.tsd-kind-function.tsd-parent-kind-class > .tsd-kind-icon:before {
860 | background-position: -51px -170px;
861 | }
862 | .tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-inherited
863 | > .tsd-kind-icon:before {
864 | background-position: -68px -170px;
865 | }
866 | .tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected
867 | > .tsd-kind-icon:before {
868 | background-position: -85px -170px;
869 | }
870 | .tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
871 | > .tsd-kind-icon:before {
872 | background-position: -102px -170px;
873 | }
874 | .tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-private
875 | > .tsd-kind-icon:before {
876 | background-position: -119px -170px;
877 | }
878 | .tsd-is-static.tsd-kind-function.tsd-parent-kind-enum > .tsd-kind-icon:before {
879 | background-position: -170px -170px;
880 | }
881 | .tsd-is-static.tsd-kind-function.tsd-parent-kind-enum.tsd-is-protected
882 | > .tsd-kind-icon:before {
883 | background-position: -187px -170px;
884 | }
885 | .tsd-is-static.tsd-kind-function.tsd-parent-kind-enum.tsd-is-private
886 | > .tsd-kind-icon:before {
887 | background-position: -119px -170px;
888 | }
889 | .tsd-is-static.tsd-kind-function.tsd-parent-kind-interface
890 | > .tsd-kind-icon:before {
891 | background-position: -204px -170px;
892 | }
893 | .tsd-is-static.tsd-kind-function.tsd-parent-kind-interface.tsd-is-inherited
894 | > .tsd-kind-icon:before {
895 | background-position: -221px -170px;
896 | }
897 |
898 | .tsd-is-static.tsd-kind-method > .tsd-kind-icon:before {
899 | background-position: -136px -170px;
900 | }
901 | .tsd-is-static.tsd-kind-method.tsd-is-protected > .tsd-kind-icon:before {
902 | background-position: -153px -170px;
903 | }
904 | .tsd-is-static.tsd-kind-method.tsd-is-private > .tsd-kind-icon:before {
905 | background-position: -119px -170px;
906 | }
907 | .tsd-is-static.tsd-kind-method.tsd-parent-kind-class > .tsd-kind-icon:before {
908 | background-position: -51px -170px;
909 | }
910 | .tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-inherited
911 | > .tsd-kind-icon:before {
912 | background-position: -68px -170px;
913 | }
914 | .tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected
915 | > .tsd-kind-icon:before {
916 | background-position: -85px -170px;
917 | }
918 | .tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
919 | > .tsd-kind-icon:before {
920 | background-position: -102px -170px;
921 | }
922 | .tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-private
923 | > .tsd-kind-icon:before {
924 | background-position: -119px -170px;
925 | }
926 | .tsd-is-static.tsd-kind-method.tsd-parent-kind-enum > .tsd-kind-icon:before {
927 | background-position: -170px -170px;
928 | }
929 | .tsd-is-static.tsd-kind-method.tsd-parent-kind-enum.tsd-is-protected
930 | > .tsd-kind-icon:before {
931 | background-position: -187px -170px;
932 | }
933 | .tsd-is-static.tsd-kind-method.tsd-parent-kind-enum.tsd-is-private
934 | > .tsd-kind-icon:before {
935 | background-position: -119px -170px;
936 | }
937 | .tsd-is-static.tsd-kind-method.tsd-parent-kind-interface
938 | > .tsd-kind-icon:before {
939 | background-position: -204px -170px;
940 | }
941 | .tsd-is-static.tsd-kind-method.tsd-parent-kind-interface.tsd-is-inherited
942 | > .tsd-kind-icon:before {
943 | background-position: -221px -170px;
944 | }
945 |
946 | .tsd-is-static.tsd-kind-call-signature > .tsd-kind-icon:before {
947 | background-position: -136px -170px;
948 | }
949 | .tsd-is-static.tsd-kind-call-signature.tsd-is-protected
950 | > .tsd-kind-icon:before {
951 | background-position: -153px -170px;
952 | }
953 | .tsd-is-static.tsd-kind-call-signature.tsd-is-private > .tsd-kind-icon:before {
954 | background-position: -119px -170px;
955 | }
956 | .tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class
957 | > .tsd-kind-icon:before {
958 | background-position: -51px -170px;
959 | }
960 | .tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-inherited
961 | > .tsd-kind-icon:before {
962 | background-position: -68px -170px;
963 | }
964 | .tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected
965 | > .tsd-kind-icon:before {
966 | background-position: -85px -170px;
967 | }
968 | .tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
969 | > .tsd-kind-icon:before {
970 | background-position: -102px -170px;
971 | }
972 | .tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-private
973 | > .tsd-kind-icon:before {
974 | background-position: -119px -170px;
975 | }
976 | .tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum
977 | > .tsd-kind-icon:before {
978 | background-position: -170px -170px;
979 | }
980 | .tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-protected
981 | > .tsd-kind-icon:before {
982 | background-position: -187px -170px;
983 | }
984 | .tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-private
985 | > .tsd-kind-icon:before {
986 | background-position: -119px -170px;
987 | }
988 | .tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-interface
989 | > .tsd-kind-icon:before {
990 | background-position: -204px -170px;
991 | }
992 | .tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-interface.tsd-is-inherited
993 | > .tsd-kind-icon:before {
994 | background-position: -221px -170px;
995 | }
996 |
997 | .tsd-is-static.tsd-kind-event > .tsd-kind-icon:before {
998 | background-position: -136px -187px;
999 | }
1000 | .tsd-is-static.tsd-kind-event.tsd-is-protected > .tsd-kind-icon:before {
1001 | background-position: -153px -187px;
1002 | }
1003 | .tsd-is-static.tsd-kind-event.tsd-is-private > .tsd-kind-icon:before {
1004 | background-position: -119px -187px;
1005 | }
1006 | .tsd-is-static.tsd-kind-event.tsd-parent-kind-class > .tsd-kind-icon:before {
1007 | background-position: -51px -187px;
1008 | }
1009 | .tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-inherited
1010 | > .tsd-kind-icon:before {
1011 | background-position: -68px -187px;
1012 | }
1013 | .tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected
1014 | > .tsd-kind-icon:before {
1015 | background-position: -85px -187px;
1016 | }
1017 | .tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited
1018 | > .tsd-kind-icon:before {
1019 | background-position: -102px -187px;
1020 | }
1021 | .tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-private
1022 | > .tsd-kind-icon:before {
1023 | background-position: -119px -187px;
1024 | }
1025 | .tsd-is-static.tsd-kind-event.tsd-parent-kind-enum > .tsd-kind-icon:before {
1026 | background-position: -170px -187px;
1027 | }
1028 | .tsd-is-static.tsd-kind-event.tsd-parent-kind-enum.tsd-is-protected
1029 | > .tsd-kind-icon:before {
1030 | background-position: -187px -187px;
1031 | }
1032 | .tsd-is-static.tsd-kind-event.tsd-parent-kind-enum.tsd-is-private
1033 | > .tsd-kind-icon:before {
1034 | background-position: -119px -187px;
1035 | }
1036 | .tsd-is-static.tsd-kind-event.tsd-parent-kind-interface
1037 | > .tsd-kind-icon:before {
1038 | background-position: -204px -187px;
1039 | }
1040 | .tsd-is-static.tsd-kind-event.tsd-parent-kind-interface.tsd-is-inherited
1041 | > .tsd-kind-icon:before {
1042 | background-position: -221px -187px;
1043 | }
1044 |
--------------------------------------------------------------------------------
/docs/assets/icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/placemark/check-geojson/5701f8fe832c10793275c9174dd387829c4b4c7b/docs/assets/icons.png
--------------------------------------------------------------------------------
/docs/assets/icons@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/placemark/check-geojson/5701f8fe832c10793275c9174dd387829c4b4c7b/docs/assets/icons@2x.png
--------------------------------------------------------------------------------
/docs/assets/search.js:
--------------------------------------------------------------------------------
1 | window.searchData = JSON.parse("{\"kinds\":{\"64\":\"Function\",\"128\":\"Class\",\"256\":\"Interface\",\"512\":\"Constructor\",\"1024\":\"Property\",\"65536\":\"Type literal\",\"262144\":\"Accessor\"},\"rows\":[{\"id\":0,\"kind\":64,\"name\":\"getIssues\",\"url\":\"modules.html#getIssues\",\"classes\":\"tsd-kind-function\"},{\"id\":1,\"kind\":64,\"name\":\"check\",\"url\":\"modules.html#check\",\"classes\":\"tsd-kind-function\"},{\"id\":2,\"kind\":64,\"name\":\"scavenge\",\"url\":\"modules.html#scavenge\",\"classes\":\"tsd-kind-function\"},{\"id\":3,\"kind\":128,\"name\":\"HintError\",\"url\":\"classes/HintError.html\",\"classes\":\"tsd-kind-class\"},{\"id\":4,\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/HintError.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"HintError\"},{\"id\":5,\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/HintError.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-overwrite\",\"parent\":\"HintError\"},{\"id\":6,\"kind\":1024,\"name\":\"issues\",\"url\":\"classes/HintError.html#issues\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"HintError\"},{\"id\":7,\"kind\":262144,\"name\":\"message\",\"url\":\"classes/HintError.html#message\",\"classes\":\"tsd-kind-get-signature tsd-parent-kind-class tsd-is-overwrite\",\"parent\":\"HintError\"},{\"id\":8,\"kind\":256,\"name\":\"HintIssue\",\"url\":\"interfaces/HintIssue.html\",\"classes\":\"tsd-kind-interface\"},{\"id\":9,\"kind\":1024,\"name\":\"from\",\"url\":\"interfaces/HintIssue.html#from\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"HintIssue\"},{\"id\":10,\"kind\":1024,\"name\":\"to\",\"url\":\"interfaces/HintIssue.html#to\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"HintIssue\"},{\"id\":11,\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/HintIssue.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"HintIssue\"},{\"id\":12,\"kind\":1024,\"name\":\"severity\",\"url\":\"interfaces/HintIssue.html#severity\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"HintIssue\"},{\"id\":13,\"kind\":1024,\"name\":\"message\",\"url\":\"interfaces/HintIssue.html#message\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"HintIssue\"}],\"index\":{\"version\":\"2.3.9\",\"fields\":[\"name\",\"parent\"],\"fieldVectors\":[[\"name/0\",[0,23.026]],[\"parent/0\",[]],[\"name/1\",[1,23.026]],[\"parent/1\",[]],[\"name/2\",[2,23.026]],[\"parent/2\",[]],[\"name/3\",[3,10.033]],[\"parent/3\",[]],[\"name/4\",[4,23.026]],[\"parent/4\",[3,0.818]],[\"name/5\",[5,23.026]],[\"parent/5\",[3,0.818]],[\"name/6\",[6,23.026]],[\"parent/6\",[3,0.818]],[\"name/7\",[7,17.918]],[\"parent/7\",[3,0.818]],[\"name/8\",[8,8.362]],[\"parent/8\",[]],[\"name/9\",[9,23.026]],[\"parent/9\",[8,0.681]],[\"name/10\",[10,23.026]],[\"parent/10\",[8,0.681]],[\"name/11\",[11,23.026]],[\"parent/11\",[8,0.681]],[\"name/12\",[12,23.026]],[\"parent/12\",[8,0.681]],[\"name/13\",[7,17.918]],[\"parent/13\",[8,0.681]]],\"invertedIndex\":[[\"__type\",{\"_index\":4,\"name\":{\"4\":{}},\"parent\":{}}],[\"check\",{\"_index\":1,\"name\":{\"1\":{}},\"parent\":{}}],[\"constructor\",{\"_index\":5,\"name\":{\"5\":{}},\"parent\":{}}],[\"from\",{\"_index\":9,\"name\":{\"9\":{}},\"parent\":{}}],[\"getissues\",{\"_index\":0,\"name\":{\"0\":{}},\"parent\":{}}],[\"hinterror\",{\"_index\":3,\"name\":{\"3\":{}},\"parent\":{\"4\":{},\"5\":{},\"6\":{},\"7\":{}}}],[\"hintissue\",{\"_index\":8,\"name\":{\"8\":{}},\"parent\":{\"9\":{},\"10\":{},\"11\":{},\"12\":{},\"13\":{}}}],[\"issues\",{\"_index\":6,\"name\":{\"6\":{}},\"parent\":{}}],[\"message\",{\"_index\":7,\"name\":{\"7\":{},\"13\":{}},\"parent\":{}}],[\"node\",{\"_index\":11,\"name\":{\"11\":{}},\"parent\":{}}],[\"scavenge\",{\"_index\":2,\"name\":{\"2\":{}},\"parent\":{}}],[\"severity\",{\"_index\":12,\"name\":{\"12\":{}},\"parent\":{}}],[\"to\",{\"_index\":10,\"name\":{\"10\":{}},\"parent\":{}}]],\"pipeline\":[]}}");
--------------------------------------------------------------------------------
/docs/assets/widgets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/placemark/check-geojson/5701f8fe832c10793275c9174dd387829c4b4c7b/docs/assets/widgets.png
--------------------------------------------------------------------------------
/docs/assets/widgets@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/placemark/check-geojson/5701f8fe832c10793275c9174dd387829c4b4c7b/docs/assets/widgets@2x.png
--------------------------------------------------------------------------------
/docs/classes/HintError.html:
--------------------------------------------------------------------------------
1 |
HintError | @placemarkio/check-geojson Properties Optional causecause?: Error
Optional stackstack?: string
Static Optional prepare Stack Traceprepare Stack Trace?: ( err: Error , stackTraces: CallSite [] ) => any
Type declaration ( err: Error , stackTraces: CallSite [] ) : any Parameters err: Error stackTraces: CallSite [] Returns any Static stack Trace Limitstack Trace Limit: number
Methods Static capture Stack Tracecapture Stack Trace( targetObject: object , constructorOpt?: Function ) : void Parameters targetObject: object Optional constructorOpt: Function Returns void Legend Settings Theme OS Light Dark
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 | @placemarkio/check-geojson
2 |
3 | check-geojson
4 |
5 |
check-geojson development is supported by 🌎 placemark.io
6 |
geojsonhint for 2021.
7 |
I started working on geojsonhint in 2014. It's a pretty useful project.
8 | But it has been stagnant for a long time now, and has some annoying long-term
9 | issues.
10 |
check-geojson is intended to be a full successor for geojsonhint. Like geojsonhint,
11 | it is tailored to a particular usecase: writing GeoJSON by hand, or quickly sussing
12 | out issues in GeoJSON that you've received.
13 |
14 |
15 |
16 |
17 |
18 |
19 | Main differences from geojsonhint
20 |
21 |
22 | Actively maintained
23 | Written in TypeScript and includes types
24 | Uses momoa to parse JSON instead of a homemade
25 | parser. This is probably the biggest one. jsonlint-lines was a hack, which I created
26 | because I could not find a single parser that actually parsed JSON and gave line numbers
27 | for values. momoa is much better than that hack, and using it makes line-level errors
28 | much cleaner.
29 |
30 |
Unlike geojsonhint, this checker only produces errors, not warnings. So things
31 | that geojsonhint would warn about, like:
32 |
33 | excessive coordinate precision
34 | right-hand rule compliance
35 |
36 |
This does not check for. Additionally, the crs
member is ignored by this tool: as of
37 | the latest GeoJSON specification, this is not used .
38 |
We're using the same test fixtures as geojsonhint as a starter.
39 |
40 |
41 | Usage
42 |
43 |
Not finalized yet
44 |
import { check } from "check-geojson" try { const parseValue = check ( '… geojson string …' ) } catch ( e ) { /// e.issues }
45 |
46 |
47 |
48 |
Legend Settings Theme OS Light Dark
--------------------------------------------------------------------------------
/docs/interfaces/HintIssue.html:
--------------------------------------------------------------------------------
1 | HintIssue | @placemarkio/check-geojson Properties severity severity: "error"
Legend Settings Theme OS Light Dark
--------------------------------------------------------------------------------
/docs/modules.html:
--------------------------------------------------------------------------------
1 | @placemarkio/check-geojson Functions check check( jsonStr: string ) : GeoJSON Parameters Returns GeoJSON scavenge scavenge( jsonStr: string ) : { rejected: { feature: any ; reasons: HintIssue [] } [] ; result: GeoJSON } Parameters Returns { rejected: { feature: any ; reasons: HintIssue [] } [] ; result: GeoJSON } rejected: { feature: any ; reasons: HintIssue [] } [] result: GeoJSON Legend Settings Theme OS Light Dark
--------------------------------------------------------------------------------
/lib/array_is_numbers.ts:
--------------------------------------------------------------------------------
1 | import { Node } from '@humanwhocodes/momoa';
2 | import { makeIssue } from './errors';
3 | import { Ctx } from './types';
4 |
5 | export function arrayIsNumbers(ctx: Ctx, elements: Node[], name: string) {
6 | for (const element of elements) {
7 | if (element.type !== 'Number') {
8 | ctx.issues.push(
9 | makeIssue(`Each element in a ${name} must be a number.`, element)
10 | );
11 | return;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/lib/check_duplicate_keys.ts:
--------------------------------------------------------------------------------
1 | import { makeIssue } from './errors';
2 | import { ObjectNode } from '@humanwhocodes/momoa';
3 | import { Ctx } from './types';
4 |
5 | export function checkDuplicateKeys(ctx: Ctx, parent: ObjectNode): ObjectNode {
6 | const keys = new Set();
7 | for (const node of parent.members) {
8 | const {
9 | name: { value },
10 | } = node;
11 | if (keys.has(value)) {
12 | ctx.issues.push(
13 | makeIssue('Duplicate properties are ambiguous in GeoJSON', node)
14 | );
15 | }
16 | keys.add(value);
17 | }
18 | return parent;
19 | }
20 |
--------------------------------------------------------------------------------
/lib/enforce_bbox.ts:
--------------------------------------------------------------------------------
1 | import { makeIssue } from './errors';
2 | import { ObjectNode } from '@humanwhocodes/momoa';
3 | import { getArray } from './get_array';
4 | import { arrayIsNumbers } from './array_is_numbers';
5 | import { Ctx } from './types';
6 |
7 | export function enforceBbox(ctx: Ctx, node: ObjectNode) {
8 | const member = node.members.find((member) => {
9 | return member.name.value === 'bbox';
10 | });
11 |
12 | // bboxes are optional
13 | if (member === undefined) return;
14 |
15 | const array = getArray(ctx, member.value);
16 |
17 | if (!array) return;
18 |
19 | if (!(array.elements.length === 4 || array.elements.length === 6)) {
20 | ctx.issues.push(makeIssue('A bbox must have 4 or 6 positions', array));
21 | }
22 |
23 | arrayIsNumbers(ctx, array.elements, 'bbox');
24 | }
25 |
--------------------------------------------------------------------------------
/lib/enforce_position.ts:
--------------------------------------------------------------------------------
1 | import { makeIssue } from './errors';
2 | import { ArrayNode } from '@humanwhocodes/momoa';
3 | import { arrayIsNumbers } from './array_is_numbers';
4 | import { Ctx } from './types';
5 |
6 | export function enforcePosition(ctx: Ctx, node: ArrayNode | null) {
7 | // This error has already been caught. Allow a no-op for simplicity.
8 | if (node === null) return;
9 |
10 | if (node.elements.length < 2 || node.elements.length > 3) {
11 | ctx.issues.push(
12 | makeIssue(
13 | `A position should have 2 or 3 elements - found ${node.elements.length}.`,
14 | node
15 | )
16 | );
17 | }
18 |
19 | arrayIsNumbers(ctx, node.elements, 'position');
20 | }
21 |
--------------------------------------------------------------------------------
/lib/enforce_position_array.ts:
--------------------------------------------------------------------------------
1 | import { makeIssue } from './errors';
2 | import { enforcePosition } from './enforce_position';
3 | import { enforceSamePosition } from './enforce_same_position';
4 | import { Node, ArrayNode } from '@humanwhocodes/momoa';
5 | import { Ctx } from './types';
6 |
7 | function getArray(ctx: Ctx, node: Node): ArrayNode | null {
8 | if (node.type !== 'Array') {
9 | ctx.issues.push(
10 | makeIssue('Expected to find an array of positions here.', node)
11 | );
12 | return null;
13 | }
14 | return node;
15 | }
16 |
17 | type PositionKind = 'Polygon' | 'LineString';
18 |
19 | export function enforcePositionArray(
20 | ctx: Ctx,
21 | node: Node | null,
22 | kind?: PositionKind
23 | ) {
24 | // This error has already been caught. Allow a no-op for simplicity.
25 | if (node === null) return;
26 |
27 | node = getArray(ctx, node);
28 | if (!node) return;
29 |
30 | for (const element of node.elements) {
31 | if (element.type !== 'Array') {
32 | ctx.issues.push(
33 | makeIssue(
34 | 'Expected to find a position here, found another type.',
35 | element
36 | )
37 | );
38 | return;
39 | } else {
40 | enforcePosition(ctx, element);
41 | }
42 | }
43 |
44 | switch (kind) {
45 | case 'LineString': {
46 | if (node.elements.length < 2) {
47 | ctx.issues.push(
48 | makeIssue('Expected to find two or more positions here.', node)
49 | );
50 | }
51 | break;
52 | }
53 | case 'Polygon':
54 | if (node.elements.length < 4) {
55 | ctx.issues.push(
56 | makeIssue('Expected to find four or more positions here.', node)
57 | );
58 | }
59 | enforceSamePosition(ctx, node);
60 | break;
61 | }
62 | }
63 |
64 | export function enforcePositionArray2(
65 | ctx: Ctx,
66 | node: Node | null,
67 | kind?: PositionKind
68 | ) {
69 | // This error has already been caught. Allow a no-op for simplicity.
70 | if (node === null) return;
71 |
72 | node = getArray(ctx, node);
73 | if (!node) return;
74 |
75 | for (const element of node.elements) {
76 | enforcePositionArray(ctx, element, kind);
77 | }
78 | }
79 |
80 | export function enforcePositionArray3(
81 | ctx: Ctx,
82 | node: ArrayNode | null,
83 | kind?: PositionKind
84 | ) {
85 | // This error has already been caught. Allow a no-op for simplicity.
86 | if (node === null) return;
87 |
88 | node = getArray(ctx, node);
89 | if (!node) return;
90 |
91 | for (const element of node.elements) {
92 | enforcePositionArray2(ctx, element, kind);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/lib/enforce_same_position.ts:
--------------------------------------------------------------------------------
1 | import { makeIssue } from './errors';
2 | import { ArrayNode, NumberNode } from '@humanwhocodes/momoa';
3 | import { Ctx } from './types';
4 |
5 | export function enforceSamePosition(ctx: Ctx, node: ArrayNode) {
6 | const first = node.elements[0] as ArrayNode;
7 | const last = node.elements[node.elements.length - 1] as ArrayNode;
8 | const len = Math.max(first.elements.length, last.elements.length);
9 |
10 | for (let j = 0; j < len; j++) {
11 | const firstValue = (first.elements[j] as NumberNode | undefined)?.value;
12 | const secondValue = (last.elements[j] as NumberNode | undefined)?.value;
13 | if (firstValue !== secondValue) {
14 | ctx.issues.push(
15 | makeIssue(
16 | 'First and last positions of a Polygon or MultiPolygon’s ring should be the same.',
17 | first
18 | ),
19 | makeIssue(
20 | 'First and last positions of a Polygon or MultiPolygon’s ring should be the same.',
21 | last
22 | )
23 | );
24 | return;
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lib/errors.ts:
--------------------------------------------------------------------------------
1 | import { Node } from '@humanwhocodes/momoa';
2 | import { HintIssue } from './types';
3 |
4 | export function makeIssue(message: string, node: Node): HintIssue {
5 | return {
6 | message,
7 | severity: 'error',
8 | // node,
9 | from: node.loc.start.offset,
10 | to: node.loc.end.offset,
11 | };
12 | }
13 |
14 | export class HintError extends Error {
15 | issues: HintIssue[] = [];
16 |
17 | constructor(issues: HintIssue[]) {
18 | super();
19 | // restore prototype chain
20 | const actualProto = new.target.prototype;
21 | Object.setPrototypeOf(this, actualProto);
22 | this.issues = issues;
23 | }
24 |
25 | get message() {
26 | return JSON.stringify(this.issues, null, 2);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lib/forbid_confusing_properties.ts:
--------------------------------------------------------------------------------
1 | import { makeIssue } from './errors';
2 | import { ObjectNode, MemberNode } from '@humanwhocodes/momoa';
3 | import { Ctx } from './types';
4 |
5 | type PropertiesFrom = 'Feature' | 'FeatureCollection' | 'Geometry';
6 |
7 | function forbidProperty(
8 | ctx: Ctx,
9 | member: MemberNode,
10 | propertiesFrom: PropertiesFrom,
11 | name: string
12 | ) {
13 | if (member.name.value === name) {
14 | ctx.issues.push(
15 | makeIssue(
16 | `${propertiesFrom} objects cannot contain a member named ${member.name.value}`,
17 | member.name
18 | )
19 | );
20 | }
21 | }
22 |
23 | const FORBIDDEN_PROPERTIES = {
24 | Geometry: ['properties', 'geometry', 'features'],
25 | Feature: ['features'],
26 | FeatureCollection: ['properties', 'coordinates'],
27 | } as const;
28 |
29 | export function forbidConfusingProperties(
30 | ctx: Ctx,
31 | node: ObjectNode,
32 | propertiesFrom: PropertiesFrom
33 | ) {
34 | for (const member of node.members) {
35 | for (const property of FORBIDDEN_PROPERTIES[propertiesFrom]) {
36 | forbidProperty(ctx, member, propertiesFrom, property);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/lib/get_array.ts:
--------------------------------------------------------------------------------
1 | import { makeIssue } from './errors';
2 | import { Node, ArrayNode } from '@humanwhocodes/momoa';
3 | import { Ctx } from './types';
4 |
5 | export function getArray(ctx: Ctx, node: Node | null): ArrayNode | null {
6 | if (node?.type === 'Array') return node;
7 | if (node) {
8 | ctx.issues.push(makeIssue('This must be an array.', node));
9 | }
10 | return null;
11 | }
12 |
--------------------------------------------------------------------------------
/lib/get_member_value.ts:
--------------------------------------------------------------------------------
1 | import { makeIssue } from './errors';
2 | import { ObjectNode } from '@humanwhocodes/momoa';
3 | import { Ctx } from './types';
4 |
5 | export function getMemberValue(ctx: Ctx, node: ObjectNode, name: string) {
6 | const member = node.members.find((member) => {
7 | return member.name.value === name;
8 | });
9 |
10 | if (!member) {
11 | ctx.issues.push(
12 | makeIssue(
13 | `This GeoJSON object requires a ${name} member but it is missing.`,
14 | node
15 | )
16 | );
17 |
18 | return null;
19 | }
20 |
21 | return member.value;
22 | }
23 |
--------------------------------------------------------------------------------
/lib/get_object.ts:
--------------------------------------------------------------------------------
1 | import { makeIssue } from './errors';
2 | import { Node, ObjectNode } from '@humanwhocodes/momoa';
3 | import { Ctx } from './types';
4 |
5 | export function getObject(ctx: Ctx, node: Node | null): ObjectNode | null {
6 | if (node?.type === 'Object') return node;
7 | if (node) {
8 | ctx.issues.push(makeIssue('This must be an object.', node));
9 | }
10 | return null;
11 | }
12 |
--------------------------------------------------------------------------------
/lib/get_type.ts:
--------------------------------------------------------------------------------
1 | import { Ctx, GeoJSONTypeSet } from './types';
2 | import { GeoJSON } from 'geojson';
3 | import { HintError, makeIssue } from './errors';
4 | import { Node } from '@humanwhocodes/momoa';
5 |
6 | export function getType(ctx: Ctx, node: Node, allowedTypes: GeoJSONTypeSet) {
7 | if (node.type !== 'Object') {
8 | throw new HintError([
9 | makeIssue('Expected an object, but found an incorrect type.', node),
10 | ]);
11 | }
12 |
13 | const typeMember = node.members.find((member) => {
14 | return member.name.value === 'type';
15 | });
16 |
17 | if (!typeMember) {
18 | ctx.issues.push(
19 | makeIssue('This GeoJSON object is missing its type member.', node)
20 | );
21 | return {};
22 | }
23 |
24 | const value = typeMember.value;
25 |
26 | if (value.type !== 'String') {
27 | ctx.issues.push(
28 | makeIssue('The type member should have been a string.', node)
29 | );
30 |
31 | return {};
32 | }
33 |
34 | if (!allowedTypes.has(value.value as any)) {
35 | ctx.issues.push(
36 | makeIssue('This type of GeoJSON object is not allowed here.', node)
37 | );
38 |
39 | return {};
40 | }
41 |
42 | return {
43 | type: value.value as GeoJSON['type'],
44 | objectNode: node,
45 | };
46 | }
47 |
--------------------------------------------------------------------------------
/lib/index.ts:
--------------------------------------------------------------------------------
1 | import {
2 | parse,
3 | evaluate,
4 | DocumentNode,
5 | Node,
6 | ObjectNode,
7 | } from '@humanwhocodes/momoa';
8 | import { GeoJSON } from 'geojson';
9 | import { HintError, makeIssue } from './errors';
10 | import {
11 | GeoJSONTypeSet,
12 | GEOJSON_TYPES,
13 | GEOJSON_GEOMETRY_TYPES,
14 | GEOJSON_GEOMETRY_TYPES_EX_GEOMETRY_COLLECTION,
15 | GEOJSON_FEATURE_TYPE,
16 | HintIssue,
17 | Ctx,
18 | } from './types';
19 | import { getType } from './get_type';
20 | import { getMemberValue } from './get_member_value';
21 | import { getArray } from './get_array';
22 | import { getObject } from './get_object';
23 | import { enforcePosition } from './enforce_position';
24 | import { checkDuplicateKeys } from './check_duplicate_keys';
25 | import {
26 | enforcePositionArray,
27 | enforcePositionArray2,
28 | enforcePositionArray3,
29 | } from './enforce_position_array';
30 | import { enforceBbox } from './enforce_bbox';
31 | import { forbidConfusingProperties } from './forbid_confusing_properties';
32 |
33 | type Checker = (ctx: Ctx, node: ObjectNode) => void;
34 |
35 | function getCoordinates(ctx: Ctx, node: ObjectNode) {
36 | const coordinatesMember = getMemberValue(ctx, node, 'coordinates');
37 | if (!coordinatesMember) return null;
38 | return getArray(ctx, coordinatesMember);
39 | }
40 |
41 | const checkGeometryShared: Checker = (ctx, node) => {
42 | enforceBbox(ctx, node);
43 | forbidConfusingProperties(ctx, node, 'Geometry');
44 | };
45 |
46 | const checkLineString: Checker = (ctx, node) => {
47 | enforcePositionArray(ctx, getCoordinates(ctx, node), 'LineString');
48 | checkGeometryShared(ctx, node);
49 | };
50 |
51 | const checkMultiLineString: Checker = (ctx, node) => {
52 | enforcePositionArray2(ctx, getCoordinates(ctx, node), 'LineString');
53 | checkGeometryShared(ctx, node);
54 | };
55 |
56 | const checkPolygon: Checker = (ctx, node) => {
57 | enforcePositionArray2(ctx, getCoordinates(ctx, node), 'Polygon');
58 | checkGeometryShared(ctx, node);
59 | };
60 |
61 | const checkMultiPolygon: Checker = (ctx, node) => {
62 | enforcePositionArray3(ctx, getCoordinates(ctx, node), 'Polygon');
63 | checkGeometryShared(ctx, node);
64 | };
65 |
66 | const checkPoint: Checker = (ctx, node) => {
67 | enforcePosition(ctx, getCoordinates(ctx, node));
68 | checkGeometryShared(ctx, node);
69 | };
70 |
71 | const checkMultiPoint: Checker = (ctx, node) => {
72 | enforcePositionArray(ctx, getCoordinates(ctx, node));
73 | checkGeometryShared(ctx, node);
74 | };
75 |
76 | const checkGeometryCollection: Checker = (ctx, node) => {
77 | checkGeometryShared(ctx, node);
78 | const geometriesMember = getArray(
79 | ctx,
80 | getMemberValue(ctx, node, 'geometries')
81 | );
82 | if (!geometriesMember) return;
83 | for (const element of geometriesMember.elements) {
84 | checkObject(ctx, element, GEOJSON_GEOMETRY_TYPES_EX_GEOMETRY_COLLECTION);
85 | }
86 | };
87 |
88 | const checkFeature: Checker = (ctx, node) => {
89 | forbidConfusingProperties(ctx, node, 'Feature');
90 | const geometryMember = getMemberValue(ctx, node, 'geometry');
91 | enforceBbox(ctx, node);
92 | if (geometryMember?.type !== 'Null') {
93 | const geometry = getObject(ctx, geometryMember);
94 | if (geometry) checkObject(ctx, geometry, GEOJSON_GEOMETRY_TYPES);
95 | }
96 |
97 | const idMember = node.members.find((member) => {
98 | return member.name.value === 'id';
99 | });
100 | if (
101 | idMember &&
102 | !(idMember.value.type === 'String' || idMember.value.type === 'Number')
103 | ) {
104 | ctx.issues.push(
105 | makeIssue(`The Feature id must be a string or number.`, node)
106 | );
107 | }
108 |
109 | const properties = getMemberValue(ctx, node, 'properties');
110 | if (!properties) {
111 | ctx.issues.push(makeIssue(`The properties member is missing.`, node));
112 | return;
113 | }
114 |
115 | const { type } = properties;
116 |
117 | if (!(type === 'Object' || type === 'Null')) {
118 | ctx.issues.push(
119 | makeIssue(`The Feature properties member can be an object or null.`, node)
120 | );
121 | }
122 | };
123 |
124 | const checkFeatureCollection: Checker = (ctx, node) => {
125 | forbidConfusingProperties(ctx, node, 'FeatureCollection');
126 | const featuresMember = getArray(ctx, getMemberValue(ctx, node, 'features'));
127 | if (!featuresMember) return;
128 | for (const feature of featuresMember.elements) {
129 | const beforeCount = ctx.issues.length;
130 | const obj = getObject(ctx, feature);
131 | if (obj) {
132 | getType(ctx, obj, GEOJSON_FEATURE_TYPE);
133 | checkFeature(ctx, obj);
134 | }
135 | ctx.valid.push(
136 | ctx.issues.length === beforeCount
137 | ? undefined
138 | : ctx.issues.slice(beforeCount)
139 | );
140 | }
141 | };
142 |
143 | const CHECKERS: Record = {
144 | LineString: checkLineString,
145 | MultiLineString: checkMultiLineString,
146 |
147 | Polygon: checkPolygon,
148 | MultiPolygon: checkMultiPolygon,
149 |
150 | Point: checkPoint,
151 | MultiPoint: checkMultiPoint,
152 |
153 | GeometryCollection: checkGeometryCollection,
154 |
155 | Feature: checkFeature,
156 | FeatureCollection: checkFeatureCollection,
157 | };
158 |
159 | function checkObject(
160 | ctx: Ctx,
161 | node: Node,
162 | typeSet: GeoJSONTypeSet = GEOJSON_TYPES
163 | ) {
164 | const { type, objectNode } = getType(ctx, node, typeSet);
165 | if (!(type && objectNode)) return;
166 | checkDuplicateKeys(ctx, objectNode);
167 | CHECKERS[type](ctx, objectNode);
168 | }
169 |
170 | function checkInternal(jsonStr: string): {
171 | ast: DocumentNode | undefined;
172 | ctx: Ctx;
173 | } {
174 | if (typeof jsonStr !== 'string') {
175 | throw new TypeError('Input must be a string. (Use JSON.stringify first.)');
176 | }
177 | const ctx: Ctx = {
178 | issues: [],
179 | valid: [],
180 | };
181 | let ast;
182 | try {
183 | ast = parse(jsonStr, {
184 | ranges: true,
185 | });
186 | checkObject(ctx, ast.body);
187 | } catch (e: unknown) {
188 | ctx.issues.push({
189 | message: `Invalid JSON: ${(e as Error).message}`,
190 | from: 0,
191 | to: 0,
192 | severity: 'error',
193 | });
194 | }
195 |
196 | return { ast, ctx };
197 | }
198 |
199 | /**
200 | * Given a string of possibly valid GeoJSON data,
201 | * return an array of issues. This will handle invalid JSON
202 | * data, invalid GeoJSON structure, and anything else that will
203 | * prevent this string of data from being parsed and
204 | * displayed on a map.
205 | *
206 | * check-geojson looks for invalid structure and invalid syntax.
207 | * It does not check for complex geometry issues like
208 | * self-intersections, which are hard to detect and don't cause
209 | * failures in most display & manipulation software.
210 | */
211 | export const getIssues = (jsonStr: string): HintIssue[] => {
212 | return checkInternal(jsonStr).ctx.issues;
213 | };
214 |
215 | /**
216 | * This catches the same issues as `getIssues`, but instead
217 | * of returning a list of issues, it will throw a HintError
218 | * if any errors are detected, and return the parsed
219 | * GeoJSON as an object if no errors are.
220 | */
221 | export const check = (jsonStr: string): GeoJSON => {
222 | const { ctx, ast } = checkInternal(jsonStr);
223 | if (ctx.issues.length || !ast) throw new HintError(ctx.issues);
224 | return evaluate(ast);
225 | };
226 |
227 | /**
228 | * This method will allow you to parse a possibly-valid
229 | * bit of GeoJSON data. If nothing can be parsed, it will
230 | * throw a HintError. However, if the GeoJSON can be parsed,
231 | * it will return an object with valid features
232 | * and rejected features along with the reasons why those
233 | * features were rejected.
234 | */
235 | export const scavenge = (
236 | jsonStr: string
237 | ): {
238 | result: GeoJSON;
239 | rejected: Array<{ feature: any; reasons: HintIssue[] }>;
240 | } => {
241 | const {
242 | ctx: { issues, valid },
243 | ast,
244 | } = checkInternal(jsonStr);
245 | // If GeoJSON can't be parsed, throw.
246 | if (!ast) throw new HintError(issues);
247 | const result = evaluate(ast) as GeoJSON;
248 | // If everything was fine, return.
249 | if (!issues.length) return { result, rejected: [] };
250 | // If there were errors but it's a featurecollection, sift
251 | if (result.type === 'FeatureCollection') {
252 | return {
253 | result: {
254 | ...result,
255 | features: result.features.filter((_, i) => {
256 | return valid[i] === undefined;
257 | }),
258 | },
259 | rejected: result.features.flatMap((feature, i) => {
260 | const reasons = valid[i];
261 | if (reasons) {
262 | return [
263 | {
264 | feature,
265 | reasons,
266 | },
267 | ];
268 | }
269 | return [];
270 | }),
271 | };
272 | }
273 | // Otherwise, throw
274 | throw new HintError(issues);
275 | };
276 |
277 | export { HintError, HintIssue };
278 |
--------------------------------------------------------------------------------
/lib/types.ts:
--------------------------------------------------------------------------------
1 | import { GeoJSON } from 'geojson';
2 |
3 | export type GeoJSONTypeSet = Set;
4 |
5 | export interface HintIssue {
6 | from: number;
7 | to: number;
8 | node?: Node;
9 | severity: 'error';
10 | message: string;
11 | }
12 |
13 | export interface Ctx {
14 | issues: HintIssue[];
15 | valid: Array;
16 | }
17 |
18 | export const GEOJSON_FEATURE_TYPE = new Set(['Feature']);
19 |
20 | export const GEOJSON_GEOMETRY_TYPES = new Set([
21 | 'Point',
22 | 'MultiPoint',
23 | 'Polygon',
24 | 'MultiPolygon',
25 | 'LineString',
26 | 'MultiLineString',
27 | 'GeometryCollection',
28 | ]);
29 |
30 | export const GEOJSON_GEOMETRY_TYPES_EX_GEOMETRY_COLLECTION = new Set<
31 | GeoJSON['type']
32 | >([
33 | 'Point',
34 | 'MultiPoint',
35 | 'Polygon',
36 | 'MultiPolygon',
37 | 'LineString',
38 | 'MultiLineString',
39 | ]);
40 |
41 | export const GEOJSON_TYPES = new Set(
42 | Array.from(GEOJSON_GEOMETRY_TYPES).concat([
43 | 'Feature',
44 | 'FeatureCollection',
45 | ]));
46 |
--------------------------------------------------------------------------------
/mise.toml:
--------------------------------------------------------------------------------
1 | [tools]
2 | node = "22"
3 | pnpm = "latest"
4 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.1.14",
3 | "license": "MIT",
4 | "main": "dist/index.js",
5 | "typings": "dist/index.d.ts",
6 | "source": "lib/index.ts",
7 | "module": "dist/index.esm.mjs",
8 | "files": [
9 | "dist",
10 | "lib"
11 | ],
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/placemark/check-geojson.git"
15 | },
16 | "publishConfig": {
17 | "access": "public"
18 | },
19 | "engines": {
20 | "node": ">=10"
21 | },
22 | "scripts": {
23 | "build": "microbundle",
24 | "doc": "typedoc --options ./typedoc.json",
25 | "test": "vitest",
26 | "lint": "eslint . && tsc --noEmit",
27 | "prepare": "husky install",
28 | "prepublishOnly": "pnpm run build && pnpm run doc && cp CNAME docs/CNAME"
29 | },
30 | "peerDependencies": {},
31 | "husky": {
32 | "hooks": {
33 | "pre-commit": "pnpm lint"
34 | }
35 | },
36 | "prettier": {
37 | "printWidth": 80,
38 | "semi": true,
39 | "singleQuote": true,
40 | "trailingComma": "es5"
41 | },
42 | "name": "@placemarkio/check-geojson",
43 | "author": "Tom MacWright",
44 | "devDependencies": {
45 | "@humanwhocodes/momoa": "^2.0.4",
46 | "@types/geojson": "^7946.0.8",
47 | "@typescript-eslint/eslint-plugin": "^5.25.0",
48 | "@typescript-eslint/parser": "^5.25.0",
49 | "eslint": "^8.16.0",
50 | "husky": "^8.0.1",
51 | "microbundle": "^0.15.0",
52 | "prettier": "^2.6.2",
53 | "tslib": "^2.4.0",
54 | "type-fest": "^2.12.2",
55 | "typedoc": "^0.22.15",
56 | "typescript": "^4.6.4",
57 | "vitest": "^0.24.4"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/test/bad.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from "vitest";
2 | import { check, getIssues, HintError } from "../lib";
3 | import * as Path from "path";
4 | import { readFileSync, readdirSync } from "fs";
5 |
6 | describe("check", () => {
7 | it("invalid input", () => {
8 | // @ts-expect-error this is a test for wrong usage
9 | expect(() => check({})).toThrow(TypeError);
10 | // @ts-expect-error this is a test for wrong usage
11 | expect(() => check([])).toThrow(TypeError);
12 | });
13 | it("invalid root object", () => {
14 | expect(() => check(JSON.stringify([]))).toThrow(HintError);
15 | expect(() => check(JSON.stringify({}))).toThrow(HintError);
16 | try {
17 | check('{"foo": 1.}');
18 | } catch (e) {
19 | expect(e.issues).toHaveLength(1);
20 | }
21 | expect(() => check(JSON.stringify({ type: ["foo"] }))).toThrow(HintError);
22 | expect(() => check(JSON.stringify({ type: "foo" }))).toThrow(HintError);
23 | expect(getIssues(JSON.stringify({}))).toEqual([
24 | {
25 | from: 0,
26 | message: "This GeoJSON object is missing its type member.",
27 | severity: "error",
28 | to: 2,
29 | },
30 | ]);
31 | expect(getIssues(JSON.stringify({ type: "test" }))).toEqual([
32 | {
33 | from: 0,
34 | message: "This type of GeoJSON object is not allowed here.",
35 | severity: "error",
36 | to: 15,
37 | },
38 | ]);
39 | });
40 |
41 | it("invalid coordinates", () => {
42 | expect(() => check(JSON.stringify({ type: "Point" }))).toThrow(HintError);
43 | expect(() =>
44 | check(JSON.stringify({ type: "Point", coordinates: null })),
45 | ).toThrow(HintError);
46 | });
47 |
48 | it("bad points", () => {
49 | expect(() =>
50 | check(JSON.stringify({ type: "Point", coordinates: [1] })),
51 | ).toThrow(HintError);
52 | expect(() =>
53 | check(JSON.stringify({ type: "Point", coordinates: [1, 2, 3, 4] })),
54 | ).toThrow(HintError);
55 | });
56 |
57 | it("bad multipoints", () => {
58 | expect(() =>
59 | check(JSON.stringify({ type: "MultiPoint", coordinates: [[true]] })),
60 | ).toThrow(HintError);
61 | });
62 |
63 | it("geometry collection with null", () => {
64 | expect(() =>
65 | check(JSON.stringify({ type: "GeometryCollection", geometries: [null] })),
66 | ).toThrow(HintError);
67 | });
68 |
69 | it("forbidden properties", () => {
70 | expect(() =>
71 | check(
72 | JSON.stringify({ type: "Point", coordinates: [1, 2], properties: {} }),
73 | ),
74 | ).toThrow(HintError);
75 | });
76 |
77 | it("bad json", () => {
78 | try {
79 | check(
80 | `{
81 | "type": "MultiPoint"
82 | "coordinates": [["foo", "bar"]]
83 | }`,
84 | );
85 | } catch (e) {
86 | expect(e.issues[0]).toEqual({
87 | message:
88 | 'Invalid JSON: Unexpected token String("coordinates") found. (3:5)',
89 | from: 0,
90 | to: 0,
91 | severity: "error",
92 | });
93 | }
94 | });
95 |
96 | describe("works with fixtures", () => {
97 | const fixtureNames = readdirSync(Path.join(__dirname, "./fixture/bad/"));
98 | for (const name of fixtureNames) {
99 | it(`fixture: ${name}`, () => {
100 | const input = readFileSync(
101 | Path.join(__dirname, "./fixture/bad/", name),
102 | "utf8",
103 | );
104 | expect(() => check(input)).toThrow(HintError);
105 | });
106 | }
107 | });
108 | });
109 |
--------------------------------------------------------------------------------
/test/fixture/bad/bad-duplicate-properties.cli-output-json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "message": "An object contained duplicate members, making parsing ambigous: type",
4 | "line": 1
5 | },
6 | {
7 | "message": "Feature object cannot contain a \"features\" member",
8 | "line": 1
9 | },
10 | {
11 | "message": "\"properties\" member required",
12 | "line": 1
13 | },
14 | {
15 | "message": "\"geometry\" member required",
16 | "line": 1
17 | }
18 | ]
19 |
--------------------------------------------------------------------------------
/test/fixture/bad/bad-duplicate-properties.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "type": "Feature",
4 | "features": []
5 | }
6 |
--------------------------------------------------------------------------------
/test/fixture/bad/bad-featurelist.cli-output-json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "message": "a number was found where a coordinate array should have been found: this needs to be nested more deeply",
4 | "line": 3
5 | }
6 | ]
7 |
--------------------------------------------------------------------------------
/test/fixture/bad/bad-featurelist.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "Polygon",
3 | "coordinates": [5]
4 | }
5 |
--------------------------------------------------------------------------------
/test/fixture/bad/bad-json.cli-output-json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "line": 1,
4 | "message": "Parse error on line 2:\n...\": \"MultiPoint\" \"coordinates\": [[\"fo\n----------------------^\nExpecting 'EOF', '}', ':', ',', ']', got 'STRING'",
5 | "error": {
6 | "message": "Parse error on line 2:\n...\": \"MultiPoint\" \"coordinates\": [[\"fo\n----------------------^\nExpecting 'EOF', '}', ':', ',', ']', got 'STRING'",
7 | "hash": {
8 | "text": "\"coordinates\"",
9 | "token": "STRING",
10 | "line": 2,
11 | "loc": {
12 | "first_line": 2,
13 | "last_line": 2,
14 | "first_column": 12,
15 | "last_column": 24
16 | },
17 | "expected": [
18 | "'EOF'",
19 | "'}'",
20 | "':'",
21 | "','",
22 | "']'"
23 | ]
24 | }
25 | }
26 | }
27 | ]
28 |
--------------------------------------------------------------------------------
/test/fixture/bad/bad-json.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "MultiPoint"
3 | "coordinates": [["foo", "bar"]]
4 | }
5 |
--------------------------------------------------------------------------------
/test/fixture/bad/bad-object-type.cli-output-json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "message": "\"type\" member should be string, but is an object instead",
4 | "line": 1
5 | }
6 | ]
7 |
--------------------------------------------------------------------------------
/test/fixture/bad/bad-object-type.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": {}
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixture/bad/bad-polygonloop.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "geometry": {
3 | "type": "Polygon",
4 | "coordinates": [
5 | [
6 | -80.59869,
7 | 41.05173
8 | ],
9 | [
10 | -80.59482,
11 | 41.21846
12 | ],
13 | [
14 | -80.59094,
15 | 41.21862
16 | ],
17 | [
18 | -80.58705,
19 | 41.21873
20 | ],
21 | [
22 | -80.58315,
23 | 41.21879
24 | ],
25 | [
26 | -80.57925,
27 | 41.2188
28 | ],
29 | [
30 | -80.57535,
31 | 41.21875
32 | ],
33 | [
34 | -80.57144,
35 | 41.21865
36 | ],
37 | [
38 | -80.56752,
39 | 41.2185
40 | ],
41 | [
42 | -80.56361,
43 | 41.2183
44 | ],
45 | [
46 | -80.5597,
47 | 41.21804
48 | ],
49 | [
50 | -80.55578,
51 | 41.21773
52 | ],
53 | [
54 | -80.55187,
55 | 41.21737
56 | ],
57 | [
58 | -80.54797,
59 | 41.21696
60 | ],
61 | [
62 | -80.54407,
63 | 41.21649
64 | ],
65 | [
66 | -80.54017,
67 | 41.21597
68 | ],
69 | [
70 | -80.53629,
71 | 41.2154
72 | ],
73 | [
74 | -80.53241,
75 | 41.21477
76 | ],
77 | [
78 | -80.52854,
79 | 41.21409
80 | ],
81 | [
82 | -80.52469,
83 | 41.21336
84 | ],
85 | [
86 | -80.52085,
87 | 41.21258
88 | ],
89 | [
90 | -80.51702,
91 | 41.21174
92 | ],
93 | [
94 | -80.51332,
95 | 41.21064
96 | ],
97 | [
98 | -80.50965,
99 | 41.2095
100 | ],
101 | [
102 | -80.506,
103 | 41.2083
104 | ],
105 | [
106 | -80.50238,
107 | 41.20706
108 | ],
109 | [
110 | -80.4988,
111 | 41.20577
112 | ],
113 | [
114 | -80.49524,
115 | 41.20443
116 | ],
117 | [
118 | -80.49171,
119 | 41.20304
120 | ],
121 | [
122 | -80.48822,
123 | 41.20161
124 | ],
125 | [
126 | -80.48476,
127 | 41.20013
128 | ],
129 | [
130 | -80.48134,
131 | 41.19861
132 | ],
133 | [
134 | -80.47789,
135 | 41.19712
136 | ],
137 | [
138 | -80.47447,
139 | 41.19559
140 | ],
141 | [
142 | -80.47108,
143 | 41.19401
144 | ],
145 | [
146 | -80.46773,
147 | 41.19238
148 | ],
149 | [
150 | -80.46442,
151 | 41.19071
152 | ],
153 | [
154 | -80.46115,
155 | 41.18899
156 | ],
157 | [
158 | -80.45791,
159 | 41.18724
160 | ],
161 | [
162 | -80.45472,
163 | 41.18543
164 | ],
165 | [
166 | -80.45156,
167 | 41.18359
168 | ],
169 | [
170 | -80.44845,
171 | 41.1817
172 | ],
173 | [
174 | -80.44538,
175 | 41.17977
176 | ],
177 | [
178 | -80.44236,
179 | 41.1778
180 | ],
181 | [
182 | -80.43937,
183 | 41.17579
184 | ],
185 | [
186 | -80.43644,
187 | 41.17374
188 | ],
189 | [
190 | -80.43355,
191 | 41.17164
192 | ],
193 | [
194 | -80.43071,
195 | 41.16951
196 | ],
197 | [
198 | -80.42792,
199 | 41.16735
200 | ],
201 | [
202 | -80.42518,
203 | 41.16514
204 | ],
205 | [
206 | -80.42249,
207 | 41.1629
208 | ],
209 | [
210 | -80.41985,
211 | 41.16062
212 | ],
213 | [
214 | -80.41716,
215 | 41.15836
216 | ],
217 | [
218 | -80.41453,
219 | 41.15606
220 | ],
221 | [
222 | -80.41195,
223 | 41.15372
224 | ],
225 | [
226 | -80.40943,
227 | 41.15135
228 | ],
229 | [
230 | -80.40695,
231 | 41.14895
232 | ],
233 | [
234 | -80.40454,
235 | 41.14651
236 | ],
237 | [
238 | -80.40217,
239 | 41.14403
240 | ],
241 | [
242 | -80.39986,
243 | 41.14152
244 | ],
245 | [
246 | -80.39761,
247 | 41.13898
248 | ],
249 | [
250 | -80.39542,
251 | 41.1364
252 | ],
253 | [
254 | -80.3935,
255 | 41.13372
256 | ],
257 | [
258 | -80.39163,
259 | 41.131
260 | ],
261 | [
262 | -80.38983,
263 | 41.12827
264 | ],
265 | [
266 | -80.38809,
267 | 41.1255
268 | ],
269 | [
270 | -80.38642,
271 | 41.12272
272 | ],
273 | [
274 | -80.38481,
275 | 41.11992
276 | ],
277 | [
278 | -80.38327,
279 | 41.11709
280 | ],
281 | [
282 | -80.38179,
283 | 41.11425
284 | ],
285 | [
286 | -80.38038,
287 | 41.11138
288 | ],
289 | [
290 | -80.37904,
291 | 41.1085
292 | ],
293 | [
294 | -80.37799,
295 | 41.10555
296 | ],
297 | [
298 | -80.377,
299 | 41.10258
300 | ],
301 | [
302 | -80.37609,
303 | 41.09961
304 | ],
305 | [
306 | -80.37525,
307 | 41.09663
308 | ],
309 | [
310 | -80.37447,
311 | 41.09364
312 | ],
313 | [
314 | -80.37377,
315 | 41.09064
316 | ],
317 | [
318 | -80.37314,
319 | 41.08764
320 | ],
321 | [
322 | -80.37258,
323 | 41.08463
324 | ],
325 | [
326 | -80.3721,
327 | 41.08162
328 | ],
329 | [
330 | -80.37168,
331 | 41.0786
332 | ],
333 | [
334 | -80.37145,
335 | 41.07558
336 | ],
337 | [
338 | -80.3713,
339 | 41.07255
340 | ],
341 | [
342 | -80.37121,
343 | 41.06953
344 | ],
345 | [
346 | -80.3712,
347 | 41.06651
348 | ],
349 | [
350 | -80.37126,
351 | 41.06349
352 | ],
353 | [
354 | -80.37139,
355 | 41.06048
356 | ],
357 | [
358 | -80.37159,
359 | 41.05748
360 | ],
361 | [
362 | -80.37187,
363 | 41.05449
364 | ],
365 | [
366 | -80.37221,
367 | 41.0515
368 | ],
369 | [
370 | -80.37262,
371 | 41.04853
372 | ],
373 | [
374 | -80.37408,
375 | 41.04559
376 | ],
377 | [
378 | -80.37562,
379 | 41.04269
380 | ],
381 | [
382 | -80.37725,
383 | 41.03983
384 | ],
385 | [
386 | -80.37895,
387 | 41.03702
388 | ],
389 | [
390 | -80.38072,
391 | 41.03424
392 | ],
393 | [
394 | -80.38258,
395 | 41.03151
396 | ],
397 | [
398 | -80.3845,
399 | 41.02882
400 | ],
401 | [
402 | -80.38651,
403 | 41.02618
404 | ],
405 | [
406 | -80.38857,
407 | 41.02358
408 | ],
409 | [
410 | -80.3893,
411 | 41.02083
412 | ],
413 | [
414 | -80.38629,
415 | 41.01747
416 | ],
417 | [
418 | -80.38244,
419 | 41.01385
420 | ],
421 | [
422 | -80.37529,
423 | 41.00948
424 | ],
425 | [
426 | -80.3636,
427 | 41.00395
428 | ],
429 | [
430 | -80.3516,
431 | 40.99799
432 | ],
433 | [
434 | -80.34035,
435 | 40.99182
436 | ],
437 | [
438 | -80.33112,
439 | 40.98579
440 | ],
441 | [
442 | -80.32527,
443 | 40.98033
444 | ],
445 | [
446 | -80.32169,
447 | 40.97528
448 | ],
449 | [
450 | -80.32132,
451 | 40.971
452 | ],
453 | [
454 | -80.32489,
455 | 40.96787
456 | ],
457 | [
458 | -80.33313,
459 | 40.96631
460 | ],
461 | [
462 | -80.34609,
463 | 40.96653
464 | ],
465 | [
466 | -80.36318,
467 | 40.96857
468 | ],
469 | [
470 | -80.38569,
471 | 40.9731
472 | ],
473 | [
474 | -80.41078,
475 | 40.97929
476 | ],
477 | [
478 | -80.43525,
479 | 40.98601
480 | ],
481 | [
482 | -80.44189,
483 | 40.98601
484 | ],
485 | [
486 | -80.44487,
487 | 40.98459
488 | ],
489 | [
490 | -80.44787,
491 | 40.98322
492 | ],
493 | [
494 | -80.4513,
495 | 40.98211
496 | ],
497 | [
498 | -80.45473,
499 | 40.98106
500 | ],
501 | [
502 | -80.45815,
503 | 40.98008
504 | ],
505 | [
506 | -80.46162,
507 | 40.97919
508 | ],
509 | [
510 | -80.46505,
511 | 40.97835
512 | ],
513 | [
514 | -80.46851,
515 | 40.97759
516 | ],
517 | [
518 | -80.472,
519 | 40.97693
520 | ],
521 | [
522 | -80.47545,
523 | 40.97632
524 | ],
525 | [
526 | -80.47894,
527 | 40.9758
528 | ],
529 | [
530 | -80.48243,
531 | 40.97537
532 | ],
533 | [
534 | -80.48542,
535 | 40.97467
536 | ],
537 | [
538 | -80.48843,
539 | 40.97405
540 | ],
541 | [
542 | -80.49147,
543 | 40.97351
544 | ],
545 | [
546 | -80.49448,
547 | 40.973
548 | ],
549 | [
550 | -80.4975,
551 | 40.97257
552 | ],
553 | [
554 | -80.50054,
555 | 40.97222
556 | ],
557 | [
558 | -80.50357,
559 | 40.97193
560 | ],
561 | [
562 | -80.5066,
563 | 40.9717
564 | ],
565 | [
566 | -80.50963,
567 | 40.97156
568 | ],
569 | [
570 | -80.51267,
571 | 40.97149
572 | ],
573 | [
574 | -80.5148,
575 | 40.97063
576 | ],
577 | [
578 | -80.51694,
579 | 40.96979
580 | ],
581 | [
582 | -80.5191,
583 | 40.96899
584 | ],
585 | [
586 | -80.52127,
587 | 40.96822
588 | ],
589 | [
590 | -80.52346,
591 | 40.96749
592 | ],
593 | [
594 | -80.52565,
595 | 40.96679
596 | ],
597 | [
598 | -80.52786,
599 | 40.96612
600 | ],
601 | [
602 | -80.53008,
603 | 40.96549
604 | ],
605 | [
606 | -80.53231,
607 | 40.96489
608 | ],
609 | [
610 | -80.53454,
611 | 40.96433
612 | ],
613 | [
614 | -80.53636,
615 | 40.9632
616 | ],
617 | [
618 | -80.53821,
619 | 40.96209
620 | ],
621 | [
622 | -80.5401,
623 | 40.96101
624 | ],
625 | [
626 | -80.54202,
627 | 40.95995
628 | ],
629 | [
630 | -80.54397,
631 | 40.95891
632 | ],
633 | [
634 | -80.54596,
635 | 40.95791
636 | ],
637 | [
638 | -80.54797,
639 | 40.95692
640 | ],
641 | [
642 | -80.55002,
643 | 40.95597
644 | ],
645 | [
646 | -80.55209,
647 | 40.95504
648 | ],
649 | [
650 | -80.5542,
651 | 40.95414
652 | ],
653 | [
654 | -80.55617,
655 | 40.9529
656 | ],
657 | [
658 | -80.55819,
659 | 40.95169
660 | ],
661 | [
662 | -80.56026,
663 | 40.9505
664 | ],
665 | [
666 | -80.56237,
667 | 40.94935
668 | ],
669 | [
670 | -80.56452,
671 | 40.94823
672 | ],
673 | [
674 | -80.56672,
675 | 40.94715
676 | ],
677 | [
678 | -80.56896,
679 | 40.9461
680 | ],
681 | [
682 | -80.57124,
683 | 40.94507
684 | ],
685 | [
686 | -80.57355,
687 | 40.94407
688 | ],
689 | [
690 | -80.57591,
691 | 40.9431
692 | ],
693 | [
694 | -80.5783,
695 | 40.94217
696 | ],
697 | [
698 | -80.58073,
699 | 40.94129
700 | ],
701 | [
702 | -80.5832,
703 | 40.94044
704 | ],
705 | [
706 | -80.5857,
707 | 40.93962
708 | ],
709 | [
710 | -80.58823,
711 | 40.93882
712 | ],
713 | [
714 | -80.5908,
715 | 40.93807
716 | ],
717 | [
718 | -80.5934,
719 | 40.93735
720 | ],
721 | [
722 | -80.59603,
723 | 40.93667
724 | ],
725 | [
726 | -80.59868,
727 | 40.93604
728 | ],
729 | [
730 | -80.60137,
731 | 40.93545
732 | ],
733 | [
734 | -80.60413,
735 | 40.9339
736 | ],
737 | [
738 | -80.60696,
739 | 40.93241
740 | ],
741 | [
742 | -80.60986,
743 | 40.931
744 | ],
745 | [
746 | -80.61283,
747 | 40.92961
748 | ],
749 | [
750 | -80.61586,
751 | 40.92828
752 | ],
753 | [
754 | -80.61895,
755 | 40.92704
756 | ],
757 | [
758 | -80.62211,
759 | 40.9258
760 | ],
761 | [
762 | -80.62532,
763 | 40.92464
764 | ],
765 | [
766 | -80.62859,
767 | 40.92355
768 | ],
769 | [
770 | -80.63193,
771 | 40.92248
772 | ],
773 | [
774 | -80.63523,
775 | 40.9218
776 | ],
777 | [
778 | -80.63856,
779 | 40.92119
780 | ],
781 | [
782 | -80.64193,
783 | 40.92064
784 | ],
785 | [
786 | -80.64536,
787 | 40.92009
788 | ],
789 | [
790 | -80.64881,
791 | 40.91961
792 | ],
793 | [
794 | -80.6523,
795 | 40.9192
796 | ],
797 | [
798 | -80.65582,
799 | 40.91884
800 | ],
801 | [
802 | -80.65939,
803 | 40.91848
804 | ],
805 | [
806 | -80.66299,
807 | 40.9182
808 | ],
809 | [
810 | -80.66661,
811 | 40.91799
812 | ],
813 | [
814 | -80.67006,
815 | 40.91821
816 | ],
817 | [
818 | -80.67354,
819 | 40.91845
820 | ],
821 | [
822 | -80.67702,
823 | 40.91875
824 | ],
825 | [
826 | -80.6805,
827 | 40.91911
828 | ],
829 | [
830 | -80.68399,
831 | 40.91953
832 | ],
833 | [
834 | -80.68748,
835 | 40.92
836 | ],
837 | [
838 | -80.69098,
839 | 40.92053
840 | ],
841 | [
842 | -80.69447,
843 | 40.92111
844 | ],
845 | [
846 | -80.69796,
847 | 40.92176
848 | ],
849 | [
850 | -80.70144,
851 | 40.92246
852 | ],
853 | [
854 | -80.70508,
855 | 40.92303
856 | ],
857 | [
858 | -80.70871,
859 | 40.92366
860 | ],
861 | [
862 | -80.71234,
863 | 40.92436
864 | ],
865 | [
866 | -80.71596,
867 | 40.92511
868 | ],
869 | [
870 | -80.71958,
871 | 40.92594
872 | ],
873 | [
874 | -80.72319,
875 | 40.92683
876 | ],
877 | [
878 | -80.72678,
879 | 40.92778
880 | ],
881 | [
882 | -80.73037,
883 | 40.92879
884 | ],
885 | [
886 | -80.73394,
887 | 40.92987
888 | ],
889 | [
890 | -80.73749,
891 | 40.93101
892 | ],
893 | [
894 | -80.74071,
895 | 40.93247
896 | ],
897 | [
898 | -80.7439,
899 | 40.93399
900 | ],
901 | [
902 | -80.74706,
903 | 40.93555
904 | ],
905 | [
906 | -80.75019,
907 | 40.93717
908 | ],
909 | [
910 | -80.7533,
911 | 40.93883
912 | ],
913 | [
914 | -80.75637,
915 | 40.94054
916 | ],
917 | [
918 | -80.7594,
919 | 40.9423
920 | ],
921 | [
922 | -80.7624,
923 | 40.94411
924 | ],
925 | [
926 | -80.76536,
927 | 40.94597
928 | ],
929 | [
930 | -80.76828,
931 | 40.94787
932 | ],
933 | [
934 | -80.77091,
935 | 40.94997
936 | ],
937 | [
938 | -80.7735,
939 | 40.9521
940 | ],
941 | [
942 | -80.77603,
943 | 40.95428
944 | ],
945 | [
946 | -80.77852,
947 | 40.95649
948 | ],
949 | [
950 | -80.78096,
951 | 40.95873
952 | ],
953 | [
954 | -80.78335,
955 | 40.96102
956 | ],
957 | [
958 | -80.78569,
959 | 40.96333
960 | ],
961 | [
962 | -80.78798,
963 | 40.96568
964 | ],
965 | [
966 | -80.79022,
967 | 40.96807
968 | ],
969 | [
970 | -80.7924,
971 | 40.97048
972 | ],
973 | [
974 | -80.79487,
975 | 40.9728
976 | ],
977 | [
978 | -80.79728,
979 | 40.97516
980 | ],
981 | [
982 | -80.79964,
983 | 40.97755
984 | ],
985 | [
986 | -80.80194,
987 | 40.97999
988 | ],
989 | [
990 | -80.80419,
991 | 40.98247
992 | ],
993 | [
994 | -80.80639,
995 | 40.98499
996 | ],
997 | [
998 | -80.80852,
999 | 40.98754
1000 | ],
1001 | [
1002 | -80.8106,
1003 | 40.99013
1004 | ],
1005 | [
1006 | -80.81263,
1007 | 40.99275
1008 | ],
1009 | [
1010 | -80.81459,
1011 | 40.99541
1012 | ],
1013 | [
1014 | -80.81632,
1015 | 40.99815
1016 | ],
1017 | [
1018 | -80.81799,
1019 | 41.00092
1020 | ],
1021 | [
1022 | -80.81959,
1023 | 41.00371
1024 | ],
1025 | [
1026 | -80.82113,
1027 | 41.00653
1028 | ],
1029 | [
1030 | -80.82261,
1031 | 41.00938
1032 | ],
1033 | [
1034 | -80.82402,
1035 | 41.01225
1036 | ],
1037 | [
1038 | -80.82536,
1039 | 41.01515
1040 | ],
1041 | [
1042 | -80.82663,
1043 | 41.01807
1044 | ],
1045 | [
1046 | -80.82784,
1047 | 41.02101
1048 | ],
1049 | [
1050 | -80.82899,
1051 | 41.02398
1052 | ],
1053 | [
1054 | -80.8296,
1055 | 41.02701
1056 | ],
1057 | [
1058 | -80.83014,
1059 | 41.03006
1060 | ],
1061 | [
1062 | -80.83061,
1063 | 41.0331
1064 | ],
1065 | [
1066 | -80.83101,
1067 | 41.03616
1068 | ],
1069 | [
1070 | -80.83134,
1071 | 41.03922
1072 | ],
1073 | [
1074 | -80.8316,
1075 | 41.04228
1076 | ],
1077 | [
1078 | -80.83179,
1079 | 41.04535
1080 | ],
1081 | [
1082 | -80.83191,
1083 | 41.04842
1084 | ],
1085 | [
1086 | -80.83195,
1087 | 41.05149
1088 | ],
1089 | [
1090 | -80.83193,
1091 | 41.05456
1092 | ],
1093 | [
1094 | -80.83183,
1095 | 41.05763
1096 | ],
1097 | [
1098 | -80.83167,
1099 | 41.0607
1100 | ],
1101 | [
1102 | -80.83143,
1103 | 41.06376
1104 | ],
1105 | [
1106 | -80.83112,
1107 | 41.06682
1108 | ],
1109 | [
1110 | -80.83074,
1111 | 41.06988
1112 | ],
1113 | [
1114 | -80.83006,
1115 | 41.07291
1116 | ],
1117 | [
1118 | -80.82931,
1119 | 41.07593
1120 | ],
1121 | [
1122 | -80.82848,
1123 | 41.07893
1124 | ],
1125 | [
1126 | -80.82759,
1127 | 41.08192
1128 | ],
1129 | [
1130 | -80.82664,
1131 | 41.0849
1132 | ],
1133 | [
1134 | -80.82584,
1135 | 41.08789
1136 | ],
1137 | [
1138 | -80.82497,
1139 | 41.09088
1140 | ],
1141 | [
1142 | -80.82403,
1143 | 41.09385
1144 | ],
1145 | [
1146 | -80.82303,
1147 | 41.09681
1148 | ],
1149 | [
1150 | -80.82196,
1151 | 41.09975
1152 | ],
1153 | [
1154 | -80.82082,
1155 | 41.10269
1156 | ],
1157 | [
1158 | -80.81961,
1159 | 41.1056
1160 | ],
1161 | [
1162 | -80.81833,
1163 | 41.1085
1164 | ],
1165 | [
1166 | -80.81699,
1167 | 41.11138
1168 | ],
1169 | [
1170 | -80.81558,
1171 | 41.11425
1172 | ],
1173 | [
1174 | -80.81412,
1175 | 41.1171
1176 | ],
1177 | [
1178 | -80.8126,
1179 | 41.11993
1180 | ],
1181 | [
1182 | -80.81101,
1183 | 41.12274
1184 | ],
1185 | [
1186 | -80.80936,
1187 | 41.12553
1188 | ],
1189 | [
1190 | -80.80764,
1191 | 41.1283
1192 | ],
1193 | [
1194 | -80.80586,
1195 | 41.13105
1196 | ],
1197 | [
1198 | -80.80402,
1199 | 41.13377
1200 | ],
1201 | [
1202 | -80.80211,
1203 | 41.13647
1204 | ],
1205 | [
1206 | -80.80014,
1207 | 41.13914
1208 | ],
1209 | [
1210 | -80.79811,
1211 | 41.14179
1212 | ],
1213 | [
1214 | -80.79599,
1215 | 41.1444
1216 | ],
1217 | [
1218 | -80.79382,
1219 | 41.14699
1220 | ],
1221 | [
1222 | -80.79158,
1223 | 41.14954
1224 | ],
1225 | [
1226 | -80.79085,
1227 | 41.15288
1228 | ],
1229 | [
1230 | -80.79138,
1231 | 41.15697
1232 | ],
1233 | [
1234 | -80.79229,
1235 | 41.1614
1236 | ],
1237 | [
1238 | -80.79478,
1239 | 41.16689
1240 | ],
1241 | [
1242 | -80.79937,
1243 | 41.17388
1244 | ],
1245 | [
1246 | -80.80562,
1247 | 41.18222
1248 | ],
1249 | [
1250 | -80.81232,
1251 | 41.19128
1252 | ],
1253 | [
1254 | -80.81787,
1255 | 41.20001
1256 | ],
1257 | [
1258 | -80.82153,
1259 | 41.20785
1260 | ],
1261 | [
1262 | -80.82297,
1263 | 41.21444
1264 | ],
1265 | [
1266 | -80.82322,
1267 | 41.2204
1268 | ],
1269 | [
1270 | -80.82282,
1271 | 41.22607
1272 | ],
1273 | [
1274 | -80.82211,
1275 | 41.2317
1276 | ],
1277 | [
1278 | -80.82079,
1279 | 41.237
1280 | ],
1281 | [
1282 | -80.81856,
1283 | 41.24171
1284 | ],
1285 | [
1286 | -80.81487,
1287 | 41.24525
1288 | ],
1289 | [
1290 | -80.80924,
1291 | 41.24703
1292 | ],
1293 | [
1294 | -80.80169,
1295 | 41.24691
1296 | ],
1297 | [
1298 | -80.79285,
1299 | 41.2453
1300 | ],
1301 | [
1302 | -80.78279,
1303 | 41.24211
1304 | ],
1305 | [
1306 | -80.77179,
1307 | 41.2375
1308 | ],
1309 | [
1310 | -80.76044,
1311 | 41.23196
1312 | ],
1313 | [
1314 | -80.74976,
1315 | 41.2266
1316 | ],
1317 | [
1318 | -80.74038,
1319 | 41.2222
1320 | ],
1321 | [
1322 | -80.73242,
1323 | 41.21907
1324 | ],
1325 | [
1326 | -80.72538,
1327 | 41.21673
1328 | ],
1329 | [
1330 | -80.71954,
1331 | 41.21567
1332 | ],
1333 | [
1334 | -80.71359,
1335 | 41.21423
1336 | ],
1337 | [
1338 | -80.708,
1339 | 41.21307
1340 | ],
1341 | [
1342 | -80.70323,
1343 | 41.21293
1344 | ],
1345 | [
1346 | -80.69894,
1347 | 41.21341
1348 | ],
1349 | [
1350 | -80.6952,
1351 | 41.21476
1352 | ],
1353 | [
1354 | -80.69193,
1355 | 41.21693
1356 | ],
1357 | [
1358 | -80.68926,
1359 | 41.22032
1360 | ],
1361 | [
1362 | -80.68634,
1363 | 41.22345
1364 | ],
1365 | [
1366 | -80.68369,
1367 | 41.22735
1368 | ],
1369 | [
1370 | -80.6805,
1371 | 41.23039
1372 | ],
1373 | [
1374 | -80.67657,
1375 | 41.23197
1376 | ],
1377 | [
1378 | -80.67201,
1379 | 41.23206
1380 | ],
1381 | [
1382 | -80.66693,
1383 | 41.23069
1384 | ],
1385 | [
1386 | -80.66194,
1387 | 41.22926
1388 | ],
1389 | [
1390 | -80.65711,
1391 | 41.22795
1392 | ],
1393 | [
1394 | -80.65234,
1395 | 41.2265
1396 | ],
1397 | [
1398 | -80.64744,
1399 | 41.22423
1400 | ],
1401 | [
1402 | -80.64236,
1403 | 41.22074
1404 | ],
1405 | [
1406 | -80.63744,
1407 | 41.21707
1408 | ],
1409 | [
1410 | -80.63356,
1411 | 41.21737
1412 | ],
1413 | [
1414 | -80.6297,
1415 | 41.21771
1416 | ],
1417 | [
1418 | -80.62583,
1419 | 41.218
1420 | ],
1421 | [
1422 | -80.62195,
1423 | 41.21823
1424 | ],
1425 | [
1426 | -80.61807,
1427 | 41.21842
1428 | ],
1429 | [
1430 | -80.61419,
1431 | 41.21855
1432 | ],
1433 | [
1434 | -80.61031,
1435 | 41.21864
1436 | ],
1437 | [
1438 | -80.60643,
1439 | 41.21867
1440 | ],
1441 | [
1442 | -80.60256,
1443 | 41.21865
1444 | ],
1445 | [
1446 | -80.59868,
1447 | 41.21858
1448 | ]
1449 | ]
1450 | },
1451 | "type": "Feature",
1452 | "properties": {
1453 | "application_id": "811",
1454 | "description": "WKTL BLED-1805",
1455 | "service": "FM"
1456 | }
1457 | }
1458 |
--------------------------------------------------------------------------------
/test/fixture/bad/bad-properties-as-array.cli-output-json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "message": "\"properties\" member should be object, but is an Array instead",
4 | "line": 1
5 | }
6 | ]
7 |
--------------------------------------------------------------------------------
/test/fixture/bad/bad-properties-as-array.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "Feature",
3 | "properties": [],
4 | "geometry": null
5 | }
6 |
--------------------------------------------------------------------------------
/test/fixture/bad/badcoord.cli-output-json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "message": "each element in a position must be a number",
4 | "line": 3
5 | }
6 | ]
7 |
--------------------------------------------------------------------------------
/test/fixture/bad/badcoord.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "Point",
3 | "coordinates": [ 1, 2, "f" ]
4 | }
5 |
--------------------------------------------------------------------------------
/test/fixture/bad/badcoordtype.cli-output-json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "message": "a number was found where a coordinate array should have been found: this needs to be nested more deeply",
4 | "line": 9
5 | }
6 | ]
7 |
--------------------------------------------------------------------------------
/test/fixture/bad/badcoordtype.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "features": [
4 | {
5 | "type": "Feature",
6 | "properties": {},
7 | "geometry": {
8 | "type": "MultiPolygon",
9 | "coordinates": [[[1]]]
10 | }
11 | }
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/test/fixture/bad/badfeature-no-properties.geojson:
--------------------------------------------------------------------------------
1 | { "type": "Feature", "geometry": null }
2 |
--------------------------------------------------------------------------------
/test/fixture/bad/badfeature.cli-output-json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "message": "Every feature must be an object",
4 | "line": 1
5 | }
6 | ]
7 |
--------------------------------------------------------------------------------
/test/fixture/bad/badfeature.geojson:
--------------------------------------------------------------------------------
1 | { "type": "FeatureCollection", "features": [null] }
2 |
--------------------------------------------------------------------------------
/test/fixture/bad/badfeatureid.cli-output-json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "message": "Feature \"id\" member must have a string or number value",
4 | "line": 4
5 | }
6 | ]
7 |
--------------------------------------------------------------------------------
/test/fixture/bad/badfeatureid.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "features": [
4 | {
5 | "type": "Feature",
6 | "id": {},
7 | "properties": {},
8 | "geometry": {
9 | "type": "Point",
10 | "coordinates": [
11 | -100.898438,
12 | 39.368279
13 | ]
14 | }
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/test/fixture/bad/bbox-4or6elements.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "Point",
3 | "coordinates": [2, 2],
4 | "bbox": [1, 2, 3]
5 | }
6 |
--------------------------------------------------------------------------------
/test/fixture/bad/bbox-contains-string.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "Point",
3 | "coordinates": [2, 2],
4 | "bbox": [1, 2, 3, "4"]
5 | }
6 |
--------------------------------------------------------------------------------
/test/fixture/bad/bbox-string.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "Point",
3 | "coordinates": [2, 2],
4 | "bbox": "string"
5 | }
6 |
--------------------------------------------------------------------------------
/test/fixture/bad/different-first-last.geojson:
--------------------------------------------------------------------------------
1 | { "type": "Polygon",
2 | "coordinates": [
3 | [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0] ]
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/test/fixture/bad/different-first-size.geojson:
--------------------------------------------------------------------------------
1 | { "type": "MultiPolygon",
2 | "coordinates": [
3 | [[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]]],
4 | [[[100.0, 0.0], [100.0, 1.0], [101.0, 1.0], [101.0, 0.0], [100.0, 0.0, 4.9]],
5 | [[100.2, 0.2], [100.2, 0.8], [100.8, 0.8], [100.8, 0.2], [100.2, 0.2]]]
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/test/fixture/bad/expected_object.geojson:
--------------------------------------------------------------------------------
1 | {"type": "Feature", "properties": 123, "geometry": null}
2 |
--------------------------------------------------------------------------------
/test/fixture/bad/false.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "GeometryCollection",
3 | "geometries": [false]
4 | }
5 |
--------------------------------------------------------------------------------
/test/fixture/bad/feature_changed_semantics.geojson:
--------------------------------------------------------------------------------
1 | { "type": "Feature",
2 | "features": [],
3 | "coordinates": null,
4 | "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
5 | "properties": {"prop0": "value0"}
6 | }
7 |
--------------------------------------------------------------------------------
/test/fixture/bad/featurecollection-obj.geojson:
--------------------------------------------------------------------------------
1 | { "type": "FeatureCollection", "features": {} }
2 |
--------------------------------------------------------------------------------
/test/fixture/bad/featurecollection-type-case.geojson:
--------------------------------------------------------------------------------
1 | { "type": "featurecollection",
2 | "features": [
3 | { "type": "feature",
4 | "geometry": {"type": "point", "coordinates": [102.0, 0.5]},
5 | "properties": {"prop0": "value0"}
6 | },
7 | { "type": "feature",
8 | "geometry": {
9 | "type": "linestring",
10 | "coordinates": [
11 | [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]
12 | ]
13 | },
14 | "properties": {
15 | "prop0": "value0",
16 | "prop1": 0.0
17 | }
18 | },
19 | { "type": "feature",
20 | "geometry": {
21 | "type": "polygon",
22 | "coordinates": [
23 | [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
24 | [100.0, 1.0], [100.0, 0.0] ]
25 | ]
26 | },
27 | "properties": {
28 | "prop0": "value0",
29 | "prop1": {"this": "that"}
30 | }
31 | }
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/test/fixture/bad/featurecollection.geojson:
--------------------------------------------------------------------------------
1 | { "type": "FeatureCollection" }
2 |
--------------------------------------------------------------------------------
/test/fixture/bad/featurecollection_changed_semantics.geojson:
--------------------------------------------------------------------------------
1 | { "type": "FeatureCollection",
2 | "properties": {},
3 | "coordinates": null,
4 | "features": [
5 | { "type": "Feature",
6 | "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
7 | "properties": {"prop0": "value0"}
8 | },
9 | { "type": "Feature",
10 | "geometry": {
11 | "type": "LineString",
12 | "coordinates": [
13 | [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]
14 | ]
15 | },
16 | "properties": {
17 | "prop0": "value0",
18 | "prop1": 0.0
19 | }
20 | },
21 | { "type": "Feature",
22 | "geometry": {
23 | "type": "Polygon",
24 | "coordinates": [
25 | [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ]
26 | ]
27 | },
28 | "properties": {
29 | "prop0": "value0",
30 | "prop1": {"this": "that"}
31 | }
32 | }
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/test/fixture/bad/geometry_changed_semantics.geojson:
--------------------------------------------------------------------------------
1 | { "type": "Point",
2 | "features": [],
3 | "geometry": null,
4 | "properties": {},
5 | "coordinates": [100.0, 0.0] }
6 |
--------------------------------------------------------------------------------
/test/fixture/bad/geometrycollection_nested.geojson:
--------------------------------------------------------------------------------
1 | { "type": "GeometryCollection",
2 | "geometries": [
3 | { "type": "Point",
4 | "coordinates": [101.0, 2.0]
5 | },
6 | { "type": "GeometryCollection",
7 | "geometries": [
8 | { "type": "Point",
9 | "coordinates": [100.0, 0.0]
10 | },
11 | { "type": "LineString",
12 | "coordinates": [ [101.0, 0.0], [102.0, 1.0] ]
13 | }
14 | ]
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/test/fixture/bad/multiple_problems.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "features": [
4 | {
5 | "type": "Feature",
6 | "properties": {},
7 | "id": {},
8 | "geometry": {
9 | "type": "Point",
10 | "coordinates": [
11 | -100.8984375,
12 | "39.36827914916011"
13 | ]
14 | }
15 | },
16 | {
17 | "type": "Feature",
18 | "properties": {},
19 | "geometry": {
20 | "type": "Point",
21 | "coordinates": [
22 | 20.390625,
23 | 41.508577
24 | ]
25 | }
26 | },
27 | {
28 | "type": "Foo",
29 | "properties": {},
30 | "geometry": {
31 | "type": "Point",
32 | "coordinates": [
33 | 20.390625,
34 | 41.508577
35 | ]
36 | }
37 | },
38 | {
39 | "type": "Foo",
40 | "properties": {},
41 | "geometry": {
42 | "type": "Point",
43 | "coordinates": "foo"
44 | }
45 | }
46 | ]
47 | }
48 |
--------------------------------------------------------------------------------
/test/fixture/bad/multipoint-multidimension.geojson:
--------------------------------------------------------------------------------
1 | { "type": "MultiPoint", "coordinates": [[[0,0],[0,0]]] }
2 |
--------------------------------------------------------------------------------
/test/fixture/bad/multipoint-nocoordinates.geojson:
--------------------------------------------------------------------------------
1 | { "type": "MultiPoint" }
2 |
--------------------------------------------------------------------------------
/test/fixture/bad/multipoint-nondimension.geojson:
--------------------------------------------------------------------------------
1 | { "type": "MultiPoint", "coordinates": [0,0] }
2 |
--------------------------------------------------------------------------------
/test/fixture/bad/nofeaturetype.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "features": [
4 | {
5 | "type": "Featre",
6 | "properties": {},
7 | "geometry": {
8 | "type": "Point",
9 | "coordinates": [
10 | -73.828125,
11 | 38.548165
12 | ]
13 | }
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/test/fixture/bad/notype.geojson:
--------------------------------------------------------------------------------
1 | {
2 | }
3 |
--------------------------------------------------------------------------------
/test/fixture/bad/point-labeled-as-a-multipolygon.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "Feature",
3 | "properties": {},
4 | "geometry": {
5 | "type": "MultiPolygon",
6 | "coordinates": [
7 | -0.087890625,
8 | 51.56341232867588
9 | ]
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/test/fixture/bad/point-string.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "Point",
3 | "coordinates": ["foo", 2]
4 | }
5 |
--------------------------------------------------------------------------------
/test/fixture/bad/point-toofew.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "Point",
3 | "coordinates": [2]
4 | }
5 |
--------------------------------------------------------------------------------
/test/fixture/bad/point-toomany.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "Point",
3 | "coordinates": [2, 4, 6, 8]
4 | }
5 |
--------------------------------------------------------------------------------
/test/fixture/bad/point.geojson:
--------------------------------------------------------------------------------
1 | { "type": "Point" }
2 |
--------------------------------------------------------------------------------
/test/fixture/bad/rootstring.geojson:
--------------------------------------------------------------------------------
1 | null
2 |
--------------------------------------------------------------------------------
/test/fixture/bad/short-line.geojson:
--------------------------------------------------------------------------------
1 | { "type": "LineString",
2 | "coordinates": [ [100.0, 0.0] ]
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixture/bad/short-linearring.geojson:
--------------------------------------------------------------------------------
1 | { "type": "Polygon",
2 | "coordinates": [
3 | [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0] ]
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/test/fixture/bad/short-multilinestring.geojson:
--------------------------------------------------------------------------------
1 | { "type": "MultiLineString",
2 | "coordinates": [
3 | [ [100.0, 0.0], [101.0, 1.0] ],
4 | [ [102.0, 2.0] ]
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/test/fixture/bad/stringcoord.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FeatureCollection",
3 | "features": [
4 | {
5 | "type": "Feature",
6 | "properties": {},
7 | "geometry": {
8 | "type": "Point",
9 | "coordinates": [
10 | -100.8984375,
11 | "39.36827914916011"
12 | ]
13 | }
14 | },
15 | {
16 | "type": "Feature",
17 | "properties": {},
18 | "geometry": {
19 | "type": "Point",
20 | "coordinates": [
21 | 20.390625,
22 | 41.508577
23 | ]
24 | }
25 | }
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/test/fixture/bad/unknowntype.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "FooBar"
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixture/good/good-feature-with-id.geojson:
--------------------------------------------------------------------------------
1 | { "type": "Feature",
2 | "id": 100,
3 | "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
4 | "properties": {"prop0": "value0"}
5 | }
6 |
--------------------------------------------------------------------------------
/test/fixture/good/good-feature-with-string-id.geojson:
--------------------------------------------------------------------------------
1 | { "type": "Feature",
2 | "id": "myfeature",
3 | "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
4 | "properties": {"prop0": "value0"}
5 | }
6 |
--------------------------------------------------------------------------------
/test/fixture/good/good-feature.geojson:
--------------------------------------------------------------------------------
1 | {
2 | "type": "Feature",
3 | "bbox": [102.0, 0.5, 102.0, 0.5],
4 | "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
5 | "properties": {"prop0": "value0"}
6 | }
7 |
--------------------------------------------------------------------------------
/test/fixture/good/good-featurecollection-bbox.geojson:
--------------------------------------------------------------------------------
1 | { "type": "FeatureCollection",
2 | "bbox": [100.0, 0.5, 102.0, 2.5],
3 | "features": [
4 | { "type": "Feature",
5 | "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
6 | "properties": {"prop0": "value0"}
7 | },
8 | { "type": "Feature",
9 | "geometry": {"type": "Point", "coordinates": [100.0, 2.5]},
10 | "properties": {"prop0": "value0"}
11 | }
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/test/fixture/good/good-featurecollection-bbox3d.geojson:
--------------------------------------------------------------------------------
1 | { "type": "FeatureCollection",
2 | "bbox": [100.0, 0.5, 15.0, 102.0, 2.5, 25.0],
3 | "features": [
4 | { "type": "Feature",
5 | "geometry": {"type": "Point", "coordinates": [102.0, 0.5, 15.0]},
6 | "properties": {"prop0": "value0"}
7 | },
8 | { "type": "Feature",
9 | "geometry": {"type": "Point", "coordinates": [100.0, 2.5, 25.0]},
10 | "properties": {"prop0": "value0"}
11 | }
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/test/fixture/good/good-featurecollection-extensions.geojson:
--------------------------------------------------------------------------------
1 | { "type": "FeatureCollection",
2 | "custom": true,
3 | "features": [
4 | { "type": "Feature",
5 | "geometry": {
6 | "type": "Point",
7 | "custom": true,
8 | "coordinates": [102.0, 0.5]},
9 | "properties": {"prop0": "value0"},
10 | "custom": true
11 | },
12 | { "type": "Feature",
13 | "geometry": {
14 | "type": "LineString",
15 | "custom": true,
16 | "coordinates": [
17 | [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]
18 | ]
19 | },
20 | "properties": {
21 | "prop0": "value0",
22 | "prop1": 0.0
23 | }
24 | },
25 | { "type": "Feature",
26 | "geometry": {
27 | "type": "Polygon",
28 | "custom": true,
29 | "coordinates": [
30 | [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
31 | [100.0, 1.0], [100.0, 0.0] ]
32 | ]
33 | },
34 | "properties": {
35 | "prop0": "value0",
36 | "prop1": {"this": "that"}
37 | }
38 | }
39 | ]
40 | }
41 |
--------------------------------------------------------------------------------
/test/fixture/good/good-featurecollection.geojson:
--------------------------------------------------------------------------------
1 | { "type": "FeatureCollection",
2 | "features": [
3 | { "type": "Feature",
4 | "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
5 | "properties": {"prop0": "value0"}
6 | },
7 | { "type": "Feature",
8 | "geometry": {
9 | "type": "LineString",
10 | "coordinates": [
11 | [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]
12 | ]
13 | },
14 | "properties": {
15 | "prop0": "value0",
16 | "prop1": 0.0
17 | }
18 | },
19 | { "type": "Feature",
20 | "geometry": {
21 | "type": "Polygon",
22 | "coordinates": [
23 | [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ]
24 | ]
25 | },
26 | "properties": {
27 | "prop0": "value0",
28 | "prop1": {"this": "that"}
29 | }
30 | }
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/test/fixture/good/good-geometrycollection.geojson:
--------------------------------------------------------------------------------
1 | { "type": "GeometryCollection",
2 | "geometries": [
3 | { "type": "Point",
4 | "coordinates": [100.0, 0.0]
5 | },
6 | { "type": "LineString",
7 | "coordinates": [ [101.0, 0.0], [102.0, 1.0] ]
8 | }
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/test/fixture/good/good-linestring.geojson:
--------------------------------------------------------------------------------
1 | { "type": "LineString",
2 | "coordinates": [ [100.0, 0.0], [101.0, 1.0] ]
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixture/good/good-multilinestring.geojson:
--------------------------------------------------------------------------------
1 | { "type": "MultiLineString",
2 | "coordinates": [
3 | [ [100.0, 0.0], [101.0, 1.0] ],
4 | [ [102.0, 2.0], [103.0, 3.0] ]
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/test/fixture/good/good-multipoint.geojson:
--------------------------------------------------------------------------------
1 | { "type": "MultiPoint", "coordinates": [[100.0, 0.0]] }
2 |
--------------------------------------------------------------------------------
/test/fixture/good/good-point-3d.geojson:
--------------------------------------------------------------------------------
1 | { "type": "Point", "coordinates": [100.0, 0.0, 15.0] }
2 |
--------------------------------------------------------------------------------
/test/fixture/good/good-point.geojson:
--------------------------------------------------------------------------------
1 | { "type": "Point", "coordinates": [100.0, 0.0] }
2 |
--------------------------------------------------------------------------------
/test/fixture/good/good-polygon.geojson:
--------------------------------------------------------------------------------
1 | { "type": "Polygon",
2 | "coordinates": [
3 | [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ]
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/test/fixture/good/multipolygon.geojson:
--------------------------------------------------------------------------------
1 | { "type": "MultiPolygon",
2 | "coordinates": [
3 | [[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]]],
4 | [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],
5 | [[100.2, 0.2], [100.2, 0.8], [100.8, 0.8], [100.8, 0.2], [100.2, 0.2]]]
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/test/fixture/good/nullgeometry.geojson:
--------------------------------------------------------------------------------
1 | { "type": "FeatureCollection", "features": [{
2 | "type": "Feature",
3 | "properties": {},
4 | "geometry": null
5 | }] }
6 |
--------------------------------------------------------------------------------
/test/fixture/good/nullproperties.geojson:
--------------------------------------------------------------------------------
1 | { "type": "FeatureCollection", "features": [{
2 | "type": "Feature",
3 | "properties": null,
4 | "geometry": {
5 | "type": "Point",
6 | "coordinates": [0,0]
7 | }
8 | }] }
9 |
--------------------------------------------------------------------------------
/test/good.test.ts:
--------------------------------------------------------------------------------
1 | import { check } from '../lib';
2 | import { describe, expect, it } from 'vitest';
3 | import * as Path from 'path';
4 | import { readFileSync, readdirSync } from 'fs';
5 |
6 | const examplePoint = {
7 | type: 'Point',
8 | coordinates: [0, 1],
9 | };
10 | const exampleFeature = {
11 | type: 'Feature',
12 | properties: {
13 | test: true,
14 | },
15 | geometry: examplePoint,
16 | };
17 | const exampleFeatureCollection = {
18 | type: 'FeatureCollection',
19 | features: [exampleFeature],
20 | };
21 | describe('check', () => {
22 | it('works with fixed examples', () => {
23 | const examples = [
24 | examplePoint,
25 | exampleFeature,
26 | exampleFeatureCollection,
27 | {
28 | type: 'Polygon',
29 | coordinates: [
30 | [
31 | [100.0, 0.0],
32 | [101.0, 0.0],
33 | [101.0, 1.0],
34 | [100.0, 1.0],
35 | [100.0, 0.0],
36 | ],
37 | [
38 | [100.8, 0.8],
39 | [100.8, 0.2],
40 | [100.2, 0.2],
41 | [100.2, 0.8],
42 | [100.8, 0.8],
43 | ],
44 | ],
45 | },
46 | {
47 | type: 'MultiPoint',
48 | coordinates: [
49 | [100.0, 0.0],
50 | [101.0, 1.0],
51 | ],
52 | },
53 | {
54 | type: 'MultiLineString',
55 | coordinates: [
56 | [
57 | [100.0, 0.0],
58 | [101.0, 1.0],
59 | ],
60 | [
61 | [102.0, 2.0],
62 | [103.0, 3.0],
63 | ],
64 | ],
65 | },
66 | {
67 | type: 'MultiPolygon',
68 | coordinates: [
69 | [
70 | [
71 | [102.0, 2.0],
72 | [103.0, 2.0],
73 | [103.0, 3.0],
74 | [102.0, 3.0],
75 | [102.0, 2.0],
76 | ],
77 | ],
78 | [
79 | [
80 | [100.0, 0.0],
81 | [101.0, 0.0],
82 | [101.0, 1.0],
83 | [100.0, 1.0],
84 | [100.0, 0.0],
85 | ],
86 | [
87 | [100.2, 0.2],
88 | [100.2, 0.8],
89 | [100.8, 0.8],
90 | [100.8, 0.2],
91 | [100.2, 0.2],
92 | ],
93 | ],
94 | ],
95 | },
96 | {
97 | type: 'GeometryCollection',
98 | geometries: [
99 | {
100 | type: 'Point',
101 | coordinates: [100.0, 0.0],
102 | },
103 | {
104 | type: 'LineString',
105 | coordinates: [
106 | [101.0, 0.0],
107 | [102.0, 1.0],
108 | ],
109 | },
110 | ],
111 | },
112 | ];
113 | for (const obj of examples) {
114 | check(JSON.stringify(obj));
115 | expect(check(JSON.stringify(obj))).toEqual(obj);
116 | }
117 | });
118 | describe('works with fixtures', () => {
119 | const fixtureNames = readdirSync(Path.join(__dirname, './fixture/good/'));
120 | for (const name of fixtureNames) {
121 | it(`fixture: ${name}`, () => {
122 | const input = readFileSync(
123 | Path.join(__dirname, './fixture/good/', name),
124 | 'utf8'
125 | );
126 | expect(check(input)).toEqual(JSON.parse(input));
127 | });
128 | }
129 | });
130 | });
131 |
--------------------------------------------------------------------------------
/test/scavenge.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 | import { scavenge } from '../lib';
3 |
4 | describe('scavenge', () => {
5 | it('partially correct fc', () => {
6 | expect(
7 | scavenge(
8 | JSON.stringify({
9 | type: 'FeatureCollection',
10 |
11 | features: [
12 | {
13 | type: 'Feature',
14 | geometry: {
15 | type: 'Point',
16 | coordinates: [0, 0],
17 | },
18 | properties: {},
19 | },
20 | {
21 | type: 'bad',
22 | },
23 | ],
24 | })
25 | )
26 | ).toEqual({
27 | result: {
28 | type: 'FeatureCollection',
29 | features: [
30 | {
31 | type: 'Feature',
32 | geometry: {
33 | type: 'Point',
34 | coordinates: [0, 0],
35 | },
36 | properties: {},
37 | },
38 | ],
39 | },
40 | rejected: [
41 | {
42 | feature: {
43 | type: 'bad',
44 | },
45 | reasons: [
46 | {
47 | from: 123,
48 | message: 'This type of GeoJSON object is not allowed here.',
49 | severity: 'error',
50 | to: 137,
51 | },
52 | {
53 | from: 123,
54 | message:
55 | 'This GeoJSON object requires a geometry member but it is missing.',
56 | severity: 'error',
57 | to: 137,
58 | },
59 | {
60 | from: 123,
61 | message:
62 | 'This GeoJSON object requires a properties member but it is missing.',
63 | severity: 'error',
64 | to: 137,
65 | },
66 | {
67 | from: 123,
68 | message: 'The properties member is missing.',
69 | severity: 'error',
70 | to: 137,
71 | },
72 | ],
73 | },
74 | ],
75 | });
76 | });
77 | });
78 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs
3 | "include": ["lib", "types"],
4 | "compilerOptions": {
5 | "module": "esnext",
6 | "target": "es6",
7 | "lib": ["dom", "esnext"],
8 | "importHelpers": true,
9 | // output .d.ts declaration files for consumers
10 | "declaration": true,
11 | // output .js.map sourcemap files for consumers
12 | "sourceMap": true,
13 | // match output dir to input dir. e.g. dist/index instead of dist/src/index
14 | "rootDir": "./lib",
15 | // stricter type-checking for stronger correctness. Recommended by TS
16 | "strict": true,
17 | // linter checks for common issues
18 | "noImplicitReturns": true,
19 | "noFallthroughCasesInSwitch": true,
20 | // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative
21 | "noUnusedLocals": true,
22 | // "noUnusedParameters": true,
23 | // use Node's module resolution algorithm, instead of the legacy TS one
24 | "moduleResolution": "node",
25 | // transpile JSX to React.createElement
26 | "jsx": "preserve",
27 | // interop between ESM and CJS modules. Recommended by TS
28 | "esModuleInterop": true,
29 | // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS
30 | "skipLibCheck": true,
31 | // error out if import and file system have a casing mismatch. Recommended by TS
32 | "forceConsistentCasingInFileNames": true,
33 | // `tsdx build` ignores this option, but it is commonly used when type-checking separately with `tsc`
34 | "noEmit": true,
35 | "downlevelIteration": true
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/typedoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "entryPoints": ["./lib/index.ts"],
3 | "entryPointStrategy":"Expand",
4 | "out": "docs"
5 | }
6 |
--------------------------------------------------------------------------------
/types/momoa.d.ts:
--------------------------------------------------------------------------------
1 | declare module '@humanwhocodes/momoa' {
2 | import { JSONValue } from 'type-fest';
3 |
4 | type ParseOptions = {
5 | ranges?: boolean;
6 | comments?: boolean;
7 | tokens?: boolean;
8 | };
9 |
10 | export type Loc = {
11 | line: number;
12 | column: number;
13 | offset: number;
14 | };
15 |
16 | export type LocRange = {
17 | start: Loc;
18 | end: Loc;
19 | };
20 |
21 | export type Range = [number, number];
22 |
23 | interface BaseNode {
24 | loc: LocRange;
25 | range: {
26 | range: Range;
27 | };
28 | }
29 |
30 | export interface DocumentNode extends BaseNode {
31 | type: 'Document';
32 | body: Node;
33 | }
34 |
35 | export interface BooleanNode extends BaseNode {
36 | type: 'Boolean';
37 | value: boolean;
38 | }
39 |
40 | export interface NumberNode extends BaseNode {
41 | type: 'Number';
42 | value: number;
43 | }
44 |
45 | export interface NullNode extends BaseNode {
46 | type: 'Null';
47 | value: null;
48 | }
49 |
50 | export interface StringNode extends BaseNode {
51 | type: 'String';
52 | value: string;
53 | }
54 |
55 | export interface ObjectNode extends BaseNode {
56 | type: 'Object';
57 | name: StringNode;
58 | members: MemberNode[];
59 | }
60 |
61 | export interface ArrayNode extends BaseNode {
62 | type: 'Array';
63 | elements: Node[];
64 | }
65 |
66 | export interface MemberNode extends BaseNode {
67 | type: 'Member';
68 | name: StringNode;
69 | value: Node;
70 | }
71 |
72 | type Node =
73 | | MemberNode
74 | | ObjectNode
75 | | StringNode
76 | | NumberNode
77 | | DocumentNode
78 | | NullNode
79 | | ArrayNode;
80 |
81 | type Phase = 'enter' | 'exit';
82 |
83 | interface IteratorState {
84 | node: Node;
85 | parent: Node;
86 | phase: Phase;
87 | }
88 |
89 | export function parse(jsonStr: string, options?: ParseOptions): DocumentNode;
90 | export function iterator(ast: Node): Generator;
91 | export function evaluate(ast: Node): JSONValue;
92 | }
93 |
--------------------------------------------------------------------------------
Optional override for formatting stack traces
3 |https://v8.dev/docs/stack-trace-api#customizing-stack-traces
4 |