@openparachute/vault 0.7.3-rc.7 → 0.7.3-rc.8
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.
|
@@ -83,6 +83,47 @@ describe("computeDisplayTitle", () => {
|
|
|
83
83
|
const result = computeDisplayTitle(emojiTitle)!;
|
|
84
84
|
expect(Array.from(result).length).toBe(DISPLAY_TITLE_MAX_LEN);
|
|
85
85
|
});
|
|
86
|
+
|
|
87
|
+
describe("leading frontmatter block (misuse path — direct create with raw frontmatter)", () => {
|
|
88
|
+
it("skips a closed frontmatter block and derives the first line of the DOCUMENT", () => {
|
|
89
|
+
expect(computeDisplayTitle("---\ntitle: X\n---\n# Real Title")).toBe("Real Title");
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("skips a closed frontmatter block with multiple fields + blank lines after", () => {
|
|
93
|
+
expect(
|
|
94
|
+
computeDisplayTitle("---\ntitle: X\ntags: [a, b]\n---\n\n\nReal Title\nbody"),
|
|
95
|
+
).toBe("Real Title");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("falls back to treating an UNTERMINATED opening `---` as ordinary content", () => {
|
|
99
|
+
// No closing fence anywhere in the content — a note whose real first
|
|
100
|
+
// line is literally "---" (e.g. a markdown horizontal rule opener)
|
|
101
|
+
// must not be mangled.
|
|
102
|
+
expect(computeDisplayTitle("---\nnot frontmatter, just a rule\nmore text")).toBe("---");
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("returns null when content is EXACTLY a closed frontmatter block (nothing after)", () => {
|
|
106
|
+
expect(computeDisplayTitle("---\ntitle: X\n---\n")).toBeNull();
|
|
107
|
+
expect(computeDisplayTitle("---\ntitle: X\n---")).toBeNull();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("returns null when only blank lines follow a closed frontmatter block", () => {
|
|
111
|
+
expect(computeDisplayTitle("---\ntitle: X\n---\n\n \n")).toBeNull();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("does not treat a closing fence found past the bounded scan window as a frontmatter close", () => {
|
|
115
|
+
// Opening `---` with the closing fence past FRONTMATTER_SCAN_LINES
|
|
116
|
+
// (100): the scan gives up and falls back to ordinary-content
|
|
117
|
+
// behavior, deriving from line 0.
|
|
118
|
+
const filler = Array.from({ length: 150 }, (_, i) => `line ${i}`).join("\n");
|
|
119
|
+
expect(computeDisplayTitle(`---\n${filler}\n---\nReal Title`)).toBe("---");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("normal content with no leading `---` is byte-identical to prior behavior", () => {
|
|
123
|
+
expect(computeDisplayTitle("# Grocery List\nmilk, eggs")).toBe("Grocery List");
|
|
124
|
+
expect(computeDisplayTitle("Just a note\nbody text")).toBe("Just a note");
|
|
125
|
+
});
|
|
126
|
+
});
|
|
86
127
|
});
|
|
87
128
|
|
|
88
129
|
describe("toNoteIndex — displayTitle wiring", () => {
|
package/core/src/notes.ts
CHANGED
|
@@ -2769,6 +2769,15 @@ export const NOTE_INDEX_PREVIEW_LEN = 120;
|
|
|
2769
2769
|
/** Max code points in a computed `displayTitle` (title axis, ratified 2026-07-17). */
|
|
2770
2770
|
export const DISPLAY_TITLE_MAX_LEN = 120;
|
|
2771
2771
|
|
|
2772
|
+
/**
|
|
2773
|
+
* Bounded line-count a leading frontmatter block's closing fence is
|
|
2774
|
+
* searched within (see `computeDisplayTitle`). Frontmatter blocks are a
|
|
2775
|
+
* handful of lines in practice; capping the scan keeps a pathological
|
|
2776
|
+
* "content starts with `---` but never closes it" note O(1)-ish rather
|
|
2777
|
+
* than a full-content scan on every derivation.
|
|
2778
|
+
*/
|
|
2779
|
+
const FRONTMATTER_SCAN_LINES = 100;
|
|
2780
|
+
|
|
2772
2781
|
/**
|
|
2773
2782
|
* Derive a note's display title: the first non-empty line of `content`,
|
|
2774
2783
|
* with a leading markdown heading marker (`#` through `######`) and its
|
|
@@ -2783,11 +2792,33 @@ export const DISPLAY_TITLE_MAX_LEN = 120;
|
|
|
2783
2792
|
* in place of a `null` title — is deliberately NOT this function's job; it
|
|
2784
2793
|
* reports the honest content-derived value (or its absence) and leaves
|
|
2785
2794
|
* rendering to the caller.
|
|
2795
|
+
*
|
|
2796
|
+
* Frontmatter skip: normal ingestion strips a YAML frontmatter block into
|
|
2797
|
+
* `metadata` before create, so `content` never carries one — but a direct
|
|
2798
|
+
* MCP/REST create can paste raw frontmatter-bearing text
|
|
2799
|
+
* (`---\ntitle: X\n---\n# Real Title`), and the first line of that
|
|
2800
|
+
* DOCUMENT is not the first line of its delimiter. When `content` opens
|
|
2801
|
+
* with a `---` line, derivation starts after the matching CLOSING `---`
|
|
2802
|
+
* (searched within the first `FRONTMATTER_SCAN_LINES` lines). An
|
|
2803
|
+
* unterminated opening `---` falls back to the pre-existing behavior —
|
|
2804
|
+
* scanning from line 0 — so a note whose real first line is literally
|
|
2805
|
+
* `---` isn't mangled.
|
|
2786
2806
|
*/
|
|
2787
2807
|
export function computeDisplayTitle(content: string | null | undefined): string | null {
|
|
2788
2808
|
if (!content) return null;
|
|
2789
|
-
|
|
2790
|
-
|
|
2809
|
+
const lines = content.split("\n");
|
|
2810
|
+
let startIndex = 0;
|
|
2811
|
+
if (lines[0]?.trim() === "---") {
|
|
2812
|
+
const scanLimit = Math.min(lines.length, FRONTMATTER_SCAN_LINES);
|
|
2813
|
+
for (let i = 1; i < scanLimit; i++) {
|
|
2814
|
+
if (lines[i]?.trim() === "---") {
|
|
2815
|
+
startIndex = i + 1;
|
|
2816
|
+
break;
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2820
|
+
for (let i = startIndex; i < lines.length; i++) {
|
|
2821
|
+
const stripped = lines[i]!.replace(/^#{1,6}\s*/, "").trim();
|
|
2791
2822
|
if (stripped === "") continue;
|
|
2792
2823
|
// Iterate by Unicode code points so we don't split surrogate pairs mid-character.
|
|
2793
2824
|
const codePoints = Array.from(stripped);
|
|
@@ -104,4 +104,22 @@ describe("search title-boost", () => {
|
|
|
104
104
|
const hits = await store.searchNotes("nonexistent_term_xyz");
|
|
105
105
|
expect(hits).toEqual([]);
|
|
106
106
|
});
|
|
107
|
+
|
|
108
|
+
it("boosts on the post-frontmatter title line, not the `---` delimiter (shares computeDisplayTitle's frontmatter skip)", async () => {
|
|
109
|
+
// Direct-create misuse path: raw frontmatter-bearing content. Without
|
|
110
|
+
// the frontmatter skip, the derived "title" would be the literal
|
|
111
|
+
// string "---", which never matches any query term, so this note
|
|
112
|
+
// would wrongly land in the body-only tier.
|
|
113
|
+
await store.createNote(
|
|
114
|
+
"---\ntitle: irrelevant\n---\n# Budget Review\nQ3 numbers",
|
|
115
|
+
{ path: "frontmatter-led" },
|
|
116
|
+
);
|
|
117
|
+
await store.createNote(
|
|
118
|
+
"Weekly Standup\nsomewhere we discuss the budget in passing",
|
|
119
|
+
{ path: "body-only" },
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
const hits = await store.searchNotes("budget review");
|
|
123
|
+
expect(hits[0].path).toBe("frontmatter-led");
|
|
124
|
+
});
|
|
107
125
|
});
|