@bitcobblers/wod-wiki-engine 0.35.2116 → 0.35.2117
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/bin/wod.cjs +912 -937
- package/dist/bin/wod.cjs.map +1 -1
- package/dist/bin/wod.mjs +2 -2
- package/dist/{chunk-B2OYLNEZ.mjs → chunk-AKNXDA75.mjs} +735 -679
- package/dist/chunk-AKNXDA75.mjs.map +1 -0
- package/dist/chunk-Y6WO6MXS.mjs +187 -0
- package/dist/chunk-Y6WO6MXS.mjs.map +1 -0
- package/dist/{compiler-KTBR6OEL.mjs → compiler-MQRZVZQW.mjs} +64 -326
- package/dist/compiler-MQRZVZQW.mjs.map +1 -0
- package/dist/index.cjs +924 -936
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -23
- package/dist/index.d.ts +93 -23
- package/dist/index.mjs +8 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/dist/chunk-6L5ZDZJ7.mjs +0 -15
- package/dist/chunk-6L5ZDZJ7.mjs.map +0 -1
- package/dist/chunk-B2OYLNEZ.mjs.map +0 -1
- package/dist/compiler-KTBR6OEL.mjs.map +0 -1
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
import { isEffortDiscipline } from '@bitcobblers/wod-wiki-lang';
|
|
3
|
+
import { KNOWN_SECTION_WIDGETS } from '@bitcobblers/wod-wiki-core';
|
|
4
|
+
|
|
5
|
+
if (typeof globalThis.require === 'undefined') {
|
|
6
|
+
try { globalThis.require = createRequire(import.meta.url); } catch {}
|
|
7
|
+
}
|
|
8
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
9
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
10
|
+
}) : x)(function(x) {
|
|
11
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
12
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// src/cli/seedbuild/frontmatter.ts
|
|
16
|
+
var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
17
|
+
function unquote(value) {
|
|
18
|
+
return value.replace(
|
|
19
|
+
/^(['"])(.*)\1$/,
|
|
20
|
+
(_match, quote, inner) => quote === '"' ? inner.replace(/\\(["\\])/g, "$1") : inner
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
function parseFrontmatter(raw) {
|
|
24
|
+
const match = raw.match(FRONTMATTER_RE);
|
|
25
|
+
if (!match) return { meta: {}, body: raw };
|
|
26
|
+
return { meta: parseMetaLines(match[1].split(/\r?\n/)), body: raw.slice(match[0].length) };
|
|
27
|
+
}
|
|
28
|
+
function parseMetaLines(lines) {
|
|
29
|
+
const meta = {};
|
|
30
|
+
for (let i = 0; i < lines.length; i++) {
|
|
31
|
+
const keyMatch = lines[i].match(/^([A-Za-z][\w.-]*)\s*:(.*)$/);
|
|
32
|
+
if (!keyMatch) continue;
|
|
33
|
+
const key = keyMatch[1];
|
|
34
|
+
const rawVal = keyMatch[2].trim();
|
|
35
|
+
if (rawVal === "") {
|
|
36
|
+
const items = [];
|
|
37
|
+
while (i + 1 < lines.length) {
|
|
38
|
+
const itemMatch = lines[i + 1].match(/^\s+-\s+(.+)$/);
|
|
39
|
+
if (!itemMatch) break;
|
|
40
|
+
items.push(itemMatch[1].trim());
|
|
41
|
+
i++;
|
|
42
|
+
}
|
|
43
|
+
meta[key] = items.length > 0 ? items : "";
|
|
44
|
+
} else {
|
|
45
|
+
const wasQuoted = /^(['"])(.*)\1$/.test(rawVal);
|
|
46
|
+
const value = unquote(rawVal);
|
|
47
|
+
const num = Number(value);
|
|
48
|
+
meta[key] = !wasQuoted && value !== "" && !isNaN(num) ? num : value;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return meta;
|
|
52
|
+
}
|
|
53
|
+
function getScalar(meta, key) {
|
|
54
|
+
const value = meta[key];
|
|
55
|
+
return typeof value === "string" || typeof value === "number" ? value : void 0;
|
|
56
|
+
}
|
|
57
|
+
function getList(meta, key) {
|
|
58
|
+
const value = meta[key];
|
|
59
|
+
return Array.isArray(value) ? value : [];
|
|
60
|
+
}
|
|
61
|
+
function parseDiscipline(val) {
|
|
62
|
+
if (!val) return void 0;
|
|
63
|
+
const normalized = unquoteYaml(val.trim()).toLowerCase();
|
|
64
|
+
if (isEffortDiscipline(normalized)) return normalized;
|
|
65
|
+
console.warn(`[effort-file] unknown discipline '${val}' \u2014 treating as unset`);
|
|
66
|
+
return void 0;
|
|
67
|
+
}
|
|
68
|
+
function unquoteYaml(val) {
|
|
69
|
+
if (val.startsWith('"') && val.endsWith('"')) {
|
|
70
|
+
return val.slice(1, -1).replace(/\\(["\\])/g, "$1");
|
|
71
|
+
}
|
|
72
|
+
if (val.startsWith("'") && val.endsWith("'")) {
|
|
73
|
+
return val.slice(1, -1).replace(/\\'/g, "'");
|
|
74
|
+
}
|
|
75
|
+
return val;
|
|
76
|
+
}
|
|
77
|
+
function coerceNestedScalar(raw) {
|
|
78
|
+
if (raw === "true") return true;
|
|
79
|
+
if (raw === "false") return false;
|
|
80
|
+
if (raw !== "" && !Number.isNaN(Number(raw))) return Number(raw);
|
|
81
|
+
return raw;
|
|
82
|
+
}
|
|
83
|
+
function readNestedSection(lines, key) {
|
|
84
|
+
const start = lines.findIndex((l) => new RegExp(`^${key}:\\s*$`).test(l));
|
|
85
|
+
if (start === -1) return void 0;
|
|
86
|
+
const result = {};
|
|
87
|
+
let subKey = null;
|
|
88
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
89
|
+
const line = lines[i];
|
|
90
|
+
if (/^\S/.test(line)) break;
|
|
91
|
+
const trimmed = line.trim();
|
|
92
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
93
|
+
const indent = line.length - line.trimStart().length;
|
|
94
|
+
const m = trimmed.match(/^([\w.-]+):\s*(.*)$/);
|
|
95
|
+
if (!m) continue;
|
|
96
|
+
const [, k, rawVal] = m;
|
|
97
|
+
if (indent === 2) {
|
|
98
|
+
if (rawVal === "") {
|
|
99
|
+
subKey = k;
|
|
100
|
+
result[k] = {};
|
|
101
|
+
} else {
|
|
102
|
+
subKey = null;
|
|
103
|
+
result[k] = coerceNestedScalar(rawVal);
|
|
104
|
+
}
|
|
105
|
+
} else if (indent >= 4 && subKey !== null) {
|
|
106
|
+
result[subKey][k] = coerceNestedScalar(rawVal);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
110
|
+
}
|
|
111
|
+
function parseEffortFile(raw) {
|
|
112
|
+
const blockMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
113
|
+
if (!blockMatch) return null;
|
|
114
|
+
const { meta, body } = parseFrontmatter(raw);
|
|
115
|
+
const innerLines = blockMatch[1].split(/\r?\n/);
|
|
116
|
+
const id = getScalar(meta, "id");
|
|
117
|
+
const slug = getScalar(meta, "slug");
|
|
118
|
+
const label = getScalar(meta, "label");
|
|
119
|
+
const aliases = getList(meta, "aliases");
|
|
120
|
+
const baseAttrs = readNestedSection(innerLines, "baseAttributes");
|
|
121
|
+
const hints = readNestedSection(innerLines, "hints");
|
|
122
|
+
const derivation = readNestedSection(innerLines, "derivation");
|
|
123
|
+
const metRaw = baseAttrs?.met;
|
|
124
|
+
const met = typeof metRaw === "number" ? metRaw : Number(metRaw);
|
|
125
|
+
if (!id || !slug || !label || metRaw === void 0 || Number.isNaN(met)) return null;
|
|
126
|
+
const discipline = parseDiscipline(
|
|
127
|
+
typeof baseAttrs?.discipline === "string" ? baseAttrs.discipline : void 0
|
|
128
|
+
);
|
|
129
|
+
const intensityTier = baseAttrs?.intensityTier;
|
|
130
|
+
const trimmedBody = body.trim();
|
|
131
|
+
return {
|
|
132
|
+
id: String(id),
|
|
133
|
+
slug: String(slug),
|
|
134
|
+
label: String(label),
|
|
135
|
+
aliases,
|
|
136
|
+
baseAttributes: {
|
|
137
|
+
met,
|
|
138
|
+
...discipline ? { discipline } : {},
|
|
139
|
+
...intensityTier ? { intensityTier } : {}
|
|
140
|
+
},
|
|
141
|
+
registrySource: "bundled",
|
|
142
|
+
...trimmedBody ? { body: trimmedBody } : {},
|
|
143
|
+
...hints ? { hints } : {},
|
|
144
|
+
...derivation ? { derivation } : {}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
var SEED_SCHEMA = 8;
|
|
148
|
+
var SEED_REGISTERED_WIDGETS = KNOWN_SECTION_WIDGETS;
|
|
149
|
+
var SEED_BROADCAST_CHANNEL = "wodwiki.seed";
|
|
150
|
+
var EFFORTS_CHUNK_ID = "efforts";
|
|
151
|
+
var CANVAS_CHUNK_ID = "canvas";
|
|
152
|
+
var DASHBOARDS_CHUNK_ID = "dashboards";
|
|
153
|
+
var TEMPLATE_CHUNK_ID = "template";
|
|
154
|
+
function seedMetaKey(sourceId) {
|
|
155
|
+
return `seed:${sourceId}`;
|
|
156
|
+
}
|
|
157
|
+
function emptySeedMeta(key) {
|
|
158
|
+
return { key, schema: SEED_SCHEMA, seedVersion: 0, builtAt: "", importedAt: 0, chunks: {}, claim: null };
|
|
159
|
+
}
|
|
160
|
+
function catalogForChunkId(chunkId) {
|
|
161
|
+
const value = /^(?:collection|feed)\.(.+)$/.exec(chunkId)?.[1];
|
|
162
|
+
return value && value !== "_root" ? value : void 0;
|
|
163
|
+
}
|
|
164
|
+
function canvasRouteSlug(content) {
|
|
165
|
+
const fm = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content);
|
|
166
|
+
if (fm?.[1] && !/^template:\s*canvas\s*$/m.test(fm[1])) return null;
|
|
167
|
+
return fm?.[1]?.match(/^route:\s*(\S+)\s*$/m)?.[1]?.replace(/^\//, "") || null;
|
|
168
|
+
}
|
|
169
|
+
function seedNoteSourceId(path, content, chunkId) {
|
|
170
|
+
const parts = path.split("/");
|
|
171
|
+
const stem = (parts.at(-1) ?? "").replace(/\.md$/i, "");
|
|
172
|
+
const under = parts.slice(2).map((p) => p.replace(/\.md$/i, "")).join("/");
|
|
173
|
+
if (chunkId === CANVAS_CHUNK_ID) return `guides:${canvasRouteSlug(content) ?? under}`;
|
|
174
|
+
if (chunkId === DASHBOARDS_CHUNK_ID) return "dashboards";
|
|
175
|
+
if (chunkId === EFFORTS_CHUNK_ID) return "efforts";
|
|
176
|
+
if (chunkId === TEMPLATE_CHUNK_ID) return "playground";
|
|
177
|
+
if (chunkId.startsWith("collection.")) {
|
|
178
|
+
const catalog = catalogForChunkId(chunkId);
|
|
179
|
+
return !catalog ? "collection:_root" : stem.toLowerCase() === "readme" ? `collection:${catalog}` : `collection:${catalog}/${stem}`;
|
|
180
|
+
}
|
|
181
|
+
if (chunkId.startsWith("feed.")) return `feed:feeds/${under}`;
|
|
182
|
+
return void 0;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export { CANVAS_CHUNK_ID, DASHBOARDS_CHUNK_ID, EFFORTS_CHUNK_ID, SEED_BROADCAST_CHANNEL, SEED_REGISTERED_WIDGETS, SEED_SCHEMA, TEMPLATE_CHUNK_ID, __require, canvasRouteSlug, catalogForChunkId, emptySeedMeta, parseEffortFile, parseFrontmatter, seedMetaKey, seedNoteSourceId };
|
|
186
|
+
//# sourceMappingURL=chunk-Y6WO6MXS.mjs.map
|
|
187
|
+
//# sourceMappingURL=chunk-Y6WO6MXS.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/seedbuild/frontmatter.ts","../src/cli/seedbuild/effort-file.ts","../src/cli/seedbuild/contract.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAiBA,IAAM,cAAA,GAAiB,mCAAA;AAIvB,SAAS,QAAQ,KAAA,EAAuB;AACtC,EAAA,OAAO,KAAA,CAAM,OAAA;AAAA,IAAQ,gBAAA;AAAA,IAAkB,CAAC,MAAA,EAAQ,KAAA,EAAe,KAAA,KAC7D,KAAA,KAAU,MAAM,KAAA,CAAM,OAAA,CAAQ,YAAA,EAAc,IAAI,CAAA,GAAI;AAAA,GACtD;AACF;AAaO,SAAS,iBAAiB,GAAA,EAAgC;AAC/D,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,cAAc,CAAA;AACtC,EAAA,IAAI,CAAC,OAAO,OAAO,EAAE,MAAM,EAAC,EAAG,MAAM,GAAA,EAAI;AACzC,EAAA,OAAO,EAAE,IAAA,EAAM,cAAA,CAAe,KAAA,CAAM,CAAC,EAAE,KAAA,CAAM,OAAO,CAAC,CAAA,EAAG,MAAM,GAAA,CAAI,KAAA,CAAM,MAAM,CAAC,CAAA,CAAE,MAAM,CAAA,EAAE;AAC3F;AAEA,SAAS,eAAe,KAAA,EAA4C;AAClE,EAAA,MAAM,OAAkC,EAAC;AAEzC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,QAAA,GAAW,KAAA,CAAM,CAAC,CAAA,CAAE,MAAM,6BAA6B,CAAA;AAC7D,IAAA,IAAI,CAAC,QAAA,EAAU;AAEf,IAAA,MAAM,GAAA,GAAM,SAAS,CAAC,CAAA;AACtB,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,CAAC,CAAA,CAAE,IAAA,EAAK;AAEhC,IAAA,IAAI,WAAW,EAAA,EAAI;AACjB,MAAA,MAAM,QAAkB,EAAC;AACzB,MAAA,OAAO,CAAA,GAAI,CAAA,GAAI,KAAA,CAAM,MAAA,EAAQ;AAC3B,QAAA,MAAM,YAAY,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA,CAAE,MAAM,eAAe,CAAA;AACpD,QAAA,IAAI,CAAC,SAAA,EAAW;AAChB,QAAA,KAAA,CAAM,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,CAAE,MAAM,CAAA;AAC9B,QAAA,CAAA,EAAA;AAAA,MACF;AACA,MAAA,IAAA,CAAK,GAAG,CAAA,GAAI,KAAA,CAAM,MAAA,GAAS,IAAI,KAAA,GAAQ,EAAA;AAAA,IACzC,CAAA,MAAO;AACL,MAAA,MAAM,SAAA,GAAY,gBAAA,CAAiB,IAAA,CAAK,MAAM,CAAA;AAC9C,MAAA,MAAM,KAAA,GAAQ,QAAQ,MAAM,CAAA;AAC5B,MAAA,MAAM,GAAA,GAAM,OAAO,KAAK,CAAA;AACxB,MAAA,IAAA,CAAK,GAAG,CAAA,GAAI,CAAC,SAAA,IAAa,KAAA,KAAU,MAAM,CAAC,KAAA,CAAM,GAAG,CAAA,GAAI,GAAA,GAAM,KAAA;AAAA,IAChE;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,SAAA,CACd,MACA,GAAA,EAC6B;AAC7B,EAAA,MAAM,KAAA,GAAQ,KAAK,GAAG,CAAA;AACtB,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,KAAA,KAAU,WAAW,KAAA,GAAQ,MAAA;AAC1E;AAGO,SAAS,OAAA,CAAQ,MAAiC,GAAA,EAAuB;AAC9E,EAAA,MAAM,KAAA,GAAQ,KAAK,GAAG,CAAA;AACtB,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,QAAQ,EAAC;AACzC;AChEA,SAAS,gBAAgB,GAAA,EAAkE;AACzF,EAAA,IAAI,CAAC,KAAK,OAAO,MAAA;AACjB,EAAA,MAAM,aAAa,WAAA,CAAY,GAAA,CAAI,IAAA,EAAM,EAAE,WAAA,EAAY;AACvD,EAAA,IAAI,kBAAA,CAAmB,UAAU,CAAA,EAAG,OAAO,UAAA;AAC3C,EAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,kCAAA,EAAqC,GAAG,CAAA,0BAAA,CAAuB,CAAA;AAC5E,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,YAAY,GAAA,EAAqB;AACxC,EAAA,IAAI,IAAI,UAAA,CAAW,GAAG,KAAK,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AAC5C,IAAA,OAAO,IAAI,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,CAAE,OAAA,CAAQ,cAAc,IAAI,CAAA;AAAA,EACpD;AACA,EAAA,IAAI,IAAI,UAAA,CAAW,GAAG,KAAK,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AAC5C,IAAA,OAAO,IAAI,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,CAAE,OAAA,CAAQ,QAAQ,GAAG,CAAA;AAAA,EAC7C;AACA,EAAA,OAAO,GAAA;AACT;AAGA,SAAS,mBAAmB,GAAA,EAAsB;AAChD,EAAA,IAAI,GAAA,KAAQ,QAAQ,OAAO,IAAA;AAC3B,EAAA,IAAI,GAAA,KAAQ,SAAS,OAAO,KAAA;AAC5B,EAAA,IAAI,GAAA,KAAQ,EAAA,IAAM,CAAC,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA,EAAG,OAAO,MAAA,CAAO,GAAG,CAAA;AAC/D,EAAA,OAAO,GAAA;AACT;AAMA,SAAS,iBAAA,CAAkB,OAAiB,GAAA,EAAkD;AAC5F,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,SAAA,CAAU,CAAA,CAAA,KAAK,IAAI,MAAA,CAAO,CAAA,CAAA,EAAI,GAAG,CAAA,MAAA,CAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAC,CAAA;AACtE,EAAA,IAAI,KAAA,KAAU,IAAI,OAAO,MAAA;AAEzB,EAAA,MAAM,SAAkC,EAAC;AACzC,EAAA,IAAI,MAAA,GAAwB,IAAA;AAE5B,EAAA,KAAA,IAAS,IAAI,KAAA,GAAQ,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AAC7C,IAAA,MAAM,IAAA,GAAO,MAAM,CAAC,CAAA;AACpB,IAAA,IAAI,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,EAAG;AAEtB,IAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,IAAA,IAAI,CAAC,OAAA,IAAW,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,EAAG;AAEzC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,GAAS,IAAA,CAAK,WAAU,CAAE,MAAA;AAC9C,IAAA,MAAM,CAAA,GAAI,OAAA,CAAQ,KAAA,CAAM,qBAAqB,CAAA;AAC7C,IAAA,IAAI,CAAC,CAAA,EAAG;AACR,IAAA,MAAM,GAAG,CAAA,EAAG,MAAM,CAAA,GAAI,CAAA;AAEtB,IAAA,IAAI,WAAW,CAAA,EAAG;AAChB,MAAA,IAAI,WAAW,EAAA,EAAI;AACjB,QAAA,MAAA,GAAS,CAAA;AACT,QAAA,MAAA,CAAO,CAAC,IAAI,EAAC;AAAA,MACf,CAAA,MAAO;AACL,QAAA,MAAA,GAAS,IAAA;AACT,QAAA,MAAA,CAAO,CAAC,CAAA,GAAI,kBAAA,CAAmB,MAAM,CAAA;AAAA,MACvC;AAAA,IACF,CAAA,MAAA,IAAW,MAAA,IAAU,CAAA,IAAK,MAAA,KAAW,IAAA,EAAM;AACzC,MAAC,OAAO,MAAM,CAAA,CAA8B,CAAC,CAAA,GAAI,mBAAmB,MAAM,CAAA;AAAA,IAC5E;AAAA,EACF;AAEA,EAAA,OAAO,OAAO,IAAA,CAAK,MAAM,CAAA,CAAE,MAAA,GAAS,IAAI,MAAA,GAAS,MAAA;AACnD;AAGO,SAAS,gBAAgB,GAAA,EAA6B;AAC3D,EAAA,MAAM,UAAA,GAAa,GAAA,CAAI,KAAA,CAAM,6BAA6B,CAAA;AAC1D,EAAA,IAAI,CAAC,YAAY,OAAO,IAAA;AAExB,EAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAK,GAAI,iBAAiB,GAAG,CAAA;AAC3C,EAAA,MAAM,UAAA,GAAa,UAAA,CAAW,CAAC,CAAA,CAAE,MAAM,OAAO,CAAA;AAE9C,EAAA,MAAM,EAAA,GAAK,SAAA,CAAU,IAAA,EAAM,IAAI,CAAA;AAC/B,EAAA,MAAM,IAAA,GAAO,SAAA,CAAU,IAAA,EAAM,MAAM,CAAA;AACnC,EAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,IAAA,EAAM,OAAO,CAAA;AACrC,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,IAAA,EAAM,SAAS,CAAA;AAEvC,EAAA,MAAM,SAAA,GAAY,iBAAA,CAAkB,UAAA,EAAY,gBAAgB,CAAA;AAChE,EAAA,MAAM,KAAA,GAAQ,iBAAA,CAAkB,UAAA,EAAY,OAAO,CAAA;AACnD,EAAA,MAAM,UAAA,GAAa,iBAAA,CAAkB,UAAA,EAAY,YAAY,CAAA;AAE7D,EAAA,MAAM,SAAS,SAAA,EAAW,GAAA;AAC1B,EAAA,MAAM,MAAM,OAAO,MAAA,KAAW,QAAA,GAAW,MAAA,GAAS,OAAO,MAAM,CAAA;AAC/D,EAAA,IAAI,CAAC,EAAA,IAAM,CAAC,IAAA,IAAQ,CAAC,KAAA,IAAS,MAAA,KAAW,MAAA,IAAa,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,EAAG,OAAO,IAAA;AAEhF,EAAA,MAAM,UAAA,GAAa,eAAA;AAAA,IACjB,OAAO,SAAA,EAAW,UAAA,KAAe,QAAA,GAAW,UAAU,UAAA,GAAa;AAAA,GACrE;AACA,EAAA,MAAM,gBAAgB,SAAA,EAAW,aAAA;AACjC,EAAA,MAAM,WAAA,GAAc,KAAK,IAAA,EAAK;AAE9B,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,OAAO,EAAE,CAAA;AAAA,IACb,IAAA,EAAM,OAAO,IAAI,CAAA;AAAA,IACjB,KAAA,EAAO,OAAO,KAAK,CAAA;AAAA,IACnB,OAAA;AAAA,IACA,cAAA,EAAgB;AAAA,MACd,GAAA;AAAA,MACA,GAAI,UAAA,GAAa,EAAE,UAAA,KAAe,EAAC;AAAA,MACnC,GAAI,aAAA,GAAgB,EAAE,aAAA,KAAkD;AAAC,KAC3E;AAAA,IACA,cAAA,EAAgB,SAAA;AAAA,IAChB,GAAI,WAAA,GAAc,EAAE,IAAA,EAAM,WAAA,KAAgB,EAAC;AAAA,IAC3C,GAAI,KAAA,GAAQ,EAAE,KAAA,KAAU,EAAC;AAAA,IACzB,GAAI,UAAA,GAAa,EAAE,UAAA,KAAoD;AAAC,GAC1E;AACF;AC/HO,IAAM,WAAA,GAAc;AACpB,IAAM,uBAAA,GAA0B;AAsChC,IAAM,sBAAA,GAAyB;AAC/B,IAAM,gBAAA,GAAmB;AACzB,IAAM,eAAA,GAAkB;AACxB,IAAM,mBAAA,GAAsB;AAC5B,IAAM,iBAAA,GAAoB;AAC1B,SAAS,YAAY,QAAA,EAA0B;AAAE,EAAA,OAAO,QAAQ,QAAQ,CAAA,CAAA;AAAI;AAC5E,SAAS,cAAc,GAAA,EAA6B;AACzD,EAAA,OAAO,EAAE,GAAA,EAAK,MAAA,EAAQ,WAAA,EAAa,aAAa,CAAA,EAAG,OAAA,EAAS,EAAA,EAAI,UAAA,EAAY,CAAA,EAAG,MAAA,EAAQ,EAAC,EAAG,OAAO,IAAA,EAAK;AACzG;AACO,SAAS,kBAAkB,OAAA,EAAqC;AACrE,EAAA,MAAM,KAAA,GAAQ,6BAAA,CAA8B,IAAA,CAAK,OAAO,IAAI,CAAC,CAAA;AAC7D,EAAA,OAAO,KAAA,IAAS,KAAA,KAAU,OAAA,GAAU,KAAA,GAAQ,MAAA;AAC9C;AACO,SAAS,gBAAgB,OAAA,EAAgC;AAC9D,EAAA,MAAM,EAAA,GAAK,6BAAA,CAA8B,IAAA,CAAK,OAAO,CAAA;AACrD,EAAA,IAAI,EAAA,GAAK,CAAC,CAAA,IAAK,CAAC,0BAAA,CAA2B,KAAK,EAAA,CAAG,CAAC,CAAC,CAAA,EAAG,OAAO,IAAA;AAC/D,EAAA,OAAO,EAAA,GAAK,CAAC,CAAA,EAAG,KAAA,CAAM,sBAAsB,CAAA,GAAI,CAAC,CAAA,EAAG,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,IAAK,IAAA;AAC5E;AACO,SAAS,gBAAA,CAAiB,IAAA,EAAc,OAAA,EAAiB,OAAA,EAAqC;AACnG,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC5B,EAAA,MAAM,IAAA,GAAA,CAAQ,MAAM,EAAA,CAAG,EAAE,KAAK,EAAA,EAAI,OAAA,CAAQ,UAAU,EAAE,CAAA;AACtD,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,CAAC,EAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,QAAA,EAAU,EAAE,CAAC,CAAA,CAAE,KAAK,GAAG,CAAA;AACzE,EAAA,IAAI,YAAY,eAAA,EAAiB,OAAO,UAAU,eAAA,CAAgB,OAAO,KAAK,KAAK,CAAA,CAAA;AACnF,EAAA,IAAI,OAAA,KAAY,qBAAqB,OAAO,YAAA;AAC5C,EAAA,IAAI,OAAA,KAAY,kBAAkB,OAAO,SAAA;AACzC,EAAA,IAAI,OAAA,KAAY,mBAAmB,OAAO,YAAA;AAC1C,EAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,aAAa,CAAA,EAAG;AACrC,IAAA,MAAM,OAAA,GAAU,kBAAkB,OAAO,CAAA;AACzC,IAAA,OAAO,CAAC,OAAA,GAAU,kBAAA,GAAqB,IAAA,CAAK,WAAA,EAAY,KAAM,QAAA,GAAW,CAAA,WAAA,EAAc,OAAO,CAAA,CAAA,GAAK,CAAA,WAAA,EAAc,OAAO,IAAI,IAAI,CAAA,CAAA;AAAA,EAClI;AACA,EAAA,IAAI,QAAQ,UAAA,CAAW,OAAO,CAAA,EAAG,OAAO,cAAc,KAAK,CAAA,CAAA;AAC3D,EAAA,OAAO,MAAA;AACT","file":"chunk-Y6WO6MXS.mjs","sourcesContent":["/**\n * Frontmatter parser — port of wod-wiki's apps/playground/src/lib/frontmatter.ts\n * (parseFrontmatter/getScalar/getList only; the editor-only helpers\n * (LinkWidget, YouTube, serialize) stay in the app).\n *\n * ponytail: semantics must match the app's parser exactly — the seed\n * compiler and the app runtime derive frontmatter from the same corpus.\n * Upgrade path: publish the parser in @bitcobblers/wod-wiki-core and import\n * from both sides.\n */\n\nexport interface ParsedFrontmatter {\n meta: Record<string, string | number | string[]>\n body: string\n}\n\n/** Leading `---` … `---` block; body is everything after the closing delimiter. */\nconst FRONTMATTER_RE = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/;\n\n/** Strip matched wrapping quotes: `\"x\"` / `'x'` → `x`; mismatched quotes are kept.\n * Double-quoted values also collapse the serializer's escapes (`\\\\\"`, `\\\\\\\\`). */\nfunction unquote(value: string): string {\n return value.replace(/^(['\"])(.*)\\1$/, (_match, quote: string, inner: string) =>\n quote === '\"' ? inner.replace(/\\\\([\"\\\\])/g, '$1') : inner,\n );\n}\n\n/**\n * Parse the leading YAML frontmatter block of a markdown string.\n *\n * Semantics (mirrors the app):\n * - Scalar `key: value` (key `/^[A-Za-z][\\w.-]*$/`, dots allow flat nested\n * keys like `book.title`): wrapping quotes stripped; bare numeric strings\n * become `number`, quoted scalars always stay strings.\n * - `key:` with empty value followed by indented `- item` lines → `string[]`.\n * - `key:` with empty value and no list items → `''`.\n * - Inline `key: [a, b]` stays a plain scalar string.\n */\nexport function parseFrontmatter(raw: string): ParsedFrontmatter {\n const match = raw.match(FRONTMATTER_RE);\n if (!match) return { meta: {}, body: raw };\n return { meta: parseMetaLines(match[1].split(/\\r?\\n/)), body: raw.slice(match[0].length) };\n}\n\nfunction parseMetaLines(lines: string[]): ParsedFrontmatter['meta'] {\n const meta: ParsedFrontmatter['meta'] = {};\n\n for (let i = 0; i < lines.length; i++) {\n const keyMatch = lines[i].match(/^([A-Za-z][\\w.-]*)\\s*:(.*)$/);\n if (!keyMatch) continue; // indented/nested/list lines are not top-level keys\n\n const key = keyMatch[1];\n const rawVal = keyMatch[2].trim();\n\n if (rawVal === '') {\n const items: string[] = [];\n while (i + 1 < lines.length) {\n const itemMatch = lines[i + 1].match(/^\\s+-\\s+(.+)$/);\n if (!itemMatch) break;\n items.push(itemMatch[1].trim());\n i++;\n }\n meta[key] = items.length > 0 ? items : '';\n } else {\n const wasQuoted = /^(['\"])(.*)\\1$/.test(rawVal);\n const value = unquote(rawVal);\n const num = Number(value);\n meta[key] = !wasQuoted && value !== '' && !isNaN(num) ? num : value;\n }\n }\n\n return meta;\n}\n\n/** Scalar value at `key`, or `undefined` when absent or a list. */\nexport function getScalar(\n meta: ParsedFrontmatter['meta'],\n key: string,\n): string | number | undefined {\n const value = meta[key];\n return typeof value === 'string' || typeof value === 'number' ? value : undefined;\n}\n\n/** List value at `key`, or `[]` when absent or a scalar. */\nexport function getList(meta: ParsedFrontmatter['meta'], key: string): string[] {\n const value = meta[key];\n return Array.isArray(value) ? value : [];\n}\n","/**\n * Effort-file parsing — port of wod-wiki's\n * apps/playground/src/repositories/effort-markdown.ts (parse-frontmatter\n * direction only; effortToDocument/documentToEffort stay in the app).\n *\n * The compiler needs `parseEffortFile` to build the effort alias map used by\n * block-efforts row derivation. Semantics MUST match the app's runtime effort\n * materialization — alias/slug drift would desync the block plane from the\n * note plane.\n *\n * ponytail: duplicated rather than package-shared to keep this repo\n * standalone; upgrade path is the same published effort-format module\n * imported by both sides.\n */\nimport {\n isEffortDiscipline,\n type IEffort,\n type EffortRegistrySource,\n type IntensityTier,\n} from '@bitcobblers/wod-wiki-lang';\nimport { parseFrontmatter, getScalar, getList } from './frontmatter';\n\n/** Validate a parsed discipline against the canonical vocabulary. */\nfunction parseDiscipline(val: string | undefined): IEffort['baseAttributes']['discipline'] {\n if (!val) return undefined;\n const normalized = unquoteYaml(val.trim()).toLowerCase();\n if (isEffortDiscipline(normalized)) return normalized as IEffort['baseAttributes']['discipline'];\n console.warn(`[effort-file] unknown discipline '${val}' — treating as unset`);\n return undefined;\n}\n\nfunction unquoteYaml(val: string): string {\n if (val.startsWith('\"') && val.endsWith('\"')) {\n return val.slice(1, -1).replace(/\\\\([\"\\\\])/g, '$1');\n }\n if (val.startsWith(\"'\") && val.endsWith(\"'\")) {\n return val.slice(1, -1).replace(/\\\\'/g, \"'\");\n }\n return val;\n}\n\n/** Coerce a scalar from a nested block: booleans/numbers are coerced; everything else stays a string. */\nfunction coerceNestedScalar(raw: string): unknown {\n if (raw === 'true') return true;\n if (raw === 'false') return false;\n if (raw !== '' && !Number.isNaN(Number(raw))) return Number(raw);\n return raw;\n}\n\n/**\n * Read a nested (`key:` followed by indented entries) section from frontmatter\n * lines. Two levels are supported (`derivation.coefficients.*`).\n */\nfunction readNestedSection(lines: string[], key: string): Record<string, unknown> | undefined {\n const start = lines.findIndex(l => new RegExp(`^${key}:\\\\s*$`).test(l));\n if (start === -1) return undefined;\n\n const result: Record<string, unknown> = {};\n let subKey: string | null = null;\n\n for (let i = start + 1; i < lines.length; i++) {\n const line = lines[i];\n if (/^\\S/.test(line)) break; // next top-level key ends the block\n\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n\n const indent = line.length - line.trimStart().length;\n const m = trimmed.match(/^([\\w.-]+):\\s*(.*)$/);\n if (!m) continue;\n const [, k, rawVal] = m;\n\n if (indent === 2) {\n if (rawVal === '') {\n subKey = k;\n result[k] = {};\n } else {\n subKey = null;\n result[k] = coerceNestedScalar(rawVal);\n }\n } else if (indent >= 4 && subKey !== null) {\n (result[subKey] as Record<string, unknown>)[k] = coerceNestedScalar(rawVal);\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\n/** Parse a single bundled effort markdown file into an IEffort (null when malformed). */\nexport function parseEffortFile(raw: string): IEffort | null {\n const blockMatch = raw.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---/);\n if (!blockMatch) return null;\n\n const { meta, body } = parseFrontmatter(raw);\n const innerLines = blockMatch[1].split(/\\r?\\n/);\n\n const id = getScalar(meta, 'id');\n const slug = getScalar(meta, 'slug');\n const label = getScalar(meta, 'label');\n const aliases = getList(meta, 'aliases');\n\n const baseAttrs = readNestedSection(innerLines, 'baseAttributes');\n const hints = readNestedSection(innerLines, 'hints');\n const derivation = readNestedSection(innerLines, 'derivation');\n\n const metRaw = baseAttrs?.met;\n const met = typeof metRaw === 'number' ? metRaw : Number(metRaw);\n if (!id || !slug || !label || metRaw === undefined || Number.isNaN(met)) return null;\n\n const discipline = parseDiscipline(\n typeof baseAttrs?.discipline === 'string' ? baseAttrs.discipline : undefined,\n );\n const intensityTier = baseAttrs?.intensityTier;\n const trimmedBody = body.trim();\n\n return {\n id: String(id),\n slug: String(slug),\n label: String(label),\n aliases,\n baseAttributes: {\n met,\n ...(discipline ? { discipline } : {}),\n ...(intensityTier ? { intensityTier: intensityTier as IntensityTier } : {}),\n },\n registrySource: 'bundled' as EffortRegistrySource,\n ...(trimmedBody ? { body: trimmedBody } : {}),\n ...(hints ? { hints } : {}),\n ...(derivation ? { derivation: derivation as IEffort['derivation'] } : {}),\n };\n}\n","import type { BlockEffort, BlockIndexRow, NoteBlock } from '@bitcobblers/wod-wiki-core';\nimport { KNOWN_SECTION_WIDGETS } from '@bitcobblers/wod-wiki-core';\n\nexport const SEED_SCHEMA = 8;\nexport const SEED_REGISTERED_WIDGETS = KNOWN_SECTION_WIDGETS;\n\n/** Source and all current derived rows commit as one chunk. */\nexport interface SeedRow {\n path: string;\n content: string;\n blocks: Record<string, NoteBlock>;\n blockIndex: BlockIndexRow[];\n blockEfforts: BlockEffort[];\n}\n\nexport type ChunkKind = 'notes';\nexport interface ManifestChunk {\n id: string;\n path: string;\n sha256: string;\n bytes: number;\n count: number;\n kind?: ChunkKind;\n}\nexport interface SeedManifest {\n schema: number;\n version: number;\n versionLabel?: string;\n commit?: string;\n dirty?: boolean;\n builtAt: string;\n chunks: ManifestChunk[];\n}\nexport interface SeedMetaRecord {\n key: string;\n schema: number;\n seedVersion: number;\n builtAt: string;\n importedAt: number;\n chunks: Record<string, { sha256: string; noteIds?: string[] }>;\n claim?: { owner: string; at: number } | null;\n}\nexport const SEED_BROADCAST_CHANNEL = 'wodwiki.seed';\nexport const EFFORTS_CHUNK_ID = 'efforts';\nexport const CANVAS_CHUNK_ID = 'canvas';\nexport const DASHBOARDS_CHUNK_ID = 'dashboards';\nexport const TEMPLATE_CHUNK_ID = 'template';\nexport function seedMetaKey(sourceId: string): string { return `seed:${sourceId}`; }\nexport function emptySeedMeta(key: string): SeedMetaRecord {\n return { key, schema: SEED_SCHEMA, seedVersion: 0, builtAt: '', importedAt: 0, chunks: {}, claim: null };\n}\nexport function catalogForChunkId(chunkId: string): string | undefined {\n const value = /^(?:collection|feed)\\.(.+)$/.exec(chunkId)?.[1];\n return value && value !== '_root' ? value : undefined;\n}\nexport function canvasRouteSlug(content: string): string | null {\n const fm = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/.exec(content);\n if (fm?.[1] && !/^template:\\s*canvas\\s*$/m.test(fm[1])) return null;\n return fm?.[1]?.match(/^route:\\s*(\\S+)\\s*$/m)?.[1]?.replace(/^\\//, '') || null;\n}\nexport function seedNoteSourceId(path: string, content: string, chunkId: string): string | undefined {\n const parts = path.split('/');\n const stem = (parts.at(-1) ?? '').replace(/\\.md$/i, '');\n const under = parts.slice(2).map((p) => p.replace(/\\.md$/i, '')).join('/');\n if (chunkId === CANVAS_CHUNK_ID) return `guides:${canvasRouteSlug(content) ?? under}`;\n if (chunkId === DASHBOARDS_CHUNK_ID) return 'dashboards';\n if (chunkId === EFFORTS_CHUNK_ID) return 'efforts';\n if (chunkId === TEMPLATE_CHUNK_ID) return 'playground';\n if (chunkId.startsWith('collection.')) {\n const catalog = catalogForChunkId(chunkId);\n return !catalog ? 'collection:_root' : stem.toLowerCase() === 'readme' ? `collection:${catalog}` : `collection:${catalog}/${stem}`;\n }\n if (chunkId.startsWith('feed.')) return `feed:feeds/${under}`;\n return undefined;\n}\n"]}
|