anytomd 1.2.1 → 1.3.1
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 +85 -7
- package/anytomd_bg.js +11 -11
- package/anytomd_bg.wasm +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,11 +16,11 @@ A pure Rust tool and library that converts various document formats into Markdow
|
|
|
16
16
|
|
|
17
17
|
| Format | Extensions | Notes |
|
|
18
18
|
|--------|-----------|-------|
|
|
19
|
-
| DOCX | `.docx` | Headings, tables, lists, bold/italic, hyperlinks, images, text boxes |
|
|
20
|
-
| PPTX | `.pptx` | Slides, tables, speaker notes, images, group shapes |
|
|
21
|
-
| XLSX | `.xlsx` | Multi-sheet, date/time handling, images |
|
|
22
|
-
| XLS | `.xls` | Legacy Excel (via calamine) |
|
|
23
|
-
| HTML | `.html`, `.htm` | Full DOM: headings, tables, lists, links, blockquotes, code blocks |
|
|
19
|
+
| DOCX | `.docx` | Headings, tables (incl. merged/layout tables), lists, bold/italic, hyperlinks, images, text boxes |
|
|
20
|
+
| PPTX | `.pptx` | Slides, tables (incl. merged cells), speaker notes, images, group shapes |
|
|
21
|
+
| XLSX | `.xlsx` | Multi-sheet, date/time handling, images, single-pass table rendering |
|
|
22
|
+
| XLS | `.xls` | Legacy Excel (via calamine), single-pass table rendering |
|
|
23
|
+
| HTML | `.html`, `.htm` | Full DOM: headings, tables (incl. `colspan`/`rowspan`), lists, links, blockquotes, code blocks |
|
|
24
24
|
| CSV | `.csv` | Converted to Markdown tables |
|
|
25
25
|
| Jupyter Notebook | `.ipynb` | Markdown cells preserved, code cells in fenced blocks with language detection |
|
|
26
26
|
| JSON | `.json` | Pretty-printed in fenced code blocks |
|
|
@@ -33,6 +33,8 @@ A pure Rust tool and library that converts various document formats into Markdow
|
|
|
33
33
|
|
|
34
34
|
Format is auto-detected from magic bytes and file extension. ZIP-based formats (DOCX/PPTX/XLSX) are distinguished by inspecting internal archive structure.
|
|
35
35
|
|
|
36
|
+
Large XLSX/XLS sheets render Markdown and plain text together in one row pass. Workbook parsing still uses memory proportional to the worksheet, but conversion does not build a second full cell matrix before producing output.
|
|
37
|
+
|
|
36
38
|
## Conversion Examples
|
|
37
39
|
|
|
38
40
|
### CSV
|
|
@@ -117,6 +119,30 @@ Data Overview
|
|
|
117
119
|
> Note: Test multilingual rendering.
|
|
118
120
|
```
|
|
119
121
|
|
|
122
|
+
### Tables and merged cells
|
|
123
|
+
|
|
124
|
+
Every table — plain, merged, or used for page layout — becomes a single
|
|
125
|
+
pipe-delimited Markdown table of the table's true column count. Merged cells
|
|
126
|
+
(`gridSpan`/`vMerge` in DOCX, `colspan`/`rowspan` in HTML) are handled so no
|
|
127
|
+
content is lost:
|
|
128
|
+
|
|
129
|
+
- a horizontally spanned cell puts its text in the first column it covers and
|
|
130
|
+
leaves the spanned-over columns empty (empty-fill);
|
|
131
|
+
- a vertically merged (continuation) cell is left blank;
|
|
132
|
+
- a full-width row (a single cell spanning every column) is kept as a normal
|
|
133
|
+
grid row, empty-filled to the table width — it is **not** turned into a heading
|
|
134
|
+
or a `**Label:** value` line.
|
|
135
|
+
|
|
136
|
+
This is deliberately uniform: keeping a merged/layout table as one table (rather
|
|
137
|
+
than splitting it into headings and field lines) gives downstream consumers,
|
|
138
|
+
especially LLMs, a consistent structure. The one exception is a table that
|
|
139
|
+
contains a **nested table** — a nested table cannot live inside a single Markdown
|
|
140
|
+
cell, so such a table is linearized and each cell's text and nested table are
|
|
141
|
+
emitted as standalone blocks.
|
|
142
|
+
|
|
143
|
+
PPTX tables are likewise rendered as Markdown tables; merged cells keep the
|
|
144
|
+
correct column count and the spanning cell's text is not duplicated.
|
|
145
|
+
|
|
120
146
|
## Installation
|
|
121
147
|
|
|
122
148
|
### Rust (Cargo)
|
|
@@ -252,9 +278,19 @@ anytomd --plain-text document.docx
|
|
|
252
278
|
# Plain text from stdin
|
|
253
279
|
echo "Name,Age" | anytomd --format csv --plain-text
|
|
254
280
|
|
|
255
|
-
#
|
|
281
|
+
# Extract comments (DOCX/PPTX) into an appended Comments section
|
|
282
|
+
anytomd --extract-comments document.docx
|
|
283
|
+
|
|
284
|
+
# Image descriptions via Gemini (requires GEMINI_API_KEY env var)
|
|
256
285
|
export GEMINI_API_KEY=your-key
|
|
257
|
-
anytomd presentation.pptx
|
|
286
|
+
anytomd --gemini presentation.pptx
|
|
287
|
+
|
|
288
|
+
# Use a specific Gemini model
|
|
289
|
+
anytomd --gemini --gemini-model gemini-2.5-flash-lite presentation.pptx
|
|
290
|
+
|
|
291
|
+
# Resource limits (defaults: 8GiB input, 4GiB images, 16GiB zip)
|
|
292
|
+
anytomd --max-input-size 500MB document.docx
|
|
293
|
+
anytomd --max-zip-size 2GiB archive.xlsx
|
|
258
294
|
```
|
|
259
295
|
|
|
260
296
|
### Exit Codes
|
|
@@ -313,6 +349,47 @@ for (filename, bytes) in &result.images {
|
|
|
313
349
|
}
|
|
314
350
|
```
|
|
315
351
|
|
|
352
|
+
### Extracting Comments (DOCX / PPTX)
|
|
353
|
+
|
|
354
|
+
Setting `extract_comments` appends a `# Comments` section to the end of the
|
|
355
|
+
output (both Markdown and plain text). Each comment records the commenter, the
|
|
356
|
+
comment body, and the source — the commented-on text for DOCX, or the slide
|
|
357
|
+
label for PPTX (whose comments are anchored to a point, not a text span).
|
|
358
|
+
Replies are flattened and marked `(reply)`; the flag is a no-op for other
|
|
359
|
+
formats.
|
|
360
|
+
|
|
361
|
+
```rust
|
|
362
|
+
use anytomd::{convert_file, ConversionOptions};
|
|
363
|
+
|
|
364
|
+
let options = ConversionOptions {
|
|
365
|
+
extract_comments: true,
|
|
366
|
+
..Default::default()
|
|
367
|
+
};
|
|
368
|
+
let result = convert_file("document.docx", &options).unwrap();
|
|
369
|
+
println!("{}", result.markdown);
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Example appended section:
|
|
373
|
+
|
|
374
|
+
```markdown
|
|
375
|
+
# Comments
|
|
376
|
+
|
|
377
|
+
## 1
|
|
378
|
+
- **author**: Jane Smith (2024-01-15T09:30:00Z)
|
|
379
|
+
- **comment**: Please revise this paragraph.
|
|
380
|
+
- **source**: the quick brown fox
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
Notes:
|
|
384
|
+
|
|
385
|
+
- **DOCX:** commenter identity comes from the comment author and date; the
|
|
386
|
+
source is the commented-on text (collapsed to one line, capped at 200
|
|
387
|
+
characters). Ranges in the body, headers, footers, footnotes, and endnotes
|
|
388
|
+
are all scanned. Threaded replies are detected via `commentsExtended.xml`.
|
|
389
|
+
- **PPTX:** both the legacy (`commentAuthors.xml`) and modern
|
|
390
|
+
(`authors.xml` / threaded) comment schemes are supported. The source is the
|
|
391
|
+
slide label (e.g. `Slide 2: Quarterly Results`).
|
|
392
|
+
|
|
316
393
|
### LLM-Based Image Descriptions
|
|
317
394
|
|
|
318
395
|
anytomd can generate alt text for images using any LLM backend via the `ImageDescriber` trait. A built-in Google Gemini implementation is included.
|
|
@@ -431,6 +508,7 @@ pub async fn convert_bytes_async(
|
|
|
431
508
|
| Field | Type | Default | Description |
|
|
432
509
|
|-------|------|---------|-------------|
|
|
433
510
|
| `extract_images` | `bool` | `false` | Extract embedded images into `result.images` |
|
|
511
|
+
| `extract_comments` | `bool` | `false` | Append a `# Comments` section (DOCX/PPTX only) |
|
|
434
512
|
| `max_total_image_bytes` | `usize` | 50 MB | Hard cap for total extracted image bytes |
|
|
435
513
|
| `max_input_bytes` | `usize` | 100 MB | Maximum input file size |
|
|
436
514
|
| `max_uncompressed_zip_bytes` | `usize` | 500 MB | ZIP bomb guard |
|
package/anytomd_bg.js
CHANGED
|
@@ -216,7 +216,7 @@ export function __wbg_new_typed_893dbec5fe999814(arg0, arg1) {
|
|
|
216
216
|
const a = state0.a;
|
|
217
217
|
state0.a = 0;
|
|
218
218
|
try {
|
|
219
|
-
return
|
|
219
|
+
return wasm_bindgen_33c3f992c135746b___convert__closures_____invoke___js_sys_74fce3adb247d89d___Function_fn_wasm_bindgen_33c3f992c135746b___JsValue_____wasm_bindgen_33c3f992c135746b___sys__Undefined___js_sys_74fce3adb247d89d___Function_fn_wasm_bindgen_33c3f992c135746b___JsValue_____wasm_bindgen_33c3f992c135746b___sys__Undefined______(a, state0.b, arg0, arg1);
|
|
220
220
|
} finally {
|
|
221
221
|
state0.a = a;
|
|
222
222
|
}
|
|
@@ -335,13 +335,13 @@ export function __wbg_value_414b42ce7b3eca22(arg0) {
|
|
|
335
335
|
return ret;
|
|
336
336
|
}
|
|
337
337
|
export function __wbindgen_cast_0000000000000001(arg0, arg1) {
|
|
338
|
-
// Cast intrinsic for `Closure(Closure { dtor_idx:
|
|
339
|
-
const ret = makeMutClosure(arg0, arg1, wasm.
|
|
338
|
+
// Cast intrinsic for `Closure(Closure { dtor_idx: 203, function: Function { arguments: [], shim_idx: 204, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
|
339
|
+
const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen_33c3f992c135746b___closure__destroy___dyn_core_9b3796e30d99ddb7___ops__function__FnMut_____Output_______, wasm_bindgen_33c3f992c135746b___convert__closures_____invoke______);
|
|
340
340
|
return ret;
|
|
341
341
|
}
|
|
342
342
|
export function __wbindgen_cast_0000000000000002(arg0, arg1) {
|
|
343
|
-
// Cast intrinsic for `Closure(Closure { dtor_idx:
|
|
344
|
-
const ret = makeMutClosure(arg0, arg1, wasm.
|
|
343
|
+
// Cast intrinsic for `Closure(Closure { dtor_idx: 224, function: Function { arguments: [Externref], shim_idx: 225, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
|
344
|
+
const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen_33c3f992c135746b___closure__destroy___dyn_core_9b3796e30d99ddb7___ops__function__FnMut__wasm_bindgen_33c3f992c135746b___JsValue____Output___core_9b3796e30d99ddb7___result__Result_____wasm_bindgen_33c3f992c135746b___JsError___, wasm_bindgen_33c3f992c135746b___convert__closures_____invoke___wasm_bindgen_33c3f992c135746b___JsValue__core_9b3796e30d99ddb7___result__Result_____wasm_bindgen_33c3f992c135746b___JsError__);
|
|
345
345
|
return ret;
|
|
346
346
|
}
|
|
347
347
|
export function __wbindgen_cast_0000000000000003(arg0, arg1) {
|
|
@@ -358,19 +358,19 @@ export function __wbindgen_init_externref_table() {
|
|
|
358
358
|
table.set(offset + 2, true);
|
|
359
359
|
table.set(offset + 3, false);
|
|
360
360
|
}
|
|
361
|
-
function
|
|
362
|
-
wasm.
|
|
361
|
+
function wasm_bindgen_33c3f992c135746b___convert__closures_____invoke______(arg0, arg1) {
|
|
362
|
+
wasm.wasm_bindgen_33c3f992c135746b___convert__closures_____invoke______(arg0, arg1);
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
-
function
|
|
366
|
-
const ret = wasm.
|
|
365
|
+
function wasm_bindgen_33c3f992c135746b___convert__closures_____invoke___wasm_bindgen_33c3f992c135746b___JsValue__core_9b3796e30d99ddb7___result__Result_____wasm_bindgen_33c3f992c135746b___JsError__(arg0, arg1, arg2) {
|
|
366
|
+
const ret = wasm.wasm_bindgen_33c3f992c135746b___convert__closures_____invoke___wasm_bindgen_33c3f992c135746b___JsValue__core_9b3796e30d99ddb7___result__Result_____wasm_bindgen_33c3f992c135746b___JsError__(arg0, arg1, arg2);
|
|
367
367
|
if (ret[1]) {
|
|
368
368
|
throw takeFromExternrefTable0(ret[0]);
|
|
369
369
|
}
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
-
function
|
|
373
|
-
wasm.
|
|
372
|
+
function wasm_bindgen_33c3f992c135746b___convert__closures_____invoke___js_sys_74fce3adb247d89d___Function_fn_wasm_bindgen_33c3f992c135746b___JsValue_____wasm_bindgen_33c3f992c135746b___sys__Undefined___js_sys_74fce3adb247d89d___Function_fn_wasm_bindgen_33c3f992c135746b___JsValue_____wasm_bindgen_33c3f992c135746b___sys__Undefined______(arg0, arg1, arg2, arg3) {
|
|
373
|
+
wasm.wasm_bindgen_33c3f992c135746b___convert__closures_____invoke___js_sys_74fce3adb247d89d___Function_fn_wasm_bindgen_33c3f992c135746b___JsValue_____wasm_bindgen_33c3f992c135746b___sys__Undefined___js_sys_74fce3adb247d89d___Function_fn_wasm_bindgen_33c3f992c135746b___JsValue_____wasm_bindgen_33c3f992c135746b___sys__Undefined______(arg0, arg1, arg2, arg3);
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
|
package/anytomd_bg.wasm
CHANGED
|
Binary file
|