TemplateLoader.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. using AspNetCoreSsrTemplateEngine.Renders;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text.RegularExpressions;
  7. namespace AspNetCoreSsrTemplateEngine.Template
  8. {
  9. public static class TemplateLoader
  10. {
  11. private const string FileExtension = ".html";
  12. private static readonly Regex ParseRegex = new Regex(@"<!--(.*?)-->", RegexOptions.Singleline | RegexOptions.Compiled);
  13. private const string InstructPrefix = "STE:";
  14. public static ITemplate Load(object instance, IComponentResolver componentResolver)
  15. {
  16. if (instance == null) throw new ArgumentNullException(nameof(instance));
  17. var fullTypeName = instance.GetType().FullName;
  18. #if !EMBED_HTML
  19. return new HotLoadTemplate(fullTypeName, componentResolver);
  20. #else
  21. return new SimpleTemplate(LoadByFullTypeName(fullTypeName, componentResolver));
  22. #endif
  23. }
  24. internal static IRender[] LoadByFullTypeName(string fullTypeName, IComponentResolver componentResolver)
  25. {
  26. var template = LoadTemplateResource(fullTypeName);
  27. var seq = ParseInternal(template, componentResolver);
  28. return seq;
  29. }
  30. private static string LoadTemplateResource(string typeFullName)
  31. {
  32. #if EMBED_HTML
  33. var asm = instance.GetType().Assembly;
  34. var manifestResourceStream = asm.GetManifestResourceStream(typeFullName);
  35. if (null == manifestResourceStream) throw new System.Resources.MissingManifestResourceException($"resource `{typeFullName}' not found");
  36. var template = Utils.StreamExtensionMethod.ReadUtf8(manifestResourceStream);
  37. #else
  38. var path = GetTemplateFilePath(typeFullName);
  39. var template = File.ReadAllText(path);
  40. #endif
  41. return template;
  42. }
  43. #if !EMBED_HTML
  44. internal static string GetTemplateFilePath(string typeFullName)
  45. {
  46. var projectDir = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../../"));
  47. var path = Path.Combine(projectDir, typeFullName.Replace(".", "/") + FileExtension);
  48. return Path.GetFullPath(path);
  49. }
  50. #endif
  51. internal static IRender[] ParseInternal(string template, IComponentResolver componentResolver)
  52. {
  53. var comments = ParseRegex.Matches(template).OrderBy(p => p.Index);
  54. var renders = new List<IRender>();
  55. var index = 0;
  56. foreach (var match in comments)
  57. {
  58. var fixedLen = match.Index - index;
  59. if (0 != fixedLen)
  60. {
  61. var fixedContent = template.Substring(index, fixedLen);
  62. renders.Add(new FixedContentRender(fixedContent));
  63. }
  64. var commentContent = match.Groups[1].Value.Trim();
  65. if (commentContent.StartsWith(InstructPrefix))
  66. {
  67. var args = commentContent.Split(":");
  68. if (args.Length > 2)
  69. {
  70. var instruct = args[1];
  71. switch (instruct)
  72. {
  73. case "OUT":
  74. if (args.Length < 2) throw new FormatException("SET:OUT net a key");
  75. renders.Add(new OutputRender(args[2]));
  76. break;
  77. case "SLOT":
  78. if (args.Length < 2) throw new FormatException("SET:SLOT net a key");
  79. renders.Add(new TemplateRender(args[2]));
  80. break;
  81. case "COM":
  82. if (args.Length < 2) throw new FormatException("SET:COM net a key");
  83. var component = componentResolver.Resolve<IRender>(args[2]);
  84. renders.Add(component ?? new FixedContentRender($"[Unknown component `{args[2]}']"));
  85. break;
  86. default:
  87. renders.Add(new FixedContentRender($"[Unknown template instruct `{commentContent}']"));
  88. break;
  89. }
  90. }
  91. }
  92. #if DEBUG
  93. else
  94. {
  95. renders.Add(new NullRender(commentContent));
  96. }
  97. #endif
  98. index = match.Index + match.Length;
  99. }
  100. if (index < template.Length)
  101. {
  102. var len = template.Length - index;
  103. var content = template.Substring(index, len);
  104. renders.Add(new FixedContentRender(content));
  105. }
  106. return renders.ToArray();
  107. }
  108. }
  109. }