@bitcobblers/wod-wiki-tools 0.36.2136 → 0.37.2137
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 +299 -16
- package/dist/bin/wod.cjs.map +1 -1
- package/dist/bin/wod.mjs +3 -2
- package/dist/bin/wod.mjs.map +1 -1
- package/dist/{chunk-6QNX4FED.mjs → chunk-GBBJBDLS.mjs} +29 -11
- package/dist/chunk-GBBJBDLS.mjs.map +1 -0
- package/dist/{chunk-FZKXOYMJ.mjs → chunk-NATJMTAW.mjs} +47 -4
- package/dist/chunk-NATJMTAW.mjs.map +1 -0
- package/dist/chunk-SQAI6B4P.mjs +12 -0
- package/dist/chunk-SQAI6B4P.mjs.map +1 -0
- package/dist/{compiler-CTPLIZJK.mjs → compiler-B77PITYH.mjs} +3 -3
- package/dist/{compiler-CTPLIZJK.mjs.map → compiler-B77PITYH.mjs.map} +1 -1
- package/dist/index.cjs +299 -16
- 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 +3 -2
- package/dist/scaffoldCatalog-LQOUCJ4X.mjs +205 -0
- package/dist/scaffoldCatalog-LQOUCJ4X.mjs.map +1 -0
- package/dist/web/playground/assets/main-CFDrblxn.css +2 -0
- package/dist/web/playground/assets/main-OGIV1avF.js +188 -0
- package/dist/web/playground/assets/{statementBuilderFlow-ugwi0fu0.js → statementBuilderFlow-BL8OKlcb.js} +2 -2
- package/dist/web/playground/assets/{vendor-g-NJOjvC.js → vendor-CTANVdPW.js} +19 -19
- package/dist/web/playground/assets/{vendor-codemirror-C41SFn-r.js → vendor-codemirror-BlXDdJID.js} +8 -8
- package/dist/web/playground/index.html +4 -4
- package/dist/web/{server/seed/core/chunks/canvas.20048125.json → playground/seed/core/chunks/canvas.a2e32d8c.json} +1 -1
- package/dist/web/playground/seed/core/manifest.json +8 -5
- package/dist/web/playground/seed/core/report.html +9 -9
- package/dist/web/server/assets/main-BdUrlkaF.js +187 -0
- package/dist/web/server/assets/main-CFDrblxn.css +2 -0
- package/dist/web/server/assets/{statementBuilderFlow-40WaYjdq.js → statementBuilderFlow-xqsK_3T8.js} +2 -2
- package/dist/web/server/assets/{vendor-g-NJOjvC.js → vendor-CTANVdPW.js} +19 -19
- package/dist/web/server/assets/{vendor-codemirror-C41SFn-r.js → vendor-codemirror-BlXDdJID.js} +8 -8
- package/dist/web/server/index.html +4 -4
- package/dist/web/{playground/seed/core/chunks/canvas.20048125.json → server/seed/core/chunks/canvas.a2e32d8c.json} +1 -1
- package/dist/web/server/seed/core/manifest.json +8 -5
- package/dist/web/server/seed/core/report.html +9 -9
- package/package.json +6 -6
- package/dist/chunk-6QNX4FED.mjs.map +0 -1
- package/dist/chunk-FZKXOYMJ.mjs.map +0 -1
- package/dist/web/playground/assets/main-B-bffxwE.css +0 -2
- package/dist/web/playground/assets/main-iLSeEl2E.js +0 -188
- package/dist/web/server/assets/main-B-bffxwE.css +0 -2
- package/dist/web/server/assets/main-CRyLxlPN.js +0 -187
package/dist/bin/wod.cjs
CHANGED
|
@@ -161,7 +161,7 @@ function sqliteEventStore(db) {
|
|
|
161
161
|
getEventsByTimeRange: async (start, end) => (await all()).filter((r) => r.timestamp >= start && r.timestamp <= end),
|
|
162
162
|
getEventsByResult: async (resultId) => (await all()).filter((r) => r.resultId === resultId),
|
|
163
163
|
getEventsForNote: async (noteId) => (await all()).filter((r) => r.noteId === noteId),
|
|
164
|
-
getEventsByContent: async (
|
|
164
|
+
getEventsByContent: async (blockContentId5) => (await all()).filter((r) => r.blockContentId === blockContentId5),
|
|
165
165
|
scanAll: all,
|
|
166
166
|
appendEvents: async (appended) => {
|
|
167
167
|
const sql = await loadSql();
|
|
@@ -614,6 +614,31 @@ var init_report = __esm({
|
|
|
614
614
|
"src/seedbuild/report.ts"() {
|
|
615
615
|
}
|
|
616
616
|
});
|
|
617
|
+
function object(value) {
|
|
618
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
619
|
+
}
|
|
620
|
+
function nonnegative(value) {
|
|
621
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
622
|
+
}
|
|
623
|
+
function assertSeedManifest2(value) {
|
|
624
|
+
if (!object(value) || value.schema !== SEED_SCHEMA2) throw new Error("Incompatible seed schema; rebuild seed artifacts");
|
|
625
|
+
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");
|
|
626
|
+
for (const key of ["versionLabel", "commit", "name", "description"]) if (value[key] !== void 0 && typeof value[key] !== "string") throw new Error("invalid seed manifest metadata");
|
|
627
|
+
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");
|
|
628
|
+
if (value.dirty !== void 0 && typeof value.dirty !== "boolean") throw new Error("invalid seed manifest metadata");
|
|
629
|
+
const ids = /* @__PURE__ */ new Set(), paths = /* @__PURE__ */ new Set();
|
|
630
|
+
for (const chunk of value.chunks) {
|
|
631
|
+
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");
|
|
632
|
+
ids.add(chunk.id);
|
|
633
|
+
paths.add(chunk.path);
|
|
634
|
+
}
|
|
635
|
+
return value;
|
|
636
|
+
}
|
|
637
|
+
var init_validation = __esm({
|
|
638
|
+
"src/seedbuild/validation.ts"() {
|
|
639
|
+
init_contract();
|
|
640
|
+
}
|
|
641
|
+
});
|
|
617
642
|
|
|
618
643
|
// src/seedbuild/compiler.ts
|
|
619
644
|
var compiler_exports = {};
|
|
@@ -625,6 +650,7 @@ __export(compiler_exports, {
|
|
|
625
650
|
compileSeedRow: () => compileSeedRow,
|
|
626
651
|
discoverUncatalogedEfforts: () => discoverUncatalogedEfforts,
|
|
627
652
|
feedDateToCreatedAt: () => feedDateToCreatedAt,
|
|
653
|
+
frontmatterDateToCreatedAt: () => frontmatterDateToCreatedAt,
|
|
628
654
|
generateSeed: () => generateSeed,
|
|
629
655
|
loadExistingEffortMap: () => loadExistingEffortMap,
|
|
630
656
|
partitionIntoChunks: () => partitionIntoChunks,
|
|
@@ -726,6 +752,18 @@ function getFileCreatedAt(file, repoRoot) {
|
|
|
726
752
|
return 0;
|
|
727
753
|
}
|
|
728
754
|
}
|
|
755
|
+
function frontmatterDateToCreatedAt(raw, path) {
|
|
756
|
+
const value = getScalar(parseFrontmatter(raw).meta, "date");
|
|
757
|
+
if (value === void 0 || value === "") return void 0;
|
|
758
|
+
const text = String(value);
|
|
759
|
+
const parts = text.match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
|
760
|
+
const ts = parts ? Date.parse(`${text}T12:00:00Z`) : NaN;
|
|
761
|
+
const valid = !!parts && Number.isFinite(ts) && new Date(ts).getUTCMonth() === Number(parts[2]) - 1 && new Date(ts).getUTCDate() === Number(parts[3]);
|
|
762
|
+
if (!valid) {
|
|
763
|
+
throw new Error(`[wod build] invalid frontmatter date '${text}' in '${path}' \u2014 expected a real calendar day (YYYY-MM-DD)`);
|
|
764
|
+
}
|
|
765
|
+
return ts;
|
|
766
|
+
}
|
|
729
767
|
function feedDateToCreatedAt(dateKey) {
|
|
730
768
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(dateKey)) return 0;
|
|
731
769
|
const ts = Date.parse(`${dateKey}T00:00:00Z`);
|
|
@@ -753,7 +791,7 @@ function buildBlockIndexRows(markdownDir, corpusRoot) {
|
|
|
753
791
|
const catalog = parts[2];
|
|
754
792
|
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;
|
|
755
793
|
const sourceId = seedNoteSourceId(path$1, content, chunkId);
|
|
756
|
-
const createdAt = chunkId.startsWith("feed.") ? feedDateToCreatedAt(parts.at(-2) ?? "") : getFileCreatedAt(path$1, corpusRoot);
|
|
794
|
+
const createdAt = frontmatterDateToCreatedAt(content, path$1) ?? (chunkId.startsWith("feed.") ? feedDateToCreatedAt(parts.at(-2) ?? "") : getFileCreatedAt(path$1, corpusRoot));
|
|
757
795
|
rows.push(...compileSeedRow(path$1, content, { routeId, sourceId, createdAt }).blockIndex);
|
|
758
796
|
}
|
|
759
797
|
return rows;
|
|
@@ -913,6 +951,13 @@ function generateSeed(options = {}) {
|
|
|
913
951
|
const markdownDir = options.markdownDir ?? path.join(corpusRoot, "markdown");
|
|
914
952
|
const outDir = options.outDir ?? path.join(corpusRoot, "dist");
|
|
915
953
|
const gitVersion = options.version !== void 0 ? { ...resolveGitVersion(corpusRoot), version: options.version } : resolveGitVersion(corpusRoot);
|
|
954
|
+
const packageFile = path.join(corpusRoot, "package.json");
|
|
955
|
+
const packageMetadata = fs.existsSync(packageFile) ? JSON.parse(fs.readFileSync(packageFile, "utf8")) : {};
|
|
956
|
+
const metadata = packageMetadata && typeof packageMetadata === "object" ? packageMetadata : {};
|
|
957
|
+
const repository = "repository" in metadata ? metadata.repository : void 0;
|
|
958
|
+
const repositoryUrl = typeof repository === "string" ? repository : repository && typeof repository === "object" && "url" in repository && typeof repository.url === "string" ? repository.url : void 0;
|
|
959
|
+
const webRepositoryUrl = repositoryUrl?.replace(/^git\+/, "").replace(/\.git$/, "");
|
|
960
|
+
const repositoryLink = webRepositoryUrl && URL.canParse(webRepositoryUrl) ? new URL(webRepositoryUrl) : void 0;
|
|
916
961
|
if (options.scaffoldDiscoveredEfforts) {
|
|
917
962
|
const discovered = discoverUncatalogedEfforts(markdownDir, corpusRoot);
|
|
918
963
|
if (discovered.length > 0) {
|
|
@@ -981,6 +1026,9 @@ ${shown}${more}`);
|
|
|
981
1026
|
}
|
|
982
1027
|
passMs.write = Date.now() - tWrite;
|
|
983
1028
|
const manifest = {
|
|
1029
|
+
name: "name" in metadata && typeof metadata.name === "string" ? metadata.name : void 0,
|
|
1030
|
+
description: "description" in metadata && typeof metadata.description === "string" ? metadata.description : void 0,
|
|
1031
|
+
repositoryUrl: repositoryLink?.protocol === "https:" && !repositoryLink.username && !repositoryLink.password ? repositoryLink.href : void 0,
|
|
984
1032
|
schema: SEED_SCHEMA2,
|
|
985
1033
|
version: gitVersion.version,
|
|
986
1034
|
versionLabel: gitVersion.versionLabel,
|
|
@@ -989,6 +1037,7 @@ ${shown}${more}`);
|
|
|
989
1037
|
builtAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
990
1038
|
chunks: manifestChunks
|
|
991
1039
|
};
|
|
1040
|
+
assertSeedManifest2(manifest);
|
|
992
1041
|
fs.writeFileSync(path.join(outDir, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
|
|
993
1042
|
const reportPath = writeBuildReport(outDir, {
|
|
994
1043
|
manifest,
|
|
@@ -1007,6 +1056,7 @@ var init_compiler = __esm({
|
|
|
1007
1056
|
init_git_version();
|
|
1008
1057
|
init_report();
|
|
1009
1058
|
init_frontmatter();
|
|
1059
|
+
init_validation();
|
|
1010
1060
|
NON_EFFORT_SLUGS = {
|
|
1011
1061
|
"amrap": true,
|
|
1012
1062
|
"emom": true,
|
|
@@ -1056,6 +1106,219 @@ var init_compiler = __esm({
|
|
|
1056
1106
|
}
|
|
1057
1107
|
});
|
|
1058
1108
|
|
|
1109
|
+
// src/version.ts
|
|
1110
|
+
var VERSION;
|
|
1111
|
+
var init_version = __esm({
|
|
1112
|
+
"src/version.ts"() {
|
|
1113
|
+
VERSION = "0.37.2137";
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
|
|
1117
|
+
// src/cli/scaffoldCatalog.ts
|
|
1118
|
+
var scaffoldCatalog_exports = {};
|
|
1119
|
+
__export(scaffoldCatalog_exports, {
|
|
1120
|
+
scaffoldCatalog: () => scaffoldCatalog,
|
|
1121
|
+
validateCatalogName: () => validateCatalogName
|
|
1122
|
+
});
|
|
1123
|
+
function validateCatalogName(name) {
|
|
1124
|
+
if (name.length === 0 || name === "." || name === "..") {
|
|
1125
|
+
throw new Error("Catalog name must be a single non-empty directory name");
|
|
1126
|
+
}
|
|
1127
|
+
if (name.includes("/") || name.includes("\\") || name.includes("\0")) {
|
|
1128
|
+
throw new Error(`Invalid catalog name '${name}': must be a single directory name (no path separators or traversal)`);
|
|
1129
|
+
}
|
|
1130
|
+
if (/^(?:[A-Za-z]:)?[/\\]/.test(name)) {
|
|
1131
|
+
throw new Error(`Invalid catalog name '${name}': absolute paths are not allowed`);
|
|
1132
|
+
}
|
|
1133
|
+
if (name.length > 214 || !/^[a-z0-9][a-z0-9._-]*$/.test(name)) {
|
|
1134
|
+
throw new Error(
|
|
1135
|
+
`Invalid catalog name '${name}': must be a valid npm package name (lowercase letters, digits, dots, hyphens, underscores; no leading dot/hyphen)`
|
|
1136
|
+
);
|
|
1137
|
+
}
|
|
1138
|
+
return name;
|
|
1139
|
+
}
|
|
1140
|
+
function scaffoldCatalog(name, opts = {}) {
|
|
1141
|
+
validateCatalogName(name);
|
|
1142
|
+
const dir = path.resolve(opts.cwd ?? process.cwd(), name);
|
|
1143
|
+
try {
|
|
1144
|
+
fs.mkdirSync(dir);
|
|
1145
|
+
} catch (error) {
|
|
1146
|
+
if (error.code === "EEXIST") {
|
|
1147
|
+
throw new Error(`Refusing to overwrite '${dir}': destination already exists`, { cause: error });
|
|
1148
|
+
}
|
|
1149
|
+
throw error;
|
|
1150
|
+
}
|
|
1151
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1152
|
+
const files = [
|
|
1153
|
+
["package.json", `${JSON.stringify(
|
|
1154
|
+
{
|
|
1155
|
+
name,
|
|
1156
|
+
version: "0.1.0",
|
|
1157
|
+
private: true,
|
|
1158
|
+
type: "module",
|
|
1159
|
+
description: `WOD Wiki workout catalog: ${name}`,
|
|
1160
|
+
scripts: {
|
|
1161
|
+
build: "wod build . --output dist"
|
|
1162
|
+
},
|
|
1163
|
+
devDependencies: {
|
|
1164
|
+
"@bitcobblers/wod-wiki-tools": `^${VERSION}`
|
|
1165
|
+
}
|
|
1166
|
+
},
|
|
1167
|
+
null,
|
|
1168
|
+
2
|
|
1169
|
+
)}
|
|
1170
|
+
`],
|
|
1171
|
+
[".gitignore", "node_modules/\ndist/\n"],
|
|
1172
|
+
[".github/workflows/publish-catalog.yml", publishWorkflow()],
|
|
1173
|
+
["markdown/collections/example/README.md", collectionReadme(name)],
|
|
1174
|
+
[`markdown/collections/example/morning-session.md`, exampleWorkout(date)],
|
|
1175
|
+
["README.md", catalogReadme(name)]
|
|
1176
|
+
];
|
|
1177
|
+
try {
|
|
1178
|
+
for (const [rel, content] of files) {
|
|
1179
|
+
const target = path.join(dir, rel);
|
|
1180
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
1181
|
+
fs.writeFileSync(target, content, "utf-8");
|
|
1182
|
+
}
|
|
1183
|
+
} catch (error) {
|
|
1184
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
1185
|
+
throw error;
|
|
1186
|
+
}
|
|
1187
|
+
return { dir, files: files.map(([rel]) => rel) };
|
|
1188
|
+
}
|
|
1189
|
+
var publishWorkflow, collectionReadme, exampleWorkout, catalogReadme;
|
|
1190
|
+
var init_scaffoldCatalog = __esm({
|
|
1191
|
+
"src/cli/scaffoldCatalog.ts"() {
|
|
1192
|
+
init_version();
|
|
1193
|
+
publishWorkflow = () => `name: Publish catalog
|
|
1194
|
+
|
|
1195
|
+
# Compile the catalog with the wod CLI and deploy dist/ to GitHub Pages.
|
|
1196
|
+
# Requires Pages enabled: repo Settings \u2192 Pages \u2192 Source: "GitHub Actions".
|
|
1197
|
+
|
|
1198
|
+
on:
|
|
1199
|
+
push:
|
|
1200
|
+
branches: [main]
|
|
1201
|
+
workflow_dispatch:
|
|
1202
|
+
|
|
1203
|
+
permissions:
|
|
1204
|
+
contents: read
|
|
1205
|
+
pages: write
|
|
1206
|
+
id-token: write
|
|
1207
|
+
|
|
1208
|
+
concurrency:
|
|
1209
|
+
group: pages
|
|
1210
|
+
cancel-in-progress: true
|
|
1211
|
+
|
|
1212
|
+
jobs:
|
|
1213
|
+
publish:
|
|
1214
|
+
runs-on: ubuntu-latest
|
|
1215
|
+
environment:
|
|
1216
|
+
name: github-pages
|
|
1217
|
+
url: \${{ steps.deployment.outputs.page_url }}
|
|
1218
|
+
steps:
|
|
1219
|
+
- uses: actions/checkout@v4
|
|
1220
|
+
with:
|
|
1221
|
+
# Full history: seed manifest version stamps derive from git commit count.
|
|
1222
|
+
fetch-depth: 0
|
|
1223
|
+
|
|
1224
|
+
- name: Set up Bun
|
|
1225
|
+
uses: oven-sh/setup-bun@v2
|
|
1226
|
+
with:
|
|
1227
|
+
bun-version: 1.4.x
|
|
1228
|
+
|
|
1229
|
+
- name: Install dependencies
|
|
1230
|
+
run: bun install
|
|
1231
|
+
|
|
1232
|
+
- name: Build seed
|
|
1233
|
+
run: bunx wod build . --output dist
|
|
1234
|
+
|
|
1235
|
+
- uses: actions/configure-pages@v5
|
|
1236
|
+
|
|
1237
|
+
- name: Upload dist
|
|
1238
|
+
uses: actions/upload-pages-artifact@v3
|
|
1239
|
+
with:
|
|
1240
|
+
path: dist
|
|
1241
|
+
|
|
1242
|
+
- id: deployment
|
|
1243
|
+
uses: actions/deploy-pages@v4
|
|
1244
|
+
`;
|
|
1245
|
+
collectionReadme = (name) => `# ${name}
|
|
1246
|
+
|
|
1247
|
+
Example benchmark collection. Each \`.md\` file in this directory becomes part of
|
|
1248
|
+
the \`example\` collection chunk; \`README.md\` is the collection's landing page.
|
|
1249
|
+
|
|
1250
|
+
Add one file per workout:
|
|
1251
|
+
|
|
1252
|
+
\`\`\`\`markdown
|
|
1253
|
+
---
|
|
1254
|
+
title: My workout
|
|
1255
|
+
date: 2026-01-01
|
|
1256
|
+
---
|
|
1257
|
+
|
|
1258
|
+
# My workout
|
|
1259
|
+
|
|
1260
|
+
\`\`\`time
|
|
1261
|
+
(21-15-9)
|
|
1262
|
+
Thrusters @95lb
|
|
1263
|
+
Pull-ups
|
|
1264
|
+
\`\`\`
|
|
1265
|
+
\`\`\`\`
|
|
1266
|
+
|
|
1267
|
+
The \`date:\` frontmatter field sets the workout's chronological placement
|
|
1268
|
+
(regardless of filename or directory).
|
|
1269
|
+
`;
|
|
1270
|
+
exampleWorkout = (date) => `---
|
|
1271
|
+
title: Morning session
|
|
1272
|
+
date: ${date}
|
|
1273
|
+
---
|
|
1274
|
+
|
|
1275
|
+
# Morning session
|
|
1276
|
+
|
|
1277
|
+
\`\`\`time
|
|
1278
|
+
(21-15-9)
|
|
1279
|
+
Thrusters @95lb
|
|
1280
|
+
Pull-ups
|
|
1281
|
+
\`\`\`
|
|
1282
|
+
`;
|
|
1283
|
+
catalogReadme = (name) => `# ${name}
|
|
1284
|
+
|
|
1285
|
+
A [WOD Wiki](https://github.com/bitcobblers/wod-wiki) workout catalog: plain
|
|
1286
|
+
Markdown workouts compiled to static, version-stamped seed chunks and published
|
|
1287
|
+
via GitHub Pages.
|
|
1288
|
+
|
|
1289
|
+
## Develop
|
|
1290
|
+
|
|
1291
|
+
\`\`\`sh
|
|
1292
|
+
bun install
|
|
1293
|
+
bunx wod build . --output dist
|
|
1294
|
+
\`\`\`
|
|
1295
|
+
|
|
1296
|
+
Workouts live under \`markdown/\` \u2014 this scaffold starts with one example
|
|
1297
|
+
collection. Validate everything with \`bunx wod build\`: it gates every file on
|
|
1298
|
+
the Whiteboard grammar and corpus layout before writing \`dist/\`.
|
|
1299
|
+
|
|
1300
|
+
## Publish
|
|
1301
|
+
|
|
1302
|
+
Push to GitHub and enable Pages (**Settings \u2192 Pages \u2192 Source: GitHub
|
|
1303
|
+
Actions**). The bundled workflow (\`.github/workflows/publish-catalog.yml\`)
|
|
1304
|
+
builds the catalog on every push to \`main\` and deploys \`dist/\`.
|
|
1305
|
+
|
|
1306
|
+
## Share
|
|
1307
|
+
|
|
1308
|
+
Once published, anyone can subscribe to this catalog from a WOD Wiki instance
|
|
1309
|
+
at:
|
|
1310
|
+
|
|
1311
|
+
\`\`\`
|
|
1312
|
+
<app-url>/subscribe?source=<url-encoded published catalog URL>
|
|
1313
|
+
\`\`\`
|
|
1314
|
+
|
|
1315
|
+
For \`owner\`/\`repo\` on GitHub Pages the catalog URL is the deployed
|
|
1316
|
+
directory, \`https://owner.github.io/repo/\`, e.g.
|
|
1317
|
+
\`/subscribe?source=https%3A%2F%2Fowner.github.io%2Frepo%2F\`.
|
|
1318
|
+
`;
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1321
|
+
|
|
1059
1322
|
// src/server/errors.ts
|
|
1060
1323
|
var HttpError;
|
|
1061
1324
|
var init_errors = __esm({
|
|
@@ -1359,13 +1622,13 @@ __export(server_exports, {
|
|
|
1359
1622
|
runCliServer: () => runCliServer
|
|
1360
1623
|
});
|
|
1361
1624
|
function withResolvers() {
|
|
1362
|
-
let
|
|
1625
|
+
let resolve3;
|
|
1363
1626
|
let reject;
|
|
1364
1627
|
const promise = new Promise((res, rej) => {
|
|
1365
|
-
|
|
1628
|
+
resolve3 = res;
|
|
1366
1629
|
reject = rej;
|
|
1367
1630
|
});
|
|
1368
|
-
return { promise, resolve:
|
|
1631
|
+
return { promise, resolve: resolve3, reject };
|
|
1369
1632
|
}
|
|
1370
1633
|
function startHttpServer(handler, host, port) {
|
|
1371
1634
|
const b = globalThis.Bun;
|
|
@@ -1373,7 +1636,7 @@ function startHttpServer(handler, host, port) {
|
|
|
1373
1636
|
const s = b.serve({ port, hostname: host, fetch: handler });
|
|
1374
1637
|
return Promise.resolve({ stop: () => s.stop() });
|
|
1375
1638
|
}
|
|
1376
|
-
const { promise, resolve:
|
|
1639
|
+
const { promise, resolve: resolve3, reject } = withResolvers();
|
|
1377
1640
|
const server = http__default.default.createServer(async (req, res) => {
|
|
1378
1641
|
try {
|
|
1379
1642
|
const url = new URL(req.url || "/", `http://${req.headers.host || `${host}:${port}`}`);
|
|
@@ -1398,7 +1661,7 @@ function startHttpServer(handler, host, port) {
|
|
|
1398
1661
|
});
|
|
1399
1662
|
server.once("error", reject);
|
|
1400
1663
|
server.listen(port, host, () => {
|
|
1401
|
-
|
|
1664
|
+
resolve3({
|
|
1402
1665
|
stop: () => {
|
|
1403
1666
|
const close = withResolvers();
|
|
1404
1667
|
server.close(() => close.resolve());
|
|
@@ -1542,8 +1805,8 @@ async function loadLanguagePack(moduleSpec) {
|
|
|
1542
1805
|
try {
|
|
1543
1806
|
let importPath = moduleSpec;
|
|
1544
1807
|
if (moduleSpec.startsWith(".") || moduleSpec.startsWith("/") || moduleSpec.includes("\\") || moduleSpec.endsWith(".ts") || moduleSpec.endsWith(".js") || moduleSpec.endsWith(".mjs")) {
|
|
1545
|
-
const { resolve:
|
|
1546
|
-
const resolved =
|
|
1808
|
+
const { resolve: resolve3, pathToFileURL } = getPathUtils();
|
|
1809
|
+
const resolved = resolve3(process.cwd(), moduleSpec);
|
|
1547
1810
|
importPath = pathToFileURL(resolved).href;
|
|
1548
1811
|
}
|
|
1549
1812
|
const imported = await import(
|
|
@@ -2552,7 +2815,9 @@ async function publishCatalogSeed(db, options) {
|
|
|
2552
2815
|
})) : compileSeedRow(notePath, note.rawContent, {
|
|
2553
2816
|
routeId: `${catalogName}/${stem}`,
|
|
2554
2817
|
sourceId: `collection:${catalogName}/${stem}`,
|
|
2555
|
-
|
|
2818
|
+
// Authored frontmatter date first — exports keep the post's own
|
|
2819
|
+
// day, never the import/publish time.
|
|
2820
|
+
createdAt: note.date ?? note.createdAt,
|
|
2556
2821
|
noteTitle: note.title
|
|
2557
2822
|
}).blockIndex;
|
|
2558
2823
|
const blockEfforts = noteBlockEfforts.map((e) => ({
|
|
@@ -2894,10 +3159,8 @@ ${escapeCsvField(data.parsed.metric)},${data.scalar},${escapeCsvField(data.unit
|
|
|
2894
3159
|
return lines.join("\n");
|
|
2895
3160
|
}
|
|
2896
3161
|
|
|
2897
|
-
// src/version.ts
|
|
2898
|
-
var VERSION = "0.36.2136";
|
|
2899
|
-
|
|
2900
3162
|
// src/cli/runner.ts
|
|
3163
|
+
init_version();
|
|
2901
3164
|
function getFs2() {
|
|
2902
3165
|
if (typeof globalThis.process?.versions?.node === "undefined" && typeof globalThis.Bun === "undefined") {
|
|
2903
3166
|
throw new Error("File system operations are only supported in Node / Bun environments");
|
|
@@ -3049,7 +3312,7 @@ function parseCliArgs(args) {
|
|
|
3049
3312
|
if (Number.isSafeInteger(v) && v >= 0) result.seedVersion = v;
|
|
3050
3313
|
i++;
|
|
3051
3314
|
} else if (!result.subcommand) {
|
|
3052
|
-
if (arg === "parse" || arg === "run" || arg === "query" || arg === "download" || arg === "export" || arg === "import" || arg === "publish" || arg === "build" || arg === "seed" || arg === "reset" || arg === "init" || arg === "server" || arg === "serve" || arg === "playground" || arg === "help" || arg === "version") {
|
|
3315
|
+
if (arg === "parse" || arg === "run" || arg === "query" || arg === "download" || arg === "export" || arg === "import" || arg === "publish" || arg === "build" || arg === "seed" || arg === "reset" || arg === "init" || arg === "server" || arg === "serve" || arg === "playground" || arg === "init-catalog" || arg === "help" || arg === "version") {
|
|
3053
3316
|
result.subcommand = arg;
|
|
3054
3317
|
} else {
|
|
3055
3318
|
result.target = arg;
|
|
@@ -3089,13 +3352,13 @@ function readBunStdinText() {
|
|
|
3089
3352
|
async function readStdin() {
|
|
3090
3353
|
const bunText = readBunStdinText();
|
|
3091
3354
|
if (bunText) return bunText();
|
|
3092
|
-
return new Promise((
|
|
3355
|
+
return new Promise((resolve3, reject) => {
|
|
3093
3356
|
const chunks = [];
|
|
3094
3357
|
process.stdin.on("data", (chunk) => {
|
|
3095
3358
|
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
3096
3359
|
});
|
|
3097
3360
|
process.stdin.on("end", () => {
|
|
3098
|
-
|
|
3361
|
+
resolve3(Buffer.concat(chunks).toString("utf-8"));
|
|
3099
3362
|
});
|
|
3100
3363
|
process.stdin.on("error", (err) => {
|
|
3101
3364
|
reject(err);
|
|
@@ -3115,6 +3378,10 @@ USAGE:
|
|
|
3115
3378
|
wod import <note|playground|session|effort|equipment> <file> [options]
|
|
3116
3379
|
wod publish [catalog] [options]
|
|
3117
3380
|
wod build [dir] [options]
|
|
3381
|
+
wod init-catalog <name>
|
|
3382
|
+
Scaffold a new catalog repository (package.json, example
|
|
3383
|
+
collection, GitHub Actions Pages workflow). Refuses an
|
|
3384
|
+
existing destination.
|
|
3118
3385
|
wod seed [options]
|
|
3119
3386
|
wod reset [options]
|
|
3120
3387
|
wod init Initialize the configured database (idempotent)
|
|
@@ -3317,6 +3584,22 @@ async function cliMain(argv = process.argv.slice(2), io = {}) {
|
|
|
3317
3584
|
}
|
|
3318
3585
|
};
|
|
3319
3586
|
try {
|
|
3587
|
+
if (parsed.subcommand === "init-catalog") {
|
|
3588
|
+
if (!parsed.target) {
|
|
3589
|
+
writeErr("[wod init-catalog] Error: Missing catalog name (a single new directory name)");
|
|
3590
|
+
return 1;
|
|
3591
|
+
}
|
|
3592
|
+
const { scaffoldCatalog: scaffoldCatalog2 } = await Promise.resolve().then(() => (init_scaffoldCatalog(), scaffoldCatalog_exports));
|
|
3593
|
+
try {
|
|
3594
|
+
const result = scaffoldCatalog2(parsed.target);
|
|
3595
|
+
writeOut(`[wod init-catalog] Created ${result.dir} (${result.files.length} files)`);
|
|
3596
|
+
writeOut(`Next: cd ${parsed.target} && bun install && bunx wod build . --output dist`);
|
|
3597
|
+
return 0;
|
|
3598
|
+
} catch (error) {
|
|
3599
|
+
writeErr(`[wod init-catalog] ${error.message}`);
|
|
3600
|
+
return 1;
|
|
3601
|
+
}
|
|
3602
|
+
}
|
|
3320
3603
|
if (parsed.subcommand === "parse") {
|
|
3321
3604
|
if (!parsed.target) {
|
|
3322
3605
|
writeErr('[wod parse] Error: Missing input file or "-" for stdin');
|