using System; using System.Collections.Generic; using System.IO; using Esprima.Ast; using ln.templates.html; namespace ln.templates; public class RecursiveResolver : ITemplateResolver { public RecursiveResolver(string path) :this(null, path) { } private RecursiveResolver(RecursiveResolver parent, string path) { Parent = parent; Path = System.IO.Path.Combine(Parent?.Path ?? "", path); if (!Directory.Exists(Path)) throw new DirectoryNotFoundException(Path); } public RecursiveResolver Root => Parent?.Root ?? this; public RecursiveResolver Parent { get; private set; } public string Path { get; private set; } private bool IsAlive => Directory.Exists(Path); private Dictionary _children = new Dictionary(); private Dictionary _templates = new Dictionary(); public RecursiveResolver FindResolver(string path) => FindResolver( path.Split(System.IO.Path.DirectorySeparatorChar) ?? Array.Empty()); private RecursiveResolver FindResolver(Span pathElements) { if (pathElements.Length == 0) return this; if (!_children.TryGetValue(pathElements[0], out RecursiveResolver child)) { if (Directory.Exists(System.IO.Path.Combine(Path, pathElements[0]))) { child = new RecursiveResolver(this, pathElements[0]); _children.Add(pathElements[0], child); } } if (child?.IsAlive ?? false) return child.FindResolver(pathElements.Slice(1)); if (child is not null) _children.Remove(pathElements[0]); return null; } public Template GetTemplateByPath(string templatePath) { 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) { string filename = System.IO.Path.Combine(Path, name); if (File.Exists(filename)) { if (!_templates.TryGetValue(filename, out Template template)) { template = new Template(filename, this); _templates.Add(filename, template); } return template; } if (Parent is not null) return Parent.GetTemplate(name); return null; } public override string ToString() { return String.Format("[RecursiveResolver {0}]", Path); } }