| // TODO(jmesserly): reconcile this with dart:web htmlEscape. |
| // This one might be more useful, as it is HTML5 spec compliant. |
| /// Escapes [text] for use in the |
| /// [HTML fragment serialization algorithm][1]. In particular, as described |
| /// in the [specification][2]: |
| /// |
| /// - Replace any occurrence of the `&` character by the string `&`. |
| /// - Replace any occurrences of the U+00A0 NO-BREAK SPACE character by the |
| /// string ` `. |
| /// - If the algorithm was invoked in [attributeMode], replace any occurrences |
| /// of the `"` character by the string `"`. |
| /// - If the algorithm was not invoked in [attributeMode], replace any |
| /// occurrences of the `<` character by the string `<`, and any occurrences |
| /// of the `>` character by the string `>`. |
| /// |
| /// [1]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments |
| /// [2]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString |
| String htmlSerializeEscape(String text, {bool attributeMode = false}) { |
| // TODO(jmesserly): is it faster to build up a list of codepoints? |
| // StringBuffer seems cleaner assuming Dart can unbox 1-char strings. |
| StringBuffer? result; |
| for (var i = 0; i < text.length; i++) { |
| final ch = text[i]; |
| String? replace; |
| switch (ch) { |
| case '&': |
| replace = '&'; |
| break; |
| case '\u00A0' /*NO-BREAK SPACE*/ : |
| replace = ' '; |
| break; |
| case '"': |
| if (attributeMode) replace = '"'; |
| break; |
| case '<': |
| if (!attributeMode) replace = '<'; |
| break; |
| case '>': |
| if (!attributeMode) replace = '>'; |
| break; |
| } |
| if (replace != null) { |
| result ??= StringBuffer(text.substring(0, i)); |
| result.write(replace); |
| } else if (result != null) { |
| result.write(ch); |
| } |
| } |
| |
| return result != null ? result.toString() : text; |
| } |