Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
32f53d3
fix(spreadsheet): single-row sheets, workbook titles, XLSB detection
chaliy Oct 26, 2026
c913ef0
fix(spreadsheet): single-row sheets, workbook titles, XLSB detection
chaliy Oct 26, 2026
b7fad42
chore: merge stale branch head
chaliy Oct 26, 2026
7322499
fix(spreadsheet): satisfy clippy chunks_exact_to_as_chunks
chaliy Oct 27, 2026
119c757
chore: merge origin/main
chaliy Oct 27, 2026
465cb08
Merge remote-tracking branch 'origin/main' into claude/project-thread…
chaliy Oct 27, 2026
f4b06d9
Merge remote-tracking branch 'origin/main' into claude/project-thread…
chaliy Oct 27, 2026
86b7104
chore(knowledge): tidy log after merge
chaliy Oct 27, 2026
28f4d17
Merge remote-tracking branch 'origin/main' into claude/project-thread…
chaliy Oct 27, 2026
3a62597
Merge remote-tracking branch 'origin/main' into claude/project-thread…
chaliy Oct 27, 2026
e0365e9
Merge remote-tracking branch 'origin/main' into claude/project-thread…
chaliy Oct 27, 2026
a6a7d7d
feat(spreadsheet): read XLSB workbooks with a bounds-checked BIFF12 r…
chaliy Oct 27, 2026
f36f38e
chore: supersede merged PR history
chaliy Oct 27, 2026
7130864
chore: merge origin/main; XLSB honours the parse time budget
chaliy Oct 27, 2026
50b5aea
chore: merge origin/main
chaliy Oct 27, 2026
7b9703c
feat(pptx): convert PowerPoint presentations slide by slide
chaliy Oct 27, 2026
c422071
chore: supersede merged PR history
chaliy Oct 27, 2026
5e2469b
test(js): use legacy .ppt as the unsupported-format example
chaliy Oct 27, 2026
c058ec4
chore: merge origin/main
chaliy Oct 27, 2026
41e90ee
chore(knowledge): drop trailing whitespace
chaliy Oct 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
pulldown-cmark and rendered back, so raw HTML never passes through. Front matter `title:` or the
first `# ` heading becomes `Extraction::title`. Available in the CLI, Python, Node and WASM packages; `format` serializes as
`"text"` and `"markdown"`.
- PPTX support behind the new `pptx` feature (included in `all_formats`, so in the CLI and the
Python/Node bindings): one `## Slide N: <title>` section per slide with bullets, text boxes,
tables, hyperlinks and speaker notes. Hidden slides are skipped with a `hidden_slide_skipped`
warning unless `include_hidden_content(true)`. Legacy `.ppt` is detected as the new `Format::Ppt`
and rejected explicitly. `Error::PptxExtract` reports malformed presentations.
- Nightly cargo-fuzz targets for every parser and the renderer (`crates/markkit/fuzz`, `just fuzz`,
`.github/workflows/fuzz.yml`), each checking the output-safety oracle.
- HTML page metadata: `extract_document` fills `Extraction::title` (Open Graph, JSON-LD or
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package for browsers and edge runtimes.

- **HTML** – Web pages and HTML documents; nav, header, footer, scripts, styles and forms stripped by default
- **DOCX** – Headings, lists, tables, links, emphasis
- **PPTX** – One section per slide: titles, bullets, tables, links, speaker notes
- **Spreadsheets** – XLSX/XLSM, XLSB, XLS and ODS workbooks to markdown tables, one section per sheet
- **CSV / TSV** – One markdown table; `;` and `|` delimiters detected, RFC 4180 quoting
- **Plain text / Markdown** – Text to paragraphs; Markdown normalized through the same IR (raw HTML never passed through)
Expand All @@ -33,12 +34,13 @@ package for browsers and edge runtimes.
|---|---|---|
| HTML / XHTML | Supported | `html` (default) |
| DOCX | Supported | `docx` |
| PPTX, PPTM, PPSX | Supported | `pptx` |
| XLSX, XLSM, XLSB, XLS, ODS | Supported | `spreadsheet` |
| Plain text | Supported | always on |
| CSV, TSV | Supported | always on |
| Markdown | Supported | `markdown` |
| PDF (text layer) | Supported | `pdf` |
| DOC, PPTX | Detected, rejected explicitly | – |
| DOC, PPT | Detected, rejected explicitly | – |

## Quick Start

Expand Down Expand Up @@ -193,10 +195,11 @@ let markkit = Markkit::builder()
| `html` | Yes | HTML parsing and conversion |
| `http_client` | No | URL fetching via reqwest (`extract_url`) |
| `docx` | No | DOCX conversion (zip + quick-xml) |
| `pptx` | No | PPTX conversion (zip + quick-xml) |
| `spreadsheet` | No | XLSX/XLSM, XLS, ODS conversion (calamine) |
| `pdf` | No | PDF text-layer extraction (hayro-syntax, pure Rust) |
| `markdown` | No | Markdown normalization (pulldown-cmark) |
| `all_formats` | No | `html`, `pdf`, `docx`, `spreadsheet`, `markdown` |
| `all_formats` | No | `html`, `pdf`, `docx`, `pptx`, `spreadsheet`, `markdown` |
| `tool` | No | `markkit::tool::MarkkitTool` LLM agent tool (Everruns toolkit contract) |
| `logging` | No | Reserved: pulls in `tracing`, emits no events yet |

Expand All @@ -207,7 +210,7 @@ Enable it to get `extract_url` (the CLI and the Python/Node bindings ship with i
[dependencies]
markkit = { version = "0.1", features = ["http_client"] }
# office formats only, no HTML, no network:
# markkit = { version = "0.1", default-features = false, features = ["docx", "spreadsheet"] }
# markkit = { version = "0.1", default-features = false, features = ["docx", "pptx", "spreadsheet"] }
```

### Resource limits
Expand Down
1 change: 1 addition & 0 deletions crates/markkit-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ default = ["all_formats"]
all_formats = ["markkit/all_formats"]
pdf = ["markkit/pdf"]
docx = ["markkit/docx"]
pptx = ["markkit/pptx"]
spreadsheet = ["markkit/spreadsheet"]
markdown = ["markkit/markdown"]

Expand Down
2 changes: 1 addition & 1 deletion crates/markkit-js/__test__/options.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ test("extractDocument returns metadata", async () => {
assert.equal(out.format, "html");
assert.deepEqual(out.warnings, []);
assert.equal(out.title ?? null, null);
assert.throws(() => m.extractDocumentSync(Buffer.from("PK"), { fileName: "a.pptx" }), /Unsupported/);
assert.throws(() => m.extractDocumentSync(Buffer.from("PK"), { fileName: "a.ppt" }), /Unsupported/);
});

test("extractDocument exposes page metadata", () => {
Expand Down
3 changes: 2 additions & 1 deletion crates/markkit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ default = ["html"]
html = ["dep:scraper", "dep:html5ever", "dep:ego-tree", "dep:url"]
pdf = ["dep:hayro-syntax", "dep:miniz_oxide"]
docx = ["dep:zip", "dep:quick-xml"]
pptx = ["dep:zip", "dep:quick-xml"]
spreadsheet = ["dep:calamine", "dep:zip", "dep:quick-xml", "dep:cfb"]
markdown = ["dep:pulldown-cmark"]
# Opt-in: the default build has no network stack (no reqwest/hyper/TLS).
Expand All @@ -27,7 +28,7 @@ logging = ["dep:tracing"]
tool = ["dep:tower", "dep:futures-core", "dep:base64"]
# JSON Schema for the IR (`markkit::ir::json_schema()`)
json-schema = ["dep:schemars"]
all_formats = ["html", "pdf", "docx", "spreadsheet", "markdown"]
all_formats = ["html", "pdf", "docx", "pptx", "spreadsheet", "markdown"]

[dependencies]
# Async
Expand Down
Loading
Loading