@math.gl/crs 4.2.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +140 -0
- package/README.md +40 -0
- package/dist/crs.d.ts +22 -0
- package/dist/crs.d.ts.map +1 -0
- package/dist/crs.js +5 -0
- package/dist/crs.js.map +1 -0
- package/dist/index.cjs +804 -0
- package/dist/index.cjs.map +6 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/proj-string.d.ts +32 -0
- package/dist/proj-string.d.ts.map +1 -0
- package/dist/proj-string.js +195 -0
- package/dist/proj-string.js.map +1 -0
- package/dist/projjson-schema-constants.d.ts +5 -0
- package/dist/projjson-schema-constants.d.ts.map +1 -0
- package/dist/projjson-schema-constants.js +8 -0
- package/dist/projjson-schema-constants.js.map +1 -0
- package/dist/projjson-types.d.ts +509 -0
- package/dist/projjson-types.d.ts.map +1 -0
- package/dist/projjson-types.js +5 -0
- package/dist/projjson-types.js.map +1 -0
- package/dist/wkt-crs.d.ts +86 -0
- package/dist/wkt-crs.d.ts.map +1 -0
- package/dist/wkt-crs.js +610 -0
- package/dist/wkt-crs.js.map +1 -0
- package/package.json +40 -0
- package/schemas/README.md +9 -0
- package/schemas/projjson.schema.json +1174 -0
- package/src/crs.ts +36 -0
- package/src/index.ts +46 -0
- package/src/proj-string.ts +229 -0
- package/src/projjson-schema-constants.ts +9 -0
- package/src/projjson-types.ts +613 -0
- package/src/wkt-crs.ts +787 -0
package/src/crs.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// math.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import type {PROJJSONCRS} from './projjson-types';
|
|
6
|
+
|
|
7
|
+
/** A registered or named CRS identifier, such as `EPSG:4326` or `WGS84`. */
|
|
8
|
+
export type CRSIdentifier = string;
|
|
9
|
+
|
|
10
|
+
/** A coordinate reference system serialized using WKT1 or WKT2. */
|
|
11
|
+
export type WKTCRSDefinition = string;
|
|
12
|
+
|
|
13
|
+
/** A coordinate reference system serialized using PROJ string syntax. */
|
|
14
|
+
export type PROJStringDefinition = string;
|
|
15
|
+
|
|
16
|
+
/** A serialized or named coordinate reference system definition. */
|
|
17
|
+
export type CRSStringDefinition = CRSIdentifier | WKTCRSDefinition | PROJStringDefinition;
|
|
18
|
+
|
|
19
|
+
/** Top-level coordinate reference system object types defined by PROJJSON v0.7. */
|
|
20
|
+
export type PROJJSONCRSType = NonNullable<PROJJSONCRS['type']>;
|
|
21
|
+
|
|
22
|
+
type PROJJSONCRSBranchByType<CRS, T> = CRS extends {type?: infer Type}
|
|
23
|
+
? T extends Type
|
|
24
|
+
? CRS & {type: T}
|
|
25
|
+
: never
|
|
26
|
+
: never;
|
|
27
|
+
|
|
28
|
+
/** Selects PROJJSON CRS objects with a specific required top-level `type`. */
|
|
29
|
+
export type PROJJSONCRSByType<T extends PROJJSONCRSType> = T extends unknown
|
|
30
|
+
? PROJJSONCRSBranchByType<PROJJSONCRS, T>
|
|
31
|
+
: never;
|
|
32
|
+
|
|
33
|
+
/** A serialized CRS definition or a standards-based PROJJSON CRS object. */
|
|
34
|
+
export type CRSDefinition<T extends PROJJSONCRS = PROJJSONCRS> = CRSStringDefinition | T;
|
|
35
|
+
|
|
36
|
+
export type {PROJJSONCRS};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// math.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
PROJJSON_SCHEMA_URL,
|
|
7
|
+
PROJJSON_SCHEMA_VERSION
|
|
8
|
+
} from './projjson-schema-constants';
|
|
9
|
+
export type {
|
|
10
|
+
CRSDefinition,
|
|
11
|
+
CRSIdentifier,
|
|
12
|
+
CRSStringDefinition,
|
|
13
|
+
PROJJSONCRS,
|
|
14
|
+
PROJJSONCRSByType,
|
|
15
|
+
PROJJSONCRSType,
|
|
16
|
+
PROJStringDefinition,
|
|
17
|
+
WKTCRSDefinition
|
|
18
|
+
} from './crs';
|
|
19
|
+
export type {
|
|
20
|
+
EncodeWKTCRSOptions,
|
|
21
|
+
ParseWKTCRSOptions,
|
|
22
|
+
ValidateWKTCRSOptions,
|
|
23
|
+
WKTCRSAst,
|
|
24
|
+
WKTCRSDelimiter,
|
|
25
|
+
WKTCRSEnumeration,
|
|
26
|
+
WKTCRSNode,
|
|
27
|
+
WKTCRSNumber,
|
|
28
|
+
WKTCRSProfile,
|
|
29
|
+
WKTCRSString,
|
|
30
|
+
WKTCRSValidationIssue,
|
|
31
|
+
WKTCRSValidationIssueCode,
|
|
32
|
+
WKTCRSValue
|
|
33
|
+
} from './wkt-crs';
|
|
34
|
+
export {
|
|
35
|
+
encodeWKTCRS,
|
|
36
|
+
parseWKTCRS,
|
|
37
|
+
validateWKTCRS,
|
|
38
|
+
WKTCRSSyntaxError,
|
|
39
|
+
WKTCRSValidationError
|
|
40
|
+
} from './wkt-crs';
|
|
41
|
+
export type {EncodePROJStringOptions, PROJParameter, PROJStringAst} from './proj-string';
|
|
42
|
+
export {
|
|
43
|
+
encodePROJString,
|
|
44
|
+
parsePROJString,
|
|
45
|
+
PROJStringSyntaxError
|
|
46
|
+
} from './proj-string';
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// math.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
/** One ordered parameter or flag in a PROJ string. */
|
|
6
|
+
export type PROJParameter = {
|
|
7
|
+
readonly type: 'parameter';
|
|
8
|
+
readonly name: string;
|
|
9
|
+
/** Decoded parameter value. Omitted for flags such as `+no_defs`. */
|
|
10
|
+
readonly value?: string;
|
|
11
|
+
/** Original value lexeme, including quotes, retained for value-preserving encoding. */
|
|
12
|
+
readonly rawValue?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/** Syntax tree for one PROJ string. */
|
|
16
|
+
export type PROJStringAst = {
|
|
17
|
+
readonly type: 'proj-string';
|
|
18
|
+
readonly parameters: readonly PROJParameter[];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** Options for encoding a PROJ syntax tree. */
|
|
22
|
+
export type EncodePROJStringOptions = {
|
|
23
|
+
/** Compact output uses spaces; multiline output emits one parameter per line. */
|
|
24
|
+
format?: 'compact' | 'multiline';
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** Syntax error containing a source offset and one-based line and column. */
|
|
28
|
+
export class PROJStringSyntaxError extends SyntaxError {
|
|
29
|
+
readonly offset: number;
|
|
30
|
+
readonly line: number;
|
|
31
|
+
readonly column: number;
|
|
32
|
+
|
|
33
|
+
/** Create a PROJ string syntax error at a source location. */
|
|
34
|
+
constructor(message: string, source: string, offset: number) {
|
|
35
|
+
const location = getSourceLocation(source, offset);
|
|
36
|
+
super(`${message} at ${location.line}:${location.column}`);
|
|
37
|
+
this.name = 'PROJStringSyntaxError';
|
|
38
|
+
this.offset = offset;
|
|
39
|
+
this.line = location.line;
|
|
40
|
+
this.column = location.column;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Parse an ordered PROJ definition or pipeline without interpreting parameter semantics. */
|
|
45
|
+
export function parsePROJString(text: string): PROJStringAst {
|
|
46
|
+
const tokens = tokenizePROJString(text);
|
|
47
|
+
if (tokens.length === 0) {
|
|
48
|
+
throw new PROJStringSyntaxError('PROJ string is empty', text, 0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const parameters = tokens.map(token => parseParameter(token.raw, token.offset, text));
|
|
52
|
+
return {type: 'proj-string', parameters};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Encode an ordered PROJ definition using canonical leading plus signs. */
|
|
56
|
+
export function encodePROJString(ast: PROJStringAst, options?: EncodePROJStringOptions): string {
|
|
57
|
+
if (!ast || ast.type !== 'proj-string' || !Array.isArray(ast.parameters)) {
|
|
58
|
+
throw new TypeError('encodePROJString expects a PROJStringAst');
|
|
59
|
+
}
|
|
60
|
+
if (ast.parameters.length === 0) {
|
|
61
|
+
throw new TypeError('encodePROJString expects at least one parameter');
|
|
62
|
+
}
|
|
63
|
+
const separator = options?.format === 'multiline' ? '\n' : ' ';
|
|
64
|
+
return ast.parameters
|
|
65
|
+
.map(parameter => {
|
|
66
|
+
if (!parameter.name || /[\s+=]/.test(parameter.name)) {
|
|
67
|
+
throw new TypeError(`Invalid PROJ parameter name: ${parameter.name}`);
|
|
68
|
+
}
|
|
69
|
+
if (parameter.rawValue !== undefined) {
|
|
70
|
+
validateRawParameterValue(parameter.rawValue);
|
|
71
|
+
return `+${parameter.name}=${parameter.rawValue}`;
|
|
72
|
+
}
|
|
73
|
+
if (parameter.value !== undefined) {
|
|
74
|
+
return `+${parameter.name}=${encodeParameterValue(parameter.value)}`;
|
|
75
|
+
}
|
|
76
|
+
return `+${parameter.name}`;
|
|
77
|
+
})
|
|
78
|
+
.join(separator);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function validateRawParameterValue(rawValue: string): void {
|
|
82
|
+
if (typeof rawValue !== 'string') {
|
|
83
|
+
throw new TypeError('Invalid PROJ raw parameter value');
|
|
84
|
+
}
|
|
85
|
+
if (!rawValue) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const first = rawValue[0];
|
|
89
|
+
if (first !== '"' && first !== "'") {
|
|
90
|
+
if (/\s|["']/.test(rawValue)) {
|
|
91
|
+
throw new TypeError(`Invalid PROJ raw parameter value: ${rawValue}`);
|
|
92
|
+
}
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
let escaped = false;
|
|
96
|
+
for (let index = 1; index < rawValue.length; index++) {
|
|
97
|
+
const character = rawValue[index];
|
|
98
|
+
if (escaped) {
|
|
99
|
+
escaped = false;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (character === '\\') {
|
|
103
|
+
escaped = true;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (character === first && index !== rawValue.length - 1) {
|
|
107
|
+
throw new TypeError(`Invalid PROJ raw parameter value: ${rawValue}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (escaped || rawValue[rawValue.length - 1] !== first) {
|
|
111
|
+
throw new TypeError(`Invalid PROJ raw parameter value: ${rawValue}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function parseParameter(rawToken: string, offset: number, source: string): PROJParameter {
|
|
116
|
+
const token = rawToken.startsWith('+') ? rawToken.slice(1) : rawToken;
|
|
117
|
+
if (!token) {
|
|
118
|
+
throw new PROJStringSyntaxError("Expected a parameter after '+'", source, offset);
|
|
119
|
+
}
|
|
120
|
+
const equalsIndex = token.indexOf('=');
|
|
121
|
+
const name = equalsIndex < 0 ? token : token.slice(0, equalsIndex);
|
|
122
|
+
if (!name || /[\s+=]/.test(name)) {
|
|
123
|
+
throw new PROJStringSyntaxError(`Invalid PROJ parameter name '${name}'`, source, offset);
|
|
124
|
+
}
|
|
125
|
+
if (equalsIndex < 0) {
|
|
126
|
+
return {type: 'parameter', name};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const rawValue = token.slice(equalsIndex + 1);
|
|
130
|
+
const value = decodeParameterValue(rawValue, source, offset + equalsIndex + 1);
|
|
131
|
+
return {type: 'parameter', name, value, rawValue};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function tokenizePROJString(source: string): {raw: string; offset: number}[] {
|
|
135
|
+
const tokens: {raw: string; offset: number}[] = [];
|
|
136
|
+
let offset = 0;
|
|
137
|
+
while (offset < source.length) {
|
|
138
|
+
while (offset < source.length && /\s/.test(source[offset])) {
|
|
139
|
+
offset++;
|
|
140
|
+
}
|
|
141
|
+
if (offset >= source.length) {
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
const start = offset;
|
|
145
|
+
let quote: '"' | "'" | null = null;
|
|
146
|
+
let escaped = false;
|
|
147
|
+
while (offset < source.length) {
|
|
148
|
+
const character = source[offset];
|
|
149
|
+
if (escaped) {
|
|
150
|
+
escaped = false;
|
|
151
|
+
offset++;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (character === '\\' && quote) {
|
|
155
|
+
escaped = true;
|
|
156
|
+
offset++;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (quote) {
|
|
160
|
+
if (character === quote) {
|
|
161
|
+
quote = null;
|
|
162
|
+
}
|
|
163
|
+
offset++;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (character === '"' || character === "'") {
|
|
167
|
+
quote = character;
|
|
168
|
+
offset++;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (/\s/.test(character)) {
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
offset++;
|
|
175
|
+
}
|
|
176
|
+
if (quote) {
|
|
177
|
+
throw new PROJStringSyntaxError('Unterminated quoted PROJ value', source, start);
|
|
178
|
+
}
|
|
179
|
+
tokens.push({raw: source.slice(start, offset), offset: start});
|
|
180
|
+
}
|
|
181
|
+
return tokens;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function decodeParameterValue(rawValue: string, source: string, offset: number): string {
|
|
185
|
+
if (!rawValue) {
|
|
186
|
+
return '';
|
|
187
|
+
}
|
|
188
|
+
const first = rawValue[0];
|
|
189
|
+
if (first !== '"' && first !== "'") {
|
|
190
|
+
if (rawValue.includes('"') || rawValue.includes("'")) {
|
|
191
|
+
throw new PROJStringSyntaxError('Quote must begin a PROJ parameter value', source, offset);
|
|
192
|
+
}
|
|
193
|
+
return rawValue;
|
|
194
|
+
}
|
|
195
|
+
if (rawValue[rawValue.length - 1] !== first) {
|
|
196
|
+
throw new PROJStringSyntaxError('Unterminated quoted PROJ value', source, offset);
|
|
197
|
+
}
|
|
198
|
+
let value = '';
|
|
199
|
+
for (let index = 1; index < rawValue.length - 1; index++) {
|
|
200
|
+
const character = rawValue[index];
|
|
201
|
+
if (character === '\\' && index + 1 < rawValue.length - 1) {
|
|
202
|
+
value += rawValue[++index];
|
|
203
|
+
} else {
|
|
204
|
+
value += character;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return value;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function encodeParameterValue(value: string): string {
|
|
211
|
+
if (value && !/\s/.test(value) && !/["']/.test(value)) {
|
|
212
|
+
return value;
|
|
213
|
+
}
|
|
214
|
+
return `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function getSourceLocation(source: string, offset: number): {line: number; column: number} {
|
|
218
|
+
let line = 1;
|
|
219
|
+
let column = 1;
|
|
220
|
+
for (let index = 0; index < offset && index < source.length; index++) {
|
|
221
|
+
if (source[index] === '\n') {
|
|
222
|
+
line++;
|
|
223
|
+
column = 1;
|
|
224
|
+
} else {
|
|
225
|
+
column++;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return {line, column};
|
|
229
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// math.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
/** Version of the vendored PROJJSON schema. */
|
|
6
|
+
export const PROJJSON_SCHEMA_VERSION = '0.7';
|
|
7
|
+
|
|
8
|
+
/** Canonical URL for the vendored PROJJSON schema. */
|
|
9
|
+
export const PROJJSON_SCHEMA_URL = 'https://proj.org/schemas/v0.7/projjson.schema.json';
|