@jackens/nnn 2024.4.5 → 2024.4.14
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 +14 -2
- package/nnn.js +16 -1
- package/package.json +3 -5
- package/readme.md +125 -5
package/nnn.d.ts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tiny helper for CSV parsing.
|
|
3
|
+
*
|
|
4
|
+
* Options:
|
|
5
|
+
* - `header`: flag indicating that the parsed CSV has a header row (default: `true`)
|
|
6
|
+
* - `separator`: field separator (default: `','`)
|
|
7
|
+
*/
|
|
8
|
+
export declare const csvParse: (text: string, { header, separator }?: {
|
|
9
|
+
header?: boolean | undefined;
|
|
10
|
+
separator?: string | undefined;
|
|
11
|
+
}) => Partial<Array<Partial<Record<PropertyKey, string>>>> | Partial<Array<Partial<Array<string>>>>;
|
|
12
|
+
|
|
1
13
|
/**
|
|
2
14
|
* The type of arguments of the `escapeValues` and `escape` helpers.
|
|
3
15
|
*/
|
|
@@ -145,7 +157,7 @@ export declare const locale: (map: Partial<Record<PropertyKey, Partial<Record<Pr
|
|
|
145
157
|
/**
|
|
146
158
|
* A generic helper for syntax highlighting (see also `nanolightJs`).
|
|
147
159
|
*/
|
|
148
|
-
export declare const nanolight: (pattern: RegExp, highlighters: (
|
|
160
|
+
export declare const nanolight: (pattern: RegExp, highlighters: Partial<Array<(chunk: string, index: number) => HArgs1>>, code: string) => HArgs1[];
|
|
149
161
|
|
|
150
162
|
/**
|
|
151
163
|
* A helper for highlighting JavaScript.
|
|
@@ -177,7 +189,7 @@ export declare const pro: (ref: unknown) => any;
|
|
|
177
189
|
*
|
|
178
190
|
* It returns an array of triples: `[«name», «prototype-name», «array-of-own-property-names»]`.
|
|
179
191
|
*/
|
|
180
|
-
export declare const refsInfo: (...refs: Partial<Array<unknown>>) => [string, string,
|
|
192
|
+
export declare const refsInfo: (...refs: Partial<Array<unknown>>) => Partial<Array<[string, string, Partial<Array<string>>]>>;
|
|
181
193
|
|
|
182
194
|
/**
|
|
183
195
|
* A helper that generates a UUID v1 identifier (with a creation timestamp).
|
package/nnn.js
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
// src/nnn/csvParse.ts
|
|
2
|
+
var csvParse = (text, { header = true, separator = "," } = {}) => {
|
|
3
|
+
const regExp = new RegExp(`${separator}|(?<!")\\s*"((?:[^"]|"")*)"\\s*(?!")`, "g");
|
|
4
|
+
const rows = text.replace(/\r/g, "").replace(/\n+$/, "").replace(/\n|(?<!")("(?:[^"]|"")*")(?!")/g, (_, chunk) => chunk ?? "\r").split("\r").map((line) => line.replace(regExp, (_, chunk) => chunk == null ? "\r" : chunk.replace(/""/g, '"')).split("\r"));
|
|
5
|
+
if (header) {
|
|
6
|
+
const keys = rows.shift();
|
|
7
|
+
return rows.map((row) => keys.reduce((record, key, index) => {
|
|
8
|
+
record[key] = row[index];
|
|
9
|
+
return record;
|
|
10
|
+
}, {}));
|
|
11
|
+
}
|
|
12
|
+
return rows;
|
|
13
|
+
};
|
|
14
|
+
|
|
1
15
|
// src/nnn/escape.ts
|
|
2
16
|
var escapeValues = (escapeMap, values) => values.map((value) => (escapeMap.get(value?.constructor) ?? escapeMap.get(undefined))?.(value) ?? "");
|
|
3
17
|
var escape = (escapeMap, template, ...values) => String.raw(template, ...escapeValues(escapeMap, values));
|
|
@@ -272,5 +286,6 @@ export {
|
|
|
272
286
|
h,
|
|
273
287
|
fixTypography,
|
|
274
288
|
escapeValues,
|
|
275
|
-
escape
|
|
289
|
+
escape,
|
|
290
|
+
csvParse
|
|
276
291
|
};
|
package/package.json
CHANGED
|
@@ -4,13 +4,11 @@
|
|
|
4
4
|
"homepage": "https://jackens.github.io/nnn/doc/",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"CSS-in-JS",
|
|
7
|
-
"
|
|
7
|
+
"CSV",
|
|
8
|
+
"csvParse",
|
|
8
9
|
"DOM",
|
|
9
|
-
"eq",
|
|
10
|
-
"equal",
|
|
11
10
|
"escape",
|
|
12
11
|
"Gantt",
|
|
13
|
-
"graph",
|
|
14
12
|
"h",
|
|
15
13
|
"has",
|
|
16
14
|
"highlight",
|
|
@@ -40,5 +38,5 @@
|
|
|
40
38
|
"types": "nnn.d.ts",
|
|
41
39
|
"name": "@jackens/nnn",
|
|
42
40
|
"type": "module",
|
|
43
|
-
"version": "2024.4.
|
|
41
|
+
"version": "2024.4.14"
|
|
44
42
|
}
|
package/readme.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Jackens’ JavaScript helpers.
|
|
4
4
|
|
|
5
|
-
<sub>Version: <code class="version">2024.4.
|
|
5
|
+
<sub>Version: <code class="version">2024.4.14</code></sub>
|
|
6
6
|
|
|
7
7
|
## Examples
|
|
8
8
|
|
|
@@ -44,6 +44,7 @@ import { «something» } from './node_modules/@jackens/nnn/nnn.js'
|
|
|
44
44
|
- `HArgs1`: The type of arguments of the `h` and `s` helpers.
|
|
45
45
|
- `JcNode`: The type of arguments of the `jc` helper.
|
|
46
46
|
- `JcRoot`: The type of arguments of the `jc` helper.
|
|
47
|
+
- `csvParse`: A tiny helper for CSV parsing.
|
|
47
48
|
- `escape`: A generic helper for escaping `values` by given `escapeMap` (in *TemplateStrings* flavor).
|
|
48
49
|
- `escapeValues`: A generic helper for escaping `values` by given `escapeMap`.
|
|
49
50
|
- `fixTypography`: A helper that implements typographic corrections specific to Polish typography.
|
|
@@ -86,6 +87,8 @@ The type of arguments of the `h` and `s` helpers.
|
|
|
86
87
|
type HArgs1 = Partial<Record<PropertyKey, unknown>> | null | undefined | Node | string | number | HArgs;
|
|
87
88
|
```
|
|
88
89
|
|
|
90
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Record>` instead of `Record`.
|
|
91
|
+
|
|
89
92
|
The type of arguments of the `h` and `s` helpers.
|
|
90
93
|
|
|
91
94
|
### JcNode
|
|
@@ -104,14 +107,63 @@ The type of arguments of the `jc` helper.
|
|
|
104
107
|
type JcRoot = Partial<Record<PropertyKey, JcNode>>;
|
|
105
108
|
```
|
|
106
109
|
|
|
110
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Record>` instead of `Record`.
|
|
111
|
+
|
|
107
112
|
The type of arguments of the `jc` helper.
|
|
108
113
|
|
|
114
|
+
### csvParse
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
const csvParse: (text: string, { header, separator }?: {
|
|
118
|
+
header?: boolean | undefined;
|
|
119
|
+
separator?: string | undefined;
|
|
120
|
+
}) => Partial<Array<Partial<Record<PropertyKey, string>>>> | Partial<Array<Partial<Array<string>>>>;
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Array>`/`Partial<Record>` instead of `Array`/`Record`.
|
|
124
|
+
|
|
125
|
+
A tiny helper for CSV parsing.
|
|
126
|
+
|
|
127
|
+
Options:
|
|
128
|
+
- `header`: flag indicating that the parsed CSV has a header row (default: `true`)
|
|
129
|
+
- `separator`: field separator (default: `','`)
|
|
130
|
+
|
|
131
|
+
#### Usage Examples
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
const text = `"aaa
|
|
135
|
+
""aaa""
|
|
136
|
+
aaa",bbb, "ccc,ccc"
|
|
137
|
+
"xxx,xxx", "yyy
|
|
138
|
+
yyy",zzz
|
|
139
|
+
42 , "42" , 17
|
|
140
|
+
|
|
141
|
+
`
|
|
142
|
+
expect(csvParse(text, { header: false })).toStrictEqual([
|
|
143
|
+
['aaa\n"aaa"\naaa', 'bbb', 'ccc,ccc'],
|
|
144
|
+
['xxx,xxx', 'yyy\nyyy', 'zzz'],
|
|
145
|
+
[' 42 ', '42', ' 17']
|
|
146
|
+
])
|
|
147
|
+
|
|
148
|
+
expect(csvParse(text)).toStrictEqual([{
|
|
149
|
+
'aaa\n"aaa"\naaa': 'xxx,xxx',
|
|
150
|
+
bbb: 'yyy\nyyy',
|
|
151
|
+
'ccc,ccc': 'zzz'
|
|
152
|
+
}, {
|
|
153
|
+
'aaa\n"aaa"\naaa': ' 42 ',
|
|
154
|
+
bbb: '42',
|
|
155
|
+
'ccc,ccc': ' 17'
|
|
156
|
+
}])
|
|
157
|
+
```
|
|
158
|
+
|
|
109
159
|
### escape
|
|
110
160
|
|
|
111
161
|
```ts
|
|
112
162
|
const escape: (escapeMap: EscapeMap, template: TemplateStringsArray, ...values: Partial<Array<unknown>>) => string;
|
|
113
163
|
```
|
|
114
164
|
|
|
165
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Array>` instead of `Array`.
|
|
166
|
+
|
|
115
167
|
A generic helper for escaping `values` by given `escapeMap` (in *TemplateStrings* flavor).
|
|
116
168
|
|
|
117
169
|
#### Usage Examples
|
|
@@ -147,6 +199,8 @@ expect(actual).toStrictEqual(expected)
|
|
|
147
199
|
const escapeValues: (escapeMap: EscapeMap, values: Partial<Array<unknown>>) => Partial<Array<string>>;
|
|
148
200
|
```
|
|
149
201
|
|
|
202
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Array>` instead of `Array`.
|
|
203
|
+
|
|
150
204
|
A generic helper for escaping `values` by given `escapeMap`.
|
|
151
205
|
|
|
152
206
|
### fixTypography
|
|
@@ -179,6 +233,8 @@ const h: {
|
|
|
179
233
|
};
|
|
180
234
|
```
|
|
181
235
|
|
|
236
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Array>` instead of `Array`.
|
|
237
|
+
|
|
182
238
|
A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also `s`).
|
|
183
239
|
|
|
184
240
|
- The first argument of type `string` specifies the tag of the element to be created.
|
|
@@ -316,6 +372,8 @@ const is: {
|
|
|
316
372
|
};
|
|
317
373
|
```
|
|
318
374
|
|
|
375
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Array>`/`Partial<Record>` instead of `Array`/`Record`.
|
|
376
|
+
|
|
319
377
|
A helper that checks if the given argument is of a certain type.
|
|
320
378
|
|
|
321
379
|
#### Usage Examples
|
|
@@ -593,6 +651,8 @@ expect(actual).toStrictEqual(expected)
|
|
|
593
651
|
const jsOnParse: (handlers: Partial<Record<PropertyKey, Function>>, text: string) => any;
|
|
594
652
|
```
|
|
595
653
|
|
|
654
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Record>` instead of `Record`.
|
|
655
|
+
|
|
596
656
|
`JSON.parse` with “JavaScript turned on”.
|
|
597
657
|
|
|
598
658
|
Objects having *exactly* one property which is present in the `handlers` map, i.e. objects of the form:
|
|
@@ -660,6 +720,8 @@ expect(actual).toStrictEqual(expected)
|
|
|
660
720
|
const locale: (map: Partial<Record<PropertyKey, Partial<Record<PropertyKey, string>>>>, defaultVersion: string) => (text: string, version?: string) => string;
|
|
661
721
|
```
|
|
662
722
|
|
|
723
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Record>` instead of `Record`.
|
|
724
|
+
|
|
663
725
|
Language translations helper.
|
|
664
726
|
|
|
665
727
|
#### Usage Examples
|
|
@@ -687,9 +749,11 @@ expect(_('toString', 'undefined_version')).toStrictEqual('toString')
|
|
|
687
749
|
### nanolight
|
|
688
750
|
|
|
689
751
|
```ts
|
|
690
|
-
const nanolight: (pattern: RegExp, highlighters: (
|
|
752
|
+
const nanolight: (pattern: RegExp, highlighters: Partial<Array<(chunk: string, index: number) => HArgs1>>, code: string) => HArgs1[];
|
|
691
753
|
```
|
|
692
754
|
|
|
755
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Array>` instead of `Array`.
|
|
756
|
+
|
|
693
757
|
A generic helper for syntax highlighting (see also `nanolightJs`).
|
|
694
758
|
|
|
695
759
|
### nanolightJs
|
|
@@ -722,6 +786,8 @@ expect(nanolightJs(codeJs)).toStrictEqual([
|
|
|
722
786
|
const omit: <T extends Partial<Record<PropertyKey, unknown>>, K extends (keyof T)[]>(obj: Partial<Record<PropertyKey, unknown>>, keys: Partial<Array<unknown>>) => Omit<T, K[number]>;
|
|
723
787
|
```
|
|
724
788
|
|
|
789
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Array>`/`Partial<Record>` instead of `Array`/`Record`.
|
|
790
|
+
|
|
725
791
|
A helper that implements TypeScript’s `Omit` utility type.
|
|
726
792
|
|
|
727
793
|
#### Usage Examples
|
|
@@ -738,6 +804,8 @@ expect(omit(obj, ['c'])).toStrictEqual({ a: 42, b: '42' })
|
|
|
738
804
|
const pick: <T extends Partial<Record<PropertyKey, unknown>>, K extends (keyof T)[]>(obj: Partial<Record<PropertyKey, unknown>>, keys: Partial<Array<unknown>>) => Pick<T, K[number]>;
|
|
739
805
|
```
|
|
740
806
|
|
|
807
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Array>`/`Partial<Record>` instead of `Array`/`Record`.
|
|
808
|
+
|
|
741
809
|
A helper that implements TypeScript’s `Pick` utility type.
|
|
742
810
|
|
|
743
811
|
#### Usage Examples
|
|
@@ -815,9 +883,11 @@ expect(ref).toStrictEqual({ one: { two: { three: { four: 1234 } } } })
|
|
|
815
883
|
### refsInfo
|
|
816
884
|
|
|
817
885
|
```ts
|
|
818
|
-
const refsInfo: (...refs: Partial<Array<unknown>>) => [string, string,
|
|
886
|
+
const refsInfo: (...refs: Partial<Array<unknown>>) => Partial<Array<[string, string, Partial<Array<string>>]>>;
|
|
819
887
|
```
|
|
820
888
|
|
|
889
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Array>` instead of `Array`.
|
|
890
|
+
|
|
821
891
|
A helper that provides information about the given `refs`.
|
|
822
892
|
|
|
823
893
|
It returns an array of triples: `[«name», «prototype-name», «array-of-own-property-names»]`.
|
|
@@ -827,8 +897,8 @@ It returns an array of triples: `[«name», «prototype-name», «array-of-own-p
|
|
|
827
897
|
```js
|
|
828
898
|
const info = refsInfo(Array, Function)
|
|
829
899
|
|
|
830
|
-
expect(info.find(
|
|
831
|
-
expect(info.find(
|
|
900
|
+
expect(info.find(item => item?.[0] === 'Array')?.[2]?.includes('length')).toBeTrue()
|
|
901
|
+
expect(info.find(item => item?.[0] === 'Function')?.[2]?.includes('length')).toBeTrue()
|
|
832
902
|
```
|
|
833
903
|
|
|
834
904
|
```js
|
|
@@ -865,6 +935,8 @@ const s: {
|
|
|
865
935
|
};
|
|
866
936
|
```
|
|
867
937
|
|
|
938
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Array>` instead of `Array`.
|
|
939
|
+
|
|
868
940
|
A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also `h`).
|
|
869
941
|
|
|
870
942
|
- The first argument of type `string` specifies the tag of the element to be created.
|
|
@@ -885,6 +957,8 @@ A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style help
|
|
|
885
957
|
const svgUse: (id: string, ...args: Partial<Array<HArgs1>>) => SVGSVGElement;
|
|
886
958
|
```
|
|
887
959
|
|
|
960
|
+
> See [here](https://jackens.github.io/nnn/doc/#Why-Partial-Array-and-Partial-Record) for an explanation of why `Partial<Array>` instead of `Array`.
|
|
961
|
+
|
|
888
962
|
A convenient shortcut for `s('svg', ['use', { 'xlink:href': '#' + id }], ...args)`.
|
|
889
963
|
|
|
890
964
|
### uuid1
|
|
@@ -926,6 +1000,52 @@ expect(uuid1({ node: '123456789' }).split('-')[4]).toStrictEqual('000123456789')
|
|
|
926
1000
|
expect(uuid1({ date: new Date(323325000000) }).startsWith('c1399400-9a71-11bd')).toBeTrue()
|
|
927
1001
|
```
|
|
928
1002
|
|
|
1003
|
+
## Why Partial\<Array\> and Partial\<Record\>
|
|
1004
|
+
|
|
1005
|
+
Consider the following code snippet:
|
|
1006
|
+
|
|
1007
|
+
```ts
|
|
1008
|
+
const arr = ['one', 'two', 'three'] // type: string[]
|
|
1009
|
+
const arrAt42 = arr[42] // type: string
|
|
1010
|
+
|
|
1011
|
+
arrAt42.toUpperCase() // 👎 allowed by TypeScript
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
TypeScript allows `arrAt42.toUpperCase()`,
|
|
1015
|
+
which causes a <code class="log">TypeError: undefined is not an object</code>.
|
|
1016
|
+
The variable `arr` should be of type `Partial<Array<string>>`:
|
|
1017
|
+
|
|
1018
|
+
```ts
|
|
1019
|
+
const arr: Partial<Array<string>> = ['one', 'two', 'three']
|
|
1020
|
+
const arrAt42 = arr[42] // type: string | undefined
|
|
1021
|
+
|
|
1022
|
+
arrAt42.toUpperCase() // 👍 forbidden by TypeScript
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
Now `arrAt42.toUpperCase()` is forbidden by TypeScript (<code class="log">'arrAt42' is possibly undefined</code>).
|
|
1026
|
+
|
|
1027
|
+
Similarly for the type `Record`:
|
|
1028
|
+
|
|
1029
|
+
```ts
|
|
1030
|
+
const rec = Object.fromEntries(['one', 'two', 'three'].map((k, i) => [k, i])) // type: Record<string, number>
|
|
1031
|
+
const { tree } = rec // type: number
|
|
1032
|
+
|
|
1033
|
+
tree.toFixed() // 👎 allowed by TypeScript
|
|
1034
|
+
```
|
|
1035
|
+
|
|
1036
|
+
TypeScript allows `tree.toFixed()`, which causes a <code class="log">TypeError: undefined is not an object</code>.
|
|
1037
|
+
The variable `rec` should be of type `Partial<Record<PropertyKey, number>>`:
|
|
1038
|
+
|
|
1039
|
+
```ts
|
|
1040
|
+
const rec: Partial<Record<PropertyKey, number>> =
|
|
1041
|
+
Object.fromEntries(['one', 'two', 'three'].map((k, i) => [k, i]))
|
|
1042
|
+
const { tree } = rec // type: number | undefined
|
|
1043
|
+
|
|
1044
|
+
tree.toFixed() // 👍 forbidden by TypeScript
|
|
1045
|
+
```
|
|
1046
|
+
|
|
1047
|
+
Now `tree.toFixed()` is forbidden by TypeScript (<code class="log">'tree' is possibly undefined</code>).
|
|
1048
|
+
|
|
929
1049
|
## License
|
|
930
1050
|
|
|
931
1051
|
The MIT License (MIT)
|