worldorbit 2.5.13 → 2.5.15
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/unpkg/worldorbit-core.min.js +12 -5
- 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 +2 -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/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/packages/editor/dist/editor.d.ts +0 -2
- package/packages/editor/dist/editor.js +0 -2998
- package/packages/editor/dist/index.d.ts +0 -2
- package/packages/editor/dist/index.js +0 -1
- package/packages/editor/dist/types.d.ts +0 -53
- package/packages/editor/dist/types.js +0 -1
- package/packages/markdown/dist/html.d.ts +0 -3
- package/packages/markdown/dist/html.js +0 -57
- package/packages/markdown/dist/index.d.ts +0 -4
- package/packages/markdown/dist/index.js +0 -3
- package/packages/markdown/dist/rehype.d.ts +0 -10
- package/packages/markdown/dist/rehype.js +0 -49
- package/packages/markdown/dist/remark.d.ts +0 -9
- package/packages/markdown/dist/remark.js +0 -28
- package/packages/markdown/dist/types.d.ts +0 -11
- package/packages/markdown/dist/types.js +0 -1
|
@@ -4,9 +4,12 @@ interface UpgradeOptions extends Pick<SceneRenderOptions, "preset" | "projection
|
|
|
4
4
|
export declare function upgradeDocumentToV2(document: WorldOrbitDocument, options?: UpgradeOptions): WorldOrbitAtlasDocument;
|
|
5
5
|
export declare function upgradeDocumentToDraftV2(document: WorldOrbitDocument, options?: UpgradeOptions): {
|
|
6
6
|
version: "2.0-draft";
|
|
7
|
+
schemaVersion: "2.0-draft";
|
|
7
8
|
format: "worldorbit";
|
|
8
9
|
sourceVersion: import("./types.js").WorldOrbitDocumentVersion;
|
|
9
10
|
system: WorldOrbitAtlasSystem | null;
|
|
11
|
+
groups: import("./types.js").WorldOrbitGroup[];
|
|
12
|
+
relations: import("./types.js").WorldOrbitRelation[];
|
|
10
13
|
objects: WorldOrbitObject[];
|
|
11
14
|
diagnostics: WorldOrbitDiagnostic[];
|
|
12
15
|
};
|
|
@@ -19,8 +19,11 @@ export function upgradeDocumentToV2(document, options = {}) {
|
|
|
19
19
|
return {
|
|
20
20
|
format: "worldorbit",
|
|
21
21
|
version: "2.0",
|
|
22
|
+
schemaVersion: "2.0",
|
|
22
23
|
sourceVersion: document.version,
|
|
23
24
|
system,
|
|
25
|
+
groups: structuredClone(document.groups ?? []),
|
|
26
|
+
relations: structuredClone(document.relations ?? []),
|
|
24
27
|
objects: document.objects.map(cloneWorldOrbitObject),
|
|
25
28
|
diagnostics,
|
|
26
29
|
};
|
|
@@ -33,6 +36,10 @@ export function materializeAtlasDocument(document) {
|
|
|
33
36
|
? {
|
|
34
37
|
type: "system",
|
|
35
38
|
id: document.system.id,
|
|
39
|
+
title: document.system.title,
|
|
40
|
+
description: document.system.description,
|
|
41
|
+
epoch: document.system.epoch,
|
|
42
|
+
referencePlane: document.system.referencePlane,
|
|
36
43
|
properties: materializeDraftSystemProperties(document.system),
|
|
37
44
|
info: materializeDraftSystemInfo(document.system),
|
|
38
45
|
}
|
|
@@ -40,7 +47,10 @@ export function materializeAtlasDocument(document) {
|
|
|
40
47
|
return {
|
|
41
48
|
format: "worldorbit",
|
|
42
49
|
version: "1.0",
|
|
50
|
+
schemaVersion: document.version,
|
|
43
51
|
system,
|
|
52
|
+
groups: structuredClone(document.groups ?? []),
|
|
53
|
+
relations: structuredClone(document.relations ?? []),
|
|
44
54
|
objects: document.objects.map(cloneWorldOrbitObject),
|
|
45
55
|
};
|
|
46
56
|
}
|
|
@@ -55,9 +65,12 @@ function createDraftSystem(document, defaults, atlasMetadata, annotations, diagn
|
|
|
55
65
|
return {
|
|
56
66
|
type: "system",
|
|
57
67
|
id: document.system?.id ?? "WorldOrbit",
|
|
58
|
-
title: typeof document.system?.properties.title === "string"
|
|
68
|
+
title: document.system?.title ?? (typeof document.system?.properties.title === "string"
|
|
59
69
|
? document.system.properties.title
|
|
60
|
-
: null,
|
|
70
|
+
: null),
|
|
71
|
+
description: document.system?.description ?? null,
|
|
72
|
+
epoch: document.system?.epoch ?? null,
|
|
73
|
+
referencePlane: document.system?.referencePlane ?? null,
|
|
61
74
|
defaults,
|
|
62
75
|
atlasMetadata,
|
|
63
76
|
viewpoints: scene.viewpoints.map(mapSceneViewpointToDraftViewpoint),
|
|
@@ -200,6 +213,27 @@ function mapSceneViewpointToDraftViewpoint(viewpoint) {
|
|
|
200
213
|
function cloneWorldOrbitObject(object) {
|
|
201
214
|
return {
|
|
202
215
|
...object,
|
|
216
|
+
groups: object.groups ? [...object.groups] : undefined,
|
|
217
|
+
resonance: object.resonance ? { ...object.resonance } : object.resonance,
|
|
218
|
+
renderHints: object.renderHints ? { ...object.renderHints } : object.renderHints,
|
|
219
|
+
deriveRules: object.deriveRules ? object.deriveRules.map((rule) => ({ ...rule })) : undefined,
|
|
220
|
+
validationRules: object.validationRules
|
|
221
|
+
? object.validationRules.map((rule) => ({ ...rule }))
|
|
222
|
+
: undefined,
|
|
223
|
+
lockedFields: object.lockedFields ? [...object.lockedFields] : undefined,
|
|
224
|
+
tolerances: object.tolerances
|
|
225
|
+
? object.tolerances.map((entry) => ({
|
|
226
|
+
field: entry.field,
|
|
227
|
+
value: entry.value && typeof entry.value === "object" && "value" in entry.value
|
|
228
|
+
? { value: entry.value.value, unit: entry.value.unit }
|
|
229
|
+
: Array.isArray(entry.value)
|
|
230
|
+
? [...entry.value]
|
|
231
|
+
: entry.value,
|
|
232
|
+
}))
|
|
233
|
+
: undefined,
|
|
234
|
+
typedBlocks: object.typedBlocks
|
|
235
|
+
? Object.fromEntries(Object.entries(object.typedBlocks).map(([key, block]) => [key, { ...(block ?? {}) }]))
|
|
236
|
+
: undefined,
|
|
203
237
|
properties: cloneProperties(object.properties),
|
|
204
238
|
placement: object.placement ? structuredClone(object.placement) : null,
|
|
205
239
|
info: { ...object.info },
|
|
@@ -255,6 +289,15 @@ function materializeDraftSystemProperties(system) {
|
|
|
255
289
|
if (system.defaults.units) {
|
|
256
290
|
properties.units = system.defaults.units;
|
|
257
291
|
}
|
|
292
|
+
if (system.description) {
|
|
293
|
+
properties.description = system.description;
|
|
294
|
+
}
|
|
295
|
+
if (system.epoch) {
|
|
296
|
+
properties.epoch = system.epoch;
|
|
297
|
+
}
|
|
298
|
+
if (system.referencePlane) {
|
|
299
|
+
properties.referencePlane = system.referencePlane;
|
|
300
|
+
}
|
|
258
301
|
return properties;
|
|
259
302
|
}
|
|
260
303
|
function materializeDraftSystemInfo(system) {
|
|
@@ -328,7 +371,7 @@ function serializeViewpointLayers(layers) {
|
|
|
328
371
|
if (orbitFront !== undefined || orbitBack !== undefined) {
|
|
329
372
|
tokens.push(orbitFront !== false || orbitBack !== false ? "orbits" : "-orbits");
|
|
330
373
|
}
|
|
331
|
-
for (const key of ["background", "guides", "objects", "labels", "metadata"]) {
|
|
374
|
+
for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
|
|
332
375
|
if (layers[key] !== undefined) {
|
|
333
376
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
334
377
|
}
|
|
@@ -339,5 +382,6 @@ function convertAtlasDocumentToLegacyDraft(document) {
|
|
|
339
382
|
return {
|
|
340
383
|
...document,
|
|
341
384
|
version: "2.0-draft",
|
|
385
|
+
schemaVersion: "2.0-draft",
|
|
342
386
|
};
|
|
343
387
|
}
|
|
@@ -37,29 +37,40 @@ const CANONICAL_FIELD_ORDER = [
|
|
|
37
37
|
export function formatDocument(document, options = {}) {
|
|
38
38
|
const schema = options.schema ?? "auto";
|
|
39
39
|
const useDraft = schema === "2.0" ||
|
|
40
|
+
schema === "2.1" ||
|
|
40
41
|
schema === "2.0-draft" ||
|
|
41
42
|
document.version === "2.0" ||
|
|
43
|
+
document.version === "2.1" ||
|
|
42
44
|
document.version === "2.0-draft";
|
|
43
45
|
if (useDraft) {
|
|
44
46
|
if (schema === "2.0-draft") {
|
|
45
47
|
const legacyDraftDocument = document.version === "2.0-draft"
|
|
46
48
|
? document
|
|
47
|
-
: document.version === "2.0"
|
|
49
|
+
: document.version === "2.0" || document.version === "2.1"
|
|
48
50
|
? {
|
|
49
51
|
...document,
|
|
50
52
|
version: "2.0-draft",
|
|
53
|
+
schemaVersion: "2.0-draft",
|
|
51
54
|
}
|
|
52
55
|
: upgradeDocumentToDraftV2(document);
|
|
53
56
|
return formatDraftDocument(legacyDraftDocument);
|
|
54
57
|
}
|
|
55
|
-
const atlasDocument = document.version === "2.0"
|
|
58
|
+
const atlasDocument = document.version === "2.0" || document.version === "2.1"
|
|
56
59
|
? document
|
|
57
60
|
: document.version === "2.0-draft"
|
|
58
61
|
? {
|
|
59
62
|
...document,
|
|
60
63
|
version: "2.0",
|
|
64
|
+
schemaVersion: "2.0",
|
|
61
65
|
}
|
|
62
66
|
: upgradeDocumentToV2(document);
|
|
67
|
+
if (schema === "2.1" && atlasDocument.version !== "2.1") {
|
|
68
|
+
return formatAtlasDocument({
|
|
69
|
+
...atlasDocument,
|
|
70
|
+
version: "2.1",
|
|
71
|
+
schemaVersion: "2.1",
|
|
72
|
+
});
|
|
73
|
+
}
|
|
63
74
|
return formatAtlasDocument(atlasDocument);
|
|
64
75
|
}
|
|
65
76
|
const lines = [];
|
|
@@ -77,10 +88,18 @@ export function formatDocument(document, options = {}) {
|
|
|
77
88
|
return lines.join("\n");
|
|
78
89
|
}
|
|
79
90
|
export function formatAtlasDocument(document) {
|
|
80
|
-
const lines = [
|
|
91
|
+
const lines = [`schema ${document.version}`, ""];
|
|
81
92
|
if (document.system) {
|
|
82
93
|
lines.push(...formatAtlasSystem(document.system));
|
|
83
94
|
}
|
|
95
|
+
for (const group of [...document.groups].sort(compareIdLike)) {
|
|
96
|
+
lines.push("");
|
|
97
|
+
lines.push(...formatAtlasGroup(group));
|
|
98
|
+
}
|
|
99
|
+
for (const relation of [...document.relations].sort(compareIdLike)) {
|
|
100
|
+
lines.push("");
|
|
101
|
+
lines.push(...formatAtlasRelation(relation));
|
|
102
|
+
}
|
|
84
103
|
const sortedObjects = [...document.objects].sort(compareObjects);
|
|
85
104
|
if (sortedObjects.length > 0 && lines.at(-1) !== "") {
|
|
86
105
|
lines.push("");
|
|
@@ -99,11 +118,20 @@ export function formatDraftDocument(document) {
|
|
|
99
118
|
: {
|
|
100
119
|
...document,
|
|
101
120
|
version: "2.0-draft",
|
|
121
|
+
schemaVersion: "2.0-draft",
|
|
102
122
|
};
|
|
103
123
|
const lines = ["schema 2.0-draft", ""];
|
|
104
124
|
if (legacy.system) {
|
|
105
125
|
lines.push(...formatAtlasSystem(legacy.system));
|
|
106
126
|
}
|
|
127
|
+
for (const group of [...legacy.groups].sort(compareIdLike)) {
|
|
128
|
+
lines.push("");
|
|
129
|
+
lines.push(...formatAtlasGroup(group));
|
|
130
|
+
}
|
|
131
|
+
for (const relation of [...legacy.relations].sort(compareIdLike)) {
|
|
132
|
+
lines.push("");
|
|
133
|
+
lines.push(...formatAtlasRelation(relation));
|
|
134
|
+
}
|
|
107
135
|
const sortedObjects = [...legacy.objects].sort(compareObjects);
|
|
108
136
|
if (sortedObjects.length > 0 && lines.at(-1) !== "") {
|
|
109
137
|
lines.push("");
|
|
@@ -119,11 +147,38 @@ export function formatDraftDocument(document) {
|
|
|
119
147
|
function formatSystem(system) {
|
|
120
148
|
return formatLines("system", system.id, system.properties, null, system.info);
|
|
121
149
|
}
|
|
150
|
+
function formatLines(objectType, id, properties, placement, info) {
|
|
151
|
+
const lines = [`${objectType} ${id}`];
|
|
152
|
+
const fieldLines = [...formatPlacement(placement), ...formatProperties(properties)];
|
|
153
|
+
for (const fieldLine of fieldLines) {
|
|
154
|
+
lines.push(` ${fieldLine}`);
|
|
155
|
+
}
|
|
156
|
+
const infoEntries = Object.entries(info).sort(([left], [right]) => left.localeCompare(right));
|
|
157
|
+
if (infoEntries.length > 0) {
|
|
158
|
+
if (fieldLines.length > 0) {
|
|
159
|
+
lines.push("");
|
|
160
|
+
}
|
|
161
|
+
lines.push(" info");
|
|
162
|
+
for (const [key, value] of infoEntries) {
|
|
163
|
+
lines.push(` ${key} ${quoteIfNeeded(value)}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return lines;
|
|
167
|
+
}
|
|
122
168
|
function formatAtlasSystem(system) {
|
|
123
169
|
const lines = [`system ${system.id}`];
|
|
124
170
|
if (system.title) {
|
|
125
171
|
lines.push(` title ${quoteIfNeeded(system.title)}`);
|
|
126
172
|
}
|
|
173
|
+
if (system.description) {
|
|
174
|
+
lines.push(` description ${quoteIfNeeded(system.description)}`);
|
|
175
|
+
}
|
|
176
|
+
if (system.epoch) {
|
|
177
|
+
lines.push(` epoch ${quoteIfNeeded(system.epoch)}`);
|
|
178
|
+
}
|
|
179
|
+
if (system.referencePlane) {
|
|
180
|
+
lines.push(` referencePlane ${quoteIfNeeded(system.referencePlane)}`);
|
|
181
|
+
}
|
|
127
182
|
lines.push("");
|
|
128
183
|
lines.push("defaults");
|
|
129
184
|
lines.push(` view ${system.defaults.view}`);
|
|
@@ -158,18 +213,22 @@ function formatAtlasSystem(system) {
|
|
|
158
213
|
return lines;
|
|
159
214
|
}
|
|
160
215
|
function formatObject(object) {
|
|
161
|
-
return
|
|
216
|
+
return formatWorldOrbitObject(object.type, object.id, object);
|
|
162
217
|
}
|
|
163
218
|
function formatAtlasObject(object) {
|
|
164
|
-
return
|
|
219
|
+
return formatWorldOrbitObject(`object ${object.type}`, object.id, object);
|
|
165
220
|
}
|
|
166
|
-
function
|
|
221
|
+
function formatWorldOrbitObject(objectType, id, object) {
|
|
167
222
|
const lines = [`${objectType} ${id}`];
|
|
168
|
-
const fieldLines = [
|
|
223
|
+
const fieldLines = [
|
|
224
|
+
...formatPlacement(object.placement),
|
|
225
|
+
...formatProperties(object.properties),
|
|
226
|
+
...formatObjectMetadata(object),
|
|
227
|
+
];
|
|
169
228
|
for (const fieldLine of fieldLines) {
|
|
170
229
|
lines.push(` ${fieldLine}`);
|
|
171
230
|
}
|
|
172
|
-
const infoEntries = Object.entries(info).sort(([left], [right]) => left.localeCompare(right));
|
|
231
|
+
const infoEntries = Object.entries(object.info).sort(([left], [right]) => left.localeCompare(right));
|
|
173
232
|
if (infoEntries.length > 0) {
|
|
174
233
|
if (fieldLines.length > 0) {
|
|
175
234
|
lines.push("");
|
|
@@ -179,6 +238,16 @@ function formatLines(objectType, id, properties, placement, info) {
|
|
|
179
238
|
lines.push(` ${key} ${quoteIfNeeded(value)}`);
|
|
180
239
|
}
|
|
181
240
|
}
|
|
241
|
+
for (const blockName of ["climate", "habitability", "settlement"]) {
|
|
242
|
+
const blockEntries = Object.entries(object.typedBlocks?.[blockName] ?? {}).sort(([left], [right]) => left.localeCompare(right));
|
|
243
|
+
if (blockEntries.length > 0) {
|
|
244
|
+
lines.push("");
|
|
245
|
+
lines.push(` ${blockName}`);
|
|
246
|
+
for (const [key, value] of blockEntries) {
|
|
247
|
+
lines.push(` ${key} ${quoteIfNeeded(value)}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
182
251
|
return lines;
|
|
183
252
|
}
|
|
184
253
|
function formatPlacement(placement) {
|
|
@@ -209,6 +278,46 @@ function formatProperties(properties) {
|
|
|
209
278
|
.sort(compareFieldKeys)
|
|
210
279
|
.map((key) => `${key} ${formatValue(properties[key])}`);
|
|
211
280
|
}
|
|
281
|
+
function formatObjectMetadata(object) {
|
|
282
|
+
const lines = [];
|
|
283
|
+
if (object.groups?.length) {
|
|
284
|
+
lines.push(`groups ${object.groups.join(" ")}`);
|
|
285
|
+
}
|
|
286
|
+
if (object.epoch) {
|
|
287
|
+
lines.push(`epoch ${quoteIfNeeded(object.epoch)}`);
|
|
288
|
+
}
|
|
289
|
+
if (object.referencePlane) {
|
|
290
|
+
lines.push(`referencePlane ${quoteIfNeeded(object.referencePlane)}`);
|
|
291
|
+
}
|
|
292
|
+
if (object.tidalLock !== undefined) {
|
|
293
|
+
lines.push(`tidalLock ${object.tidalLock ? "true" : "false"}`);
|
|
294
|
+
}
|
|
295
|
+
if (object.renderHints?.renderLabel !== undefined) {
|
|
296
|
+
lines.push(`renderLabel ${object.renderHints.renderLabel ? "true" : "false"}`);
|
|
297
|
+
}
|
|
298
|
+
if (object.renderHints?.renderOrbit !== undefined) {
|
|
299
|
+
lines.push(`renderOrbit ${object.renderHints.renderOrbit ? "true" : "false"}`);
|
|
300
|
+
}
|
|
301
|
+
if (object.renderHints?.renderPriority !== undefined) {
|
|
302
|
+
lines.push(`renderPriority ${object.renderHints.renderPriority}`);
|
|
303
|
+
}
|
|
304
|
+
if (object.resonance) {
|
|
305
|
+
lines.push(`resonance ${object.resonance.targetObjectId} ${object.resonance.ratio}`);
|
|
306
|
+
}
|
|
307
|
+
for (const rule of object.deriveRules ?? []) {
|
|
308
|
+
lines.push(`derive ${rule.field} ${rule.strategy}`);
|
|
309
|
+
}
|
|
310
|
+
for (const rule of object.validationRules ?? []) {
|
|
311
|
+
lines.push(`validate ${rule.rule}`);
|
|
312
|
+
}
|
|
313
|
+
if (object.lockedFields?.length) {
|
|
314
|
+
lines.push(`locked ${object.lockedFields.join(" ")}`);
|
|
315
|
+
}
|
|
316
|
+
for (const tolerance of object.tolerances ?? []) {
|
|
317
|
+
lines.push(`tolerance ${tolerance.field} ${formatValue(tolerance.value)}`);
|
|
318
|
+
}
|
|
319
|
+
return lines;
|
|
320
|
+
}
|
|
212
321
|
function formatAtlasViewpoint(viewpoint) {
|
|
213
322
|
const lines = [`viewpoint ${viewpoint.id}`, ` label ${quoteIfNeeded(viewpoint.label)}`];
|
|
214
323
|
if (viewpoint.focusObjectId) {
|
|
@@ -264,6 +373,50 @@ function formatAtlasAnnotation(annotation) {
|
|
|
264
373
|
}
|
|
265
374
|
return lines;
|
|
266
375
|
}
|
|
376
|
+
function formatAtlasGroup(group) {
|
|
377
|
+
const lines = [`group ${group.id}`, ` label ${quoteIfNeeded(group.label)}`];
|
|
378
|
+
if (group.summary) {
|
|
379
|
+
lines.push(` summary ${quoteIfNeeded(group.summary)}`);
|
|
380
|
+
}
|
|
381
|
+
if (group.color) {
|
|
382
|
+
lines.push(` color ${quoteIfNeeded(group.color)}`);
|
|
383
|
+
}
|
|
384
|
+
if (group.tags.length > 0) {
|
|
385
|
+
lines.push(` tags ${group.tags.map(quoteIfNeeded).join(" ")}`);
|
|
386
|
+
}
|
|
387
|
+
if (group.hidden) {
|
|
388
|
+
lines.push(" hidden true");
|
|
389
|
+
}
|
|
390
|
+
return lines;
|
|
391
|
+
}
|
|
392
|
+
function formatAtlasRelation(relation) {
|
|
393
|
+
const lines = [`relation ${relation.id}`];
|
|
394
|
+
if (relation.from) {
|
|
395
|
+
lines.push(` from ${quoteIfNeeded(relation.from)}`);
|
|
396
|
+
}
|
|
397
|
+
if (relation.to) {
|
|
398
|
+
lines.push(` to ${quoteIfNeeded(relation.to)}`);
|
|
399
|
+
}
|
|
400
|
+
if (relation.kind) {
|
|
401
|
+
lines.push(` kind ${quoteIfNeeded(relation.kind)}`);
|
|
402
|
+
}
|
|
403
|
+
if (relation.label) {
|
|
404
|
+
lines.push(` label ${quoteIfNeeded(relation.label)}`);
|
|
405
|
+
}
|
|
406
|
+
if (relation.summary) {
|
|
407
|
+
lines.push(` summary ${quoteIfNeeded(relation.summary)}`);
|
|
408
|
+
}
|
|
409
|
+
if (relation.tags.length > 0) {
|
|
410
|
+
lines.push(` tags ${relation.tags.map(quoteIfNeeded).join(" ")}`);
|
|
411
|
+
}
|
|
412
|
+
if (relation.color) {
|
|
413
|
+
lines.push(` color ${quoteIfNeeded(relation.color)}`);
|
|
414
|
+
}
|
|
415
|
+
if (relation.hidden) {
|
|
416
|
+
lines.push(" hidden true");
|
|
417
|
+
}
|
|
418
|
+
return lines;
|
|
419
|
+
}
|
|
267
420
|
function formatValue(value) {
|
|
268
421
|
if (Array.isArray(value)) {
|
|
269
422
|
return value.map((item) => quoteIfNeeded(item)).join(" ");
|
|
@@ -309,7 +462,7 @@ function formatDraftLayers(layers) {
|
|
|
309
462
|
? "orbits"
|
|
310
463
|
: "-orbits");
|
|
311
464
|
}
|
|
312
|
-
for (const key of ["background", "guides", "objects", "labels", "metadata"]) {
|
|
465
|
+
for (const key of ["background", "guides", "relations", "objects", "labels", "metadata"]) {
|
|
313
466
|
if (layers[key] !== undefined) {
|
|
314
467
|
tokens.push(layers[key] ? key : `-${key}`);
|
|
315
468
|
}
|
|
@@ -334,6 +487,9 @@ function compareObjects(left, right) {
|
|
|
334
487
|
return leftIndex - rightIndex;
|
|
335
488
|
return left.id.localeCompare(right.id);
|
|
336
489
|
}
|
|
490
|
+
function compareIdLike(left, right) {
|
|
491
|
+
return left.id.localeCompare(right.id);
|
|
492
|
+
}
|
|
337
493
|
function objectTypeIndex(objectType) {
|
|
338
494
|
switch (objectType) {
|
|
339
495
|
case "star":
|
|
@@ -5,10 +5,11 @@ import { WorldOrbitError } from "./errors.js";
|
|
|
5
5
|
import { normalizeDocument } from "./normalize.js";
|
|
6
6
|
import { parseWorldOrbit } from "./parse.js";
|
|
7
7
|
import { validateDocument } from "./validate.js";
|
|
8
|
-
const ATLAS_SCHEMA_PATTERN = /^schema\s+2(?:\.0)?$/i;
|
|
8
|
+
const ATLAS_SCHEMA_PATTERN = /^schema\s+2(?:\.0|\.1)?$/i;
|
|
9
|
+
const ATLAS_SCHEMA_21_PATTERN = /^schema\s+2\.1$/i;
|
|
9
10
|
const LEGACY_DRAFT_SCHEMA_PATTERN = /^schema\s+2\.0-draft$/i;
|
|
10
11
|
export function detectWorldOrbitSchemaVersion(source) {
|
|
11
|
-
for (const line of source.split(/\r?\n/)) {
|
|
12
|
+
for (const line of stripCommentsForSchemaDetection(source).split(/\r?\n/)) {
|
|
12
13
|
const trimmed = line.trim();
|
|
13
14
|
if (!trimmed) {
|
|
14
15
|
continue;
|
|
@@ -16,6 +17,9 @@ export function detectWorldOrbitSchemaVersion(source) {
|
|
|
16
17
|
if (LEGACY_DRAFT_SCHEMA_PATTERN.test(trimmed)) {
|
|
17
18
|
return "2.0-draft";
|
|
18
19
|
}
|
|
20
|
+
if (ATLAS_SCHEMA_21_PATTERN.test(trimmed)) {
|
|
21
|
+
return "2.1";
|
|
22
|
+
}
|
|
19
23
|
if (ATLAS_SCHEMA_PATTERN.test(trimmed)) {
|
|
20
24
|
return "2.0";
|
|
21
25
|
}
|
|
@@ -23,6 +27,49 @@ export function detectWorldOrbitSchemaVersion(source) {
|
|
|
23
27
|
}
|
|
24
28
|
return "1.0";
|
|
25
29
|
}
|
|
30
|
+
function stripCommentsForSchemaDetection(source) {
|
|
31
|
+
const chars = [...source];
|
|
32
|
+
let inString = false;
|
|
33
|
+
let inBlockComment = false;
|
|
34
|
+
for (let index = 0; index < chars.length; index++) {
|
|
35
|
+
const ch = chars[index];
|
|
36
|
+
const next = chars[index + 1];
|
|
37
|
+
if (inBlockComment) {
|
|
38
|
+
if (ch === "*" && next === "/") {
|
|
39
|
+
chars[index] = " ";
|
|
40
|
+
chars[index + 1] = " ";
|
|
41
|
+
inBlockComment = false;
|
|
42
|
+
index++;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (ch !== "\n" && ch !== "\r") {
|
|
46
|
+
chars[index] = " ";
|
|
47
|
+
}
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (!inString && ch === "/" && next === "*") {
|
|
51
|
+
chars[index] = " ";
|
|
52
|
+
chars[index + 1] = " ";
|
|
53
|
+
inBlockComment = true;
|
|
54
|
+
index++;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (!inString && ch === "#") {
|
|
58
|
+
chars[index] = " ";
|
|
59
|
+
let inner = index + 1;
|
|
60
|
+
while (inner < chars.length && chars[inner] !== "\n" && chars[inner] !== "\r") {
|
|
61
|
+
chars[inner] = " ";
|
|
62
|
+
inner++;
|
|
63
|
+
}
|
|
64
|
+
index = inner - 1;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (ch === '"' && chars[index - 1] !== "\\") {
|
|
68
|
+
inString = !inString;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return chars.join("");
|
|
72
|
+
}
|
|
26
73
|
export function loadWorldOrbitSource(source) {
|
|
27
74
|
const result = loadWorldOrbitSourceWithDiagnostics(source);
|
|
28
75
|
if (!result.ok || !result.value) {
|
|
@@ -33,7 +80,7 @@ export function loadWorldOrbitSource(source) {
|
|
|
33
80
|
}
|
|
34
81
|
export function loadWorldOrbitSourceWithDiagnostics(source) {
|
|
35
82
|
const schemaVersion = detectWorldOrbitSchemaVersion(source);
|
|
36
|
-
if (schemaVersion === "2.0" || schemaVersion === "2.0-draft") {
|
|
83
|
+
if (schemaVersion === "2.0" || schemaVersion === "2.0-draft" || schemaVersion === "2.1") {
|
|
37
84
|
return loadAtlasSourceWithDiagnostics(source, schemaVersion);
|
|
38
85
|
}
|
|
39
86
|
let ast;
|
|
@@ -93,25 +140,23 @@ function loadAtlasSourceWithDiagnostics(source, schemaVersion) {
|
|
|
93
140
|
diagnostics: [diagnosticFromError(error, "parse", "load.atlas.failed")],
|
|
94
141
|
};
|
|
95
142
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
document = materializeAtlasDocument(atlasDocument);
|
|
99
|
-
}
|
|
100
|
-
catch (error) {
|
|
143
|
+
const atlasDiagnostics = [...atlasDocument.diagnostics];
|
|
144
|
+
if (atlasDiagnostics.some((diagnostic) => diagnostic.severity === "error")) {
|
|
101
145
|
return {
|
|
102
146
|
ok: false,
|
|
103
147
|
value: null,
|
|
104
|
-
diagnostics:
|
|
148
|
+
diagnostics: atlasDiagnostics,
|
|
105
149
|
};
|
|
106
150
|
}
|
|
151
|
+
let document;
|
|
107
152
|
try {
|
|
108
|
-
|
|
153
|
+
document = materializeAtlasDocument(atlasDocument);
|
|
109
154
|
}
|
|
110
155
|
catch (error) {
|
|
111
156
|
return {
|
|
112
157
|
ok: false,
|
|
113
158
|
value: null,
|
|
114
|
-
diagnostics: [diagnosticFromError(error, "
|
|
159
|
+
diagnostics: [diagnosticFromError(error, "normalize", "load.atlas.materialize.failed")],
|
|
115
160
|
};
|
|
116
161
|
}
|
|
117
162
|
const loaded = {
|
|
@@ -120,11 +165,11 @@ function loadAtlasSourceWithDiagnostics(source, schemaVersion) {
|
|
|
120
165
|
document,
|
|
121
166
|
atlasDocument,
|
|
122
167
|
draftDocument: atlasDocument,
|
|
123
|
-
diagnostics:
|
|
168
|
+
diagnostics: atlasDiagnostics,
|
|
124
169
|
};
|
|
125
170
|
return {
|
|
126
171
|
ok: true,
|
|
127
172
|
value: loaded,
|
|
128
|
-
diagnostics:
|
|
173
|
+
diagnostics: atlasDiagnostics,
|
|
129
174
|
};
|
|
130
175
|
}
|
|
@@ -26,7 +26,10 @@ export function normalizeDocument(ast) {
|
|
|
26
26
|
return {
|
|
27
27
|
format: "worldorbit",
|
|
28
28
|
version: "1.0",
|
|
29
|
+
schemaVersion: "1.0",
|
|
29
30
|
system,
|
|
31
|
+
groups: [],
|
|
32
|
+
relations: [],
|
|
30
33
|
objects,
|
|
31
34
|
};
|
|
32
35
|
}
|
|
@@ -41,6 +44,10 @@ function normalizeObject(node) {
|
|
|
41
44
|
return {
|
|
42
45
|
type: "system",
|
|
43
46
|
id: node.name,
|
|
47
|
+
title: typeof properties.title === "string" ? properties.title : null,
|
|
48
|
+
description: null,
|
|
49
|
+
epoch: null,
|
|
50
|
+
referencePlane: null,
|
|
44
51
|
properties,
|
|
45
52
|
info,
|
|
46
53
|
};
|