@bitcobblers/wod-wiki-core 0.36.2136 → 0.37.2139

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 CHANGED
@@ -36,6 +36,7 @@ var MetricType = /* @__PURE__ */ ((MetricType2) => {
36
36
  MetricType2["Total"] = "total";
37
37
  MetricType2["Rep"] = "rep";
38
38
  MetricType2["Effort"] = "effort";
39
+ MetricType2["Equipment"] = "equipment";
39
40
  MetricType2["Distance"] = "distance";
40
41
  MetricType2["Rounds"] = "rounds";
41
42
  MetricType2["CurrentRound"] = "current-round";
@@ -530,6 +531,29 @@ function convertViaCatalog(value, from, to) {
530
531
  return value * fromDef.factor / toDef.factor;
531
532
  }
532
533
 
534
+ // src/models/ReferenceMetadata.ts
535
+ var REFERENCE_METADATA_KEY = "references";
536
+ var REFERENCE_MATCH_KINDS = ["explicit", "split", "whole", "default", "none"];
537
+ function isValidReferenceRef(value) {
538
+ if (!value || typeof value !== "object") return false;
539
+ const candidate = value;
540
+ return (candidate.kind === "effort" || candidate.kind === "equipment") && typeof candidate.slug === "string" && !!candidate.slug && typeof candidate.label === "string";
541
+ }
542
+ function isValidReferenceDiagnostic(value) {
543
+ if (!value || typeof value !== "object") return false;
544
+ return typeof value.reason === "string";
545
+ }
546
+ function getReferenceMetadata(metadata) {
547
+ const value = metadata?.[REFERENCE_METADATA_KEY];
548
+ if (!value || typeof value !== "object") return void 0;
549
+ const candidate = value;
550
+ if (typeof candidate.matched !== "string" || !REFERENCE_MATCH_KINDS.includes(candidate.matched)) return void 0;
551
+ if (typeof candidate.source !== "string") return void 0;
552
+ if (candidate.refs !== void 0 && (!Array.isArray(candidate.refs) || !candidate.refs.every(isValidReferenceRef))) return void 0;
553
+ if (candidate.diagnostics !== void 0 && (!Array.isArray(candidate.diagnostics) || !candidate.diagnostics.every(isValidReferenceDiagnostic))) return void 0;
554
+ return value;
555
+ }
556
+
533
557
  // src/models/CodeMetadata.ts
534
558
  var CodeMetadata = class {
535
559
  constructor(line, startOffset, endOffset, length, columnStart = 0, columnEnd = 0, raw = "") {
@@ -988,13 +1012,14 @@ function matchDialectFence(trimmedLine) {
988
1012
  }
989
1013
  function frontmatterSubtype(properties) {
990
1014
  const type = properties.type?.toLowerCase();
991
- if (type === "youtube" || type === "strava" || type === "amazon" || type === "file" || type === "effort") return type;
1015
+ if (type === "youtube" || type === "strava" || type === "amazon" || type === "file" || type === "effort" || type === "equipment") return type;
992
1016
  const url = properties.url || properties.link || "";
993
1017
  const host = url.replace(/^[a-z][a-z0-9+.-]*:\/\//i, "").split(/[/?#:]/, 1)[0].toLowerCase();
994
1018
  if (host === "youtu.be" || host === "youtube.com" || host.endsWith(".youtube.com")) return "youtube";
995
1019
  if (host === "strava.com" || host.endsWith(".strava.com")) return "strava";
996
1020
  if (host === "amzn.to" || host === "amazon.com" || host.endsWith(".amazon.com")) return "amazon";
997
1021
  if (["baseAttributes", "discipline", "effortType", "targetRPE", "equipment", "aliases", "derivation"].some((key) => key in properties)) return "effort";
1022
+ if (["slug", "label", "registrySource", "ownerNoteId", "sourcePath"].some((key) => key in properties)) return "equipment";
998
1023
  return "default";
999
1024
  }
1000
1025
  function markdownSubtype(text) {
@@ -1211,14 +1236,173 @@ function extractBlockContent(content, startLine, endLine) {
1211
1236
  return parseDocumentSections(content).find((section) => section.startLine === startLine && section.endLine === endLine && section.scriptBlock)?.scriptBlock?.content ?? "";
1212
1237
  }
1213
1238
 
1239
+ // src/sections/frontmatter.ts
1240
+ var KEY_RE = /^[A-Za-z][\w.-]*$/;
1241
+ var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---/;
1242
+ function escapeRe(s) {
1243
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1244
+ }
1245
+ function isBlankOrComment(line) {
1246
+ const t = line.trim();
1247
+ return t === "" || t.startsWith("#");
1248
+ }
1249
+ function isList(value) {
1250
+ return Array.isArray(value);
1251
+ }
1252
+ function quoteYamlScalar(value) {
1253
+ if (value === "") return '""';
1254
+ const looksNumeric = !isNaN(Number(value));
1255
+ const looksKeyword = /^(true|false|null|yes|no|on|off)$/i.test(value);
1256
+ if (/[:"'\n#{}[\],&*?|<>=%!@`]/.test(value) || value !== value.trim() || value.startsWith("-") || looksNumeric || looksKeyword) {
1257
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t")}"`;
1258
+ }
1259
+ return value;
1260
+ }
1261
+ function propertyLines(indent, key, value) {
1262
+ const pad = " ".repeat(indent);
1263
+ if (isList(value)) {
1264
+ if (value.length === 0) return [`${pad}${key}: []`];
1265
+ return [`${pad}${key}:`, ...value.map((item) => `${pad} - ${typeof item === "number" ? String(item) : quoteYamlScalar(item)}`)];
1266
+ }
1267
+ return [`${pad}${key}: ${typeof value === "number" ? String(value) : quoteYamlScalar(value)}`];
1268
+ }
1269
+ function missingChainLines(path, from, value, baseIndent) {
1270
+ const out = [];
1271
+ let indent = baseIndent;
1272
+ for (let i = from; i < path.length; i++) {
1273
+ if (i === path.length - 1) {
1274
+ out.push(...propertyLines(indent, path[i], value));
1275
+ } else {
1276
+ out.push(`${" ".repeat(indent)}${path[i]}:`);
1277
+ }
1278
+ indent += 2;
1279
+ }
1280
+ return out;
1281
+ }
1282
+ function inlineCommentIndex(line) {
1283
+ let inSingle = false;
1284
+ let inDouble = false;
1285
+ for (let i = 0; i < line.length; i++) {
1286
+ const c = line[i];
1287
+ if (inDouble) {
1288
+ if (c === "\\") i++;
1289
+ else if (c === '"') inDouble = false;
1290
+ continue;
1291
+ }
1292
+ if (inSingle) {
1293
+ if (c === "'") inSingle = false;
1294
+ continue;
1295
+ }
1296
+ if (c === '"') inDouble = true;
1297
+ else if (c === "'") inSingle = true;
1298
+ else if (c === "#" && (i === 0 || /\s/.test(line[i - 1]))) return i;
1299
+ }
1300
+ return -1;
1301
+ }
1302
+ function propertyExtent(lines, start, indent) {
1303
+ const extent = [start];
1304
+ let pending = [];
1305
+ for (let j = start + 1; j < lines.length; j++) {
1306
+ const line = lines[j];
1307
+ if (isBlankOrComment(line)) {
1308
+ pending.push(j);
1309
+ continue;
1310
+ }
1311
+ if (line.length - line.trimStart().length > indent) {
1312
+ extent.push(...pending, j);
1313
+ pending = [];
1314
+ } else {
1315
+ break;
1316
+ }
1317
+ }
1318
+ return extent;
1319
+ }
1320
+ function findProperty(lines, key, indent, from, to) {
1321
+ const re = new RegExp(`^ {${indent}}${escapeRe(key)}\\s*:`);
1322
+ for (let i = from; i < to; i++) {
1323
+ if (re.test(lines[i])) return i;
1324
+ }
1325
+ return -1;
1326
+ }
1327
+ function patchFrontmatterProperty(raw, path, value) {
1328
+ if (path.length === 0 || !path.every((k) => typeof k === "string" && KEY_RE.test(k))) return raw;
1329
+ const eol = raw.includes("\r\n") ? "\r\n" : "\n";
1330
+ const m = raw.match(FRONTMATTER_RE);
1331
+ if (!m) {
1332
+ if (value === null) return raw;
1333
+ const inner = missingChainLines(path, 0, value, 0);
1334
+ const block = `---${eol}${inner.join(eol)}${eol}---${eol}`;
1335
+ return raw.length ? block + raw : block;
1336
+ }
1337
+ const lines = m[1] === "" ? [] : m[1].split(/\r?\n/);
1338
+ let searchStart = 0;
1339
+ let searchEnd = lines.length;
1340
+ let foundDepth = -1;
1341
+ let foundIdx = -1;
1342
+ let foundExtent = [];
1343
+ for (let d = 0; d < path.length; d++) {
1344
+ const indent = d * 2;
1345
+ const idx = findProperty(lines, path[d], indent, searchStart, searchEnd);
1346
+ if (idx === -1) break;
1347
+ foundDepth = d;
1348
+ foundIdx = idx;
1349
+ foundExtent = propertyExtent(lines, idx, indent);
1350
+ searchStart = idx + 1;
1351
+ searchEnd = foundExtent[foundExtent.length - 1] + 1;
1352
+ }
1353
+ if (value === null) {
1354
+ if (foundDepth !== path.length - 1) return raw;
1355
+ const doomed = new Set(foundExtent);
1356
+ for (let d = foundDepth - 1; d >= 0; d--) {
1357
+ const indent = d * 2;
1358
+ const idx = findProperty(lines, path[d], indent, 0, lines.length);
1359
+ if (idx === -1 || doomed.has(idx)) break;
1360
+ let hasChild = false;
1361
+ for (let j = idx + 1; j < lines.length; j++) {
1362
+ if (doomed.has(j)) continue;
1363
+ const line = lines[j];
1364
+ if (isBlankOrComment(line)) continue;
1365
+ if (line.length - line.trimStart().length > indent) hasChild = true;
1366
+ break;
1367
+ }
1368
+ if (hasChild) break;
1369
+ doomed.add(idx);
1370
+ }
1371
+ const next2 = lines.filter((_, i) => !doomed.has(i));
1372
+ return `---${eol}${next2.length ? next2.join(eol) + eol : ""}---` + raw.slice(m[0].length);
1373
+ }
1374
+ let spliceIndex;
1375
+ let removeCount;
1376
+ let replacement;
1377
+ if (foundDepth === path.length - 1) {
1378
+ replacement = propertyLines(foundDepth * 2, path[foundDepth], value);
1379
+ if (!isList(value)) {
1380
+ const ci = inlineCommentIndex(lines[foundIdx]);
1381
+ if (ci !== -1) {
1382
+ const comment = lines[foundIdx].slice(ci).trim();
1383
+ replacement[0] = `${replacement[0]} ${comment}`;
1384
+ }
1385
+ }
1386
+ spliceIndex = foundExtent[0];
1387
+ removeCount = foundExtent.length;
1388
+ } else {
1389
+ spliceIndex = foundDepth === -1 ? lines.length : searchEnd;
1390
+ removeCount = 0;
1391
+ replacement = missingChainLines(path, foundDepth + 1, value, (foundDepth + 1) * 2);
1392
+ }
1393
+ const next = [...lines];
1394
+ next.splice(spliceIndex, removeCount, ...replacement);
1395
+ return `---${eol}${next.length ? next.join(eol) + eol : ""}---` + raw.slice(m[0].length);
1396
+ }
1397
+
1214
1398
  // src/version.ts
1215
- var VERSION = "0.36.2136";
1216
- var GIT_SHA = "ea2c980";
1217
- var BUILD_TIME = "2026-10-16T16:23:51.969Z";
1399
+ var VERSION = "0.37.2139";
1400
+ var GIT_SHA = "491ec71";
1401
+ var BUILD_TIME = "2026-10-17T15:36:01.834Z";
1218
1402
  var SEMVER = {
1219
- version: "0.36.2136",
1220
- gitSha: "ea2c980",
1221
- buildTime: "2026-10-16T16:23:51.969Z"
1403
+ version: "0.37.2139",
1404
+ gitSha: "491ec71",
1405
+ buildTime: "2026-10-17T15:36:01.834Z"
1222
1406
  };
1223
1407
 
1224
1408
  exports.BUILD_TIME = BUILD_TIME;
@@ -1237,6 +1421,7 @@ exports.NOTEBOOK_TAG_PREFIX = NOTEBOOK_TAG_PREFIX;
1237
1421
  exports.OutputStatement = OutputStatement;
1238
1422
  exports.OwnershipResolver = OwnershipResolver;
1239
1423
  exports.ParsedCodeStatement = ParsedCodeStatement;
1424
+ exports.REFERENCE_METADATA_KEY = REFERENCE_METADATA_KEY;
1240
1425
  exports.SEMVER = SEMVER;
1241
1426
  exports.SYSTEM_DEFAULT_OUTPUT_UNIT = SYSTEM_DEFAULT_OUTPUT_UNIT;
1242
1427
  exports.UNIT_CATALOG = UNIT_CATALOG;
@@ -1258,6 +1443,7 @@ exports.findBlockAtLine = findBlockAtLine;
1258
1443
  exports.flattenFieldLeaves = flattenFieldLeaves;
1259
1444
  exports.fromNotebookTag = fromNotebookTag;
1260
1445
  exports.getMetricOwnershipLayer = getMetricOwnershipLayer;
1446
+ exports.getReferenceMetadata = getReferenceMetadata;
1261
1447
  exports.isNotebookTag = isNotebookTag;
1262
1448
  exports.isWorkoutSectionType = isWorkoutSectionType;
1263
1449
  exports.lookupUnit = lookupUnit;
@@ -1267,6 +1453,7 @@ exports.normalizeFieldComponent = normalizeFieldComponent;
1267
1453
  exports.normalizeFieldPath = normalizeFieldPath;
1268
1454
  exports.ownershipRank = ownershipRank;
1269
1455
  exports.parseDocumentSections = parseDocumentSections;
1456
+ exports.patchFrontmatterProperty = patchFrontmatterProperty;
1270
1457
  exports.reconcileNoteBlocks = reconcileNoteBlocks;
1271
1458
  exports.resolveLayer = resolveLayer;
1272
1459
  exports.runAffordance = runAffordance;