| Index: tool/input_sdk/lib/convert/html_escape.dart
 | 
| diff --git a/tool/input_sdk/lib/convert/html_escape.dart b/tool/input_sdk/lib/convert/html_escape.dart
 | 
| index 512d9c31f2bf4da229779f9a6dba2d21d6869946..7efe317c7bf93f56ebf3d6b4af9744089bd365d3 100644
 | 
| --- a/tool/input_sdk/lib/convert/html_escape.dart
 | 
| +++ b/tool/input_sdk/lib/convert/html_escape.dart
 | 
| @@ -4,42 +4,167 @@
 | 
|  
 | 
|  part of dart.convert;
 | 
|  
 | 
| -// TODO(floitsch) - Document - Issue 13097
 | 
| +/**
 | 
| + * A `String` converter that converts characters to HTML entities.
 | 
| + *
 | 
| + * This is intended to sanitice text before inserting the text into an HTML
 | 
| + * document. Characters that are meaningful in HTML are converted to
 | 
| + * HTML entities (like `&` for `&`).
 | 
| + *
 | 
| + * The general converter escapes all characters that are meaningful in HTML
 | 
| + * attributes or normal element context. Elements with special content types
 | 
| + * (like CSS or JavaScript) may need a more specialized escaping that
 | 
| + * understands that content type.
 | 
| + *
 | 
| + * If the context where the text will be inserted is known in more detail,
 | 
| + * it's possible to omit escaping some characters (like quotes when not
 | 
| + * inside an attribute value).
 | 
| + *
 | 
| + * The escaped text should only be used inside quoted HTML attributes values
 | 
| + * or as text content of a normal element. Using the escaped text inside a
 | 
| + * tag, but not inside a quoted attribute value, is still dangerous.
 | 
| + */
 | 
|  const HtmlEscape HTML_ESCAPE = const HtmlEscape();
 | 
|  
 | 
| +/**
 | 
| + * HTML escape modes.
 | 
| + *
 | 
| + * Allows specifying a mode for HTML escaping that depend on the context
 | 
| + * where the escaped result is going to be used.
 | 
| + * The relevant contexts are:
 | 
| + *
 | 
| + * * as text content of an HTML element.
 | 
| + * * as value of a (single- or double-) quoted attribute value.
 | 
| + *
 | 
| + * All modes require escaping of `&` (ampersand) characters, and may
 | 
| + * enable escaping of more characters.
 | 
| + *
 | 
| + * Custom escape modes can be created using the [HtmlEscapeMode.HtmlEscapeMode]
 | 
| + * constructor.
 | 
| + */
 | 
|  class HtmlEscapeMode {
 | 
|    final String _name;
 | 
| +  /** Whether to escape '<' and '>'. */
 | 
|    final bool escapeLtGt;
 | 
| +  /** Whether to escape '"' (quote). */
 | 
|    final bool escapeQuot;
 | 
| +  /** Whether to escape "'" (apostrophe). */
 | 
|    final bool escapeApos;
 | 
| +  /**
 | 
| +   * Whether to escape "/" (forward slash, solidus).
 | 
| +   *
 | 
| +   * Escaping a slash is recommended to avoid cross-site scripting attacks by
 | 
| +   * [the Open Web Application Security Project](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content)
 | 
| +   */
 | 
|    final bool escapeSlash;
 | 
|  
 | 
| -  // TODO(floitsch) - Document - Issue 13097
 | 
| +  /**
 | 
| +   * Default escaping mode which escape all characters.
 | 
| +   *
 | 
| +   * The result of such an escaping is usable both in element content and
 | 
| +   * in any attribute value.
 | 
| +   *
 | 
| +   * The escaping only works for elements with normal HTML content,
 | 
| +   * and not for, for example, script or style element content,
 | 
| +   * which require escapes matching their particular content syntax.
 | 
| +   */
 | 
|    static const HtmlEscapeMode UNKNOWN =
 | 
| -    const HtmlEscapeMode._('unknown', true, true, true, true);
 | 
| -
 | 
| -  // TODO(floitsch) - Document - Issue 13097
 | 
| +      const HtmlEscapeMode._('unknown', true, true, true, true);
 | 
| +
 | 
| +  /**
 | 
| +   * Escaping mode for text going into double-quoted HTML attribute values.
 | 
| +   *
 | 
| +   * The result should not be used as the content of an unquoted
 | 
| +   * or single-quoted attribute value.
 | 
| +   *
 | 
| +   * Escapes double quotes (`"`) but not single quotes (`'`),
 | 
| +   * and escapes `<` and `>` characters because they are not allowed
 | 
| +   * in strict XHTML attributes
 | 
| +   */
 | 
|    static const HtmlEscapeMode ATTRIBUTE =
 | 
| -    const HtmlEscapeMode._('attribute', false, true, false, false);
 | 
| -
 | 
| -  // TODO(floitsch) - Document - Issue 13097
 | 
| +      const HtmlEscapeMode._('attribute', true, true, false, false);
 | 
| +
 | 
| +  /**
 | 
| +   * Escaping mode for text going into single-quoted HTML attribute values.
 | 
| +   *
 | 
| +   * The result should not be used as the content of an unquoted
 | 
| +   * or double-quoted attribute value.
 | 
| +   *
 | 
| +   * Escapes single quotes (`'`) but not double quotes (`"`),
 | 
| +   * and escapes `<` and `>` characters because they are not allowed
 | 
| +   * in strict XHTML attributes
 | 
| +   */
 | 
| +  static const HtmlEscapeMode SQ_ATTRIBUTE =
 | 
| +      const HtmlEscapeMode._('attribute', true, false, true, false);
 | 
| +
 | 
| +  /**
 | 
| +   * Escaping mode for text going into HTML element content.
 | 
| +   *
 | 
| +   * The escaping only works for elements with normal HTML content,
 | 
| +   * and not for, for example, script or style element content,
 | 
| +   * which require escapes matching their particular content syntax.
 | 
| +   *
 | 
| +   * Escapes `<` and `>` characters.
 | 
| +   */
 | 
|    static const HtmlEscapeMode ELEMENT =
 | 
| -    const HtmlEscapeMode._('element', true, false, false, true);
 | 
| -
 | 
| -  // TODO(floitsch) - Document - Issue 13097
 | 
| -  const HtmlEscapeMode._(this._name, this.escapeLtGt, this.escapeQuot,
 | 
| -    this.escapeApos, this.escapeSlash);
 | 
| +      const HtmlEscapeMode._('element', true, false, false, false);
 | 
| +
 | 
| +  const HtmlEscapeMode._(this._name,
 | 
| +                         this.escapeLtGt,
 | 
| +                         this.escapeQuot,
 | 
| +                         this.escapeApos,
 | 
| +                         this.escapeSlash);
 | 
| +
 | 
| +  /**
 | 
| +   * Create a custom escaping mode.
 | 
| +   *
 | 
| +   * All modes escape `&`.
 | 
| +   * The mode can further be set to escape `<` and `>` ([escapeLtGt]),
 | 
| +   * `"` ([escapeQuot]), `'` ([escapeApos]), and/or `/` ([escapeSlash]).
 | 
| +   */
 | 
| +  const HtmlEscapeMode({String name: "custom",
 | 
| +                        this.escapeLtGt: false,
 | 
| +                        this.escapeQuot: false,
 | 
| +                        this.escapeApos: false,
 | 
| +                        this.escapeSlash: false}) : _name = name;
 | 
|  
 | 
|    String toString() => _name;
 | 
|  }
 | 
|  
 | 
| -  // TODO(floitsch) - Document - Issue 13097
 | 
| -class HtmlEscape extends Converter<String, String> {
 | 
| -
 | 
| -  // TODO(floitsch) - Document - Issue 13097
 | 
| +/**
 | 
| + * Converter which escapes characters with special meaning in HTML.
 | 
| + *
 | 
| + * The converter finds characters that are siginificant in HTML source and
 | 
| + * replaces them with corresponding HTML entities.
 | 
| + *
 | 
| + * The characters that need escaping in HTML are:
 | 
| + *
 | 
| + * * `&` (ampersand) always need to be escaped.
 | 
| + * * `<` (less than) and '>' (greater than) when inside an element.
 | 
| + * * `"` (quote) when inside a double-quoted attribute value.
 | 
| + * * `'` (apostrophe) when inside a single-quoted attribute value.
 | 
| + *       Apostrophe is escaped as `'` instead of `'` since
 | 
| + *       not all browsers understand `'`.
 | 
| + * * `/` (slash) is recommended to be escaped because it may be used
 | 
| + *       to terminate an element in some HTML dialects.
 | 
| + *
 | 
| + * Escaping `>` (greater than) isn't necessary, but the result is often
 | 
| + * found to be easier to read if greater-than is also escaped whenever
 | 
| + * less-than is.
 | 
| + */
 | 
| +class HtmlEscape extends ChunkedConverter<String, String, String, String> {
 | 
| +
 | 
| +  /** The [HtmlEscapeMode] used by the converter. */
 | 
|    final HtmlEscapeMode mode;
 | 
|  
 | 
| -  // TODO(floitsch) - Document - Issue 13097
 | 
| +  /**
 | 
| +   * Create converter that escapes HTML characters.
 | 
| +   *
 | 
| +   * If [mode] is provided as either [HtmlEscapeMode.ATTRIBUTE] or
 | 
| +   * [HtmlEscapeMode.ELEMENT], only the corresponding subset of HTML
 | 
| +   * characters are escaped.
 | 
| +   * The default is to escape all HTML characters.
 | 
| +   */
 | 
|    const HtmlEscape([this.mode = HtmlEscapeMode.UNKNOWN]);
 | 
|  
 | 
|    String convert(String text) {
 | 
| @@ -47,29 +172,35 @@ class HtmlEscape extends Converter<String, String> {
 | 
|      return val == null ? text : val;
 | 
|    }
 | 
|  
 | 
| +  /**
 | 
| +   * Converts the substring of text from start to end.
 | 
| +   *
 | 
| +   * Returns `null` if no changes were necessary, otherwise returns
 | 
| +   * the converted string.
 | 
| +   */
 | 
|    String _convert(String text, int start, int end) {
 | 
|      StringBuffer result = null;
 | 
|      for (int i = start; i < end; i++) {
 | 
|        var ch = text[i];
 | 
| -      String replace = null;
 | 
| +      String replacement = null;
 | 
|        switch (ch) {
 | 
| -        case '&': replace = '&'; break;
 | 
| -        case '\u00A0'/*NO-BREAK SPACE*/: replace = ' '; break;
 | 
| -        case '"': if (mode.escapeQuot) replace = '"'; break;
 | 
| -        case "'": if (mode.escapeApos) replace = '''; break;
 | 
| -        case '<': if (mode.escapeLtGt) replace = '<'; break;
 | 
| -        case '>': if (mode.escapeLtGt) replace = '>'; break;
 | 
| -        case '/': if (mode.escapeSlash) replace = '/'; break;
 | 
| +        case '&': replacement = '&'; break;
 | 
| +        case '"': if (mode.escapeQuot) replacement = '"'; break;
 | 
| +        case "'": if (mode.escapeApos) replacement = '''; break;
 | 
| +        case '<': if (mode.escapeLtGt) replacement = '<'; break;
 | 
| +        case '>': if (mode.escapeLtGt) replacement = '>'; break;
 | 
| +        case '/': if (mode.escapeSlash) replacement = '/'; break;
 | 
|        }
 | 
| -      if (replace != null) {
 | 
| -        if (result == null) result = new StringBuffer(text.substring(start, i));
 | 
| -        result.write(replace);
 | 
| -      } else if (result != null) {
 | 
| -        result.write(ch);
 | 
| +      if (replacement != null) {
 | 
| +        if (result == null) result = new StringBuffer();
 | 
| +        if (i > start) result.write(text.substring(start, i));
 | 
| +        result.write(replacement);
 | 
| +        start = i + 1;
 | 
|        }
 | 
|      }
 | 
| -
 | 
| -    return result != null ? result.toString() : null;
 | 
| +    if (result == null) return null;
 | 
| +    if (end > start) result.write(text.substring(start, end));
 | 
| +    return result.toString();
 | 
|    }
 | 
|  
 | 
|    StringConversionSink startChunkedConversion(Sink<String> sink) {
 | 
| @@ -96,5 +227,5 @@ class _HtmlEscapeSink extends StringConversionSinkBase {
 | 
|      }
 | 
|    }
 | 
|  
 | 
| -  void close() => _sink.close();
 | 
| +  void close() { _sink.close(); }
 | 
|  }
 | 
| 
 |