178 lines
5.3 KiB
JavaScript
Vendored
178 lines
5.3 KiB
JavaScript
Vendored
/*! http://mths.be/cssesc v0.1.0 by @mathias */
|
||
;(function(root) {
|
||
|
||
// Detect free variables `exports`
|
||
var freeExports = typeof exports == 'object' && exports;
|
||
|
||
// Detect free variable `module`
|
||
var freeModule = typeof module == 'object' && module &&
|
||
module.exports == freeExports && module;
|
||
|
||
// Detect free variable `global`, from Node.js or Browserified code,
|
||
// and use it as `root`
|
||
var freeGlobal = typeof global == 'object' && global;
|
||
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
|
||
root = freeGlobal;
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
var object = {};
|
||
var hasOwnProperty = object.hasOwnProperty;
|
||
var merge = function(options, defaults) {
|
||
if (!options) {
|
||
return defaults;
|
||
}
|
||
var key;
|
||
var result = {};
|
||
for (key in defaults) {
|
||
// `if (defaults.hasOwnProperty(key) { … }` is not needed here, since
|
||
// only recognized option names are used
|
||
result[key] = hasOwnProperty.call(options, key)
|
||
? options[key]
|
||
: defaults[key];
|
||
}
|
||
return result;
|
||
};
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
var regexAnySingleEscape = /[\x20-\x2C\x2E\x2F\x3B-\x40\x5B-\x5E\x60\x7B-\x7E]/;
|
||
var regexSingleEscape = /[\x20\x21\x23-\x26\x28-\x2C\x2E\x2F\x3B-\x40\x5B\x5D\x5E\x60\x7B-\x7E]/;
|
||
var regexAlwaysEscape = /['"\\]/;
|
||
var regexExcessiveSpaces = /(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g;
|
||
|
||
// http://mathiasbynens.be/notes/css-escapes#css
|
||
var cssesc = function(string, options) {
|
||
|
||
// Handle options
|
||
options = merge(options, cssesc.options);
|
||
if (options.quotes != 'single' && options.quotes != 'double') {
|
||
options.quotes = 'single';
|
||
}
|
||
var quote = options.quotes == 'double' ? '"' : '\'';
|
||
var isIdentifier = options.isIdentifier;
|
||
|
||
var firstChar = string.charAt(0);
|
||
var output = '';
|
||
var counter = 0;
|
||
var length = string.length;
|
||
var value;
|
||
var character;
|
||
var codePoint;
|
||
var extra; // used for potential low surrogates
|
||
|
||
while (counter < length) {
|
||
character = string.charAt(counter++);
|
||
codePoint = character.charCodeAt();
|
||
// if it’s not a printable ASCII character
|
||
if (codePoint < 0x20 || codePoint > 0x7E) {
|
||
if (codePoint >= 0xD800 && codePoint <= 0xDBFF && counter < length) {
|
||
// high surrogate, and there is a next character
|
||
extra = string.charCodeAt(counter++);
|
||
if ((extra & 0xFC00) == 0xDC00) { // next character is low surrogate
|
||
codePoint = ((codePoint & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000;
|
||
} else {
|
||
// unmatched surrogate; only append this code unit, in case the next
|
||
// code unit is the high surrogate of a surrogate pair
|
||
counter--;
|
||
}
|
||
}
|
||
value = '\\' + codePoint.toString(16).toUpperCase() + ' ';
|
||
} else {
|
||
if (options.escapeEverything) {
|
||
if (regexAnySingleEscape.test(character)) {
|
||
value = '\\' + character;
|
||
} else {
|
||
value = '\\' + codePoint.toString(16).toUpperCase() + ' ';
|
||
}
|
||
// `:` can be escaped as `\:`, but that fails in IE < 8
|
||
} else if (/[\t\n\f\r\x0B:]/.test(character)) {
|
||
if (!isIdentifier && character == ':') {
|
||
value = character;
|
||
} else {
|
||
value = '\\' + codePoint.toString(16).toUpperCase() + ' ';
|
||
}
|
||
} else if (
|
||
character == '\\' ||
|
||
(
|
||
!isIdentifier &&
|
||
(
|
||
(character == '"' && quote == character) ||
|
||
(character == '\'' && quote == character)
|
||
)
|
||
) ||
|
||
(isIdentifier && regexSingleEscape.test(character))
|
||
) {
|
||
value = '\\' + character;
|
||
} else {
|
||
value = character;
|
||
}
|
||
}
|
||
output += value;
|
||
}
|
||
|
||
if (isIdentifier) {
|
||
if (/^_/.test(output)) {
|
||
// Prevent IE6 from ignoring the rule altogether (in case this is for an
|
||
// identifier used as a selector)
|
||
output = '\\_' + output.slice(1);
|
||
} else if (/^-[-\d]/.test(output)) {
|
||
output = '\\-' + output.slice(1);
|
||
} else if (/\d/.test(firstChar)) {
|
||
output = '\\3' + firstChar + ' ' + output.slice(1);
|
||
}
|
||
}
|
||
|
||
// Remove spaces after `\HEX` escapes that are not followed by a hex digit,
|
||
// since they’re redundant. Note that this is only possible if the escape
|
||
// sequence isn’t preceded by an odd number of backslashes.
|
||
output = output.replace(regexExcessiveSpaces, function($0, $1, $2) {
|
||
if ($1 && $1.length % 2) {
|
||
// it’s not safe to remove the space, so don’t
|
||
return $0;
|
||
}
|
||
// strip the space
|
||
return ($1 || '') + $2;
|
||
});
|
||
|
||
if (!isIdentifier && options.wrap) {
|
||
return quote + output + quote;
|
||
}
|
||
return output;
|
||
};
|
||
|
||
// Expose default options (so they can be overridden globally)
|
||
cssesc.options = {
|
||
'escapeEverything': false,
|
||
'isIdentifier': false,
|
||
'quotes': 'single',
|
||
'wrap': false
|
||
};
|
||
|
||
cssesc.version = '0.1.0';
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
// Some AMD build optimizers, like r.js, check for specific condition patterns
|
||
// like the following:
|
||
if (
|
||
typeof define == 'function' &&
|
||
typeof define.amd == 'object' &&
|
||
define.amd
|
||
) {
|
||
define(function() {
|
||
return cssesc;
|
||
});
|
||
} else if (freeExports && !freeExports.nodeType) {
|
||
if (freeModule) { // in Node.js or RingoJS v0.8.0+
|
||
freeModule.exports = cssesc;
|
||
} else { // in Narwhal or RingoJS v0.7.0-
|
||
freeExports.cssesc = cssesc;
|
||
}
|
||
} else { // in Rhino or a web browser
|
||
root.cssesc = cssesc;
|
||
}
|
||
|
||
}(this));
|