docs: @CheckReturnValue
    Context transitionToTagName(HtmlTagNode node) {
      // according to spec ascii case is not meaningful for tag names.
      String tagName = node.getTagName().getStaticTagNameAsLowerCase();
      boolean isEndTag = state == HtmlContext.HTML_BEFORE_CLOSE_TAG_NAME;
      Context.ElementType elType = ElementType.NORMAL;
      int newTemplateNestDepth = templateNestDepth;
      if (tagName.equals("template")) {
        newTemplateNestDepth += isEndTag ? -1 : 1;
        if (newTemplateNestDepth < 0) {
          throw SoyAutoescapeException.createWithNode(
              "Saw an html5 </template> without encountering <template>.", node);
        }
      } else if (!isEndTag) {
        // We currently only treat <img> and SVG's <image> as a media type, since for <video> and
        // <audio> there are concerns that attackers could introduce rich video or audio that
        // facilitates social engineering.  Upon further review, it's possible we may allow them.
        switch (tagName) {
          case "img":
          case "image":
            elType = ElementType.MEDIA;
            break;
          case "iframe":
            elType = ElementType.IFRAME;
            break;
          case "script":
            elType = ElementType.SCRIPT;
            break;
          case "style":
            elType = ElementType.STYLE;
            break;
          case "base":
            elType = ElementType.BASE;
            break;
          case "link":
            if (node.getDirectAttributeNamed("rel") == null
                && node.getDirectAttributeNamed("itemprop") != null) {
              elType = ElementType.NORMAL;
            } else {
              String rel = getStaticAttributeValue(node, "rel");
              elType =
                  rel != null && REGULAR_LINK_PATTERN.matcher(rel).matches()
                      ? ElementType.NORMAL
                      : ElementType.LINK_EXECUTABLE;
            }
            break;
          case "meta":
            String httpEquiv = getStaticAttributeValue(node, "http-equiv");
            elType =
                "refresh".equalsIgnoreCase(httpEquiv) ? ElementType.META_REFRESH : ElementType.NORMAL;
            break;
          case "textarea":
            elType = ElementType.TEXTAREA;
            break;
          case "title":
            elType = ElementType.TITLE;
            break;
          case "xmp":
            elType = ElementType.XMP;
            break;
          default: // fall out
        }
      }
      return toBuilder()
          .withState(HtmlContext.HTML_TAG_NAME)
          .withoutAttrContext()
          .withElType(elType)
          .withTemplateNestDepth(newTemplateNestDepth)
          .build();
    }