Iterate string considering ranges, as if they were already applied

§ Quick Take

import { strict as assert } from "assert";
import processOutside from "ranges-process-outside";

const gathered = [];

// a callback interface:
    [1, 5], // delete from "b" to "f"
  (fromIdx, toIdx, offsetValueCb) => {

assert.deepEqual(gathered, [0, 5, 6, 7, 8, 9]);

§ Purpose

Processes the string outside the given ranges. Each "gap" in the string between ranges will be fed into callback you supply — same like in Array.prototype.forEach().

This program makes the life easier because if you did it manually, you'd have to invert ranges and loop over each inverted chunk. Finally, you'd have to write unit tests of all that.


processOutside(originalStr, originalRanges, cb, [skipChecks])

In other words, it's a function which takes 4 arguments:

Input argumentTypeObligatory?Description
originalStrstringyesSource string
originalRangesnull or ranges - array of arraysyesString indexes outside these ranges will be processed (fed to callback function)
cbfunctionyesCallback function you provide (like in Array.forEach)
skipChecksbooleannoBy default checks are performed upon inputs but you can turn that off to boost the performance

§ Callback cb

This program operates in a callback fashion, just like Array.prototype.forEach(), for example:

const processOutside = require("ranges-process-outside");
const gather = [];
[[0, 5]],
(idx) => {
// => [5, 6, 7, 8, 9]

This (idx) => { gather.push(idx); } above is the callback function (as arrow opens in a new tab-function).

It's API is the following:

Input argumentTypeDescription
fromIdxString index: natural number or zeroStarting index of the chunk programs pings you
toIdxString index: natural number or zeroEnding index of the chunk programs pings you
offsetValueCbFunction or something falsyCallback function to bump the indexes in the loop that pings you all this. See below for more.

§ offsetValueCb API

A callback inside a callback!

offsetValueCb argument the cb() gives you is a function. Call it with a single argument, a natural number — that will instruct the outer loop function to skip that many characters.

For example, skip one character:

const processOutside = require("ranges-process-outside");
const gather = [];
[[0, 5]],
(fromIdx, toIdx, offsetValueCb) => {
if (fromIdx === 6) {
// at index 6, skip the next index:
// => [5, 6, 8, 9]
// notice 7 is missing because we skipped by 1 while being at index 6

The third argument in the callback cb (the arrow function (fromIdx, toIdx, offsetValueCb) => {...} above) is a function which lets you bump the looping index. This way, you can skip the characters being pinged.

For example, Detergent processes HTML code. A string with bunch of invisible characters are detected and their from-to ranges are pushed to ranges being gathered. While processing the input further, Detergent avoids processing the characters booked for deletion (marked by ranges). It uses this program to work on everything in-between the ranges (invisible character locations). Now, Detergent detects a named HTML entity:  . Once it stumbles on its first character, the ampersand &, it does what it has to do and it needs to skip 6 characters further.

This skipping is performed by this callback. You can see it in action here opens in a new tab.

offsetBy is a function which is passed to processCharacter() module, an imported function from a file nearby, processCharacter.js opens in a new tab. Now, processCharacter() can initiate the skipping opens in a new tab of any characters taking more than single character's length, like CRLF line breaks or encoded entities.

§ Changelog

See it in the monorepo opens in a new tab, on Sourcehut.

§ Licence

MIT opens in a new tab

Copyright © 2010–2020 Roy Revelt and other contributors

Related packages:

📦 ranges-apply 4.0.2
Take an array of string index ranges, delete/replace the string according to them
📦 ranges-ent-decode 3.0.3
Recursive HTML entity decoding for Ranges workflow
📦 ranges-sort 3.14.0
Sort string index ranges
📦 ranges-iterate 1.2.2
Iterate a string and any changes within given string index ranges
📦 ranges-offset 1.0.3
Increment or decrement each index in every range
📦 ranges-crop 3.0.2
Crop array of ranges when they go beyond the reference string's length
📦 ranges-merge 6.2.0
Merge and sort string index ranges