@jackens/nnn 2026.2.20 → 2026.2.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/nnn.d.ts +31 -31
- package/nnn.js +130 -130
- package/package.json +9 -8
- package/readme.md +139 -172
package/readme.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# nnn
|
|
2
2
|
|
|
3
|
-
A collection of Jackens’ JavaScript helper utilities (version: `2026.2.
|
|
3
|
+
A collection of Jackens’ JavaScript helper utilities (version: `2026.2.23`).
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -19,28 +19,28 @@ npm i @jackens/nnn
|
|
|
19
19
|
```js
|
|
20
20
|
import {
|
|
21
21
|
c,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
csvParse,
|
|
23
|
+
escapeValues,
|
|
24
|
+
fixPlTypography,
|
|
25
25
|
h,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
hasOown,
|
|
27
|
+
isArray,
|
|
28
|
+
isFiniteNumber,
|
|
29
|
+
isNumber,
|
|
30
|
+
isRecord,
|
|
31
|
+
isString,
|
|
32
|
+
jsOnParse,
|
|
33
33
|
monokai,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
nanolightTs,
|
|
35
|
+
newEscape,
|
|
36
|
+
newNounForm,
|
|
37
|
+
newTokenizer,
|
|
38
38
|
omit,
|
|
39
39
|
pick,
|
|
40
40
|
rwd,
|
|
41
41
|
s,
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
svgUse,
|
|
43
|
+
uuidV1,
|
|
44
44
|
vivify
|
|
45
45
|
} from '@jackens/nnn' // or './node_modules/@jackens/nnn/nnn.js'
|
|
46
46
|
```
|
|
@@ -53,35 +53,35 @@ import {
|
|
|
53
53
|
- [`HArgs`](#HArgs): Tuple argument type for the [`h`](#h) and [`s`](#s) helpers.
|
|
54
54
|
- [`HArgs1`](#HArgs1): Single argument type for the [`h`](#h) and [`s`](#s) helpers.
|
|
55
55
|
- [`c`](#c): A minimal CSS-in-JS helper that converts a JavaScript object hierarchy into a CSS string.
|
|
56
|
-
- [`
|
|
57
|
-
- [`
|
|
58
|
-
- [`
|
|
56
|
+
- [`csvParse`](#csvParse): Parses a CSV string into a two-dimensional array of strings.
|
|
57
|
+
- [`escapeValues`](#escapeValues): Escapes an array of values using the provided escape map.
|
|
58
|
+
- [`fixPlTypography`](#fixPlTypography): Applies Polish-specific typographic corrections to a DOM subtree.
|
|
59
59
|
- [`h`](#h): A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also [`s`](#s)).
|
|
60
|
-
- [`
|
|
61
|
-
- [`
|
|
62
|
-
- [`
|
|
63
|
-
- [`
|
|
64
|
-
- [`
|
|
65
|
-
- [`
|
|
66
|
-
- [`
|
|
67
|
-
- [`monokai`](#monokai): A Monokai-inspired color scheme for use with the [`c`](#c) helper and [`
|
|
68
|
-
- [`
|
|
69
|
-
- [`
|
|
70
|
-
- [`
|
|
71
|
-
- [`
|
|
60
|
+
- [`hasOown`](#hasOown): Checks whether an object has the specified key as its own property.
|
|
61
|
+
- [`isArray`](#isArray): Checks whether the argument is an array.
|
|
62
|
+
- [`isFiniteNumber`](#isFiniteNumber): Checks whether the argument is a finite number (excludes `±Infinity` and `NaN`).
|
|
63
|
+
- [`isNumber`](#isNumber): Checks whether the argument is of type `number` (includes `NaN` and `±Infinity`).
|
|
64
|
+
- [`isRecord`](#isRecord): Checks whether the argument is a plain object (not `null` and not an array).
|
|
65
|
+
- [`isString`](#isString): Checks whether the argument is a string.
|
|
66
|
+
- [`jsOnParse`](#jsOnParse): Parses JSON with support for handler-based value transformation (“JavaScript ON”).
|
|
67
|
+
- [`monokai`](#monokai): A Monokai-inspired color scheme for use with the [`c`](#c) helper and [`nanolightTs`](#nanolightTs) tokenizer.
|
|
68
|
+
- [`nanolightTs`](#nanolightTs): A TypeScript/JavaScript syntax highlighting tokenizer built using [`newTokenizer`](#newTokenizer).
|
|
69
|
+
- [`newEscape`](#newEscape): Creates a tag function for escaping interpolated values in template literals.
|
|
70
|
+
- [`newNounForm`](#newNounForm): Creates a function that returns the appropriate noun form based on a numeric value using `Intl.PluralRules`.
|
|
71
|
+
- [`newTokenizer`](#newTokenizer): A helper for building simple tokenizers (see also [`nanolightTs`](#nanolightTs)).
|
|
72
72
|
- [`omit`](#omit): Creates a new object excluding the specified keys from the source object.
|
|
73
73
|
- [`pick`](#pick): Creates a new object containing only the specified keys from the source object.
|
|
74
74
|
- [`rwd`](#rwd): A responsive web design helper that generates CSS rules for a grid-like layout.
|
|
75
75
|
- [`s`](#s): A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also [`h`](#h)).
|
|
76
|
-
- [`
|
|
77
|
-
- [`
|
|
76
|
+
- [`svgUse`](#svgUse): Shorthand for creating an SVG element with a `<use>` child referencing an icon by ID.
|
|
77
|
+
- [`uuidV1`](#uuidV1): Generates a UUID v1 (time-based) identifier.
|
|
78
78
|
- [`vivify`](#vivify): A Proxy-based helper for auto-vivification of nested object structures.
|
|
79
79
|
|
|
80
80
|
### CNode
|
|
81
81
|
|
|
82
82
|
```ts
|
|
83
83
|
type CNode = {
|
|
84
|
-
[
|
|
84
|
+
[attributeOrSelector: string]: string | number | CNode | undefined;
|
|
85
85
|
};
|
|
86
86
|
```
|
|
87
87
|
|
|
@@ -103,7 +103,7 @@ type EscapeMap = Map<unknown, (value?: unknown) => string>;
|
|
|
103
103
|
|
|
104
104
|
A map from value constructors (or `null`/`undefined`) to escape functions.
|
|
105
105
|
|
|
106
|
-
Used by [`
|
|
106
|
+
Used by [`escapeValues`](#escapeValues) and [`newEscape`](#newEscape).
|
|
107
107
|
|
|
108
108
|
### HArgs
|
|
109
109
|
|
|
@@ -155,7 +155,7 @@ A CSS string representing the compiled rules.
|
|
|
155
155
|
#### Usage Examples
|
|
156
156
|
|
|
157
157
|
```ts
|
|
158
|
-
const
|
|
158
|
+
const actual1 = c({
|
|
159
159
|
a: {
|
|
160
160
|
color: 'red',
|
|
161
161
|
margin: 1,
|
|
@@ -164,7 +164,7 @@ const actual_1 = c({
|
|
|
164
164
|
}
|
|
165
165
|
})
|
|
166
166
|
|
|
167
|
-
const
|
|
167
|
+
const expected1 = `
|
|
168
168
|
a{
|
|
169
169
|
color:red;
|
|
170
170
|
margin:1
|
|
@@ -177,9 +177,9 @@ a{
|
|
|
177
177
|
padding:1
|
|
178
178
|
}`.replace(/\n\s*/g, '')
|
|
179
179
|
|
|
180
|
-
expect(
|
|
180
|
+
expect(actual1).to.equal(expected1)
|
|
181
181
|
|
|
182
|
-
const
|
|
182
|
+
const actual2 = c({
|
|
183
183
|
a: {
|
|
184
184
|
'.b': {
|
|
185
185
|
color: 'red',
|
|
@@ -190,7 +190,7 @@ const actual_2 = c({
|
|
|
190
190
|
}
|
|
191
191
|
})
|
|
192
192
|
|
|
193
|
-
const
|
|
193
|
+
const expected2 = `
|
|
194
194
|
a.b{
|
|
195
195
|
color:red;
|
|
196
196
|
margin:1
|
|
@@ -203,9 +203,9 @@ a.b{
|
|
|
203
203
|
padding:1
|
|
204
204
|
}`.replace(/\n\s*/g, '')
|
|
205
205
|
|
|
206
|
-
expect(
|
|
206
|
+
expect(actual2).to.equal(expected2)
|
|
207
207
|
|
|
208
|
-
const
|
|
208
|
+
const actual3 = c({
|
|
209
209
|
'@font-face$$1': {
|
|
210
210
|
fontFamily: 'Jackens',
|
|
211
211
|
src$$1: 'url(otf/jackens.otf)',
|
|
@@ -234,7 +234,7 @@ const actual_3 = c({
|
|
|
234
234
|
}
|
|
235
235
|
})
|
|
236
236
|
|
|
237
|
-
const
|
|
237
|
+
const expected3 = `
|
|
238
238
|
@font-face{
|
|
239
239
|
font-family:Jackens;
|
|
240
240
|
src:url(otf/jackens.otf);
|
|
@@ -276,9 +276,9 @@ div.c2{
|
|
|
276
276
|
}
|
|
277
277
|
}`.replace(/\n\s*/g, '')
|
|
278
278
|
|
|
279
|
-
expect(
|
|
279
|
+
expect(actual3).to.equal(expected3)
|
|
280
280
|
|
|
281
|
-
const
|
|
281
|
+
const actual4 = c({
|
|
282
282
|
a: {
|
|
283
283
|
'.b,.c': {
|
|
284
284
|
margin: 1,
|
|
@@ -289,7 +289,7 @@ const actual_4 = c({
|
|
|
289
289
|
}
|
|
290
290
|
})
|
|
291
291
|
|
|
292
|
-
const
|
|
292
|
+
const expected4 = `
|
|
293
293
|
a.b,a.c{
|
|
294
294
|
margin:1
|
|
295
295
|
}
|
|
@@ -297,9 +297,9 @@ a.b.d,a.c.d{
|
|
|
297
297
|
margin:2
|
|
298
298
|
}`.replace(/\n\s*/g, '')
|
|
299
299
|
|
|
300
|
-
expect(
|
|
300
|
+
expect(actual4).to.equal(expected4)
|
|
301
301
|
|
|
302
|
-
const
|
|
302
|
+
const actual5 = c({
|
|
303
303
|
'.b,.c': {
|
|
304
304
|
margin: 1,
|
|
305
305
|
'.d': {
|
|
@@ -308,7 +308,7 @@ const actual_5 = c({
|
|
|
308
308
|
}
|
|
309
309
|
})
|
|
310
310
|
|
|
311
|
-
const
|
|
311
|
+
const expected5 = `
|
|
312
312
|
.b,.c{
|
|
313
313
|
margin:1
|
|
314
314
|
}
|
|
@@ -316,9 +316,9 @@ const expected_5 = `
|
|
|
316
316
|
margin:2
|
|
317
317
|
}`.replace(/\n\s*/g, '')
|
|
318
318
|
|
|
319
|
-
expect(
|
|
319
|
+
expect(actual5).to.equal(expected5)
|
|
320
320
|
|
|
321
|
-
const
|
|
321
|
+
const actual6 = c({
|
|
322
322
|
'.a,.b': {
|
|
323
323
|
margin: 1,
|
|
324
324
|
'.c,.d': {
|
|
@@ -327,7 +327,7 @@ const actual_6 = c({
|
|
|
327
327
|
}
|
|
328
328
|
})
|
|
329
329
|
|
|
330
|
-
const
|
|
330
|
+
const expected6 = `
|
|
331
331
|
.a,.b{
|
|
332
332
|
margin:1
|
|
333
333
|
}
|
|
@@ -335,13 +335,13 @@ const expected_6 = `
|
|
|
335
335
|
margin:2
|
|
336
336
|
}`.replace(/\n\s*/g, '')
|
|
337
337
|
|
|
338
|
-
expect(
|
|
338
|
+
expect(actual6).to.equal(expected6)
|
|
339
339
|
```
|
|
340
340
|
|
|
341
|
-
###
|
|
341
|
+
### csvParse
|
|
342
342
|
|
|
343
343
|
```ts
|
|
344
|
-
const
|
|
344
|
+
const csvParse: (csv: string, separator?: string) => string[][];
|
|
345
345
|
```
|
|
346
346
|
|
|
347
347
|
Parses a CSV string into a two-dimensional array of strings.
|
|
@@ -372,22 +372,22 @@ yyy",zzz
|
|
|
372
372
|
|
|
373
373
|
`
|
|
374
374
|
|
|
375
|
-
expect(
|
|
375
|
+
expect(csvParse(text)).to.deep.equal([
|
|
376
376
|
['aaa\n"aaa"\naaa', 'bbb', 'ccc,ccc'],
|
|
377
377
|
['xxx,xxx', 'yyy\nyyy', 'zzz'],
|
|
378
378
|
[' 42 ', '42', ' 17']
|
|
379
379
|
])
|
|
380
380
|
```
|
|
381
381
|
|
|
382
|
-
###
|
|
382
|
+
### escapeValues
|
|
383
383
|
|
|
384
384
|
```ts
|
|
385
|
-
const
|
|
385
|
+
const escapeValues: (escapeMap: EscapeMap, values: unknown[]) => string[];
|
|
386
386
|
```
|
|
387
387
|
|
|
388
388
|
Escapes an array of values using the provided escape map.
|
|
389
389
|
|
|
390
|
-
####
|
|
390
|
+
#### escapeMap
|
|
391
391
|
|
|
392
392
|
A map where keys are constructors (e.g., `String`, `Number`) and values are escape functions.
|
|
393
393
|
|
|
@@ -399,10 +399,10 @@ The array of values to escape.
|
|
|
399
399
|
|
|
400
400
|
An array of escaped strings.
|
|
401
401
|
|
|
402
|
-
###
|
|
402
|
+
### fixPlTypography
|
|
403
403
|
|
|
404
404
|
```ts
|
|
405
|
-
const
|
|
405
|
+
const fixPlTypography: (node: Node) => void;
|
|
406
406
|
```
|
|
407
407
|
|
|
408
408
|
Applies Polish-specific typographic corrections to a DOM subtree.
|
|
@@ -421,7 +421,7 @@ except those inside `IFRAME`, `NOSCRIPT`, `PRE`, `SCRIPT`, `STYLE`, or `TEXTAREA
|
|
|
421
421
|
```ts
|
|
422
422
|
const p = h('p', 'Pchnąć w tę łódź jeża lub ośm skrzyń fig (zob. https://pl.wikipedia.org/wiki/Pangram).')
|
|
423
423
|
|
|
424
|
-
|
|
424
|
+
fixPlTypography(p)
|
|
425
425
|
|
|
426
426
|
expect(p.innerHTML).to.deep.equal(
|
|
427
427
|
'Pchnąć <span style="white-space:nowrap">w </span>tę łódź jeża lub ośm skrzyń fig ' +
|
|
@@ -434,13 +434,13 @@ expect(p.innerHTML).to.deep.equal(
|
|
|
434
434
|
const h: {
|
|
435
435
|
<T extends keyof HTMLElementTagNameMap>(tag: T, ...args1: HArgs1[]): HTMLElementTagNameMap[T];
|
|
436
436
|
<N extends Node>(node: N, ...args1: HArgs1[]): N;
|
|
437
|
-
(
|
|
437
|
+
(tagOrNode: string | Node, ...args1: HArgs1[]): Node;
|
|
438
438
|
};
|
|
439
439
|
```
|
|
440
440
|
|
|
441
441
|
A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also [`s`](#s)).
|
|
442
442
|
|
|
443
|
-
####
|
|
443
|
+
#### tagOrNode
|
|
444
444
|
|
|
445
445
|
If a `string`, it is treated as the tag name for a new element.
|
|
446
446
|
If a `Node`, that node is modified in place.
|
|
@@ -522,10 +522,10 @@ h(div, { $key: { two: 2 } })
|
|
|
522
522
|
expect(div.key).to.deep.equal({ one: 1, two: 2 })
|
|
523
523
|
```
|
|
524
524
|
|
|
525
|
-
###
|
|
525
|
+
### hasOown
|
|
526
526
|
|
|
527
527
|
```ts
|
|
528
|
-
const
|
|
528
|
+
const hasOown: (ref: unknown, key: unknown) => boolean;
|
|
529
529
|
```
|
|
530
530
|
|
|
531
531
|
Checks whether an object has the specified key as its own property.
|
|
@@ -544,43 +544,10 @@ The property key to look for.
|
|
|
544
544
|
|
|
545
545
|
`true` if `ref` is not nullish and has `key` as an own property, `false` otherwise.
|
|
546
546
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
```ts
|
|
550
|
-
const obj = { 42: null, null: 'k,e,y', 'k,e,y': 42 }
|
|
551
|
-
|
|
552
|
-
expect(42 in obj).to.be.true
|
|
553
|
-
expect(has_own(obj, 42)).to.be.true
|
|
554
|
-
|
|
555
|
-
expect('42' in obj).to.be.true
|
|
556
|
-
expect(has_own(obj, '42')).to.be.true
|
|
557
|
-
|
|
558
|
-
expect('null' in obj).to.be.true
|
|
559
|
-
expect(has_own(obj, 'null')).to.be.true
|
|
560
|
-
|
|
561
|
-
expect(null in obj).to.be.true
|
|
562
|
-
expect(has_own(obj, null)).to.be.true
|
|
563
|
-
|
|
564
|
-
expect('k,e,y' in obj).to.be.true
|
|
565
|
-
expect(has_own(obj, 'k,e,y')).to.be.true
|
|
566
|
-
|
|
567
|
-
expect(['k', 'e', 'y'] in obj).to.be.true
|
|
568
|
-
expect(has_own(obj, ['k', 'e', 'y'])).to.be.true
|
|
569
|
-
|
|
570
|
-
expect('toString' in obj).to.be.true
|
|
571
|
-
expect(has_own(obj, 'toString')).to.be.false
|
|
572
|
-
|
|
573
|
-
expect(() => 'key' in null).to.throw
|
|
574
|
-
expect(has_own(null, 'key')).to.be.false
|
|
575
|
-
|
|
576
|
-
expect(() => 'key' in undefined).to.throw
|
|
577
|
-
expect(has_own(undefined, 'key')).to.be.false
|
|
578
|
-
```
|
|
579
|
-
|
|
580
|
-
### is_array
|
|
547
|
+
### isArray
|
|
581
548
|
|
|
582
549
|
```ts
|
|
583
|
-
const
|
|
550
|
+
const isArray: (arg: unknown) => arg is unknown[];
|
|
584
551
|
```
|
|
585
552
|
|
|
586
553
|
Checks whether the argument is an array.
|
|
@@ -596,15 +563,15 @@ The value to check.
|
|
|
596
563
|
#### Usage Examples
|
|
597
564
|
|
|
598
565
|
```ts
|
|
599
|
-
expect(
|
|
600
|
-
expect(
|
|
601
|
-
expect(
|
|
566
|
+
expect(isArray([])).to.be.true
|
|
567
|
+
expect(isArray(Object.create({ constructor: Array }))).to.be.false
|
|
568
|
+
expect(isArray(Object.create({ [Symbol.toStringTag]: Array.name }))).to.be.false
|
|
602
569
|
```
|
|
603
570
|
|
|
604
|
-
###
|
|
571
|
+
### isFiniteNumber
|
|
605
572
|
|
|
606
573
|
```ts
|
|
607
|
-
const
|
|
574
|
+
const isFiniteNumber: (arg: unknown) => arg is number;
|
|
608
575
|
```
|
|
609
576
|
|
|
610
577
|
Checks whether the argument is a finite number (excludes `±Infinity` and `NaN`).
|
|
@@ -620,17 +587,17 @@ The value to check.
|
|
|
620
587
|
#### Usage Examples
|
|
621
588
|
|
|
622
589
|
```ts
|
|
623
|
-
expect(
|
|
624
|
-
expect(
|
|
625
|
-
expect(
|
|
626
|
-
expect(
|
|
627
|
-
expect(
|
|
590
|
+
expect(isFiniteNumber(42)).to.be.true
|
|
591
|
+
expect(isFiniteNumber(Number(42))).to.be.true
|
|
592
|
+
expect(isFiniteNumber(new Number(42))).to.be.false
|
|
593
|
+
expect(isFiniteNumber(NaN)).to.be.false
|
|
594
|
+
expect(isFiniteNumber(Infinity)).to.be.false
|
|
628
595
|
```
|
|
629
596
|
|
|
630
|
-
###
|
|
597
|
+
### isNumber
|
|
631
598
|
|
|
632
599
|
```ts
|
|
633
|
-
const
|
|
600
|
+
const isNumber: (arg: unknown) => arg is number;
|
|
634
601
|
```
|
|
635
602
|
|
|
636
603
|
Checks whether the argument is of type `number` (includes `NaN` and `±Infinity`).
|
|
@@ -646,17 +613,17 @@ The value to check.
|
|
|
646
613
|
#### Usage Examples
|
|
647
614
|
|
|
648
615
|
```ts
|
|
649
|
-
expect(
|
|
650
|
-
expect(
|
|
651
|
-
expect(
|
|
652
|
-
expect(
|
|
653
|
-
expect(
|
|
616
|
+
expect(isNumber(42)).to.be.true
|
|
617
|
+
expect(isNumber(Number(42))).to.be.true
|
|
618
|
+
expect(isNumber(new Number(42))).to.be.false
|
|
619
|
+
expect(isNumber(NaN)).to.be.true
|
|
620
|
+
expect(isNumber(Infinity)).to.be.true
|
|
654
621
|
```
|
|
655
622
|
|
|
656
|
-
###
|
|
623
|
+
### isRecord
|
|
657
624
|
|
|
658
625
|
```ts
|
|
659
|
-
const
|
|
626
|
+
const isRecord: (arg: unknown) => arg is Record<PropertyKey, unknown>;
|
|
660
627
|
```
|
|
661
628
|
|
|
662
629
|
Checks whether the argument is a plain object (not `null` and not an array).
|
|
@@ -672,23 +639,23 @@ The value to check.
|
|
|
672
639
|
#### Usage Examples
|
|
673
640
|
|
|
674
641
|
```ts
|
|
675
|
-
expect(
|
|
676
|
-
expect(
|
|
677
|
-
expect(
|
|
678
|
-
expect(
|
|
679
|
-
expect(
|
|
680
|
-
expect(
|
|
681
|
-
expect(
|
|
642
|
+
expect(isRecord({})).to.be.true
|
|
643
|
+
expect(isRecord([])).to.be.false
|
|
644
|
+
expect(isRecord(Object.create(null))).to.be.true
|
|
645
|
+
expect(isRecord(Object.create({ constructor: Number }))).to.be.true
|
|
646
|
+
expect(isRecord(Object.create({ [Symbol.toStringTag]: Number.name }))).to.be.true
|
|
647
|
+
expect(isRecord(new Number(42))).to.be.true
|
|
648
|
+
expect(isRecord(new String('42'))).to.be.true
|
|
682
649
|
|
|
683
|
-
class
|
|
650
|
+
class FooBar { }
|
|
684
651
|
|
|
685
|
-
expect(
|
|
652
|
+
expect(isRecord(new FooBar())).to.be.true
|
|
686
653
|
```
|
|
687
654
|
|
|
688
|
-
###
|
|
655
|
+
### isString
|
|
689
656
|
|
|
690
657
|
```ts
|
|
691
|
-
const
|
|
658
|
+
const isString: (arg: unknown) => arg is string;
|
|
692
659
|
```
|
|
693
660
|
|
|
694
661
|
Checks whether the argument is a string.
|
|
@@ -704,15 +671,15 @@ The value to check.
|
|
|
704
671
|
#### Usage Examples
|
|
705
672
|
|
|
706
673
|
```ts
|
|
707
|
-
expect(
|
|
708
|
-
expect(
|
|
709
|
-
expect(
|
|
674
|
+
expect(isString('42')).to.be.true
|
|
675
|
+
expect(isString(String('42'))).to.be.true
|
|
676
|
+
expect(isString(new String('42'))).to.be.false
|
|
710
677
|
```
|
|
711
678
|
|
|
712
|
-
###
|
|
679
|
+
### jsOnParse
|
|
713
680
|
|
|
714
681
|
```ts
|
|
715
|
-
const
|
|
682
|
+
const jsOnParse: (handlers: Record<PropertyKey, Function>, text: string) => any;
|
|
716
683
|
```
|
|
717
684
|
|
|
718
685
|
Parses JSON with support for handler-based value transformation (“JavaScript ON”).
|
|
@@ -741,7 +708,7 @@ const handlers = {
|
|
|
741
708
|
$foo: () => 'bar'
|
|
742
709
|
}
|
|
743
710
|
|
|
744
|
-
const actual =
|
|
711
|
+
const actual = jsOnParse(handlers, `[
|
|
745
712
|
{
|
|
746
713
|
"$add": [1, 2]
|
|
747
714
|
},
|
|
@@ -790,15 +757,15 @@ expect(actual).to.deep.equal(expected)
|
|
|
790
757
|
const monokai: CRoot;
|
|
791
758
|
```
|
|
792
759
|
|
|
793
|
-
A Monokai-inspired color scheme for use with the [`c`](#c) helper and [`
|
|
760
|
+
A Monokai-inspired color scheme for use with the [`c`](#c) helper and [`nanolightTs`](#nanolightTs) tokenizer.
|
|
794
761
|
|
|
795
|
-
###
|
|
762
|
+
### nanolightTs
|
|
796
763
|
|
|
797
764
|
```ts
|
|
798
|
-
const
|
|
765
|
+
const nanolightTs: (code: string) => HArgs1[];
|
|
799
766
|
```
|
|
800
767
|
|
|
801
|
-
A TypeScript/JavaScript syntax highlighting tokenizer built using [`
|
|
768
|
+
A TypeScript/JavaScript syntax highlighting tokenizer built using [`newTokenizer`](#newTokenizer).
|
|
802
769
|
|
|
803
770
|
#### code
|
|
804
771
|
|
|
@@ -811,12 +778,12 @@ An array of [`HArgs1`](#HArgs1) elements suitable for rendering with [`h`](#h).
|
|
|
811
778
|
#### Usage Examples
|
|
812
779
|
|
|
813
780
|
```ts
|
|
814
|
-
const
|
|
781
|
+
const codeJs = "const answerToLifeTheUniverseAndEverything = { 42: 42 }['42'] /* 42 */"
|
|
815
782
|
|
|
816
|
-
expect(
|
|
783
|
+
expect(nanolightTs(codeJs)).to.deep.equal([
|
|
817
784
|
['span', { class: 'keyword-1' }, 'const'],
|
|
818
785
|
' ',
|
|
819
|
-
['span', { class: 'identifier-4' }, '
|
|
786
|
+
['span', { class: 'identifier-4' }, 'answerToLifeTheUniverseAndEverything'],
|
|
820
787
|
' ',
|
|
821
788
|
['span', { class: 'operator' }, '='],
|
|
822
789
|
' ',
|
|
@@ -836,15 +803,15 @@ expect(nanolight_ts(code_js)).to.deep.equal([
|
|
|
836
803
|
])
|
|
837
804
|
```
|
|
838
805
|
|
|
839
|
-
###
|
|
806
|
+
### newEscape
|
|
840
807
|
|
|
841
808
|
```ts
|
|
842
|
-
const
|
|
809
|
+
const newEscape: (escapeMap: EscapeMap) => (template: TemplateStringsArray, ...values: unknown[]) => string;
|
|
843
810
|
```
|
|
844
811
|
|
|
845
812
|
Creates a tag function for escaping interpolated values in template literals.
|
|
846
813
|
|
|
847
|
-
####
|
|
814
|
+
#### escapeMap
|
|
848
815
|
|
|
849
816
|
A map where keys are constructors and values are escape functions.
|
|
850
817
|
|
|
@@ -855,17 +822,17 @@ A tag function that escapes interpolated values using the provided escape map.
|
|
|
855
822
|
#### Usage Examples
|
|
856
823
|
|
|
857
824
|
```ts
|
|
858
|
-
const
|
|
825
|
+
const escapeMap: EscapeMap = new Map([
|
|
859
826
|
[null, () => 'NULL'],
|
|
860
827
|
[undefined, () => 'NULL'],
|
|
861
|
-
[Array, (values: unknown[]) =>
|
|
828
|
+
[Array, (values: unknown[]) => escapeValues(escapeMap, values).join(', ')],
|
|
862
829
|
[Boolean, (value: boolean) => `b'${+value}'`],
|
|
863
830
|
[Date, (value: Date) => `'${value.toISOString().replace(/^(.+)T(.+)\..*$/, '$1 $2')}'`],
|
|
864
831
|
[Number, (value: number) => `${value}`],
|
|
865
832
|
[String, (value: string) => `'${value.replace(/'/g, "''")}'`]
|
|
866
833
|
])
|
|
867
834
|
|
|
868
|
-
const sql =
|
|
835
|
+
const sql = newEscape(escapeMap)
|
|
869
836
|
|
|
870
837
|
const actual = sql`
|
|
871
838
|
SELECT *
|
|
@@ -880,10 +847,10 @@ const expected = `
|
|
|
880
847
|
expect(actual).to.equal(expected)
|
|
881
848
|
```
|
|
882
849
|
|
|
883
|
-
###
|
|
850
|
+
### newNounForm
|
|
884
851
|
|
|
885
852
|
```ts
|
|
886
|
-
const
|
|
853
|
+
const newNounForm: (locale: string, forms: Partial<Record<Intl.LDMLPluralRule, string>>) => (value: number) => string;
|
|
887
854
|
```
|
|
888
855
|
|
|
889
856
|
Creates a function that returns the appropriate noun form based on a numeric value using `Intl.PluralRules`.
|
|
@@ -914,14 +881,14 @@ A function that takes a numeric value and returns the appropriate noun form.
|
|
|
914
881
|
#### Usage Examples
|
|
915
882
|
|
|
916
883
|
```ts
|
|
917
|
-
const auto =
|
|
884
|
+
const auto = newNounForm('pl', { one: 'auto', few: 'auta', other: 'aut' })
|
|
918
885
|
|
|
919
886
|
expect(auto(0)).to.equal('aut')
|
|
920
887
|
expect(auto(1)).to.equal('auto')
|
|
921
888
|
expect(auto(17)).to.equal('aut')
|
|
922
889
|
expect(auto(42)).to.equal('auta')
|
|
923
890
|
|
|
924
|
-
const car =
|
|
891
|
+
const car = newNounForm('en', { one: 'car', other: 'cars' })
|
|
925
892
|
|
|
926
893
|
expect(car(0)).to.equal('cars')
|
|
927
894
|
expect(car(1)).to.equal('car')
|
|
@@ -929,13 +896,13 @@ expect(car(17)).to.equal('cars')
|
|
|
929
896
|
expect(car(42)).to.equal('cars')
|
|
930
897
|
```
|
|
931
898
|
|
|
932
|
-
###
|
|
899
|
+
### newTokenizer
|
|
933
900
|
|
|
934
901
|
```ts
|
|
935
|
-
const
|
|
902
|
+
const newTokenizer: <M, T>(decorator: (chunk: string, metadata?: M) => T, ...specs: [M, string | RegExp][]) => (code: string) => T[];
|
|
936
903
|
```
|
|
937
904
|
|
|
938
|
-
A helper for building simple tokenizers (see also [`
|
|
905
|
+
A helper for building simple tokenizers (see also [`nanolightTs`](#nanolightTs)).
|
|
939
906
|
|
|
940
907
|
#### decorator
|
|
941
908
|
|
|
@@ -1022,7 +989,7 @@ expect(pick(ref, ['a', 'b'])).to.deep.equal({ a: 42, b: '42' })
|
|
|
1022
989
|
### rwd
|
|
1023
990
|
|
|
1024
991
|
```ts
|
|
1025
|
-
const rwd: (root: CRoot, selector: string,
|
|
992
|
+
const rwd: (root: CRoot, selector: string, cellWidthPx: number, cellHeightPx: number, ...specs: [number, number?, number?][]) => void;
|
|
1026
993
|
```
|
|
1027
994
|
|
|
1028
995
|
A responsive web design helper that generates CSS rules for a grid-like layout.
|
|
@@ -1035,18 +1002,18 @@ The CSS root object to populate (see [`c`](#c)).
|
|
|
1035
1002
|
|
|
1036
1003
|
The CSS selector for the grid item.
|
|
1037
1004
|
|
|
1038
|
-
####
|
|
1005
|
+
#### cellWidthPx
|
|
1039
1006
|
|
|
1040
1007
|
The base cell width in pixels.
|
|
1041
1008
|
|
|
1042
|
-
####
|
|
1009
|
+
#### cellHeightPx
|
|
1043
1010
|
|
|
1044
1011
|
The base cell height in pixels.
|
|
1045
1012
|
|
|
1046
1013
|
#### specs
|
|
1047
1014
|
|
|
1048
1015
|
An array of breakpoint specifications, each a tuple of:
|
|
1049
|
-
- `
|
|
1016
|
+
- `maxWidth`: maximum number of cells per row (defines the viewport breakpoint).
|
|
1050
1017
|
- `width` (optional, default `1`): number of horizontal cells the element spans.
|
|
1051
1018
|
- `height` (optional, default `1`): number of vertical cells the element spans.
|
|
1052
1019
|
|
|
@@ -1103,13 +1070,13 @@ expect(style).to.deep.equal({
|
|
|
1103
1070
|
const s: {
|
|
1104
1071
|
<T extends keyof SVGElementTagNameMap>(tag: T, ...args1: HArgs1[]): SVGElementTagNameMap[T];
|
|
1105
1072
|
<N extends Node>(node: N, ...args1: HArgs1[]): N;
|
|
1106
|
-
(
|
|
1073
|
+
(tagOrNode: string | Node, ...args1: HArgs1[]): Node;
|
|
1107
1074
|
};
|
|
1108
1075
|
```
|
|
1109
1076
|
|
|
1110
1077
|
A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also [`h`](#h)).
|
|
1111
1078
|
|
|
1112
|
-
####
|
|
1079
|
+
#### tagOrNode
|
|
1113
1080
|
|
|
1114
1081
|
If a `string`, it is treated as the tag name for a new element.
|
|
1115
1082
|
If a `Node`, that node is modified in place.
|
|
@@ -1128,10 +1095,10 @@ Additional arguments processed as follows:
|
|
|
1128
1095
|
|
|
1129
1096
|
The created or modified `SVGElement`.
|
|
1130
1097
|
|
|
1131
|
-
###
|
|
1098
|
+
### svgUse
|
|
1132
1099
|
|
|
1133
1100
|
```ts
|
|
1134
|
-
const
|
|
1101
|
+
const svgUse: (id: string, ...args: HArgs1[]) => SVGSVGElement;
|
|
1135
1102
|
```
|
|
1136
1103
|
|
|
1137
1104
|
Shorthand for creating an SVG element with a `<use>` child referencing an icon by ID.
|
|
@@ -1150,10 +1117,10 @@ Additional arguments passed to the outer `<svg>` element.
|
|
|
1150
1117
|
|
|
1151
1118
|
An `SVGSVGElement` containing a `<use>` element.
|
|
1152
1119
|
|
|
1153
|
-
###
|
|
1120
|
+
### uuidV1
|
|
1154
1121
|
|
|
1155
1122
|
```ts
|
|
1156
|
-
const
|
|
1123
|
+
const uuidV1: (date?: Date, node?: string) => string;
|
|
1157
1124
|
```
|
|
1158
1125
|
|
|
1159
1126
|
Generates a UUID v1 (time-based) identifier.
|
|
@@ -1175,7 +1142,7 @@ A UUID v1 `string` in the standard format `xxxxxxxx-xxxx-1xxx-xxxx-xxxxxxxxxxxx`
|
|
|
1175
1142
|
|
|
1176
1143
|
```ts
|
|
1177
1144
|
for (let i = 1; i <= 22136; ++i) {
|
|
1178
|
-
const uuid =
|
|
1145
|
+
const uuid = uuidV1()
|
|
1179
1146
|
|
|
1180
1147
|
if (i === 1) {
|
|
1181
1148
|
expect(uuid.split('-')[3]).to.equal('8001')
|
|
@@ -1206,10 +1173,10 @@ for (let i = 1; i <= 22136; ++i) {
|
|
|
1206
1173
|
}
|
|
1207
1174
|
}
|
|
1208
1175
|
|
|
1209
|
-
expect(
|
|
1210
|
-
expect(
|
|
1176
|
+
expect(uuidV1(new Date(), '000123456789abc').split('-')[4]).to.equal('123456789abc')
|
|
1177
|
+
expect(uuidV1(new Date(), '123456789').split('-')[4]).to.equal('000123456789')
|
|
1211
1178
|
|
|
1212
|
-
expect(
|
|
1179
|
+
expect(uuidV1(new Date(323325000000)).startsWith('c1399400-9a71-11bd')).to.be.true
|
|
1213
1180
|
```
|
|
1214
1181
|
|
|
1215
1182
|
### vivify
|