Skip to Content
  • Website
Codsen
  • Home
  • Open Source
  • Articles
  • About

prevOpen Source→html-crushnext

html-crush6.3.0

Minify email templates

Downloads per monthChangelogMIT LicensePlayground
  • the top
  • Installation
  • Quick Take
  • Examples
  • PURPOSE
  • API — CRUSH()
  • PROGRESS REP…
  • API — DEFAULTS
  • API — VERSION
  • API — TYPES
  • Changelog

Permalink to InstallationInstallation

Permalink to Quick TakeQuick Take

Permalink to ExamplesExamples

  • Configure CSS comment removal
  • Insert line breaks before selected tokens
  • Treat a custom element as inline
  • Choose which HTML comments to remove
  • Wrap minified HTML at a line-length limit
  • Observe progress in a custom interval
  • Remove line indentations
  • Remove HTML line breaks
  • Inspect result metadata and edit ranges
Open html-crush playground

Purpose

html-crush minifies mixed HTML and CSS, with a focus on email templates. It scans the input without parsing it into an abstract syntax tree, so it can work with incomplete markup and templates that contain Nunjucks, JSP, ESP, CDATA, or other embedded languages.

Email HTML needs controls that general web-page minifiers do not always provide. For example, you can preserve Outlook conditional comments and place line breaks before selected tokens to keep generated lines within an email transport limit.

The scanner preserves ordinary quoted attribute values, CSS strings, and the contents of script, pre, code, and textarea elements. HTML element names are matched case-insensitively.

API — crush()

The main function crush() is imported like this:

Pass the HTML source as a string and, optionally, an options object or null:

function crush(str: string, opts?: InputOpts | null): Res;

InputOpts has the following shape. Every property is optional:

interface InputOpts {
  lineLengthLimit?: number;
  removeIndentations?: boolean;
  removeLineBreaks?: boolean;
  removeHTMLComments?: boolean | 0 | 1 | 2;
  removeCSSComments?: boolean;
  reportProgressFunc?: null | false | 0 | ((percentage: number) => void);
  reportProgressFuncFrom?: number;
  reportProgressFuncTo?: number;
  breakToTheLeftOf?: string[] | null | false;
  mindTheInlineTags?: string[];
}
KeyInput typeDefaultDescription
lineLengthLimit
Default: 500
lineLengthLimitnumber500Sets the preferred maximum line length when removeLineBreaks is enabled.
removeIndentations
Default: true
removeIndentationsbooleantrueRemoves indentation while retaining line breaks. Enabling removeLineBreaks also enables this behavior.
removeLineBreaks
Default: false
removeLineBreaksbooleanfalseRemoves existing line breaks, subject to lineLengthLimit and breakToTheLeftOf.
removeHTMLComments
Default: false
removeHTMLCommentsboolean | 0 | 1 | 2falsefalse or 0 keeps comments. true or 1 removes ordinary comments but preserves Outlook conditionals. 2 removes all recognized HTML comments, including conditionals.
removeCSSComments
Default: true
removeCSSCommentsbooleantrueRemoves recognized CSS comments in style elements and quoted style attributes. Comment-like text inside CSS strings is preserved.
reportProgressFunc
Default: null
reportProgressFuncFunction or null, false, or 0nullReceives integer progress values for sufficiently large inputs. See Progress reporting.
reportProgressFuncFrom
Default: 0
reportProgressFuncFromnumber0Sets the beginning of the reported progress interval.
reportProgressFuncTo
Default: 100
reportProgressFuncTonumber100Sets the end of the reported progress interval.
breakToTheLeftOf
Default: See below
breakToTheLeftOfstring[] | null | falseSee belowStarts a new line before a matching token when removeLineBreaks is enabled. Pass false, null, or an empty array to disable the defaults.
mindTheInlineTags
Default: See below
mindTheInlineTagsstring[]See belowLists inline element names whose surrounding whitespace needs extra protection.

Here are all defaults in one place for copying:

The function returns a plain Res object:

type Range =
  | [from: number, to: number]
  | [from: number, to: number, whatToInsert: string | null | undefined];

interface Res {
  log: {
    timeTakenInMilliseconds: number;
    originalLength: number;
    cleanedLength: number;
    bytesSaved: number;
    percentageReducedOfOriginal: number;
    originalLengthInCodeUnits: number;
    cleanedLengthInCodeUnits: number;
    codeUnitsSaved: number;
    percentageReducedOfOriginalInCodeUnits: number;
    originalLengthInUtf8Bytes: number;
    cleanedLengthInUtf8Bytes: number;
    utf8BytesSaved: number;
    percentageReducedOfOriginalInUtf8Bytes: number;
  };
  applicableOpts: {
    removeHTMLComments: boolean;
    removeCSSComments: boolean;
  };
  ranges: Range[] | null;
  result: string;
}
KeyDescription
result
resultThe minified HTML string.
ranges
rangesThe edits in ranges notation, or null when no edit is needed.
applicableOpts
applicableOptsReports whether the input contains removable HTML or CSS comments, independently of the current removal settings.
log
logContains elapsed time and size statistics.

The result contains only plain objects, arrays, strings, numbers, booleans, and null. It can be serialized as JSON or sent through postMessage().

Size and timing fields

JavaScript string lengths count UTF-16 code units, not bytes. The explicit fields distinguish those lengths from the UTF-8 size that an encoded email would occupy. Percentages are rounded to the nearest integer.

log fieldMeaning
timeTakenInMilliseconds
timeTakenInMillisecondsBest-effort elapsed time. Do not use it for exact comparisons.
originalLength
originalLengthLegacy input length in UTF-16 code units.
cleanedLength
cleanedLengthLegacy output length in UTF-16 code units.
bytesSaved
bytesSavedLegacy name for UTF-16 code units saved. This field does not contain a byte count.
percentageReducedOfOriginal
percentageReducedOfOriginalLegacy reduction percentage calculated from UTF-16 code units.
originalLengthInCodeUnits
originalLengthInCodeUnitsInput length in UTF-16 code units.
cleanedLengthInCodeUnits
cleanedLengthInCodeUnitsOutput length in UTF-16 code units.
codeUnitsSaved
codeUnitsSavedNumber of UTF-16 code units removed.
percentageReducedOfOriginalInCodeUnits
percentageReducedOfOriginalInCodeUnitsReduction percentage calculated from UTF-16 code units.
originalLengthInUtf8Bytes
originalLengthInUtf8BytesInput size in UTF-8 bytes.
cleanedLengthInUtf8Bytes
cleanedLengthInUtf8BytesOutput size in UTF-8 bytes.
utf8BytesSaved
utf8BytesSavedNumber of UTF-8 bytes removed.
percentageReducedOfOriginalInUtf8Bytes
percentageReducedOfOriginalInUtf8BytesReduction percentage calculated from UTF-8 bytes.

For compatibility, the four legacy size fields keep their existing UTF-16 code-unit meaning. Use the explicit fields in new integrations.

Progress reporting

Use reportProgressFunc when crush() runs in a Web Worker or another UI that needs completion feedback. Inputs of 1,000 code units or fewer do not call the callback. Inputs from 1,001 through 1,999 code units report a midpoint and completion. Longer inputs report incremental values.

Every reported value is an integer within the interval configured by reportProgressFuncFrom and reportProgressFuncTo. Both changed and unchanged inputs finish at the configured ending value. The callback is observational: it does not change the result, ranges, or deterministic statistics.

import { crush } from "html-crush";

const res = crush(source, {
  removeLineBreaks: true,
  reportProgressFunc: (percentage) => {
    postMessage({ type: "progress", percentage });
  },
});

postMessage({ type: "result", res });

API — defaults

You can import defaults:

It's a plain object:

The main function calculates the options to be used by merging the options you passed with these defaults.

API — version

You can import version:

API — types

This package is written in TypeScript and exports these public types:

TypeDescription
InputOpts
Type: InputOpts
InputOptsThe optional input accepted by crush(), including the supported disabling sentinels.
Opts
Type: Opts
OptsThe fully resolved internal option shape after defaults and input normalization.
Res
Type: Res
ResThe minified result, edit ranges, applicability report, and completion statistics.
import type { InputOpts, Opts, Res } from "html-crush";

Permalink to changelogChangelog

Open Changelog
↑ back to top
prev next

Copyright

All rights reserved © Roy Revelt 2026
All our open source packages are under MIT licenceopens in a new tab

Activities

🐛 See a bug? Raise an issueopens in a new tab
💘 Check out the Indiewebopens in a new tab and Libera manifestoopens in a new tab