@jackens/nnn 2026.4.14 → 2026.4.15
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/package.json +1 -1
- package/readme.md +226 -189
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# nnn
|
|
2
2
|
|
|
3
|
-
A collection of Jackens’ JavaScript helper utilities (version: `2026.4.
|
|
3
|
+
A collection of Jackens’ JavaScript helper utilities (version: `2026.4.15`).
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -19,30 +19,29 @@ npm i @jackens/nnn
|
|
|
19
19
|
```js
|
|
20
20
|
import {
|
|
21
21
|
c,
|
|
22
|
-
csvParse,
|
|
23
|
-
fixPlTypography,
|
|
24
|
-
h,
|
|
25
|
-
hasOwn,
|
|
26
|
-
isArray,
|
|
27
|
-
isFiniteNumber,
|
|
28
|
-
isInteger,
|
|
29
|
-
isNumber,
|
|
30
|
-
isRecord,
|
|
31
|
-
isString,
|
|
32
|
-
jsOnParse,
|
|
33
|
-
monokai,
|
|
34
|
-
nanolightTs,
|
|
35
|
-
newEscape,
|
|
36
|
-
newNounForm,
|
|
37
|
-
newTokenizer,
|
|
38
|
-
omit,
|
|
39
|
-
pick,
|
|
40
|
-
rwd,
|
|
41
|
-
s,
|
|
42
|
-
svgUse,
|
|
43
|
-
uuidV1,
|
|
44
|
-
vivify,
|
|
45
|
-
|
|
22
|
+
csvParse,
|
|
23
|
+
fixPlTypography,
|
|
24
|
+
h,
|
|
25
|
+
hasOwn,
|
|
26
|
+
isArray,
|
|
27
|
+
isFiniteNumber,
|
|
28
|
+
isInteger,
|
|
29
|
+
isNumber,
|
|
30
|
+
isRecord,
|
|
31
|
+
isString,
|
|
32
|
+
jsOnParse,
|
|
33
|
+
monokai,
|
|
34
|
+
nanolightTs,
|
|
35
|
+
newEscape,
|
|
36
|
+
newNounForm,
|
|
37
|
+
newTokenizer,
|
|
38
|
+
omit,
|
|
39
|
+
pick,
|
|
40
|
+
rwd,
|
|
41
|
+
s,
|
|
42
|
+
svgUse,
|
|
43
|
+
uuidV1,
|
|
44
|
+
vivify,
|
|
46
45
|
} from '@jackens/nnn' // or './node_modules/@jackens/nnn/nnn.js'
|
|
47
46
|
```
|
|
48
47
|
|
|
@@ -216,14 +215,16 @@ A CSS string representing the compiled rules.
|
|
|
216
215
|
#### Usage Examples
|
|
217
216
|
|
|
218
217
|
```ts
|
|
219
|
-
const actual1 = c(
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
218
|
+
const actual1 = c(
|
|
219
|
+
{
|
|
220
|
+
a: {
|
|
221
|
+
color: 'red',
|
|
222
|
+
margin: 1,
|
|
223
|
+
'.c': { margin: 2, padding: 2 },
|
|
224
|
+
padding: 1,
|
|
225
|
+
},
|
|
225
226
|
},
|
|
226
|
-
|
|
227
|
+
)
|
|
227
228
|
|
|
228
229
|
const expected1 = `
|
|
229
230
|
a{
|
|
@@ -240,16 +241,18 @@ a{
|
|
|
240
241
|
|
|
241
242
|
expect(actual1).to.equal(expected1)
|
|
242
243
|
|
|
243
|
-
const actual2 = c(
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
244
|
+
const actual2 = c(
|
|
245
|
+
{
|
|
246
|
+
a: {
|
|
247
|
+
'.b': {
|
|
248
|
+
color: 'red',
|
|
249
|
+
margin: 1,
|
|
250
|
+
'.c': { margin: 2, padding: 2 },
|
|
251
|
+
padding: 1,
|
|
252
|
+
},
|
|
250
253
|
},
|
|
251
254
|
},
|
|
252
|
-
|
|
255
|
+
)
|
|
253
256
|
|
|
254
257
|
const expected2 = `
|
|
255
258
|
a.b{
|
|
@@ -266,34 +269,36 @@ a.b{
|
|
|
266
269
|
|
|
267
270
|
expect(actual2).to.equal(expected2)
|
|
268
271
|
|
|
269
|
-
const actual3 = c(
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
const actual3 = c(
|
|
273
|
+
{
|
|
274
|
+
'@font-face$$1': {
|
|
275
|
+
fontFamily: 'Jackens',
|
|
276
|
+
src$$1: 'url(otf/jackens.otf)',
|
|
277
|
+
src$$2: "url(otf/jackens.otf) format('opentype')," +
|
|
274
278
|
"url(svg/jackens.svg) format('svg')",
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
279
|
+
font_weight: 'normal',
|
|
280
|
+
'font-style': 'normal',
|
|
281
|
+
},
|
|
282
|
+
'@font-face$$2': {
|
|
283
|
+
font_family: 'C64',
|
|
284
|
+
src: 'url(fonts/C64_Pro_Mono-STYLE.woff)',
|
|
285
|
+
},
|
|
286
|
+
'@keyframes spin': {
|
|
287
|
+
'0%': { transform: 'rotate(0deg)' },
|
|
288
|
+
'100%': { transform: 'rotate(360deg)' },
|
|
289
|
+
},
|
|
290
|
+
div: {
|
|
291
|
+
border: 'solid red 1px',
|
|
292
|
+
'.c1': { 'background-color': '#000' },
|
|
293
|
+
' .c1': { background_color: 'black' },
|
|
294
|
+
'.c2': { backgroundColor: 'rgb(0,0,0)' },
|
|
295
|
+
},
|
|
296
|
+
'@media(min-width:200px)': {
|
|
297
|
+
div: { margin: 0, padding: 0 },
|
|
298
|
+
span: { color: '#000' },
|
|
299
|
+
},
|
|
295
300
|
},
|
|
296
|
-
|
|
301
|
+
)
|
|
297
302
|
|
|
298
303
|
const expected3 = `
|
|
299
304
|
@font-face{
|
|
@@ -339,16 +344,18 @@ div.c2{
|
|
|
339
344
|
|
|
340
345
|
expect(actual3).to.equal(expected3)
|
|
341
346
|
|
|
342
|
-
const actual4 = c(
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
347
|
+
const actual4 = c(
|
|
348
|
+
{
|
|
349
|
+
a: {
|
|
350
|
+
'.b,.c': {
|
|
351
|
+
margin: 1,
|
|
352
|
+
'.d': {
|
|
353
|
+
margin: 2,
|
|
354
|
+
},
|
|
348
355
|
},
|
|
349
356
|
},
|
|
350
357
|
},
|
|
351
|
-
|
|
358
|
+
)
|
|
352
359
|
|
|
353
360
|
const expected4 = `
|
|
354
361
|
a.b,a.c{
|
|
@@ -360,14 +367,16 @@ a.b.d,a.c.d{
|
|
|
360
367
|
|
|
361
368
|
expect(actual4).to.equal(expected4)
|
|
362
369
|
|
|
363
|
-
const actual5 = c(
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
370
|
+
const actual5 = c(
|
|
371
|
+
{
|
|
372
|
+
'.b,.c': {
|
|
373
|
+
margin: 1,
|
|
374
|
+
'.d': {
|
|
375
|
+
margin: 2,
|
|
376
|
+
},
|
|
368
377
|
},
|
|
369
378
|
},
|
|
370
|
-
|
|
379
|
+
)
|
|
371
380
|
|
|
372
381
|
const expected5 = `
|
|
373
382
|
.b,.c{
|
|
@@ -379,14 +388,16 @@ const expected5 = `
|
|
|
379
388
|
|
|
380
389
|
expect(actual5).to.equal(expected5)
|
|
381
390
|
|
|
382
|
-
const actual6 = c(
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
391
|
+
const actual6 = c(
|
|
392
|
+
{
|
|
393
|
+
'.a,.b': {
|
|
394
|
+
margin: 1,
|
|
395
|
+
'.c,.d': {
|
|
396
|
+
margin: 2,
|
|
397
|
+
},
|
|
387
398
|
},
|
|
388
399
|
},
|
|
389
|
-
|
|
400
|
+
)
|
|
390
401
|
|
|
391
402
|
const expected6 = `
|
|
392
403
|
.a,.b{
|
|
@@ -436,11 +447,13 @@ yyy",zzz
|
|
|
436
447
|
|
|
437
448
|
`
|
|
438
449
|
|
|
439
|
-
expect(csvParse(text)).to.deep.equal(
|
|
440
|
-
[
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
]
|
|
450
|
+
expect(csvParse(text)).to.deep.equal(
|
|
451
|
+
[
|
|
452
|
+
['aaa\n"aaa"\naaa', 'bbb', 'ccc,ccc'],
|
|
453
|
+
['xxx,xxx', 'yyy\nyyy', 'zzz'],
|
|
454
|
+
[' 42 ', '42', ' 17'],
|
|
455
|
+
],
|
|
456
|
+
)
|
|
444
457
|
```
|
|
445
458
|
|
|
446
459
|
### fixPlTypography
|
|
@@ -922,24 +935,26 @@ const actual1 = jsOnParse(handlers, `[
|
|
|
922
935
|
}
|
|
923
936
|
]`)
|
|
924
937
|
|
|
925
|
-
expect(actual1).to.deep.equal(
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
938
|
+
expect(actual1).to.deep.equal(
|
|
939
|
+
[
|
|
940
|
+
3,
|
|
941
|
+
'Hello World!',
|
|
942
|
+
{
|
|
943
|
+
nested: 'Hello nested World!',
|
|
944
|
+
one: 1,
|
|
945
|
+
two: 2,
|
|
946
|
+
},
|
|
947
|
+
'bar',
|
|
948
|
+
{
|
|
949
|
+
$foo: [
|
|
950
|
+
'The parent object does not have ' +
|
|
951
|
+
'exactly one property!',
|
|
952
|
+
],
|
|
953
|
+
one: 1,
|
|
954
|
+
two: 2,
|
|
955
|
+
},
|
|
956
|
+
],
|
|
957
|
+
)
|
|
943
958
|
|
|
944
959
|
const actual2 = jsOnParse(
|
|
945
960
|
{ $notFunc: 'handler not being a function' } as any,
|
|
@@ -1000,30 +1015,32 @@ const codeJs =
|
|
|
1000
1015
|
'const answerToLifeTheUniverseAndEverything = ' +
|
|
1001
1016
|
"{ 42: 42 }['42'] /* 42 */"
|
|
1002
1017
|
|
|
1003
|
-
expect(nanolightTs(codeJs)).to.deep.equal(
|
|
1004
|
-
[
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1018
|
+
expect(nanolightTs(codeJs)).to.deep.equal(
|
|
1019
|
+
[
|
|
1020
|
+
['span', { class: 'keyword-1' }, 'const'],
|
|
1021
|
+
' ',
|
|
1022
|
+
['span',
|
|
1023
|
+
{ class: 'identifier-4' },
|
|
1024
|
+
'answerToLifeTheUniverseAndEverything',
|
|
1025
|
+
],
|
|
1026
|
+
' ',
|
|
1027
|
+
['span', { class: 'operator' }, '='],
|
|
1028
|
+
' ',
|
|
1029
|
+
['span', { class: 'punctuation' }, '{'],
|
|
1030
|
+
' ',
|
|
1031
|
+
['span', { class: 'number' }, '42'],
|
|
1032
|
+
['span', { class: 'operator' }, ':'],
|
|
1033
|
+
' ',
|
|
1034
|
+
['span', { class: 'number' }, '42'],
|
|
1035
|
+
' ',
|
|
1036
|
+
['span', { class: 'punctuation' }, '}'],
|
|
1037
|
+
['span', { class: 'punctuation' }, '['],
|
|
1038
|
+
['span', { class: 'string' }, "'42'"],
|
|
1039
|
+
['span', { class: 'punctuation' }, ']'],
|
|
1040
|
+
' ',
|
|
1041
|
+
['span', { class: 'comment' }, '/* 42 */'],
|
|
1009
1042
|
],
|
|
1010
|
-
|
|
1011
|
-
['span', { class: 'operator' }, '='],
|
|
1012
|
-
' ',
|
|
1013
|
-
['span', { class: 'punctuation' }, '{'],
|
|
1014
|
-
' ',
|
|
1015
|
-
['span', { class: 'number' }, '42'],
|
|
1016
|
-
['span', { class: 'operator' }, ':'],
|
|
1017
|
-
' ',
|
|
1018
|
-
['span', { class: 'number' }, '42'],
|
|
1019
|
-
' ',
|
|
1020
|
-
['span', { class: 'punctuation' }, '}'],
|
|
1021
|
-
['span', { class: 'punctuation' }, '['],
|
|
1022
|
-
['span', { class: 'string' }, "'42'"],
|
|
1023
|
-
['span', { class: 'punctuation' }, ']'],
|
|
1024
|
-
' ',
|
|
1025
|
-
['span', { class: 'comment' }, '/* 42 */'],
|
|
1026
|
-
])
|
|
1043
|
+
)
|
|
1027
1044
|
```
|
|
1028
1045
|
|
|
1029
1046
|
### newEscape
|
|
@@ -1066,23 +1083,27 @@ const sql = newEscape(escapeFn)
|
|
|
1066
1083
|
const actual = sql`
|
|
1067
1084
|
SELECT *
|
|
1068
1085
|
FROM table_name
|
|
1069
|
-
WHERE column_name IN (
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1086
|
+
WHERE column_name IN (
|
|
1087
|
+
${[
|
|
1088
|
+
true,
|
|
1089
|
+
null,
|
|
1090
|
+
undefined,
|
|
1091
|
+
NaN,
|
|
1092
|
+
Infinity,
|
|
1093
|
+
42,
|
|
1094
|
+
'42',
|
|
1095
|
+
"4'2",
|
|
1096
|
+
/42/,
|
|
1097
|
+
new Date(323325000000),
|
|
1098
|
+
]}
|
|
1099
|
+
)`
|
|
1081
1100
|
|
|
1082
1101
|
const expected = `
|
|
1083
1102
|
SELECT *
|
|
1084
1103
|
FROM table_name
|
|
1085
|
-
WHERE column_name IN (
|
|
1104
|
+
WHERE column_name IN (
|
|
1105
|
+
b'1', NULL, NULL, NULL, NULL, 42, '42', '4''2', NULL, '1980-03-31 04:30:00'
|
|
1106
|
+
)`
|
|
1086
1107
|
|
|
1087
1108
|
expect(actual).to.equal(expected)
|
|
1088
1109
|
```
|
|
@@ -1206,15 +1227,17 @@ const tokenizer1 = newTokenizer(
|
|
|
1206
1227
|
)
|
|
1207
1228
|
const result1 = tokenizer1('if "hello" else "world"')
|
|
1208
1229
|
|
|
1209
|
-
expect(result1).to.deep.equal(
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1230
|
+
expect(result1).to.deep.equal(
|
|
1231
|
+
[
|
|
1232
|
+
{ chunk: 'if', metadata: 'keyword' },
|
|
1233
|
+
{ chunk: ' ', metadata: undefined },
|
|
1234
|
+
{ chunk: '"hello"', metadata: 'string' },
|
|
1235
|
+
{ chunk: ' ', metadata: undefined },
|
|
1236
|
+
{ chunk: 'else', metadata: 'keyword' },
|
|
1237
|
+
{ chunk: ' ', metadata: undefined },
|
|
1238
|
+
{ chunk: '"world"', metadata: 'string' },
|
|
1239
|
+
],
|
|
1240
|
+
)
|
|
1218
1241
|
|
|
1219
1242
|
const tokenizer2 = newTokenizer(
|
|
1220
1243
|
(chunk, metadata) => `${metadata}:${chunk}`,
|
|
@@ -1223,13 +1246,15 @@ const tokenizer2 = newTokenizer(
|
|
|
1223
1246
|
)
|
|
1224
1247
|
const result2 = tokenizer2('aBEGINbENDc')
|
|
1225
1248
|
|
|
1226
|
-
expect(result2).to.deep.equal(
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1249
|
+
expect(result2).to.deep.equal(
|
|
1250
|
+
[
|
|
1251
|
+
'undefined:a',
|
|
1252
|
+
'tag:BEGIN',
|
|
1253
|
+
'undefined:b',
|
|
1254
|
+
'end:END',
|
|
1255
|
+
'undefined:c',
|
|
1256
|
+
],
|
|
1257
|
+
)
|
|
1233
1258
|
|
|
1234
1259
|
const tokenizer3 = newTokenizer(
|
|
1235
1260
|
(chunk) => chunk,
|
|
@@ -1245,10 +1270,12 @@ const tokenizer4 = newTokenizer(
|
|
|
1245
1270
|
)
|
|
1246
1271
|
const result4 = tokenizer4('test here')
|
|
1247
1272
|
|
|
1248
|
-
expect(result4).to.deep.equal(
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1273
|
+
expect(result4).to.deep.equal(
|
|
1274
|
+
[
|
|
1275
|
+
{ chunk: 'test', metadata: 'start' },
|
|
1276
|
+
{ chunk: ' here', metadata: undefined },
|
|
1277
|
+
],
|
|
1278
|
+
)
|
|
1252
1279
|
|
|
1253
1280
|
const tokenizer5 = newTokenizer(
|
|
1254
1281
|
(chunk, metadata) => metadata,
|
|
@@ -1722,48 +1749,58 @@ const ref: any = {}
|
|
|
1722
1749
|
|
|
1723
1750
|
vivify(ref).one.two[3][4]
|
|
1724
1751
|
|
|
1725
|
-
expect(ref).to.deep.equal(
|
|
1726
|
-
|
|
1727
|
-
|
|
1752
|
+
expect(ref).to.deep.equal(
|
|
1753
|
+
{
|
|
1754
|
+
one: {
|
|
1755
|
+
two: [undefined, undefined, undefined, []],
|
|
1756
|
+
},
|
|
1728
1757
|
},
|
|
1729
|
-
|
|
1758
|
+
)
|
|
1730
1759
|
|
|
1731
1760
|
vivify(ref).one.two[3][4] = 5
|
|
1732
1761
|
|
|
1733
|
-
expect(ref).to.deep.equal(
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1762
|
+
expect(ref).to.deep.equal(
|
|
1763
|
+
{
|
|
1764
|
+
one: {
|
|
1765
|
+
two: [
|
|
1766
|
+
undefined,
|
|
1767
|
+
undefined,
|
|
1768
|
+
undefined,
|
|
1769
|
+
[undefined, undefined, undefined, undefined, 5],
|
|
1770
|
+
],
|
|
1771
|
+
},
|
|
1741
1772
|
},
|
|
1742
|
-
|
|
1773
|
+
)
|
|
1743
1774
|
|
|
1744
1775
|
vivify(ref).one.two[3].length = 1
|
|
1745
1776
|
|
|
1746
|
-
expect(ref).to.deep.equal(
|
|
1747
|
-
|
|
1748
|
-
|
|
1777
|
+
expect(ref).to.deep.equal(
|
|
1778
|
+
{
|
|
1779
|
+
one: {
|
|
1780
|
+
two: [undefined, undefined, undefined, [undefined]],
|
|
1781
|
+
},
|
|
1749
1782
|
},
|
|
1750
|
-
|
|
1783
|
+
)
|
|
1751
1784
|
|
|
1752
1785
|
vivify(ref).one.two[3] = 4
|
|
1753
1786
|
|
|
1754
|
-
expect(ref).to.deep.equal(
|
|
1755
|
-
|
|
1756
|
-
|
|
1787
|
+
expect(ref).to.deep.equal(
|
|
1788
|
+
{
|
|
1789
|
+
one: {
|
|
1790
|
+
two: [undefined, undefined, undefined, 4],
|
|
1791
|
+
},
|
|
1757
1792
|
},
|
|
1758
|
-
|
|
1793
|
+
)
|
|
1759
1794
|
|
|
1760
1795
|
expect(vivify(ref).one.two.length).to.equal(4)
|
|
1761
1796
|
|
|
1762
|
-
expect(ref).to.deep.equal(
|
|
1763
|
-
|
|
1764
|
-
|
|
1797
|
+
expect(ref).to.deep.equal(
|
|
1798
|
+
{
|
|
1799
|
+
one: {
|
|
1800
|
+
two: [undefined, undefined, undefined, 4],
|
|
1801
|
+
},
|
|
1765
1802
|
},
|
|
1766
|
-
|
|
1803
|
+
)
|
|
1767
1804
|
|
|
1768
1805
|
vivify(ref).one.two = 3
|
|
1769
1806
|
|