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

prevOpen Source→ast-comparenext

ast-compare4.2.6

Compare anything: AST, objects, arrays, strings and nested thereof

Downloads per monthChangelogMIT Licenselibera manifesto
  • the top
  • Installation
  • Quick Take
  • Examples
  • PURPOSE
  • MIGRATING FRO…
  • COMPARE()
  • OBJECT MATCHI…
  • ARRAY MATCHI…
  • WHITESPACE…
  • WILDCARD MAT…
  • PROGRESS AND…
  • DEFAULTS
  • VERSION
  • TYPES
  • OPTS — VERBOSEWHEN…
  • DIFFERENCES…
  • Changelog

No 3rd party dependencies. All dependencies and devDependencies, checked recursively, are Codsen packages.

Permalink to InstallationInstallation

Permalink to Quick TakeQuick Take

Permalink to ExamplesExamples

  • Compare Arrays
  • Compare Plain Objects
  • Compare Strings
  • opts.arrayOrder
  • opts.hungryForWhitespace
  • opts.matchStrictly
  • opts.useWildcards
  • opts.verboseWhenMismatches
  • Report deterministic work and elapsed time
  • Report comparison progress
  • Match each unordered array element only once
  • Compare nested arrays without regard to order
  • Match object keys using wildcards

Purpose

compare(firstValue, secondPattern) checks whether the second value is equal to, or a subset of, the first. It is especially useful for comparing abstract syntax trees (ASTs).

It compares parsed HTML and CSS trees or individual branches.

import { compare } from "ast-compare";

compare({ tag: "a", attrs: { href: "/" } }, { tag: "a" });
// true

compare({ tag: "a", attrs: { href: "/" } }, { tag: "a" }, {
  matchStrictly: true,
});
// false: the first object has an extra key

Supported values are strings, numbers, booleans, null, plain objects, arrays, and explicit undefined, including nested combinations of these values.

Migrating from ast-loose-compare

For whitespace-tolerant subset comparisons, enable hungryForWhitespace when calling compare. Read the migration guide before replacing looseCompare: array matching, missing-input handling, and some primitive results differ. The default options of compare remain unchanged.

compare()

The main function compare() is imported like this:

The function takes two values and an optional options object:

Input argumentTypeRequiredDescription
firstValue
Type: ComparableValue
firstValueComparableValueyesThe value that may contain the requested pattern.
secondPattern
Type: ComparableValue
secondPatternComparableValueyesThe value that must equal, or be a subset of, the first value.
opts
Type: Partial<Opts> or null
optsPartial<Opts> or nullnoOptions. null has the same effect as omitting this argument.
  • A match returns true.
  • A mismatch returns false by default. With verboseWhenMismatches: true, it returns a string that describes the mismatch and its path.
  • Missing arguments and invalid options throw a TypeError or RangeError with an identifier such as [THROW_ID_01].

The function does not mutate either input.

The options object has the following shape:

KeyTypeDefaultDescription
arrayOrder
Type: "ordered" or "any"
Default: "ordered"
arrayOrder"ordered" or "any""ordered"Match array patterns as an ordered subsequence, or match each pattern item at any unused position.
hungryForWhitespace
Type: boolean
Default: false
hungryForWhitespacebooleanfalseTreat recursively whitespace-only strings and containers as equivalent empty values.
matchStrictly
Type: boolean
Default: false
matchStrictlybooleanfalseRequire arrays and objects to contain the same number of entries as their patterns.
reportCompletionFunc
Type: function or null
Default: null
reportCompletionFuncfunction or nullnullReceive completion statistics after a comparison.
reportProgressFunc
Type: function or null
Default: null
reportProgressFuncfunction or nullnullReceive monotonic progress percentages.
reportProgressFuncFrom
Type: number
Default: 0
reportProgressFuncFromnumber0Set the start of the progress range.
reportProgressFuncTo
Type: number
Default: 100
reportProgressFuncTonumber100Set the end of the progress range.
verboseWhenMismatches
Type: boolean
Default: false
verboseWhenMismatchesbooleanfalseReturn an explanatory string instead of false when values do not match.
useWildcards
Type: boolean
Default: false
useWildcardsbooleanfalseEnable wildcard string patterns in values and object keys.

The options object accepts only the keys listed in this table, with values of the documented types. Omit an option to use its default; explicitly setting an option to undefined is invalid. Progress range endpoints must be finite numbers, and the start must not exceed the end.

The exported defaults object is a frozen, read-only snapshot. Attempting to modify it cannot change later comparisons.

Object matching

The second object’s own enumerable string keys must exist in the first object, and their values must match. Inherited properties, non-enumerable properties, and symbol keys do not participate. Key order does not matter.

By default, the first object can contain extra keys. matchStrictly: true requires equal key counts at every depth. An empty object pattern matches only an empty object unless both values qualify for whitespace matching.

Array matching

With the default arrayOrder: "ordered", pattern items must appear in the first array in the same order, but other items can occur between them. With arrayOrder: "any", every pattern item must match a different item in the first array; repeated or ambiguous items are matched one-to-one. These rules apply at every depth.

compare(["a", "b", "c"], ["a", "c"]); // true
compare(["a", "b"], ["b", "a"]); // false
compare(["a", "b"], ["b", "a"], { arrayOrder: "any" }); // true
compare(["a", "b"], ["a", "a"], { arrayOrder: "any" }); // false

matchStrictly: true additionally requires equal array lengths at every depth. With ordered matching, this means corresponding positions must match. Wildcard keys and values keep their normal meaning in strict mode. Whitespace matching can override the length and key-count requirements, as described next.

Whitespace matching

With hungryForWhitespace: true, any two recursively empty values match, even when their types, shapes, lengths, or key counts differ. This also applies with matchStrictly: true. Empty values are:

  • strings containing only whitespace;
  • arrays whose entries are all empty; and
  • plain objects whose values are all empty.

Numbers, booleans, null, undefined, and sparse array holes are meaningful; they are not whitespace. A whitespace-only pattern does not match meaningful content merely because it appears inside an array or object. Sparse array holes compare as undefined.

compare({ content: [" ", "\n"] }, [], {
  hungryForWhitespace: true,
  matchStrictly: true,
});
// true: both values are recursively empty

compare(["content"], [" "], { hungryForWhitespace: true }); // false

Wildcard matching

With useWildcards: true, * matches zero or more characters, including line breaks. Escape it as \* to match a literal asterisk. A leading ! negates the whole pattern. Matching is case-sensitive and anchored to the complete string. The second value supplies the pattern; wildcard syntax in the first value is ordinary text.

compare("heading", "head*", { useWildcards: true }); // true
compare("heading", "!head*", { useWildcards: true }); // false
compare("*", "\\*", { useWildcards: true }); // true: a literal asterisk

Wildcard object keys are fallbacks: an exact own enumerable key takes precedence when it exists. Each wildcard key must consume a different key in the first object, and the corresponding values must recursively match as well. An exact key that fails its value comparison does not fall back to other keys.

compare({ dataPrimary: 1, dataSecondary: 2 }, { "data*": 2 }, {
  useWildcards: true,
});
// true: dataSecondary matches both the key pattern and the value

Progress and completion reports

reportProgressFunc receives the configured start value and end value for both matches and mismatches. Longer comparisons also emit monotonic intermediate values. These are estimates based on work performed, not exact percentages of the total work. Short comparisons can emit only the endpoints; equal endpoints produce one callback.

Use reportProgressFuncFrom and reportProgressFuncTo to compose this work into a wider progress range. Callbacks run synchronously during compare().

reportCompletionFunc receives these statistics:

KeyDescription
candidateComparisons
candidateComparisonsCandidate pairs checked during unordered array or wildcard matching.
comparisons
comparisonsNested value comparisons performed.
matchingEdges
matchingEdgesCompatible candidate pairs found for injective matching.
timeTakenInMilliseconds
timeTakenInMillisecondsBest-effort elapsed time.

The counters describe work performed by the implementation; their values can change when the comparison algorithm is optimized. Elapsed time is measured in milliseconds and can be zero for short comparisons or when the clock is unavailable.

Exceptions thrown by either reporting callback are ignored and do not change the comparison result.

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.

version

You can import version:

Types

This package is written in TypeScript and exports the following types:

TypeDescription
AnyObject
Type: AnyObject
AnyObjectA read-only object with string keys and unknown values.
BooleanOpts
Type: BooleanOpts
BooleanOptsOptions that make compare() return a boolean.
ComparableValue
Type: ComparableValue
ComparableValueA JsonValue or explicit undefined.
CompletionStats
Type: CompletionStats
CompletionStatsCounters and elapsed time passed to reportCompletionFunc.
JsonArray
Type: JsonArray
JsonArrayA read-only array of JsonValue or undefined entries.
JsonObject
Type: JsonObject
JsonObjectA read-only object whose values are JsonValue or undefined.
JsonValue
Type: JsonValue
JsonValueA nested string, number, boolean, null, JsonObject, or JsonArray.
Opts
Type: Opts
OptsThe complete options object documented above.
VerboseOpts
Type: VerboseOpts
VerboseOptsOptions with verboseWhenMismatches: true, making the return type true | string.
import type {
  AnyObject,
  BooleanOpts,
  ComparableValue,
  CompletionStats,
  JsonArray,
  JsonObject,
  JsonValue,
  Opts,
  VerboseOpts,
} from "ast-compare";

opts.verboseWhenMismatches

Use verboseWhenMismatches: true when you need to explain why a pattern did not match. Every mismatch returns a string containing the failing path, the reason, and correctly labelled first and second values. A successful comparison still returns true.

The VerboseOpts overload exposes this as true | string; it does not return false.

Differences from _.isMatch

Partial comparisons will match empty array and empty object source values against any array or object value, respectively.

Lodash isMatch documentationopens in a new tab

_.isMatchopens in a new tab matches an empty array pattern to every array. That is often undesirable when comparing parsed HTML or CSS trees. This library does not match an empty array or object pattern to a non-empty value of the same type unless hungryForWhitespace is enabled and both values are recursively whitespace-empty.

compare(["a", "b", "c"], []); // false
compare({ tag: "a" }, {}); // false

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