1.9.0 (2026-09-27)
✨ Highlight: OpenDocument / LibreOffice templates
Templify now fills OpenDocument Text templates (.odt, and .ott templates, which produce .odt) created with LibreOffice Writer, Collabora or OpenOffice. It uses the same syntax and features as for Word documents:
- placeholders and format specifiers;
- conditionals (block, inline,
elseif, table rows, list items); - loops (paragraphs, table rows, list items, nested,
@index/@number); - headers and footers (including header/footer regions), footnotes and endnotes, text boxes and sections;
- markdown formatting (
EnableMarkdown,:raw),ValidateTemplateand document properties.
This matters for public-sector and other organisations standardising on ODF.
using TriasDev.Templify.Core;
// Explicit OpenDocument processor ...
var odt = new OdtTemplateProcessor();
ProcessingResult result = odt.ProcessTemplateFile("letter.odt", "letter-out.odt", data);
// ... or the new format-detecting facade for both .docx and .odt/.ott
var processor = new TemplateProcessor();
result = processor.ProcessTemplateFile(templatePath, outputPath, data);
TemplateFormat format = TemplateProcessor.DetectFormat(stream); // Docx, Odt or Unknown- No new dependencies: ODF packages are read and written with
System.IO.CompressionandSystem.Xml. - Memory: only the XML parts are inflated; images and other entries are streamed. Each XML part is capped at 256 MB.
- Safety: DTDs are prohibited, and duplicate or unsafe ZIP entry names are rejected.
- Verified with LibreOffice: outputs open and render correctly, including numbered lists that continue across loop iterations.
- Word path unchanged:
DocumentTemplateProcessorbehaves as in 1.8.0, and results for the same template are identical in both formats. - Known differences from Word (whitespace collapsing, bookmarks, merged cells across rows,
UpdateFieldsOnOpen, comments,.fodt) are documented at LibreOffice / OpenDocument. - Developer guide: OpenDocument (.odt).
- The GUI accepts
.odt/.ott, and the Demo and examples include a LibreOffice letter.
New public API (additive)
OdtTemplateProcessor: same methods asDocumentTemplateProcessor.TemplateProcessor: a facade that detects the format and passes the call to the matching processor.TemplateFormat: enum withUnknown,DocxandOdt.ValidationErrorType.InvalidDocument: for unsupported, corrupted or rejected input. Used by the new ODT and facade paths.ValidationWarningType.MissingConditionVariable: a warning when{{#if Missing}}uses a variable missing from the data as a bare operand.IsValidis not affected.
⚠️ Behavior changes (bug fixes)
The public C# API remains source- and binary-compatible with 1.8.0 (verified by package validation). These fixes can change results for existing Word templates.
ValidateTemplate for Word templates:
- Inline expressions
{{(…)}}are validated properly (#233).- An expression was reported as one missing variable (
Variable '(A and B)' …) even when all operands were present, so correct templates showedIsValid = false. Now each operand is checked with the same rules processing uses. AllPlaceholderslists the expression's variables instead of the expression text.- Expressions that cannot be parsed are reported as
InvalidConditionalExpression.
- An expression was reported as one missing variable (
- Collections of nested loops appear in
AllPlaceholderseven when validating without data (#226). - An unmatched
{{#if}}marker in a table row is now reported as invalid (#227). Processing already failed on it.
- An output stream with existing content is now truncated before writing.
- Before, a stream opened without truncation over a longer file could leave trailing bytes (ODT) or fail after partly overwriting it (Word).
- If the stream cannot be truncated, processing returns a
Failureand nothing is written. - Prefer
File.Createfor output files.
Removed dead marker handling: the unsupported {{#empty}} / {{/empty}} text is no longer treated specially, so a paragraph containing it gets normal placeholder replacement.
Features
- format-detecting TemplateProcessor facade for .docx and .odt/.ott (#138) (#215) (1157864)
- gui: support OpenDocument templates (#138) (#219) (5dcb0bf)
- odt: conditionals for OpenDocument Text templates (#138) (#211) (eaf4673)
- odt: loops, table-row and list-item loops for OpenDocument Text templates (#138) (#212) (08d2588)
- odt: markdown via automatic styles, ValidateTemplate and document properties for ODT (#138) (#214) (1b62908)
- odt: nested containers and unique object names after cloning (#138) (#213) (caa48c7)
- odt: OdtTemplateProcessor with placeholder replacement for .odt/.ott (#138) (#210) (dda2bd0)
- validation: add ValidationErrorType.InvalidDocument for unreadable or unsupported templates (#225) (271b038)
- validation: warn about missing variables used as bare condition operands (#231) (9cd92bb)
Bug Fixes
- never leave trailing bytes when the output stream cannot be truncated (#232) (dcd7c6e)
- odt: continue list numbering across loop copies, process header/footer regions, drop dead {{#empty}} markers (#138) (#223) (92a9b19)
- odt: markdown styles no longer shadow common styles of styles.xml (#229) (f38af46)
- odt: reject duplicate and unsafe entry names, compare media types case-insensitively, drop the stale thumbnail (#138) (#222) (857bfb5)
- odt: report an unmatched row or list-item marker once in ValidateTemplate (#228) (8932a55)
- odt: ValidateTemplate no longer reports the markers of table-row and list-item blocks as unmatched (#138) (#216) (53c13dc)
- validation: list collections of nested loops in AllPlaceholders without data (#226) (524ab09)
- validation: report unmatched table row conditionals in Word templates (#227) (9838714)
- validation: validate inline expressions via the condition AST instead of reporting them as one missing variable (#233) (d3aca9e)