HtmlMarkupFormatter
Represents the standard HTML5 markup formatter.
using AngleSharp.Dom;
using AngleSharp.Text;
using System.Runtime.CompilerServices;
using System.Text;
namespace AngleSharp.Html
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public class HtmlMarkupFormatter : IMarkupFormatter
{
public static readonly IMarkupFormatter Instance = new HtmlMarkupFormatter();
public virtual string Comment(IComment comment)
{
return "<!--" + comment.Data + "-->";
}
public virtual string Doctype(IDocumentType doctype)
{
string ids = GetIds(doctype.PublicIdentifier, doctype.SystemIdentifier);
return "<!DOCTYPE " + doctype.Name + ids + ">";
}
public virtual string Processing(IProcessingInstruction processing)
{
string str = processing.Target + " " + processing.Data;
return "<?" + str + ">";
}
public virtual string LiteralText(ICharacterData text)
{
return text.Data;
}
public virtual string Text(ICharacterData text)
{
return EscapeText(text.Data);
}
public virtual string OpenTag(IElement element, bool selfClosing)
{
StringBuilder stringBuilder = StringBuilderPool.Obtain();
stringBuilder.Append('<');
if (!string.IsNullOrEmpty(element.Prefix))
stringBuilder.Append(element.Prefix).Append(':');
stringBuilder.Append(element.LocalName);
foreach (IAttr attribute in element.Attributes) {
stringBuilder.Append(' ').Append(Attribute(attribute));
}
stringBuilder.Append('>');
return stringBuilder.ToPool();
}
public virtual string CloseTag(IElement element, bool selfClosing)
{
string prefix = element.Prefix;
string localName = element.LocalName;
string str = (!string.IsNullOrEmpty(prefix)) ? (prefix + ":" + localName) : localName;
if (!selfClosing)
return "</" + str + ">";
return string.Empty;
}
protected virtual string Attribute(IAttr attr)
{
StringBuilder stringBuilder = StringBuilderPool.Obtain();
WriteAttributeName(attr, stringBuilder);
if (attr.Value != null) {
stringBuilder.Append('=').Append('"');
WriteAttributeValue(attr, stringBuilder);
return stringBuilder.Append('"').ToPool();
}
return stringBuilder.ToPool();
}
internal static void WriteAttributeName(IAttr attr, StringBuilder stringBuilder)
{
string namespaceUri = attr.NamespaceUri;
string localName = attr.LocalName;
if (string.IsNullOrEmpty(namespaceUri))
stringBuilder.Append(localName);
else if (namespaceUri.Is(NamespaceNames.XmlUri)) {
stringBuilder.Append(NamespaceNames.XmlPrefix).Append(':').Append(localName);
} else if (namespaceUri.Is(NamespaceNames.XLinkUri)) {
stringBuilder.Append(NamespaceNames.XLinkPrefix).Append(':').Append(localName);
} else if (namespaceUri.Is(NamespaceNames.XmlNsUri)) {
stringBuilder.Append(XmlNamespaceLocalName(localName));
} else {
stringBuilder.Append(attr.Name);
}
}
internal static void WriteAttributeValue(IAttr attr, StringBuilder stringBuilder)
{
string text = attr.Value ?? string.Empty;
for (int i = 0; i < text.Length; i++) {
switch (text[i]) {
case '&':
stringBuilder.Append("&");
break;
case ' ':
stringBuilder.Append(" ");
break;
case '"':
stringBuilder.Append(""");
break;
default:
stringBuilder.Append(text[i]);
break;
}
}
}
public static string EscapeText(string content)
{
StringBuilder stringBuilder = StringBuilderPool.Obtain();
for (int i = 0; i < content.Length; i++) {
switch (content[i]) {
case '&':
stringBuilder.Append("&");
break;
case ' ':
stringBuilder.Append(" ");
break;
case '>':
stringBuilder.Append(">");
break;
case '<':
stringBuilder.Append("<");
break;
default:
stringBuilder.Append(content[i]);
break;
}
}
return stringBuilder.ToPool();
}
public static string GetIds(string publicId, string systemId)
{
if (string.IsNullOrEmpty(publicId) && string.IsNullOrEmpty(systemId))
return string.Empty;
if (string.IsNullOrEmpty(systemId))
return " PUBLIC \"" + publicId + "\"";
if (string.IsNullOrEmpty(publicId))
return " SYSTEM \"" + systemId + "\"";
return " PUBLIC \"" + publicId + "\" \"" + systemId + "\"";
}
public static string XmlNamespaceLocalName(string name)
{
if (!(name != NamespaceNames.XmlNsPrefix))
return name;
return NamespaceNames.XmlNsPrefix + ":" + name;
}
}
}