docs: @TCB
    private static void encodeHtmlOnto(
        String plainText, Appendable output, @Nullable String braceReplacement)
            throws IOException {
      int n = plainText.length();
      int pos = 0;
      for (int i = 0; i < n; ++i) {
        char ch = plainText.charAt(i);
        if (ch < REPLACEMENTS.length) {  // Handles all ASCII.
          String repl = REPLACEMENTS[ch];
          if (ch == '{' && repl == null) {
            if (i + 1 == n || plainText.charAt(i + 1) == '{') {
              repl = braceReplacement;
            }
          }
          if (repl != null) {
            output.append(plainText, pos, i).append(repl);
            pos = i + 1;
          }
        } else if ((0x93A <= ch && ch <= 0xC4C)
            && (
                // Devanagari vowel
                ch <= 0x94F
                // Benagli vowels
                || 0x985 <= ch && ch <= 0x994
                || 0x9BE <= ch && ch < 0x9CC  // 0x9CC (Bengali AU) is ok
                || 0x9E0 <= ch && ch <= 0x9E3
                // Telugu vowels
                || 0xC05 <= ch && ch <= 0xC14
                || 0xC3E <= ch && ch != 0xC48 /* 0xC48 (Telugu AI) is ok */)) {
          // https://manishearth.github.io/blog/2018/02/15/picking-apart-the-crashing-ios-string/
          // > So, ultimately, the full set of cases that cause the crash are:
          // >   Any sequence <consonant1, virama, consonant2, ZWNJ, vowel>
          // > in Devanagari, Bengali, and Telugu, where: ...
  
          // TODO: This is needed as of February 2018, but hopefully not long after that.
          // We eliminate the ZWNJ which seems the minimally damaging thing to do to
          // Telugu rendering per the article above:
          // > a ZWNJ before a vowel doesn’t really do anything for most Indic scripts.
  
          if (pos < i) {
            if (plainText.charAt(i - 1) == 0x200C /* ZWNJ */) {
              output.append(plainText, pos, i - 1);
              // Drop the ZWNJ on the floor.
              pos = i;
            }
          } else if (output instanceof StringBuilder) {
            StringBuilder sb = (StringBuilder) output;
            int len = sb.length();
            if (len != 0) {
              if (sb.charAt(len - 1) == 0x200C /* ZWNJ */) {
                sb.setLength(len - 1);
              }
            }
          }
        } else if (((char) 0xd800) <= ch) {
          if (ch <= ((char) 0xdfff)) {
            char next;
            if (i + 1 < n
                && Character.isSurrogatePair(
                    ch, next = plainText.charAt(i + 1))) {
              // Emit supplemental codepoints as entity so that they cannot
              // be mis-encoded as UTF-8 of surrogates instead of UTF-8 proper
              // and get involved in UTF-16/UCS-2 confusion.
              int codepoint = Character.toCodePoint(ch, next);
              output.append(plainText, pos, i);
              appendNumericEntity(codepoint, output);
              ++i;
              pos = i + 1;
            } else {
              output.append(plainText, pos, i);
              // Elide the orphaned surrogate.
              pos = i + 1;
            }
          } else if (0xfe60 <= ch) {
            // Is a control character or possible full-width version of a
            // special character, a BOM, or one of the FE60 block that might
            // be elided or normalized to an HTML special character.
            // Running
            //   cat NormalizationText.txt \
            //     | perl -pe 's/ ?#.*//' \
            //     | egrep '(;003C(;|$)|003E|0026|0022|0027|0060)'
            // dumps a list of code-points that can normalize to HTML special
            // characters.
            output.append(plainText, pos, i);
            pos = i + 1;
            if ((ch & 0xfffe) == 0xfffe) {
              // Elide since not an the XML Character.
            } else {
              appendNumericEntity(ch, output);
            }
          }
        } else if (ch == '\u1FEF') {  // Normalizes to backtick.
          output.append(plainText, pos, i).append("&#8175;");
          pos = i + 1;
        }
      }
      output.append(plainText, pos, n);
    }