Releases: leiverkus/open-document-skills
Release list
v1.15.0
Citable-software release.
- Add
CITATION.cff(CFF 1.2.0) and.zenodo.jsonfor citation metadata and Zenodo archiving. - Bump version 1.14.0 → 1.15.0 across all sync points.
Publishing this release archives the tag on Zenodo (concept + version DOI) and triggers publish.yml to build and upload open-document-lib to PyPI.
v1.14.0 — Speaker-notes PDF export for Impress
v1.14.0 - 2026-05-23
Speaker-notes PDF export for Impress. LibreOffice's impress_pdf_Export
filter has always supported notes-page export via the ExportNotesPages
and ExportOnlyNotesPages FilterData properties, but the ODP render
script only ever produced slide-only PDFs. v1.14 surfaces the capability
so reviewers and presenters can pull a handout PDF straight out of the
visual-design loop.
Added
odf_lib.odf_common.render_impress_to_pdf— thin wrapper around
convert_with_sofficethat sets the rightimpress_pdf_Export
FilterData JSON. Renders into a private temp directory and renames the
result to<stem>-with-notes.pdfor<stem>-notes.pdfso a slide-only
<stem>.pdfrendered in the same run is not clobbered.skills/odp/scripts/render.pygains mutually exclusive--notes
and--notes-onlyflags:--notes→ also emit<stem>-with-notes.pdf(slides interleaved
with notes pages).--notes-only→ also emit<stem>-notes.pdf(notes pages only).
The default slide-only<stem>.pdfcontinues to be produced in every
run; the new flags add a sibling PDF alongside it.
skills/odp/scripts/odp_common.pyre-exports
render_impress_to_pdf.skills/odp/SKILL.mddocuments the new flags in the visual-design-loop
section.tests/test_libreoffice_integration.py::test_odp_render_with_notes
exercises both flags end-to-end against the existingodp_slides.json
fixture (which already carries a speaker-note). Total: 403 tests
(was 402).
Changed
examples/dao/and thegrant-proposaltemplate documentation reframe
the DAO localisation as a German-language proposal to a third-party
funder. Earlier copy positioned the DAO example as a proposal to the
Deutsches Archäologisches Institut (DAI), which does not award
third-party grants, and listed the DFG alongside ERC/VW/Thyssen/EU.
Both references are removed throughoutexamples/dao/README.md, the
shippedgrant-proposalREADME/PROVENANCE/styles.xml,skills/odt/,
docs/,ROADMAP.md, and the trigger keywords. The DAO branding
itself (Nunito Sans,#02416C,DAO-*style names, logo placeholder)
is retained as a pure styling showcase.
v1.13.0 — ODT template ecosystem (English-first)
Generalises the v1.12 ODP template toolchain to ODT, and ships five
English-first, institution-neutral templates covering the major
scholarly document genres. ODT is where the project's scholarly
authoring stack (BibTeX/MathML/Indexes/Tracked Changes from v0.3–v1.10)
lives, so templates here matter most for the core audience.
Added
- ODT inspector layer in
odt_common.py—inspect_styles_xml
reports page layouts (margins, header/footer heights), master pages
with header/footer text previews + frames, outline-styles with their
level configurations, named paragraph/text/list styles, and font
declarations.load_styles_xmlaccepts.odt/.ott/.fodtpackages
or standalone XML files. inspect_template.py— JSON inventory CLI.extract_template.py— distil.odt/.ott/.fodt/.docxinto
a reusable template directory; DOCX auto-converts via the v1.11 OOXML
bridge.apply_template.py— one-call inject-styles + embed-pictures +
validate-refs.--template-name <shipped>or--template PATH.- Five shipped templates in
skills/odt/templates/:grant-proposal— generalised research-grant proposal for any
funding agency (DFG / ERC / VolkswagenStiftung / Gerda Henkel /
Fritz Thyssen / BMBF / EU Horizon). English, institution-neutral.academic-paper— IMRaD article with hanging-indent References.letterhead— DIN-5008-ish business letter.cv— academic CV.dissertation— long-form thesis with 5-level outline numbering,
chapter-per-page, hanging-indent bibliography.
Changed
examples/dao/build_grant_proposal.pyreduced to the
apply_template-based pipeline;examples/dao/remains as the
German DAO-archaeology localisation showcase (German prose, DAO
blue, Nunito Sans, DAO-specific styles). Logo moved to
Pictures/logo.pngso the directory is itself a valid template
consumable via--template examples/dao.
Installation
Templates ship inside skills/odt/, so install_skills.py bundles them
into every Smithery / skills.sh / Claude Code plugin install — no extra
download or configuration.
See CHANGELOG.md for the full release notes.
v1.12.0 — ODP template ecosystem
Closes the last competitive-positioning gap with Anthropic's pptx skill.
Where pptx uses an HTML-design-loop, this release takes the other route:
curated templates the agent picks from, plus tools to inspect them per-slide
and extract new ones from any .odp/.otp/.pptx (PPTX via the v1.11
OOXML bridge).
Added
inspect_template.py— JSON inventory of master pages, slide layouts,
named styles, font declarations. The agent's per-slide layout-picking input.extract_template.py— distil any.odp/.otp/.pptxinto a reusable
template directory. Filtersoffice:automatic-stylesto keep only what
master pages reference (and parent chains); copies master-page-referenced
Pictures/; seedsLICENSE.txt/PROVENANCE.md/README.md.apply_template.py— one-call inject-styles + embed-pictures +
validate-refs. Supports--template-name <shipped>and--template PATH.- Three shipped templates in
skills/odp/templates/:dao-conference— deep-blue branded, logo bottom-right (migrated from
examples/deck/styles.xml).academic-blue— cream background, navy Lato + Source Serif.minimalist-mono— near-white, JetBrains Mono + Inter.
inspect_styles_xmlandload_styles_xmlhelpers inodp_common.
Changed
examples/deck/build_deck.pyreduced from 90-line orchestration to a thin
apply_template-based wrapper. The brandedstyles.xmland the logo
moved into the shippeddao-conferencetemplate.
Installation
Templates live inside skills/odp/, so install_skills.py includes them
in every Smithery / skills.sh / Claude Code plugin install — no extra
download or configuration.
See CHANGELOG.md for the full release notes.
v1.11.0 — OOXML format conversion (ODF ↔ DOCX/XLSX/PPTX)
Bidirectional bridges between ODT/ODS/ODP and their Microsoft Office
counterparts (DOCX/XLSX/PPTX), plus the legacy MS Office binary formats
(DOC/XLS/PPT), via headless LibreOffice. Closes the last interop gap with
the OOXML world.
Added
convert_with_soffice(input, target_format, outdir, filter_name=None)
inodf_lib.odf_common, in the public API. Isolated-env:UserInstallation
temp profile — the real LibreOffice user profile is never touched.
render_to_pdfis now a one-line wrapper around it.skills/odt/scripts/convert.py— ODT ↔ DOCX/DOC.skills/ods/scripts/convert.py— ODS ↔ XLSX/XLS.skills/odp/scripts/convert.py— ODP ↔ PPTX/PPT.- Cross-family conversions (e.g. ODT → XLSX) are rejected with a clear hint.
Changed
- The previous "DOCX/PPTX/XLSX import-and-edit" README non-goal is precisely
scoped to in-place native-OOXML editing only. One-shot conversion
in either direction ships here. For sustained DOCX work the natural
pattern isconvert.py → edit as ODF → convert.pyback.
See CHANGELOG.md for the full release notes.
v1.10.0 — Generated indexes for ODT
Generated indexes for ODT — the last remaining "Out of scope" README entry
("generated indexes and tables of contents") is now in scope. The ODT skill
ships placeholder inserters for the four ODF index types plus a marker script
for the alphabetical index, and an update_indexes.py that mirrors recalc.py
(ODS v0.6) to dispatch the LibreOffice headless refresh.
Added
add_toc.py—text:table-of-contentwith configurable outline level (default 3).add_bibliography.py—text:bibliographywith entry templates.add_illustration_index.py—text:illustration-index(ortext:table-indexfor--sequence Table); covers Figure/Table/Equation/custom sequences.add_alphabetical_index.py+add_index_mark.py— alphabetical index container + point markers.update_indexes.py— soffice-driven refresh in an isolated temp profile; never touches the user's real LibreOffice profile.build_index_body_placeholder— new helper inodf_lib.odf_common's public API.validate_refs.py(ODT) — four new warn-checks for structurally empty indexes.
See CHANGELOG.md for the full release notes.
v1.9.0 — Curated themes
Curated themes — the last open roadmap post (Track D item 6 / Track C). A theme is a colour palette plus a heading/body font pairing, applied across a document through a new --theme flag. Themes are code data — one source of truth — not a static styles.xml gallery that drifts.
Added
odf_lib/themes.py— a theme registry with five curated themes:corporate-blue,warm-editorial,high-contrast,slate-mono,forest. Each is a palette + heading/body font pairing.get_theme()andtheme_font_faces()join the published library API.--theme NAMEon all five generators —create_minimal_odt,create_from_markdown,create_minimal_odp,create_minimal_ods,create_minimal_odg. The flag is purely additive: without it, every generator's output is byte-identical to before.
Changed
- The generators now declare fonts (
office:font-face-decls+style:font-name) for the first time. Themes name fonts as CSS-style stacks ending in a Liberation fallback, so a themed document renders deterministically even where the first-choice font is absent. create_minimal_odsgains a light themed touch — a themed header-row cell style plus a table-cell default style for the body font.
Full changelog: CHANGELOG.md
🤖 Generated with Claude Code
v1.8.0 — ODP slide layouts
Named slide layouts, multiple master pages, and per-slide assignment for ODP — reclassifying the former "Impress slide-master hierarchies" non-goal. ODF has no master-page hierarchy: a slide references a master page (chrome) and a slide layout (placeholder zones) independently. This delivers the achievable equivalent of PowerPoint slide layouts.
Added
odp_layouts.py— a slide-layout library: six standard layouts (title-slide,title-content,two-content,section-header,title-only,blank) defined as placeholder-zone data — one source of truth for both thestyle:presentation-page-layoutdefinitions and frame placement.set_layout.py— reassign the slide layout and/or master page on one or more slides, repositioning placeholder frames to the new layout's zones.create_minimal_odp.pyaccepts a per-slidelayoutkey (content keystitle/subtitle/body/body_left/body_rightfill the layout's zones) and a top-levelmastersarray for extra master pages with their own background colour.
Changed
create_minimal_odp.pyemits astyle:presentation-page-layoutper layout and tags slide frames withpresentation:class. Specs without alayoutkey are unchanged —title/bodyfill the defaulttitle-contentlayout.list_masters.pyreports slide layouts (presentation-page-layout+ placeholders) alongside master pages.validate_refs.py(ODP) flags slides whosepresentation-page-layout-namedoes not resolve.
Full changelog: CHANGELOG.md
🤖 Generated with Claude Code
v1.7.0 — ODS conditional formatting & pivot tables
ODS conditional formatting and pivot tables (ROADMAP Track D, item 5) — the two remaining xlsx-skill features that were ODS gaps.
Added
add_conditional_format.py— highlight a cell range by value or formula condition (value > N,value between A B,formula:EXPR, …) with--background,--text-color,--bold,--italic. Each rule is written both as acalcext:conditional-format(the form LibreOffice renders) and as an ODF-corestyle:map; repeating the command on the same range stacks another rule.add_pivot_table.py— compute a pivot (group-by +sum/count/average/min/max) and write the result grid into the target range, plus a matching ODF-coretable:data-pilot-tableso LibreOffice treats it as a real, refreshable pivot.--rowssupports nested grouping;--columnsis optional; the target sheet is created if missing.list_pivot_tables.py— list alltable:data-pilot-tabledefinitions as JSON.
Changed
parse_rangemoved fromadd_data_validation.pytoods_common.pyand is now shared; it also accepts the fully-qualifiedSheet.A1:Sheet.C10range form.validate_refs.py(ODS) gains checks for danglingstyle:mapstyle references and pivot tables whose source/target range names an unknown sheet.validate_refs.py --strictis now extension-aware: the documentedcalcextLibreOffice namespace is excluded from the OASIS core-schema check and reported as a warning instead of an error.
Full changelog: CHANGELOG.md
🤖 Generated with Claude Code
v1.6.0 — Richer editing primitives (ODT)
Structural editing for ODT (ROADMAP Track D, item 4), benchmarked against the docx skill's formatting-preserving edits. The skill could replace text and add inline apparatus but could not restructure an existing document — four new scripts close that.
Added
restyle.py— bulk-settext:style-nameon paragraphs and headings matching--current-style,--headings/--paragraphs, and/or--level.insert_blocks.py— splice a block fragment into a document. The fragment is a JSONblocksarray (the same formatcreate_minimal_odtconsumes); position via--after-anchor/--before-anchor/--at-paragraph/--at start|end.delete_block.py— remove a whole block (paragraph, heading, list, or table) by anchor text or index.edit_table.py— edit a table by name:--add-row,--add-column,--delete-row,--delete-column,--set-cell; expands repeated-cell/row shorthands first.
Changed
create_minimal_odt.pyexposes a sharedbuild_blockdispatch, reused byinsert_blocks.py.
See CHANGELOG.md.