escape-carriage
A tiny npm library that escapes carriage return (\r) characters in text the way a real terminal would render them.
Repository Health
Technical Analysis
escape-carriage is a small, focused JavaScript utility that solves one very specific problem: correctly interpreting carriage return (\r) characters in captured text output. Terminals treat \r as “move the cursor back to the start of the line,” which is how progress bars and spinners overwrite themselves in place. When that raw output is captured and displayed elsewhere (in a browser, a log viewer, or a notebook), naively rendering the \r characters produces garbled, overlapping text instead of the clean final line a real terminal would show.
The package exports two functions: escapeCarriageReturn, which processes a complete chunk of text and collapses each carriage-return-interrupted line down to what a terminal would actually display, and escapeCarriageReturnSafe, a variant designed for streaming scenarios where more output may still be appended to the last line — it leaves the trailing (possibly incomplete) line untouched while still fully resolving all preceding lines.
Originally extracted for use in the nteract/Jupyter notebook ecosystem to correctly render captured stdout from long-running or progress-reporting processes, it has since been picked up as a dependency by tools that need to display raw process output (build tools, CI log viewers, terminal-in-browser components) without the visual corruption that comes from ignoring \r semantics.
What You Get
escapeCarriageReturn(text)— collapses\r-interrupted lines into their final terminal-rendered formescapeCarriageReturnSafe(text)— a streaming-safe variant that leaves the last, possibly-incomplete line untouched so more output can still be appended- Zero runtime dependencies and a tiny (~2KB) footprint suitable for embedding anywhere raw process output is displayed
- Bundled TypeScript type declarations (
index.d.ts) for both named exports and the default export - A default export equal to
escapeCarriageReturnfor drop-inrequire('escape-carriage')usage
Common Use Cases
- Rendering captured stdout from long-running CLI processes (build tools, installers) in a web UI or log viewer without overlapping/garbled text
- Correctly displaying Jupyter/nteract notebook cell output that was produced with progress bars or spinners using
\r - Cleaning up CI/CD log output before storing or re-displaying it, so progress-bar noise collapses to the final reported line
- Building terminal-emulator-like components in the browser that need accurate cursor-return semantics for pasted or streamed text
Under The Hood
Architecture
The entire library is a single CommonJS module (index.js, ~65 lines) exposing two functions built from three small private helpers: a regex-driven escapeCarriageReturn that repeatedly rewrites ^([^\r\n]*)\r+([^\r\n]+) matches to splice later text over earlier text within a line, a findLongestString/escapeSingleLineSafe pair that reconstructs a single line’s final state by tracking the longest \r-delimited segment, and escapeCarriageReturnSafe, which composes the two by splitting the input at the last newline and running the strict algorithm on everything before it while applying the safe, single-line algorithm to the trailing (potentially incomplete) segment. There is no class hierarchy, no state, and no I/O — it is a pure string-transform utility with a single entry point (module.exports) carrying both named exports as properties.
Tech Stack
Plain JavaScript (ES5-style var/function syntax, no transpilation step) with no runtime dependencies at all. TypeScript consumers are served by a hand-written index.d.ts declaration file rather than a TS build. The only tooling present is a GitHub Actions workflow (node.js.yml) running npm ci and npm test on Node 18, plus legacy Travis CI and Greenkeeper badges in the README reflecting its 2016 origin. Packaging is a minimal package.json with main/types fields and no build step — the published package is the source as-is.
Code Quality
Tests live in test/index-spec.js using Mocha + Chai expect assertions, covering both functions against several handcrafted multi-carriage-return strings, including a deliberately “complicated” combined case exercising newline-then-carriage-return sequences. There are no type annotations in the JS source itself (types are provided out-of-band via index.d.ts), no linter configuration, and no CI type-checking step — quality assurance rests entirely on the small, targeted Mocha suite. A benchmark.js script under test/ times both functions against synthetic inputs but is not part of the automated test run.