English | 简体中文
A modern TypeScript + ESM refactor of the popular jsesc library with 100% API compatibility
Given some data, jsesc-es returns a stringified representation of that data. jsesc-es is similar to JSON.stringify() except:
- it outputs JavaScript instead of JSON by default, enabling support for data structures like ES6 maps and sets;
- it offers many options to customize the output;
- its output is ASCII-safe by default, thanks to its use of escape sequences where needed;
- NEW: Full TypeScript support with comprehensive type definitions;
- NEW: Native ES Modules with tree-shaking support;
- NEW: Modern development toolchain and improved performance.
For any input, jsesc-es generates the shortest possible valid printable-ASCII-only output. Here's an online demo.
jsesc-es's output can be used instead of JSON.stringify's to avoid mojibake and other encoding issues, or even to avoid errors when passing JSON-formatted data (which may contain U+2028 LINE SEPARATOR, U+2029 PARAGRAPH SEPARATOR, or lone surrogates) to a JavaScript parser or an UTF-8 encoder.
- Built-in type definitions - No need for
@types/jsesc - Full type safety with comprehensive
JsescOptionsinterface - Better IDE support with IntelliSense and auto-completion
- Type-safe option validation at compile time
- Native ES Modules with tree-shaking support
- Multiple import styles - default, named, or mixed imports
- CommonJS compatibility for legacy projects
- Optimized bundle size with modern build tools
- Improved function handling with better type detection
- Optimized escape logic for common use cases
- Modern JavaScript features for better performance
- Reduced bundle overhead compared to the original
- Modern toolchain with Vitest, tsdown, and pnpm
- Better error messages with TypeScript integration
- Comprehensive test coverage with type checking
- Active maintenance with regular updates
# pnpm (recommended) - https://pnpm.io/
pnpm add jsesc-es
# yarn - https://yarnpkg.com/
yarn add jsesc-es
# npm - https://www.npmjs.com/
npm install jsesc-es
# Or other runtime linke...
# bun - https://bun.sh/
bun add jsesc-es
# deno - https://deno.land/
deno add jsesc-es
// Default import (most common)
import jsesc from 'jsesc-es'
// Named import
import { jsesc } from 'jsesc-es'
// Import with types (TypeScript)
import type { JsescOptions } from 'jsesc-es'
import jsesc from 'jsesc-es'
// Import version info
import { version } from 'jsesc-es'
// Mixed import (not recommended)
import jsesc, { version, type JsescOptions } from 'jsesc-es'import type { JsescOptions } from 'jsesc-es'
import jsesc from 'jsesc-es'
// Type-safe options
const options: JsescOptions = {
quotes: 'single',
wrap: true,
es6: true,
minimal: false
}
// Type-safe function usage
function escapeForHTML(input: string): string {
return jsesc(input, {
quotes: 'double',
wrap: true,
isScriptContext: true
})
}
// Type-safe configuration objects
const configs = {
json: { json: true } as JsescOptions,
minimal: { minimal: true } as JsescOptions,
es6: { es6: true, quotes: 'backtick' } as JsescOptions
}// CommonJS require (still supported)
const jsesc = require('jsesc-es')
// Dynamic import (modern alternative)
const { jsesc } = await import('jsesc-es')Ensure your package.json includes:
{
"type": "module"
}Or use .mjs file extension:
// app.mjs
import jsesc from 'jsesc-es'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 JavaScript strings. The first supported value type is strings:
jsesc('Ich ♥ Bücher')
// → 'Ich \\u2665 B\\xFCcher'
jsesc('foo 𝌆 bar')
// → 'foo \\uD834\\uDF06 bar'Instead of a string, the value can also be an array, an object, a map, a set, a number, a BigInt, or a buffer. In such cases, jsesc returns a stringified version of the value where any characters that are not printable ASCII symbols are escaped in the same way.
// Escaping an array
jsesc([
'Ich ♥ Bücher',
'foo 𝌆 bar'
])
// → '[\'Ich \\u2665 B\\xFCcher\',\'foo \\uD834\\uDF06 bar\']'
// Escaping an object
jsesc({
'Ich ♥ Bücher': 'foo 𝌆 bar'
})
// → '{\'Ich \\u2665 B\\xFCcher\':\'foo \\uD834\\uDF06 bar\'}'The optional options argument accepts an object with the following options. In TypeScript, use the JsescOptions type for full type safety:
import { type JsescOptions } from 'jsesc-es'
const options: JsescOptions = {
// Your options here with full IntelliSense support
}The default value for the quotes option is 'single'. This means that any occurrences of ' in the input string are escaped as \', so that the output can be used in a string literal wrapped in single quotes.
jsesc('`Lorem` ipsum "dolor" sit \'amet\' etc.')
// → 'Lorem ipsum "dolor" sit \\\'amet\\\' etc.'
jsesc('`Lorem` ipsum "dolor" sit \'amet\' etc.', {
quotes: 'single'
})
// → '`Lorem` ipsum "dolor" sit \\\'amet\\\' etc.'If you want to use the output as part of a string literal wrapped in double quotes, set the quotes option to 'double'.
jsesc('`Lorem` ipsum "dolor" sit \'amet\' etc.', {
quotes: 'double'
})
// → '`Lorem` ipsum \\"dolor\\" sit \'amet\' etc.'If you want to use the output as part of a template literal (i.e. wrapped in backticks), set the quotes option to 'backtick'.
jsesc('`Lorem` ipsum "dolor" sit \'amet\' etc.', {
quotes: 'backtick'
})
// → '\\`Lorem\\` ipsum "dolor" sit \'amet\' etc.'The default value for the numbers option is 'decimal'. This means that any numeric values are represented using decimal integer literals. Other valid options are binary, octal, and hexadecimal.
jsesc(42, { numbers: 'binary' })
// → '0b101010'
jsesc(42, { numbers: 'octal' })
// → '0o52'
jsesc(42, { numbers: 'decimal' })
// → '42'
jsesc(42, { numbers: 'hexadecimal' })
// → '0x2A'The wrap option takes a boolean value (true or false), and defaults to false (disabled). When enabled, the output is a valid JavaScript string literal wrapped in quotes.
jsesc('Lorem ipsum "dolor" sit \'amet\' etc.', {
quotes: 'single',
wrap: true
})
// → '\'Lorem ipsum "dolor" sit \\\'amet\\\' etc.\''
jsesc('Lorem ipsum "dolor" sit \'amet\' etc.', {
quotes: 'double',
wrap: true
})
// → '"Lorem ipsum \\"dolor\\" sit \'amet\' etc."'The es6 option takes a boolean value (true or false), and defaults to false (disabled). When enabled, any astral Unicode symbols in the input are escaped using ECMAScript 6 Unicode code point escape sequences.
// By default, the `es6` option is disabled:
jsesc('foo 𝌆 bar 💩 baz')
// → 'foo \\uD834\\uDF06 bar \\uD83D\\uDCA9 baz'
// To enable it:
jsesc('foo 𝌆 bar 💩 baz', {
es6: true
})
// → 'foo \\u{1D306} bar \\u{1F4A9} baz'The escapeEverything option takes a boolean value (true or false), and defaults to false (disabled). When enabled, all the symbols in the output are escaped — even printable ASCII symbols.
jsesc('lolwat"foo\'bar', {
escapeEverything: true
})
// → '\\x6C\\x6F\\x6C\\x77\\x61\\x74\\"\\x66\\x6F\\x6F\\\'\\x62\\x61\\x72'The minimal option takes a boolean value (true or false), and defaults to false (disabled). When enabled, only a limited set of symbols in the output are escaped.
Note: with this option enabled, jsesc-es output is no longer guaranteed to be ASCII-safe.
jsesc('foo\u2029bar\nbaz©qux𝌆flops', {
minimal: true
})
// → 'foo\\u2029bar\\nbaz©qux𝌆flops'The isScriptContext option takes a boolean value (true or false), and defaults to false (disabled). When enabled, occurrences of </script and </style in the output are escaped.
jsesc('foo</script>bar', {
isScriptContext: true
})
// → 'foo<\\/script>bar'The compact option takes a boolean value (true or false), and defaults to true (enabled). When enabled, the output for arrays and objects is as compact as possible.
jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
compact: true // this is the default
})
// → '{\'Ich \u2665 B\xFCcher\':\'foo \uD834\uDF06 bar\'}'
jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
compact: false
})
// → '{\n\t\'Ich \u2665 B\xFCcher\': \'foo \uD834\uDF06 bar\'\n}'The indent option takes a string value, and defaults to '\t'. When the compact setting is disabled (false), the value of the indent option is used to format the output.
jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
compact: false,
indent: ' '
})
// → '{\n \'Ich \u2665 B\xFCcher\': \'foo \uD834\uDF06 bar\'\n}'The indentLevel option takes a numeric value, and defaults to 0. It represents the current indentation level.
jsesc(['a', 'b', 'c'], {
compact: false,
indentLevel: 1
})
// → '[\n\t\t\'a\',\n\t\t\'b\',\n\t\t\'c\'\n\t]'The json option takes a boolean value (true or false), and defaults to false (disabled). When enabled, the output is valid JSON.
jsesc('foo\x00bar\xFF\uFFFDbaz', {
json: true
})
// → '"foo\\u0000bar\\u00FF\\uFFFDbaz"'
jsesc({ 'foo\x00bar\xFF\uFFFDbaz': 'foo\x00bar\xFF\uFFFDbaz' }, {
json: true
})
// → '{"foo\\u0000bar\\u00FF\\uFFFDbaz":"foo\\u0000bar\\u00FF\\uFFFDbaz"}'The lowercaseHex option takes a boolean value (true or false), and defaults to false (disabled). When enabled, any alphabetical hexadecimal digits in escape sequences are in lowercase.
jsesc('Ich ♥ Bücher', {
lowercaseHex: true
})
// → 'Ich \\u2665 B\\xfccher'
// ^^
jsesc(42, {
numbers: 'hexadecimal',
lowercaseHex: true
})
// → '0x2a'
// ^^// Access version information
import jsesc, { version } from 'jsesc-es'
console.log(jsesc.version) // e.g., "0.0.3"
console.log(version) // e.g., "0.0.3"Migrating from the original jsesc library is straightforward:
# Remove old package
npm uninstall jsesc
# Install new package
npm install jsesc-es// Before (CommonJS)
const jsesc = require('jsesc')
// After (ES Modules)
import jsesc from 'jsesc-es'
// Or with types (TypeScript)
import jsesc, { type JsescOptions } from 'jsesc-es'- Full TypeScript support with no additional setup
- Better IDE experience with IntelliSense
- Modern module system with tree-shaking
- 100% API compatibility - no code changes needed
For detailed migration instructions, see MIGRATION.md.
import jsesc, { type JsescOptions } from 'jsesc-es'
// Create type-safe utility functions
const createEscaper = (defaultOptions: JsescOptions) => {
return (input: string, options?: Partial<JsescOptions>): string => {
return jsesc(input, { ...defaultOptions, ...options })
}
}
// Pre-configured escapers
const escapeForHTML = createEscaper({
quotes: 'double',
wrap: true,
isScriptContext: true
})
const escapeForJSON = createEscaper({
json: true
})
const escapeMinimal = createEscaper({
minimal: true
})
// Usage with full type safety
const htmlSafe = escapeForHTML('Hello "World"')
const jsonSafe = escapeForJSON({ message: 'Hello 世界' })
const minimalEscape = escapeMinimal('Simple text')import { type JsescOptions } from 'jsesc-es'
// Define configuration presets
const PRESETS: Record<string, JsescOptions> = {
html: {
quotes: 'double',
wrap: true,
isScriptContext: true,
escapeEverything: false
},
json: {
json: true,
compact: true
},
es6: {
es6: true,
quotes: 'backtick',
wrap: true
},
debug: {
escapeEverything: true,
compact: false,
indent: ' '
}
} as const
// Type-safe preset usage
function escapeWithPreset(
input: any,
preset: keyof typeof PRESETS,
overrides?: Partial<JsescOptions>
): string {
const config = { ...PRESETS[preset], ...overrides }
return jsesc(input, config)
}jsesc-es includes several performance improvements over the original:
- Optimized type checking for better runtime performance
- Improved function handling with enhanced detection logic
- Modern JavaScript features for better engine optimization
- Reduced overhead in common escape scenarios
- Tree-shaking support for smaller bundle sizes
jsesc-es provides broad compatibility through its dual build system:
For ES Modules (recommended):
- Node.js: 14+ (native ESM support)
- Browsers: Chrome 61+, Firefox 60+, Safari 10.1+, Edge 16+
- ES Modules: Native support required
For CommonJS (legacy):
- Node.js: 6+ (transpiled output)
- Browsers: Chrome 27+, Firefox 3+, Safari 4+, Opera 10+ (with bundler)
While jsesc-es maintains compatibility with legacy environments through its transpiled CommonJS build (targeting node6, chrome27, etc.), ES Modules require modern environments that support the import/export syntax natively. The build targets ensure the JavaScript syntax and APIs work in older environments, but the module system itself has minimum version requirements.
Key Points:
- 📦 CommonJS build: Works in very old environments (Node 6+, Chrome 27+)
- 🚀 ESM build: Requires modern environments with native ESM support
- 🔧 Legacy projects: Use CommonJS or transpile ESM with Babel/TypeScript
- ⚡ Modern projects: Use ESM for better tree-shaking and performance
- TypeScript: 4.5+
- Built-in types: No
@types/package needed
# Clone the repository
git clone https://github.com/Drswith/jsesc-es.git
cd jsesc-es
# Install dependencies
pnpm install
# Run tests
pnpm test
# Build the project
pnpm build
# Type checking
pnpm typecheck
# Linting
pnpm lintContributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
This project is licensed under the MIT License - see the LICENSE file for details.
- Mathias Bynens - Creator of the original jsesc library
- The TypeScript team - For excellent tooling and type system
- The open source community - For continuous feedback and contributions
jsesc-es - A modern, TypeScript-first approach to JavaScript string escaping. 🚀