123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- using AspNetCoreSsrTemplateEngine.Renders;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text.RegularExpressions;
- namespace AspNetCoreSsrTemplateEngine.Template
- {
- public static class TemplateLoader
- {
- private const string FileExtension = ".html";
- private static readonly Regex ParseRegex = new Regex(@"<!--(.*?)-->", RegexOptions.Singleline | RegexOptions.Compiled);
- private const string InstructPrefix = "STE:";
- public static ITemplate Load(object instance, IComponentResolver componentResolver)
- {
- if (instance == null) throw new ArgumentNullException(nameof(instance));
- var fullTypeName = instance.GetType().FullName;
- #if !EMBED_HTML
- return new HotLoadTemplate(fullTypeName, componentResolver);
- #else
- return new SimpleTemplate(LoadByFullTypeName(fullTypeName, componentResolver));
- #endif
- }
- internal static IRender[] LoadByFullTypeName(string fullTypeName, IComponentResolver componentResolver)
- {
- var template = LoadTemplateResource(fullTypeName);
- var seq = ParseInternal(template, componentResolver);
- return seq;
- }
- private static string LoadTemplateResource(string typeFullName)
- {
- #if EMBED_HTML
- var asm = instance.GetType().Assembly;
- var manifestResourceStream = asm.GetManifestResourceStream(typeFullName);
- if (null == manifestResourceStream) throw new System.Resources.MissingManifestResourceException($"resource `{typeFullName}' not found");
- var template = Utils.StreamExtensionMethod.ReadUtf8(manifestResourceStream);
- #else
- var path = GetTemplateFilePath(typeFullName);
- var template = File.ReadAllText(path);
- #endif
- return template;
- }
- #if !EMBED_HTML
- internal static string GetTemplateFilePath(string typeFullName)
- {
- var projectDir = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../../"));
- var path = Path.Combine(projectDir, typeFullName.Replace(".", "/") + FileExtension);
- return Path.GetFullPath(path);
- }
- #endif
- internal static IRender[] ParseInternal(string template, IComponentResolver componentResolver)
- {
- var comments = ParseRegex.Matches(template).OrderBy(p => p.Index);
- var renders = new List<IRender>();
- var index = 0;
- foreach (var match in comments)
- {
- var fixedLen = match.Index - index;
- if (0 != fixedLen)
- {
- var fixedContent = template.Substring(index, fixedLen);
- renders.Add(new FixedContentRender(fixedContent));
- }
- var commentContent = match.Groups[1].Value.Trim();
- if (commentContent.StartsWith(InstructPrefix))
- {
- var args = commentContent.Split(":");
- if (args.Length > 2)
- {
- var instruct = args[1];
- switch (instruct)
- {
- case "OUT":
- if (args.Length < 2) throw new FormatException("SET:OUT net a key");
- renders.Add(new OutputRender(args[2]));
- break;
- case "SLOT":
- if (args.Length < 2) throw new FormatException("SET:SLOT net a key");
- renders.Add(new TemplateRender(args[2]));
- break;
- case "COM":
- if (args.Length < 2) throw new FormatException("SET:COM net a key");
- var component = componentResolver.Resolve<IRender>(args[2]);
- renders.Add(component ?? new FixedContentRender($"[Unknown component `{args[2]}']"));
- break;
- default:
- renders.Add(new FixedContentRender($"[Unknown template instruct `{commentContent}']"));
- break;
- }
- }
- }
- #if DEBUG
- else
- {
- renders.Add(new NullRender(commentContent));
- }
- #endif
- index = match.Index + match.Length;
- }
- if (index < template.Length)
- {
- var len = template.Length - index;
- var content = template.Substring(index, len);
- renders.Add(new FixedContentRender(content));
- }
- return renders.ToArray();
- }
- }
- }
|