@jackens/nnn 2026.2.26 → 2026.4.11
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 +21 -43
- package/nnn.js +49 -55
- package/package.json +1 -1
- package/readme.md +270 -105
package/nnn.d.ts
CHANGED
|
@@ -128,6 +128,24 @@ export declare const s: {
|
|
|
128
128
|
<N extends Node>(node: N, ...args1: HArgs1[]): N;
|
|
129
129
|
(tagOrNode: string | Node, ...args1: HArgs1[]): Node;
|
|
130
130
|
};
|
|
131
|
+
/**
|
|
132
|
+
* Shorthand for creating an SVG element with a `<use>` child referencing an icon by ID.
|
|
133
|
+
*
|
|
134
|
+
* Equivalent to: `s('svg', ['use', { 'xlink:href': '#' + id }], ...args)`.
|
|
135
|
+
*
|
|
136
|
+
* @param id
|
|
137
|
+
*
|
|
138
|
+
* The ID of the symbol to reference (without the `#` prefix).
|
|
139
|
+
*
|
|
140
|
+
* @param args
|
|
141
|
+
*
|
|
142
|
+
* Additional arguments passed to the outer `<svg>` element.
|
|
143
|
+
*
|
|
144
|
+
* @returns
|
|
145
|
+
*
|
|
146
|
+
* An `SVGSVGElement` containing a `<use>` element.
|
|
147
|
+
*/
|
|
148
|
+
export declare const svgUse: (id: string, ...args: HArgs1[]) => SVGSVGElement;
|
|
131
149
|
/**
|
|
132
150
|
* Checks whether an object has the specified key as its own property.
|
|
133
151
|
*
|
|
@@ -253,40 +271,18 @@ export declare const monokai: CRoot;
|
|
|
253
271
|
* An array of {@link HArgs1} elements suitable for rendering with {@link h}.
|
|
254
272
|
*/
|
|
255
273
|
export declare const nanolightTs: (code: string) => HArgs1[];
|
|
256
|
-
/**
|
|
257
|
-
* A map from value constructors (or `null`/`undefined`) to escape functions.
|
|
258
|
-
*
|
|
259
|
-
* Used by {@link escapeValues} and {@link newEscape}.
|
|
260
|
-
*/
|
|
261
|
-
export type EscapeMap = Map<unknown, (value?: unknown) => string>;
|
|
262
|
-
/**
|
|
263
|
-
* Escapes an array of values using the provided escape map.
|
|
264
|
-
*
|
|
265
|
-
* @param escapeMap
|
|
266
|
-
*
|
|
267
|
-
* A map where keys are constructors (e.g., `String`, `Number`) and values are escape functions.
|
|
268
|
-
*
|
|
269
|
-
* @param values
|
|
270
|
-
*
|
|
271
|
-
* The array of values to escape.
|
|
272
|
-
*
|
|
273
|
-
* @returns
|
|
274
|
-
*
|
|
275
|
-
* An array of escaped strings.
|
|
276
|
-
*/
|
|
277
|
-
export declare const escapeValues: (escapeMap: EscapeMap, values: unknown[]) => string[];
|
|
278
274
|
/**
|
|
279
275
|
* Creates a tag function for escaping interpolated values in template literals.
|
|
280
276
|
*
|
|
281
|
-
* @param
|
|
277
|
+
* @param escapeFn
|
|
282
278
|
*
|
|
283
|
-
* A
|
|
279
|
+
* A function that takes a value and returns its escaped string representation.
|
|
284
280
|
*
|
|
285
281
|
* @returns
|
|
286
282
|
*
|
|
287
283
|
* A tag function that escapes interpolated values using the provided escape map.
|
|
288
284
|
*/
|
|
289
|
-
export declare const newEscape: (
|
|
285
|
+
export declare const newEscape: (escapeFn: (value: any) => string) => (template: TemplateStringsArray, ...values: unknown[]) => string;
|
|
290
286
|
/**
|
|
291
287
|
* Creates a function that returns the appropriate noun form based on a numeric value using `Intl.PluralRules`.
|
|
292
288
|
*
|
|
@@ -403,24 +399,6 @@ export declare const pick: <T, K extends keyof T>(ref: T, keys: K[]) => Pick<T,
|
|
|
403
399
|
* - `height` (optional, default `1`): number of vertical cells the element spans.
|
|
404
400
|
*/
|
|
405
401
|
export declare const rwd: (root: CRoot, selector: string, cellWidthPx: number, cellHeightPx: number, ...specs: [number, number?, number?][]) => void;
|
|
406
|
-
/**
|
|
407
|
-
* Shorthand for creating an SVG element with a `<use>` child referencing an icon by ID.
|
|
408
|
-
*
|
|
409
|
-
* Equivalent to: `s('svg', ['use', { 'xlink:href': '#' + id }], ...args)`.
|
|
410
|
-
*
|
|
411
|
-
* @param id
|
|
412
|
-
*
|
|
413
|
-
* The ID of the symbol to reference (without the `#` prefix).
|
|
414
|
-
*
|
|
415
|
-
* @param args
|
|
416
|
-
*
|
|
417
|
-
* Additional arguments passed to the outer `<svg>` element.
|
|
418
|
-
*
|
|
419
|
-
* @returns
|
|
420
|
-
*
|
|
421
|
-
* An `SVGSVGElement` containing a `<use>` element.
|
|
422
|
-
*/
|
|
423
|
-
export declare const svgUse: (id: string, ...args: HArgs1[]) => SVGSVGElement;
|
|
424
402
|
/**
|
|
425
403
|
* Generates a UUID v1 (time-based) identifier.
|
|
426
404
|
*
|
package/nnn.js
CHANGED
|
@@ -66,66 +66,64 @@ var csvParse = (csv, separator = ",") => {
|
|
|
66
66
|
var isRecord = (arg) => typeof arg === "object" && arg != null && !isArray(arg);
|
|
67
67
|
|
|
68
68
|
// src/nnn/h.ts
|
|
69
|
-
var
|
|
69
|
+
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
70
|
+
var _h = (namespaceUri, tagOrNode, ...args) => {
|
|
70
71
|
const createElement = namespaceUri == null ? (tag) => document.createElement(tag) : (tag) => document.createElementNS(namespaceUri, tag);
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const ns = "http://www.w3.org/1999/xlink";
|
|
96
|
-
const basename = name.slice(indexOfColon + 1);
|
|
97
|
-
if (value === true) {
|
|
98
|
-
node.setAttributeNS(ns, basename, "");
|
|
99
|
-
} else if (value === false) {
|
|
100
|
-
node.removeAttributeNS(ns, basename);
|
|
101
|
-
} else {
|
|
102
|
-
node.setAttributeNS(ns, basename, "" + value);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
} else {
|
|
72
|
+
const node = isString(tagOrNode) ? createElement(tagOrNode) : tagOrNode;
|
|
73
|
+
args.forEach((arg) => {
|
|
74
|
+
let child = null;
|
|
75
|
+
if (arg instanceof Node) {
|
|
76
|
+
child = arg;
|
|
77
|
+
} else if (isArray(arg)) {
|
|
78
|
+
child = _h(namespaceUri, ...arg);
|
|
79
|
+
} else if (isRecord(arg)) {
|
|
80
|
+
for (const name in arg) {
|
|
81
|
+
const value = arg[name];
|
|
82
|
+
if (name[0] === "$") {
|
|
83
|
+
const name1 = name.slice(1);
|
|
84
|
+
if (isRecord(value)) {
|
|
85
|
+
node[name1] ??= {};
|
|
86
|
+
Object.assign(node[name1], value);
|
|
87
|
+
} else {
|
|
88
|
+
node[name1] = value;
|
|
89
|
+
}
|
|
90
|
+
} else if (node instanceof Element) {
|
|
91
|
+
const indexOfColon = name.indexOf(":");
|
|
92
|
+
if (indexOfColon >= 0) {
|
|
93
|
+
const nsKey = name.slice(0, indexOfColon);
|
|
94
|
+
if (nsKey === "xlink") {
|
|
95
|
+
const basename = name.slice(indexOfColon + 1);
|
|
106
96
|
if (value === true) {
|
|
107
|
-
node.
|
|
97
|
+
node.setAttributeNS(XLINK_NS, basename, "");
|
|
108
98
|
} else if (value === false) {
|
|
109
|
-
node.
|
|
99
|
+
node.removeAttributeNS(XLINK_NS, basename);
|
|
110
100
|
} else {
|
|
111
|
-
node.
|
|
101
|
+
node.setAttributeNS(XLINK_NS, basename, "" + value);
|
|
112
102
|
}
|
|
113
103
|
}
|
|
104
|
+
} else {
|
|
105
|
+
if (value === true) {
|
|
106
|
+
node.setAttribute(name, "");
|
|
107
|
+
} else if (value === false) {
|
|
108
|
+
node.removeAttribute(name);
|
|
109
|
+
} else {
|
|
110
|
+
node.setAttribute(name, "" + value);
|
|
111
|
+
}
|
|
114
112
|
}
|
|
115
113
|
}
|
|
116
|
-
} else if (isString(arg) || isNumber(arg)) {
|
|
117
|
-
child = document.createTextNode(arg);
|
|
118
|
-
}
|
|
119
|
-
if (child != null) {
|
|
120
|
-
node.appendChild(child);
|
|
121
114
|
}
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
115
|
+
} else if (isString(arg) || isNumber(arg)) {
|
|
116
|
+
child = document.createTextNode(arg);
|
|
117
|
+
}
|
|
118
|
+
if (child != null) {
|
|
119
|
+
node.appendChild(child);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
return node;
|
|
126
123
|
};
|
|
127
|
-
var h =
|
|
128
|
-
var s =
|
|
124
|
+
var h = _h.bind(null, null);
|
|
125
|
+
var s = _h.bind(null, "http://www.w3.org/2000/svg");
|
|
126
|
+
var svgUse = (id, ...args) => s("svg", ["use", { "xlink:href": "#" + id }], ...args);
|
|
129
127
|
|
|
130
128
|
// src/nnn/fixPlTypography.ts
|
|
131
129
|
var TAGS_TO_SKIP = ["IFRAME", "NOSCRIPT", "PRE", "SCRIPT", "STYLE", "TEXTAREA"];
|
|
@@ -298,8 +296,7 @@ var PUNCTUATION = "punctuation";
|
|
|
298
296
|
var STRING = "string";
|
|
299
297
|
var nanolightTs = /* @__PURE__ */ newTokenizer((chunk, name) => name != null ? ["span", { class: name }, chunk] : chunk, [COMMENT, /\/\*.*?\*\//s], [COMMENT, /(?<!\\)\/\/.*?(?=\n)/], [STRING, /".*?"/], [STRING, /'.*?'/], [STRING, /`.*?`/s], [STRING, /\/[^\s]*[^\\]\/[dgimsuvy]*/], [NUMBER, /0b[01_]+/], [NUMBER, /0o[01234567_]+/], [NUMBER, /0x[\dabcdef_]+/], [NUMBER, /\d[\d_]*(\.[\d_]+)?(e[+-]?[\d_]+)?/], [OPERATOR, "!"], [OPERATOR, "!="], [OPERATOR, "!=="], [OPERATOR, "%"], [OPERATOR, "%="], [OPERATOR, "&&"], [OPERATOR, "&&="], [OPERATOR, "&"], [OPERATOR, "&="], [OPERATOR, "*"], [OPERATOR, "**"], [OPERATOR, "**="], [OPERATOR, "*="], [OPERATOR, "+"], [OPERATOR, "++"], [OPERATOR, "+="], [OPERATOR, "-"], [OPERATOR, "--"], [OPERATOR, "-="], [OPERATOR, "..."], [OPERATOR, "/"], [OPERATOR, "/="], [OPERATOR, ":"], [OPERATOR, "<"], [OPERATOR, "<<"], [OPERATOR, "<<="], [OPERATOR, "<="], [OPERATOR, "="], [OPERATOR, "=="], [OPERATOR, "==="], [OPERATOR, "=>"], [OPERATOR, ">"], [OPERATOR, ">="], [OPERATOR, ">>"], [OPERATOR, ">>="], [OPERATOR, ">>>"], [OPERATOR, ">>>="], [OPERATOR, "?"], [OPERATOR, "?"], [OPERATOR, "??"], [OPERATOR, "??="], [OPERATOR, "^"], [OPERATOR, "^="], [OPERATOR, "|"], [OPERATOR, "|="], [OPERATOR, "||"], [OPERATOR, "||="], [OPERATOR, "~"], [OPERATOR, "~="], [OPERATOR, /(?<=\s):/], [PUNCTUATION, "("], [PUNCTUATION, ")"], [PUNCTUATION, ","], [PUNCTUATION, "."], [PUNCTUATION, ":"], [PUNCTUATION, ";"], [PUNCTUATION, "?."], [PUNCTUATION, "["], [PUNCTUATION, "]"], [PUNCTUATION, "{"], [PUNCTUATION, "}"], [KEYWORD_1, "as"], [KEYWORD_1, "async"], [KEYWORD_1, "await"], [KEYWORD_1, "break"], [KEYWORD_1, "case"], [KEYWORD_1, "catch"], [KEYWORD_1, "class"], [KEYWORD_1, "const"], [KEYWORD_1, "continue"], [KEYWORD_1, "debugger"], [KEYWORD_1, "default"], [KEYWORD_1, "delete"], [KEYWORD_1, "do"], [KEYWORD_1, "else"], [KEYWORD_1, "export"], [KEYWORD_1, "extends"], [KEYWORD_1, "finally"], [KEYWORD_1, "for"], [KEYWORD_1, "from"], [KEYWORD_1, "function"], [KEYWORD_1, "function*"], [KEYWORD_1, "goto"], [KEYWORD_1, "if"], [KEYWORD_1, "import"], [KEYWORD_1, "in"], [KEYWORD_1, "instanceof"], [KEYWORD_1, "is"], [KEYWORD_1, "keyof"], [KEYWORD_1, "let"], [KEYWORD_1, "new"], [KEYWORD_1, "of"], [KEYWORD_1, "package"], [KEYWORD_1, "return"], [KEYWORD_1, "super"], [KEYWORD_1, "switch"], [KEYWORD_1, "this"], [KEYWORD_1, "throw"], [KEYWORD_1, "try"], [KEYWORD_1, "type"], [KEYWORD_1, "typeof"], [KEYWORD_1, "var"], [KEYWORD_1, "void"], [KEYWORD_1, "while"], [KEYWORD_1, "with"], [KEYWORD_1, "yield"], [KEYWORD_1, "yield*"], [KEYWORD_2, "false"], [KEYWORD_2, "Infinity"], [KEYWORD_2, "NaN"], [KEYWORD_2, "null"], [KEYWORD_2, "true"], [KEYWORD_2, "undefined"], [KEYWORD_3, "any"], [KEYWORD_3, "bigint"], [KEYWORD_3, "boolean"], [KEYWORD_3, "eval"], [KEYWORD_3, "number"], [KEYWORD_3, "string"], [KEYWORD_3, "symbol"], [KEYWORD_3, "unknown"], [IDENTIFIER_1, /[\p{Lu}_$][\p{Lu}\d_$]*/u], [IDENTIFIER_2, /[\p{L}_$][\p{L}\d_$]*(?=[(`])/u], [IDENTIFIER_3, /\p{Lu}[\p{L}\d_$]*/u], [IDENTIFIER_4, /[\p{L}_$][\p{L}\d_$]*/u]);
|
|
300
298
|
// src/nnn/newEscape.ts
|
|
301
|
-
var
|
|
302
|
-
var newEscape = (escapeMap) => (template, ...values) => String.raw(template, ...escapeValues(escapeMap, values));
|
|
299
|
+
var newEscape = (escapeFn) => (template, ...values) => String.raw(template, ...values.map(escapeFn));
|
|
303
300
|
// src/nnn/newNounForm.ts
|
|
304
301
|
var PLURAL_RULES = {};
|
|
305
302
|
var newNounForm = (locale, forms) => (value) => forms[(PLURAL_RULES[locale] ??= new Intl.PluralRules(locale)).select(value)] ?? forms.other ?? "";
|
|
@@ -352,8 +349,6 @@ var rwd = (root, selector, cellWidthPx, cellHeightPx, ...specs) => {
|
|
|
352
349
|
node.height = `${cellHeightPx * height}px`;
|
|
353
350
|
}
|
|
354
351
|
};
|
|
355
|
-
// src/nnn/svgUse.ts
|
|
356
|
-
var svgUse = (id, ...args) => s("svg", ["use", { "xlink:href": "#" + id }], ...args);
|
|
357
352
|
// src/nnn/uuidV1.ts
|
|
358
353
|
var ZEROS = /* @__PURE__ */ "0".repeat(16);
|
|
359
354
|
var counter = 0;
|
|
@@ -384,7 +379,6 @@ export {
|
|
|
384
379
|
hasOwn,
|
|
385
380
|
h,
|
|
386
381
|
fixPlTypography,
|
|
387
|
-
escapeValues,
|
|
388
382
|
csvParse,
|
|
389
383
|
c
|
|
390
384
|
};
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# nnn
|
|
2
2
|
|
|
3
|
-
A collection of Jackens’ JavaScript helper utilities (version: `2026.
|
|
3
|
+
A collection of Jackens’ JavaScript helper utilities (version: `2026.4.11`).
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -20,7 +20,6 @@ npm i @jackens/nnn
|
|
|
20
20
|
import {
|
|
21
21
|
c,
|
|
22
22
|
csvParse,
|
|
23
|
-
escapeValues,
|
|
24
23
|
fixPlTypography,
|
|
25
24
|
h,
|
|
26
25
|
hasOwn,
|
|
@@ -50,12 +49,10 @@ import {
|
|
|
50
49
|
|
|
51
50
|
- [`CNode`](#CNode): Represents a CSS rule node for the [`c`](#c) helper. Keys are CSS properties or nested selectors.
|
|
52
51
|
- [`CRoot`](#CRoot): Represents the root CSS object for the [`c`](#c) helper. Keys are top-level selectors or at-rules.
|
|
53
|
-
- [`EscapeMap`](#EscapeMap): A map from value constructors (or `null`/`undefined`) to escape functions.
|
|
54
52
|
- [`HArgs`](#HArgs): Tuple argument type for the [`h`](#h) and [`s`](#s) helpers.
|
|
55
53
|
- [`HArgs1`](#HArgs1): Single argument type for the [`h`](#h) and [`s`](#s) helpers.
|
|
56
54
|
- [`c`](#c): A minimal CSS-in-JS helper that converts a JavaScript object hierarchy into a CSS string.
|
|
57
55
|
- [`csvParse`](#csvParse): Parses a CSV string into a two-dimensional array of strings.
|
|
58
|
-
- [`escapeValues`](#escapeValues): Escapes an array of values using the provided escape map.
|
|
59
56
|
- [`fixPlTypography`](#fixPlTypography): Applies Polish-specific typographic corrections to a DOM subtree.
|
|
60
57
|
- [`h`](#h): A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also [`s`](#s)).
|
|
61
58
|
- [`hasOwn`](#hasOwn): Checks whether an object has the specified key as its own property.
|
|
@@ -97,16 +94,6 @@ type CRoot = Record<PropertyKey, CNode>;
|
|
|
97
94
|
|
|
98
95
|
Represents the root CSS object for the [`c`](#c) helper. Keys are top-level selectors or at-rules.
|
|
99
96
|
|
|
100
|
-
### EscapeMap
|
|
101
|
-
|
|
102
|
-
```ts
|
|
103
|
-
type EscapeMap = Map<unknown, (value?: unknown) => string>;
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
A map from value constructors (or `null`/`undefined`) to escape functions.
|
|
107
|
-
|
|
108
|
-
Used by [`escapeValues`](#escapeValues) and [`newEscape`](#newEscape).
|
|
109
|
-
|
|
110
97
|
### HArgs
|
|
111
98
|
|
|
112
99
|
```ts
|
|
@@ -162,8 +149,8 @@ const actual1 = c({
|
|
|
162
149
|
color: 'red',
|
|
163
150
|
margin: 1,
|
|
164
151
|
'.c': { margin: 2, padding: 2 },
|
|
165
|
-
padding: 1
|
|
166
|
-
}
|
|
152
|
+
padding: 1,
|
|
153
|
+
},
|
|
167
154
|
})
|
|
168
155
|
|
|
169
156
|
const expected1 = `
|
|
@@ -187,9 +174,9 @@ const actual2 = c({
|
|
|
187
174
|
color: 'red',
|
|
188
175
|
margin: 1,
|
|
189
176
|
'.c': { margin: 2, padding: 2 },
|
|
190
|
-
padding: 1
|
|
191
|
-
}
|
|
192
|
-
}
|
|
177
|
+
padding: 1,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
193
180
|
})
|
|
194
181
|
|
|
195
182
|
const expected2 = `
|
|
@@ -214,26 +201,26 @@ const actual3 = c({
|
|
|
214
201
|
src$$2: "url(otf/jackens.otf) format('opentype')," +
|
|
215
202
|
"url(svg/jackens.svg) format('svg')",
|
|
216
203
|
font_weight: 'normal',
|
|
217
|
-
'font-style': 'normal'
|
|
204
|
+
'font-style': 'normal',
|
|
218
205
|
},
|
|
219
206
|
'@font-face$$2': {
|
|
220
207
|
font_family: 'C64',
|
|
221
|
-
src: 'url(fonts/C64_Pro_Mono-STYLE.woff)'
|
|
208
|
+
src: 'url(fonts/C64_Pro_Mono-STYLE.woff)',
|
|
222
209
|
},
|
|
223
210
|
'@keyframes spin': {
|
|
224
211
|
'0%': { transform: 'rotate(0deg)' },
|
|
225
|
-
'100%': { transform: 'rotate(360deg)' }
|
|
212
|
+
'100%': { transform: 'rotate(360deg)' },
|
|
226
213
|
},
|
|
227
214
|
div: {
|
|
228
215
|
border: 'solid red 1px',
|
|
229
216
|
'.c1': { 'background-color': '#000' },
|
|
230
217
|
' .c1': { background_color: 'black' },
|
|
231
|
-
'.c2': { backgroundColor: 'rgb(0,0,0)' }
|
|
218
|
+
'.c2': { backgroundColor: 'rgb(0,0,0)' },
|
|
232
219
|
},
|
|
233
220
|
'@media(min-width:200px)': {
|
|
234
221
|
div: { margin: 0, padding: 0 },
|
|
235
|
-
span: { color: '#000' }
|
|
236
|
-
}
|
|
222
|
+
span: { color: '#000' },
|
|
223
|
+
},
|
|
237
224
|
})
|
|
238
225
|
|
|
239
226
|
const expected3 = `
|
|
@@ -285,10 +272,10 @@ const actual4 = c({
|
|
|
285
272
|
'.b,.c': {
|
|
286
273
|
margin: 1,
|
|
287
274
|
'.d': {
|
|
288
|
-
margin: 2
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
275
|
+
margin: 2,
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
},
|
|
292
279
|
})
|
|
293
280
|
|
|
294
281
|
const expected4 = `
|
|
@@ -305,9 +292,9 @@ const actual5 = c({
|
|
|
305
292
|
'.b,.c': {
|
|
306
293
|
margin: 1,
|
|
307
294
|
'.d': {
|
|
308
|
-
margin: 2
|
|
309
|
-
}
|
|
310
|
-
}
|
|
295
|
+
margin: 2,
|
|
296
|
+
},
|
|
297
|
+
},
|
|
311
298
|
})
|
|
312
299
|
|
|
313
300
|
const expected5 = `
|
|
@@ -324,9 +311,9 @@ const actual6 = c({
|
|
|
324
311
|
'.a,.b': {
|
|
325
312
|
margin: 1,
|
|
326
313
|
'.c,.d': {
|
|
327
|
-
margin: 2
|
|
328
|
-
}
|
|
329
|
-
}
|
|
314
|
+
margin: 2,
|
|
315
|
+
},
|
|
316
|
+
},
|
|
330
317
|
})
|
|
331
318
|
|
|
332
319
|
const expected6 = `
|
|
@@ -377,30 +364,10 @@ yyy",zzz
|
|
|
377
364
|
expect(csvParse(text)).to.deep.equal([
|
|
378
365
|
['aaa\n"aaa"\naaa', 'bbb', 'ccc,ccc'],
|
|
379
366
|
['xxx,xxx', 'yyy\nyyy', 'zzz'],
|
|
380
|
-
[' 42 ', '42', ' 17']
|
|
367
|
+
[' 42 ', '42', ' 17'],
|
|
381
368
|
])
|
|
382
369
|
```
|
|
383
370
|
|
|
384
|
-
### escapeValues
|
|
385
|
-
|
|
386
|
-
```ts
|
|
387
|
-
const escapeValues: (escapeMap: EscapeMap, values: unknown[]) => string[];
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
Escapes an array of values using the provided escape map.
|
|
391
|
-
|
|
392
|
-
#### escapeMap
|
|
393
|
-
|
|
394
|
-
A map where keys are constructors (e.g., `String`, `Number`) and values are escape functions.
|
|
395
|
-
|
|
396
|
-
#### values
|
|
397
|
-
|
|
398
|
-
The array of values to escape.
|
|
399
|
-
|
|
400
|
-
#### Returns
|
|
401
|
-
|
|
402
|
-
An array of escaped strings.
|
|
403
|
-
|
|
404
371
|
### fixPlTypography
|
|
405
372
|
|
|
406
373
|
```ts
|
|
@@ -421,13 +388,18 @@ except those inside `IFRAME`, `NOSCRIPT`, `PRE`, `SCRIPT`, `STYLE`, or `TEXTAREA
|
|
|
421
388
|
#### Usage Examples
|
|
422
389
|
|
|
423
390
|
```ts
|
|
424
|
-
const p = h('p',
|
|
391
|
+
const p = h('p',
|
|
392
|
+
'Pchnąć w tę łódź jeża lub ośm skrzyń fig (zob. https://pl.wikipedia.org/wiki/Pangram).',
|
|
393
|
+
['br'],
|
|
394
|
+
['b', 'Zażółć gęślą jaźń.'],
|
|
395
|
+
)
|
|
425
396
|
|
|
426
397
|
fixPlTypography(p)
|
|
427
398
|
|
|
428
399
|
expect(p.innerHTML).to.deep.equal(
|
|
429
400
|
'Pchnąć <span style="white-space:nowrap">w </span>tę łódź jeża lub ośm skrzyń fig ' +
|
|
430
|
-
'(zob. https://\u200Bpl.\u200Bwikipedia.\u200Borg/\u200Bwiki/\u200BPangram).'
|
|
401
|
+
'(zob. https://\u200Bpl.\u200Bwikipedia.\u200Borg/\u200Bwiki/\u200BPangram).' +
|
|
402
|
+
'<br><b>Zażółć gęślą jaźń.</b>')
|
|
431
403
|
```
|
|
432
404
|
|
|
433
405
|
### h
|
|
@@ -522,6 +494,19 @@ expect(div.key).to.deep.equal({ one: 1 })
|
|
|
522
494
|
h(div, { $key: { two: 2 } })
|
|
523
495
|
|
|
524
496
|
expect(div.key).to.deep.equal({ one: 1, two: 2 })
|
|
497
|
+
|
|
498
|
+
const elemWithClass = h('div', { class: 'test' })
|
|
499
|
+
|
|
500
|
+
expect(elemWithClass.getAttribute('class')).to.equal('test')
|
|
501
|
+
|
|
502
|
+
const elemWithText = h('div', 'initial')
|
|
503
|
+
|
|
504
|
+
h(elemWithText, ' more')
|
|
505
|
+
expect(elemWithText.outerHTML).to.equal('<div>initial more</div>')
|
|
506
|
+
|
|
507
|
+
const elemWithNested = h('div', ['span', 'hello'], ['b', 'world'])
|
|
508
|
+
|
|
509
|
+
expect(elemWithNested.outerHTML).to.equal('<div><span>hello</span><b>world</b></div>')
|
|
525
510
|
```
|
|
526
511
|
|
|
527
512
|
### hasOwn
|
|
@@ -768,10 +753,10 @@ The parsed value with handler substitutions applied.
|
|
|
768
753
|
const handlers = {
|
|
769
754
|
$add: (a: number, b: number) => a + b,
|
|
770
755
|
$hello: (name: string) => `Hello ${name}!`,
|
|
771
|
-
$foo: () => 'bar'
|
|
756
|
+
$foo: () => 'bar',
|
|
772
757
|
}
|
|
773
758
|
|
|
774
|
-
const
|
|
759
|
+
const actual1 = jsOnParse(handlers, `[
|
|
775
760
|
{
|
|
776
761
|
"$add": [1, 2]
|
|
777
762
|
},
|
|
@@ -795,23 +780,33 @@ const actual = jsOnParse(handlers, `[
|
|
|
795
780
|
}
|
|
796
781
|
]`)
|
|
797
782
|
|
|
798
|
-
|
|
783
|
+
expect(actual1).to.deep.equal([
|
|
799
784
|
3,
|
|
800
785
|
'Hello World!',
|
|
801
786
|
{
|
|
802
787
|
nested: 'Hello nested World!',
|
|
803
788
|
one: 1,
|
|
804
|
-
two: 2
|
|
789
|
+
two: 2,
|
|
805
790
|
},
|
|
806
791
|
'bar',
|
|
807
792
|
{
|
|
808
793
|
$foo: ['The parent object does not have exactly one property!'],
|
|
809
794
|
one: 1,
|
|
810
|
-
two: 2
|
|
811
|
-
}
|
|
812
|
-
]
|
|
795
|
+
two: 2,
|
|
796
|
+
},
|
|
797
|
+
])
|
|
798
|
+
|
|
799
|
+
const actual2 = jsOnParse({ $notFunc: 'handler not being a function' } as any, '{"$notFunc": [1, 2]}')
|
|
813
800
|
|
|
814
|
-
expect(
|
|
801
|
+
expect(actual2).to.deep.equal({ $notFunc: [1, 2] })
|
|
802
|
+
|
|
803
|
+
const actual3 = jsOnParse(handlers, '{"$unknown_handler_key": [1, 2]}')
|
|
804
|
+
|
|
805
|
+
expect(actual3).to.deep.equal({ $unknown_handler_key: [1, 2] })
|
|
806
|
+
|
|
807
|
+
const actual4 = jsOnParse(handlers, '{"$add": {"not": "array"}}')
|
|
808
|
+
|
|
809
|
+
expect(actual4).to.deep.equal({ $add: { not: 'array' } })
|
|
815
810
|
```
|
|
816
811
|
|
|
817
812
|
### monokai
|
|
@@ -862,21 +857,21 @@ expect(nanolightTs(codeJs)).to.deep.equal([
|
|
|
862
857
|
['span', { class: 'string' }, "'42'"],
|
|
863
858
|
['span', { class: 'punctuation' }, ']'],
|
|
864
859
|
' ',
|
|
865
|
-
['span', { class: 'comment' }, '/* 42 */']
|
|
860
|
+
['span', { class: 'comment' }, '/* 42 */'],
|
|
866
861
|
])
|
|
867
862
|
```
|
|
868
863
|
|
|
869
864
|
### newEscape
|
|
870
865
|
|
|
871
866
|
```ts
|
|
872
|
-
const newEscape: (
|
|
867
|
+
const newEscape: (escapeFn: (value: any) => string) => (template: TemplateStringsArray, ...values: unknown[]) => string;
|
|
873
868
|
```
|
|
874
869
|
|
|
875
870
|
Creates a tag function for escaping interpolated values in template literals.
|
|
876
871
|
|
|
877
|
-
####
|
|
872
|
+
#### escapeFn
|
|
878
873
|
|
|
879
|
-
A
|
|
874
|
+
A function that takes a value and returns its escaped string representation.
|
|
880
875
|
|
|
881
876
|
#### Returns
|
|
882
877
|
|
|
@@ -885,27 +880,30 @@ A tag function that escapes interpolated values using the provided escape map.
|
|
|
885
880
|
#### Usage Examples
|
|
886
881
|
|
|
887
882
|
```ts
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
883
|
+
const escapeFn = (value: any): string =>
|
|
884
|
+
isArray(value)
|
|
885
|
+
? value.map(escapeFn).join(', ')
|
|
886
|
+
: value === true || value === false
|
|
887
|
+
? `b'${+value}'`
|
|
888
|
+
: value instanceof Date
|
|
889
|
+
? `'${value.toISOString().replace(/^(.+)T(.+)\..*$/, '$1 $2')}'`
|
|
890
|
+
: isFiniteNumber(value)
|
|
891
|
+
? `${value}`
|
|
892
|
+
: isString(value)
|
|
893
|
+
? `'${value.replace(/'/g, "''")}'`
|
|
894
|
+
: 'NULL'
|
|
895
|
+
|
|
896
|
+
const sql = newEscape(escapeFn)
|
|
899
897
|
|
|
900
898
|
const actual = sql`
|
|
901
899
|
SELECT *
|
|
902
900
|
FROM table_name
|
|
903
|
-
WHERE column_name IN (${[true, null, undefined, 42, '42', "4'2", new Date(323325000000)]})`
|
|
901
|
+
WHERE column_name IN (${[true, null, undefined, NaN, Infinity, 42, '42', "4'2", /42/, new Date(323325000000)]})`
|
|
904
902
|
|
|
905
903
|
const expected = `
|
|
906
904
|
SELECT *
|
|
907
905
|
FROM table_name
|
|
908
|
-
WHERE column_name IN (b'1', NULL, NULL, 42, '42', '4''2', '1980-03-31 04:30:00')`
|
|
906
|
+
WHERE column_name IN (b'1', NULL, NULL, NULL, NULL, 42, '42', '4''2', NULL, '1980-03-31 04:30:00')`
|
|
909
907
|
|
|
910
908
|
expect(actual).to.equal(expected)
|
|
911
909
|
```
|
|
@@ -957,6 +955,13 @@ expect(car(0)).to.equal('cars')
|
|
|
957
955
|
expect(car(1)).to.equal('car')
|
|
958
956
|
expect(car(17)).to.equal('cars')
|
|
959
957
|
expect(car(42)).to.equal('cars')
|
|
958
|
+
|
|
959
|
+
const empty = newNounForm('en', {})
|
|
960
|
+
|
|
961
|
+
expect(empty(0)).to.equal('')
|
|
962
|
+
expect(empty(1)).to.equal('')
|
|
963
|
+
expect(empty(17)).to.equal('')
|
|
964
|
+
expect(empty(42)).to.equal('')
|
|
960
965
|
```
|
|
961
966
|
|
|
962
967
|
### newTokenizer
|
|
@@ -989,6 +994,99 @@ A tokenizer function that accepts a code string and returns an array of decorate
|
|
|
989
994
|
2. Among matches at the same position, the longer one wins.
|
|
990
995
|
3. Among matches of the same position and length, the one defined earlier wins.
|
|
991
996
|
|
|
997
|
+
#### Usage Examples
|
|
998
|
+
|
|
999
|
+
```ts
|
|
1000
|
+
const tokenizer1 = newTokenizer(
|
|
1001
|
+
(chunk, metadata) => ({ chunk, metadata }),
|
|
1002
|
+
['keyword', /\b(if|else|for)\b/],
|
|
1003
|
+
['string', /"[^"]*"/],
|
|
1004
|
+
)
|
|
1005
|
+
const result1 = tokenizer1('if "hello" else "world"')
|
|
1006
|
+
|
|
1007
|
+
expect(result1).to.deep.equal([
|
|
1008
|
+
{ chunk: 'if', metadata: 'keyword' },
|
|
1009
|
+
{ chunk: ' ', metadata: undefined },
|
|
1010
|
+
{ chunk: '"hello"', metadata: 'string' },
|
|
1011
|
+
{ chunk: ' ', metadata: undefined },
|
|
1012
|
+
{ chunk: 'else', metadata: 'keyword' },
|
|
1013
|
+
{ chunk: ' ', metadata: undefined },
|
|
1014
|
+
{ chunk: '"world"', metadata: 'string' },
|
|
1015
|
+
])
|
|
1016
|
+
|
|
1017
|
+
const tokenizer2 = newTokenizer(
|
|
1018
|
+
(chunk, metadata) => `${metadata}:${chunk}`,
|
|
1019
|
+
['tag', 'BEGIN'],
|
|
1020
|
+
['end', 'END'],
|
|
1021
|
+
)
|
|
1022
|
+
const result2 = tokenizer2('aBEGINbENDc')
|
|
1023
|
+
|
|
1024
|
+
expect(result2).to.deep.equal(['undefined:a', 'tag:BEGIN', 'undefined:b', 'end:END', 'undefined:c'])
|
|
1025
|
+
|
|
1026
|
+
const tokenizer3 = newTokenizer(
|
|
1027
|
+
(chunk) => chunk,
|
|
1028
|
+
['test', /test/],
|
|
1029
|
+
)
|
|
1030
|
+
const result3 = tokenizer3('')
|
|
1031
|
+
|
|
1032
|
+
expect(result3).to.deep.equal([])
|
|
1033
|
+
|
|
1034
|
+
const tokenizer4 = newTokenizer(
|
|
1035
|
+
(chunk, metadata) => ({ chunk, metadata }),
|
|
1036
|
+
['start', /^test/],
|
|
1037
|
+
)
|
|
1038
|
+
const result4 = tokenizer4('test here')
|
|
1039
|
+
|
|
1040
|
+
expect(result4).to.deep.equal([
|
|
1041
|
+
{ chunk: 'test', metadata: 'start' },
|
|
1042
|
+
{ chunk: ' here', metadata: undefined },
|
|
1043
|
+
])
|
|
1044
|
+
|
|
1045
|
+
const tokenizer5 = newTokenizer(
|
|
1046
|
+
(chunk, metadata) => metadata,
|
|
1047
|
+
['later', /x/],
|
|
1048
|
+
['earlier', /y/],
|
|
1049
|
+
)
|
|
1050
|
+
const result5 = tokenizer5('yx')
|
|
1051
|
+
|
|
1052
|
+
expect(result5).to.deep.equal(['earlier', 'later'])
|
|
1053
|
+
|
|
1054
|
+
const tokenizer6 = newTokenizer(
|
|
1055
|
+
(chunk) => chunk,
|
|
1056
|
+
['short', 'a'],
|
|
1057
|
+
['long', 'abc'],
|
|
1058
|
+
)
|
|
1059
|
+
const result6 = tokenizer6('abc')
|
|
1060
|
+
|
|
1061
|
+
expect(result6).to.deep.equal(['abc'])
|
|
1062
|
+
|
|
1063
|
+
const tokenizer7 = newTokenizer(
|
|
1064
|
+
(chunk) => chunk,
|
|
1065
|
+
['empty', ''],
|
|
1066
|
+
['word', /\w+/],
|
|
1067
|
+
)
|
|
1068
|
+
const result7 = tokenizer7('hello')
|
|
1069
|
+
|
|
1070
|
+
expect(result7).to.deep.equal(['hello'])
|
|
1071
|
+
|
|
1072
|
+
const tokenizer8 = newTokenizer(
|
|
1073
|
+
(chunk) => chunk,
|
|
1074
|
+
['test', /xyz/],
|
|
1075
|
+
)
|
|
1076
|
+
const result8 = tokenizer8('abc')
|
|
1077
|
+
|
|
1078
|
+
expect(result8).to.deep.equal(['abc'])
|
|
1079
|
+
|
|
1080
|
+
const tokenizer9 = newTokenizer(
|
|
1081
|
+
(chunk, metadata) => metadata,
|
|
1082
|
+
['a', 'a'],
|
|
1083
|
+
['b', 'b'],
|
|
1084
|
+
)
|
|
1085
|
+
const result9 = tokenizer9('aabb')
|
|
1086
|
+
|
|
1087
|
+
expect(result9).to.deep.equal(['a', 'a', 'b', 'b'])
|
|
1088
|
+
```
|
|
1089
|
+
|
|
992
1090
|
### omit
|
|
993
1091
|
|
|
994
1092
|
```ts
|
|
@@ -1085,45 +1183,45 @@ An array of breakpoint specifications, each a tuple of:
|
|
|
1085
1183
|
```ts
|
|
1086
1184
|
const style: CRoot = {
|
|
1087
1185
|
body: {
|
|
1088
|
-
margin: 0
|
|
1186
|
+
margin: 0,
|
|
1089
1187
|
},
|
|
1090
1188
|
'.r6': {
|
|
1091
1189
|
border: 'solid red 1px',
|
|
1092
1190
|
'.no-border': {
|
|
1093
|
-
border: 'none'
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1191
|
+
border: 'none',
|
|
1192
|
+
},
|
|
1193
|
+
},
|
|
1096
1194
|
}
|
|
1097
1195
|
|
|
1098
1196
|
rwd(style, '.r6', 200, 50, [6], [3], [1, 1, 2])
|
|
1099
1197
|
|
|
1100
1198
|
expect(style).to.deep.equal({
|
|
1101
1199
|
body: {
|
|
1102
|
-
margin: 0
|
|
1200
|
+
margin: 0,
|
|
1103
1201
|
},
|
|
1104
1202
|
'.r6': {
|
|
1105
1203
|
border: 'solid red 1px',
|
|
1106
1204
|
'.no-border': {
|
|
1107
|
-
border: 'none'
|
|
1205
|
+
border: 'none',
|
|
1108
1206
|
},
|
|
1109
1207
|
boxSizing: 'border-box',
|
|
1110
1208
|
display: 'block',
|
|
1111
1209
|
float: 'left',
|
|
1112
1210
|
width: '100%',
|
|
1113
|
-
height: '100px'
|
|
1211
|
+
height: '100px',
|
|
1114
1212
|
},
|
|
1115
1213
|
'@media(min-width:600px)': {
|
|
1116
1214
|
'.r6': {
|
|
1117
1215
|
width: 'calc(100% / 3)',
|
|
1118
|
-
height: '50px'
|
|
1119
|
-
}
|
|
1216
|
+
height: '50px',
|
|
1217
|
+
},
|
|
1120
1218
|
},
|
|
1121
1219
|
'@media(min-width:1200px)': {
|
|
1122
1220
|
'.r6': {
|
|
1123
1221
|
width: 'calc(50% / 3)',
|
|
1124
|
-
height: '50px'
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1222
|
+
height: '50px',
|
|
1223
|
+
},
|
|
1224
|
+
},
|
|
1127
1225
|
})
|
|
1128
1226
|
```
|
|
1129
1227
|
|
|
@@ -1158,6 +1256,30 @@ Additional arguments processed as follows:
|
|
|
1158
1256
|
|
|
1159
1257
|
The created or modified `SVGElement`.
|
|
1160
1258
|
|
|
1259
|
+
#### Usage Examples
|
|
1260
|
+
|
|
1261
|
+
```ts
|
|
1262
|
+
const svg = s('svg')
|
|
1263
|
+
|
|
1264
|
+
s(svg, { 'xlink:href': true })
|
|
1265
|
+
expect(svg.getAttributeNS('http://www.w3.org/1999/xlink', 'href')).to.equal('')
|
|
1266
|
+
|
|
1267
|
+
const svg2 = s('svg')
|
|
1268
|
+
|
|
1269
|
+
s(svg2, { 'xlink:href': false })
|
|
1270
|
+
expect(svg2.getAttributeNS('http://www.w3.org/1999/xlink', 'href')).to.be.null
|
|
1271
|
+
|
|
1272
|
+
const svg3 = s('svg')
|
|
1273
|
+
|
|
1274
|
+
s(svg3, { 'xlink:href': 'http://example.com' })
|
|
1275
|
+
expect(svg3.getAttributeNS('http://www.w3.org/1999/xlink', 'href')).to.equal('http://example.com')
|
|
1276
|
+
|
|
1277
|
+
const svg4 = s('svg')
|
|
1278
|
+
|
|
1279
|
+
s(svg4, { 'xlink:title': 42 })
|
|
1280
|
+
expect(svg4.getAttributeNS('http://www.w3.org/1999/xlink', 'title')).to.equal('42')
|
|
1281
|
+
```
|
|
1282
|
+
|
|
1161
1283
|
### svgUse
|
|
1162
1284
|
|
|
1163
1285
|
```ts
|
|
@@ -1180,6 +1302,49 @@ Additional arguments passed to the outer `<svg>` element.
|
|
|
1180
1302
|
|
|
1181
1303
|
An `SVGSVGElement` containing a `<use>` element.
|
|
1182
1304
|
|
|
1305
|
+
#### Usage Examples
|
|
1306
|
+
|
|
1307
|
+
```ts
|
|
1308
|
+
const XLINK_NS = 'http://www.w3.org/1999/xlink'
|
|
1309
|
+
|
|
1310
|
+
const svg = svgUse('icon-home')
|
|
1311
|
+
|
|
1312
|
+
expect(svg.tagName).to.equal('SVG')
|
|
1313
|
+
expect(svg.children.length).to.equal(1)
|
|
1314
|
+
|
|
1315
|
+
const useElement = svg.children[0]
|
|
1316
|
+
|
|
1317
|
+
expect(useElement.tagName).to.equal('USE')
|
|
1318
|
+
expect(useElement.getAttributeNS(XLINK_NS, 'href')).to.equal('#icon-home')
|
|
1319
|
+
|
|
1320
|
+
const svgWithViewBox = svgUse('icon-star', { viewBox: '0 0 24 24' })
|
|
1321
|
+
|
|
1322
|
+
expect(svgWithViewBox.getAttribute('viewBox')).to.equal('0 0 24 24')
|
|
1323
|
+
|
|
1324
|
+
const useViewBox = svgWithViewBox.children[0]
|
|
1325
|
+
|
|
1326
|
+
expect(useViewBox.getAttributeNS(XLINK_NS, 'href')).to.equal('#icon-star')
|
|
1327
|
+
|
|
1328
|
+
const svgWithClass = svgUse('icon-menu', { class: 'icon-btn' })
|
|
1329
|
+
|
|
1330
|
+
expect(svgWithClass.getAttribute('class')).to.equal('icon-btn')
|
|
1331
|
+
expect(svgWithClass.children.length).to.equal(1)
|
|
1332
|
+
|
|
1333
|
+
const useClass = svgWithClass.children[0]
|
|
1334
|
+
|
|
1335
|
+
expect(useClass.getAttributeNS(XLINK_NS, 'href')).to.equal('#icon-menu')
|
|
1336
|
+
|
|
1337
|
+
const svgWithMultipleAttrs = svgUse('icon-settings', { width: 24, height: 24, class: 'icon' })
|
|
1338
|
+
|
|
1339
|
+
expect(svgWithMultipleAttrs.getAttribute('width')).to.equal('24')
|
|
1340
|
+
expect(svgWithMultipleAttrs.getAttribute('height')).to.equal('24')
|
|
1341
|
+
expect(svgWithMultipleAttrs.getAttribute('class')).to.equal('icon')
|
|
1342
|
+
|
|
1343
|
+
const useMultiple = svgWithMultipleAttrs.children[0]
|
|
1344
|
+
|
|
1345
|
+
expect(useMultiple.getAttributeNS(XLINK_NS, 'href')).to.equal('#icon-settings')
|
|
1346
|
+
```
|
|
1347
|
+
|
|
1183
1348
|
### uuidV1
|
|
1184
1349
|
|
|
1185
1350
|
```ts
|
|
@@ -1282,40 +1447,40 @@ vivify(ref).one.two[3][4]
|
|
|
1282
1447
|
|
|
1283
1448
|
expect(ref).to.deep.equal({
|
|
1284
1449
|
one: {
|
|
1285
|
-
two: [undefined, undefined, undefined, []]
|
|
1286
|
-
}
|
|
1450
|
+
two: [undefined, undefined, undefined, []],
|
|
1451
|
+
},
|
|
1287
1452
|
})
|
|
1288
1453
|
|
|
1289
1454
|
vivify(ref).one.two[3][4] = 5
|
|
1290
1455
|
|
|
1291
1456
|
expect(ref).to.deep.equal({
|
|
1292
1457
|
one: {
|
|
1293
|
-
two: [undefined, undefined, undefined, [undefined, undefined, undefined, undefined, 5]]
|
|
1294
|
-
}
|
|
1458
|
+
two: [undefined, undefined, undefined, [undefined, undefined, undefined, undefined, 5]],
|
|
1459
|
+
},
|
|
1295
1460
|
})
|
|
1296
1461
|
|
|
1297
1462
|
vivify(ref).one.two[3].length = 1
|
|
1298
1463
|
|
|
1299
1464
|
expect(ref).to.deep.equal({
|
|
1300
1465
|
one: {
|
|
1301
|
-
two: [undefined, undefined, undefined, [undefined]]
|
|
1302
|
-
}
|
|
1466
|
+
two: [undefined, undefined, undefined, [undefined]],
|
|
1467
|
+
},
|
|
1303
1468
|
})
|
|
1304
1469
|
|
|
1305
1470
|
vivify(ref).one.two[3] = 4
|
|
1306
1471
|
|
|
1307
1472
|
expect(ref).to.deep.equal({
|
|
1308
1473
|
one: {
|
|
1309
|
-
two: [undefined, undefined, undefined, 4]
|
|
1310
|
-
}
|
|
1474
|
+
two: [undefined, undefined, undefined, 4],
|
|
1475
|
+
},
|
|
1311
1476
|
})
|
|
1312
1477
|
|
|
1313
1478
|
expect(vivify(ref).one.two.length).to.equal(4)
|
|
1314
1479
|
|
|
1315
1480
|
expect(ref).to.deep.equal({
|
|
1316
1481
|
one: {
|
|
1317
|
-
two: [undefined, undefined, undefined, 4]
|
|
1318
|
-
}
|
|
1482
|
+
two: [undefined, undefined, undefined, 4],
|
|
1483
|
+
},
|
|
1319
1484
|
})
|
|
1320
1485
|
|
|
1321
1486
|
vivify(ref).one.two = 3
|