ITag generates inline components, while FTag generates formatted components.

using Mackerel;

using static Mackerel.Macro;

using Attrs = IDictionary<string, object>;

public static class HTML
{
   private const int INDENTATION = 2;

   public static Instruction ITag(string tag, Instruction body) =>
      Block(Write($"<{tag}>"), body, Write($"</{tag}>"));

   public static Instruction ITag(string tag, string body) =>
      Write($"<{tag}>{body}</{tag}");

   public static Instruction ITag(string tag, Attrs attrs, Instruction body) =>
      Block(
         Write($"<{tag} "),
         Write(
            Mutate(
               attrs,
               attrs => Text(string.Join(
                  ' ',
                  attrs.Select(pair => pair.Value is string str
                     ? $"{pair.Key}=\"{str}\""
                     : $"{pair.Key}={pair.Value}"))))),
         Write(">"),
         body,
         Write($"</{tag}>")
      );

   public static Instruction ITag(string tag, Attrs attrs, string body) => 
      ITag(tag, attrs, Write(body))

   public static Instruction FTag(string tag, Instruction body) =>
      Block(
         WriteLine($"<{tag}>"),
         Indent(INDENTATION),
         body,
         Dedent(INDENTATION),
         WriteLine(),
         Write($"</{tag}>")
      );

   public static Instruction FTag(string tag, string body) => 
      FTag(tag, Write(body))

   public static Instruction FTag(string tag, Attrs attrs, Instruction body) =>
      Block(
         Write($"<{tag} "),
         Write(
            Mutate(
               attrs,
               attributes => Text(string.Join(
                  ' ',
                  attributes.Select(pair => pair.Value is string str
                     ? $"{pair.Key}=\"{str}\""
                     : $"{pair.Key}={pair.Value}"))))),
         WriteLine(">"),
         Indent(INDENTATION),
         body,
         Dedent(INDENTATION),
         WriteLine(),
         Write($"</{tag}>")
      );

   public static Instruction FTag(string tag, Attrs attrs, string body) =>
      FTag(tag, attrs, Write(body));
}


Reproducing this snippet generated with the help of https://lotremipsum.com


<!DOCTYPE html>
<html>
  <head>
    <title>Mackerel: HTMLGenerator</title>
  </head>
  <body style="width: 100%">
    <h1>Gravy piety Nazgûl knocking what about?</h1>
    <p>
      Poisoned observation lsengard parted stubbornness may golf Thranduil. 
      All right, then. Keep your secrets. Goblins adjusted diversion form 
      loses darkness.
    </p>
    <h2>Chest clot-head's deserted World secrets poring?</h2>
    <p>
      A wizard is never late, Frodo Baggins. Nor is he early. He arrives 
      precisely when he means to. Halflings heathen surprises mattered 
      spawn metal stupidity! Sorceress ceases tilled Samwise delays abyss 
      walks amaze remarked 17?
    </p>
    <h3>Hill legions inspection Haldir solitary yearns bitterness.</h3>
    <p>
      Thofin love leaderless flee t riding women. Nobody tosses a Dwarf. 
      Mouthful web fishes smoked bowl appearances hmm Mereth guessed 
      licensed. Lessened Esgaroth paws
    </p>
    <ul>
      <li>Sauron the White?</li>
      <li>Misty Mountain.</li>
      <li>Ringwraiths.</li>
      <li>Caradhras.</li>
      <li>Gollum.</li>
    </ul>
  </body>
</html>


We get


var lorem = Block(
   WriteLine("<!DOCTYPE html>"),
   HTML.FTag("html",
      Block(
         HTML.FTag("head",
            HTML.ITag("title", "Mackerel: HTMLGenerator")
         ),
         WriteLine(),
         HTML.FTag("body", 
            new Dictionary<string, object>() { ["style"] = "width: 100%;"}
            Join(
               Environment.NewLine,
               HTML.ITag("h1", "Gravy piety Nazgûl knocking what about?"),
               HTML.FTag("p", Write(LongText(
                  """
                  Poisoned observation lsengard parted stubbornness 
                  may golf Thranduil. All right, then. Keep your 
                  secrets. Goblins adjusted diversion form loses darkness.
                  """)
               )),
               HTML.ITag("h2", "Chest clot-head's deserted World secrets poring?"),
               HTML.FTag("p", Write(LongText(
                  """
                  A wizard is never late, Frodo Baggins. Nor is he 
                  early. He arrives precisely when he means to. 
                  Halflings heathen surprises mattered spawn metal 
                  stupidity! Sorceress ceases tilled Samwise delays  
                  abyss walks amaze remarked 17?"
                  """)
               )),
               HTML.ITag("h2", 
                  "Hill legions inspection Haldir solitary yearns bitterness."),
               HTML.FTag("p", Write(LongText(
                  """
                  Thofin love leaderless flee t riding women. Nobody 
                  tosses a Dwarf. Mouthful web fishes smoked bowl 
                  appearances hmm Mereth guessed licensed. Lessened 
                  Esgaroth paws.
                  """)
               )),
               HTML.FTag("ul",
                  Join(
                     Environment.NewLine,
                     HTML.ITag("li", "Sauron the White?")
                     HTML.ITag("li", "Misty Mountain."),
                     HTML.ITag("li", "Ringwraiths."),
                     HTML.ITag("li", "Caradhras."),
                     HTML.ITag("li", "Gollum.")
                  )
               )
            )
         )
      )
   ),
   Read()
)

var doc = new Document();

Console.WriteLine(lorem(in doc));