npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@egainoss/htmldiff-ts

v1.0.9

Published

Revamped version of htmldiff-js. Display diff between two html strings.

Readme

htmldiff-ts

This is a fork of htmldiff-js, which is a JavaScript port of HtmlDiff.NET, which is itself a C# port of the Ruby implementation, HtmlDiff.

NPM package: @wesley-edwards/htmldiff-ts

Changes in 1.0.9

Version 1.0.9 fixes a regression from 1.0.8 where deleted content lost its bold and italic formatting. On the delete side, insertTag was replacing every <strong> / <em> with <del class="mod">, so diffing an article against an empty article stripped all 271 formatting tags from the output.

Fix

Delete-side tag runs are now emitted verbatim. Only the insert side uses renderTagRun to wrap formatting changes with <ins class="mod">. Deleted bold text now renders as <strong><del class="diffdel">text</del></strong> instead of <del class="mod"><del class="diffdel">text</del></del>.

Changes in 1.0.8

Version 1.0.8 fixes a leaking <strong> (or any inline formatting tag) that made the rest of the document render as bold. It showed up most clearly when diffing an article against an empty article, where every word becomes a delete.

Root cause

insertTag only inspected the first token of a run of consecutive tags. A formatting tag that appeared later in the run (for example the </strong> in </a></strong>, or the <strong> in <li><strong>) was written to the output verbatim and never pushed to or popped from specialTagDiffStack. The stack drifted out of sync, so a later </strong> matched a stale entry and was replaced by </del> instead of being written out, leaving its <strong> open for the rest of the document.

Fixes (insertTag)

| Change | Why | |--------|-----| | Walk every tag in a run (renderTagRun) instead of only words[0] | Keeps specialTagDiffStack in sync with what is actually written to the output | | Derive formatting tags from FORMATTING_TAGS in Utils instead of a separate regex and closing-tag map | Removes the stateful /g regex and the missing </sup> entry | | Emit the remaining mod wrappers at the end of insertTag | A formatting element can open in one operation and close in another; the output now stays balanced |

Formatting-only changes

coalesceWrapperOperations now also coalesces formatting tags, not just semantic wrappers such as eg-condition. Adding or removing only the formatting around unchanged text (for example <strong>First option:</strong>First option:) is split into delete / equal / delete operations, which previously emitted an empty <del class="mod"> plus an orphan </strong>. Those three operations are now coalesced into a single replace, so they render through the format-change highlights added in 1.0.5.

Changes in 1.0.7

Version 1.0.7 fixes corrupted diffs when only block-level tag attributes change (for example <table> gaining class="confluenceTable wrapped" or <div> gaining panel wrapper classes). Block and structural elements now receive a data-diff="attrmod" marker on the changed opening tag instead of being wrapped in <ins class="diffmod"> / <del class="diffmod">, which previously produced invalid HTML and caused the browser to highlight most of the document.

Inline and semantic elements (such as eg-condition) still use the existing <ins class="diffmod"> wrap behaviour from 1.0.4.

Changes in 1.0.6

Version 1.0.6 fixes invisible diffs when plain text is wrapped or unwrapped in semantic tags such as eg-condition. Wrapper insert/delete operations are coalesced and rendered with structure-change highlights instead of emitting raw tags.

Changes in 1.0.5

Version 1.0.5 fixes noisy diffs for formatting-only inline changes (for example bolding one character in testt<strong>e</strong>st). When plain text is unchanged, processReplaceOperation now renders format-change highlights instead of del.diffmod/ins.diffmod fragmentation.

Changes in 1.0.4

Version 1.0.4 fixes invisible diffs when only HTML tag attributes change (for example eg-condition tags="..." updates). Matching still strips attributes to find structural anchors, but processEqualOperation now detects attribute-only tag differences and wraps the full new element subtree in <ins class="diffmod"> without a <del> wrapper.

Changes in 1.0.3

Version 1.0.3 fixes incorrect handling of inline formatting tags (<strong>, <em>, <b>, <i>, etc.) inside insertTag in src/Diff.js. The bug showed up when a replace operation ran a delete pass followed by an insert pass on the same region (for example, collapsing a nested list step into flat list text). The diff could emit unbalanced markup such as </strong></li><strong>, which made the rest of the document render as bold.

Root cause

specialTagDiffStack tracked open formatting tags while wrapping changed text with <ins class="mod"> / <del class="mod">. The stack was shared across the delete and insert halves of a replace, and closing tags were popped even when they did not match the stack top. On delete, closing tags were sometimes removed from the token stream without being written to the output.

Fixes (insertTag)

| Change | Why | |--------|-----| | Reset specialTagDiffStack at the start of each insertTag call | Prevents state from the delete pass leaking into the insert pass on replace operations | | Use <del class="mod"> / </del> for delete and <ins class="mod"> / </ins> for insert | Mod wrappers must match the operation type; previously both used <ins class="mod"> | | Peek the stack top and only pop when the closing tag matches | Avoids dropping </strong> (and similar) on mismatch | | On delete, strip closing formatting tags only after a successful stack match | Keeps needed closing tags in the output when the stack does not match |

Build

npm install
npm run build

The package entry point is dist/htmldiff.min.js. Use Node 14 when building this project (see package.json scripts).