@jackens/nnn 2024.2.20 → 2024.2.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.
- package/nnn.d.ts +220 -21
- package/nnn.js +419 -37
- package/package.json +1 -1
- package/readme.md +177 -172
- package/chartable.d.ts +0 -33
- package/chartable.js +0 -195
- package/eq.d.ts +0 -8
- package/eq.js +0 -83
- package/escape.d.ts +0 -18
- package/escape.js +0 -51
- package/fixTypography.d.ts +0 -8
- package/fixTypography.js +0 -61
- package/h.d.ts +0 -55
- package/h.js +0 -213
- package/has.d.ts +0 -9
- package/has.js +0 -40
- package/is.d.ts +0 -17
- package/is.js +0 -65
- package/jcss.d.ts +0 -33
- package/jcss.js +0 -293
- package/jsOnParse.d.ts +0 -20
- package/jsOnParse.js +0 -85
- package/locale.d.ts +0 -8
- package/locale.js +0 -39
- package/nanolight.d.ts +0 -6
- package/nanolight.js +0 -21
- package/nanolightJs.d.ts +0 -8
- package/nanolightJs.js +0 -29
- package/pick.d.ts +0 -14
- package/pick.js +0 -31
- package/plUral.d.ts +0 -8
- package/plUral.js +0 -39
- package/pro.d.ts +0 -8
- package/pro.js +0 -39
- package/refsInfo.d.ts +0 -11
- package/refsInfo.js +0 -57
- package/uuid1.d.ts +0 -16
- package/uuid1.js +0 -54
package/h.js
DELETED
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
import { is } from './is.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The type of arguments of the `h` and `s` helpers.
|
|
5
|
-
*
|
|
6
|
-
* @typedef {Partial<Record<PropertyKey, any>> | null | undefined | Node | string | number | HArgs} HArgs1
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* The type of arguments of the `h` and `s` helpers.
|
|
11
|
-
*
|
|
12
|
-
* @typedef {[string | Node, ...HArgs1[]]} HArgs
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const NS = {
|
|
16
|
-
xlink: 'http://www.w3.org/1999/xlink'
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @type {{
|
|
21
|
-
* (namespaceURI?: null | undefined): {
|
|
22
|
-
* <T extends keyof HTMLElementTagNameMap>(tag: T, ...args1: HArgs1[]): HTMLElementTagNameMap[T];
|
|
23
|
-
* <N extends Node> (node: N, ...args1: HArgs1[]): N;
|
|
24
|
-
* (tagOrNode: string | Node, ...args1: HArgs1[]): Node;
|
|
25
|
-
* };
|
|
26
|
-
* (namespaceURI: 'http://www.w3.org/2000/svg'): {
|
|
27
|
-
* <T extends keyof SVGElementTagNameMap> (tag: T, ...args1: HArgs1[]): SVGElementTagNameMap[T];
|
|
28
|
-
* <N extends Node> (node: N, ...args1: HArgs1[]): N;
|
|
29
|
-
* (tagOrNode: string | Node, ...args1: HArgs1[]): Node;
|
|
30
|
-
* };
|
|
31
|
-
* }}
|
|
32
|
-
*/
|
|
33
|
-
const _h = (/** @type {string?=} */ namespaceURI) => {
|
|
34
|
-
const createElement = namespaceURI == null
|
|
35
|
-
? (/** @type {string } */ tag) => document.createElement(tag)
|
|
36
|
-
: (/** @type {string } */ tag) => document.createElementNS(namespaceURI, tag)
|
|
37
|
-
|
|
38
|
-
const h = (/** @type {string | Node} */ tagOrNode, /** @type {HArgs1[]} */ ...args) => {
|
|
39
|
-
const node = is(String, tagOrNode) ? createElement(tagOrNode) : tagOrNode
|
|
40
|
-
|
|
41
|
-
args.forEach(arg => {
|
|
42
|
-
let child = null
|
|
43
|
-
|
|
44
|
-
if (arg instanceof Node) {
|
|
45
|
-
child = arg
|
|
46
|
-
} else if (is(String, arg) || is(Number, arg)) {
|
|
47
|
-
// @ts-expect-error
|
|
48
|
-
child = new Text(arg)
|
|
49
|
-
} else if (is(Array, arg)) {
|
|
50
|
-
// @ts-expect-error
|
|
51
|
-
child = h(...arg)
|
|
52
|
-
} else if (arg != null) {
|
|
53
|
-
for (const name in arg) {
|
|
54
|
-
const value = arg[name]
|
|
55
|
-
|
|
56
|
-
if (name[0] === '$') {
|
|
57
|
-
const name1 = name.slice(1)
|
|
58
|
-
|
|
59
|
-
if (is(Object, value)) {
|
|
60
|
-
// @ts-expect-error
|
|
61
|
-
node[name1] = node[name1] ?? {}
|
|
62
|
-
// @ts-expect-error
|
|
63
|
-
Object.assign(node[name1], value)
|
|
64
|
-
} else {
|
|
65
|
-
// @ts-expect-error
|
|
66
|
-
node[name1] = value
|
|
67
|
-
}
|
|
68
|
-
} else if (node instanceof Element) {
|
|
69
|
-
const indexOfColon = name.indexOf(':')
|
|
70
|
-
|
|
71
|
-
if (indexOfColon >= 0) {
|
|
72
|
-
// @ts-expect-error
|
|
73
|
-
const /** @type {string=} */ ns = NS[name.slice(0, indexOfColon)]
|
|
74
|
-
|
|
75
|
-
if (ns != null) {
|
|
76
|
-
const basename = name.slice(indexOfColon + 1)
|
|
77
|
-
|
|
78
|
-
if (value === true) {
|
|
79
|
-
node.setAttributeNS(ns, basename, '')
|
|
80
|
-
} else if (value === false) {
|
|
81
|
-
node.removeAttributeNS(ns, basename)
|
|
82
|
-
} else {
|
|
83
|
-
node.setAttributeNS(ns, basename, is(String, value) ? value : '' + value)
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
} else {
|
|
87
|
-
if (value === true) {
|
|
88
|
-
node.setAttribute(name, '')
|
|
89
|
-
} else if (value === false) {
|
|
90
|
-
node.removeAttribute(name)
|
|
91
|
-
} else {
|
|
92
|
-
node.setAttribute(name, is(String, value) ? value : '' + value)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (child != null) {
|
|
100
|
-
node.appendChild(child)
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
return node
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return h
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also `s`).
|
|
112
|
-
*
|
|
113
|
-
* - The first argument of type `string` specifies the tag of the element to be created.
|
|
114
|
-
* - The first argument of type `Node` specifies the element to be modified.
|
|
115
|
-
* - All other arguments of type `Partial<Record<PropertyKey, any>>` are mappings of attributes and properties.
|
|
116
|
-
* Keys starting with `$` specify *properties* (without the leading `$`) to be set on the element being created or modified.
|
|
117
|
-
* (Note that `$` is not a valid attribute name character.)
|
|
118
|
-
* All other keys specify *attributes* to be set by `setAttribute`.
|
|
119
|
-
* An attribute equal to `false` causes the attribute to be removed by `removeAttribute`.
|
|
120
|
-
* - All other arguments of type `null` or `undefined` are simply ignored.
|
|
121
|
-
* - All other arguments of type `Node` are appended to the element being created or modified.
|
|
122
|
-
* - All other arguments of type `string`/`number` are converted to `Text` nodes and appended to the element being created or modified.
|
|
123
|
-
* - All other arguments of type `HArgs` are passed to `h` and the results are appended to the element being created or modified.
|
|
124
|
-
*/
|
|
125
|
-
export const h = _h()
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also `h`).
|
|
129
|
-
*
|
|
130
|
-
* - The first argument of type `string` specifies the tag of the element to be created.
|
|
131
|
-
* - The first argument of type `Node` specifies the element to be modified.
|
|
132
|
-
* - All other arguments of type `Partial<Record<PropertyKey, any>>` are mappings of attributes and properties.
|
|
133
|
-
* Keys starting with `$` specify *properties* (without the leading `$`) to be set on the element being created or modified.
|
|
134
|
-
* (Note that `$` is not a valid attribute name character.)
|
|
135
|
-
* All other keys specify *attributes* to be set by `setAttributeNS`.
|
|
136
|
-
* An attribute equal to `false` causes the attribute to be removed by `removeAttributeNS`.
|
|
137
|
-
* - All other arguments of type `null` or `undefined` are simply ignored.
|
|
138
|
-
* - All other arguments of type `Node` are appended to the element being created or modified.
|
|
139
|
-
* - All other arguments of type `string`/`number` are converted to `Text` nodes and appended to the element being created or modified.
|
|
140
|
-
* - All other arguments of type `HArgs` are passed to `s` and the results are appended to the element being created or modified.
|
|
141
|
-
*/
|
|
142
|
-
export const s = _h('http://www.w3.org/2000/svg')
|
|
143
|
-
|
|
144
|
-
export const tests = {
|
|
145
|
-
h: (/** @type {import('chai').expect} */ expect) => {
|
|
146
|
-
const b = h('b')
|
|
147
|
-
|
|
148
|
-
expect(b.outerHTML).to.deep.equal('<b></b>')
|
|
149
|
-
|
|
150
|
-
const i = h('i', 'text')
|
|
151
|
-
|
|
152
|
-
h(b, i)
|
|
153
|
-
|
|
154
|
-
expect(i.outerHTML).to.deep.equal('<i>text</i>')
|
|
155
|
-
expect(b.outerHTML).to.deep.equal('<b><i>text</i></b>')
|
|
156
|
-
|
|
157
|
-
h(i, { $className: 'some class' })
|
|
158
|
-
|
|
159
|
-
expect(i.outerHTML).to.deep.equal('<i class="some class">text</i>')
|
|
160
|
-
expect(b.outerHTML).to.deep.equal('<b><i class="some class">text</i></b>')
|
|
161
|
-
},
|
|
162
|
-
|
|
163
|
-
'h: innerText vs items': (/** @type {import('chai').expect} */ expect) => {
|
|
164
|
-
expect(h('span', 'text').outerHTML).to.deep.equal('<span>text</span>')
|
|
165
|
-
expect(h('span', { $innerText: 'text' }).outerHTML).to.deep.equal('<span>text</span>')
|
|
166
|
-
},
|
|
167
|
-
|
|
168
|
-
'h: style': (/** @type {import('chai').expect} */ expect) => {
|
|
169
|
-
expect(h('div', { style: 'margin:0;padding:0' }).outerHTML)
|
|
170
|
-
.to.deep.equal('<div style="margin:0;padding:0"></div>')
|
|
171
|
-
expect(h('div', { $style: 'margin:0;padding:0' }).outerHTML)
|
|
172
|
-
.to.deep.equal('<div style="margin: 0px; padding: 0px;"></div>')
|
|
173
|
-
expect(h('div', { $style: { margin: 0, padding: 0 } }).outerHTML)
|
|
174
|
-
.to.deep.equal('<div style="margin: 0px; padding: 0px;"></div>')
|
|
175
|
-
},
|
|
176
|
-
|
|
177
|
-
'h: attributes vs properties': (/** @type {import('chai').expect} */ expect) => {
|
|
178
|
-
const input1 = h('input', { value: 42 })
|
|
179
|
-
const input2 = h('input', { $value: '42' })
|
|
180
|
-
|
|
181
|
-
expect(input1.value).to.deep.equal('42')
|
|
182
|
-
expect(input2.value).to.deep.equal('42')
|
|
183
|
-
|
|
184
|
-
expect(input1.outerHTML).to.deep.equal('<input value="42">')
|
|
185
|
-
expect(input2.outerHTML).to.deep.equal('<input>')
|
|
186
|
-
|
|
187
|
-
const checkbox1 = h('input', { type: 'checkbox', checked: true })
|
|
188
|
-
const checkbox2 = h('input', { type: 'checkbox', $checked: true })
|
|
189
|
-
|
|
190
|
-
expect(checkbox1.checked).to.be.true
|
|
191
|
-
expect(checkbox2.checked).to.be.true
|
|
192
|
-
|
|
193
|
-
expect(checkbox1.outerHTML).to.deep.equal('<input type="checkbox" checked="">')
|
|
194
|
-
expect(checkbox2.outerHTML).to.deep.equal('<input type="checkbox">')
|
|
195
|
-
},
|
|
196
|
-
|
|
197
|
-
'h: nested properties': (/** @type {import('chai').expect} */ expect) => {
|
|
198
|
-
const div = h('div')
|
|
199
|
-
|
|
200
|
-
// @ts-expect-error
|
|
201
|
-
expect(div.key).to.be.undefined
|
|
202
|
-
|
|
203
|
-
h(div, { $key: { one: 1 } })
|
|
204
|
-
|
|
205
|
-
// @ts-expect-error
|
|
206
|
-
expect(div.key).to.deep.equal({ one: 1 })
|
|
207
|
-
|
|
208
|
-
h(div, { $key: { two: 2 } })
|
|
209
|
-
|
|
210
|
-
// @ts-expect-error
|
|
211
|
-
expect(div.key).to.deep.equal({ one: 1, two: 2 })
|
|
212
|
-
}
|
|
213
|
-
}
|
package/has.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A replacement for the `in` operator (not to be confused with the `for-in` loop) that works properly.
|
|
3
|
-
*/
|
|
4
|
-
export function has(key: any, ref: any): boolean;
|
|
5
|
-
|
|
6
|
-
export const tests: {
|
|
7
|
-
has: (expect: Chai.ExpectStatic) => void;
|
|
8
|
-
'has: null': (expect: Chai.ExpectStatic) => void;
|
|
9
|
-
};
|
package/has.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { is } from './is.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A replacement for the `in` operator (not to be confused with the `for-in` loop) that works properly.
|
|
5
|
-
*/
|
|
6
|
-
export const has = (/** @type {any} */ key, /** @type {any} */ ref) =>
|
|
7
|
-
(is(String, key) || is(Number, key) || is(Symbol, key)) && Object.hasOwnProperty.call(ref ?? Object, key)
|
|
8
|
-
|
|
9
|
-
export const tests = {
|
|
10
|
-
has: (/** @type {import('chai').expect} */ expect) => {
|
|
11
|
-
const obj = { key: 'K', null: 'N' }
|
|
12
|
-
|
|
13
|
-
expect('key' in obj).to.be.true
|
|
14
|
-
expect(has('key', obj)).to.be.true
|
|
15
|
-
|
|
16
|
-
expect('null' in obj).to.be.true
|
|
17
|
-
expect(has('null', obj)).to.be.true
|
|
18
|
-
|
|
19
|
-
// @ts-expect-error
|
|
20
|
-
expect(null in obj).to.be.true
|
|
21
|
-
expect(has(null, obj)).to.be.false
|
|
22
|
-
|
|
23
|
-
expect('toString' in obj).to.be.true
|
|
24
|
-
expect(has('toString', obj)).to.be.false
|
|
25
|
-
},
|
|
26
|
-
|
|
27
|
-
'has: null': (/** @type {import('chai').expect} */ expect) => {
|
|
28
|
-
let typeError
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
// @ts-expect-error
|
|
32
|
-
'key' in null
|
|
33
|
-
} catch (error) {
|
|
34
|
-
typeError = error
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
expect(typeError instanceof TypeError) // Cannot use 'in' operator to search for 'key' in null
|
|
38
|
-
expect(has('key', null)).to.be.false
|
|
39
|
-
}
|
|
40
|
-
}
|
package/is.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A helper that checks if the given argument is of a certain type.
|
|
3
|
-
*/
|
|
4
|
-
export const is: {
|
|
5
|
-
(type: BigIntConstructor, arg: any): arg is bigint;
|
|
6
|
-
(type: BooleanConstructor, arg: any): arg is boolean;
|
|
7
|
-
(type: NumberConstructor, arg: any): arg is number;
|
|
8
|
-
(type: StringConstructor, arg: any): arg is string;
|
|
9
|
-
(type: SymbolConstructor, arg: any): arg is symbol;
|
|
10
|
-
(type: undefined, arg: any): arg is null | undefined;
|
|
11
|
-
<T extends abstract new (...args: any[]) => any>(type: T, arg: any): arg is InstanceType<T>;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export const tests: {
|
|
15
|
-
is: (expect: Chai.ExpectStatic) => void;
|
|
16
|
-
'is: toString.call': (expect: Chai.ExpectStatic) => void;
|
|
17
|
-
};
|
package/is.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A helper that checks if the given argument is of a certain type.
|
|
3
|
-
*
|
|
4
|
-
* @template {abstract new (...args: any[]) => any} T
|
|
5
|
-
*
|
|
6
|
-
* @type {{
|
|
7
|
-
* (type: BigIntConstructor, arg: any): arg is bigint;
|
|
8
|
-
* (type: BooleanConstructor, arg: any): arg is boolean;
|
|
9
|
-
* (type: NumberConstructor, arg: any): arg is number;
|
|
10
|
-
* (type: StringConstructor, arg: any): arg is string;
|
|
11
|
-
* (type: SymbolConstructor, arg: any): arg is symbol;
|
|
12
|
-
* (type: undefined, arg: any): arg is undefined | null;
|
|
13
|
-
* <T extends abstract new (...args: any[]) => any>(type: T, arg: any): arg is InstanceType<T>;
|
|
14
|
-
* }}
|
|
15
|
-
*
|
|
16
|
-
* @return {arg is bigint | boolean | number | string | symbol | undefined | null | InstanceType<T>}
|
|
17
|
-
*/
|
|
18
|
-
export const is = (/** @type {T} */ type, /** @type {any} */ arg) => arg?.constructor === type
|
|
19
|
-
|
|
20
|
-
export const tests = {
|
|
21
|
-
is: (/** @type {import('chai').expect} */ expect) => {
|
|
22
|
-
expect(is(Number, 42)).to.be.true
|
|
23
|
-
expect(is(Number, Number(42))).to.be.true
|
|
24
|
-
// eslint-disable-next-line no-new-wrappers
|
|
25
|
-
expect(is(Number, new Number(42))).to.be.true
|
|
26
|
-
expect(is(Number, NaN)).to.be.true
|
|
27
|
-
expect(is(String, '42')).to.be.true
|
|
28
|
-
expect(is(String, String('42'))).to.be.true
|
|
29
|
-
// eslint-disable-next-line no-new-wrappers
|
|
30
|
-
expect(is(String, new String('42'))).to.be.true
|
|
31
|
-
expect(is(Symbol, Symbol('42'))).to.be.true
|
|
32
|
-
expect(is(Symbol, Object(Symbol('42')))).to.be.true
|
|
33
|
-
expect(is(undefined, undefined)).to.be.true
|
|
34
|
-
expect(is(undefined, null)).to.be.true
|
|
35
|
-
expect(is(Object, {})).to.be.true
|
|
36
|
-
expect(is(Array, [])).to.be.true
|
|
37
|
-
expect(is(RegExp, /42/)).to.be.true
|
|
38
|
-
expect(is(Date, new Date(42))).to.be.true
|
|
39
|
-
expect(is(Set, new Set(['42', 42]))).to.be.true
|
|
40
|
-
expect(is(Map, new Map([[{ j: 42 }, { J: '42' }], [{ c: 42 }, { C: '42' }]]))).to.be.true
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
'is: toString.call': (/** @type {import('chai').expect} */ expect) => {
|
|
44
|
-
const iz = (/** @type {any} */ type, /** @type {any} */ arg) => ({}).toString.call(arg).slice(8, -1) === type?.name
|
|
45
|
-
|
|
46
|
-
class FooBar { }
|
|
47
|
-
|
|
48
|
-
expect(is(FooBar, new FooBar())).to.be.true
|
|
49
|
-
expect(iz(FooBar, new FooBar())).to.be.false
|
|
50
|
-
|
|
51
|
-
expect(is(Object, new FooBar())).to.be.false
|
|
52
|
-
expect(iz(Object, new FooBar())).to.be.true
|
|
53
|
-
|
|
54
|
-
const fakeFooBar = {}
|
|
55
|
-
|
|
56
|
-
// @ts-expect-error
|
|
57
|
-
fakeFooBar[Symbol.toStringTag] = FooBar.name
|
|
58
|
-
|
|
59
|
-
expect(is(FooBar, fakeFooBar)).to.be.false
|
|
60
|
-
expect(iz(FooBar, fakeFooBar)).to.be.true
|
|
61
|
-
|
|
62
|
-
expect(is(Object, fakeFooBar)).to.be.true
|
|
63
|
-
expect(iz(Object, fakeFooBar)).to.be.false
|
|
64
|
-
}
|
|
65
|
-
}
|
package/jcss.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The type of arguments of the `jcss` helper.
|
|
3
|
-
*/
|
|
4
|
-
export type JcssNode = {
|
|
5
|
-
[attributeOrSelector: string]: string | number | JcssNode | undefined;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* The type of arguments of the `jcss` helper.
|
|
10
|
-
*/
|
|
11
|
-
export type JcssRoot = Partial<Record<PropertyKey, JcssNode>>;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* A simple 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 those CSS attributes; the concatenation of keys of all parent objects is a CSS rule.
|
|
19
|
-
* - 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`).
|
|
20
|
-
* - In keys specifying CSS attribute, all uppercase letters are replaced by lowercase letters with an additional `-` character preceding them (e.g. `fontFamily` → `font-family`).
|
|
21
|
-
* - 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}`).
|
|
22
|
-
* - Top-level keys that begin with `@` are not concatenated with sub-object keys.
|
|
23
|
-
*/
|
|
24
|
-
export function jcss(root: JcssRoot, splitter?: string): string;
|
|
25
|
-
|
|
26
|
-
export const tests: {
|
|
27
|
-
'jcss: #1': (expect: Chai.ExpectStatic) => void;
|
|
28
|
-
'jcss: #2': (expect: Chai.ExpectStatic) => void;
|
|
29
|
-
'jcss: #3': (expect: Chai.ExpectStatic) => void;
|
|
30
|
-
'jcss: #4': (expect: Chai.ExpectStatic) => void;
|
|
31
|
-
'jcss: #5': (expect: Chai.ExpectStatic) => void;
|
|
32
|
-
'jcss: #6': (expect: Chai.ExpectStatic) => void;
|
|
33
|
-
};
|
package/jcss.js
DELETED
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
import { is } from './is.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The type of arguments of the `jcss` helper.
|
|
5
|
-
*
|
|
6
|
-
* @typedef {{
|
|
7
|
-
* [attributeOrSelector: string]: string | number | JcssNode | undefined;
|
|
8
|
-
* }} JcssNode
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* The type of arguments of the `jcss` helper.
|
|
13
|
-
*
|
|
14
|
-
* @typedef {Partial<Record<PropertyKey, JcssNode>>} JcssRoot
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
const _jcss = (
|
|
18
|
-
/** @type {JcssNode} */ node,
|
|
19
|
-
/** @type {string} */ prefix,
|
|
20
|
-
/** @type {string[]} */ result,
|
|
21
|
-
/** @type {(text: string) => string} */ split
|
|
22
|
-
) => {
|
|
23
|
-
const /** @type {[JcssNode | string[], string][]} */ queue = [[node, prefix]]
|
|
24
|
-
|
|
25
|
-
while (queue.length > 0) {
|
|
26
|
-
const [style0, prefix0] = queue.shift() ?? []
|
|
27
|
-
|
|
28
|
-
if (style0 == null || prefix0 == null) {
|
|
29
|
-
continue
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (is(Array, style0)) {
|
|
33
|
-
result.push(prefix0, prefix0 !== '' ? '{' : '', style0.join(';'), prefix0 !== '' ? '}' : '')
|
|
34
|
-
} else {
|
|
35
|
-
const /** @type {[JcssNode | string[], string][]} */ todo = []
|
|
36
|
-
let /** @type {string[]} */ attributes = []
|
|
37
|
-
let attributesPushed = false
|
|
38
|
-
|
|
39
|
-
for (const key in style0) {
|
|
40
|
-
const value = style0[key]
|
|
41
|
-
|
|
42
|
-
if (is(String, value) || is(Number, value)) {
|
|
43
|
-
if (!attributesPushed) {
|
|
44
|
-
attributesPushed = true
|
|
45
|
-
attributes = []
|
|
46
|
-
todo.push([attributes, prefix0])
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
attributes.push(`${split(key).replace(/([A-Z])/g, (_, letter) => '-' + letter.toLowerCase())}:${value}`)
|
|
50
|
-
} else if (value != null) {
|
|
51
|
-
attributesPushed = false
|
|
52
|
-
|
|
53
|
-
const /** @type {string[]} */ prefixN = []
|
|
54
|
-
const keyChunks = key.split(',')
|
|
55
|
-
|
|
56
|
-
prefix0.split(',').forEach(prefixChunk => keyChunks.forEach(keyChunk => prefixN.push(prefixChunk + keyChunk)))
|
|
57
|
-
|
|
58
|
-
todo.push([value, prefixN.join(',')])
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
queue.unshift(...todo)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* A simple CSS-in-JS helper.
|
|
69
|
-
*
|
|
70
|
-
* The `root` parameter provides a hierarchical description of CSS rules.
|
|
71
|
-
*
|
|
72
|
-
* - 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.
|
|
73
|
-
* - 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`).
|
|
74
|
-
* - In keys specifying CSS attribute, all uppercase letters are replaced by lowercase letters with an additional `-` character preceding them (e.g. `fontFamily` → `font-family`).
|
|
75
|
-
* - 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}`).
|
|
76
|
-
* - Top-level keys that begin with `@` are not concatenated with sub-object keys.
|
|
77
|
-
*/
|
|
78
|
-
export const jcss = (/** @type {JcssRoot} */ root, splitter = '$$') => {
|
|
79
|
-
const split = (/** @type {string} */ text) => text.split(splitter)[0]
|
|
80
|
-
const /** @type {string[]} */ chunks = []
|
|
81
|
-
|
|
82
|
-
for (const key in root) {
|
|
83
|
-
const value = root[key]
|
|
84
|
-
|
|
85
|
-
if (value != null) {
|
|
86
|
-
if (key[0] === '@') {
|
|
87
|
-
chunks.push(split(key) + '{')
|
|
88
|
-
_jcss(value, '', chunks, split)
|
|
89
|
-
chunks.push('}')
|
|
90
|
-
} else {
|
|
91
|
-
_jcss(value, split(key), chunks, split)
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return chunks.join('')
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export const tests = {
|
|
100
|
-
'jcss: #1': (/** @type {import('chai').expect} */ expect) => {
|
|
101
|
-
const actual = jcss({
|
|
102
|
-
a: {
|
|
103
|
-
color: 'red',
|
|
104
|
-
margin: 1,
|
|
105
|
-
'.c': { margin: 2, padding: 2 },
|
|
106
|
-
padding: 1
|
|
107
|
-
}
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
const expected = `
|
|
111
|
-
a{
|
|
112
|
-
color:red;
|
|
113
|
-
margin:1
|
|
114
|
-
}
|
|
115
|
-
a.c{
|
|
116
|
-
margin:2;
|
|
117
|
-
padding:2
|
|
118
|
-
}
|
|
119
|
-
a{
|
|
120
|
-
padding:1
|
|
121
|
-
}`.replace(/\n\s*/g, '')
|
|
122
|
-
|
|
123
|
-
expect(actual).to.deep.equal(expected)
|
|
124
|
-
},
|
|
125
|
-
|
|
126
|
-
'jcss: #2': (/** @type {import('chai').expect} */ expect) => {
|
|
127
|
-
const actual = jcss({
|
|
128
|
-
a: {
|
|
129
|
-
'.b': {
|
|
130
|
-
color: 'red',
|
|
131
|
-
margin: 1,
|
|
132
|
-
'.c': { margin: 2, padding: 2 },
|
|
133
|
-
padding: 1
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
const expected = `
|
|
139
|
-
a.b{
|
|
140
|
-
color:red;
|
|
141
|
-
margin:1
|
|
142
|
-
}
|
|
143
|
-
a.b.c{
|
|
144
|
-
margin:2;
|
|
145
|
-
padding:2
|
|
146
|
-
}
|
|
147
|
-
a.b{
|
|
148
|
-
padding:1
|
|
149
|
-
}`.replace(/\n\s*/g, '')
|
|
150
|
-
|
|
151
|
-
expect(actual).to.deep.equal(expected)
|
|
152
|
-
},
|
|
153
|
-
|
|
154
|
-
'jcss: #3': (/** @type {import('chai').expect} */ expect) => {
|
|
155
|
-
const actual = jcss({
|
|
156
|
-
'@font-face$$1': {
|
|
157
|
-
fontFamily: 'Jackens',
|
|
158
|
-
src$$1: 'url(otf/jackens.otf)',
|
|
159
|
-
src$$2: "url(otf/jackens.otf) format('opentype')," +
|
|
160
|
-
"url(svg/jackens.svg) format('svg')",
|
|
161
|
-
fontWeight: 'normal',
|
|
162
|
-
fontStyle: 'normal'
|
|
163
|
-
},
|
|
164
|
-
'@font-face$$2': {
|
|
165
|
-
fontFamily: 'C64',
|
|
166
|
-
src: 'url(fonts/C64_Pro_Mono-STYLE.woff)'
|
|
167
|
-
},
|
|
168
|
-
'@keyframes spin': {
|
|
169
|
-
'0%': { transform: 'rotate(0deg)' },
|
|
170
|
-
'100%': { transform: 'rotate(360deg)' }
|
|
171
|
-
},
|
|
172
|
-
div: {
|
|
173
|
-
border: 'solid red 1px',
|
|
174
|
-
'.c1': { 'background-color': '#000' },
|
|
175
|
-
' .c1': { backgroundColor: 'black' },
|
|
176
|
-
'.c2': { backgroundColor: 'rgb(0,0,0)' }
|
|
177
|
-
},
|
|
178
|
-
'@media(min-width:200px)': {
|
|
179
|
-
div: { margin: 0, padding: 0 },
|
|
180
|
-
span: { color: '#000' }
|
|
181
|
-
}
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
const expected = `
|
|
185
|
-
@font-face{
|
|
186
|
-
font-family:Jackens;
|
|
187
|
-
src:url(otf/jackens.otf);
|
|
188
|
-
src:url(otf/jackens.otf) format('opentype'),url(svg/jackens.svg) format('svg');
|
|
189
|
-
font-weight:normal;
|
|
190
|
-
font-style:normal
|
|
191
|
-
}
|
|
192
|
-
@font-face{
|
|
193
|
-
font-family:C64;
|
|
194
|
-
src:url(fonts/C64_Pro_Mono-STYLE.woff)
|
|
195
|
-
}
|
|
196
|
-
@keyframes spin{
|
|
197
|
-
0%{
|
|
198
|
-
transform:rotate(0deg)
|
|
199
|
-
}
|
|
200
|
-
100%{
|
|
201
|
-
transform:rotate(360deg)
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
div{
|
|
205
|
-
border:solid red 1px
|
|
206
|
-
}
|
|
207
|
-
div.c1{
|
|
208
|
-
background-color:#000
|
|
209
|
-
}
|
|
210
|
-
div .c1{
|
|
211
|
-
background-color:black
|
|
212
|
-
}
|
|
213
|
-
div.c2{
|
|
214
|
-
background-color:rgb(0,0,0)
|
|
215
|
-
}
|
|
216
|
-
@media(min-width:200px){
|
|
217
|
-
div{
|
|
218
|
-
margin:0;
|
|
219
|
-
padding:0
|
|
220
|
-
}
|
|
221
|
-
span{
|
|
222
|
-
color:#000
|
|
223
|
-
}
|
|
224
|
-
}`.replace(/\n\s*/g, '')
|
|
225
|
-
|
|
226
|
-
expect(actual).to.deep.equal(expected)
|
|
227
|
-
},
|
|
228
|
-
|
|
229
|
-
'jcss: #4': (/** @type {import('chai').expect} */ expect) => {
|
|
230
|
-
const actual = jcss({
|
|
231
|
-
a: {
|
|
232
|
-
'.b,.c': {
|
|
233
|
-
margin: 1,
|
|
234
|
-
'.d': {
|
|
235
|
-
margin: 2
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
})
|
|
240
|
-
|
|
241
|
-
const expected = `
|
|
242
|
-
a.b,a.c{
|
|
243
|
-
margin:1
|
|
244
|
-
}
|
|
245
|
-
a.b.d,a.c.d{
|
|
246
|
-
margin:2
|
|
247
|
-
}`.replace(/\n\s*/g, '')
|
|
248
|
-
|
|
249
|
-
expect(actual).to.deep.equal(expected)
|
|
250
|
-
},
|
|
251
|
-
|
|
252
|
-
'jcss: #5': (/** @type {import('chai').expect} */ expect) => {
|
|
253
|
-
const actual = jcss({
|
|
254
|
-
'.b,.c': {
|
|
255
|
-
margin: 1,
|
|
256
|
-
'.d': {
|
|
257
|
-
margin: 2
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
const expected = `
|
|
263
|
-
.b,.c{
|
|
264
|
-
margin:1
|
|
265
|
-
}
|
|
266
|
-
.b.d,.c.d{
|
|
267
|
-
margin:2
|
|
268
|
-
}`.replace(/\n\s*/g, '')
|
|
269
|
-
|
|
270
|
-
expect(actual).to.deep.equal(expected)
|
|
271
|
-
},
|
|
272
|
-
|
|
273
|
-
'jcss: #6': (/** @type {import('chai').expect} */ expect) => {
|
|
274
|
-
const actual = jcss({
|
|
275
|
-
'.a,.b': {
|
|
276
|
-
margin: 1,
|
|
277
|
-
'.c,.d': {
|
|
278
|
-
margin: 2
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
})
|
|
282
|
-
|
|
283
|
-
const expected = `
|
|
284
|
-
.a,.b{
|
|
285
|
-
margin:1
|
|
286
|
-
}
|
|
287
|
-
.a.c,.a.d,.b.c,.b.d{
|
|
288
|
-
margin:2
|
|
289
|
-
}`.replace(/\n\s*/g, '')
|
|
290
|
-
|
|
291
|
-
expect(actual).to.deep.equal(expected)
|
|
292
|
-
}
|
|
293
|
-
}
|
package/jsOnParse.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `JSON.parse` with “JavaScript turned on”.
|
|
3
|
-
*
|
|
4
|
-
* Objects having *exactly* one property which is present in the `handlers` map, i.e. objects of the form:
|
|
5
|
-
*
|
|
6
|
-
* ```js
|
|
7
|
-
* { "«handlerName»": [«params»] }
|
|
8
|
-
* ```
|
|
9
|
-
*
|
|
10
|
-
* are replaced by the result of call
|
|
11
|
-
*
|
|
12
|
-
* ```js
|
|
13
|
-
* handlers['«handlerName»'](...«params»)
|
|
14
|
-
* ```
|
|
15
|
-
*/
|
|
16
|
-
export function jsOnParse(handlers: Partial<Record<PropertyKey, Function>>, text: string): any;
|
|
17
|
-
|
|
18
|
-
export namespace tests {
|
|
19
|
-
function jsOnParse(expect: Chai.ExpectStatic): void;
|
|
20
|
-
}
|