worldorbit 3.2.0 → 3.2.2
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/dist/browser/core/dist/scene.js +98 -16
- package/dist/browser/core/dist/spatial-scene.js +1 -0
- package/dist/browser/core/dist/types.d.ts +3 -0
- package/dist/browser/editor/dist/editor.js +55 -12
- package/dist/browser/obsidian-plugin/dist/diagnostics.d.ts +3 -0
- package/dist/browser/obsidian-plugin/dist/diagnostics.js +23 -0
- package/dist/browser/obsidian-plugin/dist/examples.d.ts +3 -0
- package/dist/browser/obsidian-plugin/dist/examples.js +77 -0
- package/dist/browser/obsidian-plugin/dist/index.d.ts +9 -0
- package/dist/browser/obsidian-plugin/dist/index.js +8 -0
- package/dist/browser/obsidian-plugin/dist/main.d.ts +2 -0
- package/dist/browser/obsidian-plugin/dist/main.js +2 -0
- package/dist/browser/obsidian-plugin/dist/navigation.d.ts +6 -0
- package/dist/browser/obsidian-plugin/dist/navigation.js +44 -0
- package/dist/browser/obsidian-plugin/dist/plugin.d.ts +8 -0
- package/dist/browser/obsidian-plugin/dist/plugin.js +508 -0
- package/dist/browser/obsidian-plugin/dist/positions.d.ts +7 -0
- package/dist/browser/obsidian-plugin/dist/positions.js +14 -0
- package/dist/browser/obsidian-plugin/dist/settings.d.ts +2 -0
- package/dist/browser/obsidian-plugin/dist/settings.js +5 -0
- package/dist/browser/obsidian-plugin/dist/theme.d.ts +2 -0
- package/dist/browser/obsidian-plugin/dist/theme.js +31 -0
- package/dist/browser/obsidian-plugin/dist/types.d.ts +42 -0
- package/dist/browser/obsidian-plugin/dist/types.js +1 -0
- package/dist/browser/obsidian-plugin/dist/viewer-host.d.ts +14 -0
- package/dist/browser/obsidian-plugin/dist/viewer-host.js +110 -0
- package/dist/browser/viewer/dist/atlas-state.js +3 -0
- package/dist/browser/viewer/dist/index.d.ts +1 -0
- package/dist/browser/viewer/dist/index.js +1 -0
- package/dist/browser/viewer/dist/interactive-2d.d.ts +21 -0
- package/dist/browser/viewer/dist/interactive-2d.js +201 -0
- package/dist/browser/viewer/dist/render.d.ts +1 -1
- package/dist/browser/viewer/dist/render.js +2 -1
- package/dist/browser/viewer/dist/types.d.ts +1 -0
- package/dist/browser/viewer/dist/viewer-state.d.ts +1 -1
- package/dist/browser/viewer/dist/viewer-state.js +1 -1
- package/dist/browser/viewer/dist/viewer.js +2 -0
- package/dist/obsidian-plugin/LICENSE +21 -0
- package/dist/obsidian-plugin/README.md +124 -0
- package/dist/obsidian-plugin/main.js +108 -0
- package/dist/obsidian-plugin/manifest.json +9 -0
- package/dist/obsidian-plugin/obsidian_scsh_1.png +0 -0
- package/dist/obsidian-plugin/obsidian_scsh_2.png +0 -0
- package/dist/obsidian-plugin/styles.css +164 -0
- package/dist/unpkg/core/dist/scene.js +98 -16
- package/dist/unpkg/core/dist/spatial-scene.js +1 -0
- package/dist/unpkg/core/dist/types.d.ts +3 -0
- package/dist/unpkg/editor/dist/editor.js +55 -12
- package/dist/unpkg/obsidian-plugin/dist/diagnostics.d.ts +3 -0
- package/dist/unpkg/obsidian-plugin/dist/diagnostics.js +23 -0
- package/dist/unpkg/obsidian-plugin/dist/examples.d.ts +3 -0
- package/dist/unpkg/obsidian-plugin/dist/examples.js +77 -0
- package/dist/unpkg/obsidian-plugin/dist/index.d.ts +9 -0
- package/dist/unpkg/obsidian-plugin/dist/index.js +8 -0
- package/dist/unpkg/obsidian-plugin/dist/main.d.ts +2 -0
- package/dist/unpkg/obsidian-plugin/dist/main.js +2 -0
- package/dist/unpkg/obsidian-plugin/dist/navigation.d.ts +6 -0
- package/dist/unpkg/obsidian-plugin/dist/navigation.js +44 -0
- package/dist/unpkg/obsidian-plugin/dist/plugin.d.ts +8 -0
- package/dist/unpkg/obsidian-plugin/dist/plugin.js +508 -0
- package/dist/unpkg/obsidian-plugin/dist/positions.d.ts +7 -0
- package/dist/unpkg/obsidian-plugin/dist/positions.js +14 -0
- package/dist/unpkg/obsidian-plugin/dist/settings.d.ts +2 -0
- package/dist/unpkg/obsidian-plugin/dist/settings.js +5 -0
- package/dist/unpkg/obsidian-plugin/dist/theme.d.ts +2 -0
- package/dist/unpkg/obsidian-plugin/dist/theme.js +31 -0
- package/dist/unpkg/obsidian-plugin/dist/types.d.ts +42 -0
- package/dist/unpkg/obsidian-plugin/dist/types.js +1 -0
- package/dist/unpkg/obsidian-plugin/dist/viewer-host.d.ts +14 -0
- package/dist/unpkg/obsidian-plugin/dist/viewer-host.js +110 -0
- package/dist/unpkg/viewer/dist/atlas-state.js +3 -0
- package/dist/unpkg/viewer/dist/index.d.ts +1 -0
- package/dist/unpkg/viewer/dist/index.js +1 -0
- package/dist/unpkg/viewer/dist/interactive-2d.d.ts +21 -0
- package/dist/unpkg/viewer/dist/interactive-2d.js +201 -0
- package/dist/unpkg/viewer/dist/render.d.ts +1 -1
- package/dist/unpkg/viewer/dist/render.js +2 -1
- package/dist/unpkg/viewer/dist/types.d.ts +1 -0
- package/dist/unpkg/viewer/dist/viewer-state.d.ts +1 -1
- package/dist/unpkg/viewer/dist/viewer-state.js +1 -1
- package/dist/unpkg/viewer/dist/viewer.js +2 -0
- package/dist/unpkg/worldorbit-core.min.js +12 -12
- package/dist/unpkg/worldorbit-editor.min.js +342 -342
- package/dist/unpkg/worldorbit-markdown.min.js +23 -23
- package/dist/unpkg/worldorbit-viewer.min.js +197 -197
- package/dist/unpkg/worldorbit.js +297 -21
- package/dist/unpkg/worldorbit.min.js +201 -201
- package/package.json +18 -1
- package/packages/core/dist/scene.js +98 -16
- package/packages/core/dist/spatial-scene.js +1 -0
- package/packages/core/dist/types.d.ts +3 -0
- package/packages/editor/dist/editor.js +55 -12
- package/packages/viewer/dist/atlas-state.js +3 -0
- package/packages/viewer/dist/index.d.ts +1 -0
- package/packages/viewer/dist/index.js +1 -0
- package/packages/viewer/dist/interactive-2d.d.ts +21 -0
- package/packages/viewer/dist/interactive-2d.js +201 -0
- package/packages/viewer/dist/render.d.ts +1 -1
- package/packages/viewer/dist/render.js +2 -1
- package/packages/viewer/dist/types.d.ts +1 -0
- package/packages/viewer/dist/viewer-state.d.ts +1 -1
- package/packages/viewer/dist/viewer-state.js +1 -1
- package/packages/viewer/dist/viewer.js +2 -0
|
@@ -17,11 +17,12 @@ export function renderDocumentToScene(document, options = {}) {
|
|
|
17
17
|
const schemaProjection = resolveProjection(document, options.projection);
|
|
18
18
|
const camera = normalizeViewCamera(options.camera ?? null);
|
|
19
19
|
const renderProjection = resolveRenderProjection(schemaProjection, camera);
|
|
20
|
-
const scaleModel = resolveScaleModel(layoutPreset, options.scaleModel);
|
|
21
20
|
const spacingFactor = layoutPresetSpacing(layoutPreset);
|
|
21
|
+
const scaleModel = resolveScaleModel(layoutPreset, options.scaleModel, options.bodyScaleMode);
|
|
22
22
|
const systemId = document.system?.id ?? null;
|
|
23
23
|
const activeEventId = options.activeEventId ?? null;
|
|
24
24
|
const effectiveObjects = createEffectiveObjects(document.objects, document.events ?? [], activeEventId);
|
|
25
|
+
const sceneMetricScale = resolveSceneMetricScale(effectiveObjects, width, height, padding, spacingFactor, scaleModel);
|
|
25
26
|
const objectMap = new Map(effectiveObjects.map((object) => [object.id, object]));
|
|
26
27
|
const relationships = buildSceneRelationships(effectiveObjects, objectMap);
|
|
27
28
|
const positions = new Map();
|
|
@@ -61,6 +62,7 @@ export function renderDocumentToScene(document, options = {}) {
|
|
|
61
62
|
spacingFactor,
|
|
62
63
|
projection: renderProjection,
|
|
63
64
|
scaleModel,
|
|
65
|
+
sceneMetricScale,
|
|
64
66
|
};
|
|
65
67
|
const primaryRoot = rootObjects.find((object) => object.type === "star") ?? rootObjects[0] ?? null;
|
|
66
68
|
if (primaryRoot) {
|
|
@@ -82,14 +84,14 @@ export function renderDocumentToScene(document, options = {}) {
|
|
|
82
84
|
const x = width -
|
|
83
85
|
padding -
|
|
84
86
|
140 -
|
|
85
|
-
freePlacementOffsetPx(object.placement?.mode === "free" ? object.placement.distance : undefined, scaleModel);
|
|
87
|
+
freePlacementOffsetPx(object.placement?.mode === "free" ? object.placement.distance : undefined, scaleModel, sceneMetricScale);
|
|
86
88
|
const rowStep = Math.max(76, ((height - padding * 2 - 180) / Math.max(1, freeObjects.length)) * spacingFactor) * scaleModel.freePlacementMultiplier;
|
|
87
89
|
const y = padding + 92 + index * rowStep;
|
|
88
90
|
positions.set(object.id, {
|
|
89
91
|
object,
|
|
90
92
|
x,
|
|
91
93
|
y,
|
|
92
|
-
radius: visualRadiusFor(object, 0, scaleModel),
|
|
94
|
+
radius: visualRadiusFor(object, 0, scaleModel, sceneMetricScale),
|
|
93
95
|
sortKey: computeSortKey(x, y, 0),
|
|
94
96
|
});
|
|
95
97
|
leaderDrafts.push({
|
|
@@ -112,7 +114,7 @@ export function renderDocumentToScene(document, options = {}) {
|
|
|
112
114
|
object,
|
|
113
115
|
x: resolved.x,
|
|
114
116
|
y: resolved.y,
|
|
115
|
-
radius: visualRadiusFor(object, 2, scaleModel),
|
|
117
|
+
radius: visualRadiusFor(object, 2, scaleModel, sceneMetricScale),
|
|
116
118
|
sortKey: computeSortKey(resolved.x, resolved.y, 2),
|
|
117
119
|
anchorX: resolved.anchorX,
|
|
118
120
|
anchorY: resolved.anchorY,
|
|
@@ -164,6 +166,7 @@ export function renderDocumentToScene(document, options = {}) {
|
|
|
164
166
|
scale: String(document.system?.properties.scale ?? layoutPreset),
|
|
165
167
|
units: String(document.system?.properties.units ?? "mixed"),
|
|
166
168
|
preset: frame.preset ?? "custom",
|
|
169
|
+
"body.scaleMode": scaleModel.bodyScaleMode,
|
|
167
170
|
...(camera?.azimuth !== null ? { "camera.azimuth": String(camera?.azimuth) } : {}),
|
|
168
171
|
...(camera?.elevation !== null ? { "camera.elevation": String(camera?.elevation) } : {}),
|
|
169
172
|
...(camera?.roll !== null ? { "camera.roll": String(camera?.roll) } : {}),
|
|
@@ -344,10 +347,11 @@ function buildSceneSubtitle(projection, renderProjection, layoutPreset, camera)
|
|
|
344
347
|
}
|
|
345
348
|
return parts.join(" - ");
|
|
346
349
|
}
|
|
347
|
-
function resolveScaleModel(layoutPreset, overrides) {
|
|
350
|
+
function resolveScaleModel(layoutPreset, overrides, bodyScaleMode) {
|
|
348
351
|
const defaults = defaultScaleModel(layoutPreset);
|
|
349
352
|
return {
|
|
350
353
|
...defaults,
|
|
354
|
+
...(bodyScaleMode ? { bodyScaleMode } : {}),
|
|
351
355
|
...overrides,
|
|
352
356
|
};
|
|
353
357
|
}
|
|
@@ -362,6 +366,7 @@ function defaultScaleModel(layoutPreset) {
|
|
|
362
366
|
ringThicknessMultiplier: 0.92,
|
|
363
367
|
minBodyRadius: 4,
|
|
364
368
|
maxBodyRadius: 36,
|
|
369
|
+
bodyScaleMode: "readable",
|
|
365
370
|
};
|
|
366
371
|
case "presentation":
|
|
367
372
|
return {
|
|
@@ -372,6 +377,7 @@ function defaultScaleModel(layoutPreset) {
|
|
|
372
377
|
ringThicknessMultiplier: 1.16,
|
|
373
378
|
minBodyRadius: 5,
|
|
374
379
|
maxBodyRadius: 48,
|
|
380
|
+
bodyScaleMode: "readable",
|
|
375
381
|
};
|
|
376
382
|
default:
|
|
377
383
|
return {
|
|
@@ -382,6 +388,7 @@ function defaultScaleModel(layoutPreset) {
|
|
|
382
388
|
ringThicknessMultiplier: 1,
|
|
383
389
|
minBodyRadius: 4,
|
|
384
390
|
maxBodyRadius: 40,
|
|
391
|
+
bodyScaleMode: "readable",
|
|
385
392
|
};
|
|
386
393
|
}
|
|
387
394
|
}
|
|
@@ -395,6 +402,51 @@ function layoutPresetSpacing(layoutPreset) {
|
|
|
395
402
|
return 1;
|
|
396
403
|
}
|
|
397
404
|
}
|
|
405
|
+
function resolveSceneMetricScale(objects, width, height, padding, spacingFactor, scaleModel) {
|
|
406
|
+
const orbitMetrics = [];
|
|
407
|
+
const bodyMetrics = [];
|
|
408
|
+
for (const object of objects) {
|
|
409
|
+
const radiusMetric = objectRadiusMetric(object);
|
|
410
|
+
if (radiusMetric !== null && radiusMetric > 0) {
|
|
411
|
+
bodyMetrics.push(radiusMetric);
|
|
412
|
+
}
|
|
413
|
+
const placement = object.placement;
|
|
414
|
+
if (!placement) {
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
if (placement.mode === "orbit") {
|
|
418
|
+
const orbitMetricValue = toDistanceMetric(placement.semiMajor ?? placement.distance ?? null);
|
|
419
|
+
if (orbitMetricValue !== null && orbitMetricValue > 0) {
|
|
420
|
+
orbitMetrics.push(orbitMetricValue);
|
|
421
|
+
}
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
if (placement.mode === "free") {
|
|
425
|
+
const freeMetric = toDistanceMetric(placement.distance ?? null);
|
|
426
|
+
if (freeMetric !== null && freeMetric > 0) {
|
|
427
|
+
orbitMetrics.push(freeMetric);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
const maxDistanceMetric = Math.max(...orbitMetrics, 0);
|
|
432
|
+
const maxBodyMetric = Math.max(...bodyMetrics, 0);
|
|
433
|
+
const baseMetric = Math.max(maxDistanceMetric, maxBodyMetric * 6, 0);
|
|
434
|
+
const referenceMetric = baseMetric +
|
|
435
|
+
Math.max(Math.sqrt(baseMetric), maxBodyMetric * 2, maxDistanceMetric > 0 ? 0.25 : 0);
|
|
436
|
+
if (referenceMetric <= 0) {
|
|
437
|
+
return {
|
|
438
|
+
pixelsPerMetric: null,
|
|
439
|
+
hasExplicitScale: false,
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
const availableRadius = Math.max(Math.min(width, height) / 2 - padding - 24, 120) *
|
|
443
|
+
spacingFactor *
|
|
444
|
+
scaleModel.orbitDistanceMultiplier;
|
|
445
|
+
return {
|
|
446
|
+
pixelsPerMetric: availableRadius / referenceMetric,
|
|
447
|
+
hasExplicitScale: true,
|
|
448
|
+
};
|
|
449
|
+
}
|
|
398
450
|
function createSceneObject(position, scaleModel, relationships) {
|
|
399
451
|
const { object, x, y, radius, sortKey, anchorX, anchorY } = position;
|
|
400
452
|
const renderPriority = object.renderHints?.renderPriority ?? 0;
|
|
@@ -1198,7 +1250,7 @@ function placeObject(object, x, y, depth, positions, orbitDrafts, leaderDrafts,
|
|
|
1198
1250
|
object,
|
|
1199
1251
|
x,
|
|
1200
1252
|
y,
|
|
1201
|
-
radius: visualRadiusFor(object, depth, context.scaleModel),
|
|
1253
|
+
radius: visualRadiusFor(object, depth, context.scaleModel, context.sceneMetricScale),
|
|
1202
1254
|
sortKey: computeSortKey(x, y, depth),
|
|
1203
1255
|
});
|
|
1204
1256
|
placeOrbitingChildren(object, positions, orbitDrafts, leaderDrafts, context, depth + 1);
|
|
@@ -1209,7 +1261,7 @@ function placeOrbitingChildren(object, positions, orbitDrafts, leaderDrafts, con
|
|
|
1209
1261
|
return;
|
|
1210
1262
|
}
|
|
1211
1263
|
const orbiting = [...(context.orbitChildren.get(object.id) ?? [])].sort(compareOrbiting);
|
|
1212
|
-
const orbitMetricContext = computeOrbitMetricContext(orbiting, parent.radius, context.spacingFactor, context.scaleModel);
|
|
1264
|
+
const orbitMetricContext = computeOrbitMetricContext(orbiting, parent.radius, context.spacingFactor, context.scaleModel, context.sceneMetricScale);
|
|
1213
1265
|
const orbitRadiiPx = resolveOrbitRadiiPx(orbiting, orbitMetricContext);
|
|
1214
1266
|
orbiting.forEach((child, index) => {
|
|
1215
1267
|
const orbitGeometry = resolveOrbitGeometry(child, index, orbiting.length, parent, orbitMetricContext, orbitRadiiPx[index] ?? orbitMetricContext.innerPx, context);
|
|
@@ -1244,7 +1296,7 @@ function placeOrbitingChildren(object, positions, orbitDrafts, leaderDrafts, con
|
|
|
1244
1296
|
object: child,
|
|
1245
1297
|
x,
|
|
1246
1298
|
y,
|
|
1247
|
-
radius: visualRadiusFor(child, depth + 1, context.scaleModel),
|
|
1299
|
+
radius: visualRadiusFor(child, depth + 1, context.scaleModel, context.sceneMetricScale),
|
|
1248
1300
|
sortKey: computeSortKey(x, y, depth + 1),
|
|
1249
1301
|
anchorX,
|
|
1250
1302
|
anchorY,
|
|
@@ -1273,10 +1325,13 @@ function compareOrbiting(left, right) {
|
|
|
1273
1325
|
return 1;
|
|
1274
1326
|
return left.id.localeCompare(right.id);
|
|
1275
1327
|
}
|
|
1276
|
-
function computeOrbitMetricContext(objects, parentRadius, spacingFactor, scaleModel) {
|
|
1328
|
+
function computeOrbitMetricContext(objects, parentRadius, spacingFactor, scaleModel, sceneMetricScale) {
|
|
1277
1329
|
const metrics = objects.map((object) => orbitMetric(object));
|
|
1278
1330
|
const presentMetrics = metrics.filter((value) => value !== null);
|
|
1279
|
-
const
|
|
1331
|
+
const minimumGapPx = scaleModel.bodyScaleMode === "strict"
|
|
1332
|
+
? Math.max(2, 8 * spacingFactor * scaleModel.orbitDistanceMultiplier)
|
|
1333
|
+
: (objects.length > 2 ? 54 : 64) * spacingFactor * scaleModel.orbitDistanceMultiplier * 0.42;
|
|
1334
|
+
const innerPx = parentRadius + Math.max(minimumGapPx * 1.2, 24 * spacingFactor);
|
|
1280
1335
|
const stepPx = (objects.length > 2 ? 54 : 64) * spacingFactor * scaleModel.orbitDistanceMultiplier;
|
|
1281
1336
|
if (presentMetrics.length === 0) {
|
|
1282
1337
|
return {
|
|
@@ -1287,7 +1342,8 @@ function computeOrbitMetricContext(objects, parentRadius, spacingFactor, scaleMo
|
|
|
1287
1342
|
innerPx,
|
|
1288
1343
|
stepPx,
|
|
1289
1344
|
pixelSpread: Math.max(stepPx * Math.max(objects.length - 1, 1), stepPx),
|
|
1290
|
-
minimumGapPx
|
|
1345
|
+
minimumGapPx,
|
|
1346
|
+
pixelsPerMetric: sceneMetricScale.pixelsPerMetric,
|
|
1291
1347
|
};
|
|
1292
1348
|
}
|
|
1293
1349
|
const minMetric = Math.min(...presentMetrics);
|
|
@@ -1301,7 +1357,8 @@ function computeOrbitMetricContext(objects, parentRadius, spacingFactor, scaleMo
|
|
|
1301
1357
|
innerPx,
|
|
1302
1358
|
stepPx,
|
|
1303
1359
|
pixelSpread: Math.max(stepPx * Math.max(objects.length - 1, 1), stepPx),
|
|
1304
|
-
minimumGapPx
|
|
1360
|
+
minimumGapPx,
|
|
1361
|
+
pixelsPerMetric: sceneMetricScale.pixelsPerMetric,
|
|
1305
1362
|
};
|
|
1306
1363
|
}
|
|
1307
1364
|
function resolveOrbitGeometry(object, index, count, parent, metricContext, orbitRadiusPx, context) {
|
|
@@ -1366,6 +1423,9 @@ function resolveOrbitGeometry(object, index, count, parent, metricContext, orbit
|
|
|
1366
1423
|
};
|
|
1367
1424
|
}
|
|
1368
1425
|
function resolveOrbitRadiusPx(metric, metricContext) {
|
|
1426
|
+
if (metricContext.pixelsPerMetric !== null) {
|
|
1427
|
+
return metric * metricContext.pixelsPerMetric;
|
|
1428
|
+
}
|
|
1369
1429
|
return metricContext.innerPx + metricContext.stepPx * log2(Math.max(metric, 0) + 1);
|
|
1370
1430
|
}
|
|
1371
1431
|
function resolveOrbitRadiiPx(objects, metricContext) {
|
|
@@ -1404,6 +1464,12 @@ function resolveBandThickness(object, orbitRadius, metricContext, scaleModel) {
|
|
|
1404
1464
|
const outerMetric = toDistanceMetric(toUnitValue(object.properties.outer));
|
|
1405
1465
|
if (innerMetric !== null && outerMetric !== null) {
|
|
1406
1466
|
const thicknessMetric = Math.abs(outerMetric - innerMetric);
|
|
1467
|
+
if (metricContext.pixelsPerMetric !== null) {
|
|
1468
|
+
const thicknessPx = thicknessMetric * metricContext.pixelsPerMetric;
|
|
1469
|
+
return scaleModel.bodyScaleMode === "strict"
|
|
1470
|
+
? Math.max(thicknessPx * scaleModel.ringThicknessMultiplier, 1)
|
|
1471
|
+
: clampNumber(Math.max(thicknessPx * scaleModel.ringThicknessMultiplier, 8), 8, 54);
|
|
1472
|
+
}
|
|
1407
1473
|
if (metricContext.metricSpread > 0) {
|
|
1408
1474
|
return clampNumber((thicknessMetric / metricContext.metricSpread) *
|
|
1409
1475
|
metricContext.pixelSpread *
|
|
@@ -1698,8 +1764,8 @@ function deriveParentAnchor(objectId, positions, objectMap) {
|
|
|
1698
1764
|
}
|
|
1699
1765
|
return positions.get(object.placement.target);
|
|
1700
1766
|
}
|
|
1701
|
-
function visualRadiusFor(object, depth, scaleModel) {
|
|
1702
|
-
const explicitRadius = toVisualSizeMetric(object.properties.radius, scaleModel);
|
|
1767
|
+
function visualRadiusFor(object, depth, scaleModel, sceneMetricScale) {
|
|
1768
|
+
const explicitRadius = toVisualSizeMetric(object.properties.radius, scaleModel, sceneMetricScale);
|
|
1703
1769
|
if (explicitRadius !== null) {
|
|
1704
1770
|
return explicitRadius;
|
|
1705
1771
|
}
|
|
@@ -1766,18 +1832,31 @@ function toDistanceMetric(value) {
|
|
|
1766
1832
|
return value.value;
|
|
1767
1833
|
}
|
|
1768
1834
|
}
|
|
1769
|
-
function freePlacementOffsetPx(distance, scaleModel) {
|
|
1835
|
+
function freePlacementOffsetPx(distance, scaleModel, sceneMetricScale) {
|
|
1770
1836
|
const metric = toDistanceMetric(distance ?? null);
|
|
1771
1837
|
if (metric === null || metric <= 0) {
|
|
1772
1838
|
return 0;
|
|
1773
1839
|
}
|
|
1840
|
+
if (sceneMetricScale.pixelsPerMetric !== null) {
|
|
1841
|
+
const scaled = metric * sceneMetricScale.pixelsPerMetric * scaleModel.freePlacementMultiplier;
|
|
1842
|
+
return scaleModel.bodyScaleMode === "strict"
|
|
1843
|
+
? Math.max(scaled, 0)
|
|
1844
|
+
: clampNumber(scaled, 0, 420);
|
|
1845
|
+
}
|
|
1774
1846
|
return clampNumber(metric * 96 * scaleModel.freePlacementMultiplier, 0, 420);
|
|
1775
1847
|
}
|
|
1776
|
-
function toVisualSizeMetric(value, scaleModel) {
|
|
1848
|
+
function toVisualSizeMetric(value, scaleModel, sceneMetricScale) {
|
|
1777
1849
|
const unitValue = toUnitValue(value);
|
|
1778
1850
|
if (!unitValue) {
|
|
1779
1851
|
return null;
|
|
1780
1852
|
}
|
|
1853
|
+
const physicalMetric = toDistanceMetric(unitValue);
|
|
1854
|
+
if (sceneMetricScale.pixelsPerMetric !== null && physicalMetric !== null && physicalMetric > 0) {
|
|
1855
|
+
const scaled = physicalMetric * sceneMetricScale.pixelsPerMetric * scaleModel.bodyRadiusMultiplier;
|
|
1856
|
+
return scaleModel.bodyScaleMode === "strict"
|
|
1857
|
+
? Math.max(scaled, 0.1)
|
|
1858
|
+
: clampNumber(Math.max(scaled, scaleModel.minBodyRadius), scaleModel.minBodyRadius, scaleModel.maxBodyRadius);
|
|
1859
|
+
}
|
|
1781
1860
|
let size;
|
|
1782
1861
|
switch (unitValue.unit) {
|
|
1783
1862
|
case "sol":
|
|
@@ -1795,6 +1874,9 @@ function toVisualSizeMetric(value, scaleModel) {
|
|
|
1795
1874
|
}
|
|
1796
1875
|
return clampNumber(size * scaleModel.bodyRadiusMultiplier, scaleModel.minBodyRadius, scaleModel.maxBodyRadius);
|
|
1797
1876
|
}
|
|
1877
|
+
function objectRadiusMetric(object) {
|
|
1878
|
+
return toDistanceMetric(toUnitValue(object.properties.radius));
|
|
1879
|
+
}
|
|
1798
1880
|
function toUnitValue(value) {
|
|
1799
1881
|
if (!value || typeof value !== "object" || !("value" in value)) {
|
|
1800
1882
|
return null;
|
|
@@ -12,6 +12,7 @@ export function renderDocumentToSpatialScene(document, options = {}) {
|
|
|
12
12
|
projection: options.projection,
|
|
13
13
|
camera: options.camera,
|
|
14
14
|
scaleModel: options.scaleModel,
|
|
15
|
+
bodyScaleMode: options.bodyScaleMode,
|
|
15
16
|
activeEventId: options.activeEventId,
|
|
16
17
|
};
|
|
17
18
|
const scene = renderDocumentToScene(document, renderOptions);
|
|
@@ -8,6 +8,7 @@ export type WorldOrbitAnyDocumentVersion = WorldOrbitDocumentVersion | WorldOrbi
|
|
|
8
8
|
export type ViewProjection = "topdown" | "isometric" | "orthographic" | "perspective";
|
|
9
9
|
export type RenderProjectionFallback = "topdown" | "isometric";
|
|
10
10
|
export type RenderPresetName = "diagram" | "presentation" | "atlas-card" | "markdown";
|
|
11
|
+
export type BodyScaleMode = "readable" | "strict";
|
|
11
12
|
export interface CoordinatePoint {
|
|
12
13
|
x: number;
|
|
13
14
|
y: number;
|
|
@@ -263,6 +264,7 @@ export interface RenderScaleModel {
|
|
|
263
264
|
ringThicknessMultiplier: number;
|
|
264
265
|
minBodyRadius: number;
|
|
265
266
|
maxBodyRadius: number;
|
|
267
|
+
bodyScaleMode: BodyScaleMode;
|
|
266
268
|
}
|
|
267
269
|
export interface SceneRenderOptions {
|
|
268
270
|
width?: number;
|
|
@@ -272,6 +274,7 @@ export interface SceneRenderOptions {
|
|
|
272
274
|
projection?: "document" | ViewProjection;
|
|
273
275
|
camera?: WorldOrbitViewCamera | null;
|
|
274
276
|
scaleModel?: Partial<RenderScaleModel>;
|
|
277
|
+
bodyScaleMode?: BodyScaleMode;
|
|
275
278
|
activeEventId?: string | null;
|
|
276
279
|
}
|
|
277
280
|
export interface SpatialScaleModel {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { cloneAtlasDocument, createEmptyAtlasDocument, formatDocument, getAtlasDocumentNode, loadWorldOrbitSourceWithDiagnostics, materializeAtlasDocument, removeAtlasDocumentNode, resolveAtlasDiagnostics, rotatePoint, upgradeDocumentToV2, validateAtlasDocumentWithDiagnostics, } from "@worldorbit/core";
|
|
1
|
+
import { cloneAtlasDocument, createEmptyAtlasDocument, formatDocument, getAtlasDocumentNode, loadWorldOrbitSourceWithDiagnostics, materializeAtlasDocument, removeAtlasDocumentNode, renderDocumentToScene, resolveAtlasDiagnostics, rotatePoint, upgradeDocumentToV2, validateAtlasDocumentWithDiagnostics, } from "@worldorbit/core";
|
|
2
2
|
import { renderWorldOrbitBlock } from "@worldorbit/markdown";
|
|
3
3
|
import { createInteractiveViewer, } from "@worldorbit/viewer";
|
|
4
4
|
import { getViewerVisibleBounds, invertViewerPoint } from "@worldorbit/viewer/viewer-state";
|
|
@@ -1250,7 +1250,7 @@ export function createWorldOrbitEditor(container, options = {}) {
|
|
|
1250
1250
|
break;
|
|
1251
1251
|
case "orbit-radius":
|
|
1252
1252
|
if (details.object.placement?.mode === "orbit" && details.orbit) {
|
|
1253
|
-
nextDocument = updateOrbitRadius(atlasDocument, dragState.path, dragState.objectId, details, pointer, dragState.orbitRadiusContext ?? null);
|
|
1253
|
+
nextDocument = updateOrbitRadius(atlasDocument, dragState.path, dragState.objectId, viewer.getScene(), details, pointer, dragState.orbitRadiusContext ?? null);
|
|
1254
1254
|
}
|
|
1255
1255
|
break;
|
|
1256
1256
|
case "at-reference":
|
|
@@ -2468,7 +2468,7 @@ function updateOrbitPhase(document, path, objectId, details, pointer) {
|
|
|
2468
2468
|
};
|
|
2469
2469
|
return next;
|
|
2470
2470
|
}
|
|
2471
|
-
function updateOrbitRadius(document, path, objectId, details, pointer, dragContext) {
|
|
2471
|
+
function updateOrbitRadius(document, path, objectId, scene, details, pointer, dragContext) {
|
|
2472
2472
|
const orbit = details.orbit;
|
|
2473
2473
|
if (!orbit || details.object.placement?.mode !== "orbit" || !dragContext) {
|
|
2474
2474
|
return document;
|
|
@@ -2476,25 +2476,54 @@ function updateOrbitRadius(document, path, objectId, details, pointer, dragConte
|
|
|
2476
2476
|
const unrotated = rotatePoint(pointer, { x: orbit.cx, y: orbit.cy }, -orbit.rotationDeg);
|
|
2477
2477
|
const nextDisplayedRadius = Math.max(Math.abs(unrotated.x - orbit.cx), 24);
|
|
2478
2478
|
const nextBaseRadius = Math.max(nextDisplayedRadius - dragContext.radiusOffsetPx, dragContext.innerPx);
|
|
2479
|
-
const nextMetric = orbitRadiusPxToMetric(nextBaseRadius, dragContext.innerPx, dragContext.stepPx);
|
|
2479
|
+
const nextMetric = orbitRadiusPxToMetric(nextBaseRadius, dragContext.innerPx, dragContext.stepPx, dragContext.mode, dragContext.pixelsPerMetric);
|
|
2480
2480
|
const next = cloneAtlasDocument(document);
|
|
2481
2481
|
const placementOwner = findEditablePlacementOwner(next, path, objectId);
|
|
2482
2482
|
if (!placementOwner || placementOwner.placement.mode !== "orbit") {
|
|
2483
2483
|
return document;
|
|
2484
2484
|
}
|
|
2485
|
-
const
|
|
2486
|
-
|
|
2485
|
+
const orbitPlacementOwner = placementOwner;
|
|
2486
|
+
const currentValue = orbitPlacementOwner.placement.semiMajor ??
|
|
2487
|
+
orbitPlacementOwner.placement.distance ?? {
|
|
2487
2488
|
value: 1,
|
|
2488
2489
|
unit: "au",
|
|
2489
2490
|
};
|
|
2490
2491
|
const scaled = distanceMetricToUnitValue(Math.max(nextMetric, 0), dragContext.preferredUnit ?? currentValue.unit);
|
|
2492
|
+
applyOrbitDistanceValue(orbitPlacementOwner, scaled);
|
|
2493
|
+
const targetDisplayedRadius = nextDisplayedRadius;
|
|
2494
|
+
let correctedMetric = nextMetric;
|
|
2495
|
+
for (let iteration = 0; iteration < 3; iteration += 1) {
|
|
2496
|
+
const candidateScene = renderDocumentToScene(materializeAtlasDocument(next), {
|
|
2497
|
+
width: scene.width,
|
|
2498
|
+
height: scene.height,
|
|
2499
|
+
padding: scene.padding,
|
|
2500
|
+
preset: scene.renderPreset ?? undefined,
|
|
2501
|
+
projection: scene.projection,
|
|
2502
|
+
camera: scene.camera,
|
|
2503
|
+
scaleModel: { ...scene.scaleModel },
|
|
2504
|
+
bodyScaleMode: scene.scaleModel.bodyScaleMode,
|
|
2505
|
+
activeEventId: scene.activeEventId,
|
|
2506
|
+
});
|
|
2507
|
+
const renderedOrbit = candidateScene.orbitVisuals.find((entry) => entry.objectId === objectId);
|
|
2508
|
+
const renderedRadius = renderedOrbit?.kind === "circle"
|
|
2509
|
+
? renderedOrbit.radius ?? 0
|
|
2510
|
+
: renderedOrbit?.rx ?? 0;
|
|
2511
|
+
if (renderedRadius >= targetDisplayedRadius - 1) {
|
|
2512
|
+
break;
|
|
2513
|
+
}
|
|
2514
|
+
const correctionFactor = targetDisplayedRadius / Math.max(renderedRadius, 1);
|
|
2515
|
+
correctedMetric *= Math.max(correctionFactor, 1.02);
|
|
2516
|
+
applyOrbitDistanceValue(orbitPlacementOwner, distanceMetricToUnitValue(Math.max(correctedMetric, 0), dragContext.preferredUnit ?? currentValue.unit));
|
|
2517
|
+
}
|
|
2518
|
+
return next;
|
|
2519
|
+
}
|
|
2520
|
+
function applyOrbitDistanceValue(placementOwner, value) {
|
|
2491
2521
|
if (placementOwner.placement.semiMajor) {
|
|
2492
|
-
placementOwner.placement.semiMajor =
|
|
2522
|
+
placementOwner.placement.semiMajor = value;
|
|
2493
2523
|
}
|
|
2494
2524
|
else {
|
|
2495
|
-
placementOwner.placement.distance =
|
|
2525
|
+
placementOwner.placement.distance = value;
|
|
2496
2526
|
}
|
|
2497
|
-
return next;
|
|
2498
2527
|
}
|
|
2499
2528
|
function updateAtReference(document, path, objectId, scene, pointer) {
|
|
2500
2529
|
const candidate = findNearestAtCandidate(scene, objectId, pointer);
|
|
@@ -2533,15 +2562,26 @@ function createOrbitRadiusDragContext(document, scene, details) {
|
|
|
2533
2562
|
!entry.hidden).length;
|
|
2534
2563
|
const spacingFactor = layoutPresetSpacingForScene(scene.layoutPreset);
|
|
2535
2564
|
const stepPx = (siblingCount > 2 ? 54 : 64) * spacingFactor * scene.scaleModel.orbitDistanceMultiplier;
|
|
2565
|
+
const minimumGapPx = scene.scaleModel.bodyScaleMode === "strict"
|
|
2566
|
+
? Math.max(2, 8 * spacingFactor * scene.scaleModel.orbitDistanceMultiplier)
|
|
2567
|
+
: stepPx * 0.42;
|
|
2536
2568
|
const innerPx = details.parent.radius +
|
|
2537
|
-
|
|
2569
|
+
Math.max(minimumGapPx * 1.2, 24 * spacingFactor);
|
|
2538
2570
|
const currentValue = details.object.placement.semiMajor ?? details.object.placement.distance ?? null;
|
|
2539
2571
|
const currentMetric = unitValueToDistanceMetric(currentValue);
|
|
2540
2572
|
const displayedRadius = details.orbit.kind === "circle" ? details.orbit.radius ?? 1 : details.orbit.rx ?? 1;
|
|
2541
|
-
const
|
|
2573
|
+
const usesLinearScale = currentMetric !== null && currentMetric > 0;
|
|
2574
|
+
const pixelsPerMetric = usesLinearScale
|
|
2575
|
+
? displayedRadius / Math.max(currentMetric, 0.0001)
|
|
2576
|
+
: null;
|
|
2577
|
+
const baseRadius = usesLinearScale
|
|
2578
|
+
? currentMetric * Math.max(pixelsPerMetric ?? 0, 0)
|
|
2579
|
+
: orbitMetricToRadiusPx(currentMetric ?? 0, innerPx, stepPx);
|
|
2542
2580
|
return {
|
|
2581
|
+
mode: usesLinearScale ? "linear" : "log",
|
|
2543
2582
|
innerPx,
|
|
2544
2583
|
stepPx,
|
|
2584
|
+
pixelsPerMetric,
|
|
2545
2585
|
radiusOffsetPx: displayedRadius - baseRadius,
|
|
2546
2586
|
preferredUnit: currentValue?.unit ?? null,
|
|
2547
2587
|
};
|
|
@@ -3191,7 +3231,10 @@ function distanceMetricToUnitValue(metric, unit) {
|
|
|
3191
3231
|
function orbitMetricToRadiusPx(metric, innerPx, stepPx) {
|
|
3192
3232
|
return innerPx + stepPx * log2(Math.max(metric, 0) + 1);
|
|
3193
3233
|
}
|
|
3194
|
-
function orbitRadiusPxToMetric(radiusPx, innerPx, stepPx) {
|
|
3234
|
+
function orbitRadiusPxToMetric(radiusPx, innerPx, stepPx, mode, pixelsPerMetric) {
|
|
3235
|
+
if (mode === "linear" && pixelsPerMetric !== null && pixelsPerMetric > 0) {
|
|
3236
|
+
return Math.max(radiusPx / pixelsPerMetric, 0);
|
|
3237
|
+
}
|
|
3195
3238
|
if (radiusPx <= innerPx) {
|
|
3196
3239
|
return 0;
|
|
3197
3240
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function formatDiagnosticLocation(diagnostic) {
|
|
2
|
+
if (!diagnostic.line) {
|
|
3
|
+
return "No position";
|
|
4
|
+
}
|
|
5
|
+
if (!diagnostic.column) {
|
|
6
|
+
return `Line ${diagnostic.line}`;
|
|
7
|
+
}
|
|
8
|
+
return `Line ${diagnostic.line}, Column ${diagnostic.column}`;
|
|
9
|
+
}
|
|
10
|
+
export function summarizeDiagnostics(diagnostics) {
|
|
11
|
+
const errors = diagnostics.filter((diagnostic) => diagnostic.severity === "error").length;
|
|
12
|
+
const warnings = diagnostics.filter((diagnostic) => diagnostic.severity === "warning").length;
|
|
13
|
+
if (!errors && !warnings) {
|
|
14
|
+
return "Ready";
|
|
15
|
+
}
|
|
16
|
+
if (errors && warnings) {
|
|
17
|
+
return `${errors} error${errors === 1 ? "" : "s"}, ${warnings} warning${warnings === 1 ? "" : "s"}`;
|
|
18
|
+
}
|
|
19
|
+
if (errors) {
|
|
20
|
+
return `${errors} error${errors === 1 ? "" : "s"}`;
|
|
21
|
+
}
|
|
22
|
+
return `${warnings} warning${warnings === 1 ? "" : "s"}`;
|
|
23
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export const WORLDORBIT_HELP_TITLE = "WorldOrbit Quick Start";
|
|
2
|
+
export function buildSolarSystemExampleBlock() {
|
|
3
|
+
return [
|
|
4
|
+
"```worldorbit",
|
|
5
|
+
"schema 2.5",
|
|
6
|
+
"",
|
|
7
|
+
"system Sol",
|
|
8
|
+
' title "Solar System"',
|
|
9
|
+
" referencePlane ecliptic",
|
|
10
|
+
"",
|
|
11
|
+
"defaults",
|
|
12
|
+
" view orthographic",
|
|
13
|
+
" preset atlas-card",
|
|
14
|
+
"",
|
|
15
|
+
'group inner-system',
|
|
16
|
+
' label "Inner System"',
|
|
17
|
+
"",
|
|
18
|
+
"object star Sun",
|
|
19
|
+
" mass 1sol",
|
|
20
|
+
"",
|
|
21
|
+
"object planet Mercury",
|
|
22
|
+
" orbit Sun",
|
|
23
|
+
" semiMajor 0.39au",
|
|
24
|
+
" color #b7b1a7",
|
|
25
|
+
" groups inner-system",
|
|
26
|
+
"",
|
|
27
|
+
"object planet Venus",
|
|
28
|
+
" orbit Sun",
|
|
29
|
+
" semiMajor 0.72au",
|
|
30
|
+
" color #d9b37a",
|
|
31
|
+
" groups inner-system",
|
|
32
|
+
"",
|
|
33
|
+
"object planet Earth",
|
|
34
|
+
" orbit Sun",
|
|
35
|
+
" semiMajor 1au",
|
|
36
|
+
" color #6fa8ff",
|
|
37
|
+
" atmosphere nitrogen-oxygen",
|
|
38
|
+
" groups inner-system",
|
|
39
|
+
"",
|
|
40
|
+
"object moon Luna",
|
|
41
|
+
" orbit Earth",
|
|
42
|
+
" distance 384400km",
|
|
43
|
+
"",
|
|
44
|
+
"object planet Mars",
|
|
45
|
+
" orbit Sun",
|
|
46
|
+
" semiMajor 1.52au",
|
|
47
|
+
" color #d97c52",
|
|
48
|
+
" groups inner-system",
|
|
49
|
+
"```",
|
|
50
|
+
].join("\n");
|
|
51
|
+
}
|
|
52
|
+
export function getQuickStartMarkdown() {
|
|
53
|
+
return [
|
|
54
|
+
"Paste this into a note:",
|
|
55
|
+
"",
|
|
56
|
+
"```worldorbit",
|
|
57
|
+
"schema 2.5",
|
|
58
|
+
"",
|
|
59
|
+
"system Sol",
|
|
60
|
+
"",
|
|
61
|
+
"object star Sun",
|
|
62
|
+
"",
|
|
63
|
+
"object planet Earth",
|
|
64
|
+
" orbit Sun",
|
|
65
|
+
" semiMajor 1au",
|
|
66
|
+
"```",
|
|
67
|
+
"",
|
|
68
|
+
"Useful fields:",
|
|
69
|
+
"- `object planet NAME` creates a body",
|
|
70
|
+
"- `orbit TARGET` places it around another object",
|
|
71
|
+
"- `semiMajor 1au` or `distance 384400km` controls placement",
|
|
72
|
+
"- `color #6fa8ff` sets a display color hint",
|
|
73
|
+
"- `radius`, `mass`, `kind`, and `atmosphere` add more detail",
|
|
74
|
+
"",
|
|
75
|
+
"Locked mode keeps scrolling safe in notes. Activate interaction only when you want to pan or zoom the diagram.",
|
|
76
|
+
].join("\n");
|
|
77
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { WorldOrbitObsidianPlugin } from "./plugin.js";
|
|
2
|
+
export { DEFAULT_SETTINGS } from "./settings.js";
|
|
3
|
+
export { formatDiagnosticLocation, summarizeDiagnostics } from "./diagnostics.js";
|
|
4
|
+
export { buildSolarSystemExampleBlock, getQuickStartMarkdown, WORLDORBIT_HELP_TITLE, } from "./examples.js";
|
|
5
|
+
export { inferFenceContentStartLine, resolveDiagnosticEditorPosition, } from "./positions.js";
|
|
6
|
+
export { createDiagnosticNavigationTarget, navigateToWorldOrbitDiagnostic, resolveFenceNavigationContext, } from "./navigation.js";
|
|
7
|
+
export { createObsidianViewerTheme } from "./theme.js";
|
|
8
|
+
export { WorldOrbitEmbeddedView } from "./viewer-host.js";
|
|
9
|
+
export type * from "./types.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { WorldOrbitObsidianPlugin } from "./plugin.js";
|
|
2
|
+
export { DEFAULT_SETTINGS } from "./settings.js";
|
|
3
|
+
export { formatDiagnosticLocation, summarizeDiagnostics } from "./diagnostics.js";
|
|
4
|
+
export { buildSolarSystemExampleBlock, getQuickStartMarkdown, WORLDORBIT_HELP_TITLE, } from "./examples.js";
|
|
5
|
+
export { inferFenceContentStartLine, resolveDiagnosticEditorPosition, } from "./positions.js";
|
|
6
|
+
export { createDiagnosticNavigationTarget, navigateToWorldOrbitDiagnostic, resolveFenceNavigationContext, } from "./navigation.js";
|
|
7
|
+
export { createObsidianViewerTheme } from "./theme.js";
|
|
8
|
+
export { WorldOrbitEmbeddedView } from "./viewer-host.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { WorldOrbitDiagnostic } from "@worldorbit/core/types";
|
|
2
|
+
import { type App, type MarkdownPostProcessorContext } from "obsidian";
|
|
3
|
+
import type { BlockNavigationContext, DiagnosticNavigationTarget } from "./types.js";
|
|
4
|
+
export declare function resolveFenceNavigationContext(ctx: MarkdownPostProcessorContext, el: HTMLElement): BlockNavigationContext | null;
|
|
5
|
+
export declare function createDiagnosticNavigationTarget(contentStartLine: number | null, diagnostic: WorldOrbitDiagnostic): DiagnosticNavigationTarget;
|
|
6
|
+
export declare function navigateToWorldOrbitDiagnostic(app: App, sourcePath: string, contentStartLine: number, diagnostic: WorldOrbitDiagnostic): Promise<boolean>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { MarkdownView, TFile, } from "obsidian";
|
|
2
|
+
import { inferFenceContentStartLine, resolveDiagnosticEditorPosition, } from "./positions.js";
|
|
3
|
+
export function resolveFenceNavigationContext(ctx, el) {
|
|
4
|
+
if (!ctx.sourcePath) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
const sectionInfo = ctx.getSectionInfo(el);
|
|
8
|
+
if (!sectionInfo) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
sourcePath: ctx.sourcePath,
|
|
13
|
+
contentStartLine: inferFenceContentStartLine(sectionInfo),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function createDiagnosticNavigationTarget(contentStartLine, diagnostic) {
|
|
17
|
+
return {
|
|
18
|
+
diagnostic,
|
|
19
|
+
position: contentStartLine === null
|
|
20
|
+
? null
|
|
21
|
+
: resolveDiagnosticEditorPosition(contentStartLine, diagnostic),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export async function navigateToWorldOrbitDiagnostic(app, sourcePath, contentStartLine, diagnostic) {
|
|
25
|
+
const position = resolveDiagnosticEditorPosition(contentStartLine, diagnostic);
|
|
26
|
+
if (!position) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
const file = app.vault.getAbstractFileByPath(sourcePath);
|
|
30
|
+
if (!(file instanceof TFile)) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const leaf = app.workspace.getMostRecentLeaf() ?? app.workspace.getLeaf(true);
|
|
34
|
+
await leaf.openFile(file);
|
|
35
|
+
const view = leaf.view instanceof MarkdownView
|
|
36
|
+
? leaf.view
|
|
37
|
+
: app.workspace.getActiveViewOfType(MarkdownView);
|
|
38
|
+
if (!view) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
view.editor.setCursor(position);
|
|
42
|
+
view.editor.focus();
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Plugin } from "obsidian";
|
|
2
|
+
import type { WorldOrbitObsidianPluginSettings } from "./types.js";
|
|
3
|
+
export declare class WorldOrbitObsidianPlugin extends Plugin {
|
|
4
|
+
settings: WorldOrbitObsidianPluginSettings;
|
|
5
|
+
onload(): Promise<void>;
|
|
6
|
+
loadSettings(): Promise<void>;
|
|
7
|
+
saveSettings(): Promise<void>;
|
|
8
|
+
}
|