diff --git a/Htmt/Parser.cs b/Htmt/Parser.cs index 798685c..fb4fd16 100644 --- a/Htmt/Parser.cs +++ b/Htmt/Parser.cs @@ -72,6 +72,7 @@ private void Parse() _docType = GetDoctype(Template); RemoveDoctype(); + FillBooleanAttributes(); CloseVoidElements(); TransformHtmlEntities(); @@ -190,6 +191,53 @@ private void CloseVoidElements() Template = Template.Replace(element, newElement); } } + + [GeneratedRegex(@"(<[^>]*?)(?\s[\w-]+)(?=\s|>|/>)", RegexOptions.IgnoreCase)] + private static partial Regex BooleanAttributeRegex(); + + /// + /// Fills boolean HTML attributes such as "checked" or "defer". + /// + private void FillBooleanAttributes() + { + var voidAttributes = new Dictionary + { + { "allowfullscreen", "" }, + { "async", "" }, + { "autofocus", "" }, + { "autoplay", "" }, + { "checked", "" }, + { "controls", "" }, + { "default", "" }, + { "defer", "" }, + { "disabled", "" }, + { "formnovalidate", "" }, + { "hidden", "" }, + { "ismap", "" }, + { "itemscope", "" }, + { "loop", "" }, + { "multiple", "" }, + { "muted", "" }, + { "nomodule", "" }, + { "novalidate", "" }, + { "open", "" }, + { "playsinline", "" }, + { "readonly", "" }, + { "required", "" }, + { "reversed", "" }, + { "selected", "" } + }; + + foreach (Match match in BooleanAttributeRegex().Matches(Template)) + { + var attribute = match.Groups["attr"].Value.Trim(); + + if (!voidAttributes.TryGetValue(attribute, out var val)) continue; + + // Replace the attribute with the filled one + Template = Template.Replace(attribute, $"{attribute}=\"{val}\""); + } + } /// /// The regex for HTML entities. diff --git a/HtmtTests/ParserTest.cs b/HtmtTests/ParserTest.cs index 45e84e2..46002e9 100644 --- a/HtmtTests/ParserTest.cs +++ b/HtmtTests/ParserTest.cs @@ -115,4 +115,22 @@ public void TestRemoveXmlnsFromChildren() Assert.AreEqual("
One
Two
Three
", parser.ToHtml()); } + + [TestMethod] + public void TestFillVoidAttributes() + { + const string template = ""; + var parser = new Htmt.Parser { Template = template }; + + Assert.AreEqual("", parser.ToHtml()); + } + + [TestMethod] + public void TestFillVoidAttributes2() + { + const string template = ""; + var parser = new Htmt.Parser { Template = template }; + + Assert.AreEqual("", parser.ToHtml()); + } } \ No newline at end of file