@xberg-io/opencode-xberg 1.3.6 → 1.3.8
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/.opencode/ai-rulez-bundle.json +51 -0
- package/.opencode/ai-rulez-content.js +167 -0
- package/.opencode/commands/xberg-extract.md +14 -0
- package/.opencode/commands/xberg-ocr.md +14 -0
- package/.opencode/plugins/xberg.js +75 -62
- package/.opencode/skills/batch-extraction/SKILL.md +168 -0
- package/.opencode/skills/chunking/SKILL.md +163 -0
- package/.opencode/skills/extracting-keywords/SKILL.md +171 -0
- package/.opencode/skills/extracting-tables/SKILL.md +156 -0
- package/.opencode/skills/extracting-with-ocr/SKILL.md +130 -0
- package/.opencode/skills/picking-a-format/SKILL.md +104 -0
- package/.opencode/skills/xberg/SKILL.md +427 -0
- package/.opencode/skills/xberg/references/advanced-features.md +628 -0
- package/.opencode/skills/xberg/references/cli-reference.md +462 -0
- package/.opencode/skills/xberg/references/configuration.md +587 -0
- package/.opencode/skills/xberg/references/nodejs-api.md +485 -0
- package/.opencode/skills/xberg/references/other-bindings.md +345 -0
- package/.opencode/skills/xberg/references/python-api.md +657 -0
- package/.opencode/skills/xberg/references/rust-api.md +412 -0
- package/.opencode/skills/xberg/references/supported-formats.md +252 -0
- package/.pi/prompts/xberg-extract.md +14 -0
- package/.pi/prompts/xberg-ocr.md +14 -0
- package/.pi/skills/batch-extraction/SKILL.md +168 -0
- package/.pi/skills/chunking/SKILL.md +163 -0
- package/.pi/skills/extracting-keywords/SKILL.md +171 -0
- package/.pi/skills/extracting-tables/SKILL.md +156 -0
- package/.pi/skills/extracting-with-ocr/SKILL.md +130 -0
- package/.pi/skills/picking-a-format/SKILL.md +104 -0
- package/.pi/skills/xberg/SKILL.md +427 -0
- package/.pi/skills/xberg/references/advanced-features.md +628 -0
- package/.pi/skills/xberg/references/cli-reference.md +462 -0
- package/.pi/skills/xberg/references/configuration.md +587 -0
- package/.pi/skills/xberg/references/nodejs-api.md +485 -0
- package/.pi/skills/xberg/references/other-bindings.md +345 -0
- package/.pi/skills/xberg/references/python-api.md +657 -0
- package/.pi/skills/xberg/references/rust-api.md +412 -0
- package/.pi/skills/xberg/references/supported-formats.md +252 -0
- package/README.md +40 -0
- package/package.json +69 -16
- package/scripts/mcp-launch.sh +188 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: picking-a-format
|
|
3
|
+
description: Use when choosing an output format for extracted documents — plain text, markdown, djot, HTML, JSON, or DocTags. Maps consumer (LLM, parser, archive) to the right `--format` / `--content-format` pair.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!--
|
|
7
|
+
AI-RULEZ :: GENERATED FILE — DO NOT EDIT
|
|
8
|
+
Content-Hash: blake3:bcdbffe958890e1c589f3ea44540c67c86540196a844e6de5c011faccdd345fc
|
|
9
|
+
Source-Hash: blake3:3fca38eb564d0ed9c9194d070fd8dec96de727edc92e82954cb4b9af52cddbaf
|
|
10
|
+
Schema-Version: v1
|
|
11
|
+
-->
|
|
12
|
+
|
|
13
|
+
# Picking a format
|
|
14
|
+
|
|
15
|
+
Xberg has two orthogonal format knobs. Get them right up front and the
|
|
16
|
+
downstream code stays simple.
|
|
17
|
+
|
|
18
|
+
| Knob | What it controls | Values | Default |
|
|
19
|
+
| ------------------- | ------------------------------------------------- | -------------------------------------- | ---------------- |
|
|
20
|
+
| `--format` | How the CLI prints the result | `text`, `json`, `toon` | `text` (`extract`), `json` (`batch`) |
|
|
21
|
+
| `--content-format` | How extracted content is rendered inside `result` | `plain`, `markdown`, `djot`, `html`, `json`, `doctags` | `plain` |
|
|
22
|
+
| `--token-reduction` | Strip whitespace / boilerplate for LLM contexts | `off`, `light`, `moderate`, `aggressive`, `maximum` | `off` |
|
|
23
|
+
|
|
24
|
+
`--format json` returns an envelope wrapping the `ExtractedDocument` — the
|
|
25
|
+
document lives under `.result` for `extract` and under `.results[]` for
|
|
26
|
+
`batch`, with `content`, `metadata`, `tables`, and `images` as fields of
|
|
27
|
+
that nested document. `--format text` prints just `content`.
|
|
28
|
+
`--content-format` is what shows up inside that `content` field.
|
|
29
|
+
|
|
30
|
+
## Decision tree
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
Who consumes the output?
|
|
34
|
+
├── LLM (Claude, GPT, Gemini, local) — embed/prompt context
|
|
35
|
+
│ --format text --content-format markdown
|
|
36
|
+
├── Vector store / RAG indexer
|
|
37
|
+
│ --format json --content-format markdown
|
|
38
|
+
│ (markdown preserves structure for chunking)
|
|
39
|
+
├── Downstream parser that expects machine-readable JSON
|
|
40
|
+
│ --format json --content-format plain
|
|
41
|
+
│ (cleanest text + structured metadata)
|
|
42
|
+
├── Human review / archival
|
|
43
|
+
│ --format text --content-format markdown
|
|
44
|
+
├── HTML re-rendering / web display
|
|
45
|
+
│ --format json --content-format html
|
|
46
|
+
├── Lossless intermediate for pandoc / academic tooling
|
|
47
|
+
│ --format json --content-format djot
|
|
48
|
+
└── Token-budget-constrained pipeline
|
|
49
|
+
--format text --content-format plain
|
|
50
|
+
(drops markup; add --token-reduction moderate for further savings)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Examples
|
|
54
|
+
|
|
55
|
+
Feed a PDF directly into an LLM:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
xberg extract paper.pdf --content-format markdown
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Index a corpus into a RAG store with tables and headings preserved:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
xberg batch docs/*.pdf --format json --content-format markdown \
|
|
65
|
+
| jq -c '.results[] | {content: .content, tables: .tables}'
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Strip a file to bare text for a token-tight summarizer:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
xberg extract long.pdf \
|
|
72
|
+
--content-format plain \
|
|
73
|
+
--token-reduction moderate
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Pull metadata only, ignore content:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
xberg extract file.pdf --format json | jq '.result.metadata'
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## When in doubt
|
|
83
|
+
|
|
84
|
+
- **Default to `markdown`** as the content format. It is the best
|
|
85
|
+
compromise across LLMs, RAG, and human review, and Xberg has the
|
|
86
|
+
most faithful renderer for it.
|
|
87
|
+
- Reach for `plain` only when downstream cannot tolerate any markup.
|
|
88
|
+
- Reach for `djot` only if you're already in a djot/pandoc pipeline.
|
|
89
|
+
- Reach for `html` only when re-rendering for the web.
|
|
90
|
+
- Reach for `json` for a heading-driven content tree, or `doctags` for Docling-compatible output.
|
|
91
|
+
|
|
92
|
+
## Token-reduction (orthogonal)
|
|
93
|
+
|
|
94
|
+
`--token-reduction` collapses whitespace, strips repeated headers/footers,
|
|
95
|
+
and trims boilerplate. It composes with any `--content-format`:
|
|
96
|
+
|
|
97
|
+
- `off` (default), `light`, `moderate`, `aggressive`, `maximum`.
|
|
98
|
+
|
|
99
|
+
Use `moderate` as a safe starting point for LLM context windows. `maximum`
|
|
100
|
+
is lossy — verify before relying on it.
|
|
101
|
+
|
|
102
|
+
See `references/cli-reference.md` for the full flag set and
|
|
103
|
+
`references/configuration.md` for the equivalent `output_format` and
|
|
104
|
+
`token_reduction` keys in `xberg.toml`.
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: xberg
|
|
3
|
+
description: >-
|
|
4
|
+
Extract text, tables, metadata, and images from 107 document formats
|
|
5
|
+
(PDF, Office, images, HTML, email, archives, academic) using Xberg.
|
|
6
|
+
Use when writing code that calls Xberg APIs in Python, Node.js/TypeScript,
|
|
7
|
+
Rust, or CLI. Covers installation, extraction (sync/async), configuration
|
|
8
|
+
(OCR, chunking, output format), batch processing, error handling, and plugins.
|
|
9
|
+
license: Elastic-2.0
|
|
10
|
+
metadata:
|
|
11
|
+
author: xberg-io
|
|
12
|
+
version: "0.1.0"
|
|
13
|
+
repository: https://github.com/xberg-io/xberg
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<!--
|
|
17
|
+
AI-RULEZ :: GENERATED FILE — DO NOT EDIT
|
|
18
|
+
Content-Hash: blake3:8d1ddd2c0fd7b6e9473737826178427138c3fac45cedd5b6c3d0b8a243739deb
|
|
19
|
+
Source-Hash: blake3:3fca38eb564d0ed9c9194d070fd8dec96de727edc92e82954cb4b9af52cddbaf
|
|
20
|
+
Schema-Version: v1
|
|
21
|
+
-->
|
|
22
|
+
|
|
23
|
+
# Xberg Document Extraction
|
|
24
|
+
|
|
25
|
+
Xberg is a document intelligence library with a Rust core and bindings for Python, TypeScript/Node.js, Ruby, PHP, Go, Java, C#, Elixir, WebAssembly, Dart, Kotlin Android, Swift, Zig, and C. It extracts text, tables, metadata, and images from 107 formats across 140 unique file extensions and accepts 53 compatibility MIME aliases, including PDF, Office documents, images, HTML, email, archives, and academic formats.
|
|
26
|
+
|
|
27
|
+
Use this skill when writing code that:
|
|
28
|
+
|
|
29
|
+
- Extracts text or metadata from documents
|
|
30
|
+
- Performs OCR on scanned documents or images
|
|
31
|
+
- Batch-processes multiple files
|
|
32
|
+
- Configures extraction options (output format, chunking, OCR, language detection)
|
|
33
|
+
- Implements custom plugins (post-processors, validators, OCR backends)
|
|
34
|
+
|
|
35
|
+
> If the `xberg` MCP server is registered in this session, prefer its tools over shelling out to the CLI — they expose the same extraction surface with structured arguments and results.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
### Python
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install xberg
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Node.js
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install @xberg-io/xberg
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Rust
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
cargo add xberg
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```toml
|
|
58
|
+
# Cargo.toml
|
|
59
|
+
[dependencies]
|
|
60
|
+
xberg = { version = "1.1.0", features = ["full"] }
|
|
61
|
+
tokio = { version = "1", features = ["full"] }
|
|
62
|
+
# feature flags: pdf, ocr, chunking, embeddings, language-detection, keywords, api, mcp
|
|
63
|
+
# (or "formats" / "full" aggregates); tokio-runtime is on by default
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### CLI
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
brew install xberg-io/tap/xberg
|
|
70
|
+
# or run without a persistent install (the CLI proxy package self-installs the binary):
|
|
71
|
+
npx @xberg-io/xberg-cli --help
|
|
72
|
+
uvx --from xberg-cli xberg --help
|
|
73
|
+
# or download a prebuilt binary from the latest GitHub release:
|
|
74
|
+
# https://github.com/xberg-io/xberg/releases/latest
|
|
75
|
+
# or build from source:
|
|
76
|
+
cargo install xberg-cli
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Quick Start
|
|
80
|
+
|
|
81
|
+
The library entry points are `extract(input, config)` and `extract_batch(inputs, config)`. Both return an `ExtractionResult` **envelope** — the extracted document(s) live in `result.results`, and per-document data (`content`, `tables`, `metadata`, …) is on each `result.results[i]`. Python and Node are async-only.
|
|
82
|
+
|
|
83
|
+
### Python
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
import asyncio
|
|
87
|
+
from xberg import ExtractInput, extract, ExtractionConfig
|
|
88
|
+
|
|
89
|
+
async def main() -> None:
|
|
90
|
+
result = await extract(ExtractInput(uri="document.pdf"), ExtractionConfig())
|
|
91
|
+
doc = result.results[0]
|
|
92
|
+
print(doc.content) # extracted text
|
|
93
|
+
print(doc.metadata) # document metadata
|
|
94
|
+
print(doc.tables) # extracted tables
|
|
95
|
+
|
|
96
|
+
asyncio.run(main())
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Node.js
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { extract } from "@xberg-io/xberg";
|
|
103
|
+
|
|
104
|
+
const output = await extract({ kind: "uri", uri: "document.pdf" });
|
|
105
|
+
const doc = output.results[0];
|
|
106
|
+
console.log(doc.content);
|
|
107
|
+
console.log(doc.metadata);
|
|
108
|
+
console.log(doc.tables);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Rust
|
|
112
|
+
|
|
113
|
+
```rust
|
|
114
|
+
use xberg::{extract, ExtractInput, ExtractionConfig};
|
|
115
|
+
|
|
116
|
+
#[tokio::main]
|
|
117
|
+
async fn main() -> xberg::Result<()> {
|
|
118
|
+
let output = extract(ExtractInput::from_uri("document.pdf"), &ExtractionConfig::default()).await?;
|
|
119
|
+
println!("{}", output.results[0].content);
|
|
120
|
+
Ok(())
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### CLI
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
xberg extract document.pdf
|
|
128
|
+
xberg extract document.pdf --format json
|
|
129
|
+
xberg extract document.pdf --content-format markdown
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Configuration
|
|
133
|
+
|
|
134
|
+
All languages use the same configuration structure with language-appropriate naming conventions.
|
|
135
|
+
|
|
136
|
+
### Python (snake_case)
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from xberg import (
|
|
140
|
+
ExtractInput, extract,
|
|
141
|
+
ExtractionConfig, OcrConfig, TesseractConfig, PdfConfig, ChunkingConfig, OutputFormat,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
config = ExtractionConfig(
|
|
145
|
+
ocr=OcrConfig(
|
|
146
|
+
backend="tesseract",
|
|
147
|
+
language=["eng"],
|
|
148
|
+
tesseract_config=TesseractConfig(psm=6, enable_table_detection=True),
|
|
149
|
+
),
|
|
150
|
+
pdf_options=PdfConfig(passwords=["secret123"]),
|
|
151
|
+
chunking=ChunkingConfig(max_characters=1000, overlap=200),
|
|
152
|
+
output_format=OutputFormat("markdown"),
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
result = await extract(ExtractInput(uri="document.pdf"), config)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Node.js (camelCase)
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
import { extract, type ExtractionConfig } from "@xberg-io/xberg";
|
|
162
|
+
|
|
163
|
+
const config: ExtractionConfig = {
|
|
164
|
+
ocr: { backend: "tesseract", language: ["eng"] },
|
|
165
|
+
pdfOptions: { passwords: ["secret123"] },
|
|
166
|
+
chunking: { maxCharacters: 1000, overlap: 200 },
|
|
167
|
+
outputFormat: "markdown",
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const output = await extract({ kind: "uri", uri: "document.pdf" }, config);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Rust (snake_case)
|
|
174
|
+
|
|
175
|
+
```rust
|
|
176
|
+
use xberg::{extract, ExtractInput, ExtractionConfig, OcrConfig, ChunkingConfig, OutputFormat};
|
|
177
|
+
|
|
178
|
+
let config = ExtractionConfig {
|
|
179
|
+
ocr: Some(OcrConfig {
|
|
180
|
+
backend: "tesseract".into(),
|
|
181
|
+
language: vec!["eng".to_string()],
|
|
182
|
+
..Default::default()
|
|
183
|
+
}),
|
|
184
|
+
chunking: Some(ChunkingConfig {
|
|
185
|
+
max_characters: 1000,
|
|
186
|
+
overlap: 200,
|
|
187
|
+
..Default::default()
|
|
188
|
+
}),
|
|
189
|
+
output_format: OutputFormat::Markdown,
|
|
190
|
+
..Default::default()
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
let output = extract(ExtractInput::from_uri("document.pdf"), &config).await?;
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Config File (TOML)
|
|
197
|
+
|
|
198
|
+
```toml
|
|
199
|
+
output_format = "markdown"
|
|
200
|
+
|
|
201
|
+
[ocr]
|
|
202
|
+
backend = "tesseract"
|
|
203
|
+
language = "eng"
|
|
204
|
+
|
|
205
|
+
[chunking]
|
|
206
|
+
max_characters = 1000
|
|
207
|
+
overlap = 200
|
|
208
|
+
|
|
209
|
+
[pdf_options]
|
|
210
|
+
passwords = ["secret123"]
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
# CLI: auto-discovers xberg.toml/yaml/yml/json in current/parent directories
|
|
215
|
+
xberg extract doc.pdf
|
|
216
|
+
# or explicit:
|
|
217
|
+
xberg extract doc.pdf --config xberg.toml
|
|
218
|
+
xberg extract doc.pdf --config-json '{"ocr":{"backend":"tesseract","language":"deu"}}'
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Batch Processing
|
|
222
|
+
|
|
223
|
+
`extract_batch` takes a list of `ExtractInput`s and returns one envelope whose `results` array holds a document per input (in input order); per-input failures are reported in `result.errors`.
|
|
224
|
+
|
|
225
|
+
### Python
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
from xberg import ExtractInput, extract_batch, ExtractionConfig
|
|
229
|
+
|
|
230
|
+
inputs = [
|
|
231
|
+
ExtractInput(uri="doc1.pdf"),
|
|
232
|
+
ExtractInput(uri="doc2.docx"),
|
|
233
|
+
ExtractInput(uri="doc3.xlsx"),
|
|
234
|
+
]
|
|
235
|
+
output = await extract_batch(inputs, ExtractionConfig())
|
|
236
|
+
|
|
237
|
+
for doc in output.results:
|
|
238
|
+
print(f"{len(doc.content)} chars extracted")
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Node.js
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
import { extractBatch } from "@xberg-io/xberg";
|
|
245
|
+
|
|
246
|
+
const output = await extractBatch([
|
|
247
|
+
{ kind: "uri", uri: "doc1.pdf" },
|
|
248
|
+
{ kind: "uri", uri: "doc2.docx" },
|
|
249
|
+
]);
|
|
250
|
+
for (const doc of output.results) {
|
|
251
|
+
console.log(`${doc.content.length} chars`);
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Rust
|
|
256
|
+
|
|
257
|
+
```rust
|
|
258
|
+
use xberg::{extract_batch, ExtractInput, ExtractionConfig};
|
|
259
|
+
|
|
260
|
+
let config = ExtractionConfig::default();
|
|
261
|
+
let inputs = vec![ExtractInput::from_uri("doc1.pdf"), ExtractInput::from_uri("doc2.docx")];
|
|
262
|
+
let output = extract_batch(inputs, &config).await?;
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### CLI
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
xberg batch *.pdf --format json
|
|
269
|
+
xberg batch docs/*.docx --content-format markdown
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## OCR
|
|
273
|
+
|
|
274
|
+
OCR runs automatically for images and scanned PDFs. Tesseract is the default backend (native binding, no external install required).
|
|
275
|
+
|
|
276
|
+
### Backends
|
|
277
|
+
|
|
278
|
+
Select with `OcrConfig.backend`:
|
|
279
|
+
|
|
280
|
+
- **tesseract** (default): built-in native binding. All Tesseract languages supported.
|
|
281
|
+
- **paddleocr** (`"paddleocr"` / `"paddle-ocr"`): ONNX-based PaddleOCR.
|
|
282
|
+
- **vlm**: Vision-Language-Model OCR (configure via `OcrConfig.vlm_config`).
|
|
283
|
+
|
|
284
|
+
Custom backends can be registered in Python/Node via `register_ocr_backend` (see [Advanced Features](references/advanced-features.md)).
|
|
285
|
+
|
|
286
|
+
### Language Codes
|
|
287
|
+
|
|
288
|
+
```python
|
|
289
|
+
config = ExtractionConfig(ocr=OcrConfig(language=["eng"])) # English
|
|
290
|
+
config = ExtractionConfig(ocr=OcrConfig(language=["eng", "deu"])) # Multiple
|
|
291
|
+
# The single-string shorthand ("eng+deu") is only accepted in config files / --config-json,
|
|
292
|
+
# not in the OcrConfig constructor (Python takes a list, Node takes an array).
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Force OCR
|
|
296
|
+
|
|
297
|
+
```python
|
|
298
|
+
config = ExtractionConfig(force_ocr=True) # OCR even if text is extractable
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Result Envelope and Document Fields
|
|
302
|
+
|
|
303
|
+
`extract` / `extract_batch` return an `ExtractionResult` envelope: `results` (list of documents), `errors` (per-input failures), and `summary` (counts). Per-document fields live on each document in `results` — bind `doc = result.results[0]` (Python/Node) or `&output.results[0]` (Rust) first.
|
|
304
|
+
|
|
305
|
+
| Field | Python (`doc.`) | Node.js (`doc.`) | Rust (`document.`) | Description |
|
|
306
|
+
| ------------ | ---------------------- | --------------------- | ----------------------- | --------------------------------------------- |
|
|
307
|
+
| Text content | `content` | `content` | `content` | Extracted text (str/String) |
|
|
308
|
+
| MIME type | `mime_type` | `mimeType` | `mime_type` | Input document MIME type |
|
|
309
|
+
| Metadata | `metadata` | `metadata` | `metadata` | Document metadata (flat mapping) |
|
|
310
|
+
| Tables | `tables` | `tables` | `tables` | Extracted tables with cells + markdown |
|
|
311
|
+
| Languages | `detected_languages` | `detectedLanguages` | `detected_languages` | Detected languages (if enabled) |
|
|
312
|
+
| Chunks | `chunks` | `chunks` | `chunks` | Text chunks (if chunking enabled) |
|
|
313
|
+
| Images | `images` | `images` | `images` | Extracted images (if enabled) |
|
|
314
|
+
| Elements | `elements` | `elements` | `elements` | Semantic elements (if element_based format) |
|
|
315
|
+
| Pages | `pages` | `pages` | `pages` | Per-page content (if page extraction enabled) |
|
|
316
|
+
| Keywords | `extracted_keywords` | `extractedKeywords` | `extracted_keywords` | Extracted keywords (if enabled) |
|
|
317
|
+
|
|
318
|
+
## Error Handling
|
|
319
|
+
|
|
320
|
+
### Python
|
|
321
|
+
|
|
322
|
+
`extract` / `extract_batch` raise a plain `RuntimeError` on failure — the typed `XbergError` subclasses are not raised by these entry points, so catch `RuntimeError`. Per-input failures during `extract_batch` are reported non-fatally in `result.errors`.
|
|
323
|
+
|
|
324
|
+
```python
|
|
325
|
+
from xberg import ExtractInput, extract, ExtractionConfig
|
|
326
|
+
|
|
327
|
+
try:
|
|
328
|
+
result = await extract(ExtractInput(uri="file.pdf"), ExtractionConfig())
|
|
329
|
+
for err in result.errors:
|
|
330
|
+
print(f"Per-input error: {err}")
|
|
331
|
+
except RuntimeError as e:
|
|
332
|
+
print(f"Extraction failed: {e}")
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Node.js
|
|
336
|
+
|
|
337
|
+
The Node binding throws plain `Error` objects (it does not export typed error subclasses). Catch with `instanceof Error`, and inspect `output.errors` for non-fatal per-input failures.
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
import { extract } from "@xberg-io/xberg";
|
|
341
|
+
|
|
342
|
+
try {
|
|
343
|
+
const output = await extract({ kind: "uri", uri: "file.pdf" });
|
|
344
|
+
if (output.errors.length > 0) {
|
|
345
|
+
console.error("Per-input errors:", output.errors);
|
|
346
|
+
}
|
|
347
|
+
} catch (e) {
|
|
348
|
+
if (e instanceof Error) {
|
|
349
|
+
console.error(`Extraction failed: ${e.message}`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Rust
|
|
355
|
+
|
|
356
|
+
```rust
|
|
357
|
+
use xberg::{extract, ExtractInput, ExtractionConfig, XbergError};
|
|
358
|
+
|
|
359
|
+
let config = ExtractionConfig::default();
|
|
360
|
+
match extract(ExtractInput::from_uri("file.pdf"), &config).await {
|
|
361
|
+
Ok(output) => println!("{}", output.results[0].content),
|
|
362
|
+
Err(XbergError::Parsing { message, .. }) => eprintln!("Parse error: {message}"),
|
|
363
|
+
Err(XbergError::Ocr { message, .. }) => eprintln!("OCR error: {message}"),
|
|
364
|
+
Err(XbergError::UnsupportedFormat(mime)) => eprintln!("Unsupported: {mime}"),
|
|
365
|
+
Err(e) => eprintln!("Error: {e}"),
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## Common Pitfalls
|
|
370
|
+
|
|
371
|
+
1. **Result is an envelope**: `extract` / `extract_batch` return `ExtractionResult` with `results`, `errors`, and `summary`. Per-document fields (`content`, `tables`, `chunks`, …) are on `result.results[i]`, NOT on the top-level return.
|
|
372
|
+
2. **Async-only**: Python and Node have no sync variants — always `await extract(...)`. Rust `extract` is async; use `#[tokio::main]` or an async context.
|
|
373
|
+
3. **Build the input**: pass an `ExtractInput`, not a bare path. Use `ExtractInput(uri=...)` / `ExtractInput::from_uri(...)` (Python/Rust) or `{ kind: "uri", uri: "..." }` (Node); for bytes use `kind="bytes"` with `bytes`/`mime_type`.
|
|
374
|
+
4. **Python ChunkingConfig fields**: construct with `max_characters` and `overlap` (defaults 1000 / 200); these are also the readable attributes. When passing config as a dict/JSON, the `max_chars` / `max_overlap` aliases are also accepted. Node uses `maxCharacters` / `overlap`; Rust struct fields are `max_characters` / `overlap`.
|
|
375
|
+
5. **Python errors**: `extract` / `extract_batch` raise a plain `RuntimeError` on failure, not typed `XbergError` subclasses — catch `RuntimeError`. Node throws plain `Error` (no typed error subclasses).
|
|
376
|
+
6. **Rust extract signature**: `extract(input, &config)` — the config is a reference. Use `&ExtractionConfig::default()` for defaults.
|
|
377
|
+
7. **CLI --format vs --content-format**: `--format` controls CLI output (`text`, `json`, or `toon`). `--content-format` controls content rendering (`plain`, `markdown`, `djot`, `html`, `json`, or `doctags`).
|
|
378
|
+
8. **Config file field names**: Use snake_case in TOML/YAML/JSON config files — `[chunking]` fields are `max_characters` and `overlap`; other fields use names like `output_format`, `pdf_options`.
|
|
379
|
+
|
|
380
|
+
## Supported Formats (Summary)
|
|
381
|
+
|
|
382
|
+
| Category | Extensions |
|
|
383
|
+
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
384
|
+
| **PDF** | `.pdf` |
|
|
385
|
+
| **Word** | `.docx`, `.docm`, `.doc`, `.dotx`, `.dotm`, `.dot`, `.odt`, `.pages`, `.wpd`, `.wp`, `.wp5`, `.wp6`, `.hwp`, `.hwpx` |
|
|
386
|
+
| **Spreadsheets** | `.xlsx`, `.xlsm`, `.xlsb`, `.xls`, `.xla`, `.xlam`, `.xltm`, `.xltx`, `.xlt`, `.ods`, `.numbers` |
|
|
387
|
+
| **Presentations** | `.pptx`, `.pptm`, `.ppt`, `.pps`, `.ppsx`, `.potx`, `.potm`, `.pot`, `.odp`, `.key` |
|
|
388
|
+
| **eBooks** | `.epub`, `.fb2` |
|
|
389
|
+
| **Images** | `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.bmp`, `.tiff`, `.tif`, `.jp2`, `.jpg2`, `.j2c`, `.j2k`, `.jpc`, `.jbig2`, `.jb2`, `.pnm`, `.pbm`, `.pgm`, `.ppm`, `.heic`, `.heics`, `.heif`, `.heifs`, `.hif`, `.avif`, `.avcs`, `.svg` |
|
|
390
|
+
| **Markup** | `.html`, `.htm`, `.xhtml`, `.xht`, `.xml`, `.kml` |
|
|
391
|
+
| **Data** | `.json`, `.geojson`, `.jsonl`, `.ndjson`, `.yaml`, `.yml`, `.toml`, `.csv`, `.tsv`, `.dbf`, `.sqlite`, `.sqlite3`, `.db`, `.gpkg`, `.gpkx` |
|
|
392
|
+
| **Text** | `.txt`, `.adoc`, `.asciidoc`, `.vtt`, `.md`, `.markdown`, `.commonmark`, `.qmd`, `.rmd`, `.mdx`, `.djot`, `.dj`, `.doctags`, `.rst`, `.org`, `.rtf` |
|
|
393
|
+
| **Email** | `.eml`, `.msg`, `.pst` |
|
|
394
|
+
| **Archives** | `.zip`, `.tar`, `.tgz`, `.gz`, `.7z` |
|
|
395
|
+
| **Audio/Video** | `.mp3`, `.mpga`, `.m4a`, `.wav`, `.webm`, `.mp4`, `.mpg4`, `.mp4v`, `.m4v`, `.mpeg`, `.mpg`, `.mpe`, `.m1v`, `.m2v` |
|
|
396
|
+
| **Academic** | `.bib`, `.ris`, `.nbib`, `.enw`, `.tex`, `.latex`, `.typ`, `.typst`, `.jats`, `.nxml`, `.ipynb`, `.docbook`, `.dbk`, `.docbook4`, `.docbook5`, `.opml` |
|
|
397
|
+
|
|
398
|
+
CSL JSON is supported through an explicit MIME type but does not have a registered file extension.
|
|
399
|
+
|
|
400
|
+
See [references/supported-formats.md](references/supported-formats.md) for the complete format reference with MIME types.
|
|
401
|
+
|
|
402
|
+
## Additional Resources
|
|
403
|
+
|
|
404
|
+
Detailed reference files for specific topics:
|
|
405
|
+
|
|
406
|
+
- **[Python API Reference](references/python-api.md)** — All functions, config classes, plugin protocols, exact signatures
|
|
407
|
+
- **[Node.js API Reference](references/nodejs-api.md)** — All functions, TypeScript interfaces, worker pool APIs
|
|
408
|
+
- **[Rust API Reference](references/rust-api.md)** — All functions with feature gates, structs, Cargo.toml examples
|
|
409
|
+
- **[CLI Reference](references/cli-reference.md)** — All commands, flags, config precedence, exit codes
|
|
410
|
+
- **[Configuration Reference](references/configuration.md)** — TOML/YAML/JSON formats, auto-discovery, env vars, full schema
|
|
411
|
+
- **[Supported Formats](references/supported-formats.md)** — Format families, extensions, capabilities, and authoritative discovery commands
|
|
412
|
+
- **[Advanced Features](references/advanced-features.md)** — Plugins, embeddings, MCP server, API server, security limits
|
|
413
|
+
- **[Other Language Bindings](references/other-bindings.md)** — Go, Ruby, Java, C#, PHP, Elixir, WASM, Dart, Kotlin Android, Swift, Zig, C, and Docker
|
|
414
|
+
|
|
415
|
+
## Related skills
|
|
416
|
+
|
|
417
|
+
Task-focused sibling skills go deeper than this overview:
|
|
418
|
+
|
|
419
|
+
- **extracting-with-ocr** — OCR backends, language packs, force-OCR, tuning.
|
|
420
|
+
- **extracting-tables** — layout-aware table detection and table models.
|
|
421
|
+
- **chunking** — chunk size/overlap, markdown/yaml/semantic chunkers, the `chunk` command.
|
|
422
|
+
- **extracting-keywords** — YAKE/RAKE keywords, language detection, the `embed` command.
|
|
423
|
+
- **batch-extraction** — the `batch` command, `--file-configs`, parallelism, error recovery.
|
|
424
|
+
- **picking-a-format** — choosing `--format` / `--content-format` per consumer.
|
|
425
|
+
|
|
426
|
+
Full documentation: <https://docs.xberg.io>
|
|
427
|
+
GitHub: <https://github.com/xberg-io/xberg>
|