["^ ","~:resource-id",["~:shadow.build.classpath/resource","goog/string/string.js"],"~:js","goog.provide(\"goog.string\");\ngoog.provide(\"goog.string.Unicode\");\ngoog.require(\"goog.dom.safe\");\ngoog.require(\"goog.html.uncheckedconversions\");\ngoog.require(\"goog.string.Const\");\ngoog.require(\"goog.string.internal\");\ngoog.string.DETECT_DOUBLE_ESCAPING = goog.define(\"goog.string.DETECT_DOUBLE_ESCAPING\", false);\ngoog.string.FORCE_NON_DOM_HTML_UNESCAPING = goog.define(\"goog.string.FORCE_NON_DOM_HTML_UNESCAPING\", false);\ngoog.string.Unicode = {NBSP:\" \", ZERO_WIDTH_SPACE:\"​\"};\ngoog.string.startsWith = goog.string.internal.startsWith;\ngoog.string.endsWith = goog.string.internal.endsWith;\ngoog.string.caseInsensitiveStartsWith = goog.string.internal.caseInsensitiveStartsWith;\ngoog.string.caseInsensitiveEndsWith = goog.string.internal.caseInsensitiveEndsWith;\ngoog.string.caseInsensitiveEquals = goog.string.internal.caseInsensitiveEquals;\ngoog.string.subs = function(str, var_args) {\n  const splitParts = str.split(\"%s\");\n  let returnString = \"\";\n  const subsArguments = Array.prototype.slice.call(arguments, 1);\n  while (subsArguments.length && splitParts.length > 1) {\n    returnString += splitParts.shift() + subsArguments.shift();\n  }\n  return returnString + splitParts.join(\"%s\");\n};\ngoog.string.collapseWhitespace = function(str) {\n  return str.replace(/[\\s\\xa0]+/g, \" \").replace(/^\\s+|\\s+$/g, \"\");\n};\ngoog.string.isEmptyOrWhitespace = goog.string.internal.isEmptyOrWhitespace;\ngoog.string.isEmptyString = function(str) {\n  return str.length == 0;\n};\ngoog.string.isEmpty = goog.string.isEmptyOrWhitespace;\ngoog.string.isEmptyOrWhitespaceSafe = function(str) {\n  return goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str));\n};\ngoog.string.isEmptySafe = goog.string.isEmptyOrWhitespaceSafe;\ngoog.string.isBreakingWhitespace = function(str) {\n  return !/[^\\t\\n\\r ]/.test(str);\n};\ngoog.string.isAlpha = function(str) {\n  return !/[^a-zA-Z]/.test(str);\n};\ngoog.string.isNumeric = function(str) {\n  return !/[^0-9]/.test(str);\n};\ngoog.string.isAlphaNumeric = function(str) {\n  return !/[^a-zA-Z0-9]/.test(str);\n};\ngoog.string.isSpace = function(ch) {\n  return ch == \" \";\n};\ngoog.string.isUnicodeChar = function(ch) {\n  return ch.length == 1 && ch >= \" \" && ch <= \"~\" || ch >= \"€\" && ch <= \"�\";\n};\ngoog.string.stripNewlines = function(str) {\n  return str.replace(/(\\r\\n|\\r|\\n)+/g, \" \");\n};\ngoog.string.canonicalizeNewlines = function(str) {\n  return str.replace(/(\\r\\n|\\r|\\n)/g, \"\\n\");\n};\ngoog.string.normalizeWhitespace = function(str) {\n  return str.replace(/\\xa0|\\s/g, \" \");\n};\ngoog.string.normalizeSpaces = function(str) {\n  return str.replace(/\\xa0|[ \\t]+/g, \" \");\n};\ngoog.string.collapseBreakingSpaces = function(str) {\n  return str.replace(/[\\t\\r\\n ]+/g, \" \").replace(/^[\\t\\r\\n ]+|[\\t\\r\\n ]+$/g, \"\");\n};\ngoog.string.trim = goog.string.internal.trim;\ngoog.string.trimLeft = function(str) {\n  return str.replace(/^[\\s\\xa0]+/, \"\");\n};\ngoog.string.trimRight = function(str) {\n  return str.replace(/[\\s\\xa0]+$/, \"\");\n};\ngoog.string.caseInsensitiveCompare = goog.string.internal.caseInsensitiveCompare;\ngoog.string.numberAwareCompare_ = function(str1, str2, tokenizerRegExp) {\n  if (str1 == str2) {\n    return 0;\n  }\n  if (!str1) {\n    return -1;\n  }\n  if (!str2) {\n    return 1;\n  }\n  const tokens1 = str1.toLowerCase().match(tokenizerRegExp);\n  const tokens2 = str2.toLowerCase().match(tokenizerRegExp);\n  const count = Math.min(tokens1.length, tokens2.length);\n  for (let i = 0; i < count; i++) {\n    const a = tokens1[i];\n    const b = tokens2[i];\n    if (a != b) {\n      const num1 = parseInt(a, 10);\n      if (!isNaN(num1)) {\n        const num2 = parseInt(b, 10);\n        if (!isNaN(num2) && num1 - num2) {\n          return num1 - num2;\n        }\n      }\n      return a < b ? -1 : 1;\n    }\n  }\n  if (tokens1.length != tokens2.length) {\n    return tokens1.length - tokens2.length;\n  }\n  return str1 < str2 ? -1 : 1;\n};\ngoog.string.intAwareCompare = function(str1, str2) {\n  return goog.string.numberAwareCompare_(str1, str2, /\\d+|\\D+/g);\n};\ngoog.string.floatAwareCompare = function(str1, str2) {\n  return goog.string.numberAwareCompare_(str1, str2, /\\d+|\\.\\d+|\\D+/g);\n};\ngoog.string.numerateCompare = goog.string.floatAwareCompare;\ngoog.string.urlEncode = function(str) {\n  return encodeURIComponent(String(str));\n};\ngoog.string.urlDecode = function(str) {\n  return decodeURIComponent(str.replace(/\\+/g, \" \"));\n};\ngoog.string.newLineToBr = goog.string.internal.newLineToBr;\ngoog.string.htmlEscape = function(str, opt_isLikelyToContainHtmlChars) {\n  str = goog.string.internal.htmlEscape(str, opt_isLikelyToContainHtmlChars);\n  if (goog.string.DETECT_DOUBLE_ESCAPING) {\n    str = str.replace(goog.string.E_RE_, \"\\x26#101;\");\n  }\n  return str;\n};\ngoog.string.E_RE_ = /e/g;\ngoog.string.unescapeEntities = function(str) {\n  if (goog.string.contains(str, \"\\x26\")) {\n    if (!goog.string.FORCE_NON_DOM_HTML_UNESCAPING && \"document\" in goog.global) {\n      return goog.string.unescapeEntitiesUsingDom_(str);\n    } else {\n      return goog.string.unescapePureXmlEntities_(str);\n    }\n  }\n  return str;\n};\ngoog.string.unescapeEntitiesWithDocument = function(str, document) {\n  if (goog.string.contains(str, \"\\x26\")) {\n    return goog.string.unescapeEntitiesUsingDom_(str, document);\n  }\n  return str;\n};\ngoog.string.unescapeEntitiesUsingDom_ = function(str, opt_document) {\n  const seen = {\"\\x26amp;\":\"\\x26\", \"\\x26lt;\":\"\\x3c\", \"\\x26gt;\":\"\\x3e\", \"\\x26quot;\":'\"'};\n  let div;\n  if (opt_document) {\n    div = opt_document.createElement(\"div\");\n  } else {\n    div = goog.global.document.createElement(\"div\");\n  }\n  return str.replace(goog.string.HTML_ENTITY_PATTERN_, function(s, entity) {\n    let value = seen[s];\n    if (value) {\n      return value;\n    }\n    if (entity.charAt(0) == \"#\") {\n      const n = Number(\"0\" + entity.slice(1));\n      if (!isNaN(n)) {\n        value = String.fromCharCode(n);\n      }\n    }\n    if (!value) {\n      goog.dom.safe.setInnerHtml(div, goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract(goog.string.Const.from(\"Single HTML entity.\"), s + \" \"));\n      value = div.firstChild.nodeValue.slice(0, -1);\n    }\n    return seen[s] = value;\n  });\n};\ngoog.string.unescapePureXmlEntities_ = function(str) {\n  return str.replace(/&([^;]+);/g, function(s, entity) {\n    switch(entity) {\n      case \"amp\":\n        return \"\\x26\";\n      case \"lt\":\n        return \"\\x3c\";\n      case \"gt\":\n        return \"\\x3e\";\n      case \"quot\":\n        return '\"';\n      default:\n        if (entity.charAt(0) == \"#\") {\n          const n = Number(\"0\" + entity.slice(1));\n          if (!isNaN(n)) {\n            return String.fromCharCode(n);\n          }\n        }\n        return s;\n    }\n  });\n};\ngoog.string.HTML_ENTITY_PATTERN_ = /&([^;\\s<&]+);?/g;\ngoog.string.whitespaceEscape = function(str, opt_xml) {\n  return goog.string.newLineToBr(str.replace(/  /g, \" \\x26#160;\"), opt_xml);\n};\ngoog.string.preserveSpaces = function(str) {\n  return str.replace(/(^|[\\n ]) /g, \"$1\" + goog.string.Unicode.NBSP);\n};\ngoog.string.stripQuotes = function(str, quoteChars) {\n  const length = quoteChars.length;\n  for (let i = 0; i < length; i++) {\n    const quoteChar = length == 1 ? quoteChars : quoteChars.charAt(i);\n    if (str.charAt(0) == quoteChar && str.charAt(str.length - 1) == quoteChar) {\n      return str.substring(1, str.length - 1);\n    }\n  }\n  return str;\n};\ngoog.string.truncate = function(str, chars, opt_protectEscapedCharacters) {\n  if (opt_protectEscapedCharacters) {\n    str = goog.string.unescapeEntities(str);\n  }\n  if (str.length > chars) {\n    str = str.substring(0, chars - 3) + \"...\";\n  }\n  if (opt_protectEscapedCharacters) {\n    str = goog.string.htmlEscape(str);\n  }\n  return str;\n};\ngoog.string.truncateMiddle = function(str, chars, opt_protectEscapedCharacters, opt_trailingChars) {\n  if (opt_protectEscapedCharacters) {\n    str = goog.string.unescapeEntities(str);\n  }\n  if (opt_trailingChars && str.length > chars) {\n    if (opt_trailingChars > chars) {\n      opt_trailingChars = chars;\n    }\n    const endPoint = str.length - opt_trailingChars;\n    const startPoint = chars - opt_trailingChars;\n    str = str.substring(0, startPoint) + \"...\" + str.substring(endPoint);\n  } else if (str.length > chars) {\n    let half = Math.floor(chars / 2);\n    const endPos = str.length - half;\n    half += chars % 2;\n    str = str.substring(0, half) + \"...\" + str.substring(endPos);\n  }\n  if (opt_protectEscapedCharacters) {\n    str = goog.string.htmlEscape(str);\n  }\n  return str;\n};\ngoog.string.specialEscapeChars_ = {\"\\x00\":\"\\\\0\", \"\\b\":\"\\\\b\", \"\\f\":\"\\\\f\", \"\\n\":\"\\\\n\", \"\\r\":\"\\\\r\", \"\\t\":\"\\\\t\", \"\\v\":\"\\\\x0B\", '\"':'\\\\\"', \"\\\\\":\"\\\\\\\\\", \"\\x3c\":\"\\\\u003C\"};\ngoog.string.jsEscapeCache_ = {\"'\":\"\\\\'\"};\ngoog.string.quote = function(s) {\n  s = String(s);\n  const sb = ['\"'];\n  for (let i = 0; i < s.length; i++) {\n    const ch = s.charAt(i);\n    const cc = ch.charCodeAt(0);\n    sb[i + 1] = goog.string.specialEscapeChars_[ch] || (cc > 31 && cc < 127 ? ch : goog.string.escapeChar(ch));\n  }\n  sb.push('\"');\n  return sb.join(\"\");\n};\ngoog.string.escapeString = function(str) {\n  const sb = [];\n  for (let i = 0; i < str.length; i++) {\n    sb[i] = goog.string.escapeChar(str.charAt(i));\n  }\n  return sb.join(\"\");\n};\ngoog.string.escapeChar = function(c) {\n  if (c in goog.string.jsEscapeCache_) {\n    return goog.string.jsEscapeCache_[c];\n  }\n  if (c in goog.string.specialEscapeChars_) {\n    return goog.string.jsEscapeCache_[c] = goog.string.specialEscapeChars_[c];\n  }\n  let rv = c;\n  const cc = c.charCodeAt(0);\n  if (cc > 31 && cc < 127) {\n    rv = c;\n  } else {\n    if (cc < 256) {\n      rv = \"\\\\x\";\n      if (cc < 16 || cc > 256) {\n        rv += \"0\";\n      }\n    } else {\n      rv = \"\\\\u\";\n      if (cc < 4096) {\n        rv += \"0\";\n      }\n    }\n    rv += cc.toString(16).toUpperCase();\n  }\n  return goog.string.jsEscapeCache_[c] = rv;\n};\ngoog.string.contains = goog.string.internal.contains;\ngoog.string.caseInsensitiveContains = goog.string.internal.caseInsensitiveContains;\ngoog.string.countOf = function(s, ss) {\n  return s && ss ? s.split(ss).length - 1 : 0;\n};\ngoog.string.removeAt = function(s, index, stringLength) {\n  let resultStr = s;\n  if (index >= 0 && index < s.length && stringLength > 0) {\n    resultStr = s.slice(0, index) + s.slice(index + stringLength);\n  }\n  return resultStr;\n};\ngoog.string.remove = function(str, substr) {\n  return str.replace(substr, \"\");\n};\ngoog.string.removeAll = function(s, ss) {\n  const re = new RegExp(goog.string.regExpEscape(ss), \"g\");\n  return s.replace(re, \"\");\n};\ngoog.string.replaceAll = function(s, ss, replacement) {\n  const re = new RegExp(goog.string.regExpEscape(ss), \"g\");\n  return s.replace(re, replacement.replace(/\\$/g, \"$$$$\"));\n};\ngoog.string.regExpEscape = function(s) {\n  return String(s).replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g, \"\\\\$1\").replace(/\\x08/g, \"\\\\x08\");\n};\ngoog.string.repeat = String.prototype.repeat ? function(string, length) {\n  return string.repeat(length);\n} : function(string, length) {\n  return (new Array(length + 1)).join(string);\n};\ngoog.string.padNumber = function(num, length, opt_precision) {\n  if (!Number.isFinite(num)) {\n    return String(num);\n  }\n  let s = opt_precision !== undefined ? num.toFixed(opt_precision) : String(num);\n  let index = s.indexOf(\".\");\n  if (index === -1) {\n    index = s.length;\n  }\n  const sign = s[0] === \"-\" ? \"-\" : \"\";\n  if (sign) {\n    s = s.substring(1);\n  }\n  return sign + goog.string.repeat(\"0\", Math.max(0, length - index)) + s;\n};\ngoog.string.makeSafe = function(obj) {\n  return obj == null ? \"\" : String(obj);\n};\ngoog.string.getRandomString = function() {\n  const x = 2147483648;\n  return Math.floor(Math.random() * x).toString(36) + Math.abs(Math.floor(Math.random() * x) ^ goog.now()).toString(36);\n};\ngoog.string.compareVersions = goog.string.internal.compareVersions;\ngoog.string.hashCode = function(str) {\n  let result = 0;\n  for (let i = 0; i < str.length; ++i) {\n    result = 31 * result + str.charCodeAt(i) >>> 0;\n  }\n  return result;\n};\ngoog.string.uniqueStringCounter_ = Math.random() * 2147483648 | 0;\ngoog.string.createUniqueString = function() {\n  return \"goog_\" + goog.string.uniqueStringCounter_++;\n};\ngoog.string.toNumber = function(str) {\n  const num = Number(str);\n  if (num == 0 && goog.string.isEmptyOrWhitespace(str)) {\n    return NaN;\n  }\n  return num;\n};\ngoog.string.isLowerCamelCase = function(str) {\n  return /^[a-z]+([A-Z][a-z]*)*$/.test(str);\n};\ngoog.string.isUpperCamelCase = function(str) {\n  return /^([A-Z][a-z]*)+$/.test(str);\n};\ngoog.string.toCamelCase = function(str) {\n  return String(str).replace(/\\-([a-z])/g, function(all, match) {\n    return match.toUpperCase();\n  });\n};\ngoog.string.toSelectorCase = function(str) {\n  return String(str).replace(/([A-Z])/g, \"-$1\").toLowerCase();\n};\ngoog.string.toTitleCase = function(str, opt_delimiters) {\n  let delimiters = typeof opt_delimiters === \"string\" ? goog.string.regExpEscape(opt_delimiters) : \"\\\\s\";\n  delimiters = delimiters ? \"|[\" + delimiters + \"]+\" : \"\";\n  const regexp = new RegExp(\"(^\" + delimiters + \")([a-z])\", \"g\");\n  return str.replace(regexp, function(all, p1, p2) {\n    return p1 + p2.toUpperCase();\n  });\n};\ngoog.string.capitalize = function(str) {\n  return String(str.charAt(0)).toUpperCase() + String(str.slice(1)).toLowerCase();\n};\ngoog.string.parseInt = function(value) {\n  if (isFinite(value)) {\n    value = String(value);\n  }\n  if (typeof value === \"string\") {\n    return /^\\s*-?0x/i.test(value) ? parseInt(value, 16) : parseInt(value, 10);\n  }\n  return NaN;\n};\ngoog.string.splitLimit = function(str, separator, limit) {\n  const parts = str.split(separator);\n  const returnVal = [];\n  while (limit > 0 && parts.length) {\n    returnVal.push(parts.shift());\n    limit--;\n  }\n  if (parts.length) {\n    returnVal.push(parts.join(separator));\n  }\n  return returnVal;\n};\ngoog.string.lastComponent = function(str, separators) {\n  if (!separators) {\n    return str;\n  } else if (typeof separators == \"string\") {\n    separators = [separators];\n  }\n  let lastSeparatorIndex = -1;\n  for (let i = 0; i < separators.length; i++) {\n    if (separators[i] == \"\") {\n      continue;\n    }\n    const currentSeparatorIndex = str.lastIndexOf(separators[i]);\n    if (currentSeparatorIndex > lastSeparatorIndex) {\n      lastSeparatorIndex = currentSeparatorIndex;\n    }\n  }\n  if (lastSeparatorIndex == -1) {\n    return str;\n  }\n  return str.slice(lastSeparatorIndex + 1);\n};\ngoog.string.editDistance = function(a, b) {\n  const v0 = [];\n  const v1 = [];\n  if (a == b) {\n    return 0;\n  }\n  if (!a.length || !b.length) {\n    return Math.max(a.length, b.length);\n  }\n  for (let i = 0; i < b.length + 1; i++) {\n    v0[i] = i;\n  }\n  for (let i = 0; i < a.length; i++) {\n    v1[0] = i + 1;\n    for (let j = 0; j < b.length; j++) {\n      const cost = Number(a[i] != b[j]);\n      v1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\n    }\n    for (let j = 0; j < v0.length; j++) {\n      v0[j] = v1[j];\n    }\n  }\n  return v1[b.length];\n};\n","~:source","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview Utilities for string manipulation.\n */\n\n\n/**\n * Namespace for string utilities\n */\ngoog.provide('goog.string');\ngoog.provide('goog.string.Unicode');\n\ngoog.require('goog.dom.safe');\ngoog.require('goog.html.uncheckedconversions');\ngoog.require('goog.string.Const');\ngoog.require('goog.string.internal');\n\n\n/**\n * @define {boolean} Enables HTML escaping of lowercase letter \"e\" which helps\n * with detection of double-escaping as this letter is frequently used.\n */\ngoog.string.DETECT_DOUBLE_ESCAPING =\n    goog.define('goog.string.DETECT_DOUBLE_ESCAPING', false);\n\n\n/**\n * @define {boolean} Whether to force non-dom html unescaping.\n */\ngoog.string.FORCE_NON_DOM_HTML_UNESCAPING =\n    goog.define('goog.string.FORCE_NON_DOM_HTML_UNESCAPING', false);\n\n\n/**\n * Common Unicode string characters.\n * @enum {string}\n */\ngoog.string.Unicode = {\n  NBSP: '\\xa0',\n  ZERO_WIDTH_SPACE: '\\u200b'  // This is equivalent to <wbr>.\n};\n\n\n/**\n * Fast prefix-checker.\n * @param {string} str The string to check.\n * @param {string} prefix A string to look for at the start of `str`.\n * @return {boolean} True if `str` begins with `prefix`.\n */\ngoog.string.startsWith = goog.string.internal.startsWith;\n\n\n/**\n * Fast suffix-checker.\n * @param {string} str The string to check.\n * @param {string} suffix A string to look for at the end of `str`.\n * @return {boolean} True if `str` ends with `suffix`.\n */\ngoog.string.endsWith = goog.string.internal.endsWith;\n\n\n/**\n * Case-insensitive prefix-checker.\n * @param {string} str The string to check.\n * @param {string} prefix  A string to look for at the end of `str`.\n * @return {boolean} True if `str` begins with `prefix` (ignoring\n *     case).\n */\ngoog.string.caseInsensitiveStartsWith =\n    goog.string.internal.caseInsensitiveStartsWith;\n\n\n/**\n * Case-insensitive suffix-checker.\n * @param {string} str The string to check.\n * @param {string} suffix A string to look for at the end of `str`.\n * @return {boolean} True if `str` ends with `suffix` (ignoring\n *     case).\n */\ngoog.string.caseInsensitiveEndsWith =\n    goog.string.internal.caseInsensitiveEndsWith;\n\n\n/**\n * Case-insensitive equality checker.\n * @param {string} str1 First string to check.\n * @param {string} str2 Second string to check.\n * @return {boolean} True if `str1` and `str2` are the same string,\n *     ignoring case.\n */\ngoog.string.caseInsensitiveEquals = goog.string.internal.caseInsensitiveEquals;\n\n\n/**\n * Does simple python-style string substitution.\n * subs(\"foo%s hot%s\", \"bar\", \"dog\") becomes \"foobar hotdog\".\n * @param {string} str The string containing the pattern.\n * @param {...*} var_args The items to substitute into the pattern.\n * @return {string} A copy of `str` in which each occurrence of\n *     {@code %s} has been replaced an argument from `var_args`.\n */\ngoog.string.subs = function(str, var_args) {\n  'use strict';\n  const splitParts = str.split('%s');\n  let returnString = '';\n\n  const subsArguments = Array.prototype.slice.call(arguments, 1);\n  while (subsArguments.length &&\n         // Replace up to the last split part. We are inserting in the\n         // positions between split parts.\n         splitParts.length > 1) {\n    returnString += splitParts.shift() + subsArguments.shift();\n  }\n\n  return returnString + splitParts.join('%s');  // Join unused '%s'\n};\n\n\n/**\n * Converts multiple whitespace chars (spaces, non-breaking-spaces, new lines\n * and tabs) to a single space, and strips leading and trailing whitespace.\n * @param {string} str Input string.\n * @return {string} A copy of `str` with collapsed whitespace.\n */\ngoog.string.collapseWhitespace = function(str) {\n  'use strict';\n  // Since IE doesn't include non-breaking-space (0xa0) in their \\s character\n  // class (as required by section 7.2 of the ECMAScript spec), we explicitly\n  // include it in the regexp to enforce consistent cross-browser behavior.\n  return str.replace(/[\\s\\xa0]+/g, ' ').replace(/^\\s+|\\s+$/g, '');\n};\n\n\n/**\n * Checks if a string is empty or contains only whitespaces.\n * @param {string} str The string to check.\n * @return {boolean} Whether `str` is empty or whitespace only.\n */\ngoog.string.isEmptyOrWhitespace = goog.string.internal.isEmptyOrWhitespace;\n\n\n/**\n * Checks if a string is empty.\n * @param {string} str The string to check.\n * @return {boolean} Whether `str` is empty.\n */\ngoog.string.isEmptyString = function(str) {\n  'use strict';\n  return str.length == 0;\n};\n\n\n/**\n * Checks if a string is empty or contains only whitespaces.\n *\n * @param {string} str The string to check.\n * @return {boolean} Whether `str` is empty or whitespace only.\n * @deprecated Use goog.string.isEmptyOrWhitespace instead.\n */\ngoog.string.isEmpty = goog.string.isEmptyOrWhitespace;\n\n\n/**\n * Checks if a string is null, undefined, empty or contains only whitespaces.\n * @param {*} str The string to check.\n * @return {boolean} Whether `str` is null, undefined, empty, or\n *     whitespace only.\n * @deprecated Use goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str))\n *     instead.\n */\ngoog.string.isEmptyOrWhitespaceSafe = function(str) {\n  'use strict';\n  return goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str));\n};\n\n\n/**\n * Checks if a string is null, undefined, empty or contains only whitespaces.\n *\n * @param {*} str The string to check.\n * @return {boolean} Whether `str` is null, undefined, empty, or\n *     whitespace only.\n * @deprecated Use goog.string.isEmptyOrWhitespace instead.\n */\ngoog.string.isEmptySafe = goog.string.isEmptyOrWhitespaceSafe;\n\n\n/**\n * Checks if a string is all breaking whitespace.\n * @param {string} str The string to check.\n * @return {boolean} Whether the string is all breaking whitespace.\n */\ngoog.string.isBreakingWhitespace = function(str) {\n  'use strict';\n  return !/[^\\t\\n\\r ]/.test(str);\n};\n\n\n/**\n * Checks if a string contains all letters.\n * @param {string} str string to check.\n * @return {boolean} True if `str` consists entirely of letters.\n */\ngoog.string.isAlpha = function(str) {\n  'use strict';\n  return !/[^a-zA-Z]/.test(str);\n};\n\n\n/**\n * Checks if a string contains only numbers.\n * @param {*} str string to check. If not a string, it will be\n *     casted to one.\n * @return {boolean} True if `str` is numeric.\n */\ngoog.string.isNumeric = function(str) {\n  'use strict';\n  return !/[^0-9]/.test(str);\n};\n\n\n/**\n * Checks if a string contains only numbers or letters.\n * @param {string} str string to check.\n * @return {boolean} True if `str` is alphanumeric.\n */\ngoog.string.isAlphaNumeric = function(str) {\n  'use strict';\n  return !/[^a-zA-Z0-9]/.test(str);\n};\n\n\n/**\n * Checks if a character is a space character.\n * @param {string} ch Character to check.\n * @return {boolean} True if `ch` is a space.\n */\ngoog.string.isSpace = function(ch) {\n  'use strict';\n  return ch == ' ';\n};\n\n\n/**\n * Checks if a character is a valid unicode character.\n * @param {string} ch Character to check.\n * @return {boolean} True if `ch` is a valid unicode character.\n */\ngoog.string.isUnicodeChar = function(ch) {\n  'use strict';\n  return ch.length == 1 && ch >= ' ' && ch <= '~' ||\n      ch >= '\\u0080' && ch <= '\\uFFFD';\n};\n\n\n/**\n * Takes a string and replaces newlines with a space. Multiple lines are\n * replaced with a single space.\n * @param {string} str The string from which to strip newlines.\n * @return {string} A copy of `str` stripped of newlines.\n */\ngoog.string.stripNewlines = function(str) {\n  'use strict';\n  return str.replace(/(\\r\\n|\\r|\\n)+/g, ' ');\n};\n\n\n/**\n * Replaces Windows and Mac new lines with unix style: \\r or \\r\\n with \\n.\n * @param {string} str The string to in which to canonicalize newlines.\n * @return {string} `str` A copy of {@code} with canonicalized newlines.\n */\ngoog.string.canonicalizeNewlines = function(str) {\n  'use strict';\n  return str.replace(/(\\r\\n|\\r|\\n)/g, '\\n');\n};\n\n\n/**\n * Normalizes whitespace in a string, replacing all whitespace chars with\n * a space.\n * @param {string} str The string in which to normalize whitespace.\n * @return {string} A copy of `str` with all whitespace normalized.\n */\ngoog.string.normalizeWhitespace = function(str) {\n  'use strict';\n  return str.replace(/\\xa0|\\s/g, ' ');\n};\n\n\n/**\n * Normalizes spaces in a string, replacing all consecutive spaces and tabs\n * with a single space. Replaces non-breaking space with a space.\n * @param {string} str The string in which to normalize spaces.\n * @return {string} A copy of `str` with all consecutive spaces and tabs\n *    replaced with a single space.\n */\ngoog.string.normalizeSpaces = function(str) {\n  'use strict';\n  return str.replace(/\\xa0|[ \\t]+/g, ' ');\n};\n\n\n/**\n * Removes the breaking spaces from the left and right of the string and\n * collapses the sequences of breaking spaces in the middle into single spaces.\n * The original and the result strings render the same way in HTML.\n * @param {string} str A string in which to collapse spaces.\n * @return {string} Copy of the string with normalized breaking spaces.\n */\ngoog.string.collapseBreakingSpaces = function(str) {\n  'use strict';\n  return str.replace(/[\\t\\r\\n ]+/g, ' ')\n      .replace(/^[\\t\\r\\n ]+|[\\t\\r\\n ]+$/g, '');\n};\n\n\n/**\n * Trims white spaces to the left and right of a string.\n * @param {string} str The string to trim.\n * @return {string} A trimmed copy of `str`.\n */\ngoog.string.trim = goog.string.internal.trim;\n\n\n/**\n * Trims whitespaces at the left end of a string.\n * @param {string} str The string to left trim.\n * @return {string} A trimmed copy of `str`.\n */\ngoog.string.trimLeft = function(str) {\n  'use strict';\n  // Since IE doesn't include non-breaking-space (0xa0) in their \\s character\n  // class (as required by section 7.2 of the ECMAScript spec), we explicitly\n  // include it in the regexp to enforce consistent cross-browser behavior.\n  return str.replace(/^[\\s\\xa0]+/, '');\n};\n\n\n/**\n * Trims whitespaces at the right end of a string.\n * @param {string} str The string to right trim.\n * @return {string} A trimmed copy of `str`.\n */\ngoog.string.trimRight = function(str) {\n  'use strict';\n  // Since IE doesn't include non-breaking-space (0xa0) in their \\s character\n  // class (as required by section 7.2 of the ECMAScript spec), we explicitly\n  // include it in the regexp to enforce consistent cross-browser behavior.\n  return str.replace(/[\\s\\xa0]+$/, '');\n};\n\n\n/**\n * A string comparator that ignores case.\n * -1 = str1 less than str2\n *  0 = str1 equals str2\n *  1 = str1 greater than str2\n *\n * @param {string} str1 The string to compare.\n * @param {string} str2 The string to compare `str1` to.\n * @return {number} The comparator result, as described above.\n */\ngoog.string.caseInsensitiveCompare =\n    goog.string.internal.caseInsensitiveCompare;\n\n\n/**\n * Compares two strings interpreting their numeric substrings as numbers.\n *\n * @param {string} str1 First string.\n * @param {string} str2 Second string.\n * @param {!RegExp} tokenizerRegExp Splits a string into substrings of\n *     non-negative integers, non-numeric characters and optionally fractional\n *     numbers starting with a decimal point.\n * @return {number} Negative if str1 < str2, 0 is str1 == str2, positive if\n *     str1 > str2.\n * @private\n */\ngoog.string.numberAwareCompare_ = function(str1, str2, tokenizerRegExp) {\n  'use strict';\n  if (str1 == str2) {\n    return 0;\n  }\n  if (!str1) {\n    return -1;\n  }\n  if (!str2) {\n    return 1;\n  }\n\n  // Using match to split the entire string ahead of time turns out to be faster\n  // for most inputs than using RegExp.exec or iterating over each character.\n  const tokens1 = str1.toLowerCase().match(tokenizerRegExp);\n  const tokens2 = str2.toLowerCase().match(tokenizerRegExp);\n\n  const count = Math.min(tokens1.length, tokens2.length);\n\n  for (let i = 0; i < count; i++) {\n    const a = tokens1[i];\n    const b = tokens2[i];\n\n    // Compare pairs of tokens, returning if one token sorts before the other.\n    if (a != b) {\n      // Only if both tokens are integers is a special comparison required.\n      // Decimal numbers are sorted as strings (e.g., '.09' < '.1').\n      const num1 = parseInt(a, 10);\n      if (!isNaN(num1)) {\n        const num2 = parseInt(b, 10);\n        if (!isNaN(num2) && num1 - num2) {\n          return num1 - num2;\n        }\n      }\n      return a < b ? -1 : 1;\n    }\n  }\n\n  // If one string is a substring of the other, the shorter string sorts first.\n  if (tokens1.length != tokens2.length) {\n    return tokens1.length - tokens2.length;\n  }\n\n  // The two strings must be equivalent except for case (perfect equality is\n  // tested at the head of the function.) Revert to default ASCII string\n  // comparison to stabilize the sort.\n  return str1 < str2 ? -1 : 1;\n};\n\n\n/**\n * String comparison function that handles non-negative integer numbers in a\n * way humans might expect. Using this function, the string 'File 2.jpg' sorts\n * before 'File 10.jpg', and 'Version 1.9' before 'Version 1.10'. The comparison\n * is mostly case-insensitive, though strings that are identical except for case\n * are sorted with the upper-case strings before lower-case.\n *\n * This comparison function is up to 50x slower than either the default or the\n * case-insensitive compare. It should not be used in time-critical code, but\n * should be fast enough to sort several hundred short strings (like filenames)\n * with a reasonable delay.\n *\n * @param {string} str1 The string to compare in a numerically sensitive way.\n * @param {string} str2 The string to compare `str1` to.\n * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than\n *     0 if str1 > str2.\n */\ngoog.string.intAwareCompare = function(str1, str2) {\n  'use strict';\n  return goog.string.numberAwareCompare_(str1, str2, /\\d+|\\D+/g);\n};\n\n\n/**\n * String comparison function that handles non-negative integer and fractional\n * numbers in a way humans might expect. Using this function, the string\n * 'File 2.jpg' sorts before 'File 10.jpg', and '3.14' before '3.2'. Equivalent\n * to {@link goog.string.intAwareCompare} apart from the way how it interprets\n * dots.\n *\n * @param {string} str1 The string to compare in a numerically sensitive way.\n * @param {string} str2 The string to compare `str1` to.\n * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than\n *     0 if str1 > str2.\n */\ngoog.string.floatAwareCompare = function(str1, str2) {\n  'use strict';\n  return goog.string.numberAwareCompare_(str1, str2, /\\d+|\\.\\d+|\\D+/g);\n};\n\n\n/**\n * Alias for {@link goog.string.floatAwareCompare}.\n *\n * @param {string} str1\n * @param {string} str2\n * @return {number}\n */\ngoog.string.numerateCompare = goog.string.floatAwareCompare;\n\n\n/**\n * URL-encodes a string\n * @param {*} str The string to url-encode.\n * @return {string} An encoded copy of `str` that is safe for urls.\n *     Note that '#', ':', and other characters used to delimit portions\n *     of URLs *will* be encoded.\n */\ngoog.string.urlEncode = function(str) {\n  'use strict';\n  return encodeURIComponent(String(str));\n};\n\n\n/**\n * URL-decodes the string. We need to specially handle '+'s because\n * the javascript library doesn't convert them to spaces.\n * @param {string} str The string to url decode.\n * @return {string} The decoded `str`.\n */\ngoog.string.urlDecode = function(str) {\n  'use strict';\n  return decodeURIComponent(str.replace(/\\+/g, ' '));\n};\n\n\n/**\n * Converts \\n to <br>s or <br />s.\n * @param {string} str The string in which to convert newlines.\n * @param {boolean=} opt_xml Whether to use XML compatible tags.\n * @return {string} A copy of `str` with converted newlines.\n */\ngoog.string.newLineToBr = goog.string.internal.newLineToBr;\n\n\n/**\n * Escapes double quote '\"' and single quote '\\'' characters in addition to\n * '&', '<', and '>' so that a string can be included in an HTML tag attribute\n * value within double or single quotes.\n *\n * It should be noted that > doesn't need to be escaped for the HTML or XML to\n * be valid, but it has been decided to escape it for consistency with other\n * implementations.\n *\n * With goog.string.DETECT_DOUBLE_ESCAPING, this function escapes also the\n * lowercase letter \"e\".\n *\n * NOTE(user):\n * HtmlEscape is often called during the generation of large blocks of HTML.\n * Using statics for the regular expressions and strings is an optimization\n * that can more than half the amount of time IE spends in this function for\n * large apps, since strings and regexes both contribute to GC allocations.\n *\n * Testing for the presence of a character before escaping increases the number\n * of function calls, but actually provides a speed increase for the average\n * case -- since the average case often doesn't require the escaping of all 4\n * characters and indexOf() is much cheaper than replace().\n * The worst case does suffer slightly from the additional calls, therefore the\n * opt_isLikelyToContainHtmlChars option has been included for situations\n * where all 4 HTML entities are very likely to be present and need escaping.\n *\n * Some benchmarks (times tended to fluctuate +-0.05ms):\n *                                     FireFox                     IE6\n * (no chars / average (mix of cases) / all 4 chars)\n * no checks                     0.13 / 0.22 / 0.22         0.23 / 0.53 / 0.80\n * indexOf                       0.08 / 0.17 / 0.26         0.22 / 0.54 / 0.84\n * indexOf + re test             0.07 / 0.17 / 0.28         0.19 / 0.50 / 0.85\n *\n * An additional advantage of checking if replace actually needs to be called\n * is a reduction in the number of object allocations, so as the size of the\n * application grows the difference between the various methods would increase.\n *\n * @param {string} str string to be escaped.\n * @param {boolean=} opt_isLikelyToContainHtmlChars Don't perform a check to see\n *     if the character needs replacing - use this option if you expect each of\n *     the characters to appear often. Leave false if you expect few html\n *     characters to occur in your strings, such as if you are escaping HTML.\n * @return {string} An escaped copy of `str`.\n */\ngoog.string.htmlEscape = function(str, opt_isLikelyToContainHtmlChars) {\n  'use strict';\n  str = goog.string.internal.htmlEscape(str, opt_isLikelyToContainHtmlChars);\n  if (goog.string.DETECT_DOUBLE_ESCAPING) {\n    str = str.replace(goog.string.E_RE_, '&#101;');\n  }\n  return str;\n};\n\n\n/**\n * Regular expression that matches a lowercase letter \"e\", for use in escaping.\n * @const {!RegExp}\n * @private\n */\ngoog.string.E_RE_ = /e/g;\n\n\n/**\n * Unescapes an HTML string.\n *\n * @param {string} str The string to unescape.\n * @return {string} An unescaped copy of `str`.\n */\ngoog.string.unescapeEntities = function(str) {\n  'use strict';\n  if (goog.string.contains(str, '&')) {\n    // We are careful not to use a DOM if we do not have one or we explicitly\n    // requested non-DOM html unescaping.\n    if (!goog.string.FORCE_NON_DOM_HTML_UNESCAPING &&\n        'document' in goog.global) {\n      return goog.string.unescapeEntitiesUsingDom_(str);\n    } else {\n      // Fall back on pure XML entities\n      return goog.string.unescapePureXmlEntities_(str);\n    }\n  }\n  return str;\n};\n\n\n/**\n * Unescapes a HTML string using the provided document.\n *\n * @param {string} str The string to unescape.\n * @param {!Document} document A document to use in escaping the string.\n * @return {string} An unescaped copy of `str`.\n */\ngoog.string.unescapeEntitiesWithDocument = function(str, document) {\n  'use strict';\n  if (goog.string.contains(str, '&')) {\n    return goog.string.unescapeEntitiesUsingDom_(str, document);\n  }\n  return str;\n};\n\n\n/**\n * Unescapes an HTML string using a DOM to resolve non-XML, non-numeric\n * entities. This function is XSS-safe and whitespace-preserving.\n * @private\n * @param {string} str The string to unescape.\n * @param {Document=} opt_document An optional document to use for creating\n *     elements. If this is not specified then the default window.document\n *     will be used.\n * @return {string} The unescaped `str` string.\n */\ngoog.string.unescapeEntitiesUsingDom_ = function(str, opt_document) {\n  'use strict';\n  /** @type {!Object<string, string>} */\n  const seen = {'&amp;': '&', '&lt;': '<', '&gt;': '>', '&quot;': '\"'};\n  /** @type {!Element} */\n  let div;\n  if (opt_document) {\n    div = opt_document.createElement('div');\n  } else {\n    div = goog.global.document.createElement('div');\n  }\n  // Match as many valid entity characters as possible. If the actual entity\n  // happens to be shorter, it will still work as innerHTML will return the\n  // trailing characters unchanged. Since the entity characters do not include\n  // open angle bracket, there is no chance of XSS from the innerHTML use.\n  // Since no whitespace is passed to innerHTML, whitespace is preserved.\n  return str.replace(goog.string.HTML_ENTITY_PATTERN_, function(s, entity) {\n    'use strict';\n    // Check for cached entity.\n    let value = seen[s];\n    if (value) {\n      return value;\n    }\n    // Check for numeric entity.\n    if (entity.charAt(0) == '#') {\n      // Prefix with 0 so that hex entities (e.g. &#x10) parse as hex numbers.\n      const n = Number('0' + entity.slice(1));\n      if (!isNaN(n)) {\n        value = String.fromCharCode(n);\n      }\n    }\n    // Fall back to innerHTML otherwise.\n    if (!value) {\n      // Append a non-entity character to avoid a bug in Webkit that parses\n      // an invalid entity at the end of innerHTML text as the empty string.\n      goog.dom.safe.setInnerHtml(\n          div,\n          goog.html.uncheckedconversions\n              .safeHtmlFromStringKnownToSatisfyTypeContract(\n                  goog.string.Const.from('Single HTML entity.'), s + ' '));\n      // Then remove the trailing character from the result.\n      value = div.firstChild.nodeValue.slice(0, -1);\n    }\n    // Cache and return.\n    return seen[s] = value;\n  });\n};\n\n\n/**\n * Unescapes XML entities.\n * @private\n * @param {string} str The string to unescape.\n * @return {string} An unescaped copy of `str`.\n */\ngoog.string.unescapePureXmlEntities_ = function(str) {\n  'use strict';\n  return str.replace(/&([^;]+);/g, function(s, entity) {\n    'use strict';\n    switch (entity) {\n      case 'amp':\n        return '&';\n      case 'lt':\n        return '<';\n      case 'gt':\n        return '>';\n      case 'quot':\n        return '\"';\n      default:\n        if (entity.charAt(0) == '#') {\n          // Prefix with 0 so that hex entities (e.g. &#x10) parse as hex.\n          const n = Number('0' + entity.slice(1));\n          if (!isNaN(n)) {\n            return String.fromCharCode(n);\n          }\n        }\n        // For invalid entities we just return the entity\n        return s;\n    }\n  });\n};\n\n\n/**\n * Regular expression that matches an HTML entity.\n * See also HTML5: Tokenization / Tokenizing character references.\n * @private\n * @type {!RegExp}\n */\ngoog.string.HTML_ENTITY_PATTERN_ = /&([^;\\s<&]+);?/g;\n\n\n/**\n * Do escaping of whitespace to preserve spatial formatting. We use character\n * entity #160 to make it safer for xml.\n * @param {string} str The string in which to escape whitespace.\n * @param {boolean=} opt_xml Whether to use XML compatible tags.\n * @return {string} An escaped copy of `str`.\n */\ngoog.string.whitespaceEscape = function(str, opt_xml) {\n  'use strict';\n  // This doesn't use goog.string.preserveSpaces for backwards compatibility.\n  return goog.string.newLineToBr(str.replace(/  /g, ' &#160;'), opt_xml);\n};\n\n\n/**\n * Preserve spaces that would be otherwise collapsed in HTML by replacing them\n * with non-breaking space Unicode characters.\n * @param {string} str The string in which to preserve whitespace.\n * @return {string} A copy of `str` with preserved whitespace.\n */\ngoog.string.preserveSpaces = function(str) {\n  'use strict';\n  return str.replace(/(^|[\\n ]) /g, '$1' + goog.string.Unicode.NBSP);\n};\n\n\n/**\n * Strip quote characters around a string.  The second argument is a string of\n * characters to treat as quotes.  This can be a single character or a string of\n * multiple character and in that case each of those are treated as possible\n * quote characters. For example:\n *\n * <pre>\n * goog.string.stripQuotes('\"abc\"', '\"`') --> 'abc'\n * goog.string.stripQuotes('`abc`', '\"`') --> 'abc'\n * </pre>\n *\n * @param {string} str The string to strip.\n * @param {string} quoteChars The quote characters to strip.\n * @return {string} A copy of `str` without the quotes.\n */\ngoog.string.stripQuotes = function(str, quoteChars) {\n  'use strict';\n  const length = quoteChars.length;\n  for (let i = 0; i < length; i++) {\n    const quoteChar = length == 1 ? quoteChars : quoteChars.charAt(i);\n    if (str.charAt(0) == quoteChar && str.charAt(str.length - 1) == quoteChar) {\n      return str.substring(1, str.length - 1);\n    }\n  }\n  return str;\n};\n\n\n/**\n * Truncates a string to a certain length and adds '...' if necessary.  The\n * length also accounts for the ellipsis, so a maximum length of 10 and a string\n * 'Hello World!' produces 'Hello W...'.\n * @param {string} str The string to truncate.\n * @param {number} chars Max number of characters.\n * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped\n *     characters from being cut off in the middle.\n * @return {string} The truncated `str` string.\n */\ngoog.string.truncate = function(str, chars, opt_protectEscapedCharacters) {\n  'use strict';\n  if (opt_protectEscapedCharacters) {\n    str = goog.string.unescapeEntities(str);\n  }\n\n  if (str.length > chars) {\n    str = str.substring(0, chars - 3) + '...';\n  }\n\n  if (opt_protectEscapedCharacters) {\n    str = goog.string.htmlEscape(str);\n  }\n\n  return str;\n};\n\n\n/**\n * Truncate a string in the middle, adding \"...\" if necessary,\n * and favoring the beginning of the string.\n * @param {string} str The string to truncate the middle of.\n * @param {number} chars Max number of characters.\n * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped\n *     characters from being cutoff in the middle.\n * @param {number=} opt_trailingChars Optional number of trailing characters to\n *     leave at the end of the string, instead of truncating as close to the\n *     middle as possible.\n * @return {string} A truncated copy of `str`.\n */\ngoog.string.truncateMiddle = function(\n    str, chars, opt_protectEscapedCharacters, opt_trailingChars) {\n  'use strict';\n  if (opt_protectEscapedCharacters) {\n    str = goog.string.unescapeEntities(str);\n  }\n\n  if (opt_trailingChars && str.length > chars) {\n    if (opt_trailingChars > chars) {\n      opt_trailingChars = chars;\n    }\n    const endPoint = str.length - opt_trailingChars;\n    const startPoint = chars - opt_trailingChars;\n    str = str.substring(0, startPoint) + '...' + str.substring(endPoint);\n  } else if (str.length > chars) {\n    // Favor the beginning of the string:\n    let half = Math.floor(chars / 2);\n    const endPos = str.length - half;\n    half += chars % 2;\n    str = str.substring(0, half) + '...' + str.substring(endPos);\n  }\n\n  if (opt_protectEscapedCharacters) {\n    str = goog.string.htmlEscape(str);\n  }\n\n  return str;\n};\n\n\n/**\n * Special chars that need to be escaped for goog.string.quote.\n * @private {!Object<string, string>}\n */\ngoog.string.specialEscapeChars_ = {\n  '\\0': '\\\\0',\n  '\\b': '\\\\b',\n  '\\f': '\\\\f',\n  '\\n': '\\\\n',\n  '\\r': '\\\\r',\n  '\\t': '\\\\t',\n  '\\x0B': '\\\\x0B',  // '\\v' is not supported in JScript\n  '\"': '\\\\\"',\n  '\\\\': '\\\\\\\\',\n  // To support the use case of embedding quoted strings inside of script\n  // tags, we have to make sure HTML comments and opening/closing script tags do\n  // not appear in the resulting string. The specific strings that must be\n  // escaped are documented at:\n  // https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements\n  '<': '\\\\u003C'  // NOTE: JSON.parse crashes on '\\\\x3c'.\n};\n\n\n/**\n * Character mappings used internally for goog.string.escapeChar.\n * @private {!Object<string, string>}\n */\ngoog.string.jsEscapeCache_ = {\n  '\\'': '\\\\\\''\n};\n\n\n/**\n * Encloses a string in double quotes and escapes characters so that the\n * string is a valid JS string. The resulting string is safe to embed in\n * `<script>` tags as \"<\" is escaped.\n * @param {string} s The string to quote.\n * @return {string} A copy of `s` surrounded by double quotes.\n */\ngoog.string.quote = function(s) {\n  'use strict';\n  s = String(s);\n  const sb = ['\"'];\n  for (let i = 0; i < s.length; i++) {\n    const ch = s.charAt(i);\n    const cc = ch.charCodeAt(0);\n    sb[i + 1] = goog.string.specialEscapeChars_[ch] ||\n        ((cc > 31 && cc < 127) ? ch : goog.string.escapeChar(ch));\n  }\n  sb.push('\"');\n  return sb.join('');\n};\n\n\n/**\n * Takes a string and returns the escaped string for that input string.\n * @param {string} str The string to escape.\n * @return {string} An escaped string representing `str`.\n */\ngoog.string.escapeString = function(str) {\n  'use strict';\n  const sb = [];\n  for (let i = 0; i < str.length; i++) {\n    sb[i] = goog.string.escapeChar(str.charAt(i));\n  }\n  return sb.join('');\n};\n\n\n/**\n * Takes a character and returns the escaped string for that character. For\n * example escapeChar(String.fromCharCode(15)) -> \"\\\\x0E\".\n * @param {string} c The character to escape.\n * @return {string} An escaped string representing `c`.\n */\ngoog.string.escapeChar = function(c) {\n  'use strict';\n  if (c in goog.string.jsEscapeCache_) {\n    return goog.string.jsEscapeCache_[c];\n  }\n\n  if (c in goog.string.specialEscapeChars_) {\n    return goog.string.jsEscapeCache_[c] = goog.string.specialEscapeChars_[c];\n  }\n\n  let rv = c;\n  const cc = c.charCodeAt(0);\n  if (cc > 31 && cc < 127) {\n    rv = c;\n  } else {\n    // tab is 9 but handled above\n    if (cc < 256) {\n      rv = '\\\\x';\n      if (cc < 16 || cc > 256) {\n        rv += '0';\n      }\n    } else {\n      rv = '\\\\u';\n      if (cc < 4096) {  // \\u1000\n        rv += '0';\n      }\n    }\n    rv += cc.toString(16).toUpperCase();\n  }\n\n  return goog.string.jsEscapeCache_[c] = rv;\n};\n\n\n/**\n * Determines whether a string contains a substring.\n * @param {string} str The string to search.\n * @param {string} subString The substring to search for.\n * @return {boolean} Whether `str` contains `subString`.\n */\ngoog.string.contains = goog.string.internal.contains;\n\n\n/**\n * Determines whether a string contains a substring, ignoring case.\n * @param {string} str The string to search.\n * @param {string} subString The substring to search for.\n * @return {boolean} Whether `str` contains `subString`.\n */\ngoog.string.caseInsensitiveContains =\n    goog.string.internal.caseInsensitiveContains;\n\n\n/**\n * Returns the non-overlapping occurrences of ss in s.\n * If either s or ss evalutes to false, then returns zero.\n * @param {string} s The string to look in.\n * @param {string} ss The string to look for.\n * @return {number} Number of occurrences of ss in s.\n */\ngoog.string.countOf = function(s, ss) {\n  'use strict';\n  return s && ss ? s.split(ss).length - 1 : 0;\n};\n\n\n/**\n * Removes a substring of a specified length at a specific\n * index in a string.\n * @param {string} s The base string from which to remove.\n * @param {number} index The index at which to remove the substring.\n * @param {number} stringLength The length of the substring to remove.\n * @return {string} A copy of `s` with the substring removed or the full\n *     string if nothing is removed or the input is invalid.\n */\ngoog.string.removeAt = function(s, index, stringLength) {\n  'use strict';\n  let resultStr = s;\n  // If the index is greater or equal to 0 then remove substring\n  if (index >= 0 && index < s.length && stringLength > 0) {\n    resultStr = s.slice(0, index) + s.slice(index + stringLength);\n  }\n  return resultStr;\n};\n\n\n/**\n * Removes the first occurrence of a substring from a string.\n * @param {string} str The base string from which to remove.\n * @param {string} substr The string to remove.\n * @return {string} A copy of `str` with `substr` removed or the\n *     full string if nothing is removed.\n */\ngoog.string.remove = function(str, substr) {\n  'use strict';\n  return str.replace(substr, '');\n};\n\n\n/**\n *  Removes all occurrences of a substring from a string.\n *  @param {string} s The base string from which to remove.\n *  @param {string} ss The string to remove.\n *  @return {string} A copy of `s` with `ss` removed or the full\n *      string if nothing is removed.\n */\ngoog.string.removeAll = function(s, ss) {\n  'use strict';\n  const re = new RegExp(goog.string.regExpEscape(ss), 'g');\n  return s.replace(re, '');\n};\n\n\n/**\n *  Replaces all occurrences of a substring of a string with a new substring.\n *  @param {string} s The base string from which to remove.\n *  @param {string} ss The string to replace.\n *  @param {string} replacement The replacement string.\n *  @return {string} A copy of `s` with `ss` replaced by\n *      `replacement` or the original string if nothing is replaced.\n */\ngoog.string.replaceAll = function(s, ss, replacement) {\n  'use strict';\n  const re = new RegExp(goog.string.regExpEscape(ss), 'g');\n  return s.replace(re, replacement.replace(/\\$/g, '$$$$'));\n};\n\n\n/**\n * Escapes characters in the string that are not safe to use in a RegExp.\n * @param {*} s The string to escape. If not a string, it will be casted\n *     to one.\n * @return {string} A RegExp safe, escaped copy of `s`.\n */\ngoog.string.regExpEscape = function(s) {\n  'use strict';\n  return String(s)\n      .replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g, '\\\\$1')\n      .replace(/\\x08/g, '\\\\x08');\n};\n\n\n/**\n * Repeats a string n times.\n * @param {string} string The string to repeat.\n * @param {number} length The number of times to repeat.\n * @return {string} A string containing `length` repetitions of\n *     `string`.\n */\ngoog.string.repeat = (String.prototype.repeat) ? function(string, length) {\n  'use strict';\n  // The native method is over 100 times faster than the alternative.\n  return string.repeat(length);\n} : function(string, length) {\n  'use strict';\n  return new Array(length + 1).join(string);\n};\n\n\n/**\n * Pads number to given length and optionally rounds it to a given precision.\n * For example:\n * <pre>padNumber(1.25, 2, 3) -> '01.250'\n * padNumber(1.25, 2) -> '01.25'\n * padNumber(1.25, 2, 1) -> '01.3'\n * padNumber(1.25, 0) -> '1.25'</pre>\n *\n * @param {number} num The number to pad.\n * @param {number} length The desired length.\n * @param {number=} opt_precision The desired precision.\n * @return {string} `num` as a string with the given options.\n */\ngoog.string.padNumber = function(num, length, opt_precision) {\n  'use strict';\n  if (!Number.isFinite(num)) return String(num);\n  let s =\n      (opt_precision !== undefined) ? num.toFixed(opt_precision) : String(num);\n  let index = s.indexOf('.');\n  if (index === -1) {\n    index = s.length;\n  }\n  const sign = s[0] === '-' ? '-' : '';\n  if (sign) {\n    s = s.substring(1);\n  }\n  return sign + goog.string.repeat('0', Math.max(0, length - index)) + s;\n};\n\n\n/**\n * Returns a string representation of the given object, with\n * null and undefined being returned as the empty string.\n *\n * @param {*} obj The object to convert.\n * @return {string} A string representation of the `obj`.\n */\ngoog.string.makeSafe = function(obj) {\n  'use strict';\n  return obj == null ? '' : String(obj);\n};\n\n/**\n * Returns a string with at least 64-bits of randomness.\n *\n * Doesn't trust JavaScript's random function entirely. Uses a combination of\n * random and current timestamp, and then encodes the string in base-36 to\n * make it shorter.\n *\n * @return {string} A random string, e.g. sn1s7vb4gcic.\n */\ngoog.string.getRandomString = function() {\n  'use strict';\n  const x = 2147483648;\n  return Math.floor(Math.random() * x).toString(36) +\n      Math.abs(Math.floor(Math.random() * x) ^ goog.now()).toString(36);\n};\n\n\n/**\n * Compares two version numbers.\n *\n * @param {string|number} version1 Version of first item.\n * @param {string|number} version2 Version of second item.\n *\n * @return {number}  1 if `version1` is higher.\n *                   0 if arguments are equal.\n *                  -1 if `version2` is higher.\n */\ngoog.string.compareVersions = goog.string.internal.compareVersions;\n\n\n/**\n * String hash function similar to java.lang.String.hashCode().\n * The hash code for a string is computed as\n * s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],\n * where s[i] is the ith character of the string and n is the length of\n * the string. We mod the result to make it between 0 (inclusive) and 2^32\n * (exclusive).\n * @param {string} str A string.\n * @return {number} Hash value for `str`, between 0 (inclusive) and 2^32\n *  (exclusive). The empty string returns 0.\n */\ngoog.string.hashCode = function(str) {\n  'use strict';\n  let result = 0;\n  for (let i = 0; i < str.length; ++i) {\n    // Normalize to 4 byte range, 0 ... 2^32.\n    result = (31 * result + str.charCodeAt(i)) >>> 0;\n  }\n  return result;\n};\n\n\n/**\n * The most recent unique ID. |0 is equivalent to Math.floor in this case.\n * @type {number}\n * @private\n */\ngoog.string.uniqueStringCounter_ = Math.random() * 0x80000000 | 0;\n\n\n/**\n * Generates and returns a string which is unique in the current document.\n * This is useful, for example, to create unique IDs for DOM elements.\n * @return {string} A unique id.\n */\ngoog.string.createUniqueString = function() {\n  'use strict';\n  return 'goog_' + goog.string.uniqueStringCounter_++;\n};\n\n\n/**\n * Converts the supplied string to a number, which may be Infinity or NaN.\n * This function strips whitespace: (toNumber(' 123') === 123)\n * This function accepts scientific notation: (toNumber('1e1') === 10)\n *\n * This is better than JavaScript's built-in conversions because, sadly:\n *     (Number(' ') === 0) and (parseFloat('123a') === 123)\n *\n * @param {string} str The string to convert.\n * @return {number} The number the supplied string represents, or NaN.\n */\ngoog.string.toNumber = function(str) {\n  'use strict';\n  const num = Number(str);\n  if (num == 0 && goog.string.isEmptyOrWhitespace(str)) {\n    return NaN;\n  }\n  return num;\n};\n\n\n/**\n * Returns whether the given string is lower camel case (e.g. \"isFooBar\").\n *\n * Note that this assumes the string is entirely letters.\n * @see http://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms\n *\n * @param {string} str String to test.\n * @return {boolean} Whether the string is lower camel case.\n */\ngoog.string.isLowerCamelCase = function(str) {\n  'use strict';\n  return /^[a-z]+([A-Z][a-z]*)*$/.test(str);\n};\n\n\n/**\n * Returns whether the given string is upper camel case (e.g. \"FooBarBaz\").\n *\n * Note that this assumes the string is entirely letters.\n * @see http://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms\n *\n * @param {string} str String to test.\n * @return {boolean} Whether the string is upper camel case.\n */\ngoog.string.isUpperCamelCase = function(str) {\n  'use strict';\n  return /^([A-Z][a-z]*)+$/.test(str);\n};\n\n\n/**\n * Converts a string from selector-case to camelCase (e.g. from\n * \"multi-part-string\" to \"multiPartString\"), useful for converting\n * CSS selectors and HTML dataset keys to their equivalent JS properties.\n * @param {string} str The string in selector-case form.\n * @return {string} The string in camelCase form.\n */\ngoog.string.toCamelCase = function(str) {\n  'use strict';\n  return String(str).replace(/\\-([a-z])/g, function(all, match) {\n    'use strict';\n    return match.toUpperCase();\n  });\n};\n\n\n/**\n * Converts a string from camelCase to selector-case (e.g. from\n * \"multiPartString\" to \"multi-part-string\"), useful for converting JS\n * style and dataset properties to equivalent CSS selectors and HTML keys.\n * @param {string} str The string in camelCase form.\n * @return {string} The string in selector-case form.\n */\ngoog.string.toSelectorCase = function(str) {\n  'use strict';\n  return String(str).replace(/([A-Z])/g, '-$1').toLowerCase();\n};\n\n\n/**\n * Converts a string into TitleCase. First character of the string is always\n * capitalized in addition to the first letter of every subsequent word.\n * Words are delimited by one or more whitespaces by default. Custom delimiters\n * can optionally be specified to replace the default, which doesn't preserve\n * whitespace delimiters and instead must be explicitly included if needed.\n *\n * Default delimiter => \" \":\n *    goog.string.toTitleCase('oneTwoThree')    => 'OneTwoThree'\n *    goog.string.toTitleCase('one two three')  => 'One Two Three'\n *    goog.string.toTitleCase('  one   two   ') => '  One   Two   '\n *    goog.string.toTitleCase('one_two_three')  => 'One_two_three'\n *    goog.string.toTitleCase('one-two-three')  => 'One-two-three'\n *\n * Custom delimiter => \"_-.\":\n *    goog.string.toTitleCase('oneTwoThree', '_-.')       => 'OneTwoThree'\n *    goog.string.toTitleCase('one two three', '_-.')     => 'One two three'\n *    goog.string.toTitleCase('  one   two   ', '_-.')    => '  one   two   '\n *    goog.string.toTitleCase('one_two_three', '_-.')     => 'One_Two_Three'\n *    goog.string.toTitleCase('one-two-three', '_-.')     => 'One-Two-Three'\n *    goog.string.toTitleCase('one...two...three', '_-.') => 'One...Two...Three'\n *    goog.string.toTitleCase('one. two. three', '_-.')   => 'One. two. three'\n *    goog.string.toTitleCase('one-two.three', '_-.')     => 'One-Two.Three'\n *\n * @param {string} str String value in camelCase form.\n * @param {string=} opt_delimiters Custom delimiter character set used to\n *      distinguish words in the string value. Each character represents a\n *      single delimiter. When provided, default whitespace delimiter is\n *      overridden and must be explicitly included if needed.\n * @return {string} String value in TitleCase form.\n */\ngoog.string.toTitleCase = function(str, opt_delimiters) {\n  'use strict';\n  let delimiters = (typeof opt_delimiters === 'string') ?\n      goog.string.regExpEscape(opt_delimiters) :\n      '\\\\s';\n\n  // For IE8, we need to prevent using an empty character set. Otherwise,\n  // incorrect matching will occur.\n  delimiters = delimiters ? '|[' + delimiters + ']+' : '';\n\n  const regexp = new RegExp('(^' + delimiters + ')([a-z])', 'g');\n  return str.replace(regexp, function(all, p1, p2) {\n    'use strict';\n    return p1 + p2.toUpperCase();\n  });\n};\n\n\n/**\n * Capitalizes a string, i.e. converts the first letter to uppercase\n * and all other letters to lowercase, e.g.:\n *\n * goog.string.capitalize('one')     => 'One'\n * goog.string.capitalize('ONE')     => 'One'\n * goog.string.capitalize('one two') => 'One two'\n *\n * Note that this function does not trim initial whitespace.\n *\n * @param {string} str String value to capitalize.\n * @return {string} String value with first letter in uppercase.\n */\ngoog.string.capitalize = function(str) {\n  'use strict';\n  return String(str.charAt(0)).toUpperCase() +\n      String(str.slice(1)).toLowerCase();\n};\n\n\n/**\n * Parse a string in decimal or hexidecimal ('0xFFFF') form.\n *\n * To parse a particular radix, please use parseInt(string, radix) directly. See\n * https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/parseInt\n *\n * This is a wrapper for the built-in parseInt function that will only parse\n * numbers as base 10 or base 16.  Some JS implementations assume strings\n * starting with \"0\" are intended to be octal. ES3 allowed but discouraged\n * this behavior. ES5 forbids it.  This function emulates the ES5 behavior.\n *\n * For more information, see Mozilla JS Reference: http://goo.gl/8RiFj\n *\n * @param {string|number|null|undefined} value The value to be parsed.\n * @return {number} The number, parsed. If the string failed to parse, this\n *     will be NaN.\n */\ngoog.string.parseInt = function(value) {\n  'use strict';\n  // Force finite numbers to strings.\n  if (isFinite(value)) {\n    value = String(value);\n  }\n\n  if (typeof value === 'string') {\n    // If the string starts with '0x' or '-0x', parse as hex.\n    return /^\\s*-?0x/i.test(value) ? parseInt(value, 16) : parseInt(value, 10);\n  }\n\n  return NaN;\n};\n\n\n/**\n * Splits a string on a separator a limited number of times.\n *\n * This implementation is more similar to Python or Java, where the limit\n * parameter specifies the maximum number of splits rather than truncating\n * the number of results.\n *\n * See http://docs.python.org/2/library/stdtypes.html#str.split\n * See JavaDoc: http://goo.gl/F2AsY\n * See Mozilla reference: http://goo.gl/dZdZs\n *\n * @param {string} str String to split.\n * @param {string} separator The separator.\n * @param {number} limit The limit to the number of splits. The resulting array\n *     will have a maximum length of limit+1.  Negative numbers are the same\n *     as zero.\n * @return {!Array<string>} The string, split.\n */\ngoog.string.splitLimit = function(str, separator, limit) {\n  'use strict';\n  const parts = str.split(separator);\n  const returnVal = [];\n\n  // Only continue doing this while we haven't hit the limit and we have\n  // parts left.\n  while (limit > 0 && parts.length) {\n    returnVal.push(parts.shift());\n    limit--;\n  }\n\n  // If there are remaining parts, append them to the end.\n  if (parts.length) {\n    returnVal.push(parts.join(separator));\n  }\n\n  return returnVal;\n};\n\n\n/**\n * Finds the characters to the right of the last instance of any separator\n *\n * This function is similar to goog.string.path.baseName, except it can take a\n * list of characters to split the string on. It will return the rightmost\n * grouping of characters to the right of any separator as a left-to-right\n * oriented string.\n *\n * @see goog.string.path.baseName\n * @param {string} str The string\n * @param {string|!Array<string>} separators A list of separator characters\n * @return {string} The last part of the string with respect to the separators\n */\ngoog.string.lastComponent = function(str, separators) {\n  'use strict';\n  if (!separators) {\n    return str;\n  } else if (typeof separators == 'string') {\n    separators = [separators];\n  }\n\n  let lastSeparatorIndex = -1;\n  for (let i = 0; i < separators.length; i++) {\n    if (separators[i] == '') {\n      continue;\n    }\n    const currentSeparatorIndex = str.lastIndexOf(separators[i]);\n    if (currentSeparatorIndex > lastSeparatorIndex) {\n      lastSeparatorIndex = currentSeparatorIndex;\n    }\n  }\n  if (lastSeparatorIndex == -1) {\n    return str;\n  }\n  return str.slice(lastSeparatorIndex + 1);\n};\n\n\n/**\n * Computes the Levenshtein edit distance between two strings.\n * @param {string} a\n * @param {string} b\n * @return {number} The edit distance between the two strings.\n */\ngoog.string.editDistance = function(a, b) {\n  'use strict';\n  const v0 = [];\n  const v1 = [];\n\n  if (a == b) {\n    return 0;\n  }\n\n  if (!a.length || !b.length) {\n    return Math.max(a.length, b.length);\n  }\n\n  for (let i = 0; i < b.length + 1; i++) {\n    v0[i] = i;\n  }\n\n  for (let i = 0; i < a.length; i++) {\n    v1[0] = i + 1;\n\n    for (let j = 0; j < b.length; j++) {\n      const cost = Number(a[i] != b[j]);\n      // Cost for the substring is the minimum of adding one character, removing\n      // one character, or a swap.\n      v1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\n    }\n\n    for (let j = 0; j < v0.length; j++) {\n      v0[j] = v1[j];\n    }\n  }\n\n  return v1[b.length];\n};\n","~:compiled-at",1684858197928,"~:source-map-json","{\n\"version\":3,\n\"file\":\"goog.string.string.js\",\n\"lineCount\":456,\n\"mappings\":\"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\",\n\"sources\":[\"goog/string/string.js\"],\n\"sourcesContent\":[\"/**\\n * @license\\n * Copyright The Closure Library Authors.\\n * SPDX-License-Identifier: Apache-2.0\\n */\\n\\n/**\\n * @fileoverview Utilities for string manipulation.\\n */\\n\\n\\n/**\\n * Namespace for string utilities\\n */\\ngoog.provide('goog.string');\\ngoog.provide('goog.string.Unicode');\\n\\ngoog.require('goog.dom.safe');\\ngoog.require('goog.html.uncheckedconversions');\\ngoog.require('goog.string.Const');\\ngoog.require('goog.string.internal');\\n\\n\\n/**\\n * @define {boolean} Enables HTML escaping of lowercase letter \\\"e\\\" which helps\\n * with detection of double-escaping as this letter is frequently used.\\n */\\ngoog.string.DETECT_DOUBLE_ESCAPING =\\n    goog.define('goog.string.DETECT_DOUBLE_ESCAPING', false);\\n\\n\\n/**\\n * @define {boolean} Whether to force non-dom html unescaping.\\n */\\ngoog.string.FORCE_NON_DOM_HTML_UNESCAPING =\\n    goog.define('goog.string.FORCE_NON_DOM_HTML_UNESCAPING', false);\\n\\n\\n/**\\n * Common Unicode string characters.\\n * @enum {string}\\n */\\ngoog.string.Unicode = {\\n  NBSP: '\\\\xa0',\\n  ZERO_WIDTH_SPACE: '\\\\u200b'  // This is equivalent to <wbr>.\\n};\\n\\n\\n/**\\n * Fast prefix-checker.\\n * @param {string} str The string to check.\\n * @param {string} prefix A string to look for at the start of `str`.\\n * @return {boolean} True if `str` begins with `prefix`.\\n */\\ngoog.string.startsWith = goog.string.internal.startsWith;\\n\\n\\n/**\\n * Fast suffix-checker.\\n * @param {string} str The string to check.\\n * @param {string} suffix A string to look for at the end of `str`.\\n * @return {boolean} True if `str` ends with `suffix`.\\n */\\ngoog.string.endsWith = goog.string.internal.endsWith;\\n\\n\\n/**\\n * Case-insensitive prefix-checker.\\n * @param {string} str The string to check.\\n * @param {string} prefix  A string to look for at the end of `str`.\\n * @return {boolean} True if `str` begins with `prefix` (ignoring\\n *     case).\\n */\\ngoog.string.caseInsensitiveStartsWith =\\n    goog.string.internal.caseInsensitiveStartsWith;\\n\\n\\n/**\\n * Case-insensitive suffix-checker.\\n * @param {string} str The string to check.\\n * @param {string} suffix A string to look for at the end of `str`.\\n * @return {boolean} True if `str` ends with `suffix` (ignoring\\n *     case).\\n */\\ngoog.string.caseInsensitiveEndsWith =\\n    goog.string.internal.caseInsensitiveEndsWith;\\n\\n\\n/**\\n * Case-insensitive equality checker.\\n * @param {string} str1 First string to check.\\n * @param {string} str2 Second string to check.\\n * @return {boolean} True if `str1` and `str2` are the same string,\\n *     ignoring case.\\n */\\ngoog.string.caseInsensitiveEquals = goog.string.internal.caseInsensitiveEquals;\\n\\n\\n/**\\n * Does simple python-style string substitution.\\n * subs(\\\"foo%s hot%s\\\", \\\"bar\\\", \\\"dog\\\") becomes \\\"foobar hotdog\\\".\\n * @param {string} str The string containing the pattern.\\n * @param {...*} var_args The items to substitute into the pattern.\\n * @return {string} A copy of `str` in which each occurrence of\\n *     {@code %s} has been replaced an argument from `var_args`.\\n */\\ngoog.string.subs = function(str, var_args) {\\n  'use strict';\\n  const splitParts = str.split('%s');\\n  let returnString = '';\\n\\n  const subsArguments = Array.prototype.slice.call(arguments, 1);\\n  while (subsArguments.length &&\\n         // Replace up to the last split part. We are inserting in the\\n         // positions between split parts.\\n         splitParts.length > 1) {\\n    returnString += splitParts.shift() + subsArguments.shift();\\n  }\\n\\n  return returnString + splitParts.join('%s');  // Join unused '%s'\\n};\\n\\n\\n/**\\n * Converts multiple whitespace chars (spaces, non-breaking-spaces, new lines\\n * and tabs) to a single space, and strips leading and trailing whitespace.\\n * @param {string} str Input string.\\n * @return {string} A copy of `str` with collapsed whitespace.\\n */\\ngoog.string.collapseWhitespace = function(str) {\\n  'use strict';\\n  // Since IE doesn't include non-breaking-space (0xa0) in their \\\\s character\\n  // class (as required by section 7.2 of the ECMAScript spec), we explicitly\\n  // include it in the regexp to enforce consistent cross-browser behavior.\\n  return str.replace(/[\\\\s\\\\xa0]+/g, ' ').replace(/^\\\\s+|\\\\s+$/g, '');\\n};\\n\\n\\n/**\\n * Checks if a string is empty or contains only whitespaces.\\n * @param {string} str The string to check.\\n * @return {boolean} Whether `str` is empty or whitespace only.\\n */\\ngoog.string.isEmptyOrWhitespace = goog.string.internal.isEmptyOrWhitespace;\\n\\n\\n/**\\n * Checks if a string is empty.\\n * @param {string} str The string to check.\\n * @return {boolean} Whether `str` is empty.\\n */\\ngoog.string.isEmptyString = function(str) {\\n  'use strict';\\n  return str.length == 0;\\n};\\n\\n\\n/**\\n * Checks if a string is empty or contains only whitespaces.\\n *\\n * @param {string} str The string to check.\\n * @return {boolean} Whether `str` is empty or whitespace only.\\n * @deprecated Use goog.string.isEmptyOrWhitespace instead.\\n */\\ngoog.string.isEmpty = goog.string.isEmptyOrWhitespace;\\n\\n\\n/**\\n * Checks if a string is null, undefined, empty or contains only whitespaces.\\n * @param {*} str The string to check.\\n * @return {boolean} Whether `str` is null, undefined, empty, or\\n *     whitespace only.\\n * @deprecated Use goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str))\\n *     instead.\\n */\\ngoog.string.isEmptyOrWhitespaceSafe = function(str) {\\n  'use strict';\\n  return goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str));\\n};\\n\\n\\n/**\\n * Checks if a string is null, undefined, empty or contains only whitespaces.\\n *\\n * @param {*} str The string to check.\\n * @return {boolean} Whether `str` is null, undefined, empty, or\\n *     whitespace only.\\n * @deprecated Use goog.string.isEmptyOrWhitespace instead.\\n */\\ngoog.string.isEmptySafe = goog.string.isEmptyOrWhitespaceSafe;\\n\\n\\n/**\\n * Checks if a string is all breaking whitespace.\\n * @param {string} str The string to check.\\n * @return {boolean} Whether the string is all breaking whitespace.\\n */\\ngoog.string.isBreakingWhitespace = function(str) {\\n  'use strict';\\n  return !/[^\\\\t\\\\n\\\\r ]/.test(str);\\n};\\n\\n\\n/**\\n * Checks if a string contains all letters.\\n * @param {string} str string to check.\\n * @return {boolean} True if `str` consists entirely of letters.\\n */\\ngoog.string.isAlpha = function(str) {\\n  'use strict';\\n  return !/[^a-zA-Z]/.test(str);\\n};\\n\\n\\n/**\\n * Checks if a string contains only numbers.\\n * @param {*} str string to check. If not a string, it will be\\n *     casted to one.\\n * @return {boolean} True if `str` is numeric.\\n */\\ngoog.string.isNumeric = function(str) {\\n  'use strict';\\n  return !/[^0-9]/.test(str);\\n};\\n\\n\\n/**\\n * Checks if a string contains only numbers or letters.\\n * @param {string} str string to check.\\n * @return {boolean} True if `str` is alphanumeric.\\n */\\ngoog.string.isAlphaNumeric = function(str) {\\n  'use strict';\\n  return !/[^a-zA-Z0-9]/.test(str);\\n};\\n\\n\\n/**\\n * Checks if a character is a space character.\\n * @param {string} ch Character to check.\\n * @return {boolean} True if `ch` is a space.\\n */\\ngoog.string.isSpace = function(ch) {\\n  'use strict';\\n  return ch == ' ';\\n};\\n\\n\\n/**\\n * Checks if a character is a valid unicode character.\\n * @param {string} ch Character to check.\\n * @return {boolean} True if `ch` is a valid unicode character.\\n */\\ngoog.string.isUnicodeChar = function(ch) {\\n  'use strict';\\n  return ch.length == 1 && ch >= ' ' && ch <= '~' ||\\n      ch >= '\\\\u0080' && ch <= '\\\\uFFFD';\\n};\\n\\n\\n/**\\n * Takes a string and replaces newlines with a space. Multiple lines are\\n * replaced with a single space.\\n * @param {string} str The string from which to strip newlines.\\n * @return {string} A copy of `str` stripped of newlines.\\n */\\ngoog.string.stripNewlines = function(str) {\\n  'use strict';\\n  return str.replace(/(\\\\r\\\\n|\\\\r|\\\\n)+/g, ' ');\\n};\\n\\n\\n/**\\n * Replaces Windows and Mac new lines with unix style: \\\\r or \\\\r\\\\n with \\\\n.\\n * @param {string} str The string to in which to canonicalize newlines.\\n * @return {string} `str` A copy of {@code} with canonicalized newlines.\\n */\\ngoog.string.canonicalizeNewlines = function(str) {\\n  'use strict';\\n  return str.replace(/(\\\\r\\\\n|\\\\r|\\\\n)/g, '\\\\n');\\n};\\n\\n\\n/**\\n * Normalizes whitespace in a string, replacing all whitespace chars with\\n * a space.\\n * @param {string} str The string in which to normalize whitespace.\\n * @return {string} A copy of `str` with all whitespace normalized.\\n */\\ngoog.string.normalizeWhitespace = function(str) {\\n  'use strict';\\n  return str.replace(/\\\\xa0|\\\\s/g, ' ');\\n};\\n\\n\\n/**\\n * Normalizes spaces in a string, replacing all consecutive spaces and tabs\\n * with a single space. Replaces non-breaking space with a space.\\n * @param {string} str The string in which to normalize spaces.\\n * @return {string} A copy of `str` with all consecutive spaces and tabs\\n *    replaced with a single space.\\n */\\ngoog.string.normalizeSpaces = function(str) {\\n  'use strict';\\n  return str.replace(/\\\\xa0|[ \\\\t]+/g, ' ');\\n};\\n\\n\\n/**\\n * Removes the breaking spaces from the left and right of the string and\\n * collapses the sequences of breaking spaces in the middle into single spaces.\\n * The original and the result strings render the same way in HTML.\\n * @param {string} str A string in which to collapse spaces.\\n * @return {string} Copy of the string with normalized breaking spaces.\\n */\\ngoog.string.collapseBreakingSpaces = function(str) {\\n  'use strict';\\n  return str.replace(/[\\\\t\\\\r\\\\n ]+/g, ' ')\\n      .replace(/^[\\\\t\\\\r\\\\n ]+|[\\\\t\\\\r\\\\n ]+$/g, '');\\n};\\n\\n\\n/**\\n * Trims white spaces to the left and right of a string.\\n * @param {string} str The string to trim.\\n * @return {string} A trimmed copy of `str`.\\n */\\ngoog.string.trim = goog.string.internal.trim;\\n\\n\\n/**\\n * Trims whitespaces at the left end of a string.\\n * @param {string} str The string to left trim.\\n * @return {string} A trimmed copy of `str`.\\n */\\ngoog.string.trimLeft = function(str) {\\n  'use strict';\\n  // Since IE doesn't include non-breaking-space (0xa0) in their \\\\s character\\n  // class (as required by section 7.2 of the ECMAScript spec), we explicitly\\n  // include it in the regexp to enforce consistent cross-browser behavior.\\n  return str.replace(/^[\\\\s\\\\xa0]+/, '');\\n};\\n\\n\\n/**\\n * Trims whitespaces at the right end of a string.\\n * @param {string} str The string to right trim.\\n * @return {string} A trimmed copy of `str`.\\n */\\ngoog.string.trimRight = function(str) {\\n  'use strict';\\n  // Since IE doesn't include non-breaking-space (0xa0) in their \\\\s character\\n  // class (as required by section 7.2 of the ECMAScript spec), we explicitly\\n  // include it in the regexp to enforce consistent cross-browser behavior.\\n  return str.replace(/[\\\\s\\\\xa0]+$/, '');\\n};\\n\\n\\n/**\\n * A string comparator that ignores case.\\n * -1 = str1 less than str2\\n *  0 = str1 equals str2\\n *  1 = str1 greater than str2\\n *\\n * @param {string} str1 The string to compare.\\n * @param {string} str2 The string to compare `str1` to.\\n * @return {number} The comparator result, as described above.\\n */\\ngoog.string.caseInsensitiveCompare =\\n    goog.string.internal.caseInsensitiveCompare;\\n\\n\\n/**\\n * Compares two strings interpreting their numeric substrings as numbers.\\n *\\n * @param {string} str1 First string.\\n * @param {string} str2 Second string.\\n * @param {!RegExp} tokenizerRegExp Splits a string into substrings of\\n *     non-negative integers, non-numeric characters and optionally fractional\\n *     numbers starting with a decimal point.\\n * @return {number} Negative if str1 < str2, 0 is str1 == str2, positive if\\n *     str1 > str2.\\n * @private\\n */\\ngoog.string.numberAwareCompare_ = function(str1, str2, tokenizerRegExp) {\\n  'use strict';\\n  if (str1 == str2) {\\n    return 0;\\n  }\\n  if (!str1) {\\n    return -1;\\n  }\\n  if (!str2) {\\n    return 1;\\n  }\\n\\n  // Using match to split the entire string ahead of time turns out to be faster\\n  // for most inputs than using RegExp.exec or iterating over each character.\\n  const tokens1 = str1.toLowerCase().match(tokenizerRegExp);\\n  const tokens2 = str2.toLowerCase().match(tokenizerRegExp);\\n\\n  const count = Math.min(tokens1.length, tokens2.length);\\n\\n  for (let i = 0; i < count; i++) {\\n    const a = tokens1[i];\\n    const b = tokens2[i];\\n\\n    // Compare pairs of tokens, returning if one token sorts before the other.\\n    if (a != b) {\\n      // Only if both tokens are integers is a special comparison required.\\n      // Decimal numbers are sorted as strings (e.g., '.09' < '.1').\\n      const num1 = parseInt(a, 10);\\n      if (!isNaN(num1)) {\\n        const num2 = parseInt(b, 10);\\n        if (!isNaN(num2) && num1 - num2) {\\n          return num1 - num2;\\n        }\\n      }\\n      return a < b ? -1 : 1;\\n    }\\n  }\\n\\n  // If one string is a substring of the other, the shorter string sorts first.\\n  if (tokens1.length != tokens2.length) {\\n    return tokens1.length - tokens2.length;\\n  }\\n\\n  // The two strings must be equivalent except for case (perfect equality is\\n  // tested at the head of the function.) Revert to default ASCII string\\n  // comparison to stabilize the sort.\\n  return str1 < str2 ? -1 : 1;\\n};\\n\\n\\n/**\\n * String comparison function that handles non-negative integer numbers in a\\n * way humans might expect. Using this function, the string 'File 2.jpg' sorts\\n * before 'File 10.jpg', and 'Version 1.9' before 'Version 1.10'. The comparison\\n * is mostly case-insensitive, though strings that are identical except for case\\n * are sorted with the upper-case strings before lower-case.\\n *\\n * This comparison function is up to 50x slower than either the default or the\\n * case-insensitive compare. It should not be used in time-critical code, but\\n * should be fast enough to sort several hundred short strings (like filenames)\\n * with a reasonable delay.\\n *\\n * @param {string} str1 The string to compare in a numerically sensitive way.\\n * @param {string} str2 The string to compare `str1` to.\\n * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than\\n *     0 if str1 > str2.\\n */\\ngoog.string.intAwareCompare = function(str1, str2) {\\n  'use strict';\\n  return goog.string.numberAwareCompare_(str1, str2, /\\\\d+|\\\\D+/g);\\n};\\n\\n\\n/**\\n * String comparison function that handles non-negative integer and fractional\\n * numbers in a way humans might expect. Using this function, the string\\n * 'File 2.jpg' sorts before 'File 10.jpg', and '3.14' before '3.2'. Equivalent\\n * to {@link goog.string.intAwareCompare} apart from the way how it interprets\\n * dots.\\n *\\n * @param {string} str1 The string to compare in a numerically sensitive way.\\n * @param {string} str2 The string to compare `str1` to.\\n * @return {number} less than 0 if str1 < str2, 0 if str1 == str2, greater than\\n *     0 if str1 > str2.\\n */\\ngoog.string.floatAwareCompare = function(str1, str2) {\\n  'use strict';\\n  return goog.string.numberAwareCompare_(str1, str2, /\\\\d+|\\\\.\\\\d+|\\\\D+/g);\\n};\\n\\n\\n/**\\n * Alias for {@link goog.string.floatAwareCompare}.\\n *\\n * @param {string} str1\\n * @param {string} str2\\n * @return {number}\\n */\\ngoog.string.numerateCompare = goog.string.floatAwareCompare;\\n\\n\\n/**\\n * URL-encodes a string\\n * @param {*} str The string to url-encode.\\n * @return {string} An encoded copy of `str` that is safe for urls.\\n *     Note that '#', ':', and other characters used to delimit portions\\n *     of URLs *will* be encoded.\\n */\\ngoog.string.urlEncode = function(str) {\\n  'use strict';\\n  return encodeURIComponent(String(str));\\n};\\n\\n\\n/**\\n * URL-decodes the string. We need to specially handle '+'s because\\n * the javascript library doesn't convert them to spaces.\\n * @param {string} str The string to url decode.\\n * @return {string} The decoded `str`.\\n */\\ngoog.string.urlDecode = function(str) {\\n  'use strict';\\n  return decodeURIComponent(str.replace(/\\\\+/g, ' '));\\n};\\n\\n\\n/**\\n * Converts \\\\n to <br>s or <br />s.\\n * @param {string} str The string in which to convert newlines.\\n * @param {boolean=} opt_xml Whether to use XML compatible tags.\\n * @return {string} A copy of `str` with converted newlines.\\n */\\ngoog.string.newLineToBr = goog.string.internal.newLineToBr;\\n\\n\\n/**\\n * Escapes double quote '\\\"' and single quote '\\\\'' characters in addition to\\n * '&', '<', and '>' so that a string can be included in an HTML tag attribute\\n * value within double or single quotes.\\n *\\n * It should be noted that > doesn't need to be escaped for the HTML or XML to\\n * be valid, but it has been decided to escape it for consistency with other\\n * implementations.\\n *\\n * With goog.string.DETECT_DOUBLE_ESCAPING, this function escapes also the\\n * lowercase letter \\\"e\\\".\\n *\\n * NOTE(user):\\n * HtmlEscape is often called during the generation of large blocks of HTML.\\n * Using statics for the regular expressions and strings is an optimization\\n * that can more than half the amount of time IE spends in this function for\\n * large apps, since strings and regexes both contribute to GC allocations.\\n *\\n * Testing for the presence of a character before escaping increases the number\\n * of function calls, but actually provides a speed increase for the average\\n * case -- since the average case often doesn't require the escaping of all 4\\n * characters and indexOf() is much cheaper than replace().\\n * The worst case does suffer slightly from the additional calls, therefore the\\n * opt_isLikelyToContainHtmlChars option has been included for situations\\n * where all 4 HTML entities are very likely to be present and need escaping.\\n *\\n * Some benchmarks (times tended to fluctuate +-0.05ms):\\n *                                     FireFox                     IE6\\n * (no chars / average (mix of cases) / all 4 chars)\\n * no checks                     0.13 / 0.22 / 0.22         0.23 / 0.53 / 0.80\\n * indexOf                       0.08 / 0.17 / 0.26         0.22 / 0.54 / 0.84\\n * indexOf + re test             0.07 / 0.17 / 0.28         0.19 / 0.50 / 0.85\\n *\\n * An additional advantage of checking if replace actually needs to be called\\n * is a reduction in the number of object allocations, so as the size of the\\n * application grows the difference between the various methods would increase.\\n *\\n * @param {string} str string to be escaped.\\n * @param {boolean=} opt_isLikelyToContainHtmlChars Don't perform a check to see\\n *     if the character needs replacing - use this option if you expect each of\\n *     the characters to appear often. Leave false if you expect few html\\n *     characters to occur in your strings, such as if you are escaping HTML.\\n * @return {string} An escaped copy of `str`.\\n */\\ngoog.string.htmlEscape = function(str, opt_isLikelyToContainHtmlChars) {\\n  'use strict';\\n  str = goog.string.internal.htmlEscape(str, opt_isLikelyToContainHtmlChars);\\n  if (goog.string.DETECT_DOUBLE_ESCAPING) {\\n    str = str.replace(goog.string.E_RE_, '&#101;');\\n  }\\n  return str;\\n};\\n\\n\\n/**\\n * Regular expression that matches a lowercase letter \\\"e\\\", for use in escaping.\\n * @const {!RegExp}\\n * @private\\n */\\ngoog.string.E_RE_ = /e/g;\\n\\n\\n/**\\n * Unescapes an HTML string.\\n *\\n * @param {string} str The string to unescape.\\n * @return {string} An unescaped copy of `str`.\\n */\\ngoog.string.unescapeEntities = function(str) {\\n  'use strict';\\n  if (goog.string.contains(str, '&')) {\\n    // We are careful not to use a DOM if we do not have one or we explicitly\\n    // requested non-DOM html unescaping.\\n    if (!goog.string.FORCE_NON_DOM_HTML_UNESCAPING &&\\n        'document' in goog.global) {\\n      return goog.string.unescapeEntitiesUsingDom_(str);\\n    } else {\\n      // Fall back on pure XML entities\\n      return goog.string.unescapePureXmlEntities_(str);\\n    }\\n  }\\n  return str;\\n};\\n\\n\\n/**\\n * Unescapes a HTML string using the provided document.\\n *\\n * @param {string} str The string to unescape.\\n * @param {!Document} document A document to use in escaping the string.\\n * @return {string} An unescaped copy of `str`.\\n */\\ngoog.string.unescapeEntitiesWithDocument = function(str, document) {\\n  'use strict';\\n  if (goog.string.contains(str, '&')) {\\n    return goog.string.unescapeEntitiesUsingDom_(str, document);\\n  }\\n  return str;\\n};\\n\\n\\n/**\\n * Unescapes an HTML string using a DOM to resolve non-XML, non-numeric\\n * entities. This function is XSS-safe and whitespace-preserving.\\n * @private\\n * @param {string} str The string to unescape.\\n * @param {Document=} opt_document An optional document to use for creating\\n *     elements. If this is not specified then the default window.document\\n *     will be used.\\n * @return {string} The unescaped `str` string.\\n */\\ngoog.string.unescapeEntitiesUsingDom_ = function(str, opt_document) {\\n  'use strict';\\n  /** @type {!Object<string, string>} */\\n  const seen = {'&amp;': '&', '&lt;': '<', '&gt;': '>', '&quot;': '\\\"'};\\n  /** @type {!Element} */\\n  let div;\\n  if (opt_document) {\\n    div = opt_document.createElement('div');\\n  } else {\\n    div = goog.global.document.createElement('div');\\n  }\\n  // Match as many valid entity characters as possible. If the actual entity\\n  // happens to be shorter, it will still work as innerHTML will return the\\n  // trailing characters unchanged. Since the entity characters do not include\\n  // open angle bracket, there is no chance of XSS from the innerHTML use.\\n  // Since no whitespace is passed to innerHTML, whitespace is preserved.\\n  return str.replace(goog.string.HTML_ENTITY_PATTERN_, function(s, entity) {\\n    'use strict';\\n    // Check for cached entity.\\n    let value = seen[s];\\n    if (value) {\\n      return value;\\n    }\\n    // Check for numeric entity.\\n    if (entity.charAt(0) == '#') {\\n      // Prefix with 0 so that hex entities (e.g. &#x10) parse as hex numbers.\\n      const n = Number('0' + entity.slice(1));\\n      if (!isNaN(n)) {\\n        value = String.fromCharCode(n);\\n      }\\n    }\\n    // Fall back to innerHTML otherwise.\\n    if (!value) {\\n      // Append a non-entity character to avoid a bug in Webkit that parses\\n      // an invalid entity at the end of innerHTML text as the empty string.\\n      goog.dom.safe.setInnerHtml(\\n          div,\\n          goog.html.uncheckedconversions\\n              .safeHtmlFromStringKnownToSatisfyTypeContract(\\n                  goog.string.Const.from('Single HTML entity.'), s + ' '));\\n      // Then remove the trailing character from the result.\\n      value = div.firstChild.nodeValue.slice(0, -1);\\n    }\\n    // Cache and return.\\n    return seen[s] = value;\\n  });\\n};\\n\\n\\n/**\\n * Unescapes XML entities.\\n * @private\\n * @param {string} str The string to unescape.\\n * @return {string} An unescaped copy of `str`.\\n */\\ngoog.string.unescapePureXmlEntities_ = function(str) {\\n  'use strict';\\n  return str.replace(/&([^;]+);/g, function(s, entity) {\\n    'use strict';\\n    switch (entity) {\\n      case 'amp':\\n        return '&';\\n      case 'lt':\\n        return '<';\\n      case 'gt':\\n        return '>';\\n      case 'quot':\\n        return '\\\"';\\n      default:\\n        if (entity.charAt(0) == '#') {\\n          // Prefix with 0 so that hex entities (e.g. &#x10) parse as hex.\\n          const n = Number('0' + entity.slice(1));\\n          if (!isNaN(n)) {\\n            return String.fromCharCode(n);\\n          }\\n        }\\n        // For invalid entities we just return the entity\\n        return s;\\n    }\\n  });\\n};\\n\\n\\n/**\\n * Regular expression that matches an HTML entity.\\n * See also HTML5: Tokenization / Tokenizing character references.\\n * @private\\n * @type {!RegExp}\\n */\\ngoog.string.HTML_ENTITY_PATTERN_ = /&([^;\\\\s<&]+);?/g;\\n\\n\\n/**\\n * Do escaping of whitespace to preserve spatial formatting. We use character\\n * entity #160 to make it safer for xml.\\n * @param {string} str The string in which to escape whitespace.\\n * @param {boolean=} opt_xml Whether to use XML compatible tags.\\n * @return {string} An escaped copy of `str`.\\n */\\ngoog.string.whitespaceEscape = function(str, opt_xml) {\\n  'use strict';\\n  // This doesn't use goog.string.preserveSpaces for backwards compatibility.\\n  return goog.string.newLineToBr(str.replace(/  /g, ' &#160;'), opt_xml);\\n};\\n\\n\\n/**\\n * Preserve spaces that would be otherwise collapsed in HTML by replacing them\\n * with non-breaking space Unicode characters.\\n * @param {string} str The string in which to preserve whitespace.\\n * @return {string} A copy of `str` with preserved whitespace.\\n */\\ngoog.string.preserveSpaces = function(str) {\\n  'use strict';\\n  return str.replace(/(^|[\\\\n ]) /g, '$1' + goog.string.Unicode.NBSP);\\n};\\n\\n\\n/**\\n * Strip quote characters around a string.  The second argument is a string of\\n * characters to treat as quotes.  This can be a single character or a string of\\n * multiple character and in that case each of those are treated as possible\\n * quote characters. For example:\\n *\\n * <pre>\\n * goog.string.stripQuotes('\\\"abc\\\"', '\\\"`') --\\u003e 'abc'\\n * goog.string.stripQuotes('`abc`', '\\\"`') --\\u003e 'abc'\\n * </pre>\\n *\\n * @param {string} str The string to strip.\\n * @param {string} quoteChars The quote characters to strip.\\n * @return {string} A copy of `str` without the quotes.\\n */\\ngoog.string.stripQuotes = function(str, quoteChars) {\\n  'use strict';\\n  const length = quoteChars.length;\\n  for (let i = 0; i < length; i++) {\\n    const quoteChar = length == 1 ? quoteChars : quoteChars.charAt(i);\\n    if (str.charAt(0) == quoteChar && str.charAt(str.length - 1) == quoteChar) {\\n      return str.substring(1, str.length - 1);\\n    }\\n  }\\n  return str;\\n};\\n\\n\\n/**\\n * Truncates a string to a certain length and adds '...' if necessary.  The\\n * length also accounts for the ellipsis, so a maximum length of 10 and a string\\n * 'Hello World!' produces 'Hello W...'.\\n * @param {string} str The string to truncate.\\n * @param {number} chars Max number of characters.\\n * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped\\n *     characters from being cut off in the middle.\\n * @return {string} The truncated `str` string.\\n */\\ngoog.string.truncate = function(str, chars, opt_protectEscapedCharacters) {\\n  'use strict';\\n  if (opt_protectEscapedCharacters) {\\n    str = goog.string.unescapeEntities(str);\\n  }\\n\\n  if (str.length > chars) {\\n    str = str.substring(0, chars - 3) + '...';\\n  }\\n\\n  if (opt_protectEscapedCharacters) {\\n    str = goog.string.htmlEscape(str);\\n  }\\n\\n  return str;\\n};\\n\\n\\n/**\\n * Truncate a string in the middle, adding \\\"...\\\" if necessary,\\n * and favoring the beginning of the string.\\n * @param {string} str The string to truncate the middle of.\\n * @param {number} chars Max number of characters.\\n * @param {boolean=} opt_protectEscapedCharacters Whether to protect escaped\\n *     characters from being cutoff in the middle.\\n * @param {number=} opt_trailingChars Optional number of trailing characters to\\n *     leave at the end of the string, instead of truncating as close to the\\n *     middle as possible.\\n * @return {string} A truncated copy of `str`.\\n */\\ngoog.string.truncateMiddle = function(\\n    str, chars, opt_protectEscapedCharacters, opt_trailingChars) {\\n  'use strict';\\n  if (opt_protectEscapedCharacters) {\\n    str = goog.string.unescapeEntities(str);\\n  }\\n\\n  if (opt_trailingChars && str.length > chars) {\\n    if (opt_trailingChars > chars) {\\n      opt_trailingChars = chars;\\n    }\\n    const endPoint = str.length - opt_trailingChars;\\n    const startPoint = chars - opt_trailingChars;\\n    str = str.substring(0, startPoint) + '...' + str.substring(endPoint);\\n  } else if (str.length > chars) {\\n    // Favor the beginning of the string:\\n    let half = Math.floor(chars / 2);\\n    const endPos = str.length - half;\\n    half += chars % 2;\\n    str = str.substring(0, half) + '...' + str.substring(endPos);\\n  }\\n\\n  if (opt_protectEscapedCharacters) {\\n    str = goog.string.htmlEscape(str);\\n  }\\n\\n  return str;\\n};\\n\\n\\n/**\\n * Special chars that need to be escaped for goog.string.quote.\\n * @private {!Object<string, string>}\\n */\\ngoog.string.specialEscapeChars_ = {\\n  '\\\\0': '\\\\\\\\0',\\n  '\\\\b': '\\\\\\\\b',\\n  '\\\\f': '\\\\\\\\f',\\n  '\\\\n': '\\\\\\\\n',\\n  '\\\\r': '\\\\\\\\r',\\n  '\\\\t': '\\\\\\\\t',\\n  '\\\\x0B': '\\\\\\\\x0B',  // '\\\\v' is not supported in JScript\\n  '\\\"': '\\\\\\\\\\\"',\\n  '\\\\\\\\': '\\\\\\\\\\\\\\\\',\\n  // To support the use case of embedding quoted strings inside of script\\n  // tags, we have to make sure HTML comments and opening/closing script tags do\\n  // not appear in the resulting string. The specific strings that must be\\n  // escaped are documented at:\\n  // https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements\\n  '<': '\\\\\\\\u003C'  // NOTE: JSON.parse crashes on '\\\\\\\\x3c'.\\n};\\n\\n\\n/**\\n * Character mappings used internally for goog.string.escapeChar.\\n * @private {!Object<string, string>}\\n */\\ngoog.string.jsEscapeCache_ = {\\n  '\\\\'': '\\\\\\\\\\\\''\\n};\\n\\n\\n/**\\n * Encloses a string in double quotes and escapes characters so that the\\n * string is a valid JS string. The resulting string is safe to embed in\\n * `<script>` tags as \\\"<\\\" is escaped.\\n * @param {string} s The string to quote.\\n * @return {string} A copy of `s` surrounded by double quotes.\\n */\\ngoog.string.quote = function(s) {\\n  'use strict';\\n  s = String(s);\\n  const sb = ['\\\"'];\\n  for (let i = 0; i < s.length; i++) {\\n    const ch = s.charAt(i);\\n    const cc = ch.charCodeAt(0);\\n    sb[i + 1] = goog.string.specialEscapeChars_[ch] ||\\n        ((cc > 31 && cc < 127) ? ch : goog.string.escapeChar(ch));\\n  }\\n  sb.push('\\\"');\\n  return sb.join('');\\n};\\n\\n\\n/**\\n * Takes a string and returns the escaped string for that input string.\\n * @param {string} str The string to escape.\\n * @return {string} An escaped string representing `str`.\\n */\\ngoog.string.escapeString = function(str) {\\n  'use strict';\\n  const sb = [];\\n  for (let i = 0; i < str.length; i++) {\\n    sb[i] = goog.string.escapeChar(str.charAt(i));\\n  }\\n  return sb.join('');\\n};\\n\\n\\n/**\\n * Takes a character and returns the escaped string for that character. For\\n * example escapeChar(String.fromCharCode(15)) -> \\\"\\\\\\\\x0E\\\".\\n * @param {string} c The character to escape.\\n * @return {string} An escaped string representing `c`.\\n */\\ngoog.string.escapeChar = function(c) {\\n  'use strict';\\n  if (c in goog.string.jsEscapeCache_) {\\n    return goog.string.jsEscapeCache_[c];\\n  }\\n\\n  if (c in goog.string.specialEscapeChars_) {\\n    return goog.string.jsEscapeCache_[c] = goog.string.specialEscapeChars_[c];\\n  }\\n\\n  let rv = c;\\n  const cc = c.charCodeAt(0);\\n  if (cc > 31 && cc < 127) {\\n    rv = c;\\n  } else {\\n    // tab is 9 but handled above\\n    if (cc < 256) {\\n      rv = '\\\\\\\\x';\\n      if (cc < 16 || cc > 256) {\\n        rv += '0';\\n      }\\n    } else {\\n      rv = '\\\\\\\\u';\\n      if (cc < 4096) {  // \\\\u1000\\n        rv += '0';\\n      }\\n    }\\n    rv += cc.toString(16).toUpperCase();\\n  }\\n\\n  return goog.string.jsEscapeCache_[c] = rv;\\n};\\n\\n\\n/**\\n * Determines whether a string contains a substring.\\n * @param {string} str The string to search.\\n * @param {string} subString The substring to search for.\\n * @return {boolean} Whether `str` contains `subString`.\\n */\\ngoog.string.contains = goog.string.internal.contains;\\n\\n\\n/**\\n * Determines whether a string contains a substring, ignoring case.\\n * @param {string} str The string to search.\\n * @param {string} subString The substring to search for.\\n * @return {boolean} Whether `str` contains `subString`.\\n */\\ngoog.string.caseInsensitiveContains =\\n    goog.string.internal.caseInsensitiveContains;\\n\\n\\n/**\\n * Returns the non-overlapping occurrences of ss in s.\\n * If either s or ss evalutes to false, then returns zero.\\n * @param {string} s The string to look in.\\n * @param {string} ss The string to look for.\\n * @return {number} Number of occurrences of ss in s.\\n */\\ngoog.string.countOf = function(s, ss) {\\n  'use strict';\\n  return s && ss ? s.split(ss).length - 1 : 0;\\n};\\n\\n\\n/**\\n * Removes a substring of a specified length at a specific\\n * index in a string.\\n * @param {string} s The base string from which to remove.\\n * @param {number} index The index at which to remove the substring.\\n * @param {number} stringLength The length of the substring to remove.\\n * @return {string} A copy of `s` with the substring removed or the full\\n *     string if nothing is removed or the input is invalid.\\n */\\ngoog.string.removeAt = function(s, index, stringLength) {\\n  'use strict';\\n  let resultStr = s;\\n  // If the index is greater or equal to 0 then remove substring\\n  if (index >= 0 && index < s.length && stringLength > 0) {\\n    resultStr = s.slice(0, index) + s.slice(index + stringLength);\\n  }\\n  return resultStr;\\n};\\n\\n\\n/**\\n * Removes the first occurrence of a substring from a string.\\n * @param {string} str The base string from which to remove.\\n * @param {string} substr The string to remove.\\n * @return {string} A copy of `str` with `substr` removed or the\\n *     full string if nothing is removed.\\n */\\ngoog.string.remove = function(str, substr) {\\n  'use strict';\\n  return str.replace(substr, '');\\n};\\n\\n\\n/**\\n *  Removes all occurrences of a substring from a string.\\n *  @param {string} s The base string from which to remove.\\n *  @param {string} ss The string to remove.\\n *  @return {string} A copy of `s` with `ss` removed or the full\\n *      string if nothing is removed.\\n */\\ngoog.string.removeAll = function(s, ss) {\\n  'use strict';\\n  const re = new RegExp(goog.string.regExpEscape(ss), 'g');\\n  return s.replace(re, '');\\n};\\n\\n\\n/**\\n *  Replaces all occurrences of a substring of a string with a new substring.\\n *  @param {string} s The base string from which to remove.\\n *  @param {string} ss The string to replace.\\n *  @param {string} replacement The replacement string.\\n *  @return {string} A copy of `s` with `ss` replaced by\\n *      `replacement` or the original string if nothing is replaced.\\n */\\ngoog.string.replaceAll = function(s, ss, replacement) {\\n  'use strict';\\n  const re = new RegExp(goog.string.regExpEscape(ss), 'g');\\n  return s.replace(re, replacement.replace(/\\\\$/g, '$$$$'));\\n};\\n\\n\\n/**\\n * Escapes characters in the string that are not safe to use in a RegExp.\\n * @param {*} s The string to escape. If not a string, it will be casted\\n *     to one.\\n * @return {string} A RegExp safe, escaped copy of `s`.\\n */\\ngoog.string.regExpEscape = function(s) {\\n  'use strict';\\n  return String(s)\\n      .replace(/([-()\\\\[\\\\]{}+?*.$\\\\^|,:#<!\\\\\\\\])/g, '\\\\\\\\$1')\\n      .replace(/\\\\x08/g, '\\\\\\\\x08');\\n};\\n\\n\\n/**\\n * Repeats a string n times.\\n * @param {string} string The string to repeat.\\n * @param {number} length The number of times to repeat.\\n * @return {string} A string containing `length` repetitions of\\n *     `string`.\\n */\\ngoog.string.repeat = (String.prototype.repeat) ? function(string, length) {\\n  'use strict';\\n  // The native method is over 100 times faster than the alternative.\\n  return string.repeat(length);\\n} : function(string, length) {\\n  'use strict';\\n  return new Array(length + 1).join(string);\\n};\\n\\n\\n/**\\n * Pads number to given length and optionally rounds it to a given precision.\\n * For example:\\n * <pre>padNumber(1.25, 2, 3) -> '01.250'\\n * padNumber(1.25, 2) -> '01.25'\\n * padNumber(1.25, 2, 1) -> '01.3'\\n * padNumber(1.25, 0) -> '1.25'</pre>\\n *\\n * @param {number} num The number to pad.\\n * @param {number} length The desired length.\\n * @param {number=} opt_precision The desired precision.\\n * @return {string} `num` as a string with the given options.\\n */\\ngoog.string.padNumber = function(num, length, opt_precision) {\\n  'use strict';\\n  if (!Number.isFinite(num)) return String(num);\\n  let s =\\n      (opt_precision !== undefined) ? num.toFixed(opt_precision) : String(num);\\n  let index = s.indexOf('.');\\n  if (index === -1) {\\n    index = s.length;\\n  }\\n  const sign = s[0] === '-' ? '-' : '';\\n  if (sign) {\\n    s = s.substring(1);\\n  }\\n  return sign + goog.string.repeat('0', Math.max(0, length - index)) + s;\\n};\\n\\n\\n/**\\n * Returns a string representation of the given object, with\\n * null and undefined being returned as the empty string.\\n *\\n * @param {*} obj The object to convert.\\n * @return {string} A string representation of the `obj`.\\n */\\ngoog.string.makeSafe = function(obj) {\\n  'use strict';\\n  return obj == null ? '' : String(obj);\\n};\\n\\n/**\\n * Returns a string with at least 64-bits of randomness.\\n *\\n * Doesn't trust JavaScript's random function entirely. Uses a combination of\\n * random and current timestamp, and then encodes the string in base-36 to\\n * make it shorter.\\n *\\n * @return {string} A random string, e.g. sn1s7vb4gcic.\\n */\\ngoog.string.getRandomString = function() {\\n  'use strict';\\n  const x = 2147483648;\\n  return Math.floor(Math.random() * x).toString(36) +\\n      Math.abs(Math.floor(Math.random() * x) ^ goog.now()).toString(36);\\n};\\n\\n\\n/**\\n * Compares two version numbers.\\n *\\n * @param {string|number} version1 Version of first item.\\n * @param {string|number} version2 Version of second item.\\n *\\n * @return {number}  1 if `version1` is higher.\\n *                   0 if arguments are equal.\\n *                  -1 if `version2` is higher.\\n */\\ngoog.string.compareVersions = goog.string.internal.compareVersions;\\n\\n\\n/**\\n * String hash function similar to java.lang.String.hashCode().\\n * The hash code for a string is computed as\\n * s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],\\n * where s[i] is the ith character of the string and n is the length of\\n * the string. We mod the result to make it between 0 (inclusive) and 2^32\\n * (exclusive).\\n * @param {string} str A string.\\n * @return {number} Hash value for `str`, between 0 (inclusive) and 2^32\\n *  (exclusive). The empty string returns 0.\\n */\\ngoog.string.hashCode = function(str) {\\n  'use strict';\\n  let result = 0;\\n  for (let i = 0; i < str.length; ++i) {\\n    // Normalize to 4 byte range, 0 ... 2^32.\\n    result = (31 * result + str.charCodeAt(i)) >>> 0;\\n  }\\n  return result;\\n};\\n\\n\\n/**\\n * The most recent unique ID. |0 is equivalent to Math.floor in this case.\\n * @type {number}\\n * @private\\n */\\ngoog.string.uniqueStringCounter_ = Math.random() * 0x80000000 | 0;\\n\\n\\n/**\\n * Generates and returns a string which is unique in the current document.\\n * This is useful, for example, to create unique IDs for DOM elements.\\n * @return {string} A unique id.\\n */\\ngoog.string.createUniqueString = function() {\\n  'use strict';\\n  return 'goog_' + goog.string.uniqueStringCounter_++;\\n};\\n\\n\\n/**\\n * Converts the supplied string to a number, which may be Infinity or NaN.\\n * This function strips whitespace: (toNumber(' 123') === 123)\\n * This function accepts scientific notation: (toNumber('1e1') === 10)\\n *\\n * This is better than JavaScript's built-in conversions because, sadly:\\n *     (Number(' ') === 0) and (parseFloat('123a') === 123)\\n *\\n * @param {string} str The string to convert.\\n * @return {number} The number the supplied string represents, or NaN.\\n */\\ngoog.string.toNumber = function(str) {\\n  'use strict';\\n  const num = Number(str);\\n  if (num == 0 && goog.string.isEmptyOrWhitespace(str)) {\\n    return NaN;\\n  }\\n  return num;\\n};\\n\\n\\n/**\\n * Returns whether the given string is lower camel case (e.g. \\\"isFooBar\\\").\\n *\\n * Note that this assumes the string is entirely letters.\\n * @see http://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms\\n *\\n * @param {string} str String to test.\\n * @return {boolean} Whether the string is lower camel case.\\n */\\ngoog.string.isLowerCamelCase = function(str) {\\n  'use strict';\\n  return /^[a-z]+([A-Z][a-z]*)*$/.test(str);\\n};\\n\\n\\n/**\\n * Returns whether the given string is upper camel case (e.g. \\\"FooBarBaz\\\").\\n *\\n * Note that this assumes the string is entirely letters.\\n * @see http://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms\\n *\\n * @param {string} str String to test.\\n * @return {boolean} Whether the string is upper camel case.\\n */\\ngoog.string.isUpperCamelCase = function(str) {\\n  'use strict';\\n  return /^([A-Z][a-z]*)+$/.test(str);\\n};\\n\\n\\n/**\\n * Converts a string from selector-case to camelCase (e.g. from\\n * \\\"multi-part-string\\\" to \\\"multiPartString\\\"), useful for converting\\n * CSS selectors and HTML dataset keys to their equivalent JS properties.\\n * @param {string} str The string in selector-case form.\\n * @return {string} The string in camelCase form.\\n */\\ngoog.string.toCamelCase = function(str) {\\n  'use strict';\\n  return String(str).replace(/\\\\-([a-z])/g, function(all, match) {\\n    'use strict';\\n    return match.toUpperCase();\\n  });\\n};\\n\\n\\n/**\\n * Converts a string from camelCase to selector-case (e.g. from\\n * \\\"multiPartString\\\" to \\\"multi-part-string\\\"), useful for converting JS\\n * style and dataset properties to equivalent CSS selectors and HTML keys.\\n * @param {string} str The string in camelCase form.\\n * @return {string} The string in selector-case form.\\n */\\ngoog.string.toSelectorCase = function(str) {\\n  'use strict';\\n  return String(str).replace(/([A-Z])/g, '-$1').toLowerCase();\\n};\\n\\n\\n/**\\n * Converts a string into TitleCase. First character of the string is always\\n * capitalized in addition to the first letter of every subsequent word.\\n * Words are delimited by one or more whitespaces by default. Custom delimiters\\n * can optionally be specified to replace the default, which doesn't preserve\\n * whitespace delimiters and instead must be explicitly included if needed.\\n *\\n * Default delimiter => \\\" \\\":\\n *    goog.string.toTitleCase('oneTwoThree')    => 'OneTwoThree'\\n *    goog.string.toTitleCase('one two three')  => 'One Two Three'\\n *    goog.string.toTitleCase('  one   two   ') => '  One   Two   '\\n *    goog.string.toTitleCase('one_two_three')  => 'One_two_three'\\n *    goog.string.toTitleCase('one-two-three')  => 'One-two-three'\\n *\\n * Custom delimiter => \\\"_-.\\\":\\n *    goog.string.toTitleCase('oneTwoThree', '_-.')       => 'OneTwoThree'\\n *    goog.string.toTitleCase('one two three', '_-.')     => 'One two three'\\n *    goog.string.toTitleCase('  one   two   ', '_-.')    => '  one   two   '\\n *    goog.string.toTitleCase('one_two_three', '_-.')     => 'One_Two_Three'\\n *    goog.string.toTitleCase('one-two-three', '_-.')     => 'One-Two-Three'\\n *    goog.string.toTitleCase('one...two...three', '_-.') => 'One...Two...Three'\\n *    goog.string.toTitleCase('one. two. three', '_-.')   => 'One. two. three'\\n *    goog.string.toTitleCase('one-two.three', '_-.')     => 'One-Two.Three'\\n *\\n * @param {string} str String value in camelCase form.\\n * @param {string=} opt_delimiters Custom delimiter character set used to\\n *      distinguish words in the string value. Each character represents a\\n *      single delimiter. When provided, default whitespace delimiter is\\n *      overridden and must be explicitly included if needed.\\n * @return {string} String value in TitleCase form.\\n */\\ngoog.string.toTitleCase = function(str, opt_delimiters) {\\n  'use strict';\\n  let delimiters = (typeof opt_delimiters === 'string') ?\\n      goog.string.regExpEscape(opt_delimiters) :\\n      '\\\\\\\\s';\\n\\n  // For IE8, we need to prevent using an empty character set. Otherwise,\\n  // incorrect matching will occur.\\n  delimiters = delimiters ? '|[' + delimiters + ']+' : '';\\n\\n  const regexp = new RegExp('(^' + delimiters + ')([a-z])', 'g');\\n  return str.replace(regexp, function(all, p1, p2) {\\n    'use strict';\\n    return p1 + p2.toUpperCase();\\n  });\\n};\\n\\n\\n/**\\n * Capitalizes a string, i.e. converts the first letter to uppercase\\n * and all other letters to lowercase, e.g.:\\n *\\n * goog.string.capitalize('one')     => 'One'\\n * goog.string.capitalize('ONE')     => 'One'\\n * goog.string.capitalize('one two') => 'One two'\\n *\\n * Note that this function does not trim initial whitespace.\\n *\\n * @param {string} str String value to capitalize.\\n * @return {string} String value with first letter in uppercase.\\n */\\ngoog.string.capitalize = function(str) {\\n  'use strict';\\n  return String(str.charAt(0)).toUpperCase() +\\n      String(str.slice(1)).toLowerCase();\\n};\\n\\n\\n/**\\n * Parse a string in decimal or hexidecimal ('0xFFFF') form.\\n *\\n * To parse a particular radix, please use parseInt(string, radix) directly. See\\n * https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/parseInt\\n *\\n * This is a wrapper for the built-in parseInt function that will only parse\\n * numbers as base 10 or base 16.  Some JS implementations assume strings\\n * starting with \\\"0\\\" are intended to be octal. ES3 allowed but discouraged\\n * this behavior. ES5 forbids it.  This function emulates the ES5 behavior.\\n *\\n * For more information, see Mozilla JS Reference: http://goo.gl/8RiFj\\n *\\n * @param {string|number|null|undefined} value The value to be parsed.\\n * @return {number} The number, parsed. If the string failed to parse, this\\n *     will be NaN.\\n */\\ngoog.string.parseInt = function(value) {\\n  'use strict';\\n  // Force finite numbers to strings.\\n  if (isFinite(value)) {\\n    value = String(value);\\n  }\\n\\n  if (typeof value === 'string') {\\n    // If the string starts with '0x' or '-0x', parse as hex.\\n    return /^\\\\s*-?0x/i.test(value) ? parseInt(value, 16) : parseInt(value, 10);\\n  }\\n\\n  return NaN;\\n};\\n\\n\\n/**\\n * Splits a string on a separator a limited number of times.\\n *\\n * This implementation is more similar to Python or Java, where the limit\\n * parameter specifies the maximum number of splits rather than truncating\\n * the number of results.\\n *\\n * See http://docs.python.org/2/library/stdtypes.html#str.split\\n * See JavaDoc: http://goo.gl/F2AsY\\n * See Mozilla reference: http://goo.gl/dZdZs\\n *\\n * @param {string} str String to split.\\n * @param {string} separator The separator.\\n * @param {number} limit The limit to the number of splits. The resulting array\\n *     will have a maximum length of limit+1.  Negative numbers are the same\\n *     as zero.\\n * @return {!Array<string>} The string, split.\\n */\\ngoog.string.splitLimit = function(str, separator, limit) {\\n  'use strict';\\n  const parts = str.split(separator);\\n  const returnVal = [];\\n\\n  // Only continue doing this while we haven't hit the limit and we have\\n  // parts left.\\n  while (limit > 0 && parts.length) {\\n    returnVal.push(parts.shift());\\n    limit--;\\n  }\\n\\n  // If there are remaining parts, append them to the end.\\n  if (parts.length) {\\n    returnVal.push(parts.join(separator));\\n  }\\n\\n  return returnVal;\\n};\\n\\n\\n/**\\n * Finds the characters to the right of the last instance of any separator\\n *\\n * This function is similar to goog.string.path.baseName, except it can take a\\n * list of characters to split the string on. It will return the rightmost\\n * grouping of characters to the right of any separator as a left-to-right\\n * oriented string.\\n *\\n * @see goog.string.path.baseName\\n * @param {string} str The string\\n * @param {string|!Array<string>} separators A list of separator characters\\n * @return {string} The last part of the string with respect to the separators\\n */\\ngoog.string.lastComponent = function(str, separators) {\\n  'use strict';\\n  if (!separators) {\\n    return str;\\n  } else if (typeof separators == 'string') {\\n    separators = [separators];\\n  }\\n\\n  let lastSeparatorIndex = -1;\\n  for (let i = 0; i < separators.length; i++) {\\n    if (separators[i] == '') {\\n      continue;\\n    }\\n    const currentSeparatorIndex = str.lastIndexOf(separators[i]);\\n    if (currentSeparatorIndex > lastSeparatorIndex) {\\n      lastSeparatorIndex = currentSeparatorIndex;\\n    }\\n  }\\n  if (lastSeparatorIndex == -1) {\\n    return str;\\n  }\\n  return str.slice(lastSeparatorIndex + 1);\\n};\\n\\n\\n/**\\n * Computes the Levenshtein edit distance between two strings.\\n * @param {string} a\\n * @param {string} b\\n * @return {number} The edit distance between the two strings.\\n */\\ngoog.string.editDistance = function(a, b) {\\n  'use strict';\\n  const v0 = [];\\n  const v1 = [];\\n\\n  if (a == b) {\\n    return 0;\\n  }\\n\\n  if (!a.length || !b.length) {\\n    return Math.max(a.length, b.length);\\n  }\\n\\n  for (let i = 0; i < b.length + 1; i++) {\\n    v0[i] = i;\\n  }\\n\\n  for (let i = 0; i < a.length; i++) {\\n    v1[0] = i + 1;\\n\\n    for (let j = 0; j < b.length; j++) {\\n      const cost = Number(a[i] != b[j]);\\n      // Cost for the substring is the minimum of adding one character, removing\\n      // one character, or a swap.\\n      v1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\\n    }\\n\\n    for (let j = 0; j < v0.length; j++) {\\n      v0[j] = v1[j];\\n    }\\n  }\\n\\n  return v1[b.length];\\n};\\n\"],\n\"names\":[\"goog\",\"provide\",\"require\",\"string\",\"DETECT_DOUBLE_ESCAPING\",\"define\",\"FORCE_NON_DOM_HTML_UNESCAPING\",\"Unicode\",\"NBSP\",\"ZERO_WIDTH_SPACE\",\"startsWith\",\"internal\",\"endsWith\",\"caseInsensitiveStartsWith\",\"caseInsensitiveEndsWith\",\"caseInsensitiveEquals\",\"subs\",\"goog.string.subs\",\"str\",\"var_args\",\"splitParts\",\"split\",\"returnString\",\"subsArguments\",\"Array\",\"prototype\",\"slice\",\"call\",\"arguments\",\"length\",\"shift\",\"join\",\"collapseWhitespace\",\"goog.string.collapseWhitespace\",\"replace\",\"isEmptyOrWhitespace\",\"isEmptyString\",\"goog.string.isEmptyString\",\"isEmpty\",\"isEmptyOrWhitespaceSafe\",\"goog.string.isEmptyOrWhitespaceSafe\",\"makeSafe\",\"isEmptySafe\",\"isBreakingWhitespace\",\"goog.string.isBreakingWhitespace\",\"test\",\"isAlpha\",\"goog.string.isAlpha\",\"isNumeric\",\"goog.string.isNumeric\",\"isAlphaNumeric\",\"goog.string.isAlphaNumeric\",\"isSpace\",\"goog.string.isSpace\",\"ch\",\"isUnicodeChar\",\"goog.string.isUnicodeChar\",\"stripNewlines\",\"goog.string.stripNewlines\",\"canonicalizeNewlines\",\"goog.string.canonicalizeNewlines\",\"normalizeWhitespace\",\"goog.string.normalizeWhitespace\",\"normalizeSpaces\",\"goog.string.normalizeSpaces\",\"collapseBreakingSpaces\",\"goog.string.collapseBreakingSpaces\",\"trim\",\"trimLeft\",\"goog.string.trimLeft\",\"trimRight\",\"goog.string.trimRight\",\"caseInsensitiveCompare\",\"numberAwareCompare_\",\"goog.string.numberAwareCompare_\",\"str1\",\"str2\",\"tokenizerRegExp\",\"tokens1\",\"toLowerCase\",\"match\",\"tokens2\",\"count\",\"Math\",\"min\",\"i\",\"a\",\"b\",\"num1\",\"parseInt\",\"isNaN\",\"num2\",\"intAwareCompare\",\"goog.string.intAwareCompare\",\"floatAwareCompare\",\"goog.string.floatAwareCompare\",\"numerateCompare\",\"urlEncode\",\"goog.string.urlEncode\",\"encodeURIComponent\",\"String\",\"urlDecode\",\"goog.string.urlDecode\",\"decodeURIComponent\",\"newLineToBr\",\"htmlEscape\",\"goog.string.htmlEscape\",\"opt_isLikelyToContainHtmlChars\",\"E_RE_\",\"unescapeEntities\",\"goog.string.unescapeEntities\",\"contains\",\"global\",\"unescapeEntitiesUsingDom_\",\"unescapePureXmlEntities_\",\"unescapeEntitiesWithDocument\",\"goog.string.unescapeEntitiesWithDocument\",\"document\",\"goog.string.unescapeEntitiesUsingDom_\",\"opt_document\",\"seen\",\"div\",\"createElement\",\"HTML_ENTITY_PATTERN_\",\"s\",\"entity\",\"value\",\"charAt\",\"n\",\"Number\",\"fromCharCode\",\"dom\",\"safe\",\"setInnerHtml\",\"html\",\"uncheckedconversions\",\"safeHtmlFromStringKnownToSatisfyTypeContract\",\"Const\",\"from\",\"firstChild\",\"nodeValue\",\"goog.string.unescapePureXmlEntities_\",\"whitespaceEscape\",\"goog.string.whitespaceEscape\",\"opt_xml\",\"preserveSpaces\",\"goog.string.preserveSpaces\",\"stripQuotes\",\"goog.string.stripQuotes\",\"quoteChars\",\"quoteChar\",\"substring\",\"truncate\",\"goog.string.truncate\",\"chars\",\"opt_protectEscapedCharacters\",\"truncateMiddle\",\"goog.string.truncateMiddle\",\"opt_trailingChars\",\"endPoint\",\"startPoint\",\"half\",\"floor\",\"endPos\",\"specialEscapeChars_\",\"jsEscapeCache_\",\"quote\",\"goog.string.quote\",\"sb\",\"cc\",\"charCodeAt\",\"escapeChar\",\"push\",\"escapeString\",\"goog.string.escapeString\",\"goog.string.escapeChar\",\"c\",\"rv\",\"toString\",\"toUpperCase\",\"caseInsensitiveContains\",\"countOf\",\"goog.string.countOf\",\"ss\",\"removeAt\",\"goog.string.removeAt\",\"index\",\"stringLength\",\"resultStr\",\"remove\",\"goog.string.remove\",\"substr\",\"removeAll\",\"goog.string.removeAll\",\"re\",\"RegExp\",\"regExpEscape\",\"replaceAll\",\"goog.string.replaceAll\",\"replacement\",\"goog.string.regExpEscape\",\"repeat\",\"padNumber\",\"goog.string.padNumber\",\"num\",\"opt_precision\",\"isFinite\",\"undefined\",\"toFixed\",\"indexOf\",\"sign\",\"max\",\"goog.string.makeSafe\",\"obj\",\"getRandomString\",\"goog.string.getRandomString\",\"x\",\"random\",\"abs\",\"now\",\"compareVersions\",\"hashCode\",\"goog.string.hashCode\",\"result\",\"uniqueStringCounter_\",\"createUniqueString\",\"goog.string.createUniqueString\",\"toNumber\",\"goog.string.toNumber\",\"NaN\",\"isLowerCamelCase\",\"goog.string.isLowerCamelCase\",\"isUpperCamelCase\",\"goog.string.isUpperCamelCase\",\"toCamelCase\",\"goog.string.toCamelCase\",\"all\",\"toSelectorCase\",\"goog.string.toSelectorCase\",\"toTitleCase\",\"goog.string.toTitleCase\",\"opt_delimiters\",\"delimiters\",\"regexp\",\"p1\",\"p2\",\"capitalize\",\"goog.string.capitalize\",\"goog.string.parseInt\",\"splitLimit\",\"goog.string.splitLimit\",\"separator\",\"limit\",\"parts\",\"returnVal\",\"lastComponent\",\"goog.string.lastComponent\",\"separators\",\"lastSeparatorIndex\",\"currentSeparatorIndex\",\"lastIndexOf\",\"editDistance\",\"goog.string.editDistance\",\"v0\",\"v1\",\"j\",\"cost\"]\n}\n"]