/// <summary> /// Read @directive from header file /// </summary> private KeyValuePair <string, string> ReadDirective(StringScanner s) { var key = s.Scan(@"\s*@(\w+)", 1); if (key.Length == 0) { return(new KeyValuePair <string, string>(null, null)); } var value = s.Scan(@"[\s\S]*?\n").Trim(); return(new KeyValuePair <string, string>(key, value)); }
/// <summary> /// Read @directive from header file /// </summary> private IEnumerable <KeyValuePair <string, string> > ReadDirectives(StringScanner s) { while (!s.HasTerminated) { var key = s.Scan(@"\s*@(\w+)", 1); if (key.Length == 0) { yield break; } var value = s.Scan(@"[\s\S]*?\n").Trim(); yield return(new KeyValuePair <string, string>(key, string.IsNullOrWhiteSpace(value) ? null : value)); } }
/// <summary> /// Read root tags from file /// </summary> private HtmlTag ReadTag(StringScanner s) { // discard non tag text before if (!s.Match(@"[\s\S]*?<[\w-]+")) { return(null); } var tag = new HtmlTag(s.Scan(@"[\s\S]*?<([\w-]+)", 1).ToLower()); // read attributes while (!s.HasTerminated) { var key = s.Scan(@"\s*([\w:@\-\.]+)\s*=?\s*", 1); var quote = s.Scan(@"[""']"); var value = quote.Length == 0 ? s.Scan(@"\w+") : s.Scan(@"([\s\S]*?)" + quote, 1); if (key.Length > 0) { tag.Attributes[key] = value; } if (s.Scan(@"\/>").Length > 0) { return(tag); // self closed tag } if (s.Read(1) == ">") { break; } } if (tag.TagName.Equals("link", StringComparison.OrdinalIgnoreCase)) { return(tag); } var expr = (tag.TagName.Equals("template", StringComparison.OrdinalIgnoreCase)) ? @"([\s\S]*)</" + tag.TagName + ">" : @"([\s\S]*?)</" + tag.TagName + ">"; tag.InnerHtml.Append(s.Scan(expr, 1)); return(tag); }
public HtmlFile(string content, StringBuilder globalScripts) { var s = new StringScanner(content, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); this.Directives = this.ReadDirectives(s).ToDictionary(x => x.Key, x => x.Value, StringComparer.OrdinalIgnoreCase); var scoped = false; var scopedId = "s-" + Guid.NewGuid().ToString("d").Substring(0, 6); while (!s.HasTerminated) { if (s.Match(@"<style\s+scoped>([\s\S]*?)</style>")) { if (scoped) { this.Template.Append("<h1>Only 1 style scoped supported<h1>"); } else { scoped = true; var style = s.Scan(@"<style\s+scoped>([\s\S]*?)</style>", 1); this.Styles.Append($"[{scopedId}] {{ {style} }}"); } } else if (s.Match(@"<style>([\s\S]*?)</style>")) { this.Styles.Append(s.Scan(@"<style>([\s\S]*?)</style>", 1)); } else if (s.Match(@"<script>([\s\S]*?)</script>")) { this.Scripts.Append(s.Scan(@"<script>([\s\S]*?)</script>", 1)); } else if (s.Match(@"<script\s+mixin>([\s\S]*?)</script>")) { this.Mixins.Add(s.Scan(@"<script\s+mixin>([\s\S]*?)</script>", 1)); } else if (s.Match(@"<script\s+global>([\s\S]*?)</script>")) { globalScripts.Append(s.Scan(@"<script\s+global>([\s\S]*?)</script>", 1)); } else if (s.Match(@"<template>([\s\S]*?)</template>")) { this.Template.Append(s.Scan(@"<template>([\s\S]*?)</template>", 1)); } else { this.Template.Append(s.Read(1)); } } // change template if scoped was used if (scoped) { var htm = Regex.Replace(this.Template.ToString(), @"^\s*(<[\w-]+)", $"$1 {scopedId}"); this.Template.Clear(); this.Template.Append(htm); } }