Skip to content

Releases: leiverkus/open-document-skills

v1.15.0

Choose a tag to compare

@leiverkus leiverkus released this 16 Jun 11:38

Citable-software release.

  • Add CITATION.cff (CFF 1.2.0) and .zenodo.json for 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

Choose a tag to compare

@leiverkus leiverkus released this 23 May 20:12

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_soffice that sets the right impress_pdf_Export
    FilterData JSON. Renders into a private temp directory and renames the
    result to <stem>-with-notes.pdf or <stem>-notes.pdf so a slide-only
    <stem>.pdf rendered in the same run is not clobbered.
  • skills/odp/scripts/render.py gains mutually exclusive --notes
    and --notes-only flags:
    • --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>.pdf continues to be produced in every
      run; the new flags add a sibling PDF alongside it.
  • skills/odp/scripts/odp_common.py re-exports
    render_impress_to_pdf.
  • skills/odp/SKILL.md documents 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 existing odp_slides.json
    fixture (which already carries a speaker-note). Total: 403 tests
    (was 402).

Changed

  • examples/dao/ and the grant-proposal template 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 throughout examples/dao/README.md, the
    shipped grant-proposal README/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)

Choose a tag to compare

@leiverkus leiverkus released this 23 May 15:48

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.pyinspect_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_xml accepts .odt/.ott/.fodt packages
    or standalone XML files.
  • inspect_template.py — JSON inventory CLI.
  • extract_template.py — distil .odt/.ott/.fodt/.docx into
    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.py reduced 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.png so 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

Choose a tag to compare

@leiverkus leiverkus released this 23 May 14:15

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/.pptx into a reusable
    template directory. Filters office:automatic-styles to keep only what
    master pages reference (and parent chains); copies master-page-referenced
    Pictures/; seeds LICENSE.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_xml and load_styles_xml helpers in odp_common.

Changed

  • examples/deck/build_deck.py reduced from 90-line orchestration to a thin
    apply_template-based wrapper. The branded styles.xml and the logo
    moved into the shipped dao-conference template.

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)

Choose a tag to compare

@leiverkus leiverkus released this 23 May 11:28

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)
    in odf_lib.odf_common, in the public API. Isolated -env:UserInstallation
    temp profile — the real LibreOffice user profile is never touched.
    render_to_pdf is 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 is convert.py → edit as ODF → convert.py back.

See CHANGELOG.md for the full release notes.

v1.10.0 — Generated indexes for ODT

Choose a tag to compare

@leiverkus leiverkus released this 23 May 09:17

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.pytext:table-of-content with configurable outline level (default 3).
  • add_bibliography.pytext:bibliography with entry templates.
  • add_illustration_index.pytext:illustration-index (or text:table-index for --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 in odf_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

Choose a tag to compare

@leiverkus leiverkus released this 22 May 18:09

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() and theme_font_faces() join the published library API.
  • --theme NAME on all five generatorscreate_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_ods gains 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

Choose a tag to compare

@leiverkus leiverkus released this 22 May 16:58

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 the style:presentation-page-layout definitions 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.py accepts a per-slide layout key (content keys title/subtitle/body/body_left/body_right fill the layout's zones) and a top-level masters array for extra master pages with their own background colour.

Changed

  • create_minimal_odp.py emits a style:presentation-page-layout per layout and tags slide frames with presentation:class. Specs without a layout key are unchanged — title/body fill the default title-content layout.
  • list_masters.py reports slide layouts (presentation-page-layout + placeholders) alongside master pages.
  • validate_refs.py (ODP) flags slides whose presentation-page-layout-name does not resolve.

Full changelog: CHANGELOG.md

🤖 Generated with Claude Code

v1.7.0 — ODS conditional formatting & pivot tables

Choose a tag to compare

@leiverkus leiverkus released this 22 May 15:32

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 a calcext:conditional-format (the form LibreOffice renders) and as an ODF-core style: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-core table:data-pilot-table so LibreOffice treats it as a real, refreshable pivot. --rows supports nested grouping; --columns is optional; the target sheet is created if missing.
  • list_pivot_tables.py — list all table:data-pilot-table definitions as JSON.

Changed

  • parse_range moved from add_data_validation.py to ods_common.py and is now shared; it also accepts the fully-qualified Sheet.A1:Sheet.C10 range form.
  • validate_refs.py (ODS) gains checks for dangling style:map style references and pivot tables whose source/target range names an unknown sheet.
  • validate_refs.py --strict is now extension-aware: the documented calcext LibreOffice 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)

Choose a tag to compare

@leiverkus leiverkus released this 22 May 14:04

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-set text:style-name on 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 JSON blocks array (the same format create_minimal_odt consumes); 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.py exposes a shared build_block dispatch, reused by insert_blocks.py.

See CHANGELOG.md.