@jackens/nnn 2023.8.19 → 2023.8.25

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 (3) hide show
  1. package/nnn.d.ts +52 -50
  2. package/nnn.js +101 -93
  3. package/package.json +1 -1
package/nnn.d.ts CHANGED
@@ -1,26 +1,26 @@
1
1
  /**
2
- * The type of arguments of the `$c` helper.
2
+ * The type of arguments of the `css` helper.
3
3
  */
4
- export type $CNode = {
5
- [attributeOrSelector: string]: string | number | $CNode;
4
+ export type CNode = {
5
+ [attributeOrSelector: string]: string | number | CNode;
6
6
  };
7
7
 
8
8
  /**
9
- * The type of arguments of the `$c` helper.
9
+ * The type of arguments of the `css` helper.
10
10
  */
11
- export type $CRoot = Record<string, $CNode>;
11
+ export type CRoot = Record<string, CNode>;
12
12
 
13
13
  /**
14
- * The type of arguments of the `$escapeValues` and `$escape` helpers.
14
+ * The type of arguments of the `escapeValues` and `escape` helpers.
15
15
  */
16
- export type $EscapeMap = Map<any, (value?: any) => string>;
16
+ export type EscapeMap = Map<any, (value?: any) => string>;
17
17
 
18
18
  /**
19
- * The type of arguments of the `$h` and `$s` helpers.
19
+ * The type of arguments of the `h` and `s` helpers.
20
20
  */
21
- export type $HArgs = [
21
+ export type HArgs = [
22
22
  string | Node,
23
- ...(Record<string, any> | null | undefined | Node | string | number | $HArgs)[]
23
+ ...(Record<string, any> | null | undefined | Node | string | number | HArgs)[]
24
24
  ];
25
25
 
26
26
  /**
@@ -34,42 +34,44 @@ export type $HArgs = [
34
34
  * - Commas in keys that makes a CSS rule cause it to “split” and create separate rules for each part (e.g. `{div:{margin:1,'.a,.b,.c':{margin:2}}}` → `div{margin:1}div.a,div.b,div.c{margin:2}`).
35
35
  * - Top-level keys that begin with `@` are not concatenated with sub-object keys.
36
36
  */
37
- export function $c(root: $CRoot, splitter?: string): string;
37
+ export function css(root: CRoot, splitter?: string): string;
38
38
 
39
39
  /**
40
40
  * A helper for creating a chart based on a table (conf. <https://jackens.github.io/nnn/chartable/>).
41
41
  *
42
42
  * Options:
43
43
  * - `bottom`: bottom padding (for X axis labels)
44
+ * - `gapX`: X axis spacing
45
+ * - `gapY`: Y axis spacing
44
46
  * - `headerColumn`: flag indicating that `table` has a header column (with X axis labels)
45
47
  * - `headerRow`: flag indicating that `table` has a header row (with data series labels)
48
+ * - `id`: chart id
46
49
  * - `left`: left padding (for data series labels)
50
+ * - `maxY`: number of Y axis lines
47
51
  * - `right`: right padding (for data series labels)
48
52
  * - `singleScale`: flag to force single scale
49
53
  * - `table`: `HTMLTableElement` to extract data, data series labels and X axis labels
50
54
  * - `title`: chart title
51
55
  * - `top`: top padding (for the title)
52
- * - `xGap`: X axis spacing
53
56
  * - `xLabels`: X axis labels
54
- * - `yGap`: Y axis spacing
55
- * - `yMax`: number of Y axis lines
56
57
  * - `zLabels`: data series labels
57
58
  * - `zxY`: chart data
58
59
  */
59
- export function $chartable(options?: {
60
+ export function chartable(options?: {
60
61
  bottom?: number;
62
+ gapX?: number;
63
+ gapY?: number;
61
64
  headerColumn?: boolean;
62
65
  headerRow?: boolean;
66
+ id?: string;
63
67
  left?: number;
68
+ maxY?: number;
64
69
  right?: number;
65
70
  singleScale?: boolean;
66
71
  table?: HTMLTableElement;
67
72
  title?: string;
68
73
  top?: number;
69
- xGap?: number;
70
74
  xLabels?: string[];
71
- yGap?: number;
72
- yMax?: number;
73
75
  zLabels?: string[];
74
76
  zxY?: number[][];
75
77
  }): SVGSVGElement;
@@ -77,30 +79,30 @@ export function $chartable(options?: {
77
79
  /**
78
80
  * A helper that checks equality of the given arguments.
79
81
  */
80
- export function $eq(x: any, y: any): boolean;
82
+ export function eq(x: any, y: any): boolean;
81
83
 
82
84
  /**
83
85
  * A generic helper for escaping `values` by given `escapeMap` (in *TemplateStrings* flavor).
84
86
  */
85
- export function $escape(escapeMap: $EscapeMap, template: TemplateStringsArray, ...values: any[]): string;
87
+ export function escape(escapeMap: EscapeMap, template: TemplateStringsArray, ...values: any[]): string;
86
88
 
87
89
  /**
88
90
  * A generic helper for escaping `values` by given `escapeMap`.
89
91
  */
90
- export function $escapeValues(escapeMap: $EscapeMap, values: any[]): string[];
92
+ export function escapeValues(escapeMap: EscapeMap, values: any[]): string[];
91
93
 
92
94
  /**
93
95
  * A helper that implements typographic corrections specific to Polish typography.
94
96
  */
95
- export function $fixTypography(node: Node): void;
97
+ export function fixTypography(node: Node): void;
96
98
 
97
99
  /**
98
100
  * A convenient helper for getting values of nested objects.
99
101
  */
100
- export function $get(defaultValue: any, ref: any, ...keys: (string | number | symbol)[]): any;
102
+ export function get(defaultValue: any, ref: any, ...keys: (string | number | symbol)[]): any;
101
103
 
102
104
  /**
103
- * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also `$s`).
105
+ * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also `s`).
104
106
  *
105
107
  * - The first argument of type `string` specifies the tag of the element to be created.
106
108
  * - The first argument of type `Node` specifies the element to be modified.
@@ -112,58 +114,58 @@ export function $get(defaultValue: any, ref: any, ...keys: (string | number | sy
112
114
  * - All other arguments of type `null` or `undefined` are simply ignored.
113
115
  * - All other arguments of type `Node` are appended to the element being created or modified.
114
116
  * - All other arguments of type `string`/`number` are converted to `Text` nodes and appended to the element being created or modified.
115
- * - All other arguments of type `$HArgs` are passed to `$h` and the results are appended to the element being created or modified.
117
+ * - All other arguments of type `HArgs` are passed to `h` and the results are appended to the element being created or modified.
116
118
  */
117
- export function $h<T extends keyof HTMLElementTagNameMap>(tag: T, ...args: $HArgs[1][]): HTMLElementTagNameMap[T];
118
- export function $h<N extends Node>(node: N, ...args: $HArgs[1][]): N;
119
- export function $h(...args: $HArgs): Node;
119
+ export function h<T extends keyof HTMLElementTagNameMap>(tag: T, ...args: HArgs[1][]): HTMLElementTagNameMap[T];
120
+ export function h<N extends Node>(node: N, ...args: HArgs[1][]): N;
121
+ export function h(...args: HArgs): Node;
120
122
 
121
123
  /**
122
124
  * A replacement for the `in` operator (not to be confused with the `for-in` loop) that works properly.
123
125
  */
124
- export function $in(key: any, ref: any): boolean;
126
+ export function has(key: any, ref: any): boolean;
125
127
 
126
128
  /**
127
129
  * A helper that checks if the given argument is of a certain type.
128
130
  */
129
- export function $is(type: BigIntConstructor, arg: any): arg is bigint;
130
- export function $is(type: BooleanConstructor, arg: any): arg is boolean;
131
- export function $is(type: NumberConstructor, arg: any): arg is number;
132
- export function $is(type: StringConstructor, arg: any): arg is string;
133
- export function $is(type: SymbolConstructor, arg: any): arg is symbol;
134
- export function $is(type: undefined, arg: any): arg is null | undefined;
135
- export function $is<T extends abstract new (...args: any[]) => any>(type: T, arg: any): arg is InstanceType<T>;
131
+ export function is(type: BigIntConstructor, arg: any): arg is bigint;
132
+ export function is(type: BooleanConstructor, arg: any): arg is boolean;
133
+ export function is(type: NumberConstructor, arg: any): arg is number;
134
+ export function is(type: StringConstructor, arg: any): arg is string;
135
+ export function is(type: SymbolConstructor, arg: any): arg is symbol;
136
+ export function is(type: undefined, arg: any): arg is null | undefined;
137
+ export function is<T extends abstract new (...args: any[]) => any>(type: T, arg: any): arg is InstanceType<T>;
136
138
 
137
139
  /**
138
140
  * Language translations helper.
139
141
  */
140
- export function $locale(
142
+ export function locale(
141
143
  locales: Record<string, Record<string, string | Record<string, string>>>,
142
144
  defaultLanguage: string,
143
145
  languages?: readonly string[]
144
146
  ): (text?: string, version?: string) => string;
145
147
 
146
148
  /**
147
- * A generic helper for syntax highlighting (see also `$nanolightJs`).
149
+ * A generic helper for syntax highlighting (see also `nanolightJs`).
148
150
  */
149
- export function $nanolight(
151
+ export function nanolight(
150
152
  pattern: RegExp,
151
- highlighters: ((chunk: string, index: number) => $HArgs[1])[],
153
+ highlighters: ((chunk: string, index: number) => HArgs[1])[],
152
154
  code: string
153
- ): $HArgs[1][];
155
+ ): HArgs[1][];
154
156
 
155
157
  /**
156
158
  * A helper for highlighting JavaScript.
157
159
  */
158
- export function $nanolightJs(codeJs: string): $HArgs[1][];
160
+ export function nanolightJs(codeJs: string): HArgs[1][];
159
161
 
160
162
  /**
161
163
  * A helper for choosing the correct singular and plural.
162
164
  */
163
- export function $plUral(singular: string, plural2: string, plural5: string, value: number): string;
165
+ export function plUral(singular: string, plural2: string, plural5: string, value: number): string;
164
166
 
165
167
  /**
166
- * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also `$h`).
168
+ * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also `h`).
167
169
  *
168
170
  * - The first argument of type `string` specifies the tag of the element to be created.
169
171
  * - The first argument of type `Node` specifies the element to be modified.
@@ -175,16 +177,16 @@ export function $plUral(singular: string, plural2: string, plural5: string, valu
175
177
  * - All other arguments of type `null` or `undefined` are simply ignored.
176
178
  * - All other arguments of type `Node` are appended to the element being created or modified.
177
179
  * - All other arguments of type `string`/`number` are converted to `Text` nodes and appended to the element being created or modified.
178
- * - All other arguments of type `$HArgs` are passed to `$s` and the results are appended to the element being created or modified.
180
+ * - All other arguments of type `HArgs` are passed to `s` and the results are appended to the element being created or modified.
179
181
  */
180
- export function $s<T extends keyof SVGElementTagNameMap>(tag: T, ...args: $HArgs[1][]): SVGElementTagNameMap[T];
181
- export function $s<N extends Node>(node: N, ...args: $HArgs[1][]): N;
182
- export function $s(...args: $HArgs): Node;
182
+ export function s<T extends keyof SVGElementTagNameMap>(tag: T, ...args: HArgs[1][]): SVGElementTagNameMap[T];
183
+ export function s<N extends Node>(node: N, ...args: HArgs[1][]): N;
184
+ export function s(...args: HArgs): Node;
183
185
 
184
186
  /**
185
187
  * A convenient helper for setting values of nested objects.
186
188
  */
187
- export function $set(value: any, ref: any, ...keys: (string | number | symbol)[]): void;
189
+ export function set(value: any, ref: any, ...keys: (string | number | symbol)[]): void;
188
190
 
189
191
  /**
190
192
  * A helper that generates a UUID v1 identifier (with a creation timestamp).
@@ -192,7 +194,7 @@ export function $set(value: any, ref: any, ...keys: (string | number | symbol)[]
192
194
  * - The optional `node` parameter should have the format `/^[0123456789abcdef]+$/`.
193
195
  * Its value will be trimmed to last 12 characters and left padded with zeros.
194
196
  */
195
- export function $uuid1(options?: {
197
+ export function uuid1(options?: {
196
198
  date?: Date;
197
199
  node?: string;
198
200
  }): string;
package/nnn.js CHANGED
@@ -1,31 +1,31 @@
1
1
  /**
2
2
  * @typedef {[
3
3
  * string | Node,
4
- * ...(Record<string, any> | null | undefined | Node | string | number | $HArgs)[]
5
- * ]} $HArgs
4
+ * ...(Record<string, any> | null | undefined | Node | string | number | HArgs)[]
5
+ * ]} HArgs
6
6
  */
7
7
 
8
8
  /**
9
9
  * @typedef {{
10
- * [attributeOrSelector: string]: string | number | $CNode;
11
- * }} $CNode
10
+ * [attributeOrSelector: string]: string | number | CNode;
11
+ * }} CNode
12
12
  */
13
13
 
14
14
  /**
15
- * @typedef {Record<string, $CNode>} $CRoot
15
+ * @typedef {Record<string, CNode>} CRoot
16
16
  */
17
17
 
18
18
  /**
19
- * @typedef {Map<any, (value?: any) => string>} $EscapeMap
19
+ * @typedef {Map<any, (value?: any) => string>} EscapeMap
20
20
  */
21
21
 
22
- const _c = (
23
- /** @type {$CNode} */ node,
22
+ const _css = (
23
+ /** @type {CNode} */ node,
24
24
  /** @type {string} */ prefix,
25
25
  /** @type {string[]} */ result,
26
26
  /** @type {(text: string) => string} */ split
27
27
  ) => {
28
- const /** @type {[$CNode | string[], string][]} */ queue = [[node, prefix]]
28
+ const /** @type {[CNode | string[], string][]} */ queue = [[node, prefix]]
29
29
 
30
30
  while (queue.length) {
31
31
  const [style2, prefix2] = queue.shift() ?? []
@@ -34,17 +34,17 @@ const _c = (
34
34
  continue
35
35
  }
36
36
 
37
- if ($is(Array, style2)) {
37
+ if (is(Array, style2)) {
38
38
  result.push(prefix2, prefix2 !== '' ? '{' : '', style2.join(';'), prefix2 !== '' ? '}' : '')
39
39
  } else {
40
- const /** @type {[$CNode | string[], string][]} */ todo = []
40
+ const /** @type {[CNode | string[], string][]} */ todo = []
41
41
  let /** @type {string[]} */ attributes = []
42
42
  let attributesPushed = false
43
43
 
44
44
  for (const key in style2) {
45
45
  const value = style2[key]
46
46
 
47
- if ($is(String, value) || $is(Number, value)) {
47
+ if (is(String, value) || is(Number, value)) {
48
48
  if (!attributesPushed) {
49
49
  attributesPushed = true
50
50
  attributes = []
@@ -73,7 +73,7 @@ const _c = (
73
73
  }
74
74
  }
75
75
 
76
- export const $c = (/** @type {$CRoot} */ root, splitter = '$$') => {
76
+ export const css = (/** @type {CRoot} */ root, splitter = '$$') => {
77
77
  const split = (/** @type {string} */ text) => text.split(splitter)[0]
78
78
  const /** @type {string[]} */ result = []
79
79
 
@@ -82,10 +82,10 @@ export const $c = (/** @type {$CRoot} */ root, splitter = '$$') => {
82
82
 
83
83
  if (key[0] === '@') {
84
84
  result.push(split(key) + '{')
85
- _c(value, '', result, split)
85
+ _css(value, '', result, split)
86
86
  result.push('}')
87
87
  } else {
88
- _c(value, split(key), result, split)
88
+ _css(value, split(key), result, split)
89
89
  }
90
90
  }
91
91
 
@@ -97,54 +97,57 @@ const _COLORS = ['#e22', '#e73', '#fc3', '#ad4', '#4d9', '#3be', '#45d', '#c3e']
97
97
  /**
98
98
  * @param {{
99
99
  * bottom?: number;
100
+ * gapX?: number;
101
+ * gapY?: number;
100
102
  * headerColumn?: boolean;
101
103
  * headerRow?: boolean;
104
+ * id?: string;
102
105
  * left?: number;
106
+ * maxY?: number;
103
107
  * right?: number;
104
108
  * singleScale?: boolean;
105
109
  * table?: HTMLTableElement;
106
110
  * title?: string;
107
111
  * top?: number;
108
- * xGap?: number;
109
112
  * xLabels?: string[];
110
- * yGap?: number;
111
- * yMax?: number;
112
113
  * zLabels?: string[];
113
114
  * zxY?: number[][];
114
115
  * }} options
115
116
  */
116
- export const $chartable = ({
117
+ export const chartable = ({
117
118
  bottom = 50,
119
+ gapX = 70,
120
+ gapY = 30,
118
121
  headerColumn = false,
119
122
  headerRow = true,
123
+ id,
120
124
  left = 200,
125
+ maxY = 10,
121
126
  right = 200,
122
127
  singleScale = false,
123
128
  table,
124
129
  title,
125
130
  top = 70,
126
- xGap = 70,
127
131
  xLabels = [],
128
- yGap = 30,
129
- yMax = 10,
130
132
  zLabels = [],
131
133
  zxY = []
132
134
  } = {}) => {
133
135
  if (table != null) {
134
- zxY = []
135
- xLabels = []
136
- zLabels = []
136
+ const zxYNotPassed = !zxY.length
137
+ const xLabelsNotPassed = !xLabels.length
138
+ const zLabelsNotPassed = !zLabels.length
139
+
137
140
  table.querySelectorAll('tr').forEach((row, r) => row.querySelectorAll('td,th').forEach((col, c) => {
138
141
  const x = r - +headerRow
139
142
  const z = c - +headerColumn
140
143
  // @ts-expect-error
141
144
  const value = col.innerText
142
145
 
143
- if (x >= 0 && z >= 0) {
144
- $set(parseFloat(value), zxY, z, x)
145
- } else if (x >= 0 && z < 0) {
146
+ if (x >= 0 && z >= 0 && zxYNotPassed) {
147
+ set(parseFloat(value), zxY, z, x)
148
+ } else if (x >= 0 && z < 0 && xLabelsNotPassed) {
146
149
  xLabels[x] = value
147
- } else if (x < 0 && z >= 0) {
150
+ } else if (x < 0 && z >= 0 && zLabelsNotPassed) {
148
151
  zLabels[z] = value
149
152
  }
150
153
  }))
@@ -177,8 +180,13 @@ export const $chartable = ({
177
180
  }
178
181
  })
179
182
 
180
- const cost = ranges.reduce((result, [min, max]) =>
181
- (result += 1 - (max - min) / (min1 <= min && max <= max1 ? max1 - min1 : max2 - min2)), 0)
183
+ let cost = 0
184
+
185
+ ranges.forEach(([min, max]) => {
186
+ if (min < max) {
187
+ cost += 1 - (max - min) / (min1 <= min && max <= max1 ? max1 - min1 : max2 - min2)
188
+ }
189
+ })
182
190
 
183
191
  if (bestScales[4] > cost) {
184
192
  bestScales = [min1, max1, min2, max2, cost]
@@ -188,22 +196,22 @@ export const $chartable = ({
188
196
  }
189
197
 
190
198
  const [min1, max1, min2, max2] = bestScales
191
- const xMax = zxY[0].length
192
- const xi = Array.from({ length: xMax }, (_, x) => x * xGap)
193
- const yi = Array.from({ length: yMax }, (_, y) => y * yGap)
194
- const w = xGap * (xMax - 1)
195
- const h = yGap * (yMax - 1)
199
+ const maxX = zxY[0].length
200
+ const xi = Array.from({ length: maxX }, (_, x) => x * gapX)
201
+ const yi = Array.from({ length: maxY }, (_, y) => y * gapY)
202
+ const w = gapX * (maxX - 1)
203
+ const h = gapY * (maxY - 1)
196
204
  const svgW = left + w + right
197
205
  const svgH = top + h + bottom
198
- const /** @type {$HArgs} */ graph = ['g', { transform: `translate(${left} ${top})` },
206
+ const /** @type {HArgs} */ graph = ['g', { transform: `translate(${left} ${top})` },
199
207
  ...yi.map(y => ['line', { x1: 0, x2: w, y1: y, y2: y, stroke: '#8888' }]),
200
208
  ...xi.map(x => ['line', { x1: x, x2: x, y1: 0, y2: h, stroke: '#8888' }])]
201
- const /** @type {$HArgs} */ lColors = ['g', { class: 'chartable-z-colors', transform: 'translate(-80 0)' }]
202
- const /** @type {$HArgs} */ lLabels = ['g', { class: 'chartable-z-labels', transform: 'translate(-95 0)' }]
203
- const /** @type {$HArgs} */ rColors = ['g', { class: 'chartable-z-colors', transform: 'translate(80 0)' }]
204
- const /** @type {$HArgs} */ rLabels = ['g', { class: 'chartable-z-labels', transform: 'translate(95 0)' }]
209
+ const /** @type {HArgs} */ lColors = ['g', { class: 'chartable-z-colors', transform: 'translate(-80 0)' }]
210
+ const /** @type {HArgs} */ lLabels = ['g', { class: 'chartable-z-labels', transform: 'translate(-95 0)' }]
211
+ const /** @type {HArgs} */ rColors = ['g', { class: 'chartable-z-colors', transform: 'translate(80 0)' }]
212
+ const /** @type {HArgs} */ rLabels = ['g', { class: 'chartable-z-labels', transform: 'translate(95 0)' }]
205
213
  const yLabel = (/** @type {number} */ min, /** @type {number} */ max, /** @type {number} */ y) =>
206
- (min + (max - min) * (yMax - 1 - y) / (yMax - 1)).toFixed(2).replace(/\.?0+$/, '')
214
+ (min + (max - min) * (maxY - 1 - y) / (maxY - 1)).toFixed(2).replace(/\.?0+$/, '')
207
215
 
208
216
  zxY.forEach((xa, z) => {
209
217
  const cls = `chartable-z-${z + 1}`
@@ -213,16 +221,16 @@ export const $chartable = ({
213
221
  if (min1 <= min && max <= max1) {
214
222
  min = min1
215
223
  max = max1
216
- lColors.push(['circle', { class: cls, cx: 0, cy: yGap * (lColors.length - 2), r: 5, fill }])
224
+ lColors.push(['circle', { class: cls, cx: 0, cy: gapY * (lColors.length - 2), r: 5, fill }])
217
225
  lLabels.push(['text',
218
- { x: 0, y: yGap * (lLabels.length - 2), 'text-anchor': 'end', 'alignment-baseline': 'middle' },
226
+ { x: 0, y: gapY * (lLabels.length - 2), 'text-anchor': 'end', 'alignment-baseline': 'middle' },
219
227
  zLabels[z]])
220
228
  } else {
221
229
  min = min2
222
230
  max = max2
223
- rColors.push(['circle', { class: cls, cx: 0, cy: yGap * (rColors.length - 2), r: 5, fill }])
231
+ rColors.push(['circle', { class: cls, cx: 0, cy: gapY * (rColors.length - 2), r: 5, fill }])
224
232
  rLabels.push(['text',
225
- { x: 0, y: yGap * (rLabels.length - 2), 'text-anchor': 'start', 'alignment-baseline': 'middle' },
233
+ { x: 0, y: gapY * (rLabels.length - 2), 'text-anchor': 'start', 'alignment-baseline': 'middle' },
226
234
  zLabels[z]])
227
235
  }
228
236
 
@@ -239,12 +247,12 @@ export const $chartable = ({
239
247
  })
240
248
  })
241
249
 
242
- return $s('svg', {
250
+ return s('svg', {
243
251
  viewBox: `0 0 ${svgW} ${svgH}`,
244
252
  width: `${svgW}px`,
245
253
  height: `${svgH}px`,
246
254
  class: 'chartable'
247
- }, title != null
255
+ }, id != null ? { id } : null, title != null
248
256
  ? ['text',
249
257
  { class: 'chartable-title', x: svgW / 2, y: top / 2, 'text-anchor': 'middle', 'alignment-baseline': 'middle' },
250
258
  title]
@@ -276,7 +284,7 @@ export const $chartable = ({
276
284
  )
277
285
  }
278
286
 
279
- export const $eq = /** @returns {boolean} */ (/** @type {any} */ x, /** @type {any} */ y) => {
287
+ export const eq = /** @returns {boolean} */ (/** @type {any} */ x, /** @type {any} */ y) => {
280
288
  if (x === y) {
281
289
  return true
282
290
  }
@@ -297,12 +305,12 @@ export const $eq = /** @returns {boolean} */ (/** @type {any} */ x, /** @type {a
297
305
  }
298
306
 
299
307
  if (xConstructor === Array) {
300
- return x.length === y.length && x.every((/** @type {any} */ item, /** @type {number} */ index) => $eq(item, y[index]))
308
+ return x.length === y.length && x.every((/** @type {any} */ item, /** @type {number} */ index) => eq(item, y[index]))
301
309
  }
302
310
 
303
311
  if (xConstructor === Object) {
304
312
  const keysOfX = Object.keys(x)
305
- return keysOfX.length === Object.keys(y).length && keysOfX.every(key => $eq(x[key], y[key]))
313
+ return keysOfX.length === Object.keys(y).length && keysOfX.every(key => eq(x[key], y[key]))
306
314
  }
307
315
 
308
316
  if (xConstructor === Set || xConstructor === Map) {
@@ -311,27 +319,27 @@ export const $eq = /** @returns {boolean} */ (/** @type {any} */ x, /** @type {a
311
319
  }
312
320
  const xa = [...x]
313
321
  const ya = [...y]
314
- return xa.every(xv => ya.find(yv => $eq(xv, yv)))
322
+ return xa.every(xv => ya.find(yv => eq(xv, yv)))
315
323
  }
316
324
  }
317
325
 
318
326
  return false
319
327
  }
320
328
 
321
- export const $escape = (
322
- /** @type {$EscapeMap} */ escapeMap,
329
+ export const escape = (
330
+ /** @type {EscapeMap} */ escapeMap,
323
331
  /** @type {TemplateStringsArray} */ template,
324
332
  /** @type {any[]} */ ...values
325
- ) => String.raw(template, ...$escapeValues(escapeMap, values))
333
+ ) => String.raw(template, ...escapeValues(escapeMap, values))
326
334
 
327
- export const $escapeValues = (
328
- /** @type {$EscapeMap} */ escapeMap,
335
+ export const escapeValues = (
336
+ /** @type {EscapeMap} */ escapeMap,
329
337
  /** @type {any[]} */ values
330
338
  ) => values.map(value => (escapeMap.get(value?.constructor) ?? escapeMap.get(undefined))?.(value) ?? '')
331
339
 
332
340
  const TAGS_TO_SKIP = { IFRAME: 1, NOSCRIPT: 1, PRE: 1, SCRIPT: 1, STYLE: 1, TEXTAREA: 1 }
333
341
 
334
- export const $fixTypography = (/** @type {Node} */ node) => {
342
+ export const fixTypography = (/** @type {Node} */ node) => {
335
343
  const /** @type {Node[]} */ queue = [node]
336
344
 
337
345
  while (queue.length > 0) {
@@ -343,7 +351,7 @@ export const $fixTypography = (/** @type {Node} */ node) => {
343
351
 
344
352
  if (childNode instanceof Text) {
345
353
  queue.push(childNode)
346
- } else if (childNode instanceof Element && !$in(childNode.tagName, TAGS_TO_SKIP)) {
354
+ } else if (childNode instanceof Element && !has(childNode.tagName, TAGS_TO_SKIP)) {
347
355
  queue.push(childNode)
348
356
  }
349
357
  }
@@ -354,7 +362,7 @@ export const $fixTypography = (/** @type {Node} */ node) => {
354
362
  i %= 3
355
363
 
356
364
  const currentNode = i === 2
357
- ? $h('span', { style: 'white-space:nowrap' }, chunk)
365
+ ? h('span', { style: 'white-space:nowrap' }, chunk)
358
366
  : i === 1
359
367
  ? document.createTextNode(chunk)
360
368
  : document.createTextNode(chunk.replace(/(\/(?=[^/\s])|\.(?=[^\s]))/g, '$1\u200B'))
@@ -371,13 +379,13 @@ export const $fixTypography = (/** @type {Node} */ node) => {
371
379
  }
372
380
  }
373
381
 
374
- export const $get = (
382
+ export const get = (
375
383
  /** @type {any} */ defaultValue,
376
384
  /** @type {any} */ ref,
377
385
  /** @type {(string | number | symbol)[]} */ ...keys
378
386
  ) => {
379
387
  for (const key of keys) {
380
- if (!$in(key, ref)) {
388
+ if (!has(key, ref)) {
381
389
  return defaultValue
382
390
  }
383
391
 
@@ -394,14 +402,14 @@ const /** @type {Record<string, string>} */ NS = {
394
402
  /**
395
403
  * @type {{
396
404
  * (namespaceURI?: null | undefined): {
397
- * <T extends keyof HTMLElementTagNameMap>(tag: T, ...args: $HArgs[1][]): HTMLElementTagNameMap[T];
398
- * <N extends Node> (node: N, ...args: $HArgs[1][]): N;
399
- * (...args: $HArgs): Node;
405
+ * <T extends keyof HTMLElementTagNameMap>(tag: T, ...args: HArgs[1][]): HTMLElementTagNameMap[T];
406
+ * <N extends Node> (node: N, ...args: HArgs[1][]): N;
407
+ * (...args: HArgs): Node;
400
408
  * };
401
409
  * (namespaceURI: 'http://www.w3.org/2000/svg'): {
402
- * <T extends keyof SVGElementTagNameMap> (tag: T, ...args: $HArgs[1][]): SVGElementTagNameMap[T];
403
- * <N extends Node> (node: N, ...args: $HArgs[1][]): N;
404
- * (...args: $HArgs): Node;
410
+ * <T extends keyof SVGElementTagNameMap> (tag: T, ...args: HArgs[1][]): SVGElementTagNameMap[T];
411
+ * <N extends Node> (node: N, ...args: HArgs[1][]): N;
412
+ * (...args: HArgs): Node;
405
413
  * };
406
414
  * }}
407
415
  */
@@ -410,18 +418,18 @@ const _h = (/** @type {string?=} */ namespaceURI) => {
410
418
  ? (/** @type {string } */ tag) => document.createElement(tag)
411
419
  : (/** @type {string } */ tag) => document.createElementNS(namespaceURI, tag)
412
420
 
413
- const h = (/** @type {$HArgs[0]} */ tagOrNode, /** @type {$HArgs[1][]} */ ...args) => {
414
- const node = $is(String, tagOrNode) ? createElement(tagOrNode) : tagOrNode
421
+ const h = (/** @type {HArgs[0]} */ tagOrNode, /** @type {HArgs[1][]} */ ...args) => {
422
+ const node = is(String, tagOrNode) ? createElement(tagOrNode) : tagOrNode
415
423
 
416
424
  for (const arg of args) {
417
425
  let child = null
418
426
 
419
427
  if (arg instanceof Node) {
420
428
  child = arg
421
- } else if ($is(String, arg) || $is(Number, arg)) {
429
+ } else if (is(String, arg) || is(Number, arg)) {
422
430
  // @ts-expect-error
423
431
  child = new Text(arg)
424
- } else if ($is(Array, arg)) {
432
+ } else if (is(Array, arg)) {
425
433
  // @ts-expect-error
426
434
  child = h(...arg)
427
435
  } else if (arg != null) {
@@ -431,7 +439,7 @@ const _h = (/** @type {string?=} */ namespaceURI) => {
431
439
  if (name[0] === '$') {
432
440
  const name1 = name.slice(1)
433
441
 
434
- if ($is(Object, value)) {
442
+ if (is(Object, value)) {
435
443
  // @ts-expect-error
436
444
  node[name1] = node[name1] ?? {}
437
445
  // @ts-expect-error
@@ -454,7 +462,7 @@ const _h = (/** @type {string?=} */ namespaceURI) => {
454
462
  } else if (value === false) {
455
463
  node.removeAttributeNS(ns, basename)
456
464
  } else {
457
- node.setAttributeNS(ns, basename, $is(String, value) ? value : '' + value)
465
+ node.setAttributeNS(ns, basename, is(String, value) ? value : '' + value)
458
466
  }
459
467
  }
460
468
  } else {
@@ -463,7 +471,7 @@ const _h = (/** @type {string?=} */ namespaceURI) => {
463
471
  } else if (value === false) {
464
472
  node.removeAttribute(name)
465
473
  } else {
466
- node.setAttribute(name, $is(String, value) ? value : '' + value)
474
+ node.setAttribute(name, is(String, value) ? value : '' + value)
467
475
  }
468
476
  }
469
477
  }
@@ -481,10 +489,10 @@ const _h = (/** @type {string?=} */ namespaceURI) => {
481
489
  return h
482
490
  }
483
491
 
484
- export const $h = _h()
492
+ export const h = _h()
485
493
 
486
- export const $in = (/** @type {any} */ key, /** @type {any} */ ref) =>
487
- ($is(String, key) || $is(Number, key) || $is(Symbol, key)) && Object.hasOwnProperty.call(ref ?? Object, key)
494
+ export const has = (/** @type {any} */ key, /** @type {any} */ ref) =>
495
+ (is(String, key) || is(Number, key) || is(Symbol, key)) && Object.hasOwnProperty.call(ref ?? Object, key)
488
496
 
489
497
  /**
490
498
  * @template {abstract new (...args: any[]) => any} T
@@ -501,7 +509,7 @@ export const $in = (/** @type {any} */ key, /** @type {any} */ ref) =>
501
509
  *
502
510
  * @returns {arg is bigint | boolean | number | string | symbol | undefined | null | InstanceType<T>}
503
511
  */
504
- export const $is = (/** @type {T} */ type, /** @type {any} */ arg) => arg?.constructor === type
512
+ export const is = (/** @type {T} */ type, /** @type {any} */ arg) => arg?.constructor === type
505
513
 
506
514
  const _locale = (
507
515
  /** @type {Record<string, Record<string, string | Record<string, string>>>} */ locales,
@@ -512,22 +520,22 @@ const _locale = (
512
520
  // @ts-expect-error
513
521
  const v = locales?.[language]?.[version]?.[text]
514
522
 
515
- if ($is(String, v)) {
523
+ if (is(String, v)) {
516
524
  return v
517
525
  }
518
526
 
519
527
  const t = locales?.[language]?.[text]
520
528
 
521
- return $is(String, t) ? t : text
529
+ return is(String, t) ? t : text
522
530
  }
523
531
 
524
- export const $locale = (
532
+ export const locale = (
525
533
  /** @type {Record<string, Record<string, string | Record<string, string>>>} */ locales,
526
534
  /** @type {string} */ defaultLanguage,
527
535
  languages = navigator.languages
528
536
  ) => {
529
537
  for (const language of languages) {
530
- if ($in(language, locales)) {
538
+ if (has(language, locales)) {
531
539
  // @ts-expect-error
532
540
  return _locale.bind(0, locales, language)
533
541
  }
@@ -537,12 +545,12 @@ export const $locale = (
537
545
  return _locale.bind(0, locales, defaultLanguage)
538
546
  }
539
547
 
540
- export const $nanolight = (
548
+ export const nanolight = (
541
549
  /** @type {RegExp} */ pattern,
542
- /** @type {((chunk: string, index: number) => $HArgs[1])[]} */ highlighters,
550
+ /** @type {((chunk: string, index: number) => HArgs[1])[]} */ highlighters,
543
551
  /** @type {string} */ code
544
552
  ) => {
545
- const /** @type {$HArgs[1][]} */ result = []
553
+ const /** @type {HArgs[1][]} */ result = []
546
554
 
547
555
  code.split(pattern).forEach((chunk, index) => {
548
556
  index %= highlighters.length
@@ -555,7 +563,7 @@ export const $nanolight = (
555
563
  }
556
564
 
557
565
  // @ts-expect-error
558
- export const $nanolightJs = $nanolight.bind(0,
566
+ export const nanolightJs = nanolight.bind(0,
559
567
  /('.*?'|".*?"|`[\s\S]*?`)|(\/\/.*?\n|\/\*[\s\S]*?\*\/)|(break|case|catch|const|continue|debugger|default|delete|do|else|eval|export\s+type|export|extends|false|finally|for|from|function|goto|if|import|in|instanceof|is|keyof|let|NaN|new|null|package|return|super|switch|this|throw|true|try|typeof|undefined|var|void|while|with|yield)(?!\w)|([<>=.?:&|!~*/%+-])|(0x[\dabcdef]+|0o[01234567]+|0b[01]+|\d+(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?)|([$\w]+)(?=\()|([$\wąćęłńóśżźĄĆĘŁŃÓŚŻŹ]+)/,
560
568
  [
561
569
  chunk => chunk, // no match
@@ -569,7 +577,7 @@ export const $nanolightJs = $nanolight.bind(0,
569
577
  ]
570
578
  )
571
579
 
572
- export const $plUral = (
580
+ export const plUral = (
573
581
  /** @type {string} */ singular,
574
582
  /** @type {string} */ plural2,
575
583
  /** @type {string} */ plural5,
@@ -587,9 +595,9 @@ export const $plUral = (
587
595
  : plural5
588
596
  }
589
597
 
590
- export const $s = _h('http://www.w3.org/2000/svg')
598
+ export const s = _h('http://www.w3.org/2000/svg')
591
599
 
592
- export const $set = (
600
+ export const set = (
593
601
  /** @type {any} */ value,
594
602
  /** @type {any} */ ref,
595
603
  /** @type {(string | number | symbol)[]} */ ...keys
@@ -603,8 +611,8 @@ export const $set = (
603
611
  for (let k = 0; k < last; ++k) {
604
612
  const key = keys[k]
605
613
 
606
- if (!$in(key, ref)) {
607
- ref[key] = $is(Number, keys[k + 1]) ? [] : {}
614
+ if (!has(key, ref)) {
615
+ ref[key] = is(Number, keys[k + 1]) ? [] : {}
608
616
  }
609
617
 
610
618
  ref = ref[key]
@@ -616,7 +624,7 @@ export const $set = (
616
624
  const _ZEROS = '0'.repeat(16)
617
625
  let _counter = 0
618
626
 
619
- export const $uuid1 = ({
627
+ export const uuid1 = ({
620
628
  date = new Date(),
621
629
  node = Math.random().toString(16).slice(2)
622
630
  } = {}) => {
package/package.json CHANGED
@@ -33,5 +33,5 @@
33
33
  "types": "nnn.d.ts",
34
34
  "name": "@jackens/nnn",
35
35
  "type": "module",
36
- "version": "2023.8.19"
36
+ "version": "2023.8.25"
37
37
  }