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

prevOpen Source→ranges-mergenext

ranges-merge9.2.5

Merge and sort string index ranges

Downloads per monthChangelogMIT Licenselibera manifesto
  • the top
  • Installation
  • Quick Take
  • Examples
  • API — RMERGE()
  • API — DEFAULTS
  • API — VERSION
  • API — TYPES
  • OPTS — PROGRESSFN
  • OPTS — MERGETYPE
  • EXAMPLE
  • 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

  • Keep the touching ranges separate
  • Merge two overlapping ranges
  • Prefer the latter value with merge type two
  • A null replacement wins over text
  • Remove the ranges that do nothing
  • Report the merging progress

API — rMerge()

The main function rMerge() is imported like this:

The function accepts two arguments:

Input argumentTypeObligatoryDescription
arrOfRanges
Type: Array
Obligatory: yes
arrOfRangesArrayyesZero or more arrays that represent natural-number index ranges
opts
Type: Plain object
Obligatory: no
optsPlain objectnoOptional configuration object. See the options API below.

The function does not mutate either argument.

The Optional Options Object has the following shape:

KeyTypeDefaultDescription
mergeType
Type: 1, 2, "1", or "2"
Default: 1
mergeType1, 2, "1", or "2"1Controls how clashing insertion values are combined. See mergeType.
progressFn
Type: false, null, or function
Default: null
progressFnfalse, null, or functionnullReceives monotonically increasing integer percentages between 0 and 99. For non-empty input, the final callback value is 99. Set it to false or null to disable progress reporting.
joinRangesThatTouchEdges
Type: boolean
Default: true
joinRangesThatTouchEdgesbooleantrueJoins touching ranges such as [[1, 2], [2, 3]]. Set this option to false to keep them separate, for example when reporting separate issues.

Pass opts as an ordinary plain object (including a null-prototype object), or omit it. Arrays, primitives, and objects such as Date and Map are rejected.

Here are all defaults in one place for copying:

The function returns merged ranges: null or an array containing one or more range arrays.

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 the following types:

TypeDescription
Opts
Type: Opts
OptsThe Optional Options Object of rMerge(), documented above.
ProgressFn
Type: ProgressFn
ProgressFnThe signature of opts.progressFn — called with the percentage done.
UnknownValueObj
Type: UnknownValueObj
UnknownValueObjA plain object with string keys and values of any type.
Range
Type: Range
RangeA single range, re-exported from ranges-sort.
Ranges
Type: Ranges
RangesZero or more Ranges, or null, re-exported from ranges-sort.
import type {
  Opts,
  ProgressFn,
  Range,
  Ranges,
  UnknownValueObj,
} from "ranges-merge";

opts.progressFn

Collect progress values by passing a callback in the options object:

const percentages = [];
const result = rMerge(
  [
    [1, 5],
    [11, 15],
    [6, 10],
    [16, 20],
    [10, 30],
  ],
  {
    progressFn: (percentage) => percentages.push(percentage),
  },
);

console.log(percentages[percentages.length - 1]);
// => 99

console.log(result);
// => [[1, 5], [6, 30]]

Intermediate percentages depend on the amount of work and the runtime’s sort schedule. They never decrease or repeat, and a non-empty invocation reports 99 before returning. This callback is useful when the function runs in a web worker and the interface needs progress updates.

opts.mergeType

Before merging, the function sorts ranges by their start index and then their end index. Ranges with identical start and end indexes keep their input order. The function then merges overlapping pairs from the end of the sorted array.

mergeType controls what happens when third-element insertion values clash.

For example,

const range1 = [1, 2, "a"];
const range2 = [1, 2, "b"];

These ranges say to replace characters from index 1 to 2 with "a" and with "b", respectively.

Do you end up with "ab" or "b" or something else?

Choose one of the following merge modes:

  • With mergeType: 1 (the default), contributing insertion values are combined. The example produces "ab".
  • With mergeType: 2, the latter value replaces the former only when both ranges start at the same index. The example produces "b". For exact coordinate ties, “latter” means later in the caller’s input array.

The two modes behave identically in all other respects. String aliases "1" and "2" are also accepted.

null insertion values

An explicit null insertion cancels replacement text. If any ranges being merged contain null, the merged insertion is null, even when the null range is wholly contained within another range.

Example

Imagine a messed up piece of code: <div>&nbbsp;</div>. Let’s say our imaginary cleaning program detected two issues with it:

  • Unencoded ampersand at position 5
  • Malformed &nbsp; where b is duplicated

Range-wise, it could look like this:

[
  {
    name: "bad-character-unencoded-ampersand",
    position: [[5, 6, "&amp;"]],
  },
  {
    name: "malformed &nbsp;",
    position: [[5, 12, "&nbsp;"]],
  },
];

The insertion values for [5, 6] and [5, 12] clash. In this case, the latter value should replace the former, so use mergeType: 2.

Mode 2 resolves same-start clashes by keeping the latter value in sorted range order.

For example,

import { rMerge } from "ranges-merge";
const res1 = rMerge(
  [
    [3, 4, "aaa"],
    [3, 12, "zzz"],
  ],
  { mergeType: 1 },
);
console.log(res1);
// => [[3, 12, "aaazzz"]]

const res2 = rMerge(
  [
    [3, 4, "aaa"],
    [3, 12, "zzz"],
  ],
  { mergeType: 2 },
);
console.log(res2);
// => [[3, 12, "zzz"]]

The ranges have the same start index, so sorting compares their end indexes next. [3, 12, "zzz"] comes after [3, 4, "aaa"]; in mode 2, its insertion value replaces "aaa".

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