@statewalker/content-extractors 0.2.2 → 0.2.3

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 (2) hide show
  1. package/README.md +82 -10
  2. package/package.json +7 -3
package/README.md CHANGED
@@ -1,26 +1,98 @@
1
1
  # @statewalker/content-extractors
2
2
 
3
- Content extractors: turn PDF, DOCX, XLSX, Markdown, and HTML into markdown **text** via a mime-aware registry.
3
+ ## What it is
4
4
 
5
- ## Installation
5
+ Turns files into Markdown text for indexing. Each extractor takes the file bytes as an iterable of `Uint8Array` chunks and returns text: PDF (page by page), DOCX (via HTML), XLSX (one Markdown table per sheet), HTML, Markdown and plain text. An `ExtractorRegistry` picks the extractor from the file name, with an optional MIME-type fallback.
6
+
7
+ ## Why it exists
8
+
9
+ An indexer needs text, while documents arrive as PDF, Office files or HTML. Each format needs a different parser; this package wraps them behind one function type, `ContentExtractor`, so an ingestion pipeline can route any file by name without knowing the parsers. Producing Markdown keeps headings and tables, which `@statewalker/indexer-chunker` then uses as cut points.
10
+
11
+ ## How to use
6
12
 
7
13
  ```sh
8
14
  pnpm add @statewalker/content-extractors
9
15
  ```
10
16
 
11
- ## Usage
17
+ | Import | Gives |
18
+ | --- | --- |
19
+ | `@statewalker/content-extractors` | Everything below. |
20
+ | `@statewalker/content-extractors/extractors` | The extractors and `createDefaultRegistry` only. |
21
+ | `@statewalker/content-extractors/types` | `ContentExtractor`, `ContentNormalizer` (types only). |
22
+
23
+ - `createDefaultRegistry()` — registry for `*.md`, `*.markdown`, `*.txt`, `*.html`, `*.htm`, `*.pdf`, `*.docx`, `*.docm`, `*.xlsx`.
24
+ - `ExtractorRegistry` — `registerByPattern(pattern, extractor)`, `registerByMime(mime, extractor)`, `getByPath(path)`, `getByMime(mime)`, `get(path, mime?)`.
25
+ - Extractors: `pdfExtractor`, `docxExtractor`, `xlsxExtractor`, `htmlExtractor`, `markdownExtractor`, `textExtractor`.
26
+ - Helpers: `htmlToMarkdown(html)`, `markdownToHtml(markdown)`, `getMimeType(path)`, `collectBytes(chunks)`, `collectText(chunks)`.
27
+
28
+ ## Examples
29
+
30
+ Extract a file by name:
12
31
 
13
32
  ```ts
33
+ import { readFile } from "node:fs/promises";
14
34
  import { createDefaultRegistry } from "@statewalker/content-extractors";
15
35
 
16
36
  const registry = createDefaultRegistry();
17
- const extractor = registry.get("report.pdf");
18
- const markdown = await extractor?.(pdfBytes); // string
37
+ const extract = registry.get("report.pdf");
38
+ if (!extract) throw new Error("unsupported file type");
39
+ const markdown = (await extract([await readFile("report.pdf")])) as string;
40
+ ```
41
+
42
+ Streamed input works the same way (`AsyncIterable<Uint8Array>`, for example a `fetch` body):
43
+
44
+ ```ts
45
+ const response = await fetch(url);
46
+ const extract = registry.get(url, response.headers.get("content-type") ?? undefined);
47
+ const text = await extract?.(response.body as AsyncIterable<Uint8Array>);
48
+ ```
49
+
50
+ Route files without an extension by MIME type:
51
+
52
+ ```ts
53
+ import { createDefaultRegistry, htmlExtractor, pdfExtractor } from "@statewalker/content-extractors";
54
+
55
+ const registry = createDefaultRegistry();
56
+ registry.registerByMime("application/pdf", pdfExtractor);
57
+ registry.registerByMime("text/html", htmlExtractor);
58
+ registry.get("upload-1234", "application/pdf"); // pdfExtractor
59
+ ```
60
+
61
+ Helpers:
62
+
63
+ ```ts
64
+ import { getMimeType, htmlToMarkdown, markdownToHtml } from "@statewalker/content-extractors";
65
+
66
+ getMimeType("a.PDF"); // "application/pdf"
67
+ htmlToMarkdown("<h1>T</h1>"); // "# T"
68
+ markdownToHtml("**b**"); // "<p><strong>b</strong></p>\n"
19
69
  ```
20
70
 
21
- ## API
71
+ ## Internals
72
+
73
+ ### What each format produces
74
+
75
+ | Format | Parser | Output |
76
+ | --- | --- | --- |
77
+ | PDF | `unpdf` | `## Page N` section per non-empty page |
78
+ | DOCX, DOCM | `mammoth` to HTML, then `htmlToMarkdown` | Markdown with headings, lists, tables |
79
+ | XLSX | `exceljs` | `## <sheet name>` and a Markdown table per sheet; first row is the header |
80
+ | HTML | `turndown` + GFM plugin | ATX headings, fenced code, GFM tables |
81
+ | Markdown, text | none | UTF-8 decoded text as-is |
82
+
83
+ ### Things that surprise
84
+
85
+ - **The default registry has no MIME routes.** `createDefaultRegistry().get("upload-1234", "application/pdf")` returns `undefined`; register MIME types yourself as shown above.
86
+ - **Path matching is by suffix, longest first.** `*.test.html` beats `*.html`. Matching is case-insensitive on the file name, and only the part after the last `/` is used.
87
+ - **XLSX formula and rich-text cells come out as `[object Object]`**, and dates as `Date.toString()` in the local time zone. Plain numbers and strings are fine.
88
+ - **`ContentExtractor` returns `Promise<string | unknown>`.** All built-in extractors return a string; cast or check before use.
89
+ - **Everything is read into memory.** PDF, DOCX and XLSX parsers need one contiguous buffer, so `collectBytes` joins the chunks first.
90
+ - `ContentNormalizer` is only an interface: a slot for a post-processing step (for example an LLM clean-up) that this package does not implement.
91
+
92
+ ### Dependencies
93
+
94
+ `unpdf` (PDF text), `mammoth` (DOCX to HTML), `exceljs` (XLSX), `turndown`, `@joplin/turndown-plugin-gfm` and `@types/turndown` (HTML to Markdown), `markdown-it` (Markdown to HTML).
95
+
96
+ ## License
22
97
 
23
- - `ContentExtractor` — the core contract: `bytes → Promise<string>`.
24
- - `ExtractorRegistry` / `createDefaultRegistry` — resolve an extractor by path or MIME type.
25
- - Format handlers under `./extractors` (PDF, DOCX, XLSX, Markdown, HTML).
26
- - `html-to-markdown`, `markdown-to-html`, `mime-utils`, `collect-bytes` helpers.
98
+ MIT
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "@statewalker/content-extractors",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Content extractors: turn PDF, DOCX, XLSX, Markdown, and HTML into markdown text.",
7
- "homepage": "https://github.com/statewalker/statewalker-content",
7
+ "bugs": {
8
+ "url": "https://github.com/statewalker/statewalker-search/issues"
9
+ },
10
+ "homepage": "https://github.com/statewalker/statewalker-search/tree/main/packages/content-extractors#readme",
8
11
  "author": {
9
12
  "name": "Mikhail Kotelnikov",
10
13
  "email": "mikhail.kotelnikov@gmail.com"
@@ -12,7 +15,8 @@
12
15
  "license": "MIT",
13
16
  "repository": {
14
17
  "type": "git",
15
- "url": "git+ssh://git@github.com/statewalker/statewalker-content.git"
18
+ "url": "git+https://github.com/statewalker/statewalker-search.git",
19
+ "directory": "packages/content-extractors"
16
20
  },
17
21
  "exports": {
18
22
  ".": {