@bitcobblers/wod-wiki-tools 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/bin/wod.cjs +522 -246
- package/dist/bin/wod.cjs.map +1 -1
- package/dist/bin/wod.mjs +4 -3
- package/dist/bin/wod.mjs.map +1 -1
- package/dist/{chunk-FZKXOYMJ.mjs → chunk-CVFMFD7D.mjs} +153 -188
- package/dist/chunk-CVFMFD7D.mjs.map +1 -0
- package/dist/{chunk-6QNX4FED.mjs → chunk-HRFOKCYI.mjs} +139 -47
- package/dist/chunk-HRFOKCYI.mjs.map +1 -0
- package/dist/{chunk-CYKNTEGY.mjs → chunk-IWT7U3WX.mjs} +8 -3
- package/dist/chunk-IWT7U3WX.mjs.map +1 -0
- package/dist/chunk-JUBKCRNV.mjs +12 -0
- package/dist/chunk-JUBKCRNV.mjs.map +1 -0
- package/dist/{chunk-MA6BBTWC.mjs → chunk-RWNL6APX.mjs} +3 -3
- package/dist/{chunk-MA6BBTWC.mjs.map → chunk-RWNL6APX.mjs.map} +1 -1
- package/dist/compiler-OXEXGIZG.mjs +9 -0
- package/dist/{compiler-CTPLIZJK.mjs.map → compiler-OXEXGIZG.mjs.map} +1 -1
- package/dist/index.cjs +522 -246
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +5 -4
- package/dist/scaffoldCatalog-OIU4FEKJ.mjs +205 -0
- package/dist/scaffoldCatalog-OIU4FEKJ.mjs.map +1 -0
- package/dist/{server-JXECWS4A.mjs → server-2DVBA35J.mjs} +4 -4
- package/dist/{server-JXECWS4A.mjs.map → server-2DVBA35J.mjs.map} +1 -1
- package/dist/web/playground/assets/main-2qCz3_0z.js +194 -0
- package/dist/web/playground/assets/main-BUcjhK2w.css +2 -0
- package/dist/web/playground/assets/{statementBuilderFlow-ugwi0fu0.js → statementBuilderFlow-DKhL-YLz.js} +2 -2
- package/dist/web/playground/assets/{vendor-g-NJOjvC.js → vendor-DaJxNU_W.js} +3 -3
- package/dist/web/playground/assets/{vendor-codemirror-C41SFn-r.js → vendor-codemirror-BtDM22HA.js} +2 -2
- package/dist/web/playground/index.html +4 -4
- package/dist/web/playground/seed/core/chunks/canvas.a45c409e.json +1 -0
- package/dist/web/playground/seed/core/chunks/efforts.e68f2093.json +1 -0
- package/dist/web/playground/seed/core/chunks/equipment.c4fb1d64.json +1 -0
- package/dist/web/playground/seed/core/chunks/{template.e5e0e82d.json → template.0120276c.json} +1 -1
- package/dist/web/playground/seed/core/manifest.json +27 -10
- package/dist/web/playground/seed/core/report.html +15 -13
- package/dist/web/server/assets/main-BUcjhK2w.css +2 -0
- package/dist/web/server/assets/main-DxsZ-yOz.js +193 -0
- package/dist/web/server/assets/{statementBuilderFlow-40WaYjdq.js → statementBuilderFlow-CI5vrd60.js} +2 -2
- package/dist/web/server/assets/{vendor-g-NJOjvC.js → vendor-DaJxNU_W.js} +3 -3
- package/dist/web/server/assets/{vendor-codemirror-C41SFn-r.js → vendor-codemirror-BtDM22HA.js} +2 -2
- package/dist/web/server/index.html +4 -4
- package/dist/web/server/seed/core/chunks/canvas.a45c409e.json +1 -0
- package/dist/web/server/seed/core/chunks/efforts.e68f2093.json +1 -0
- package/dist/web/server/seed/core/chunks/equipment.c4fb1d64.json +1 -0
- package/dist/web/server/seed/core/chunks/{template.e5e0e82d.json → template.0120276c.json} +1 -1
- package/dist/web/server/seed/core/manifest.json +27 -10
- package/dist/web/server/seed/core/report.html +15 -13
- package/package.json +6 -6
- package/dist/chunk-6QNX4FED.mjs.map +0 -1
- package/dist/chunk-CYKNTEGY.mjs.map +0 -1
- package/dist/chunk-FZKXOYMJ.mjs.map +0 -1
- package/dist/compiler-CTPLIZJK.mjs +0 -9
- package/dist/web/playground/assets/main-B-bffxwE.css +0 -2
- package/dist/web/playground/assets/main-iLSeEl2E.js +0 -188
- package/dist/web/playground/seed/core/chunks/canvas.20048125.json +0 -1
- package/dist/web/server/assets/main-B-bffxwE.css +0 -2
- package/dist/web/server/assets/main-CRyLxlPN.js +0 -187
- package/dist/web/server/seed/core/chunks/canvas.20048125.json +0 -1
package/dist/bin/wod.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'module';
|
|
3
|
-
import { cliMain } from '../chunk-
|
|
4
|
-
import '../chunk-
|
|
5
|
-
import '../chunk-
|
|
3
|
+
import { cliMain } from '../chunk-HRFOKCYI.mjs';
|
|
4
|
+
import '../chunk-CVFMFD7D.mjs';
|
|
5
|
+
import '../chunk-JUBKCRNV.mjs';
|
|
6
|
+
import '../chunk-IWT7U3WX.mjs';
|
|
6
7
|
import '../chunk-6L5ZDZJ7.mjs';
|
|
7
8
|
|
|
8
9
|
if (typeof globalThis.require === 'undefined') {
|
package/dist/bin/wod.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/bin/wod.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/bin/wod.ts"],"names":[],"mappings":";;;;;;;;;;;;;AASA,KAAA,CAAM,YAAY;AAChB,EAAA,MAAM,WAAW,MAAM,OAAA,CAAQ,QAAQ,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA;AACpD,EAAA,OAAA,CAAQ,QAAA,GAAW,QAAA;AACrB,CAAA,GAAG","file":"wod.mjs","sourcesContent":["#!/usr/bin/env node\n/**\n * wod CLI Entry Point\n *\n * Dispatches to cliMain(process.argv.slice(2)).\n * Runs under Node (v18+) or Bun across all subcommands, including server and playground.\n */\nimport { cliMain } from '../cli/runner';\n\nvoid (async () => {\n const exitCode = await cliMain(process.argv.slice(2));\n process.exitCode = exitCode;\n})();\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire } from 'module';
|
|
2
|
-
import { parseScript, whiteboardParser,
|
|
2
|
+
import { parseScript, whiteboardParser, parseEffortFile, parseEquipmentFile, createReferenceIndex, slugifyRefLabel, extractStatementRefs } from '@bitcobblers/wod-wiki-lang';
|
|
3
3
|
import { reconcileNoteBlocks, KNOWN_SECTION_WIDGETS, parseDocumentSections, blockContentId } from '@bitcobblers/wod-wiki-core';
|
|
4
4
|
import { parseDashboardNote, buildDashboardDocument, isDashboardWidgetType, resolveWidgetType, parseQuery } from '@bitcobblers/wod-wiki-wql';
|
|
5
5
|
import { execSync } from 'child_process';
|
|
@@ -10,9 +10,10 @@ import { createHash } from 'crypto';
|
|
|
10
10
|
if (typeof globalThis.require === 'undefined') {
|
|
11
11
|
try { globalThis.require = createRequire(import.meta.url); } catch {}
|
|
12
12
|
}
|
|
13
|
-
var SEED_SCHEMA =
|
|
13
|
+
var SEED_SCHEMA = 9;
|
|
14
14
|
var SEED_REGISTERED_WIDGETS = KNOWN_SECTION_WIDGETS;
|
|
15
15
|
var EFFORTS_CHUNK_ID = "efforts";
|
|
16
|
+
var EQUIPMENT_CHUNK_ID = "equipment";
|
|
16
17
|
var CANVAS_CHUNK_ID = "canvas";
|
|
17
18
|
var DASHBOARDS_CHUNK_ID = "dashboards";
|
|
18
19
|
var TEMPLATE_CHUNK_ID = "template";
|
|
@@ -32,6 +33,7 @@ function seedNoteSourceId(path, content, chunkId) {
|
|
|
32
33
|
if (chunkId === CANVAS_CHUNK_ID) return `guides:${canvasRouteSlug(content) ?? under}`;
|
|
33
34
|
if (chunkId === DASHBOARDS_CHUNK_ID) return "dashboards";
|
|
34
35
|
if (chunkId === EFFORTS_CHUNK_ID) return "efforts";
|
|
36
|
+
if (chunkId === EQUIPMENT_CHUNK_ID) return "equipment";
|
|
35
37
|
if (chunkId === TEMPLATE_CHUNK_ID) return "playground";
|
|
36
38
|
if (chunkId.startsWith("collection.")) {
|
|
37
39
|
const catalog = catalogForChunkId(chunkId);
|
|
@@ -41,24 +43,6 @@ function seedNoteSourceId(path, content, chunkId) {
|
|
|
41
43
|
return void 0;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
// src/seedbuild/effort-slugs.ts
|
|
45
|
-
function extractEffortSlugs(statements) {
|
|
46
|
-
const slugs = /* @__PURE__ */ new Set();
|
|
47
|
-
for (const statement of statements) {
|
|
48
|
-
if (statement.exerciseId) {
|
|
49
|
-
slugs.add(statement.exerciseId);
|
|
50
|
-
} else {
|
|
51
|
-
const effortMetric = statement.metrics?.getMetric?.("effort");
|
|
52
|
-
const effort = effortMetric && typeof effortMetric.value === "string" ? effortMetric.value : void 0;
|
|
53
|
-
if (effort) {
|
|
54
|
-
const slug = effort.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
55
|
-
if (slug) slugs.add(slug);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return Array.from(slugs);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
46
|
// src/seedbuild/filename.ts
|
|
63
47
|
var FILE_TITLE_STOP_WORDS = {
|
|
64
48
|
and: true,
|
|
@@ -99,141 +83,6 @@ function fileToDisplayName(filename) {
|
|
|
99
83
|
}
|
|
100
84
|
return titled.join(" ");
|
|
101
85
|
}
|
|
102
|
-
|
|
103
|
-
// src/seedbuild/frontmatter.ts
|
|
104
|
-
var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
105
|
-
function unquote(value) {
|
|
106
|
-
return value.replace(
|
|
107
|
-
/^(['"])(.*)\1$/,
|
|
108
|
-
(_match, quote, inner) => quote === '"' ? inner.replace(/\\(["\\])/g, "$1") : inner
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
function parseFrontmatter(raw) {
|
|
112
|
-
const match = raw.match(FRONTMATTER_RE);
|
|
113
|
-
if (!match) return { meta: {}, body: raw };
|
|
114
|
-
return { meta: parseMetaLines(match[1].split(/\r?\n/)), body: raw.slice(match[0].length) };
|
|
115
|
-
}
|
|
116
|
-
function parseMetaLines(lines) {
|
|
117
|
-
const meta = {};
|
|
118
|
-
for (let i = 0; i < lines.length; i++) {
|
|
119
|
-
const keyMatch = lines[i].match(/^([A-Za-z][\w.-]*)\s*:(.*)$/);
|
|
120
|
-
if (!keyMatch) continue;
|
|
121
|
-
const key = keyMatch[1];
|
|
122
|
-
const rawVal = keyMatch[2].trim();
|
|
123
|
-
if (rawVal === "") {
|
|
124
|
-
const items = [];
|
|
125
|
-
while (i + 1 < lines.length) {
|
|
126
|
-
const itemMatch = lines[i + 1].match(/^\s+-\s+(.+)$/);
|
|
127
|
-
if (!itemMatch) break;
|
|
128
|
-
items.push(itemMatch[1].trim());
|
|
129
|
-
i++;
|
|
130
|
-
}
|
|
131
|
-
meta[key] = items.length > 0 ? items : "";
|
|
132
|
-
} else {
|
|
133
|
-
const wasQuoted = /^(['"])(.*)\1$/.test(rawVal);
|
|
134
|
-
const value = unquote(rawVal);
|
|
135
|
-
const num = Number(value);
|
|
136
|
-
meta[key] = !wasQuoted && value !== "" && !isNaN(num) ? num : value;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return meta;
|
|
140
|
-
}
|
|
141
|
-
function getScalar(meta, key) {
|
|
142
|
-
const value = meta[key];
|
|
143
|
-
return typeof value === "string" || typeof value === "number" ? value : void 0;
|
|
144
|
-
}
|
|
145
|
-
function getList(meta, key) {
|
|
146
|
-
const value = meta[key];
|
|
147
|
-
return Array.isArray(value) ? value : [];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// src/seedbuild/effort-file.ts
|
|
151
|
-
function parseDiscipline(val) {
|
|
152
|
-
if (!val) return void 0;
|
|
153
|
-
const normalized = unquoteYaml(val.trim()).toLowerCase();
|
|
154
|
-
if (isEffortDiscipline(normalized)) return normalized;
|
|
155
|
-
console.warn(`[effort-file] unknown discipline '${val}' \u2014 treating as unset`);
|
|
156
|
-
return void 0;
|
|
157
|
-
}
|
|
158
|
-
function unquoteYaml(val) {
|
|
159
|
-
if (val.startsWith('"') && val.endsWith('"')) {
|
|
160
|
-
return val.slice(1, -1).replace(/\\(["\\])/g, "$1");
|
|
161
|
-
}
|
|
162
|
-
if (val.startsWith("'") && val.endsWith("'")) {
|
|
163
|
-
return val.slice(1, -1).replace(/\\'/g, "'");
|
|
164
|
-
}
|
|
165
|
-
return val;
|
|
166
|
-
}
|
|
167
|
-
function coerceNestedScalar(raw) {
|
|
168
|
-
if (raw === "true") return true;
|
|
169
|
-
if (raw === "false") return false;
|
|
170
|
-
if (raw !== "" && !Number.isNaN(Number(raw))) return Number(raw);
|
|
171
|
-
return raw;
|
|
172
|
-
}
|
|
173
|
-
function readNestedSection(lines, key) {
|
|
174
|
-
const start = lines.findIndex((l) => new RegExp(`^${key}:\\s*$`).test(l));
|
|
175
|
-
if (start === -1) return void 0;
|
|
176
|
-
const result = {};
|
|
177
|
-
let subKey = null;
|
|
178
|
-
for (let i = start + 1; i < lines.length; i++) {
|
|
179
|
-
const line = lines[i];
|
|
180
|
-
if (/^\S/.test(line)) break;
|
|
181
|
-
const trimmed = line.trim();
|
|
182
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
183
|
-
const indent = line.length - line.trimStart().length;
|
|
184
|
-
const m = trimmed.match(/^([\w.-]+):\s*(.*)$/);
|
|
185
|
-
if (!m) continue;
|
|
186
|
-
const [, k, rawVal] = m;
|
|
187
|
-
if (indent === 2) {
|
|
188
|
-
if (rawVal === "") {
|
|
189
|
-
subKey = k;
|
|
190
|
-
result[k] = {};
|
|
191
|
-
} else {
|
|
192
|
-
subKey = null;
|
|
193
|
-
result[k] = coerceNestedScalar(rawVal);
|
|
194
|
-
}
|
|
195
|
-
} else if (indent >= 4 && subKey !== null) {
|
|
196
|
-
result[subKey][k] = coerceNestedScalar(rawVal);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
return Object.keys(result).length > 0 ? result : void 0;
|
|
200
|
-
}
|
|
201
|
-
function parseEffortFile(raw) {
|
|
202
|
-
const blockMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
203
|
-
if (!blockMatch) return null;
|
|
204
|
-
const { meta, body } = parseFrontmatter(raw);
|
|
205
|
-
const innerLines = blockMatch[1].split(/\r?\n/);
|
|
206
|
-
const id = getScalar(meta, "id");
|
|
207
|
-
const slug = getScalar(meta, "slug");
|
|
208
|
-
const label = getScalar(meta, "label");
|
|
209
|
-
const aliases = getList(meta, "aliases");
|
|
210
|
-
const baseAttrs = readNestedSection(innerLines, "baseAttributes");
|
|
211
|
-
const hints = readNestedSection(innerLines, "hints");
|
|
212
|
-
const derivation = readNestedSection(innerLines, "derivation");
|
|
213
|
-
const metRaw = baseAttrs?.met;
|
|
214
|
-
const met = typeof metRaw === "number" ? metRaw : Number(metRaw);
|
|
215
|
-
if (!id || !slug || !label || metRaw === void 0 || Number.isNaN(met)) return null;
|
|
216
|
-
const discipline = parseDiscipline(
|
|
217
|
-
typeof baseAttrs?.discipline === "string" ? baseAttrs.discipline : void 0
|
|
218
|
-
);
|
|
219
|
-
const intensityTier = baseAttrs?.intensityTier;
|
|
220
|
-
const trimmedBody = body.trim();
|
|
221
|
-
return {
|
|
222
|
-
id: String(id),
|
|
223
|
-
slug: String(slug),
|
|
224
|
-
label: String(label),
|
|
225
|
-
aliases,
|
|
226
|
-
baseAttributes: {
|
|
227
|
-
met,
|
|
228
|
-
...discipline ? { discipline } : {},
|
|
229
|
-
...intensityTier ? { intensityTier } : {}
|
|
230
|
-
},
|
|
231
|
-
registrySource: "bundled",
|
|
232
|
-
...trimmedBody ? { body: trimmedBody } : {},
|
|
233
|
-
...hints ? { hints } : {},
|
|
234
|
-
...derivation ? { derivation } : {}
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
86
|
var UNKNOWN_GIT_VERSION = {
|
|
238
87
|
version: 0,
|
|
239
88
|
versionLabel: "unknown",
|
|
@@ -312,6 +161,69 @@ ${manifest.chunks.map(rowHtml).join("\n")}
|
|
|
312
161
|
writeFileSync(file, html, "utf8");
|
|
313
162
|
return file;
|
|
314
163
|
}
|
|
164
|
+
|
|
165
|
+
// src/seedbuild/frontmatter.ts
|
|
166
|
+
var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
167
|
+
function unquote(value) {
|
|
168
|
+
return value.replace(
|
|
169
|
+
/^(['"])(.*)\1$/,
|
|
170
|
+
(_match, quote, inner) => quote === '"' ? inner.replace(/\\(["\\])/g, "$1") : inner
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
function parseFrontmatter(raw) {
|
|
174
|
+
const match = raw.match(FRONTMATTER_RE);
|
|
175
|
+
if (!match) return { meta: {}, body: raw };
|
|
176
|
+
return { meta: parseMetaLines(match[1].split(/\r?\n/)), body: raw.slice(match[0].length) };
|
|
177
|
+
}
|
|
178
|
+
function parseMetaLines(lines) {
|
|
179
|
+
const meta = {};
|
|
180
|
+
for (let i = 0; i < lines.length; i++) {
|
|
181
|
+
const keyMatch = lines[i].match(/^([A-Za-z][\w.-]*)\s*:(.*)$/);
|
|
182
|
+
if (!keyMatch) continue;
|
|
183
|
+
const key = keyMatch[1];
|
|
184
|
+
const rawVal = keyMatch[2].trim();
|
|
185
|
+
if (rawVal === "") {
|
|
186
|
+
const items = [];
|
|
187
|
+
while (i + 1 < lines.length) {
|
|
188
|
+
const itemMatch = lines[i + 1].match(/^\s+-\s+(.+)$/);
|
|
189
|
+
if (!itemMatch) break;
|
|
190
|
+
items.push(itemMatch[1].trim());
|
|
191
|
+
i++;
|
|
192
|
+
}
|
|
193
|
+
meta[key] = items.length > 0 ? items : "";
|
|
194
|
+
} else {
|
|
195
|
+
const wasQuoted = /^(['"])(.*)\1$/.test(rawVal);
|
|
196
|
+
const value = unquote(rawVal);
|
|
197
|
+
const num = Number(value);
|
|
198
|
+
meta[key] = !wasQuoted && value !== "" && !isNaN(num) ? num : value;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return meta;
|
|
202
|
+
}
|
|
203
|
+
function getScalar(meta, key) {
|
|
204
|
+
const value = meta[key];
|
|
205
|
+
return typeof value === "string" || typeof value === "number" ? value : void 0;
|
|
206
|
+
}
|
|
207
|
+
function object(value) {
|
|
208
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
209
|
+
}
|
|
210
|
+
function nonnegative(value) {
|
|
211
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
212
|
+
}
|
|
213
|
+
function assertSeedManifest(value) {
|
|
214
|
+
if (!object(value) || value.schema !== SEED_SCHEMA) throw new Error("Incompatible seed schema; rebuild seed artifacts");
|
|
215
|
+
if (!nonnegative(value.version) || typeof value.builtAt !== "string" || !Number.isFinite(Date.parse(value.builtAt)) || !Array.isArray(value.chunks)) throw new Error("seed manifest failed shape validation");
|
|
216
|
+
for (const key of ["versionLabel", "commit", "name", "description"]) if (value[key] !== void 0 && typeof value[key] !== "string") throw new Error("invalid seed manifest metadata");
|
|
217
|
+
if (value.repositoryUrl !== void 0 && (typeof value.repositoryUrl !== "string" || !/^https:\/\//.test(value.repositoryUrl) || new URL(value.repositoryUrl).username || new URL(value.repositoryUrl).password)) throw new Error("invalid seed repository URL");
|
|
218
|
+
if (value.dirty !== void 0 && typeof value.dirty !== "boolean") throw new Error("invalid seed manifest metadata");
|
|
219
|
+
const ids = /* @__PURE__ */ new Set(), paths = /* @__PURE__ */ new Set();
|
|
220
|
+
for (const chunk of value.chunks) {
|
|
221
|
+
if (!object(chunk) || typeof chunk.id !== "string" || !chunk.id || typeof chunk.path !== "string" || !/^chunks\/[a-zA-Z0-9._-]+\.json$/.test(chunk.path) || typeof chunk.sha256 !== "string" || !/^[0-9a-f]{64}$/.test(chunk.sha256) || !nonnegative(chunk.bytes) || !nonnegative(chunk.count) || chunk.kind !== void 0 && chunk.kind !== "notes" || ids.has(chunk.id) || paths.has(chunk.path)) throw new Error("seed manifest failed shape validation");
|
|
222
|
+
ids.add(chunk.id);
|
|
223
|
+
paths.add(chunk.path);
|
|
224
|
+
}
|
|
225
|
+
return value;
|
|
226
|
+
}
|
|
315
227
|
function listMarkdownFiles(dir, prefix = "") {
|
|
316
228
|
if (!existsSync(dir)) return [];
|
|
317
229
|
const out = [];
|
|
@@ -332,6 +244,7 @@ function chunkIdFor(relPath) {
|
|
|
332
244
|
case "canvas":
|
|
333
245
|
case "dashboards":
|
|
334
246
|
case "efforts":
|
|
247
|
+
case "equipment":
|
|
335
248
|
return corpus;
|
|
336
249
|
case "collections":
|
|
337
250
|
return parts.length === 3 ? `collection._root` : `collection.${slug}`;
|
|
@@ -350,7 +263,7 @@ function partitionIntoChunks(paths) {
|
|
|
350
263
|
const id = chunkIdFor(p);
|
|
351
264
|
if (id === null) {
|
|
352
265
|
throw new Error(
|
|
353
|
-
`[generate-seed] Parity failure: '${p}' is not part of any known corpus (canvas | dashboards | efforts | collections | feeds). Extend chunkIdFor() if this is a new corpus.`
|
|
266
|
+
`[generate-seed] Parity failure: '${p}' is not part of any known corpus (canvas | dashboards | efforts | equipment | collections | feeds). Extend chunkIdFor() if this is a new corpus.`
|
|
354
267
|
);
|
|
355
268
|
}
|
|
356
269
|
const list = byId.get(id);
|
|
@@ -406,6 +319,18 @@ function getFileCreatedAt(file, repoRoot) {
|
|
|
406
319
|
return 0;
|
|
407
320
|
}
|
|
408
321
|
}
|
|
322
|
+
function frontmatterDateToCreatedAt(raw, path) {
|
|
323
|
+
const value = getScalar(parseFrontmatter(raw).meta, "date");
|
|
324
|
+
if (value === void 0 || value === "") return void 0;
|
|
325
|
+
const text = String(value);
|
|
326
|
+
const parts = text.match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
|
327
|
+
const ts = parts ? Date.parse(`${text}T12:00:00Z`) : NaN;
|
|
328
|
+
const valid = !!parts && Number.isFinite(ts) && new Date(ts).getUTCMonth() === Number(parts[2]) - 1 && new Date(ts).getUTCDate() === Number(parts[3]);
|
|
329
|
+
if (!valid) {
|
|
330
|
+
throw new Error(`[wod build] invalid frontmatter date '${text}' in '${path}' \u2014 expected a real calendar day (YYYY-MM-DD)`);
|
|
331
|
+
}
|
|
332
|
+
return ts;
|
|
333
|
+
}
|
|
409
334
|
function feedDateToCreatedAt(dateKey) {
|
|
410
335
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(dateKey)) return 0;
|
|
411
336
|
const ts = Date.parse(`${dateKey}T00:00:00Z`);
|
|
@@ -420,7 +345,7 @@ function compileSeedRow(path, content, metadata = {}) {
|
|
|
420
345
|
const section = sections.find((section2) => section2.from === block.from && section2.to === block.to);
|
|
421
346
|
return { id: `${noteId}:${block.id}`, noteId, blockId: block.id, blockVersion: 1, sourceRevision: 1, from: block.from, to: block.to, position, dataType: block.kind, ...block.kind === "wod" ? { blockContentId: blockContentId(section?.scriptBlock?.content ?? content.slice(block.from, block.to)) } : {}, rawContent: content.slice(block.from, block.to), noteTitle: metadata.noteTitle ?? fileToDisplayName(path.split("/").at(-1) ?? path), createdAt: metadata.createdAt ?? 0, isStatic: true, sourceId: metadata.sourceId, sourcePath: path, routeId: metadata.routeId };
|
|
422
347
|
});
|
|
423
|
-
return { path, content, blocks, blockIndex, blockEfforts: [] };
|
|
348
|
+
return { path, content, blocks, blockIndex, blockEfforts: [], blockEquipment: [] };
|
|
424
349
|
}
|
|
425
350
|
function buildBlockIndexRows(markdownDir, corpusRoot) {
|
|
426
351
|
const rows = [];
|
|
@@ -433,7 +358,7 @@ function buildBlockIndexRows(markdownDir, corpusRoot) {
|
|
|
433
358
|
const catalog = parts[2];
|
|
434
359
|
const routeId = chunkId === "canvas" ? canvasRouteSlug(content) ?? void 0 : chunkId.startsWith("collection.") ? stem.toLowerCase() === "readme" ? catalog : `${catalog}/${stem}` : chunkId.startsWith("feed.") ? parts.slice(1).join("/").replace(/\.md$/, "") : void 0;
|
|
435
360
|
const sourceId = seedNoteSourceId(path, content, chunkId);
|
|
436
|
-
const createdAt = chunkId.startsWith("feed.") ? feedDateToCreatedAt(parts.at(-2) ?? "") : getFileCreatedAt(path, corpusRoot);
|
|
361
|
+
const createdAt = frontmatterDateToCreatedAt(content, path) ?? (chunkId.startsWith("feed.") ? feedDateToCreatedAt(parts.at(-2) ?? "") : getFileCreatedAt(path, corpusRoot));
|
|
437
362
|
rows.push(...compileSeedRow(path, content, { routeId, sourceId, createdAt }).blockIndex);
|
|
438
363
|
}
|
|
439
364
|
return rows;
|
|
@@ -516,41 +441,37 @@ function formatDiscoveredLabel(raw) {
|
|
|
516
441
|
const clean = raw.replace(/[-_]+/g, " ").trim();
|
|
517
442
|
return clean.split(/\s+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
|
|
518
443
|
}
|
|
519
|
-
function
|
|
520
|
-
const
|
|
521
|
-
const
|
|
444
|
+
function loadCorpusReferenceCatalog(markdownDir) {
|
|
445
|
+
const efforts = [];
|
|
446
|
+
const equipment = [];
|
|
522
447
|
const effortsDir = join(markdownDir, "efforts");
|
|
523
448
|
for (const file of listMarkdownFiles(effortsDir)) {
|
|
524
|
-
const
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
for (const alias of parsed.aliases) {
|
|
532
|
-
aliasToCanonical.set(alias.toLowerCase(), parsed.slug);
|
|
533
|
-
aliasToCanonical.set(alias.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, ""), parsed.slug);
|
|
534
|
-
}
|
|
449
|
+
const parsed = parseEffortFile(readFileSync(join(effortsDir, file), "utf8"));
|
|
450
|
+
if (parsed) efforts.push(parsed);
|
|
451
|
+
}
|
|
452
|
+
const equipmentDir = join(markdownDir, "equipment");
|
|
453
|
+
for (const file of listMarkdownFiles(equipmentDir)) {
|
|
454
|
+
const parsed = parseEquipmentFile(readFileSync(join(equipmentDir, file), "utf8"));
|
|
455
|
+
if (parsed) equipment.push(parsed);
|
|
535
456
|
}
|
|
536
|
-
return {
|
|
457
|
+
return { efforts, equipment };
|
|
537
458
|
}
|
|
538
459
|
function discoverUncatalogedEfforts(markdownDir, corpusRoot) {
|
|
539
|
-
const
|
|
460
|
+
const catalog = loadCorpusReferenceCatalog(markdownDir);
|
|
461
|
+
const index = createReferenceIndex(catalog);
|
|
540
462
|
const blocks = buildBlockIndexRows(markdownDir, corpusRoot);
|
|
541
463
|
const discovered = /* @__PURE__ */ new Map();
|
|
542
464
|
for (const block of blocks) {
|
|
543
465
|
if (block.dataType !== "wod" || !block.rawContent) continue;
|
|
544
466
|
const section = parseDocumentSections(block.rawContent, { registeredWidgets: SEED_REGISTERED_WIDGETS }).find((section2) => section2.scriptBlock);
|
|
545
|
-
const script = parseScript(section?.scriptBlock?.content ?? block.rawContent);
|
|
467
|
+
const script = parseScript(section?.scriptBlock?.content ?? block.rawContent, { references: index });
|
|
546
468
|
for (const statement of script.statements) {
|
|
547
469
|
const effortMetric = statement.metrics?.getMetric?.("effort");
|
|
548
470
|
const effortLabel = (effortMetric && typeof effortMetric.value === "string" ? effortMetric.value : void 0) ?? statement.exerciseId;
|
|
549
471
|
if (!effortLabel) continue;
|
|
550
|
-
const slugified = effortLabel
|
|
472
|
+
const slugified = slugifyRefLabel(effortLabel);
|
|
551
473
|
if (!slugified || NON_EFFORT_SLUGS[slugified]) continue;
|
|
552
|
-
|
|
553
|
-
if (canonical && slugs.has(canonical)) continue;
|
|
474
|
+
if (index.resolveEffort(slugified) || index.resolveEffort(effortLabel)) continue;
|
|
554
475
|
const existing = discovered.get(slugified);
|
|
555
476
|
if (existing) {
|
|
556
477
|
existing.rawLabels.add(effortLabel);
|
|
@@ -600,17 +521,16 @@ ${aliases.join("\n")}` : "aliases: []",
|
|
|
600
521
|
}
|
|
601
522
|
function buildBlockEffortRows(markdownDir, corpusRoot, blocks = buildBlockIndexRows(markdownDir, corpusRoot)) {
|
|
602
523
|
const efforts = [];
|
|
603
|
-
const
|
|
524
|
+
const index = createReferenceIndex(loadCorpusReferenceCatalog(markdownDir));
|
|
604
525
|
for (const block of blocks) {
|
|
605
526
|
if (block.dataType !== "wod" || !block.rawContent) continue;
|
|
606
527
|
const section = parseDocumentSections(block.rawContent, { registeredWidgets: SEED_REGISTERED_WIDGETS }).find((section2) => section2.scriptBlock);
|
|
607
|
-
const script = parseScript(section?.scriptBlock?.content ?? block.rawContent);
|
|
608
|
-
const effortSlugs = extractEffortSlugs(script.statements);
|
|
528
|
+
const script = parseScript(section?.scriptBlock?.content ?? block.rawContent, { references: index });
|
|
609
529
|
const linked = /* @__PURE__ */ new Set();
|
|
610
|
-
for (const rawSlug of
|
|
611
|
-
const
|
|
612
|
-
const canonicalSlug =
|
|
613
|
-
if (!canonicalSlug || NON_EFFORT_SLUGS[canonicalSlug] || NON_EFFORT_SLUGS[
|
|
530
|
+
for (const rawSlug of extractStatementRefs(script.statements).efforts) {
|
|
531
|
+
const canonical = index.resolveEffort(rawSlug);
|
|
532
|
+
const canonicalSlug = canonical?.slug;
|
|
533
|
+
if (!canonicalSlug || NON_EFFORT_SLUGS[canonicalSlug] || NON_EFFORT_SLUGS[rawSlug]) {
|
|
614
534
|
continue;
|
|
615
535
|
}
|
|
616
536
|
if (linked.has(canonicalSlug)) continue;
|
|
@@ -629,6 +549,32 @@ function buildBlockEffortRows(markdownDir, corpusRoot, blocks = buildBlockIndexR
|
|
|
629
549
|
}
|
|
630
550
|
return efforts;
|
|
631
551
|
}
|
|
552
|
+
function buildBlockEquipmentRows(markdownDir, corpusRoot, blocks = buildBlockIndexRows(markdownDir, corpusRoot)) {
|
|
553
|
+
const links = [];
|
|
554
|
+
const index = createReferenceIndex(loadCorpusReferenceCatalog(markdownDir));
|
|
555
|
+
for (const block of blocks) {
|
|
556
|
+
if (block.dataType !== "wod" || !block.rawContent) continue;
|
|
557
|
+
const section = parseDocumentSections(block.rawContent, { registeredWidgets: SEED_REGISTERED_WIDGETS }).find((s) => s.scriptBlock);
|
|
558
|
+
const script = parseScript(section?.scriptBlock?.content ?? block.rawContent, { references: index });
|
|
559
|
+
const linked = /* @__PURE__ */ new Set();
|
|
560
|
+
for (const rawSlug of extractStatementRefs(script.statements).equipment) {
|
|
561
|
+
const canonicalSlug = index.resolveEquipment(rawSlug)?.slug;
|
|
562
|
+
if (!canonicalSlug || linked.has(canonicalSlug)) continue;
|
|
563
|
+
linked.add(canonicalSlug);
|
|
564
|
+
links.push({
|
|
565
|
+
id: `${block.id}:${canonicalSlug}`,
|
|
566
|
+
noteId: block.noteId,
|
|
567
|
+
blockId: block.blockId,
|
|
568
|
+
blockContentId: block.blockContentId,
|
|
569
|
+
equipmentSlug: canonicalSlug,
|
|
570
|
+
isStatic: block.isStatic,
|
|
571
|
+
sourcePath: block.sourcePath,
|
|
572
|
+
createdAt: block.createdAt
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
return links;
|
|
577
|
+
}
|
|
632
578
|
function sha256Hex(data) {
|
|
633
579
|
return createHash("sha256").update(data).digest("hex");
|
|
634
580
|
}
|
|
@@ -639,6 +585,13 @@ function generateSeed(options = {}) {
|
|
|
639
585
|
const markdownDir = options.markdownDir ?? join(corpusRoot, "markdown");
|
|
640
586
|
const outDir = options.outDir ?? join(corpusRoot, "dist");
|
|
641
587
|
const gitVersion = options.version !== void 0 ? { ...resolveGitVersion(corpusRoot), version: options.version } : resolveGitVersion(corpusRoot);
|
|
588
|
+
const packageFile = join(corpusRoot, "package.json");
|
|
589
|
+
const packageMetadata = existsSync(packageFile) ? JSON.parse(readFileSync(packageFile, "utf8")) : {};
|
|
590
|
+
const metadata = packageMetadata && typeof packageMetadata === "object" ? packageMetadata : {};
|
|
591
|
+
const repository = "repository" in metadata ? metadata.repository : void 0;
|
|
592
|
+
const repositoryUrl = typeof repository === "string" ? repository : repository && typeof repository === "object" && "url" in repository && typeof repository.url === "string" ? repository.url : void 0;
|
|
593
|
+
const webRepositoryUrl = repositoryUrl?.replace(/^git\+/, "").replace(/\.git$/, "");
|
|
594
|
+
const repositoryLink = webRepositoryUrl && URL.canParse(webRepositoryUrl) ? new URL(webRepositoryUrl) : void 0;
|
|
642
595
|
if (options.scaffoldDiscoveredEfforts) {
|
|
643
596
|
const discovered = discoverUncatalogedEfforts(markdownDir, corpusRoot);
|
|
644
597
|
if (discovered.length > 0) {
|
|
@@ -673,9 +626,11 @@ ${shown}${more}`);
|
|
|
673
626
|
const manifestChunks = [];
|
|
674
627
|
const tBlockEfforts = Date.now();
|
|
675
628
|
const effortRows = buildBlockEffortRows(markdownDir, corpusRoot, blockRows);
|
|
629
|
+
const equipmentRows = buildBlockEquipmentRows(markdownDir, corpusRoot, blockRows);
|
|
676
630
|
passMs.blockEfforts = Date.now() - tBlockEfforts;
|
|
677
631
|
const blocksByPath = /* @__PURE__ */ new Map();
|
|
678
632
|
const effortsByPath = /* @__PURE__ */ new Map();
|
|
633
|
+
const equipmentByPath = /* @__PURE__ */ new Map();
|
|
679
634
|
for (const row of blockRows) {
|
|
680
635
|
const rows = blocksByPath.get(row.sourcePath) ?? [];
|
|
681
636
|
rows.push(row);
|
|
@@ -686,6 +641,11 @@ ${shown}${more}`);
|
|
|
686
641
|
rows.push(row);
|
|
687
642
|
effortsByPath.set(row.sourcePath, rows);
|
|
688
643
|
}
|
|
644
|
+
for (const row of equipmentRows) {
|
|
645
|
+
const rows = equipmentByPath.get(row.sourcePath) ?? [];
|
|
646
|
+
rows.push(row);
|
|
647
|
+
equipmentByPath.set(row.sourcePath, rows);
|
|
648
|
+
}
|
|
689
649
|
let totalFiles = 0;
|
|
690
650
|
const tWrite = Date.now();
|
|
691
651
|
for (const { id, files } of groups) {
|
|
@@ -696,6 +656,7 @@ ${shown}${more}`);
|
|
|
696
656
|
const compiled = compileSeedRow(p, content);
|
|
697
657
|
compiled.blockIndex = blocksByPath.get(p) ?? compiled.blockIndex;
|
|
698
658
|
compiled.blockEfforts = effortsByPath.get(p) ?? [];
|
|
659
|
+
compiled.blockEquipment = equipmentByPath.get(p) ?? [];
|
|
699
660
|
return compiled;
|
|
700
661
|
});
|
|
701
662
|
const bytes = Buffer.from(JSON.stringify(rows), "utf8");
|
|
@@ -707,6 +668,9 @@ ${shown}${more}`);
|
|
|
707
668
|
}
|
|
708
669
|
passMs.write = Date.now() - tWrite;
|
|
709
670
|
const manifest = {
|
|
671
|
+
name: "name" in metadata && typeof metadata.name === "string" ? metadata.name : void 0,
|
|
672
|
+
description: "description" in metadata && typeof metadata.description === "string" ? metadata.description : void 0,
|
|
673
|
+
repositoryUrl: repositoryLink?.protocol === "https:" && !repositoryLink.username && !repositoryLink.password ? repositoryLink.href : void 0,
|
|
710
674
|
schema: SEED_SCHEMA,
|
|
711
675
|
version: gitVersion.version,
|
|
712
676
|
versionLabel: gitVersion.versionLabel,
|
|
@@ -715,6 +679,7 @@ ${shown}${more}`);
|
|
|
715
679
|
builtAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
716
680
|
chunks: manifestChunks
|
|
717
681
|
};
|
|
682
|
+
assertSeedManifest(manifest);
|
|
718
683
|
writeFileSync(join(outDir, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
|
|
719
684
|
const reportPath = writeBuildReport(outDir, {
|
|
720
685
|
manifest,
|
|
@@ -724,6 +689,6 @@ ${shown}${more}`);
|
|
|
724
689
|
return { manifest, outDir, totalFiles, reportPath, passMs };
|
|
725
690
|
}
|
|
726
691
|
|
|
727
|
-
export { SEED_SCHEMA, buildBlockEffortRows, buildBlockIndexRows, chunkIdFor, collectCorpusMarkdown, compileSeedRow, discoverUncatalogedEfforts, feedDateToCreatedAt, generateSeed,
|
|
728
|
-
//# sourceMappingURL=chunk-
|
|
729
|
-
//# sourceMappingURL=chunk-
|
|
692
|
+
export { SEED_SCHEMA, buildBlockEffortRows, buildBlockEquipmentRows, buildBlockIndexRows, chunkIdFor, collectCorpusMarkdown, compileSeedRow, discoverUncatalogedEfforts, feedDateToCreatedAt, frontmatterDateToCreatedAt, generateSeed, loadCorpusReferenceCatalog, partitionIntoChunks, scaffoldDiscoveredEfforts, validateDashboardNote, validateWodBlockSyntax, writeBuildReport };
|
|
693
|
+
//# sourceMappingURL=chunk-CVFMFD7D.mjs.map
|
|
694
|
+
//# sourceMappingURL=chunk-CVFMFD7D.mjs.map
|