worldorbit 2.5.13 → 2.5.16
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/README.md +37 -11
- package/dist/browser/core/dist/index.js +1811 -386
- package/dist/browser/editor/dist/index.js +10534 -0
- package/dist/browser/markdown/dist/index.js +1477 -221
- package/dist/browser/viewer/dist/index.js +1569 -230
- package/dist/unpkg/core/dist/index.js +1814 -389
- package/dist/unpkg/editor/dist/index.js +10559 -0
- package/dist/unpkg/markdown/dist/index.js +1480 -224
- package/dist/unpkg/viewer/dist/index.js +1572 -233
- package/dist/unpkg/worldorbit-core.min.js +12 -5
- package/dist/unpkg/worldorbit-editor.min.js +812 -0
- package/dist/unpkg/worldorbit-markdown.min.js +32 -23
- package/dist/unpkg/worldorbit-viewer.min.js +55 -41
- package/dist/unpkg/worldorbit.js +1713 -231
- package/dist/unpkg/worldorbit.min.js +58 -44
- package/package.json +3 -2
- package/packages/core/README.md +5 -1
- package/packages/core/dist/atlas-edit.d.ts +2 -2
- package/packages/core/dist/atlas-edit.js +70 -7
- package/packages/core/dist/atlas-utils.d.ts +22 -0
- package/packages/core/dist/atlas-utils.js +189 -0
- package/packages/core/dist/atlas-validate.d.ts +2 -0
- package/packages/core/dist/atlas-validate.js +285 -0
- package/packages/core/dist/draft-parse.js +786 -153
- package/packages/core/dist/draft.d.ts +3 -0
- package/packages/core/dist/draft.js +47 -3
- package/packages/core/dist/format.js +165 -9
- package/packages/core/dist/load.js +58 -13
- package/packages/core/dist/normalize.js +7 -0
- package/packages/core/dist/scene.js +66 -13
- package/packages/core/dist/types.d.ts +97 -3
- package/packages/editor/dist/editor.js +44 -0
- package/packages/markdown/README.md +1 -1
- package/packages/viewer/README.md +2 -1
- package/packages/viewer/dist/atlas-state.js +7 -1
- package/packages/viewer/dist/atlas-viewer.js +35 -1
- package/packages/viewer/dist/render.js +16 -7
- package/packages/viewer/dist/theme.js +4 -0
- package/packages/viewer/dist/tooltip.js +35 -0
- package/packages/viewer/dist/types.d.ts +7 -0
- package/packages/viewer/dist/viewer.js +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "worldorbit",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.16",
|
|
4
4
|
"description": "A text-based DSL and parser pipeline for orbital worldbuilding",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/unpkg/worldorbit.esm.js",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"license": "MIT",
|
|
53
53
|
"scripts": {
|
|
54
54
|
"build": "node ./scripts/build.mjs",
|
|
55
|
+
"prepack": "node ./scripts/prepack.mjs",
|
|
55
56
|
"test": "npm run build && node --test test/*.test.js",
|
|
56
57
|
"check": "npm run test"
|
|
57
58
|
},
|
|
@@ -64,4 +65,4 @@
|
|
|
64
65
|
"typescript": "^5.6.0",
|
|
65
66
|
"unified": "^11.0.5"
|
|
66
67
|
}
|
|
67
|
-
}
|
|
68
|
+
}
|
package/packages/core/README.md
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
# @worldorbit/core
|
|
2
2
|
|
|
3
|
-
WorldOrbit core contains the parser, schema, normalization, validation, formatting, and scene generation APIs.
|
|
3
|
+
WorldOrbit core contains the parser, schema, normalization, validation, formatting, and scene generation APIs for Schema 1.0, canonical Schema 2.0, and Schema 2.1 atlas source.
|
|
4
4
|
|
|
5
5
|
Main exports:
|
|
6
6
|
|
|
7
7
|
- `parse(source)`
|
|
8
|
+
- `parseWorldOrbitAtlas(source)`
|
|
9
|
+
- `parseWorldOrbitDraft(source)`
|
|
8
10
|
- `parseWorldOrbit(source)`
|
|
9
11
|
- `normalizeDocument(ast)`
|
|
10
12
|
- `validateDocument(document)`
|
|
13
|
+
- `validateAtlasDocumentWithDiagnostics(document)`
|
|
11
14
|
- `renderDocumentToScene(document, options?)`
|
|
12
15
|
- `formatDocument(document)`
|
|
16
|
+
- `loadWorldOrbitSource(source)`
|
|
13
17
|
- `extractWorldOrbitBlocks(markdown)`
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AtlasDocumentPath, AtlasResolvedDiagnostic, WorldOrbitAtlasDocument, WorldOrbitDiagnostic } from "./types.js";
|
|
2
|
-
export declare function createEmptyAtlasDocument(systemId?: string): WorldOrbitAtlasDocument;
|
|
1
|
+
import type { AtlasDocumentPath, AtlasResolvedDiagnostic, WorldOrbitAtlasDocument, WorldOrbitAtlasDocumentVersion, WorldOrbitDiagnostic } from "./types.js";
|
|
2
|
+
export declare function createEmptyAtlasDocument(systemId?: string, version?: WorldOrbitAtlasDocumentVersion): WorldOrbitAtlasDocument;
|
|
3
3
|
export declare function cloneAtlasDocument(document: WorldOrbitAtlasDocument): WorldOrbitAtlasDocument;
|
|
4
4
|
export declare function listAtlasDocumentPaths(document: WorldOrbitAtlasDocument): AtlasDocumentPath[];
|
|
5
5
|
export declare function getAtlasDocumentNode(document: WorldOrbitAtlasDocument, path: AtlasDocumentPath): unknown;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export function createEmptyAtlasDocument(systemId = "WorldOrbit") {
|
|
1
|
+
import { collectAtlasDiagnostics } from "./atlas-validate.js";
|
|
2
|
+
export function createEmptyAtlasDocument(systemId = "WorldOrbit", version = "2.0") {
|
|
4
3
|
return {
|
|
5
4
|
format: "worldorbit",
|
|
6
|
-
version
|
|
5
|
+
version,
|
|
6
|
+
schemaVersion: version,
|
|
7
7
|
sourceVersion: "1.0",
|
|
8
8
|
system: {
|
|
9
9
|
type: "system",
|
|
10
10
|
id: systemId,
|
|
11
11
|
title: systemId,
|
|
12
|
+
description: null,
|
|
13
|
+
epoch: null,
|
|
14
|
+
referencePlane: null,
|
|
12
15
|
defaults: {
|
|
13
16
|
view: "topdown",
|
|
14
17
|
scale: null,
|
|
@@ -20,6 +23,8 @@ export function createEmptyAtlasDocument(systemId = "WorldOrbit") {
|
|
|
20
23
|
viewpoints: [],
|
|
21
24
|
annotations: [],
|
|
22
25
|
},
|
|
26
|
+
groups: [],
|
|
27
|
+
relations: [],
|
|
23
28
|
objects: [],
|
|
24
29
|
diagnostics: [],
|
|
25
30
|
};
|
|
@@ -40,6 +45,12 @@ export function listAtlasDocumentPaths(document) {
|
|
|
40
45
|
paths.push({ kind: "annotation", id: annotation.id });
|
|
41
46
|
}
|
|
42
47
|
}
|
|
48
|
+
for (const group of [...document.groups].sort(compareIdLike)) {
|
|
49
|
+
paths.push({ kind: "group", id: group.id });
|
|
50
|
+
}
|
|
51
|
+
for (const relation of [...document.relations].sort(compareIdLike)) {
|
|
52
|
+
paths.push({ kind: "relation", id: relation.id });
|
|
53
|
+
}
|
|
43
54
|
for (const object of [...document.objects].sort(compareIdLike)) {
|
|
44
55
|
paths.push({ kind: "object", id: object.id });
|
|
45
56
|
}
|
|
@@ -53,12 +64,16 @@ export function getAtlasDocumentNode(document, path) {
|
|
|
53
64
|
return document.system?.defaults ?? null;
|
|
54
65
|
case "metadata":
|
|
55
66
|
return path.key ? (document.system?.atlasMetadata[path.key] ?? null) : null;
|
|
67
|
+
case "group":
|
|
68
|
+
return path.id ? findGroup(document, path.id) : null;
|
|
56
69
|
case "object":
|
|
57
70
|
return path.id ? findObject(document, path.id) : null;
|
|
58
71
|
case "viewpoint":
|
|
59
72
|
return path.id ? findViewpoint(document.system, path.id) : null;
|
|
60
73
|
case "annotation":
|
|
61
74
|
return path.id ? findAnnotation(document.system, path.id) : null;
|
|
75
|
+
case "relation":
|
|
76
|
+
return path.id ? findRelation(document, path.id) : null;
|
|
62
77
|
}
|
|
63
78
|
}
|
|
64
79
|
export function upsertAtlasDocumentNode(document, path, value) {
|
|
@@ -85,6 +100,12 @@ export function upsertAtlasDocumentNode(document, path, value) {
|
|
|
85
100
|
system.atlasMetadata[path.key] = String(value);
|
|
86
101
|
}
|
|
87
102
|
return next;
|
|
103
|
+
case "group":
|
|
104
|
+
if (!path.id) {
|
|
105
|
+
throw new Error('Group updates require an "id" value.');
|
|
106
|
+
}
|
|
107
|
+
upsertById(next.groups, value);
|
|
108
|
+
return next;
|
|
88
109
|
case "object":
|
|
89
110
|
if (!path.id) {
|
|
90
111
|
throw new Error('Object updates require an "id" value.');
|
|
@@ -103,6 +124,12 @@ export function upsertAtlasDocumentNode(document, path, value) {
|
|
|
103
124
|
}
|
|
104
125
|
upsertById(system.annotations, value);
|
|
105
126
|
return next;
|
|
127
|
+
case "relation":
|
|
128
|
+
if (!path.id) {
|
|
129
|
+
throw new Error('Relation updates require an "id" value.');
|
|
130
|
+
}
|
|
131
|
+
upsertById(next.relations, value);
|
|
132
|
+
return next;
|
|
106
133
|
}
|
|
107
134
|
}
|
|
108
135
|
export function updateAtlasDocumentNode(document, path, updater) {
|
|
@@ -122,6 +149,11 @@ export function removeAtlasDocumentNode(document, path) {
|
|
|
122
149
|
next.objects = next.objects.filter((object) => object.id !== path.id);
|
|
123
150
|
}
|
|
124
151
|
return next;
|
|
152
|
+
case "group":
|
|
153
|
+
if (path.id) {
|
|
154
|
+
next.groups = next.groups.filter((group) => group.id !== path.id);
|
|
155
|
+
}
|
|
156
|
+
return next;
|
|
125
157
|
case "viewpoint":
|
|
126
158
|
if (path.id) {
|
|
127
159
|
system.viewpoints = system.viewpoints.filter((viewpoint) => viewpoint.id !== path.id);
|
|
@@ -132,6 +164,11 @@ export function removeAtlasDocumentNode(document, path) {
|
|
|
132
164
|
system.annotations = system.annotations.filter((annotation) => annotation.id !== path.id);
|
|
133
165
|
}
|
|
134
166
|
return next;
|
|
167
|
+
case "relation":
|
|
168
|
+
if (path.id) {
|
|
169
|
+
next.relations = next.relations.filter((relation) => relation.id !== path.id);
|
|
170
|
+
}
|
|
171
|
+
return next;
|
|
135
172
|
default:
|
|
136
173
|
return next;
|
|
137
174
|
}
|
|
@@ -149,6 +186,15 @@ export function resolveAtlasDiagnosticPath(document, diagnostic) {
|
|
|
149
186
|
id: diagnostic.objectId,
|
|
150
187
|
};
|
|
151
188
|
}
|
|
189
|
+
if (diagnostic.field?.startsWith("group.")) {
|
|
190
|
+
const parts = diagnostic.field.split(".");
|
|
191
|
+
if (parts[1] && findGroup(document, parts[1])) {
|
|
192
|
+
return {
|
|
193
|
+
kind: "group",
|
|
194
|
+
id: parts[1],
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
}
|
|
152
198
|
if (diagnostic.field?.startsWith("viewpoint.")) {
|
|
153
199
|
const parts = diagnostic.field.split(".");
|
|
154
200
|
if (parts[1] && findViewpoint(document.system, parts[1])) {
|
|
@@ -167,6 +213,15 @@ export function resolveAtlasDiagnosticPath(document, diagnostic) {
|
|
|
167
213
|
};
|
|
168
214
|
}
|
|
169
215
|
}
|
|
216
|
+
if (diagnostic.field?.startsWith("relation.")) {
|
|
217
|
+
const parts = diagnostic.field.split(".");
|
|
218
|
+
if (parts[1] && findRelation(document, parts[1])) {
|
|
219
|
+
return {
|
|
220
|
+
kind: "relation",
|
|
221
|
+
id: parts[1],
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
170
225
|
if (diagnostic.field && diagnostic.field in ensureSystem(document).atlasMetadata) {
|
|
171
226
|
return {
|
|
172
227
|
kind: "metadata",
|
|
@@ -176,9 +231,11 @@ export function resolveAtlasDiagnosticPath(document, diagnostic) {
|
|
|
176
231
|
return null;
|
|
177
232
|
}
|
|
178
233
|
export function validateAtlasDocumentWithDiagnostics(document) {
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
234
|
+
const diagnostics = [
|
|
235
|
+
...document.diagnostics,
|
|
236
|
+
...collectAtlasDiagnostics(document, document.version),
|
|
237
|
+
];
|
|
238
|
+
return resolveAtlasDiagnostics(document, diagnostics);
|
|
182
239
|
}
|
|
183
240
|
function ensureSystem(document) {
|
|
184
241
|
if (document.system) {
|
|
@@ -190,6 +247,12 @@ function ensureSystem(document) {
|
|
|
190
247
|
function findObject(document, objectId) {
|
|
191
248
|
return document.objects.find((object) => object.id === objectId) ?? null;
|
|
192
249
|
}
|
|
250
|
+
function findGroup(document, groupId) {
|
|
251
|
+
return document.groups.find((group) => group.id === groupId) ?? null;
|
|
252
|
+
}
|
|
253
|
+
function findRelation(document, relationId) {
|
|
254
|
+
return document.relations.find((relation) => relation.id === relationId) ?? null;
|
|
255
|
+
}
|
|
193
256
|
function findViewpoint(system, viewpointId) {
|
|
194
257
|
return system?.viewpoints.find((viewpoint) => viewpoint.id === viewpointId) ?? null;
|
|
195
258
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AstFieldNode, AstSourceLocation, AtReference, NormalizedValue, UnitValue, WorldOrbitObjectType } from "./types.js";
|
|
2
|
+
export interface AtlasFieldLike {
|
|
3
|
+
key: string;
|
|
4
|
+
values: string[];
|
|
5
|
+
location: AstSourceLocation;
|
|
6
|
+
}
|
|
7
|
+
export declare function normalizeIdentifier(value: string): string;
|
|
8
|
+
export declare function humanizeIdentifier(value: string): string;
|
|
9
|
+
export declare function parseAtlasUnitValue(input: string, location?: AstSourceLocation, fieldKey?: string): UnitValue;
|
|
10
|
+
export declare function tryParseAtlasUnitValue(input: string): UnitValue | null;
|
|
11
|
+
export declare function parseAtlasNumber(input: string, key: string, location?: AstSourceLocation): number;
|
|
12
|
+
export declare function parseAtlasBoolean(input: string, key: string, location?: AstSourceLocation): boolean;
|
|
13
|
+
export declare function parseAtlasFieldBoolean(field: AtlasFieldLike): boolean;
|
|
14
|
+
export declare function parseAtlasAtReference(target: string, location?: AstSourceLocation): AtReference;
|
|
15
|
+
export declare function validateAtlasImageSource(value: string, location?: AstSourceLocation): void;
|
|
16
|
+
export declare function normalizeLegacyScalarValue(key: string, values: string[], location: AstSourceLocation): NormalizedValue;
|
|
17
|
+
export declare function ensureAtlasFieldSupported(key: string, objectType: WorldOrbitObjectType, location: AstSourceLocation): void;
|
|
18
|
+
export declare function singleAtlasFieldValue(field: Pick<AtlasFieldLike, "key" | "values" | "location">): string;
|
|
19
|
+
export declare function singleAtlasValue(values: string[], key: string, location?: AstSourceLocation): string;
|
|
20
|
+
export declare function isStructureLikeObjectType(objectType: WorldOrbitObjectType): boolean;
|
|
21
|
+
export declare function cloneNormalizedValue(value: NormalizedValue): NormalizedValue;
|
|
22
|
+
export declare function cloneFieldNode(field: AstFieldNode): AstFieldNode;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { WorldOrbitError } from "./errors.js";
|
|
2
|
+
import { getFieldSchema, unitFamilyAllowsUnit } from "./schema.js";
|
|
3
|
+
const UNIT_PATTERN = /^(-?\d+(?:\.\d+)?)(kpc|min|mj|rj|ky|my|gy|au|km|me|re|pc|ly|deg|sol|K|m|s|h|d|y)?$/;
|
|
4
|
+
const BOOLEAN_VALUES = new Map([
|
|
5
|
+
["true", true],
|
|
6
|
+
["false", false],
|
|
7
|
+
["yes", true],
|
|
8
|
+
["no", false],
|
|
9
|
+
]);
|
|
10
|
+
const URL_SCHEME_PATTERN = /^[A-Za-z][A-Za-z0-9+.-]*:/;
|
|
11
|
+
export function normalizeIdentifier(value) {
|
|
12
|
+
return value
|
|
13
|
+
.trim()
|
|
14
|
+
.toLowerCase()
|
|
15
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
16
|
+
.replace(/^-+|-+$/g, "");
|
|
17
|
+
}
|
|
18
|
+
export function humanizeIdentifier(value) {
|
|
19
|
+
return value
|
|
20
|
+
.split(/[-_]+/)
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
.map((segment) => segment[0].toUpperCase() + segment.slice(1))
|
|
23
|
+
.join(" ");
|
|
24
|
+
}
|
|
25
|
+
export function parseAtlasUnitValue(input, location, fieldKey) {
|
|
26
|
+
const match = input.match(UNIT_PATTERN);
|
|
27
|
+
if (!match) {
|
|
28
|
+
throw WorldOrbitError.fromLocation(`Invalid unit value "${input}"`, location);
|
|
29
|
+
}
|
|
30
|
+
const unitValue = {
|
|
31
|
+
value: Number(match[1]),
|
|
32
|
+
unit: match[2] ?? null,
|
|
33
|
+
};
|
|
34
|
+
if (fieldKey) {
|
|
35
|
+
const schema = getFieldSchema(fieldKey);
|
|
36
|
+
if (schema?.unitFamily && !unitFamilyAllowsUnit(schema.unitFamily, unitValue.unit)) {
|
|
37
|
+
throw WorldOrbitError.fromLocation(`Unit "${unitValue.unit ?? "none"}" is not valid for "${fieldKey}"`, location);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return unitValue;
|
|
41
|
+
}
|
|
42
|
+
export function tryParseAtlasUnitValue(input) {
|
|
43
|
+
const match = input.match(UNIT_PATTERN);
|
|
44
|
+
if (!match) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
value: Number(match[1]),
|
|
49
|
+
unit: match[2] ?? null,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export function parseAtlasNumber(input, key, location) {
|
|
53
|
+
const value = Number(input);
|
|
54
|
+
if (!Number.isFinite(value)) {
|
|
55
|
+
throw WorldOrbitError.fromLocation(`Invalid numeric value "${input}" for "${key}"`, location);
|
|
56
|
+
}
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
export function parseAtlasBoolean(input, key, location) {
|
|
60
|
+
const parsed = BOOLEAN_VALUES.get(input.toLowerCase());
|
|
61
|
+
if (parsed === undefined) {
|
|
62
|
+
throw WorldOrbitError.fromLocation(`Invalid boolean value "${input}" for "${key}"`, location);
|
|
63
|
+
}
|
|
64
|
+
return parsed;
|
|
65
|
+
}
|
|
66
|
+
export function parseAtlasFieldBoolean(field) {
|
|
67
|
+
return parseAtlasBoolean(singleAtlasFieldValue(field), field.key, field.location);
|
|
68
|
+
}
|
|
69
|
+
export function parseAtlasAtReference(target, location) {
|
|
70
|
+
if (/^[A-Za-z0-9._-]+-[A-Za-z0-9._-]+:L\d+$/i.test(target)) {
|
|
71
|
+
throw WorldOrbitError.fromLocation(`Invalid special position "${target}"`, location);
|
|
72
|
+
}
|
|
73
|
+
const pairedMatch = target.match(/^([A-Za-z0-9._-]+)-([A-Za-z0-9._-]+):(L[1-5])$/);
|
|
74
|
+
if (pairedMatch) {
|
|
75
|
+
return {
|
|
76
|
+
kind: "lagrange",
|
|
77
|
+
primary: pairedMatch[1],
|
|
78
|
+
secondary: pairedMatch[2],
|
|
79
|
+
point: pairedMatch[3],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const simpleMatch = target.match(/^([A-Za-z0-9._-]+):(L[1-5])$/);
|
|
83
|
+
if (simpleMatch) {
|
|
84
|
+
return {
|
|
85
|
+
kind: "lagrange",
|
|
86
|
+
primary: simpleMatch[1],
|
|
87
|
+
secondary: null,
|
|
88
|
+
point: simpleMatch[2],
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (/^[A-Za-z0-9._-]+:L\d+$/i.test(target)) {
|
|
92
|
+
throw WorldOrbitError.fromLocation(`Invalid special position "${target}"`, location);
|
|
93
|
+
}
|
|
94
|
+
const anchorMatch = target.match(/^([A-Za-z0-9._-]+):([A-Za-z0-9._-]+)$/);
|
|
95
|
+
if (anchorMatch) {
|
|
96
|
+
return {
|
|
97
|
+
kind: "anchor",
|
|
98
|
+
objectId: anchorMatch[1],
|
|
99
|
+
anchor: anchorMatch[2],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
kind: "named",
|
|
104
|
+
name: target,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
export function validateAtlasImageSource(value, location) {
|
|
108
|
+
if (!value) {
|
|
109
|
+
throw WorldOrbitError.fromLocation('Field "image" must not be empty', location);
|
|
110
|
+
}
|
|
111
|
+
if (value.startsWith("//")) {
|
|
112
|
+
throw WorldOrbitError.fromLocation('Field "image" must use a relative path, root-relative path, or an http/https URL', location);
|
|
113
|
+
}
|
|
114
|
+
const schemeMatch = value.match(URL_SCHEME_PATTERN);
|
|
115
|
+
if (!schemeMatch) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const scheme = schemeMatch[0].slice(0, -1).toLowerCase();
|
|
119
|
+
if (scheme !== "http" && scheme !== "https") {
|
|
120
|
+
throw WorldOrbitError.fromLocation(`Field "image" does not support the "${scheme}" scheme`, location);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export function normalizeLegacyScalarValue(key, values, location) {
|
|
124
|
+
const schema = getFieldSchema(key);
|
|
125
|
+
if (!schema) {
|
|
126
|
+
throw WorldOrbitError.fromLocation(`Unknown field "${key}"`, location);
|
|
127
|
+
}
|
|
128
|
+
if (schema.arity === "single" && values.length !== 1) {
|
|
129
|
+
throw WorldOrbitError.fromLocation(`Field "${key}" expects exactly one value`, location);
|
|
130
|
+
}
|
|
131
|
+
switch (schema.kind) {
|
|
132
|
+
case "list":
|
|
133
|
+
return values;
|
|
134
|
+
case "boolean":
|
|
135
|
+
return parseAtlasBoolean(singleAtlasValue(values, key, location), key, location);
|
|
136
|
+
case "number":
|
|
137
|
+
return parseAtlasNumber(singleAtlasValue(values, key, location), key, location);
|
|
138
|
+
case "unit":
|
|
139
|
+
return parseAtlasUnitValue(singleAtlasValue(values, key, location), location, key);
|
|
140
|
+
case "string": {
|
|
141
|
+
const value = values.join(" ").trim();
|
|
142
|
+
if (key === "image") {
|
|
143
|
+
validateAtlasImageSource(value, location);
|
|
144
|
+
}
|
|
145
|
+
return value;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
export function ensureAtlasFieldSupported(key, objectType, location) {
|
|
150
|
+
const schema = getFieldSchema(key);
|
|
151
|
+
if (!schema) {
|
|
152
|
+
throw WorldOrbitError.fromLocation(`Unknown field "${key}"`, location);
|
|
153
|
+
}
|
|
154
|
+
if (!schema.objectTypes.includes(objectType)) {
|
|
155
|
+
throw WorldOrbitError.fromLocation(`Field "${key}" is not valid on "${objectType}"`, location);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export function singleAtlasFieldValue(field) {
|
|
159
|
+
return singleAtlasValue(field.values, field.key, field.location);
|
|
160
|
+
}
|
|
161
|
+
export function singleAtlasValue(values, key, location) {
|
|
162
|
+
if (values.length !== 1) {
|
|
163
|
+
throw WorldOrbitError.fromLocation(`Field "${key}" expects exactly one value`, location);
|
|
164
|
+
}
|
|
165
|
+
return values[0];
|
|
166
|
+
}
|
|
167
|
+
export function isStructureLikeObjectType(objectType) {
|
|
168
|
+
return objectType === "structure" || objectType === "phenomenon";
|
|
169
|
+
}
|
|
170
|
+
export function cloneNormalizedValue(value) {
|
|
171
|
+
if (Array.isArray(value)) {
|
|
172
|
+
return [...value];
|
|
173
|
+
}
|
|
174
|
+
if (value && typeof value === "object" && "value" in value) {
|
|
175
|
+
return {
|
|
176
|
+
value: value.value,
|
|
177
|
+
unit: value.unit,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return value;
|
|
181
|
+
}
|
|
182
|
+
export function cloneFieldNode(field) {
|
|
183
|
+
return {
|
|
184
|
+
type: "field",
|
|
185
|
+
key: field.key,
|
|
186
|
+
values: [...field.values],
|
|
187
|
+
location: { ...field.location },
|
|
188
|
+
};
|
|
189
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import type { WorldOrbitAnyDocumentVersion, WorldOrbitAtlasDocument, WorldOrbitDiagnostic, WorldOrbitDraftDocument } from "./types.js";
|
|
2
|
+
export declare function collectAtlasDiagnostics(document: WorldOrbitAtlasDocument | WorldOrbitDraftDocument, sourceSchemaVersion?: WorldOrbitAnyDocumentVersion): WorldOrbitDiagnostic[];
|