///|
fn adjusted_svg_tag_name(name : StringView) -> String {
  match name {
    "altglyph" => "altGlyph"
    "altglyphdef" => "altGlyphDef"
    "altglyphitem" => "altGlyphItem"
    "animatecolor" => "animateColor"
    "animatemotion" => "animateMotion"
    "animatetransform" => "animateTransform"
    "clippath" => "clipPath"
    "feblend" => "feBlend"
    "fecolormatrix" => "feColorMatrix"
    "fecomponenttransfer" => "feComponentTransfer"
    "fecomposite" => "feComposite"
    "feconvolvematrix" => "feConvolveMatrix"
    "fediffuselighting" => "feDiffuseLighting"
    "fedisplacementmap" => "feDisplacementMap"
    "fedistantlight" => "feDistantLight"
    "feflood" => "feFlood"
    "fefunca" => "feFuncA"
    "fefuncb" => "feFuncB"
    "fefuncg" => "feFuncG"
    "fefuncr" => "feFuncR"
    "fegaussianblur" => "feGaussianBlur"
    "feimage" => "feImage"
    "femerge" => "feMerge"
    "femergenode" => "feMergeNode"
    "femorphology" => "feMorphology"
    "feoffset" => "feOffset"
    "fepointlight" => "fePointLight"
    "fespecularlighting" => "feSpecularLighting"
    "fespotlight" => "feSpotLight"
    "fetile" => "feTile"
    "feturbulence" => "feTurbulence"
    "foreignobject" => "foreignObject"
    "glyphref" => "glyphRef"
    "lineargradient" => "linearGradient"
    "radialgradient" => "radialGradient"
    "textpath" => "textPath"
    _ => name.to_owned()
  }
}

///|
fn adjusted_svg_attribute_name(name : StringView) -> String {
  match name {
    "attributename" => "attributeName"
    "attributetype" => "attributeType"
    "basefrequency" => "baseFrequency"
    "baseprofile" => "baseProfile"
    "calcmode" => "calcMode"
    "clippathunits" => "clipPathUnits"
    "diffuseconstant" => "diffuseConstant"
    "edgemode" => "edgeMode"
    "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"
    _ => name.to_owned()
  }
}

///|
fn adjusted_mathml_attribute_name(name : StringView) -> String {
  match name {
    "definitionurl" => "definitionURL"
    _ => name.to_owned()
  }
}

///|
fn adjusted_foreign_attribute_name(name : StringView) -> String {
  match name {
    "xlink:actuate" => "xlink:actuate"
    "xlink:arcrole" => "xlink:arcrole"
    "xlink:href" => "xlink:href"
    "xlink:role" => "xlink:role"
    "xlink:show" => "xlink:show"
    "xlink:title" => "xlink:title"
    "xlink:type" => "xlink:type"
    "xml:lang" => "xml:lang"
    "xml:space" => "xml:space"
    "xmlns" => "xmlns"
    "xmlns:xlink" => "xmlns:xlink"
    _ => name.to_owned()
  }
}

///|
fn adjusted_start_tag_name_for_namespace(
  ns : StringView,
  name : StringView,
) -> String {
  if ns == "svg" {
    adjusted_svg_tag_name(name)
  } else {
    name.to_owned()
  }
}

///|
fn prepare_foreign_attrs(
  ns : StringView,
  attrs : Map[String, String?],
) -> Map[String, String?] {
  let adjusted : Map[String, String?] = {}
  for name, value in attrs {
    let namespace_adjusted = if ns == "math" {
      adjusted_mathml_attribute_name(name)
    } else if ns == "svg" {
      adjusted_svg_attribute_name(name)
    } else {
      name
    }
    let foreign_adjusted = adjusted_foreign_attribute_name(namespace_adjusted)
    adjusted[foreign_adjusted] = value
  }
  adjusted
}