jsesc-es
Version:
Given some data, jsesc returns the shortest possible stringified & ASCII-safe representation of that data.
591 lines (432 loc) • 17 kB
Markdown
# jsesc-es
<div align="center">
[](https://www.npmjs.com/package/jsesc-es) [](https://www.npmjs.com/package/jsesc-es) [](https://www.jsdelivr.com/package/npm/jsesc-es) [](https://unpkg.com/jsesc-es/) [](https://www.typescriptlang.org/) [](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) [](https://opensource.org/licenses/MIT)
**English** | **[简体中文](README.zh-CN.md)**
</div>
> A modern TypeScript + ESM refactor of the popular [jsesc](https://github.com/mathiasbynens/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:
1. it outputs JavaScript instead of JSON [by default](#json), enabling support for data structures like ES6 maps and sets;
2. it offers [many options](#api) to customize the output;
3. its output is ASCII-safe [by default](#minimal), thanks to its use of [escape sequences](https://mathiasbynens.be/notes/javascript-escapes) where needed;
4. **NEW**: Full TypeScript support with comprehensive type definitions;
5. **NEW**: Native ES Modules with tree-shaking support;
6. **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.](https://mothereff.in/js-escapes)
jsesc-es's output can be used instead of `JSON.stringify`'s to avoid [mojibake](https://en.wikipedia.org/wiki/Mojibake) and other encoding issues, or even to [avoid errors](https://twitter.com/annevk/status/380000829643571200) when passing JSON-formatted data (which may contain U+2028 LINE SEPARATOR, U+2029 PARAGRAPH SEPARATOR, or [lone surrogates](https://esdiscuss.org/topic/code-points-vs-unicode-scalar-values#content-14)) to a JavaScript parser or an UTF-8 encoder.
## ✨ What's New in jsesc-es
### 🔥 TypeScript First
- **Built-in type definitions** - No need for `@types/jsesc`
- **Full type safety** with comprehensive `JsescOptions` interface
- **Better IDE support** with IntelliSense and auto-completion
- **Type-safe option validation** at compile time
### 📦 Modern Module System
- **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
### ⚡ Enhanced Performance
- **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
### 🛠️ Developer Experience
- **Modern toolchain** with Vitest, tsdown, and pnpm
- **Better error messages** with TypeScript integration
- **Comprehensive test coverage** with type checking
- **Active maintenance** with regular updates
## Installation
```bash
# 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
```
## Usage
### ES Modules (Recommended)
```typescript
// 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'
```
### TypeScript Usage
```typescript
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 (Legacy Support)
```javascript
// CommonJS require (still supported)
const jsesc = require('jsesc-es')
// Dynamic import (modern alternative)
const { jsesc } = await import('jsesc-es')
```
### Node.js ESM
Ensure your `package.json` includes:
```json
{
"type": "module"
}
```
Or use `.mjs` file extension:
```javascript
// app.mjs
import jsesc from 'jsesc-es'
```
## API
### `jsesc(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 JavaScript strings](https://mathiasbynens.be/notes/javascript-escapes). The first supported value type is strings:
```js
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.
```js
// 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\'}'
```
### Options
The optional `options` argument accepts an object with the following options. In TypeScript, use the `JsescOptions` type for full type safety:
```typescript
import { type JsescOptions } from 'jsesc-es'
const options: JsescOptions = {
// Your options here with full IntelliSense support
}
```
#### `quotes`
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.
```js
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'`.
```js
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'`.
```js
jsesc('`Lorem` ipsum "dolor" sit \'amet\' etc.', {
quotes: 'backtick'
})
// → '\\`Lorem\\` ipsum "dolor" sit \'amet\' etc.'
```
#### `numbers`
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`.
```js
jsesc(42, { numbers: 'binary' })
// → '0b101010'
jsesc(42, { numbers: 'octal' })
// → '0o52'
jsesc(42, { numbers: 'decimal' })
// → '42'
jsesc(42, { numbers: 'hexadecimal' })
// → '0x2A'
```
#### `wrap`
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.
```js
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."'
```
#### `es6`
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](https://mathiasbynens.be/notes/javascript-escapes#unicode-code-point).
```js
// 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'
```
#### `escapeEverything`
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.
```js
jsesc('lolwat"foo\'bar', {
escapeEverything: true
})
// → '\\x6C\\x6F\\x6C\\x77\\x61\\x74\\"\\x66\\x6F\\x6F\\\'\\x62\\x61\\x72'
```
#### `minimal`
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.
```js
jsesc('foo\u2029bar\nbaz©qux𝌆flops', {
minimal: true
})
// → 'foo\\u2029bar\\nbaz©qux𝌆flops'
```
#### `isScriptContext`
The `isScriptContext` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, occurrences of [`</script` and `</style`](https://mathiasbynens.be/notes/etago) in the output are escaped.
```js
jsesc('foo</script>bar', {
isScriptContext: true
})
// → 'foo<\\/script>bar'
```
#### `compact`
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.
```js
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}'
```
#### `indent`
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.
```js
jsesc({ 'Ich ♥ Bücher': 'foo 𝌆 bar' }, {
compact: false,
indent: ' '
})
// → '{\n \'Ich \u2665 B\xFCcher\': \'foo \uD834\uDF06 bar\'\n}'
```
#### `indentLevel`
The `indentLevel` option takes a numeric value, and defaults to `0`. It represents the current indentation level.
```js
jsesc(['a', 'b', 'c'], {
compact: false,
indentLevel: 1
})
// → '[\n\t\t\'a\',\n\t\t\'b\',\n\t\t\'c\'\n\t]'
```
#### `json`
The `json` option takes a boolean value (`true` or `false`), and defaults to `false` (disabled). When enabled, the output is valid JSON.
```js
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"}'
```
#### `lowercaseHex`
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.
```js
jsesc('Ich ♥ Bücher', {
lowercaseHex: true
})
// → 'Ich \\u2665 B\\xfccher'
// ^^
jsesc(42, {
numbers: 'hexadecimal',
lowercaseHex: true
})
// → '0x2a'
// ^^
```
### Version Information
```typescript
// 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"
```
## Migration from jsesc
Migrating from the original `jsesc` library is straightforward:
### 1. Update Dependencies
```bash
# Remove old package
npm uninstall jsesc
# Install new package
npm install jsesc-es
```
### 2. Update Imports
```javascript
// 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'
```
### 3. Enjoy Enhanced Features
- **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](./MIGRATION.md).
## TypeScript Examples
### Creating Utility Functions
```typescript
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')
```
### Advanced Configuration
```typescript
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)
}
```
## Performance
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
## Browser Support
jsesc-es provides broad compatibility through its dual build system:
### Runtime Requirements
**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)
### Build Targets vs. Module System
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 Support
- **TypeScript**: 4.5+
- **Built-in types**: No `@types/` package needed
## Development
```bash
# 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 lint
```
## Contributing
Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Acknowledgments
- **[Mathias Bynens](https://github.com/mathiasbynens)** - Creator of the original [jsesc](https://github.com/mathiasbynens/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. 🚀