htmlnano

website·Indexed 30 days ago

https://htmlnano.netlify.app/

A modular HTML minifier built on top of PostHTML. The documentation covers the JavaScript API, configuration options, and specific modules for safe HTML attribute transformations, including versions 3.5.1 and Next.

Tokens
12.7K
Snippets
68
Records
76
Agent score
72%

What's inside htmlnano

  1. Overview of htmlnano HTML minification

    htmlnano is a modular HTML minifier built on top of PostHTML and inspired by cssnano. It is designed for production HTML optimization using a modular architecture where each module handles a specific concern (such as comments, whitespace, attributes, inline CSS, or inline JS).

    Key features include:

    • Safe by default: Uses a safe preset for conservative transforms.
    • Granular Configuration: Modules can be enabled, disabled, or tuned independently.
    • Extensibility: Supports optional modules for CSS, JS, and URL minification.
    • Flexible Integration: Available via JS API, PostHTML, CLI, or bundler integrations.
  2. Overview of htmlnano HTML minifier

    htmlnano is a modular HTML minifier built on top of PostHTML, inspired by cssnano. It is designed for production HTML optimization and is safe by default using a conservative safe preset. It allows developers to enable, disable, or tune individual transformation modules independently and can be integrated via JS API, PostHTML, CLI, or various bundlers.
  3. Add a new minification module to htmlnano

    htmlnano uses a modular architecture that allows developers to add new minification tasks by following these steps:

    1. Create a new module file in src/_modules/ that performs a single minification task.
    2. Assign the module to one or more presets in src/presets/. Choose the preset based on the risk level: safe, ampSafe, or max.
    3. Implement unit tests for the module in test/modules/ using TypeScript.
    4. Add documentation for the new module in docs/docs/050-modules.md.
    5. Validate the changes by running npm run lint and npm run build before submitting a pull request.
    npm run lint
    npm run build
  4. Merge multiple style tags

    The mergeStyles module combines multiple <style> tags into a single tag if they share the same normalized media and type attributes, and all other attributes (like nonce or data-*) match exactly.

    Normalization Rules:

    • Missing or empty type is treated as text/css.
    • Missing or empty media is treated as all (whitespace is collapsed).
    • Boolean attributes (e.g., amp-custom) are treated as present when set.

    Exclusions:

    • Tags with scoped or integrity attributes are skipped.
    • AMP boilerplate styles (amp-boilerplate, amp4ads-boilerplate, amp4email-boilerplate) are skipped.

    Merging Logic & Source Order: To prevent CSS specificity issues, only contiguous runs of mergeable styles are combined. A merge group is closed (and a new one started) if any of the following appear between styles:

    • A <link rel="stylesheet"> tag.
    • A <style> tag with different attributes or a skipped attribute (e.g., scoped).
    • A <noscript> tag.

    Non-stylesheet content (text, comments, preload links) does not break a merge group. Styles inside <template> or <noscript> are merged within their own scope and never with the surrounding document.

  5. Normalize HTML attribute values

    The normalizeAttributeValues module performs three main tasks: it normalizes the casing of case-insensitive attributes (e.g., form[method], img[crossorigin]), trims surrounding whitespace from those values, and applies the HTML spec's 'invalid value default' for specific elements (e.g., button[type] becomes submit if invalid). Note that invalid value defaults are only applied to a specific list of elements; for example, button[type] is normalized, but input[type] is not.
    <!-- Source -->
    <form method="GET"></form>
    <img loading="">
    <button type="EXAMPLE"></button>
    
    <!-- Minified -->
    <form method="get"></form>
    <img loading="eager">
    <button type="submit"></button>
  6. Remove empty attributes using removeEmptyAttributes

    The removeEmptyAttributes module removes attributes that are empty or contain only whitespace, based on a fixed allowlist. Event handler attributes (e.g., onclick) are always removed when empty. Some attributes are only removed on specific tags (e.g., cols on <textarea>). Certain attributes, like alt, are intentionally preserved even when empty.

    Caveat: This may break CSS or JS that relies on attribute selectors (e.g., img[style=""]).

    <!-- Source -->
    <div id="" class="" title=""></div>
    <button onclick="" onfocus=" "></button>
    <textarea cols=""></textarea>
    <img src="foo.jpg" alt="" style="">
    
    <!-- Minified -->
    <div></div>
    <button></button>
    <textarea></textarea>
    <img src="foo.jpg" alt="">
  7. Remove empty HTML attributes

    The removeEmptyAttributes module removes attributes that are empty or contain only whitespace, provided they are on the allowlist. Event handler attributes (e.g., onclick) are always removed when empty. Some attributes are tag-specific (e.g., cols on <textarea>). Certain attributes, like alt, are intentionally preserved even when empty.

    Caveat: This may break CSS or JS selectors that target empty attributes (e.g., img[style=""]).

    <!-- Source -->
    <div id="" class="" title=""></div>
    <button onclick="" onfocus=" "></button>
    <textarea cols=""></textarea>
    <img src="foo.jpg" alt="" style="">
    
    <!-- Minified -->
    <div></div>
    <button></button>
    <textarea></textarea>
    <img src="foo.jpg" alt="">
  8. Create a custom htmlnano preset

    A preset is a configuration object. You can create a custom preset by spreading a built-in preset and overriding specific module settings, or by passing an empty object to ignore all presets and rely solely on your options object.
    const htmlnano = require('htmlnano');
    
    // Example: Creating an email-specific preset based on 'safe'
    const emailPreset = {
        ...htmlnano.presets.safe,
        mergeStyles: true,
        minifyCss: {
            safe: true
        }
    };
    
    htmlnano.process(html, { removeComments: false }, emailPreset);
    
    // Example: Using no presets at all
    htmlnano.process(html, { /* your options */ }, {});
  9. Deduplicate values in list-like attributes

    Removes duplicate values from list-like attributes including class, rel, ping, sandbox, dropzone, and headers (or sizes on link elements). For case-insensitive token lists (rel, sandbox, dropzone, sizes), duplicates are removed regardless of casing, keeping the first occurrence. Non-list-like attributes are ignored.
    <!-- Source -->
    <link rel="nofollow NoFoLlOw noopener">
    <a class="foo  foo   bar">click</a>
    
    <!-- Minified -->
    <link rel="nofollow noopener">
    <a class="foo    bar">click</a>
  10. Minify HTML inside IE conditional comments

    The minifyConditionalComments module processes HTML inside Internet Explorer conditional comments (both downlevel-hidden and downlevel-revealed). It preserves the conditional comment wrappers but applies the same htmlnano options to the inner HTML, allowing other modules like collapseWhitespace, minifyCss, and minifyJs to operate within the block. Empty conditional comments and standalone <!--<![endif]--> markers are left untouched.
    <!-- Source -->
    <!--[if lte IE 7]>
        <style type=
    
  11. Normalize HTML attribute values with normalizeAttributeValues

    The normalizeAttributeValues module performs three main tasks: it normalizes the casing of case-insensitive attributes (e.g., form[method], img[crossorigin]), trims surrounding whitespace from those values, and applies HTML spec 'invalid value defaults' to specific attributes (e.g., img[loading], button[type]). Note that invalid value defaults are only applied to the specific elements listed in the documentation; for example, button[type] is normalized, but input[type] is not.
    <!-- Source -->
    <form method="GET"></form>
    <img loading="">
    <button type="EXAMPLE"></button>
    
    <!-- Minified -->
    <form method="get"></form>
    <img loading="eager">
    <button type="submit"></button>
  12. Collapse whitespace in attributes with collapseAttributeWhitespace

    The collapseAttributeWhitespace module reduces redundant whitespace in attribute values:

    • List-like attributes (class, rel, ping, sandbox, headers, dropzone, and sizes on <link>): Internal whitespace is collapsed and ends are trimmed.
    • Single-value attributes (href, style, src, width, height): Trimmed when on correct elements.
    • Event handlers (onclick): Trimmed only at the ends; internal whitespace is preserved.
    • srcset/imagesrcset: Re-serialized with a single whitespace between URL and descriptors, and no whitespace after commas (unless the preceding candidate has no descriptor).

    Note: sizes on <img> is not modified.

    <!-- Source -->
    <a class=" content  page  " style="  display: block;    " href="   https://example.com"></a>
    <img srcset="image.png   480w ,  image2.png 2x">
    
    <!-- Minified -->
    <a class="content page" style="display: block;" href="https://example.com"></a>
    <img srcset="image.png 480w,image2.png 2x">