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

prevOpen Source→string-process-comma-separatednext

string-process-comma-separated4.3.0

Extracts chunks from possibly comma or whatever-separated string

Downloads per monthChangelogMIT Licenselibera manifesto
  • the top
  • Installation
  • Quick Take
  • Examples
  • PURPOSE
  • USAGE
  • API — PROCESSCOMM…
  • API — OPTS.CB
  • API — OPTS.ERRCB
  • OPTS — INNERWHITESPA…
  • API — VERSION
  • API — TYPES
  • Changelog

Installation

Quick Take

Examples

  • Process a bounded slice and offset reported indexes
  • Gather chunks without requesting diagnostics
  • Use a custom separator
  • Allow leading and trailing whitespace
  • Configure whitespace inside a chunk
  • Allow one space after a comma

Purpose

Imagine, you need to extract and validate 50% and 50% of HTML attribute values: <FRAMESET rows="50%, 50%">.

The first algorithm idea seems simple:

str
  .split(",")
  .forEach(oneOfValues => {
    ...
  })

But in real life, the proper extraction is quite complex and you need to cover all error cases:

  • There might be surrounding whitespace <FRAMESET rows=" 50%, 50% ">
  • There might be spaces after the comma — it might be OK or not — <FRAMESET rows=" 50%, 50% ">
  • Plain errors like leading comma — <FRAMESET rows=" ,, 50%, 50% ">
  • There might be non-space characters that look like space like NBSPopens in a new tab

This program helps to extract chunks of strings from potentially comma-separated list of string (it might be a single value, without commas).

Separator is configurable via opts.separator, so it might be not comma if you wish.

Errors are pinged to a separate callback function.

Usage

Same thing like in Array.forEach, this program uses callbacks, which allows you to tailor what happens with the values that the program gives you.

Here is quite a contrived example, too crazy to be real, but it shows the capabilities of the algorithm:

Instead of expected,

<frameset rows="50%,50%"></frameset>

we have:

<frameset rows=" ,,\t50% ,    50% ,\t\t,"></frameset>

The program above extracts both values 50% (string index ranges are fed to the callback, [20, 23] and [27, 30]) and reports all rogue spaces, tabs, non-breaking space and commas.

This program saves you time from having to tackle all those possible error cases: rogue separators, consecutive separators and spaces.

API — processCommaSep()

The main function processCommaSep() is imported like this:

It’s a function which takes three input arguments:

Input argumentTypeObligatoryDescription
input
Type: String
Obligatory: yes
inputStringyesInput string
opts
Type: Plain object
Obligatory: yes
optsPlain objectyesObligatory Options Object.

The Obligatory Options Object has the following shape:

The main thing — you must pass the callbacks in the options object, cb and errCb:

KeyTypeDefaultDescription
from
Type: Integer or falsy
Default: 0
fromInteger or falsy0Where in the string does the comma-separated chunk start
to
Type: Integer or falsy
Default: str.length
toInteger or falsystr.lengthWhere in the string does the comma-separated chunk end
offset
Type: Integer or falsy
Default: 0
offsetInteger or falsy0Handy when you’ve been given cropped string and want to report real indexes. Offset adds that number to each reported index.
leadingWhitespaceOK
Type: Boolean
Default: false
leadingWhitespaceOKBooleanfalseIs whitespace at the beginning of the range OK?
trailingWhitespaceOK
Type: Boolean
Default: false
trailingWhitespaceOKBooleanfalseIs whitespace at the end of the range OK?
oneSpaceAfterCommaOK
Type: Boolean
Default: false
oneSpaceAfterCommaOKBooleanfalseCan values have space after comma?
innerWhitespaceAllowed
Type: Boolean
Default: false
innerWhitespaceAllowedBooleanfalseAfter the string is split into chunks, can those chunks have whitespace?
separator
Type: String, non-whitespace
Default: ,
separatorString, non-whitespace,What is the separator character?
cb
Type: Function
Default: null
cbFunctionnullFunction to ping the extracted value ranges to
errCb
Type: Function
Default: null
errCbFunctionnullFunction to ping the errors to

The function will return undefined because it has a callback API.

API — opts.cb

opts is a plain object. Its key’s cb value must be a function.

Like in the example above — processCommaSeparated is a function, the second argument is the options object. Below, an arrow function is set as the cb value (you could pass a “normal”, declared function as well).

const gatheredChunks = [];
...
processCommaSeparated(
  `<FRAMESET...`,
  {
    ...
    cb: (idxFrom, idxTo) => {
      gatheredChunks.push([idxFrom, idxTo]);
    },
    ...
  }
);

The program will pass two arguments to the callback function you pass:

Passed argument at positionNameTypeDescription
1
Type: Integer
1idxFromIntegerWhere does the extracted value start
2
Type: Integer
2idxToIntegerWhere does the extracted value end

For example, if you passed the whole string abc,def (assume it’s a whole HTML attribute’s value, already extracted) and didn’t give opts.from and opts.to and thus, program traversed the whole string, it would ping your callback function with two ranges: [0, 3] and [4, 7]. Full code:

import { processCommaSep } from "string-process-comma-separated";
const gatheredChunks = [];
processCommaSeparated("abc,def", {
  cb: (idxFrom, idxTo) => {
    gatheredChunks.push([idxFrom, idxTo]);
  },
});
console.log(JSON.stringify(gatheredChunks, null, 4));
// => [
//      [0, 3],
//      [4, 7]
//    ],

The error callback is omitted for brevity (opts.errCb, see its API below), here would be no errors anyway.

API — opts.errCb

Similar to opts.cb, here two arguments are passed into the callback function, only this time first one is ranges, second-one is message string.

import { processCommaSep } from "string-process-comma-separated";
const gatheredChunks = [];
const gatheredErrors = [];
processCommaSep(`<FRAMESET rows="50%, 50%">`, {
  from: 16,
  to: 24,
  cb: (idxFrom, idxTo) => {
    gatheredChunks.push([idxFrom, idxTo]);
  },
  errCb: (ranges, message) => {
    gatheredErrors.push({ ranges, message });
  },
});
console.log(JSON.stringify(gatheredChunks, null, 4));
// => [
//      [16, 19],
//      [21, 24]
//    ]
console.log(JSON.stringify(gatheredErrors, null, 4));
// => [
//      {
//        ranges: [[20, 21]],
//        message: "Remove the whitespace."
//      }
//    ]
Passed argument at positionNameTypeDescription
1
Type: Array of zero or more arrays
1rangesArray of zero or more arraysRanges which indicate the “fix” recipe.
2
Type: String
2messageStringMessage about the error.

A quick primer on ranges — each range is an array of two or three elements. First two match String.slice indexes. If an optional third is present, it means what to add instead. Two element range array — only deletion. Three element range array — replacement.

We have made more range processing libraries.

opts.innerWhitespaceAllowed

Sometimes comma-separated values are keywords — then you don’t want to allow any whitespace between characters:

<input accept=".jpg,.g if,.png">
                      ^

But sometimes it’s fine, like in media queries:

<link rel="stylesheet" media="screen and (max-width: 100px)" href="zzz.css" />
                                                    ^

Setting opts.innerWhitespaceAllowed by default doesn’t allow inner whitespace within split chunk but you can turn it off.

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 processCommaSep(), documented above.
ErrCb
Type: ErrCb
ErrCbThe signature of opts.errCb — called with the index ranges, an explanation and an isFixable flag.
Obj
Type: Obj
ObjA plain object with string keys and values of any type.
import type { ErrCb, Obj, Opts } from "string-process-comma-separated";

Changelog

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