@jackens/nnn
v2026.9.9
Published
Jackens’ JavaScript helpers.
Maintainers
Readme
nnn
A collection of Jackens’ JavaScript helper utilities (version: 2026.9.9).
Installation
bun i @jackens/nnnor
npm i @jackens/nnnUsage
import {
CNode,
HArgs,
HArgs1,
c,
createEscape,
createTokenizer,
csvParse,
fixPlTypography,
h,
monokai,
nanolightTs,
rwd,
s,
svgUse,
uuidV1,
} from '@jackens/nnn' // or './node_modules/@jackens/nnn/nnn.js'Exports
CNode: Represents a CSS rule node for thechelper. Keys are CSS properties or nested selectors.HArgs: Tuple argument type for thehandshelpers.HArgs1: Single argument type for thehandshelpers.c: A minimal CSS-in-JS helper that converts a JavaScript object hierarchy into a CSS string.createEscape: Creates a tag function for escaping interpolated values in template literals.createTokenizer: A helper for building simple tokenizers (see alsonanolightTs).csvParse: Parses a CSV string into a two-dimensional array of strings.fixPlTypography: Applies Polish-specific typographic corrections to a DOM subtree.h: A lightweight HyperScript-style helper for creating and modifyingHTMLElements (see alsos).monokai: A Monokai-inspired color scheme for use with thechelper andnanolightTstokenizer.nanolightTs: A TypeScript/JavaScript syntax highlighting tokenizer built usingcreateTokenizer.rwd: A responsive web design helper that generates CSS rules for a grid-like layout.s: A lightweight HyperScript-style helper for creating and modifyingSVGElements (see alsoh).svgUse: Shorthand for creating an SVG element with a<use>child referencing an icon by ID.uuidV1: Generates a UUID v1 (time-based) identifier.
CNode
type CNode = {
[attributeOrSelector: string]: string | number | CNode | undefined;
};Represents a CSS rule node for the c helper. Keys
are CSS properties or nested selectors.
HArgs
type HArgs = [string | Node, ...HArgs1[]];Tuple argument type for the h and s
helpers.
HArgs1
type HArgs1 = Record<PropertyKey, unknown> | null | undefined | Node | string | number | HArgs;Single argument type for the h and s
helpers.
c
const c: (node: CNode, splitter?: string) => string;A minimal CSS-in-JS helper that converts a JavaScript object hierarchy into a CSS string.
node
An object describing CSS rules. Keys are
selectors or at-rules; values are either CSS property
values or nested rule objects. A selector key may
contain comma-separated alternatives (e.g. '.b,.c');
when nested, each alternative is combined with each
parent alternative (cartesian product), producing a
comma-joined selector list (e.g. 'a.b,a.c').
splitter
A delimiter used to create unique keys
(default: '$$'). The substring from splitter to the
end of a key is ignored (e.g., src$$1 → src).
Returns
A CSS string representing the compiled rules.
Usage Examples
const actual = c({
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
}
`.replace(/\n\s*/g, '')
expect(actual).toBe(expected)const actual = c({
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
}
`.replace(/\n\s*/g, '')
expect(actual).toBe(expected)const actual = c({
'@font-face$$1': {
'font-family': 'Jackens',
src$$1: 'url(otf/jackens.otf)',
src$$2:
"url(otf/jackens.otf) format('opentype')," +
"url(svg/jackens.svg) format('svg')",
'font-weight': 'normal',
'font-style': 'normal',
},
'@font-face$$2': {
'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',
'.c1': { 'background-color': '#000' },
' .c1': { 'background-color': 'black' },
'.c2': { 'background-color': '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(otf/jackens.otf);
src:url(otf/jackens.otf) format('opentype'),url(svg/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
}
}
`.replace(/\n\s*/g, '')
expect(actual).toBe(expected)const actual = c({
a: {
'.b,.c': {
margin: 1,
'.d': {
margin: 2,
},
},
},
})
const expected = `
a.b,a.c{
margin:1
}
a.b.d,a.c.d{
margin:2
}
`.replace(/\n\s*/g, '')
expect(actual).toBe(expected)const actual = c({
'.b,.c': {
margin: 1,
'.d': {
margin: 2,
},
},
})
const expected = `
.b,.c{
margin:1
}
.b.d,.c.d{
margin:2
}
`.replace(/\n\s*/g, '')
expect(actual).toBe(expected)const actual = c({
'.a,.b': {
margin: 1,
'.c,.d': {
margin: 2,
},
},
})
const expected = `
.a,.b{
margin:1
}
.a.c,.a.d,.b.c,.b.d{
margin:2
}
`.replace(/\n\s*/g, '')
expect(actual).toBe(expected)const actual = c({
':root$$monokai': {
'--': {
bg: '#faf4f2',
fg: '#29242a',
comment: '#918c8e',
identifier: {
1: '#7058be',
2: '#269d69',
3: '#1c8ca8',
4: '#29242a',
},
keyword: {
1: '#e14775',
2: '#7058be',
3: '#1c8ca8',
},
number: '#7058be',
operator: '#e14775',
punctuation: '#918c8e',
string: '#cc7a0a',
},
},
'@media only screen and (prefers-color-scheme: dark)$$monokai':
{
':root': {
'--': {
bg: '#2d2a2e',
fg: '#fcfcfa',
comment: '#727072',
identifier: {
1: '#ae81ff',
2: '#a9dc76',
3: '#66d9ef',
4: '#fcfcfa',
},
keyword: {
1: '#ff6188',
2: '#ae81ff',
3: '#66d9ef',
},
number: '#ae81ff',
operator: '#ff6188',
punctuation: '#727072',
string: '#ffd866',
},
},
},
})
const expected = `
:root{
--bg:#faf4f2;
--fg:#29242a;
--comment:#918c8e;
--identifier1:#7058be;
--identifier2:#269d69;
--identifier3:#1c8ca8;
--identifier4:#29242a;
--keyword1:#e14775;
--keyword2:#7058be;
--keyword3:#1c8ca8;
--number:#7058be;
--operator:#e14775;
--punctuation:#918c8e;
--string:#cc7a0a
}
@media only screen and (prefers-color-scheme: dark){
:root{
--bg:#2d2a2e;
--fg:#fcfcfa;
--comment:#727072;
--identifier1:#ae81ff;
--identifier2:#a9dc76;
--identifier3:#66d9ef;
--identifier4:#fcfcfa;
--keyword1:#ff6188;
--keyword2:#ae81ff;
--keyword3:#66d9ef;
--number:#ae81ff;
--operator:#ff6188;
--punctuation:#727072;
--string:#ffd866
}
}
`.replace(/\n\s*/g, '')
expect(actual).toBe(expected)createEscape
const createEscape: (escapeFn: (value: any) => string) => (template: TemplateStringsArray, ...values: unknown[]) => string;Creates a tag function for escaping interpolated values in template literals.
escapeFn
A function that takes a value and returns its escaped string representation.
Returns
A tag function that escapes interpolated values using the provided escape function.
Usage Examples
const escapeFn = (value: any): string =>
Array.isArray(value)
? value.map(escapeFn).join(', ')
: value === true || value === false
? `b'${+value}'`
: value instanceof Date
? `'${value
.toISOString()
.replace(/^(.+)T(.+)\..*$/, '$1 $2')}'`
: Number.isFinite(value)
? `${value}`
: typeof value === 'string'
? `'${value.replace(/'/g, "''")}'`
: 'NULL'
const sql = createEscape(escapeFn)
const actual = sql`
SELECT *
FROM table_name
WHERE column_name IN (
${[
true,
null,
undefined,
NaN,
Infinity,
42,
'42',
"4'2",
/42/,
new Date(323325000000),
]}
)
`
const expected = `
SELECT *
FROM table_name
WHERE column_name IN (
b'1', NULL, NULL, NULL, NULL, 42, '42', '4''2', NULL, '1980-03-31 04:30:00'
)
`
expect(actual).toBe(expected)createTokenizer
const createTokenizer: <M, T>(decorator: (chunk: string, metadata?: M) => T, ...specs: [M, string | RegExp][]) => (code: string) => T[];A helper for building simple tokenizers (see also
nanolightTs).
Remarks
- Matches starting at an earlier position take precedence.
- Among matches at the same position, the longer one wins.
- Among matches of the same position and length, the one defined earlier wins.
decorator
A function that wraps each matched
chunk. It receives the matched text (chunk) and
optionally the metadata associated with the pattern
that produced the match. For unmatched text between
patterns, metadata is undefined.
specs
An array of tuples [metadata, pattern]
where:
metadata: arbitrary data (e.g., a CSS class name) passed todecoratorwhen the pattern matches.pattern: astringorRegExpto match against the input.
Returns
A tokenizer function that accepts a code string and returns an array of decorated tokens.
Usage Examples
const tokenizer = createTokenizer(
(chunk, metadata) => ({ chunk, metadata }),
['keyword', /\b(if|else|for)\b/],
['string', /"[^"]*"/]
)
const result = tokenizer('if "hello" else "world"')
expect(result).toEqual([
{ chunk: 'if', metadata: 'keyword' },
{ chunk: ' ', metadata: undefined },
{ chunk: '"hello"', metadata: 'string' },
{ chunk: ' ', metadata: undefined },
{ chunk: 'else', metadata: 'keyword' },
{ chunk: ' ', metadata: undefined },
{ chunk: '"world"', metadata: 'string' },
])const tokenizer = createTokenizer(
(chunk, metadata) => `${metadata}:${chunk}`,
['tag', 'BEGIN'],
['end', 'END']
)
const result = tokenizer('aBEGINbENDc')
expect(result).toEqual([
'undefined:a',
'tag:BEGIN',
'undefined:b',
'end:END',
'undefined:c',
])const tokenizer = createTokenizer(
chunk => chunk,
['test', /test/]
)
const result = tokenizer('')
expect(result).toEqual([])const tokenizer = createTokenizer(
(chunk, metadata) => ({ chunk, metadata }),
['start', /^test/]
)
const result = tokenizer('test here')
expect(result).toEqual([
{ chunk: 'test', metadata: 'start' },
{ chunk: ' here', metadata: undefined },
])const tokenizer = createTokenizer(
(chunk, metadata) => metadata,
['later', /x/],
['earlier', /y/]
)
const result = tokenizer('yx')
expect(result).toEqual(['earlier', 'later'])const tokenizer = createTokenizer(
chunk => chunk,
['short', 'a'],
['long', 'abc']
)
const result = tokenizer('abc')
expect(result).toEqual(['abc'])const tokenizer = createTokenizer(
chunk => chunk,
['empty', ''],
['word', /\w+/]
)
const result = tokenizer('hello')
expect(result).toEqual(['hello'])const tokenizer = createTokenizer(
chunk => chunk,
['test', /xyz/]
)
const result = tokenizer('abc')
expect(result).toEqual(['abc'])const tokenizer = createTokenizer(
(_chunk, metadata) => metadata,
['a', 'a'],
['b', 'b']
)
const result = tokenizer('aabb')
expect(result).toEqual(['a', 'a', 'b', 'b'])csvParse
const csvParse: (csv: string, separator?: string) => string[][];Parses a CSV string into a two-dimensional array of strings.
Supports quoted fields with escaped double quotes ("").
Carriage returns are normalized.
csv
The CSV string to parse.
separator
The field delimiter (default: ',').
Returns
A 2D array where each inner array represents a row of fields.
Usage Examples
const text = `"aaa
""aaa""
aaa",bbb, "ccc,ccc"
"xxx,xxx", "yyy
yyy",zzz
42 , "42" , 17
`
expect(csvParse(text)).toEqual([
['aaa\n"aaa"\naaa', 'bbb', 'ccc,ccc'],
['xxx,xxx', 'yyy\nyyy', 'zzz'],
[' 42 ', '42', ' 17'],
])fixPlTypography
const fixPlTypography: (node: Node) => void;Applies Polish-specific typographic corrections to a DOM subtree.
This function prevents orphaned conjunctions
(single-letter words like “a”, “i”, “o”, “u”, “w”, “z”)
and the em dash (“—”) from appearing at the end of a
line. It wraps each such character together with the
whitespace that follows it in a white-space:nowrap
span, removing the only line-break opportunity between it
and the next word so the two stay glued together. It also
inserts zero-width spaces after slashes and dots to allow
line breaks.
node
The root DOM node to process. All descendant
text nodes are corrected recursively, except those
inside IFRAME, NOSCRIPT, PRE, SCRIPT, STYLE,
or TEXTAREA elements.
Usage Examples
const p = h(
'p',
'Pchnąć w tę łódź jeża lub ośm skrzyń fig ' +
'(zob. https://pl.wikipedia.org/wiki/Pangram).',
['br'],
['b', 'Zażółć gęślą jaźń.']
)
fixPlTypography(p)
expect(p.innerHTML).toEqual(
'Pchnąć ' +
'<span style="white-space:nowrap">w </span>' +
'tę łódź jeża lub ośm skrzyń fig ' +
'(zob. https://\u200Bpl.\u200Bwikipedia.\u200Borg/' +
'\u200Bwiki/\u200BPangram).' +
'<br>' +
'<b>Zażółć gęślą jaźń.</b>'
)h
const h: {
<T extends keyof HTMLElementTagNameMap>(tag: T, ...args1: HArgs1[]): HTMLElementTagNameMap[T];
<N extends Node>(node: N, ...args1: HArgs1[]): N;
(tagOrNode: string | Node, ...args1: HArgs1[]): Node;
};A lightweight HyperScript-style helper for creating and
modifying HTMLElements (see also s).
tagOrNode
If a string, it is treated as the tag
name for a new element. If a Node, that node is
modified in place.
args
Additional arguments processed as follows:
Object: maps attributes/properties. Keys starting with$set element properties (without the$prefix); if the value is a plain object, it is shallow-merged into the existing property instead of replacing it (useful e.g. for$style). Other keys set attributes: a key prefixed withxlink:sets the attribute viasetAttributeNSin the XLink namespace; any other key (without a colon) sets it viasetAttribute. A value offalseremoves the attribute.null/undefined: ignored.Node: appended as a child.string/number: converted to aTextnode and appended.HArgsarray: processed recursively.
Returns
The created or modified HTMLElement.
Usage Examples
const b = h('b')
expect(b.outerHTML).toBe('<b></b>')
const i = h('i', 'text')
h(b, i)
expect(i.outerHTML).toBe('<i>text</i>')
expect(b.outerHTML).toBe('<b><i>text</i></b>')
h(i, { $className: 'some class' })
expect(i.outerHTML).toBe('<i class="some class">text</i>')
expect(b.outerHTML).toBe(
'<b><i class="some class">text</i></b>'
)expect(h('span', 'text').outerHTML).toBe(
'<span>text</span>'
)
expect(h('span', { $innerText: 'text' }).outerHTML).toBe(
'<span>text</span>'
)
expect(h('span', '42').outerHTML).toBe('<span>42</span>')
expect(h('span', 42).outerHTML).toBe('<span>42</span>')expect(
h('div', { style: 'margin:0;padding:0' }).outerHTML
).toBe('<div style="margin:0;padding:0"></div>')
expect(
h('div', { $style: 'margin:0;padding:0' }).outerHTML
).toBe('<div style="margin: 0px; padding: 0px;"></div>')
expect(
h('div', { $style: { margin: 0, padding: 0 } })
.outerHTML
).toBe('<div style="margin: 0px; padding: 0px;"></div>')const input1 = h('input', { value: 42 })
const input2 = h('input', { $value: '42' })
expect(input1.value).toBe('42')
expect(input2.value).toBe('42')
expect(input1.outerHTML).toBe('<input value="42">')
expect(input2.outerHTML).toBe('<input>')const checkbox1 = h('input', {
type: 'checkbox',
checked: true,
})
const checkbox2 = h('input', {
type: 'checkbox',
$checked: true,
})
expect(checkbox1.checked).toBe(true)
expect(checkbox2.checked).toBe(true)
expect(checkbox1.outerHTML).toBe(
'<input type="checkbox" checked="">'
)
expect(checkbox2.outerHTML).toBe(
'<input type="checkbox">'
)const div = h('div')
expect(div.key).toBeUndefined()
h(div, { $key: { one: 1 } })
expect(div.key).toEqual({ one: 1 })
h(div, { $key: { two: 2 } })
expect(div.key).toEqual({ one: 1, two: 2 })const elemWithClass = h('div', { class: 'test' })
expect(elemWithClass.getAttribute('class')).toBe('test')
const elemWithText = h('div', 'initial')
h(elemWithText, ' more')
expect(elemWithText.outerHTML).toBe(
'<div>initial more</div>'
)
const elemWithNested = h(
'div',
['span', 'hello'],
['b', 'world']
)
expect(elemWithNested.outerHTML).toBe(
'<div><span>hello</span><b>world</b></div>'
)monokai
const monokai: CNode;A Monokai-inspired color scheme for use with the c
helper and nanolightTs tokenizer.
nanolightTs
const nanolightTs: (code: string) => HArgs1[];A TypeScript/JavaScript syntax highlighting tokenizer
built using createTokenizer.
code
The source code string to tokenize.
Returns
An array of HArgs1 elements suitable for
rendering with h.
Usage Examples
const codeJs =
'const answerToLifeTheUniverseAndEverything = ' +
"{ 42: 42 }['42'] /* 42 */"
expect(nanolightTs(codeJs)).toEqual([
['span', { class: 'keyword1' }, 'const'],
' ',
[
'span',
{ class: 'identifier4' },
'answerToLifeTheUniverseAndEverything',
],
' ',
['span', { class: 'operator' }, '='],
' ',
['span', { class: 'punctuation' }, '{'],
' ',
['span', { class: 'number' }, '42'],
['span', { class: 'operator' }, ':'],
' ',
['span', { class: 'number' }, '42'],
' ',
['span', { class: 'punctuation' }, '}'],
['span', { class: 'punctuation' }, '['],
['span', { class: 'string' }, "'42'"],
['span', { class: 'punctuation' }, ']'],
' ',
['span', { class: 'comment' }, '/* 42 */'],
])rwd
const rwd: (root: CNode, selector: string, cellWidthPx: number, cellHeightPx: number, ...specs: [number, number?, number?][]) => void;A responsive web design helper that generates CSS rules for a grid-like layout.
root
The CSS root object to populate (see
c).
selector
The CSS selector for the grid item.
cellWidthPx
The base cell width in pixels.
cellHeightPx
The base cell height in pixels.
specs
An array of breakpoint specifications, each a tuple of:
maxWidth: maximum number of cells per row (defines the viewport breakpoint).width(optional, default1): number of horizontal cells the element spans.height(optional, default1): number of vertical cells the element spans.
Usage Examples
const style: CNode = {
body: {
margin: 0,
},
'.r6': {
border: 'solid red 1px',
'.no-border': {
border: 'none',
},
},
}
rwd(style, '.r6', 200, 50, [6], [3], [1, 1, 2])
expect(style).toEqual({
body: {
margin: 0,
},
'.r6': {
border: 'solid red 1px',
'.no-border': {
border: 'none',
},
boxSizing: 'border-box',
display: 'block',
float: 'left',
width: '100%',
height: '100px',
},
'@media(min-width:600px)': {
'.r6': {
width: 'calc(100% / 3)',
height: '50px',
},
},
'@media(min-width:1200px)': {
'.r6': {
width: 'calc(50% / 3)',
height: '50px',
},
},
})s
const s: {
<T extends keyof SVGElementTagNameMap>(tag: T, ...args1: HArgs1[]): SVGElementTagNameMap[T];
<N extends Node>(node: N, ...args1: HArgs1[]): N;
(tagOrNode: string | Node, ...args1: HArgs1[]): Node;
};A lightweight HyperScript-style helper for creating and
modifying SVGElements (see also h).
tagOrNode
If a string, it is treated as the tag
name for a new element. If a Node, that node is
modified in place.
args
Additional arguments processed as follows:
Object: maps attributes/properties. Keys starting with$set element properties (without the$prefix); if the value is a plain object, it is shallow-merged into the existing property instead of replacing it. Other keys set attributes: a key prefixed withxlink:sets the attribute viasetAttributeNSin the XLink namespace; any other key (without a colon) sets it viasetAttribute. A value offalseremoves the attribute.null/undefined: ignored.Node: appended as a child.string/number: converted to aTextnode and appended.HArgsarray: processed recursively.
Returns
The created or modified SVGElement.
Usage Examples
const svg = s('svg', { 'xlink:href': true })
expect(
svg.getAttributeNS(
'http://www.w3.org/1999/xlink',
'href'
)
).toBe('')const svg = s('svg', { 'xlink:href': false })
expect(
svg.getAttributeNS(
'http://www.w3.org/1999/xlink',
'href'
)
).toBeNull()const svg = s('svg', {
'xlink:href': 'http://example.com',
})
expect(
svg.getAttributeNS(
'http://www.w3.org/1999/xlink',
'href'
)
).toBe('http://example.com')const svg = s('svg', { 'xlink:title': 42 })
expect(
svg.getAttributeNS(
'http://www.w3.org/1999/xlink',
'title'
)
).toBe('42')svgUse
const svgUse: (id: string, ...args: HArgs1[]) => SVGSVGElement;Shorthand for creating an SVG element with a <use>
child referencing an icon by ID.
Equivalent to:
s(
'svg',
['use', { 'xlink:href': '#' + id }],
...args
)id
The ID of the symbol to reference (without the
# prefix).
args
Additional arguments passed to the outer
<svg> element.
Returns
An SVGSVGElement containing a <use> element.
Usage Examples
const svg = svgUse('icon-home')
expect(svg.children.length).toBe(1)
const useElement = svg.children[0]
expect(
useElement.getAttributeNS(
'http://www.w3.org/1999/xlink',
'href'
)
).toBe('#icon-home')
const svgWithViewBox = svgUse('icon-star', {
viewBox: '0 0 24 24',
})
expect(svgWithViewBox.getAttribute('viewBox')).toBe(
'0 0 24 24'
)
const useViewBox = svgWithViewBox.children[0]
expect(
useViewBox.getAttributeNS(
'http://www.w3.org/1999/xlink',
'href'
)
).toBe('#icon-star')
const svgWithClass = svgUse('icon-menu', {
class: 'icon-btn',
})
expect(svgWithClass.getAttribute('class')).toBe(
'icon-btn'
)
expect(svgWithClass.children.length).toBe(1)
const useClass = svgWithClass.children[0]
expect(
useClass.getAttributeNS(
'http://www.w3.org/1999/xlink',
'href'
)
).toBe('#icon-menu')
const svgWithMultipleAttrs = svgUse('icon-settings', {
width: 24,
height: 24,
class: 'icon',
})
expect(svgWithMultipleAttrs.getAttribute('width')).toBe(
'24'
)
expect(svgWithMultipleAttrs.getAttribute('height')).toBe(
'24'
)
expect(svgWithMultipleAttrs.getAttribute('class')).toBe(
'icon'
)
const useMultiple = svgWithMultipleAttrs.children[0]
expect(
useMultiple.getAttributeNS(
'http://www.w3.org/1999/xlink',
'href'
)
).toBe('#icon-settings')uuidV1
const uuidV1: (date?: Date, node?: string) => string;Generates a UUID v1 (time-based) identifier.
date
The date to use for the timestamp portion (default: current date/time).
node
A hexadecimal string for the node portion
(default: random). Must match /^[0-9a-f]*$/; it is
trimmed to the last 12 characters and left-padded with
zeros if shorter.
Returns
A UUID v1 string in the standard format
xxxxxxxx-xxxx-1xxx-xxxx-xxxxxxxxxxxx.
Usage Examples
for (let i = 1; i <= 22136; ++i) {
const uuid = uuidV1()
if (i === 1) {
expect(uuid.split('-')[3]).toBe('8001')
}
if (i === 4095) {
expect(uuid.split('-')[3]).toBe('8fff')
}
if (i === 4096) {
expect(uuid.split('-')[3]).toBe('9000')
}
if (i === 9029) {
expect(uuid.split('-')[3]).toBe('a345')
}
if (i === 13398) {
expect(uuid.split('-')[3]).toBe('b456')
}
if (i === 16384) {
expect(uuid.split('-')[3]).toBe('8000')
}
if (i === 17767) {
expect(uuid.split('-')[3]).toBe('8567')
}
}expect(
uuidV1(new Date(), '000123456789abc').split('-')[4]
).toBe('123456789abc')
expect(
uuidV1(new Date(), '123456789').split('-')[4]
).toBe('000123456789')
expect(
uuidV1(new Date(323325000000)).startsWith(
'c1399400-9a71-11bd'
)
).toBe(true)License
The MIT License (MIT)
Copyright (c) 2016+ Jackens
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
