@jackens/nnn 2026.2.11 → 2026.2.18
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 +116 -127
- package/nnn.js +148 -120
- package/package.json +1 -1
- package/readme.md +116 -207
package/nnn.d.ts
CHANGED
|
@@ -35,33 +35,6 @@ export type CRoot = Record<PropertyKey, CNode>;
|
|
|
35
35
|
* - Top-level keys starting with `@` (at-rules) are not concatenated with child selectors.
|
|
36
36
|
*/
|
|
37
37
|
export declare const c: (root: CRoot, splitter?: string) => string;
|
|
38
|
-
/**
|
|
39
|
-
* A responsive web design helper that generates CSS rules for a grid-like layout.
|
|
40
|
-
*
|
|
41
|
-
* @param root
|
|
42
|
-
*
|
|
43
|
-
* The CSS root object to populate (see {@link c}).
|
|
44
|
-
*
|
|
45
|
-
* @param selector
|
|
46
|
-
*
|
|
47
|
-
* The CSS selector for the grid item.
|
|
48
|
-
*
|
|
49
|
-
* @param cell_width_px
|
|
50
|
-
*
|
|
51
|
-
* The base cell width in pixels.
|
|
52
|
-
*
|
|
53
|
-
* @param cell_height_px
|
|
54
|
-
*
|
|
55
|
-
* The base cell height in pixels.
|
|
56
|
-
*
|
|
57
|
-
* @param specs
|
|
58
|
-
*
|
|
59
|
-
* An array of breakpoint specifications, each a tuple of:
|
|
60
|
-
* - `max_width`: maximum number of cells per row (defines the viewport breakpoint).
|
|
61
|
-
* - `width` (optional, default `1`): number of horizontal cells the element spans.
|
|
62
|
-
* - `height` (optional, default `1`): number of vertical cells the element spans.
|
|
63
|
-
*/
|
|
64
|
-
export declare const rwd: (root: CRoot, selector: string, cell_width_px: number, cell_height_px: number, ...specs: [number, number?, number?][]) => void;
|
|
65
38
|
/**
|
|
66
39
|
* Parses a CSV string into a two-dimensional array of strings.
|
|
67
40
|
*
|
|
@@ -80,40 +53,6 @@ export declare const rwd: (root: CRoot, selector: string, cell_width_px: number,
|
|
|
80
53
|
* A 2D array where each inner array represents a row of fields.
|
|
81
54
|
*/
|
|
82
55
|
export declare const csv_parse: (csv: string, separator?: string) => string[][];
|
|
83
|
-
/**
|
|
84
|
-
* A map from value constructors (or `null`/`undefined`) to escape functions.
|
|
85
|
-
*
|
|
86
|
-
* Used by {@link escape_values} and {@link new_escape}.
|
|
87
|
-
*/
|
|
88
|
-
export type EscapeMap = Map<unknown, (value?: unknown) => string>;
|
|
89
|
-
/**
|
|
90
|
-
* Escapes an array of values using the provided escape map.
|
|
91
|
-
*
|
|
92
|
-
* @param escape_map
|
|
93
|
-
*
|
|
94
|
-
* A map where keys are constructors (e.g., `String`, `Number`) and values are escape functions.
|
|
95
|
-
*
|
|
96
|
-
* @param values
|
|
97
|
-
*
|
|
98
|
-
* The array of values to escape.
|
|
99
|
-
*
|
|
100
|
-
* @returns
|
|
101
|
-
*
|
|
102
|
-
* An array of escaped strings.
|
|
103
|
-
*/
|
|
104
|
-
export declare const escape_values: (escape_map: EscapeMap, values: unknown[]) => string[];
|
|
105
|
-
/**
|
|
106
|
-
* Creates a tag function for escaping interpolated values in template literals.
|
|
107
|
-
*
|
|
108
|
-
* @param escape_map
|
|
109
|
-
*
|
|
110
|
-
* A map where keys are constructors and values are escape functions.
|
|
111
|
-
*
|
|
112
|
-
* @returns
|
|
113
|
-
*
|
|
114
|
-
* A tag function that escapes interpolated values using the provided escape map.
|
|
115
|
-
*/
|
|
116
|
-
export declare const new_escape: (escape_map: EscapeMap) => (template: TemplateStringsArray, ...values: unknown[]) => string;
|
|
117
56
|
/**
|
|
118
57
|
* Applies Polish-specific typographic corrections to a DOM subtree.
|
|
119
58
|
*
|
|
@@ -136,8 +75,7 @@ export type HArgs1 = Record<PropertyKey, unknown> | null | undefined | Node | st
|
|
|
136
75
|
*/
|
|
137
76
|
export type HArgs = [string | Node, ...HArgs1[]];
|
|
138
77
|
/**
|
|
139
|
-
* A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper
|
|
140
|
-
* for creating and modifying `HTMLElement`s (see also {@link s}).
|
|
78
|
+
* A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also {@link s}).
|
|
141
79
|
*
|
|
142
80
|
* @param tag_or_node
|
|
143
81
|
*
|
|
@@ -164,8 +102,7 @@ export declare const h: {
|
|
|
164
102
|
(tag_or_node: string | Node, ...args1: HArgs1[]): Node;
|
|
165
103
|
};
|
|
166
104
|
/**
|
|
167
|
-
* A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper
|
|
168
|
-
* for creating and modifying `SVGElement`s (see also {@link h}).
|
|
105
|
+
* A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also {@link h}).
|
|
169
106
|
*
|
|
170
107
|
* @param tag_or_node
|
|
171
108
|
*
|
|
@@ -191,24 +128,6 @@ export declare const s: {
|
|
|
191
128
|
<N extends Node>(node: N, ...args1: HArgs1[]): N;
|
|
192
129
|
(tag_or_node: string | Node, ...args1: HArgs1[]): Node;
|
|
193
130
|
};
|
|
194
|
-
/**
|
|
195
|
-
* Shorthand for creating an SVG element with a `<use>` child referencing an icon by ID.
|
|
196
|
-
*
|
|
197
|
-
* Equivalent to: `s('svg', ['use', { 'xlink:href': '#' + id }], ...args)`.
|
|
198
|
-
*
|
|
199
|
-
* @param id
|
|
200
|
-
*
|
|
201
|
-
* The ID of the symbol to reference (without the `#` prefix).
|
|
202
|
-
*
|
|
203
|
-
* @param args
|
|
204
|
-
*
|
|
205
|
-
* Additional arguments passed to the outer `<svg>` element.
|
|
206
|
-
*
|
|
207
|
-
* @returns
|
|
208
|
-
*
|
|
209
|
-
* An `SVGSVGElement` containing a `<use>` element.
|
|
210
|
-
*/
|
|
211
|
-
export declare const svg_use: (id: string, ...args: HArgs1[]) => SVGSVGElement;
|
|
212
131
|
/**
|
|
213
132
|
* Checks whether an object has the specified key as its own property.
|
|
214
133
|
*
|
|
@@ -306,11 +225,61 @@ export declare const is_string: (arg: unknown) => arg is string;
|
|
|
306
225
|
* The parsed value with handler substitutions applied.
|
|
307
226
|
*/
|
|
308
227
|
export declare const js_on_parse: (handlers: Record<PropertyKey, Function>, text: string) => any;
|
|
228
|
+
/**
|
|
229
|
+
* A Monokai-inspired color scheme for use with the {@link c} helper and {@link nanolight_ts} tokenizer.
|
|
230
|
+
*/
|
|
231
|
+
export declare const monokai: CRoot;
|
|
232
|
+
/**
|
|
233
|
+
* A TypeScript/JavaScript syntax highlighting tokenizer built using {@link new_tokenizer}.
|
|
234
|
+
*
|
|
235
|
+
* @param code
|
|
236
|
+
*
|
|
237
|
+
* The source code string to tokenize.
|
|
238
|
+
*
|
|
239
|
+
* @returns
|
|
240
|
+
*
|
|
241
|
+
* An array of {@link HArgs1} elements suitable for rendering with {@link h}.
|
|
242
|
+
*/
|
|
243
|
+
export declare const nanolight_ts: (code: string) => HArgs1[];
|
|
244
|
+
/**
|
|
245
|
+
* A map from value constructors (or `null`/`undefined`) to escape functions.
|
|
246
|
+
*
|
|
247
|
+
* Used by {@link escape_values} and {@link new_escape}.
|
|
248
|
+
*/
|
|
249
|
+
export type EscapeMap = Map<unknown, (value?: unknown) => string>;
|
|
250
|
+
/**
|
|
251
|
+
* Escapes an array of values using the provided escape map.
|
|
252
|
+
*
|
|
253
|
+
* @param escape_map
|
|
254
|
+
*
|
|
255
|
+
* A map where keys are constructors (e.g., `String`, `Number`) and values are escape functions.
|
|
256
|
+
*
|
|
257
|
+
* @param values
|
|
258
|
+
*
|
|
259
|
+
* The array of values to escape.
|
|
260
|
+
*
|
|
261
|
+
* @returns
|
|
262
|
+
*
|
|
263
|
+
* An array of escaped strings.
|
|
264
|
+
*/
|
|
265
|
+
export declare const escape_values: (escape_map: EscapeMap, values: unknown[]) => string[];
|
|
266
|
+
/**
|
|
267
|
+
* Creates a tag function for escaping interpolated values in template literals.
|
|
268
|
+
*
|
|
269
|
+
* @param escape_map
|
|
270
|
+
*
|
|
271
|
+
* A map where keys are constructors and values are escape functions.
|
|
272
|
+
*
|
|
273
|
+
* @returns
|
|
274
|
+
*
|
|
275
|
+
* A tag function that escapes interpolated values using the provided escape map.
|
|
276
|
+
*/
|
|
277
|
+
export declare const new_escape: (escape_map: EscapeMap) => (template: TemplateStringsArray, ...values: unknown[]) => string;
|
|
309
278
|
/**
|
|
310
279
|
* Creates a function that returns the appropriate noun form based on a numeric value using `Intl.PluralRules`.
|
|
311
280
|
*
|
|
312
|
-
* Different languages have different plural rules. The `Intl.PluralRules` API provides
|
|
313
|
-
*
|
|
281
|
+
* Different languages have different plural rules. The `Intl.PluralRules` API provides locale-aware plural category selection.
|
|
282
|
+
* Possible categories are:
|
|
314
283
|
*
|
|
315
284
|
* - `zero`: for zero items (used in some languages like Arabic, Latvian)
|
|
316
285
|
* - `one`: for singular (e.g., 1 item)
|
|
@@ -334,23 +303,31 @@ export declare const js_on_parse: (handlers: Record<PropertyKey, Function>, text
|
|
|
334
303
|
*/
|
|
335
304
|
export declare const new_noun_form: (locale: string, forms: Partial<Record<Intl.LDMLPluralRule, string>>) => (value: number) => string;
|
|
336
305
|
/**
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
* A runtime equivalent of TypeScript’s `Pick<T, K>` utility type. See also {@link omit}.
|
|
306
|
+
* A helper for building simple tokenizers (see also {@link nanolight_ts}).
|
|
340
307
|
*
|
|
341
|
-
* @param
|
|
308
|
+
* @param decorator
|
|
342
309
|
*
|
|
343
|
-
*
|
|
310
|
+
* A function that wraps each matched chunk. It receives the matched text (`chunk`)
|
|
311
|
+
* and optionally the `metadata` associated with the pattern that produced the match.
|
|
312
|
+
* For unmatched text between patterns, `metadata` is `undefined`.
|
|
344
313
|
*
|
|
345
|
-
* @param
|
|
314
|
+
* @param specs
|
|
346
315
|
*
|
|
347
|
-
* An array of
|
|
316
|
+
* An array of tuples `[metadata, pattern]` where:
|
|
317
|
+
* - `metadata`: arbitrary data (e.g., a CSS class name) passed to `decorator` when the pattern matches.
|
|
318
|
+
* - `pattern`: a `string` or `RegExp` to match against the input.
|
|
348
319
|
*
|
|
349
320
|
* @returns
|
|
350
321
|
*
|
|
351
|
-
* A
|
|
322
|
+
* A tokenizer function that accepts a code string and returns an array of decorated tokens.
|
|
323
|
+
*
|
|
324
|
+
* @remarks
|
|
325
|
+
*
|
|
326
|
+
* 1. Matches starting at an earlier position take precedence.
|
|
327
|
+
* 2. Among matches at the same position, the longer one wins.
|
|
328
|
+
* 3. Among matches of the same position and length, the one defined earlier wins.
|
|
352
329
|
*/
|
|
353
|
-
export declare const
|
|
330
|
+
export declare const new_tokenizer: <M, T>(decorator: (chunk: string, metadata?: M) => T, ...specs: [M, string | RegExp][]) => (code: string) => T[];
|
|
354
331
|
/**
|
|
355
332
|
* Creates a new object excluding the specified keys from the source object.
|
|
356
333
|
*
|
|
@@ -370,56 +347,68 @@ export declare const pick: <T, K extends keyof T>(ref: T, keys: K[]) => Pick<T,
|
|
|
370
347
|
*/
|
|
371
348
|
export declare const omit: <T, K extends keyof T>(ref: T, keys: unknown[]) => Omit<T, K>;
|
|
372
349
|
/**
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
* @param decorator
|
|
350
|
+
* Creates a new object containing only the specified keys from the source object.
|
|
376
351
|
*
|
|
377
|
-
* A
|
|
378
|
-
* and optionally the `metadata` associated with the pattern that produced the match.
|
|
379
|
-
* For unmatched text between patterns, `metadata` is `undefined`.
|
|
352
|
+
* A runtime equivalent of TypeScript’s `Pick<T, K>` utility type. See also {@link omit}.
|
|
380
353
|
*
|
|
381
|
-
* @param
|
|
354
|
+
* @param ref
|
|
382
355
|
*
|
|
383
|
-
*
|
|
384
|
-
* - `metadata`: arbitrary data (e.g., a CSS class name) passed to `decorator` when the pattern matches.
|
|
385
|
-
* - `pattern`: a `string` or `RegExp` to match against the input.
|
|
356
|
+
* The source object.
|
|
386
357
|
*
|
|
387
|
-
* @
|
|
358
|
+
* @param keys
|
|
388
359
|
*
|
|
389
|
-
*
|
|
360
|
+
* An array of keys to include in the result.
|
|
390
361
|
*
|
|
391
|
-
* @
|
|
362
|
+
* @returns
|
|
392
363
|
*
|
|
393
|
-
*
|
|
394
|
-
* 2. Among matches at the same position, the longer one wins.
|
|
395
|
-
* 3. Among matches of the same position and length, the one defined earlier wins.
|
|
364
|
+
* A new object with only the specified keys.
|
|
396
365
|
*/
|
|
397
|
-
export declare const
|
|
366
|
+
export declare const pick: <T, K extends keyof T>(ref: T, keys: K[]) => Pick<T, K>;
|
|
398
367
|
/**
|
|
399
|
-
* A
|
|
368
|
+
* A responsive web design helper that generates CSS rules for a grid-like layout.
|
|
400
369
|
*
|
|
401
|
-
* @param
|
|
370
|
+
* @param root
|
|
402
371
|
*
|
|
403
|
-
* The
|
|
372
|
+
* The CSS root object to populate (see {@link c}).
|
|
404
373
|
*
|
|
405
|
-
* @
|
|
374
|
+
* @param selector
|
|
406
375
|
*
|
|
407
|
-
*
|
|
376
|
+
* The CSS selector for the grid item.
|
|
377
|
+
*
|
|
378
|
+
* @param cell_width_px
|
|
379
|
+
*
|
|
380
|
+
* The base cell width in pixels.
|
|
381
|
+
*
|
|
382
|
+
* @param cell_height_px
|
|
383
|
+
*
|
|
384
|
+
* The base cell height in pixels.
|
|
385
|
+
*
|
|
386
|
+
* @param specs
|
|
387
|
+
*
|
|
388
|
+
* An array of breakpoint specifications, each a tuple of:
|
|
389
|
+
* - `max_width`: maximum number of cells per row (defines the viewport breakpoint).
|
|
390
|
+
* - `width` (optional, default `1`): number of horizontal cells the element spans.
|
|
391
|
+
* - `height` (optional, default `1`): number of vertical cells the element spans.
|
|
408
392
|
*/
|
|
409
|
-
export declare const
|
|
393
|
+
export declare const rwd: (root: CRoot, selector: string, cell_width_px: number, cell_height_px: number, ...specs: [number, number?, number?][]) => void;
|
|
410
394
|
/**
|
|
411
|
-
*
|
|
395
|
+
* Shorthand for creating an SVG element with a `<use>` child referencing an icon by ID.
|
|
412
396
|
*
|
|
413
|
-
*
|
|
414
|
-
* `--purple`, `--red`, `--white`, `--yellow`) with both light and dark mode variants.
|
|
397
|
+
* Equivalent to: `s('svg', ['use', { 'xlink:href': '#' + id }], ...args)`.
|
|
415
398
|
*
|
|
416
|
-
* @
|
|
399
|
+
* @param id
|
|
400
|
+
*
|
|
401
|
+
* The ID of the symbol to reference (without the `#` prefix).
|
|
402
|
+
*
|
|
403
|
+
* @param args
|
|
417
404
|
*
|
|
418
|
-
*
|
|
419
|
-
*
|
|
420
|
-
*
|
|
405
|
+
* Additional arguments passed to the outer `<svg>` element.
|
|
406
|
+
*
|
|
407
|
+
* @returns
|
|
408
|
+
*
|
|
409
|
+
* An `SVGSVGElement` containing a `<use>` element.
|
|
421
410
|
*/
|
|
422
|
-
export declare const
|
|
411
|
+
export declare const svg_use: (id: string, ...args: HArgs1[]) => SVGSVGElement;
|
|
423
412
|
/**
|
|
424
413
|
* Generates a UUID v1 (time-based) identifier.
|
|
425
414
|
*
|
|
@@ -446,14 +435,14 @@ export declare const uuid_v1: (date?: Date, node?: string) => string;
|
|
|
446
435
|
* Intermediates of the last level in a get-only property chain are NOT auto-created.
|
|
447
436
|
* For example, `vivify(ref).one.two` will create `ref.one` as `{}`, but will NOT create `ref.one.two`.
|
|
448
437
|
* Only when a deeper access, assignment, or deletion occurs
|
|
449
|
-
* (e.g. `vivify(ref).one.two
|
|
438
|
+
* (e.g. `delete vivify(ref).one.two.three` or `vivify(ref).one.two.three = 4`) will `ref.one.two` be materialized.
|
|
450
439
|
*
|
|
451
440
|
* When traversal reaches a primitive value, no auto-creation happens;
|
|
452
441
|
* the primitive’s own property is returned instead
|
|
453
442
|
* (e.g. accessing `.toString.name` on a number yields `'toString'` without modifying the underlying structure).
|
|
454
443
|
*
|
|
455
444
|
* Deletion on a non-existing intermediate path will auto-create intermediates up to the parent of the deleted key
|
|
456
|
-
* (e.g. `delete vivify(ref).
|
|
445
|
+
* (e.g. `delete vivify(ref).one.two.three` will create `ref.one.two` as `{}` if it does not exist).
|
|
457
446
|
*
|
|
458
447
|
* @param ref
|
|
459
448
|
*
|
package/nnn.js
CHANGED
|
@@ -1,41 +1,11 @@
|
|
|
1
|
-
// src/nnn/
|
|
1
|
+
// src/nnn/is_array.ts
|
|
2
2
|
var is_array = Array.isArray;
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
// src/nnn/is_number.ts
|
|
4
5
|
var is_number = (arg) => typeof arg === "number";
|
|
5
|
-
var is_record = (arg) => typeof arg === "object" && arg != null && !is_array(arg);
|
|
6
|
-
var is_string = (arg) => typeof arg === "string";
|
|
7
6
|
|
|
8
|
-
// src/nnn/
|
|
9
|
-
var
|
|
10
|
-
var get_target = (parent, parent_key, child_key) => {
|
|
11
|
-
if (parent_key == null) {
|
|
12
|
-
return parent;
|
|
13
|
-
}
|
|
14
|
-
if (!(parent_key in parent)) {
|
|
15
|
-
parent[parent_key] = is_string(child_key) && ARRAY_INDEX_REGEXP.test(child_key) ? [] : {};
|
|
16
|
-
}
|
|
17
|
-
return parent[parent_key];
|
|
18
|
-
};
|
|
19
|
-
var _vivify = (parent, parent_key) => new Proxy({}, {
|
|
20
|
-
get(_, key) {
|
|
21
|
-
const target = get_target(parent, parent_key, key);
|
|
22
|
-
if (target != null && typeof target === "object") {
|
|
23
|
-
return _vivify(target, key);
|
|
24
|
-
}
|
|
25
|
-
return target?.[key];
|
|
26
|
-
},
|
|
27
|
-
set(_, key, value) {
|
|
28
|
-
const target = get_target(parent, parent_key, key);
|
|
29
|
-
target[key] = value;
|
|
30
|
-
return true;
|
|
31
|
-
},
|
|
32
|
-
deleteProperty(_, key) {
|
|
33
|
-
const target = get_target(parent, parent_key, key);
|
|
34
|
-
delete target[key];
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
var vivify = (ref) => _vivify(ref);
|
|
7
|
+
// src/nnn/is_string.ts
|
|
8
|
+
var is_string = (arg) => typeof arg === "string";
|
|
39
9
|
|
|
40
10
|
// src/nnn/c.ts
|
|
41
11
|
var _c = (node, prefix, result, splitter) => {
|
|
@@ -89,37 +59,15 @@ var c = (root, splitter = "$$") => {
|
|
|
89
59
|
}
|
|
90
60
|
return chunks.join("");
|
|
91
61
|
};
|
|
92
|
-
var rwd = (root, selector, cell_width_px, cell_height_px, ...specs) => {
|
|
93
|
-
const main = vivify(root)[selector];
|
|
94
|
-
main.boxSizing = "border-box";
|
|
95
|
-
main.display = "block";
|
|
96
|
-
main.float = "left";
|
|
97
|
-
main.width = "100%";
|
|
98
|
-
main.height = `${cell_height_px}px`;
|
|
99
|
-
specs.sort(([a], [b]) => a - b);
|
|
100
|
-
for (let [max_width, width, height] of specs) {
|
|
101
|
-
const node = max_width === 1 ? main : vivify(root)[`@media(min-width:${cell_width_px * max_width}px)`][selector];
|
|
102
|
-
width ??= 1;
|
|
103
|
-
height ??= 1;
|
|
104
|
-
let gcd = 100 * width;
|
|
105
|
-
let tmp = max_width;
|
|
106
|
-
while (tmp > 0) {
|
|
107
|
-
[gcd, tmp] = [tmp, gcd % tmp];
|
|
108
|
-
}
|
|
109
|
-
const w_100_per_gcd = 100 * width / gcd;
|
|
110
|
-
node.width = max_width === gcd ? `${w_100_per_gcd}%` : `calc(${w_100_per_gcd}% / ${max_width / gcd})`;
|
|
111
|
-
node.height = `${cell_height_px * height}px`;
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
62
|
// src/nnn/csv_parse.ts
|
|
63
|
+
var MAIN_PATTERN = /\n|(?<!")("(?:[^"]|"")*")(?!")/g;
|
|
115
64
|
var csv_parse = (csv, separator = ",") => {
|
|
116
|
-
const main_pattern = /\n|(?<!")("(?:[^"]|"")*")(?!")/g;
|
|
117
65
|
const line_pattern = new RegExp(`${separator}|(?<!")\\s*"((?:[^"]|"")*)"\\s*(?!")`, "g");
|
|
118
|
-
return csv.replace(/\r/g, "").replace(/\n+$/, "").replace(
|
|
66
|
+
return csv.replace(/\r/g, "").replace(/\n+$/, "").replace(MAIN_PATTERN, (_, chunk) => chunk ?? "\r").split("\r").map((line) => line.replace(line_pattern, (_, chunk) => chunk == null ? "\r" : chunk.replace(/""/g, '"')).split("\r"));
|
|
119
67
|
};
|
|
120
|
-
// src/nnn/
|
|
121
|
-
var
|
|
122
|
-
|
|
68
|
+
// src/nnn/is_record.ts
|
|
69
|
+
var is_record = (arg) => typeof arg === "object" && arg != null && !is_array(arg);
|
|
70
|
+
|
|
123
71
|
// src/nnn/h.ts
|
|
124
72
|
var _h = (namespace_uri) => {
|
|
125
73
|
const create_element = namespace_uri == null ? (tag) => document.createElement(tag) : (tag) => document.createElementNS(namespace_uri, tag);
|
|
@@ -181,7 +129,6 @@ var _h = (namespace_uri) => {
|
|
|
181
129
|
};
|
|
182
130
|
var h = /* @__PURE__ */ _h();
|
|
183
131
|
var s = /* @__PURE__ */ _h("http://www.w3.org/2000/svg");
|
|
184
|
-
var svg_use = (id, ...args) => s("svg", ["use", { "xlink:href": "#" + id }], ...args);
|
|
185
132
|
|
|
186
133
|
// src/nnn/fix_pl_typography.ts
|
|
187
134
|
var TAGS_TO_SKIP = ["IFRAME", "NOSCRIPT", "PRE", "SCRIPT", "STYLE", "TEXTAREA"];
|
|
@@ -216,6 +163,8 @@ var fix_pl_typography = (node) => {
|
|
|
216
163
|
};
|
|
217
164
|
// src/nnn/has_own.ts
|
|
218
165
|
var has_own = (ref, key) => ref != null && Object.hasOwn(ref, key);
|
|
166
|
+
// src/nnn/is_finite_number.ts
|
|
167
|
+
var is_finite_number = Number.isFinite;
|
|
219
168
|
// src/nnn/js_on_parse.ts
|
|
220
169
|
var js_on_parse = (handlers, text) => JSON.parse(text, (key, value) => {
|
|
221
170
|
if (is_record(value)) {
|
|
@@ -234,13 +183,72 @@ var js_on_parse = (handlers, text) => JSON.parse(text, (key, value) => {
|
|
|
234
183
|
}
|
|
235
184
|
return value;
|
|
236
185
|
});
|
|
237
|
-
// src/nnn/
|
|
238
|
-
var
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
186
|
+
// src/nnn/monokai.ts
|
|
187
|
+
var monokai = {
|
|
188
|
+
":root": {
|
|
189
|
+
__bg: "#faf4f2",
|
|
190
|
+
__fg: "#29242a",
|
|
191
|
+
__comment: "#918c8e",
|
|
192
|
+
__identifier_1: "#7058be",
|
|
193
|
+
__identifier_2: "#269d69",
|
|
194
|
+
__identifier_3: "#1c8ca8",
|
|
195
|
+
__identifier_4: "#29242a",
|
|
196
|
+
__keyword_1: "#e14775",
|
|
197
|
+
__keyword_2: "#7058be",
|
|
198
|
+
__keyword_3: "#1c8ca8",
|
|
199
|
+
__number: "#7058be",
|
|
200
|
+
__operator: "#e14775",
|
|
201
|
+
__punctuation: "#918c8e",
|
|
202
|
+
__string: "#cc7a0a"
|
|
203
|
+
},
|
|
204
|
+
body$$monokai: {
|
|
205
|
+
backgroundColor: "var(--bg)",
|
|
206
|
+
color: "var(--fg)"
|
|
207
|
+
},
|
|
208
|
+
"code>span.": {
|
|
209
|
+
bg: { color: "var(--bg)" },
|
|
210
|
+
fg: { color: "var(--fg)" },
|
|
211
|
+
comment: { color: "var(--comment)" },
|
|
212
|
+
"identifier-1": { color: "var(--identifier-1)" },
|
|
213
|
+
"identifier-2": { color: "var(--identifier-2)" },
|
|
214
|
+
"identifier-3": { color: "var(--identifier-3)" },
|
|
215
|
+
"identifier-4": { color: "var(--identifier-4)" },
|
|
216
|
+
"keyword-1": { color: "var(--keyword-1)" },
|
|
217
|
+
"keyword-2": { color: "var(--keyword-2)" },
|
|
218
|
+
"keyword-3": { color: "var(--keyword-3)" },
|
|
219
|
+
number: { color: "var(--number)" },
|
|
220
|
+
operator: { color: "var(--operator)" },
|
|
221
|
+
punctuation: { color: "var(--punctuation)" },
|
|
222
|
+
string: { color: "var(--string)" }
|
|
223
|
+
},
|
|
224
|
+
pre: {
|
|
225
|
+
margin: 0,
|
|
226
|
+
overflow: "visible",
|
|
227
|
+
" code": {
|
|
228
|
+
fontFamily: '"Source Code Pro"',
|
|
229
|
+
padding: 0
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
"@media only screen and (prefers-color-scheme: dark)": {
|
|
233
|
+
":root": {
|
|
234
|
+
__bg: "#2d2a2e",
|
|
235
|
+
__fg: "#fcfcfa",
|
|
236
|
+
__comment: "#727072",
|
|
237
|
+
__identifier_1: "#ae81ff",
|
|
238
|
+
__identifier_2: "#a9dc76",
|
|
239
|
+
__identifier_3: "#66d9ef",
|
|
240
|
+
__identifier_4: "#fcfcfa",
|
|
241
|
+
__keyword_1: "#ff6188",
|
|
242
|
+
__keyword_2: "#ae81ff",
|
|
243
|
+
__keyword_3: "#66d9ef",
|
|
244
|
+
__number: "#ae81ff",
|
|
245
|
+
__operator: "#ff6188",
|
|
246
|
+
__punctuation: "#727072",
|
|
247
|
+
__string: "#ffd866"
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
// src/nnn/new_tokenizer.ts
|
|
244
252
|
var new_tokenizer = (decorator, ...specs) => (code) => {
|
|
245
253
|
const result = [];
|
|
246
254
|
while (code.length > 0) {
|
|
@@ -278,60 +286,80 @@ var new_tokenizer = (decorator, ...specs) => (code) => {
|
|
|
278
286
|
}
|
|
279
287
|
return result;
|
|
280
288
|
};
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
var
|
|
284
|
-
var
|
|
285
|
-
var
|
|
286
|
-
var
|
|
287
|
-
var
|
|
288
|
-
var
|
|
289
|
-
var
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
289
|
+
|
|
290
|
+
// src/nnn/nanolight_ts.ts
|
|
291
|
+
var COMMENT = "comment";
|
|
292
|
+
var IDENTIFIER_1 = "identifier-1";
|
|
293
|
+
var IDENTIFIER_2 = "identifier-2";
|
|
294
|
+
var IDENTIFIER_3 = "identifier-3";
|
|
295
|
+
var IDENTIFIER_4 = "identifier-4";
|
|
296
|
+
var KEYWORD_1 = "keyword-1";
|
|
297
|
+
var KEYWORD_2 = "keyword-2";
|
|
298
|
+
var KEYWORD_3 = "keyword-3";
|
|
299
|
+
var NUMBER = "number";
|
|
300
|
+
var OPERATOR = "operator";
|
|
301
|
+
var PUNCTUATION = "punctuation";
|
|
302
|
+
var STRING = "string";
|
|
303
|
+
var nanolight_ts = /* @__PURE__ */ new_tokenizer((chunk, name) => name != null ? ["span", { class: name }, chunk] : chunk, [STRING, /".*?"/], [STRING, /'.*?'/], [STRING, /`[\s\S]*?`/], [COMMENT, /\/\*[\s\S]*?\*\//], [COMMENT, /(?<!\\)\/\/.*?(?=\n)/], [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]);
|
|
304
|
+
// src/nnn/new_escape.ts
|
|
305
|
+
var escape_values = (escape_map, values) => values.map((value) => (value == null ? escape_map.get(value) : escape_map.get(value?.constructor))?.(value) ?? "");
|
|
306
|
+
var new_escape = (escape_map) => (template, ...values) => String.raw(template, ...escape_values(escape_map, values));
|
|
307
|
+
// src/nnn/new_noun_form.ts
|
|
308
|
+
var PLURAL_RULES = {};
|
|
309
|
+
var new_noun_form = (locale, forms) => (value) => forms[(PLURAL_RULES[locale] ??= new Intl.PluralRules(locale)).select(value)] ?? forms.other ?? "";
|
|
310
|
+
// src/nnn/omit.ts
|
|
311
|
+
var omit = (ref, keys) => Object.fromEntries(Object.entries(ref).filter(([key]) => !keys.includes(key)));
|
|
312
|
+
// src/nnn/pick.ts
|
|
313
|
+
var pick = (ref, keys) => Object.fromEntries(Object.entries(ref).filter(([key]) => keys.includes(key)));
|
|
314
|
+
// src/nnn/vivify.ts
|
|
315
|
+
var ARRAY_INDEX_REGEXP = /^(0|[1-9]\d*)$/;
|
|
316
|
+
var is_object = (ref) => typeof ref === "object";
|
|
317
|
+
var get_target = (parent, parent_key, key) => parent[parent_key] ??= is_string(key) && ARRAY_INDEX_REGEXP.test(key) ? [] : {};
|
|
318
|
+
var _vivify = (parent, parent_key) => {
|
|
319
|
+
return parent != null && is_object(parent) ? new Proxy(parent, {
|
|
320
|
+
get(_, key) {
|
|
321
|
+
const target = get_target(parent, parent_key, key);
|
|
322
|
+
const value = target[key];
|
|
323
|
+
return is_string(key) && is_object(target) && (value == null || is_object(value)) ? _vivify(target, key) : value;
|
|
324
|
+
},
|
|
325
|
+
set(_, key, value) {
|
|
326
|
+
const target = get_target(parent, parent_key, key);
|
|
327
|
+
target[key] = value;
|
|
328
|
+
return true;
|
|
329
|
+
},
|
|
330
|
+
deleteProperty(_, key) {
|
|
331
|
+
const target = get_target(parent, parent_key, key);
|
|
332
|
+
return delete target[key];
|
|
320
333
|
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
334
|
+
}) : parent?.[parent_key];
|
|
335
|
+
};
|
|
336
|
+
var vivify = (ref) => _vivify({ _: ref }, "_");
|
|
337
|
+
|
|
338
|
+
// src/nnn/rwd.ts
|
|
339
|
+
var rwd = (root, selector, cell_width_px, cell_height_px, ...specs) => {
|
|
340
|
+
const main = vivify(root)[selector];
|
|
341
|
+
main.boxSizing = "border-box";
|
|
342
|
+
main.display = "block";
|
|
343
|
+
main.float = "left";
|
|
344
|
+
main.width = "100%";
|
|
345
|
+
main.height = `${cell_height_px}px`;
|
|
346
|
+
specs.sort(([a], [b]) => a - b);
|
|
347
|
+
for (let [max_width, width, height] of specs) {
|
|
348
|
+
const node = max_width === 1 ? main : vivify(root)[`@media(min-width:${cell_width_px * max_width}px)`][selector];
|
|
349
|
+
width ??= 1;
|
|
350
|
+
height ??= 1;
|
|
351
|
+
let gcd = 100 * width;
|
|
352
|
+
let tmp = max_width;
|
|
353
|
+
while (tmp > 0) {
|
|
354
|
+
[gcd, tmp] = [tmp, gcd % tmp];
|
|
332
355
|
}
|
|
356
|
+
const w_100_per_gcd = 100 * width / gcd;
|
|
357
|
+
node.width = max_width === gcd ? `${w_100_per_gcd}%` : `calc(${w_100_per_gcd}% / ${max_width / gcd})`;
|
|
358
|
+
node.height = `${cell_height_px * height}px`;
|
|
333
359
|
}
|
|
334
360
|
};
|
|
361
|
+
// src/nnn/svg_use.ts
|
|
362
|
+
var svg_use = (id, ...args) => s("svg", ["use", { "xlink:href": "#" + id }], ...args);
|
|
335
363
|
// src/nnn/uuid_v1.ts
|
|
336
364
|
var ZEROS = /* @__PURE__ */ "0".repeat(16);
|
|
337
365
|
var counter = 0;
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
# nnn
|
|
2
2
|
|
|
3
|
-
A collection of Jackens’ JavaScript helper utilities.
|
|
3
|
+
A collection of Jackens’ JavaScript helper utilities (version: `2026.2.18`).
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
bun i @jackens/nnn
|
|
8
|
+
bun i @jackens/nnn
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
or
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npm i @jackens/nnn
|
|
9
15
|
```
|
|
10
16
|
|
|
11
17
|
## Usage
|
|
12
18
|
|
|
13
19
|
```js
|
|
14
20
|
import {
|
|
15
|
-
CNode,
|
|
16
|
-
CRoot,
|
|
17
|
-
EscapeMap,
|
|
18
|
-
HArgs,
|
|
19
|
-
HArgs1,
|
|
20
21
|
c,
|
|
21
22
|
csv_parse,
|
|
22
23
|
escape_values,
|
|
@@ -41,7 +42,7 @@ import {
|
|
|
41
42
|
svg_use,
|
|
42
43
|
uuid_v1,
|
|
43
44
|
vivify
|
|
44
|
-
} from '@jackens/nnn' // './node_modules/@jackens/nnn/nnn.js'
|
|
45
|
+
} from '@jackens/nnn' // or './node_modules/@jackens/nnn/nnn.js'
|
|
45
46
|
```
|
|
46
47
|
|
|
47
48
|
## Exports
|
|
@@ -55,8 +56,7 @@ import {
|
|
|
55
56
|
- [`csv_parse`](#csv_parse): Parses a CSV string into a two-dimensional array of strings.
|
|
56
57
|
- [`escape_values`](#escape_values): Escapes an array of values using the provided escape map.
|
|
57
58
|
- [`fix_pl_typography`](#fix_pl_typography): Applies Polish-specific typographic corrections to a DOM subtree.
|
|
58
|
-
- [`h`](#h): A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper
|
|
59
|
-
for creating and modifying `HTMLElement`s (see also [`s`](#s)).
|
|
59
|
+
- [`h`](#h): A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also [`s`](#s)).
|
|
60
60
|
- [`has_own`](#has_own): Checks whether an object has the specified key as its own property.
|
|
61
61
|
- [`is_array`](#is_array): Checks whether the argument is an array.
|
|
62
62
|
- [`is_finite_number`](#is_finite_number): Checks whether the argument is a finite number (excludes `±Infinity` and `NaN`).
|
|
@@ -72,8 +72,7 @@ import {
|
|
|
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
|
-
- [`s`](#s): A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper
|
|
76
|
-
for creating and modifying `SVGElement`s (see also [`h`](#h)).
|
|
75
|
+
- [`s`](#s): A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also [`h`](#h)).
|
|
77
76
|
- [`svg_use`](#svg_use): Shorthand for creating an SVG element with a `<use>` child referencing an icon by ID.
|
|
78
77
|
- [`uuid_v1`](#uuid_v1): Generates a UUID v1 (time-based) identifier.
|
|
79
78
|
- [`vivify`](#vivify): A Proxy-based helper for auto-vivification of nested object structures.
|
|
@@ -156,7 +155,7 @@ A CSS string representing the compiled rules.
|
|
|
156
155
|
#### Usage Examples
|
|
157
156
|
|
|
158
157
|
```ts
|
|
159
|
-
const
|
|
158
|
+
const actual_1 = c({
|
|
160
159
|
a: {
|
|
161
160
|
color: 'red',
|
|
162
161
|
margin: 1,
|
|
@@ -165,7 +164,7 @@ const actual = c({
|
|
|
165
164
|
}
|
|
166
165
|
})
|
|
167
166
|
|
|
168
|
-
const
|
|
167
|
+
const expected_1 = `
|
|
169
168
|
a{
|
|
170
169
|
color:red;
|
|
171
170
|
margin:1
|
|
@@ -178,11 +177,9 @@ a{
|
|
|
178
177
|
padding:1
|
|
179
178
|
}`.replace(/\n\s*/g, '')
|
|
180
179
|
|
|
181
|
-
expect(
|
|
182
|
-
```
|
|
180
|
+
expect(actual_1).to.equal(expected_1)
|
|
183
181
|
|
|
184
|
-
|
|
185
|
-
const actual = c({
|
|
182
|
+
const actual_2 = c({
|
|
186
183
|
a: {
|
|
187
184
|
'.b': {
|
|
188
185
|
color: 'red',
|
|
@@ -193,7 +190,7 @@ const actual = c({
|
|
|
193
190
|
}
|
|
194
191
|
})
|
|
195
192
|
|
|
196
|
-
const
|
|
193
|
+
const expected_2 = `
|
|
197
194
|
a.b{
|
|
198
195
|
color:red;
|
|
199
196
|
margin:1
|
|
@@ -206,11 +203,9 @@ a.b{
|
|
|
206
203
|
padding:1
|
|
207
204
|
}`.replace(/\n\s*/g, '')
|
|
208
205
|
|
|
209
|
-
expect(
|
|
210
|
-
```
|
|
206
|
+
expect(actual_2).to.equal(expected_2)
|
|
211
207
|
|
|
212
|
-
|
|
213
|
-
const actual = c({
|
|
208
|
+
const actual_3 = c({
|
|
214
209
|
'@font-face$$1': {
|
|
215
210
|
fontFamily: 'Jackens',
|
|
216
211
|
src$$1: 'url(otf/jackens.otf)',
|
|
@@ -239,7 +234,7 @@ const actual = c({
|
|
|
239
234
|
}
|
|
240
235
|
})
|
|
241
236
|
|
|
242
|
-
const
|
|
237
|
+
const expected_3 = `
|
|
243
238
|
@font-face{
|
|
244
239
|
font-family:Jackens;
|
|
245
240
|
src:url(otf/jackens.otf);
|
|
@@ -281,11 +276,9 @@ div.c2{
|
|
|
281
276
|
}
|
|
282
277
|
}`.replace(/\n\s*/g, '')
|
|
283
278
|
|
|
284
|
-
expect(
|
|
285
|
-
```
|
|
279
|
+
expect(actual_3).to.equal(expected_3)
|
|
286
280
|
|
|
287
|
-
|
|
288
|
-
const actual = c({
|
|
281
|
+
const actual_4 = c({
|
|
289
282
|
a: {
|
|
290
283
|
'.b,.c': {
|
|
291
284
|
margin: 1,
|
|
@@ -296,7 +289,7 @@ const actual = c({
|
|
|
296
289
|
}
|
|
297
290
|
})
|
|
298
291
|
|
|
299
|
-
const
|
|
292
|
+
const expected_4 = `
|
|
300
293
|
a.b,a.c{
|
|
301
294
|
margin:1
|
|
302
295
|
}
|
|
@@ -304,11 +297,9 @@ a.b.d,a.c.d{
|
|
|
304
297
|
margin:2
|
|
305
298
|
}`.replace(/\n\s*/g, '')
|
|
306
299
|
|
|
307
|
-
expect(
|
|
308
|
-
```
|
|
300
|
+
expect(actual_4).to.equal(expected_4)
|
|
309
301
|
|
|
310
|
-
|
|
311
|
-
const actual = c({
|
|
302
|
+
const actual_5 = c({
|
|
312
303
|
'.b,.c': {
|
|
313
304
|
margin: 1,
|
|
314
305
|
'.d': {
|
|
@@ -317,7 +308,7 @@ const actual = c({
|
|
|
317
308
|
}
|
|
318
309
|
})
|
|
319
310
|
|
|
320
|
-
const
|
|
311
|
+
const expected_5 = `
|
|
321
312
|
.b,.c{
|
|
322
313
|
margin:1
|
|
323
314
|
}
|
|
@@ -325,11 +316,9 @@ const expected = `
|
|
|
325
316
|
margin:2
|
|
326
317
|
}`.replace(/\n\s*/g, '')
|
|
327
318
|
|
|
328
|
-
expect(
|
|
329
|
-
```
|
|
319
|
+
expect(actual_5).to.equal(expected_5)
|
|
330
320
|
|
|
331
|
-
|
|
332
|
-
const actual = c({
|
|
321
|
+
const actual_6 = c({
|
|
333
322
|
'.a,.b': {
|
|
334
323
|
margin: 1,
|
|
335
324
|
'.c,.d': {
|
|
@@ -338,7 +327,7 @@ const actual = c({
|
|
|
338
327
|
}
|
|
339
328
|
})
|
|
340
329
|
|
|
341
|
-
const
|
|
330
|
+
const expected_6 = `
|
|
342
331
|
.a,.b{
|
|
343
332
|
margin:1
|
|
344
333
|
}
|
|
@@ -346,7 +335,7 @@ const expected = `
|
|
|
346
335
|
margin:2
|
|
347
336
|
}`.replace(/\n\s*/g, '')
|
|
348
337
|
|
|
349
|
-
expect(
|
|
338
|
+
expect(actual_6).to.equal(expected_6)
|
|
350
339
|
```
|
|
351
340
|
|
|
352
341
|
### csv_parse
|
|
@@ -382,6 +371,7 @@ yyy",zzz
|
|
|
382
371
|
42 , "42" , 17
|
|
383
372
|
|
|
384
373
|
`
|
|
374
|
+
|
|
385
375
|
expect(csv_parse(text)).to.deep.equal([
|
|
386
376
|
['aaa\n"aaa"\naaa', 'bbb', 'ccc,ccc'],
|
|
387
377
|
['xxx,xxx', 'yyy\nyyy', 'zzz'],
|
|
@@ -448,8 +438,7 @@ const h: {
|
|
|
448
438
|
};
|
|
449
439
|
```
|
|
450
440
|
|
|
451
|
-
A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper
|
|
452
|
-
for creating and modifying `HTMLElement`s (see also [`s`](#s)).
|
|
441
|
+
A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also [`s`](#s)).
|
|
453
442
|
|
|
454
443
|
#### tag_or_node
|
|
455
444
|
|
|
@@ -475,49 +464,41 @@ The created or modified `HTMLElement`.
|
|
|
475
464
|
```ts
|
|
476
465
|
const b = h('b')
|
|
477
466
|
|
|
478
|
-
expect(b.outerHTML).to.
|
|
467
|
+
expect(b.outerHTML).to.equal('<b></b>')
|
|
479
468
|
|
|
480
469
|
const i = h('i', 'text')
|
|
481
470
|
|
|
482
471
|
h(b, i)
|
|
483
472
|
|
|
484
|
-
expect(i.outerHTML).to.
|
|
485
|
-
expect(b.outerHTML).to.
|
|
473
|
+
expect(i.outerHTML).to.equal('<i>text</i>')
|
|
474
|
+
expect(b.outerHTML).to.equal('<b><i>text</i></b>')
|
|
486
475
|
|
|
487
476
|
h(i, { $className: 'some class' })
|
|
488
477
|
|
|
489
|
-
expect(i.outerHTML).to.
|
|
490
|
-
expect(b.outerHTML).to.
|
|
491
|
-
```
|
|
478
|
+
expect(i.outerHTML).to.equal('<i class="some class">text</i>')
|
|
479
|
+
expect(b.outerHTML).to.equal('<b><i class="some class">text</i></b>')
|
|
492
480
|
|
|
493
|
-
|
|
494
|
-
expect(h('span', 'text').outerHTML).to.
|
|
495
|
-
expect(h('span', { $innerText: 'text' }).outerHTML).to.deep.equal('<span>text</span>')
|
|
496
|
-
```
|
|
481
|
+
expect(h('span', 'text').outerHTML).to.equal('<span>text</span>')
|
|
482
|
+
expect(h('span', { $innerText: 'text' }).outerHTML).to.equal('<span>text</span>')
|
|
497
483
|
|
|
498
|
-
|
|
499
|
-
expect(h('span',
|
|
500
|
-
expect(h('span', 42).outerHTML).to.deep.equal('<span>42</span>')
|
|
501
|
-
```
|
|
484
|
+
expect(h('span', '42').outerHTML).to.equal('<span>42</span>')
|
|
485
|
+
expect(h('span', 42).outerHTML).to.equal('<span>42</span>')
|
|
502
486
|
|
|
503
|
-
```ts
|
|
504
487
|
expect(h('div', { style: 'margin:0;padding:0' }).outerHTML)
|
|
505
|
-
.to.
|
|
488
|
+
.to.equal('<div style="margin:0;padding:0"></div>')
|
|
506
489
|
expect(h('div', { $style: 'margin:0;padding:0' }).outerHTML)
|
|
507
|
-
.to.
|
|
490
|
+
.to.equal('<div style="margin: 0px; padding: 0px;"></div>')
|
|
508
491
|
expect(h('div', { $style: { margin: 0, padding: 0 } }).outerHTML)
|
|
509
|
-
.to.
|
|
510
|
-
```
|
|
492
|
+
.to.equal('<div style="margin: 0px; padding: 0px;"></div>')
|
|
511
493
|
|
|
512
|
-
```ts
|
|
513
494
|
const input1 = h('input', { value: 42 })
|
|
514
495
|
const input2 = h('input', { $value: '42' })
|
|
515
496
|
|
|
516
|
-
expect(input1.value).to.
|
|
517
|
-
expect(input2.value).to.
|
|
497
|
+
expect(input1.value).to.equal('42')
|
|
498
|
+
expect(input2.value).to.equal('42')
|
|
518
499
|
|
|
519
|
-
expect(input1.outerHTML).to.
|
|
520
|
-
expect(input2.outerHTML).to.
|
|
500
|
+
expect(input1.outerHTML).to.equal('<input value="42">')
|
|
501
|
+
expect(input2.outerHTML).to.equal('<input>')
|
|
521
502
|
|
|
522
503
|
const checkbox1 = h('input', { type: 'checkbox', checked: true })
|
|
523
504
|
const checkbox2 = h('input', { type: 'checkbox', $checked: true })
|
|
@@ -525,11 +506,9 @@ const checkbox2 = h('input', { type: 'checkbox', $checked: true })
|
|
|
525
506
|
expect(checkbox1.checked).to.be.true
|
|
526
507
|
expect(checkbox2.checked).to.be.true
|
|
527
508
|
|
|
528
|
-
expect(checkbox1.outerHTML).to.
|
|
529
|
-
expect(checkbox2.outerHTML).to.
|
|
530
|
-
```
|
|
509
|
+
expect(checkbox1.outerHTML).to.equal('<input type="checkbox" checked="">')
|
|
510
|
+
expect(checkbox2.outerHTML).to.equal('<input type="checkbox">')
|
|
531
511
|
|
|
532
|
-
```ts
|
|
533
512
|
const div = h('div')
|
|
534
513
|
|
|
535
514
|
expect(div.key).to.be.undefined
|
|
@@ -700,6 +679,7 @@ expect(is_record(new Number(42))).to.be.true
|
|
|
700
679
|
expect(is_record(new String('42'))).to.be.true
|
|
701
680
|
|
|
702
681
|
class Foo_Bar { }
|
|
682
|
+
|
|
703
683
|
expect(is_record(new Foo_Bar())).to.be.true
|
|
704
684
|
```
|
|
705
685
|
|
|
@@ -810,15 +790,6 @@ const monokai: CRoot;
|
|
|
810
790
|
|
|
811
791
|
A Monokai-inspired color scheme for use with the [`c`](#c) helper and [`nanolight_ts`](#nanolight_ts) tokenizer.
|
|
812
792
|
|
|
813
|
-
Defines CSS custom properties for eight colors (`--black`, `--blue`, `--green`, `--grey`,
|
|
814
|
-
`--purple`, `--red`, `--white`, `--yellow`) with both light and dark mode variants.
|
|
815
|
-
|
|
816
|
-
#### Remarks
|
|
817
|
-
|
|
818
|
-
- In light mode, `--black` is a light background and `--white` is dark text.
|
|
819
|
-
- In dark mode (via `prefers-color-scheme: dark`), the palette inverts to a dark background with light text.
|
|
820
|
-
- Includes base styles for `body`, `pre` and `code>span.*` (syntax highlighting).
|
|
821
|
-
|
|
822
793
|
### nanolight_ts
|
|
823
794
|
|
|
824
795
|
```ts
|
|
@@ -841,25 +812,25 @@ An array of [`HArgs1`](#HArgs1) elements suitable for rendering with [`h`](#h).
|
|
|
841
812
|
const code_js = "const answer_to_life_the_universe_and_everything = { 42: 42 }['42'] /* 42 */"
|
|
842
813
|
|
|
843
814
|
expect(nanolight_ts(code_js)).to.deep.equal([
|
|
844
|
-
['span', { class: '
|
|
815
|
+
['span', { class: 'keyword-1' }, 'const'],
|
|
845
816
|
' ',
|
|
846
|
-
['span', { class: '
|
|
817
|
+
['span', { class: 'identifier-4' }, 'answer_to_life_the_universe_and_everything'],
|
|
847
818
|
' ',
|
|
848
|
-
['span', { class: '
|
|
819
|
+
['span', { class: 'operator' }, '='],
|
|
849
820
|
' ',
|
|
850
|
-
['span', { class: '
|
|
821
|
+
['span', { class: 'punctuation' }, '{'],
|
|
851
822
|
' ',
|
|
852
|
-
['span', { class: '
|
|
853
|
-
['span', { class: '
|
|
823
|
+
['span', { class: 'number' }, '42'],
|
|
824
|
+
['span', { class: 'operator' }, ':'],
|
|
854
825
|
' ',
|
|
855
|
-
['span', { class: '
|
|
826
|
+
['span', { class: 'number' }, '42'],
|
|
856
827
|
' ',
|
|
857
|
-
['span', { class: '
|
|
858
|
-
['span', { class: '
|
|
859
|
-
['span', { class: '
|
|
860
|
-
['span', { class: '
|
|
828
|
+
['span', { class: 'punctuation' }, '}'],
|
|
829
|
+
['span', { class: 'punctuation' }, '['],
|
|
830
|
+
['span', { class: 'string' }, "'42'"],
|
|
831
|
+
['span', { class: 'punctuation' }, ']'],
|
|
861
832
|
' ',
|
|
862
|
-
['span', { class: '
|
|
833
|
+
['span', { class: 'comment' }, '/* 42 */']
|
|
863
834
|
])
|
|
864
835
|
```
|
|
865
836
|
|
|
@@ -904,7 +875,7 @@ const expected = `
|
|
|
904
875
|
FROM table_name
|
|
905
876
|
WHERE column_name IN (b'1', NULL, NULL, 42, '42', '4''2', '1980-03-31 04:30:00')`
|
|
906
877
|
|
|
907
|
-
expect(actual).to.
|
|
878
|
+
expect(actual).to.equal(expected)
|
|
908
879
|
```
|
|
909
880
|
|
|
910
881
|
### new_noun_form
|
|
@@ -915,8 +886,8 @@ const new_noun_form: (locale: string, forms: Partial<Record<Intl.LDMLPluralRule,
|
|
|
915
886
|
|
|
916
887
|
Creates a function that returns the appropriate noun form based on a numeric value using `Intl.PluralRules`.
|
|
917
888
|
|
|
918
|
-
Different languages have different plural rules. The `Intl.PluralRules` API provides
|
|
919
|
-
|
|
889
|
+
Different languages have different plural rules. The `Intl.PluralRules` API provides locale-aware plural category selection.
|
|
890
|
+
Possible categories are:
|
|
920
891
|
|
|
921
892
|
- `zero`: for zero items (used in some languages like Arabic, Latvian)
|
|
922
893
|
- `one`: for singular (e.g., 1 item)
|
|
@@ -943,17 +914,17 @@ A function that takes a numeric value and returns the appropriate noun form.
|
|
|
943
914
|
```ts
|
|
944
915
|
const auto = new_noun_form('pl', { one: 'auto', few: 'auta', other: 'aut' })
|
|
945
916
|
|
|
946
|
-
expect(auto(0)).to.
|
|
947
|
-
expect(auto(1)).to.
|
|
948
|
-
expect(auto(17)).to.
|
|
949
|
-
expect(auto(42)).to.
|
|
917
|
+
expect(auto(0)).to.equal('aut')
|
|
918
|
+
expect(auto(1)).to.equal('auto')
|
|
919
|
+
expect(auto(17)).to.equal('aut')
|
|
920
|
+
expect(auto(42)).to.equal('auta')
|
|
950
921
|
|
|
951
922
|
const car = new_noun_form('en', { one: 'car', other: 'cars' })
|
|
952
923
|
|
|
953
|
-
expect(car(0)).to.
|
|
954
|
-
expect(car(1)).to.
|
|
955
|
-
expect(car(17)).to.
|
|
956
|
-
expect(car(42)).to.
|
|
924
|
+
expect(car(0)).to.equal('cars')
|
|
925
|
+
expect(car(1)).to.equal('car')
|
|
926
|
+
expect(car(17)).to.equal('cars')
|
|
927
|
+
expect(car(42)).to.equal('cars')
|
|
957
928
|
```
|
|
958
929
|
|
|
959
930
|
### new_tokenizer
|
|
@@ -1011,9 +982,9 @@ A new object without the specified keys.
|
|
|
1011
982
|
#### Usage Examples
|
|
1012
983
|
|
|
1013
984
|
```ts
|
|
1014
|
-
const
|
|
985
|
+
const ref = { a: 42, b: '42', c: 17 }
|
|
1015
986
|
|
|
1016
|
-
expect(omit(
|
|
987
|
+
expect(omit(ref, ['c'])).to.deep.equal({ a: 42, b: '42' })
|
|
1017
988
|
```
|
|
1018
989
|
|
|
1019
990
|
### pick
|
|
@@ -1041,9 +1012,9 @@ A new object with only the specified keys.
|
|
|
1041
1012
|
#### Usage Examples
|
|
1042
1013
|
|
|
1043
1014
|
```ts
|
|
1044
|
-
const
|
|
1015
|
+
const ref = { a: 42, b: '42', c: 17 }
|
|
1045
1016
|
|
|
1046
|
-
expect(pick(
|
|
1017
|
+
expect(pick(ref, ['a', 'b'])).to.deep.equal({ a: 42, b: '42' })
|
|
1047
1018
|
```
|
|
1048
1019
|
|
|
1049
1020
|
### rwd
|
|
@@ -1134,8 +1105,7 @@ const s: {
|
|
|
1134
1105
|
};
|
|
1135
1106
|
```
|
|
1136
1107
|
|
|
1137
|
-
A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper
|
|
1138
|
-
for creating and modifying `SVGElement`s (see also [`h`](#h)).
|
|
1108
|
+
A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also [`h`](#h)).
|
|
1139
1109
|
|
|
1140
1110
|
#### tag_or_node
|
|
1141
1111
|
|
|
@@ -1206,41 +1176,37 @@ for (let i = 1; i <= 22136; ++i) {
|
|
|
1206
1176
|
const uuid = uuid_v1()
|
|
1207
1177
|
|
|
1208
1178
|
if (i === 1) {
|
|
1209
|
-
expect(uuid.split('-')[3]).to.
|
|
1179
|
+
expect(uuid.split('-')[3]).to.equal('8001')
|
|
1210
1180
|
}
|
|
1211
1181
|
|
|
1212
1182
|
if (i === 4095) {
|
|
1213
|
-
expect(uuid.split('-')[3]).to.
|
|
1183
|
+
expect(uuid.split('-')[3]).to.equal('8fff')
|
|
1214
1184
|
}
|
|
1215
1185
|
|
|
1216
1186
|
if (i === 4096) {
|
|
1217
|
-
expect(uuid.split('-')[3]).to.
|
|
1187
|
+
expect(uuid.split('-')[3]).to.equal('9000')
|
|
1218
1188
|
}
|
|
1219
1189
|
|
|
1220
1190
|
if (i === 9029) {
|
|
1221
|
-
expect(uuid.split('-')[3]).to.
|
|
1191
|
+
expect(uuid.split('-')[3]).to.equal('a345')
|
|
1222
1192
|
}
|
|
1223
1193
|
|
|
1224
1194
|
if (i === 13398) {
|
|
1225
|
-
expect(uuid.split('-')[3]).to.
|
|
1195
|
+
expect(uuid.split('-')[3]).to.equal('b456')
|
|
1226
1196
|
}
|
|
1227
1197
|
|
|
1228
1198
|
if (i === 16384) {
|
|
1229
|
-
expect(uuid.split('-')[3]).to.
|
|
1199
|
+
expect(uuid.split('-')[3]).to.equal('8000')
|
|
1230
1200
|
}
|
|
1231
1201
|
|
|
1232
1202
|
if (i === 17767) {
|
|
1233
|
-
expect(uuid.split('-')[3]).to.
|
|
1203
|
+
expect(uuid.split('-')[3]).to.equal('8567')
|
|
1234
1204
|
}
|
|
1235
1205
|
}
|
|
1236
|
-
```
|
|
1237
1206
|
|
|
1238
|
-
|
|
1239
|
-
expect(uuid_v1(new Date(), '
|
|
1240
|
-
expect(uuid_v1(new Date(), '123456789').split('-')[4]).to.deep.equal('000123456789')
|
|
1241
|
-
```
|
|
1207
|
+
expect(uuid_v1(new Date(), '000123456789abc').split('-')[4]).to.equal('123456789abc')
|
|
1208
|
+
expect(uuid_v1(new Date(), '123456789').split('-')[4]).to.equal('000123456789')
|
|
1242
1209
|
|
|
1243
|
-
```ts
|
|
1244
1210
|
expect(uuid_v1(new Date(323325000000)).startsWith('c1399400-9a71-11bd')).to.be.true
|
|
1245
1211
|
```
|
|
1246
1212
|
|
|
@@ -1258,14 +1224,14 @@ Accessing, assigning, or deleting any nested property on the returned proxy auto
|
|
|
1258
1224
|
Intermediates of the last level in a get-only property chain are NOT auto-created.
|
|
1259
1225
|
For example, `vivify(ref).one.two` will create `ref.one` as `{}`, but will NOT create `ref.one.two`.
|
|
1260
1226
|
Only when a deeper access, assignment, or deletion occurs
|
|
1261
|
-
(e.g. `vivify(ref).one.two
|
|
1227
|
+
(e.g. `delete vivify(ref).one.two.three` or `vivify(ref).one.two.three = 4`) will `ref.one.two` be materialized.
|
|
1262
1228
|
|
|
1263
1229
|
When traversal reaches a primitive value, no auto-creation happens;
|
|
1264
1230
|
the primitive’s own property is returned instead
|
|
1265
1231
|
(e.g. accessing `.toString.name` on a number yields `'toString'` without modifying the underlying structure).
|
|
1266
1232
|
|
|
1267
1233
|
Deletion on a non-existing intermediate path will auto-create intermediates up to the parent of the deleted key
|
|
1268
|
-
(e.g. `delete vivify(ref).
|
|
1234
|
+
(e.g. `delete vivify(ref).one.two.three` will create `ref.one.two` as `{}` if it does not exist).
|
|
1269
1235
|
|
|
1270
1236
|
#### ref
|
|
1271
1237
|
|
|
@@ -1280,140 +1246,83 @@ A proxy that auto-creates nested objects/arrays on property access.
|
|
|
1280
1246
|
```ts
|
|
1281
1247
|
const ref: any = {}
|
|
1282
1248
|
|
|
1283
|
-
vivify(ref).one.two[
|
|
1249
|
+
vivify(ref).one.two[3][4]
|
|
1284
1250
|
|
|
1285
1251
|
expect(ref).to.deep.equal({
|
|
1286
1252
|
one: {
|
|
1287
|
-
two: [
|
|
1288
|
-
undefined,
|
|
1289
|
-
[undefined, undefined, 42]
|
|
1290
|
-
]
|
|
1253
|
+
two: [undefined, undefined, undefined, []]
|
|
1291
1254
|
}
|
|
1292
1255
|
})
|
|
1293
1256
|
|
|
1294
|
-
vivify(ref).one.two[
|
|
1257
|
+
vivify(ref).one.two[3][4] = 5
|
|
1295
1258
|
|
|
1296
1259
|
expect(ref).to.deep.equal({
|
|
1297
1260
|
one: {
|
|
1298
|
-
two: [
|
|
1299
|
-
undefined,
|
|
1300
|
-
[undefined, undefined, 42, 42]
|
|
1301
|
-
]
|
|
1261
|
+
two: [undefined, undefined, undefined, [undefined, undefined, undefined, undefined, 5]]
|
|
1302
1262
|
}
|
|
1303
1263
|
})
|
|
1304
1264
|
|
|
1305
|
-
vivify(ref).one.two[
|
|
1265
|
+
vivify(ref).one.two[3].length = 1
|
|
1306
1266
|
|
|
1307
1267
|
expect(ref).to.deep.equal({
|
|
1308
1268
|
one: {
|
|
1309
|
-
two: [
|
|
1310
|
-
undefined,
|
|
1311
|
-
42
|
|
1312
|
-
]
|
|
1269
|
+
two: [undefined, undefined, undefined, [undefined]]
|
|
1313
1270
|
}
|
|
1314
1271
|
})
|
|
1315
1272
|
|
|
1316
|
-
vivify(ref).one.two[3]
|
|
1273
|
+
vivify(ref).one.two[3] = 4
|
|
1317
1274
|
|
|
1318
1275
|
expect(ref).to.deep.equal({
|
|
1319
1276
|
one: {
|
|
1320
|
-
two: [
|
|
1321
|
-
undefined,
|
|
1322
|
-
42,
|
|
1323
|
-
undefined,
|
|
1324
|
-
[42]
|
|
1325
|
-
]
|
|
1277
|
+
two: [undefined, undefined, undefined, 4]
|
|
1326
1278
|
}
|
|
1327
1279
|
})
|
|
1328
1280
|
|
|
1329
|
-
vivify(ref).one.two
|
|
1281
|
+
expect(vivify(ref).one.two.length).to.equal(4)
|
|
1330
1282
|
|
|
1331
1283
|
expect(ref).to.deep.equal({
|
|
1332
1284
|
one: {
|
|
1333
|
-
two: [
|
|
1334
|
-
undefined,
|
|
1335
|
-
42,
|
|
1336
|
-
undefined,
|
|
1337
|
-
[42, undefined]
|
|
1338
|
-
]
|
|
1285
|
+
two: [undefined, undefined, undefined, 4]
|
|
1339
1286
|
}
|
|
1340
1287
|
})
|
|
1341
1288
|
|
|
1342
|
-
vivify(ref).one.two =
|
|
1289
|
+
vivify(ref).one.two = 3
|
|
1343
1290
|
|
|
1344
|
-
expect(ref).to.deep.equal({
|
|
1345
|
-
one: {
|
|
1346
|
-
two: 12
|
|
1347
|
-
}
|
|
1348
|
-
})
|
|
1291
|
+
expect(ref).to.deep.equal({ one: { two: 3 } })
|
|
1349
1292
|
|
|
1350
1293
|
vivify(ref).one.two = undefined
|
|
1351
1294
|
|
|
1352
|
-
expect(ref).to.deep.equal({
|
|
1353
|
-
one: {
|
|
1354
|
-
two: undefined
|
|
1355
|
-
}
|
|
1356
|
-
})
|
|
1295
|
+
expect(ref).to.deep.equal({ one: { two: undefined } })
|
|
1357
1296
|
|
|
1358
1297
|
delete vivify(ref).one.two
|
|
1359
1298
|
|
|
1360
|
-
expect(ref).to.deep.equal({
|
|
1361
|
-
|
|
1362
|
-
|
|
1299
|
+
expect(ref).to.deep.equal({ one: {} })
|
|
1300
|
+
|
|
1301
|
+
expect(vivify(ref).one.toString instanceof Function).to.be.true
|
|
1302
|
+
|
|
1303
|
+
expect(vivify(ref).one.toString.name).to.equal('toString')
|
|
1304
|
+
|
|
1305
|
+
expect(ref).to.deep.equal({ one: {} })
|
|
1363
1306
|
|
|
1364
1307
|
delete vivify(ref).one.two.three
|
|
1365
1308
|
|
|
1366
|
-
expect(ref).to.deep.equal({
|
|
1367
|
-
one: {
|
|
1368
|
-
two: {}
|
|
1369
|
-
}
|
|
1370
|
-
})
|
|
1309
|
+
expect(ref).to.deep.equal({ one: { two: {} } })
|
|
1371
1310
|
|
|
1372
1311
|
vivify(ref).one.two.three.four
|
|
1373
1312
|
|
|
1374
|
-
expect(ref).to.deep.equal({
|
|
1375
|
-
one: {
|
|
1376
|
-
two: {
|
|
1377
|
-
three: {}
|
|
1378
|
-
}
|
|
1379
|
-
}
|
|
1380
|
-
})
|
|
1313
|
+
expect(ref).to.deep.equal({ one: { two: { three: {} } } })
|
|
1381
1314
|
|
|
1382
1315
|
vivify(ref).one.two[3]
|
|
1383
1316
|
|
|
1384
|
-
expect(ref).to.deep.equal({
|
|
1385
|
-
one: {
|
|
1386
|
-
two: {
|
|
1387
|
-
three: {}
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
})
|
|
1317
|
+
expect(ref).to.deep.equal({ one: { two: { three: {} } } })
|
|
1391
1318
|
|
|
1392
|
-
vivify(ref).one.two.three.four =
|
|
1319
|
+
vivify(ref).one.two.three.four = 5
|
|
1393
1320
|
|
|
1394
|
-
expect(ref).to.deep.equal({
|
|
1395
|
-
one: {
|
|
1396
|
-
two: {
|
|
1397
|
-
three: {
|
|
1398
|
-
four: 42
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1402
|
-
})
|
|
1321
|
+
expect(ref).to.deep.equal({ one: { two: { three: { four: 5 } } } })
|
|
1403
1322
|
|
|
1404
|
-
|
|
1323
|
+
expect(vivify(ref).one.two.three.four.toString.name).to.equal('toString')
|
|
1405
1324
|
|
|
1406
|
-
expect(
|
|
1407
|
-
|
|
1408
|
-
expect(ref).to.deep.equal({
|
|
1409
|
-
one: {
|
|
1410
|
-
two: {
|
|
1411
|
-
three: {
|
|
1412
|
-
four: 42
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
})
|
|
1325
|
+
expect(ref).to.deep.equal({ one: { two: { three: { four: 5 } } } })
|
|
1417
1326
|
```
|
|
1418
1327
|
|
|
1419
1328
|
## License
|