@amsterdamdatalabs/enact-docs-search 0.1.0
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/NOTICE +50 -0
- package/README.md +35 -0
- package/dist/adapter/repo-walker.d.ts +22 -0
- package/dist/adapter/repo-walker.d.ts.map +1 -0
- package/dist/adapter/repo-walker.js +96 -0
- package/dist/adapter/repo-walker.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +310 -0
- package/dist/cli.js.map +1 -0
- package/dist/embeddings/embedding-service.d.ts +12 -0
- package/dist/embeddings/embedding-service.d.ts.map +1 -0
- package/dist/embeddings/embedding-service.js +67 -0
- package/dist/embeddings/embedding-service.js.map +1 -0
- package/dist/indexing/chunker.d.ts +52 -0
- package/dist/indexing/chunker.d.ts.map +1 -0
- package/dist/indexing/chunker.js +196 -0
- package/dist/indexing/chunker.js.map +1 -0
- package/dist/indexing/indexing-service.d.ts +29 -0
- package/dist/indexing/indexing-service.d.ts.map +1 -0
- package/dist/indexing/indexing-service.js +151 -0
- package/dist/indexing/indexing-service.js.map +1 -0
- package/dist/search/search-service.d.ts +53 -0
- package/dist/search/search-service.d.ts.map +1 -0
- package/dist/search/search-service.js +139 -0
- package/dist/search/search-service.js.map +1 -0
- package/dist/search/snippet.d.ts +65 -0
- package/dist/search/snippet.d.ts.map +1 -0
- package/dist/search/snippet.js +352 -0
- package/dist/search/snippet.js.map +1 -0
- package/dist/storage/document-store.d.ts +72 -0
- package/dist/storage/document-store.d.ts.map +1 -0
- package/dist/storage/document-store.js +134 -0
- package/dist/storage/document-store.js.map +1 -0
- package/dist/storage/persistence.d.ts +55 -0
- package/dist/storage/persistence.d.ts.map +1 -0
- package/dist/storage/persistence.js +132 -0
- package/dist/storage/persistence.js.map +1 -0
- package/dist/storage/vector-store.d.ts +63 -0
- package/dist/storage/vector-store.d.ts.map +1 -0
- package/dist/storage/vector-store.js +172 -0
- package/dist/storage/vector-store.js.map +1 -0
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +24 -0
- package/dist/types.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-service.js","sourceRoot":"","sources":["../../src/search/search-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract meaningful query terms for match/highlight purposes: lowercase,
|
|
3
|
+
* whitespace-split, drop short tokens (<3 chars) and stopwords. This is
|
|
4
|
+
* intentionally independent of whatever tokenization MiniSearch does
|
|
5
|
+
* internally for indexing/ranking — this list only drives snippet
|
|
6
|
+
* selection and highlighting, so it must not include stopwords regardless
|
|
7
|
+
* of what MiniSearch itself does under the hood.
|
|
8
|
+
*/
|
|
9
|
+
export declare function extractQueryTerms(query: string): string[];
|
|
10
|
+
/** How matched terms should be marked in a generated snippet:
|
|
11
|
+
* - "ansi": wrap with real ANSI bold escapes (\x1b[1m...\x1b[22m) — only
|
|
12
|
+
* correct when writing to an interactive terminal.
|
|
13
|
+
* - "plain": no markup at all. Used for --json output (a JSON consumer
|
|
14
|
+
* wants raw data, not a display marker) and for non-TTY text output
|
|
15
|
+
* (piped/redirected — a human doing that is likely about to grep/process
|
|
16
|
+
* the output programmatically, so escape codes would just be noise, and
|
|
17
|
+
* literal `**` clutter is exactly the bug being fixed). */
|
|
18
|
+
export type HighlightMode = "ansi" | "plain";
|
|
19
|
+
/** Context needed to resolve a chunk-local match position against the real,
|
|
20
|
+
* full source file rather than just the chunk's own text (fix #4 in the
|
|
21
|
+
* module doc-comment). `chunkStartLine` is the chunk's 1-based start line
|
|
22
|
+
* within the full file — already tracked per-chunk as
|
|
23
|
+
* `IndexedDocument.startLine`. */
|
|
24
|
+
export interface FileContext {
|
|
25
|
+
fullContent: string;
|
|
26
|
+
chunkStartLine: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build a human-readable snippet around the first occurrence of any of
|
|
30
|
+
* `terms` in `content`, then highlight those terms with word-boundary-safe
|
|
31
|
+
* bolding. Table rows are detected and handled specially so a match inside
|
|
32
|
+
* a markdown table doesn't produce a raw pipe-fragment slice.
|
|
33
|
+
*
|
|
34
|
+
* `fileContext`, when supplied, lets the rest of snippet assembly (most
|
|
35
|
+
* importantly table-header lookback) operate against the REAL file instead
|
|
36
|
+
* of just the chunk's own text — a chunk boundary can put a table's header
|
|
37
|
+
* outside the chunk that contains the matched row, even though the header
|
|
38
|
+
* is genuinely only a few lines away in the real file. The match itself is
|
|
39
|
+
* still located within `content` (the chunk actually matched by the
|
|
40
|
+
* search index); only the window used to build the surrounding snippet is
|
|
41
|
+
* widened to the full file, by converting the chunk-local match position
|
|
42
|
+
* to a file-absolute one via `chunkStartLine`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function generateSnippet(content: string, terms: string[], highlightMode?: HighlightMode, fileContext?: FileContext): string;
|
|
45
|
+
/** Minimal shape `buildSnippet` needs from an indexed chunk. */
|
|
46
|
+
export interface SnippetDoc {
|
|
47
|
+
filePath: string;
|
|
48
|
+
content: string;
|
|
49
|
+
/** 1-based line number where this chunk starts in the source file. */
|
|
50
|
+
startLine: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Convenience wrapper around `generateSnippet` for the common call-site
|
|
54
|
+
* shape: an indexed chunk plus the repo root it lives under. Reads the full
|
|
55
|
+
* source file from disk so snippet generation can see the real document,
|
|
56
|
+
* not just the chunk (fix #4). Result counts per query are small (~10), so
|
|
57
|
+
* a handful of extra file reads at query time is the right tradeoff over
|
|
58
|
+
* silently degraded snippets.
|
|
59
|
+
*
|
|
60
|
+
* If `repoRoot` is omitted, or the file can't be read (moved/deleted since
|
|
61
|
+
* indexing, permission error, etc.), falls back to chunk-only snippet
|
|
62
|
+
* generation rather than failing the whole query.
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildSnippet(doc: SnippetDoc, terms: string[], highlightMode: HighlightMode, repoRoot?: string): Promise<string>;
|
|
65
|
+
//# sourceMappingURL=snippet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippet.d.ts","sourceRoot":"","sources":["../../src/search/snippet.ts"],"names":[],"mappings":"AAwDA;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAKzD;AAMD;;;;;;;8DAO8D;AAC9D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC;AAoO7C;;;;kCAIkC;AAClC,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EAAE,EACf,aAAa,GAAE,aAAuB,EACtC,WAAW,CAAC,EAAE,WAAW,GACxB,MAAM,CA4BR;AAED,gEAAgE;AAChE,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,MAAM,EAAE,EACf,aAAa,EAAE,aAAa,EAC5B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAWjB"}
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared query-term extraction and snippet/highlight logic used by both
|
|
3
|
+
* DocumentStore (BM25/keyword results) and SearchService (vector/hybrid
|
|
4
|
+
* results). Extracted so the two code paths can't drift and produce two
|
|
5
|
+
* different (and differently broken) renderings of the same kind of bug.
|
|
6
|
+
*
|
|
7
|
+
* Fixes several related readability bugs surfaced by real queries against
|
|
8
|
+
* this repo's own docs:
|
|
9
|
+
*
|
|
10
|
+
* 1. Highlighting used a bare substring match, so short common words like
|
|
11
|
+
* "and" matched inside unrelated words ("H**and**le", "S**and**box").
|
|
12
|
+
* Fixed by requiring a word boundary on whichever side of the term is
|
|
13
|
+
* a word character.
|
|
14
|
+
* 2. Stopwords ("and", "to", ...) were treated as real query terms, so
|
|
15
|
+
* they got matched/highlighted everywhere. Fixed by filtering a small
|
|
16
|
+
* stopword list out of the extracted term list used for matching and
|
|
17
|
+
* highlighting (MiniSearch's own internal tokenization for indexing/
|
|
18
|
+
* ranking is untouched — this only affects the terms list used for
|
|
19
|
+
* snippet selection and highlighting).
|
|
20
|
+
* 3. Snippets were raw character slices with no regard for word/sentence
|
|
21
|
+
* boundaries or markdown table structure, so a match inside a table
|
|
22
|
+
* row produced meaningless pipe-delimited fragments. Fixed by
|
|
23
|
+
* expanding to word boundaries, preferring sentence boundaries within
|
|
24
|
+
* a small extra budget, and special-casing table rows.
|
|
25
|
+
* 4. Table-header pairing (`findTableHeader`) only ever saw a single
|
|
26
|
+
* CHUNK's text (`IndexedDocument.content`), not the full source file.
|
|
27
|
+
* When a matched table row happened to sit near the start of its
|
|
28
|
+
* chunk, the real header — genuinely just a handful of lines up in the
|
|
29
|
+
* actual document — fell outside the chunk entirely, so the lookback
|
|
30
|
+
* silently failed and every such row degraded to the raw `[table row]`
|
|
31
|
+
* fallback even though a perfectly good header existed in the file.
|
|
32
|
+
* Fixed by giving snippet generation an optional view of the FULL file
|
|
33
|
+
* content plus the chunk's file-absolute start line, so the header
|
|
34
|
+
* lookback (and the rest of snippet assembly, for consistency) walks
|
|
35
|
+
* the real document rather than just the chunk. See `buildSnippet`.
|
|
36
|
+
* 5. Pre-existing markdown bold already present in the SOURCE content
|
|
37
|
+
* (e.g. `**Schedule**` in a table cell) printed as literal `**`
|
|
38
|
+
* clutter — `highlightTerms` only ever wrapped query-MATCHED terms,
|
|
39
|
+
* never touching bold that was already there. Fixed by a universal
|
|
40
|
+
* final pass (`applyMarkdownBold`) that runs LAST, after highlighting
|
|
41
|
+
* and table formatting, and converts every remaining `**...**` pair in
|
|
42
|
+
* the assembled snippet to real ANSI bold (TTY) or strips it entirely
|
|
43
|
+
* (JSON / non-TTY).
|
|
44
|
+
*/
|
|
45
|
+
import { readFile } from "node:fs/promises";
|
|
46
|
+
import { join } from "node:path";
|
|
47
|
+
/** Small, deliberately conservative English stopword list — short, very
|
|
48
|
+
* common function words only. Not an aggressive/exhaustive list; the goal
|
|
49
|
+
* is just to stop them from being treated as meaningful match terms. */
|
|
50
|
+
const STOPWORDS = new Set([
|
|
51
|
+
"a", "an", "and", "the", "to", "of", "in", "on", "for", "is", "are",
|
|
52
|
+
"was", "were", "be", "been", "this", "that", "with", "as", "at", "by",
|
|
53
|
+
"from", "or",
|
|
54
|
+
]);
|
|
55
|
+
/**
|
|
56
|
+
* Extract meaningful query terms for match/highlight purposes: lowercase,
|
|
57
|
+
* whitespace-split, drop short tokens (<3 chars) and stopwords. This is
|
|
58
|
+
* intentionally independent of whatever tokenization MiniSearch does
|
|
59
|
+
* internally for indexing/ranking — this list only drives snippet
|
|
60
|
+
* selection and highlighting, so it must not include stopwords regardless
|
|
61
|
+
* of what MiniSearch itself does under the hood.
|
|
62
|
+
*/
|
|
63
|
+
export function extractQueryTerms(query) {
|
|
64
|
+
return query
|
|
65
|
+
.toLowerCase()
|
|
66
|
+
.split(/\s+/)
|
|
67
|
+
.filter((t) => t.length >= 3 && !STOPWORDS.has(t));
|
|
68
|
+
}
|
|
69
|
+
function escapeRegex(str) {
|
|
70
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
71
|
+
}
|
|
72
|
+
const ANSI_BOLD_ON = "\x1b[1m";
|
|
73
|
+
const ANSI_BOLD_OFF = "\x1b[22m";
|
|
74
|
+
/** Universal final pass: convert every remaining `**...**` pair in a fully
|
|
75
|
+
* assembled snippet — whether it's markdown bold that was already present
|
|
76
|
+
* in the source content, or bold left untouched by `highlightTerms` (which
|
|
77
|
+
* only ever wraps query-MATCHED terms) — according to the same TTY/non-TTY
|
|
78
|
+
* rule as everything else. Must run LAST, after highlighting and table
|
|
79
|
+
* formatting, so nothing downstream re-introduces or misses a `**` pair. */
|
|
80
|
+
function applyMarkdownBold(text, mode) {
|
|
81
|
+
const paired = mode === "ansi"
|
|
82
|
+
? text.replace(/\*\*(.+?)\*\*/g, `${ANSI_BOLD_ON}$1${ANSI_BOLD_OFF}`)
|
|
83
|
+
: text.replace(/\*\*(.+?)\*\*/g, "$1");
|
|
84
|
+
// A snippet window can cut through a bold span, leaving one lone `**`
|
|
85
|
+
// marker with no partner (see e.g. the 220-char prose window truncating
|
|
86
|
+
// mid-`**word**`). The paired pass above only touches complete pairs, so
|
|
87
|
+
// strip whatever's left over rather than leave literal asterisks in
|
|
88
|
+
// either mode — there's no meaningful bolding left to apply to it.
|
|
89
|
+
return paired.replace(/\*\*/g, "");
|
|
90
|
+
}
|
|
91
|
+
/** Highlight `terms` inside `text`, requiring a word boundary on whichever
|
|
92
|
+
* side of a term is itself a word character (so "and" won't match inside
|
|
93
|
+
* "handle", but a term like "project_id" that starts/ends with `_` still
|
|
94
|
+
* matches sensibly). In "plain" mode this is a no-op (no markers added). */
|
|
95
|
+
function highlightTerms(text, terms, mode) {
|
|
96
|
+
if (mode !== "ansi")
|
|
97
|
+
return text;
|
|
98
|
+
let result = text;
|
|
99
|
+
for (const term of terms) {
|
|
100
|
+
if (!term)
|
|
101
|
+
continue;
|
|
102
|
+
const escaped = escapeRegex(term);
|
|
103
|
+
const leadingBoundary = /^\w/.test(term) ? "\\b" : "";
|
|
104
|
+
const trailingBoundary = /\w$/.test(term) ? "\\b" : "";
|
|
105
|
+
const regex = new RegExp(`${leadingBoundary}(${escaped})${trailingBoundary}`, "gi");
|
|
106
|
+
result = result.replace(regex, `${ANSI_BOLD_ON}$1${ANSI_BOLD_OFF}`);
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
const SNIPPET_LENGTH = 220;
|
|
111
|
+
const SENTENCE_EXPAND_BUDGET = 80;
|
|
112
|
+
function findFirstMatchIndex(content, terms) {
|
|
113
|
+
let firstMatch = -1;
|
|
114
|
+
const lower = content.toLowerCase();
|
|
115
|
+
for (const term of terms) {
|
|
116
|
+
const index = lower.indexOf(term.toLowerCase());
|
|
117
|
+
if (index !== -1 && (firstMatch === -1 || index < firstMatch))
|
|
118
|
+
firstMatch = index;
|
|
119
|
+
}
|
|
120
|
+
return firstMatch;
|
|
121
|
+
}
|
|
122
|
+
function lineBounds(content, pos) {
|
|
123
|
+
const lineStart = content.lastIndexOf("\n", Math.max(0, pos - 1)) + 1;
|
|
124
|
+
let lineEnd = content.indexOf("\n", pos);
|
|
125
|
+
if (lineEnd === -1)
|
|
126
|
+
lineEnd = content.length;
|
|
127
|
+
return { lineStart, lineEnd };
|
|
128
|
+
}
|
|
129
|
+
/** A line "is a table row" if it has 2+ pipe characters — enough to
|
|
130
|
+
* produce multiple cells when split, which is what makes a naive
|
|
131
|
+
* character-slice truncation unreadable. */
|
|
132
|
+
function isTableLine(line) {
|
|
133
|
+
return (line.match(/\|/g)?.length ?? 0) >= 2;
|
|
134
|
+
}
|
|
135
|
+
function splitTableRow(line) {
|
|
136
|
+
let l = line.trim();
|
|
137
|
+
if (l.startsWith("|"))
|
|
138
|
+
l = l.slice(1);
|
|
139
|
+
if (l.endsWith("|"))
|
|
140
|
+
l = l.slice(0, -1);
|
|
141
|
+
return l.split("|").map((c) => c.trim());
|
|
142
|
+
}
|
|
143
|
+
const TABLE_SEPARATOR_RE = /^\|?\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)+\|?$/;
|
|
144
|
+
/** Walk upward from a table row looking for the `|---|---|` separator
|
|
145
|
+
* line, and return the header row immediately above it, if found within
|
|
146
|
+
* a reasonable number of lines (bounded so we don't walk the whole file). */
|
|
147
|
+
function findTableHeader(content, lineStart) {
|
|
148
|
+
const before = content.slice(0, Math.max(0, lineStart - 1)).split("\n");
|
|
149
|
+
const scanFrom = before.length - 1;
|
|
150
|
+
for (let i = scanFrom; i >= 0 && i >= scanFrom - 30; i--) {
|
|
151
|
+
const l = before[i].trim();
|
|
152
|
+
if (TABLE_SEPARATOR_RE.test(l)) {
|
|
153
|
+
const headerLine = before[i - 1];
|
|
154
|
+
return headerLine ? splitTableRow(headerLine) : null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
/** Look a bounded number of lines before/after a table block for a
|
|
160
|
+
* non-table, non-heading, non-empty line to use as a fallback snippet.
|
|
161
|
+
* Rejects lines that are just leftover table punctuation — a lone "|"
|
|
162
|
+
* left over at a chunk boundary (which can have too few pipes to trip
|
|
163
|
+
* `isTableLine`), a run of "-"/":" characters, etc. — via both a
|
|
164
|
+
* minimum-word-content check AND a blanket "no pipe at all" check, since
|
|
165
|
+
* a chunk boundary can split a table row so only its last fragment (e.g.
|
|
166
|
+
* `enabled. |`) lands in this chunk, and that fragment alone has just one
|
|
167
|
+
* pipe but is exactly as meaningless as a full broken row. */
|
|
168
|
+
function looksLikeRealProse(line) {
|
|
169
|
+
return /[A-Za-z]{3,}/.test(line) && !line.includes("|");
|
|
170
|
+
}
|
|
171
|
+
function findNearestProseLine(content, lineStart, lineEnd) {
|
|
172
|
+
const before = content.slice(0, lineStart).split("\n");
|
|
173
|
+
for (let i = before.length - 1; i >= 0 && i >= before.length - 15; i--) {
|
|
174
|
+
const l = before[i].trim();
|
|
175
|
+
if (l && looksLikeRealProse(l) && !TABLE_SEPARATOR_RE.test(l) && !/^#{1,6}\s/.test(l)) {
|
|
176
|
+
return l;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const after = content.slice(lineEnd).split("\n");
|
|
180
|
+
for (let i = 0; i < after.length && i < 15; i++) {
|
|
181
|
+
const l = after[i].trim();
|
|
182
|
+
if (l && looksLikeRealProse(l) && !TABLE_SEPARATOR_RE.test(l) && !/^#{1,6}\s/.test(l)) {
|
|
183
|
+
return l;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
function tableSnippet(content, lineStart, lineEnd) {
|
|
189
|
+
const line = content.slice(lineStart, lineEnd);
|
|
190
|
+
const cells = splitTableRow(line);
|
|
191
|
+
const header = findTableHeader(content, lineStart);
|
|
192
|
+
if (header && header.length === cells.length) {
|
|
193
|
+
const paired = cells
|
|
194
|
+
.map((cell, i) => {
|
|
195
|
+
const h = (header[i] ?? "").trim();
|
|
196
|
+
return h ? `${h}: ${cell}` : cell;
|
|
197
|
+
})
|
|
198
|
+
.filter((p) => p.trim() !== "");
|
|
199
|
+
if (paired.length > 0)
|
|
200
|
+
return paired.join(" | ");
|
|
201
|
+
}
|
|
202
|
+
const prose = findNearestProseLine(content, lineStart, lineEnd);
|
|
203
|
+
if (prose)
|
|
204
|
+
return prose.length > 200 ? prose.slice(0, 200) + "..." : prose;
|
|
205
|
+
// Last resort: label it plainly rather than presenting broken fragments
|
|
206
|
+
// as if they were prose, and collapse repeated pipe padding.
|
|
207
|
+
const compact = line.trim().replace(/\s*\|\s*/g, " | ").replace(/^\s*\|\s*/, "").trim();
|
|
208
|
+
return `[table row] ${compact}`;
|
|
209
|
+
}
|
|
210
|
+
/** Move `start` left until the character immediately before it is
|
|
211
|
+
* whitespace (or we hit the beginning of the string) — never cuts a word
|
|
212
|
+
* in half. */
|
|
213
|
+
function expandStartToWordBoundary(content, start) {
|
|
214
|
+
let s = start;
|
|
215
|
+
while (s > 0 && !/\s/.test(content[s - 1]))
|
|
216
|
+
s--;
|
|
217
|
+
return s;
|
|
218
|
+
}
|
|
219
|
+
/** Move `end` right until the character at it is whitespace (or we hit
|
|
220
|
+
* the end of the string) — never cuts a word in half. */
|
|
221
|
+
function expandEndToWordBoundary(content, end) {
|
|
222
|
+
let e = end;
|
|
223
|
+
while (e < content.length && !/\s/.test(content[e]))
|
|
224
|
+
e++;
|
|
225
|
+
return e;
|
|
226
|
+
}
|
|
227
|
+
/** Try to extend `end` forward, within `budget` extra characters, to the
|
|
228
|
+
* next sentence-terminating punctuation followed by whitespace/EOF. */
|
|
229
|
+
function extendToSentenceEnd(content, end, budget) {
|
|
230
|
+
const zone = content.slice(end, Math.min(content.length, end + budget));
|
|
231
|
+
const match = zone.match(/[.!?](\s|$)/);
|
|
232
|
+
if (match && match.index !== undefined)
|
|
233
|
+
return end + match.index + 1;
|
|
234
|
+
return end;
|
|
235
|
+
}
|
|
236
|
+
/** Try to pull `start` backward, within `budget` extra characters, to just
|
|
237
|
+
* after the nearest preceding sentence-terminating punctuation. */
|
|
238
|
+
function extendToSentenceStart(content, start, budget) {
|
|
239
|
+
const zoneStart = Math.max(0, start - budget);
|
|
240
|
+
const zone = content.slice(zoneStart, start);
|
|
241
|
+
const matches = [...zone.matchAll(/[.!?]\s+/g)];
|
|
242
|
+
if (matches.length > 0) {
|
|
243
|
+
const last = matches[matches.length - 1];
|
|
244
|
+
return zoneStart + last.index + last[0].length;
|
|
245
|
+
}
|
|
246
|
+
return start;
|
|
247
|
+
}
|
|
248
|
+
function proseSnippet(content, matchPos) {
|
|
249
|
+
let start = Math.max(0, matchPos - Math.floor(SNIPPET_LENGTH / 3));
|
|
250
|
+
let end = Math.min(content.length, start + SNIPPET_LENGTH);
|
|
251
|
+
start = expandStartToWordBoundary(content, start);
|
|
252
|
+
end = expandEndToWordBoundary(content, end);
|
|
253
|
+
end = extendToSentenceEnd(content, end, SENTENCE_EXPAND_BUDGET);
|
|
254
|
+
start = extendToSentenceStart(content, start, SENTENCE_EXPAND_BUDGET);
|
|
255
|
+
let snippet = content.slice(start, end).replace(/\s+/g, " ").trim();
|
|
256
|
+
if (start > 0)
|
|
257
|
+
snippet = "..." + snippet;
|
|
258
|
+
if (end < content.length)
|
|
259
|
+
snippet = snippet + "...";
|
|
260
|
+
return snippet;
|
|
261
|
+
}
|
|
262
|
+
/** 0-based index of the line containing character offset `pos` within
|
|
263
|
+
* `content` (i.e. how many newlines precede `pos`). */
|
|
264
|
+
function lineIndexAt(content, pos) {
|
|
265
|
+
let count = 0;
|
|
266
|
+
const bound = Math.min(pos, content.length);
|
|
267
|
+
for (let i = 0; i < bound; i++) {
|
|
268
|
+
if (content[i] === "\n")
|
|
269
|
+
count++;
|
|
270
|
+
}
|
|
271
|
+
return count;
|
|
272
|
+
}
|
|
273
|
+
/** Character offset where 0-based line `lineIndex` starts within `content`. */
|
|
274
|
+
function offsetOfLineIndex(content, lineIndex) {
|
|
275
|
+
if (lineIndex <= 0)
|
|
276
|
+
return 0;
|
|
277
|
+
let seen = 0;
|
|
278
|
+
for (let i = 0; i < content.length; i++) {
|
|
279
|
+
if (content[i] === "\n") {
|
|
280
|
+
seen++;
|
|
281
|
+
if (seen === lineIndex)
|
|
282
|
+
return i + 1;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return content.length;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Build a human-readable snippet around the first occurrence of any of
|
|
289
|
+
* `terms` in `content`, then highlight those terms with word-boundary-safe
|
|
290
|
+
* bolding. Table rows are detected and handled specially so a match inside
|
|
291
|
+
* a markdown table doesn't produce a raw pipe-fragment slice.
|
|
292
|
+
*
|
|
293
|
+
* `fileContext`, when supplied, lets the rest of snippet assembly (most
|
|
294
|
+
* importantly table-header lookback) operate against the REAL file instead
|
|
295
|
+
* of just the chunk's own text — a chunk boundary can put a table's header
|
|
296
|
+
* outside the chunk that contains the matched row, even though the header
|
|
297
|
+
* is genuinely only a few lines away in the real file. The match itself is
|
|
298
|
+
* still located within `content` (the chunk actually matched by the
|
|
299
|
+
* search index); only the window used to build the surrounding snippet is
|
|
300
|
+
* widened to the full file, by converting the chunk-local match position
|
|
301
|
+
* to a file-absolute one via `chunkStartLine`.
|
|
302
|
+
*/
|
|
303
|
+
export function generateSnippet(content, terms, highlightMode = "plain", fileContext) {
|
|
304
|
+
const firstMatch = findFirstMatchIndex(content, terms);
|
|
305
|
+
const matchPosInChunk = firstMatch === -1 ? 0 : firstMatch;
|
|
306
|
+
let workingContent = content;
|
|
307
|
+
let matchPos = matchPosInChunk;
|
|
308
|
+
if (fileContext) {
|
|
309
|
+
const chunkLineIndex = lineIndexAt(content, matchPosInChunk);
|
|
310
|
+
const columnInLine = matchPosInChunk - lineBounds(content, matchPosInChunk).lineStart;
|
|
311
|
+
const fileLineIndex = fileContext.chunkStartLine - 1 + chunkLineIndex;
|
|
312
|
+
const fileLineOffset = offsetOfLineIndex(fileContext.fullContent, fileLineIndex);
|
|
313
|
+
workingContent = fileContext.fullContent;
|
|
314
|
+
matchPos = Math.min(fileLineOffset + columnInLine, workingContent.length);
|
|
315
|
+
}
|
|
316
|
+
const { lineStart, lineEnd } = lineBounds(workingContent, matchPos);
|
|
317
|
+
const line = workingContent.slice(lineStart, lineEnd);
|
|
318
|
+
const snippet = isTableLine(line)
|
|
319
|
+
? tableSnippet(workingContent, lineStart, lineEnd)
|
|
320
|
+
: proseSnippet(workingContent, matchPos);
|
|
321
|
+
const highlighted = highlightTerms(snippet, terms, highlightMode);
|
|
322
|
+
// Universal final pass — must run LAST, after highlighting and table
|
|
323
|
+
// formatting, so it catches pre-existing source markdown bold as well as
|
|
324
|
+
// anything table formatting left untouched (fix #5).
|
|
325
|
+
return applyMarkdownBold(highlighted, highlightMode);
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Convenience wrapper around `generateSnippet` for the common call-site
|
|
329
|
+
* shape: an indexed chunk plus the repo root it lives under. Reads the full
|
|
330
|
+
* source file from disk so snippet generation can see the real document,
|
|
331
|
+
* not just the chunk (fix #4). Result counts per query are small (~10), so
|
|
332
|
+
* a handful of extra file reads at query time is the right tradeoff over
|
|
333
|
+
* silently degraded snippets.
|
|
334
|
+
*
|
|
335
|
+
* If `repoRoot` is omitted, or the file can't be read (moved/deleted since
|
|
336
|
+
* indexing, permission error, etc.), falls back to chunk-only snippet
|
|
337
|
+
* generation rather than failing the whole query.
|
|
338
|
+
*/
|
|
339
|
+
export async function buildSnippet(doc, terms, highlightMode, repoRoot) {
|
|
340
|
+
let fileContext;
|
|
341
|
+
if (repoRoot) {
|
|
342
|
+
try {
|
|
343
|
+
const fullContent = await readFile(join(repoRoot, doc.filePath), "utf-8");
|
|
344
|
+
fileContext = { fullContent, chunkStartLine: doc.startLine };
|
|
345
|
+
}
|
|
346
|
+
catch {
|
|
347
|
+
fileContext = undefined;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return generateSnippet(doc.content, terms, highlightMode, fileContext);
|
|
351
|
+
}
|
|
352
|
+
//# sourceMappingURL=snippet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippet.js","sourceRoot":"","sources":["../../src/search/snippet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;wEAEwE;AACxE,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK;IACnE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IACrE,MAAM,EAAE,IAAI;CACb,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,KAAK;SACT,WAAW,EAAE;SACb,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC;AAYD,MAAM,YAAY,GAAG,SAAS,CAAC;AAC/B,MAAM,aAAa,GAAG,UAAU,CAAC;AAEjC;;;;;4EAK4E;AAC5E,SAAS,iBAAiB,CAAC,IAAY,EAAE,IAAmB;IAC1D,MAAM,MAAM,GACV,IAAI,KAAK,MAAM;QACb,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,YAAY,KAAK,aAAa,EAAE,CAAC;QACrE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IAC3C,sEAAsE;IACtE,wEAAwE;IACxE,yEAAyE;IACzE,oEAAoE;IACpE,mEAAmE;IACnE,OAAO,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC;AAED;;;4EAG4E;AAC5E,SAAS,cAAc,CAAC,IAAY,EAAE,KAAe,EAAE,IAAmB;IACxE,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACjC,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,MAAM,gBAAgB,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,GAAG,eAAe,IAAI,OAAO,IAAI,gBAAgB,EAAE,EAAE,IAAI,CAAC,CAAC;QACpF,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,YAAY,KAAK,aAAa,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,cAAc,GAAG,GAAG,CAAC;AAC3B,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAElC,SAAS,mBAAmB,CAAC,OAAe,EAAE,KAAe;IAC3D,IAAI,UAAU,GAAG,CAAC,CAAC,CAAC;IACpB,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAChD,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,CAAC,IAAI,KAAK,GAAG,UAAU,CAAC;YAAE,UAAU,GAAG,KAAK,CAAC;IACpF,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,UAAU,CAAC,OAAe,EAAE,GAAW;IAC9C,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtE,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACzC,IAAI,OAAO,KAAK,CAAC,CAAC;QAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC7C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC;AAED;;4CAE4C;AAC5C,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACpB,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACtC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,kBAAkB,GAAG,6CAA6C,CAAC;AAEzE;;6EAE6E;AAC7E,SAAS,eAAe,CAAC,OAAe,EAAE,SAAiB;IACzD,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxE,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,QAAQ,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QACzD,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACjC,OAAO,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACvD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;8DAQ8D;AAC9D,SAAS,kBAAkB,CAAC,IAAY;IACtC,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAe,EAAE,SAAiB,EAAE,OAAe;IAC/E,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACvD,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QACvE,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACtF,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAChD,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACtF,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,OAAe,EAAE,SAAiB,EAAE,OAAe;IACvE,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAEnD,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,KAAK;aACjB,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;YACf,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACnC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACpC,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAClC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,KAAK,GAAG,oBAAoB,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAChE,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IAE3E,wEAAwE;IACxE,6DAA6D;IAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxF,OAAO,eAAe,OAAO,EAAE,CAAC;AAClC,CAAC;AAED;;cAEc;AACd,SAAS,yBAAyB,CAAC,OAAe,EAAE,KAAa;IAC/D,IAAI,CAAC,GAAG,KAAK,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;QAAE,CAAC,EAAE,CAAC;IACjD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;yDACyD;AACzD,SAAS,uBAAuB,CAAC,OAAe,EAAE,GAAW;IAC3D,IAAI,CAAC,GAAG,GAAG,CAAC;IACZ,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC;QAAE,CAAC,EAAE,CAAC;IAC1D,OAAO,CAAC,CAAC;AACX,CAAC;AAED;uEACuE;AACvE,SAAS,mBAAmB,CAAC,OAAe,EAAE,GAAW,EAAE,MAAc;IACvE,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC;IACxE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACxC,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,GAAG,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;IACrE,OAAO,GAAG,CAAC;AACb,CAAC;AAED;mEACmE;AACnE,SAAS,qBAAqB,CAAC,OAAe,EAAE,KAAa,EAAE,MAAc;IAC3E,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;IAChD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;QAC1C,OAAO,SAAS,GAAG,IAAI,CAAC,KAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAClD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CAAC,OAAe,EAAE,QAAgB;IACrD,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC;IACnE,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,GAAG,cAAc,CAAC,CAAC;IAE3D,KAAK,GAAG,yBAAyB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAClD,GAAG,GAAG,uBAAuB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAE5C,GAAG,GAAG,mBAAmB,CAAC,OAAO,EAAE,GAAG,EAAE,sBAAsB,CAAC,CAAC;IAChE,KAAK,GAAG,qBAAqB,CAAC,OAAO,EAAE,KAAK,EAAE,sBAAsB,CAAC,CAAC;IAEtE,IAAI,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACpE,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;IACzC,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM;QAAE,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC;IACpD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;uDACuD;AACvD,SAAS,WAAW,CAAC,OAAe,EAAE,GAAW;IAC/C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI;YAAE,KAAK,EAAE,CAAC;IACnC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,+EAA+E;AAC/E,SAAS,iBAAiB,CAAC,OAAe,EAAE,SAAiB;IAC3D,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAC7B,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACxB,IAAI,EAAE,CAAC;YACP,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,CAAC;AACxB,CAAC;AAYD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAe,EACf,KAAe,EACf,gBAA+B,OAAO,EACtC,WAAyB;IAEzB,MAAM,UAAU,GAAG,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACvD,MAAM,eAAe,GAAG,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IAE3D,IAAI,cAAc,GAAG,OAAO,CAAC;IAC7B,IAAI,QAAQ,GAAG,eAAe,CAAC;IAE/B,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,cAAc,GAAG,WAAW,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAC7D,MAAM,YAAY,GAAG,eAAe,GAAG,UAAU,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,SAAS,CAAC;QACtF,MAAM,aAAa,GAAG,WAAW,CAAC,cAAc,GAAG,CAAC,GAAG,cAAc,CAAC;QACtE,MAAM,cAAc,GAAG,iBAAiB,CAAC,WAAW,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QACjF,cAAc,GAAG,WAAW,CAAC,WAAW,CAAC;QACzC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,GAAG,YAAY,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC5E,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;IACpE,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAEtD,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC;QAC/B,CAAC,CAAC,YAAY,CAAC,cAAc,EAAE,SAAS,EAAE,OAAO,CAAC;QAClD,CAAC,CAAC,YAAY,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;IAE3C,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;IAClE,qEAAqE;IACrE,yEAAyE;IACzE,qDAAqD;IACrD,OAAO,iBAAiB,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;AACvD,CAAC;AAUD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAe,EACf,KAAe,EACf,aAA4B,EAC5B,QAAiB;IAEjB,IAAI,WAAoC,CAAC;IACzC,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;YAC1E,WAAW,GAAG,EAAE,WAAW,EAAE,cAAc,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC;QAC/D,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,GAAG,SAAS,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,OAAO,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;AACzE,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapted from obsidian-qmd (MIT): https://github.com/thirteen37/obsidian-qmd
|
|
3
|
+
* Source: src/storage/DocumentStore.ts — the original had no Obsidian
|
|
4
|
+
* dependency at all (pure MiniSearch wrapper). Adjustments: added
|
|
5
|
+
* `startLine` to the indexed schema for path:line output, added a `scope`
|
|
6
|
+
* pre-filter to `search()`, and dropped the Obsidian-flavoured
|
|
7
|
+
* `pluginBasePath` option that was already unused upstream.
|
|
8
|
+
*
|
|
9
|
+
* DocumentStore provides full-text search using MiniSearch.
|
|
10
|
+
* Implements proper BM25 ranking with inverted index.
|
|
11
|
+
*/
|
|
12
|
+
import MiniSearch from "minisearch";
|
|
13
|
+
import type { Scope } from "../types.js";
|
|
14
|
+
import type { HighlightMode } from "../search/snippet.js";
|
|
15
|
+
export interface IndexedDocument {
|
|
16
|
+
/** Unique identifier for this document/chunk */
|
|
17
|
+
id: string;
|
|
18
|
+
/** Path to the source file, relative to the repo root */
|
|
19
|
+
filePath: string;
|
|
20
|
+
/** The text content */
|
|
21
|
+
content: string;
|
|
22
|
+
/** Chunk index within the file (0 for single-chunk files) */
|
|
23
|
+
chunkIndex: number;
|
|
24
|
+
/** Last modification time of the source file (epoch ms) */
|
|
25
|
+
mtimeMs: number;
|
|
26
|
+
/** 1-based line number where this chunk starts in the source file */
|
|
27
|
+
startLine: number;
|
|
28
|
+
/** Heading hierarchy at the start of this chunk */
|
|
29
|
+
headingBreadcrumb?: string[];
|
|
30
|
+
}
|
|
31
|
+
export interface SearchResult {
|
|
32
|
+
id: string;
|
|
33
|
+
filePath: string;
|
|
34
|
+
chunkIndex: number;
|
|
35
|
+
startLine: number;
|
|
36
|
+
score: number;
|
|
37
|
+
snippet: string;
|
|
38
|
+
headingBreadcrumb?: string[];
|
|
39
|
+
content: string;
|
|
40
|
+
}
|
|
41
|
+
export interface SearchOptions {
|
|
42
|
+
limit?: number;
|
|
43
|
+
scope?: Scope;
|
|
44
|
+
/** How matched terms should be marked in generated snippets. Defaults to
|
|
45
|
+
* "plain" (no markup) when omitted. */
|
|
46
|
+
highlight?: HighlightMode;
|
|
47
|
+
/** Repo root used to read each result's full source file from disk for
|
|
48
|
+
* snippet generation (so e.g. table-header pairing can see the real
|
|
49
|
+
* document, not just the matched chunk). When omitted, snippets fall
|
|
50
|
+
* back to chunk-only generation. */
|
|
51
|
+
repoRoot?: string;
|
|
52
|
+
}
|
|
53
|
+
export interface ExportedDocumentStore {
|
|
54
|
+
documents: IndexedDocument[];
|
|
55
|
+
index: ReturnType<MiniSearch<IndexedDocument>["toJSON"]>;
|
|
56
|
+
}
|
|
57
|
+
export declare class DocumentStore {
|
|
58
|
+
private documents;
|
|
59
|
+
private searchIndex;
|
|
60
|
+
private ready;
|
|
61
|
+
initialize(existingData?: ExportedDocumentStore): Promise<void>;
|
|
62
|
+
isReady(): boolean;
|
|
63
|
+
indexDocuments(docs: IndexedDocument[]): Promise<void>;
|
|
64
|
+
getDocument(id: string): Promise<IndexedDocument | null>;
|
|
65
|
+
deleteByFilePath(filePath: string): Promise<void>;
|
|
66
|
+
/** Search for documents using MiniSearch with BM25 scoring. */
|
|
67
|
+
search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
68
|
+
getDocumentCount(): Promise<number>;
|
|
69
|
+
getAllFilePaths(): Promise<string[]>;
|
|
70
|
+
export(): ExportedDocumentStore;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=document-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-store.d.ts","sourceRoot":"","sources":["../../src/storage/document-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,UAAU,MAAM,YAAY,CAAC;AAEpC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,KAAK,CAAC;IACd;2CACuC;IACvC,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B;;;wCAGoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;CAC1D;AAYD,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAA2C;IAC5D,OAAO,CAAC,WAAW,CAA4C;IAC/D,OAAO,CAAC,KAAK,CAAS;IAEhB,UAAU,CAAC,YAAY,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBrE,OAAO,IAAI,OAAO;IAIZ,cAAc,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBtD,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAIxD,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBvD,+DAA+D;IACzD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IA0C3E,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAInC,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAQ1C,MAAM,IAAI,qBAAqB;CAOhC"}
|