Back
extracted
strip-ansi
v7.1.2
MIT

stripAnsi

A vendorable bundle of strip-ansi with ansi-regex inlined. Useful when you want the package behavior locally without carrying the dependency pair in your app.

Why copy this?

This page ships a source-faithful strip-ansi bundle with ansi-regex inlined. The point is to keep a tiny, inspectable ANSI stripping helper in your repo without installing both packages.

Native alternative: Node.js offers util.stripVTControlCharacters, but teams may still want a vendorable cross-runtime helper with fixed behavior in local code.

Note: This snippet is extracted rather than copied as-is because the published strip-ansi file imports ansi-regex.

This copy is your responsibility once you adopt it. It does not automatically receive upstream bug fixes or security updates.

Snippet
Copy-first distribution
Normalized
ESM / TS / normalized
Runtime: node, bun
/**
 * Derived from strip-ansi@7.1.2
 * Rule-based normalized variant generated by this repository.
 * Preserve the upstream license and attribution notices when copying this file.
 */
/**
 * Derived from strip-ansi@7.1.2
 * Rule-based normalized variant generated by this repository.
 * See THIRD_PARTY_NOTICES.md for upstream license and attribution details.
 */
type AnsiRegexOptions = {
  readonly onlyFirst?: boolean;
};

function ansiRegex({ onlyFirst = false }: AnsiRegexOptions = {}): RegExp {
  // Valid string terminator sequences are BEL, ESC\, and 0x9c
  const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";

  // OSC sequences only: ESC ] ... ST (non-greedy until the first ST)
  const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`;

  // CSI and related: ESC/C1, optional intermediates, optional params (supports ; and :) then final byte
  const csi = "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]";

  const pattern = `${osc}|${csi}`;

  return new RegExp(pattern, onlyFirst ? undefined : "g");
}

const regex = ansiRegex();

export default function stripAnsi(string: string): string {
  if (typeof string !== "string") {
    throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
  }

  // Even though the regex is global, we don't need to reset the `.lastIndex`
  // because unlike `.exec()` and `.test()`, `.replace()` does it automatically
  // and doing it manually has a performance penalty.
  return string.replace(regex, "");
}
Variant note: Source-faithful bundle with upstream TypeScript signature folded in for copy-paste into modern TS projects.
Transforms: bundled-upstream-dependency, js-extension-to-ts-extension, dts-signature-to-ts-annotation
Validation: This normalized variant is intended to stay oxlint and oxfmt clean in this repo.
Raw
ESM / JS / raw
Runtime: node, bun
function ansiRegex({onlyFirst = false} = {}) {
  // Valid string terminator sequences are BEL, ESC\, and 0x9c
  const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";

  // OSC sequences only: ESC ] ... ST (non-greedy until the first ST)
  const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`;

  // CSI and related: ESC/C1, optional intermediates, optional params (supports ; and :) then final byte
  const csi =
    "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]";

  const pattern = `${osc}|${csi}`;

  return new RegExp(pattern, onlyFirst ? undefined : "g");
}

const regex = ansiRegex();

export default function stripAnsi(string) {
  if (typeof string !== "string") {
    throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
  }

  // Even though the regex is global, we don't need to reset the `.lastIndex`
  // because unlike `.exec()` and `.test()`, `.replace()` does it automatically
  // and doing it manually has a performance penalty.
  return string.replace(regex, "");
}
Variant note: Source-faithful extracted bundle from strip-ansi with its ansi-regex dependency inlined into a single ESM file.