@jackens/nnn 2024.7.13 → 2024.7.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.
Files changed (4) hide show
  1. package/nnn.d.ts +49 -40
  2. package/nnn.js +58 -58
  3. package/package.json +2 -2
  4. package/readme.md +253 -244
package/nnn.d.ts CHANGED
@@ -1,3 +1,32 @@
1
+ /**
2
+ * The type of arguments of the `c` helper.
3
+ */
4
+ export type CNode = {
5
+ [attributeOrSelector: string]: string | number | CNode | undefined;
6
+ };
7
+
8
+ /**
9
+ * The type of arguments of the `c` helper.
10
+ */
11
+ export type CRoot = Partial<Record<PropertyKey, CNode>>;
12
+
13
+ /**
14
+ * A simple JS-to-CSS (aka CSS-in-JS) helper.
15
+ *
16
+ * The `root` parameter provides a hierarchical description of CSS rules.
17
+ *
18
+ * - Keys of sub-objects whose values are NOT objects are treated as CSS attribute, and values are treated as values of
19
+ * those CSS attributes; the concatenation of keys of all parent objects is a CSS rule.
20
+ * - All keys ignore the part starting with a splitter (default: `$$`) sign until the end of the key (e.g. `src$$1` →
21
+ * `src`, `@font-face$$1` → `@font-face`).
22
+ * - In keys specifying CSS attribute, all uppercase letters are replaced by lowercase letters with an additional `-`
23
+ * character preceding them (e.g. `fontFamily` → `font-family`).
24
+ * - Commas in keys that makes a CSS rule cause it to “split” and create separate rules for each part (e.g.
25
+ * `{div:{margin:1,'.a,.b,.c':{margin:2}}}` → `div{margin:1}div.a,div.b,div.c{margin:2}`).
26
+ * - Top-level keys that begin with `@` are not concatenated with sub-object keys.
27
+ */
28
+ export declare const c: (root: CRoot, splitter?: string) => string;
29
+
1
30
  /**
2
31
  * A tiny helper for CSV parsing.
3
32
  *
@@ -41,19 +70,21 @@ export type HArgs1 = Partial<Record<PropertyKey, unknown>> | null | undefined |
41
70
  export type HArgs = [string | Node, ...HArgs1[]];
42
71
 
43
72
  /**
44
- * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also `s`).
73
+ * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying
74
+ * `HTMLElement`s (see also `s`).
45
75
  *
46
76
  * - The first argument of type `string` specifies the tag of the element to be created.
47
77
  * - The first argument of type `Node` specifies the element to be modified.
48
78
  * - All other arguments of type `Partial<Record<PropertyKey, unknown>>` are mappings of attributes and properties.
49
- * Keys starting with `$` specify *properties* (without the leading `$`) to be set on the element being created or modified.
50
- * (Note that `$` is not a valid attribute name character.)
51
- * All other keys specify *attributes* to be set by `setAttribute`.
52
- * An attribute equal to `false` causes the attribute to be removed by `removeAttribute`.
79
+ * Keys starting with `$` specify *properties* (without the leading `$`) to be set on the element being created or
80
+ * modified. (Note that `$` is not a valid attribute name character.) All other keys specify *attributes* to be set by
81
+ * `setAttribute`. An attribute equal to `false` causes the attribute to be removed by `removeAttribute`.
53
82
  * - All other arguments of type `null` or `undefined` are simply ignored.
54
83
  * - All other arguments of type `Node` are appended to the element being created or modified.
55
- * - All other arguments of type `string`/`number` are converted to `Text` nodes and appended to the element being created or modified.
56
- * - All other arguments of type `HArgs` are passed to `h` and the results are appended to the element being created or modified.
84
+ * - All other arguments of type `string`/`number` are converted to `Text` nodes and appended to the element being
85
+ * created or modified.
86
+ * - All other arguments of type `HArgs` are passed to `h` and the results are appended to the element being created or
87
+ * modified.
57
88
  */
58
89
  export declare const h: {
59
90
  <T extends keyof HTMLElementTagNameMap>(tag: T, ...args1: Partial<Array<HArgs1>>): HTMLElementTagNameMap[T];
@@ -62,19 +93,21 @@ export declare const h: {
62
93
  };
63
94
 
64
95
  /**
65
- * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also `h`).
96
+ * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying
97
+ * `SVGElement`s (see also `h`).
66
98
  *
67
99
  * - The first argument of type `string` specifies the tag of the element to be created.
68
100
  * - The first argument of type `Node` specifies the element to be modified.
69
101
  * - All other arguments of type `Partial<Record<PropertyKey, unknown>>` are mappings of attributes and properties.
70
- * Keys starting with `$` specify *properties* (without the leading `$`) to be set on the element being created or modified.
71
- * (Note that `$` is not a valid attribute name character.)
72
- * All other keys specify *attributes* to be set by `setAttributeNS`.
73
- * An attribute equal to `false` causes the attribute to be removed by `removeAttributeNS`.
102
+ * Keys starting with `$` specify *properties* (without the leading `$`) to be set on the element being created or
103
+ * modified. (Note that `$` is not a valid attribute name character.) All other keys specify *attributes* to be set by
104
+ * `setAttributeNS`. An attribute equal to `false` causes the attribute to be removed by `removeAttributeNS`.
74
105
  * - All other arguments of type `null` or `undefined` are simply ignored.
75
106
  * - All other arguments of type `Node` are appended to the element being created or modified.
76
- * - All other arguments of type `string`/`number` are converted to `Text` nodes and appended to the element being created or modified.
77
- * - All other arguments of type `HArgs` are passed to `s` and the results are appended to the element being created or modified.
107
+ * - All other arguments of type `string`/`number` are converted to `Text` nodes and appended to the element being
108
+ * created or modified.
109
+ * - All other arguments of type `HArgs` are passed to `s` and the results are appended to the element being created or
110
+ * modified.
78
111
  */
79
112
  export declare const s: {
80
113
  <T extends keyof SVGElementTagNameMap>(tag: T, ...args1: Partial<Array<HArgs1>>): SVGElementTagNameMap[T];
@@ -107,31 +140,6 @@ export declare const is: {
107
140
  <T extends abstract new (...args: Partial<Array<any>>) => unknown>(type: T, arg: unknown): arg is InstanceType<T>;
108
141
  };
109
142
 
110
- /**
111
- * The type of arguments of the `jc` helper.
112
- */
113
- export type JcNode = {
114
- [attributeOrSelector: string]: string | number | JcNode | undefined;
115
- };
116
-
117
- /**
118
- * The type of arguments of the `jc` helper.
119
- */
120
- export type JcRoot = Partial<Record<PropertyKey, JcNode>>;
121
-
122
- /**
123
- * A simple JS-to-CSS (aka CSS-in-JS) helper.
124
- *
125
- * The `root` parameter provides a hierarchical description of CSS rules.
126
- *
127
- * - Keys of sub-objects whose values are NOT objects are treated as CSS attribute, and values are treated as values of those CSS attributes; the concatenation of keys of all parent objects is a CSS rule.
128
- * - All keys ignore the part starting with a splitter (default: `$$`) sign until the end of the key (e.g. `src$$1` → `src`, `@font-face$$1` → `@font-face`).
129
- * - In keys specifying CSS attribute, all uppercase letters are replaced by lowercase letters with an additional `-` character preceding them (e.g. `fontFamily` → `font-family`).
130
- * - 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}`).
131
- * - Top-level keys that begin with `@` are not concatenated with sub-object keys.
132
- */
133
- export declare const jc: (root: JcRoot, splitter?: string) => string;
134
-
135
143
  /**
136
144
  * `JSON.parse` with “JavaScript turned on”.
137
145
  *
@@ -180,7 +188,8 @@ export declare const omit: <T extends Partial<Record<PropertyKey, unknown>>, K e
180
188
  export declare const plUral: (singular: string, plural2: string, plural5: string, value: number) => string;
181
189
 
182
190
  /**
183
- * A helper that protects calls to nested properties by a `Proxy` that initializes non-existent values with an empty object.
191
+ * A helper that protects calls to nested properties by a `Proxy` that initializes non-existent values with an empty
192
+ * object.
184
193
  */
185
194
  export declare const pro: (ref: unknown) => any;
186
195
 
package/nnn.js CHANGED
@@ -1,3 +1,59 @@
1
+ // src/nnn/is.ts
2
+ var is = (type, arg) => arg?.constructor === type;
3
+
4
+ // src/nnn/c.ts
5
+ var _c = (node, prefix, result, split) => {
6
+ const queue = [[node, prefix]];
7
+ while (queue.length > 0) {
8
+ const [style0, prefix0] = queue.shift() ?? [];
9
+ if (style0 == null || prefix0 == null) {
10
+ continue;
11
+ }
12
+ if (is(Array, style0)) {
13
+ result.push(prefix0, prefix0 !== "" ? "{" : "", style0.join(";"), prefix0 !== "" ? "}" : "");
14
+ } else {
15
+ const todo = [];
16
+ let attributes = [];
17
+ let attributesPushed = false;
18
+ for (const key in style0) {
19
+ const value = style0[key];
20
+ if (is(String, value) || is(Number, value)) {
21
+ if (!attributesPushed) {
22
+ attributesPushed = true;
23
+ attributes = [];
24
+ todo.push([attributes, prefix0]);
25
+ }
26
+ attributes.push(`${split(key).replace(/([A-Z])/g, (_, letter) => "-" + letter.toLowerCase())}:${value}`);
27
+ } else if (value != null) {
28
+ attributesPushed = false;
29
+ const prefixN = [];
30
+ const keyChunks = key.split(",");
31
+ prefix0.split(",").forEach((prefixChunk) => keyChunks.forEach((keyChunk) => prefixN.push(prefixChunk + keyChunk)));
32
+ todo.push([value, prefixN.join(",")]);
33
+ }
34
+ }
35
+ queue.unshift(...todo);
36
+ }
37
+ }
38
+ };
39
+ var c = (root, splitter = "$$") => {
40
+ const split = (text) => text.split(splitter)[0];
41
+ const chunks = [];
42
+ for (const key in root) {
43
+ const value = root[key];
44
+ if (value != null) {
45
+ if (key[0] === "@") {
46
+ chunks.push(split(key) + "{");
47
+ _c(value, "", chunks, split);
48
+ chunks.push("}");
49
+ } else {
50
+ _c(value, split(key), chunks, split);
51
+ }
52
+ }
53
+ }
54
+ return chunks.join("");
55
+ };
56
+
1
57
  // src/nnn/csvParse.ts
2
58
  var csvParse = (text, { header = true, separator = "," } = {}) => {
3
59
  const regExp = new RegExp(`${separator}|(?<!")\\s*"((?:[^"]|"")*)"\\s*(?!")`, "g");
@@ -16,9 +72,6 @@ var csvParse = (text, { header = true, separator = "," } = {}) => {
16
72
  var escapeValues = (escapeMap, values) => values.map((value) => (escapeMap.get(value?.constructor) ?? escapeMap.get(undefined))?.(value) ?? "");
17
73
  var escape = (escapeMap, template, ...values) => String.raw(template, ...escapeValues(escapeMap, values));
18
74
 
19
- // src/nnn/is.ts
20
- var is = (type, arg) => arg?.constructor === type;
21
-
22
75
  // src/nnn/h.ts
23
76
  var NS = {
24
77
  xlink: "http://www.w3.org/1999/xlink"
@@ -119,59 +172,6 @@ var fixTypography = (node) => {
119
172
  // src/nnn/has.ts
120
173
  var has = (key, ref) => (is(String, key) || is(Number, key) || is(Symbol, key)) && Object.hasOwnProperty.call(ref ?? Object, key);
121
174
 
122
- // src/nnn/jc.ts
123
- var _jc = (node, prefix, result, split) => {
124
- const queue = [[node, prefix]];
125
- while (queue.length > 0) {
126
- const [style0, prefix0] = queue.shift() ?? [];
127
- if (style0 == null || prefix0 == null) {
128
- continue;
129
- }
130
- if (is(Array, style0)) {
131
- result.push(prefix0, prefix0 !== "" ? "{" : "", style0.join(";"), prefix0 !== "" ? "}" : "");
132
- } else {
133
- const todo = [];
134
- let attributes = [];
135
- let attributesPushed = false;
136
- for (const key in style0) {
137
- const value = style0[key];
138
- if (is(String, value) || is(Number, value)) {
139
- if (!attributesPushed) {
140
- attributesPushed = true;
141
- attributes = [];
142
- todo.push([attributes, prefix0]);
143
- }
144
- attributes.push(`${split(key).replace(/([A-Z])/g, (_, letter) => "-" + letter.toLowerCase())}:${value}`);
145
- } else if (value != null) {
146
- attributesPushed = false;
147
- const prefixN = [];
148
- const keyChunks = key.split(",");
149
- prefix0.split(",").forEach((prefixChunk) => keyChunks.forEach((keyChunk) => prefixN.push(prefixChunk + keyChunk)));
150
- todo.push([value, prefixN.join(",")]);
151
- }
152
- }
153
- queue.unshift(...todo);
154
- }
155
- }
156
- };
157
- var jc = (root, splitter = "$$") => {
158
- const split = (text) => text.split(splitter)[0];
159
- const chunks = [];
160
- for (const key in root) {
161
- const value = root[key];
162
- if (value != null) {
163
- if (key[0] === "@") {
164
- chunks.push(split(key) + "{");
165
- _jc(value, "", chunks, split);
166
- chunks.push("}");
167
- } else {
168
- _jc(value, split(key), chunks, split);
169
- }
170
- }
171
- }
172
- return chunks.join("");
173
- };
174
-
175
175
  // src/nnn/jsOnParse.ts
176
176
  var jsOnParse = (handlers, text) => JSON.parse(text, (key, value) => {
177
177
  if (is(Object, value)) {
@@ -280,12 +280,12 @@ export {
280
280
  nanolight,
281
281
  locale,
282
282
  jsOnParse,
283
- jc,
284
283
  is,
285
284
  has,
286
285
  h,
287
286
  fixTypography,
288
287
  escapeValues,
289
288
  escape,
290
- csvParse
289
+ csvParse,
290
+ c
291
291
  };
package/package.json CHANGED
@@ -3,6 +3,7 @@
3
3
  "description": "Jackens’ JavaScript helpers.",
4
4
  "homepage": "https://jackens.github.io/nnn/doc/",
5
5
  "keywords": [
6
+ "c",
6
7
  "CSS-in-JS",
7
8
  "CSV",
8
9
  "csvParse",
@@ -14,7 +15,6 @@
14
15
  "HyperScript",
15
16
  "in",
16
17
  "is",
17
- "jc",
18
18
  "JS-to-CSS",
19
19
  "JSON",
20
20
  "jsOnParse",
@@ -36,5 +36,5 @@
36
36
  "name": "@jackens/nnn",
37
37
  "type": "module",
38
38
  "types": "nnn.d.ts",
39
- "version": "2024.7.13"
39
+ "version": "2024.7.14"
40
40
  }
package/readme.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Jackens’ JavaScript helpers.
4
4
 
5
- <sub>Version: <code class="version">2024.7.13</code></sub>
5
+ <sub>Version: <code class="version">2024.7.14</code></sub>
6
6
 
7
7
  ## Installation
8
8
 
@@ -31,24 +31,24 @@ import { «something» } from './node_modules/@jackens/nnn/nnn.js'
31
31
  or:
32
32
 
33
33
  ```js
34
- import { «something» } from 'https://unpkg.com/@jackens/nnn@2024.7.13/nnn.js'
34
+ import { «something» } from 'https://unpkg.com/@jackens/nnn@2024.7.14/nnn.js'
35
35
  ```
36
36
 
37
37
  ## Exports
38
38
 
39
+ - `CNode`: The type of arguments of the `c` helper.
40
+ - `CRoot`: The type of arguments of the `c` helper.
39
41
  - `EscapeMap`: The type of arguments of the `escapeValues` and `escape` helpers.
40
42
  - `HArgs`: The type of arguments of the `h` and `s` helpers.
41
43
  - `HArgs1`: The type of arguments of the `h` and `s` helpers.
42
- - `JcNode`: The type of arguments of the `jc` helper.
43
- - `JcRoot`: The type of arguments of the `jc` helper.
44
+ - `c`: A simple JS-to-CSS (aka CSS-in-JS) helper.
44
45
  - `csvParse`: A tiny helper for CSV parsing.
45
46
  - `escape`: A generic helper for escaping `values` by given `escapeMap` (in *TemplateStrings* flavor).
46
47
  - `escapeValues`: A generic helper for escaping `values` by given `escapeMap`.
47
48
  - `fixTypography`: A helper that implements typographic corrections specific to Polish typography.
48
- - `h`: A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also `s`).
49
+ - `h`: A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying
49
50
  - `has`: A replacement for the `in` operator (not to be confused with the `for-in` loop) that works properly.
50
51
  - `is`: A helper that checks if the given argument is of a certain type.
51
- - `jc`: A simple JS-to-CSS (aka CSS-in-JS) helper.
52
52
  - `jsOnParse`: `JSON.parse` with “JavaScript turned on”.
53
53
  - `locale`: Language translations helper.
54
54
  - `nanolight`: A generic helper for syntax highlighting (see also `nanolightJs`).
@@ -56,12 +56,30 @@ import { «something» } from 'https://unpkg.com/@jackens/nnn@2024.7.13/nnn.js'
56
56
  - `omit`: A helper that implements TypeScript’s `Omit` utility type.
57
57
  - `pick`: A helper that implements TypeScript’s `Pick` utility type.
58
58
  - `plUral`: A helper for choosing the correct singular and plural.
59
- - `pro`: A helper that protects calls to nested properties by a `Proxy` that initializes non-existent values with an empty object.
59
+ - `pro`: A helper that protects calls to nested properties by a `Proxy` that initializes non-existent values with an empty
60
60
  - `refsInfo`: A helper that provides information about the given `refs`.
61
- - `s`: A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also `h`).
61
+ - `s`: A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying
62
62
  - `svgUse`: A convenient shortcut for `s('svg', ['use', { 'xlink:href': '#' + id }], ...args)`.
63
63
  - `uuid1`: A helper that generates a UUID v1 identifier (with a creation timestamp).
64
64
 
65
+ ### CNode
66
+
67
+ ```ts
68
+ type CNode = {
69
+ [attributeOrSelector: string]: string | number | CNode | undefined;
70
+ };
71
+ ```
72
+
73
+ The type of arguments of the `c` helper.
74
+
75
+ ### CRoot
76
+
77
+ ```ts
78
+ type CRoot = Partial<Record<PropertyKey, CNode>>;
79
+ ```
80
+
81
+ The type of arguments of the `c` helper.
82
+
65
83
  ### EscapeMap
66
84
 
67
85
  ```ts
@@ -86,23 +104,221 @@ type HArgs1 = Partial<Record<PropertyKey, unknown>> | null | undefined | Node |
86
104
 
87
105
  The type of arguments of the `h` and `s` helpers.
88
106
 
89
- ### JcNode
107
+ ### c
90
108
 
91
109
  ```ts
92
- type JcNode = {
93
- [attributeOrSelector: string]: string | number | JcNode | undefined;
94
- };
110
+ const c: (root: CRoot, splitter?: string) => string;
95
111
  ```
96
112
 
97
- The type of arguments of the `jc` helper.
113
+ A simple JS-to-CSS (aka CSS-in-JS) helper.
114
+
115
+ The `root` parameter provides a hierarchical description of CSS rules.
98
116
 
99
- ### JcRoot
117
+ - Keys of sub-objects whose values are NOT objects are treated as CSS attribute, and values are treated as values of
118
+ those CSS attributes; the concatenation of keys of all parent objects is a CSS rule.
119
+ - All keys ignore the part starting with a splitter (default: `$$`) sign until the end of the key (e.g. `src$$1` →
120
+ `src`, `@font-face$$1` → `@font-face`).
121
+ - In keys specifying CSS attribute, all uppercase letters are replaced by lowercase letters with an additional `-`
122
+ character preceding them (e.g. `fontFamily` → `font-family`).
123
+ - Commas in keys that makes a CSS rule cause it to “split” and create separate rules for each part (e.g.
124
+ `{div:{margin:1,'.a,.b,.c':{margin:2}}}` → `div{margin:1}div.a,div.b,div.c{margin:2}`).
125
+ - Top-level keys that begin with `@` are not concatenated with sub-object keys.
100
126
 
101
- ```ts
102
- type JcRoot = Partial<Record<PropertyKey, JcNode>>;
127
+ #### Usage Examples
128
+
129
+ ```js
130
+ const actual = c({
131
+ a: {
132
+ color: 'red',
133
+ margin: 1,
134
+ '.c': { margin: 2, padding: 2 },
135
+ padding: 1
136
+ }
137
+ })
138
+
139
+ const expected = `
140
+ a{
141
+ color:red;
142
+ margin:1
143
+ }
144
+ a.c{
145
+ margin:2;
146
+ padding:2
147
+ }
148
+ a{
149
+ padding:1
150
+ }`.replace(/\n\s*/g, '')
151
+
152
+ expect(actual).to.deep.equal(expected)
153
+ ```
154
+
155
+ ```js
156
+ const actual = c({
157
+ a: {
158
+ '.b': {
159
+ color: 'red',
160
+ margin: 1,
161
+ '.c': { margin: 2, padding: 2 },
162
+ padding: 1
163
+ }
164
+ }
165
+ })
166
+
167
+ const expected = `
168
+ a.b{
169
+ color:red;
170
+ margin:1
171
+ }
172
+ a.b.c{
173
+ margin:2;
174
+ padding:2
175
+ }
176
+ a.b{
177
+ padding:1
178
+ }`.replace(/\n\s*/g, '')
179
+
180
+ expect(actual).to.deep.equal(expected)
181
+ ```
182
+
183
+ ```js
184
+ const actual = c({
185
+ '@font-face$$1': {
186
+ fontFamily: 'Jackens',
187
+ src$$1: 'url(otf/jackens.otf)',
188
+ src$$2: "url(otf/jackens.otf) format('opentype')," +
189
+ "url(svg/jackens.svg) format('svg')",
190
+ fontWeight: 'normal',
191
+ fontStyle: 'normal'
192
+ },
193
+ '@font-face$$2': {
194
+ fontFamily: 'C64',
195
+ src: 'url(fonts/C64_Pro_Mono-STYLE.woff)'
196
+ },
197
+ '@keyframes spin': {
198
+ '0%': { transform: 'rotate(0deg)' },
199
+ '100%': { transform: 'rotate(360deg)' }
200
+ },
201
+ div: {
202
+ border: 'solid red 1px',
203
+ '.c1': { 'background-color': '#000' },
204
+ ' .c1': { backgroundColor: 'black' },
205
+ '.c2': { backgroundColor: 'rgb(0,0,0)' }
206
+ },
207
+ '@media(min-width:200px)': {
208
+ div: { margin: 0, padding: 0 },
209
+ span: { color: '#000' }
210
+ }
211
+ })
212
+
213
+ const expected = `
214
+ @font-face{
215
+ font-family:Jackens;
216
+ src:url(otf/jackens.otf);
217
+ src:url(otf/jackens.otf) format('opentype'),url(svg/jackens.svg) format('svg');
218
+ font-weight:normal;
219
+ font-style:normal
220
+ }
221
+ @font-face{
222
+ font-family:C64;
223
+ src:url(fonts/C64_Pro_Mono-STYLE.woff)
224
+ }
225
+ @keyframes spin{
226
+ 0%{
227
+ transform:rotate(0deg)
228
+ }
229
+ 100%{
230
+ transform:rotate(360deg)
231
+ }
232
+ }
233
+ div{
234
+ border:solid red 1px
235
+ }
236
+ div.c1{
237
+ background-color:#000
238
+ }
239
+ div .c1{
240
+ background-color:black
241
+ }
242
+ div.c2{
243
+ background-color:rgb(0,0,0)
244
+ }
245
+ @media(min-width:200px){
246
+ div{
247
+ margin:0;
248
+ padding:0
249
+ }
250
+ span{
251
+ color:#000
252
+ }
253
+ }`.replace(/\n\s*/g, '')
254
+
255
+ expect(actual).to.deep.equal(expected)
103
256
  ```
104
257
 
105
- The type of arguments of the `jc` helper.
258
+ ```js
259
+ const actual = c({
260
+ a: {
261
+ '.b,.c': {
262
+ margin: 1,
263
+ '.d': {
264
+ margin: 2
265
+ }
266
+ }
267
+ }
268
+ })
269
+
270
+ const expected = `
271
+ a.b,a.c{
272
+ margin:1
273
+ }
274
+ a.b.d,a.c.d{
275
+ margin:2
276
+ }`.replace(/\n\s*/g, '')
277
+
278
+ expect(actual).to.deep.equal(expected)
279
+ ```
280
+
281
+ ```js
282
+ const actual = c({
283
+ '.b,.c': {
284
+ margin: 1,
285
+ '.d': {
286
+ margin: 2
287
+ }
288
+ }
289
+ })
290
+
291
+ const expected = `
292
+ .b,.c{
293
+ margin:1
294
+ }
295
+ .b.d,.c.d{
296
+ margin:2
297
+ }`.replace(/\n\s*/g, '')
298
+
299
+ expect(actual).to.deep.equal(expected)
300
+ ```
301
+
302
+ ```js
303
+ const actual = c({
304
+ '.a,.b': {
305
+ margin: 1,
306
+ '.c,.d': {
307
+ margin: 2
308
+ }
309
+ }
310
+ })
311
+
312
+ const expected = `
313
+ .a,.b{
314
+ margin:1
315
+ }
316
+ .a.c,.a.d,.b.c,.b.d{
317
+ margin:2
318
+ }`.replace(/\n\s*/g, '')
319
+
320
+ expect(actual).to.deep.equal(expected)
321
+ ```
106
322
 
107
323
  ### csvParse
108
324
 
@@ -220,19 +436,21 @@ const h: {
220
436
  };
221
437
  ```
222
438
 
223
- A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also `s`).
439
+ A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying
440
+ `HTMLElement`s (see also `s`).
224
441
 
225
442
  - The first argument of type `string` specifies the tag of the element to be created.
226
443
  - The first argument of type `Node` specifies the element to be modified.
227
444
  - All other arguments of type `Partial<Record<PropertyKey, unknown>>` are mappings of attributes and properties.
228
- Keys starting with `$` specify *properties* (without the leading `$`) to be set on the element being created or modified.
229
- (Note that `$` is not a valid attribute name character.)
230
- All other keys specify *attributes* to be set by `setAttribute`.
231
- An attribute equal to `false` causes the attribute to be removed by `removeAttribute`.
445
+ Keys starting with `$` specify *properties* (without the leading `$`) to be set on the element being created or
446
+ modified. (Note that `$` is not a valid attribute name character.) All other keys specify *attributes* to be set by
447
+ `setAttribute`. An attribute equal to `false` causes the attribute to be removed by `removeAttribute`.
232
448
  - All other arguments of type `null` or `undefined` are simply ignored.
233
449
  - All other arguments of type `Node` are appended to the element being created or modified.
234
- - All other arguments of type `string`/`number` are converted to `Text` nodes and appended to the element being created or modified.
235
- - All other arguments of type `HArgs` are passed to `h` and the results are appended to the element being created or modified.
450
+ - All other arguments of type `string`/`number` are converted to `Text` nodes and appended to the element being
451
+ created or modified.
452
+ - All other arguments of type `HArgs` are passed to `h` and the results are appended to the element being created or
453
+ modified.
236
454
 
237
455
  #### Usage Examples
238
456
 
@@ -419,218 +637,6 @@ try {
419
637
  expect(is(Number, num)).to.be.true
420
638
  ```
421
639
 
422
- ### jc
423
-
424
- ```ts
425
- const jc: (root: JcRoot, splitter?: string) => string;
426
- ```
427
-
428
- A simple JS-to-CSS (aka CSS-in-JS) helper.
429
-
430
- The `root` parameter provides a hierarchical description of CSS rules.
431
-
432
- - Keys of sub-objects whose values are NOT objects are treated as CSS attribute, and values are treated as values of those CSS attributes; the concatenation of keys of all parent objects is a CSS rule.
433
- - All keys ignore the part starting with a splitter (default: `$$`) sign until the end of the key (e.g. `src$$1` → `src`, `@font-face$$1` → `@font-face`).
434
- - In keys specifying CSS attribute, all uppercase letters are replaced by lowercase letters with an additional `-` character preceding them (e.g. `fontFamily` → `font-family`).
435
- - 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}`).
436
- - Top-level keys that begin with `@` are not concatenated with sub-object keys.
437
-
438
- #### Usage Examples
439
-
440
- ```js
441
- const actual = jc({
442
- a: {
443
- color: 'red',
444
- margin: 1,
445
- '.c': { margin: 2, padding: 2 },
446
- padding: 1
447
- }
448
- })
449
-
450
- const expected = `
451
- a{
452
- color:red;
453
- margin:1
454
- }
455
- a.c{
456
- margin:2;
457
- padding:2
458
- }
459
- a{
460
- padding:1
461
- }`.replace(/\n\s*/g, '')
462
-
463
- expect(actual).to.deep.equal(expected)
464
- ```
465
-
466
- ```js
467
- const actual = jc({
468
- a: {
469
- '.b': {
470
- color: 'red',
471
- margin: 1,
472
- '.c': { margin: 2, padding: 2 },
473
- padding: 1
474
- }
475
- }
476
- })
477
-
478
- const expected = `
479
- a.b{
480
- color:red;
481
- margin:1
482
- }
483
- a.b.c{
484
- margin:2;
485
- padding:2
486
- }
487
- a.b{
488
- padding:1
489
- }`.replace(/\n\s*/g, '')
490
-
491
- expect(actual).to.deep.equal(expected)
492
- ```
493
-
494
- ```js
495
- const actual = jc({
496
- '@font-face$$1': {
497
- fontFamily: 'Jackens',
498
- src$$1: 'url(otf/jackens.otf)',
499
- src$$2: "url(otf/jackens.otf) format('opentype')," +
500
- "url(svg/jackens.svg) format('svg')",
501
- fontWeight: 'normal',
502
- fontStyle: 'normal'
503
- },
504
- '@font-face$$2': {
505
- fontFamily: 'C64',
506
- src: 'url(fonts/C64_Pro_Mono-STYLE.woff)'
507
- },
508
- '@keyframes spin': {
509
- '0%': { transform: 'rotate(0deg)' },
510
- '100%': { transform: 'rotate(360deg)' }
511
- },
512
- div: {
513
- border: 'solid red 1px',
514
- '.c1': { 'background-color': '#000' },
515
- ' .c1': { backgroundColor: 'black' },
516
- '.c2': { backgroundColor: 'rgb(0,0,0)' }
517
- },
518
- '@media(min-width:200px)': {
519
- div: { margin: 0, padding: 0 },
520
- span: { color: '#000' }
521
- }
522
- })
523
-
524
- const expected = `
525
- @font-face{
526
- font-family:Jackens;
527
- src:url(otf/jackens.otf);
528
- src:url(otf/jackens.otf) format('opentype'),url(svg/jackens.svg) format('svg');
529
- font-weight:normal;
530
- font-style:normal
531
- }
532
- @font-face{
533
- font-family:C64;
534
- src:url(fonts/C64_Pro_Mono-STYLE.woff)
535
- }
536
- @keyframes spin{
537
- 0%{
538
- transform:rotate(0deg)
539
- }
540
- 100%{
541
- transform:rotate(360deg)
542
- }
543
- }
544
- div{
545
- border:solid red 1px
546
- }
547
- div.c1{
548
- background-color:#000
549
- }
550
- div .c1{
551
- background-color:black
552
- }
553
- div.c2{
554
- background-color:rgb(0,0,0)
555
- }
556
- @media(min-width:200px){
557
- div{
558
- margin:0;
559
- padding:0
560
- }
561
- span{
562
- color:#000
563
- }
564
- }`.replace(/\n\s*/g, '')
565
-
566
- expect(actual).to.deep.equal(expected)
567
- ```
568
-
569
- ```js
570
- const actual = jc({
571
- a: {
572
- '.b,.c': {
573
- margin: 1,
574
- '.d': {
575
- margin: 2
576
- }
577
- }
578
- }
579
- })
580
-
581
- const expected = `
582
- a.b,a.c{
583
- margin:1
584
- }
585
- a.b.d,a.c.d{
586
- margin:2
587
- }`.replace(/\n\s*/g, '')
588
-
589
- expect(actual).to.deep.equal(expected)
590
- ```
591
-
592
- ```js
593
- const actual = jc({
594
- '.b,.c': {
595
- margin: 1,
596
- '.d': {
597
- margin: 2
598
- }
599
- }
600
- })
601
-
602
- const expected = `
603
- .b,.c{
604
- margin:1
605
- }
606
- .b.d,.c.d{
607
- margin:2
608
- }`.replace(/\n\s*/g, '')
609
-
610
- expect(actual).to.deep.equal(expected)
611
- ```
612
-
613
- ```js
614
- const actual = jc({
615
- '.a,.b': {
616
- margin: 1,
617
- '.c,.d': {
618
- margin: 2
619
- }
620
- }
621
- })
622
-
623
- const expected = `
624
- .a,.b{
625
- margin:1
626
- }
627
- .a.c,.a.d,.b.c,.b.d{
628
- margin:2
629
- }`.replace(/\n\s*/g, '')
630
-
631
- expect(actual).to.deep.equal(expected)
632
- ```
633
-
634
640
  ### jsOnParse
635
641
 
636
642
  ```ts
@@ -824,7 +830,8 @@ expect(car(42)).to.deep.equal('cars')
824
830
  const pro: (ref: unknown) => any;
825
831
  ```
826
832
 
827
- A helper that protects calls to nested properties by a `Proxy` that initializes non-existent values with an empty object.
833
+ A helper that protects calls to nested properties by a `Proxy` that initializes non-existent values with an empty
834
+ object.
828
835
 
829
836
  #### Usage Examples
830
837
 
@@ -909,19 +916,21 @@ const s: {
909
916
  };
910
917
  ```
911
918
 
912
- A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also `h`).
919
+ A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying
920
+ `SVGElement`s (see also `h`).
913
921
 
914
922
  - The first argument of type `string` specifies the tag of the element to be created.
915
923
  - The first argument of type `Node` specifies the element to be modified.
916
924
  - All other arguments of type `Partial<Record<PropertyKey, unknown>>` are mappings of attributes and properties.
917
- Keys starting with `$` specify *properties* (without the leading `$`) to be set on the element being created or modified.
918
- (Note that `$` is not a valid attribute name character.)
919
- All other keys specify *attributes* to be set by `setAttributeNS`.
920
- An attribute equal to `false` causes the attribute to be removed by `removeAttributeNS`.
925
+ Keys starting with `$` specify *properties* (without the leading `$`) to be set on the element being created or
926
+ modified. (Note that `$` is not a valid attribute name character.) All other keys specify *attributes* to be set by
927
+ `setAttributeNS`. An attribute equal to `false` causes the attribute to be removed by `removeAttributeNS`.
921
928
  - All other arguments of type `null` or `undefined` are simply ignored.
922
929
  - All other arguments of type `Node` are appended to the element being created or modified.
923
- - All other arguments of type `string`/`number` are converted to `Text` nodes and appended to the element being created or modified.
924
- - All other arguments of type `HArgs` are passed to `s` and the results are appended to the element being created or modified.
930
+ - All other arguments of type `string`/`number` are converted to `Text` nodes and appended to the element being
931
+ created or modified.
932
+ - All other arguments of type `HArgs` are passed to `s` and the results are appended to the element being created or
933
+ modified.
925
934
 
926
935
  ### svgUse
927
936