1 line
55 KiB
JavaScript
1 line
55 KiB
JavaScript
["^ ","~:resource-id",["~:shadow.build.classpath/resource","goog/html/safestyle.js"],"~:js","goog.loadModule(function(exports) {\n \"use strict\";\n goog.module(\"goog.html.SafeStyle\");\n goog.module.declareLegacyNamespace();\n const Const = goog.require(\"goog.string.Const\");\n const SafeUrl = goog.require(\"goog.html.SafeUrl\");\n const TypedString = goog.require(\"goog.string.TypedString\");\n const {AssertionError, assert, fail} = goog.require(\"goog.asserts\");\n const {contains, endsWith} = goog.require(\"goog.string.internal\");\n const CONSTRUCTOR_TOKEN_PRIVATE = {};\n class SafeStyle {\n constructor(value, token) {\n this.privateDoNotAccessOrElseSafeStyleWrappedValue_ = token === CONSTRUCTOR_TOKEN_PRIVATE ? value : \"\";\n this.implementsGoogStringTypedString = true;\n }\n static fromConstant(style) {\n const styleString = Const.unwrap(style);\n if (styleString.length === 0) {\n return SafeStyle.EMPTY;\n }\n assert(endsWith(styleString, \";\"), `Last character of style string is not ';': ${styleString}`);\n assert(contains(styleString, \":\"), \"Style string must contain at least one ':', to \" + 'specify a \"name: value\" pair: ' + styleString);\n return SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(styleString);\n }\n getTypedStringValue() {\n return this.privateDoNotAccessOrElseSafeStyleWrappedValue_;\n }\n toString() {\n return this.privateDoNotAccessOrElseSafeStyleWrappedValue_.toString();\n }\n static unwrap(safeStyle) {\n if (safeStyle instanceof SafeStyle && safeStyle.constructor === SafeStyle) {\n return safeStyle.privateDoNotAccessOrElseSafeStyleWrappedValue_;\n } else {\n fail(`expected object of type SafeStyle, got '${safeStyle}` + \"' of type \" + goog.typeOf(safeStyle));\n return \"type_error:SafeStyle\";\n }\n }\n static createSafeStyleSecurityPrivateDoNotAccessOrElse(style) {\n return new SafeStyle(style, CONSTRUCTOR_TOKEN_PRIVATE);\n }\n static create(map) {\n let style = \"\";\n for (let name in map) {\n if (Object.prototype.hasOwnProperty.call(map, name)) {\n if (!/^[-_a-zA-Z0-9]+$/.test(name)) {\n throw new Error(`Name allows only [-_a-zA-Z0-9], got: ${name}`);\n }\n let value = map[name];\n if (value == null) {\n continue;\n }\n if (Array.isArray(value)) {\n value = value.map(sanitizePropertyValue).join(\" \");\n } else {\n value = sanitizePropertyValue(value);\n }\n style += `${name}:${value};`;\n }\n }\n if (!style) {\n return SafeStyle.EMPTY;\n }\n return SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(style);\n }\n static concat(var_args) {\n let style = \"\";\n const addArgument = argument => {\n if (Array.isArray(argument)) {\n argument.forEach(addArgument);\n } else {\n style += SafeStyle.unwrap(argument);\n }\n };\n Array.prototype.forEach.call(arguments, addArgument);\n if (!style) {\n return SafeStyle.EMPTY;\n }\n return SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(style);\n }\n }\n SafeStyle.EMPTY = SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(\"\");\n SafeStyle.INNOCUOUS_STRING = \"zClosurez\";\n SafeStyle.PropertyValue;\n SafeStyle.PropertyMap;\n function sanitizePropertyValue(value) {\n if (value instanceof SafeUrl) {\n const url = SafeUrl.unwrap(value);\n return 'url(\"' + url.replace(/</g, \"%3c\").replace(/[\\\\\"]/g, \"\\\\$\\x26\") + '\")';\n }\n const result = value instanceof Const ? Const.unwrap(value) : sanitizePropertyValueString(String(value));\n if (/[{;}]/.test(result)) {\n throw new AssertionError(\"Value does not allow [{;}], got: %s.\", [result]);\n }\n return result;\n }\n function sanitizePropertyValueString(value) {\n const valueWithoutFunctions = value.replace(FUNCTIONS_RE, \"$1\").replace(FUNCTIONS_RE, \"$1\").replace(URL_RE, \"url\");\n if (!VALUE_RE.test(valueWithoutFunctions)) {\n fail(`String value allows only ${VALUE_ALLOWED_CHARS}` + \" and simple functions, got: \" + value);\n return SafeStyle.INNOCUOUS_STRING;\n } else if (COMMENT_RE.test(value)) {\n fail(`String value disallows comments, got: ${value}`);\n return SafeStyle.INNOCUOUS_STRING;\n } else if (!hasBalancedQuotes(value)) {\n fail(`String value requires balanced quotes, got: ${value}`);\n return SafeStyle.INNOCUOUS_STRING;\n } else if (!hasBalancedSquareBrackets(value)) {\n fail(\"String value requires balanced square brackets and one\" + \" identifier per pair of brackets, got: \" + value);\n return SafeStyle.INNOCUOUS_STRING;\n }\n return sanitizeUrl(value);\n }\n function hasBalancedQuotes(value) {\n let outsideSingle = true;\n let outsideDouble = true;\n for (let i = 0; i < value.length; i++) {\n const c = value.charAt(i);\n if (c == \"'\" && outsideDouble) {\n outsideSingle = !outsideSingle;\n } else if (c == '\"' && outsideSingle) {\n outsideDouble = !outsideDouble;\n }\n }\n return outsideSingle && outsideDouble;\n }\n function hasBalancedSquareBrackets(value) {\n let outside = true;\n const tokenRe = /^[-_a-zA-Z0-9]$/;\n for (let i = 0; i < value.length; i++) {\n const c = value.charAt(i);\n if (c == \"]\") {\n if (outside) {\n return false;\n }\n outside = true;\n } else if (c == \"[\") {\n if (!outside) {\n return false;\n }\n outside = false;\n } else if (!outside && !tokenRe.test(c)) {\n return false;\n }\n }\n return outside;\n }\n const VALUE_ALLOWED_CHARS = \"[-+,.\\\"'%_!#/ a-zA-Z0-9\\\\[\\\\]]\";\n const VALUE_RE = new RegExp(`^${VALUE_ALLOWED_CHARS}+\\$`);\n const URL_RE = new RegExp(\"\\\\b(url\\\\([ \\t\\n]*)(\" + \"'[ -\\x26(-\\\\[\\\\]-~]*'\" + '|\"[ !#-\\\\[\\\\]-~]*\"' + \"|[!#-\\x26*-\\\\[\\\\]-~]*\" + \")([ \\t\\n]*\\\\))\", \"g\");\n const ALLOWED_FUNCTIONS = [\"calc\", \"cubic-bezier\", \"fit-content\", \"hsl\", \"hsla\", \"linear-gradient\", \"matrix\", \"minmax\", \"radial-gradient\", \"repeat\", \"rgb\", \"rgba\", \"(rotate|scale|translate)(X|Y|Z|3d)?\", \"steps\", \"var\",];\n const FUNCTIONS_RE = new RegExp(\"\\\\b(\" + ALLOWED_FUNCTIONS.join(\"|\") + \")\" + \"\\\\([-+*/0-9a-zA-Z.%#\\\\[\\\\], ]+\\\\)\", \"g\");\n const COMMENT_RE = /\\/\\*/;\n function sanitizeUrl(value) {\n return value.replace(URL_RE, (match, before, url, after) => {\n let quote = \"\";\n url = url.replace(/^(['\"])(.*)\\1$/, (match, start, inside) => {\n quote = start;\n return inside;\n });\n const sanitized = SafeUrl.sanitize(url).getTypedStringValue();\n return before + quote + sanitized + quote + after;\n });\n }\n exports = SafeStyle;\n return exports;\n});\n","~:source","/**\n * @license\n * Copyright The Closure Library Authors.\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * @fileoverview The SafeStyle type and its builders.\n *\n * TODO(xtof): Link to document stating type contract.\n */\n\ngoog.module('goog.html.SafeStyle');\ngoog.module.declareLegacyNamespace();\n\nconst Const = goog.require('goog.string.Const');\nconst SafeUrl = goog.require('goog.html.SafeUrl');\nconst TypedString = goog.require('goog.string.TypedString');\nconst {AssertionError, assert, fail} = goog.require('goog.asserts');\nconst {contains, endsWith} = goog.require('goog.string.internal');\n\n/**\n * Token used to ensure that object is created only from this file. No code\n * outside of this file can access this token.\n * @type {!Object}\n * @const\n */\nconst CONSTRUCTOR_TOKEN_PRIVATE = {};\n\n/**\n * A string-like object which represents a sequence of CSS declarations\n * (`propertyName1: propertyvalue1; propertyName2: propertyValue2; ...`)\n * and that carries the security type contract that its value, as a string,\n * will not cause untrusted script execution (XSS) when evaluated as CSS in a\n * browser.\n *\n * Instances of this type must be created via the factory methods\n * (`SafeStyle.create` or `SafeStyle.fromConstant`)\n * and not by invoking its constructor. The constructor intentionally takes an\n * extra parameter that cannot be constructed outside of this file and the type\n * is immutable; hence only a default instance corresponding to the empty string\n * can be obtained via constructor invocation.\n *\n * SafeStyle's string representation can safely be:\n * <ul>\n * <li>Interpolated as the content of a *quoted* HTML style attribute.\n * However, the SafeStyle string *must be HTML-attribute-escaped* before\n * interpolation.\n * <li>Interpolated as the content of a {}-wrapped block within a stylesheet.\n * '<' characters in the SafeStyle string *must be CSS-escaped* before\n * interpolation. The SafeStyle string is also guaranteed not to be able\n * to introduce new properties or elide existing ones.\n * <li>Interpolated as the content of a {}-wrapped block within an HTML\n * <style> element. '<' characters in the SafeStyle string\n * *must be CSS-escaped* before interpolation.\n * <li>Assigned to the style property of a DOM node. The SafeStyle string\n * should not be escaped before being assigned to the property.\n * </ul>\n *\n * A SafeStyle may never contain literal angle brackets. Otherwise, it could\n * be unsafe to place a SafeStyle into a <style> tag (where it can't\n * be HTML escaped). For example, if the SafeStyle containing\n * `font: 'foo <style/><script>evil</script>'` were\n * interpolated within a <style> tag, this would then break out of the\n * style context into HTML.\n *\n * A SafeStyle may contain literal single or double quotes, and as such the\n * entire style string must be escaped when used in a style attribute (if\n * this were not the case, the string could contain a matching quote that\n * would escape from the style attribute).\n *\n * Values of this type must be composable, i.e. for any two values\n * `style1` and `style2` of this type,\n * `SafeStyle.unwrap(style1) +\n * SafeStyle.unwrap(style2)` must itself be a value that satisfies\n * the SafeStyle type constraint. This requirement implies that for any value\n * `style` of this type, `SafeStyle.unwrap(style)` must\n * not end in a \"property value\" or \"property name\" context. For example,\n * a value of `background:url(\"` or `font-` would not satisfy the\n * SafeStyle contract. This is because concatenating such strings with a\n * second value that itself does not contain unsafe CSS can result in an\n * overall string that does. For example, if `javascript:evil())\"` is\n * appended to `background:url(\"}, the resulting string may result in\n * the execution of a malicious script.\n *\n * TODO(mlourenco): Consider whether we should implement UTF-8 interchange\n * validity checks and blacklisting of newlines (including Unicode ones) and\n * other whitespace characters (\\t, \\f). Document here if so and also update\n * SafeStyle.fromConstant().\n *\n * The following example values comply with this type's contract:\n * <ul>\n * <li><pre>width: 1em;</pre>\n * <li><pre>height:1em;</pre>\n * <li><pre>width: 1em;height: 1em;</pre>\n * <li><pre>background:url('http://url');</pre>\n * </ul>\n * In addition, the empty string is safe for use in a CSS attribute.\n *\n * The following example values do NOT comply with this type's contract:\n * <ul>\n * <li><pre>background: red</pre> (missing a trailing semi-colon)\n * <li><pre>background:</pre> (missing a value and a trailing semi-colon)\n * <li><pre>1em</pre> (missing an attribute name, which provides context for\n * the value)\n * </ul>\n *\n * @see SafeStyle#create\n * @see SafeStyle#fromConstant\n * @see http://www.w3.org/TR/css3-syntax/\n * @final\n * @struct\n * @implements {TypedString}\n */\nclass SafeStyle {\n /**\n * @param {string} value\n * @param {!Object} token package-internal implementation detail.\n */\n constructor(value, token) {\n /**\n * The contained value of this SafeStyle. The field has a purposely\n * ugly name to make (non-compiled) code that attempts to directly access\n * this field stand out.\n * @private {string}\n */\n this.privateDoNotAccessOrElseSafeStyleWrappedValue_ =\n (token === CONSTRUCTOR_TOKEN_PRIVATE) ? value : '';\n\n /**\n * @override\n * @const {boolean}\n */\n this.implementsGoogStringTypedString = true;\n }\n\n\n /**\n * Creates a SafeStyle object from a compile-time constant string.\n *\n * `style` should be in the format\n * `name: value; [name: value; ...]` and must not have any < or >\n * characters in it. This is so that SafeStyle's contract is preserved,\n * allowing the SafeStyle to correctly be interpreted as a sequence of CSS\n * declarations and without affecting the syntactic structure of any\n * surrounding CSS and HTML.\n *\n * This method performs basic sanity checks on the format of `style`\n * but does not constrain the format of `name` and `value`, except\n * for disallowing tag characters.\n *\n * @param {!Const} style A compile-time-constant string from which\n * to create a SafeStyle.\n * @return {!SafeStyle} A SafeStyle object initialized to\n * `style`.\n */\n static fromConstant(style) {\n const styleString = Const.unwrap(style);\n if (styleString.length === 0) {\n return SafeStyle.EMPTY;\n }\n assert(\n endsWith(styleString, ';'),\n `Last character of style string is not ';': ${styleString}`);\n assert(\n contains(styleString, ':'),\n 'Style string must contain at least one \\':\\', to ' +\n 'specify a \"name: value\" pair: ' + styleString);\n return SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(\n styleString);\n };\n\n\n /**\n * Returns this SafeStyle's value as a string.\n *\n * IMPORTANT: In code where it is security relevant that an object's type is\n * indeed `SafeStyle`, use `SafeStyle.unwrap` instead of\n * this method. If in doubt, assume that it's security relevant. In\n * particular, note that goog.html functions which return a goog.html type do\n * not guarantee the returned instance is of the right type. For example:\n *\n * <pre>\n * var fakeSafeHtml = new String('fake');\n * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;\n * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);\n * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by\n * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml\n * // instanceof goog.html.SafeHtml.\n * </pre>\n *\n * @return {string}\n * @see SafeStyle#unwrap\n * @override\n */\n getTypedStringValue() {\n return this.privateDoNotAccessOrElseSafeStyleWrappedValue_;\n }\n\n\n /**\n * Returns a string-representation of this value.\n *\n * To obtain the actual string value wrapped in a SafeStyle, use\n * `SafeStyle.unwrap`.\n *\n * @return {string}\n * @see SafeStyle#unwrap\n * @override\n */\n toString() {\n return this.privateDoNotAccessOrElseSafeStyleWrappedValue_.toString();\n }\n\n\n /**\n * Performs a runtime check that the provided object is indeed a\n * SafeStyle object, and returns its value.\n *\n * @param {!SafeStyle} safeStyle The object to extract from.\n * @return {string} The safeStyle object's contained string, unless\n * the run-time type check fails. In that case, `unwrap` returns an\n * innocuous string, or, if assertions are enabled, throws\n * `AssertionError`.\n */\n static unwrap(safeStyle) {\n // Perform additional Run-time type-checking to ensure that\n // safeStyle is indeed an instance of the expected type. This\n // provides some additional protection against security bugs due to\n // application code that disables type checks.\n // Specifically, the following checks are performed:\n // 1. The object is an instance of the expected type.\n // 2. The object is not an instance of a subclass.\n if (safeStyle instanceof SafeStyle && safeStyle.constructor === SafeStyle) {\n return safeStyle.privateDoNotAccessOrElseSafeStyleWrappedValue_;\n } else {\n fail(\n `expected object of type SafeStyle, got '${safeStyle}` +\n '\\' of type ' + goog.typeOf(safeStyle));\n return 'type_error:SafeStyle';\n }\n }\n\n\n /**\n * Package-internal utility method to create SafeStyle instances.\n *\n * @param {string} style The string to initialize the SafeStyle object with.\n * @return {!SafeStyle} The initialized SafeStyle object.\n * @package\n */\n static createSafeStyleSecurityPrivateDoNotAccessOrElse(style) {\n return new SafeStyle(style, CONSTRUCTOR_TOKEN_PRIVATE);\n }\n\n /**\n * Creates a new SafeStyle object from the properties specified in the map.\n * @param {!SafeStyle.PropertyMap} map Mapping of property names to\n * their values, for example {'margin': '1px'}. Names must consist of\n * [-_a-zA-Z0-9]. Values might be strings consisting of\n * [-,.'\"%_!# a-zA-Z0-9[\\]], where \", ', and [] must be properly balanced.\n * We also allow simple functions like rgb() and url() which sanitizes its\n * contents. Other values must be wrapped in Const. URLs might\n * be passed as SafeUrl which will be wrapped into url(\"\"). We\n * also support array whose elements are joined with ' '. Null value\n * causes skipping the property.\n * @return {!SafeStyle}\n * @throws {!Error} If invalid name is provided.\n * @throws {!AssertionError} If invalid value is provided. With\n * disabled assertions, invalid value is replaced by\n * SafeStyle.INNOCUOUS_STRING.\n */\n static create(map) {\n let style = '';\n for (let name in map) {\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty#Using_hasOwnProperty_as_a_property_name\n if (Object.prototype.hasOwnProperty.call(map, name)) {\n if (!/^[-_a-zA-Z0-9]+$/.test(name)) {\n throw new Error(`Name allows only [-_a-zA-Z0-9], got: ${name}`);\n }\n let value = map[name];\n if (value == null) {\n continue;\n }\n if (Array.isArray(value)) {\n value = value.map(sanitizePropertyValue).join(' ');\n } else {\n value = sanitizePropertyValue(value);\n }\n style += `${name}:${value};`;\n }\n }\n if (!style) {\n return SafeStyle.EMPTY;\n }\n return SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(style);\n };\n\n /**\n * Creates a new SafeStyle object by concatenating the values.\n * @param {...(!SafeStyle|!Array<!SafeStyle>)} var_args\n * SafeStyles to concatenate.\n * @return {!SafeStyle}\n */\n static concat(var_args) {\n let style = '';\n\n /**\n * @param {!SafeStyle|!Array<!SafeStyle>} argument\n */\n const addArgument = argument => {\n if (Array.isArray(argument)) {\n argument.forEach(addArgument);\n } else {\n style += SafeStyle.unwrap(argument);\n }\n };\n\n Array.prototype.forEach.call(arguments, addArgument);\n if (!style) {\n return SafeStyle.EMPTY;\n }\n return SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(style);\n };\n}\n\n/**\n * A SafeStyle instance corresponding to the empty string.\n * @const {!SafeStyle}\n */\nSafeStyle.EMPTY = SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse('');\n\n\n/**\n * The innocuous string generated by SafeStyle.create when passed\n * an unsafe value.\n * @const {string}\n */\nSafeStyle.INNOCUOUS_STRING = 'zClosurez';\n\n\n/**\n * A single property value.\n * @typedef {string|!Const|!SafeUrl}\n */\nSafeStyle.PropertyValue;\n\n\n/**\n * Mapping of property names to their values.\n * We don't support numbers even though some values might be numbers (e.g.\n * line-height or 0 for any length). The reason is that most numeric values need\n * units (e.g. '1px') and allowing numbers could cause users forgetting about\n * them.\n * @typedef {!Object<string, ?SafeStyle.PropertyValue|\n * ?Array<!SafeStyle.PropertyValue>>}\n */\nSafeStyle.PropertyMap;\n\n\n\n/**\n * Checks and converts value to string.\n * @param {!SafeStyle.PropertyValue} value\n * @return {string}\n */\nfunction sanitizePropertyValue(value) {\n if (value instanceof SafeUrl) {\n const url = SafeUrl.unwrap(value);\n return 'url(\"' + url.replace(/</g, '%3c').replace(/[\\\\\"]/g, '\\\\$&') + '\")';\n }\n const result = value instanceof Const ?\n Const.unwrap(value) :\n sanitizePropertyValueString(String(value));\n // These characters can be used to change context and we don't want that even\n // with const values.\n if (/[{;}]/.test(result)) {\n throw new AssertionError('Value does not allow [{;}], got: %s.', [result]);\n }\n return result;\n}\n\n\n/**\n * Checks string value.\n * @param {string} value\n * @return {string}\n */\nfunction sanitizePropertyValueString(value) {\n // Some CSS property values permit nested functions. We allow one level of\n // nesting, and all nested functions must also be in the FUNCTIONS_RE_ list.\n const valueWithoutFunctions = value.replace(FUNCTIONS_RE, '$1')\n .replace(FUNCTIONS_RE, '$1')\n .replace(URL_RE, 'url');\n if (!VALUE_RE.test(valueWithoutFunctions)) {\n fail(\n `String value allows only ${VALUE_ALLOWED_CHARS}` +\n ' and simple functions, got: ' + value);\n return SafeStyle.INNOCUOUS_STRING;\n } else if (COMMENT_RE.test(value)) {\n fail(`String value disallows comments, got: ${value}`);\n return SafeStyle.INNOCUOUS_STRING;\n } else if (!hasBalancedQuotes(value)) {\n fail(`String value requires balanced quotes, got: ${value}`);\n return SafeStyle.INNOCUOUS_STRING;\n } else if (!hasBalancedSquareBrackets(value)) {\n fail(\n 'String value requires balanced square brackets and one' +\n ' identifier per pair of brackets, got: ' + value);\n return SafeStyle.INNOCUOUS_STRING;\n }\n return sanitizeUrl(value);\n}\n\n\n/**\n * Checks that quotes (\" and ') are properly balanced inside a string. Assumes\n * that neither escape (\\) nor any other character that could result in\n * breaking out of a string parsing context are allowed;\n * see http://www.w3.org/TR/css3-syntax/#string-token-diagram.\n * @param {string} value Untrusted CSS property value.\n * @return {boolean} True if property value is safe with respect to quote\n * balancedness.\n */\nfunction hasBalancedQuotes(value) {\n let outsideSingle = true;\n let outsideDouble = true;\n for (let i = 0; i < value.length; i++) {\n const c = value.charAt(i);\n if (c == '\\'' && outsideDouble) {\n outsideSingle = !outsideSingle;\n } else if (c == '\"' && outsideSingle) {\n outsideDouble = !outsideDouble;\n }\n }\n return outsideSingle && outsideDouble;\n}\n\n\n/**\n * Checks that square brackets ([ and ]) are properly balanced inside a string,\n * and that the content in the square brackets is one ident-token;\n * see https://www.w3.org/TR/css-syntax-3/#ident-token-diagram.\n * For practicality, and in line with other restrictions posed on SafeStyle\n * strings, we restrict the character set allowable in the ident-token to\n * [-_a-zA-Z0-9].\n * @param {string} value Untrusted CSS property value.\n * @return {boolean} True if property value is safe with respect to square\n * bracket balancedness.\n */\nfunction hasBalancedSquareBrackets(value) {\n let outside = true;\n const tokenRe = /^[-_a-zA-Z0-9]$/;\n for (let i = 0; i < value.length; i++) {\n const c = value.charAt(i);\n if (c == ']') {\n if (outside) return false; // Unbalanced ].\n outside = true;\n } else if (c == '[') {\n if (!outside) return false; // No nesting.\n outside = false;\n } else if (!outside && !tokenRe.test(c)) {\n return false;\n }\n }\n return outside;\n}\n\n\n/**\n * Characters allowed in VALUE_RE.\n * @type {string}\n */\nconst VALUE_ALLOWED_CHARS = '[-+,.\"\\'%_!#/ a-zA-Z0-9\\\\[\\\\]]';\n\n\n/**\n * Regular expression for safe values.\n * Quotes (\" and ') are allowed, but a check must be done elsewhere to ensure\n * they're balanced.\n * Square brackets ([ and ]) are allowed, but a check must be done elsewhere\n * to ensure they're balanced. The content inside a pair of square brackets must\n * be one alphanumeric identifier.\n * ',' allows multiple values to be assigned to the same property\n * (e.g. background-attachment or font-family) and hence could allow\n * multiple values to get injected, but that should pose no risk of XSS.\n * The expression checks only for XSS safety, not for CSS validity.\n * @const {!RegExp}\n */\nconst VALUE_RE = new RegExp(`^${VALUE_ALLOWED_CHARS}+\\$`);\n\n\n/**\n * Regular expression for url(). We support URLs allowed by\n * https://www.w3.org/TR/css-syntax-3/#url-token-diagram without using escape\n * sequences. Use percent-encoding if you need to use special characters like\n * backslash.\n * @const {!RegExp}\n */\nconst URL_RE = new RegExp(\n '\\\\b(url\\\\([ \\t\\n]*)(' +\n '\\'[ -&(-\\\\[\\\\]-~]*\\'' + // Printable characters except ' and \\.\n '|\"[ !#-\\\\[\\\\]-~]*\"' + // Printable characters except \" and \\.\n '|[!#-&*-\\\\[\\\\]-~]*' + // Printable characters except [ \"'()\\\\].\n ')([ \\t\\n]*\\\\))',\n 'g');\n\n/**\n * Names of functions allowed in FUNCTIONS_RE.\n * @const {!Array<string>}\n */\nconst ALLOWED_FUNCTIONS = [\n 'calc',\n 'cubic-bezier',\n 'fit-content',\n 'hsl',\n 'hsla',\n 'linear-gradient',\n 'matrix',\n 'minmax',\n 'radial-gradient',\n 'repeat',\n 'rgb',\n 'rgba',\n '(rotate|scale|translate)(X|Y|Z|3d)?',\n 'steps',\n 'var',\n];\n\n\n/**\n * Regular expression for simple functions.\n * @const {!RegExp}\n */\nconst FUNCTIONS_RE = new RegExp(\n '\\\\b(' + ALLOWED_FUNCTIONS.join('|') + ')' +\n '\\\\([-+*/0-9a-zA-Z.%#\\\\[\\\\], ]+\\\\)',\n 'g');\n\n\n/**\n * Regular expression for comments. These are disallowed in CSS property values.\n * @const {!RegExp}\n */\nconst COMMENT_RE = /\\/\\*/;\n\n\n/**\n * Sanitize URLs inside url().\n * NOTE: We could also consider using CSS.escape once that's available in the\n * browsers. However, loosely matching URL e.g. with url\\(.*\\) and then escaping\n * the contents would result in a slightly different language than CSS leading\n * to confusion of users. E.g. url(\")\") is valid in CSS but it would be invalid\n * as seen by our parser. On the other hand, url(\\) is invalid in CSS but our\n * parser would be fine with it.\n * @param {string} value Untrusted CSS property value.\n * @return {string}\n */\nfunction sanitizeUrl(value) {\n return value.replace(URL_RE, (match, before, url, after) => {\n let quote = '';\n url = url.replace(/^(['\"])(.*)\\1$/, (match, start, inside) => {\n quote = start;\n return inside;\n });\n const sanitized = SafeUrl.sanitize(url).getTypedStringValue();\n return before + quote + sanitized + quote + after;\n });\n}\n\n\nexports = SafeStyle;\n","~:compiled-at",1684858197880,"~:source-map-json","{\n\"version\":3,\n\"file\":\"goog.html.safestyle.js\",\n\"lineCount\":168,\n\"mappings\":\"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\",\n\"sources\":[\"goog/html/safestyle.js\"],\n\"sourcesContent\":[\"/**\\n * @license\\n * Copyright The Closure Library Authors.\\n * SPDX-License-Identifier: Apache-2.0\\n */\\n\\n/**\\n * @fileoverview The SafeStyle type and its builders.\\n *\\n * TODO(xtof): Link to document stating type contract.\\n */\\n\\ngoog.module('goog.html.SafeStyle');\\ngoog.module.declareLegacyNamespace();\\n\\nconst Const = goog.require('goog.string.Const');\\nconst SafeUrl = goog.require('goog.html.SafeUrl');\\nconst TypedString = goog.require('goog.string.TypedString');\\nconst {AssertionError, assert, fail} = goog.require('goog.asserts');\\nconst {contains, endsWith} = goog.require('goog.string.internal');\\n\\n/**\\n * Token used to ensure that object is created only from this file. No code\\n * outside of this file can access this token.\\n * @type {!Object}\\n * @const\\n */\\nconst CONSTRUCTOR_TOKEN_PRIVATE = {};\\n\\n/**\\n * A string-like object which represents a sequence of CSS declarations\\n * (`propertyName1: propertyvalue1; propertyName2: propertyValue2; ...`)\\n * and that carries the security type contract that its value, as a string,\\n * will not cause untrusted script execution (XSS) when evaluated as CSS in a\\n * browser.\\n *\\n * Instances of this type must be created via the factory methods\\n * (`SafeStyle.create` or `SafeStyle.fromConstant`)\\n * and not by invoking its constructor. The constructor intentionally takes an\\n * extra parameter that cannot be constructed outside of this file and the type\\n * is immutable; hence only a default instance corresponding to the empty string\\n * can be obtained via constructor invocation.\\n *\\n * SafeStyle's string representation can safely be:\\n * <ul>\\n * <li>Interpolated as the content of a *quoted* HTML style attribute.\\n * However, the SafeStyle string *must be HTML-attribute-escaped* before\\n * interpolation.\\n * <li>Interpolated as the content of a {}-wrapped block within a stylesheet.\\n * '<' characters in the SafeStyle string *must be CSS-escaped* before\\n * interpolation. The SafeStyle string is also guaranteed not to be able\\n * to introduce new properties or elide existing ones.\\n * <li>Interpolated as the content of a {}-wrapped block within an HTML\\n * <style> element. '<' characters in the SafeStyle string\\n * *must be CSS-escaped* before interpolation.\\n * <li>Assigned to the style property of a DOM node. The SafeStyle string\\n * should not be escaped before being assigned to the property.\\n * </ul>\\n *\\n * A SafeStyle may never contain literal angle brackets. Otherwise, it could\\n * be unsafe to place a SafeStyle into a <style> tag (where it can't\\n * be HTML escaped). For example, if the SafeStyle containing\\n * `font: 'foo <style/><script>evil</script>'` were\\n * interpolated within a <style> tag, this would then break out of the\\n * style context into HTML.\\n *\\n * A SafeStyle may contain literal single or double quotes, and as such the\\n * entire style string must be escaped when used in a style attribute (if\\n * this were not the case, the string could contain a matching quote that\\n * would escape from the style attribute).\\n *\\n * Values of this type must be composable, i.e. for any two values\\n * `style1` and `style2` of this type,\\n * `SafeStyle.unwrap(style1) +\\n * SafeStyle.unwrap(style2)` must itself be a value that satisfies\\n * the SafeStyle type constraint. This requirement implies that for any value\\n * `style` of this type, `SafeStyle.unwrap(style)` must\\n * not end in a \\\"property value\\\" or \\\"property name\\\" context. For example,\\n * a value of `background:url(\\\"` or `font-` would not satisfy the\\n * SafeStyle contract. This is because concatenating such strings with a\\n * second value that itself does not contain unsafe CSS can result in an\\n * overall string that does. For example, if `javascript:evil())\\\"` is\\n * appended to `background:url(\\\"}, the resulting string may result in\\n * the execution of a malicious script.\\n *\\n * TODO(mlourenco): Consider whether we should implement UTF-8 interchange\\n * validity checks and blacklisting of newlines (including Unicode ones) and\\n * other whitespace characters (\\\\t, \\\\f). Document here if so and also update\\n * SafeStyle.fromConstant().\\n *\\n * The following example values comply with this type's contract:\\n * <ul>\\n * <li><pre>width: 1em;</pre>\\n * <li><pre>height:1em;</pre>\\n * <li><pre>width: 1em;height: 1em;</pre>\\n * <li><pre>background:url('http://url');</pre>\\n * </ul>\\n * In addition, the empty string is safe for use in a CSS attribute.\\n *\\n * The following example values do NOT comply with this type's contract:\\n * <ul>\\n * <li><pre>background: red</pre> (missing a trailing semi-colon)\\n * <li><pre>background:</pre> (missing a value and a trailing semi-colon)\\n * <li><pre>1em</pre> (missing an attribute name, which provides context for\\n * the value)\\n * </ul>\\n *\\n * @see SafeStyle#create\\n * @see SafeStyle#fromConstant\\n * @see http://www.w3.org/TR/css3-syntax/\\n * @final\\n * @struct\\n * @implements {TypedString}\\n */\\nclass SafeStyle {\\n /**\\n * @param {string} value\\n * @param {!Object} token package-internal implementation detail.\\n */\\n constructor(value, token) {\\n /**\\n * The contained value of this SafeStyle. The field has a purposely\\n * ugly name to make (non-compiled) code that attempts to directly access\\n * this field stand out.\\n * @private {string}\\n */\\n this.privateDoNotAccessOrElseSafeStyleWrappedValue_ =\\n (token === CONSTRUCTOR_TOKEN_PRIVATE) ? value : '';\\n\\n /**\\n * @override\\n * @const {boolean}\\n */\\n this.implementsGoogStringTypedString = true;\\n }\\n\\n\\n /**\\n * Creates a SafeStyle object from a compile-time constant string.\\n *\\n * `style` should be in the format\\n * `name: value; [name: value; ...]` and must not have any < or >\\n * characters in it. This is so that SafeStyle's contract is preserved,\\n * allowing the SafeStyle to correctly be interpreted as a sequence of CSS\\n * declarations and without affecting the syntactic structure of any\\n * surrounding CSS and HTML.\\n *\\n * This method performs basic sanity checks on the format of `style`\\n * but does not constrain the format of `name` and `value`, except\\n * for disallowing tag characters.\\n *\\n * @param {!Const} style A compile-time-constant string from which\\n * to create a SafeStyle.\\n * @return {!SafeStyle} A SafeStyle object initialized to\\n * `style`.\\n */\\n static fromConstant(style) {\\n const styleString = Const.unwrap(style);\\n if (styleString.length === 0) {\\n return SafeStyle.EMPTY;\\n }\\n assert(\\n endsWith(styleString, ';'),\\n `Last character of style string is not ';': ${styleString}`);\\n assert(\\n contains(styleString, ':'),\\n 'Style string must contain at least one \\\\':\\\\', to ' +\\n 'specify a \\\"name: value\\\" pair: ' + styleString);\\n return SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(\\n styleString);\\n };\\n\\n\\n /**\\n * Returns this SafeStyle's value as a string.\\n *\\n * IMPORTANT: In code where it is security relevant that an object's type is\\n * indeed `SafeStyle`, use `SafeStyle.unwrap` instead of\\n * this method. If in doubt, assume that it's security relevant. In\\n * particular, note that goog.html functions which return a goog.html type do\\n * not guarantee the returned instance is of the right type. For example:\\n *\\n * <pre>\\n * var fakeSafeHtml = new String('fake');\\n * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;\\n * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);\\n * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by\\n * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml\\n * // instanceof goog.html.SafeHtml.\\n * </pre>\\n *\\n * @return {string}\\n * @see SafeStyle#unwrap\\n * @override\\n */\\n getTypedStringValue() {\\n return this.privateDoNotAccessOrElseSafeStyleWrappedValue_;\\n }\\n\\n\\n /**\\n * Returns a string-representation of this value.\\n *\\n * To obtain the actual string value wrapped in a SafeStyle, use\\n * `SafeStyle.unwrap`.\\n *\\n * @return {string}\\n * @see SafeStyle#unwrap\\n * @override\\n */\\n toString() {\\n return this.privateDoNotAccessOrElseSafeStyleWrappedValue_.toString();\\n }\\n\\n\\n /**\\n * Performs a runtime check that the provided object is indeed a\\n * SafeStyle object, and returns its value.\\n *\\n * @param {!SafeStyle} safeStyle The object to extract from.\\n * @return {string} The safeStyle object's contained string, unless\\n * the run-time type check fails. In that case, `unwrap` returns an\\n * innocuous string, or, if assertions are enabled, throws\\n * `AssertionError`.\\n */\\n static unwrap(safeStyle) {\\n // Perform additional Run-time type-checking to ensure that\\n // safeStyle is indeed an instance of the expected type. This\\n // provides some additional protection against security bugs due to\\n // application code that disables type checks.\\n // Specifically, the following checks are performed:\\n // 1. The object is an instance of the expected type.\\n // 2. The object is not an instance of a subclass.\\n if (safeStyle instanceof SafeStyle && safeStyle.constructor === SafeStyle) {\\n return safeStyle.privateDoNotAccessOrElseSafeStyleWrappedValue_;\\n } else {\\n fail(\\n `expected object of type SafeStyle, got '${safeStyle}` +\\n '\\\\' of type ' + goog.typeOf(safeStyle));\\n return 'type_error:SafeStyle';\\n }\\n }\\n\\n\\n /**\\n * Package-internal utility method to create SafeStyle instances.\\n *\\n * @param {string} style The string to initialize the SafeStyle object with.\\n * @return {!SafeStyle} The initialized SafeStyle object.\\n * @package\\n */\\n static createSafeStyleSecurityPrivateDoNotAccessOrElse(style) {\\n return new SafeStyle(style, CONSTRUCTOR_TOKEN_PRIVATE);\\n }\\n\\n /**\\n * Creates a new SafeStyle object from the properties specified in the map.\\n * @param {!SafeStyle.PropertyMap} map Mapping of property names to\\n * their values, for example {'margin': '1px'}. Names must consist of\\n * [-_a-zA-Z0-9]. Values might be strings consisting of\\n * [-,.'\\\"%_!# a-zA-Z0-9[\\\\]], where \\\", ', and [] must be properly balanced.\\n * We also allow simple functions like rgb() and url() which sanitizes its\\n * contents. Other values must be wrapped in Const. URLs might\\n * be passed as SafeUrl which will be wrapped into url(\\\"\\\"). We\\n * also support array whose elements are joined with ' '. Null value\\n * causes skipping the property.\\n * @return {!SafeStyle}\\n * @throws {!Error} If invalid name is provided.\\n * @throws {!AssertionError} If invalid value is provided. With\\n * disabled assertions, invalid value is replaced by\\n * SafeStyle.INNOCUOUS_STRING.\\n */\\n static create(map) {\\n let style = '';\\n for (let name in map) {\\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty#Using_hasOwnProperty_as_a_property_name\\n if (Object.prototype.hasOwnProperty.call(map, name)) {\\n if (!/^[-_a-zA-Z0-9]+$/.test(name)) {\\n throw new Error(`Name allows only [-_a-zA-Z0-9], got: ${name}`);\\n }\\n let value = map[name];\\n if (value == null) {\\n continue;\\n }\\n if (Array.isArray(value)) {\\n value = value.map(sanitizePropertyValue).join(' ');\\n } else {\\n value = sanitizePropertyValue(value);\\n }\\n style += `${name}:${value};`;\\n }\\n }\\n if (!style) {\\n return SafeStyle.EMPTY;\\n }\\n return SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(style);\\n };\\n\\n /**\\n * Creates a new SafeStyle object by concatenating the values.\\n * @param {...(!SafeStyle|!Array<!SafeStyle>)} var_args\\n * SafeStyles to concatenate.\\n * @return {!SafeStyle}\\n */\\n static concat(var_args) {\\n let style = '';\\n\\n /**\\n * @param {!SafeStyle|!Array<!SafeStyle>} argument\\n */\\n const addArgument = argument => {\\n if (Array.isArray(argument)) {\\n argument.forEach(addArgument);\\n } else {\\n style += SafeStyle.unwrap(argument);\\n }\\n };\\n\\n Array.prototype.forEach.call(arguments, addArgument);\\n if (!style) {\\n return SafeStyle.EMPTY;\\n }\\n return SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(style);\\n };\\n}\\n\\n/**\\n * A SafeStyle instance corresponding to the empty string.\\n * @const {!SafeStyle}\\n */\\nSafeStyle.EMPTY = SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse('');\\n\\n\\n/**\\n * The innocuous string generated by SafeStyle.create when passed\\n * an unsafe value.\\n * @const {string}\\n */\\nSafeStyle.INNOCUOUS_STRING = 'zClosurez';\\n\\n\\n/**\\n * A single property value.\\n * @typedef {string|!Const|!SafeUrl}\\n */\\nSafeStyle.PropertyValue;\\n\\n\\n/**\\n * Mapping of property names to their values.\\n * We don't support numbers even though some values might be numbers (e.g.\\n * line-height or 0 for any length). The reason is that most numeric values need\\n * units (e.g. '1px') and allowing numbers could cause users forgetting about\\n * them.\\n * @typedef {!Object<string, ?SafeStyle.PropertyValue|\\n * ?Array<!SafeStyle.PropertyValue>>}\\n */\\nSafeStyle.PropertyMap;\\n\\n\\n\\n/**\\n * Checks and converts value to string.\\n * @param {!SafeStyle.PropertyValue} value\\n * @return {string}\\n */\\nfunction sanitizePropertyValue(value) {\\n if (value instanceof SafeUrl) {\\n const url = SafeUrl.unwrap(value);\\n return 'url(\\\"' + url.replace(/</g, '%3c').replace(/[\\\\\\\\\\\"]/g, '\\\\\\\\$&') + '\\\")';\\n }\\n const result = value instanceof Const ?\\n Const.unwrap(value) :\\n sanitizePropertyValueString(String(value));\\n // These characters can be used to change context and we don't want that even\\n // with const values.\\n if (/[{;}]/.test(result)) {\\n throw new AssertionError('Value does not allow [{;}], got: %s.', [result]);\\n }\\n return result;\\n}\\n\\n\\n/**\\n * Checks string value.\\n * @param {string} value\\n * @return {string}\\n */\\nfunction sanitizePropertyValueString(value) {\\n // Some CSS property values permit nested functions. We allow one level of\\n // nesting, and all nested functions must also be in the FUNCTIONS_RE_ list.\\n const valueWithoutFunctions = value.replace(FUNCTIONS_RE, '$1')\\n .replace(FUNCTIONS_RE, '$1')\\n .replace(URL_RE, 'url');\\n if (!VALUE_RE.test(valueWithoutFunctions)) {\\n fail(\\n `String value allows only ${VALUE_ALLOWED_CHARS}` +\\n ' and simple functions, got: ' + value);\\n return SafeStyle.INNOCUOUS_STRING;\\n } else if (COMMENT_RE.test(value)) {\\n fail(`String value disallows comments, got: ${value}`);\\n return SafeStyle.INNOCUOUS_STRING;\\n } else if (!hasBalancedQuotes(value)) {\\n fail(`String value requires balanced quotes, got: ${value}`);\\n return SafeStyle.INNOCUOUS_STRING;\\n } else if (!hasBalancedSquareBrackets(value)) {\\n fail(\\n 'String value requires balanced square brackets and one' +\\n ' identifier per pair of brackets, got: ' + value);\\n return SafeStyle.INNOCUOUS_STRING;\\n }\\n return sanitizeUrl(value);\\n}\\n\\n\\n/**\\n * Checks that quotes (\\\" and ') are properly balanced inside a string. Assumes\\n * that neither escape (\\\\) nor any other character that could result in\\n * breaking out of a string parsing context are allowed;\\n * see http://www.w3.org/TR/css3-syntax/#string-token-diagram.\\n * @param {string} value Untrusted CSS property value.\\n * @return {boolean} True if property value is safe with respect to quote\\n * balancedness.\\n */\\nfunction hasBalancedQuotes(value) {\\n let outsideSingle = true;\\n let outsideDouble = true;\\n for (let i = 0; i < value.length; i++) {\\n const c = value.charAt(i);\\n if (c == '\\\\'' && outsideDouble) {\\n outsideSingle = !outsideSingle;\\n } else if (c == '\\\"' && outsideSingle) {\\n outsideDouble = !outsideDouble;\\n }\\n }\\n return outsideSingle && outsideDouble;\\n}\\n\\n\\n/**\\n * Checks that square brackets ([ and ]) are properly balanced inside a string,\\n * and that the content in the square brackets is one ident-token;\\n * see https://www.w3.org/TR/css-syntax-3/#ident-token-diagram.\\n * For practicality, and in line with other restrictions posed on SafeStyle\\n * strings, we restrict the character set allowable in the ident-token to\\n * [-_a-zA-Z0-9].\\n * @param {string} value Untrusted CSS property value.\\n * @return {boolean} True if property value is safe with respect to square\\n * bracket balancedness.\\n */\\nfunction hasBalancedSquareBrackets(value) {\\n let outside = true;\\n const tokenRe = /^[-_a-zA-Z0-9]$/;\\n for (let i = 0; i < value.length; i++) {\\n const c = value.charAt(i);\\n if (c == ']') {\\n if (outside) return false; // Unbalanced ].\\n outside = true;\\n } else if (c == '[') {\\n if (!outside) return false; // No nesting.\\n outside = false;\\n } else if (!outside && !tokenRe.test(c)) {\\n return false;\\n }\\n }\\n return outside;\\n}\\n\\n\\n/**\\n * Characters allowed in VALUE_RE.\\n * @type {string}\\n */\\nconst VALUE_ALLOWED_CHARS = '[-+,.\\\"\\\\'%_!#/ a-zA-Z0-9\\\\\\\\[\\\\\\\\]]';\\n\\n\\n/**\\n * Regular expression for safe values.\\n * Quotes (\\\" and ') are allowed, but a check must be done elsewhere to ensure\\n * they're balanced.\\n * Square brackets ([ and ]) are allowed, but a check must be done elsewhere\\n * to ensure they're balanced. The content inside a pair of square brackets must\\n * be one alphanumeric identifier.\\n * ',' allows multiple values to be assigned to the same property\\n * (e.g. background-attachment or font-family) and hence could allow\\n * multiple values to get injected, but that should pose no risk of XSS.\\n * The expression checks only for XSS safety, not for CSS validity.\\n * @const {!RegExp}\\n */\\nconst VALUE_RE = new RegExp(`^${VALUE_ALLOWED_CHARS}+\\\\$`);\\n\\n\\n/**\\n * Regular expression for url(). We support URLs allowed by\\n * https://www.w3.org/TR/css-syntax-3/#url-token-diagram without using escape\\n * sequences. Use percent-encoding if you need to use special characters like\\n * backslash.\\n * @const {!RegExp}\\n */\\nconst URL_RE = new RegExp(\\n '\\\\\\\\b(url\\\\\\\\([ \\\\t\\\\n]*)(' +\\n '\\\\'[ -&(-\\\\\\\\[\\\\\\\\]-~]*\\\\'' + // Printable characters except ' and \\\\.\\n '|\\\"[ !#-\\\\\\\\[\\\\\\\\]-~]*\\\"' + // Printable characters except \\\" and \\\\.\\n '|[!#-&*-\\\\\\\\[\\\\\\\\]-~]*' + // Printable characters except [ \\\"'()\\\\\\\\].\\n ')([ \\\\t\\\\n]*\\\\\\\\))',\\n 'g');\\n\\n/**\\n * Names of functions allowed in FUNCTIONS_RE.\\n * @const {!Array<string>}\\n */\\nconst ALLOWED_FUNCTIONS = [\\n 'calc',\\n 'cubic-bezier',\\n 'fit-content',\\n 'hsl',\\n 'hsla',\\n 'linear-gradient',\\n 'matrix',\\n 'minmax',\\n 'radial-gradient',\\n 'repeat',\\n 'rgb',\\n 'rgba',\\n '(rotate|scale|translate)(X|Y|Z|3d)?',\\n 'steps',\\n 'var',\\n];\\n\\n\\n/**\\n * Regular expression for simple functions.\\n * @const {!RegExp}\\n */\\nconst FUNCTIONS_RE = new RegExp(\\n '\\\\\\\\b(' + ALLOWED_FUNCTIONS.join('|') + ')' +\\n '\\\\\\\\([-+*/0-9a-zA-Z.%#\\\\\\\\[\\\\\\\\], ]+\\\\\\\\)',\\n 'g');\\n\\n\\n/**\\n * Regular expression for comments. These are disallowed in CSS property values.\\n * @const {!RegExp}\\n */\\nconst COMMENT_RE = /\\\\/\\\\*/;\\n\\n\\n/**\\n * Sanitize URLs inside url().\\n * NOTE: We could also consider using CSS.escape once that's available in the\\n * browsers. However, loosely matching URL e.g. with url\\\\(.*\\\\) and then escaping\\n * the contents would result in a slightly different language than CSS leading\\n * to confusion of users. E.g. url(\\\")\\\") is valid in CSS but it would be invalid\\n * as seen by our parser. On the other hand, url(\\\\) is invalid in CSS but our\\n * parser would be fine with it.\\n * @param {string} value Untrusted CSS property value.\\n * @return {string}\\n */\\nfunction sanitizeUrl(value) {\\n return value.replace(URL_RE, (match, before, url, after) => {\\n let quote = '';\\n url = url.replace(/^(['\\\"])(.*)\\\\1$/, (match, start, inside) => {\\n quote = start;\\n return inside;\\n });\\n const sanitized = SafeUrl.sanitize(url).getTypedStringValue();\\n return before + quote + sanitized + quote + after;\\n });\\n}\\n\\n\\nexports = SafeStyle;\\n\"],\n\"names\":[\"goog\",\"module\",\"declareLegacyNamespace\",\"Const\",\"require\",\"SafeUrl\",\"TypedString\",\"AssertionError\",\"assert\",\"fail\",\"contains\",\"endsWith\",\"CONSTRUCTOR_TOKEN_PRIVATE\",\"SafeStyle\",\"constructor\",\"value\",\"token\",\"privateDoNotAccessOrElseSafeStyleWrappedValue_\",\"implementsGoogStringTypedString\",\"fromConstant\",\"style\",\"styleString\",\"unwrap\",\"length\",\"EMPTY\",\"createSafeStyleSecurityPrivateDoNotAccessOrElse\",\"getTypedStringValue\",\"toString\",\"safeStyle\",\"typeOf\",\"create\",\"map\",\"name\",\"Object\",\"prototype\",\"hasOwnProperty\",\"call\",\"test\",\"Error\",\"Array\",\"isArray\",\"sanitizePropertyValue\",\"join\",\"concat\",\"var_args\",\"addArgument\",\"argument\",\"forEach\",\"arguments\",\"INNOCUOUS_STRING\",\"PropertyValue\",\"PropertyMap\",\"url\",\"replace\",\"result\",\"sanitizePropertyValueString\",\"String\",\"valueWithoutFunctions\",\"FUNCTIONS_RE\",\"URL_RE\",\"VALUE_RE\",\"VALUE_ALLOWED_CHARS\",\"COMMENT_RE\",\"hasBalancedQuotes\",\"hasBalancedSquareBrackets\",\"sanitizeUrl\",\"outsideSingle\",\"outsideDouble\",\"i\",\"c\",\"charAt\",\"outside\",\"tokenRe\",\"RegExp\",\"ALLOWED_FUNCTIONS\",\"match\",\"before\",\"after\",\"quote\",\"start\",\"inside\",\"sanitized\",\"sanitize\",\"exports\"]\n}\n"] |