@jackens/nnn 2026.2.25 → 2026.2.27
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 +3 -25
- package/nnn.js +17 -21
- package/package.json +1 -1
- package/readme.md +46 -52
package/nnn.d.ts
CHANGED
|
@@ -253,40 +253,18 @@ export declare const monokai: CRoot;
|
|
|
253
253
|
* An array of {@link HArgs1} elements suitable for rendering with {@link h}.
|
|
254
254
|
*/
|
|
255
255
|
export declare const nanolightTs: (code: string) => HArgs1[];
|
|
256
|
-
/**
|
|
257
|
-
* A map from value constructors (or `null`/`undefined`) to escape functions.
|
|
258
|
-
*
|
|
259
|
-
* Used by {@link escapeValues} and {@link newEscape}.
|
|
260
|
-
*/
|
|
261
|
-
export type EscapeMap = Map<unknown, (value?: unknown) => string>;
|
|
262
|
-
/**
|
|
263
|
-
* Escapes an array of values using the provided escape map.
|
|
264
|
-
*
|
|
265
|
-
* @param escapeMap
|
|
266
|
-
*
|
|
267
|
-
* A map where keys are constructors (e.g., `String`, `Number`) and values are escape functions.
|
|
268
|
-
*
|
|
269
|
-
* @param values
|
|
270
|
-
*
|
|
271
|
-
* The array of values to escape.
|
|
272
|
-
*
|
|
273
|
-
* @returns
|
|
274
|
-
*
|
|
275
|
-
* An array of escaped strings.
|
|
276
|
-
*/
|
|
277
|
-
export declare const escapeValues: (escapeMap: EscapeMap, values: unknown[]) => string[];
|
|
278
256
|
/**
|
|
279
257
|
* Creates a tag function for escaping interpolated values in template literals.
|
|
280
258
|
*
|
|
281
|
-
* @param
|
|
259
|
+
* @param escapeFn
|
|
282
260
|
*
|
|
283
|
-
* A
|
|
261
|
+
* A function that takes a value and returns its escaped string representation.
|
|
284
262
|
*
|
|
285
263
|
* @returns
|
|
286
264
|
*
|
|
287
265
|
* A tag function that escapes interpolated values using the provided escape map.
|
|
288
266
|
*/
|
|
289
|
-
export declare const newEscape: (
|
|
267
|
+
export declare const newEscape: (escapeFn: (value: any) => string) => (template: TemplateStringsArray, ...values: unknown[]) => string;
|
|
290
268
|
/**
|
|
291
269
|
* Creates a function that returns the appropriate noun form based on a numeric value using `Intl.PluralRules`.
|
|
292
270
|
*
|
package/nnn.js
CHANGED
|
@@ -298,8 +298,7 @@ var PUNCTUATION = "punctuation";
|
|
|
298
298
|
var STRING = "string";
|
|
299
299
|
var nanolightTs = /* @__PURE__ */ newTokenizer((chunk, name) => name != null ? ["span", { class: name }, chunk] : chunk, [COMMENT, /\/\*.*?\*\//s], [COMMENT, /(?<!\\)\/\/.*?(?=\n)/], [STRING, /".*?"/], [STRING, /'.*?'/], [STRING, /`.*?`/s], [STRING, /\/[^\s]*[^\\]\/[dgimsuvy]*/], [NUMBER, /0b[01_]+/], [NUMBER, /0o[01234567_]+/], [NUMBER, /0x[\dabcdef_]+/], [NUMBER, /\d[\d_]*(\.[\d_]+)?(e[+-]?[\d_]+)?/], [OPERATOR, "!"], [OPERATOR, "!="], [OPERATOR, "!=="], [OPERATOR, "%"], [OPERATOR, "%="], [OPERATOR, "&&"], [OPERATOR, "&&="], [OPERATOR, "&"], [OPERATOR, "&="], [OPERATOR, "*"], [OPERATOR, "**"], [OPERATOR, "**="], [OPERATOR, "*="], [OPERATOR, "+"], [OPERATOR, "++"], [OPERATOR, "+="], [OPERATOR, "-"], [OPERATOR, "--"], [OPERATOR, "-="], [OPERATOR, "..."], [OPERATOR, "/"], [OPERATOR, "/="], [OPERATOR, ":"], [OPERATOR, "<"], [OPERATOR, "<<"], [OPERATOR, "<<="], [OPERATOR, "<="], [OPERATOR, "="], [OPERATOR, "=="], [OPERATOR, "==="], [OPERATOR, "=>"], [OPERATOR, ">"], [OPERATOR, ">="], [OPERATOR, ">>"], [OPERATOR, ">>="], [OPERATOR, ">>>"], [OPERATOR, ">>>="], [OPERATOR, "?"], [OPERATOR, "?"], [OPERATOR, "??"], [OPERATOR, "??="], [OPERATOR, "^"], [OPERATOR, "^="], [OPERATOR, "|"], [OPERATOR, "|="], [OPERATOR, "||"], [OPERATOR, "||="], [OPERATOR, "~"], [OPERATOR, "~="], [OPERATOR, /(?<=\s):/], [PUNCTUATION, "("], [PUNCTUATION, ")"], [PUNCTUATION, ","], [PUNCTUATION, "."], [PUNCTUATION, ":"], [PUNCTUATION, ";"], [PUNCTUATION, "?."], [PUNCTUATION, "["], [PUNCTUATION, "]"], [PUNCTUATION, "{"], [PUNCTUATION, "}"], [KEYWORD_1, "as"], [KEYWORD_1, "async"], [KEYWORD_1, "await"], [KEYWORD_1, "break"], [KEYWORD_1, "case"], [KEYWORD_1, "catch"], [KEYWORD_1, "class"], [KEYWORD_1, "const"], [KEYWORD_1, "continue"], [KEYWORD_1, "debugger"], [KEYWORD_1, "default"], [KEYWORD_1, "delete"], [KEYWORD_1, "do"], [KEYWORD_1, "else"], [KEYWORD_1, "export"], [KEYWORD_1, "extends"], [KEYWORD_1, "finally"], [KEYWORD_1, "for"], [KEYWORD_1, "from"], [KEYWORD_1, "function"], [KEYWORD_1, "function*"], [KEYWORD_1, "goto"], [KEYWORD_1, "if"], [KEYWORD_1, "import"], [KEYWORD_1, "in"], [KEYWORD_1, "instanceof"], [KEYWORD_1, "is"], [KEYWORD_1, "keyof"], [KEYWORD_1, "let"], [KEYWORD_1, "new"], [KEYWORD_1, "of"], [KEYWORD_1, "package"], [KEYWORD_1, "return"], [KEYWORD_1, "super"], [KEYWORD_1, "switch"], [KEYWORD_1, "this"], [KEYWORD_1, "throw"], [KEYWORD_1, "try"], [KEYWORD_1, "type"], [KEYWORD_1, "typeof"], [KEYWORD_1, "var"], [KEYWORD_1, "void"], [KEYWORD_1, "while"], [KEYWORD_1, "with"], [KEYWORD_1, "yield"], [KEYWORD_1, "yield*"], [KEYWORD_2, "false"], [KEYWORD_2, "Infinity"], [KEYWORD_2, "NaN"], [KEYWORD_2, "null"], [KEYWORD_2, "true"], [KEYWORD_2, "undefined"], [KEYWORD_3, "any"], [KEYWORD_3, "bigint"], [KEYWORD_3, "boolean"], [KEYWORD_3, "eval"], [KEYWORD_3, "number"], [KEYWORD_3, "string"], [KEYWORD_3, "symbol"], [KEYWORD_3, "unknown"], [IDENTIFIER_1, /[\p{Lu}_$][\p{Lu}\d_$]*/u], [IDENTIFIER_2, /[\p{L}_$][\p{L}\d_$]*(?=[(`])/u], [IDENTIFIER_3, /\p{Lu}[\p{L}\d_$]*/u], [IDENTIFIER_4, /[\p{L}_$][\p{L}\d_$]*/u]);
|
|
300
300
|
// src/nnn/newEscape.ts
|
|
301
|
-
var
|
|
302
|
-
var newEscape = (escapeMap) => (template, ...values) => String.raw(template, ...escapeValues(escapeMap, values));
|
|
301
|
+
var newEscape = (escapeFn) => (template, ...values) => String.raw(template, ...values.map(escapeFn));
|
|
303
302
|
// src/nnn/newNounForm.ts
|
|
304
303
|
var PLURAL_RULES = {};
|
|
305
304
|
var newNounForm = (locale, forms) => (value) => forms[(PLURAL_RULES[locale] ??= new Intl.PluralRules(locale)).select(value)] ?? forms.other ?? "";
|
|
@@ -311,24 +310,22 @@ var pick = (ref, keys) => Object.fromEntries(Object.entries(ref).filter(([key])
|
|
|
311
310
|
var ARRAY_INDEX_REGEXP = /^(0|[1-9]\d*)$/;
|
|
312
311
|
var isObject = (ref) => typeof ref === "object";
|
|
313
312
|
var getTarget = (parent, parentKey, key) => parent[parentKey] ??= isString(key) && ARRAY_INDEX_REGEXP.test(key) ? [] : {};
|
|
314
|
-
var _vivify = (parent, parentKey) => {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}) : parent?.[parentKey];
|
|
331
|
-
};
|
|
313
|
+
var _vivify = (parent, parentKey) => new Proxy(parent, {
|
|
314
|
+
get(_, key) {
|
|
315
|
+
const target = getTarget(parent, parentKey, key);
|
|
316
|
+
const value = target[key];
|
|
317
|
+
return isString(key) && isObject(target) && (value == null || isObject(value)) ? _vivify(target, key) : value;
|
|
318
|
+
},
|
|
319
|
+
set(_, key, value) {
|
|
320
|
+
const target = getTarget(parent, parentKey, key);
|
|
321
|
+
target[key] = value;
|
|
322
|
+
return true;
|
|
323
|
+
},
|
|
324
|
+
deleteProperty(_, key) {
|
|
325
|
+
const target = getTarget(parent, parentKey, key);
|
|
326
|
+
return delete target[key];
|
|
327
|
+
}
|
|
328
|
+
});
|
|
332
329
|
var vivify = (ref) => _vivify({ _: ref }, "_");
|
|
333
330
|
|
|
334
331
|
// src/nnn/rwd.ts
|
|
@@ -386,7 +383,6 @@ export {
|
|
|
386
383
|
hasOwn,
|
|
387
384
|
h,
|
|
388
385
|
fixPlTypography,
|
|
389
|
-
escapeValues,
|
|
390
386
|
csvParse,
|
|
391
387
|
c
|
|
392
388
|
};
|
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.2.
|
|
3
|
+
A collection of Jackens’ JavaScript helper utilities (version: `2026.2.27`).
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -20,7 +20,6 @@ npm i @jackens/nnn
|
|
|
20
20
|
import {
|
|
21
21
|
c,
|
|
22
22
|
csvParse,
|
|
23
|
-
escapeValues,
|
|
24
23
|
fixPlTypography,
|
|
25
24
|
h,
|
|
26
25
|
hasOwn,
|
|
@@ -50,12 +49,10 @@ import {
|
|
|
50
49
|
|
|
51
50
|
- [`CNode`](#CNode): Represents a CSS rule node for the [`c`](#c) helper. Keys are CSS properties or nested selectors.
|
|
52
51
|
- [`CRoot`](#CRoot): Represents the root CSS object for the [`c`](#c) helper. Keys are top-level selectors or at-rules.
|
|
53
|
-
- [`EscapeMap`](#EscapeMap): A map from value constructors (or `null`/`undefined`) to escape functions.
|
|
54
52
|
- [`HArgs`](#HArgs): Tuple argument type for the [`h`](#h) and [`s`](#s) helpers.
|
|
55
53
|
- [`HArgs1`](#HArgs1): Single argument type for the [`h`](#h) and [`s`](#s) helpers.
|
|
56
54
|
- [`c`](#c): A minimal CSS-in-JS helper that converts a JavaScript object hierarchy into a CSS string.
|
|
57
55
|
- [`csvParse`](#csvParse): Parses a CSV string into a two-dimensional array of strings.
|
|
58
|
-
- [`escapeValues`](#escapeValues): Escapes an array of values using the provided escape map.
|
|
59
56
|
- [`fixPlTypography`](#fixPlTypography): Applies Polish-specific typographic corrections to a DOM subtree.
|
|
60
57
|
- [`h`](#h): A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also [`s`](#s)).
|
|
61
58
|
- [`hasOwn`](#hasOwn): Checks whether an object has the specified key as its own property.
|
|
@@ -97,16 +94,6 @@ type CRoot = Record<PropertyKey, CNode>;
|
|
|
97
94
|
|
|
98
95
|
Represents the root CSS object for the [`c`](#c) helper. Keys are top-level selectors or at-rules.
|
|
99
96
|
|
|
100
|
-
### EscapeMap
|
|
101
|
-
|
|
102
|
-
```ts
|
|
103
|
-
type EscapeMap = Map<unknown, (value?: unknown) => string>;
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
A map from value constructors (or `null`/`undefined`) to escape functions.
|
|
107
|
-
|
|
108
|
-
Used by [`escapeValues`](#escapeValues) and [`newEscape`](#newEscape).
|
|
109
|
-
|
|
110
97
|
### HArgs
|
|
111
98
|
|
|
112
99
|
```ts
|
|
@@ -381,26 +368,6 @@ expect(csvParse(text)).to.deep.equal([
|
|
|
381
368
|
])
|
|
382
369
|
```
|
|
383
370
|
|
|
384
|
-
### escapeValues
|
|
385
|
-
|
|
386
|
-
```ts
|
|
387
|
-
const escapeValues: (escapeMap: EscapeMap, values: unknown[]) => string[];
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
Escapes an array of values using the provided escape map.
|
|
391
|
-
|
|
392
|
-
#### escapeMap
|
|
393
|
-
|
|
394
|
-
A map where keys are constructors (e.g., `String`, `Number`) and values are escape functions.
|
|
395
|
-
|
|
396
|
-
#### values
|
|
397
|
-
|
|
398
|
-
The array of values to escape.
|
|
399
|
-
|
|
400
|
-
#### Returns
|
|
401
|
-
|
|
402
|
-
An array of escaped strings.
|
|
403
|
-
|
|
404
371
|
### fixPlTypography
|
|
405
372
|
|
|
406
373
|
```ts
|
|
@@ -421,13 +388,18 @@ except those inside `IFRAME`, `NOSCRIPT`, `PRE`, `SCRIPT`, `STYLE`, or `TEXTAREA
|
|
|
421
388
|
#### Usage Examples
|
|
422
389
|
|
|
423
390
|
```ts
|
|
424
|
-
const p = h('p',
|
|
391
|
+
const p = h('p',
|
|
392
|
+
'Pchnąć w tę łódź jeża lub ośm skrzyń fig (zob. https://pl.wikipedia.org/wiki/Pangram).',
|
|
393
|
+
['br'],
|
|
394
|
+
['b', 'Zażółć gęślą jaźń.']
|
|
395
|
+
)
|
|
425
396
|
|
|
426
397
|
fixPlTypography(p)
|
|
427
398
|
|
|
428
399
|
expect(p.innerHTML).to.deep.equal(
|
|
429
400
|
'Pchnąć <span style="white-space:nowrap">w </span>tę łódź jeża lub ośm skrzyń fig ' +
|
|
430
|
-
'(zob. https://\u200Bpl.\u200Bwikipedia.\u200Borg/\u200Bwiki/\u200BPangram).'
|
|
401
|
+
'(zob. https://\u200Bpl.\u200Bwikipedia.\u200Borg/\u200Bwiki/\u200BPangram).' +
|
|
402
|
+
'<br><b>Zażółć gęślą jaźń.</b>')
|
|
431
403
|
```
|
|
432
404
|
|
|
433
405
|
### h
|
|
@@ -869,14 +841,14 @@ expect(nanolightTs(codeJs)).to.deep.equal([
|
|
|
869
841
|
### newEscape
|
|
870
842
|
|
|
871
843
|
```ts
|
|
872
|
-
const newEscape: (
|
|
844
|
+
const newEscape: (escapeFn: (value: any) => string) => (template: TemplateStringsArray, ...values: unknown[]) => string;
|
|
873
845
|
```
|
|
874
846
|
|
|
875
847
|
Creates a tag function for escaping interpolated values in template literals.
|
|
876
848
|
|
|
877
|
-
####
|
|
849
|
+
#### escapeFn
|
|
878
850
|
|
|
879
|
-
A
|
|
851
|
+
A function that takes a value and returns its escaped string representation.
|
|
880
852
|
|
|
881
853
|
#### Returns
|
|
882
854
|
|
|
@@ -885,27 +857,30 @@ A tag function that escapes interpolated values using the provided escape map.
|
|
|
885
857
|
#### Usage Examples
|
|
886
858
|
|
|
887
859
|
```ts
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
860
|
+
const escapeFn = (value: any): string =>
|
|
861
|
+
isArray(value)
|
|
862
|
+
? value.map(escapeFn).join(', ')
|
|
863
|
+
: value === true || value === false
|
|
864
|
+
? `b'${+value}'`
|
|
865
|
+
: value instanceof Date
|
|
866
|
+
? `'${value.toISOString().replace(/^(.+)T(.+)\..*$/, '$1 $2')}'`
|
|
867
|
+
: isFiniteNumber(value)
|
|
868
|
+
? `${value}`
|
|
869
|
+
: isString(value)
|
|
870
|
+
? `'${value.replace(/'/g, "''")}'`
|
|
871
|
+
: 'NULL'
|
|
872
|
+
|
|
873
|
+
const sql = newEscape(escapeFn)
|
|
899
874
|
|
|
900
875
|
const actual = sql`
|
|
901
876
|
SELECT *
|
|
902
877
|
FROM table_name
|
|
903
|
-
WHERE column_name IN (${[true, null, undefined, 42, '42', "4'2", new Date(323325000000)]})`
|
|
878
|
+
WHERE column_name IN (${[true, null, undefined, NaN, Infinity, 42, '42', "4'2", /42/, new Date(323325000000)]})`
|
|
904
879
|
|
|
905
880
|
const expected = `
|
|
906
881
|
SELECT *
|
|
907
882
|
FROM table_name
|
|
908
|
-
WHERE column_name IN (b'1', NULL, NULL, 42, '42', '4''2', '1980-03-31 04:30:00')`
|
|
883
|
+
WHERE column_name IN (b'1', NULL, NULL, NULL, NULL, 42, '42', '4''2', NULL, '1980-03-31 04:30:00')`
|
|
909
884
|
|
|
910
885
|
expect(actual).to.equal(expected)
|
|
911
886
|
```
|
|
@@ -957,6 +932,13 @@ expect(car(0)).to.equal('cars')
|
|
|
957
932
|
expect(car(1)).to.equal('car')
|
|
958
933
|
expect(car(17)).to.equal('cars')
|
|
959
934
|
expect(car(42)).to.equal('cars')
|
|
935
|
+
|
|
936
|
+
const empty = newNounForm('en', {})
|
|
937
|
+
|
|
938
|
+
expect(empty(0)).to.equal('')
|
|
939
|
+
expect(empty(1)).to.equal('')
|
|
940
|
+
expect(empty(17)).to.equal('')
|
|
941
|
+
expect(empty(42)).to.equal('')
|
|
960
942
|
```
|
|
961
943
|
|
|
962
944
|
### newTokenizer
|
|
@@ -1355,6 +1337,18 @@ expect(ref).to.deep.equal({ one: { two: { three: { four: 5 } } } })
|
|
|
1355
1337
|
expect(vivify(ref).one.two.three.four.toString.name).to.equal('toString')
|
|
1356
1338
|
|
|
1357
1339
|
expect(ref).to.deep.equal({ one: { two: { three: { four: 5 } } } })
|
|
1340
|
+
|
|
1341
|
+
const u = undefined
|
|
1342
|
+
|
|
1343
|
+
vivify(u).one.two = 3
|
|
1344
|
+
|
|
1345
|
+
expect(u).to.be.undefined
|
|
1346
|
+
|
|
1347
|
+
const n = null
|
|
1348
|
+
|
|
1349
|
+
delete vivify(n).one.two.three
|
|
1350
|
+
|
|
1351
|
+
expect(n).to.be.null
|
|
1358
1352
|
```
|
|
1359
1353
|
|
|
1360
1354
|
## License
|