From eceac8031aecb2044417756c1c4f91b76c7013c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asko=20N=C3=B5mm?= <asko@nth.ee> Date: Thu, 7 Nov 2024 17:15:32 +0200 Subject: [PATCH] Auto fill boolean html attributes --- Htmt/Parser.cs | 48 +++++++++++++++++++++++++++++++++++++++++ HtmtTests/ParserTest.cs | 18 ++++++++++++++++ 2 files changed, 66 insertions(+) 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(@"(<[^>]*?)(?<attr>\s[\w-]+)(?=\s|>|/>)", RegexOptions.IgnoreCase)] + private static partial Regex BooleanAttributeRegex(); + + /// <summary> + /// Fills boolean HTML attributes such as "checked" or "defer". + /// </summary> + private void FillBooleanAttributes() + { + var voidAttributes = new Dictionary<string, string> + { + { "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}\""); + } + } /// <summary> /// 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("<html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body><div><span>One</span></div><div><span>Two</span></div><div><span>Three</span></div></body></html>", parser.ToHtml()); } + + [TestMethod] + public void TestFillVoidAttributes() + { + const string template = "<html><head></head><body><input type=\"checkbox\" checked /></body></html>"; + var parser = new Htmt.Parser { Template = template }; + + Assert.AreEqual("<html><head></head><body><input type=\"checkbox\" checked=\"\" /></body></html>", parser.ToHtml()); + } + + [TestMethod] + public void TestFillVoidAttributes2() + { + const string template = "<html><head><script defer src=\"\"></script></head><body></body></html>"; + var parser = new Htmt.Parser { Template = template }; + + Assert.AreEqual("<html><head><script defer=\"\" src=\"\"></script></head><body></body></html>", parser.ToHtml()); + } } \ No newline at end of file