@v1nvn/readability 0.44.0 → 0.45.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/README.md +3 -3
- package/package.json +7 -9
- package/src/cli.ts +134 -0
- package/src/config.ts +42 -0
- package/src/dev.ts +77 -0
- package/src/errors.ts +19 -0
- package/src/handler.ts +8 -0
- package/src/host-sampling.ts +86 -0
- package/src/index.ts +27 -0
- package/src/logger.ts +3 -0
- package/src/output/format.ts +132 -0
- package/src/pipeline/cell-text.ts +56 -0
- package/src/pipeline/context.ts +88 -0
- package/src/pipeline/dom.ts +23 -0
- package/src/pipeline/footnotes.ts +181 -0
- package/src/pipeline/math.ts +130 -0
- package/src/pipeline/normalize.ts +594 -0
- package/src/pipeline/readability.ts +36 -0
- package/src/pipeline/resolver.ts +143 -0
- package/src/pipeline/sanitize.ts +42 -0
- package/src/pipeline/tables.ts +286 -0
- package/src/pipeline/turndown.ts +191 -0
- package/src/pipeline/urls.ts +13 -0
- package/src/policy/chunk.ts +482 -0
- package/src/policy/diagnostics.ts +96 -0
- package/src/policy/explain.ts +182 -0
- package/src/policy/fallback.ts +110 -0
- package/src/policy/gating.ts +106 -0
- package/src/policy/grid-detector.ts +313 -0
- package/src/policy/identifiers.ts +75 -0
- package/src/policy/images.ts +64 -0
- package/src/policy/list-detector.ts +308 -0
- package/src/policy/lost-signal.ts +69 -0
- package/src/policy/markdown.ts +76 -0
- package/src/policy/metadata.ts +312 -0
- package/src/policy/outline-chains.ts +215 -0
- package/src/policy/outline.ts +89 -0
- package/src/policy/pagination.ts +104 -0
- package/src/policy/presets.ts +142 -0
- package/src/policy/section.ts +127 -0
- package/src/policy/selector-lint.ts +186 -0
- package/src/policy/sibling-scan.ts +99 -0
- package/src/policy/text.ts +36 -0
- package/src/policy/truncate.ts +59 -0
- package/src/preset-cache.ts +221 -0
- package/src/resources.ts +317 -0
- package/src/sampling.ts +74 -0
- package/src/server.ts +85 -0
- package/src/tools/chunk_text.ts +65 -0
- package/src/tools/explain.ts +299 -0
- package/src/tools/extract.ts +368 -0
- package/src/tools/extract_grid.ts +90 -0
- package/src/tools/extract_links.ts +138 -0
- package/src/tools/extract_list.ts +97 -0
- package/src/tools/extract_metadata.ts +102 -0
- package/src/tools/extract_section.ts +84 -0
- package/src/tools/extract_tables.ts +101 -0
- package/src/tools/html-source.ts +40 -0
- package/src/tools/html_to_markdown.ts +180 -0
- package/src/tools/outline.ts +77 -0
- package/src/tools/output-schema.ts +715 -0
- package/src/tools/schemas.ts +442 -0
- package/src/tools/suggest-preset.ts +708 -0
- package/src/types/jsdom.d.ts +15 -0
- package/src/types/turndown-plugin-gfm.d.ts +11 -0
- package/dist/assets/cli-Dfjg7dOQ.js +0 -76
- package/dist/assets/cli-Dfjg7dOQ.js.map +0 -1
- package/dist/assets/extract-CdDp-KwX.js +0 -2880
- package/dist/assets/extract-CdDp-KwX.js.map +0 -1
- package/dist/index.js +0 -2267
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const formatSchema = z.enum(['html', 'json', 'markdown', 'text']);
|
|
4
|
+
export const metadataModeSchema = z.enum(['json', 'none', 'yaml']);
|
|
5
|
+
export const extractionSchema = z.enum([
|
|
6
|
+
'aggressive',
|
|
7
|
+
'balanced',
|
|
8
|
+
'conservative',
|
|
9
|
+
]);
|
|
10
|
+
export const headingStyleSchema = z.enum(['atx', 'setext']);
|
|
11
|
+
export const codeBlockStyleSchema = z.enum(['fenced', 'indented']);
|
|
12
|
+
export const imageModeSchema = z.enum([
|
|
13
|
+
'drop',
|
|
14
|
+
'keep',
|
|
15
|
+
'reference',
|
|
16
|
+
'src-only',
|
|
17
|
+
]);
|
|
18
|
+
export const tableFormatSchema = z.enum(['csv', 'gfm', 'json']);
|
|
19
|
+
|
|
20
|
+
export const localPathField = z
|
|
21
|
+
.string()
|
|
22
|
+
.describe(
|
|
23
|
+
'Absolute or relative path to a file holding the already-rendered (post-JavaScript) HTML to process, e.g. `document.documentElement.outerHTML` written to disk by a browser/devtools capture. Read by the server so the page bytes never enter the model context — only this path string does. Resolved relative to the server process working directory; the server makes no outbound requests.',
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
export const selectorsSchema = z
|
|
27
|
+
.object({
|
|
28
|
+
include: z
|
|
29
|
+
.string()
|
|
30
|
+
.optional()
|
|
31
|
+
.describe(
|
|
32
|
+
'CSS selector restricting extraction to a matching subtree (e.g. "main", "article", ".post"). The first match replaces the document body before processing.',
|
|
33
|
+
),
|
|
34
|
+
exclude: z
|
|
35
|
+
.array(z.string())
|
|
36
|
+
.optional()
|
|
37
|
+
.describe(
|
|
38
|
+
'CSS selectors for boilerplate to remove before extraction (e.g. ["nav", "footer", "[role=banner]"]).',
|
|
39
|
+
),
|
|
40
|
+
})
|
|
41
|
+
.optional()
|
|
42
|
+
.describe(
|
|
43
|
+
'Scope the extracted/converted content by CSS selector before processing.',
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
export const readabilityOverridesSchema = z
|
|
47
|
+
.record(z.string(), z.unknown())
|
|
48
|
+
.optional()
|
|
49
|
+
.describe(
|
|
50
|
+
'Escape hatch: a record spread verbatim into the Readability options. Unstable and unvalidated; overrides the extraction/keepClasses/maxNodes/minArticleLength knobs.',
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
export const chunkStrategySchema = z.enum(['char', 'semantic']);
|
|
54
|
+
|
|
55
|
+
export const chunkOptionsSchema = z
|
|
56
|
+
.object({
|
|
57
|
+
maxTokens: z
|
|
58
|
+
.number()
|
|
59
|
+
.int()
|
|
60
|
+
.min(1)
|
|
61
|
+
.describe(
|
|
62
|
+
'Per-chunk token budget. Each chunk.text is sized so Math.round(text.length/4) stays within this bound (hard cap; oversized blocks are split by line, then hard-split).',
|
|
63
|
+
),
|
|
64
|
+
overlap: z
|
|
65
|
+
.number()
|
|
66
|
+
.int()
|
|
67
|
+
.min(0)
|
|
68
|
+
.describe(
|
|
69
|
+
'Tokens to overlap between consecutive chunks (>=0). The trailing overlapChars of chunk N becomes the leading context of chunk N+1, preserving cross-chunk coherence at a cost of redundant tokens.',
|
|
70
|
+
)
|
|
71
|
+
.default(0),
|
|
72
|
+
strategy: chunkStrategySchema
|
|
73
|
+
.describe(
|
|
74
|
+
"Chunking strategy. 'semantic' (default) breaks on heading/section boundaries and never splits a fenced code block; 'char' greedily groups blank-line-separated blocks under a chars/4 token budget (may split a code block).",
|
|
75
|
+
)
|
|
76
|
+
.default('semantic'),
|
|
77
|
+
})
|
|
78
|
+
.describe(
|
|
79
|
+
'Token-bounded chunking options for splitting the extracted markdown into RAG/embedding-ready slices.',
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
export const turndownOptionsShape = {
|
|
83
|
+
debug: z
|
|
84
|
+
.boolean()
|
|
85
|
+
.describe(
|
|
86
|
+
'Emit per-stage timings (normalize, readability, sanitize, turndown, metadata) under diagnostics.trace. Debug-only — leaves trace absent by default.',
|
|
87
|
+
)
|
|
88
|
+
.default(false),
|
|
89
|
+
cleanChrome: z
|
|
90
|
+
.boolean()
|
|
91
|
+
.describe(
|
|
92
|
+
'Strip browser chrome (scrollbars, consent/cookie banners, fixed nav and overlays) before conversion. These elements poison Readability density scoring and clutter fragment output.',
|
|
93
|
+
)
|
|
94
|
+
.default(true),
|
|
95
|
+
codeBlockStyle: codeBlockStyleSchema
|
|
96
|
+
.describe(
|
|
97
|
+
"Markdown code-block style: 'fenced' (triple backticks) or 'indented' (four-space).",
|
|
98
|
+
)
|
|
99
|
+
.default('fenced'),
|
|
100
|
+
format: formatSchema
|
|
101
|
+
.describe(
|
|
102
|
+
"Returned payload format: 'markdown' (default), 'html', 'text', or 'json' (emits {metadata, content, diagnostics}).",
|
|
103
|
+
)
|
|
104
|
+
.default('markdown'),
|
|
105
|
+
gfm: z
|
|
106
|
+
.boolean()
|
|
107
|
+
.describe(
|
|
108
|
+
'Enable GitHub-Flavored Markdown: tables, strikethrough, and task lists.',
|
|
109
|
+
)
|
|
110
|
+
.default(true),
|
|
111
|
+
headingStyle: headingStyleSchema
|
|
112
|
+
.describe(
|
|
113
|
+
"Markdown heading style: 'atx' (#) or 'setext' (underlining with = / -).",
|
|
114
|
+
)
|
|
115
|
+
.default('atx'),
|
|
116
|
+
images: imageModeSchema
|
|
117
|
+
.describe(
|
|
118
|
+
"Image handling: 'keep' (inline ), 'drop', 'src-only' (bare URL text), or 'reference' (link-reference style).",
|
|
119
|
+
)
|
|
120
|
+
.default('keep'),
|
|
121
|
+
maxChars: z
|
|
122
|
+
.number()
|
|
123
|
+
.int()
|
|
124
|
+
.min(0)
|
|
125
|
+
.describe(
|
|
126
|
+
'Truncate markdown/text output at a block boundary; never splits a fenced code block. Ignored for html/json formats.',
|
|
127
|
+
)
|
|
128
|
+
.optional(),
|
|
129
|
+
metadataMode: metadataModeSchema
|
|
130
|
+
.describe(
|
|
131
|
+
"Prepend a metadata block to the markdown/text payload: 'none' (default), 'yaml', or 'json'.",
|
|
132
|
+
)
|
|
133
|
+
.default('none'),
|
|
134
|
+
sanitize: z
|
|
135
|
+
.boolean()
|
|
136
|
+
.describe(
|
|
137
|
+
'Run DOMPurify over the extracted/fragment HTML before conversion (strips scripts, event handlers, and iframes).',
|
|
138
|
+
)
|
|
139
|
+
.default(true),
|
|
140
|
+
tables: tableFormatSchema
|
|
141
|
+
.describe(
|
|
142
|
+
'Render <table> elements via a rowspan/colspan-aware matrix: "gfm" (default native GFM table), "csv" (RFC-4180-ish code block), or "json" (array of row objects keyed by the header). When unset, tables pass through Turndown\'s native rule unchanged.',
|
|
143
|
+
)
|
|
144
|
+
.optional(),
|
|
145
|
+
// zod v4 renamed `z.string().url()` to `z.url()`.
|
|
146
|
+
baseUrl: z
|
|
147
|
+
.url()
|
|
148
|
+
.describe(
|
|
149
|
+
'Base URL for absolutizing relative links and images. NEVER fetched — origin context only.',
|
|
150
|
+
)
|
|
151
|
+
.optional(),
|
|
152
|
+
wordsPerMinute: z
|
|
153
|
+
.number()
|
|
154
|
+
.int()
|
|
155
|
+
.min(1)
|
|
156
|
+
.describe(
|
|
157
|
+
'Reading speed (words per minute) used to compute metadata.readingTimeMin.',
|
|
158
|
+
)
|
|
159
|
+
.default(200),
|
|
160
|
+
} as const;
|
|
161
|
+
|
|
162
|
+
export const extractInputShape = {
|
|
163
|
+
localPath: localPathField,
|
|
164
|
+
...turndownOptionsShape,
|
|
165
|
+
|
|
166
|
+
cache: z
|
|
167
|
+
.boolean()
|
|
168
|
+
.describe(
|
|
169
|
+
'When true, cache the result keyed by a normalized hash of the HTML plus the output-affecting options; repeat calls with the same normalized HTML hit the cache and report diagnostics.cache (hit/miss + both hashes). The cache is in-memory and bounded; entries are also exposed as readability://page/{hash} resources.',
|
|
170
|
+
)
|
|
171
|
+
.default(false),
|
|
172
|
+
extraction: extractionSchema
|
|
173
|
+
.describe(
|
|
174
|
+
"Readability scoring aggressiveness: 'balanced' (default), 'aggressive', or 'conservative'. Maps to Readability's scorer knobs.",
|
|
175
|
+
)
|
|
176
|
+
.default('balanced'),
|
|
177
|
+
keepClasses: z
|
|
178
|
+
.boolean()
|
|
179
|
+
.describe(
|
|
180
|
+
'Retain all CSS classes on extracted nodes. Defaults false, which strips non-language classes.',
|
|
181
|
+
)
|
|
182
|
+
.default(false),
|
|
183
|
+
maxNodes: z
|
|
184
|
+
.number()
|
|
185
|
+
.int()
|
|
186
|
+
.min(0)
|
|
187
|
+
.describe(
|
|
188
|
+
'Hard cap on elements parsed (Readability maxElemsToParse). Safety/perf guard for very large documents.',
|
|
189
|
+
)
|
|
190
|
+
.optional(),
|
|
191
|
+
minArticleLength: z
|
|
192
|
+
.number()
|
|
193
|
+
.int()
|
|
194
|
+
.min(0)
|
|
195
|
+
.describe(
|
|
196
|
+
'Minimum article character length below which extraction falls back to the selector cascade (Readability charThreshold).',
|
|
197
|
+
)
|
|
198
|
+
.optional(),
|
|
199
|
+
readabilityOverrides: readabilityOverridesSchema,
|
|
200
|
+
selectors: selectorsSchema,
|
|
201
|
+
chunk: chunkOptionsSchema
|
|
202
|
+
.optional()
|
|
203
|
+
.describe(
|
|
204
|
+
'Split the extracted markdown into token-bounded chunks (RAG/embedding-ready). When set, structuredContent.chunks is populated. Only applies to format:"markdown" | "text"; HTML/JSON payloads carry no markdown body to slice and leave chunks unset.',
|
|
205
|
+
),
|
|
206
|
+
imageInventory: z
|
|
207
|
+
.boolean()
|
|
208
|
+
.describe(
|
|
209
|
+
'Emit structuredContent.images: a list of {src (absolute, resolved), alt, width?, height?, caption} for every <img> in the extracted article. Independent of the `images` option (which governs inline rendering). Placeholders are skipped.',
|
|
210
|
+
)
|
|
211
|
+
.default(false),
|
|
212
|
+
} as const;
|
|
213
|
+
|
|
214
|
+
export const extractInputSchema = z.object(extractInputShape);
|
|
215
|
+
|
|
216
|
+
export const htmlToMarkdownInputShape = {
|
|
217
|
+
localPath: localPathField,
|
|
218
|
+
...turndownOptionsShape,
|
|
219
|
+
selectors: selectorsSchema,
|
|
220
|
+
} as const;
|
|
221
|
+
|
|
222
|
+
export const htmlToMarkdownInputSchema = z.object(htmlToMarkdownInputShape);
|
|
223
|
+
|
|
224
|
+
export const outlineInputShape = {
|
|
225
|
+
localPath: localPathField,
|
|
226
|
+
baseUrl: z
|
|
227
|
+
.url()
|
|
228
|
+
.describe(
|
|
229
|
+
'Base URL, carried through to metadata.baseUrl and used to absolutize links. NEVER fetched — origin context only.',
|
|
230
|
+
)
|
|
231
|
+
.optional(),
|
|
232
|
+
selectors: selectorsSchema,
|
|
233
|
+
} as const;
|
|
234
|
+
|
|
235
|
+
export const outlineInputSchema = z.object(outlineInputShape);
|
|
236
|
+
|
|
237
|
+
export const extractMetadataInputShape = {
|
|
238
|
+
localPath: localPathField,
|
|
239
|
+
baseUrl: z
|
|
240
|
+
.url()
|
|
241
|
+
.describe(
|
|
242
|
+
'Base URL, carried through to metadata.baseUrl and used to absolutize links. NEVER fetched — origin context only.',
|
|
243
|
+
)
|
|
244
|
+
.optional(),
|
|
245
|
+
} as const;
|
|
246
|
+
|
|
247
|
+
export const extractMetadataInputSchema = z.object(extractMetadataInputShape);
|
|
248
|
+
|
|
249
|
+
export const extractLinksInputShape = {
|
|
250
|
+
localPath: localPathField,
|
|
251
|
+
baseUrl: z
|
|
252
|
+
.url()
|
|
253
|
+
.describe(
|
|
254
|
+
'Base URL for absolutizing relative hrefs and computing isExternal. NEVER fetched — origin context only.',
|
|
255
|
+
)
|
|
256
|
+
.optional(),
|
|
257
|
+
sameOriginOnly: z
|
|
258
|
+
.boolean()
|
|
259
|
+
.describe(
|
|
260
|
+
'Drop cross-origin links; keep same-origin, relative, and fragment links.',
|
|
261
|
+
)
|
|
262
|
+
.default(false),
|
|
263
|
+
selectors: selectorsSchema,
|
|
264
|
+
} as const;
|
|
265
|
+
|
|
266
|
+
export const extractLinksInputSchema = z.object(extractLinksInputShape);
|
|
267
|
+
|
|
268
|
+
export const chunkTextInputShape = {
|
|
269
|
+
text: z
|
|
270
|
+
.string()
|
|
271
|
+
.describe(
|
|
272
|
+
'Already-extracted text to split (e.g. markdown from `extract` or any plain text). No HTML parsing or Readability scoring is applied — the input is chunked verbatim.',
|
|
273
|
+
),
|
|
274
|
+
maxTokens: z
|
|
275
|
+
.number()
|
|
276
|
+
.int()
|
|
277
|
+
.min(1)
|
|
278
|
+
.describe(
|
|
279
|
+
'Per-chunk token budget. Each chunk.text is sized so Math.round(text.length/4) stays within this bound (hard cap; oversized blocks are split by line, then hard-split).',
|
|
280
|
+
)
|
|
281
|
+
.default(500),
|
|
282
|
+
overlap: z
|
|
283
|
+
.number()
|
|
284
|
+
.int()
|
|
285
|
+
.min(0)
|
|
286
|
+
.describe(
|
|
287
|
+
'Tokens to overlap between consecutive chunks (>=0). The trailing overlapChars of chunk N becomes the leading context of chunk N+1.',
|
|
288
|
+
)
|
|
289
|
+
.default(0),
|
|
290
|
+
strategy: chunkStrategySchema
|
|
291
|
+
.describe(
|
|
292
|
+
"Chunking strategy. 'semantic' (default) breaks on heading/section boundaries and never splits a fenced code block; 'char' greedily groups blank-line-separated blocks under a chars/4 token budget.",
|
|
293
|
+
)
|
|
294
|
+
.default('semantic'),
|
|
295
|
+
} as const;
|
|
296
|
+
|
|
297
|
+
export const chunkTextInputSchema = z.object(chunkTextInputShape);
|
|
298
|
+
|
|
299
|
+
export const extractSectionInputShape = {
|
|
300
|
+
localPath: localPathField,
|
|
301
|
+
baseUrl: z
|
|
302
|
+
.url()
|
|
303
|
+
.describe(
|
|
304
|
+
'Base URL for absolutizing relative links and images. NEVER fetched — origin context only.',
|
|
305
|
+
)
|
|
306
|
+
.optional(),
|
|
307
|
+
selector: z
|
|
308
|
+
.string()
|
|
309
|
+
.describe(
|
|
310
|
+
'CSS selector scoping extraction to one subtree; passed straight through as selectors.include. Provide exactly one of selector/heading.',
|
|
311
|
+
)
|
|
312
|
+
.optional(),
|
|
313
|
+
heading: z
|
|
314
|
+
.string()
|
|
315
|
+
.describe(
|
|
316
|
+
'Heading text selecting one section; the section spans from this heading to the next same-or-higher-level heading. Case-insensitive; first match wins. Provide exactly one of selector/heading.',
|
|
317
|
+
)
|
|
318
|
+
.optional(),
|
|
319
|
+
} as const;
|
|
320
|
+
|
|
321
|
+
export const extractSectionInputSchema = z
|
|
322
|
+
.object(extractSectionInputShape)
|
|
323
|
+
.superRefine((value, ctx) => {
|
|
324
|
+
const hasSelector = value.selector !== undefined;
|
|
325
|
+
const hasHeading = value.heading !== undefined;
|
|
326
|
+
if (hasSelector === hasHeading) {
|
|
327
|
+
ctx.addIssue({
|
|
328
|
+
code: 'custom',
|
|
329
|
+
message:
|
|
330
|
+
'Provide exactly one of `selector` or `heading` (both set or both unset is invalid).',
|
|
331
|
+
path: ['selector'],
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
export const extractTablesInputShape = {
|
|
337
|
+
localPath: localPathField,
|
|
338
|
+
baseUrl: z
|
|
339
|
+
.url()
|
|
340
|
+
.describe(
|
|
341
|
+
'Base URL, carried through to metadata.baseUrl. NEVER fetched — origin context only.',
|
|
342
|
+
)
|
|
343
|
+
.optional(),
|
|
344
|
+
format: tableFormatSchema
|
|
345
|
+
.describe(
|
|
346
|
+
'Output format for every table: "gfm" (default — native GFM table with a delimiter row), "csv" (RFC-4180-ish, quoted fields), or "json" (array of row objects keyed by the header row).',
|
|
347
|
+
)
|
|
348
|
+
.default('gfm'),
|
|
349
|
+
selectors: selectorsSchema,
|
|
350
|
+
} as const;
|
|
351
|
+
|
|
352
|
+
export const extractTablesInputSchema = z.object(extractTablesInputShape);
|
|
353
|
+
|
|
354
|
+
export const extractListInputShape = {
|
|
355
|
+
localPath: localPathField,
|
|
356
|
+
baseUrl: z
|
|
357
|
+
.url()
|
|
358
|
+
.describe(
|
|
359
|
+
'Base URL for absolutizing item hrefs against. NEVER fetched — origin context only.',
|
|
360
|
+
)
|
|
361
|
+
.optional(),
|
|
362
|
+
selectors: selectorsSchema,
|
|
363
|
+
} as const;
|
|
364
|
+
|
|
365
|
+
export const extractListInputSchema = z.object(extractListInputShape);
|
|
366
|
+
|
|
367
|
+
export const extractGridInputShape = {
|
|
368
|
+
localPath: localPathField,
|
|
369
|
+
baseUrl: z
|
|
370
|
+
.url()
|
|
371
|
+
.describe(
|
|
372
|
+
'Base URL, carried through to metadata.baseUrl. NEVER fetched — origin context only.',
|
|
373
|
+
)
|
|
374
|
+
.optional(),
|
|
375
|
+
format: tableFormatSchema
|
|
376
|
+
.describe(
|
|
377
|
+
'Output format for the grid: "gfm" (default — native GFM table with a delimiter row), "csv" (RFC-4180-ish, quoted fields), or "json" (array of row objects keyed by the header row).',
|
|
378
|
+
)
|
|
379
|
+
.default('gfm'),
|
|
380
|
+
selectors: selectorsSchema,
|
|
381
|
+
rowSelector: z
|
|
382
|
+
.string()
|
|
383
|
+
.describe(
|
|
384
|
+
'CSS selector for repeating row containers. When set WITH cellSelector, selector mode is used (no auto-detection). Example: \'[class*="estimate-row"]\'.',
|
|
385
|
+
)
|
|
386
|
+
.optional(),
|
|
387
|
+
cellSelector: z
|
|
388
|
+
.string()
|
|
389
|
+
.describe(
|
|
390
|
+
'CSS selector for cells within each row (scoped to the row subtree). Required together with rowSelector for selector mode. Example: \'[class*="cell"]\'.',
|
|
391
|
+
)
|
|
392
|
+
.optional(),
|
|
393
|
+
} as const;
|
|
394
|
+
|
|
395
|
+
// rowSelector and cellSelector are both-or-neither: both set routes through
|
|
396
|
+
// selector mode, neither set routes through auto-detection. Exactly one set is
|
|
397
|
+
// ambiguous (which mode?), so it is rejected up front rather than silently
|
|
398
|
+
// falling back.
|
|
399
|
+
export const extractGridInputSchema = z
|
|
400
|
+
.object(extractGridInputShape)
|
|
401
|
+
.superRefine((value, ctx) => {
|
|
402
|
+
const hasRow = value.rowSelector !== undefined;
|
|
403
|
+
const hasCell = value.cellSelector !== undefined;
|
|
404
|
+
if (hasRow !== hasCell) {
|
|
405
|
+
ctx.addIssue({
|
|
406
|
+
code: 'custom',
|
|
407
|
+
message:
|
|
408
|
+
'Provide both `rowSelector` and `cellSelector` for selector mode, or neither for auto-detection (setting only one is invalid).',
|
|
409
|
+
path: ['rowSelector'],
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
export type ChunkTextInput = z.infer<typeof chunkTextInputSchema>;
|
|
415
|
+
export type ExtractGridInput = z.infer<typeof extractGridInputSchema>;
|
|
416
|
+
export type ExtractInput = z.infer<typeof extractInputSchema>;
|
|
417
|
+
export type ExtractLinksInput = z.infer<typeof extractLinksInputSchema>;
|
|
418
|
+
export type ExtractListInput = z.infer<typeof extractListInputSchema>;
|
|
419
|
+
export type ExtractMetadataInput = z.infer<typeof extractMetadataInputSchema>;
|
|
420
|
+
export type ExtractSectionInput = z.infer<typeof extractSectionInputSchema>;
|
|
421
|
+
export type ExtractTablesInput = z.infer<typeof extractTablesInputSchema>;
|
|
422
|
+
export type HtmlToMarkdownInput = z.infer<typeof htmlToMarkdownInputSchema>;
|
|
423
|
+
export type OutlineInput = z.infer<typeof outlineInputSchema>;
|
|
424
|
+
export type Selectors = z.infer<typeof selectorsSchema>;
|
|
425
|
+
|
|
426
|
+
// A worker takes the same fields as its public schema minus `localPath`, plus
|
|
427
|
+
// the already-resolved `html` string. The option fields are all optional here:
|
|
428
|
+
// the public fn hands a fully-defaulted object (it parsed the schema), while
|
|
429
|
+
// internal callers (the CLI, extract_section, tests) pass only what they care
|
|
430
|
+
// about and the worker merges schema defaults for the rest. Tools whose schema
|
|
431
|
+
// has no `.default()` fields have nothing to merge.
|
|
432
|
+
export type FromHtmlInput<T> = Partial<Omit<T, 'localPath'>> & { html: string };
|
|
433
|
+
|
|
434
|
+
export type ExtractFromHtmlInput = FromHtmlInput<ExtractInput>;
|
|
435
|
+
export type HtmlToMarkdownFromHtmlInput = FromHtmlInput<HtmlToMarkdownInput>;
|
|
436
|
+
export type OutlineFromHtmlInput = FromHtmlInput<OutlineInput>;
|
|
437
|
+
export type ExtractLinksFromHtmlInput = FromHtmlInput<ExtractLinksInput>;
|
|
438
|
+
export type ExtractListFromHtmlInput = FromHtmlInput<ExtractListInput>;
|
|
439
|
+
export type ExtractMetadataFromHtmlInput = FromHtmlInput<ExtractMetadataInput>;
|
|
440
|
+
export type ExtractSectionFromHtmlInput = FromHtmlInput<ExtractSectionInput>;
|
|
441
|
+
export type ExtractTablesFromHtmlInput = FromHtmlInput<ExtractTablesInput>;
|
|
442
|
+
export type ExtractGridFromHtmlInput = FromHtmlInput<ExtractGridInput>;
|