HtmlForeignExtensions
A collection of useful helpers when working with foreign content.
using AngleSharp.Dom;
using AngleSharp.Dom.Mathml;
using AngleSharp.Dom.Svg;
using AngleSharp.Extensions;
using AngleSharp.Html;
using System;
using System.Collections.Generic;
namespace AngleSharp.Parser.Html
{
internal static class HtmlForeignExtensions
{
private static readonly Dictionary<string, string> svgAttributeNames = new Dictionary<string, string>(StringComparer.Ordinal) {
{
"attributename",
"attributeName"
},
{
"attributetype",
"attributeType"
},
{
"basefrequency",
"baseFrequency"
},
{
"baseprofile",
"baseProfile"
},
{
"calcmode",
"calcMode"
},
{
"clippathunits",
"clipPathUnits"
},
{
"contentscripttype",
"contentScriptType"
},
{
"contentstyletype",
"contentStyleType"
},
{
"diffuseconstant",
"diffuseConstant"
},
{
"edgemode",
"edgeMode"
},
{
"externalresourcesrequired",
"externalResourcesRequired"
},
{
"filterres",
"filterRes"
},
{
"filterunits",
"filterUnits"
},
{
"glyphref",
"glyphRef"
},
{
"gradienttransform",
"gradientTransform"
},
{
"gradientunits",
"gradientUnits"
},
{
"kernelmatrix",
"kernelMatrix"
},
{
"kernelunitlength",
"kernelUnitLength"
},
{
"keypoints",
"keyPoints"
},
{
"keysplines",
"keySplines"
},
{
"keytimes",
"keyTimes"
},
{
"lengthadjust",
"lengthAdjust"
},
{
"limitingconeangle",
"limitingConeAngle"
},
{
"markerheight",
"markerHeight"
},
{
"markerunits",
"markerUnits"
},
{
"markerwidth",
"markerWidth"
},
{
"maskcontentunits",
"maskContentUnits"
},
{
"maskunits",
"maskUnits"
},
{
"numoctaves",
"numOctaves"
},
{
"pathlength",
"pathLength"
},
{
"patterncontentunits",
"patternContentUnits"
},
{
"patterntransform",
"patternTransform"
},
{
"patternunits",
"patternUnits"
},
{
"pointsatx",
"pointsAtX"
},
{
"pointsaty",
"pointsAtY"
},
{
"pointsatz",
"pointsAtZ"
},
{
"preservealpha",
"preserveAlpha"
},
{
"preserveaspectratio",
"preserveAspectRatio"
},
{
"primitiveunits",
"primitiveUnits"
},
{
"refx",
"refX"
},
{
"refy",
"refY"
},
{
"repeatcount",
"repeatCount"
},
{
"repeatdur",
"repeatDur"
},
{
"requiredextensions",
"requiredExtensions"
},
{
"requiredfeatures",
"requiredFeatures"
},
{
"specularconstant",
"specularConstant"
},
{
"specularexponent",
"specularExponent"
},
{
"spreadmethod",
"spreadMethod"
},
{
"startoffset",
"startOffset"
},
{
"stddeviation",
"stdDeviation"
},
{
"stitchtiles",
"stitchTiles"
},
{
"surfacescale",
"surfaceScale"
},
{
"systemlanguage",
"systemLanguage"
},
{
"tablevalues",
"tableValues"
},
{
"targetx",
"targetX"
},
{
"targety",
"targetY"
},
{
"textlength",
"textLength"
},
{
"viewbox",
"viewBox"
},
{
"viewtarget",
"viewTarget"
},
{
"xchannelselector",
"xChannelSelector"
},
{
"ychannelselector",
"yChannelSelector"
},
{
"zoomandpan",
"zoomAndPan"
}
};
public static MathElement Setup(this MathElement element, HtmlTagToken tag)
{
int count = tag.Attributes.Count;
for (int i = 0; i < count; i++) {
string key = tag.Attributes[i].Key;
string value = tag.Attributes[i].Value;
element.AdjustAttribute(key.AdjustToMathAttribute(), value);
}
element.SetupElement();
return element;
}
public static SvgElement Setup(this SvgElement element, HtmlTagToken tag)
{
int count = tag.Attributes.Count;
for (int i = 0; i < count; i++) {
string key = tag.Attributes[i].Key;
string value = tag.Attributes[i].Value;
element.AdjustAttribute(key.AdjustToSvgAttribute(), value);
}
element.SetupElement();
return element;
}
public static void AdjustAttribute(this Element element, string name, string value)
{
if (IsXLinkAttribute(name))
element.SetAttribute(NamespaceNames.XLinkUri, name.Substring(name.IndexOf(':') + 1), value);
else if (IsXmlAttribute(name)) {
element.SetAttribute(NamespaceNames.XmlUri, name, value);
} else if (IsXmlNamespaceAttribute(name)) {
element.SetAttribute(NamespaceNames.XmlNsUri, name, value);
} else {
element.SetOwnAttribute(name, value);
}
}
public static string AdjustToMathAttribute(this string attributeName)
{
if (attributeName.Is("definitionurl"))
return "definitionURL";
return attributeName;
}
public static string AdjustToSvgAttribute(this string attributeName)
{
string value = null;
if (svgAttributeNames.TryGetValue(attributeName, out value))
return value;
return attributeName;
}
private static bool IsXmlNamespaceAttribute(string name)
{
if (name.Length > 4) {
if (!name.Is(NamespaceNames.XmlNsPrefix))
return name.Is("xmlns:xlink");
return true;
}
return false;
}
private static bool IsXmlAttribute(string name)
{
if (name.Length > 7 && "xml:".EqualsSubset(name, 0, 4)) {
if (!TagNames.Base.EqualsSubset(name, 4, 4) && !AttributeNames.Lang.EqualsSubset(name, 4, 4))
return AttributeNames.Space.EqualsSubset(name, 4, 5);
return true;
}
return false;
}
private static bool IsXLinkAttribute(string name)
{
if (name.Length > 9 && "xlink:".EqualsSubset(name, 0, 6)) {
if (!AttributeNames.Actuate.EqualsSubset(name, 6, 7) && !AttributeNames.Arcrole.EqualsSubset(name, 6, 7) && !AttributeNames.Href.EqualsSubset(name, 6, 4) && !AttributeNames.Role.EqualsSubset(name, 6, 4) && !AttributeNames.Show.EqualsSubset(name, 6, 4) && !AttributeNames.Type.EqualsSubset(name, 6, 4))
return AttributeNames.Title.EqualsSubset(name, 6, 5);
return true;
}
return false;
}
private static bool EqualsSubset(this string a, string b, int index, int length)
{
return string.Compare(a, 0, b, index, length, StringComparison.Ordinal) == 0;
}
}
}