178 lines
5.3 KiB
JavaScript
178 lines
5.3 KiB
JavaScript
|
|
/*! 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));
|