| // Copyright (c) project authors. All rights reserved. | |
| // Licensed under the MIT license. | |
| // See LICENSE file in the project root for details. | |
| // 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; | |
| } |