Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@chocolatey/conjoin

chocolateboy26Artistic-2.03.0.1TypeScript support: included

A fast and flexible joiner for iterables and arrays with a tiny footprint

array, array-join, conjoin, curried, iterable, join, joiner, list, oxford-comma, sentence, separator, separators, serial-comma

readme

conjoin

Build Status NPM Version

NAME

conjoin - a fast and flexible joiner for iterables and arrays with a tiny footprint

FEATURES

  • works with ES6+ iterables, plain arrays and array-likes
  • custom default, pair, and last separators
  • currying (generate a function with baked-in options)
  • no dependencies
  • < 350 B minified + gzipped
  • fully typed (TypeScript)
  • CDN builds (UMD) - jsDelivr, unpkg

INSTALLATION

$ npm install @chocolatey/conjoin

SYNOPSIS

import { conjoin, conjoiner } from '@chocolatey/conjoin'

const array = ['foo', 'bar', 'baz', 'quux']
const iterable = new Set(array)
const single = array.slice(0, 1)
const pair = array.slice(0, 2)
const triple = array.slice(0, 3)

works with iterables, arrays, and array-likes

const arrayLike = { length: 4, ...array }

conjoin([])        // ""
conjoin(single)    // "foo"
conjoin(pair)      // "foo and bar"
conjoin(triple)    // "foo, bar and baz"
conjoin(array)     // "foo, bar, baz and quux"
conjoin(iterable)  // "foo, bar, baz and quux"
conjoin(arrayLike) // "foo, bar, baz and quux"

custom separators

conjoin(array, { with: '; ' })   // "foo; bar; baz and quux"
conjoin(array, { last: ' or ' }) // "foo, bar, baz or quux"
conjoin(pair, { pair: '/' })     // "foo/bar"

transform values

const map = (value, index) => JSON.stringify(value)
const $map = JSON.stringify

join(array, { map })  // '"foo", "bar", "baz" and "quux"'
join(array, { $map }) // '"foo", "bar", "baz" and "quux"'

currying

const map = it => it.toUpperCase()
const join = conjoiner({ map })

join(array)                    // "FOO, BAR, BAZ and QUUX"
join(array, { last: ' AND ' }) // "FOO, BAR, BAZ AND QUUX"

serial comma

const join = conjoiner({ serial: ' or ' })

join(pair)  // "foo or bar"
join(array) // "foo, bar, baz, or quux"

DESCRIPTION

This module exports a function which can be used to join array/iterable elements to form a string. The default and last separators can be customized, as well as the separator to use if there are only two elements. Options can be baked into the function by currying.

Why?

I often need to glue a list of values together with a default separator and a different separator for the last two values, e.g. for error messages:

const want = ['string', 'symbol', 'function']
const message = 'Invalid name: expected string, symbol or function'

Several libraries which support this are available on NPM, but most haven't been updated to work with iterables (they throw an error rather than converting), and many come with hardwired, immutable separators. This library aims to be at least as fast as the other implementations, and more flexible, while keeping the package size small.

TYPES

The following types are referenced in the descriptions below.

type Joinable<T> = ArrayLike<T> | Iterable<T>;

type Options<T> = {
    last?: string;
    map?: (value: T, index: number) => any;
    pair?: string;
    serial?: string | boolean;
    with?: string;
    $map?: (value: T) => any;
};

EXPORTS

conjoin

  • Type: (values: Joinable<T>, options?: Options<T>) ⇒ string
  • Alias: join
import { join } from '@chocolatey/conjoin'

join(single)                  // "foo"
join(pair)                    // "foo and bar"
join(array, { last: ' or ' }) // "foo, bar, baz or quux"

Takes an array-like or iterable and joins its values with the supplied separators.

conjoiner

  • Type:
    • <U>(options?: Options<U>) ⇒ (values: Joinable<U>) ⇒ string
    • <U>(options?: Options<U>) ⇒ <T>(values: Joinable<T>, options: Options<T>) ⇒ string
  • Alias: joiner
import { joiner } from '@chocolatey/conjoin'

const join = joiner({ last: ' or ' })

join(pair)                  // "foo or bar"
join(triple)                // "foo, bar or baz"
join(array, { with: '/' })  // "foo/bar/baz or quux"
join(array, { last: ': ' }) // "foo, bar, baz: quux"

Returns a function which takes an array/iterable and joins its values with the supplied separators. Options passed to the generated function override the options passed to the generator.

OPTIONS

The conjoin and conjoiner functions take the following options.

last

  • Type: string
  • Default: " and "
join(array)                   // "foo, bar, baz and quux"
join(array, { last: ' or ' }) // "foo, bar, baz or quux"

The separator to use between the last two values. Used if there are three or more values, or if there are two values and no pair separator is defined.

map

  • Type: (value: T, index: number) => any
  • Default: undefined
const repeat = (it, i) => String(it).repeat(i + 1)
const toInt = it => parseInt(it)

join(['a', 'b', 'c', 'd'], { map: repeat })    // "a, bb, ccc and dddd"
join(['1.', '2.', '3.', '4.'], { map: toInt }) // "1, 2, 3 and 4"

An optional function to transform each joined value. If supplied, the function is passed the value and its 0-based index within the array/iterable.

Note that functions like parseInt need to be wrapped to ensure the second argument passed to the map function (the index) isn't disallowed or misinterpreted. Rather than wrapping these functions manually, they can be wrapped automatically via the $map option.

pair

  • Type: string
  • Default: value of the last option
const join = conjoiner({ pair: ' or ', last: ', or ' })

join(single) // "foo"
join(pair)   // "foo or bar"
join(triple) // "foo, bar, or baz"
join(array)  // "foo, bar, baz, or quux"

The separator to use when there are exactly two values. If not supplied, it defaults to the value of the last option.

Can be used in conjunction with last to produce lists in the "Oxford comma" style.

serial

  • Type: string | boolean
  • Default: undefined
join(pair, { serial: ' or ' })                          // "foo or bar"
join(array, { serial: ' or ' })                         // "foo, bar, baz, or quux"
join(['eats', 'shoots', 'leaves'], { serial: ' and ' }) // "eats, shoots, and leaves"

This option provides a way to create an Oxford-comma-style list with a single option by taking advantage of the fact that the last separator in such lists is the pair separator with a comma prepended. Supplying a serial option of <string> is equivalent to providing a pair option of <string> and a last option of "," + <string>, e.g.:

before

const join = joiner({ pair: ' or ', last: ', or ' })

join(pair)  // "foo or bar"
join(array) // "foo, bar, baz, or quux"

after

const join = joiner({ serial: ' or ' })

join(pair)  // "foo or bar"
join(array) // "foo, bar, baz, or quux"

As a convenience, if the value is true, it's assigned the value of the last option, e.g.:

const array = ['eats', 'shoots', 'leaves']

conjoin(array)                   // "eats, shoots and leaves"
conjoin(array, { serial: true }) // "eats, shoots, and leaves"
const join = joiner({ last: ' or ' })

join(array)                      // "eats, shoots or leaves"
join(array, { serial: true })    // "eats, shoots, or leaves"

with

  • Type: string
  • Default: ", "
join(pair,   { with: '/' })     // "foo and bar"
join(triple, { with: '/' })     // "foo/bar and baz"
join(triple, { with: ' and ' }) // "foo and bar and baz"

The default separator, used for all but the only (pair) and last separators.

$map

  • Type: (value: T) => any
  • Default: undefined
const items = ['1.', '2)', '3:', '4/']

join(items, { $map: parseInt })       // "1, 2, 3 and 4"
join(array, { $map: JSON.stringify }) // '"foo", "bar", "baz" and "quux"'

An optional function to transform each joined value.

This is the same as the map option, but the function is automatically wrapped to ensure it's only passed a value rather than a value and its index. This is needed for functions that disallow or misinterpret additional arguments such as parseInt and JSON.stringify.

Assigning a function to $map is the same as assigning its wrapper to map, so the following are equivalent:

const map = it => JSON.stringify(it)

join(array, { map })                  // '"foo", "bar", "baz" and "quux"'
join(array, { $map: JSON.stringify }) // '"foo", "bar", "baz" and "quux"'

DEVELOPMENT

NPM Scripts

The following NPM scripts are available:

  • build - compile the library for testing and save to the target directory
  • build:release - compile the library for release and save to the target directory
  • clean - remove the target directory and its contents
  • doctoc - generate the README's TOC (table of contents)
  • rebuild - clean the target directory and recompile the library
  • test - recompile the library and run the test suite
  • test:run - run the test suite
  • typecheck - sanity check the library's type definitions

COMPATIBILITY

SEE ALSO

VERSION

3.0.1

AUTHOR

chocolateboy

COPYRIGHT AND LICENSE

Copyright © 2020 by chocolateboy.

This is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.

changelog

3.0.1 - 2020-09-10

  • documentation fix

3.0.0 - 2020-09-10

Breaking Changes

  • remove support for the { map: true } shortcut for JSON.stringify
  • reinstate collection types

Features

  • add a new $map option, an alternative to map which automatically wraps the supplied function so that it only takes a single value

Fixes

  • fix pkg.module filename: index.es.js -> index.esm.js

2.0.0 - 2020-09-04

Breaking Changes

  • last now defaults to " and " rather than the value of the default separator
  • drop the legacy-browser build

Features

  • setting map to true uses a JSON.stringify wrapper
  • setting serial to true uses the value of the last option

Changes

Types

  • remove unused type parameters: iterables, arrays and map are now untyped (e.g. Array<any>)
  • conjoin can now take any array-like, rather than just arrays and iterables

Misc

  • test and document the fact that options supplied to the curried function are merged into its default options
  • reduce the minified file size

1.0.2 - 2020-06-23

  • restore standard ESM bundle name

1.0.1 - 2020-06-21

  • restore missing ESM bundle

1.0.0 - 2020-06-20

  • add missing license

0.1.1 - 2020-06-06

  • documentation fix

0.1.0 - 2020-06-01

  • add support for a map function

0.0.1 - 2020-05-31

  • initial release