cssesc-3.0.0/ 0000775 0000000 0000000 00000000000 13426064560 0013003 5 ustar 00root root 0000000 0000000 cssesc-3.0.0/.babelrc 0000664 0000000 0000000 00000000241 13426064560 0014373 0 ustar 00root root 0000000 0000000 {
"presets": [
["env", {
"targets": {
"node": "4.0",
"browsers": ["last 2 versions", "safari >= 7", "ie >= 11"]
}
}]
]
}
cssesc-3.0.0/.editorconfig 0000664 0000000 0000000 00000000327 13426064560 0015462 0 ustar 00root root 0000000 0000000 root = true
[*]
charset = utf-8
indent_style = tab
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[{README.md,package.json,.travis.yml,.babelrc}]
indent_style = space
indent_size = 2
cssesc-3.0.0/.gitattributes 0000664 0000000 0000000 00000000114 13426064560 0015672 0 ustar 00root root 0000000 0000000 # Automatically normalize line endings for all text-based files
* text=auto
cssesc-3.0.0/.gitignore 0000664 0000000 0000000 00000000405 13426064560 0014772 0 ustar 00root root 0000000 0000000 # JSON version of coverage report
coverage/coverage.json
# Installed npm modules
node_modules
# Folder view configuration files
.DS_Store
Desktop.ini
# Thumbnail cache files
._*
Thumbs.db
# Files that might appear on external disks
.Spotlight-V100
.Trashes
cssesc-3.0.0/.travis.yml 0000664 0000000 0000000 00000000300 13426064560 0015105 0 ustar 00root root 0000000 0000000 sudo: false
language: node_js
node_js:
- "4"
- "5"
- "6"
after_script:
- 'istanbul cover --report html node_modules/.bin/_mocha tests -- -u exports -R spec && codecov'
git:
depth: 1
cssesc-3.0.0/Gruntfile.js 0000664 0000000 0000000 00000000602 13426064560 0015276 0 ustar 00root root 0000000 0000000 module.exports = function(grunt) {
grunt.initConfig({
'template': {
'build': {
'options': {
// Generate the regular expressions dynamically using Regenerate.
'data': require('./src/data.js')
},
'files': {
'cssesc.js': ['src/cssesc.js']
}
}
}
});
grunt.loadNpmTasks('grunt-template');
grunt.registerTask('default', [
'template'
]);
};
cssesc-3.0.0/LICENSE-MIT.txt 0000664 0000000 0000000 00000002065 13426064560 0015260 0 ustar 00root root 0000000 0000000 Copyright Mathias Bynens
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cssesc-3.0.0/README.md 0000664 0000000 0000000 00000014671 13426064560 0014273 0 ustar 00root root 0000000 0000000 # cssesc [](https://travis-ci.org/mathiasbynens/cssesc) [](https://codecov.io/gh/mathiasbynens/cssesc)
A JavaScript library for escaping CSS strings and identifiers while generating the shortest possible ASCII-only output.
This is a JavaScript library for [escaping text for use in CSS strings or identifiers](https://mathiasbynens.be/notes/css-escapes) while generating the shortest possible valid ASCII-only output. [Here’s an online demo.](https://mothereff.in/css-escapes)
[A polyfill for the CSSOM `CSS.escape()` method is available in a separate repository.](https://mths.be/cssescape) (In comparison, _cssesc_ is much more powerful.)
Feel free to fork if you see possible improvements!
## Installation
Via [npm](https://www.npmjs.com/):
```bash
npm install cssesc
```
In a browser:
```html
```
In [Node.js](https://nodejs.org/):
```js
const cssesc = require('cssesc');
```
In Ruby using [the `ruby-cssesc` wrapper gem](https://github.com/borodean/ruby-cssesc):
```bash
gem install ruby-cssesc
```
```ruby
require 'ruby-cssesc'
CSSEsc.escape('I ♥ Ruby', is_identifier: true)
```
In Sass using [`sassy-escape`](https://github.com/borodean/sassy-escape):
```bash
gem install sassy-escape
```
```scss
body {
content: escape('I ♥ Sass', $is-identifier: true);
}
```
## API
### `cssesc(value, options)`
This function takes a value and returns an escaped version of the value where any characters that are not printable ASCII symbols are escaped using the shortest possible (but valid) [escape sequences for use in CSS strings or identifiers](https://mathiasbynens.be/notes/css-escapes).
```js
cssesc('Ich ♥ Bücher');
// → 'Ich \\2665 B\\FC cher'
cssesc('foo 𝌆 bar');
// → 'foo \\1D306 bar'
```
By default, `cssesc` returns a string that can be used as part of a CSS string. If the target is a CSS identifier rather than a CSS string, use the `isIdentifier: true` setting (see below).
The optional `options` argument accepts an object with the following options:
#### `isIdentifier`
The default value for the `isIdentifier` option is `false`. This means that the input text will be escaped for use in a CSS string literal. If you want to use the result as a CSS identifier instead (in a selector, for example), set this option to `true`.
```js
cssesc('123a2b');
// → '123a2b'
cssesc('123a2b', {
'isIdentifier': true
});
// → '\\31 23a2b'
```
#### `quotes`
The default value for the `quotes` option is `'single'`. This means that any occurences of `'` in the input text will be escaped as `\'`, so that the output can be used in a CSS string literal wrapped in single quotes.
```js
cssesc('Lorem ipsum "dolor" sit \'amet\' etc.');
// → 'Lorem ipsum "dolor" sit \\\'amet\\\' etc.'
// → "Lorem ipsum \"dolor\" sit \\'amet\\' etc."
cssesc('Lorem ipsum "dolor" sit \'amet\' etc.', {
'quotes': 'single'
});
// → 'Lorem ipsum "dolor" sit \\\'amet\\\' etc.'
// → "Lorem ipsum \"dolor\" sit \\'amet\\' etc."
```
If you want to use the output as part of a CSS string literal wrapped in double quotes, set the `quotes` option to `'double'`.
```js
cssesc('Lorem ipsum "dolor" sit \'amet\' etc.', {
'quotes': 'double'
});
// → 'Lorem ipsum \\"dolor\\" sit \'amet\' etc.'
// → "Lorem ipsum \\\"dolor\\\" sit 'amet' etc."
```
#### `wrap`
The `wrap` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, the output will be a valid CSS string literal wrapped in quotes. The type of quotes can be specified through the `quotes` setting.
```js
cssesc('Lorem ipsum "dolor" sit \'amet\' etc.', {
'quotes': 'single',
'wrap': true
});
// → '\'Lorem ipsum "dolor" sit \\\'amet\\\' etc.\''
// → "\'Lorem ipsum \"dolor\" sit \\\'amet\\\' etc.\'"
cssesc('Lorem ipsum "dolor" sit \'amet\' etc.', {
'quotes': 'double',
'wrap': true
});
// → '"Lorem ipsum \\"dolor\\" sit \'amet\' etc."'
// → "\"Lorem ipsum \\\"dolor\\\" sit \'amet\' etc.\""
```
#### `escapeEverything`
The `escapeEverything` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, all the symbols in the output will be escaped, even printable ASCII symbols.
```js
cssesc('lolwat"foo\'bar', {
'escapeEverything': true
});
// → '\\6C\\6F\\6C\\77\\61\\74\\"\\66\\6F\\6F\\\'\\62\\61\\72'
// → "\\6C\\6F\\6C\\77\\61\\74\\\"\\66\\6F\\6F\\'\\62\\61\\72"
```
#### Overriding the default options globally
The global default settings can be overridden by modifying the `css.options` object. This saves you from passing in an `options` object for every call to `encode` if you want to use the non-default setting.
```js
// Read the global default setting for `escapeEverything`:
cssesc.options.escapeEverything;
// → `false` by default
// Override the global default setting for `escapeEverything`:
cssesc.options.escapeEverything = true;
// Using the global default setting for `escapeEverything`, which is now `true`:
cssesc('foo © bar ≠ baz 𝌆 qux');
// → '\\66\\6F\\6F\\ \\A9\\ \\62\\61\\72\\ \\2260\\ \\62\\61\\7A\\ \\1D306\\ \\71\\75\\78'
```
### `cssesc.version`
A string representing the semantic version number.
### Using the `cssesc` binary
To use the `cssesc` binary in your shell, simply install cssesc globally using npm:
```bash
npm install -g cssesc
```
After that you will be able to escape text for use in CSS strings or identifiers from the command line:
```bash
$ cssesc 'föo ♥ bår 𝌆 baz'
f\F6o \2665 b\E5r \1D306 baz
```
If the output needs to be a CSS identifier rather than part of a string literal, use the `-i`/`--identifier` option:
```bash
$ cssesc --identifier 'föo ♥ bår 𝌆 baz'
f\F6o\ \2665\ b\E5r\ \1D306\ baz
```
See `cssesc --help` for the full list of options.
## Support
This library supports the Node.js and browser versions mentioned in [`.babelrc`](https://github.com/mathiasbynens/cssesc/blob/master/.babelrc). For a version that supports a wider variety of legacy browsers and environments out-of-the-box, [see v0.1.0](https://github.com/mathiasbynens/cssesc/releases/tag/v0.1.0).
## Author
| [](https://twitter.com/mathias "Follow @mathias on Twitter") |
|---|
| [Mathias Bynens](https://mathiasbynens.be/) |
## License
This library is available under the [MIT](https://mths.be/mit) license.
cssesc-3.0.0/bin/ 0000775 0000000 0000000 00000000000 13426064560 0013553 5 ustar 00root root 0000000 0000000 cssesc-3.0.0/bin/cssesc 0000775 0000000 0000000 00000006037 13426064560 0014772 0 ustar 00root root 0000000 0000000 #!/usr/bin/env node
const fs = require('fs');
const cssesc = require('../cssesc.js');
const strings = process.argv.splice(2);
const stdin = process.stdin;
const options = {};
const log = console.log;
const main = function() {
const option = strings[0];
if (/^(?:-h|--help|undefined)$/.test(option)) {
log(
'cssesc v%s - https://mths.be/cssesc',
cssesc.version
);
log([
'\nUsage:\n',
'\tcssesc [string]',
'\tcssesc [-i | --identifier] [string]',
'\tcssesc [-s | --single-quotes] [string]',
'\tcssesc [-d | --double-quotes] [string]',
'\tcssesc [-w | --wrap] [string]',
'\tcssesc [-e | --escape-everything] [string]',
'\tcssesc [-v | --version]',
'\tcssesc [-h | --help]',
'\nExamples:\n',
'\tcssesc \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\'',
'\tcssesc --identifier \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\'',
'\tcssesc --escape-everything \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\'',
'\tcssesc --double-quotes --wrap \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\'',
'\techo \'f\xF6o \u2665 b\xE5r \uD834\uDF06 baz\' | cssesc'
].join('\n'));
return process.exit(1);
}
if (/^(?:-v|--version)$/.test(option)) {
log('v%s', cssesc.version);
return process.exit(1);
}
strings.forEach(function(string) {
// Process options
if (/^(?:-i|--identifier)$/.test(string)) {
options.isIdentifier = true;
return;
}
if (/^(?:-s|--single-quotes)$/.test(string)) {
options.quotes = 'single';
return;
}
if (/^(?:-d|--double-quotes)$/.test(string)) {
options.quotes = 'double';
return;
}
if (/^(?:-w|--wrap)$/.test(string)) {
options.wrap = true;
return;
}
if (/^(?:-e|--escape-everything)$/.test(string)) {
options.escapeEverything = true;
return;
}
// Process string(s)
let result;
try {
result = cssesc(string, options);
log(result);
} catch (exception) {
log(exception.message + '\n');
log('Error: failed to escape.');
log('If you think this is a bug in cssesc, please report it:');
log('https://github.com/mathiasbynens/cssesc/issues/new');
log(
'\nStack trace using cssesc@%s:\n',
cssesc.version
);
log(exception.stack);
return process.exit(1);
}
});
// Return with exit status 0 outside of the `forEach` loop, in case
// multiple strings were passed in.
return process.exit(0);
};
if (stdin.isTTY) {
// handle shell arguments
main();
} else {
let timeout;
// Either the script is called from within a non-TTY context, or `stdin`
// content is being piped in.
if (!process.stdout.isTTY) {
// The script was called from a non-TTY context. This is a rather uncommon
// use case we don’t actively support. However, we don’t want the script
// to wait forever in such cases, so…
timeout = setTimeout(function() {
// …if no piped data arrived after a whole minute, handle shell
// arguments instead.
main();
}, 60000);
}
let data = '';
stdin.on('data', function(chunk) {
clearTimeout(timeout);
data += chunk;
});
stdin.on('end', function() {
strings.push(data.trim());
main();
});
stdin.resume();
}
cssesc-3.0.0/cssesc.js 0000664 0000000 0000000 00000006672 13426064560 0014637 0 ustar 00root root 0000000 0000000 /*! https://mths.be/cssesc v3.0.0 by @mathias */
'use strict';
var object = {};
var hasOwnProperty = object.hasOwnProperty;
var merge = function merge(options, defaults) {
if (!options) {
return defaults;
}
var result = {};
for (var 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 = /[ -,\.\/:-@\[-\^`\{-~]/;
var regexSingleEscape = /[ -,\.\/:-@\[\]\^`\{-~]/;
var regexAlwaysEscape = /['"\\]/;
var regexExcessiveSpaces = /(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g;
// https://mathiasbynens.be/notes/css-escapes#css
var cssesc = function cssesc(string, 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;
while (counter < length) {
var character = string.charAt(counter++);
var codePoint = character.charCodeAt();
var value = void 0;
// If it’s not a printable ASCII character…
if (codePoint < 0x20 || codePoint > 0x7E) {
if (codePoint >= 0xD800 && codePoint <= 0xDBFF && counter < length) {
// It’s a high surrogate, and there is a next character.
var extra = string.charCodeAt(counter++);
if ((extra & 0xFC00) == 0xDC00) {
// next character is low surrogate
codePoint = ((codePoint & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000;
} else {
// It’s an 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() + ' ';
}
} else if (/[\t\n\f\r\x0B]/.test(character)) {
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 (/^-[-\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 = '3.0.0';
module.exports = cssesc;
cssesc-3.0.0/man/ 0000775 0000000 0000000 00000000000 13426064560 0013556 5 ustar 00root root 0000000 0000000 cssesc-3.0.0/man/cssesc.1 0000664 0000000 0000000 00000003645 13426064560 0015133 0 ustar 00root root 0000000 0000000 .Dd August 9, 2013
.Dt cssesc 1
.Sh NAME
.Nm cssesc
.Nd escape text for use in CSS string literals or identifiers
.Sh SYNOPSIS
.Nm
.Op Fl i | -identifier Ar string
.br
.Op Fl s | -single-quotes Ar string
.br
.Op Fl d | -double-quotes Ar string
.br
.Op Fl w | -wrap Ar string
.br
.Op Fl e | -escape-everything Ar string
.br
.Op Fl v | -version
.br
.Op Fl h | -help
.Sh DESCRIPTION
.Nm
escapes strings for use in CSS string literals or identifiers while generating the shortest possible valid ASCII-only output.
.Sh OPTIONS
.Bl -ohang -offset
.It Sy "-s, --single-quotes"
Escape any occurences of ' in the input string as \\', so that the output can be used in a CSS string literal wrapped in single quotes.
.It Sy "-d, --double-quotes"
Escape any occurences of " in the input string as \\", so that the output can be used in a CSS string literal wrapped in double quotes.
.It Sy "-w, --wrap"
Make sure the output is a valid CSS string literal wrapped in quotes. The type of quotes can be specified using the
.Ar -s | --single-quotes
or
.Ar -d | --double-quotes
settings.
.It Sy "-e, --escape-everything"
Escape all the symbols in the output, even printable ASCII symbols.
.It Sy "-v, --version"
Print cssesc's version.
.It Sy "-h, --help"
Show the help screen.
.El
.Sh EXIT STATUS
The
.Nm cssesc
utility exits with one of the following values:
.Pp
.Bl -tag -width flag -compact
.It Li 0
.Nm
successfully escaped the given text and printed the result.
.It Li 1
.Nm
wasn't instructed to escape anything (for example, the
.Ar --help
flag was set); or, an error occurred.
.El
.Sh EXAMPLES
.Bl -ohang -offset
.It Sy "cssesc 'foo bar baz'"
Print an escaped version of the given text.
.It Sy echo\ 'foo bar baz'\ |\ cssesc
Print an escaped version of the text that gets piped in.
.El
.Sh BUGS
cssesc's bug tracker is located at .
.Sh AUTHOR
Mathias Bynens
.Sh WWW
cssesc-3.0.0/package.json 0000664 0000000 0000000 00000002344 13426064560 0015274 0 ustar 00root root 0000000 0000000 {
"name": "cssesc",
"version": "3.0.0",
"description": "A JavaScript library for escaping CSS strings and identifiers while generating the shortest possible ASCII-only output.",
"homepage": "https://mths.be/cssesc",
"engines": {
"node": ">=4"
},
"main": "cssesc.js",
"bin": "bin/cssesc",
"man": "man/cssesc.1",
"keywords": [
"css",
"escape",
"identifier",
"string",
"tool"
],
"license": "MIT",
"author": {
"name": "Mathias Bynens",
"url": "https://mathiasbynens.be/"
},
"repository": {
"type": "git",
"url": "https://github.com/mathiasbynens/cssesc.git"
},
"bugs": "https://github.com/mathiasbynens/cssesc/issues",
"files": [
"LICENSE-MIT.txt",
"cssesc.js",
"bin/",
"man/"
],
"scripts": {
"build": "grunt template && babel cssesc.js -o cssesc.js",
"test": "mocha tests",
"cover": "istanbul cover --report html node_modules/.bin/_mocha tests -- -u exports -R spec"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-preset-env": "^1.6.1",
"codecov": "^1.0.1",
"grunt": "^1.0.1",
"grunt-template": "^1.0.0",
"istanbul": "^0.4.4",
"mocha": "^2.5.3",
"regenerate": "^1.2.1",
"requirejs": "^2.1.16"
}
}
cssesc-3.0.0/src/ 0000775 0000000 0000000 00000000000 13426064560 0013572 5 ustar 00root root 0000000 0000000 cssesc-3.0.0/src/cssesc.js 0000664 0000000 0000000 00000007003 13426064560 0015413 0 ustar 00root root 0000000 0000000 /*! https://mths.be/cssesc v<%= version %> by @mathias */
'use strict';
const object = {};
const hasOwnProperty = object.hasOwnProperty;
const merge = (options, defaults) => {
if (!options) {
return defaults;
}
const result = {};
for (let 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;
};
const regexAnySingleEscape = /<%= anySingleEscape %>/;
const regexSingleEscape = /<%= singleEscapes %>/;
const regexAlwaysEscape = /['"\\]/;
const regexExcessiveSpaces = /(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g;
// https://mathiasbynens.be/notes/css-escapes#css
const cssesc = (string, options) => {
options = merge(options, cssesc.options);
if (options.quotes != 'single' && options.quotes != 'double') {
options.quotes = 'single';
}
const quote = options.quotes == 'double' ? '"' : '\'';
const isIdentifier = options.isIdentifier;
const firstChar = string.charAt(0);
let output = '';
let counter = 0;
const length = string.length;
while (counter < length) {
const character = string.charAt(counter++);
let codePoint = character.charCodeAt();
let value;
// If it’s not a printable ASCII character…
if (codePoint < 0x20 || codePoint > 0x7E) {
if (codePoint >= 0xD800 && codePoint <= 0xDBFF && counter < length) {
// It’s a high surrogate, and there is a next character.
const extra = string.charCodeAt(counter++);
if ((extra & 0xFC00) == 0xDC00) { // next character is low surrogate
codePoint = ((codePoint & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000;
} else {
// It’s an 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() + ' ';
}
} else if (/[\t\n\f\r\x0B]/.test(character)) {
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 (/^-[-\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 = '<%= version %>';
module.exports = cssesc;
cssesc-3.0.0/src/data.js 0000664 0000000 0000000 00000001034 13426064560 0015037 0 ustar 00root root 0000000 0000000 var regenerate = require('regenerate');
var fs = require('fs');
// Characters with special meaning in CSS, except for quotes and backslashes
// (they get a separate regex)
var set = regenerate().add(
' ', '!', '#', '$', '%', '&', '(', ')', '*', '+', ',', '.', '/', ';', '<', ':',
'=', '>', '?', '@', '[', ']', '^', '`', '{', '|', '}', '~', '"', '\'', '\\'
);
module.exports = {
'anySingleEscape': set.toString(),
'singleEscapes': set.remove('\\').toString(),
'version': JSON.parse(fs.readFileSync('package.json', 'utf8')).version
};
cssesc-3.0.0/tests/ 0000775 0000000 0000000 00000000000 13426064560 0014145 5 ustar 00root root 0000000 0000000 cssesc-3.0.0/tests/tests.js 0000664 0000000 0000000 00000010666 13426064560 0015656 0 ustar 00root root 0000000 0000000 'use strict';
const assert = require('assert');
const cssesc = require('../cssesc.js');
describe('common usage', () => {
it('works as expected', () => {
assert.equal(
typeof cssesc.version,
'string',
'`cssesc.version` must be a string'
);
assert.equal(
cssesc('-foo'),
'-foo',
'-foo'
);
assert.equal(
cssesc('--foo', { 'isIdentifier': false }),
'--foo',
'--foo with `isIdentifier: false`'
);
assert.equal(
cssesc('--foo', { 'isIdentifier': true }),
'\\--foo',
'--foo with `isIdentifier: true`'
);
assert.equal(
cssesc('-0foo', { 'isIdentifier': false }),
'-0foo',
'-0foo with `isIdentifier: false`'
);
assert.equal(
cssesc('-0foo', { 'isIdentifier': true }),
'\\-0foo',
'-0foo with `isIdentifier: true`'
);
assert.equal(
cssesc('-9foo', { 'isIdentifier': false }),
'-9foo',
'-9foo with `isIdentifier: false`'
);
assert.equal(
cssesc('-9foo', { 'isIdentifier': true }),
'\\-9foo',
'-9foo with `isIdentifier: true`'
);
assert.equal(
cssesc('foo:bar', { 'isIdentifier': false }),
'foo:bar',
'foo:bar with `isIdentifier: false`'
);
assert.equal(
cssesc('foo:bar', { 'isIdentifier': true }),
'foo\\:bar',
'foo:bar with `isIdentifier: true`'
);
assert.equal(
cssesc('_foo_bar', { 'isIdentifier': false }),
'_foo_bar',
'_foo_bar with `isIdentifier: false`'
);
assert.equal(
cssesc('_foo_bar', { 'isIdentifier': true }),
'_foo_bar',
'_foo_bar with `isIdentifier: true`'
);
assert.equal(
cssesc('a\t\n\v\f\rb'),
'a\\9\\A\\B\\C\\D b',
'whitespace characters'
);
assert.equal(
cssesc('\\A _'),
'\\\\A _',
'backslash escapes that look like a hex escape: space is preserved'
);
assert.equal(
cssesc('\\\\A _'),
'\\\\\\\\A _',
'backslash escapes that look like a hex escape: space is preserved'
);
assert.equal(
cssesc('a\\b'),
'a\\\\b',
'backslash'
);
assert.equal(
cssesc('-\\ABC -', { 'isIdentifier': false }),
'-\\\\ABC -',
'more backslashes with `isIdentifier: false`'
);
assert.equal(
cssesc('-\\ABC -', { 'isIdentifier': true }),
'-\\\\ABC\\ -',
'more backslashes with `isIdentifier: true`'
);
assert.equal(
cssesc('id"ent\'ifier', { 'isIdentifier': true }),
'id\\"ent\\\'ifier',
'quotes are escaped with `isIdentifier: true`'
);
assert.equal(
cssesc('a"b\'c\xA9d', { 'wrap': true }),
'\'a"b\\\'c\\A9 d\'',
'quotes with `wrap: true`'
);
assert.equal(
cssesc('a"b\'c\xA9d', { 'wrap': true, 'quotes': 'LOLWAT' }),
'\'a"b\\\'c\\A9 d\'',
'quotes with `wrap: true, quotes: \'LOLWAT\'` (incorrect value)'
);
assert.equal(
cssesc('a"b\'c\xA9d', { 'wrap': true, 'quotes': 'single' }),
'\'a"b\\\'c\\A9 d\'',
'quotes with `wrap: true, quotes: \'single\'`'
);
assert.equal(
cssesc('a"b\'c\xA9d', { 'wrap': true, 'quotes': 'double' }),
'"a\\"b\'c\\A9 d"',
'quotes with `wrap: true, quotes: \'double\'`'
);
assert.equal(
cssesc('a\xA9b'),
'a\\A9 b',
'non-ASCII symbol'
);
assert.equal(
cssesc('Ich \u2665 B\xFCcher'),
'Ich \\2665 B\\FC cher',
'non-ASCII symbols'
);
assert.equal(
cssesc('a123b'),
'a123b',
'numbers not at the start of the string'
);
assert.equal(
cssesc('123a2b', { 'isIdentifier': false }),
'123a2b',
'numbers at the start of the string with `isIdentifier: false`'
);
assert.equal(
cssesc('123a2b', { 'isIdentifier': true }),
'\\31 23a2b',
'numbers at the start of the string with `isIdentifier: true`'
);
assert.equal(
cssesc('1_23a2b', { 'isIdentifier': false }),
'1_23a2b',
'numbers at the start of the string with `isIdentifier: false`'
);
assert.equal(
cssesc('1_23a2b', { 'isIdentifier': true }),
'\\31_23a2b',
'numbers at the start of the string with `isIdentifier: true`'
);
assert.equal(
cssesc('foo\\bar', { 'isIdentifier': false }),
'foo\\\\bar',
'backslashes are escaped with `isIdentifier: false`'
);
assert.equal(
cssesc('foo\\bar', { 'isIdentifier': true }),
'foo\\\\bar',
'backslashes are escaped with `isIdentifier: true`'
);
assert.equal(
cssesc('a\uD834\uDF06b'),
'a\\1D306 b',
'astral symbol'
);
assert.equal(
cssesc('a\uD834b'),
'a\\D834 b',
'lone high surrogate'
);
assert.equal(
cssesc('lolwat"foo\'bar\xA9k', {
'escapeEverything': true
}),
'\\6C\\6F\\6C\\77\\61\\74\\"\\66\\6F\\6F\\\'\\62\\61\\72\\A9\\6B',
'`escapeEverything: true`'
);
});
});