@jackens/nnn 2025.12.11 → 2025.12.13

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.
Files changed (4) hide show
  1. package/nnn.d.ts +206 -195
  2. package/nnn.js +162 -145
  3. package/package.json +1 -1
  4. package/readme.md +18 -20
package/nnn.d.ts CHANGED
@@ -1,138 +1,3 @@
1
- /**
2
- * Single argument type for the {@link h} and {@link s} helpers.
3
- */
4
- export type HArgs1 = Record<PropertyKey, unknown> | null | undefined | Node | string | number | HArgs;
5
- /**
6
- * Tuple argument type for the {@link h} and {@link s} helpers.
7
- */
8
- export type HArgs = [string | Node, ...HArgs1[]];
9
- /**
10
- * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper
11
- * for creating and modifying `HTMLElement`s (see also {@link s}).
12
- *
13
- * @param tag_or_node
14
- *
15
- * If a `string`, it is treated as the tag name for a new element.
16
- * If a `Node`, that node is modified in place.
17
- *
18
- * @param args
19
- *
20
- * Additional arguments processed as follows:
21
- * - `Object`: Maps attributes/properties. Keys starting with `$` set element properties
22
- * (without the `$` prefix); other keys set attributes via `setAttribute`.
23
- * A value of `false` removes the attribute.
24
- * - `null` / `undefined`: Ignored.
25
- * - `Node`: Appended as a child.
26
- * - `string` / `number`: Converted to a `Text` node and appended.
27
- * - {@link HArgs} array: Processed recursively.
28
- *
29
- * @returns
30
- *
31
- * The created or modified `HTMLElement`.
32
- */
33
- export declare const h: {
34
- <T extends keyof HTMLElementTagNameMap>(tag: T, ...args1: HArgs1[]): HTMLElementTagNameMap[T];
35
- <N extends Node>(node: N, ...args1: HArgs1[]): N;
36
- (tag_or_node: string | Node, ...args1: HArgs1[]): Node;
37
- };
38
- /**
39
- * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper
40
- * for creating and modifying `SVGElement`s (see also {@link h}).
41
- *
42
- * @param tag_or_node
43
- *
44
- * If a `string`, it is treated as the tag name for a new element.
45
- * If a `Node`, that node is modified in place.
46
- *
47
- * @param args
48
- *
49
- * Additional arguments processed as follows:
50
- * - `Object`: Maps attributes/properties. Keys starting with `$` set element properties
51
- * (without the `$` prefix); other keys set attributes via `setAttributeNS`.
52
- * A value of `false` removes the attribute.
53
- * - `null` / `undefined`: Ignored.
54
- * - `Node`: Appended as a child.
55
- * - `string` / `number`: Converted to a `Text` node and appended.
56
- * - {@link HArgs} array: Processed recursively.
57
- *
58
- * @returns
59
- *
60
- * The created or modified `SVGElement`.
61
- */
62
- export declare const s: {
63
- <T extends keyof SVGElementTagNameMap>(tag: T, ...args1: HArgs1[]): SVGElementTagNameMap[T];
64
- <N extends Node>(node: N, ...args1: HArgs1[]): N;
65
- (tag_or_node: string | Node, ...args1: HArgs1[]): Node;
66
- };
67
- /**
68
- * Shorthand for creating an SVG element with a `<use>` child referencing an icon by ID.
69
- *
70
- * Equivalent to: `s('svg', ['use', { 'xlink:href': '#' + id }], ...args)`.
71
- *
72
- * @param id
73
- *
74
- * The ID of the symbol to reference (without the `#` prefix).
75
- *
76
- * @param args
77
- *
78
- * Additional arguments passed to the outer `<svg>` element.
79
- *
80
- * @returns
81
- *
82
- * An `SVGSVGElement` containing a `<use>` element.
83
- */
84
- export declare const svg_use: (id: string, ...args: HArgs1[]) => SVGSVGElement;
85
- /**
86
- * A helper for building simple tokenizers (see also {@link nanolight_ts}).
87
- *
88
- * @param decorator
89
- *
90
- * A function that wraps each matched chunk. It receives the matched text (`chunk`)
91
- * and optionally the `metadata` associated with the pattern that produced the match.
92
- * For unmatched text between patterns, `metadata` is `undefined`.
93
- *
94
- * @param specs
95
- *
96
- * An array of tuples `[metadata, pattern]` where:
97
- * - `metadata`: Arbitrary data (e.g., a CSS class name) passed to `decorator` when the pattern matches.
98
- * - `pattern`: A `string` or `RegExp` to match against the input.
99
- *
100
- * @returns
101
- *
102
- * A tokenizer function that accepts a code string and returns an array of decorated tokens.
103
- *
104
- * @remarks
105
- *
106
- * 1. Matches starting at an earlier position take precedence.
107
- * 2. Among matches at the same position, the longer one wins.
108
- * 3. Among matches of the same position and length, the one defined earlier wins.
109
- */
110
- export declare const new_tokenizer: <M, T>(decorator: (chunk: string, metadata?: M) => T, ...specs: [M, string | RegExp][]) => (code: string) => T[];
111
- /**
112
- * A TypeScript/JavaScript syntax highlighting tokenizer built using {@link new_tokenizer}.
113
- *
114
- * @param code
115
- *
116
- * The source code string to tokenize.
117
- *
118
- * @returns
119
- *
120
- * An array of {@link HArgs1} elements suitable for rendering with {@link h} or {@link s}.
121
- */
122
- export declare const nanolight_ts: (code: string) => HArgs1[];
123
- /**
124
- * Applies Polish-specific typographic corrections to a DOM subtree.
125
- *
126
- * This function prevents orphaned conjunctions (single-letter words like “a”, “i”, “o”, “u”, “w”, “z”)
127
- * from appearing at the end of a line by wrapping them with the following word in a non-breaking span.
128
- * It also inserts zero-width spaces after slashes and dots to allow line breaks.
129
- *
130
- * @param node
131
- *
132
- * The root DOM node to process. All descendant text nodes are corrected recursively,
133
- * except those inside `IFRAME`, `NOSCRIPT`, `PRE`, `SCRIPT`, `STYLE`, or `TEXTAREA` elements.
134
- */
135
- export declare const fix_typography: (node: Node) => void;
136
1
  /**
137
2
  * Represents a CSS rule node for the {@link c} helper. Keys are CSS properties or nested selectors.
138
3
  */
@@ -192,11 +57,31 @@ export declare const c: (root: CRoot, splitter?: string) => string;
192
57
  * @param specs
193
58
  *
194
59
  * An array of breakpoint specifications, each a tuple of:
195
- * - `max_width`: Maximum number of cells per row (defines the viewport breakpoint).
196
- * - `width` (optional, default `1`): Number of horizontal cells the element spans.
197
- * - `height` (optional, default `1`): Number of vertical cells the element spans.
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.
198
63
  */
199
64
  export declare const rwd: (root: CRoot, selector: string, cell_width_px: number, cell_height_px: number, ...specs: [number, number?, number?][]) => void;
65
+
66
+ /**
67
+ * Parses a CSV string into a two-dimensional array of strings.
68
+ *
69
+ * Supports quoted fields with escaped double quotes (`""`). Carriage returns are normalized.
70
+ *
71
+ * @param csv
72
+ *
73
+ * The CSV string to parse.
74
+ *
75
+ * @param separator
76
+ *
77
+ * The field delimiter (default: `','`).
78
+ *
79
+ * @returns
80
+ *
81
+ * A 2D array where each inner array represents a row of fields.
82
+ */
83
+ export declare const csv_parse: (csv: string, separator?: string) => string[][];
84
+
200
85
  /**
201
86
  * A map from value constructors (or `null`/`undefined`) to escape functions.
202
87
  *
@@ -239,71 +124,123 @@ export declare const escape_values: (escape_map: EscapeMap, values: unknown[]) =
239
124
  * The resulting string with all interpolated values escaped.
240
125
  */
241
126
  export declare const escape: (escape_map: EscapeMap, template: TemplateStringsArray, ...values: unknown[]) => string;
127
+
242
128
  /**
243
- * Returns the appropriate Polish noun form based on a numeric value.
129
+ * Applies Polish-specific typographic corrections to a DOM subtree.
244
130
  *
245
- * Polish has three plural forms depending on the number:
246
- * - Singular: used for exactly 1.
247
- * - “Plural 2-4”: used for 2, 3, 4, 22, 23, 24, etc. (but not 12, 13, 14).
248
- * - “Plural 5+”: used for 0, 5–21, 25–31, etc.
131
+ * This function prevents orphaned conjunctions (single-letter words like “a”, “i”, “o”, “u”, “w”, “z”)
132
+ * from appearing at the end of a line by wrapping them with the following word in a non-breaking span.
133
+ * It also inserts zero-width spaces after slashes and dots to allow line breaks.
249
134
  *
250
- * @param singular
135
+ * @param node
251
136
  *
252
- * The singular form (e.g., ”auto” for “car”).
137
+ * The root DOM node to process. All descendant text nodes are corrected recursively,
138
+ * except those inside `IFRAME`, `NOSCRIPT`, `PRE`, `SCRIPT`, `STYLE`, or `TEXTAREA` elements.
139
+ */
140
+ export declare const fix_typography: (node: Node) => void;
141
+
142
+ /**
143
+ * Single argument type for the {@link h} and {@link s} helpers.
144
+ */
145
+ export type HArgs1 = Record<PropertyKey, unknown> | null | undefined | Node | string | number | HArgs;
146
+ /**
147
+ * Tuple argument type for the {@link h} and {@link s} helpers.
148
+ */
149
+ export type HArgs = [string | Node, ...HArgs1[]];
150
+ /**
151
+ * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper
152
+ * for creating and modifying `HTMLElement`s (see also {@link s}).
253
153
  *
254
- * @param plural_2
154
+ * @param tag_or_node
255
155
  *
256
- * The form for 2, 3, 4 (e.g., “auta”).
156
+ * If a `string`, it is treated as the tag name for a new element.
157
+ * If a `Node`, that node is modified in place.
257
158
  *
258
- * @param plural_5
159
+ * @param args
259
160
  *
260
- * The form for 5+ (e.g., “aut”).
161
+ * Additional arguments processed as follows:
162
+ * - `Object`: maps attributes/properties. Keys starting with `$` set element properties (without the `$` prefix);
163
+ * other keys set attributes via `setAttribute`. A value of `false` removes the attribute.
164
+ * - `null`/`undefined`: ignored.
165
+ * - `Node`: appended as a child.
166
+ * - `string`/`number`: converted to a `Text` node and appended.
167
+ * - {@link HArgs} array: processed recursively.
261
168
  *
262
- * @param value
169
+ * @returns
263
170
  *
264
- * The numeric value to evaluate.
171
+ * The created or modified `HTMLElement`.
172
+ */
173
+ export declare const h: {
174
+ <T extends keyof HTMLElementTagNameMap>(tag: T, ...args1: HArgs1[]): HTMLElementTagNameMap[T];
175
+ <N extends Node>(node: N, ...args1: HArgs1[]): N;
176
+ (tag_or_node: string | Node, ...args1: HArgs1[]): Node;
177
+ };
178
+ /**
179
+ * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper
180
+ * for creating and modifying `SVGElement`s (see also {@link h}).
181
+ *
182
+ * @param tag_or_node
183
+ *
184
+ * If a `string`, it is treated as the tag name for a new element.
185
+ * If a `Node`, that node is modified in place.
186
+ *
187
+ * @param args
188
+ *
189
+ * Additional arguments processed as follows:
190
+ * - `Object`: maps attributes/properties. Keys starting with `$` set element properties (without the `$` prefix);
191
+ * other keys set attributes via `setAttributeNS`. A value of `false` removes the attribute.
192
+ * - `null`/`undefined`: ignored.
193
+ * - `Node`: appended as a child.
194
+ * - `string`/`number`: converted to a `Text` node and appended.
195
+ * - {@link HArgs} array: processed recursively.
265
196
  *
266
197
  * @returns
267
198
  *
268
- * The appropriate noun form for the given value.
199
+ * The created or modified `SVGElement`.
269
200
  */
270
- export declare const pl_ural: (singular: string, plural_2: string, plural_5: string, value: number) => string;
201
+ export declare const s: {
202
+ <T extends keyof SVGElementTagNameMap>(tag: T, ...args1: HArgs1[]): SVGElementTagNameMap[T];
203
+ <N extends Node>(node: N, ...args1: HArgs1[]): N;
204
+ (tag_or_node: string | Node, ...args1: HArgs1[]): Node;
205
+ };
271
206
  /**
272
- * Generates a UUID v1 (time-based) identifier.
207
+ * Shorthand for creating an SVG element with a `<use>` child referencing an icon by ID.
273
208
  *
274
- * @param date
209
+ * Equivalent to: `s('svg', ['use', { 'xlink:href': '#' + id }], ...args)`.
275
210
  *
276
- * The date to use for the timestamp portion (default: current date/time).
211
+ * @param id
277
212
  *
278
- * @param node
213
+ * The ID of the symbol to reference (without the `#` prefix).
279
214
  *
280
- * A hexadecimal `string` for the node portion (default: random).
281
- * Must match `/^[0-9a-f]*$/`; it is trimmed to the last 12 characters and left-padded with zeros if shorter.
215
+ * @param args
216
+ *
217
+ * Additional arguments passed to the outer `<svg>` element.
282
218
  *
283
219
  * @returns
284
220
  *
285
- * A UUID v1 `string` in the standard format `xxxxxxxx-xxxx-1xxx-xxxx-xxxxxxxxxxxx`.
221
+ * An `SVGSVGElement` containing a `<use>` element.
286
222
  */
287
- export declare const uuid_v1: (date?: Date, node?: string) => string;
223
+ export declare const svg_use: (id: string, ...args: HArgs1[]) => SVGSVGElement;
224
+
288
225
  /**
289
- * Parses JSON with support for handler-based value transformation (“JavaScript ON”).
226
+ * Checks whether an object has the specified key as its own property.
290
227
  *
291
- * Objects with exactly one property whose key exists in `handlers` and whose value is an array
292
- * are replaced by invoking the corresponding handler with the array elements as arguments.
228
+ * A null-safe wrapper around `Object.hasOwn`.
293
229
  *
294
- * @param handlers
230
+ * @param ref
295
231
  *
296
- * An object mapping handler names to functions.
232
+ * The object to check.
297
233
  *
298
- * @param text
234
+ * @param key
299
235
  *
300
- * The JSON string to parse.
236
+ * The property key to look for.
301
237
  *
302
238
  * @returns
303
239
  *
304
- * The parsed value with handler substitutions applied.
240
+ * `true` if `ref` is not nullish and has `key` as an own property, `false` otherwise.
305
241
  */
306
- export declare const js_on_parse: (handlers: Record<PropertyKey, Function>, text: string) => any;
242
+ export declare const has_own: (ref: unknown, key: unknown) => boolean;
243
+
307
244
  /**
308
245
  * Checks whether the argument is an array.
309
246
  *
@@ -364,57 +301,67 @@ export declare const is_record: (arg: unknown) => arg is Record<PropertyKey, unk
364
301
  * `true` if `typeof arg === 'string'`, `false` otherwise.
365
302
  */
366
303
  export declare const is_string: (arg: unknown) => arg is string;
304
+
367
305
  /**
368
- * Checks whether an object has the specified key as its own property.
306
+ * Parses JSON with support for handler-based value transformation (“JavaScript ON”).
369
307
  *
370
- * A null-safe wrapper around `Object.hasOwn`.
308
+ * Objects with exactly one property whose key exists in `handlers` and whose value is an array
309
+ * are replaced by invoking the corresponding handler with the array elements as arguments.
371
310
  *
372
- * @param ref
311
+ * @param handlers
373
312
  *
374
- * The object to check.
313
+ * An object mapping handler names to functions.
375
314
  *
376
- * @param key
315
+ * @param text
377
316
  *
378
- * The property key to look for.
317
+ * The JSON string to parse.
379
318
  *
380
319
  * @returns
381
320
  *
382
- * `true` if `ref` is not nullish and has `key` as an own property, `false` otherwise.
321
+ * The parsed value with handler substitutions applied.
383
322
  */
384
- export declare const has_own: (ref: unknown, key: unknown) => boolean;
323
+ export declare const js_on_parse: (handlers: Record<PropertyKey, Function>, text: string) => any;
324
+
385
325
  /**
386
- * A Proxy-based helper for auto-vivification of nested object structures.
387
- *
388
- * Accessing any property on the returned proxy automatically creates an empty object if the property does not exist,
389
- * allowing deep assignments without explicit null checks.
326
+ * A TypeScript/JavaScript syntax highlighting tokenizer built using {@link new_tokenizer}.
390
327
  *
391
- * @param ref
328
+ * @param code
392
329
  *
393
- * The root object to wrap.
330
+ * The source code string to tokenize.
394
331
  *
395
332
  * @returns
396
333
  *
397
- * A proxy that auto-creates nested objects on property access.
334
+ * An array of {@link HArgs1} elements suitable for rendering with {@link h} or {@link s}.
398
335
  */
399
- export declare const pro: (ref: unknown) => any;
336
+ export declare const nanolight_ts: (code: string) => HArgs1[];
337
+
400
338
  /**
401
- * Parses a CSV string into a two-dimensional array of strings.
402
- *
403
- * Supports quoted fields with escaped double quotes (`""`). Carriage returns are normalized.
339
+ * A helper for building simple tokenizers (see also {@link nanolight_ts}).
404
340
  *
405
- * @param csv
341
+ * @param decorator
406
342
  *
407
- * The CSV string to parse.
343
+ * A function that wraps each matched chunk. It receives the matched text (`chunk`)
344
+ * and optionally the `metadata` associated with the pattern that produced the match.
345
+ * For unmatched text between patterns, `metadata` is `undefined`.
408
346
  *
409
- * @param separator
347
+ * @param specs
410
348
  *
411
- * The field delimiter (default: `','`).
349
+ * An array of tuples `[metadata, pattern]` where:
350
+ * - `metadata`: arbitrary data (e.g., a CSS class name) passed to `decorator` when the pattern matches.
351
+ * - `pattern`: a `string` or `RegExp` to match against the input.
412
352
  *
413
353
  * @returns
414
354
  *
415
- * A 2D array where each inner array represents a row of fields.
355
+ * A tokenizer function that accepts a code string and returns an array of decorated tokens.
356
+ *
357
+ * @remarks
358
+ *
359
+ * 1. Matches starting at an earlier position take precedence.
360
+ * 2. Among matches at the same position, the longer one wins.
361
+ * 3. Among matches of the same position and length, the one defined earlier wins.
416
362
  */
417
- export declare const csv_parse: (csv: string, separator?: string) => string[][];
363
+ export declare const new_tokenizer: <M, T>(decorator: (chunk: string, metadata?: M) => T, ...specs: [M, string | RegExp][]) => (code: string) => T[];
364
+
418
365
  /**
419
366
  * Creates a new object containing only the specified keys from the source object.
420
367
  *
@@ -451,3 +398,67 @@ export declare const pick: <T, K extends keyof T>(ref: T, keys: K[]) => Pick<T,
451
398
  * A new object without the specified keys.
452
399
  */
453
400
  export declare const omit: <T, K extends keyof T>(ref: T, keys: unknown[]) => Omit<T, K>;
401
+
402
+ /**
403
+ * Returns the appropriate Polish noun form based on a numeric value.
404
+ *
405
+ * Polish has three plural forms depending on the number:
406
+ * - Singular: used for exactly 1.
407
+ * - “Plural 2-4”: used for 2, 3, 4, 22, 23, 24, etc. (but not 12, 13, 14).
408
+ * - “Plural 5+”: used for 0, 5–21, 25–31, etc.
409
+ *
410
+ * @param singular
411
+ *
412
+ * The singular form (e.g., “auto” for “car”).
413
+ *
414
+ * @param plural_2
415
+ *
416
+ * The form for 2, 3, 4 (e.g., “auta”).
417
+ *
418
+ * @param plural_5
419
+ *
420
+ * The form for 5+ (e.g., “aut”).
421
+ *
422
+ * @param value
423
+ *
424
+ * The numeric value to evaluate.
425
+ *
426
+ * @returns
427
+ *
428
+ * The appropriate noun form for the given value.
429
+ */
430
+ export declare const pl_ural: (singular: string, plural_2: string, plural_5: string, value: number) => string;
431
+
432
+ /**
433
+ * A Proxy-based helper for auto-vivification of nested object structures.
434
+ *
435
+ * Accessing any property on the returned proxy automatically creates an empty object if the property does not exist,
436
+ * allowing deep assignments without explicit null checks.
437
+ *
438
+ * @param ref
439
+ *
440
+ * The root object to wrap.
441
+ *
442
+ * @returns
443
+ *
444
+ * A proxy that auto-creates nested objects on property access.
445
+ */
446
+ export declare const pro: (ref: unknown) => any;
447
+
448
+ /**
449
+ * Generates a UUID v1 (time-based) identifier.
450
+ *
451
+ * @param date
452
+ *
453
+ * The date to use for the timestamp portion (default: current date/time).
454
+ *
455
+ * @param node
456
+ *
457
+ * A hexadecimal `string` for the node portion (default: random).
458
+ * Must match `/^[0-9a-f]*$/`; it is trimmed to the last 12 characters and left-padded with zeros if shorter.
459
+ *
460
+ * @returns
461
+ *
462
+ * A UUID v1 `string` in the standard format `xxxxxxxx-xxxx-1xxx-xxxx-xxxxxxxxxxxx`.
463
+ */
464
+ export declare const uuid_v1: (date?: Date, node?: string) => string;
package/nnn.js CHANGED
@@ -1,4 +1,101 @@
1
- // src/nnn.ts
1
+ // src/nnn/is.ts
2
+ var is_array = Array.isArray;
3
+ var is_finite_number = Number.isFinite;
4
+ 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
+
8
+ // src/nnn/pro.ts
9
+ var pro = (ref) => new Proxy(ref, {
10
+ get(target, key) {
11
+ return pro(target[key] ??= {});
12
+ }
13
+ });
14
+
15
+ // src/nnn/c.ts
16
+ var _c = (node, prefix, result, splitter) => {
17
+ const queue = [[node, prefix]];
18
+ while (queue.length > 0) {
19
+ const [style_0, prefix_0] = queue.shift();
20
+ if (style_0 == null || prefix_0 == null) {
21
+ continue;
22
+ }
23
+ if (is_array(style_0)) {
24
+ result.push(prefix_0, prefix_0 !== "" ? "{" : "", style_0.join(";"), prefix_0 !== "" ? "}" : "");
25
+ } else {
26
+ const todo = [];
27
+ let attributes = [];
28
+ let attributes_pushed = false;
29
+ for (const key in style_0) {
30
+ const value = style_0[key];
31
+ if (is_string(value) || is_number(value)) {
32
+ if (!attributes_pushed) {
33
+ attributes_pushed = true;
34
+ attributes = [];
35
+ todo.push([attributes, prefix_0]);
36
+ }
37
+ const attribute = key.split(splitter)[0].replace(/_/g, "-").replace(/([A-Z])/g, (_, letter) => "-" + letter.toLowerCase());
38
+ attributes.push(`${attribute}:${value}`);
39
+ } else if (value != null) {
40
+ attributes_pushed = false;
41
+ const prefix_n = [];
42
+ const key_chunks = key.split(",");
43
+ prefix_0.split(",").forEach((prefix_chunk) => key_chunks.forEach((key_chunk) => prefix_n.push(prefix_chunk + key_chunk)));
44
+ todo.push([value, prefix_n.join()]);
45
+ }
46
+ }
47
+ queue.unshift(...todo);
48
+ }
49
+ }
50
+ };
51
+ var c = (root, splitter = "$$") => {
52
+ const chunks = [];
53
+ for (const key in root) {
54
+ const value = root[key];
55
+ if (value != null) {
56
+ if (key[0] === "@") {
57
+ chunks.push(key.split(splitter)[0] + "{");
58
+ _c(value, "", chunks, splitter);
59
+ chunks.push("}");
60
+ } else {
61
+ _c(value, key.split(splitter)[0], chunks, splitter);
62
+ }
63
+ }
64
+ }
65
+ return chunks.join("");
66
+ };
67
+ var rwd = (root, selector, cell_width_px, cell_height_px, ...specs) => {
68
+ const main = pro(root)[selector];
69
+ main.boxSizing = "border-box";
70
+ main.display = "block";
71
+ main.float = "left";
72
+ main.width = "100%";
73
+ main.height = `${cell_height_px}px`;
74
+ specs.sort(([a], [b]) => a - b);
75
+ for (let [max_width, width, height] of specs) {
76
+ const node = max_width === 1 ? main : pro(root)[`@media(min-width:${cell_width_px * max_width}px)`][selector];
77
+ width ??= 1;
78
+ height ??= 1;
79
+ let gcd = 100 * width;
80
+ let tmp = max_width;
81
+ while (tmp > 0) {
82
+ [gcd, tmp] = [tmp, gcd % tmp];
83
+ }
84
+ const w_100_per_gcd = 100 * width / gcd;
85
+ node.width = max_width === gcd ? `${w_100_per_gcd}%` : `calc(${w_100_per_gcd}% / ${max_width / gcd})`;
86
+ node.height = `${cell_height_px * height}px`;
87
+ }
88
+ };
89
+ // src/nnn/csv_parse.ts
90
+ var csv_parse = (csv, separator = ",") => {
91
+ const main_pattern = /\n|(?<!")("(?:[^"]|"")*")(?!")/g;
92
+ const line_pattern = new RegExp(`${separator}|(?<!")\\s*"((?:[^"]|"")*)"\\s*(?!")`, "g");
93
+ 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"));
94
+ };
95
+ // src/nnn/escape.ts
96
+ var escape_values = (escape_map, values) => values.map((value) => (value == null ? escape_map.get(value) : escape_map.get(value?.constructor))?.(value) ?? "");
97
+ var escape = (escape_map, template, ...values) => String.raw(template, ...escape_values(escape_map, values));
98
+ // src/nnn/h.ts
2
99
  var _h = (namespace_uri) => {
3
100
  const create_element = namespace_uri == null ? (tag) => document.createElement(tag) : (tag) => document.createElementNS(namespace_uri, tag);
4
101
  const h = (tag_or_node, ...args) => {
@@ -57,9 +154,62 @@ var _h = (namespace_uri) => {
57
154
  };
58
155
  return h;
59
156
  };
60
- var h = _h();
61
- var s = _h("http://www.w3.org/2000/svg");
157
+ var h = /* @__PURE__ */ _h();
158
+ var s = /* @__PURE__ */ _h("http://www.w3.org/2000/svg");
62
159
  var svg_use = (id, ...args) => s("svg", ["use", { "xlink:href": "#" + id }], ...args);
160
+
161
+ // src/nnn/fix_typography.ts
162
+ var TAGS_TO_SKIP = ["IFRAME", "NOSCRIPT", "PRE", "SCRIPT", "STYLE", "TEXTAREA"];
163
+ var fix_typography = (node) => {
164
+ const queue = [node];
165
+ while (queue.length > 0) {
166
+ const node_0 = queue.shift();
167
+ if (node_0 instanceof Element) {
168
+ node_0.childNodes.forEach((child_node) => {
169
+ if (child_node instanceof Text) {
170
+ queue.push(child_node);
171
+ } else if (child_node instanceof Element && !TAGS_TO_SKIP.includes(child_node.tagName)) {
172
+ queue.push(child_node);
173
+ }
174
+ });
175
+ } else if (node_0 instanceof Text) {
176
+ const node_value = node_0.nodeValue?.trim?.();
177
+ if (node_value != null) {
178
+ let previous_node = node_0;
179
+ node_value.split(/(\s|\(|„)([aiouwz—]\s)/gi).forEach((chunk, i) => {
180
+ i %= 3;
181
+ const current_node = i === 2 ? h("span", { style: "white-space:nowrap" }, chunk) : i === 1 ? document.createTextNode(chunk) : document.createTextNode(chunk.replace(/(\/(?=[^/\s])|\.(?=[^\s]))/g, "$1​"));
182
+ if (node_0.parentNode != null) {
183
+ node_0.parentNode.insertBefore(current_node, previous_node.nextSibling);
184
+ }
185
+ previous_node = current_node;
186
+ });
187
+ node_0.parentNode?.removeChild(node_0);
188
+ }
189
+ }
190
+ }
191
+ };
192
+ // src/nnn/has_own.ts
193
+ var has_own = (ref, key) => ref != null && Object.hasOwn(ref, key);
194
+ // src/nnn/js_on_parse.ts
195
+ var js_on_parse = (handlers, text) => JSON.parse(text, (key, value) => {
196
+ if (is_record(value)) {
197
+ let is_second_key = false;
198
+ for (key in value) {
199
+ if (is_second_key) {
200
+ return value;
201
+ }
202
+ is_second_key = true;
203
+ }
204
+ const handler = handlers[key];
205
+ const params = value[key];
206
+ if (handler instanceof Function && is_array(params)) {
207
+ return handler(...params);
208
+ }
209
+ }
210
+ return value;
211
+ });
212
+ // src/nnn/new_tokenizer.ts
63
213
  var new_tokenizer = (decorator, ...specs) => (code) => {
64
214
  const result = [];
65
215
  while (code.length > 0) {
@@ -97,6 +247,8 @@ var new_tokenizer = (decorator, ...specs) => (code) => {
97
247
  }
98
248
  return result;
99
249
  };
250
+
251
+ // src/nnn/nanolight.ts
100
252
  var BLUE = "blue";
101
253
  var GREEN = "green";
102
254
  var GREY = "grey";
@@ -104,159 +256,24 @@ var PURPLE = "purple";
104
256
  var RED = "red";
105
257
  var WHITE = "white";
106
258
  var YELLOW = "yellow";
107
- var nanolight_ts = new_tokenizer((chunk, name) => name != null ? ["span", { class: name }, chunk] : chunk, [YELLOW, /".*?"/], [YELLOW, /'.*?'/], [YELLOW, /`[\s\S]*?`/], [GREY, "("], [GREY, ")"], [GREY, ","], [GREY, "."], [GREY, ":"], [GREY, ";"], [GREY, "?"], [GREY, "["], [GREY, "]"], [GREY, "{"], [GREY, "}"], [GREY, /\/\*[\s\S]*?\*\//], [GREY, /\/\/.*?(?=\n)/], [RED, "!"], [RED, "!="], [RED, "!=="], [RED, "%"], [RED, "%="], [RED, "&&"], [RED, "&&="], [RED, "&"], [RED, "&="], [RED, "*"], [RED, "**"], [RED, "**="], [RED, "*="], [RED, "+"], [RED, "++"], [RED, "+="], [RED, "-"], [RED, "--"], [RED, "-="], [RED, "/"], [RED, "/="], [RED, ":"], [RED, "<"], [RED, "<<"], [RED, "<<="], [RED, "<="], [RED, "="], [RED, "=="], [RED, "==="], [RED, "=>"], [RED, ">"], [RED, ">="], [RED, ">>"], [RED, ">>="], [RED, ">>>"], [RED, ">>>="], [RED, "?"], [RED, "??"], [RED, "??="], [RED, "^"], [RED, "^="], [RED, "as"], [RED, "async"], [RED, "await"], [RED, "break"], [RED, "case"], [RED, "catch"], [RED, "class"], [RED, "const"], [RED, "continue"], [RED, "debugger"], [RED, "default"], [RED, "delete"], [RED, "do"], [RED, "else"], [RED, "export"], [RED, "extends"], [RED, "finally"], [RED, "for"], [RED, "from"], [RED, "function"], [RED, "function*"], [RED, "goto"], [RED, "if"], [RED, "import"], [RED, "in"], [RED, "instanceof"], [RED, "is"], [RED, "keyof"], [RED, "let"], [RED, "new"], [RED, "of"], [RED, "package"], [RED, "return"], [RED, "super"], [RED, "switch"], [RED, "this"], [RED, "throw"], [RED, "try"], [RED, "type"], [RED, "typeof"], [RED, "var"], [RED, "void"], [RED, "while"], [RED, "with"], [RED, "yield"], [RED, "yield*"], [RED, "|"], [RED, "|="], [RED, "||"], [RED, "||="], [RED, "~"], [RED, "~="], [PURPLE, "false"], [PURPLE, "Infinity"], [PURPLE, "NaN"], [PURPLE, "null"], [PURPLE, "true"], [PURPLE, "undefined"], [PURPLE, /0b[01_]+/], [PURPLE, /0o[01234567_]+/], [PURPLE, /0x[\dabcdef_]+/], [PURPLE, /[A-Z_$][A-Z0-9_$]+/], [PURPLE, /\d[\d_]*(\.[\d_]+)?(e[+-]?[\d_]+)?/], [BLUE, "any"], [BLUE, "bigint"], [BLUE, "boolean"], [BLUE, "eval"], [BLUE, "number"], [BLUE, "string"], [BLUE, "symbol"], [BLUE, "unknown"], [GREEN, /[$\w]+(?=\()/], [BLUE, /[A-Z][$\w]+/], [WHITE, /[$\w]+/]);
108
- var TAGS_TO_SKIP = ["IFRAME", "NOSCRIPT", "PRE", "SCRIPT", "STYLE", "TEXTAREA"];
109
- var fix_typography = (node) => {
110
- const queue = [node];
111
- while (queue.length > 0) {
112
- const node_0 = queue.shift();
113
- if (node_0 instanceof Element) {
114
- node_0.childNodes.forEach((child_node) => {
115
- if (child_node instanceof Text) {
116
- queue.push(child_node);
117
- } else if (child_node instanceof Element && !TAGS_TO_SKIP.includes(child_node.tagName)) {
118
- queue.push(child_node);
119
- }
120
- });
121
- } else if (node_0 instanceof Text) {
122
- const node_value = node_0.nodeValue?.trim?.();
123
- if (node_value != null) {
124
- let previous_node = node_0;
125
- node_value.split(/(\s|\(|„)([aiouwz—]\s)/gi).forEach((chunk, i) => {
126
- i %= 3;
127
- const current_node = i === 2 ? h("span", { style: "white-space:nowrap" }, chunk) : i === 1 ? document.createTextNode(chunk) : document.createTextNode(chunk.replace(/(\/(?=[^/\s])|\.(?=[^\s]))/g, "$1​"));
128
- if (node_0.parentNode != null) {
129
- node_0.parentNode.insertBefore(current_node, previous_node.nextSibling);
130
- }
131
- previous_node = current_node;
132
- });
133
- node_0.parentNode?.removeChild(node_0);
134
- }
135
- }
136
- }
137
- };
138
- var _c = (node, prefix, result, splitter) => {
139
- const queue = [[node, prefix]];
140
- while (queue.length > 0) {
141
- const [style_0, prefix_0] = queue.shift();
142
- if (style_0 == null || prefix_0 == null) {
143
- continue;
144
- }
145
- if (is_array(style_0)) {
146
- result.push(prefix_0, prefix_0 !== "" ? "{" : "", style_0.join(";"), prefix_0 !== "" ? "}" : "");
147
- } else {
148
- const todo = [];
149
- let attributes = [];
150
- let attributes_pushed = false;
151
- for (const key in style_0) {
152
- const value = style_0[key];
153
- if (is_string(value) || is_number(value)) {
154
- if (!attributes_pushed) {
155
- attributes_pushed = true;
156
- attributes = [];
157
- todo.push([attributes, prefix_0]);
158
- }
159
- const attribute = key.split(splitter)[0].replace(/_/g, "-").replace(/([A-Z])/g, (_, letter) => "-" + letter.toLowerCase());
160
- attributes.push(`${attribute}:${value}`);
161
- } else if (value != null) {
162
- attributes_pushed = false;
163
- const prefix_n = [];
164
- const key_chunks = key.split(",");
165
- prefix_0.split(",").forEach((prefix_chunk) => key_chunks.forEach((key_chunk) => prefix_n.push(prefix_chunk + key_chunk)));
166
- todo.push([value, prefix_n.join()]);
167
- }
168
- }
169
- queue.unshift(...todo);
170
- }
171
- }
172
- };
173
- var c = (root, splitter = "$$") => {
174
- const chunks = [];
175
- for (const key in root) {
176
- const value = root[key];
177
- if (value != null) {
178
- if (key[0] === "@") {
179
- chunks.push(key.split(splitter)[0] + "{");
180
- _c(value, "", chunks, splitter);
181
- chunks.push("}");
182
- } else {
183
- _c(value, key.split(splitter)[0], chunks, splitter);
184
- }
185
- }
186
- }
187
- return chunks.join("");
188
- };
189
- var rwd = (root, selector, cell_width_px, cell_height_px, ...specs) => {
190
- const main = pro(root)[selector];
191
- main.boxSizing = "border-box";
192
- main.display = "block";
193
- main.float = "left";
194
- main.width = "100%";
195
- main.height = `${cell_height_px}px`;
196
- specs.sort(([a], [b]) => a - b);
197
- for (let [max_width, width, height] of specs) {
198
- const node = max_width === 1 ? main : pro(root)[`@media(min-width:${cell_width_px * max_width}px)`][selector];
199
- width ??= 1;
200
- height ??= 1;
201
- let gcd = 100 * width;
202
- let tmp = max_width;
203
- while (tmp) {
204
- [gcd, tmp] = [tmp, gcd % tmp];
205
- }
206
- const w_100_per_gcd = 100 * width / gcd;
207
- node.width = max_width === gcd ? `${w_100_per_gcd}%` : `calc(${w_100_per_gcd}% / ${max_width / gcd})`;
208
- node.height = `${cell_height_px * height}px`;
209
- }
210
- };
211
- var escape_values = (escape_map, values) => values.map((value) => (value == null ? escape_map.get(value) : escape_map.get(value?.constructor))?.(value) ?? "");
212
- var escape = (escape_map, template, ...values) => String.raw(template, ...escape_values(escape_map, values));
259
+ var nanolight_ts = /* @__PURE__ */ new_tokenizer((chunk, name) => name != null ? ["span", { class: name }, chunk] : chunk, [YELLOW, /".*?"/], [YELLOW, /'.*?'/], [YELLOW, /`[\s\S]*?`/], [GREY, "("], [GREY, ")"], [GREY, ","], [GREY, "."], [GREY, ":"], [GREY, ";"], [GREY, "?"], [GREY, "["], [GREY, "]"], [GREY, "{"], [GREY, "}"], [GREY, /\/\*[\s\S]*?\*\//], [GREY, /\/\/.*?(?=\n)/], [RED, "!"], [RED, "!="], [RED, "!=="], [RED, "%"], [RED, "%="], [RED, "&&"], [RED, "&&="], [RED, "&"], [RED, "&="], [RED, "*"], [RED, "**"], [RED, "**="], [RED, "*="], [RED, "+"], [RED, "++"], [RED, "+="], [RED, "-"], [RED, "--"], [RED, "-="], [RED, "/"], [RED, "/="], [RED, ":"], [RED, "<"], [RED, "<<"], [RED, "<<="], [RED, "<="], [RED, "="], [RED, "=="], [RED, "==="], [RED, "=>"], [RED, ">"], [RED, ">="], [RED, ">>"], [RED, ">>="], [RED, ">>>"], [RED, ">>>="], [RED, "?"], [RED, "??"], [RED, "??="], [RED, "^"], [RED, "^="], [RED, "as"], [RED, "async"], [RED, "await"], [RED, "break"], [RED, "case"], [RED, "catch"], [RED, "class"], [RED, "const"], [RED, "continue"], [RED, "debugger"], [RED, "default"], [RED, "delete"], [RED, "do"], [RED, "else"], [RED, "export"], [RED, "extends"], [RED, "finally"], [RED, "for"], [RED, "from"], [RED, "function"], [RED, "function*"], [RED, "goto"], [RED, "if"], [RED, "import"], [RED, "in"], [RED, "instanceof"], [RED, "is"], [RED, "keyof"], [RED, "let"], [RED, "new"], [RED, "of"], [RED, "package"], [RED, "return"], [RED, "super"], [RED, "switch"], [RED, "this"], [RED, "throw"], [RED, "try"], [RED, "type"], [RED, "typeof"], [RED, "var"], [RED, "void"], [RED, "while"], [RED, "with"], [RED, "yield"], [RED, "yield*"], [RED, "|"], [RED, "|="], [RED, "||"], [RED, "||="], [RED, "~"], [RED, "~="], [PURPLE, "false"], [PURPLE, "Infinity"], [PURPLE, "NaN"], [PURPLE, "null"], [PURPLE, "true"], [PURPLE, "undefined"], [PURPLE, /0b[01_]+/], [PURPLE, /0o[01234567_]+/], [PURPLE, /0x[\dabcdef_]+/], [PURPLE, /[A-Z_$][A-Z0-9_$]+/], [PURPLE, /\d[\d_]*(\.[\d_]+)?(e[+-]?[\d_]+)?/], [BLUE, "any"], [BLUE, "bigint"], [BLUE, "boolean"], [BLUE, "eval"], [BLUE, "number"], [BLUE, "string"], [BLUE, "symbol"], [BLUE, "unknown"], [GREEN, /[$\w]+(?=\()/], [BLUE, /[A-Z][$\w]+/], [WHITE, /[$\w]+/]);
260
+ // src/nnn/omit_pick.ts
261
+ var pick = (ref, keys) => Object.fromEntries(Object.entries(ref).filter(([key]) => keys.includes(key)));
262
+ var omit = (ref, keys) => Object.fromEntries(Object.entries(ref).filter(([key]) => !keys.includes(key)));
263
+ // src/nnn/pl_ural.ts
213
264
  var pl_ural = (singular, plural_2, plural_5, value) => {
214
265
  const abs_value = Math.abs(value);
215
266
  const abs_value_mod_10 = abs_value % 10;
216
267
  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
268
  };
218
- var ZEROS = "0".repeat(16);
269
+ // src/nnn/uuid_v1.ts
270
+ var ZEROS = /* @__PURE__ */ "0".repeat(16);
219
271
  var counter = 0;
220
272
  var uuid_v1 = (date = new Date, node = Math.random().toString(16).slice(2)) => {
221
273
  const time = ZEROS + (1e4 * (+date + 12219292800000)).toString(16);
222
274
  counter = counter + 1 & 16383;
223
275
  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));
224
276
  };
225
- var js_on_parse = (handlers, text) => JSON.parse(text, (key, value) => {
226
- if (is_record(value)) {
227
- let is_second_key = false;
228
- for (key in value) {
229
- if (is_second_key) {
230
- return value;
231
- }
232
- is_second_key = true;
233
- }
234
- const handler = handlers[key];
235
- const params = value[key];
236
- if (handler instanceof Function && is_array(params)) {
237
- return handler(...params);
238
- }
239
- }
240
- return value;
241
- });
242
- var is_array = Array.isArray;
243
- var is_finite_number = Number.isFinite;
244
- var is_number = (arg) => typeof arg === "number";
245
- var is_record = (arg) => typeof arg === "object" && arg != null && !is_array(arg);
246
- var is_string = (arg) => typeof arg === "string";
247
- var has_own = (ref, key) => ref != null && Object.hasOwn(ref, key);
248
- var pro = (ref) => new Proxy(ref, {
249
- get(target, key) {
250
- return pro(target[key] ??= {});
251
- }
252
- });
253
- var csv_parse = (csv, separator = ",") => {
254
- const main_pattern = /\n|(?<!")("(?:[^"]|"")*")(?!")/g;
255
- const line_pattern = new RegExp(`${separator}|(?<!")\\s*"((?:[^"]|"")*)"\\s*(?!")`, "g");
256
- 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"));
257
- };
258
- var pick = (ref, keys) => Object.fromEntries(Object.entries(ref).filter(([key]) => keys.includes(key)));
259
- var omit = (ref, keys) => Object.fromEntries(Object.entries(ref).filter(([key]) => !keys.includes(key)));
260
277
  export {
261
278
  uuid_v1,
262
279
  svg_use,
package/package.json CHANGED
@@ -38,5 +38,5 @@
38
38
  "name": "@jackens/nnn",
39
39
  "type": "module",
40
40
  "types": "nnn.d.ts",
41
- "version": "2025.12.11"
41
+ "version": "2025.12.13"
42
42
  }
package/readme.md CHANGED
@@ -490,13 +490,12 @@ If a `Node`, that node is modified in place.
490
490
  #### args
491
491
 
492
492
  Additional arguments processed as follows:
493
- - `Object`: Maps attributes/properties. Keys starting with `$` set element properties
494
- (without the `$` prefix); other keys set attributes via `setAttribute`.
495
- A value of `false` removes the attribute.
496
- - `null` / `undefined`: Ignored.
497
- - `Node`: Appended as a child.
498
- - `string` / `number`: Converted to a `Text` node and appended.
499
- - [`HArgs`](#HArgs) array: Processed recursively.
493
+ - `Object`: maps attributes/properties. Keys starting with `$` set element properties (without the `$` prefix);
494
+ other keys set attributes via `setAttribute`. A value of `false` removes the attribute.
495
+ - `null`/`undefined`: ignored.
496
+ - `Node`: appended as a child.
497
+ - `string`/`number`: converted to a `Text` node and appended.
498
+ - [`HArgs`](#HArgs) array: processed recursively.
500
499
 
501
500
  #### Returns
502
501
 
@@ -895,8 +894,8 @@ For unmatched text between patterns, `metadata` is `undefined`.
895
894
  #### specs
896
895
 
897
896
  An array of tuples `[metadata, pattern]` where:
898
- - `metadata`: Arbitrary data (e.g., a CSS class name) passed to `decorator` when the pattern matches.
899
- - `pattern`: A `string` or `RegExp` to match against the input.
897
+ - `metadata`: arbitrary data (e.g., a CSS class name) passed to `decorator` when the pattern matches.
898
+ - `pattern`: a `string` or `RegExp` to match against the input.
900
899
 
901
900
  #### Returns
902
901
 
@@ -983,7 +982,7 @@ Polish has three plural forms depending on the number:
983
982
 
984
983
  #### singular
985
984
 
986
- The singular form (e.g., auto” for “car”).
985
+ The singular form (e.g., auto” for “car”).
987
986
 
988
987
  #### plural_2
989
988
 
@@ -1095,9 +1094,9 @@ The base cell height in pixels.
1095
1094
  #### specs
1096
1095
 
1097
1096
  An array of breakpoint specifications, each a tuple of:
1098
- - `max_width`: Maximum number of cells per row (defines the viewport breakpoint).
1099
- - `width` (optional, default `1`): Number of horizontal cells the element spans.
1100
- - `height` (optional, default `1`): Number of vertical cells the element spans.
1097
+ - `max_width`: maximum number of cells per row (defines the viewport breakpoint).
1098
+ - `width` (optional, default `1`): number of horizontal cells the element spans.
1099
+ - `height` (optional, default `1`): number of vertical cells the element spans.
1101
1100
 
1102
1101
  #### Usage Examples
1103
1102
 
@@ -1167,13 +1166,12 @@ If a `Node`, that node is modified in place.
1167
1166
  #### args
1168
1167
 
1169
1168
  Additional arguments processed as follows:
1170
- - `Object`: Maps attributes/properties. Keys starting with `$` set element properties
1171
- (without the `$` prefix); other keys set attributes via `setAttributeNS`.
1172
- A value of `false` removes the attribute.
1173
- - `null` / `undefined`: Ignored.
1174
- - `Node`: Appended as a child.
1175
- - `string` / `number`: Converted to a `Text` node and appended.
1176
- - [`HArgs`](#HArgs) array: Processed recursively.
1169
+ - `Object`: maps attributes/properties. Keys starting with `$` set element properties (without the `$` prefix);
1170
+ other keys set attributes via `setAttributeNS`. A value of `false` removes the attribute.
1171
+ - `null`/`undefined`: ignored.
1172
+ - `Node`: appended as a child.
1173
+ - `string`/`number`: converted to a `Text` node and appended.
1174
+ - [`HArgs`](#HArgs) array: processed recursively.
1177
1175
 
1178
1176
  #### Returns
1179
1177