obsidian-mcp-server 3.5.4 → 3.6.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.
Files changed (58) hide show
  1. package/AGENTS.md +9 -3
  2. package/CLAUDE.md +9 -3
  3. package/README.md +14 -13
  4. package/changelog/3.5.x/3.5.5.md +20 -0
  5. package/changelog/3.6.x/3.6.0.md +31 -0
  6. package/dist/mcp-server/tools/definitions/_shared/schemas.d.ts.map +1 -1
  7. package/dist/mcp-server/tools/definitions/_shared/schemas.js +2 -2
  8. package/dist/mcp-server/tools/definitions/_shared/schemas.js.map +1 -1
  9. package/dist/mcp-server/tools/definitions/index.d.ts +97 -61
  10. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
  11. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts +14 -2
  12. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.d.ts.map +1 -1
  13. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js +17 -4
  14. package/dist/mcp-server/tools/definitions/obsidian-append-to-note.tool.js.map +1 -1
  15. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.d.ts.map +1 -1
  16. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js +4 -3
  17. package/dist/mcp-server/tools/definitions/obsidian-get-note.tool.js.map +1 -1
  18. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.d.ts +5 -2
  19. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.d.ts.map +1 -1
  20. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js +6 -3
  21. package/dist/mcp-server/tools/definitions/obsidian-manage-tags.tool.js.map +1 -1
  22. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.d.ts +17 -4
  23. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.d.ts.map +1 -1
  24. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.js +20 -6
  25. package/dist/mcp-server/tools/definitions/obsidian-patch-note.tool.js.map +1 -1
  26. package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.d.ts +6 -5
  27. package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.d.ts.map +1 -1
  28. package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.js +26 -24
  29. package/dist/mcp-server/tools/definitions/obsidian-search-notes.tool.js.map +1 -1
  30. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts +14 -2
  31. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.d.ts.map +1 -1
  32. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js +26 -13
  33. package/dist/mcp-server/tools/definitions/obsidian-write-note.tool.js.map +1 -1
  34. package/dist/services/obsidian/frontmatter-ops.d.ts +7 -4
  35. package/dist/services/obsidian/frontmatter-ops.d.ts.map +1 -1
  36. package/dist/services/obsidian/frontmatter-ops.js +502 -59
  37. package/dist/services/obsidian/frontmatter-ops.js.map +1 -1
  38. package/dist/services/obsidian/markdown-blocks.d.ts +39 -0
  39. package/dist/services/obsidian/markdown-blocks.d.ts.map +1 -0
  40. package/dist/services/obsidian/markdown-blocks.js +611 -0
  41. package/dist/services/obsidian/markdown-blocks.js.map +1 -0
  42. package/dist/services/obsidian/obsidian-service.d.ts +18 -12
  43. package/dist/services/obsidian/obsidian-service.d.ts.map +1 -1
  44. package/dist/services/obsidian/obsidian-service.js +653 -130
  45. package/dist/services/obsidian/obsidian-service.js.map +1 -1
  46. package/dist/services/obsidian/patch-instruction.d.ts +141 -0
  47. package/dist/services/obsidian/patch-instruction.d.ts.map +1 -0
  48. package/dist/services/obsidian/patch-instruction.js +217 -0
  49. package/dist/services/obsidian/patch-instruction.js.map +1 -0
  50. package/dist/services/obsidian/section-extractor.d.ts +109 -6
  51. package/dist/services/obsidian/section-extractor.d.ts.map +1 -1
  52. package/dist/services/obsidian/section-extractor.js +364 -87
  53. package/dist/services/obsidian/section-extractor.js.map +1 -1
  54. package/dist/services/obsidian/types.d.ts +23 -9
  55. package/dist/services/obsidian/types.d.ts.map +1 -1
  56. package/manifest.json +1 -1
  57. package/package.json +3 -2
  58. package/server.json +3 -3
@@ -1,10 +1,12 @@
1
1
  /**
2
- * @fileoverview Client-side section extraction from a NoteJson body.
3
- * The upstream Local REST API exposes section *targeting* for PATCH but not
4
- * section-extracted GET, so we slice the markdown ourselves for `format: 'section'`.
2
+ * @fileoverview Client-side section extraction from a NoteJson body for
3
+ * `format: 'section'`. Headings are found the way the plugin's markdown-patch
4
+ * finds them for its document map and PATCH targeting, so a section read
5
+ * covers the span a section write edits, sliced from the note's own bytes.
5
6
  * @module services/obsidian/section-extractor
6
7
  */
7
8
  import { notFound } from '@cyanheads/mcp-ts-core/errors';
9
+ import { getDefaults, Lexer, Tokenizer } from 'marked';
8
10
  import { splice } from './frontmatter-ops.js';
9
11
  /** Delimiter joining a heading path, matching upstream's PATCH `Target-Delimiter`. */
10
12
  const HEADING_DELIMITER = '::';
@@ -32,68 +34,311 @@ function extractFrontmatterField(note, key) {
32
34
  return note.frontmatter[key];
33
35
  }
34
36
  /**
35
- * Collect every ATX heading in the note body, in document order. Setext
36
- * headings are not markdown this extractor recognizes, and lines inside a
37
- * fenced code block or a frontmatter block are excluded.
37
+ * The frontmatter block markdown-patch strips before it lexes: an opening
38
+ * `---` line, then either a `---` line at once or YAML and a closing `---`
39
+ * line, with CRLF, LF, or lone-CR endings. `splice` — the boundary block
40
+ * extraction and the body-scoped writers use — also closes on a `---` with
41
+ * more text after it on its line; the heading scan follows the plugin here so
42
+ * its paths match the plugin's map.
38
43
  */
39
- function scanHeadings(lines, bodyStart, inFence) {
40
- const headings = [];
41
- for (let i = bodyStart; i < lines.length; i++) {
42
- if (inFence[i])
43
- continue;
44
- const m = /^(#{1,6})\s+(.*?)\s*$/.exec(lines[i] ?? '');
45
- if (!m)
46
- continue;
47
- headings.push({ index: i, level: (m[1] ?? '').length, text: (m[2] ?? '').trim() });
44
+ const PLUGIN_FRONTMATTER = /^---(?:\r\n|\r|\n)(?:---(?:\r\n|\r|\n|$)|[\s\S]*?(?:\r\n|\r|\n)---(?:\r\n|\r|\n|$))/;
45
+ /**
46
+ * Every heading in `content`, in document order, found the way the plugin's
47
+ * markdown-patch 2.0 finds them for its document map and PATCH targeting: the
48
+ * frontmatter-stripped body, line endings normalized, lexed with `marked`, and
49
+ * each top-level `heading` token located by accumulating token `raw` lengths.
50
+ * That reads setext headings and skips `#` lines inside fences, HTML blocks,
51
+ * list items, and blockquotes, exactly as the map does. Offsets are mapped
52
+ * back to `content`, so a slice between them is the note's own bytes, CRs
53
+ * included.
54
+ */
55
+ export function scanHeadings(content) {
56
+ const { normalized, at } = pluginBody(content);
57
+ return [...topLevelTokens(normalized)].flatMap((top) => {
58
+ const heading = headingOf(normalized, top);
59
+ return heading ? [{ ...heading, start: at(heading.start), end: at(heading.end) }] : [];
60
+ });
61
+ }
62
+ /**
63
+ * The body markdown-patch lexes — `content` past its frontmatter, line endings
64
+ * read as `\n` — and a map from an offset in it back to `content`.
65
+ */
66
+ function pluginBody(content) {
67
+ const bodyStart = PLUGIN_FRONTMATTER.exec(content)?.[0].length ?? 0;
68
+ const { normalized, toOriginal } = normalizeLineEndings(content.slice(bodyStart));
69
+ return { normalized, at: (offset) => bodyStart + toOriginal(offset) };
70
+ }
71
+ /**
72
+ * The top-level token at `offset` in `normalized` as a heading, its offsets in
73
+ * `normalized`: `end` is just past its last line and that line's ending — or
74
+ * `undefined` when the token is not a heading.
75
+ */
76
+ function headingOf(normalized, { token, offset }) {
77
+ if (token.type !== 'heading')
78
+ return;
79
+ const { depth, text } = token;
80
+ const lineEnd = normalized.indexOf('\n', offset + token.raw.trimEnd().length);
81
+ return {
82
+ level: depth,
83
+ text: text.trim(),
84
+ start: offset,
85
+ end: lineEnd === -1 ? normalized.length : lineEnd + 1,
86
+ };
87
+ }
88
+ /**
89
+ * The body of the heading at full path `path` (its first occurrence), read
90
+ * from one lex of the note, or `undefined` when the note has no such heading.
91
+ * 2.0 assigns a section every top-level token between its heading and the
92
+ * next heading of any level; a `space` token is not a block.
93
+ */
94
+ export function sectionBody(content, path) {
95
+ const { normalized, at } = pluginBody(content);
96
+ const tokens = [...topLevelTokens(normalized)];
97
+ const headings = tokens.flatMap((top, index) => {
98
+ const heading = headingOf(normalized, top);
99
+ return heading ? [{ ...heading, index }] : [];
100
+ });
101
+ const h = headingPaths(headings).indexOf(path);
102
+ const heading = headings[h];
103
+ if (!heading)
104
+ return;
105
+ const next = headings[h + 1];
106
+ const closing = headings.find((other, i) => i > h && other.level <= heading.level);
107
+ return {
108
+ blocks: tokens
109
+ .slice(heading.index + 1, next?.index)
110
+ .filter(({ token }) => token.type !== 'space')
111
+ .map(({ token }) => token.type),
112
+ content: content.slice(at(heading.end), at(closing?.start ?? normalized.length)),
113
+ subsections: next !== undefined && next.level > heading.level,
114
+ };
115
+ }
116
+ /** The `marked` token type of each top-level block in `markdown`, in order. */
117
+ export function blockKinds(markdown) {
118
+ return [...topLevelTokens(normalizeLineEndings(markdown).normalized)].flatMap(({ token }) => token.type === 'space' ? [] : [token.type]);
119
+ }
120
+ /**
121
+ * The top-level block tokens `marked` reads in `markdown` (line endings
122
+ * already `\n`), each with its offset — the running sum of the `raw` lengths
123
+ * before it, which cover the input exactly.
124
+ */
125
+ function* topLevelTokens(markdown) {
126
+ const tokenizer = new HeadingScanTokenizer();
127
+ const lexer = new Lexer({ ...getDefaults(), tokenizer });
128
+ const { rules } = tokenizer;
129
+ tokenizer.rules = { ...rules, block: { ...rules.block, paragraph: PARAGRAPH } };
130
+ let offset = 0;
131
+ for (const token of lexer.blockTokens(markdown)) {
132
+ yield { offset, token };
133
+ offset += token.raw.length;
134
+ }
135
+ }
136
+ /**
137
+ * `marked`'s GFM paragraph rule, changed in cost and not in outcome. At every
138
+ * line a paragraph runs on to, the stock rule asks whether a table starts
139
+ * there, and its table pattern goes on through every following row before the
140
+ * answer comes back — a scan of the rest of the note per paragraph, so a note
141
+ * of pipe lines over one-dash lines (`| a | b |` / `| - |`, repeated) lexes in
142
+ * quadratic time. The rows cannot change the answer (the pattern accepts none
143
+ * of them), so here the check ends after the header and delimiter lines.
144
+ * Built from the stock rule's own source, so it follows the installed
145
+ * `marked`; a source that no longer embeds the table pattern fails at load.
146
+ */
147
+ const PARAGRAPH = (() => {
148
+ const { paragraph, table } = Lexer.rules.block.gfm;
149
+ /** The table pattern as `marked` embeds it: every `^` outside a class dropped. */
150
+ const embedded = table.source.replace(/(^|[^[])\^/g, '$1');
151
+ const rows = embedded.indexOf('(?:\\n((?:');
152
+ const bounded = `${embedded.slice(0, rows)}(?:\\n|$)`;
153
+ const source = paragraph.source.replace(embedded, () => bounded);
154
+ if (rows === -1 || source === paragraph.source) {
155
+ throw new Error("marked's GFM paragraph rule no longer embeds its table rule as expected.");
156
+ }
157
+ return new RegExp(source, paragraph.flags);
158
+ })();
159
+ /**
160
+ * `marked`'s tokenizer, changed in cost and not in the top-level tokens'
161
+ * types and extents — all the heading scan reads.
162
+ *
163
+ * - `table`: the GFM table rule matches every following row before it checks
164
+ * the header and delimiter lines, so a line that looks like a header over
165
+ * one that looks like a delimiter but fails the column check (`t` over `-`,
166
+ * `a|b` over `-`) costs a scan of the rest of the note, repeated at each
167
+ * such pair. The header and delimiter lines decide the outcome on their
168
+ * own, so the rule runs on those two lines first and on the whole source
169
+ * only when they pass.
170
+ * - `blockquote`: the stock rule lexes a blockquote's content to find where
171
+ * it ends, and each nested level lexes it again, so `>` nested a thousand
172
+ * deep costs a thousand passes over every line after it. A run of lines
173
+ * that each open with `>` and that ends the note or meets an empty line is
174
+ * the whole blockquote whatever the lines hold, so its extent is known
175
+ * without lexing it. The token then carries no child tokens, which nothing
176
+ * here reads. Any other shape — a lazy continuation line — goes to the
177
+ * stock rule, which still costs a pass per nesting level.
178
+ */
179
+ class HeadingScanTokenizer extends Tokenizer {
180
+ table(src) {
181
+ const headerEnd = src.indexOf('\n');
182
+ const delimiterEnd = headerEnd === -1 ? -1 : src.indexOf('\n', headerEnd + 1);
183
+ if (delimiterEnd !== -1 && !super.table(src.slice(0, delimiterEnd + 1)))
184
+ return;
185
+ return super.table(src);
48
186
  }
49
- return headings;
50
- }
51
- /**
52
- * Build the full `Parent::Child` path of one heading by walking backward
53
- * through the enclosing headings — each ancestor is the nearest preceding
54
- * heading strictly shallower than the level reached so far. This is the same
55
- * serialization upstream's document map emits (trimmed heading text, joined by
56
- * the PATCH target delimiter), so a path built here is a locator the write path
57
- * resolves as an exact map entry.
58
- */
59
- function headingPath(headings, idx) {
60
- const matched = headings[idx];
61
- if (!matched)
62
- return '';
63
- const segments = [matched.text];
64
- let level = matched.level;
65
- for (let i = idx - 1; i >= 0 && level > 1; i--) {
66
- const ancestor = headings[i];
67
- if (ancestor && ancestor.level < level) {
68
- segments.unshift(ancestor.text);
69
- level = ancestor.level;
187
+ blockquote(src) {
188
+ const { blockquoteStart, blockquoteSetextReplace, blockquoteSetextReplace2 } = this.rules.other;
189
+ let end = -1;
190
+ let next = 0;
191
+ while (next < src.length) {
192
+ const newline = src.indexOf('\n', next);
193
+ const lineEnd = newline === -1 ? src.length : newline;
194
+ if (!blockquoteStart.test(src.slice(next, lineEnd)))
195
+ break;
196
+ end = lineEnd;
197
+ next = lineEnd + 1;
70
198
  }
199
+ /**
200
+ * A run of `>` lines that ends the note or meets an empty line is the whole
201
+ * blockquote: only a non-empty line can continue it lazily.
202
+ */
203
+ if (end === -1 || (next < src.length && src[next] !== '\n'))
204
+ return super.blockquote(src);
205
+ const raw = src.slice(0, end);
206
+ const text = raw
207
+ .replace(blockquoteSetextReplace, '\n $1')
208
+ .replace(blockquoteSetextReplace2, '');
209
+ return { type: 'blockquote', raw, text, tokens: [] };
71
210
  }
72
- return segments.join(HEADING_DELIMITER);
73
211
  }
74
212
  /**
75
- * Match a heading by "::"-delimited hierarchy. "Top::Sub" walks to a level-N
76
- * heading "Top" and then a deeper heading "Sub" beneath it. A single-segment
77
- * target matches a leaf at any depth and resolves to the first such heading —
78
- * the resolution is reported back in `sectionTarget`, and competing headings in
79
- * `candidates`, rather than changing which one wins.
80
- *
81
- * A target that already carries the delimiter is left out of collision
82
- * detection, mirroring the write-side resolver's own short-circuit: the walk is
83
- * scoped to the first matching ancestor and never inspects a repeat of it.
213
+ * `text` with every `\r\n` and lone `\r` read as `\n` — what `marked` lexes —
214
+ * and a map from an offset in that text back to the same position in `text`.
215
+ * A collapsed `\r\n` maps to its `\r`.
84
216
  */
85
- function extractHeading(content, target) {
86
- const parts = target
87
- .split(HEADING_DELIMITER)
88
- .map((p) => p.trim())
89
- .filter(Boolean);
90
- if (parts.length === 0) {
91
- throw notFound('Empty heading target.', { target });
217
+ function normalizeLineEndings(text) {
218
+ /** Offsets in `normalized` of each `\n` that stands for a `\r\n`, ascending. */
219
+ const collapsed = [];
220
+ const normalized = text.replace(/\r\n?/g, (ending, at) => {
221
+ if (ending.length === 2)
222
+ collapsed.push(at - collapsed.length);
223
+ return '\n';
224
+ });
225
+ return {
226
+ normalized,
227
+ toOriginal: (offset) => {
228
+ let lo = 0;
229
+ let hi = collapsed.length;
230
+ while (lo < hi) {
231
+ const mid = (lo + hi) >>> 1;
232
+ if ((collapsed[mid] ?? 0) < offset)
233
+ lo = mid + 1;
234
+ else
235
+ hi = mid;
236
+ }
237
+ return offset + lo;
238
+ },
239
+ };
240
+ }
241
+ /**
242
+ * Build the full `Parent::Child` path of every heading, in document order. A
243
+ * heading's parent is the nearest preceding heading strictly shallower than it,
244
+ * and its path is the parent's path plus its own text — the serialization the
245
+ * document map emits, so a path built here is a locator the write path resolves
246
+ * as an exact map entry. Untitled headings contribute an empty segment
247
+ * (`::Request body`, `Top::::Child`), and a top-level untitled heading's own
248
+ * path is `""`, which the map omits.
249
+ */
250
+ function headingPaths(headings) {
251
+ const stack = [];
252
+ return headings.map(({ level, text }) => {
253
+ while ((stack.at(-1)?.level ?? 0) >= level)
254
+ stack.pop();
255
+ const parent = stack.at(-1);
256
+ const path = parent ? `${parent.path}${HEADING_DELIMITER}${text}` : text;
257
+ stack.push({ level, path });
258
+ return path;
259
+ });
260
+ }
261
+ /**
262
+ * Full `::`-joined path of every heading in `content`, in document order,
263
+ * repeats included — the markdown-patch 2.0 map's heading tree, flattened.
264
+ * Deduplicated and with the `""` entry dropped, it is the 1.x map's `headings`
265
+ * array.
266
+ */
267
+ export function listHeadingPaths(content) {
268
+ return headingPaths(scanHeadings(content));
269
+ }
270
+ /**
271
+ * The level of the heading at full path `path` in `content` — its first
272
+ * occurrence. For a path the note does not have: with `create`, the level
273
+ * markdown-patch 2.0 gives it when `createTargetIfMissing` creates it — one
274
+ * below the deepest existing ancestor for each missing segment, counted from 0
275
+ * when no ancestor exists — and without, `undefined`.
276
+ */
277
+ export function sectionLevel(content, path, create) {
278
+ const headings = scanHeadings(content);
279
+ const paths = headingPaths(headings);
280
+ const own = headings[paths.indexOf(path)];
281
+ if (own || !create)
282
+ return own?.level;
283
+ const segments = path.split(HEADING_DELIMITER);
284
+ for (let depth = segments.length - 1; depth >= 1; depth--) {
285
+ const found = headings[paths.indexOf(segments.slice(0, depth).join(HEADING_DELIMITER))];
286
+ if (found)
287
+ return found.level + segments.length - depth;
92
288
  }
93
- const lines = content.split('\n');
289
+ return segments.length;
290
+ }
291
+ /**
292
+ * True when `blockId` is referenced in `content` by an isolated marker: a
293
+ * `^blockId` line on its own, after a blank line (or at the body's start), so
294
+ * the parser reads it as its own paragraph and the id names the block above.
295
+ * A marker line with no blank line above it continues that block instead (a
296
+ * table row, a paragraph line, a list item), and a line inside a fence or
297
+ * indented as code is not a marker.
298
+ */
299
+ export function isIsolatedBlockId(content, blockId) {
300
+ const lines = content.split('\n').map((line) => line.replace(/\r$/, ''));
94
301
  const bodyStart = frontmatterEndLine(content);
95
302
  const inFence = computeFenceMask(lines, bodyStart);
96
- const headings = scanHeadings(lines, bodyStart, inFence);
303
+ const marker = `^${blockId}`;
304
+ return lines.some((line, i) => i >= bodyStart &&
305
+ !inFence[i] &&
306
+ line.trim() === marker &&
307
+ !/^(?: {4}|\t)/.test(line) &&
308
+ (i === bodyStart || (lines[i - 1] ?? '').trim() === ''));
309
+ }
310
+ /** An ATX heading's opening: up to three spaces or tabs, then its `#` run. */
311
+ const ATX_OPENING = /^([ \t]{0,3})(#+)/;
312
+ /**
313
+ * The `#` run of every top-level ATX heading in `markdown`, found as
314
+ * markdown-patch 2.0 finds the headings it re-levels in written content: line
315
+ * endings normalized, lexed with `marked`, and each top-level `heading` token
316
+ * whose raw text opens with a `#` run. A setext heading, a `#` line inside a
317
+ * fence or HTML block, and a hashtag carry none.
318
+ */
319
+ export function atxHeadingMarkers(markdown) {
320
+ const { normalized } = normalizeLineEndings(markdown);
321
+ const markers = [];
322
+ for (const { token, offset } of topLevelTokens(normalized)) {
323
+ const opening = token.type === 'heading' ? ATX_OPENING.exec(token.raw) : null;
324
+ if (!opening)
325
+ continue;
326
+ const [, indent = '', hashes = ''] = opening;
327
+ markers.push({
328
+ hashes: hashes.length,
329
+ line: token.raw.trim().split('\n')[0] ?? '',
330
+ start: offset + indent.length,
331
+ });
332
+ }
333
+ return { markers, normalized };
334
+ }
335
+ /**
336
+ * Walk a `::`-split target one segment at a time: each segment matches the
337
+ * first heading with that text below the previous match, at any depth, before
338
+ * the walk leaves the previous match's subtree. Returns the index of the heading
339
+ * the last segment matched, or -1.
340
+ */
341
+ function walkSegments(headings, parts) {
97
342
  let cursor = 0;
98
343
  let parentLevel = 0;
99
344
  let matched = -1;
@@ -103,58 +348,73 @@ function extractHeading(content, target) {
103
348
  const heading = headings[i];
104
349
  if (!heading)
105
350
  continue;
106
- if (parentLevel > 0 && heading.level <= parentLevel) {
107
- // exited the parent; stop searching deeper for this part
351
+ if (parentLevel > 0 && heading.level <= parentLevel)
108
352
  break;
109
- }
110
353
  if (heading.text === part) {
111
354
  found = i;
112
355
  break;
113
356
  }
114
357
  }
115
358
  const hit = headings[found];
116
- if (!hit) {
117
- throw notFound(`Heading '${target}' not found.`, { target });
118
- }
359
+ if (!hit)
360
+ return -1;
119
361
  matched = found;
120
362
  cursor = found + 1;
121
363
  parentLevel = hit.level;
122
364
  }
123
- // Slice from the matched heading line to the next heading at the same or shallower level.
124
- const startLine = headings[matched]?.index ?? 0;
125
- let endLine = lines.length;
126
- for (let i = matched + 1; i < headings.length; i++) {
127
- const heading = headings[i];
128
- if (heading && heading.level <= parentLevel) {
129
- endLine = heading.index;
130
- break;
131
- }
365
+ return matched;
366
+ }
367
+ /**
368
+ * Match a heading by "::"-delimited hierarchy. A target carrying the delimiter
369
+ * resolves by exact full path first, so every document-map locator reads back
370
+ * as itself; failing that, the segments walk the hierarchy, which lets a path
371
+ * that skips a level (`Top::Child` for `Top::::Child`) still resolve. Empty
372
+ * segments are kept — they name untitled headings. A single-segment target
373
+ * matches a leaf at any depth and resolves to the first such heading.
374
+ *
375
+ * The resolution is reported back in `sectionTarget`. When the read could have
376
+ * meant another heading, `candidates` lists every full path it could name: for
377
+ * a bare leaf, each heading sharing that text; for a delimited target, each
378
+ * occurrence of the resolved path when that path repeats in the note. Which
379
+ * heading wins never changes.
380
+ */
381
+ function extractHeading(content, target) {
382
+ const parts = target.split(HEADING_DELIMITER).map((p) => p.trim());
383
+ const [leaf] = parts;
384
+ const qualified = parts.length > 1;
385
+ if (!qualified && !leaf) {
386
+ throw notFound('Empty heading target.', { target });
132
387
  }
133
- const leaf = parts.length === 1 ? parts[0] : undefined;
134
- const collisions = [];
135
- if (leaf !== undefined) {
136
- headings.forEach((h, i) => {
137
- if (h.text === leaf)
138
- collisions.push(i);
139
- });
388
+ const headings = scanHeadings(content);
389
+ const paths = headingPaths(headings);
390
+ const exact = qualified ? paths.indexOf(parts.join(HEADING_DELIMITER)) : -1;
391
+ const matched = exact >= 0 ? exact : walkSegments(headings, parts);
392
+ const hit = headings[matched];
393
+ const resolved = paths[matched];
394
+ if (!hit || resolved === undefined) {
395
+ throw notFound(`Heading '${target}' not found.`, { target });
140
396
  }
397
+ // Slice from the matched heading to the next heading at the same or shallower level.
398
+ const end = headings.find((h, i) => i > matched && h.level <= hit.level);
399
+ const candidates = qualified
400
+ ? paths.filter((p) => p === resolved)
401
+ : paths.filter((_, i) => headings[i]?.text === leaf);
141
402
  return {
142
- value: lines.slice(startLine, endLine).join('\n').replace(/\n+$/, ''),
143
- sectionTarget: headingPath(headings, matched),
144
- ...(collisions.length > 1
145
- ? { candidates: collisions.map((i) => headingPath(headings, i)) }
146
- : {}),
403
+ value: content.slice(hit.start, end?.start).replace(/\n+$/, ''),
404
+ sectionTarget: resolved,
405
+ ...(candidates.length > 1 ? { candidates } : {}),
147
406
  };
148
407
  }
149
408
  /**
150
409
  * Match a block by its `^blockId` reference. Returns the line containing the
151
410
  * reference plus any preceding lines belonging to the same paragraph (until a
152
- * blank line or heading).
411
+ * blank line or a heading line — a setext underline, an untitled heading).
153
412
  */
154
413
  function extractBlock(content, blockId) {
155
414
  const lines = content.split('\n');
156
415
  const bodyStart = frontmatterEndLine(content);
157
416
  const inFence = computeFenceMask(lines, bodyStart);
417
+ const isHeading = headingLineMask(content, lines);
158
418
  const escaped = blockId.replace(/[\\^$.*+?()[\]{}|]/g, '\\$&');
159
419
  const ref = new RegExp(`(^|\\s)\\^${escaped}\\s*$`);
160
420
  for (let i = bodyStart; i < lines.length; i++) {
@@ -164,7 +424,7 @@ function extractBlock(content, blockId) {
164
424
  let start = i;
165
425
  while (start > bodyStart) {
166
426
  const prev = lines[start - 1] ?? '';
167
- if (prev.trim() === '' || /^#{1,6}\s+/.test(prev))
427
+ if (prev.trim() === '' || isHeading[start - 1])
168
428
  break;
169
429
  start--;
170
430
  }
@@ -173,12 +433,29 @@ function extractBlock(content, blockId) {
173
433
  }
174
434
  throw notFound(`Block reference '^${blockId}' not found.`, { blockId });
175
435
  }
436
+ /**
437
+ * Mark the indices of `lines` (`content` split on `\n`) that a heading
438
+ * occupies: an ATX heading's line, or a setext heading's text lines and
439
+ * underline.
440
+ */
441
+ function headingLineMask(content, lines) {
442
+ const headings = scanHeadings(content);
443
+ let h = 0;
444
+ let lineStart = 0;
445
+ return lines.map((line) => {
446
+ const lineEnd = lineStart + line.length;
447
+ while ((headings[h]?.end ?? Number.POSITIVE_INFINITY) <= lineStart)
448
+ h++;
449
+ const onHeading = (headings[h]?.start ?? Number.POSITIVE_INFINITY) <= lineEnd;
450
+ lineStart = lineEnd + 1;
451
+ return onHeading;
452
+ });
453
+ }
176
454
  /**
177
455
  * Return the line index where the document body starts, skipping a leading YAML
178
456
  * frontmatter block. Returns 0 when no frontmatter is present. Without this
179
- * guard, heading and block extraction would scan inside the frontmatter and
180
- * falsely match YAML comment lines or include the fence in a paragraph
181
- * walk-back.
457
+ * guard, block extraction would scan inside the frontmatter and falsely match a
458
+ * reference there or include the fence in a paragraph walk-back.
182
459
  *
183
460
  * The boundary comes from `splice` rather than a second line scan, so the read
184
461
  * path and every body-scoped write path agree on where the body starts —
@@ -1 +1 @@
1
- {"version":3,"file":"section-extractor.js","sourceRoot":"","sources":["../../../src/services/obsidian/section-extractor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"section-extractor.js","sourceRoot":"","sources":["../../../src/services/obsidian/section-extractor.ts"],"names":[],"mappings":"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"}
@@ -80,15 +80,22 @@ export interface ObsidianCommand {
80
80
  name: string;
81
81
  }
82
82
  export type SearchMode = 'text' | 'jsonlogic' | 'omnisearch';
83
+ /**
84
+ * A text-search hit. Each entry of `matches` is a match location: one upstream
85
+ * span, or — for a query with two or more distinct tokens — consecutive spans
86
+ * of the same subject merged into one window (see `mergeIntoLocations`).
87
+ */
83
88
  export interface TextSearchHit {
84
89
  filename: string;
85
90
  matches: Array<{
91
+ /** A contiguous slice of the subject; a merged location's windows stitched into one. */
86
92
  context: string;
87
93
  /**
88
- * `start`/`end` are upstream's own offsets into the subject it matched —
89
- * the note body, or the note basename for a filename match.
90
- * `contextStart`/`contextEnd` are derived by the service and index
91
- * `context` directly.
94
+ * `start`/`end` are offsets into the subject upstream matched — the note
95
+ * body, or the note basename for a filename match — running from the
96
+ * location's first span to its last. `contextStart`/`contextEnd` are
97
+ * derived by the service and index `context` directly, so
98
+ * `context.slice(contextStart, contextEnd)` is `subject.slice(start, end)`.
92
99
  */
93
100
  match: {
94
101
  start: number;
@@ -119,21 +126,28 @@ export interface OmnisearchHit {
119
126
  }>;
120
127
  score: number;
121
128
  }
122
- export interface PatchHeaders {
129
+ /**
130
+ * A section write, independent of the markdown-patch format that carries it —
131
+ * the service sends it as 1.x request headers or a 2.0 JSON instruction,
132
+ * whichever the installed plugin speaks.
133
+ */
134
+ export interface PatchInstruction {
123
135
  /**
124
136
  * When false/undefined (the protective default), the patch is rejected if
125
137
  * matching content already exists in the target. Set to true to force-apply
126
- * even when it would duplicate. The wire header is `Reject-If-Content-
127
- * Preexists` (markdown-patch 1.0+) — the service inverts this flag on the
128
- * way out. Replace operations are exempt at the plugin layer.
138
+ * even when it would duplicate. Both formats carry the inverse flag
139
+ * (`Reject-If-Content-Preexists` / `rejectIfContentPreexists`), so the
140
+ * service inverts this on the way out. Replace operations are exempt at the
141
+ * plugin layer.
129
142
  */
130
143
  applyIfContentPreexists?: boolean | undefined;
131
144
  contentType?: 'markdown' | 'json' | undefined;
132
145
  createTargetIfMissing?: boolean | undefined;
133
146
  operation: 'append' | 'prepend' | 'replace';
147
+ /** Heading path (`::`-joined), block ID, or frontmatter key. */
134
148
  target: string;
135
- targetDelimiter?: string | undefined;
136
149
  targetType: SectionType;
150
+ /** Markdown-patch 1.x only; 2.0 owns the whitespace around inserted content and ignores it. */
137
151
  trimTargetWhitespace?: boolean | undefined;
138
152
  }
139
153
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/obsidian/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/obsidian/types.ts"],"names":[],"mappings":"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"}