Skip to content

feat: format-detecting TemplateProcessor facade for .docx and .odt/.ott (#138) - #215

Merged
vaceslav merged 1 commit into
mainfrom
feat/138-template-processor-facade
Sep 26, 2026
Merged

vaceslav merged 1 commit into
mainfrom
feat/138-template-processor-facade

Conversation

@vaceslav

Copy link
Copy Markdown
Contributor

Summary

Adds the universal facade decided in #138: TemplateProcessor detects the template format from the package content and delegates to DocumentTemplateProcessor (Word) or OdtTemplateProcessor (OpenDocument Text). DocumentTemplateProcessor and OdtTemplateProcessor are unchanged.

Changes

  • Core/TemplateProcessor.cs (public, sealed): the same method shapes as the two processors — ProcessTemplate Stream/Stream with Dictionary, IReadOnlyDictionary and JSON, byte[] with out byte[] ×3, ProcessTemplateFile ×3, ValidateTemplate ×3 — plus static TemplateFormat DetectFormat(Stream).
  • Core/TemplateFormat.cs (public enum): Unknown = 0, Docx = 1, Odt = 2.
  • Core/TemplateFormatDetector.cs (internal): reads the ZIP central directory and small entries only.
    • ODF: the mimetype entry, with a fallback to the manifest root media type (as OdtPackage does). …opendocument.text and …text-template → Odt. Other ODF types (spreadsheet, presentation, text-master) → Unknown, and the error message names the media type.
    • OOXML: [Content_Types].xml declares a WordprocessingML main part (document, template, macro-enabled document or template) → Docx. Spreadsheets and other packages → Unknown.
    • Not a ZIP (empty, random bytes, legacy .doc, flat .fodt) → Unknown.
  • Behavior decisions:
    • Results, warnings, exceptions and output-stream requirements are those of the processor the facade delegates to. Word needs a readable, writable and seekable output stream. ODT needs only a writable one.
    • A non-seekable template stream is copied into memory first, because the format must be known before processing. The existing processors also accept readable, non-seekable template streams, so this keeps the contract.
    • DetectFormat requires a readable, seekable stream (otherwise ArgumentException). It inspects the whole package and restores the stream position.
    • An unreadable template stream or an unsupported format → ProcessingResult.Failure("Unsupported template format: …"), and nothing is written. ValidateTemplate returns an invalid result with one error in that case.
    • JSON is parsed before detection, so invalid JSON throws JsonException as in the other processors.
    • Files are detected by content, not by extension. The file overloads delegate to the processors' own file overloads, so the write-only-on-success behavior and the IO exceptions stay the same.

Tests

TriasDev.Templify.Tests/Core/TemplateProcessorTests.cs covers:

  • Detection: docx, docm/dotx/dotm, odt, ott, ODT without a mimetype entry, other ODF types, fodt, an xlsx-like package, random bytes, an empty stream, a zip without markers, malformed content types, position restore (also for unknown input), non-seekable input and null.
  • Delegation equivalence with the direct processors: result, warnings, missing variables, byte-identical ODT output, the same DOCX text, the .ott → .odt media type, the Stream, byte[], File, IReadOnlyDictionary and JSON overloads, buffering of non-seekable templates, the delegate's syntax failures, ThrowException, and options applied to both formats.
  • Unsupported format and unreadable stream for process, file (no output file is created) and validate.

Local checks: dotnet build templify.sln -c Release -p:ContinuousIntegrationBuild=true passed. All test projects pass on every TFM (2076 core tests per TFM, including the LibreOffice round trips; Tools 42; Converter 95). dotnet format --verify-no-changes and dotnet pack (package validation against 1.8.0) passed.

Public API impact

Additive (declared in PublicAPI.Unshipped.txt):

  • TriasDev.Templify.Core.TemplateFormat (Unknown, Docx, Odt)
  • TriasDev.Templify.Core.TemplateProcessor: constructor, 6× ProcessTemplate, 3× ProcessTemplateFile, 3× ValidateTemplate, and static DetectFormat(Stream)

Refs #138

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 91.66667% with 17 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
TriasDev.Templify/Core/TemplateFormatDetector.cs 86.76% 2 Missing and 7 partials ⚠️
TriasDev.Templify/Core/TemplateProcessor.cs 94.11% 2 Missing and 6 partials ⚠️

📢 Thoughts on this report? Let us know!

@vaceslav
vaceslav merged commit 1157864 into main Sep 26, 2026
12 checks passed
@vaceslav
vaceslav deleted the feat/138-template-processor-facade branch September 26, 2026 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants