Skip to content

Drswith/jsesc-es

Repository files navigation

jsesc-es

npm version npm downloads jsdelivr unpkg TypeScript ES Modules License: MIT

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:

  1. it outputs JavaScript instead of JSON by default, enabling support for data structures like ES6 maps and sets;
  2. it offers many options to customize the output;
  3. its output is ASCII-safe by default, thanks to its use of escape sequences 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.

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.

✨ 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

# 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)

// 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

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)

// 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:

{
  "type": "module"
}

Or use .mjs file extension:

// 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. 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\'}'

Options

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
}

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.

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.'

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.

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.

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.

// 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.

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.

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 in the output are escaped.

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.

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.

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.

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.

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.

jsesc('Ich ♥ Bücher', {
  lowercaseHex: true
})
// → 'Ich \\u2665 B\\xfccher'
//                    ^^

jsesc(42, {
  numbers: 'hexadecimal',
  lowercaseHex: true
})
// → '0x2a'
//      ^^

Version Information

// 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

# Remove old package
npm uninstall jsesc

# Install new package
npm install jsesc-es

2. Update Imports

// 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.

TypeScript Examples

Creating Utility Functions

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

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

# 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 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 file for details.

Acknowledgments

  • 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. 🚀

About

Given some data, jsesc returns the shortest possible stringified & ASCII-safe representation of that data.

Resources

License

Contributing

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors