diff --git a/.editorconfig b/.editorconfig index 8fbfd8a..c6c8b36 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,14 +2,8 @@ root = true [*] indent_style = space -indent_size = 4 +indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true - -[*.{json,mdastrc,eslintrc,sh}] -indent_size = 2 - -[*.md] -trim_trailing_whitespace = false diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 10aee2c..0000000 --- a/.eslintignore +++ /dev/null @@ -1,6 +0,0 @@ -build/ -components/ -coverage/ -build.js -stringify-entities.js -stringify-entities.min.js diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 4426f37..0000000 --- a/.eslintrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "eslint:recommended", - "rules": { - "quotes": [2, "single"] - } -} diff --git a/.gitignore b/.gitignore index 71b45f0..0a690e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ .DS_Store *.log -build/ -components/ coverage/ node_modules/ -build.js stringify-entities.js stringify-entities.min.js diff --git a/.jscs.json b/.jscs.json deleted file mode 100644 index 6fb8e69..0000000 --- a/.jscs.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "excludeFiles": [ - "build/", - "components/", - "coverage/", - "node_modules/", - "build.js", - "stringify-entities.js", - "stringify-entities.min.js" - ], - "preset": "yandex", - "requireQuotedKeysInObjects": true, - "disallowQuotedKeysInObjects": false, - "maximumLineLength": { - "value": 79, - "allExcept": [ - "regex", - "urlComments" - ] - }, - "jsDoc": { - "checkAnnotations": "jsdoc3", - "checkParamExistence": true, - "checkParamNames": true, - "checkRedundantAccess": true, - "checkRedundantParams": true, - "checkRedundantReturns": true, - "checkReturnTypes": true, - "checkTypes": "strictNativeCase", - "enforceExistence": true, - "requireHyphenBeforeDescription": true, - "requireNewlineAfterDescription": true, - "requireParamDescription": true, - "requireParamTypes": true, - "requireReturnDescription": true, - "requireReturnTypes": true - } -} diff --git a/.mdastignore b/.mdastignore deleted file mode 100644 index 44be31f..0000000 --- a/.mdastignore +++ /dev/null @@ -1 +0,0 @@ -components diff --git a/.mdastrc b/.mdastrc deleted file mode 100644 index c5ec5af..0000000 --- a/.mdastrc +++ /dev/null @@ -1,13 +0,0 @@ -{ - "output": true, - "plugins": [ - "lint", - "github", - "comment-config", - "slug", - "validate-links" - ], - "settings": { - "bullet": "*" - } -} diff --git a/.travis.yml b/.travis.yml index ad446c7..a258a5d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,11 @@ language: node_js node_js: -- '0.10' - '0.11' - '0.12' - '4.0' - '5.0' -- iojs -after_script: npm install codecov.io && cat ./coverage/lcov.info | codecov +- '6.0' +after_success: bash <(curl -s https://codecov.io/bash) deploy: provider: releases api_key: @@ -16,3 +15,4 @@ deploy: - "stringify-entities.min.js" on: tags: true + node: '6.0' diff --git a/component.json b/component.json deleted file mode 100644 index 551f674..0000000 --- a/component.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "stringify-entities", - "version": "1.0.1", - "description": "Encode HTML character references and character entities", - "license": "MIT", - "keywords": [ - "stringify", - "encode", - "escape", - "html", - "character", - "reference", - "entity", - "entities" - ], - "repository": "wooorm/stringify-entities", - "scripts": [ - "index.js", - "lib/expression.js" - ], - "dependencies": { - "wooorm/character-entities-html4": "^1.0.0" - } -} diff --git a/history.md b/history.md index 5f5f4a2..cba1b91 100644 --- a/history.md +++ b/history.md @@ -1,13 +1,13 @@ - + - + 1.0.1 / 2015-12-27 ================== * Fix typo in `readme.md` ([fca0bc9](https://github.com/wooorm/stringify-entities/commit/fca0bc9)) * Fix typo in `component.json` ([fe7ecec](https://github.com/wooorm/stringify-entities/commit/fe7ecec)) -* Fix typographic styling in readme.md` ([b5c09db](https://github.com/wooorm/stringify-entities/commit/b5c09db)) +* Fix typographic styling in readme.md\` ([b5c09db](https://github.com/wooorm/stringify-entities/commit/b5c09db)) 1.0.0 / 2015-11-22 ================== diff --git a/index.js b/index.js index c26906b..45f7f57 100644 --- a/index.js +++ b/index.js @@ -10,43 +10,28 @@ /* eslint-env commonjs */ -/* - * Dependencies. - */ - +/* Dependencies. */ var entities = require('character-entities-html4'); var EXPRESSION_NAMED = require('./lib/expression.js'); -/* - * Methods. - */ - +/* Methods. */ var has = {}.hasOwnProperty; -/* - * List of enforced escapes. - */ - +/* List of enforced escapes. */ var escapes = ['"', '\'', '<', '>', '&', '`']; -/* - * Map of characters to names. - */ - +/* Map of characters to names. */ var characters = {}; (function () { - var name; + var name; - for (name in entities) { - characters[entities[name]] = name; - } + for (name in entities) { + characters[entities[name]] = name; + } })(); -/* - * Regular expressions. - */ - +/* Regular expressions. */ var EXPRESSION_ESCAPE = toExpression(escapes); var EXPRESSION_SURROGATE_PAIR = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; var EXPRESSION_BMP = /[\x01-\t\x0B\f\x0E-\x1F\x7F\x81\x8D\x8F\x90\x9D\xA0-\uFFFF]/g; @@ -58,7 +43,7 @@ var EXPRESSION_BMP = /[\x01-\t\x0B\f\x0E-\x1F\x7F\x81\x8D\x8F\x90\x9D\xA0-\uFFFF * @return {string} - `code` encoded as hexadecimal. */ function characterCodeToHexadecimalReference(code) { - return '&#x' + code.toString(16).toUpperCase() + ';'; + return '&#x' + code.toString(16).toUpperCase() + ';'; } /** @@ -69,7 +54,7 @@ function characterCodeToHexadecimalReference(code) { * @return {string} - `character` encoded as hexadecimal. */ function characterToHexadecimalReference(character) { - return characterCodeToHexadecimalReference(character.charCodeAt(0)); + return characterCodeToHexadecimalReference(character.charCodeAt(0)); } /** @@ -79,7 +64,7 @@ function characterToHexadecimalReference(character) { * @return {string} - `name` encoded as hexadecimal. */ function toNamedEntity(name) { - return '&' + name + ';'; + return '&' + name + ';'; } /** @@ -89,7 +74,7 @@ function toNamedEntity(name) { * @return {string} - `name` encoded as hexadecimal. */ function characterToNamedEntity(character) { - return toNamedEntity(characters[character]); + return toNamedEntity(characters[character]); } /** @@ -99,7 +84,7 @@ function characterToNamedEntity(character) { * @return {RegExp} - Expression. */ function toExpression(characters) { - return new RegExp('[' + characters.join('') + ']', 'g'); + return new RegExp('[' + characters.join('') + ']', 'g'); } /** @@ -116,35 +101,35 @@ function toExpression(characters) { * @return {string} - Encoded `value`. */ function encode(value, options) { - var settings = options || {}; - var escapeOnly = settings.escapeOnly; - var named = settings.useNamedReferences; - var subset = settings.subset; - var map = named ? characters : null; - var set = subset ? toExpression(subset) : EXPRESSION_ESCAPE; - - value = value.replace(set, function (character) { - return map && has.call(map, character) ? - toNamedEntity(map[character]) : - characterToHexadecimalReference(character); - }); - - if (subset || escapeOnly) { - return value; - } - - if (named) { - value = value.replace(EXPRESSION_NAMED, characterToNamedEntity); - } - - return value - .replace(EXPRESSION_SURROGATE_PAIR, function (pair) { - return characterCodeToHexadecimalReference( - (pair.charCodeAt(0) - 0xD800) * 0x400 + - pair.charCodeAt(1) - 0xDC00 + 0x10000 - ); - }) - .replace(EXPRESSION_BMP, characterToHexadecimalReference); + var settings = options || {}; + var escapeOnly = settings.escapeOnly; + var named = settings.useNamedReferences; + var subset = settings.subset; + var map = named ? characters : null; + var set = subset ? toExpression(subset) : EXPRESSION_ESCAPE; + + value = value.replace(set, function (character) { + return map && has.call(map, character) ? + toNamedEntity(map[character]) : + characterToHexadecimalReference(character); + }); + + if (subset || escapeOnly) { + return value; + } + + if (named) { + value = value.replace(EXPRESSION_NAMED, characterToNamedEntity); + } + + return value + .replace(EXPRESSION_SURROGATE_PAIR, function (pair) { + return characterCodeToHexadecimalReference( + ((pair.charCodeAt(0) - 0xD800) * 0x400) + + pair.charCodeAt(1) - 0xDC00 + 0x10000 + ); + }) + .replace(EXPRESSION_BMP, characterToHexadecimalReference); } /** @@ -154,16 +139,13 @@ function encode(value, options) { * @return {string} - Encoded `value`. */ function escape(value) { - return encode(value, { - 'escapeOnly': true, - 'useNamedReferences': true - }); + return encode(value, { + escapeOnly: true, + useNamedReferences: true + }); } encode.escape = escape; -/* - * Expose. - */ - +/* Expose. */ module.exports = encode; diff --git a/package.json b/package.json index e5223e3..088b2a9 100644 --- a/package.json +++ b/package.json @@ -13,46 +13,72 @@ "entity", "entities" ], - "repository": { - "type": "git", - "url": "https://github.com/wooorm/stringify-entities.git" - }, - "author": "Titus Wormer ", + "repository": "https://github.com/wooorm/stringify-entities.git", + "bugs": "https://github.com/wooorm/hast-util-to-html/issues", + "author": "Titus Wormer (http://wooorm.com)", + "contributors": [ + "Titus Wormer (http://wooorm.com)" + ], "files": [ "index.js", - "lib/expression.js", - "LICENSE" + "lib/expression.js" ], "dependencies": { "character-entities-html4": "^1.0.0" }, "devDependencies": { - "browserify": "^12.0.0", - "eslint": "^1.0.0", + "browserify": "^13.0.0", "esmangle": "^1.0.0", "istanbul": "^0.4.0", - "jscs": "^2.0.0", - "jscs-jsdoc": "^1.0.0", - "mdast": "^2.0.0", - "mdast-comment-config": "^1.0.0", - "mdast-github": "^1.0.0", - "mdast-lint": "^1.0.0", - "mdast-slug": "^2.0.0", - "mdast-validate-links": "^1.1.1", - "mdast-yaml-config": "^1.0.0", - "tape": "^4.2.0" + "remark-cli": "^1.0.0", + "remark-comment-config": "^4.0.0", + "remark-github": "^5.0.0", + "remark-lint": "^4.0.0", + "remark-toc": "^3.0.0", + "remark-validate-links": "^4.0.0", + "tape": "^4.0.0", + "xo": "^0.16.0" }, "scripts": { - "build-md": "mdast . --quiet --frail", + "build-md": "remark . --quiet --frail", "build-expression": "node script/generate-expression.js", "build-bundle": "browserify index.js --bare -s stringifyEntities > stringify-entities.js", "build-mangle": "esmangle stringify-entities.js > stringify-entities.min.js", "build": "npm run build-md && npm run build-expression && npm run build-bundle && npm run build-mangle", - "lint-api": "eslint .", - "lint-style": "jscs --reporter inline .", - "lint": "npm run lint-api && npm run lint-style", + "lint": "xo", "test-api": "node test.js", "test-coverage": "istanbul cover test.js", "test": "npm run build && npm run lint && npm run test-coverage" + }, + "xo": { + "space": true, + "rules": { + "guard-for-in": [ + 0 + ], + "eqeqeq": [ + 0, + "allow-null" + ], + "no-eq-null": [ + 0 + ] + }, + "ignores": [ + "stringify-entities.js", + "stringify-entities.min.js" + ] + }, + "remarkConfig": { + "output": true, + "plugins": [ + "comment-config", + "lint", + "github", + "validate-links" + ], + "settings": { + "bullet": "*" + } } } diff --git a/readme.md b/readme.md index be11354..72668e6 100644 --- a/readme.md +++ b/readme.md @@ -1,11 +1,11 @@ -# stringify-entities [![Build Status](https://img.shields.io/travis/wooorm/stringify-entities.svg?style=flat)](https://travis-ci.org/wooorm/stringify-entities) [![Coverage Status](https://img.shields.io/codecov/c/github/wooorm/stringify-entities.svg)](https://codecov.io/github/wooorm/stringify-entities) +# stringify-entities [![Build Status][build-badge]][build-status] [![Coverage Status][coverage-badge]][coverage-status] + + Encode HTML character references and character entities. * [x] Very fast; - * [x] Just the encoding part; - * [x] Reliable: ``"`"`` characters are escaped to ensure no scripts run in IE6-8. Additionally, only named entities recognized by HTML4 are encoded, meaning the infamous `'` (which people think is a @@ -14,15 +14,14 @@ Encode HTML character references and character entities. ## Installation -[npm](https://docs.npmjs.com/cli/install): +[npm][]: ```bash npm install stringify-entities ``` -**stringify-entities** is also available for [duo](http://duojs.org/#getting-started), -and [bundled](https://github.com/wooorm/stringify-entities/releases) for AMD, -CommonJS, and globals (uncompressed and compressed). +**stringify-entities** is also available as an AMD, CommonJS, and globals +module, [uncompressed and compressed][releases]. ## Usage @@ -38,7 +37,7 @@ Yields: alpha © bravo ≠ charlie 𝌆 delta ``` -…and with `useNamedReferences: true`. +…and with `useNamedReferences: true`. ```js stringify.encode('alpha Β© bravo β‰  charlie πŒ† delta', { useNamedReferences: true }); @@ -52,37 +51,44 @@ alpha © bravo ≠ charlie 𝌆 delta ## API -### stringifyEntities(value\[, options?]) +### `stringifyEntities(value[, options])` Encode special characters in `value`. -**Parameters**: +##### `options` -* `value` (`string`) β€” Value to encode; +###### `options.escapeOnly` -* `options` (`Object?`, optional) β€” Configuration: +Whether to only escape possibly dangerous characters (`boolean`, +default: `false`). Those characters are `"`, `'`, `<`, `>` `&`, and +`` ` ``. - * `escapeOnly` (`boolean?`, optional, default: `false`) - β€” Whether to only escape possibly dangerous characters - (`"`, `'`, `<`, `>` `&`, and `` ` ``); +###### `options.subset` - * `subset` (`Array.`, optional) - β€” Whether to only escape the given subset of characters; +Whether to only escape the given subset of characters (`Array.`). - * `useNamedReferences` (`boolean?`, optional, default: `false`) - β€” Whether to use entities where possible. +###### `options.useNamedReferences` -**Returns**: `string`, encoded `value`. +Whether to use entities where possible. (`boolean?`, default: `false`). -### stringifyEntities.escape(value\[, options?]) +## License -Escape special characters in `value`. Shortcut for `stringifyEntities` -with `escapeOnly: true` and `useNamedReferences: true`. +[MIT][license] Β© [Titus Wormer][author] -## Support + -See [html.spec.whatwg.org](https://html.spec.whatwg.org/multipage/syntax.html#named-character-references). +[build-badge]: https://img.shields.io/travis/wooorm/stringify-entities.svg -## License +[build-status]: https://travis-ci.org/wooorm/stringify-entities + +[coverage-badge]: https://img.shields.io/codecov/c/github/wooorm/stringify-entities.svg + +[coverage-status]: https://codecov.io/github/wooorm/stringify-entities + +[releases]: https://github.com/wooorm/stringify-entities/releases + +[license]: LICENSE + +[author]: http://wooorm.com -[MIT](LICENSE) Β© [Titus Wormer](http://wooorm.com) +[npm]: https://docs.npmjs.com/cli/install diff --git a/script/generate-expression.js b/script/generate-expression.js index 86c97e6..426d8ad 100644 --- a/script/generate-expression.js +++ b/script/generate-expression.js @@ -11,48 +11,36 @@ /* eslint-env node */ -/* - * Dependencies. - */ - +/* Dependencies. */ var fs = require('fs'); var path = require('path'); var entities = require('character-entities-html4'); -/* - * Escape-codes. - */ - +/* Escape-codes. */ var escapes = ['"', '\'', '<', '>', '&', '`']; -/* - * Generate the expression. - */ - +/* Generate the expression. */ var list = []; var name; for (name in entities) { - if (escapes.indexOf(entities[name]) === -1) { - list.push(entities[name]); - } + if (escapes.indexOf(entities[name]) === -1) { + list.push(entities[name]); + } } var expression = new RegExp('[' + list.join('') + ']', 'g'); -/* - * Write. - */ - +/* Write. */ var doc = [ - '/* This script was generated by `script/generate-expression.js` */', - '', - '\'use strict\';', - '', - '/* eslint-env commonjs */', - '/* eslint-disable no-irregular-whitespace */', - '', - 'module.exports = ' + expression + ';' + '/* This script was generated by `script/generate-expression.js` */', + '', + '\'use strict\';', + '', + '/* eslint-env commonjs */', + '/* eslint-disable no-irregular-whitespace */', + '', + 'module.exports = ' + expression + ';' ].join('\n'); fs.writeFileSync(path.join('lib', 'expression.js'), doc + '\n'); diff --git a/test.js b/test.js index f59be19..eb80ffe 100644 --- a/test.js +++ b/test.js @@ -11,152 +11,146 @@ /* eslint-env node */ /* jscs:disable maximumLineLength */ -/* - * Dependencies. - */ - +/* Dependencies. */ var test = require('tape'); var stringify = require('./'); var named = { - 'useNamedReferences': true + useNamedReferences: true }; -/* - * Tests. - */ - +/* Tests. */ test('stringifyEntities.escape(value)', function (t) { - t.equal( - stringify.escape( - '' + - '' + - '' - ), - '<img src='x' onerror="prompt(1)">' + - '<script>alert(1)</script>' + - '<img src="x` `' + - '<script>alert(1)</script>"` `>', - 'XML/HTML-escape' - ); - - t.end(); + t.equal( + stringify.escape( + '' + + '' + + '' + ), + '<img src='x' onerror="prompt(1)">' + + '<script>alert(1)</script>' + + '<img src="x` `' + + '<script>alert(1)</script>"` `>', + 'XML/HTML-escape' + ); + + t.end(); }); test('stringifyEntities(value[, options])', function (t) { - t.equal( - stringify('foo\xA9bar\uD834\uDF06baz\u2603qux'), - 'foo©bar𝌆baz☃qux', - 'Other non-ASCII symbols are represented through hexadecimal escapes' - ); - - t.equal( - stringify('foo\xA9bar\uD834\uDF06baz\u2603qux', named), - 'foo©bar𝌆baz☃qux', - 'Other non-ASCII symbols are represented through hexadecimal escapes' - ); - - t.equal( - stringify('\'"<>&'), - ''"<>&', - 'Encode `escape`’s characters without using named references' - ); - - t.equal( - stringify('\'"<>&', { - 'subset': ['&'] - }), - '\'"<>&', - 'Encode support a `subset`' - ); - - t.equal( - stringify('\'"<>&', { - 'subset': ['&'], - 'useNamedReferences': true - }), - '\'"<>&', - 'Encode support a `subset` with `useNamedReferences`' - ); - - t.equal( - stringify('foo\uD800bar'), - 'foo�bar', - 'Lone high surrogate (lowest)' - ); - - t.equal( - stringify('foo\uDBFFbar'), - 'foo�bar', - 'Lone high surrogate (highest)' - ); - - t.equal( - stringify('\uD800bar'), - '�bar', - 'Lone high surrogate at the start of a string (lowest)' - ); - - t.equal( - stringify('\uDBFFbar'), - '�bar', - 'Lone high surrogate at the start of a string (highest)' - ); - - t.equal( - stringify('foo\uD800'), - 'foo�', - 'Lone high surrogate at the end of a string (lowest)' - ); - - t.equal( - stringify('foo\uDBFF'), - 'foo�', - 'Lone high surrogate at the end of a string (highest)' - ); - - t.equal( - stringify('foo\uDC00bar'), - 'foo�bar', - 'Lone low surrogate (lowest)' - ); - - t.equal( - stringify('foo\uDFFFbar'), - 'foo�bar', - 'Lone low surrogate (highest)' - ); - - t.equal( - stringify('\uDC00bar'), - '�bar', - 'Lone low surrogate at the start of a string (lowest)' - ); - - t.equal( - stringify('\uDFFFbar'), - '�bar', - 'Lone low surrogate at the start of a string (highest)' - ); - - t.equal( - stringify('foo\uDC00'), - 'foo�', - 'Lone low surrogate at the end of a string (lowest)' - ); - - t.equal( - stringify('\0\x01\x02\x03\x04\x05\x06\x07\b\x0B\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\uFDD0\uFDD1\uFDD2\uFDD3\uFDD4\uFDD5\uFDD6\uFDD7\uFDD8\uFDD9\uFDDA\uFDDB\uFDDC\uFDDD\uFDDE\uFDDF\uFDE0\uFDE1\uFDE2\uFDE3\uFDE4\uFDE5\uFDE6\uFDE7\uFDE8\uFDE9\uFDEA\uFDEB\uFDEC\uFDED\uFDEE\uFDEF\uFFFE\uFFFF\uD83F\uDFFE\uD83F\uDFFF\uD87F\uDFFE\uD87F\uDFFF\uD8BF\uDFFE\uD8BF\uDFFF\uD8FF\uDFFE\uD8FF\uDFFF\uD93F\uDFFE\uD93F\uDFFF\uD97F\uDFFE\uD97F\uDFFF\uD9BF\uDFFE\uD9BF\uDFFF\uD9FF\uDFFE\uD9FF\uDFFF\uDA3F\uDFFE\uDA3F\uDFFF\uDA7F\uDFFE\uDA7F\uDFFF\uDABF\uDFFE\uDABF\uDFFF\uDAFF\uDFFE\uDAFF\uDFFF\uDB3F\uDFFE\uDB3F\uDFFF\uDB7F\uDFFE\uDB7F\uDFFF\uDBBF\uDFFE\uDBBF\uDFFF\uDBFF\uDFFE\uDBFF\uDFFF'), - '\0 \x80\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8E\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9E\x9F﷐﷑﷒﷓﷔﷕﷖﷗﷘﷙﷚﷛﷜﷝﷞﷟﷠﷡﷢﷣﷤﷥﷦﷧﷨﷩﷪﷫﷬﷭﷮﷯￾￿🿾🿿𯿾𯿿𿿾𿿿񏿾񏿿񟿾񟿿񯿾񯿿񿿾񿿿򏿾򏿿򟿾򟿿򯿾򯿿򿿾򿿿󏿾󏿿󟿾󟿿󯿾󯿿󿿾󿿿􏿾􏿿', - 'Encodes disallowed code points in input, except those whose character references would refer to another code point' - ); - - t.equal( - stringify('\0\x89'), - '\0\x89', - 'Does not encode invalid code points whose character references would refer to another code point' - ); - - t.end(); + t.equal( + stringify('foo\xA9bar\uD834\uDF06baz\u2603qux'), + 'foo©bar𝌆baz☃qux', + 'Other non-ASCII symbols are represented through hexadecimal escapes' + ); + + t.equal( + stringify('foo\xA9bar\uD834\uDF06baz\u2603qux', named), + 'foo©bar𝌆baz☃qux', + 'Other non-ASCII symbols are represented through hexadecimal escapes' + ); + + t.equal( + stringify('\'"<>&'), + ''"<>&', + 'Encode `escape`’s characters without using named references' + ); + + t.equal( + stringify('\'"<>&', { + subset: ['&'] + }), + '\'"<>&', + 'Encode support a `subset`' + ); + + t.equal( + stringify('\'"<>&', { + subset: ['&'], + useNamedReferences: true + }), + '\'"<>&', + 'Encode support a `subset` with `useNamedReferences`' + ); + + t.equal( + stringify('foo\uD800bar'), + 'foo�bar', + 'Lone high surrogate (lowest)' + ); + + t.equal( + stringify('foo\uDBFFbar'), + 'foo�bar', + 'Lone high surrogate (highest)' + ); + + t.equal( + stringify('\uD800bar'), + '�bar', + 'Lone high surrogate at the start of a string (lowest)' + ); + + t.equal( + stringify('\uDBFFbar'), + '�bar', + 'Lone high surrogate at the start of a string (highest)' + ); + + t.equal( + stringify('foo\uD800'), + 'foo�', + 'Lone high surrogate at the end of a string (lowest)' + ); + + t.equal( + stringify('foo\uDBFF'), + 'foo�', + 'Lone high surrogate at the end of a string (highest)' + ); + + t.equal( + stringify('foo\uDC00bar'), + 'foo�bar', + 'Lone low surrogate (lowest)' + ); + + t.equal( + stringify('foo\uDFFFbar'), + 'foo�bar', + 'Lone low surrogate (highest)' + ); + + t.equal( + stringify('\uDC00bar'), + '�bar', + 'Lone low surrogate at the start of a string (lowest)' + ); + + t.equal( + stringify('\uDFFFbar'), + '�bar', + 'Lone low surrogate at the start of a string (highest)' + ); + + t.equal( + stringify('foo\uDC00'), + 'foo�', + 'Lone low surrogate at the end of a string (lowest)' + ); + + t.equal( + stringify('\0\x01\x02\x03\x04\x05\x06\x07\b\x0B\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\uFDD0\uFDD1\uFDD2\uFDD3\uFDD4\uFDD5\uFDD6\uFDD7\uFDD8\uFDD9\uFDDA\uFDDB\uFDDC\uFDDD\uFDDE\uFDDF\uFDE0\uFDE1\uFDE2\uFDE3\uFDE4\uFDE5\uFDE6\uFDE7\uFDE8\uFDE9\uFDEA\uFDEB\uFDEC\uFDED\uFDEE\uFDEF\uFFFE\uFFFF\uD83F\uDFFE\uD83F\uDFFF\uD87F\uDFFE\uD87F\uDFFF\uD8BF\uDFFE\uD8BF\uDFFF\uD8FF\uDFFE\uD8FF\uDFFF\uD93F\uDFFE\uD93F\uDFFF\uD97F\uDFFE\uD97F\uDFFF\uD9BF\uDFFE\uD9BF\uDFFF\uD9FF\uDFFE\uD9FF\uDFFF\uDA3F\uDFFE\uDA3F\uDFFF\uDA7F\uDFFE\uDA7F\uDFFF\uDABF\uDFFE\uDABF\uDFFF\uDAFF\uDFFE\uDAFF\uDFFF\uDB3F\uDFFE\uDB3F\uDFFF\uDB7F\uDFFE\uDB7F\uDFFF\uDBBF\uDFFE\uDBBF\uDFFF\uDBFF\uDFFE\uDBFF\uDFFF'), + '\0 \x80\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8E\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9E\x9F﷐﷑﷒﷓﷔﷕﷖﷗﷘﷙﷚﷛﷜﷝﷞﷟﷠﷡﷢﷣﷤﷥﷦﷧﷨﷩﷪﷫﷬﷭﷮﷯￾￿🿾🿿𯿾𯿿𿿾𿿿񏿾񏿿񟿾񟿿񯿾񯿿񿿾񿿿򏿾򏿿򟿾򟿿򯿾򯿿򿿾򿿿󏿾󏿿󟿾󟿿󯿾󯿿󿿾󿿿􏿾􏿿', + 'Encodes disallowed code points in input, except those whose character references would refer to another code point' + ); + + t.equal( + stringify('\0\x89'), + '\0\x89', + 'Does not encode invalid code points whose character references would refer to another code point' + ); + + t.end(); });