@jackens/nnn 2025.12.29 → 2026.2.7
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 +35 -29
- package/nnn.js +26 -15
- package/package.json +4 -2
- package/readme.md +122 -86
package/nnn.d.ts
CHANGED
|
@@ -126,7 +126,7 @@ export declare const new_escape: (escape_map: EscapeMap) => (template: TemplateS
|
|
|
126
126
|
* The root DOM node to process. All descendant text nodes are corrected recursively,
|
|
127
127
|
* except those inside `IFRAME`, `NOSCRIPT`, `PRE`, `SCRIPT`, `STYLE`, or `TEXTAREA` elements.
|
|
128
128
|
*/
|
|
129
|
-
export declare const
|
|
129
|
+
export declare const fix_pl_typography: (node: Node) => void;
|
|
130
130
|
/**
|
|
131
131
|
* Single argument type for the {@link h} and {@link s} helpers.
|
|
132
132
|
*/
|
|
@@ -307,30 +307,32 @@ export declare const is_string: (arg: unknown) => arg is string;
|
|
|
307
307
|
*/
|
|
308
308
|
export declare const js_on_parse: (handlers: Record<PropertyKey, Function>, text: string) => any;
|
|
309
309
|
/**
|
|
310
|
-
* Creates a function that returns the appropriate
|
|
310
|
+
* Creates a function that returns the appropriate noun form based on a numeric value using `Intl.PluralRules`.
|
|
311
311
|
*
|
|
312
|
-
*
|
|
313
|
-
* -
|
|
314
|
-
* - “Plural 2-4”: used for 2, 3, 4, 22, 23, 24, etc. (but not 12, 13, 14).
|
|
315
|
-
* - “Plural 5+”: used for 0, 5–21, 25–31, etc.
|
|
312
|
+
* Different languages have different plural rules. The `Intl.PluralRules` API provides
|
|
313
|
+
* locale-aware plural category selection. Possible categories are:
|
|
316
314
|
*
|
|
317
|
-
*
|
|
315
|
+
* - `zero`: for zero items (used in some languages like Arabic, Latvian)
|
|
316
|
+
* - `one`: for singular (e.g., 1 item)
|
|
317
|
+
* - `two`: for dual (used in some languages like Arabic, Hebrew)
|
|
318
|
+
* - `few`: for small plurals (e.g., 2-4 in Polish)
|
|
319
|
+
* - `many`: for larger plurals (e.g., 5-21 in Polish)
|
|
320
|
+
* - `other`: fallback category (used by all languages)
|
|
318
321
|
*
|
|
319
|
-
*
|
|
322
|
+
* @param locale
|
|
320
323
|
*
|
|
321
|
-
*
|
|
324
|
+
* A BCP 47 language tag (e.g., `pl`, `en`).
|
|
322
325
|
*
|
|
323
|
-
*
|
|
326
|
+
* @param forms
|
|
324
327
|
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
* The form for 5+ (e.g., “aut”).
|
|
328
|
+
* An object mapping plural categories to noun forms. Not all categories need to be provided;
|
|
329
|
+
* if a category is missing, the function falls back to `other`, then to an empty string.
|
|
328
330
|
*
|
|
329
331
|
* @returns
|
|
330
332
|
*
|
|
331
333
|
* A function that takes a numeric value and returns the appropriate noun form.
|
|
332
334
|
*/
|
|
333
|
-
export declare const new_noun_form: (
|
|
335
|
+
export declare const new_noun_form: (locale: string, forms: Partial<Record<Intl.LDMLPluralRule, string>>) => (value: number) => string;
|
|
334
336
|
/**
|
|
335
337
|
* Creates a new object containing only the specified keys from the source object.
|
|
336
338
|
*
|
|
@@ -367,21 +369,6 @@ export declare const pick: <T, K extends keyof T>(ref: T, keys: K[]) => Pick<T,
|
|
|
367
369
|
* A new object without the specified keys.
|
|
368
370
|
*/
|
|
369
371
|
export declare const omit: <T, K extends keyof T>(ref: T, keys: unknown[]) => Omit<T, K>;
|
|
370
|
-
/**
|
|
371
|
-
* A Proxy-based helper for auto-vivification of nested object structures.
|
|
372
|
-
*
|
|
373
|
-
* Accessing any property on the returned proxy automatically creates an empty object if the property does not exist,
|
|
374
|
-
* allowing deep assignments without explicit null checks.
|
|
375
|
-
*
|
|
376
|
-
* @param ref
|
|
377
|
-
*
|
|
378
|
-
* The root object to wrap.
|
|
379
|
-
*
|
|
380
|
-
* @returns
|
|
381
|
-
*
|
|
382
|
-
* A proxy that auto-creates nested objects on property access.
|
|
383
|
-
*/
|
|
384
|
-
export declare const pro: (ref: unknown) => any;
|
|
385
372
|
/**
|
|
386
373
|
* A helper for building simple tokenizers (see also {@link nanolight_ts}).
|
|
387
374
|
*
|
|
@@ -450,3 +437,22 @@ export declare const monokai: CRoot;
|
|
|
450
437
|
* A UUID v1 `string` in the standard format `xxxxxxxx-xxxx-1xxx-xxxx-xxxxxxxxxxxx`.
|
|
451
438
|
*/
|
|
452
439
|
export declare const uuid_v1: (date?: Date, node?: string) => string;
|
|
440
|
+
/**
|
|
441
|
+
* A Proxy-based helper for auto-vivification of nested object structures.
|
|
442
|
+
*
|
|
443
|
+
* Accessing any property on the returned proxy automatically creates an empty object
|
|
444
|
+
* (or array for numeric keys) if the property does not exist,
|
|
445
|
+
* allowing deep assignments without explicit null checks.
|
|
446
|
+
*
|
|
447
|
+
* When a numeric key (like `[42]`) is accessed, the parent structure is
|
|
448
|
+
* automatically converted to an array if it isn’t one already.
|
|
449
|
+
*
|
|
450
|
+
* @param ref
|
|
451
|
+
*
|
|
452
|
+
* The root object to wrap.
|
|
453
|
+
*
|
|
454
|
+
* @returns
|
|
455
|
+
*
|
|
456
|
+
* A proxy that auto-creates nested objects/arrays on property access.
|
|
457
|
+
*/
|
|
458
|
+
export declare const vivify: (ref: unknown) => any;
|
package/nnn.js
CHANGED
|
@@ -5,12 +5,26 @@ var is_number = (arg) => typeof arg === "number";
|
|
|
5
5
|
var is_record = (arg) => typeof arg === "object" && arg != null && !is_array(arg);
|
|
6
6
|
var is_string = (arg) => typeof arg === "string";
|
|
7
7
|
|
|
8
|
-
// src/nnn/
|
|
9
|
-
var
|
|
8
|
+
// src/nnn/vivify.ts
|
|
9
|
+
var ARRAY_INDEX_REGEXP = /^(0|[1-9]\d*)$/;
|
|
10
|
+
var should_convert_target_to_array = (target, key, parent) => parent != null && typeof key === "string" && ARRAY_INDEX_REGEXP.test(key) && !is_array(target);
|
|
11
|
+
var _vivify = (ref, parent, parentKey) => new Proxy(ref, {
|
|
10
12
|
get(target, key) {
|
|
11
|
-
|
|
13
|
+
if (should_convert_target_to_array(target, key, parent)) {
|
|
14
|
+
target = parent[parentKey] = [];
|
|
15
|
+
}
|
|
16
|
+
target[key] ??= {};
|
|
17
|
+
return _vivify(target[key], target, key);
|
|
18
|
+
},
|
|
19
|
+
set(target, key, value) {
|
|
20
|
+
if (should_convert_target_to_array(target, key, parent)) {
|
|
21
|
+
target = parent[parentKey] = [];
|
|
22
|
+
}
|
|
23
|
+
target[key] = value;
|
|
24
|
+
return true;
|
|
12
25
|
}
|
|
13
26
|
});
|
|
27
|
+
var vivify = (ref) => _vivify(ref);
|
|
14
28
|
|
|
15
29
|
// src/nnn/c.ts
|
|
16
30
|
var _c = (node, prefix, result, splitter) => {
|
|
@@ -65,7 +79,7 @@ var c = (root, splitter = "$$") => {
|
|
|
65
79
|
return chunks.join("");
|
|
66
80
|
};
|
|
67
81
|
var rwd = (root, selector, cell_width_px, cell_height_px, ...specs) => {
|
|
68
|
-
const main =
|
|
82
|
+
const main = vivify(root)[selector];
|
|
69
83
|
main.boxSizing = "border-box";
|
|
70
84
|
main.display = "block";
|
|
71
85
|
main.float = "left";
|
|
@@ -73,7 +87,7 @@ var rwd = (root, selector, cell_width_px, cell_height_px, ...specs) => {
|
|
|
73
87
|
main.height = `${cell_height_px}px`;
|
|
74
88
|
specs.sort(([a], [b]) => a - b);
|
|
75
89
|
for (let [max_width, width, height] of specs) {
|
|
76
|
-
const node = max_width === 1 ? main :
|
|
90
|
+
const node = max_width === 1 ? main : vivify(root)[`@media(min-width:${cell_width_px * max_width}px)`][selector];
|
|
77
91
|
width ??= 1;
|
|
78
92
|
height ??= 1;
|
|
79
93
|
let gcd = 100 * width;
|
|
@@ -158,9 +172,9 @@ var h = /* @__PURE__ */ _h();
|
|
|
158
172
|
var s = /* @__PURE__ */ _h("http://www.w3.org/2000/svg");
|
|
159
173
|
var svg_use = (id, ...args) => s("svg", ["use", { "xlink:href": "#" + id }], ...args);
|
|
160
174
|
|
|
161
|
-
// src/nnn/
|
|
175
|
+
// src/nnn/fix_pl_typography.ts
|
|
162
176
|
var TAGS_TO_SKIP = ["IFRAME", "NOSCRIPT", "PRE", "SCRIPT", "STYLE", "TEXTAREA"];
|
|
163
|
-
var
|
|
177
|
+
var fix_pl_typography = (node) => {
|
|
164
178
|
const queue = [node];
|
|
165
179
|
while (queue.length > 0) {
|
|
166
180
|
const node_0 = queue.shift();
|
|
@@ -209,12 +223,9 @@ var js_on_parse = (handlers, text) => JSON.parse(text, (key, value) => {
|
|
|
209
223
|
}
|
|
210
224
|
return value;
|
|
211
225
|
});
|
|
212
|
-
// src/nnn/
|
|
213
|
-
var
|
|
214
|
-
|
|
215
|
-
const abs_value_mod_10 = abs_value % 10;
|
|
216
|
-
return value === 1 ? singular : (abs_value_mod_10 === 2 || abs_value_mod_10 === 3 || abs_value_mod_10 === 4) && abs_value !== 12 && abs_value !== 13 && abs_value !== 14 ? plural_2 : plural_5;
|
|
217
|
-
};
|
|
226
|
+
// src/nnn/new_noun_form.ts
|
|
227
|
+
var PLURAL_RULES = {};
|
|
228
|
+
var new_noun_form = (locale, forms) => (value) => forms[(PLURAL_RULES[locale] ??= new Intl.PluralRules(locale)).select(value)] ?? forms.other ?? "";
|
|
218
229
|
// src/nnn/omit_pick.ts
|
|
219
230
|
var pick = (ref, keys) => Object.fromEntries(Object.entries(ref).filter(([key]) => keys.includes(key)));
|
|
220
231
|
var omit = (ref, keys) => Object.fromEntries(Object.entries(ref).filter(([key]) => !keys.includes(key)));
|
|
@@ -319,11 +330,11 @@ var uuid_v1 = (date = new Date, node = Math.random().toString(16).slice(2)) => {
|
|
|
319
330
|
return time.slice(-8).concat("-", time.slice(-12, -8), -1, time.slice(-15, -12), "-", (8 | counter >> 12).toString(16), (ZEROS + (counter & 4095).toString(16)).slice(-3), "-", (ZEROS + node).slice(-12));
|
|
320
331
|
};
|
|
321
332
|
export {
|
|
333
|
+
vivify,
|
|
322
334
|
uuid_v1,
|
|
323
335
|
svg_use,
|
|
324
336
|
s,
|
|
325
337
|
rwd,
|
|
326
|
-
pro,
|
|
327
338
|
pick,
|
|
328
339
|
omit,
|
|
329
340
|
new_tokenizer,
|
|
@@ -339,7 +350,7 @@ export {
|
|
|
339
350
|
is_array,
|
|
340
351
|
has_own,
|
|
341
352
|
h,
|
|
342
|
-
|
|
353
|
+
fix_pl_typography,
|
|
343
354
|
escape_values,
|
|
344
355
|
csv_parse,
|
|
345
356
|
c
|
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"author": "Jackens",
|
|
3
3
|
"description": "Jackens’ JavaScript helpers.",
|
|
4
4
|
"keywords": [
|
|
5
|
+
"autovivify",
|
|
5
6
|
"c",
|
|
6
7
|
"CSS-in-JS",
|
|
7
8
|
"CSV parse",
|
|
@@ -34,12 +35,13 @@
|
|
|
34
35
|
"tokenizer",
|
|
35
36
|
"typography",
|
|
36
37
|
"uuid",
|
|
37
|
-
"uuidv1"
|
|
38
|
+
"uuidv1",
|
|
39
|
+
"vivify"
|
|
38
40
|
],
|
|
39
41
|
"license": "MIT",
|
|
40
42
|
"main": "nnn.js",
|
|
41
43
|
"name": "@jackens/nnn",
|
|
42
44
|
"type": "module",
|
|
43
45
|
"types": "nnn.d.ts",
|
|
44
|
-
"version": "
|
|
46
|
+
"version": "2026.2.7"
|
|
45
47
|
}
|
package/readme.md
CHANGED
|
@@ -5,25 +5,43 @@ A collection of Jackens’ JavaScript helper utilities.
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
bun i @jackens/nnn
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
or
|
|
12
|
-
|
|
13
|
-
```sh
|
|
14
|
-
npm i @jackens/nnn
|
|
8
|
+
bun i @jackens/nnn # npm i @jackens/nnn
|
|
15
9
|
```
|
|
16
10
|
|
|
17
11
|
## Usage
|
|
18
12
|
|
|
19
13
|
```js
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
import {
|
|
15
|
+
CNode,
|
|
16
|
+
CRoot,
|
|
17
|
+
EscapeMap,
|
|
18
|
+
HArgs,
|
|
19
|
+
HArgs1,
|
|
20
|
+
c,
|
|
21
|
+
csv_parse,
|
|
22
|
+
escape_values,
|
|
23
|
+
fix_pl_typography,
|
|
24
|
+
h,
|
|
25
|
+
has_own,
|
|
26
|
+
is_array,
|
|
27
|
+
is_finite_number,
|
|
28
|
+
is_number,
|
|
29
|
+
is_record,
|
|
30
|
+
is_string,
|
|
31
|
+
js_on_parse,
|
|
32
|
+
monokai,
|
|
33
|
+
nanolight_ts,
|
|
34
|
+
new_escape,
|
|
35
|
+
new_noun_form,
|
|
36
|
+
new_tokenizer,
|
|
37
|
+
omit,
|
|
38
|
+
pick,
|
|
39
|
+
rwd,
|
|
40
|
+
s,
|
|
41
|
+
svg_use,
|
|
42
|
+
uuid_v1,
|
|
43
|
+
vivify
|
|
44
|
+
} from '@jackens/nnn' // './node_modules/@jackens/nnn/nnn.js'
|
|
27
45
|
```
|
|
28
46
|
|
|
29
47
|
## Exports
|
|
@@ -36,7 +54,7 @@ import { «something» } from './node_modules/@jackens/nnn/nnn.js'
|
|
|
36
54
|
- [`c`](#c): A minimal CSS-in-JS helper that converts a JavaScript object hierarchy into a CSS string.
|
|
37
55
|
- [`csv_parse`](#csv_parse): Parses a CSV string into a two-dimensional array of strings.
|
|
38
56
|
- [`escape_values`](#escape_values): Escapes an array of values using the provided escape map.
|
|
39
|
-
- [`
|
|
57
|
+
- [`fix_pl_typography`](#fix_pl_typography): Applies Polish-specific typographic corrections to a DOM subtree.
|
|
40
58
|
- [`h`](#h): A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper
|
|
41
59
|
for creating and modifying `HTMLElement`s (see also [`s`](#s)).
|
|
42
60
|
- [`has_own`](#has_own): Checks whether an object has the specified key as its own property.
|
|
@@ -49,16 +67,16 @@ import { «something» } from './node_modules/@jackens/nnn/nnn.js'
|
|
|
49
67
|
- [`monokai`](#monokai): A Monokai-inspired color scheme for use with the [`c`](#c) helper and [`nanolight_ts`](#nanolight_ts) tokenizer.
|
|
50
68
|
- [`nanolight_ts`](#nanolight_ts): A TypeScript/JavaScript syntax highlighting tokenizer built using [`new_tokenizer`](#new_tokenizer).
|
|
51
69
|
- [`new_escape`](#new_escape): Creates a tag function for escaping interpolated values in template literals.
|
|
52
|
-
- [`new_noun_form`](#new_noun_form): Creates a function that returns the appropriate
|
|
70
|
+
- [`new_noun_form`](#new_noun_form): Creates a function that returns the appropriate noun form based on a numeric value using `Intl.PluralRules`.
|
|
53
71
|
- [`new_tokenizer`](#new_tokenizer): A helper for building simple tokenizers (see also [`nanolight_ts`](#nanolight_ts)).
|
|
54
72
|
- [`omit`](#omit): Creates a new object excluding the specified keys from the source object.
|
|
55
73
|
- [`pick`](#pick): Creates a new object containing only the specified keys from the source object.
|
|
56
|
-
- [`pro`](#pro): A Proxy-based helper for auto-vivification of nested object structures.
|
|
57
74
|
- [`rwd`](#rwd): A responsive web design helper that generates CSS rules for a grid-like layout.
|
|
58
75
|
- [`s`](#s): A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper
|
|
59
76
|
for creating and modifying `SVGElement`s (see also [`h`](#h)).
|
|
60
77
|
- [`svg_use`](#svg_use): Shorthand for creating an SVG element with a `<use>` child referencing an icon by ID.
|
|
61
78
|
- [`uuid_v1`](#uuid_v1): Generates a UUID v1 (time-based) identifier.
|
|
79
|
+
- [`vivify`](#vivify): A Proxy-based helper for auto-vivification of nested object structures.
|
|
62
80
|
|
|
63
81
|
### CNode
|
|
64
82
|
|
|
@@ -391,10 +409,10 @@ The array of values to escape.
|
|
|
391
409
|
|
|
392
410
|
An array of escaped strings.
|
|
393
411
|
|
|
394
|
-
###
|
|
412
|
+
### fix_pl_typography
|
|
395
413
|
|
|
396
414
|
```ts
|
|
397
|
-
const
|
|
415
|
+
const fix_pl_typography: (node: Node) => void;
|
|
398
416
|
```
|
|
399
417
|
|
|
400
418
|
Applies Polish-specific typographic corrections to a DOM subtree.
|
|
@@ -413,7 +431,7 @@ except those inside `IFRAME`, `NOSCRIPT`, `PRE`, `SCRIPT`, `STYLE`, or `TEXTAREA
|
|
|
413
431
|
```ts
|
|
414
432
|
const p = h('p', 'Pchnąć w tę łódź jeża lub ośm skrzyń fig (zob. https://pl.wikipedia.org/wiki/Pangram).')
|
|
415
433
|
|
|
416
|
-
|
|
434
|
+
fix_pl_typography(p)
|
|
417
435
|
|
|
418
436
|
expect(p.innerHTML).to.deep.equal(
|
|
419
437
|
'Pchnąć <span style="white-space:nowrap">w </span>tę łódź jeża lub ośm skrzyń fig ' +
|
|
@@ -879,12 +897,12 @@ const sql = new_escape(escape_map)
|
|
|
879
897
|
const actual = sql`
|
|
880
898
|
SELECT *
|
|
881
899
|
FROM table_name
|
|
882
|
-
WHERE column_name IN (${[true, null, undefined, 42, '42', "4'2",
|
|
900
|
+
WHERE column_name IN (${[true, null, undefined, 42, '42', "4'2", new Date(323325000000)]})`
|
|
883
901
|
|
|
884
902
|
const expected = `
|
|
885
903
|
SELECT *
|
|
886
904
|
FROM table_name
|
|
887
|
-
WHERE column_name IN (b'1', NULL, NULL, 42, '42', '4''2',
|
|
905
|
+
WHERE column_name IN (b'1', NULL, NULL, 42, '42', '4''2', '1980-03-31 04:30:00')`
|
|
888
906
|
|
|
889
907
|
expect(actual).to.deep.equal(expected)
|
|
890
908
|
```
|
|
@@ -892,27 +910,29 @@ expect(actual).to.deep.equal(expected)
|
|
|
892
910
|
### new_noun_form
|
|
893
911
|
|
|
894
912
|
```ts
|
|
895
|
-
const new_noun_form: (
|
|
913
|
+
const new_noun_form: (locale: string, forms: Partial<Record<Intl.LDMLPluralRule, string>>) => (value: number) => string;
|
|
896
914
|
```
|
|
897
915
|
|
|
898
|
-
Creates a function that returns the appropriate
|
|
899
|
-
|
|
900
|
-
Polish has three plural forms depending on the number:
|
|
901
|
-
- Singular: used for exactly 1.
|
|
902
|
-
- “Plural 2-4”: used for 2, 3, 4, 22, 23, 24, etc. (but not 12, 13, 14).
|
|
903
|
-
- “Plural 5+”: used for 0, 5–21, 25–31, etc.
|
|
916
|
+
Creates a function that returns the appropriate noun form based on a numeric value using `Intl.PluralRules`.
|
|
904
917
|
|
|
905
|
-
|
|
918
|
+
Different languages have different plural rules. The `Intl.PluralRules` API provides
|
|
919
|
+
locale-aware plural category selection. Possible categories are:
|
|
906
920
|
|
|
907
|
-
|
|
921
|
+
- `zero`: for zero items (used in some languages like Arabic, Latvian)
|
|
922
|
+
- `one`: for singular (e.g., 1 item)
|
|
923
|
+
- `two`: for dual (used in some languages like Arabic, Hebrew)
|
|
924
|
+
- `few`: for small plurals (e.g., 2-4 in Polish)
|
|
925
|
+
- `many`: for larger plurals (e.g., 5-21 in Polish)
|
|
926
|
+
- `other`: fallback category (used by all languages)
|
|
908
927
|
|
|
909
|
-
####
|
|
928
|
+
#### locale
|
|
910
929
|
|
|
911
|
-
|
|
930
|
+
A BCP 47 language tag (e.g., `pl`, `en`).
|
|
912
931
|
|
|
913
|
-
####
|
|
932
|
+
#### forms
|
|
914
933
|
|
|
915
|
-
|
|
934
|
+
An object mapping plural categories to noun forms. Not all categories need to be provided;
|
|
935
|
+
if a category is missing, the function falls back to `other`, then to an empty string.
|
|
916
936
|
|
|
917
937
|
#### Returns
|
|
918
938
|
|
|
@@ -921,14 +941,14 @@ A function that takes a numeric value and returns the appropriate noun form.
|
|
|
921
941
|
#### Usage Examples
|
|
922
942
|
|
|
923
943
|
```ts
|
|
924
|
-
const auto = new_noun_form('auto', 'auta', 'aut')
|
|
944
|
+
const auto = new_noun_form('pl', { one: 'auto', few: 'auta', other: 'aut' })
|
|
925
945
|
|
|
926
946
|
expect(auto(0)).to.deep.equal('aut')
|
|
927
947
|
expect(auto(1)).to.deep.equal('auto')
|
|
928
948
|
expect(auto(17)).to.deep.equal('aut')
|
|
929
949
|
expect(auto(42)).to.deep.equal('auta')
|
|
930
950
|
|
|
931
|
-
const car = new_noun_form('
|
|
951
|
+
const car = new_noun_form('en', { one: 'car', other: 'cars' })
|
|
932
952
|
|
|
933
953
|
expect(car(0)).to.deep.equal('cars')
|
|
934
954
|
expect(car(1)).to.deep.equal('car')
|
|
@@ -1026,55 +1046,6 @@ const obj = { a: 42, b: '42', c: 17 }
|
|
|
1026
1046
|
expect(pick(obj, ['a', 'b'])).to.deep.equal({ a: 42, b: '42' })
|
|
1027
1047
|
```
|
|
1028
1048
|
|
|
1029
|
-
### pro
|
|
1030
|
-
|
|
1031
|
-
```ts
|
|
1032
|
-
const pro: (ref: unknown) => any;
|
|
1033
|
-
```
|
|
1034
|
-
|
|
1035
|
-
A Proxy-based helper for auto-vivification of nested object structures.
|
|
1036
|
-
|
|
1037
|
-
Accessing any property on the returned proxy automatically creates an empty object if the property does not exist,
|
|
1038
|
-
allowing deep assignments without explicit null checks.
|
|
1039
|
-
|
|
1040
|
-
#### ref
|
|
1041
|
-
|
|
1042
|
-
The root object to wrap.
|
|
1043
|
-
|
|
1044
|
-
#### Returns
|
|
1045
|
-
|
|
1046
|
-
A proxy that auto-creates nested objects on property access.
|
|
1047
|
-
|
|
1048
|
-
#### Usage Examples
|
|
1049
|
-
|
|
1050
|
-
```ts
|
|
1051
|
-
const ref = {}
|
|
1052
|
-
|
|
1053
|
-
pro(ref).one.two[3][4] = 1234
|
|
1054
|
-
|
|
1055
|
-
expect(ref).to.deep.equal({ one: { two: { 3: { 4: 1234 } } } })
|
|
1056
|
-
|
|
1057
|
-
pro(ref).one.two.tree = 123
|
|
1058
|
-
|
|
1059
|
-
expect(ref).to.deep.equal({ one: { two: { 3: { 4: 1234 }, tree: 123 } } })
|
|
1060
|
-
|
|
1061
|
-
pro(ref).one.two = undefined
|
|
1062
|
-
|
|
1063
|
-
expect(ref).to.deep.equal({ one: { two: undefined } })
|
|
1064
|
-
|
|
1065
|
-
delete pro(ref).one.two
|
|
1066
|
-
|
|
1067
|
-
expect(ref).to.deep.equal({ one: {} })
|
|
1068
|
-
|
|
1069
|
-
pro(ref).one.two.three.four
|
|
1070
|
-
|
|
1071
|
-
expect(ref).to.deep.equal({ one: { two: { three: { four: {} } } } })
|
|
1072
|
-
|
|
1073
|
-
pro(ref).one.two.three.four = 1234
|
|
1074
|
-
|
|
1075
|
-
expect(ref).to.deep.equal({ one: { two: { three: { four: 1234 } } } })
|
|
1076
|
-
```
|
|
1077
|
-
|
|
1078
1049
|
### rwd
|
|
1079
1050
|
|
|
1080
1051
|
```ts
|
|
@@ -1273,6 +1244,71 @@ expect(uuid_v1(new Date(), '123456789').split('-')[4]).to.deep.equal('0001234567
|
|
|
1273
1244
|
expect(uuid_v1(new Date(323325000000)).startsWith('c1399400-9a71-11bd')).to.be.true
|
|
1274
1245
|
```
|
|
1275
1246
|
|
|
1247
|
+
### vivify
|
|
1248
|
+
|
|
1249
|
+
```ts
|
|
1250
|
+
const vivify: (ref: unknown) => any;
|
|
1251
|
+
```
|
|
1252
|
+
|
|
1253
|
+
A Proxy-based helper for auto-vivification of nested object structures.
|
|
1254
|
+
|
|
1255
|
+
Accessing any property on the returned proxy automatically creates an empty object
|
|
1256
|
+
(or array for numeric keys) if the property does not exist,
|
|
1257
|
+
allowing deep assignments without explicit null checks.
|
|
1258
|
+
|
|
1259
|
+
When a numeric key (like `[42]`) is accessed, the parent structure is
|
|
1260
|
+
automatically converted to an array if it isn’t one already.
|
|
1261
|
+
|
|
1262
|
+
#### ref
|
|
1263
|
+
|
|
1264
|
+
The root object to wrap.
|
|
1265
|
+
|
|
1266
|
+
#### Returns
|
|
1267
|
+
|
|
1268
|
+
A proxy that auto-creates nested objects/arrays on property access.
|
|
1269
|
+
|
|
1270
|
+
#### Usage Examples
|
|
1271
|
+
|
|
1272
|
+
```ts
|
|
1273
|
+
const ref: any = {}
|
|
1274
|
+
|
|
1275
|
+
vivify(ref).one.two[3][4] = 1234
|
|
1276
|
+
|
|
1277
|
+
expect(ref).to.deep.equal({ one: { two: [, , , [, , , , 1234]] } })
|
|
1278
|
+
|
|
1279
|
+
vivify(ref).one.two[3][5] = 1235
|
|
1280
|
+
|
|
1281
|
+
expect(ref).to.deep.equal({ one: { two: [, , , [, , , , 1234, 1235]] } })
|
|
1282
|
+
|
|
1283
|
+
vivify(ref).one.two[1] = 121
|
|
1284
|
+
|
|
1285
|
+
expect(ref).to.deep.equal({ one: { two: [, 121, , [, , , , 1234, 1235]] } })
|
|
1286
|
+
|
|
1287
|
+
vivify(ref).one.two = 12
|
|
1288
|
+
|
|
1289
|
+
expect(ref).to.deep.equal({ one: { two: 12 } })
|
|
1290
|
+
|
|
1291
|
+
vivify(ref).one.two = undefined
|
|
1292
|
+
|
|
1293
|
+
expect(ref).to.deep.equal({ one: { two: undefined } })
|
|
1294
|
+
|
|
1295
|
+
delete vivify(ref).one.two
|
|
1296
|
+
|
|
1297
|
+
expect(ref).to.deep.equal({ one: {} })
|
|
1298
|
+
|
|
1299
|
+
delete vivify(ref).one.two.three
|
|
1300
|
+
|
|
1301
|
+
expect(ref).to.deep.equal({ one: { two: {} } })
|
|
1302
|
+
|
|
1303
|
+
vivify(ref).one.two.three.four
|
|
1304
|
+
|
|
1305
|
+
expect(ref).to.deep.equal({ one: { two: { three: { four: {} } } } })
|
|
1306
|
+
|
|
1307
|
+
vivify(ref).one.two.three.four = 1234
|
|
1308
|
+
|
|
1309
|
+
expect(ref).to.deep.equal({ one: { two: { three: { four: 1234 } } } })
|
|
1310
|
+
```
|
|
1311
|
+
|
|
1276
1312
|
## License
|
|
1277
1313
|
|
|
1278
1314
|
The MIT License (MIT)
|