feat: migrate template engine from Stencil to swift-jinja - #60
Conversation
Summary of ChangesHello @alexey1312, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request undertakes a significant refactoring of the project's templating infrastructure by replacing the Stencil engine with swift-jinja. This migration streamlines template rendering, reduces external dependencies, and modernizes the codebase. The changes involve updating template file extensions, adapting template syntax, and modifying core exporter logic to integrate with the new Jinja-based system, ultimately improving maintainability and performance. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
The pull request successfully migrates the template engine from Stencil to swift-jinja, resulting in a significant reduction of dependencies. The migration includes renaming templates, updating syntax, and rewriting the base exporter logic. My feedback focuses on improving maintainability by reducing code duplication across the four export modules and optimizing performance in loops where templates are repeatedly parsed and rendered. I also noted some minor inconsistencies in error handling and context filtering.
Add renderTemplate(source:context:) overload that accepts a pre-loaded template string. Use it in WebIconsExporter and WebImagesExporter loops to load the template once instead of on every iteration. Addresses review feedback from PR #60. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
a4b1f1a to
ae83930
Compare
Replace Stencil + StencilSwiftKit + PathKit with swift-jinja (HuggingFace)
for template rendering across all 4 export modules.
Changes:
- Package.swift: swap Stencil/StencilSwiftKit deps for swift-jinja
- 34 templates: .stencil → .jinja with syntax adaptations
- {% include "header.stencil" %} → {{ header }} context variable
- {% include "Bundle+extension..." %} → {{ bundleExtension }} pre-rendered
- forloop.last → loop.last (Jinja standard)
- Image/UIImage .include partials inlined into parent templates
- 4 base exporters: Stencil Environment → renderTemplate() + loadTemplate()
with recursive Any→Value conversion
- 15 exporter files: updated all ~27 call sites
- contextWithHeader() / contextWithHeaderAndBundle() helpers for DRY injection
Net effect: -6 packages from dependency graph (Stencil, StencilSwiftKit,
PathKit*, Komondor, PackageConfig, ShellOut, Spectre → +1 swift-jinja)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add renderTemplate(source:context:) overload that accepts a pre-loaded template string. Use it in WebIconsExporter and WebImagesExporter loops to load the template once instead of on every iteration. Addresses review feedback from PR #60. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ae83930 to
19f8d7c
Compare
Eliminates ~130 lines of duplicated template loading, rendering, and error handling code across AndroidExport, FlutterExport, WebExport, and XcodeExport by centralizing into a shared JinjaTemplateRenderer. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- testExportJSON now parses JSON to validate loop.last comma placement - testExportJSONLightOnly verifies JSON without dark section - testExportImageComponentContent verifies Jinja brace escaping in JSX - testExportIconComponentContent verifies icon component structure Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace `try?` with proper error discrimination: catch only file-not-found, propagate permission/encoding/IO errors immediately - Fix regression: custom templatesPath now uses `try` (not `try?`) to propagate errors instead of silently falling back to bundle - Guard against nil Bundle.module.resourcePath with descriptive error - Include searched paths in TemplateLoadError for easier debugging - Remove unnecessary context filtering in contextWithHeaderAndBundle Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Jinja renders arrays with single quotes (['a', 'b']) which is invalid Swift. Use explicit for loop to produce double-quoted Swift string literals: ["a", "b"]. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…m path When templatesPath is set in PKL config, .jinja.include files (like Bundle+extension.swift.jinja.include) were resolved only from the custom directory. Now loadTemplate falls back to bundle resources when a file is not found in the custom path, matching user expectations. Also updates hk.pkl to exclude .jinja files from trailing-whitespace and newline checks (replaces stale .stencil excludes). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…S/Android entries Add Web platform templates section to CustomTemplates.md with context variables and example. Document missing iOS templates (LabelStyle, CodeConnect) and Android CodeConnect template. Add note about .jinja.include partial templates. Update ExFig.md and Development.md to mention Web platform. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Surface real errors (permissions, I/O) from custom template path instead of silently falling back to bundle. Add templateName parameter through the renderer chain for better error diagnostics. Update CLAUDE.md docs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
.stencil→.jinjawith Jinja syntax adaptations ({% include %}→ context variables,forloop.last→loop.last)EnvironmenttorenderTemplate()+loadTemplate()with recursiveAny → ValueconversioncontextWithHeader()/contextWithHeaderAndBundle()helpersDependency impact
Net: −6 packages from the dependency graph
*PathKit remains as transitive dep of XcodeProj
Breaking changes for custom templates
Users with custom
templatesPathtemplates need to:.stencil→.jinja{% include "header.stencil" %}→{{ header }}forloop.last→loop.last(if used)Test plan
🤖 Generated with Claude Code