cssesc-3.0.0/000077500000000000000000000000001342606456000130035ustar00rootroot00000000000000cssesc-3.0.0/.babelrc000066400000000000000000000002411342606456000143730ustar00rootroot00000000000000{ "presets": [ ["env", { "targets": { "node": "4.0", "browsers": ["last 2 versions", "safari >= 7", "ie >= 11"] } }] ] } cssesc-3.0.0/.editorconfig000066400000000000000000000003271342606456000154620ustar00rootroot00000000000000root = 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/.gitattributes000066400000000000000000000001141342606456000156720ustar00rootroot00000000000000# Automatically normalize line endings for all text-based files * text=auto cssesc-3.0.0/.gitignore000066400000000000000000000004051342606456000147720ustar00rootroot00000000000000# 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.yml000066400000000000000000000003001342606456000151050ustar00rootroot00000000000000sudo: 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.js000066400000000000000000000006021342606456000152760ustar00rootroot00000000000000module.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.txt000066400000000000000000000020651342606456000152600ustar00rootroot00000000000000Copyright 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.md000066400000000000000000000146711342606456000142730ustar00rootroot00000000000000# cssesc [![Build status](https://travis-ci.org/mathiasbynens/cssesc.svg?branch=master)](https://travis-ci.org/mathiasbynens/cssesc) [![Code coverage status](https://img.shields.io/codecov/c/github/mathiasbynens/cssesc.svg)](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 | [![twitter/mathias](https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](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/000077500000000000000000000000001342606456000135535ustar00rootroot00000000000000cssesc-3.0.0/bin/cssesc000077500000000000000000000060371342606456000147720ustar00rootroot00000000000000#!/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.js000066400000000000000000000066721342606456000146370ustar00rootroot00000000000000/*! 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/000077500000000000000000000000001342606456000135565ustar00rootroot00000000000000cssesc-3.0.0/man/cssesc.1000066400000000000000000000036451342606456000151330ustar00rootroot00000000000000.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.json000066400000000000000000000023441342606456000152740ustar00rootroot00000000000000{ "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/000077500000000000000000000000001342606456000135725ustar00rootroot00000000000000cssesc-3.0.0/src/cssesc.js000066400000000000000000000070031342606456000154130ustar00rootroot00000000000000/*! 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.js000066400000000000000000000010341342606456000150370ustar00rootroot00000000000000var 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/000077500000000000000000000000001342606456000141455ustar00rootroot00000000000000cssesc-3.0.0/tests/tests.js000066400000000000000000000106661342606456000156560ustar00rootroot00000000000000'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`' ); }); });