From dfb3850f361e96f7eec359f84c18fcd6cd46d181 Mon Sep 17 00:00:00 2001 From: Harald Wolff-Thobaben Date: Sun, 23 Jul 2023 16:33:29 +0200 Subject: [PATCH] Fixed Template lookup and caching in RecursiveResolver.cs --- ln.templates/README.md | 55 +++++++++++++++++++++++++++++++ ln.templates/RecursiveResolver.cs | 40 +++++++++++++--------- 2 files changed, 80 insertions(+), 15 deletions(-) diff --git a/ln.templates/README.md b/ln.templates/README.md index e113d66..a2a7753 100644 --- a/ln.templates/README.md +++ b/ln.templates/README.md @@ -67,3 +67,58 @@ Include content by expressions within text elements:
This is my favourite color: {{ myFavouriteColor }}. +### Filesystem overlay + +Overlaying is possible by using RecursiveResolver class as ITemplateResolver. + +Example directory layout: + + /layout/frame.html + /layout/htmlhead.html + /tmpl_a.html + +The files use the following references: + + tmpl_a.html -> /layout/frame.html -> /layout/htmlhead.html + +htmlhead.html may contain something like + + + ... + + ... + + +We can now add a file to new folder: + + /layout/frame.html + /layout/htmlhead.html + /tmpl_a.html + /layouts/b/layout/htmlhead.html + +By a call to RecursiveResolver.FindResolver("/layouts/b") we get a ITemplateResolver +that looks up Folders and Templates in that directory first, then in the +parent folders back to the root folder of this structure. + +So if we call GetTemplateByPath("tmpl_a.html") we get the same Template +but this instance will use the reference chain + + tmpl_a.html -> /layout/frame.html -> /layouts/b/htmlhead.html + +which effectivly overlays *htmlhead.html* with an alternative version and still uses the +*/layout/frame.html* template. + + + + + + + + + + + + + + + diff --git a/ln.templates/RecursiveResolver.cs b/ln.templates/RecursiveResolver.cs index 5565ccf..56378d4 100644 --- a/ln.templates/RecursiveResolver.cs +++ b/ln.templates/RecursiveResolver.cs @@ -60,19 +60,29 @@ public class RecursiveResolver : ITemplateResolver public Template GetTemplateByPath(string templatePath) { - RecursiveResolver resolver; - Span pathElements = templatePath.Split(System.IO.Path.DirectorySeparatorChar); - if (string.Empty.Equals(pathElements[0])) - resolver = Root; - else - resolver = FindResolver(pathElements.Slice(0, pathElements.Length - 1)); - - Template template = resolver?.GetTemplate(pathElements[^1]); - if (template is null) - return null; - - template.Resolver = this; - return template; + RecursiveResolver resolver = templatePath.StartsWith(System.IO.Path.DirectorySeparatorChar) ? Root : this; + + do + { + string templateFileName = System.IO.Path.Join(resolver.Path, templatePath); + if (File.Exists(templateFileName)) + { + if (!_templates.TryGetValue(templateFileName, out Template template)) + { + template = new Template(templateFileName, this); + _templates.Add(templateFileName, template); + } + + return template; + } + + if (resolver.Parent is null) + break; + + resolver = resolver.Parent; + } while (true); + + return null; } public Template GetTemplate(string name) @@ -80,10 +90,10 @@ public class RecursiveResolver : ITemplateResolver string filename = System.IO.Path.Combine(Path, name); if (File.Exists(filename)) { - if (!_templates.TryGetValue(name, out Template template)) + if (!_templates.TryGetValue(filename, out Template template)) { template = new Template(filename, this); - _templates.Add(name, template); + _templates.Add(filename, template); } return template;