@bitcobblers/wod-wiki-core 0.11.43 → 0.35.2116
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/index.cjs +690 -150
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +479 -160
- package/dist/index.d.ts +479 -160
- package/dist/index.mjs +667 -149
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -24,6 +24,88 @@ function getMetricOwnershipLayer(origin) {
|
|
|
24
24
|
return LEGACY_ORIGIN_TO_OWNERSHIP_LAYER[origin ?? "parser"] ?? "parser";
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
// src/models/Metric.ts
|
|
28
|
+
var MetricType = /* @__PURE__ */ ((MetricType2) => {
|
|
29
|
+
MetricType2["Duration"] = "duration";
|
|
30
|
+
MetricType2["Spans"] = "spans";
|
|
31
|
+
MetricType2["SystemTime"] = "system-time";
|
|
32
|
+
MetricType2["Time"] = "time";
|
|
33
|
+
MetricType2["Elapsed"] = "elapsed";
|
|
34
|
+
MetricType2["Total"] = "total";
|
|
35
|
+
MetricType2["Rep"] = "rep";
|
|
36
|
+
MetricType2["Effort"] = "effort";
|
|
37
|
+
MetricType2["Distance"] = "distance";
|
|
38
|
+
MetricType2["Rounds"] = "rounds";
|
|
39
|
+
MetricType2["CurrentRound"] = "current-round";
|
|
40
|
+
MetricType2["Action"] = "action";
|
|
41
|
+
MetricType2["Increment"] = "increment";
|
|
42
|
+
MetricType2["Group"] = "group";
|
|
43
|
+
MetricType2["Text"] = "text";
|
|
44
|
+
MetricType2["Resistance"] = "resistance";
|
|
45
|
+
MetricType2["Sound"] = "sound";
|
|
46
|
+
MetricType2["System"] = "system";
|
|
47
|
+
MetricType2["Label"] = "label";
|
|
48
|
+
MetricType2["Lap"] = "lap";
|
|
49
|
+
MetricType2["Metric"] = "metric";
|
|
50
|
+
MetricType2["Hint"] = "hint";
|
|
51
|
+
MetricType2["Custom"] = "custom";
|
|
52
|
+
MetricType2["Volume"] = "volume";
|
|
53
|
+
MetricType2["Intensity"] = "intensity";
|
|
54
|
+
MetricType2["Grade"] = "grade";
|
|
55
|
+
MetricType2["Load"] = "load";
|
|
56
|
+
MetricType2["Work"] = "work";
|
|
57
|
+
MetricType2["RIR"] = "rir";
|
|
58
|
+
MetricType2["SessionRPE"] = "session-rpe";
|
|
59
|
+
MetricType2["SessionLoad"] = "session-load";
|
|
60
|
+
MetricType2["METScore"] = "met-score";
|
|
61
|
+
MetricType2["TIS"] = "tis";
|
|
62
|
+
MetricType2["Calculated"] = "calculated";
|
|
63
|
+
MetricType2["Choice"] = "choice";
|
|
64
|
+
return MetricType2;
|
|
65
|
+
})(MetricType || {});
|
|
66
|
+
var Metric = class {
|
|
67
|
+
type;
|
|
68
|
+
metricType;
|
|
69
|
+
value;
|
|
70
|
+
origin;
|
|
71
|
+
unit;
|
|
72
|
+
action;
|
|
73
|
+
image;
|
|
74
|
+
sourceBlockKey;
|
|
75
|
+
timestamp;
|
|
76
|
+
metadata;
|
|
77
|
+
name;
|
|
78
|
+
ownershipLayer;
|
|
79
|
+
constructor(typeOrName, valueOrType, originOrValue, unit, origin, action, image) {
|
|
80
|
+
if (typeof valueOrType === "string" && (typeof originOrValue === "number" || typeof originOrValue === "string" || typeof originOrValue === "boolean" || originOrValue === null || originOrValue === void 0)) {
|
|
81
|
+
this.name = String(typeOrName);
|
|
82
|
+
this.type = valueOrType;
|
|
83
|
+
this.metricType = valueOrType;
|
|
84
|
+
this.value = originOrValue;
|
|
85
|
+
this.unit = unit;
|
|
86
|
+
this.origin = origin || "parser";
|
|
87
|
+
this.action = action === "suppress" ? "suppress" : void 0;
|
|
88
|
+
this.image = image ?? String(originOrValue ?? valueOrType);
|
|
89
|
+
} else {
|
|
90
|
+
this.type = typeOrName;
|
|
91
|
+
this.metricType = typeOrName;
|
|
92
|
+
this.value = valueOrType;
|
|
93
|
+
this.origin = originOrValue || "parser";
|
|
94
|
+
this.unit = unit;
|
|
95
|
+
this.action = typeof origin === "string" && origin === "suppress" ? "suppress" : action === "suppress" ? "suppress" : void 0;
|
|
96
|
+
this.image = image ?? String(valueOrType ?? typeOrName);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
toNumber() {
|
|
100
|
+
if (typeof this.value === "number") return this.value;
|
|
101
|
+
if (typeof this.value === "string") {
|
|
102
|
+
const parsed = parseFloat(this.value);
|
|
103
|
+
return isNaN(parsed) ? 0 : parsed;
|
|
104
|
+
}
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
27
109
|
// src/ownership/ledger.ts
|
|
28
110
|
var LAYER_RANK = {
|
|
29
111
|
parser: 0,
|
|
@@ -39,6 +121,10 @@ function resolveLayer(metric) {
|
|
|
39
121
|
}
|
|
40
122
|
return getMetricOwnershipLayer(metric.origin);
|
|
41
123
|
}
|
|
124
|
+
function ownershipRank(metric) {
|
|
125
|
+
const layer = resolveLayer(metric);
|
|
126
|
+
return LAYER_RANK[layer] ?? 0;
|
|
127
|
+
}
|
|
42
128
|
function normalize(metrics) {
|
|
43
129
|
return metrics.map((metric, index) => {
|
|
44
130
|
const layer = resolveLayer(metric);
|
|
@@ -232,98 +318,6 @@ function createMetricOwnershipLedger(metrics) {
|
|
|
232
318
|
}
|
|
233
319
|
};
|
|
234
320
|
}
|
|
235
|
-
|
|
236
|
-
// src/models/Metric.ts
|
|
237
|
-
var MetricType = /* @__PURE__ */ ((MetricType2) => {
|
|
238
|
-
MetricType2["Duration"] = "duration";
|
|
239
|
-
MetricType2["Spans"] = "spans";
|
|
240
|
-
MetricType2["SystemTime"] = "system-time";
|
|
241
|
-
MetricType2["Time"] = "time";
|
|
242
|
-
MetricType2["Elapsed"] = "elapsed";
|
|
243
|
-
MetricType2["Total"] = "total";
|
|
244
|
-
MetricType2["Rep"] = "rep";
|
|
245
|
-
MetricType2["Effort"] = "effort";
|
|
246
|
-
MetricType2["Distance"] = "distance";
|
|
247
|
-
MetricType2["Rounds"] = "rounds";
|
|
248
|
-
MetricType2["CurrentRound"] = "current-round";
|
|
249
|
-
MetricType2["Action"] = "action";
|
|
250
|
-
MetricType2["Increment"] = "increment";
|
|
251
|
-
MetricType2["Group"] = "group";
|
|
252
|
-
MetricType2["Text"] = "text";
|
|
253
|
-
MetricType2["Resistance"] = "resistance";
|
|
254
|
-
MetricType2["Sound"] = "sound";
|
|
255
|
-
MetricType2["System"] = "system";
|
|
256
|
-
MetricType2["Label"] = "label";
|
|
257
|
-
MetricType2["Lap"] = "lap";
|
|
258
|
-
MetricType2["Metric"] = "metric";
|
|
259
|
-
MetricType2["Hint"] = "hint";
|
|
260
|
-
MetricType2["Custom"] = "custom";
|
|
261
|
-
MetricType2["Volume"] = "volume";
|
|
262
|
-
MetricType2["Intensity"] = "intensity";
|
|
263
|
-
MetricType2["Load"] = "load";
|
|
264
|
-
MetricType2["Work"] = "work";
|
|
265
|
-
MetricType2["RIR"] = "rir";
|
|
266
|
-
MetricType2["SessionRPE"] = "session-rpe";
|
|
267
|
-
MetricType2["SessionLoad"] = "session-load";
|
|
268
|
-
MetricType2["METScore"] = "met-score";
|
|
269
|
-
MetricType2["TIS"] = "tis";
|
|
270
|
-
MetricType2["Calculated"] = "calculated";
|
|
271
|
-
MetricType2["Choice"] = "choice";
|
|
272
|
-
return MetricType2;
|
|
273
|
-
})(MetricType || {});
|
|
274
|
-
var Metric = class {
|
|
275
|
-
type;
|
|
276
|
-
metricType;
|
|
277
|
-
value;
|
|
278
|
-
origin;
|
|
279
|
-
unit;
|
|
280
|
-
action;
|
|
281
|
-
image;
|
|
282
|
-
sourceBlockKey;
|
|
283
|
-
timestamp;
|
|
284
|
-
metadata;
|
|
285
|
-
name;
|
|
286
|
-
ownershipLayer;
|
|
287
|
-
constructor(typeOrName, valueOrType, originOrValue, unit, origin, action, image) {
|
|
288
|
-
if (typeof valueOrType === "string" && (typeof originOrValue === "number" || typeof originOrValue === "string" || typeof originOrValue === "boolean" || originOrValue === null || originOrValue === void 0)) {
|
|
289
|
-
this.name = String(typeOrName);
|
|
290
|
-
this.type = valueOrType;
|
|
291
|
-
this.metricType = valueOrType;
|
|
292
|
-
this.value = originOrValue;
|
|
293
|
-
this.unit = unit;
|
|
294
|
-
this.origin = origin || "parser";
|
|
295
|
-
this.action = action === "suppress" ? "suppress" : void 0;
|
|
296
|
-
this.image = image ?? String(originOrValue ?? valueOrType);
|
|
297
|
-
} else {
|
|
298
|
-
this.type = typeOrName;
|
|
299
|
-
this.metricType = typeOrName;
|
|
300
|
-
this.value = valueOrType;
|
|
301
|
-
this.origin = originOrValue || "parser";
|
|
302
|
-
this.unit = unit;
|
|
303
|
-
this.action = typeof origin === "string" && origin === "suppress" ? "suppress" : action === "suppress" ? "suppress" : void 0;
|
|
304
|
-
this.image = image ?? String(valueOrType ?? typeOrName);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
toNumber() {
|
|
308
|
-
if (typeof this.value === "number") return this.value;
|
|
309
|
-
if (typeof this.value === "string") {
|
|
310
|
-
const parsed = parseFloat(this.value);
|
|
311
|
-
return isNaN(parsed) ? 0 : parsed;
|
|
312
|
-
}
|
|
313
|
-
return 0;
|
|
314
|
-
}
|
|
315
|
-
};
|
|
316
|
-
|
|
317
|
-
// src/ownership/OwnershipResolver.ts
|
|
318
|
-
function resolveLayer2(metric) {
|
|
319
|
-
const maybeLayer = metric.ownershipLayer;
|
|
320
|
-
if (maybeLayer != null) return maybeLayer;
|
|
321
|
-
return getMetricOwnershipLayer(metric.origin ?? "parser");
|
|
322
|
-
}
|
|
323
|
-
function ownershipRank(metric) {
|
|
324
|
-
const layer = resolveLayer2(metric);
|
|
325
|
-
return METRIC_OWNERSHIP_LAYER_CHAIN.indexOf(layer);
|
|
326
|
-
}
|
|
327
321
|
function applyFilter(metrics, filter) {
|
|
328
322
|
let filtered = [...metrics];
|
|
329
323
|
const wantsHints = filter?.types?.includes("hint" /* Hint */) ?? false;
|
|
@@ -358,6 +352,181 @@ var OwnershipResolver = class {
|
|
|
358
352
|
}
|
|
359
353
|
};
|
|
360
354
|
|
|
355
|
+
// src/fields/fieldIdentity.ts
|
|
356
|
+
function splitWords(component) {
|
|
357
|
+
const onSeparators = component.split(/[\s_\-\u2010-\u2015]+/).filter(Boolean);
|
|
358
|
+
const words = [];
|
|
359
|
+
for (const chunk of onSeparators) {
|
|
360
|
+
const cased = chunk.replace(/([\p{Ll}\p{Nd}])(\p{Lu})/gu, "$1\0$2").replace(/(\p{Lu})(\p{Lu}\p{Ll})/gu, "$1\0$2");
|
|
361
|
+
for (const word of cased.split("\0")) {
|
|
362
|
+
if (word) words.push(word);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return words;
|
|
366
|
+
}
|
|
367
|
+
function normalizeFieldComponent(component) {
|
|
368
|
+
const words = splitWords(component);
|
|
369
|
+
if (words.length === 0) return "";
|
|
370
|
+
return words.map((word, index) => {
|
|
371
|
+
const lower = word.toLowerCase();
|
|
372
|
+
return index === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
|
|
373
|
+
}).join("");
|
|
374
|
+
}
|
|
375
|
+
function normalizeFieldPath(path) {
|
|
376
|
+
return path.split(".").map(normalizeFieldComponent).filter((component) => component.length > 0).join(".");
|
|
377
|
+
}
|
|
378
|
+
function valueKindOf(value) {
|
|
379
|
+
if (value === null) return "null";
|
|
380
|
+
if (value === void 0) return "undefined";
|
|
381
|
+
if (Array.isArray(value)) return "array";
|
|
382
|
+
switch (typeof value) {
|
|
383
|
+
case "number":
|
|
384
|
+
return "number";
|
|
385
|
+
case "string":
|
|
386
|
+
return "string";
|
|
387
|
+
case "boolean":
|
|
388
|
+
return "boolean";
|
|
389
|
+
case "object":
|
|
390
|
+
return "object";
|
|
391
|
+
default:
|
|
392
|
+
return "undefined";
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
function flattenFieldLeaves(input, prefix = "") {
|
|
396
|
+
const leaves = [];
|
|
397
|
+
for (const [rawKey, value] of Object.entries(input)) {
|
|
398
|
+
const path = prefix ? `${prefix}.${normalizeFieldPath(rawKey)}` : normalizeFieldPath(rawKey);
|
|
399
|
+
if (!path) continue;
|
|
400
|
+
const kind = valueKindOf(value);
|
|
401
|
+
if (kind === "object") {
|
|
402
|
+
leaves.push(...flattenFieldLeaves(value, path));
|
|
403
|
+
} else if (kind !== "undefined") {
|
|
404
|
+
leaves.push({ path, kind, value, originalPath: prefix ? `${prefix}.${rawKey}` : rawKey });
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return leaves;
|
|
408
|
+
}
|
|
409
|
+
function fieldRefKey(ref) {
|
|
410
|
+
return JSON.stringify([ref.path, ref.kind, ref.dimension ?? null]);
|
|
411
|
+
}
|
|
412
|
+
function fieldRefFromKey(key) {
|
|
413
|
+
const [path, kind, dimension] = JSON.parse(key);
|
|
414
|
+
return { path, kind, ...dimension ? { dimension } : {} };
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// src/units/catalog.ts
|
|
418
|
+
var UnitConversionError = class extends Error {
|
|
419
|
+
code;
|
|
420
|
+
constructor(code, message) {
|
|
421
|
+
super(message);
|
|
422
|
+
this.name = "UnitConversionError";
|
|
423
|
+
this.code = code;
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
var UNIT_CATALOG = [
|
|
427
|
+
// Distance — base m
|
|
428
|
+
{ canonical: "m", dimension: "distance", factor: 1, aliases: ["meter", "meters", "metre", "metres"] },
|
|
429
|
+
{ canonical: "km", dimension: "distance", factor: 1e3, aliases: ["kilometer", "kilometers", "kilometre", "kilometres"] },
|
|
430
|
+
{ canonical: "cm", dimension: "distance", factor: 0.01, aliases: ["centimeter", "centimeters"] },
|
|
431
|
+
{ canonical: "mm", dimension: "distance", factor: 1e-3, aliases: ["millimeter", "millimeters"] },
|
|
432
|
+
{ canonical: "ft", dimension: "distance", factor: 0.3048, aliases: ["foot", "feet"] },
|
|
433
|
+
{ canonical: "in", dimension: "distance", factor: 0.0254, aliases: ["inch", "inches"] },
|
|
434
|
+
{ canonical: "yd", dimension: "distance", factor: 0.9144, aliases: ["yard", "yards"] },
|
|
435
|
+
{ canonical: "mi", dimension: "distance", factor: 1609.344, aliases: ["mile", "miles"] },
|
|
436
|
+
// Mass — base kg
|
|
437
|
+
{ canonical: "kg", dimension: "mass", factor: 1, aliases: ["kilogram", "kilograms", "kilo", "kilos"] },
|
|
438
|
+
{ canonical: "g", dimension: "mass", factor: 1e-3, aliases: ["gram", "grams"] },
|
|
439
|
+
{ canonical: "lb", dimension: "mass", factor: 0.45359237, aliases: ["lbs", "pound", "pounds"] },
|
|
440
|
+
// Duration — base s
|
|
441
|
+
{ canonical: "ms", dimension: "duration", factor: 1e-3, aliases: ["millisecond", "milliseconds"] },
|
|
442
|
+
{ canonical: "s", dimension: "duration", factor: 1, aliases: ["sec", "secs", "second", "seconds"] },
|
|
443
|
+
{ canonical: "min", dimension: "duration", factor: 60, aliases: ["mins", "minute", "minutes"] },
|
|
444
|
+
{ canonical: "h", dimension: "duration", factor: 3600, aliases: ["hr", "hrs", "hour", "hours"] },
|
|
445
|
+
// Count — base count. Test-result scales ("pull-up", "thruster",
|
|
446
|
+
// "problem") are count-dimension scales: one of their units is one rep.
|
|
447
|
+
{ canonical: "count", dimension: "count", factor: 1 },
|
|
448
|
+
{ canonical: "rep", dimension: "count", factor: 1, aliases: ["reps"] },
|
|
449
|
+
{ canonical: "pull-up", dimension: "count", factor: 1 },
|
|
450
|
+
{ canonical: "thruster", dimension: "count", factor: 1 },
|
|
451
|
+
{ canonical: "problem", dimension: "count", factor: 1 },
|
|
452
|
+
// Count-rate — base count/s; bpm (beats per minute) is its registered scale
|
|
453
|
+
{ canonical: "count/s", dimension: "count-rate", factor: 1 },
|
|
454
|
+
{ canonical: "bpm", dimension: "count-rate", factor: 1 / 60 },
|
|
455
|
+
// Energy — base cal
|
|
456
|
+
{ canonical: "cal", dimension: "energy", factor: 1, aliases: ["calorie", "calories"] },
|
|
457
|
+
{ canonical: "kcal", dimension: "energy", factor: 1e3, aliases: ["kilocalorie", "kilocalories"] },
|
|
458
|
+
// Speed — base m/s
|
|
459
|
+
{ canonical: "m/s", dimension: "speed", factor: 1 },
|
|
460
|
+
{ canonical: "km/h", dimension: "speed", factor: 1e3 / 3600, aliases: ["kmh", "kph"] },
|
|
461
|
+
{ canonical: "mph", dimension: "speed", factor: 1609.344 / 3600 },
|
|
462
|
+
// Pace — base min/km
|
|
463
|
+
{ canonical: "min/km", dimension: "pace", factor: 1 },
|
|
464
|
+
{ canonical: "min/mi", dimension: "pace", factor: 1e3 / 1609.344 },
|
|
465
|
+
{ canonical: "s/m", dimension: "pace", factor: 1 / 60 },
|
|
466
|
+
// Ratio — unitless base (factor 1); percent via 100% = 1.
|
|
467
|
+
// Dimensionless named scales (arbitrary units, points) share the ratio
|
|
468
|
+
// dimension but are convertible only to the base — never to each other.
|
|
469
|
+
{ canonical: "ratio", dimension: "ratio", factor: 1, aliases: ["x"] },
|
|
470
|
+
{ canonical: "%", dimension: "ratio", factor: 0.01, aliases: ["pct", "percent"] },
|
|
471
|
+
{ canonical: "au", dimension: "ratio", factor: 1, aliases: ["AU"] },
|
|
472
|
+
{ canonical: "pts", dimension: "ratio", factor: 1, aliases: ["point", "points"] },
|
|
473
|
+
{ canonical: "rating", dimension: "ratio", factor: 1, aliases: ["ratings"] }
|
|
474
|
+
];
|
|
475
|
+
var bySpelling = (() => {
|
|
476
|
+
const map = /* @__PURE__ */ new Map();
|
|
477
|
+
for (const def of UNIT_CATALOG) {
|
|
478
|
+
map.set(def.canonical.toLowerCase(), def);
|
|
479
|
+
for (const alias of def.aliases ?? []) {
|
|
480
|
+
if (!map.has(alias.toLowerCase())) map.set(alias.toLowerCase(), def);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return map;
|
|
484
|
+
})();
|
|
485
|
+
function lookupUnit(spelling) {
|
|
486
|
+
return bySpelling.get(spelling.trim().toLowerCase());
|
|
487
|
+
}
|
|
488
|
+
function dimensionKeyOf(spelling) {
|
|
489
|
+
return lookupUnit(spelling)?.dimension;
|
|
490
|
+
}
|
|
491
|
+
var SYSTEM_DEFAULT_OUTPUT_UNIT = Object.freeze({
|
|
492
|
+
mass: "kg",
|
|
493
|
+
distance: "m",
|
|
494
|
+
duration: "s",
|
|
495
|
+
count: "count",
|
|
496
|
+
"count-rate": "count/s",
|
|
497
|
+
energy: "cal",
|
|
498
|
+
speed: "m/s",
|
|
499
|
+
pace: "min/km",
|
|
500
|
+
ratio: void 0
|
|
501
|
+
});
|
|
502
|
+
function systemDefaultUnit(dimension) {
|
|
503
|
+
return SYSTEM_DEFAULT_OUTPUT_UNIT[dimension];
|
|
504
|
+
}
|
|
505
|
+
function convertViaCatalog(value, from, to) {
|
|
506
|
+
const fromDef = lookupUnit(from);
|
|
507
|
+
if (!fromDef) throw new UnitConversionError("unknown-unit", `Unknown unit "${from}"`);
|
|
508
|
+
const toDef = lookupUnit(to);
|
|
509
|
+
if (!toDef) throw new UnitConversionError("unknown-unit", `Unknown unit "${to}"`);
|
|
510
|
+
if (fromDef.dimension !== toDef.dimension) {
|
|
511
|
+
throw new UnitConversionError(
|
|
512
|
+
"dimension-mismatch",
|
|
513
|
+
`Cannot convert ${from} (${fromDef.dimension}) to ${to} (${toDef.dimension})`
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
if (fromDef.dimension === "ratio" && fromDef.canonical !== toDef.canonical) {
|
|
517
|
+
if (fromDef.canonical !== "ratio" && toDef.canonical !== "ratio") {
|
|
518
|
+
throw new UnitConversionError(
|
|
519
|
+
"scale-mismatch",
|
|
520
|
+
`Named scales ${from} and ${to} are not interchangeable`
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
if (!Number.isFinite(value)) {
|
|
525
|
+
throw new UnitConversionError("non-finite", `Non-finite value cannot be converted`);
|
|
526
|
+
}
|
|
527
|
+
return value * fromDef.factor / toDef.factor;
|
|
528
|
+
}
|
|
529
|
+
|
|
361
530
|
// src/models/CodeMetadata.ts
|
|
362
531
|
var CodeMetadata = class {
|
|
363
532
|
constructor(line, startOffset, endOffset, length, columnStart = 0, columnEnd = 0, raw = "") {
|
|
@@ -684,7 +853,7 @@ var ParsedCodeStatement = class extends CodeStatement {
|
|
|
684
853
|
};
|
|
685
854
|
|
|
686
855
|
// src/models/OutputStatement.ts
|
|
687
|
-
var OutputStatement = class _OutputStatement {
|
|
856
|
+
var OutputStatement = class _OutputStatement extends CodeStatement {
|
|
688
857
|
static nextId = 1e6;
|
|
689
858
|
id;
|
|
690
859
|
outputType;
|
|
@@ -702,6 +871,7 @@ var OutputStatement = class _OutputStatement {
|
|
|
702
871
|
statement;
|
|
703
872
|
timestamp;
|
|
704
873
|
constructor(optionsOrStatement, metricsArg, timestamp) {
|
|
874
|
+
super();
|
|
705
875
|
if (optionsOrStatement && "outputType" in optionsOrStatement && "timeSpan" in optionsOrStatement) {
|
|
706
876
|
const options = optionsOrStatement;
|
|
707
877
|
this.id = _OutputStatement.nextId++;
|
|
@@ -709,6 +879,9 @@ var OutputStatement = class _OutputStatement {
|
|
|
709
879
|
this.timeSpan = options.timeSpan;
|
|
710
880
|
this.sourceBlockKey = options.sourceBlockKey ?? "";
|
|
711
881
|
this.sourceStatementId = options.sourceStatementId;
|
|
882
|
+
this.line = options.line;
|
|
883
|
+
this.text = options.text;
|
|
884
|
+
this.dialect = options.dialect;
|
|
712
885
|
this.stackLevel = options.stackLevel ?? 0;
|
|
713
886
|
this.metrics = MetricContainer.from(options.metrics, this.id);
|
|
714
887
|
this.metricMeta = options.metricMeta ?? /* @__PURE__ */ new Map();
|
|
@@ -731,27 +904,13 @@ var OutputStatement = class _OutputStatement {
|
|
|
731
904
|
this.children = [];
|
|
732
905
|
this.isLeaf = true;
|
|
733
906
|
this.meta = stmt?.meta ?? new CodeMetadata(0, 0, 0, 0);
|
|
907
|
+
this.line = stmt?.line;
|
|
908
|
+
this.text = stmt?.text;
|
|
909
|
+
this.dialect = stmt?.dialect;
|
|
734
910
|
this.timestamp = timestamp ?? Date.now();
|
|
735
911
|
}
|
|
736
912
|
}
|
|
737
|
-
//
|
|
738
|
-
// IMetricSource implementation
|
|
739
|
-
// ═══════════════════════════════════════════════════════════════
|
|
740
|
-
getDisplayMetrics(filter) {
|
|
741
|
-
return this.metrics.getDisplayMetrics(filter);
|
|
742
|
-
}
|
|
743
|
-
getMetric(type) {
|
|
744
|
-
return this.metrics.getMetric(type);
|
|
745
|
-
}
|
|
746
|
-
getAllMetricsByType(type) {
|
|
747
|
-
return this.metrics.getAllMetricsByType(type);
|
|
748
|
-
}
|
|
749
|
-
hasMetric(type) {
|
|
750
|
-
return this.metrics.hasMetric(type);
|
|
751
|
-
}
|
|
752
|
-
get rawMetrics() {
|
|
753
|
-
return this.metrics.rawMetrics;
|
|
754
|
-
}
|
|
913
|
+
// IMetricSource implementation is inherited from CodeStatement
|
|
755
914
|
/**
|
|
756
915
|
* Reset the ID counter (useful for testing)
|
|
757
916
|
*/
|
|
@@ -760,37 +919,6 @@ var OutputStatement = class _OutputStatement {
|
|
|
760
919
|
}
|
|
761
920
|
};
|
|
762
921
|
|
|
763
|
-
// src/models/Duration.ts
|
|
764
|
-
var Duration = class {
|
|
765
|
-
constructor(original) {
|
|
766
|
-
this.original = original;
|
|
767
|
-
let remaining = original ?? 0;
|
|
768
|
-
this.days = Math.floor(remaining / 864e5);
|
|
769
|
-
remaining %= 864e5;
|
|
770
|
-
this.hours = Math.floor(remaining / 36e5);
|
|
771
|
-
remaining %= 36e5;
|
|
772
|
-
this.minutes = Math.floor(remaining / 6e4);
|
|
773
|
-
remaining %= 6e4;
|
|
774
|
-
this.seconds = Math.floor(remaining / 1e3);
|
|
775
|
-
this.milliseconds = Math.round(remaining - this.seconds * 1e3);
|
|
776
|
-
}
|
|
777
|
-
original;
|
|
778
|
-
days;
|
|
779
|
-
hours;
|
|
780
|
-
minutes;
|
|
781
|
-
seconds;
|
|
782
|
-
milliseconds;
|
|
783
|
-
};
|
|
784
|
-
var SpanDuration = class extends Duration {
|
|
785
|
-
constructor(spans) {
|
|
786
|
-
const total = spans.reduce((sum, span) => {
|
|
787
|
-
const end = span.ended ?? Date.now();
|
|
788
|
-
return sum + Math.max(0, end - span.started);
|
|
789
|
-
}, 0);
|
|
790
|
-
super(total);
|
|
791
|
-
}
|
|
792
|
-
};
|
|
793
|
-
|
|
794
922
|
// src/models/BlockKey.ts
|
|
795
923
|
var BlockKey = class {
|
|
796
924
|
value;
|
|
@@ -808,6 +936,17 @@ var BlockKey = class {
|
|
|
808
936
|
}
|
|
809
937
|
};
|
|
810
938
|
|
|
939
|
+
// src/models/blockContentId.ts
|
|
940
|
+
function blockContentId(content) {
|
|
941
|
+
const normalized = content.trim();
|
|
942
|
+
let hash = 2166136261;
|
|
943
|
+
for (let i = 0; i < normalized.length; i++) {
|
|
944
|
+
hash ^= normalized.charCodeAt(i);
|
|
945
|
+
hash = Math.imul(hash, 16777619);
|
|
946
|
+
}
|
|
947
|
+
return `bc-${(hash >>> 0).toString(16).padStart(8, "0")}`;
|
|
948
|
+
}
|
|
949
|
+
|
|
811
950
|
// src/types/storage.ts
|
|
812
951
|
var KNOWN_OUTPUT_TYPES = [
|
|
813
952
|
"segment",
|
|
@@ -837,16 +976,395 @@ var toNotebookTag = (notebookId) => `${NOTEBOOK_TAG_PREFIX}${notebookId}`;
|
|
|
837
976
|
var fromNotebookTag = (tag) => tag.startsWith(NOTEBOOK_TAG_PREFIX) ? tag.slice(NOTEBOOK_TAG_PREFIX.length) : null;
|
|
838
977
|
var isNotebookTag = (tag) => tag.startsWith(NOTEBOOK_TAG_PREFIX);
|
|
839
978
|
|
|
979
|
+
// src/sections/blockDetection.ts
|
|
980
|
+
function matchDialectFence(trimmedLine) {
|
|
981
|
+
if (!trimmedLine.startsWith("```")) return null;
|
|
982
|
+
const tag = trimmedLine.slice(3).split(/[\s\t]/)[0].toLowerCase();
|
|
983
|
+
const [base, sport] = tag.split(":", 2);
|
|
984
|
+
if (VALID_FENCE_DIALECTS.includes(base)) {
|
|
985
|
+
return { dialect: base, sport: sport || void 0 };
|
|
986
|
+
}
|
|
987
|
+
return null;
|
|
988
|
+
}
|
|
989
|
+
function detectScriptBlocks(content) {
|
|
990
|
+
const lines = content.split("\n");
|
|
991
|
+
const blocks = [];
|
|
992
|
+
let inBlock = false;
|
|
993
|
+
let currentBlock = {};
|
|
994
|
+
let blockContent = [];
|
|
995
|
+
lines.forEach((line, index) => {
|
|
996
|
+
const trimmedLine = line.trim();
|
|
997
|
+
if (!inBlock) {
|
|
998
|
+
const fence = matchDialectFence(trimmedLine);
|
|
999
|
+
if (fence) {
|
|
1000
|
+
inBlock = true;
|
|
1001
|
+
const now = Date.now();
|
|
1002
|
+
currentBlock = {
|
|
1003
|
+
id: `${fence.dialect}-block-${now}-${Math.random().toString(36).slice(2, 9)}`,
|
|
1004
|
+
dialect: fence.dialect,
|
|
1005
|
+
sport: fence.sport,
|
|
1006
|
+
startLine: index,
|
|
1007
|
+
state: "idle",
|
|
1008
|
+
version: 1,
|
|
1009
|
+
createdAt: now
|
|
1010
|
+
};
|
|
1011
|
+
blockContent = [];
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
if (inBlock && trimmedLine.startsWith("```")) {
|
|
1016
|
+
inBlock = false;
|
|
1017
|
+
currentBlock.endLine = index;
|
|
1018
|
+
currentBlock.content = blockContent.join("\n");
|
|
1019
|
+
blocks.push(currentBlock);
|
|
1020
|
+
currentBlock = {};
|
|
1021
|
+
blockContent = [];
|
|
1022
|
+
} else if (inBlock) {
|
|
1023
|
+
blockContent.push(line);
|
|
1024
|
+
}
|
|
1025
|
+
});
|
|
1026
|
+
if (inBlock && currentBlock.startLine !== void 0) {
|
|
1027
|
+
currentBlock.endLine = lines.length - 1;
|
|
1028
|
+
currentBlock.content = blockContent.join("\n");
|
|
1029
|
+
blocks.push(currentBlock);
|
|
1030
|
+
}
|
|
1031
|
+
return blocks;
|
|
1032
|
+
}
|
|
1033
|
+
function findBlockAtLine(blocks, lineNumber) {
|
|
1034
|
+
return blocks.find(
|
|
1035
|
+
(block) => lineNumber >= block.startLine && lineNumber <= block.endLine
|
|
1036
|
+
) ?? null;
|
|
1037
|
+
}
|
|
1038
|
+
function extractBlockContent(content, startLine, endLine) {
|
|
1039
|
+
const lines = content.split("\n");
|
|
1040
|
+
return lines.slice(startLine + 1, endLine).join("\n");
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
// src/sections/sectionParser.ts
|
|
1044
|
+
var METADATA_REGEX = /<!--\s*section-metadata\s+id:(\S+)\s+version:(\d+)\s+created:(\d+)\s*-->/i;
|
|
1045
|
+
function extractMetadata(text) {
|
|
1046
|
+
const match = text.match(METADATA_REGEX);
|
|
1047
|
+
if (!match) return { metadata: null, cleanText: text };
|
|
1048
|
+
return {
|
|
1049
|
+
metadata: {
|
|
1050
|
+
id: match[1],
|
|
1051
|
+
version: parseInt(match[2], 10),
|
|
1052
|
+
createdAt: parseInt(match[3], 10)
|
|
1053
|
+
},
|
|
1054
|
+
cleanText: text.replace(METADATA_REGEX, "").trim()
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
1057
|
+
function generateSectionId(type, startLine, content) {
|
|
1058
|
+
let hash = 0;
|
|
1059
|
+
for (let i = 0; i < content.length && i < 64; i++) {
|
|
1060
|
+
hash = (hash << 5) - hash + content.charCodeAt(i) | 0;
|
|
1061
|
+
}
|
|
1062
|
+
const hashHex = (hash >>> 0).toString(16).padStart(8, "0");
|
|
1063
|
+
return `${type}-${startLine}-${hashHex}`;
|
|
1064
|
+
}
|
|
1065
|
+
function detectUrlSubtype(url) {
|
|
1066
|
+
if (!url) return null;
|
|
1067
|
+
const withoutScheme = url.trim().replace(/^[a-z][a-z0-9+.-]*:\/\//i, "");
|
|
1068
|
+
const host = withoutScheme.split(/[/?#:]/, 1)[0].toLowerCase();
|
|
1069
|
+
if (host === "youtube.com" || host.endsWith(".youtube.com") || host === "youtu.be") return "youtube";
|
|
1070
|
+
if (host === "strava.com" || host.endsWith(".strava.com")) return "strava";
|
|
1071
|
+
if (host === "amazon.com" || host.endsWith(".amazon.com") || host === "amzn.to") return "amazon";
|
|
1072
|
+
return null;
|
|
1073
|
+
}
|
|
1074
|
+
function resolveFrontMatterSubtype(props) {
|
|
1075
|
+
const typeValue = (props["type"] || "").toLowerCase();
|
|
1076
|
+
if (typeValue === "youtube") return "youtube";
|
|
1077
|
+
if (typeValue === "strava") return "strava";
|
|
1078
|
+
if (typeValue === "amazon") return "amazon";
|
|
1079
|
+
if (typeValue === "file") return "file";
|
|
1080
|
+
if (typeValue === "effort") return "effort";
|
|
1081
|
+
const url = props["url"] || props["link"] || "";
|
|
1082
|
+
if (url) {
|
|
1083
|
+
const detected = detectUrlSubtype(url);
|
|
1084
|
+
if (detected) return detected;
|
|
1085
|
+
}
|
|
1086
|
+
if (props["baseAttributes"] !== void 0 || props["discipline"] !== void 0 || props["effortType"] !== void 0 || props["targetRPE"] !== void 0 || props["equipment"] !== void 0 || props["aliases"] !== void 0 || props["derivation"] !== void 0) {
|
|
1087
|
+
return "effort";
|
|
1088
|
+
}
|
|
1089
|
+
return "default";
|
|
1090
|
+
}
|
|
1091
|
+
function parseFrontMatterProperties(innerLines) {
|
|
1092
|
+
const props = {};
|
|
1093
|
+
for (const line of innerLines) {
|
|
1094
|
+
const match = line.match(/^([^:]+):\s*(.*)$/);
|
|
1095
|
+
if (match) {
|
|
1096
|
+
props[match[1].trim()] = match[2].trim();
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
return props;
|
|
1100
|
+
}
|
|
1101
|
+
function matchMarkdownEmbed(trimmed) {
|
|
1102
|
+
const match = trimmed.match(/^(!)?\[([^\]]*)\]\(([^)]+)\)$/);
|
|
1103
|
+
if (!match) return null;
|
|
1104
|
+
const isImage = !!match[1];
|
|
1105
|
+
const label = match[2];
|
|
1106
|
+
const url = match[3];
|
|
1107
|
+
let type = isImage ? "image" : "link";
|
|
1108
|
+
if (/youtube\.com|youtu\.be/i.test(url)) {
|
|
1109
|
+
type = "youtube";
|
|
1110
|
+
}
|
|
1111
|
+
return { type, label, url, isImage };
|
|
1112
|
+
}
|
|
1113
|
+
function detectFrontMatterBlocks(lines, scriptBlocks) {
|
|
1114
|
+
const ranges = [];
|
|
1115
|
+
let i = 0;
|
|
1116
|
+
while (i < lines.length) {
|
|
1117
|
+
const inScript = scriptBlocks.some((b) => i >= b.startLine && i <= b.endLine);
|
|
1118
|
+
if (inScript) {
|
|
1119
|
+
i++;
|
|
1120
|
+
continue;
|
|
1121
|
+
}
|
|
1122
|
+
if (lines[i].trim() === "---") {
|
|
1123
|
+
const openLine = i;
|
|
1124
|
+
let j = i + 1;
|
|
1125
|
+
while (j < lines.length) {
|
|
1126
|
+
const inScriptInner = scriptBlocks.some((b) => j >= b.startLine && j <= b.endLine);
|
|
1127
|
+
if (inScriptInner) {
|
|
1128
|
+
j++;
|
|
1129
|
+
continue;
|
|
1130
|
+
}
|
|
1131
|
+
if (lines[j].trim() === "---") {
|
|
1132
|
+
ranges.push({ startLine: openLine, endLine: j });
|
|
1133
|
+
i = j + 1;
|
|
1134
|
+
break;
|
|
1135
|
+
}
|
|
1136
|
+
j++;
|
|
1137
|
+
}
|
|
1138
|
+
if (j >= lines.length) {
|
|
1139
|
+
i++;
|
|
1140
|
+
}
|
|
1141
|
+
} else {
|
|
1142
|
+
i++;
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
return ranges;
|
|
1146
|
+
}
|
|
1147
|
+
function parseDocumentSections(content, scriptBlocks) {
|
|
1148
|
+
if (!content) return [];
|
|
1149
|
+
const blocks = scriptBlocks ?? detectScriptBlocks(content);
|
|
1150
|
+
const lines = content.split("\n");
|
|
1151
|
+
const sections = [];
|
|
1152
|
+
const fmRanges = detectFrontMatterBlocks(lines, blocks);
|
|
1153
|
+
const now = Date.now();
|
|
1154
|
+
let currentLine = 0;
|
|
1155
|
+
let isFirstTextBlock = true;
|
|
1156
|
+
function flushMarkdownLines(mdLines, startLine) {
|
|
1157
|
+
if (mdLines.length === 0) return;
|
|
1158
|
+
let currentGroup = [];
|
|
1159
|
+
let groupStartLine = startLine;
|
|
1160
|
+
const flushGroup = () => {
|
|
1161
|
+
if (currentGroup.length > 0) {
|
|
1162
|
+
const raw = currentGroup.join("\n");
|
|
1163
|
+
const { metadata, cleanText } = extractMetadata(raw);
|
|
1164
|
+
const trimmed = cleanText.trim();
|
|
1165
|
+
const embed = currentGroup.length === 1 ? matchMarkdownEmbed(trimmed) : null;
|
|
1166
|
+
if (embed) {
|
|
1167
|
+
sections.push({
|
|
1168
|
+
id: metadata?.id || generateSectionId("embed", groupStartLine, trimmed),
|
|
1169
|
+
type: "embed",
|
|
1170
|
+
rawContent: cleanText,
|
|
1171
|
+
displayContent: cleanText,
|
|
1172
|
+
startLine: groupStartLine,
|
|
1173
|
+
endLine: groupStartLine,
|
|
1174
|
+
lineCount: 1,
|
|
1175
|
+
embed,
|
|
1176
|
+
version: metadata?.version || 1,
|
|
1177
|
+
createdAt: metadata?.createdAt || now
|
|
1178
|
+
});
|
|
1179
|
+
} else if (isFirstTextBlock) {
|
|
1180
|
+
isFirstTextBlock = false;
|
|
1181
|
+
sections.push({
|
|
1182
|
+
id: metadata?.id || generateSectionId("title", groupStartLine, cleanText),
|
|
1183
|
+
type: "title",
|
|
1184
|
+
rawContent: cleanText,
|
|
1185
|
+
displayContent: cleanText,
|
|
1186
|
+
startLine: groupStartLine,
|
|
1187
|
+
endLine: groupStartLine + currentGroup.length - 1,
|
|
1188
|
+
lineCount: currentGroup.length,
|
|
1189
|
+
version: metadata?.version || 1,
|
|
1190
|
+
createdAt: metadata?.createdAt || now
|
|
1191
|
+
});
|
|
1192
|
+
} else {
|
|
1193
|
+
sections.push({
|
|
1194
|
+
id: metadata?.id || generateSectionId("markdown", groupStartLine, cleanText),
|
|
1195
|
+
type: "markdown",
|
|
1196
|
+
rawContent: cleanText,
|
|
1197
|
+
displayContent: cleanText,
|
|
1198
|
+
startLine: groupStartLine,
|
|
1199
|
+
endLine: groupStartLine + currentGroup.length - 1,
|
|
1200
|
+
lineCount: currentGroup.length,
|
|
1201
|
+
version: metadata?.version || 1,
|
|
1202
|
+
createdAt: metadata?.createdAt || now
|
|
1203
|
+
});
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
currentGroup = [];
|
|
1207
|
+
};
|
|
1208
|
+
for (let i = 0; i < mdLines.length; i++) {
|
|
1209
|
+
const line = mdLines[i];
|
|
1210
|
+
if (line.trim().length === 0) {
|
|
1211
|
+
flushGroup();
|
|
1212
|
+
sections.push({
|
|
1213
|
+
id: generateSectionId("markdown", startLine + i, ""),
|
|
1214
|
+
type: "markdown",
|
|
1215
|
+
rawContent: "",
|
|
1216
|
+
displayContent: "",
|
|
1217
|
+
startLine: startLine + i,
|
|
1218
|
+
endLine: startLine + i,
|
|
1219
|
+
lineCount: 1,
|
|
1220
|
+
version: 1,
|
|
1221
|
+
createdAt: now
|
|
1222
|
+
});
|
|
1223
|
+
groupStartLine = startLine + i + 1;
|
|
1224
|
+
} else {
|
|
1225
|
+
currentGroup.push(line);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
flushGroup();
|
|
1229
|
+
}
|
|
1230
|
+
let mdBuffer = [];
|
|
1231
|
+
let mdBufferStart = 0;
|
|
1232
|
+
while (currentLine < lines.length) {
|
|
1233
|
+
const scriptBlock = blocks.find((b) => b.startLine === currentLine);
|
|
1234
|
+
if (scriptBlock) {
|
|
1235
|
+
flushMarkdownLines(mdBuffer, mdBufferStart);
|
|
1236
|
+
mdBuffer = [];
|
|
1237
|
+
const dialect = scriptBlock.dialect ?? "time";
|
|
1238
|
+
const { metadata, cleanText } = extractMetadata(scriptBlock.content);
|
|
1239
|
+
const fenceTag = scriptBlock.sport ? `${dialect}:${scriptBlock.sport}` : dialect;
|
|
1240
|
+
const cleanRawContent = `\`\`\`${fenceTag}
|
|
1241
|
+
${cleanText}
|
|
1242
|
+
\`\`\``;
|
|
1243
|
+
const cleanLineCount = cleanRawContent.split("\n").length;
|
|
1244
|
+
const sectionId = metadata?.id || generateSectionId(dialect, scriptBlock.startLine, cleanText);
|
|
1245
|
+
const contentId = blockContentId(cleanText);
|
|
1246
|
+
sections.push({
|
|
1247
|
+
id: sectionId,
|
|
1248
|
+
contentId,
|
|
1249
|
+
type: dialect,
|
|
1250
|
+
sport: scriptBlock.sport,
|
|
1251
|
+
rawContent: cleanRawContent,
|
|
1252
|
+
displayContent: cleanText,
|
|
1253
|
+
startLine: scriptBlock.startLine,
|
|
1254
|
+
endLine: scriptBlock.startLine + cleanLineCount - 1,
|
|
1255
|
+
lineCount: cleanLineCount,
|
|
1256
|
+
scriptBlock: {
|
|
1257
|
+
...scriptBlock,
|
|
1258
|
+
id: sectionId,
|
|
1259
|
+
contentId,
|
|
1260
|
+
content: cleanText,
|
|
1261
|
+
dialect,
|
|
1262
|
+
version: metadata?.version || 1,
|
|
1263
|
+
createdAt: metadata?.createdAt || now
|
|
1264
|
+
},
|
|
1265
|
+
version: metadata?.version || 1,
|
|
1266
|
+
createdAt: metadata?.createdAt || now
|
|
1267
|
+
});
|
|
1268
|
+
currentLine = scriptBlock.endLine + 1;
|
|
1269
|
+
mdBufferStart = currentLine;
|
|
1270
|
+
continue;
|
|
1271
|
+
}
|
|
1272
|
+
const fmRange = fmRanges.find((r) => r.startLine === currentLine);
|
|
1273
|
+
if (fmRange) {
|
|
1274
|
+
flushMarkdownLines(mdBuffer, mdBufferStart);
|
|
1275
|
+
mdBuffer = [];
|
|
1276
|
+
const rawLines = lines.slice(fmRange.startLine, fmRange.endLine + 1);
|
|
1277
|
+
const raw = rawLines.join("\n");
|
|
1278
|
+
const innerLines = lines.slice(fmRange.startLine + 1, fmRange.endLine);
|
|
1279
|
+
const { metadata, cleanText } = extractMetadata(innerLines.join("\n"));
|
|
1280
|
+
const properties = parseFrontMatterProperties(cleanText.split("\n"));
|
|
1281
|
+
const subtype = resolveFrontMatterSubtype(properties);
|
|
1282
|
+
const lineCount = fmRange.endLine - fmRange.startLine + 1;
|
|
1283
|
+
sections.push({
|
|
1284
|
+
id: metadata?.id || generateSectionId("frontmatter", fmRange.startLine, raw),
|
|
1285
|
+
type: "frontmatter",
|
|
1286
|
+
rawContent: raw,
|
|
1287
|
+
displayContent: cleanText,
|
|
1288
|
+
startLine: fmRange.startLine,
|
|
1289
|
+
endLine: fmRange.endLine,
|
|
1290
|
+
lineCount,
|
|
1291
|
+
properties,
|
|
1292
|
+
frontmatterType: subtype,
|
|
1293
|
+
version: metadata?.version || 1,
|
|
1294
|
+
createdAt: metadata?.createdAt || now
|
|
1295
|
+
});
|
|
1296
|
+
currentLine = fmRange.endLine + 1;
|
|
1297
|
+
mdBufferStart = currentLine;
|
|
1298
|
+
continue;
|
|
1299
|
+
}
|
|
1300
|
+
if (mdBuffer.length === 0) {
|
|
1301
|
+
mdBufferStart = currentLine;
|
|
1302
|
+
}
|
|
1303
|
+
mdBuffer.push(lines[currentLine]);
|
|
1304
|
+
currentLine++;
|
|
1305
|
+
}
|
|
1306
|
+
flushMarkdownLines(mdBuffer, mdBufferStart);
|
|
1307
|
+
return sections;
|
|
1308
|
+
}
|
|
1309
|
+
function buildRawContent(sections) {
|
|
1310
|
+
return sections.filter((s) => !s.deleted).map((s) => s.rawContent).join("\n");
|
|
1311
|
+
}
|
|
1312
|
+
function calculateTotalLines(sections) {
|
|
1313
|
+
const visible = sections.filter((s) => !s.deleted);
|
|
1314
|
+
if (visible.length === 0) return 0;
|
|
1315
|
+
const last = visible[visible.length - 1];
|
|
1316
|
+
return last.endLine + 1;
|
|
1317
|
+
}
|
|
1318
|
+
function matchSectionIds(oldSections, newSections) {
|
|
1319
|
+
return newSections.map((newSec) => {
|
|
1320
|
+
const { metadata } = extractMetadata(newSec.rawContent);
|
|
1321
|
+
if (metadata) {
|
|
1322
|
+
const updated = { ...newSec, id: metadata.id, version: metadata.version, createdAt: metadata.createdAt };
|
|
1323
|
+
if (updated.scriptBlock) {
|
|
1324
|
+
updated.scriptBlock = { ...updated.scriptBlock, id: metadata.id };
|
|
1325
|
+
}
|
|
1326
|
+
return updated;
|
|
1327
|
+
}
|
|
1328
|
+
const exactMatch = oldSections.find(
|
|
1329
|
+
(old) => old.type === newSec.type && old.startLine === newSec.startLine && old.displayContent === newSec.displayContent
|
|
1330
|
+
);
|
|
1331
|
+
if (exactMatch) {
|
|
1332
|
+
const updated = { ...newSec, id: exactMatch.id, version: exactMatch.version, createdAt: exactMatch.createdAt };
|
|
1333
|
+
if (updated.scriptBlock) {
|
|
1334
|
+
updated.scriptBlock = { ...updated.scriptBlock, id: exactMatch.id };
|
|
1335
|
+
}
|
|
1336
|
+
return updated;
|
|
1337
|
+
}
|
|
1338
|
+
const positionMatch = oldSections.find(
|
|
1339
|
+
(old) => old.type === newSec.type && old.startLine === newSec.startLine
|
|
1340
|
+
);
|
|
1341
|
+
if (positionMatch) {
|
|
1342
|
+
const newVersion = (positionMatch.version || 1) + 1;
|
|
1343
|
+
const updated = {
|
|
1344
|
+
...newSec,
|
|
1345
|
+
id: positionMatch.id,
|
|
1346
|
+
version: newVersion,
|
|
1347
|
+
createdAt: positionMatch.createdAt
|
|
1348
|
+
};
|
|
1349
|
+
if (updated.scriptBlock) {
|
|
1350
|
+
updated.scriptBlock = { ...updated.scriptBlock, id: positionMatch.id, version: newVersion };
|
|
1351
|
+
}
|
|
1352
|
+
return updated;
|
|
1353
|
+
}
|
|
1354
|
+
return newSec;
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1357
|
+
|
|
840
1358
|
// src/version.ts
|
|
841
|
-
var VERSION = "0.
|
|
842
|
-
var GIT_SHA = "
|
|
843
|
-
var BUILD_TIME = "2026-
|
|
1359
|
+
var VERSION = "0.35.2116";
|
|
1360
|
+
var GIT_SHA = "a4d411f";
|
|
1361
|
+
var BUILD_TIME = "2026-10-12T00:14:24.795Z";
|
|
844
1362
|
var SEMVER = {
|
|
845
|
-
version: "0.
|
|
846
|
-
gitSha: "
|
|
847
|
-
buildTime: "2026-
|
|
1363
|
+
version: "0.35.2116",
|
|
1364
|
+
gitSha: "a4d411f",
|
|
1365
|
+
buildTime: "2026-10-12T00:14:24.795Z"
|
|
848
1366
|
};
|
|
849
1367
|
|
|
850
|
-
export { BUILD_TIME, BlockKey, CodeMetadata, CodeStatement,
|
|
1368
|
+
export { BUILD_TIME, BlockKey, CodeMetadata, CodeStatement, GIT_SHA, KNOWN_OUTPUT_TYPES, LEGACY_ORIGIN_TO_OWNERSHIP_LAYER, METRIC_OWNERSHIP_LAYER_CHAIN, Metric, MetricContainer, MetricType, NOTEBOOK_TAG_PREFIX, OutputStatement, OwnershipResolver, ParsedCodeStatement, SEMVER, SYSTEM_DEFAULT_OUTPUT_UNIT, UNIT_CATALOG, UnitConversionError, VALID_FENCE_DIALECTS, VERSION, blockContentId, buildRawContent, calculateTotalLines, convertViaCatalog, createMetricOwnershipLedger, detectScriptBlocks, dimensionKeyOf, extractBlockContent, fieldRefFromKey, fieldRefKey, findBlockAtLine, flattenFieldLeaves, fromNotebookTag, generateSectionId, getMetricOwnershipLayer, isNotebookTag, isWorkoutSectionType, lookupUnit, matchDialectFence, matchSectionIds, normalizeFieldComponent, normalizeFieldPath, ownershipRank, parseDocumentSections, resolveLayer, runAffordance, systemDefaultUnit, toNotebookTag, valueKindOf };
|
|
851
1369
|
//# sourceMappingURL=index.mjs.map
|
|
852
1370
|
//# sourceMappingURL=index.mjs.map
|