22.7.10-9.23.16 • Published 2 years ago

@jackens/jc v22.7.10-9.23.16

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

Jackens’ Collection

A collection of useful JavaScript helpers.

Demos

Usage

Installation:

npm i '@jackens/jc'

ES Modules:

import { «something» } from '@jackens/jc/esm/«file_name.js»'

CommonJS:

const { «something» } = require('@jackens/jc/cjs/«file_name.js»')

Sources

📄 File: src/deepEqual.js

Helper that verifies deeply equality of two arguments of any type.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import { deepEqual } from '../src/deepEqual.js'

test('deepEqual', () => {
  assert.deepStrictEqual(deepEqual(true, true), true)
  assert.deepStrictEqual(deepEqual(true, false), false)
  assert.deepStrictEqual(deepEqual(false, true), false)
  assert.deepStrictEqual(deepEqual(false, false), true)

  assert.deepStrictEqual(deepEqual(null, null), true)
  assert.deepStrictEqual(deepEqual(null, undefined), false)
  assert.deepStrictEqual(deepEqual(undefined, null), false)
  assert.deepStrictEqual(deepEqual(undefined, undefined), true)

  assert.deepStrictEqual(deepEqual(42, 42), true)
  assert.deepStrictEqual(deepEqual(42, '42'), false)
  assert.deepStrictEqual(deepEqual('42', 42), false)
  assert.deepStrictEqual(deepEqual('42', '42'), true)

  assert.deepStrictEqual(deepEqual([1, { a: 2, b: 3 }, 4], [1, { b: 3, a: 2 }, 4]), true)
  assert.deepStrictEqual(deepEqual([1, { a: 2, b: 3 }, 4], [1, { b: 3, a: '2' }, 4]), false)
  assert.deepStrictEqual(deepEqual([1, { a: 2, b: 3 }, 4], [1, { b: 3, a: 2 }, '4']), false)

  assert.deepStrictEqual(deepEqual(Object.create(null), {}), true)

  assert.deepStrictEqual(deepEqual(() => { }, () => { }), false)

  const keys = 'abcdefghilklmnopqrstuvwxyz0123456789_$'.split('')
  const a = [{}, {}, {}]
  const t = [a[0], a[1], a[2]]

  for (let i = 0; i < t.length; ++i) {
    for (let k = 0; k < 10000; ++k) {
      t[i] = t[i][keys[k % keys.length]] = {}
    }
    t[i].deepest = !i
    // console.log(JSON.stringify(a[i])) // Maximum call stack size exceeded
  }

  assert.deepStrictEqual(deepEqual(a[0], a[1]), false)
  assert.deepStrictEqual(deepEqual(a[0], a[2]), false)
  assert.deepStrictEqual(deepEqual(a[1], a[2]), true)
})

🟨 Function: deepEqual

function deepEqual(actual: any, expected: any): boolean;

Helper that verifies deeply equality of two arguments of any type. An iterative implementation that does not cause a stack overflow exception.

🔴 Parameter: actual

any

🔴 Parameter: expected

any

🟢 Returns

boolean

📄 File: src/download.js

Helper for handling client-side (web browser) generated downloads.

🟨 Function: download

function download(blobPart?: BlobPart[] | undefined, download?: string | undefined, type?: string | undefined): void;

Helper for handling client-side (web browser) generated downloads.

🔴 Parameter: blobPart

BlobPart[]=

🔴 Parameter: download

string=

🔴 Parameter: type

string=

📄 File: src/elvis.js

A set of helpers to deal with nested objects.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import { get, set } from '../src/elvis.js'

test('should get existing non-nested property', () => {
  const actual = { a: 42 }
  assert.deepStrictEqual(get(actual, 'a'), 42)
})

test('should get existing nested property and get undefined for non existing nested property', () => {
  const actual = {
    The: {
      answer: {
        to: {
          life: {
            the: {
              universe: {
                and: {
                  everything: 42
                }
              }
            }
          }
        }
      }
    }
  }

  assert.deepStrictEqual(get(actual, 'The', 'answer', 'to', 'life', 'the', 'universe', 'and', 'everything'), 42)
  assert.deepStrictEqual(get(actual, 'The', 'answer', 'to', 'life', 'the', 'Universe', 'and', 'everything'), undefined)
})

test('should set not existing non-nested property', () => {
  const actual = {}
  set(actual).a = 42
  assert.deepStrictEqual(actual, { a: 42 })
})

test('shoud set not existing nested property', () => {
  const actual = {}
  set(actual, 'E', 'l', 'v', 'i').s = 42
  assert.deepStrictEqual(actual, { E: { l: { v: { i: { s: 42 } } } } })
})

🟨 Function: get

function get(ref: object, ...keys: string[]): any | undefined;

Helper similar to ? operator (Elvis operator) for easy accessing nested object values.

🔴 Parameter: ref

object

🔴 Parameter: keys

string[]

🟢 Returns

any=

🟨 Function: set

function set(ref: object, ...keys: string[]): any | undefined;

Helper similar to ? operator (Elvis operator) for easy assigning values to nested objects.

🔴 Parameter: ref

object

🔴 Parameter: keys

string[]

🟢 Returns

any=

📄 File: src/fixTypography.js

Helper implementing typographic corrections appropriate for Polish typography.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import './setup.js'
import { fixTypography } from '../src/fixTypography.js'
import { j } from '../src/j.js'

test('fixTypography', () => {
  const p = j({
    t: 'p',
    k: {
      innerHTML: 'a b c d e f g h i j k l m n o p q r s t u v w x y z ' +
        'https://example.com ' +
        '<a href="https://example.com">https://example.com</a>'
    }
  }).e

  fixTypography(p)

  assert.deepStrictEqual(p.outerHTML.replace(/\u200B/g, '&#x200B;'),
    '<p>a b c d e f g h ' +
    '<span class="nbsp">i </span>j k l m n ' +
    '<span class="nbsp">o </span>p q r s t ' +
    '<span class="nbsp">u </span>v ' +
    '<span class="nbsp">w </span>x y ' +
    '<span class="nbsp">z </span>' +
    'https:/&#x200B;/&#x200B;example.&#x200B;com ' +
    '<a href="https://example.com">' +
    'https:/&#x200B;/&#x200B;example.&#x200B;com' +
    '</a></p>'
  )
})

🟨 Function: fixTypography

function fixTypography(htmlElement: HTMLElement): void;

Helper implementing typographic corrections appropriate for Polish typography. An iterative implementation that does not cause a stack overflow exception.

🔴 Parameter: htmlElement

HTMLElement

📄 File: src/fts.js

A set of helpers for Full-Text Search.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import { ftsIndex, ftsRank, levenshteinDistance, substitutionCostsDefault, substitutionCostsPL } from '../src/fts.js'

test('should work', () => {
  const countWordId = {}
  const countWord = {}
  const countId = {}
  const index = ftsIndex.bind(0, countWordId, countWord, countId)
  const rank = ftsRank.bind(0, countWordId, countWord, countId)

  index('one', 1)
  index('one', 2)
  index('two', 2)
  index('two', 3)

  assert.deepStrictEqual(rank('one'), { 1: 0.5, 2: 0.25 })
  assert.deepStrictEqual(rank('two'), { 2: 0.25, 3: 0.5 })
})

test('should correctly calculate the Levenshtein distance', () => {
  const levenshtein = levenshteinDistance.bind(null, 1, 1, substitutionCostsDefault)
  assert.deepStrictEqual(levenshtein('kot', 'kat'), 1)
  assert.deepStrictEqual(levenshtein('koty', 'kat'), 2)
  assert.deepStrictEqual(levenshtein('levenshtein', 'lewensztejn'), 3)
  assert.deepStrictEqual(levenshtein('kitten', 'sitting'), 3)
  assert.deepStrictEqual(levenshtein('kat', 'kąt'), 1)

  const levenshteinPL = levenshteinDistance.bind(null, 1, 1, substitutionCostsPL)
  assert.deepStrictEqual(levenshteinPL('kat', 'kąt'), 0.3)
})

🟩 Type: SubstitutionCost

type SubstitutionCost = (letter1: string, letter2: string) => number;

The substitution cost function used by levenshteinDistance.

🔴 Parameter: letter1

string

🔴 Parameter: letter2

string

🟢 Returns

number

🟨 Function: ftsIndex

function ftsIndex(countWordId: Record<string, Record<string, number>>, countWord: Record<string, number>, countId: Record<string, number>, word: string, id: string, rank?: number | undefined): void;

Helper that indexes the specified word within the specified id.

🔴 Parameter: countWordId

Record<string, Record<string, number>>

🔴 Parameter: countWord

Record<string, number>

🔴 Parameter: countId

Record<string, number>

🔴 Parameter: word

string

🔴 Parameter: id

string

🔴 Parameter: rank

number=

🟨 Function: ftsInitCounters

function ftsInitCounters(countWordId: Record<string, Record<string, number>>): [Record<string, number>, Record<string, number>];

Helper that creates countWord and countId maps based on the countWordId map.

🔴 Parameter: countWordId

Record<string, Record<string, number>>

🟢 Returns

[Record<string, number>, Record<string, number>]

🟨 Function: ftsRank

function ftsRank(countWordId: Record<string, Record<string, number>>, countWord: Record<string, number>, countId: Record<string, number>, word: string, result?: Record<string, number> | undefined): Record<string, number>;

Helper that searches for the given word among indexed words. Returns a map of non-zero relevance coefficients for registered identifiers.

🔴 Parameter: countWordId

Record<string, Record<string, number>>

🔴 Parameter: countWord

Record<string, number>

🔴 Parameter: countId

Record<string, number>

🔴 Parameter: word

string

🔴 Parameter: result

Record<string, number>=

🟢 Returns

Record<string, number>

🟨 Function: levenshteinDistance

function levenshteinDistance(deletionCost: number, insertionCost: number, substitutionCost: SubstitutionCost, word1: string, word2: string): number;

Helper for calculating Levenshtein distances.

🔴 Parameter: deletionCost

number

🔴 Parameter: insertionCost

number

🔴 Parameter: substitutionCost

SubstitutionCost

🔴 Parameter: word1

string

🔴 Parameter: word2

string

🟢 Returns

number

🟥 Constant: substitutionCostsDefault

const substitutionCostsDefault: SubstitutionCost;

Default substitution costs function to use with levenshteinDistance.

🟠 Type

SubstitutionCost

🟥 Constant: substitutionCostsPL

const substitutionCostsPL: SubstitutionCost;

Substitution costs function for the Polish language (to use with levenshteinDistance).

🟠 Type

SubstitutionCost

📄 File: src/hasOwnProperty.js

Replacement for the in operator (not to be confused with the for-in loop) that works properly.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import { hasOwnProperty } from '../src/hasOwnProperty.js'

test('hasOwnProperty', () => {
  const ob = { key: 'K', null: 'N' }

  assert.deepStrictEqual('key' in ob, true)
  assert.deepStrictEqual(hasOwnProperty(ob, 'key'), true)

  assert.deepStrictEqual('null' in ob, true)
  assert.deepStrictEqual(hasOwnProperty(ob, 'null'), true)

  assert.deepStrictEqual(null in ob, true)
  assert.deepStrictEqual(hasOwnProperty(ob, null), false)

  assert.deepStrictEqual('toString' in ob, true)
  assert.deepStrictEqual(hasOwnProperty(ob, 'toString'), false)

  assert.deepStrictEqual(hasOwnProperty(null, 'key'), false)
})

🟨 Function: hasOwnProperty

function hasOwnProperty(map: any, key: any): boolean;

Replacement for the in operator (not to be confused with the for-in loop) that works properly.

🔴 Parameter: map

any

🔴 Parameter: key

any

🟢 Returns

boolean

📄 File: src/j.js

Lightweight helper for creating and modifying DOM elements.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import './setup.js'
import { j, jStyle, jSvg, jSvgUse, jSymbol } from '../src/j.js'

test('j', () => {
  assert.deepStrictEqual(j({
    t: 'b',
    i: [{
      t: 'i', k: { className: 'some class', textContent: 'text' }
    }]
  }).e.outerHTML, '<b><i class="some class">text</i></b>')

  const b = j({ t: 'b' })

  assert.deepStrictEqual(b.e.outerHTML, '<b></b>')

  const i = j({
    t: 'i', i: [{ e: 'text' }], p: b.e
  })

  assert.deepStrictEqual(i.e.outerHTML, '<i>text</i>')
  assert.deepStrictEqual(b.e.outerHTML, '<b><i>text</i></b>')

  j({
    e: i.e, k: { className: 'some class' }
  })

  assert.deepStrictEqual(i.e.outerHTML, '<i class="some class">text</i>')
  assert.deepStrictEqual(b.e.outerHTML, '<b><i class="some class">text</i></b>')

  assert.deepStrictEqual(j({
    t: 'span', k: { className: 'some class' }, i: [{ e: 0 }]
  }).e.outerHTML, '<span class="some class">0</span>')

  assert.deepStrictEqual(j({
    t: 'span', k: { className: 'some class', textContent: 'one' }
  }).e.outerHTML, '<span class="some class">one</span>')

  assert.deepStrictEqual(j({
    t: 'div',
    k: {
      style: { margin: 0 }
    }
  }).e.outerHTML, '<div style="margin: 0px;"></div>')

  assert.deepStrictEqual(j({
    t: 'div',
    k: { className: 'some class' },
    i: [{
      t: 'b', i: [{ e: 'bold 1' }]
    }, {
      t: 'b', i: [{ e: 'bold 2' }]
    }, {
      t: 'i', i: [{ e: 'italic' }]
    }]
  }).e.outerHTML,
  '<div class="some class">' +
    '<b>bold 1</b><b>bold 2</b><i>italic</i>' +
    '</div>')

  const input1 = j({
    t: 'input', k: { value: 42 }
  })
  const input2 = j({
    t: 'input', a: { value: 42 }
  })

  assert.deepStrictEqual(input1.e.value, '42')
  assert.deepStrictEqual(input2.e.value, '42')

  assert.deepStrictEqual(input1.e.outerHTML, '<input>')
  assert.deepStrictEqual(input2.e.outerHTML, '<input value="42">')

  assert.deepStrictEqual(j({
    t: 'input', a: { type: 'checkbox', checked: true }
  }).e.outerHTML, '<input type="checkbox" checked="">')

  assert.deepStrictEqual(j({
    t: 'input', a: { type: 'checkbox', checked: false }
  }).e.outerHTML, '<input type="checkbox">')

  assert.deepStrictEqual(j({
    t: 'input', a: { type: 'checkbox', 'xhtml:checked': true }
  }).e.outerHTML, '<input type="checkbox" checked="">')

  assert.deepStrictEqual(j({
    t: 'input', a: { type: 'checkbox', 'xhtml:checked': false }
  }).e.outerHTML, '<input type="checkbox">')

  assert.deepStrictEqual(j({
    t: 'div', k: { key: { key_2: 42 } }
  }).e.key, { key_2: 42 })

  assert.deepStrictEqual(jSymbol({}).e.outerHTML, '<symbol></symbol>')
  assert.deepStrictEqual(jSymbol({ t: 'non-symbol' }).e.outerHTML, '<symbol></symbol>')
  assert.deepStrictEqual(jSymbol({ a: { id: 'id' } }).e.outerHTML, '<symbol id="id"></symbol>')

  assert.deepStrictEqual(jSvg([{
    a: { viewBox: '0 1 2 3', id: 'id' },
    i: [{ t: 'some-tag' }]
  }]).e.outerHTML,
  '<svg style="display: none;">' +
    '<symbol viewBox="0 1 2 3" id="id"><some-tag></some-tag></symbol>' +
    '</svg>')

  assert.deepStrictEqual(j(jSvgUse('id')).e.outerHTML.replace('xlink:', ''),
    '<svg><use href="#id"></use></svg>')

  assert.deepStrictEqual(j({
    ...jSvgUse('id'),
    a: { fill: '#000', stroke: '#000', width: 42, height: 42 }
  }).e.outerHTML.replace('xlink:', ''),
  '<svg fill="#000" stroke="#000" width="42" height="42">' +
    '<use href="#id"></use>' +
    '</svg>')
  const jsStyle = {
    a: { b$$1: 1, b$$2: 2 }
  }

  assert.deepStrictEqual(jStyle(jsStyle).e.outerHTML,
    '<style>a{b:1;b:2}</style>')
  assert.deepStrictEqual(jStyle(jsStyle, '$$$').e.outerHTML,
    '<style>a{b$$1:1;b$$2:2}</style>')
})

🟩 Type: JConfig

type JConfig = {
    a?: Record<string, any>;
    e?: Element | Text | string | number;
    i?: JConfig[];
    k?: Record<string, any>;
    n?: string;
    p?: Element;
    t?: string;
};

The j helper configuration.

  • a: attributes of the created or modified element set by setAttribute or setAttributeNS
  • e: modified element
  • i: an array of subelements (items) of the created or modified element
  • k: properties (keys) to set in the created or modified element
  • n: namespace for createElementNS, setAttributeNS and removeAttributeNS methods
  • p: reference to the parent element for the created or modified element
  • t: tag of the created element

🟥 Constant: NAMESPACE_SVG

const NAMESPACE_SVG: "http://www.w3.org/2000/svg";

🟨 Function: j

function j({ a, e, i, k, n, p, t }: JConfig): {
    e: Element | Text;
};

Lightweight helper for creating and modifying DOM elements.

🔴 Parameter: config

JConfig

🟢 Returns

{
  e: Element | Text;
}

🟨 Function: jStyle

function jStyle(jsStyle: import('./jss.js').JSS, splitter?: string | undefined): {
    e: HTMLStyleElement;
};

Helper for creating <style> elements.

🔴 Parameter: jsStyle

import('./jss.js').JSS

🔴 Parameter: splitter

string=

🟢 Returns

{
  e: HTMLStyleElement;
}

🟨 Function: jSvg

function jSvg(configs: JConfig[]): {
    e: SVGSVGElement;
};

Helper for creating <svg> container elements.

🔴 Parameter: configs

JConfig[]

🟢 Returns

{
  e: SVGSVGElement;
}

🟨 Function: jSvgUse

function jSvgUse(id: string): JConfig;

Helper for creating <svg><use> elements.

🔴 Parameter: id

string

🟢 Returns

JConfig

🟨 Function: jSymbol

function jSymbol(config: JConfig): {
    e: SVGSymbolElement;
};

Helper for creating <symbol> elements.

🔴 Parameter: config

JConfig

🟢 Returns

{
  e: SVGSymbolElement;
}

📄 File: src/jCmp.js

Jackens’ Components.

The sample file selection button component shown below

npm.io

has the following HTML representation:

<body>

<div class="jCmp" label="Label">
  <input type="file" id="jCmp1" />
  <div>
    <label for="jCmp1">Text</label>
  </div>
</div>

<script type="module">
import { j, jStyle } from '../../src/j.js'
import { jCmpJss } from '../../src/jCmp.js'

window.onload = () => j({
  e: document.body, i: [jStyle(jCmpJss())]
})
</script>

</body>

The file selection button component shown above can be generated with the following code:

<script type="module">
import { j, jStyle } from '../../src/j.js'
import { jCmp, jCmpJss } from '../../src/jCmp.js'

window.onload = () => j({
  e: document.body,
  i: [
    jStyle(jCmpJss()),
    jCmp({ type: 'file', label: 'Label', text: 'Text' })
  ]
})
</script>

Jackens’ Components layout system

Jackens’ Components layout system contains only two types of classes:

  • .w-«w»-«sw»: width of «w» slots when the screen is wide enough for «sw» slots.
  • .h-«h»-«sw»: height of «h» slots when the screen is wide enough for «sw» slots.

The minimum slot width is 200 pixels.

Example. Components defined as follows:

<script type="module">
import { j, jStyle } from '../../src/j.js'
import { jCmp, jCmpJss } from '../../src/jCmp.js'

window.onload = () => j({
  e: document.body,
  i: [
    jStyle(jCmpJss()),
    jCmp({
      label: 'Component #1',
      class: 'jCmp w-1-3 w-1-2',
      text: 'jCmp w-1-3 w-1-2'
    }), jCmp({
      label: 'Component #2',
      class: 'jCmp w-1-3 w-1-2',
      text: 'jCmp w-1-3 w-1-2'
    }), jCmp({
      label: 'Component #3',
      class: 'jCmp w-1-3',
      text: 'jCmp w-1-3'
    })
  ]
})
</script>

on a screen at least 600 pixels wide, will be arranged on a single line:

npm.io

on a screen less than 600 pixels wide, but not less than 400 pixels wide, will be arranged in two lines:

npm.io

while on a screen less than 400 pixels wide, they will be arranged in three rows:

npm.io

🟩 Type: JCmpConfig

type JCmpConfig = ({
    w?: import('./j.js').JConfig;
    c?: import('./j.js').JConfig;
    l?: import('./j.js').JConfig;
    class?: string;
    icon?: string;
    label?: string;
    p?: HTMLElement;
    style?: Record<string, any>;
    t?: keyof HTMLElementTagNameMap | keyof SVGElementTagNameMap;
    text?: string;
} & Partial<{
    onabort: (e: UIEvent) => any;
    onanimationcancel: (e: AnimationEvent) => any;
    onanimationend: (e: AnimationEvent) => any;
    onanimationiteration: (e: AnimationEvent) => any;
    onanimationstart: (e: AnimationEvent) => any;
    onauxclick: (e: MouseEvent) => any;
    onbeforeinput: (e: InputEvent) => any;
    onblur: (e: FocusEvent) => any;
    oncanplay: (e: Event) => any;
    oncanplaythrough: (e: Event) => any;
    onchange: (e: Event) => any;
    onclick: (e: MouseEvent) => any;
    onclose: (e: Event) => any;
    oncompositionend: (e: CompositionEvent) => any;
    oncompositionstart: (e: CompositionEvent) => any;
    oncompositionupdate: (e: CompositionEvent) => any;
    oncontextmenu: (e: MouseEvent) => any;
    oncuechange: (e: Event) => any;
    ondblclick: (e: MouseEvent) => any;
    ondrag: (e: DragEvent) => any;
    ondragend: (e: DragEvent) => any;
    ondragenter: (e: DragEvent) => any;
    ondragleave: (e: DragEvent) => any;
    ondragover: (e: DragEvent) => any;
    ondragstart: (e: DragEvent) => any;
    ondrop: (e: DragEvent) => any;
    ondurationchange: (e: Event) => any;
    onemptied: (e: Event) => any;
    onended: (e: Event) => any;
    onerror: (e: ErrorEvent) => any;
    onfocus: (e: FocusEvent) => any;
    onfocusin: (e: FocusEvent) => any;
    onfocusout: (e: FocusEvent) => any;
    onformdata: (e: FormDataEvent) => any;
    ongotpointercapture: (e: PointerEvent) => any;
    oninput: (e: Event) => any;
    oninvalid: (e: Event) => any;
    onkeydown: (e: KeyboardEvent) => any;
    onkeypress: (e: KeyboardEvent) => any;
    onkeyup: (e: KeyboardEvent) => any;
    onload: (e: Event) => any;
    onloadeddata: (e: Event) => any;
    onloadedmetadata: (e: Event) => any;
    onloadstart: (e: Event) => any;
    onlostpointercapture: (e: PointerEvent) => any;
    onmousedown: (e: MouseEvent) => any;
    onmouseenter: (e: MouseEvent) => any;
    onmouseleave: (e: MouseEvent) => any;
    onmousemove: (e: MouseEvent) => any;
    onmouseout: (e: MouseEvent) => any;
    onmouseover: (e: MouseEvent) => any;
    onmouseup: (e: MouseEvent) => any;
    onpause: (e: Event) => any;
    onplay: (e: Event) => any;
    onplaying: (e: Event) => any;
    onpointercancel: (e: PointerEvent) => any;
    onpointerdown: (e: PointerEvent) => any;
    onpointerenter: (e: PointerEvent) => any;
    onpointerleave: (e: PointerEvent) => any;
    onpointermove: (e: PointerEvent) => any;
    onpointerout: (e: PointerEvent) => any;
    onpointerover: (e: PointerEvent) => any;
    onpointerup: (e: PointerEvent) => any;
    onprogress: (e: ProgressEvent<EventTarget>) => any;
    onratechange: (e: Event) => any;
    onreset: (e: Event) => any;
    onresize: (e: UIEvent) => any;
    onscroll: (e: Event) => any;
    onsecuritypolicyviolation: (e: SecurityPolicyViolationEvent) => any;
    onseeked: (e: Event) => any;
    onseeking: (e: Event) => any;
    onselect: (e: Event) => any;
    onselectionchange: (e: Event) => any;
    onselectstart: (e: Event) => any;
    onslotchange: (e: Event) => any;
    onstalled: (e: Event) => any;
    onsubmit: (e: SubmitEvent) => any;
    onsuspend: (e: Event) => any;
    ontimeupdate: (e: Event) => any;
    ontoggle: (e: Event) => any;
    ontouchcancel: (e: TouchEvent) => any;
    ontouchend: (e: TouchEvent) => any;
    ontouchmove: (e: TouchEvent) => any;
    ontouchstart: (e: TouchEvent) => any;
    ontransitioncancel: (e: TransitionEvent) => any;
    ontransitionend: (e: TransitionEvent) => any;
    ontransitionrun: (e: TransitionEvent) => any;
    ontransitionstart: (e: TransitionEvent) => any;
    onvolumechange: (e: Event) => any;
    onwaiting: (e: Event) => any;
    onwebkitanimationend: (e: Event) => any;
    onwebkitanimationiteration: (e: Event) => any;
    onwebkitanimationstart: (e: Event) => any;
    onwebkittransitionend: (e: Event) => any;
    onwheel: (e: WheelEvent) => any;
}>) | Record<string, string | number | boolean>;

Jackens’ Components configuration.

Jackens’ Components configuration format (JCmpConfig) is based on three main keys:

  • w (wrapper): JConfig format configuration of the component wrapper (HTMLDivElement element)
  • c (control): JConfig format configuration of the component control
  • l (label): JConfig format configuration of the component label (HTMLLabelElement element; applies to input controls of type checkbox, radio and file)

All other keys are just an alternative, more convenient form for configuration using the main keys:

  • class: w.a.class configuration
  • icon: icon configuration
  • label: w.a.label configuration
  • p: w.p configuration
  • style: c.k.style configuration
  • t: c.t configuration
  • test: text configuration
  • other: c.a configuration (string, number or boolean) or c.k configuration (function)

The icon and text keys are handled in a special way: they allow you to conveniently specify the icon and text of the component you are defining.

The JCmpConfig format has the following default values:

{ […], t: 'input', class: 'jCmp', […] }

🟨 Function: jCmp

function jCmp(config: JCmpConfig): import('./j.js').JConfig;

Convenient converter from JCmpConfig format to JConfig format.

import assert from 'node:assert/strict'
import { test } from 'node:test'
import './setup.js'
import { jSvgUse } from '../src/j.js'
import { jCmp, jCmpJss } from '../src/jCmp.js'
import { isObject } from '../src/typeOf.js'

test('jCmp', () => {
  const svgUseConfig = {
    a: { fill: '#fff', stroke: '#fff', width: 17, height: 17 }
  }

  const button1 = jCmp({
    t: 'button',
    w: {
      a: { class: 'jCmp' }
    },
    c: {
      a: { 'aria-label': 'button' },
      i: [{
        ...jSvgUse('icon-id'), ...svgUseConfig
      }, {
        t: 'div'
      }, {
        e: 'Button'
      }],
      k: {
        style: { marginLeft: 42, marginRight: 17 },
        onclick: console.log // eslint-disable-line no-console
      }
    }
  })

  const button2 = jCmp({
    t: 'button',
    style: { marginLeft: 42, marginRight: 17 },
    onclick: console.log, // eslint-disable-line no-console
    text: 'Button',
    icon: 'icon-id',
    'aria-label': 'button'
  })

  assert.deepStrictEqual(button2, button1)

  const file1 = jCmp({
    t: 'input',
    type: 'file',
    w: {
      a: { class: 'jCmp' }
    },
    l: {
      i: [{ e: 'Choose file…' }]
    }
  })

  const file2 = jCmp({
    t: 'input', type: 'file', text: 'Choose file…'
  })

  file2.i[0].a.id = file2.i[1].i[0].a.for = 'jCmp1'

  assert.deepStrictEqual(file2, file1)

  const css = jCmpJss()

  assert.deepStrictEqual(isObject(css), true)
})

🔴 Parameter: config

JCmpConfig

🟢 Returns

import('./j.js').JConfig

🟨 Function: jCmpJss

function jCmpJss({ fontFamily, focusColor, mainColor }?: {
    fontFamily?: string;
    focusColor?: string;
    mainColor?: string;
}): import('./jss.js').JSS;

Jackens’ Components CSS rules in JSS format.

🔴 Parameter: config

{
  fontFamily?: string;
  focusColor?: string;
  mainColor?:  string;
}

🟢 Returns

import('./jss.js').JSS

📄 File: src/jsOnParse.js

JSON.parse with “JavaScript turned on”.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import { jsOnParse } from '../src/jsOnParse.js'

const handlers = {
  join: (...params) => params.join(' '),
  outer: text => `Hello ${text}!`,
  inner: text => text.charAt(0).toUpperCase() + text.slice(1).toLowerCase(),
  question: text => ({ d: 'Yes!', t: 42 }[text[0]])
}

test('should use ‘join’ handler', () => {
  assert.deepStrictEqual(jsOnParse(`{
    "join": ["Hello", "World!"]
  }`, handlers), 'Hello World!')
})

test('should ‘join’ and ‘to_much’ handlers', () => {
  assert.deepStrictEqual(jsOnParse(`{
    "join": ["Hello", "World!"], "to_much": "whatever"
  }`, handlers), {
    join: ['Hello', 'World!'], to_much: 'whatever'
  })
})

test('should use ‘inner’ and ‘outer’ handlers', () => {
  assert.deepStrictEqual(jsOnParse(`{
    "outer":{ "inner": "wORld" }
  }`, handlers), 'Hello World!')
})

test('should use ‘question’ handler', () => {
  assert.deepStrictEqual(jsOnParse(`[{
    "question": "does it really works?!?"
  }, {
    "question": "the answer to life the universe and everything"
  }, {
    "Question": null
  }]`, handlers), ['Yes!', 42, { Question: null }])
})

test('should process nested objects', () => {
  assert.deepStrictEqual(jsOnParse('{"H":{"e":{"l":{"l":{"o":["World!"]}}}}}', handlers)
    , { H: { e: { l: { l: { o: ['World!'] } } } } })
})

Objects having exactly one «handlerName» property present in the handlers map, i.e. objects of form:

{ "«handlerName»": «param» }

and

{ "«handlerName»": [«params»] }

are replaced by the result of call

handlers['«handlerName»'](«param»)

and

handlers['«handlerName»'](...«params»)

Remark

To pass to handlers['«handlerName»'] a single argument that is an array, use the following form:

{ "«handlerName»": [[«elements»]] }

which will force a call

handlers['«handlerName»']([«elements»])

🟨 Function: jsOnParse

function jsOnParse(text: string, handlers: Record<string, Function>): any;

JSON.parse with “JavaScript turned on”.

🔴 Parameter: text

string

🔴 Parameter: handlers

Record<string, Function>

🟢 Returns

any

📄 File: src/jss.js

CSS-in-JS helper based on the JSS format.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import { jss } from '../src/jss.js'

test('should handle nested definitions (level 1)', () => {
  const actual = {
    a: {
      color: 'red',
      margin: 1,
      '.c': {
        margin: 2,
        padding: 2
      },
      padding: 1
    }
  }
  const expected =
    'a{color:red;margin:1}' +
    'a.c{margin:2;padding:2}' +
    'a{padding:1}'

  assert.deepStrictEqual(jss(actual), expected)
})

test('should handle nested definitions (level 2)', () => {
  const actual = {
    a: {
      '.b': {
        color: 'red',
        margin: 1,
        '.c': {
          margin: 2,
          padding: 2
        },
        padding: 1
      }
    }
  }
  const expected =
    'a.b{color:red;margin:1}' +
    'a.b.c{margin:2;padding:2}' +
    'a.b{padding:1}'

  assert.deepStrictEqual(jss(actual), expected)
})

test('should handle ‘@’ prefixes and ‘$$suffix’ suffixes', () => {
  const actual = {
    '@font-face$$1': {
      fontFamily: 'Jackens',
      src$$1: 'url(fonts/jackens.otf)',
      src$$2: "url(fonts/jackens.otf) format('opentype')," +
        "url(fonts/jackens.svg) format('svg')",
      fontWeight: 'normal',
      fontStyle: 'normal'
    },
    '@font-face$$2': {
      fontFamily: 'C64',
      src: 'url(fonts/C64_Pro_Mono-STYLE.woff)'
    },
    '@keyframes spin': {
      '0%': { transform: 'rotate(0deg)' },
      '100%': { transform: 'rotate(360deg)' }
    },
    div: {
      border: 'solid red 1px',
      '.c1': { 'background-color': '#000' },
      ' .c1': { backgroundColor: 'black' },
      '.c2': { backgroundColor: 'rgb(0,0,0)' }
    },
    '@media(min-width:200px)': {
      div: { margin: 0, padding: 0 },
      span: { color: '#000' }
    }
  }
  const expected = '@font-face{font-family:Jackens;src:url(fonts/jackens.otf);' +
    "src:url(fonts/jackens.otf) format('opentype')," +
    "url(fonts/jackens.svg) format('svg');" +
    'font-weight:normal;font-style:normal}' +
    '@font-face{font-family:C64;src:url(fonts/C64_Pro_Mono-STYLE.woff)}' +
    '@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}' +
    'div{border:solid red 1px}' +
    'div.c1{background-color:#000}' +
    'div .c1{background-color:black}' +
    'div.c2{background-color:rgb(0,0,0)}' +
    '@media(min-width:200px){div{margin:0;padding:0}span{color:#000}}'

  assert.deepStrictEqual(jss(actual), expected)
})

test('should handle comma separation (level 2)', () => {
  const actual = {
    a: {
      '.b,.c': {
        margin: 1,
        '.d': {
          margin: 2
        }
      }
    }
  }
  const expected = 'a.b,a.c{margin:1}a.b.d,a.c.d{margin:2}'

  assert.deepStrictEqual(jss(actual), expected)
})

test('should handle comma separation (level 1)', () => {
  const actual = {
    '.b,.c': {
      margin: 1,
      '.d': {
        margin: 2
      }
    }
  }
  const expected = '.b,.c{margin:1}.b.d,.c.d{margin:2}'

  assert.deepStrictEqual(jss(actual), expected)
})

test('should handle multiple comma separations', () => {
  const actual = {
    '.a,.b': {
      margin: 1,
      '.c,.d': {
        margin: 2
      }
    }
  }
  const expected = '.a,.b{margin:1}' +
    '.a.c,.a.d,.b.c,.b.d{margin:2}'

  assert.deepStrictEqual(jss(actual), expected)
})

🟩 Type: JSS

type JSS = {
    [ruleOrAttribute: string]: string | number | JSS;
};

The JSS format provides a hierarchical description of CSS rules.

  • Keys of sub-objects whose values are NOT objects are treated as CSS attribute, and values are treated as values of those CSS attributes; the concatenation of keys of all parent objects is a CSS rule.
  • All keys ignore the part starting with a splitter (default: '$$') sign until the end of the key (e.g. src$$1src, @font-face$$1@font-face).
  • In keys specifying CSS attribute, all uppercase letters are replaced by lowercase letters with an additional - character preceding them (e.g. fontFamilyfont-family).
  • Commas in keys that makes a CSS rule cause it to “split” and create separate rules for each part (e.g. {div:{margin:1,'.a,.b,.c':{margin:2}}}div{margin:1}div.a,div.b,div.c{margin:2}).
  • Top-level keys that begin with @ are not concatenated with sub-object keys.

🟨 Function: jss

function jss(style: JSS, splitter?: string | undefined): string;

CSS-in-JS helper based on the JSS format. An iterative implementation that does not cause a stack overflow exception.

🔴 Parameter: style

JSS

🔴 Parameter: splitter

string=

🟢 Returns

string

📄 File: src/mdoc.js

MDoc

MDoc is a converter from JSDoc to Markdown. It is exposed as “binary”:

#!/usr/bin/env node

import { jsOnParse } from '../src/jsOnParse.js'
import { mdoc, readFile, writeFile } from '../src/mdoc.js'

jsOnParse(readFile({ path: process.argv[2] ?? '.mdoc.json' }), { mdoc, readFile, writeFile })

As you can see it reads the configuration from the specified file or from the .mdoc.json file. Also, it uses the jsOnParse helper, so the configuration can be placed anywhere in the parsed file! For example, you can use the configuration from the mdoc key in the package.json file.

MDoc configuration file used to generate this documentation:

{
  "writeFile": {
    "lines": [
      {
        "readFile": {
          "path": "readme.md",
          "toMarker": "\n# Sources\n"
        }
      },
      {
        "mdoc": {}
      },
      {
        "readFile": {
          "fromMarker": "\n# License\n",
          "path": "readme.md"
        }
      }
    ],
    "path": "readme.md"
  }
}

The readFile, writeFile and mdoc keys/methods in the MDoc configuration are responsible for building Your documentation.

The readFile and writeFile methods are fairly self-explanatory, while the mdoc method supports the following parameters:

  • debugJson: optional path to save the debug JSON file
  • insertExtraIds: optional flag to insert extra ids (<a id="…" name="…"></a>) — useful in case of some Markdown renderers (i.e. BitBucket)
  • src: array of directories with the JavaScript sources to scan
  • tocMaxDepth: optional TOC max depth, can be one of 0 1 or 2 (2 is the default; 0 means no TOC)
  • topLevelHeader: optional top-level HTML header level, can be one of 1, 2, 3 or 4 (1 is the default)

Remark

MDoc parses the .d.ts files generated by the TypeScript compiler. Your documentation may be even better if you call tsc before calling mdoc!

The tsconfig.json file used in this repo:

{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true,
    "declaration": true,
    "emitDeclarationOnly": true,
    "module": "esnext",
    "moduleResolution": "node",
    "removeComments": true,
    "skipLibCheck": true,
    "target": "esnext"
  },
  "include": [
    "app/**/*.js",
    "src/**/*.js"
  ],
  "exclude": [
    "app/bookmarks/countWordId.js"
  ]
}

Remark

MDoc supports an extra non-standard JSDoc tag @include that allows You to include files as Markdown code blocks into Your documentation.

Remark

For JavaScript source files in CommonJS format, MDoc needs @name tags in the document blocks.

🟨 Function: mdoc

function mdoc({ debugJson, insertExtraIds, src, tocMaxDepth, topLevelHeader }?: {
    debugJson?: string;
    insertExtraIds?: boolean;
    src?: string[];
    tocMaxDepth?: 0 | 1 | 2;
    topLevelHeader?: 1 | 2 | 3 | 4;
}): string;

Converter from JSDoc to Markdown.

🔴 Parameter: config

{
  debugJson?: string;
  insertExtraIds?: boolean;
  src?: string[];
  tocMaxDepth?: 0 | 1 | 2;
  topLevelHeader?:  1 | 2 | 3 | 4;
}

🟢 Returns

string

🟨 Function: readFile

function readFile({ path, fromMarker, toMarker }: {
    path: string;
    fromMarker?: string;
    toMarker?: string;
}): string;

Handler that reads the contents of the specified file.

🔴 Parameter: config

{
  path:        string;
  fromMarker?: string;
  toMarker?:   string;
}

🟢 Returns

string

🟨 Function: writeFile

function writeFile({ lines, path }: {
    lines: string[];
    path: string;
}): string;

Helper that writes an array of lines to the specified file.

🔴 Parameter: config

{
  lines: string[];
  path:  string;
}

🟢 Returns

string

📄 File: src/minifly.js

Helper that converts multiple occurrences of literals into constants in JavaScript code.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import { minifly } from '../src/minifly.js'

test('minifly', () => {
  const code = "'42' ? '42' : { '42' : /42/ }; 42 ? 42 : { 42 : /42/ }"
  const expected = "const __minifly__1 = 42,__minifly__2 = '42',__minifly__3 = /42/;" +
    "__minifly__2 ? __minifly__2 : { '42' : __minifly__3 }; __minifly__1 ? __minifly__1 : { 42 : __minifly__3 }"

  assert.deepStrictEqual(minifly(code), expected)
})

🟨 Function: minifly

function minifly(code: string, acornOptions?: import('acorn').Options | null): string;

Helper that converts multiple occurrences of literals into constants in JavaScript code.

🔴 Parameter: code

string

🔴 Parameter: acornOptions

import('acorn').Options?

🟢 Returns

string

📄 File: src/numToKey.js

Helper for converting integers to map-friendly string identifiers.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import { numToKey } from '../src/numToKey.js'

const ALPHA = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$'
const _1_TO_9 = '123456789'
const _0_TO_9 = `0${_1_TO_9}`
const ALPHA_NUM = `${_0_TO_9}${ALPHA}`
const KEYS = []

for (let a = 0; a < ALPHA_NUM.length; ++a) {
  KEYS.push(ALPHA_NUM[a])
}

for (let a = 0; a < _1_TO_9.length; ++a) {
  for (let b = 0; b < _0_TO_9.length; ++b) {
    KEYS.push(`${_1_TO_9[a]}${_0_TO_9[b]}`)
  }
}
for (let a = 0; a < ALPHA.length; ++a) {
  for (let b = 0; b < ALPHA_NUM.length; ++b) {
    KEYS.push(`${ALPHA[a]}${ALPHA_NUM[b]}`)
  }
}

for (let a = 0; a < _1_TO_9.length; ++a) {
  for (let b = 0; b < _0_TO_9.length; ++b) {
    for (let c = 0; c < _0_TO_9.length; ++c) {
      KEYS.push(`${_1_TO_9[a]}${_0_TO_9[b]}${_0_TO_9[c]}`)
    }
  }
}
for (let a = 0; a < ALPHA.length; ++a) {
  for (let b = 0; b < ALPHA_NUM.length; ++b) {
    for (let c = 0; c < ALPHA_NUM.length; ++c) {
      KEYS.push(`${ALPHA[a]}${ALPHA_NUM[b]}${ALPHA_NUM[c]}`)
    }
  }
}

test('numToKey', () => {
  for (let num = 0; num < KEYS.length; ++num) {
    assert.deepStrictEqual(numToKey(num), KEYS[num])
  }
})

🟨 Function: numToKey

function numToKey(num: number): string;

Helper for converting integers to map-friendly string identifiers.

🔴 Parameter: num

number

🟢 Returns

string

📄 File: src/plUral.js

Helper for choosing the correct singular and plural.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import { plUral } from '../src/plUral.js'

test('should handle 0', () => {
  assert.deepStrictEqual(plUral(0, 'car', 'cars', 'cars'), '0 cars')
  assert.deepStrictEqual(plUral(0, 'auto', 'auta', 'aut'), '0 aut')
})

test('should handle 1', () => {
  assert.deepStrictEqual(plUral(1, 'car', 'cars', 'cars'), '1 car')
  assert.deepStrictEqual(plUral(1, 'auto', 'auta', 'aut'), '1 auto')
})

test('should handle 5', () => {
  assert.deepStrictEqual(plUral(5, 'car', 'cars', 'cars'), '5 cars')
  assert.deepStrictEqual(plUral(5, 'auto', 'auta', 'aut'), '5 aut')
})

test('should handle 2', () => {
  assert.deepStrictEqual(plUral(42, 'car', 'cars', 'cars'), '42 cars')
  assert.deepStrictEqual(plUral(42, 'auto', 'auta', 'aut'), '42 auta')
})

🟨 Function: plUral

function plUral(value: number, singular: string, plural2: string, plural5: string, noValue1?: string | undefined, noValue?: string | undefined): string;

Helper for choosing the correct singular and plural.

🔴 Parameter: value

number

🔴 Parameter: singular

string

🔴 Parameter: plural2

string

🔴 Parameter: plural5

string

🔴 Parameter: noValue1

string=

🔴 Parameter: noValue

string=

🟢 Returns

string

📄 File: src/preloader.js

Animated gear preloader.

🟥 Constant: preloader

const preloader: {
    e: SVGSVGElement;
};

Animated gear preloader.

🟠 Type

{
  e: SVGSVGElement;
}

🟥 Constant: preloaderJss

const preloaderJss: import('./jss.js').JSS;

Animated gear preloader CSS rules in JSS format.

🟠 Type

import('./jss.js').JSS

📄 File: src/priorityQueue.js

🟩 Type: PriorityQueue

type PriorityQueue<T> = {
    isEmpty: () => boolean;
    push: (item: T, priority: string | number) => void;
    shift: () => {
        item: T;
        priority: string | number;
    };
};

🔵 Template parameter: T

🟨 Function: priorityQueue

function priorityQueue<T>(comparePriorities?: (priority_1: string | number, priority_2: string | number) => number): PriorityQueue<T>;

A simple implementation of a priority queue.

🔵 Template parameter: T

🔴 Parameter: comparePriorities

(priority_1: string | number, priority_2: string | number) => number=

Optional priorities comparison function.

🟢 Returns

PriorityQueue<T>

📄 File: src/scanDirs.js

Helper to scan files in the specified directories.

Unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import { scanDirs } from '../src/scanDirs.js'

test('scanDirs', async () => {
  const dirSrc = scanDirs('src')
  const dirTest = scanDirs('test')
  const dirsSrcAndTest = scanDirs('src', 'test')

  assert.ok(dirSrc.length > 20)
  assert.ok(dirTest.length > 20)
  assert.deepStrictEqual(dirsSrcAndTest.length, dirSrc.length + dirTest.length)
})

🟨 Function: scanDirs

function scanDirs(...dirs: string[]): string[];

Helper to scan files in the specified directories.

🔴 Parameter: dirs

...string

🟢 Returns

string[]

📄 File: src/sql.js

A set of helpers for creating safe SQL queries.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import { escapeMySQL, escapeSQL, sql } from '../src/sql.js'

test('sql', () => {
  const actual = sql`
  SELECT *
  FROM ${escapeMySQL('table`name')}
  WHERE
    ${escapeSQL('column"name')} = ${42} OR
    column_name = ${true} OR
    column_name = ${false} OR
    column_name = ${new Date('1980-03-31T04:30:00.000Z')} OR
    column_name IN (${[42, "'", true, false, new Date('1980-03-31T04:30:00.000Z')]})`
  const expected = `
  SELECT *
  FROM \`table\`\`name\`
  WHERE
    "column""name" = 42 OR
    column_name = b'1' OR
    column_name = b'0' OR
    column_name = '1980-03-31 04:30:00' OR
    column_name IN (42,'''',b'1',b'0','1980-03-31 04:30:00')`

  assert.deepStrictEqual(actual, expected)
})

🟩 Type: EscapeSQL

type EscapeSQL = {
    [Symbol.toStringTag]: "EscapeSQL";
    toString: () => string;
};

A special type for functions escaping SQL column, table and schema names.

🟨 Function: escapeMySQL

function escapeMySQL(name: string): EscapeSQL;

Helper for escaping MySQL/MariaDB column, table and schema names.

🔴 Parameter: name

string

🟢 Returns

EscapeSQL

🟨 Function: escapeSQL

function escapeSQL(name: string): EscapeSQL;

Helper for escaping SQL column, table and schema names.

🔴 Parameter: name

string

🟢 Returns

EscapeSQL

🟨 Function: sql

function sql(template: TemplateStringsArray, ...substitutions: any[]): string;

Tagged Template Literal helper for creating secure SQL queries.

🔴 Parameter: template

TemplateStringsArray

🔴 Parameter: substitutions

any[]

🟢 Returns

string

🟥 Constant: sqlEscapeType

const sqlEscapeType: Record<string, (value: any) => string>;

Methods that implement value escape for particular types.

🟠 Type

Record<string, (value: any) => string>

📄 File: src/streamToBuffer.js

Helper for converting streams to buffers.

Usage example from unit tests:

import { createReadStream } from 'fs'
import assert from 'node:assert/strict'
import { test } from 'node:test'
import { streamToBuffer } from '../src/streamToBuffer.js'

test('streamToBuffer', async () => {
  const stream = createReadStream('src/streamToBuffer.js')
  const buffer = await streamToBuffer(stream)

  assert.ok(buffer.toString('utf8').includes('export const streamToBuffer ='))
})

🟨 Function: streamToBuffer

function streamToBuffer(stream: import('stream').Stream): Promise<Buffer>;

Helper for converting streams to buffers.

🔴 Parameter: stream

import('stream').Stream

🟢 Returns

Promise<Buffer>

📄 File: src/translate.js

Language translations helper.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import { translate } from '../src/translate.js'

const locales = {
  pl: {
    Password: 'Hasło',
    button: { Login: 'Zaloguj' }
  }
}
const _ = translate.bind(0, locales, 'pl')

test('should handle defined texts', () => {
  assert.deepStrictEqual(_('Login'), 'Login')
  assert.deepStrictEqual(_('Password'), 'Hasło')
})

test('should handle undefined text', () => {
  assert.deepStrictEqual(_('Undefined text'), 'Undefined text')
})

test('should handle defined version', () => {
  assert.deepStrictEqual(_('Login', 'button'), 'Zaloguj')
})

test('should handle undefined version', () => {
  assert.deepStrictEqual(_('Password', 'undefined_version'), 'Hasło')
  assert.deepStrictEqual(_('Undefined text', 'undefined_version'), 'Undefined text')
})

test('should have empty prototype', () => {
  assert.deepStrictEqual(_('toString'), 'toString')
  assert.deepStrictEqual(_('toString', 'undefined_version'), 'toString')
})

🟨 Function: getNavigatorLanguage

function getNavigatorLanguage(locales: Record<string, Record<string, string | Record<string, string>>>, defaultLanguage: string): string;

🔴 Parameter: locales

Record<string, Record<string, string | Record<string, string>>>

🔴 Parameter: defaultLanguage

string

🟨 Function: translate

function translate(locales: Record<string, Record<string, string | Record<string, string>>>, language: string, text: string, version?: string | undefined): string;

Language translations helper.

🔴 Parameter: locales

Record<string, Record<string, string | Record<string, string>>>

🔴 Parameter: language

string

🔴 Parameter: text

string

🔴 Parameter: version

string=

🟢 Returns

string

📄 File: src/typeOf.js

A collection of type testing helpers.

Usage example from unit tests:

import assert from 'node:assert/strict'
import { test } from 'node:test'
import './setup.js'
import {
  isArray,
  isAsyncFunction,
  isBoolean,
  isDate,
  isElement,
  isFunction,
  isGeneratorFunction,
  isHTMLButtonElement,
  isHTMLInputElement,
  isHTMLTextAreaElement,
  isNumber,
  isObject,
  isPromise,
  isRegExp,
  isString,
  isText,
  typeOf
} from '../src/typeOf.js'

test('typeOf', () => {
  assert.deepStrictEqual(typeof [], 'object')
  assert.deepStrictEqual(typeOf([]), 'Array')
  assert.deepStrictEqual(isArray([]), true)

  assert.deepStrictEqual(typeof (async () => { }), 'function')
  assert.deepStrictEqual(typeOf(async () => { }), 'AsyncFunction')
  assert.deepStrictEqual(isAsyncFunction(async () => { }), true)

  assert.deepStrictEqual(typeof true, 'boolean')
  assert.deepStrictEqual(typeOf(true), 'Boolean')
  assert.deepStrictEqual(isBoolean(true), true)

  assert.deepStrictEqual(typeof new Date(), 'object')
  assert.deepStrictEqual(typeOf(new Date()), 'Date')
  assert.deepStrictEqual(isDate(new Date()), true)

  assert.deepStrictEqual(typeof document.createElement('DIV'), 'object')
  assert.deepStrictEqual(typeOf(document.createElement('DIV')), 'HTMLDivElement')
  assert.deepStrictEqual(isElement(document.createElement('DIV')), true)

  assert.deepStrictEqual(typeof function * () {}, 'function')
  assert.deepStrictEqual(typeOf(function * () {}), 'GeneratorFunction')
  assert.deepStrictEqual(isGeneratorFunction(function * () {}), true)

  assert.deepStrictEqual(typeof typeOf, 'function')
  assert.deepStrictEqual(typeOf(typeOf), 'Function')
  assert.deepStrictEqual(isFunction(typeOf), true)

  assert.deepStrictEqual(isHTMLButtonElement(document.createElement('BUTTON')), true)

  assert.deepStrictEqual(isHTMLInputElement(document.createElement('INPUT')), true)

  assert.deepStrictEqual(isHTMLTextAreaElement(document.createElement('TEXTAREA')), true)

  assert.deepStrictEqual(typeof 42, 'number')
  assert.deepStrictEqual(typeOf(42), 'Number')
  assert.deepStrictEqual(isNumber(42), true)

  assert.deepStrictEqual(typeof NaN, 'number')
  assert.deepStrictEqual(typeOf(NaN), 'Number')
  assert.deepStrictEqual(isNumber(NaN), true)

  assert.deepStrictEqual(typeof Infinity, 'number')
  assert.deepStrictEqual(typeOf(Infinity), 'Number')
  assert.deepStrictEqual(isNumber(Infinity), true)

  assert.deepStrictEqual(typeof {}, 'object')
  assert.deepStrictEqual(typeOf({}), 'Object')
  assert.deepStrictEqual(isObject({}), true)

  assert.deepStrictEqual(typeof Promise.resolve(), 'object')
  assert.deepStrictEqual(typeOf(Promise.resolve()), 'Promise')
  assert.deepStrictEqual(isPromise(Promise.resolve()), true)

  assert.deepStrictEqual(typeof /^(Reg)(Exp)$/, 'object')
  assert.deepStrictEqual(typeOf(/^(Reg)(Exp)$/), 'RegExp')
  assert.deepStrictEqual(isRegExp(/^(Reg)(Exp)$/), true)

  assert.deepStrictEqual(typeof 'Jackens', 'string')
  assert.deepStrictEqual(typeOf('Jackens'), 'String')
  assert.deepStrictEqual(isString('Jackens'), true)

  assert.deepStrictEqual(typeof String('Jackens'), 'string')
  assert.deepStrictEqual(typeOf(String('Jackens')), 'String')
  assert.deepStrictEqual(isString(String('Jackens')), true)

  assert.deepStrictEqual(typeof new String('Jackens'), 'object') // eslint-disable-line no-new-wrappers
  assert.deepStrictEqual(typeOf(new String('Jackens')), 'String') // eslint-disable-line no-new-wrappers
  assert.deepStrictEqual(isString(new String('Jackens')), true) // eslint-disable-line no-new-wrappers

  assert.deepStrictEqual(isText(document.createTextNode('')), true)
})

🟩 Type: AsyncFunction

type AsyncFunction = (...args: any[]) => Promise<any>;

🟨 Function: isArray

function isArray(arg: any): arg is any[];

Helper that checks if the arg is of type Array.

🔴 Parameter: arg

any

🟢 Returns

arg is Array

🟨 Function: isAsyncFunction

function isAsyncFunction(arg: any): arg is AsyncFunction;

Helper that checks if the arg is of type AsyncFunction.

🔴 Parameter: arg

any

🟢 Returns

arg is AsyncFunction

🟨 Function: isBoolean

function isBoolean(arg: any): arg is boolean;

Helper that checks if the arg is of type Boolean.

🔴 Parameter: arg

any

🟢 Returns

arg is Boolean

🟨 Function: isDate

function isDate(arg: any): arg is Date;

Helper that checks if the arg is of type Date.

🔴 Parameter: arg

any

🟢 Returns

arg is Date

🟨 Function: isElement

function isElement(arg: any): arg is Element;

Helper that checks if the arg is of type Element.

🔴 Parameter: arg

any

🟢 Returns

arg is Element

🟨 Function: isFunction

function isFunction(arg: any): arg is Function;

Helper that checks if the arg is of type Function.

🔴 Parameter: arg

any

🟢 Returns

arg is Function

🟨 Function: isGeneratorFunction

function isGeneratorFunction(arg: any): arg is GeneratorFunction;

Helper that checks if the arg is of type GeneratorFunction.

🔴 Parameter: arg

any

🟢 Returns

arg is GeneratorFunction

🟨 Function: isHTMLButtonElement

function isHTMLButtonElement(arg: any): arg is HTMLButtonElement;

Helper that checks if the arg is of type HTMLButtonElement.

🔴 Parameter: arg

any

🟢 Returns

arg is HTMLButtonElement

🟨 Function: isHTMLInputElement

function isHTMLInputElement(arg: any): arg is HTMLInputElement;

Helper that checks if the arg is of type HTMLInputElement.

🔴 Parameter: arg

any

🟢 Returns

arg is HTMLInputElement

🟨 Function: isHTMLTextAreaElement

function isHTMLTextAreaElement(arg: any): arg is HTMLTextAreaElement;

Helper that checks if the arg is of type HTMLTextAreaElement.

🔴 Parameter: arg

any

🟢 Returns

arg is HTMLTextAreaElement

🟨 Function: isNumber

function isNumber(arg: any): arg is number;

Helper that checks if the arg is of type Number.

🔴 Parameter: arg

any

🟢 Returns

arg is Number

🟨 Function: isObject

function isObject(arg: any): arg is any;

Helper that checks if the arg is of type Object.

🔴 Parameter: arg

any

🟢 Returns

arg is Object

🟨 Function: isPromise

function isPromise(arg: any): arg is Promise<any>;

Helper that checks if the arg is of type Promise.

🔴 Parameter: arg

any

🟢 Returns

arg is Promise

🟨 Function: isRegExp

function isRegExp(arg: any): arg is RegExp;

Helper that checks if the arg is of type RegExp.

🔴 Parameter: arg

any

🟢 Returns

arg is RegExp

🟨 Function: isString

function isString(arg: any): arg is string;

Helper that checks if the arg is of type String.

🔴 Parameter: arg

any

🟢 Returns

arg is String

🟨 Function: isText

function isText(arg: any): arg is Text;

Helper that checks if the arg is of type Text.

🔴 Parameter: arg

any

🟢 Returns

arg is Text

🟨 Function: typeOf

function typeOf(arg: any): string;

Replacement for the typeof ope

22.7.10-9.23.16

2 years ago

22.6.15-13.46.11

2 years ago

22.6.14-12.43.43

2 years ago

22.7.9-20.29.2

2 years ago

22.7.5-12.15.4

2 years ago

22.6.14-20.29.9

2 years ago

22.6.14-12.55.56

2 years ago

22.6.15-19.37.4

2 years ago

22.6.17-8.49.52

2 years ago

22.6.17-9.1.49

2 years ago

22.5.22-21.21.57

2 years ago

22.6.10-6.52.46

2 years ago

22.6.9-17.30.35

2 years ago

22.6.10-6.42.56

2 years ago

22.6.9-19.20.16

2 years ago

22.5.24-7.35.24

2 years ago

22.6.9-21.53.37

2 years ago

22.4.18-20.20.22

2 years ago

22.4.18-9.18.27

2 years ago

22.4.17-21.51.36

2 years ago

22.4.16-16.8.56

2 years ago

22.4.15-7.5.33

2 years ago

22.4.14-15.35.22

2 years ago

22.4.14-12.21.23

2 years ago

22.4.14-11.49.44

2 years ago

22.4.14-11.36.59

2 years ago

22.4.13-19.20.37

2 years ago

22.4.13-10.57.10

2 years ago

22.4.11-23.4.54

2 years ago

22.4.11-13.55.11

2 years ago

22.4.11-11.11.40

2 years ago

22.4.11-10.49.21

2 years ago

22.4.11-10.35.21

2 years ago

22.4.11-9.43.44

2 years ago

22.4.11-0.18.3

2 years ago

22.4.10-17.25.40

2 years ago

22.4.9-20.17.0

2 years ago

22.4.8-14.1.2

2 years ago

22.4.7-16.5.5

2 years ago

22.4.7-0.48.50

2 years ago

22.4.6-20.34.27

2 years ago

22.4.3-15.56.48

2 years ago

22.4.3-13.4.33

2 years ago

22.4.3-12.51.30

2 years ago

22.4.2-16.20.8

2 years ago

22.4.1-23.8.44

2 years ago

22.4.1-17.39.23

2 years ago

22.3.29-5.36.53

2 years ago

22.3.28-7.52.31

2 years ago

22.3.27-19.35.19

2 years ago