sensemaking 0.22.1 → 0.23.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 (90) hide show
  1. package/README.md +6 -8
  2. package/dist/cjs/chunk/extract.d.cts +3 -3
  3. package/dist/cjs/chunk/extract.d.ts +3 -3
  4. package/dist/cjs/chunk/extract.js +369 -72
  5. package/dist/cjs/chunk/extract.js.map +1 -1
  6. package/dist/cjs/chunk/group.js +2 -2
  7. package/dist/cjs/chunk/group.js.map +1 -1
  8. package/dist/cjs/chunk/parse.js +63 -67
  9. package/dist/cjs/chunk/parse.js.map +1 -1
  10. package/dist/cjs/chunk/parser.d.cts +2 -0
  11. package/dist/cjs/chunk/parser.d.ts +2 -0
  12. package/dist/cjs/chunk/parser.js +40 -0
  13. package/dist/cjs/chunk/parser.js.map +1 -0
  14. package/dist/cjs/chunk/types.d.cts +2 -2
  15. package/dist/cjs/chunk/types.d.ts +2 -2
  16. package/dist/cjs/chunk/version.d.cts +1 -1
  17. package/dist/cjs/chunk/version.d.ts +1 -1
  18. package/dist/cjs/chunk/version.js +1 -1
  19. package/dist/cjs/chunk/version.js.map +1 -1
  20. package/dist/cjs/features/links.js +67 -71
  21. package/dist/cjs/features/links.js.map +1 -1
  22. package/dist/cjs/features/sections.js +1 -1
  23. package/dist/cjs/features/sections.js.map +1 -1
  24. package/dist/cjs/scan/pool.js +1 -1
  25. package/dist/cjs/scan/pool.js.map +1 -1
  26. package/dist/cjs/store/builder.js +2 -3
  27. package/dist/cjs/store/builder.js.map +1 -1
  28. package/dist/cjs/store/duckdb/open.d.cts +1 -1
  29. package/dist/cjs/store/duckdb/open.d.ts +1 -1
  30. package/dist/cjs/store/duckdb/open.js +1 -1
  31. package/dist/cjs/store/duckdb/open.js.map +1 -1
  32. package/dist/cjs/store/sqlite/open.d.cts +1 -1
  33. package/dist/cjs/store/sqlite/open.d.ts +1 -1
  34. package/dist/cjs/store/sqlite/open.js +1 -1
  35. package/dist/cjs/store/sqlite/open.js.map +1 -1
  36. package/dist/cjs/store/turso/connection.d.cts +1 -0
  37. package/dist/cjs/store/turso/connection.d.ts +1 -0
  38. package/dist/cjs/store/turso/connection.js +134 -13
  39. package/dist/cjs/store/turso/connection.js.map +1 -1
  40. package/dist/cjs/store/turso/open.d.cts +1 -1
  41. package/dist/cjs/store/turso/open.d.ts +1 -1
  42. package/dist/cjs/store/turso/open.js +8 -2
  43. package/dist/cjs/store/turso/open.js.map +1 -1
  44. package/dist/cjs/store/turso/store.js +8 -1
  45. package/dist/cjs/store/turso/store.js.map +1 -1
  46. package/dist/cjs/text/strip.js +1 -3
  47. package/dist/cjs/text/strip.js.map +1 -1
  48. package/dist/cjs/workers/parse.js.map +1 -1
  49. package/dist/esm/chunk/extract.d.ts +3 -3
  50. package/dist/esm/chunk/extract.js +276 -63
  51. package/dist/esm/chunk/extract.js.map +1 -1
  52. package/dist/esm/chunk/group.js +2 -2
  53. package/dist/esm/chunk/group.js.map +1 -1
  54. package/dist/esm/chunk/parse.js +65 -64
  55. package/dist/esm/chunk/parse.js.map +1 -1
  56. package/dist/esm/chunk/parser.d.ts +2 -0
  57. package/dist/esm/chunk/parser.js +26 -0
  58. package/dist/esm/chunk/parser.js.map +1 -0
  59. package/dist/esm/chunk/types.d.ts +2 -2
  60. package/dist/esm/chunk/types.js.map +1 -1
  61. package/dist/esm/chunk/version.d.ts +1 -1
  62. package/dist/esm/chunk/version.js +1 -1
  63. package/dist/esm/chunk/version.js.map +1 -1
  64. package/dist/esm/features/links.js +59 -22
  65. package/dist/esm/features/links.js.map +1 -1
  66. package/dist/esm/features/sections.js +1 -1
  67. package/dist/esm/features/sections.js.map +1 -1
  68. package/dist/esm/scan/pool.js +1 -1
  69. package/dist/esm/scan/pool.js.map +1 -1
  70. package/dist/esm/store/builder.js +2 -3
  71. package/dist/esm/store/builder.js.map +1 -1
  72. package/dist/esm/store/duckdb/open.d.ts +1 -1
  73. package/dist/esm/store/duckdb/open.js +1 -1
  74. package/dist/esm/store/duckdb/open.js.map +1 -1
  75. package/dist/esm/store/sqlite/open.d.ts +1 -1
  76. package/dist/esm/store/sqlite/open.js +1 -1
  77. package/dist/esm/store/sqlite/open.js.map +1 -1
  78. package/dist/esm/store/turso/connection.d.ts +1 -0
  79. package/dist/esm/store/turso/connection.js +21 -8
  80. package/dist/esm/store/turso/connection.js.map +1 -1
  81. package/dist/esm/store/turso/open.d.ts +1 -1
  82. package/dist/esm/store/turso/open.js +3 -2
  83. package/dist/esm/store/turso/open.js.map +1 -1
  84. package/dist/esm/store/turso/store.js +2 -0
  85. package/dist/esm/store/turso/store.js.map +1 -1
  86. package/dist/esm/text/strip.js +1 -1
  87. package/dist/esm/text/strip.js.map +1 -1
  88. package/dist/esm/workers/parse.js.map +1 -1
  89. package/package.json +5 -19
  90. package/skills/sense-setup/SKILL.md +1 -1
package/README.md CHANGED
@@ -93,7 +93,7 @@ ORDER BY bm25(content, 10.0, 5.0, 1.0) LIMIT 10
93
93
  |---|---|
94
94
  | `presets` | named bundles of `include`/`exclude` globs, `k` (result count), `signals` (which engines this scope searches with, `words`, `links`, `vectors`; every signal whose prerequisites hold, unless the preset lists them exhaustively), `where` (a standing SQL filter). A file is indexed if any preset includes it, embedded if a model is named and some covering preset's `signals` include `vectors`; `status` shows each preset's coverage. |
95
95
  | `embed` | the model vectors are built with. Naming one gives the tree vectors; omitting the block means none at all, whatever the presets say. `sense download` fetches it. |
96
- | `store` | backing store engine: `sqlite` (default, zero-dependency, Node's built-in SQLite), or the experimental `duckdb` and `turso`. The first command that opens such a tree installs that engine's package on its own (`@duckdb/node-api`, a one-time native download of ~110 MB; `@tursodatabase/database`, much smaller). The same commands and table names run on all three; what does not port is FTS5 syntax. Under `duckdb` and `turso`, `search` text and raw `MATCH` reject FTS5's prefix (`foo*`), boolean (`AND`/`OR`/`NOT`), `NEAR`, initial-token (`^`), and column-filter (`title:foo`) operators with a named error that says how to rephrase or set `store` to `sqlite`; bare words and quoted phrases work on all three. Raw `sql` is a per-store dialect: the tables are portable, but sqlite's FTS5 `MATCH`/`snippet()`/`bm25()` do not run under `duckdb` or `turso`, so saved queries written in FTS5 syntax are sqlite dialect, and `has`/`basename`/`segment` are registered on `sqlite` and `duckdb` but not `turso`, whose client cannot register SQL functions. `sense watch` runs on all three; on `duckdb` and `turso`, which lock the cache file per connection, a concurrent command waits out the watcher's current cycle instead of failing. Each store keeps its own cache file (`.sense/cache.db`, `.sense/cache.duckdb`, `.sense/cache.turso.db`); switching stores is a rebuild, not a migration. |
96
+ | `store` | backing store engine: `sqlite` (default, zero-dependency, Node's built-in SQLite), or the experimental `duckdb` and `turso`. The first command that opens such a tree installs that engine's package on its own (`@duckdb/node-api`, a one-time native download of ~110 MB; `@tursodatabase/database`, much smaller). The same commands and table names run on all three; what does not port is FTS5 syntax. Under `duckdb` and `turso`, `search` text and raw `MATCH` reject FTS5's prefix (`foo*`), boolean (`AND`/`OR`/`NOT`), `NEAR`, initial-token (`^`), and column-filter (`title:foo`) operators with a named error that says how to rephrase or set `store` to `sqlite`; bare words and quoted phrases work on all three. Raw `sql` is a per-store dialect: the tables are portable, but sqlite's FTS5 `MATCH`/`snippet()`/`bm25()` do not run under `duckdb` or `turso`, so saved queries written in FTS5 syntax are sqlite dialect, and `has`/`basename`/`segment` are registered on `sqlite` and `duckdb` but not `turso`, whose client cannot register SQL functions. `sense watch` runs on all three; on `duckdb` and `turso`, which lock the cache file per connection, a concurrent command waits out the watcher's current cycle instead of failing. Each store keeps its own cache file (`.sense/cache.db`, `.sense/cache.duckdb`, `.sense/cache.turso.db`); switching stores is a rebuild, not a migration. Indexing speed is the other axis, and it does not follow from any of the above: sqlite builds a cold index fastest and turso slowest, by a wide margin on a large tree, and no setting closes that gap, since turso's engine costs more per write and more again to maintain each index. What turso buys instead is concurrent writers, non-blocking I/O and encryption, none of which a one-shot command uses, so reach for it for those rather than for speed. Per-store figures: [BENCHMARKING.md](BENCHMARKING.md). |
97
97
  | `queries` | entries runnable as `sense <name>`, each naming the verb it runs: `{ sql }` for SQL (`?` binds positional args) or `{ search }` for a ranked search with its settings baked in, so `sense hot` needs no flags. Running an entry validates it: a typo'd column errors and exits nonzero, and a parameterised entry validates with any argument, since preparing precedes binding. |
98
98
  | `version` | schema version; older configs auto-migrate on load, noted on stderr. |
99
99
 
@@ -170,20 +170,18 @@ Dependencies, all pure JS. No native builds by default.
170
170
  | | |
171
171
  |---|---|
172
172
  | [yaml](https://github.com/eemeli/yaml) | frontmatter |
173
- | [mdast-util-from-markdown](https://github.com/syntax-tree/mdast-util-from-markdown) | markdown parsing |
173
+ | [markdown-it](https://github.com/markdown-it/markdown-it) | markdown parsing |
174
174
  | [@huggingface/tokenizers](https://github.com/huggingface/tokenizers.js) | chunking |
175
175
  | [franc-min](https://github.com/wooorm/franc) | language detection |
176
176
  | [tinypool](https://github.com/tinylibs/tinypool) | worker pool for parallel parsing on large trees |
177
177
  | [install-module-linked](https://github.com/kmalakoff/install-module-linked) | installs the optional `duckdb` and `turso` bindings on first use, instead of shipping them to every install |
178
178
  | Node's built-in SQLite | the default store |
179
179
 
180
- Plus the five GFM extensions `mdast-util-from-markdown` needs and their mdast counterparts, not the full gfm/tagfilter bundle:
180
+ Plus two plugins for the GFM constructs the default preset lacks; tables, strikethrough, and
181
+ autolinks are built in:
181
182
 
182
- - [micromark-extension-gfm-autolink-literal](https://github.com/micromark/micromark-extension-gfm-autolink-literal) / [mdast-util-gfm-autolink-literal](https://github.com/syntax-tree/mdast-util-gfm-autolink-literal)
183
- - [micromark-extension-gfm-footnote](https://github.com/micromark/micromark-extension-gfm-footnote) / [mdast-util-gfm-footnote](https://github.com/syntax-tree/mdast-util-gfm-footnote)
184
- - [micromark-extension-gfm-strikethrough](https://github.com/micromark/micromark-extension-gfm-strikethrough) / [mdast-util-gfm-strikethrough](https://github.com/syntax-tree/mdast-util-gfm-strikethrough)
185
- - [micromark-extension-gfm-table](https://github.com/micromark/micromark-extension-gfm-table) / [mdast-util-gfm-table](https://github.com/syntax-tree/mdast-util-gfm-table)
186
- - [micromark-extension-gfm-task-list-item](https://github.com/micromark/micromark-extension-gfm-task-list-item) / [mdast-util-gfm-task-list-item](https://github.com/syntax-tree/mdast-util-gfm-task-list-item)
183
+ - [markdown-it-footnote](https://github.com/markdown-it/markdown-it-footnote)
184
+ - [markdown-it-task-lists](https://github.com/revin/markdown-it-task-lists)
187
185
 
188
186
  ## License
189
187
 
@@ -1,3 +1,3 @@
1
- import type { Nodes } from 'mdast';
2
- export declare function extractText(node: Nodes): string;
3
- export declare function extractTexts(nodes: Nodes[]): string;
1
+ import type { Block } from './types.js';
2
+ export declare function extractText(block: Block): string;
3
+ export declare function extractTexts(blocks: Block[]): string;
@@ -1,3 +1,3 @@
1
- import type { Nodes } from 'mdast';
2
- export declare function extractText(node: Nodes): string;
3
- export declare function extractTexts(nodes: Nodes[]): string;
1
+ import type { Block } from './types.js';
2
+ export declare function extractText(block: Block): string;
3
+ export declare function extractTexts(blocks: Block[]): string;
@@ -16,8 +16,58 @@ _export(exports, {
16
16
  return extractTexts;
17
17
  }
18
18
  });
19
- // mdast has no wikilink, embed, or %%comment%% node -- literal text resolved by regex passes
20
- // over non-code text (code/inlineCode is placeholder-held and spliced back verbatim, below).
19
+ var _parserts = require("./parser.js");
20
+ function _define_property(obj, key, value) {
21
+ if (key in obj) {
22
+ Object.defineProperty(obj, key, {
23
+ value: value,
24
+ enumerable: true,
25
+ configurable: true,
26
+ writable: true
27
+ });
28
+ } else obj[key] = value;
29
+ return obj;
30
+ }
31
+ function _object_spread(target) {
32
+ for(var i = 1; i < arguments.length; i++){
33
+ var source = arguments[i] != null ? arguments[i] : {};
34
+ var ownKeys = Object.keys(source);
35
+ if (typeof Object.getOwnPropertySymbols === "function") {
36
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
37
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
38
+ }));
39
+ }
40
+ ownKeys.forEach(function(key) {
41
+ _define_property(target, key, source[key]);
42
+ });
43
+ }
44
+ return target;
45
+ }
46
+ function ownKeys(object, enumerableOnly) {
47
+ var keys = Object.keys(object);
48
+ if (Object.getOwnPropertySymbols) {
49
+ var symbols = Object.getOwnPropertySymbols(object);
50
+ if (enumerableOnly) {
51
+ symbols = symbols.filter(function(sym) {
52
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
53
+ });
54
+ }
55
+ keys.push.apply(keys, symbols);
56
+ }
57
+ return keys;
58
+ }
59
+ function _object_spread_props(target, source) {
60
+ source = source != null ? source : {};
61
+ if (Object.getOwnPropertyDescriptors) Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
62
+ else {
63
+ ownKeys(Object(source)).forEach(function(key) {
64
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
65
+ });
66
+ }
67
+ return target;
68
+ }
69
+ // markdown-it, like mdast, has no wikilink, embed, or %%comment%% token -- literal text resolved
70
+ // by regex passes over non-code text (code/inline code is placeholder-held and spliced back verbatim).
21
71
  var COMMENT_PAIR = /%%[\s\S]*?%%/g;
22
72
  // An embed always yields its target, whatever follows a pipe (a resize suffix, never an alias);
23
73
  // must run before the wikilink regex below, bang included, or that regex matches first.
@@ -29,7 +79,7 @@ var BLOCK_ID = / \^[A-Za-z0-9-]+$/gm;
29
79
  // A callout marker is only ever the first thing in a blockquote's text (Obsidian's grammar),
30
80
  // so this anchors to blockquote output alone -- never applied to prose in general.
31
81
  var CALLOUT_MARKER = /^\[!\w[\w-]*\][+-]?[ \t]?/;
32
- // An html node's value is raw HTML, block or inline: a full <!-- --> comment is dropped, any
82
+ // An html token's content is raw HTML, block or inline: a full <!-- --> comment is dropped, any
33
83
  // remaining tags are stripped, and the text a browser would still render survives.
34
84
  var HTML_COMMENT = /<!--[\s\S]*?-->/g;
35
85
  var HTML_TAG = /<[^>]+>/g;
@@ -60,92 +110,339 @@ function resolveFlavor(text) {
60
110
  return wikilinkText(inner);
61
111
  }).replace(BLOCK_ID, '');
62
112
  }
63
- // Sibling blocks (list items, blockquote content, footnote bodies) joined one per line;
64
- // empties dropped so a blank child never widens the gap between its neighbors.
65
- function joinBlocks(nodes, code) {
66
- return nodes.map(function(n) {
67
- return extractNode(n, code);
68
- }).filter(function(s) {
69
- return s.length > 0;
70
- }).join('\n');
71
- }
72
- // Inline content (headings, paragraphs, emphasis, links) concatenated with no separator: the
73
- // source text nodes already carry whatever spacing separates them.
74
- function joinInline(nodes, code) {
75
- return nodes.map(function(n) {
76
- return extractNode(n, code);
77
- }).join('');
78
- }
79
113
  // U+E000 (Private Use Area) never appears in real markdown text, so it is a collision-free
80
114
  // placeholder delimiter, spliced back to the literal code value after flavor resolution.
81
115
  function codePlaceholder(value, code) {
82
116
  var idx = code.push(value) - 1;
83
117
  return "".concat(idx, "");
84
118
  }
85
- // A GFM autolink's display text is its own target, missing only the scheme
86
- // mdast-util-gfm-autolink-literal fills into node.url (http:// for www., mailto: for an email).
87
- var SCHEME_PREFIX = /^[a-z][a-z0-9+.-]*:\/{0,2}/i;
88
- function isAutolink(url, text) {
89
- return url === text || url.replace(SCHEME_PREFIX, '') === text;
90
- }
91
- function extractNode(node, code) {
92
- switch(node.type){
93
- case 'root':
94
- case 'list':
95
- case 'listItem':
96
- case 'footnoteDefinition':
97
- return joinBlocks(node.children, code);
98
- case 'blockquote':
99
- return joinBlocks(node.children, code).replace(CALLOUT_MARKER, '');
100
- case 'link':
119
+ // GFM's autolink literal ends where its path machine stops: a trail of punctuation is a genuine
120
+ // end (link stops before it) only when trailEndsAt accepts it, else the marks are part of the link.
121
+ var PUNCT = new Set([
122
+ '!',
123
+ '"',
124
+ '&',
125
+ "'",
126
+ ')',
127
+ '*',
128
+ ',',
129
+ '.',
130
+ ';',
131
+ ':',
132
+ '<',
133
+ '?',
134
+ '_',
135
+ '~',
136
+ ']'
137
+ ]);
138
+ var TRAIL_PUNCT = new Set([
139
+ '!',
140
+ '"',
141
+ "'",
142
+ ')',
143
+ '*',
144
+ ',',
145
+ '.',
146
+ ';',
147
+ ':',
148
+ '?',
149
+ '_',
150
+ '~'
151
+ ]);
152
+ var isAlpha = function isAlpha(c) {
153
+ return c !== undefined && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
154
+ };
155
+ function trailEndsAt(s, j) {
156
+ for(;;){
157
+ var c = s[j];
158
+ if (c === undefined) return true;
159
+ if (TRAIL_PUNCT.has(c)) {
160
+ j += 1;
161
+ continue;
162
+ }
163
+ if (c === '&') {
164
+ j += 1;
165
+ if (!isAlpha(s[j])) return false;
166
+ j += 1;
167
+ while(isAlpha(s[j]))j += 1;
168
+ if (s[j] !== ';') return false;
169
+ j += 1;
170
+ continue;
171
+ }
172
+ if (c === ']') {
173
+ j += 1;
174
+ var d = s[j];
175
+ return d === undefined || d === '(' || d === '[' || RegExp("\\s", "u").test(d !== null && d !== void 0 ? d : ' ');
176
+ }
177
+ if (c === '<') return true;
178
+ if (c !== undefined && RegExp("^\\s$", "u").test(c)) return true;
179
+ return false;
180
+ }
181
+ }
182
+ // Where the GFM autolink ends in S (the linkifier's text plus the following text), old-style:
183
+ // punctuation that fails the trail test, or a ) with closes <= opens, extends the link.
184
+ function gfmAutolinkEnd(s) {
185
+ var open = 0;
186
+ var close = 0;
187
+ for(var i = 0; i < s.length; i++){
188
+ var c = s[i];
189
+ if (c === '(') {
190
+ open += 1;
191
+ continue;
192
+ }
193
+ if (c === ')' && close < open) {
194
+ close += 1;
195
+ continue;
196
+ }
197
+ if (PUNCT.has(c) && trailEndsAt(s, i)) return i;
198
+ if (c !== undefined && RegExp("^\\s$", "u").test(c)) return i;
199
+ }
200
+ return s.length;
201
+ }
202
+ // linkify-it links more than GFM's autolink literal (bare domains, ftp://, //host); only the
203
+ // GFM forms (http(s)://, www., email) drop their text.
204
+ function isGfmUrl(text) {
205
+ return /^https?:\/\//i.test(text) || /^www\./i.test(text);
206
+ }
207
+ // Only a bare address is GFM's email autolink: a url keeps its @, since a path can hold one.
208
+ function isGfmEmail(text) {
209
+ return !isGfmUrl(text) && text.includes('@');
210
+ }
211
+ // The task-lists plugin injects its checkbox as the item's first inline child.
212
+ function isTaskCheckbox(token) {
213
+ return (token === null || token === void 0 ? void 0 : token.type) === 'html_inline' && /^<input\b/i.test(token.content);
214
+ }
215
+ // A linkify span can swallow the & of a following entity (span ...c& + text amp; z); the
216
+ // re-emitted lead is then a reference the entity rule never saw, so decode it old-style.
217
+ var LEAD_ENTITY = /^&[a-z#][a-z0-9]{1,31};/i;
218
+ // Split a flat token range into its top-level blocks: nesting 1 opens, nesting 0 is one block.
219
+ function topLevelBlocks(tokens) {
220
+ var out = [];
221
+ var i = 0;
222
+ while(i < tokens.length){
223
+ var token = tokens[i];
224
+ if (token.nesting === 1) {
225
+ var depth = 1;
226
+ var j = i + 1;
227
+ while(j < tokens.length && depth > 0){
228
+ depth += tokens[j].nesting === 1 ? 1 : tokens[j].nesting === -1 ? -1 : 0;
229
+ j += 1;
230
+ }
231
+ out.push(tokens.slice(i, j));
232
+ i = j;
233
+ } else if (token.nesting === 0) {
234
+ out.push(tokens.slice(i, i + 1));
235
+ i += 1;
236
+ } else {
237
+ i += 1;
238
+ }
239
+ }
240
+ return out;
241
+ }
242
+ // A first line with no source content (a bare task checkbox, whitespace) contributes no line to
243
+ // the value, so its softbreak is dropped; a first line whose content extraction removes (an
244
+ // autolink, an image) still leaves its line ending behind.
245
+ function paragraphText(children, code) {
246
+ var _children_k;
247
+ var k = 0;
248
+ var first = children[0];
249
+ if (isTaskCheckbox(first)) k = 1;
250
+ while(k < children.length && children[k].type === 'text' && children[k].content.trim() === '')k += 1;
251
+ if (k > 0 && ((_children_k = children[k]) === null || _children_k === void 0 ? void 0 : _children_k.type) === 'softbreak') return inlineText(children.slice(k + 1), code);
252
+ return inlineText(children, code);
253
+ }
254
+ function blockText(tokens, code) {
255
+ var first = tokens[0];
256
+ if (!first) return '';
257
+ switch(first.type){
258
+ case 'heading_open':
259
+ case 'paragraph_open':
101
260
  {
102
- var text = joinInline(node.children, code);
103
- return isAutolink(node.url, text) ? '' : text;
261
+ var _inline_children;
262
+ var inline = tokens.find(function(t) {
263
+ return t.type === 'inline';
264
+ });
265
+ return inline ? paragraphText((_inline_children = inline.children) !== null && _inline_children !== void 0 ? _inline_children : [], code) : '';
104
266
  }
105
- case 'heading':
106
- case 'paragraph':
107
- case 'linkReference':
108
- case 'emphasis':
109
- case 'strong':
110
- case 'delete':
111
- return joinInline(node.children, code);
112
- case 'table':
113
- return node.children.map(function(n) {
114
- return extractNode(n, code);
115
- }).join('\n');
116
- case 'tableRow':
117
- return node.children.map(function(n) {
118
- return extractNode(n, code);
119
- }).join(' ');
120
- case 'tableCell':
121
- return joinInline(node.children, code);
122
- case 'image':
123
- case 'imageReference':
124
- var _node_alt;
125
- return (_node_alt = node.alt) !== null && _node_alt !== void 0 ? _node_alt : '';
126
- case 'text':
127
- return node.value;
128
- case 'inlineCode':
129
- case 'code':
130
- return codePlaceholder(node.value, code);
131
- case 'html':
132
- return stripHtml(node.value);
133
- case 'break':
134
- return ' ';
267
+ case 'fence':
268
+ case 'code_block':
269
+ // Fence and indented code tokens carry the closing newline their lines were joined with.
270
+ return codePlaceholder(first.content.replace(/\n$/, ''), code);
271
+ case 'table_open':
272
+ return tableText(tokens, code);
273
+ case 'ordered_list_open':
274
+ case 'bullet_list_open':
275
+ return listItemsText(tokens, code);
276
+ case 'blockquote_open':
277
+ return blocksIn(tokens.slice(1, -1), code).replace(CALLOUT_MARKER, '');
278
+ case 'html_block':
279
+ // A non-final-line html block carries its last line's terminator, which the mdast value lacked.
280
+ return stripHtml(first.content.replace(/\n$/, ''));
281
+ case 'footnote_reference_open':
282
+ return blocksIn(tokens.slice(1, -1), code);
135
283
  default:
136
284
  return '';
137
285
  }
138
286
  }
287
+ // Sibling blocks (list items, blockquote children, footnote bodies) joined one per line;
288
+ // empties dropped so a blank child never widens the gap between its neighbors.
289
+ function blocksIn(tokens, code) {
290
+ return topLevelBlocks(tokens).map(function(b) {
291
+ return blockText(b, code);
292
+ }).filter(function(s) {
293
+ return s.length > 0;
294
+ }).join('\n');
295
+ }
296
+ // The task-lists plugin slices 3 of the marker's 4 chars, leaving its trailing space on the text
297
+ // after the checkbox token. Returns a copy with that space dropped, never a mutation: a block is
298
+ // extracted more than once (parse pre-extracts headings, group.ts extracts again).
299
+ function withoutTaskMarker(item) {
300
+ for(var i = 0; i < item.length; i++){
301
+ var _token_children;
302
+ var token = item[i];
303
+ // The checkbox, if any, sits in the item's first inline only.
304
+ if (token.type !== 'inline' || !((_token_children = token.children) === null || _token_children === void 0 ? void 0 : _token_children.length)) continue;
305
+ var second = token.children[1];
306
+ if (!isTaskCheckbox(token.children[0]) || (second === null || second === void 0 ? void 0 : second.type) !== 'text' || !second.content.startsWith(' ')) return item;
307
+ var children = token.children.slice();
308
+ children[1] = _object_spread_props(_object_spread({}, second), {
309
+ content: second.content.slice(1)
310
+ });
311
+ var copy = item.slice();
312
+ copy[i] = _object_spread_props(_object_spread({}, token), {
313
+ children: children
314
+ });
315
+ return copy;
316
+ }
317
+ return item;
318
+ }
319
+ function listItemsText(tokens, code) {
320
+ var items = [];
321
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
322
+ try {
323
+ for(var _iterator = topLevelBlocks(tokens.slice(1, -1))[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
324
+ var item = _step.value;
325
+ items.push(blocksIn(withoutTaskMarker(item).slice(1, -1), code));
326
+ }
327
+ } catch (err) {
328
+ _didIteratorError = true;
329
+ _iteratorError = err;
330
+ } finally{
331
+ try {
332
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
333
+ _iterator.return();
334
+ }
335
+ } finally{
336
+ if (_didIteratorError) {
337
+ throw _iteratorError;
338
+ }
339
+ }
340
+ }
341
+ return items.filter(function(s) {
342
+ return s.length > 0;
343
+ }).join('\n');
344
+ }
345
+ // Table rows joined by newline, cells by space (mdast's tableRow/tableCell joiners).
346
+ function tableText(tokens, code) {
347
+ var rows = [];
348
+ var cells = [];
349
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
350
+ try {
351
+ for(var _iterator = tokens[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
352
+ var token = _step.value;
353
+ var _token_children;
354
+ if (token.type === 'tr_open') cells = [];
355
+ else if (token.type === 'inline') cells.push(inlineText((_token_children = token.children) !== null && _token_children !== void 0 ? _token_children : [], code));
356
+ else if (token.type === 'tr_close') rows.push(cells.join(' '));
357
+ }
358
+ } catch (err) {
359
+ _didIteratorError = true;
360
+ _iteratorError = err;
361
+ } finally{
362
+ try {
363
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
364
+ _iterator.return();
365
+ }
366
+ } finally{
367
+ if (_didIteratorError) {
368
+ throw _iteratorError;
369
+ }
370
+ }
371
+ }
372
+ return rows.join('\n');
373
+ }
374
+ // Inline content (headings, paragraphs, emphasis, links) concatenated with no separator: the
375
+ // source text tokens already carry whatever spacing separates them.
376
+ function inlineText(tokens, code) {
377
+ var inAlt = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : false;
378
+ var out = '';
379
+ for(var i = 0; i < tokens.length; i++){
380
+ var token = tokens[i];
381
+ if (token.type === 'link_open') {
382
+ var skip = 0;
383
+ var j = i + 1;
384
+ var depth = 1;
385
+ while(j < tokens.length && depth > 0){
386
+ if (tokens[j].type === 'link_open') depth += 1;
387
+ else if (tokens[j].type === 'link_close') depth -= 1;
388
+ j += 1;
389
+ }
390
+ var text = inlineText(tokens.slice(i + 1, j - 1), code, inAlt);
391
+ var markup = token.markup;
392
+ var next = tokens[j];
393
+ if (inAlt) {
394
+ // An image's alt is plain text: mdast kept every link's own text there, autolinks included.
395
+ out += text;
396
+ } else if (markup === 'linkify' && isGfmUrl(text)) {
397
+ // GFM drop: the next text token resumes at the old link's boundary, re-emitting any
398
+ // trimmed trail. <www.x> has no trail to absorb (the brackets bound it), keep the >.
399
+ // Emails keep their whole remainder: GFM's email machine has no trail, so the span
400
+ // already ends at the old boundary and the entity rule has decoded the rest.
401
+ var prev = tokens[i - 1];
402
+ var bracketed = (prev === null || prev === void 0 ? void 0 : prev.type) === 'text' && prev.content.endsWith('<') && (next === null || next === void 0 ? void 0 : next.type) === 'text' && next.content.startsWith('>');
403
+ var tail = (next === null || next === void 0 ? void 0 : next.type) === 'text' ? text + next.content : text;
404
+ var k = bracketed ? text.length : gfmAutolinkEnd(tail);
405
+ out += tail.slice(k).replace(LEAD_ENTITY, function(m) {
406
+ return (0, _parserts.parser)().utils.unescapeAll(m);
407
+ });
408
+ // The trail came out of the next text token, so that token is consumed here, not re-read.
409
+ if ((next === null || next === void 0 ? void 0 : next.type) === 'text') skip = 1;
410
+ } else if (markup === 'linkify' && isGfmEmail(text)) {
411
+ // Email drop: nothing after the span to trim, so the span alone is dropped.
412
+ } else if (markup === 'autolink') {
413
+ // <...> leaf: dropped whole, its brackets live inside the token so nothing follows to trim.
414
+ } else {
415
+ out += text; // user link or non-GFM linkify target: keep the display text
416
+ }
417
+ i = j - 1 + skip;
418
+ } else if (token.type === 'text') {
419
+ out += token.content;
420
+ } else if (token.type === 'softbreak') {
421
+ out += '\n';
422
+ } else if (token.type === 'hardbreak') {
423
+ out += ' ';
424
+ } else if (token.type === 'code_inline') {
425
+ out += codePlaceholder(token.content, code);
426
+ } else if (token.type === 'html_inline') {
427
+ out += stripHtml(token.content);
428
+ } else if (token.type === 'image') {
429
+ var _token_children;
430
+ out += inlineText((_token_children = token.children) !== null && _token_children !== void 0 ? _token_children : [], code, true);
431
+ }
432
+ // Emphasis, strikethrough and footnote markers carry no text of their own.
433
+ }
434
+ return out;
435
+ }
139
436
  var CODE_PLACEHOLDER = /\uE000(\d+)\uE000/g;
140
- function extractText(node) {
437
+ function extractText(block) {
141
438
  return extractTexts([
142
- node
439
+ block
143
440
  ]);
144
441
  }
145
- function extractTexts(nodes) {
442
+ function extractTexts(blocks) {
146
443
  var code = [];
147
- var joined = nodes.map(function(n) {
148
- return extractNode(n, code);
444
+ var joined = blocks.map(function(b) {
445
+ return blockText(b.node, code);
149
446
  }).filter(function(s) {
150
447
  return s.length > 0;
151
448
  }).join('\n');
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/chunk/extract.ts"],"sourcesContent":["import type { Nodes } from 'mdast';\n\n// mdast has no wikilink, embed, or %%comment%% node -- literal text resolved by regex passes\n// over non-code text (code/inlineCode is placeholder-held and spliced back verbatim, below).\nconst COMMENT_PAIR = /%%[\\s\\S]*?%%/g;\n// An embed always yields its target, whatever follows a pipe (a resize suffix, never an alias);\n// must run before the wikilink regex below, bang included, or that regex matches first.\nconst EMBED = /!\\[\\[([^\\]]+)\\]\\]/g;\nconst WIKILINK = /\\[\\[([^\\]]+)\\]\\]/g;\n// A trailing \" ^id\" is an Obsidian block anchor, valid only at a line's end; a caret elsewhere\n// (mid-line) is ordinary text and is left alone.\nconst BLOCK_ID = / \\^[A-Za-z0-9-]+$/gm;\n// A callout marker is only ever the first thing in a blockquote's text (Obsidian's grammar),\n// so this anchors to blockquote output alone -- never applied to prose in general.\nconst CALLOUT_MARKER = /^\\[!\\w[\\w-]*\\][+-]?[ \\t]?/;\n// An html node's value is raw HTML, block or inline: a full <!-- --> comment is dropped, any\n// remaining tags are stripped, and the text a browser would still render survives.\nconst HTML_COMMENT = /<!--[\\s\\S]*?-->/g;\nconst HTML_TAG = /<[^>]+>/g;\n\nfunction stripHtml(value: string): string {\n return value.replace(HTML_COMMENT, '').replace(HTML_TAG, '');\n}\n\n// A `#anchor` keeps its text (hash dropped), unlike links.ts's parseWikilinkInner (the resolver\n// authority), which discards it entirely -- replicated here since that return value doesn't fit.\nfunction anchorText(base: string): string {\n const hashIdx = base.indexOf('#');\n if (hashIdx === -1) return base.trim();\n const target = base.slice(0, hashIdx).trim();\n const anchor = base.slice(hashIdx + 1).trim();\n return target ? `${target} ${anchor}` : anchor;\n}\n\nfunction wikilinkText(inner: string): string {\n const pipeIdx = inner.indexOf('|');\n return pipeIdx === -1 ? anchorText(inner) : inner.slice(pipeIdx + 1).trim();\n}\n\nfunction embedText(inner: string): string {\n const pipeIdx = inner.indexOf('|');\n return anchorText(pipeIdx === -1 ? inner : inner.slice(0, pipeIdx));\n}\n\nfunction resolveFlavor(text: string): string {\n return text\n .replace(HTML_COMMENT, '')\n .replace(COMMENT_PAIR, '')\n .replace(EMBED, (_, inner: string) => embedText(inner))\n .replace(WIKILINK, (_, inner: string) => wikilinkText(inner))\n .replace(BLOCK_ID, '');\n}\n\n// Sibling blocks (list items, blockquote content, footnote bodies) joined one per line;\n// empties dropped so a blank child never widens the gap between its neighbors.\nfunction joinBlocks(nodes: Nodes[], code: string[]): string {\n return nodes\n .map((n) => extractNode(n, code))\n .filter((s) => s.length > 0)\n .join('\\n');\n}\n\n// Inline content (headings, paragraphs, emphasis, links) concatenated with no separator: the\n// source text nodes already carry whatever spacing separates them.\nfunction joinInline(nodes: Nodes[], code: string[]): string {\n return nodes.map((n) => extractNode(n, code)).join('');\n}\n\n// U+E000 (Private Use Area) never appears in real markdown text, so it is a collision-free\n// placeholder delimiter, spliced back to the literal code value after flavor resolution.\nfunction codePlaceholder(value: string, code: string[]): string {\n const idx = code.push(value) - 1;\n return `\\uE000${idx}\\uE000`;\n}\n\n// A GFM autolink's display text is its own target, missing only the scheme\n// mdast-util-gfm-autolink-literal fills into node.url (http:// for www., mailto: for an email).\nconst SCHEME_PREFIX = /^[a-z][a-z0-9+.-]*:\\/{0,2}/i;\nfunction isAutolink(url: string, text: string): boolean {\n return url === text || url.replace(SCHEME_PREFIX, '') === text;\n}\n\nfunction extractNode(node: Nodes, code: string[]): string {\n switch (node.type) {\n case 'root':\n case 'list':\n case 'listItem':\n case 'footnoteDefinition':\n return joinBlocks(node.children, code);\n case 'blockquote':\n return joinBlocks(node.children, code).replace(CALLOUT_MARKER, '');\n case 'link': {\n const text = joinInline(node.children, code);\n return isAutolink(node.url, text) ? '' : text;\n }\n case 'heading':\n case 'paragraph':\n case 'linkReference':\n case 'emphasis':\n case 'strong':\n case 'delete':\n return joinInline(node.children, code);\n case 'table':\n return node.children.map((n) => extractNode(n, code)).join('\\n');\n case 'tableRow':\n return node.children.map((n) => extractNode(n, code)).join(' ');\n case 'tableCell':\n return joinInline(node.children, code);\n case 'image':\n case 'imageReference':\n return node.alt ?? '';\n case 'text':\n return node.value;\n case 'inlineCode':\n case 'code':\n return codePlaceholder(node.value, code);\n case 'html':\n return stripHtml(node.value);\n case 'break':\n return ' ';\n default:\n return '';\n }\n}\n\nconst CODE_PLACEHOLDER = /\\uE000(\\d+)\\uE000/g;\n\n// Plain text of one mdast node (or a whole tree): heading/list/table structure is kept as text,\n// markup (emphasis, link targets, task and callout markers) is dropped. Pure, synchronous.\nexport function extractText(node: Nodes): string {\n return extractTexts([node]);\n}\n\n// Blocks resolved together: a blank line inside %%...%% splits it across blocks, and a per-block\n// strip then never sees the closing %%. Code stays placeholder-held across all of them.\nexport function extractTexts(nodes: Nodes[]): string {\n const code: string[] = [];\n const joined = nodes\n .map((n) => extractNode(n, code))\n .filter((s) => s.length > 0)\n .join('\\n');\n const resolved = resolveFlavor(joined);\n return code.length === 0 ? resolved : resolved.replace(CODE_PLACEHOLDER, (_, i: string) => code[Number(i)]);\n}\n"],"names":["extractText","extractTexts","COMMENT_PAIR","EMBED","WIKILINK","BLOCK_ID","CALLOUT_MARKER","HTML_COMMENT","HTML_TAG","stripHtml","value","replace","anchorText","base","hashIdx","indexOf","trim","target","slice","anchor","wikilinkText","inner","pipeIdx","embedText","resolveFlavor","text","_","joinBlocks","nodes","code","map","n","extractNode","filter","s","length","join","joinInline","codePlaceholder","idx","push","SCHEME_PREFIX","isAutolink","url","node","type","children","alt","CODE_PLACEHOLDER","joined","resolved","i","Number"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/chunk/extract.ts"],"sourcesContent":["import type { Token } from 'markdown-it';\nimport { parser } from './parser.ts';\nimport type { Block } from './types.ts';\n\n// markdown-it, like mdast, has no wikilink, embed, or %%comment%% token -- literal text resolved\n// by regex passes over non-code text (code/inline code is placeholder-held and spliced back verbatim).\nconst COMMENT_PAIR = /%%[\\s\\S]*?%%/g;\n// An embed always yields its target, whatever follows a pipe (a resize suffix, never an alias);\n// must run before the wikilink regex below, bang included, or that regex matches first.\nconst EMBED = /!\\[\\[([^\\]]+)\\]\\]/g;\nconst WIKILINK = /\\[\\[([^\\]]+)\\]\\]/g;\n// A trailing \" ^id\" is an Obsidian block anchor, valid only at a line's end; a caret elsewhere\n// (mid-line) is ordinary text and is left alone.\nconst BLOCK_ID = / \\^[A-Za-z0-9-]+$/gm;\n// A callout marker is only ever the first thing in a blockquote's text (Obsidian's grammar),\n// so this anchors to blockquote output alone -- never applied to prose in general.\nconst CALLOUT_MARKER = /^\\[!\\w[\\w-]*\\][+-]?[ \\t]?/;\n// An html token's content is raw HTML, block or inline: a full <!-- --> comment is dropped, any\n// remaining tags are stripped, and the text a browser would still render survives.\nconst HTML_COMMENT = /<!--[\\s\\S]*?-->/g;\nconst HTML_TAG = /<[^>]+>/g;\n\nfunction stripHtml(value: string): string {\n return value.replace(HTML_COMMENT, '').replace(HTML_TAG, '');\n}\n\n// A `#anchor` keeps its text (hash dropped), unlike links.ts's parseWikilinkInner (the resolver\n// authority), which discards it entirely -- replicated here since that return value doesn't fit.\nfunction anchorText(base: string): string {\n const hashIdx = base.indexOf('#');\n if (hashIdx === -1) return base.trim();\n const target = base.slice(0, hashIdx).trim();\n const anchor = base.slice(hashIdx + 1).trim();\n return target ? `${target} ${anchor}` : anchor;\n}\n\nfunction wikilinkText(inner: string): string {\n const pipeIdx = inner.indexOf('|');\n return pipeIdx === -1 ? anchorText(inner) : inner.slice(pipeIdx + 1).trim();\n}\n\nfunction embedText(inner: string): string {\n const pipeIdx = inner.indexOf('|');\n return anchorText(pipeIdx === -1 ? inner : inner.slice(0, pipeIdx));\n}\n\nfunction resolveFlavor(text: string): string {\n return text\n .replace(HTML_COMMENT, '')\n .replace(COMMENT_PAIR, '')\n .replace(EMBED, (_, inner: string) => embedText(inner))\n .replace(WIKILINK, (_, inner: string) => wikilinkText(inner))\n .replace(BLOCK_ID, '');\n}\n\n// U+E000 (Private Use Area) never appears in real markdown text, so it is a collision-free\n// placeholder delimiter, spliced back to the literal code value after flavor resolution.\nfunction codePlaceholder(value: string, code: string[]): string {\n const idx = code.push(value) - 1;\n return `\\uE000${idx}\\uE000`;\n}\n\n// GFM's autolink literal ends where its path machine stops: a trail of punctuation is a genuine\n// end (link stops before it) only when trailEndsAt accepts it, else the marks are part of the link.\nconst PUNCT = new Set(['!', '\"', '&', \"'\", ')', '*', ',', '.', ';', ':', '<', '?', '_', '~', ']']);\nconst TRAIL_PUNCT = new Set(['!', '\"', \"'\", ')', '*', ',', '.', ';', ':', '?', '_', '~']);\nconst isAlpha = (c: string | undefined): boolean => c !== undefined && ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));\nfunction trailEndsAt(s: string, j: number): boolean {\n for (;;) {\n const c = s[j];\n if (c === undefined) return true;\n if (TRAIL_PUNCT.has(c)) {\n j += 1;\n continue;\n }\n if (c === '&') {\n j += 1;\n if (!isAlpha(s[j])) return false;\n j += 1;\n while (isAlpha(s[j])) j += 1;\n if (s[j] !== ';') return false;\n j += 1;\n continue;\n }\n if (c === ']') {\n j += 1;\n const d = s[j];\n return d === undefined || d === '(' || d === '[' || /\\s/u.test(d ?? ' ');\n }\n if (c === '<') return true;\n if (c !== undefined && /^\\s$/u.test(c)) return true;\n return false;\n }\n}\n// Where the GFM autolink ends in S (the linkifier's text plus the following text), old-style:\n// punctuation that fails the trail test, or a ) with closes <= opens, extends the link.\nfunction gfmAutolinkEnd(s: string): number {\n let open = 0;\n let close = 0;\n for (let i = 0; i < s.length; i++) {\n const c = s[i];\n if (c === '(') {\n open += 1;\n continue;\n }\n if (c === ')' && close < open) {\n close += 1;\n continue;\n }\n if (PUNCT.has(c) && trailEndsAt(s, i)) return i;\n if (c !== undefined && /^\\s$/u.test(c)) return i;\n }\n return s.length;\n}\n// linkify-it links more than GFM's autolink literal (bare domains, ftp://, //host); only the\n// GFM forms (http(s)://, www., email) drop their text.\nfunction isGfmUrl(text: string): boolean {\n return /^https?:\\/\\//i.test(text) || /^www\\./i.test(text);\n}\n// Only a bare address is GFM's email autolink: a url keeps its @, since a path can hold one.\nfunction isGfmEmail(text: string): boolean {\n return !isGfmUrl(text) && text.includes('@');\n}\n// The task-lists plugin injects its checkbox as the item's first inline child.\nfunction isTaskCheckbox(token: Token | undefined): boolean {\n return token?.type === 'html_inline' && /^<input\\b/i.test(token.content);\n}\n// A linkify span can swallow the & of a following entity (span ...c& + text amp; z); the\n// re-emitted lead is then a reference the entity rule never saw, so decode it old-style.\nconst LEAD_ENTITY = /^&[a-z#][a-z0-9]{1,31};/i;\n\n// Split a flat token range into its top-level blocks: nesting 1 opens, nesting 0 is one block.\nfunction topLevelBlocks(tokens: Token[]): Token[][] {\n const out: Token[][] = [];\n let i = 0;\n while (i < tokens.length) {\n const token = tokens[i];\n if (token.nesting === 1) {\n let depth = 1;\n let j = i + 1;\n while (j < tokens.length && depth > 0) {\n depth += tokens[j].nesting === 1 ? 1 : tokens[j].nesting === -1 ? -1 : 0;\n j += 1;\n }\n out.push(tokens.slice(i, j));\n i = j;\n } else if (token.nesting === 0) {\n out.push(tokens.slice(i, i + 1));\n i += 1;\n } else {\n i += 1;\n }\n }\n return out;\n}\n\n// A first line with no source content (a bare task checkbox, whitespace) contributes no line to\n// the value, so its softbreak is dropped; a first line whose content extraction removes (an\n// autolink, an image) still leaves its line ending behind.\nfunction paragraphText(children: Token[], code: string[]): string {\n let k = 0;\n const first = children[0];\n if (isTaskCheckbox(first)) k = 1;\n while (k < children.length && children[k].type === 'text' && children[k].content.trim() === '') k += 1;\n if (k > 0 && children[k]?.type === 'softbreak') return inlineText(children.slice(k + 1), code);\n return inlineText(children, code);\n}\n\nfunction blockText(tokens: Token[], code: string[]): string {\n const first = tokens[0];\n if (!first) return '';\n switch (first.type) {\n case 'heading_open':\n case 'paragraph_open': {\n const inline = tokens.find((t) => t.type === 'inline');\n return inline ? paragraphText(inline.children ?? [], code) : '';\n }\n case 'fence':\n case 'code_block':\n // Fence and indented code tokens carry the closing newline their lines were joined with.\n return codePlaceholder(first.content.replace(/\\n$/, ''), code);\n case 'table_open':\n return tableText(tokens, code);\n case 'ordered_list_open':\n case 'bullet_list_open':\n return listItemsText(tokens, code);\n case 'blockquote_open':\n return blocksIn(tokens.slice(1, -1), code).replace(CALLOUT_MARKER, '');\n case 'html_block':\n // A non-final-line html block carries its last line's terminator, which the mdast value lacked.\n return stripHtml(first.content.replace(/\\n$/, ''));\n case 'footnote_reference_open':\n return blocksIn(tokens.slice(1, -1), code);\n default:\n return '';\n }\n}\n\n// Sibling blocks (list items, blockquote children, footnote bodies) joined one per line;\n// empties dropped so a blank child never widens the gap between its neighbors.\nfunction blocksIn(tokens: Token[], code: string[]): string {\n return topLevelBlocks(tokens)\n .map((b) => blockText(b, code))\n .filter((s) => s.length > 0)\n .join('\\n');\n}\n\n// The task-lists plugin slices 3 of the marker's 4 chars, leaving its trailing space on the text\n// after the checkbox token. Returns a copy with that space dropped, never a mutation: a block is\n// extracted more than once (parse pre-extracts headings, group.ts extracts again).\nfunction withoutTaskMarker(item: Token[]): Token[] {\n for (let i = 0; i < item.length; i++) {\n const token = item[i];\n // The checkbox, if any, sits in the item's first inline only.\n if (token.type !== 'inline' || !token.children?.length) continue;\n const second = token.children[1];\n if (!isTaskCheckbox(token.children[0]) || second?.type !== 'text' || !second.content.startsWith(' ')) return item;\n const children = token.children.slice();\n children[1] = { ...second, content: second.content.slice(1) } as Token;\n const copy = item.slice();\n copy[i] = { ...token, children } as Token;\n return copy;\n }\n return item;\n}\n\nfunction listItemsText(tokens: Token[], code: string[]): string {\n const items: string[] = [];\n for (const item of topLevelBlocks(tokens.slice(1, -1))) {\n items.push(blocksIn(withoutTaskMarker(item).slice(1, -1), code));\n }\n return items.filter((s) => s.length > 0).join('\\n');\n}\n\n// Table rows joined by newline, cells by space (mdast's tableRow/tableCell joiners).\nfunction tableText(tokens: Token[], code: string[]): string {\n const rows: string[] = [];\n let cells: string[] = [];\n for (const token of tokens) {\n if (token.type === 'tr_open') cells = [];\n else if (token.type === 'inline') cells.push(inlineText(token.children ?? [], code));\n else if (token.type === 'tr_close') rows.push(cells.join(' '));\n }\n return rows.join('\\n');\n}\n\n// Inline content (headings, paragraphs, emphasis, links) concatenated with no separator: the\n// source text tokens already carry whatever spacing separates them.\nfunction inlineText(tokens: Token[], code: string[], inAlt = false): string {\n let out = '';\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n if (token.type === 'link_open') {\n let skip = 0;\n let j = i + 1;\n let depth = 1;\n while (j < tokens.length && depth > 0) {\n if (tokens[j].type === 'link_open') depth += 1;\n else if (tokens[j].type === 'link_close') depth -= 1;\n j += 1;\n }\n const text = inlineText(tokens.slice(i + 1, j - 1), code, inAlt);\n const markup = token.markup;\n const next = tokens[j];\n if (inAlt) {\n // An image's alt is plain text: mdast kept every link's own text there, autolinks included.\n out += text;\n } else if (markup === 'linkify' && isGfmUrl(text)) {\n // GFM drop: the next text token resumes at the old link's boundary, re-emitting any\n // trimmed trail. <www.x> has no trail to absorb (the brackets bound it), keep the >.\n // Emails keep their whole remainder: GFM's email machine has no trail, so the span\n // already ends at the old boundary and the entity rule has decoded the rest.\n const prev = tokens[i - 1];\n const bracketed = prev?.type === 'text' && prev.content.endsWith('<') && next?.type === 'text' && next.content.startsWith('>');\n const tail = next?.type === 'text' ? text + next.content : text;\n const k = bracketed ? text.length : gfmAutolinkEnd(tail);\n out += tail.slice(k).replace(LEAD_ENTITY, (m) => parser().utils.unescapeAll(m));\n // The trail came out of the next text token, so that token is consumed here, not re-read.\n if (next?.type === 'text') skip = 1;\n } else if (markup === 'linkify' && isGfmEmail(text)) {\n // Email drop: nothing after the span to trim, so the span alone is dropped.\n } else if (markup === 'autolink') {\n // <...> leaf: dropped whole, its brackets live inside the token so nothing follows to trim.\n } else {\n out += text; // user link or non-GFM linkify target: keep the display text\n }\n i = j - 1 + skip;\n } else if (token.type === 'text') {\n out += token.content;\n } else if (token.type === 'softbreak') {\n out += '\\n';\n } else if (token.type === 'hardbreak') {\n out += ' ';\n } else if (token.type === 'code_inline') {\n out += codePlaceholder(token.content, code);\n } else if (token.type === 'html_inline') {\n out += stripHtml(token.content);\n } else if (token.type === 'image') {\n out += inlineText(token.children ?? [], code, true);\n }\n // Emphasis, strikethrough and footnote markers carry no text of their own.\n }\n return out;\n}\n\nconst CODE_PLACEHOLDER = /\\uE000(\\d+)\\uE000/g;\n\n// Plain text of one parsed block: heading/list/table structure is kept as text, markup (emphasis,\n// link targets, task and callout markers) is dropped. Pure, synchronous.\nexport function extractText(block: Block): string {\n return extractTexts([block]);\n}\n\n// Blocks resolved together: a blank line inside %%...%% splits it across blocks, and a per-block\n// strip then never sees the closing %%. Code stays placeholder-held across all of them.\nexport function extractTexts(blocks: Block[]): string {\n const code: string[] = [];\n const joined = blocks\n .map((b) => blockText(b.node, code))\n .filter((s) => s.length > 0)\n .join('\\n');\n const resolved = resolveFlavor(joined);\n return code.length === 0 ? resolved : resolved.replace(CODE_PLACEHOLDER, (_, i: string) => code[Number(i)]);\n}\n"],"names":["extractText","extractTexts","COMMENT_PAIR","EMBED","WIKILINK","BLOCK_ID","CALLOUT_MARKER","HTML_COMMENT","HTML_TAG","stripHtml","value","replace","anchorText","base","hashIdx","indexOf","trim","target","slice","anchor","wikilinkText","inner","pipeIdx","embedText","resolveFlavor","text","_","codePlaceholder","code","idx","push","PUNCT","Set","TRAIL_PUNCT","isAlpha","c","undefined","trailEndsAt","s","j","has","d","test","gfmAutolinkEnd","open","close","i","length","isGfmUrl","isGfmEmail","includes","isTaskCheckbox","token","type","content","LEAD_ENTITY","topLevelBlocks","tokens","out","nesting","depth","paragraphText","children","k","first","inlineText","blockText","inline","find","t","tableText","listItemsText","blocksIn","map","b","filter","join","withoutTaskMarker","item","second","startsWith","copy","items","rows","cells","inAlt","skip","markup","next","prev","bracketed","endsWith","tail","m","parser","utils","unescapeAll","CODE_PLACEHOLDER","block","blocks","joined","node","resolved","Number"],"mappings":"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"}
@@ -250,7 +250,7 @@ var ATOMIC_TYPES = new Set([
250
250
  // without their header/delimiter rows would demote them to paragraph text.
251
251
  function piece(pieceLines, startLine, endLine, blockType, textMode) {
252
252
  var text = ATOMIC_TYPES.has(blockType) || textMode === 'raw' ? pieceLines.join('\n') : (0, _parsets.parse)(pieceLines.join('\n')).map(function(b) {
253
- return (0, _extractts.extractText)(b.node);
253
+ return (0, _extractts.extractText)(b);
254
254
  }).join('\n');
255
255
  return {
256
256
  startLine: startLine,
@@ -362,7 +362,7 @@ function groupScope(scopeBlocks, lines, resolved) {
362
362
  }
363
363
  continue;
364
364
  }
365
- var extracted = (0, _extractts.extractText)(block.node);
365
+ var extracted = (0, _extractts.extractText)(block);
366
366
  var sizeText = resolved.text === 'raw' ? raw : extracted;
367
367
  if (block.type === 'heading') {
368
368
  addPart(extracted, sizeText, block.startLine, block.endLine);