feat: YAML validation, NRE fix, Cookbook, llms updates#7
Merged
Conversation
- Add YAML property validation with Levenshtein "Did you mean?" suggestions - Fix NRE in render pipeline (null-suppression on _imageLoader) - Fix SkiaRenderer passing _defaultRenderOptions to RenderToBitmapCore - Add Cookbook wiki page with 9 practical recipes - Update llms.txt and llms-full.txt with async API, validation, and cookbook info
- Add Quick Start section with common CLI rendering commands - Add CLI examples to every existing recipe - Add Images section with 4 recipes: local file, HTTP, base64, fit modes - Document base64 vs data: URI MIME type requirements
- ContentSourceResolver now delegates all URI resolution to loaders - Base64ResourceLoader handles data:, data://, base64:, base64:// schemes - FileResourceLoader uses generic URI scheme detection instead of blacklist - FileResourceLoader supports file:, file://, file:/// prefixes - base64: is a shorthand alias for data:application/octet-stream;base64,... - Cookbook: add CLI commands and image source recipes
Prevent path traversal attacks by blocking absolute paths and verifying resolved paths stay within the configured BasePath directory.
Reflect new URI scheme support, absolute path security, and ContentSourceResolver delegation to IResourceLoader chain.
…ncy) - Reject URL-encoded characters in FileResourceLoader to prevent path traversal - Replace bare catch with catch (Exception) in TemplateExpander - Fix step numbering in ContentSourceResolver - Make Base64ResourceLoader case-insensitive for base64: prefix matching
…n path - Add CloneWithSubstitution to each TemplateElement subclass so elements own their cloning logic — prevents missed properties when adding new ones - Add WithSrc for ImageElement/SvgElement, CloneWithChildren for FlexElement - Delete ContentSourceResolver — inline logic into ExpandContentAsync - Convert ExpandTable to async, remove all sync expansion duplicates (ExpandElements, ExpandElement, ExpandEach, ExpandIf, ExpandFlex) - Extract WalkElements helper for shared tree traversal in RenderingEngine - Extract LoadImageCache to deduplicate image preload logic - Use stackalloc in LevenshteinDistance to avoid heap allocations - Document case-sensitivity in KnownProperties with improved suggestions - Preserve Bytes through ExprValue.Resolve/Materialize pipeline - Re-throw OperationCanceledException in TryLoadBytesFromLoadersAsync - Fix: FontFamily was not copied in TextElement clone - Fix: Options was not copied in ContentElement clone
RoboNET
added a commit
that referenced
this pull request
Mar 11, 2026
* feat: YAML validation, NRE fix, Cookbook, and llms updates - Add YAML property validation with Levenshtein "Did you mean?" suggestions - Fix NRE in render pipeline (null-suppression on _imageLoader) - Fix SkiaRenderer passing _defaultRenderOptions to RenderToBitmapCore - Add Cookbook wiki page with 9 practical recipes - Update llms.txt and llms-full.txt with async API, validation, and cookbook info * docs(cookbook): add CLI commands and image source recipes - Add Quick Start section with common CLI rendering commands - Add CLI examples to every existing recipe - Add Images section with 4 recipes: local file, HTTP, base64, fit modes - Document base64 vs data: URI MIME type requirements * refactor: unify resource loading through IResourceLoader chain - ContentSourceResolver now delegates all URI resolution to loaders - Base64ResourceLoader handles data:, data://, base64:, base64:// schemes - FileResourceLoader uses generic URI scheme detection instead of blacklist - FileResourceLoader supports file:, file://, file:/// prefixes - base64: is a shorthand alias for data:application/octet-stream;base64,... - Cookbook: add CLI commands and image source recipes * fix(security): reject absolute paths in FileResourceLoader Prevent path traversal attacks by blocking absolute paths and verifying resolved paths stay within the configured BasePath directory. * docs: update resource loader documentation Reflect new URI scheme support, absolute path security, and ContentSourceResolver delegation to IResourceLoader chain. * docs: add ExprValue BytesValue unification design and implementation plan * feat: add BytesValue property to ExprValue * feat: resolve BytesValue into ExprValue.Bytes in TemplateExpander * refactor: ContentSourceResolver uses ExprValue.Bytes instead of TryResolveBytes * feat: load URI sources into ExprValue.Bytes during template expansion * feat: PreloadImages uses ExprValue.Bytes, skips loader chain when bytes available * test: add BytesValue image integration tests * fix: prevent flaky cache tests by disabling parallel execution * fix: address code review findings (security, error handling, consistency) - Reject URL-encoded characters in FileResourceLoader to prevent path traversal - Replace bare catch with catch (Exception) in TemplateExpander - Fix step numbering in ContentSourceResolver - Make Base64ResourceLoader case-insensitive for base64: prefix matching * docs: add KnownProperties and test parallelism rules to checklists * refactor: move element cloning into elements, eliminate sync expansion path - Add CloneWithSubstitution to each TemplateElement subclass so elements own their cloning logic — prevents missed properties when adding new ones - Add WithSrc for ImageElement/SvgElement, CloneWithChildren for FlexElement - Delete ContentSourceResolver — inline logic into ExpandContentAsync - Convert ExpandTable to async, remove all sync expansion duplicates (ExpandElements, ExpandElement, ExpandEach, ExpandIf, ExpandFlex) - Extract WalkElements helper for shared tree traversal in RenderingEngine - Extract LoadImageCache to deduplicate image preload logic - Use stackalloc in LevenshteinDistance to avoid heap allocations - Document case-sensitivity in KnownProperties with improved suggestions - Preserve Bytes through ExprValue.Resolve/Materialize pipeline - Re-throw OperationCanceledException in TryLoadBytesFromLoadersAsync - Fix: FontFamily was not copied in TextElement clone - Fix: Options was not copied in ContentElement clone * chore: remove completed plans, known-issues, and TODO
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
TemplateParseExceptionwith Levenshtein-based "Did you mean?" suggestions (e.g.,colour→color)_imageLoaderinRenderingEngine, pass_defaultRenderOptionstoRenderToBitmapCorein async render overloadsdocs/wiki/Cookbook.md(receipts, labels, tickets, NDC content, QR codes, conditional/multi-language)llms.txtandllms-full.txtupdated with async-only API, YAML validation, and Cookbook referencesTest plan