refigure 0.3.2__tar.gz → 0.3.3__tar.gz

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 (74) hide show
  1. {refigure-0.3.2 → refigure-0.3.3}/.gitignore +1 -0
  2. {refigure-0.3.2 → refigure-0.3.3}/PKG-INFO +145 -85
  3. {refigure-0.3.2 → refigure-0.3.3}/README.md +144 -84
  4. {refigure-0.3.2 → refigure-0.3.3}/pyproject.toml +1 -1
  5. {refigure-0.3.2 → refigure-0.3.3}/ATTRIBUTION.md +0 -0
  6. {refigure-0.3.2 → refigure-0.3.3}/LICENSE +0 -0
  7. {refigure-0.3.2 → refigure-0.3.3}/NOTICE +0 -0
  8. {refigure-0.3.2 → refigure-0.3.3}/refigure/__init__.py +0 -0
  9. {refigure-0.3.2 → refigure-0.3.3}/refigure/__main__.py +0 -0
  10. {refigure-0.3.2 → refigure-0.3.3}/refigure/_io.py +0 -0
  11. {refigure-0.3.2 → refigure-0.3.3}/refigure/api.py +0 -0
  12. {refigure-0.3.2 → refigure-0.3.3}/refigure/cli.py +0 -0
  13. {refigure-0.3.2 → refigure-0.3.3}/refigure/core/__init__.py +0 -0
  14. {refigure-0.3.2 → refigure-0.3.3}/refigure/core/chart_data.py +0 -0
  15. {refigure-0.3.2 → refigure-0.3.3}/refigure/core/chart_render.py +0 -0
  16. {refigure-0.3.2 → refigure-0.3.3}/refigure/core/zipsafe.py +0 -0
  17. {refigure-0.3.2 → refigure-0.3.3}/refigure/docx/__init__.py +0 -0
  18. {refigure-0.3.2 → refigure-0.3.3}/refigure/docx_groups.py +0 -0
  19. {refigure-0.3.2 → refigure-0.3.3}/refigure/mcp/__init__.py +0 -0
  20. {refigure-0.3.2 → refigure-0.3.3}/refigure/mcp/_lru.py +0 -0
  21. {refigure-0.3.2 → refigure-0.3.3}/refigure/mcp/auth.py +0 -0
  22. {refigure-0.3.2 → refigure-0.3.3}/refigure/mcp/cli.py +0 -0
  23. {refigure-0.3.2 → refigure-0.3.3}/refigure/mcp/exceptions.py +0 -0
  24. {refigure-0.3.2 → refigure-0.3.3}/refigure/mcp/server.py +0 -0
  25. {refigure-0.3.2 → refigure-0.3.3}/refigure/mcp/state.py +0 -0
  26. {refigure-0.3.2 → refigure-0.3.3}/refigure/mcp/vlm_cache.py +0 -0
  27. {refigure-0.3.2 → refigure-0.3.3}/refigure/py.typed +0 -0
  28. {refigure-0.3.2 → refigure-0.3.3}/refigure/vlm/__init__.py +0 -0
  29. {refigure-0.3.2 → refigure-0.3.3}/refigure/vlm/cache.py +0 -0
  30. {refigure-0.3.2 → refigure-0.3.3}/refigure/vlm/client.py +0 -0
  31. {refigure-0.3.2 → refigure-0.3.3}/refigure/xlsx/__init__.py +0 -0
  32. {refigure-0.3.2 → refigure-0.3.3}/refigure/xlsx/charts.py +0 -0
  33. {refigure-0.3.2 → refigure-0.3.3}/tests/__init__.py +0 -0
  34. {refigure-0.3.2 → refigure-0.3.3}/tests/support.py +0 -0
  35. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/__init__.py +0 -0
  36. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/core/__init__.py +0 -0
  37. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/core/test_chart_data.py +0 -0
  38. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/core/test_chart_render.py +0 -0
  39. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/core/test_chart_render_missing_mermaidx.py +0 -0
  40. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/core/test_chart_render_visual.py +0 -0
  41. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/docx/__init__.py +0 -0
  42. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/docx/test_docx.py +0 -0
  43. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/__init__.py +0 -0
  44. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/conftest.py +0 -0
  45. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/test_auth.py +0 -0
  46. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/test_batch.py +0 -0
  47. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/test_bridge.py +0 -0
  48. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/test_cli.py +0 -0
  49. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/test_http.py +0 -0
  50. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/test_lru.py +0 -0
  51. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/test_prompts.py +0 -0
  52. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/test_resources.py +0 -0
  53. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/test_schema_pin.py +0 -0
  54. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/test_state.py +0 -0
  55. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/test_tools.py +0 -0
  56. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/mcp/test_vlm_cache.py +0 -0
  57. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/test_cli.py +0 -0
  58. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/test_concurrency.py +0 -0
  59. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/test_docx_chart_group_coexistence.py +0 -0
  60. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/test_docx_groups.py +0 -0
  61. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/test_io.py +0 -0
  62. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/test_optional_dependency_guards.py +0 -0
  63. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/test_property_based.py +0 -0
  64. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/test_robustness.py +0 -0
  65. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/test_vlm_max_markers.py +0 -0
  66. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/test_xml_security.py +0 -0
  67. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/vlm/__init__.py +0 -0
  68. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/vlm/test_soffice_profile_isolation.py +0 -0
  69. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/vlm/test_vlm.py +0 -0
  70. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/vlm/test_vlm_cache.py +0 -0
  71. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/vlm/test_vlm_client.py +0 -0
  72. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/xlsx/__init__.py +0 -0
  73. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/xlsx/test_xlsx.py +0 -0
  74. {refigure-0.3.2 → refigure-0.3.3}/tests/unit/xlsx/test_xlsx_charts.py +0 -0
@@ -11,6 +11,7 @@ env/
11
11
  dist/
12
12
  build/
13
13
  *.egg-info/
14
+ *.mcpb
14
15
 
15
16
  # uv auto-generates this on `uv run`/`uv pip` if absent — project's
16
17
  # dependency source of truth is requirements.txt/requirements-dev.txt
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: refigure
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: DOCX/XLSX -> Markdown conversion with native OOXML chart-data extraction (no rasterize/OCR/VLM needed) + optional VLM interpretation for figures with no native chart data
5
5
  Project-URL: Homepage, https://github.com/HelgDemidov/refigure
6
6
  Project-URL: Repository, https://github.com/HelgDemidov/refigure
@@ -46,15 +46,65 @@ Description-Content-Type: text/markdown
46
46
  [![Coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/HelgDemidov/refigure/main/docs/assets/coverage-badge.json)](https://github.com/HelgDemidov/refigure/actions/workflows/ci.yml)
47
47
  [![License: Apache 2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
48
48
  [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](pyproject.toml)
49
+ [![PyPI](https://img.shields.io/pypi/v/refigure)](https://pypi.org/project/refigure/)
50
+ [![Docker](https://img.shields.io/badge/ghcr.io-refigure-2496ED?logo=docker&logoColor=white)](https://github.com/HelgDemidov/refigure/pkgs/container/refigure)
51
+ [![MCP Registry](https://img.shields.io/badge/MCP_Registry-listed-6f42c1)](https://registry.modelcontextprotocol.io/?q=refigure)
52
+ [![Claude Desktop](https://img.shields.io/badge/Claude_Desktop-.mcpb-D97757)](https://github.com/HelgDemidov/refigure/releases/latest/download/refigure.mcpb)
49
53
 
50
54
  <!-- mcp-name: io.github.HelgDemidov/refigure -->
51
55
 
52
- DOCX / XLSX → Markdown converters that treat embedded charts, composite
53
- diagrams and infographics as single semantic objects instead of silently
54
- dropping or fragmenting them: native OOXML chart-data extraction (no
55
- rasterize/OCR/VLM) plus positioned machine-readable markers as the zero-loss
56
- floor, optional VLM interpretation (prose + mermaid) on top, cached and
57
- reproducible offline.
56
+ DOCX/XLSX → Markdown that keeps charts and infographics machine-readable
57
+ instead of losing them to OCR or a vision model: native OOXML chart data
58
+ (`numCache`/`strCache`) recovers exact numbers with zero GPU calls, zero
59
+ VLM calls, zero lost precision — by default, not as a fallback.
60
+
61
+ That default path is also why the base install (`pip install
62
+ "refigure[docx,xlsx]"`) is **~500x lighter than PyTorch-based
63
+ alternatives** (5.6MB vs. multi-GB) — the core conversion needs no ML
64
+ model at all. That number is about the core architecture, not every
65
+ distribution format: the Docker image trades it back deliberately,
66
+ bundling VLM providers + LibreOffice for a turnkey composite-figure path
67
+ (see Docker below).
68
+
69
+ VLM interpretation itself is there for the rare figure with no native
70
+ data at all (a dashboard screenshot) — never required just to get real
71
+ numbers out of a chart, on any distribution format.
72
+
73
+ Ships as a library, CLI, MCP server, and a one-click Claude Desktop
74
+ bundle — every surface returns the same native-fidelity output, not a
75
+ degraded summary for agents.
76
+
77
+ ## Features
78
+
79
+ - **Native chart-data extraction** — reads OOXML `numCache`/`strCache`
80
+ directly; no rasterize/OCR/VLM step for charts, real numbers every time.
81
+ - **Positioned zero-loss markers for composite figures** (DOCX) — grouped
82
+ shapes/infographics that mammoth would otherwise silently fragment into
83
+ disconnected pieces get a clean marker instead, with position and any
84
+ caption text preserved. Absent even in well-funded incumbents — see
85
+ [Docling issue #1287](https://github.com/docling-project/docling/issues/1287).
86
+ - **Optional VLM interpretation** (DOCX composite figures, `[vlm]` extra,
87
+ `--vlm`/`Config(use_vlm=True)`) — cloud description + a real rendered
88
+ mermaid diagram (26 supported diagram types — flowcharts, pie/xy charts,
89
+ sequence/state/ER diagrams, Gantt/timeline/sankey/treemap and more, see
90
+ Status below) on top of the zero-loss floor, for figures with no native
91
+ chart data at all (e.g. a dashboard screenshot). Provider-agnostic —
92
+ OpenRouter by default, or direct OpenAI/Ollama/vLLM/LM Studio/Anthropic
93
+ via `--vlm-provider` (`[vlm-direct]` extra). `--strict` upgrades one
94
+ specific failure (the system `soffice`/LibreOffice binary missing) from
95
+ a graceful skip to a hard error; every other VLM failure still degrades.
96
+ - **Rich, typed result** — `ConversionResult` (markdown + warnings +
97
+ chart/group counts + `vlm_used`), not a bare string.
98
+ - **CLI included** — `refigure` console command, stdin/stdout-first, native
99
+ batch mode, typed exit codes (see below).
100
+ - **MCP server included** — `refigure-mcp` console command (`[mcp]` extra),
101
+ stdio or Streamable HTTP, tools/resources/prompts, batch conversion with
102
+ per-file isolation (see below).
103
+ - **Docker image** — `ghcr.io/helgdemidov/refigure`, both console commands
104
+ on `PATH`, `soffice`/LibreOffice baked in — the VLM composite-figure
105
+ path works turnkey, no manual LibreOffice install (see below).
106
+ - **`.mcpb` bundle for Claude Desktop** — one-click install, no terminal
107
+ (`docx`+`xlsx` only, see below).
58
108
 
59
109
  ## Demo
60
110
 
@@ -117,7 +167,7 @@ uvx --from "refigure[docx,xlsx]" refigure report.docx
117
167
  ```
118
168
 
119
169
  Optional VLM interpretation, for a composite figure the chart engine can't
120
- reconstruct on its own (see Features below):
170
+ reconstruct on its own (see Features above):
121
171
 
122
172
  ```bash
123
173
  pip install "refigure[docx,vlm]"
@@ -125,37 +175,13 @@ export OPENROUTER_API_KEY=... # or --vlm-api-key-file/--vlm-prov
125
175
  refigure report.docx --vlm # needs the system soffice/LibreOffice binary too
126
176
  ```
127
177
 
128
- ## Features
178
+ ## Installation & usage
129
179
 
130
- - **Native chart-data extraction** — reads OOXML `numCache`/`strCache`
131
- directly; no rasterize/OCR/VLM step for charts, real numbers every time.
132
- - **Positioned zero-loss markers for composite figures** (DOCX) — grouped
133
- shapes/infographics that mammoth would otherwise silently fragment into
134
- disconnected pieces get a clean marker instead, with position and any
135
- caption text preserved. Absent even in well-funded incumbents — see
136
- [Docling issue #1287](https://github.com/docling-project/docling/issues/1287).
137
- - **Optional VLM interpretation** (DOCX composite figures, `[vlm]` extra,
138
- `--vlm`/`Config(use_vlm=True)`) — cloud description + a real rendered
139
- mermaid diagram (26 supported diagram types — flowcharts, pie/xy charts,
140
- sequence/state/ER diagrams, Gantt/timeline/sankey/treemap and more, see
141
- Status below) on top of the zero-loss floor, for figures with no native
142
- chart data at all (e.g. a dashboard screenshot). Provider-agnostic —
143
- OpenRouter by default, or direct OpenAI/Ollama/vLLM/LM Studio/Anthropic
144
- via `--vlm-provider` (`[vlm-direct]` extra). `--strict` upgrades one
145
- specific failure (the system `soffice`/LibreOffice binary missing) from
146
- a graceful skip to a hard error; every other VLM failure still degrades.
147
- - **Rich, typed result** — `ConversionResult` (markdown + warnings +
148
- chart/group counts + `vlm_used`), not a bare string.
149
- - **CLI included** — `refigure` console command, stdin/stdout-first, native
150
- batch mode, typed exit codes (see below).
151
- - **MCP server included** — `refigure-mcp` console command (`[mcp]` extra),
152
- stdio or Streamable HTTP, tools/resources/prompts, batch conversion with
153
- per-file isolation (see below).
154
- - **Docker image** — `ghcr.io/helgdemidov/refigure`, both console commands
155
- on `PATH`, `soffice`/LibreOffice baked in — the VLM composite-figure
156
- path works turnkey, no manual LibreOffice install (see below).
180
+ One converter, four ways to run it — pick whichever fits your pipeline.
181
+ Click a heading to expand it.
157
182
 
158
- ## CLI
183
+ <details>
184
+ <summary><b>CLI</b> — a console command, stdin/stdout-first, native batch mode</summary>
159
185
 
160
186
  `refigure` installs a console command — a thin wrapper over the same
161
187
  `convert()` used programmatically, no separate logic:
@@ -187,12 +213,17 @@ Exit codes:
187
213
  | 5 | the format's extra (`[docx]`/`[xlsx]`) isn't installed |
188
214
  | 6 | unexpected internal error |
189
215
 
190
- ## MCP server
216
+ </details>
217
+
218
+ <details>
219
+ <summary><b>MCP server</b> — for agents/IDEs that speak the protocol directly</summary>
191
220
 
192
221
  `refigure-mcp` — the same converters as an
193
222
  [MCP](https://modelcontextprotocol.io) server, for agents/IDEs that speak
194
223
  the protocol directly instead of shelling out to a CLI or importing the
195
- library:
224
+ library. Listed on the official
225
+ [MCP Registry](https://registry.modelcontextprotocol.io/?q=refigure) as
226
+ `io.github.HelgDemidov/refigure`:
196
227
 
197
228
  ```bash
198
229
  pip install "refigure[mcp,docx,xlsx]"
@@ -246,7 +277,10 @@ fairness soft-cap once 2+ callers are configured; `refigure-mcp --help`
246
277
  covers every tuning flag (concurrency, timeouts, resource-store limits,
247
278
  batch size, VLM ceiling).
248
279
 
249
- ## Docker
280
+ </details>
281
+
282
+ <details>
283
+ <summary><b>Docker</b> — one image, CLI and MCP server both on PATH, soffice baked in</summary>
250
284
 
251
285
  One image, both surfaces — `refigure` and `refigure-mcp` are already on
252
286
  `PATH`, no separate CLI/MCP builds to choose between. The one thing this
@@ -255,13 +289,17 @@ LibreOffice binary the VLM composite-figure path needs is baked in, not a
255
289
  manual install.
256
290
 
257
291
  ```bash
258
- docker pull ghcr.io/helgdemidov/refigure:0.3.1
292
+ docker pull ghcr.io/helgdemidov/refigure:latest
259
293
  ```
260
294
 
295
+ Pin an exact version instead of `:latest` for reproducibility — e.g.
296
+ `:0.3.3` — see the [package page](https://github.com/HelgDemidov/refigure/pkgs/container/refigure)
297
+ for available tags.
298
+
261
299
  CLI, via a bind mount (the image's working directory is already `/data`):
262
300
 
263
301
  ```bash
264
- docker run --rm -v "$PWD:/data:ro" ghcr.io/helgdemidov/refigure:0.3.1 \
302
+ docker run --rm -v "$PWD:/data:ro" ghcr.io/helgdemidov/refigure:latest \
265
303
  refigure /data/report.docx
266
304
  ```
267
305
 
@@ -272,7 +310,7 @@ MCP, stdio — the client launches the container itself:
272
310
  "mcpServers": {
273
311
  "refigure": {
274
312
  "command": "docker",
275
- "args": ["run", "-i", "--rm", "ghcr.io/helgdemidov/refigure:0.3.1", "refigure-mcp"]
313
+ "args": ["run", "-i", "--rm", "ghcr.io/helgdemidov/refigure:latest", "refigure-mcp"]
276
314
  }
277
315
  }
278
316
  }
@@ -287,24 +325,43 @@ flag would silently never respond:
287
325
  ```bash
288
326
  echo "sk-... = alice" > tokens.txt
289
327
  docker run --rm -p 8000:8000 -v "$PWD/tokens.txt:/data/tokens.txt:ro" \
290
- ghcr.io/helgdemidov/refigure:0.3.1 \
328
+ ghcr.io/helgdemidov/refigure:latest \
291
329
  refigure-mcp --transport http --mcp-http-host 0.0.0.0 \
292
330
  --mcp-auth-token-file /data/tokens.txt
293
331
  ```
294
332
 
333
+ </details>
334
+
335
+ <details>
336
+ <summary><b>Claude Desktop (<code>.mcpb</code>)</b> — download, double-click, done</summary>
337
+
338
+ The simplest install for a non-technical user: download, double-click,
339
+ done — no terminal, no `pip`/`uvx`/`docker`. Covers `docx`+`xlsx`
340
+ conversion only (no VLM — that needs the `[vlm]` extra, deliberately
341
+ not carried by this bundle); dependencies resolve fresh from PyPI via
342
+ `uv` on first launch, the same mechanism `uvx` uses under the hood,
343
+ just one click instead of a config snippet.
344
+
345
+ [**Download refigure.mcpb**](https://github.com/HelgDemidov/refigure/releases/latest/download/refigure.mcpb)
346
+ — open it with Claude Desktop to install.
347
+
348
+ </details>
349
+
295
350
  ## Real examples
296
351
 
297
- Full `convert()` output on real, openly-licensed documents — not
298
- cherry-picked snippets. Each file's own header states its source, license
299
- and attribution.
352
+ Concentrated excerpts (≤200 lines each) of real `convert()` output on
353
+ real, openly-licensed documents — the actual markdown a pipeline would
354
+ ingest, not a screenshot or a cherry-picked one-liner. Each file's own
355
+ header states its source, license and attribution; trimmed sections are
356
+ marked inline, never fabricated to fill space.
300
357
 
301
358
  | Source | Demonstrates | Output |
302
359
  | --- | --- | --- |
303
- | `hackair-d7.7-pilot-evaluation.docx` | native chart extraction — 8 charts, 6 render as mermaid diagrams | [examples/hackair-native-charts.md](examples/hackair-native-charts.md) |
304
- | `swd2018-254-marine-litter-ia-annex.docx` | combo: 1 chart (table-only — real verify+fallback in action, not every chart maps to mermaid) + 2 composite-figure zero-loss markers | [examples/swd2018-combo.md](examples/swd2018-combo.md) |
305
- | `govtech-2025-charts.xlsx` | XLSX at scale — 55 charts, 33 render as mermaid diagrams | [examples/govtech-xlsx-charts.md](examples/govtech-xlsx-charts.md) |
306
- | `swd2021-396-platform-work-ia.docx` | native pie chart — real EU-survey labels, all 8 charts render (3 as mermaid) | [examples/swd2021-pie-chart.md](examples/swd2021-pie-chart.md) |
307
- | `efsa-trichinella-dashboard-guide.docx` | `--vlm` interpretation — 27 figures with no native chart data, real numbers recovered from screenshots | [examples/efsa-trichinella-vlm.md](examples/efsa-trichinella-vlm.md) |
360
+ | `hackair-d7.7-pilot-evaluation.docx` | native chart extraction — real survey tables + `xychart-beta` bar charts | [examples/hackair-native-charts.md](examples/hackair-native-charts.md) |
361
+ | `swd2018-254-marine-litter-ia-annex.docx` | honest fallback — a chart that fails render-verification degrades to a clean table, plus 2 composite-figure zero-loss markers | [examples/swd2018-combo.md](examples/swd2018-combo.md) |
362
+ | `govtech-2025-charts.xlsx` | XLSX native charts — 3 distinct types (`xychart-beta`/`radar-beta`/`pie`) from one workbook | [examples/govtech-xlsx-charts.md](examples/govtech-xlsx-charts.md) |
363
+ | `swd2021-396-platform-work-ia.docx` | native pie + a 23-year time series, real EU-survey labels | [examples/swd2021-pie-chart.md](examples/swd2021-pie-chart.md) |
364
+ | `efsa-trichinella-dashboard-guide.docx` | `--vlm` interpretation — 2 screenshot figures recovered as a bar chart and a UI flowchart, real numbers | [examples/efsa-trichinella-vlm.md](examples/efsa-trichinella-vlm.md) |
308
365
 
309
366
  Open any of these on GitHub and both views are right there: the raw
310
367
  ```` ```mermaid ```` fence an LLM/RAG pipeline would read, and its native
@@ -312,37 +369,42 @@ GitHub rendering — no extra step, that's GitHub's own Markdown support.
312
369
 
313
370
  ## Status
314
371
 
315
- Published on PyPI as `refigure`. Tested against 27 real documents (15 DOCX +
316
- 12 XLSX) — 407 native charts found (400 rendered), 35 composite figures
317
- recovered as positioned zero-loss markers — see
318
- [`tests/integration/fixtures/manifest.yaml`](tests/integration/fixtures/manifest.yaml)
319
- for provenance, licenses and attribution. CI gates on a combined
320
- unit+integration test-coverage floor of 95%.
321
-
322
- The converters were extracted from a working document-analysis pipeline
323
- (government AI-policy corpus) into a single package with per-format extras
324
- (`[docx]` / `[xlsx]`). VLM interpretation of composite figures the chart
325
- engine can't reconstruct (`[vlm]` extra, `Config(use_vlm=True)`,
326
- provider-agnostic — direct OpenAI/Anthropic via `[vlm-direct]`, also needs
327
- the system `soffice`/LibreOffice binary, not installable via pip) is fully
328
- implemented, tested, and exposed through the `refigure` CLI (`--vlm` and
329
- friends — see CLI above and Quickstart). Mermaid-diagram recognition on
330
- top of that varies by diagram type and by what's actually on the source
331
- figure — common types (flowcharts, pie/xy charts) are picked reliably;
332
- more specialized ones depend on the figure carrying an unambiguous visual
333
- cue, and not every figure produces a diagram at all — a plain text
334
- description is a valid, honest fallback when it doesn't.
372
+ - **Validated** against 27 real documents (15 DOCX + 12 XLSX) — 407 native
373
+ charts found (400 rendered), 35 composite figures recovered as
374
+ positioned zero-loss markers. Full provenance:
375
+ [`tests/integration/fixtures/manifest.yaml`](tests/integration/fixtures/manifest.yaml).
376
+ - **Tested**: CI gates on a combined unit+integration coverage floor of 95%.
377
+ - **Published** as `v0.3.3` — [PyPI](https://pypi.org/project/refigure/)
378
+ (trusted publishing, no stored tokens),
379
+ [GHCR](https://github.com/HelgDemidov/refigure/pkgs/container/refigure),
380
+ and the official
381
+ [MCP Registry](https://registry.modelcontextprotocol.io/?q=refigure) as
382
+ `io.github.HelgDemidov/refigure`. `refigure-md` is a reserved alternate
383
+ name, not an active release.
384
+
385
+ Extracted from a working document-analysis pipeline (a government
386
+ AI-policy research corpus), not built from scratch for this release.
387
+
388
+ VLM interpretation of composite figures the chart engine can't reconstruct
389
+ is fully implemented and tested, not a stub — `[vlm]` extra,
390
+ provider-agnostic (direct OpenAI/Anthropic via `[vlm-direct]`), also needs
391
+ the system `soffice`/LibreOffice binary.
392
+
393
+ Mermaid-diagram recognition depends on diagram type and on what the
394
+ source figure actually contains:
395
+
396
+ - Common types (flowcharts, pie/xy charts) are picked reliably.
397
+ - More specialized ones need an unambiguous visual cue on the source figure.
398
+ - Not every figure produces a diagram — a plain-text description is an
399
+ honest fallback, not a failure.
335
400
 
336
401
  **PDF is out of scope, on purpose — a boundary, not a gap.** PDF has no
337
402
  equivalent of OOXML's cached chart data (`numCache`/`strCache`) for any
338
- mainstream chart generator, so the native, rasterize-free extraction
339
- this project is built on doesn't transfer to it — confirmed by research
340
- into PDF's own structure and how leading PDF converters handle charts
341
- today, not assumed. For mixed-format corpora, route by extension instead
342
- of expecting one tool to cover everything —
343
- [Docling](https://github.com/docling-project/docling) or
344
- [MarkItDown](https://github.com/microsoft/markitdown) for PDF, refigure
345
- for DOCX/XLSX where the chart data actually survives in the file:
403
+ mainstream chart generator, so the native, rasterize-free extraction this
404
+ project is built on doesn't transfer to it — confirmed by research into
405
+ PDF's own structure and how leading PDF converters handle charts today,
406
+ not assumed. For mixed-format corpora, route by extension instead of
407
+ expecting one tool to cover everything:
346
408
 
347
409
  ```python
348
410
  import refigure.docx
@@ -356,11 +418,9 @@ else:
356
418
  markdown = refigure.xlsx.convert(path).markdown
357
419
  ```
358
420
 
359
- `v0.3.1` published via trusted publishing (GitHub↔PyPI, no stored tokens),
360
- also on GHCR as `ghcr.io/helgdemidov/refigure` and on the official
361
- [MCP Registry](https://registry.modelcontextprotocol.io) as
362
- `io.github.HelgDemidov/refigure`. `refigure-md` is a reserved alternate
363
- name, not an active release.
421
+ Use [Docling](https://github.com/docling-project/docling) or
422
+ [MarkItDown](https://github.com/microsoft/markitdown) for PDF, refigure
423
+ for DOCX/XLSX where the chart data actually survives in the file.
364
424
 
365
425
  ## License
366
426
 
@@ -6,15 +6,65 @@
6
6
  [![Coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/HelgDemidov/refigure/main/docs/assets/coverage-badge.json)](https://github.com/HelgDemidov/refigure/actions/workflows/ci.yml)
7
7
  [![License: Apache 2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
8
8
  [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](pyproject.toml)
9
+ [![PyPI](https://img.shields.io/pypi/v/refigure)](https://pypi.org/project/refigure/)
10
+ [![Docker](https://img.shields.io/badge/ghcr.io-refigure-2496ED?logo=docker&logoColor=white)](https://github.com/HelgDemidov/refigure/pkgs/container/refigure)
11
+ [![MCP Registry](https://img.shields.io/badge/MCP_Registry-listed-6f42c1)](https://registry.modelcontextprotocol.io/?q=refigure)
12
+ [![Claude Desktop](https://img.shields.io/badge/Claude_Desktop-.mcpb-D97757)](https://github.com/HelgDemidov/refigure/releases/latest/download/refigure.mcpb)
9
13
 
10
14
  <!-- mcp-name: io.github.HelgDemidov/refigure -->
11
15
 
12
- DOCX / XLSX → Markdown converters that treat embedded charts, composite
13
- diagrams and infographics as single semantic objects instead of silently
14
- dropping or fragmenting them: native OOXML chart-data extraction (no
15
- rasterize/OCR/VLM) plus positioned machine-readable markers as the zero-loss
16
- floor, optional VLM interpretation (prose + mermaid) on top, cached and
17
- reproducible offline.
16
+ DOCX/XLSX → Markdown that keeps charts and infographics machine-readable
17
+ instead of losing them to OCR or a vision model: native OOXML chart data
18
+ (`numCache`/`strCache`) recovers exact numbers with zero GPU calls, zero
19
+ VLM calls, zero lost precision — by default, not as a fallback.
20
+
21
+ That default path is also why the base install (`pip install
22
+ "refigure[docx,xlsx]"`) is **~500x lighter than PyTorch-based
23
+ alternatives** (5.6MB vs. multi-GB) — the core conversion needs no ML
24
+ model at all. That number is about the core architecture, not every
25
+ distribution format: the Docker image trades it back deliberately,
26
+ bundling VLM providers + LibreOffice for a turnkey composite-figure path
27
+ (see Docker below).
28
+
29
+ VLM interpretation itself is there for the rare figure with no native
30
+ data at all (a dashboard screenshot) — never required just to get real
31
+ numbers out of a chart, on any distribution format.
32
+
33
+ Ships as a library, CLI, MCP server, and a one-click Claude Desktop
34
+ bundle — every surface returns the same native-fidelity output, not a
35
+ degraded summary for agents.
36
+
37
+ ## Features
38
+
39
+ - **Native chart-data extraction** — reads OOXML `numCache`/`strCache`
40
+ directly; no rasterize/OCR/VLM step for charts, real numbers every time.
41
+ - **Positioned zero-loss markers for composite figures** (DOCX) — grouped
42
+ shapes/infographics that mammoth would otherwise silently fragment into
43
+ disconnected pieces get a clean marker instead, with position and any
44
+ caption text preserved. Absent even in well-funded incumbents — see
45
+ [Docling issue #1287](https://github.com/docling-project/docling/issues/1287).
46
+ - **Optional VLM interpretation** (DOCX composite figures, `[vlm]` extra,
47
+ `--vlm`/`Config(use_vlm=True)`) — cloud description + a real rendered
48
+ mermaid diagram (26 supported diagram types — flowcharts, pie/xy charts,
49
+ sequence/state/ER diagrams, Gantt/timeline/sankey/treemap and more, see
50
+ Status below) on top of the zero-loss floor, for figures with no native
51
+ chart data at all (e.g. a dashboard screenshot). Provider-agnostic —
52
+ OpenRouter by default, or direct OpenAI/Ollama/vLLM/LM Studio/Anthropic
53
+ via `--vlm-provider` (`[vlm-direct]` extra). `--strict` upgrades one
54
+ specific failure (the system `soffice`/LibreOffice binary missing) from
55
+ a graceful skip to a hard error; every other VLM failure still degrades.
56
+ - **Rich, typed result** — `ConversionResult` (markdown + warnings +
57
+ chart/group counts + `vlm_used`), not a bare string.
58
+ - **CLI included** — `refigure` console command, stdin/stdout-first, native
59
+ batch mode, typed exit codes (see below).
60
+ - **MCP server included** — `refigure-mcp` console command (`[mcp]` extra),
61
+ stdio or Streamable HTTP, tools/resources/prompts, batch conversion with
62
+ per-file isolation (see below).
63
+ - **Docker image** — `ghcr.io/helgdemidov/refigure`, both console commands
64
+ on `PATH`, `soffice`/LibreOffice baked in — the VLM composite-figure
65
+ path works turnkey, no manual LibreOffice install (see below).
66
+ - **`.mcpb` bundle for Claude Desktop** — one-click install, no terminal
67
+ (`docx`+`xlsx` only, see below).
18
68
 
19
69
  ## Demo
20
70
 
@@ -77,7 +127,7 @@ uvx --from "refigure[docx,xlsx]" refigure report.docx
77
127
  ```
78
128
 
79
129
  Optional VLM interpretation, for a composite figure the chart engine can't
80
- reconstruct on its own (see Features below):
130
+ reconstruct on its own (see Features above):
81
131
 
82
132
  ```bash
83
133
  pip install "refigure[docx,vlm]"
@@ -85,37 +135,13 @@ export OPENROUTER_API_KEY=... # or --vlm-api-key-file/--vlm-prov
85
135
  refigure report.docx --vlm # needs the system soffice/LibreOffice binary too
86
136
  ```
87
137
 
88
- ## Features
138
+ ## Installation & usage
89
139
 
90
- - **Native chart-data extraction** — reads OOXML `numCache`/`strCache`
91
- directly; no rasterize/OCR/VLM step for charts, real numbers every time.
92
- - **Positioned zero-loss markers for composite figures** (DOCX) — grouped
93
- shapes/infographics that mammoth would otherwise silently fragment into
94
- disconnected pieces get a clean marker instead, with position and any
95
- caption text preserved. Absent even in well-funded incumbents — see
96
- [Docling issue #1287](https://github.com/docling-project/docling/issues/1287).
97
- - **Optional VLM interpretation** (DOCX composite figures, `[vlm]` extra,
98
- `--vlm`/`Config(use_vlm=True)`) — cloud description + a real rendered
99
- mermaid diagram (26 supported diagram types — flowcharts, pie/xy charts,
100
- sequence/state/ER diagrams, Gantt/timeline/sankey/treemap and more, see
101
- Status below) on top of the zero-loss floor, for figures with no native
102
- chart data at all (e.g. a dashboard screenshot). Provider-agnostic —
103
- OpenRouter by default, or direct OpenAI/Ollama/vLLM/LM Studio/Anthropic
104
- via `--vlm-provider` (`[vlm-direct]` extra). `--strict` upgrades one
105
- specific failure (the system `soffice`/LibreOffice binary missing) from
106
- a graceful skip to a hard error; every other VLM failure still degrades.
107
- - **Rich, typed result** — `ConversionResult` (markdown + warnings +
108
- chart/group counts + `vlm_used`), not a bare string.
109
- - **CLI included** — `refigure` console command, stdin/stdout-first, native
110
- batch mode, typed exit codes (see below).
111
- - **MCP server included** — `refigure-mcp` console command (`[mcp]` extra),
112
- stdio or Streamable HTTP, tools/resources/prompts, batch conversion with
113
- per-file isolation (see below).
114
- - **Docker image** — `ghcr.io/helgdemidov/refigure`, both console commands
115
- on `PATH`, `soffice`/LibreOffice baked in — the VLM composite-figure
116
- path works turnkey, no manual LibreOffice install (see below).
140
+ One converter, four ways to run it — pick whichever fits your pipeline.
141
+ Click a heading to expand it.
117
142
 
118
- ## CLI
143
+ <details>
144
+ <summary><b>CLI</b> — a console command, stdin/stdout-first, native batch mode</summary>
119
145
 
120
146
  `refigure` installs a console command — a thin wrapper over the same
121
147
  `convert()` used programmatically, no separate logic:
@@ -147,12 +173,17 @@ Exit codes:
147
173
  | 5 | the format's extra (`[docx]`/`[xlsx]`) isn't installed |
148
174
  | 6 | unexpected internal error |
149
175
 
150
- ## MCP server
176
+ </details>
177
+
178
+ <details>
179
+ <summary><b>MCP server</b> — for agents/IDEs that speak the protocol directly</summary>
151
180
 
152
181
  `refigure-mcp` — the same converters as an
153
182
  [MCP](https://modelcontextprotocol.io) server, for agents/IDEs that speak
154
183
  the protocol directly instead of shelling out to a CLI or importing the
155
- library:
184
+ library. Listed on the official
185
+ [MCP Registry](https://registry.modelcontextprotocol.io/?q=refigure) as
186
+ `io.github.HelgDemidov/refigure`:
156
187
 
157
188
  ```bash
158
189
  pip install "refigure[mcp,docx,xlsx]"
@@ -206,7 +237,10 @@ fairness soft-cap once 2+ callers are configured; `refigure-mcp --help`
206
237
  covers every tuning flag (concurrency, timeouts, resource-store limits,
207
238
  batch size, VLM ceiling).
208
239
 
209
- ## Docker
240
+ </details>
241
+
242
+ <details>
243
+ <summary><b>Docker</b> — one image, CLI and MCP server both on PATH, soffice baked in</summary>
210
244
 
211
245
  One image, both surfaces — `refigure` and `refigure-mcp` are already on
212
246
  `PATH`, no separate CLI/MCP builds to choose between. The one thing this
@@ -215,13 +249,17 @@ LibreOffice binary the VLM composite-figure path needs is baked in, not a
215
249
  manual install.
216
250
 
217
251
  ```bash
218
- docker pull ghcr.io/helgdemidov/refigure:0.3.1
252
+ docker pull ghcr.io/helgdemidov/refigure:latest
219
253
  ```
220
254
 
255
+ Pin an exact version instead of `:latest` for reproducibility — e.g.
256
+ `:0.3.3` — see the [package page](https://github.com/HelgDemidov/refigure/pkgs/container/refigure)
257
+ for available tags.
258
+
221
259
  CLI, via a bind mount (the image's working directory is already `/data`):
222
260
 
223
261
  ```bash
224
- docker run --rm -v "$PWD:/data:ro" ghcr.io/helgdemidov/refigure:0.3.1 \
262
+ docker run --rm -v "$PWD:/data:ro" ghcr.io/helgdemidov/refigure:latest \
225
263
  refigure /data/report.docx
226
264
  ```
227
265
 
@@ -232,7 +270,7 @@ MCP, stdio — the client launches the container itself:
232
270
  "mcpServers": {
233
271
  "refigure": {
234
272
  "command": "docker",
235
- "args": ["run", "-i", "--rm", "ghcr.io/helgdemidov/refigure:0.3.1", "refigure-mcp"]
273
+ "args": ["run", "-i", "--rm", "ghcr.io/helgdemidov/refigure:latest", "refigure-mcp"]
236
274
  }
237
275
  }
238
276
  }
@@ -247,24 +285,43 @@ flag would silently never respond:
247
285
  ```bash
248
286
  echo "sk-... = alice" > tokens.txt
249
287
  docker run --rm -p 8000:8000 -v "$PWD/tokens.txt:/data/tokens.txt:ro" \
250
- ghcr.io/helgdemidov/refigure:0.3.1 \
288
+ ghcr.io/helgdemidov/refigure:latest \
251
289
  refigure-mcp --transport http --mcp-http-host 0.0.0.0 \
252
290
  --mcp-auth-token-file /data/tokens.txt
253
291
  ```
254
292
 
293
+ </details>
294
+
295
+ <details>
296
+ <summary><b>Claude Desktop (<code>.mcpb</code>)</b> — download, double-click, done</summary>
297
+
298
+ The simplest install for a non-technical user: download, double-click,
299
+ done — no terminal, no `pip`/`uvx`/`docker`. Covers `docx`+`xlsx`
300
+ conversion only (no VLM — that needs the `[vlm]` extra, deliberately
301
+ not carried by this bundle); dependencies resolve fresh from PyPI via
302
+ `uv` on first launch, the same mechanism `uvx` uses under the hood,
303
+ just one click instead of a config snippet.
304
+
305
+ [**Download refigure.mcpb**](https://github.com/HelgDemidov/refigure/releases/latest/download/refigure.mcpb)
306
+ — open it with Claude Desktop to install.
307
+
308
+ </details>
309
+
255
310
  ## Real examples
256
311
 
257
- Full `convert()` output on real, openly-licensed documents — not
258
- cherry-picked snippets. Each file's own header states its source, license
259
- and attribution.
312
+ Concentrated excerpts (≤200 lines each) of real `convert()` output on
313
+ real, openly-licensed documents — the actual markdown a pipeline would
314
+ ingest, not a screenshot or a cherry-picked one-liner. Each file's own
315
+ header states its source, license and attribution; trimmed sections are
316
+ marked inline, never fabricated to fill space.
260
317
 
261
318
  | Source | Demonstrates | Output |
262
319
  | --- | --- | --- |
263
- | `hackair-d7.7-pilot-evaluation.docx` | native chart extraction — 8 charts, 6 render as mermaid diagrams | [examples/hackair-native-charts.md](examples/hackair-native-charts.md) |
264
- | `swd2018-254-marine-litter-ia-annex.docx` | combo: 1 chart (table-only — real verify+fallback in action, not every chart maps to mermaid) + 2 composite-figure zero-loss markers | [examples/swd2018-combo.md](examples/swd2018-combo.md) |
265
- | `govtech-2025-charts.xlsx` | XLSX at scale — 55 charts, 33 render as mermaid diagrams | [examples/govtech-xlsx-charts.md](examples/govtech-xlsx-charts.md) |
266
- | `swd2021-396-platform-work-ia.docx` | native pie chart — real EU-survey labels, all 8 charts render (3 as mermaid) | [examples/swd2021-pie-chart.md](examples/swd2021-pie-chart.md) |
267
- | `efsa-trichinella-dashboard-guide.docx` | `--vlm` interpretation — 27 figures with no native chart data, real numbers recovered from screenshots | [examples/efsa-trichinella-vlm.md](examples/efsa-trichinella-vlm.md) |
320
+ | `hackair-d7.7-pilot-evaluation.docx` | native chart extraction — real survey tables + `xychart-beta` bar charts | [examples/hackair-native-charts.md](examples/hackair-native-charts.md) |
321
+ | `swd2018-254-marine-litter-ia-annex.docx` | honest fallback — a chart that fails render-verification degrades to a clean table, plus 2 composite-figure zero-loss markers | [examples/swd2018-combo.md](examples/swd2018-combo.md) |
322
+ | `govtech-2025-charts.xlsx` | XLSX native charts — 3 distinct types (`xychart-beta`/`radar-beta`/`pie`) from one workbook | [examples/govtech-xlsx-charts.md](examples/govtech-xlsx-charts.md) |
323
+ | `swd2021-396-platform-work-ia.docx` | native pie + a 23-year time series, real EU-survey labels | [examples/swd2021-pie-chart.md](examples/swd2021-pie-chart.md) |
324
+ | `efsa-trichinella-dashboard-guide.docx` | `--vlm` interpretation — 2 screenshot figures recovered as a bar chart and a UI flowchart, real numbers | [examples/efsa-trichinella-vlm.md](examples/efsa-trichinella-vlm.md) |
268
325
 
269
326
  Open any of these on GitHub and both views are right there: the raw
270
327
  ```` ```mermaid ```` fence an LLM/RAG pipeline would read, and its native
@@ -272,37 +329,42 @@ GitHub rendering — no extra step, that's GitHub's own Markdown support.
272
329
 
273
330
  ## Status
274
331
 
275
- Published on PyPI as `refigure`. Tested against 27 real documents (15 DOCX +
276
- 12 XLSX) — 407 native charts found (400 rendered), 35 composite figures
277
- recovered as positioned zero-loss markers — see
278
- [`tests/integration/fixtures/manifest.yaml`](tests/integration/fixtures/manifest.yaml)
279
- for provenance, licenses and attribution. CI gates on a combined
280
- unit+integration test-coverage floor of 95%.
281
-
282
- The converters were extracted from a working document-analysis pipeline
283
- (government AI-policy corpus) into a single package with per-format extras
284
- (`[docx]` / `[xlsx]`). VLM interpretation of composite figures the chart
285
- engine can't reconstruct (`[vlm]` extra, `Config(use_vlm=True)`,
286
- provider-agnostic — direct OpenAI/Anthropic via `[vlm-direct]`, also needs
287
- the system `soffice`/LibreOffice binary, not installable via pip) is fully
288
- implemented, tested, and exposed through the `refigure` CLI (`--vlm` and
289
- friends — see CLI above and Quickstart). Mermaid-diagram recognition on
290
- top of that varies by diagram type and by what's actually on the source
291
- figure — common types (flowcharts, pie/xy charts) are picked reliably;
292
- more specialized ones depend on the figure carrying an unambiguous visual
293
- cue, and not every figure produces a diagram at all — a plain text
294
- description is a valid, honest fallback when it doesn't.
332
+ - **Validated** against 27 real documents (15 DOCX + 12 XLSX) — 407 native
333
+ charts found (400 rendered), 35 composite figures recovered as
334
+ positioned zero-loss markers. Full provenance:
335
+ [`tests/integration/fixtures/manifest.yaml`](tests/integration/fixtures/manifest.yaml).
336
+ - **Tested**: CI gates on a combined unit+integration coverage floor of 95%.
337
+ - **Published** as `v0.3.3` — [PyPI](https://pypi.org/project/refigure/)
338
+ (trusted publishing, no stored tokens),
339
+ [GHCR](https://github.com/HelgDemidov/refigure/pkgs/container/refigure),
340
+ and the official
341
+ [MCP Registry](https://registry.modelcontextprotocol.io/?q=refigure) as
342
+ `io.github.HelgDemidov/refigure`. `refigure-md` is a reserved alternate
343
+ name, not an active release.
344
+
345
+ Extracted from a working document-analysis pipeline (a government
346
+ AI-policy research corpus), not built from scratch for this release.
347
+
348
+ VLM interpretation of composite figures the chart engine can't reconstruct
349
+ is fully implemented and tested, not a stub — `[vlm]` extra,
350
+ provider-agnostic (direct OpenAI/Anthropic via `[vlm-direct]`), also needs
351
+ the system `soffice`/LibreOffice binary.
352
+
353
+ Mermaid-diagram recognition depends on diagram type and on what the
354
+ source figure actually contains:
355
+
356
+ - Common types (flowcharts, pie/xy charts) are picked reliably.
357
+ - More specialized ones need an unambiguous visual cue on the source figure.
358
+ - Not every figure produces a diagram — a plain-text description is an
359
+ honest fallback, not a failure.
295
360
 
296
361
  **PDF is out of scope, on purpose — a boundary, not a gap.** PDF has no
297
362
  equivalent of OOXML's cached chart data (`numCache`/`strCache`) for any
298
- mainstream chart generator, so the native, rasterize-free extraction
299
- this project is built on doesn't transfer to it — confirmed by research
300
- into PDF's own structure and how leading PDF converters handle charts
301
- today, not assumed. For mixed-format corpora, route by extension instead
302
- of expecting one tool to cover everything —
303
- [Docling](https://github.com/docling-project/docling) or
304
- [MarkItDown](https://github.com/microsoft/markitdown) for PDF, refigure
305
- for DOCX/XLSX where the chart data actually survives in the file:
363
+ mainstream chart generator, so the native, rasterize-free extraction this
364
+ project is built on doesn't transfer to it — confirmed by research into
365
+ PDF's own structure and how leading PDF converters handle charts today,
366
+ not assumed. For mixed-format corpora, route by extension instead of
367
+ expecting one tool to cover everything:
306
368
 
307
369
  ```python
308
370
  import refigure.docx
@@ -316,11 +378,9 @@ else:
316
378
  markdown = refigure.xlsx.convert(path).markdown
317
379
  ```
318
380
 
319
- `v0.3.1` published via trusted publishing (GitHub↔PyPI, no stored tokens),
320
- also on GHCR as `ghcr.io/helgdemidov/refigure` and on the official
321
- [MCP Registry](https://registry.modelcontextprotocol.io) as
322
- `io.github.HelgDemidov/refigure`. `refigure-md` is a reserved alternate
323
- name, not an active release.
381
+ Use [Docling](https://github.com/docling-project/docling) or
382
+ [MarkItDown](https://github.com/microsoft/markitdown) for PDF, refigure
383
+ for DOCX/XLSX where the chart data actually survives in the file.
324
384
 
325
385
  ## License
326
386
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "refigure"
7
- version = "0.3.2"
7
+ version = "0.3.3"
8
8
  description = "DOCX/XLSX -> Markdown conversion with native OOXML chart-data extraction (no rasterize/OCR/VLM needed) + optional VLM interpretation for figures with no native chart data"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes