@bitcobblers/wod-wiki-wql 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/index.cjs +227 -228
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -46
- package/dist/index.d.ts +23 -46
- package/dist/index.mjs +229 -227
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -2592,8 +2592,8 @@ function normalizeSummaryFacts(logs, identity) {
|
|
|
2592
2592
|
origin: identity.origin,
|
|
2593
2593
|
pageId: identity.pageId,
|
|
2594
2594
|
grain: "summary",
|
|
2595
|
-
|
|
2596
|
-
|
|
2595
|
+
blockId: identity.blockId ?? "",
|
|
2596
|
+
blockVersion: identity.blockVersion ?? 0,
|
|
2597
2597
|
resultId: identity.resultId,
|
|
2598
2598
|
type: f.metricKey,
|
|
2599
2599
|
value: f.value,
|
|
@@ -2645,8 +2645,8 @@ function toEventRows(logs, identity) {
|
|
|
2645
2645
|
text: output.text,
|
|
2646
2646
|
dialect: output.dialect,
|
|
2647
2647
|
completionReason: output.completionReason,
|
|
2648
|
-
|
|
2649
|
-
|
|
2648
|
+
blockId: identity.blockId,
|
|
2649
|
+
blockVersion: identity.blockVersion
|
|
2650
2650
|
}));
|
|
2651
2651
|
}
|
|
2652
2652
|
function toSummaryEventRows(logs, identity) {
|
|
@@ -2693,8 +2693,8 @@ function toSummaryEventRows(logs, identity) {
|
|
|
2693
2693
|
...f.grade ? { grade: f.grade } : {}
|
|
2694
2694
|
}
|
|
2695
2695
|
}],
|
|
2696
|
-
|
|
2697
|
-
|
|
2696
|
+
blockId: identity.blockId,
|
|
2697
|
+
blockVersion: identity.blockVersion
|
|
2698
2698
|
}));
|
|
2699
2699
|
}
|
|
2700
2700
|
function projectEventToFacts(record) {
|
|
@@ -2713,8 +2713,8 @@ function projectEventToFacts(record) {
|
|
|
2713
2713
|
origin: record.origin,
|
|
2714
2714
|
pageId: record.pageId,
|
|
2715
2715
|
grain: "summary",
|
|
2716
|
-
|
|
2717
|
-
|
|
2716
|
+
blockId: record.blockId ?? "",
|
|
2717
|
+
blockVersion: record.blockVersion ?? 0,
|
|
2718
2718
|
resultId: record.resultId,
|
|
2719
2719
|
type: metricKey,
|
|
2720
2720
|
value: m.value,
|
|
@@ -2772,8 +2772,8 @@ function projectEventToFacts(record) {
|
|
|
2772
2772
|
origin: record.origin,
|
|
2773
2773
|
pageId: record.pageId,
|
|
2774
2774
|
grain: "event",
|
|
2775
|
-
|
|
2776
|
-
|
|
2775
|
+
blockId: record.blockId ?? "",
|
|
2776
|
+
blockVersion: record.blockVersion ?? 0,
|
|
2777
2777
|
resultId: record.resultId,
|
|
2778
2778
|
type: metricKey,
|
|
2779
2779
|
value: m.value,
|
|
@@ -2815,117 +2815,6 @@ function eventsToStoredLogs(events) {
|
|
|
2815
2815
|
}));
|
|
2816
2816
|
}
|
|
2817
2817
|
|
|
2818
|
-
// src/dashboard/frontmatter.ts
|
|
2819
|
-
var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
2820
|
-
function unquote(value) {
|
|
2821
|
-
return value.replace(
|
|
2822
|
-
/^(['"])(.*)\1$/,
|
|
2823
|
-
(_match, quote, inner) => quote === '"' ? inner.replace(/\\(["\\])/g, "$1") : inner
|
|
2824
|
-
);
|
|
2825
|
-
}
|
|
2826
|
-
function parseFrontmatter(raw) {
|
|
2827
|
-
const match = raw.match(FRONTMATTER_RE);
|
|
2828
|
-
if (!match) return { meta: {}, body: raw };
|
|
2829
|
-
return { meta: parseMetaLines(match[1].split(/\r?\n/)), body: raw.slice(match[0].length) };
|
|
2830
|
-
}
|
|
2831
|
-
function parseMetaLines(lines) {
|
|
2832
|
-
const meta = {};
|
|
2833
|
-
for (let i = 0; i < lines.length; i++) {
|
|
2834
|
-
const keyMatch = lines[i].match(/^([A-Za-z][\w.-]*)\s*:(.*)$/);
|
|
2835
|
-
if (!keyMatch) continue;
|
|
2836
|
-
const key = keyMatch[1];
|
|
2837
|
-
const rawVal = keyMatch[2].trim();
|
|
2838
|
-
if (rawVal === "") {
|
|
2839
|
-
const items = [];
|
|
2840
|
-
while (i + 1 < lines.length) {
|
|
2841
|
-
const itemMatch = lines[i + 1].match(/^\s+-\s+(.+)$/);
|
|
2842
|
-
if (!itemMatch) break;
|
|
2843
|
-
items.push(itemMatch[1].trim());
|
|
2844
|
-
i++;
|
|
2845
|
-
}
|
|
2846
|
-
meta[key] = items.length > 0 ? items : "";
|
|
2847
|
-
} else {
|
|
2848
|
-
const wasQuoted = /^(['"])(.*)\1$/.test(rawVal);
|
|
2849
|
-
const value = unquote(rawVal);
|
|
2850
|
-
const num = Number(value);
|
|
2851
|
-
meta[key] = !wasQuoted && value !== "" && !isNaN(num) ? num : value;
|
|
2852
|
-
}
|
|
2853
|
-
}
|
|
2854
|
-
return meta;
|
|
2855
|
-
}
|
|
2856
|
-
function parseFrontmatterBody(innerContent) {
|
|
2857
|
-
return parseMetaLines(innerContent.split(/\r?\n/));
|
|
2858
|
-
}
|
|
2859
|
-
function quoteYamlScalar(value) {
|
|
2860
|
-
if (value === "") return '""';
|
|
2861
|
-
const looksNumeric = !isNaN(Number(value));
|
|
2862
|
-
const looksKeyword = /^(true|false|null|yes|no|on|off)$/i.test(value);
|
|
2863
|
-
if (/[":'\n#{}[\\],&*?|<>=%!@`]/.test(value) || value !== value.trim() || value.startsWith("-") || looksNumeric || looksKeyword) {
|
|
2864
|
-
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
2865
|
-
}
|
|
2866
|
-
return value;
|
|
2867
|
-
}
|
|
2868
|
-
function serializeFrontmatter(meta) {
|
|
2869
|
-
const lines = [];
|
|
2870
|
-
for (const [key, value] of Object.entries(meta)) {
|
|
2871
|
-
if (Array.isArray(value)) {
|
|
2872
|
-
if (value.length === 0) {
|
|
2873
|
-
lines.push(`${key}: ""`);
|
|
2874
|
-
continue;
|
|
2875
|
-
}
|
|
2876
|
-
lines.push(`${key}:`);
|
|
2877
|
-
for (const item of value) {
|
|
2878
|
-
lines.push(` - ${quoteYamlScalar(item)}`);
|
|
2879
|
-
}
|
|
2880
|
-
} else if (typeof value === "number") {
|
|
2881
|
-
lines.push(`${key}: ${value}`);
|
|
2882
|
-
} else {
|
|
2883
|
-
lines.push(`${key}: ${quoteYamlScalar(value)}`);
|
|
2884
|
-
}
|
|
2885
|
-
}
|
|
2886
|
-
return lines.join("\n");
|
|
2887
|
-
}
|
|
2888
|
-
function stripFrontmatter(raw) {
|
|
2889
|
-
return parseFrontmatter(raw).body;
|
|
2890
|
-
}
|
|
2891
|
-
function getScalar(meta, key) {
|
|
2892
|
-
const value = meta[key];
|
|
2893
|
-
return typeof value === "string" || typeof value === "number" ? value : void 0;
|
|
2894
|
-
}
|
|
2895
|
-
function getList(meta, key) {
|
|
2896
|
-
const value = meta[key];
|
|
2897
|
-
return Array.isArray(value) ? value : [];
|
|
2898
|
-
}
|
|
2899
|
-
function parseFrontmatterCategories(raw) {
|
|
2900
|
-
return getList(parseFrontmatter(raw).meta, "category").map((c) => c.toLowerCase());
|
|
2901
|
-
}
|
|
2902
|
-
function extractFrontmatterTags(raw) {
|
|
2903
|
-
const meta = FRONTMATTER_RE.test(raw) ? parseFrontmatter(raw).meta : parseFrontmatterBody(raw);
|
|
2904
|
-
const tags = meta["tags"];
|
|
2905
|
-
const list = Array.isArray(tags) ? tags : typeof tags === "string" && tags.trim() ? tags.trim().startsWith("[") && tags.trim().endsWith("]") ? tags.trim().slice(1, -1).split(",") : [tags] : [];
|
|
2906
|
-
return [...new Set(list.map((tag) => tag.trim()).filter(Boolean))];
|
|
2907
|
-
}
|
|
2908
|
-
function parseFlatProperties(innerContent) {
|
|
2909
|
-
const props = {};
|
|
2910
|
-
for (const line of innerContent.split(/\r?\n/)) {
|
|
2911
|
-
const match = line.match(/^([^:]+):\s*(.*)$/);
|
|
2912
|
-
if (match) {
|
|
2913
|
-
props[match[1].trim()] = match[2].trim();
|
|
2914
|
-
}
|
|
2915
|
-
}
|
|
2916
|
-
return props;
|
|
2917
|
-
}
|
|
2918
|
-
function parseFrontmatterProps(lines) {
|
|
2919
|
-
const props = {};
|
|
2920
|
-
for (const line of lines) {
|
|
2921
|
-
const match = line.match(/^([^:]+):\s*(.*)$/);
|
|
2922
|
-
if (match) {
|
|
2923
|
-
props[match[1].trim()] = match[2].trim();
|
|
2924
|
-
}
|
|
2925
|
-
}
|
|
2926
|
-
return props;
|
|
2927
|
-
}
|
|
2928
|
-
|
|
2929
2818
|
// src/selection.ts
|
|
2930
2819
|
function partitionKey(coverage, effortSlug) {
|
|
2931
2820
|
const tags = coverage?.groupTags ? Object.entries(coverage.groupTags).sort(([a], [b]) => a < b ? -1 : 1).map(([k, v]) => `${k}=${v}`).join(",") : "";
|
|
@@ -3399,7 +3288,6 @@ var QueryService = class {
|
|
|
3399
3288
|
noteStore;
|
|
3400
3289
|
blockStore;
|
|
3401
3290
|
effortStore;
|
|
3402
|
-
staticNoteStore;
|
|
3403
3291
|
pageStore;
|
|
3404
3292
|
relationStore;
|
|
3405
3293
|
datasetStore;
|
|
@@ -3414,14 +3302,13 @@ var QueryService = class {
|
|
|
3414
3302
|
noteTagsStore = {
|
|
3415
3303
|
getAllFromIndex: async () => []
|
|
3416
3304
|
};
|
|
3417
|
-
constructor(storesOrEventStore, noteStore, blockStore, effortStore
|
|
3418
|
-
if (storesOrEventStore && typeof storesOrEventStore === "object" && ("eventStore" in storesOrEventStore || "noteStore" in storesOrEventStore || "blockStore" in storesOrEventStore || "effortStore" in storesOrEventStore || "
|
|
3305
|
+
constructor(storesOrEventStore, noteStore, blockStore, effortStore) {
|
|
3306
|
+
if (storesOrEventStore && typeof storesOrEventStore === "object" && ("eventStore" in storesOrEventStore || "noteStore" in storesOrEventStore || "blockStore" in storesOrEventStore || "effortStore" in storesOrEventStore || "pageStore" in storesOrEventStore || "relationStore" in storesOrEventStore || "datasetStore" in storesOrEventStore)) {
|
|
3419
3307
|
const stores = storesOrEventStore;
|
|
3420
3308
|
this.store = stores.eventStore ?? defaultEventStore;
|
|
3421
3309
|
this.noteStore = stores.noteStore ?? defaultNoteStore;
|
|
3422
3310
|
this.blockStore = stores.blockStore ?? defaultBlockStore;
|
|
3423
3311
|
this.effortStore = stores.effortStore ?? defaultEffortStore;
|
|
3424
|
-
this.staticNoteStore = stores.staticNoteStore;
|
|
3425
3312
|
this.pageStore = stores.pageStore;
|
|
3426
3313
|
this.relationStore = stores.relationStore;
|
|
3427
3314
|
this.datasetStore = stores.datasetStore;
|
|
@@ -3433,7 +3320,6 @@ var QueryService = class {
|
|
|
3433
3320
|
this.noteStore = noteStore ?? defaultNoteStore;
|
|
3434
3321
|
this.blockStore = blockStore ?? defaultBlockStore;
|
|
3435
3322
|
this.effortStore = effortStore ?? defaultEffortStore;
|
|
3436
|
-
this.staticNoteStore = staticNoteStore;
|
|
3437
3323
|
}
|
|
3438
3324
|
}
|
|
3439
3325
|
/** Windowed flat-fact fetch — the projected view over the event store. */
|
|
@@ -3753,14 +3639,11 @@ var QueryService = class {
|
|
|
3753
3639
|
}
|
|
3754
3640
|
const isCatalogHead = parsed.target === "note" && parsed.filters.some((f) => f.key === "type" && !f.negate && f.values.some((v) => v.value === "feed")) && (parsed.filters.some((f) => f.key === "source" && !f.negate && f.values.some((v) => v.value === "feed" || v.value === "feeds")) || parsed.sourceScope?.includes("feeds"));
|
|
3755
3641
|
if (isCatalogHead) {
|
|
3756
|
-
|
|
3757
|
-
this.staticNoteStore ? await this.staticNoteStore.getAllNotes() : []
|
|
3758
|
-
);
|
|
3759
|
-
return this.runFindCatalog(parsed, options2, notes2);
|
|
3642
|
+
return this.runFindCatalog(parsed, options2, await this.noteStore.getAllNotes());
|
|
3760
3643
|
}
|
|
3761
3644
|
const read = compileContentRead(parsed.filters, "note", parsed.sourceScope);
|
|
3762
|
-
const paging = domainPaging(parsed, options2, read.residual
|
|
3763
|
-
const fetchedNotes =
|
|
3645
|
+
const paging = domainPaging(parsed, options2, read.residual);
|
|
3646
|
+
const fetchedNotes = (read.filters.length > 0 || read.selection.length > 0 || paging.paged) && this.noteStore.queryDomain ? await this.noteStore.queryDomain({
|
|
3764
3647
|
plan: "notes",
|
|
3765
3648
|
selection: read.selection,
|
|
3766
3649
|
...read.filters.length ? { filters: read.filters } : {},
|
|
@@ -3772,11 +3655,6 @@ var QueryService = class {
|
|
|
3772
3655
|
let notes = domainNotes ? domainNotes.rows : await this.noteStore.getAllNotes();
|
|
3773
3656
|
const selectedFromDomain = domainNotes ? domainNotes.selectedCount : void 0;
|
|
3774
3657
|
const notesPaged = !!domainNotes && paging.paged;
|
|
3775
|
-
if (this.staticNoteStore) {
|
|
3776
|
-
const staticRows = applyNoteSelectionStages(await this.staticNoteStore.getAllNotes(), parsed);
|
|
3777
|
-
const known = new Set(notes.map((n) => n.id));
|
|
3778
|
-
notes = notes.concat(staticRows.filter((n) => !known.has(n.id)));
|
|
3779
|
-
}
|
|
3780
3658
|
notes = applyNoteSelectionStages(notes, parsed);
|
|
3781
3659
|
const selectedCount = selectedFromDomain ?? notes.length;
|
|
3782
3660
|
const ctx = runContext(options2);
|
|
@@ -3785,16 +3663,13 @@ var QueryService = class {
|
|
|
3785
3663
|
const matchingIds = /* @__PURE__ */ new Set();
|
|
3786
3664
|
for (const v of filter.values) {
|
|
3787
3665
|
const ids = await this.noteStore.getNoteIdsForTag(v.value);
|
|
3788
|
-
const sIds = this.staticNoteStore ? await this.staticNoteStore.getNoteIdsForTag(v.value) : /* @__PURE__ */ new Set();
|
|
3789
3666
|
ids.forEach((id) => matchingIds.add(id));
|
|
3790
|
-
sIds.forEach((id) => matchingIds.add(id));
|
|
3791
3667
|
}
|
|
3792
3668
|
notes = notes.filter((n) => matchingIds.has(n.id));
|
|
3793
3669
|
} else if (filter.key === "tags" && filter.negate) {
|
|
3794
3670
|
for (const v of filter.values) {
|
|
3795
3671
|
const ids = await this.noteStore.getNoteIdsForTag(v.value);
|
|
3796
|
-
|
|
3797
|
-
notes = notes.filter((n) => !ids.has(n.id) && !sIds.has(n.id));
|
|
3672
|
+
notes = notes.filter((n) => !ids.has(n.id));
|
|
3798
3673
|
}
|
|
3799
3674
|
} else if (filter.key === "effort" && !filter.negate) {
|
|
3800
3675
|
const matchingIds = /* @__PURE__ */ new Set();
|
|
@@ -3813,9 +3688,12 @@ var QueryService = class {
|
|
|
3813
3688
|
}
|
|
3814
3689
|
}
|
|
3815
3690
|
for (const filter of parsed.filters) {
|
|
3816
|
-
if (filter.key === "text"
|
|
3691
|
+
if (filter.key === "text") {
|
|
3817
3692
|
const search = filter.values.map((v) => v.value).join(" ").toLowerCase();
|
|
3818
|
-
notes = notes.filter((n) =>
|
|
3693
|
+
notes = notes.filter((n) => {
|
|
3694
|
+
const hit = n.title.toLowerCase().includes(search) || n.rawContent.toLowerCase().includes(search);
|
|
3695
|
+
return filter.negate ? !hit : hit;
|
|
3696
|
+
});
|
|
3819
3697
|
}
|
|
3820
3698
|
}
|
|
3821
3699
|
for (const filter of parsed.filters) {
|
|
@@ -3912,6 +3790,26 @@ var QueryService = class {
|
|
|
3912
3790
|
}
|
|
3913
3791
|
return containers;
|
|
3914
3792
|
}
|
|
3793
|
+
async hydrateBlocks(rows) {
|
|
3794
|
+
const ids = [...new Set(rows.map((row) => row.noteId))];
|
|
3795
|
+
if (ids.length === 0) return [];
|
|
3796
|
+
const notes = this.noteStore.getNotesByIds ? await this.noteStore.getNotesByIds(ids) : await this.noteStore.getAllNotes();
|
|
3797
|
+
const parents = /* @__PURE__ */ new Map();
|
|
3798
|
+
for (const note of notes) {
|
|
3799
|
+
if (!Number.isSafeInteger(note.sourceRevision) || note.sourceRevision < 1) continue;
|
|
3800
|
+
try {
|
|
3801
|
+
wodWikiCore.validateNoteBlocks(note.rawContent, note.blocks, note.sourceRevision);
|
|
3802
|
+
parents.set(note.id, note);
|
|
3803
|
+
} catch {
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
return rows.flatMap((row) => {
|
|
3807
|
+
const note = parents.get(row.noteId);
|
|
3808
|
+
const block = note?.blocks[row.blockId];
|
|
3809
|
+
if (!note || !block || row.id !== `${note.id}:${block.id}` || block.id !== row.blockId || block.kind !== row.dataType || block.version !== row.blockVersion || block.sourceRevision !== row.sourceRevision || note.sourceRevision !== row.sourceRevision || block.from !== row.from || block.to !== row.to) return [];
|
|
3810
|
+
return [{ ...row, rawContent: note.rawContent.slice(block.from, block.to) }];
|
|
3811
|
+
});
|
|
3812
|
+
}
|
|
3915
3813
|
/**
|
|
3916
3814
|
* Execute a :block query against the derived block_index store.
|
|
3917
3815
|
*/
|
|
@@ -3927,17 +3825,20 @@ var QueryService = class {
|
|
|
3927
3825
|
...paging.limit !== void 0 ? { limit: paging.limit } : {}
|
|
3928
3826
|
}) : void 0;
|
|
3929
3827
|
const domainBlocks = fetchedBlocks && fetchedBlocks.plan === "blocks" ? fetchedBlocks : void 0;
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
const
|
|
3828
|
+
const candidates = domainBlocks ? domainBlocks.rows : await this.blockStore.getAllBlocks();
|
|
3829
|
+
let blocks = await this.hydrateBlocks(candidates);
|
|
3830
|
+
const invalidCandidates = blocks.length !== candidates.length;
|
|
3831
|
+
const selectedFromDomain = domainBlocks && !invalidCandidates ? domainBlocks.selectedCount : void 0;
|
|
3832
|
+
const blocksPaged = !!domainBlocks && paging.paged && !invalidCandidates;
|
|
3833
|
+
if (domainBlocks && invalidCandidates) blocks = await this.hydrateBlocks(await this.blockStore.getAllBlocks());
|
|
3933
3834
|
blocks = applySourceFilter(blocks, parsed.filters);
|
|
3934
3835
|
blocks = blocks.filter((b) => !b.sourceId || WQL_SOURCE_VALUES.some((k) => sourceMatches(b, k)));
|
|
3935
3836
|
const selectedCount = selectedFromDomain ?? blocks.length;
|
|
3936
3837
|
const ctx = runContext(options2);
|
|
3937
3838
|
for (const filter of parsed.filters) {
|
|
3938
|
-
if (filter.key === "text"
|
|
3839
|
+
if (filter.key === "text") {
|
|
3939
3840
|
const search = filter.values.map((v) => v.value).join(" ").toLowerCase();
|
|
3940
|
-
blocks = blocks.filter((b) => b.rawContent.toLowerCase().includes(search));
|
|
3841
|
+
blocks = blocks.filter((b) => filter.negate !== b.rawContent.toLowerCase().includes(search));
|
|
3941
3842
|
}
|
|
3942
3843
|
}
|
|
3943
3844
|
for (const filter of parsed.filters) {
|
|
@@ -3962,18 +3863,16 @@ var QueryService = class {
|
|
|
3962
3863
|
const matchingNoteIds = /* @__PURE__ */ new Set();
|
|
3963
3864
|
for (const v of filter.values) {
|
|
3964
3865
|
const ids = await this.noteStore.getNoteIdsForTag(v.value);
|
|
3965
|
-
const sIds = this.staticNoteStore ? await this.staticNoteStore.getNoteIdsForTag(v.value) : /* @__PURE__ */ new Set();
|
|
3966
3866
|
ids.forEach((id) => matchingNoteIds.add(id));
|
|
3967
|
-
sIds.forEach((id) => matchingNoteIds.add(id));
|
|
3968
3867
|
}
|
|
3969
3868
|
blocks = blocks.filter((b) => matchingNoteIds.has(b.noteId));
|
|
3970
3869
|
} else if (filter.key === "effort" && !filter.negate) {
|
|
3971
3870
|
const matchingBlockIds = /* @__PURE__ */ new Set();
|
|
3972
3871
|
for (const v of filter.values) {
|
|
3973
3872
|
const rows = await this.blockEffortsStore.getAllFromIndex("by-effort", v.value);
|
|
3974
|
-
for (const
|
|
3873
|
+
for (const row of rows) matchingBlockIds.add(`${row.noteId}:${row.blockId}`);
|
|
3975
3874
|
}
|
|
3976
|
-
blocks = blocks.filter((
|
|
3875
|
+
blocks = blocks.filter((block) => matchingBlockIds.has(`${block.noteId}:${block.blockId}`));
|
|
3977
3876
|
}
|
|
3978
3877
|
}
|
|
3979
3878
|
for (const filter of parsed.filters) {
|
|
@@ -3983,11 +3882,7 @@ var QueryService = class {
|
|
|
3983
3882
|
}
|
|
3984
3883
|
}
|
|
3985
3884
|
if (parsed.window || options2.range) {
|
|
3986
|
-
|
|
3987
|
-
allNotes = allNotes.concat(await this.noteStore.getAllNotes());
|
|
3988
|
-
if (this.staticNoteStore) {
|
|
3989
|
-
allNotes = allNotes.concat(await this.staticNoteStore.getAllNotes());
|
|
3990
|
-
}
|
|
3885
|
+
const allNotes = await this.noteStore.getAllNotes();
|
|
3991
3886
|
const noteTimeMap = new Map(allNotes.map((n) => [n.id, n.date ?? n.createdAt]));
|
|
3992
3887
|
blocks = blocks.filter((b) => effectiveTimeWindow(noteTimeMap.get(b.noteId) ?? b.createdAt, parsed.window, options2.range, ctx));
|
|
3993
3888
|
}
|
|
@@ -4365,7 +4260,7 @@ var QueryService = class {
|
|
|
4365
4260
|
let values;
|
|
4366
4261
|
try {
|
|
4367
4262
|
values = members.map(
|
|
4368
|
-
(m) => shouldConvert && targetUnit ? wodWikiCore.convertViaCatalog(m.value, m.unit ?? m.metricUnit, targetUnit) : m.value
|
|
4263
|
+
(m) => shouldConvert && targetUnit && (m.unit ?? m.metricUnit) !== void 0 ? wodWikiCore.convertViaCatalog(m.value, m.unit ?? m.metricUnit, targetUnit) : m.value
|
|
4369
4264
|
);
|
|
4370
4265
|
} catch (e) {
|
|
4371
4266
|
error = e instanceof Error ? e.message : String(e);
|
|
@@ -4487,7 +4382,7 @@ var QueryService = class {
|
|
|
4487
4382
|
}
|
|
4488
4383
|
/** All content blocks — journal and seeded corpus in one store. */
|
|
4489
4384
|
async allContentBlocks() {
|
|
4490
|
-
return this.blockStore.getAllBlocks();
|
|
4385
|
+
return this.hydrateBlocks(await this.blockStore.getAllBlocks());
|
|
4491
4386
|
}
|
|
4492
4387
|
/** Map each note id to the wod blockContentIds it owns. */
|
|
4493
4388
|
async noteContentMap(noteIds) {
|
|
@@ -4564,7 +4459,10 @@ var QueryService = class {
|
|
|
4564
4459
|
type: "feed",
|
|
4565
4460
|
sourceId: `page:collection:${cat}`,
|
|
4566
4461
|
catalog: cat,
|
|
4567
|
-
createdAt: n.createdAt ?? 0
|
|
4462
|
+
createdAt: n.createdAt ?? 0,
|
|
4463
|
+
rawContent: "",
|
|
4464
|
+
sourceRevision: 1,
|
|
4465
|
+
blocks: {}
|
|
4568
4466
|
});
|
|
4569
4467
|
existingCatIds.add(cat);
|
|
4570
4468
|
}
|
|
@@ -4613,9 +4511,7 @@ var QueryService = class {
|
|
|
4613
4511
|
const matchingIds = /* @__PURE__ */ new Set();
|
|
4614
4512
|
for (const v of filter.values) {
|
|
4615
4513
|
const ids = await this.noteStore.getNoteIdsForTag(v.value);
|
|
4616
|
-
const sIds = this.staticNoteStore ? await this.staticNoteStore.getNoteIdsForTag(v.value) : /* @__PURE__ */ new Set();
|
|
4617
4514
|
ids.forEach((id) => matchingIds.add(id));
|
|
4618
|
-
sIds.forEach((id) => matchingIds.add(id));
|
|
4619
4515
|
}
|
|
4620
4516
|
matchingCatalogs = matchingCatalogs.filter((c) => {
|
|
4621
4517
|
const catId = catalogOfItem(c) ?? c.id;
|
|
@@ -4640,7 +4536,7 @@ var QueryService = class {
|
|
|
4640
4536
|
matchingCatalogs = matchingCatalogs.filter((c) => {
|
|
4641
4537
|
const catId = catalogOfItem(c) ?? c.id;
|
|
4642
4538
|
const members = membersByCat.get(catId) ?? [];
|
|
4643
|
-
const hit = members.some((m) => m.title.toLowerCase().includes(search));
|
|
4539
|
+
const hit = members.some((m) => m.title.toLowerCase().includes(search) || m.rawContent.toLowerCase().includes(search));
|
|
4644
4540
|
return filter.negate ? !hit : hit;
|
|
4645
4541
|
});
|
|
4646
4542
|
} else if (filter.key === "note") {
|
|
@@ -4680,56 +4576,6 @@ var QueryService = class {
|
|
|
4680
4576
|
}
|
|
4681
4577
|
};
|
|
4682
4578
|
|
|
4683
|
-
// src/static.ts
|
|
4684
|
-
function staticCatalogRoute(block) {
|
|
4685
|
-
const sourceId = block.sourceId;
|
|
4686
|
-
if (sourceId?.startsWith("page:collection:")) {
|
|
4687
|
-
const catalog = sourceId.slice("page:collection:".length);
|
|
4688
|
-
if (catalog) return { landing: true, catalog, sourceId };
|
|
4689
|
-
} else if (sourceId?.startsWith("collection:")) {
|
|
4690
|
-
const route = sourceId.slice("collection:".length);
|
|
4691
|
-
if (route) {
|
|
4692
|
-
const slash = route.indexOf("/");
|
|
4693
|
-
return slash === -1 ? { landing: true, catalog: route, sourceId: `page:collection:${route}` } : { landing: false, catalog: route.slice(0, slash), sourceId };
|
|
4694
|
-
}
|
|
4695
|
-
} else if (sourceId?.startsWith("feed:")) {
|
|
4696
|
-
const route = sourceId.slice("feed:".length);
|
|
4697
|
-
if (route) {
|
|
4698
|
-
const stem = route.startsWith("feeds/") ? route.slice("feeds/".length) : route;
|
|
4699
|
-
return { landing: false, catalog: stem.split("/")[0], sourceId };
|
|
4700
|
-
}
|
|
4701
|
-
}
|
|
4702
|
-
return { landing: false, catalog: catalogOfItem({ noteId: block.noteId, sourceId: block.sourceId }), sourceId };
|
|
4703
|
-
}
|
|
4704
|
-
function staticNotesFromBlocks(blocks) {
|
|
4705
|
-
const map = /* @__PURE__ */ new Map();
|
|
4706
|
-
for (const block of blocks) {
|
|
4707
|
-
if (map.has(block.noteId)) continue;
|
|
4708
|
-
const route = staticCatalogRoute(block);
|
|
4709
|
-
map.set(block.noteId, {
|
|
4710
|
-
id: block.noteId,
|
|
4711
|
-
title: block.noteTitle,
|
|
4712
|
-
createdAt: block.createdAt,
|
|
4713
|
-
type: route.landing ? "feed" : "note",
|
|
4714
|
-
sourceId: route.sourceId,
|
|
4715
|
-
catalog: route.catalog
|
|
4716
|
-
});
|
|
4717
|
-
}
|
|
4718
|
-
return Array.from(map.values());
|
|
4719
|
-
}
|
|
4720
|
-
function staticTagIndexFromBlocks(blocks) {
|
|
4721
|
-
const index = /* @__PURE__ */ new Map();
|
|
4722
|
-
for (const block of blocks) {
|
|
4723
|
-
if (block.dataType !== "frontmatter") continue;
|
|
4724
|
-
for (const tag of extractFrontmatterTags(block.rawContent)) {
|
|
4725
|
-
const ids = index.get(tag);
|
|
4726
|
-
if (ids) ids.add(block.noteId);
|
|
4727
|
-
else index.set(tag, /* @__PURE__ */ new Set([block.noteId]));
|
|
4728
|
-
}
|
|
4729
|
-
}
|
|
4730
|
-
return index;
|
|
4731
|
-
}
|
|
4732
|
-
|
|
4733
4579
|
// src/dashboard/model.ts
|
|
4734
4580
|
var DASHBOARD_WIDGET_TYPES = [
|
|
4735
4581
|
"table",
|
|
@@ -4918,6 +4764,117 @@ function buildDashboardDocument(sections, meta) {
|
|
|
4918
4764
|
};
|
|
4919
4765
|
}
|
|
4920
4766
|
|
|
4767
|
+
// src/dashboard/frontmatter.ts
|
|
4768
|
+
var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
4769
|
+
function unquote(value) {
|
|
4770
|
+
return value.replace(
|
|
4771
|
+
/^(['"])(.*)\1$/,
|
|
4772
|
+
(_match, quote, inner) => quote === '"' ? inner.replace(/\\(["\\])/g, "$1") : inner
|
|
4773
|
+
);
|
|
4774
|
+
}
|
|
4775
|
+
function parseFrontmatter(raw) {
|
|
4776
|
+
const match = raw.match(FRONTMATTER_RE);
|
|
4777
|
+
if (!match) return { meta: {}, body: raw };
|
|
4778
|
+
return { meta: parseMetaLines(match[1].split(/\r?\n/)), body: raw.slice(match[0].length) };
|
|
4779
|
+
}
|
|
4780
|
+
function parseMetaLines(lines) {
|
|
4781
|
+
const meta = {};
|
|
4782
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4783
|
+
const keyMatch = lines[i].match(/^([A-Za-z][\w.-]*)\s*:(.*)$/);
|
|
4784
|
+
if (!keyMatch) continue;
|
|
4785
|
+
const key = keyMatch[1];
|
|
4786
|
+
const rawVal = keyMatch[2].trim();
|
|
4787
|
+
if (rawVal === "") {
|
|
4788
|
+
const items = [];
|
|
4789
|
+
while (i + 1 < lines.length) {
|
|
4790
|
+
const itemMatch = lines[i + 1].match(/^\s+-\s+(.+)$/);
|
|
4791
|
+
if (!itemMatch) break;
|
|
4792
|
+
items.push(itemMatch[1].trim());
|
|
4793
|
+
i++;
|
|
4794
|
+
}
|
|
4795
|
+
meta[key] = items.length > 0 ? items : "";
|
|
4796
|
+
} else {
|
|
4797
|
+
const wasQuoted = /^(['"])(.*)\1$/.test(rawVal);
|
|
4798
|
+
const value = unquote(rawVal);
|
|
4799
|
+
const num = Number(value);
|
|
4800
|
+
meta[key] = !wasQuoted && value !== "" && !isNaN(num) ? num : value;
|
|
4801
|
+
}
|
|
4802
|
+
}
|
|
4803
|
+
return meta;
|
|
4804
|
+
}
|
|
4805
|
+
function parseFrontmatterBody(innerContent) {
|
|
4806
|
+
return parseMetaLines(innerContent.split(/\r?\n/));
|
|
4807
|
+
}
|
|
4808
|
+
function quoteYamlScalar(value) {
|
|
4809
|
+
if (value === "") return '""';
|
|
4810
|
+
const looksNumeric = !isNaN(Number(value));
|
|
4811
|
+
const looksKeyword = /^(true|false|null|yes|no|on|off)$/i.test(value);
|
|
4812
|
+
if (/[":'\n#{}[\\],&*?|<>=%!@`]/.test(value) || value !== value.trim() || value.startsWith("-") || looksNumeric || looksKeyword) {
|
|
4813
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
4814
|
+
}
|
|
4815
|
+
return value;
|
|
4816
|
+
}
|
|
4817
|
+
function serializeFrontmatter(meta) {
|
|
4818
|
+
const lines = [];
|
|
4819
|
+
for (const [key, value] of Object.entries(meta)) {
|
|
4820
|
+
if (Array.isArray(value)) {
|
|
4821
|
+
if (value.length === 0) {
|
|
4822
|
+
lines.push(`${key}: ""`);
|
|
4823
|
+
continue;
|
|
4824
|
+
}
|
|
4825
|
+
lines.push(`${key}:`);
|
|
4826
|
+
for (const item of value) {
|
|
4827
|
+
lines.push(` - ${quoteYamlScalar(item)}`);
|
|
4828
|
+
}
|
|
4829
|
+
} else if (typeof value === "number") {
|
|
4830
|
+
lines.push(`${key}: ${value}`);
|
|
4831
|
+
} else {
|
|
4832
|
+
lines.push(`${key}: ${quoteYamlScalar(value)}`);
|
|
4833
|
+
}
|
|
4834
|
+
}
|
|
4835
|
+
return lines.join("\n");
|
|
4836
|
+
}
|
|
4837
|
+
function stripFrontmatter(raw) {
|
|
4838
|
+
return parseFrontmatter(raw).body;
|
|
4839
|
+
}
|
|
4840
|
+
function getScalar(meta, key) {
|
|
4841
|
+
const value = meta[key];
|
|
4842
|
+
return typeof value === "string" || typeof value === "number" ? value : void 0;
|
|
4843
|
+
}
|
|
4844
|
+
function getList(meta, key) {
|
|
4845
|
+
const value = meta[key];
|
|
4846
|
+
return Array.isArray(value) ? value : [];
|
|
4847
|
+
}
|
|
4848
|
+
function parseFrontmatterCategories(raw) {
|
|
4849
|
+
return getList(parseFrontmatter(raw).meta, "category").map((c) => c.toLowerCase());
|
|
4850
|
+
}
|
|
4851
|
+
function extractFrontmatterTags(raw) {
|
|
4852
|
+
const meta = FRONTMATTER_RE.test(raw) ? parseFrontmatter(raw).meta : parseFrontmatterBody(raw);
|
|
4853
|
+
const tags = meta["tags"];
|
|
4854
|
+
const list = Array.isArray(tags) ? tags : typeof tags === "string" && tags.trim() ? tags.trim().startsWith("[") && tags.trim().endsWith("]") ? tags.trim().slice(1, -1).split(",") : [tags] : [];
|
|
4855
|
+
return [...new Set(list.map((tag) => tag.trim()).filter(Boolean))];
|
|
4856
|
+
}
|
|
4857
|
+
function parseFlatProperties(innerContent) {
|
|
4858
|
+
const props = {};
|
|
4859
|
+
for (const line of innerContent.split(/\r?\n/)) {
|
|
4860
|
+
const match = line.match(/^([^:]+):\s*(.*)$/);
|
|
4861
|
+
if (match) {
|
|
4862
|
+
props[match[1].trim()] = match[2].trim();
|
|
4863
|
+
}
|
|
4864
|
+
}
|
|
4865
|
+
return props;
|
|
4866
|
+
}
|
|
4867
|
+
function parseFrontmatterProps(lines) {
|
|
4868
|
+
const props = {};
|
|
4869
|
+
for (const line of lines) {
|
|
4870
|
+
const match = line.match(/^([^:]+):\s*(.*)$/);
|
|
4871
|
+
if (match) {
|
|
4872
|
+
props[match[1].trim()] = match[2].trim();
|
|
4873
|
+
}
|
|
4874
|
+
}
|
|
4875
|
+
return props;
|
|
4876
|
+
}
|
|
4877
|
+
|
|
4921
4878
|
// src/dashboard/parser.ts
|
|
4922
4879
|
function parseDashboardNote(rawContent) {
|
|
4923
4880
|
const { meta } = parseFrontmatter(rawContent);
|
|
@@ -5122,6 +5079,44 @@ function appendWidget(raw, spec) {
|
|
|
5122
5079
|
while (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
|
|
5123
5080
|
return [...lines, "", ...group, ""].join("\n");
|
|
5124
5081
|
}
|
|
5082
|
+
function widgetResult(raw, note, order) {
|
|
5083
|
+
let from = 0;
|
|
5084
|
+
while (from < raw.length && from < note.length && raw[from] === note[from]) from++;
|
|
5085
|
+
let to = raw.length;
|
|
5086
|
+
let nextTo = note.length;
|
|
5087
|
+
while (to > from && nextTo > from && raw[to - 1] === note[nextTo - 1]) {
|
|
5088
|
+
to--;
|
|
5089
|
+
nextTo--;
|
|
5090
|
+
}
|
|
5091
|
+
const queries = parseDashboardNote(raw).sections.filter((section) => section.type === "query");
|
|
5092
|
+
const nextQueries = parseDashboardNote(note).sections.filter((section) => section.type === "query");
|
|
5093
|
+
const oldOffsets = lineOffsets(raw);
|
|
5094
|
+
const nextOffsets = lineOffsets(note);
|
|
5095
|
+
const oldLines = raw.split("\n");
|
|
5096
|
+
const nextLines = note.split("\n");
|
|
5097
|
+
const retainedBlocks = [];
|
|
5098
|
+
for (const [nextIndex, oldIndex] of (order ?? queries.map((_, index) => index)).entries()) {
|
|
5099
|
+
if (oldIndex === null) continue;
|
|
5100
|
+
const block = queries[oldIndex];
|
|
5101
|
+
const next = nextQueries[nextIndex];
|
|
5102
|
+
if (!block || !next) throw new Error("Widget mutation lost its source lineage");
|
|
5103
|
+
retainedBlocks.push({
|
|
5104
|
+
from: oldOffsets[block.startLine],
|
|
5105
|
+
to: oldOffsets[block.endLine] + oldLines[block.endLine].replace(/\r$/, "").length,
|
|
5106
|
+
nextFrom: nextOffsets[next.startLine],
|
|
5107
|
+
nextTo: nextOffsets[next.endLine] + nextLines[next.endLine].replace(/\r$/, "").length
|
|
5108
|
+
});
|
|
5109
|
+
}
|
|
5110
|
+
return { ok: true, note, changes: raw === note ? [] : [{ from, to, insert: note.slice(from, nextTo) }], retainedBlocks };
|
|
5111
|
+
}
|
|
5112
|
+
function lineOffsets(raw) {
|
|
5113
|
+
let offset = 0;
|
|
5114
|
+
return raw.split("\n").map((line) => {
|
|
5115
|
+
const from = offset;
|
|
5116
|
+
offset += line.length + 1;
|
|
5117
|
+
return from;
|
|
5118
|
+
});
|
|
5119
|
+
}
|
|
5125
5120
|
function updateWidget(raw, key, expectedBody, spec) {
|
|
5126
5121
|
const { sections } = parseDashboardNote(raw);
|
|
5127
5122
|
const found = findWidgetGroup(sections, key, expectedBody);
|
|
@@ -5129,7 +5124,7 @@ function updateWidget(raw, key, expectedBody, spec) {
|
|
|
5129
5124
|
const { group } = found;
|
|
5130
5125
|
const lines = raw.split("\n");
|
|
5131
5126
|
lines.splice(group.startLine, group.endLine - group.startLine + 1, ...renderWidgetGroup(spec));
|
|
5132
|
-
return
|
|
5127
|
+
return widgetResult(raw, lines.join("\n"));
|
|
5133
5128
|
}
|
|
5134
5129
|
function duplicateWidget(raw, key, expectedBody) {
|
|
5135
5130
|
const { sections } = parseDashboardNote(raw);
|
|
@@ -5139,7 +5134,9 @@ function duplicateWidget(raw, key, expectedBody) {
|
|
|
5139
5134
|
const lines = raw.split("\n");
|
|
5140
5135
|
const copy = lines.slice(group.startLine, group.endLine + 1);
|
|
5141
5136
|
lines.splice(group.endLine + 1, 0, "", ...copy);
|
|
5142
|
-
|
|
5137
|
+
const order = sections.filter((section) => section.type === "query").map((_, index) => index);
|
|
5138
|
+
order.splice(group.widgetIndex + 1, 0, null);
|
|
5139
|
+
return widgetResult(raw, lines.join("\n"), order);
|
|
5143
5140
|
}
|
|
5144
5141
|
function removeWidget(raw, key, expectedBody) {
|
|
5145
5142
|
const { sections } = parseDashboardNote(raw);
|
|
@@ -5151,7 +5148,9 @@ function removeWidget(raw, key, expectedBody) {
|
|
|
5151
5148
|
if (group.startLine > 0 && group.startLine < lines.length && lines[group.startLine - 1] === "" && lines[group.startLine] === "") {
|
|
5152
5149
|
lines.splice(group.startLine, 1);
|
|
5153
5150
|
}
|
|
5154
|
-
|
|
5151
|
+
const order = sections.filter((section) => section.type === "query").map((_, index) => index);
|
|
5152
|
+
order.splice(group.widgetIndex, 1);
|
|
5153
|
+
return widgetResult(raw, lines.join("\n"), order);
|
|
5155
5154
|
}
|
|
5156
5155
|
function moveWidget(raw, key, expectedBody, delta) {
|
|
5157
5156
|
const { sections } = parseDashboardNote(raw);
|
|
@@ -5160,7 +5159,7 @@ function moveWidget(raw, key, expectedBody, delta) {
|
|
|
5160
5159
|
const { group } = found;
|
|
5161
5160
|
const groups = widgetGroupRanges(sections);
|
|
5162
5161
|
const neighbor = groups[group.widgetIndex + delta];
|
|
5163
|
-
if (!neighbor) return
|
|
5162
|
+
if (!neighbor) return widgetResult(raw, raw);
|
|
5164
5163
|
const lines = raw.split("\n");
|
|
5165
5164
|
const moving = lines.slice(group.startLine, group.endLine + 1);
|
|
5166
5165
|
if (delta === -1) {
|
|
@@ -5172,7 +5171,10 @@ function moveWidget(raw, key, expectedBody, delta) {
|
|
|
5172
5171
|
const insertAt = neighbor.endLine - shift + 1;
|
|
5173
5172
|
lines.splice(insertAt, 0, ...moving);
|
|
5174
5173
|
}
|
|
5175
|
-
|
|
5174
|
+
const order = groups.map((_, index) => index);
|
|
5175
|
+
order.splice(group.widgetIndex, 1);
|
|
5176
|
+
order.splice(group.widgetIndex + delta, 0, group.widgetIndex);
|
|
5177
|
+
return widgetResult(raw, lines.join("\n"), order);
|
|
5176
5178
|
}
|
|
5177
5179
|
function resizeWidget(raw, key, expectedBody, span) {
|
|
5178
5180
|
if (span.spanCols != null && (span.spanCols < 1 || span.spanCols > DASHBOARD_GRID_MAX_COLS)) {
|
|
@@ -5194,7 +5196,7 @@ function resizeWidget(raw, key, expectedBody, span) {
|
|
|
5194
5196
|
attributes: block.attributes,
|
|
5195
5197
|
attributeOrder: block.attributeOrder
|
|
5196
5198
|
});
|
|
5197
|
-
return
|
|
5199
|
+
return widgetResult(raw, lines.join("\n"));
|
|
5198
5200
|
}
|
|
5199
5201
|
function migrateLegacyDashboardBodies(raw) {
|
|
5200
5202
|
let out = raw;
|
|
@@ -5215,13 +5217,13 @@ ${query}
|
|
|
5215
5217
|
}
|
|
5216
5218
|
|
|
5217
5219
|
// src/version.ts
|
|
5218
|
-
var VERSION = "0.35.
|
|
5219
|
-
var GIT_SHA = "
|
|
5220
|
-
var BUILD_TIME = "2026-10-
|
|
5220
|
+
var VERSION = "0.35.2117";
|
|
5221
|
+
var GIT_SHA = "03d1dfc";
|
|
5222
|
+
var BUILD_TIME = "2026-10-12T20:08:12.374Z";
|
|
5221
5223
|
var SEMVER = {
|
|
5222
|
-
version: "0.35.
|
|
5223
|
-
gitSha: "
|
|
5224
|
-
buildTime: "2026-10-
|
|
5224
|
+
version: "0.35.2117",
|
|
5225
|
+
gitSha: "03d1dfc",
|
|
5226
|
+
buildTime: "2026-10-12T20:08:12.374Z"
|
|
5225
5227
|
};
|
|
5226
5228
|
|
|
5227
5229
|
Object.defineProperty(exports, "SYSTEM_DEFAULT_OUTPUT_UNIT", {
|
|
@@ -5356,9 +5358,6 @@ exports.serializeFrontmatter = serializeFrontmatter;
|
|
|
5356
5358
|
exports.setDashboardTokenValue = setDashboardTokenValue;
|
|
5357
5359
|
exports.sourceMatches = sourceMatches;
|
|
5358
5360
|
exports.splitAtWhere = splitAtWhere;
|
|
5359
|
-
exports.staticCatalogRoute = staticCatalogRoute;
|
|
5360
|
-
exports.staticNotesFromBlocks = staticNotesFromBlocks;
|
|
5361
|
-
exports.staticTagIndexFromBlocks = staticTagIndexFromBlocks;
|
|
5362
5361
|
exports.stripFrontmatter = stripFrontmatter;
|
|
5363
5362
|
exports.substituteTokens = substituteTokens2;
|
|
5364
5363
|
exports.substituteTokensRaw = substituteTokens;
|