Skip to content

Commit 7fdf3eb

Browse files
committed
Refactor code-style
1 parent 8183292 commit 7fdf3eb

File tree

3 files changed

+98
-98
lines changed

3 files changed

+98
-98
lines changed

lib/index.js

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
/**
2-
* @typedef {import('hast').Root} Root
32
* @typedef {import('hast').Nodes} Nodes
43
*/
54

65
/**
7-
* @typedef {string | number} ConditionalPrimitive
8-
* Basic class names.
9-
* @typedef {Record<string, boolean>} ConditionalMap
6+
* @typedef {Record<string, boolean>} ClassMap
107
* Map of class names as keys, with whether they’re turned on or not as
118
* values.
12-
* @typedef {null | undefined | ConditionalPrimitive | ConditionalMap | Array<ConditionalPrimitive | ConditionalMap | Array<ConditionalPrimitive | ConditionalMap>>} Conditional
9+
* @typedef {Array<Array<ConditionalMap | ConditionalPrimitive> | ConditionalMap | ConditionalPrimitive> | ConditionalMap | ConditionalPrimitive | null | undefined} Conditional
1310
* Different ways to turn class names on or off.
14-
* @typedef {Record<string, boolean>} ClassMap
11+
* @typedef {Record<string, boolean>} ConditionalMap
1512
* Map of class names as keys, with whether they’re turned on or not as
1613
* values.
14+
* @typedef {number | string} ConditionalPrimitive
15+
* Basic class names.
1716
*/
1817

1918
import {parse} from 'space-separated-tokens'
@@ -33,6 +32,7 @@ const own = {}.hasOwnProperty
3332
* The given node, if any, or a list of strings.
3433
*/
3534
export const classnames =
35+
// Note: JSDoc overloads don’t support optional templates yet.
3636
/**
3737
* @type {(
3838
* (<T extends Nodes>(node: T, ...conditionals: Array<Conditional>) => T) &
@@ -41,24 +41,24 @@ export const classnames =
4141
*/
4242
(
4343
/**
44-
* @param {Nodes | Conditional | null | undefined} [node]
45-
* @param {Array<Conditional>} conditionals
44+
* @param {Conditional | Nodes | null | undefined} [node]
45+
* @param {...Conditional} conditionals
4646
*/
4747
function (node, ...conditionals) {
4848
let index = -1
49-
/** @type {ClassMap} */
50-
const map = Object.create(null)
49+
/** @type {Map<string, boolean>} */
50+
const map = new Map()
5151
/** @type {Array<string>} */
5252
const list = []
5353

5454
if (isNode(node)) {
5555
if (node.type !== 'element') throw new Error('Expected element node')
5656

57-
if (node.properties.className) {
58-
// @ts-expect-error Assume `classname` is `Array<string>`
57+
if (Array.isArray(node.properties.className)) {
5958
add(map, node.properties.className)
6059
}
6160

61+
// We’ll add to `list` later.
6262
node.properties.className = list
6363
} else {
6464
conditionals.unshift(node)
@@ -68,19 +68,16 @@ export const classnames =
6868
add(map, conditionals[index])
6969
}
7070

71-
/** @type {string} */
72-
let key
73-
74-
for (key in map) {
75-
if (map[key]) list.push(key)
71+
for (const [key, value] of map) {
72+
if (value) list.push(key)
7673
}
7774

7875
return isNode(node) ? node : list
7976
}
8077
)
8178

8279
/**
83-
* @param {ClassMap} result
80+
* @param {Map<string, boolean>} result
8481
* @param {Conditional} conditional
8582
*/
8683
function add(result, conditional) {
@@ -91,12 +88,12 @@ function add(result, conditional) {
9188
let list
9289

9390
if (typeof conditional === 'number') {
94-
result[conditional] = true
91+
result.set(String(conditional), true)
9592
} else if (typeof conditional === 'string') {
9693
list = parse(conditional)
9794

9895
while (++index < list.length) {
99-
result[list[index]] = true
96+
result.set(list[index], true)
10097
}
10198
} else if (conditional && typeof conditional === 'object') {
10299
if (Array.isArray(conditional)) {
@@ -106,15 +103,15 @@ function add(result, conditional) {
106103
} else {
107104
for (key in conditional) {
108105
if (own.call(conditional, key)) {
109-
result[key] = conditional[key]
106+
result.set(key, conditional[key])
110107
}
111108
}
112109
}
113110
}
114111
}
115112

116113
/**
117-
* @param {Nodes | Conditional} [value]
114+
* @param {Conditional | Nodes | null | undefined} value
118115
* @returns {value is Nodes}
119116
*/
120117
function isNode(value) {

readme.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ This function has two signatures, depending on whether a `node` was passed.
104104
###### Parameters
105105

106106
* `node` ([`Node`][node])
107-
— optionally, node whose classes to append to (should be
107+
— optionally, node whose classes to append to (must be
108108
[`Element`][element])
109109
* `conditionals` ([`Array<Conditional>`][conditional])
110110
— class configuration to merge
@@ -120,7 +120,7 @@ Basic class names (TypeScript type).
120120
###### Type
121121

122122
```ts
123-
type ConditionalPrimitive = string | number
123+
type ConditionalPrimitive = number | string
124124
```
125125
126126
### `ConditionalMap`
@@ -141,15 +141,15 @@ Different ways to turn class names on or off (TypeScript type).
141141
142142
```ts
143143
type Conditional =
144-
| null
145-
| undefined
146-
| ConditionalPrimitive
147-
| ConditionalMap
148144
| Array<
149-
| ConditionalPrimitive
150-
| ConditionalMap
151145
| Array<ConditionalPrimitive | ConditionalMap>
146+
| ConditionalMap
147+
| ConditionalPrimitive
152148
>
149+
| ConditionalMap
150+
| ConditionalPrimitive
151+
| null
152+
| undefined
153153
```
154154
155155
## Types

test.js

Lines changed: 71 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,89 @@
11
import assert from 'node:assert/strict'
22
import test from 'node:test'
3-
import {u} from 'unist-builder'
43
import {h} from 'hastscript'
4+
import {u} from 'unist-builder'
55
import {classnames} from './index.js'
6-
import * as mod from './index.js'
76

8-
test('classnames', () => {
9-
assert.deepEqual(
10-
Object.keys(mod).sort(),
11-
['classnames'],
12-
'should expose the public api'
13-
)
7+
test('classnames', async function (t) {
8+
await t.test('should expose the public api', async function () {
9+
assert.deepEqual(Object.keys(await import('./index.js')).sort(), [
10+
'classnames'
11+
])
12+
})
1413

15-
assert.throws(
16-
() => {
14+
await t.test('should ignore a given doctype', async function () {
15+
assert.throws(function () {
1716
classnames(u('comment', '?'))
18-
},
19-
/Expected element node/,
20-
'should ignore a given doctype'
21-
)
17+
}, /Expected element node/)
18+
})
2219

23-
assert.deepEqual(
24-
classnames(h('a'), 'alpha'),
25-
h('a.alpha'),
26-
'should support a string'
27-
)
20+
await t.test('should support a string', async function () {
21+
assert.deepEqual(classnames(h('a'), 'alpha'), h('a.alpha'))
22+
})
2823

29-
assert.deepEqual(
30-
classnames(h('a'), 'alpha bravo charlie'),
31-
h('a.alpha.bravo.charlie'),
32-
'should support a string (space-separated)'
33-
)
24+
await t.test('should support a string (space-separated)', async function () {
25+
assert.deepEqual(
26+
classnames(h('a'), 'alpha bravo charlie'),
27+
h('a.alpha.bravo.charlie')
28+
)
29+
})
3430

35-
assert.deepEqual(
36-
classnames(h('a'), 123),
37-
h('a.123'),
38-
'should support a number'
39-
)
31+
await t.test('should support a number', async function () {
32+
assert.deepEqual(classnames(h('a'), 123), h('a.123'))
33+
})
4034

41-
assert.deepEqual(
42-
classnames(h('a'), null, undefined, 2),
43-
h('a.2'),
44-
'should support (ignore) nullish values'
45-
)
35+
await t.test('should support (ignore) nullish values', async function () {
36+
assert.deepEqual(classnames(h('a'), null, undefined, 2), h('a.2'))
37+
})
4638

47-
assert.deepEqual(
48-
classnames(h('a'), {alpha: true, bravo: false, charlie: true}),
49-
h('a.alpha.charlie'),
50-
'should support an object'
51-
)
39+
await t.test('should support an object', async function () {
40+
assert.deepEqual(
41+
classnames(h('a'), {alpha: true, bravo: false, charlie: true}),
42+
h('a.alpha.charlie')
43+
)
44+
})
5245

53-
assert.deepEqual(
54-
classnames(h('a'), [
55-
'alpha',
56-
{bravo: true, charlie: false},
57-
['delta', 123]
58-
]),
59-
h('a.123.alpha.bravo.delta'),
60-
'should support an array'
61-
)
46+
await t.test('should support an array', async function () {
47+
assert.deepEqual(
48+
classnames(h('a'), [
49+
'alpha',
50+
{bravo: true, charlie: false},
51+
['delta', 123]
52+
]),
53+
h('a.alpha.bravo.delta.123')
54+
)
55+
})
6256

63-
assert.deepEqual(
64-
classnames(h('a'), ['alpha', 'bravo', {alpha: false, charlie: true}]),
65-
h('a.bravo.charlie'),
66-
'should dedupe'
67-
)
57+
await t.test('should dedupe', async function () {
58+
assert.deepEqual(
59+
classnames(h('a'), ['alpha', 'bravo', {alpha: false, charlie: true}]),
60+
h('a.bravo.charlie')
61+
)
62+
})
6863

69-
assert.deepEqual(
70-
classnames(h('a.alpha.bravo'), ['alpha', {alpha: true}]),
71-
h('a.alpha.bravo'),
72-
'should merge w/ current classnames'
73-
)
64+
await t.test('should merge w/ current classnames', async function () {
65+
assert.deepEqual(
66+
classnames(h('a.alpha.bravo'), ['alpha', {alpha: true}]),
67+
h('a.alpha.bravo')
68+
)
69+
})
7470

75-
assert.deepEqual(
76-
classnames(h('a'), 'alpha', {bravo: true, charlie: false}, ['delta', 123]),
77-
h('a.123.alpha.bravo.delta'),
78-
'should support multiple conditionals'
79-
)
71+
await t.test('should support multiple conditionals', async function () {
72+
assert.deepEqual(
73+
classnames(h('a'), 'alpha', {bravo: true, charlie: false}, [
74+
'delta',
75+
123
76+
]),
77+
h('a.alpha.bravo.delta.123')
78+
)
79+
})
8080

81-
assert.deepEqual(
82-
classnames('alpha', ['bravo', 123], {charlie: true}),
83-
['123', 'alpha', 'bravo', 'charlie'],
84-
'should return a list if w/o element'
85-
)
81+
await t.test('should return a list if w/o element', async function () {
82+
assert.deepEqual(classnames('alpha', ['bravo', 123], {charlie: true}), [
83+
'alpha',
84+
'bravo',
85+
'123',
86+
'charlie'
87+
])
88+
})
8689
})

0 commit comments

Comments
 (0)