@jackens/nnn 2024.2.17 → 2024.2.20

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/chartable.d.ts CHANGED
@@ -2,30 +2,32 @@
2
2
  * A helper for creating a chart based on a table (conf. <https://jackens.github.io/nnn/chartable/>).
3
3
  *
4
4
  * Options:
5
- * - `bottom`: bottom padding (for X axis labels)
6
- * - `gapX`: X axis spacing
7
- * - `gapY`: Y axis spacing
8
- * - `headerColumn`: flag indicating that `table` has a header column (with X axis labels)
9
- * - `left`: left padding
10
- * - `maxY`: number of Y axis lines
11
- * - `reverse`: flag to reverse all data series
12
- * - `right`: right padding (for data series labels)
13
- * - `rotate`: flag to rotate X axis labels
14
5
  * - `table`: `HTMLTableElement` to extract data, data series labels and X axis labels
15
- * - `top`: top padding
6
+ * - `headerColumn`: flag indicating that `table` has a header column with X axis labels
7
+ * - `xGap`: X axis spacing
8
+ * - `xLabelsMinHeight`: minimal height of X axis labels
9
+ * - `xLabelsRotate`: flag to rotate X axis labels
10
+ * - `xReverse`: flag to reverse all data series
11
+ * - `yGap`: Y axis spacing
12
+ * - `yLabelsLeftMinWidth`: minimal width of Y axis left labels
13
+ * - `yLabelsRightMinWidth`: minimal width of Y axis right labels
14
+ * - `yMax`: number of Y axis lines
15
+ * - `zLabelsMinWidth`: minimal width of data series labels
16
+ * - `zyMappings`: mappings per data series
16
17
  */
17
- export function chartable({ bottom, gapX, gapY, headerColumn, left, maxY, reverse, right, rotate, table, top }: {
18
- bottom?: number;
19
- gapX?: number;
20
- gapY?: number;
21
- headerColumn?: boolean;
22
- left?: number;
23
- maxY?: number;
24
- reverse?: boolean;
25
- right?: number;
26
- rotate?: boolean;
18
+ export function chartable({ table, headerColumn, xGap, xLabelsMinHeight, xLabelsRotate, xReverse, yGap, yLabelsLeftMinWidth, yLabelsRightMinWidth, yMax, zLabelsMinWidth, zyMappings }: {
27
19
  table: HTMLTableElement;
28
- top?: number;
29
- }): Node;
20
+ headerColumn?: boolean | undefined;
21
+ xGap?: number | undefined;
22
+ xLabelsMinHeight?: number | undefined;
23
+ xLabelsRotate?: boolean | undefined;
24
+ xReverse?: boolean | undefined;
25
+ yGap?: number | undefined;
26
+ yLabelsLeftMinWidth?: number | undefined;
27
+ yLabelsRightMinWidth?: number | undefined;
28
+ yMax?: number | undefined;
29
+ zLabelsMinWidth?: number | undefined;
30
+ zyMappings?: [(label: string) => number, (value: number) => string][] | undefined;
31
+ }): SVGSVGElement;
30
32
 
31
33
  export const tests: {};
package/chartable.js CHANGED
@@ -1,50 +1,59 @@
1
- import { s } from './h.js'
1
+ import { h, s } from './h.js'
2
2
 
3
3
  const COLORS = ['#e22', '#e73', '#fc3', '#ad4', '#4d9', '#3be', '#45d', '#c3e']
4
4
  const PADDING = 15
5
5
 
6
+ const _svg = s('svg', { viewBox: '0 0 0 0', width: 0, height: 0 })
7
+
8
+ h(document.body, ['div', { $style: { width: 0, height: 0 } }, _svg])
9
+
10
+ const toFixed2 = (/** @type {number} */ value) => value.toFixed(2)
11
+
6
12
  /**
7
13
  * A helper for creating a chart based on a table (conf. <https://jackens.github.io/nnn/chartable/>).
8
14
  *
9
15
  * Options:
10
- * - `bottom`: bottom padding (for X axis labels)
11
- * - `gapX`: X axis spacing
12
- * - `gapY`: Y axis spacing
13
- * - `headerColumn`: flag indicating that `table` has a header column (with X axis labels)
14
- * - `left`: left padding
15
- * - `maxY`: number of Y axis lines
16
- * - `reverse`: flag to reverse all data series
17
- * - `right`: right padding (for data series labels)
18
- * - `rotate`: flag to rotate X axis labels
19
16
  * - `table`: `HTMLTableElement` to extract data, data series labels and X axis labels
20
- * - `top`: top padding
17
+ * - `headerColumn`: flag indicating that `table` has a header column with X axis labels
18
+ * - `xGap`: X axis spacing
19
+ * - `xLabelsMinHeight`: minimal height of X axis labels
20
+ * - `xLabelsRotate`: flag to rotate X axis labels
21
+ * - `xReverse`: flag to reverse all data series
22
+ * - `yGap`: Y axis spacing
23
+ * - `yLabelsLeftMinWidth`: minimal width of Y axis left labels
24
+ * - `yLabelsRightMinWidth`: minimal width of Y axis right labels
25
+ * - `yMax`: number of Y axis lines
26
+ * - `zLabelsMinWidth`: minimal width of data series labels
27
+ * - `zyMappings`: mappings per data series
21
28
  *
22
29
  * @param {{
23
- * bottom?: number;
24
- * gapX?: number;
25
- * gapY?: number;
26
- * headerColumn?: boolean;
27
- * left?: number;
28
- * maxY?: number;
29
- * reverse?: boolean;
30
- * right?: number;
31
- * rotate?: boolean;
32
30
  * table: HTMLTableElement;
33
- * top?: number;
31
+ * headerColumn?: boolean;
32
+ * xGap?: number;
33
+ * xLabelsMinHeight?: number;
34
+ * xLabelsRotate?: boolean;
35
+ * xReverse?: boolean;
36
+ * yGap?: number;
37
+ * yLabelsLeftMinWidth?: number;
38
+ * yLabelsRightMinWidth?: number;
39
+ * yMax?: number;
40
+ * zLabelsMinWidth?: number;
41
+ * zyMappings?: [(label: string) => number, (value: number) => string][];
34
42
  * }} options
35
43
  */
36
44
  export const chartable = ({
37
- bottom = 50,
38
- gapX = 70,
39
- gapY = 30,
40
- headerColumn = false,
41
- left = 300,
42
- maxY = 10,
43
- reverse = false,
44
- right = 100,
45
- rotate = false,
46
45
  table,
47
- top = PADDING
46
+ headerColumn = false,
47
+ xGap = 70,
48
+ xLabelsMinHeight = 0,
49
+ xLabelsRotate = false,
50
+ xReverse = false,
51
+ yGap = 30,
52
+ yLabelsLeftMinWidth = 100,
53
+ yLabelsRightMinWidth = 100,
54
+ yMax = 10,
55
+ zLabelsMinWidth = 0,
56
+ zyMappings = []
48
57
  }) => {
49
58
  const /** @type {number[][]} */ zxValues = []
50
59
  const /** @type {string[]} */ xLabels = []
@@ -59,7 +68,7 @@ export const chartable = ({
59
68
 
60
69
  if (x >= 0 && z >= 0) {
61
70
  zxValues[z] = zxValues[z] ?? []
62
- zxValues[z][x] = parseFloat(value)
71
+ zxValues[z][x] = (zyMappings?.[z]?.[0] ?? parseFloat)(value)
63
72
  } else if (x >= 0 && z < 0) {
64
73
  xLabels[x] = value
65
74
  } else if (x < 0 && z >= 0) {
@@ -67,92 +76,120 @@ export const chartable = ({
67
76
  }
68
77
  }))
69
78
 
70
- if (reverse) {
79
+ if (xReverse) {
71
80
  xLabels.reverse()
72
81
  zxValues.forEach(xValues => xValues.reverse())
73
82
  }
74
83
 
75
- const maxX = zxValues[0].length
76
- const xPx = Array.from({ length: maxX }, (_, x) => x * gapX)
77
- const yPx = Array.from({ length: maxY }, (_, y) => y * gapY)
78
- const width = gapX * (maxX - 1)
79
- const height = gapY * (maxY - 1)
80
- const svgW = left + width + right
81
- const svgH = top + height + bottom
84
+ const xMax = zxValues[0].length
85
+ const xPx = Array.from({ length: xMax }, (_, x) => x * xGap)
86
+ const yPx = Array.from({ length: yMax }, (_, y) => y * yGap)
82
87
 
83
- const /** @type {import('./h.js').HArgs1} */ gGraph = ['g', { transform: `translate(${left} ${top})` },
84
- ...yPx.map(px => ['line', { x1: 0, x2: width, y1: px, y2: px, stroke: '#8888' }]),
85
- ...xPx.map(px => ['line', { x1: px, x2: px, y1: 0, y2: height, stroke: '#8888' }])]
86
- const /** @type {import('./h.js').HArgs1} */ gZColors = ['g', { transform: `translate(${PADDING} ${top})` }]
87
- const /** @type {import('./h.js').HArgs1} */ gZLabels = ['g', { transform: `translate(${2 * PADDING} ${top})` }]
88
- const /** @type {import('./h.js').HArgs} */ svg = ['svg',
89
- { viewBox: `0 0 ${svgW} ${svgH}`, width: `${svgW}px`, height: `${svgH}px`, class: 'chartable' },
90
- gGraph, gZColors, gZLabels]
88
+ const width = xGap * (xMax - 1)
89
+ const height = yGap * (yMax - 1)
91
90
 
92
- if (xLabels.length > 0) {
93
- svg.push(['g', { transform: `translate(${left} ${top + height + PADDING})` },
94
- ...xPx.slice(0).map((xp, x) => ['text',
95
- rotate
96
- ? { x: 0, y: -xp, 'text-anchor': 'start', 'alignment-baseline': 'middle', transform: 'rotate(90)' }
97
- : { x: xp, y: PADDING, 'text-anchor': 'middle', 'alignment-baseline': 'middle' },
98
- xLabels[x]])])
91
+ const gGraph = s('g',
92
+ ...yPx.map(px => ['line', { x1: 0, x2: width, y1: px, y2: px, stroke: '#8888' }]),
93
+ ...xPx.map(px => ['line', { x1: px, x2: px, y1: 0, y2: height, stroke: '#8888' }]))
94
+ const gXLabels = s('g')
95
+ const gYLabelsL = zxValues.map(_ => s('g'))
96
+ const gYLabelsR = zxValues.map(_ => s('g'))
97
+ const gZColors = s('g')
98
+ const /** @type {SVGTextElement[]} */ gZLabels = []
99
+
100
+ const onclick = (/** @type {number} */ z) => {
101
+ gYLabelsL.forEach((g, z2) => s(g, { $style: { display: z2 === z ? 'block' : 'none' } }))
102
+ gYLabelsR.forEach((g, z2) => s(g, { $style: { display: z2 === z ? 'block' : 'none' } }))
103
+ gZLabels.forEach((text, z2) => s(text, { $style: { fontWeight: z2 === z ? 'bold' : 'normal', cursor: 'pointer' } }))
99
104
  }
100
105
 
101
- const /** @type {[SVGElement, SVGElement, SVGTextElement][]} */ toUpdate = []
102
-
103
- const onclick = (/** @type {number} */ z) => toUpdate.forEach(([gLeftYLabels, gRightYLabels, zLabel], z2) => {
104
- s(gLeftYLabels, { $style: { display: z2 === z ? 'block' : 'none' } })
105
- s(gRightYLabels, { $style: { display: z2 === z ? 'block' : 'none' } })
106
- s(zLabel, { $style: { textDecoration: z2 === z ? 'underline' : 'none', cursor: 'pointer' } })
107
- })
108
-
109
106
  zxValues.forEach((values, z) => {
110
107
  const fill = COLORS[z % COLORS.length]
111
108
  const minValue = Math.min(...values.filter(value => !isNaN(value)))
112
109
  const maxValue = Math.max(...values.filter(value => !isNaN(value)))
113
110
 
114
- const valuesPx = values.map(value => isNaN(value) ? value : height * (maxValue - value) / (maxValue - minValue))
111
+ yPx.forEach((yp, y) => {
112
+ const value = (zyMappings?.[z]?.[1] ?? toFixed2)(maxValue - (maxValue - minValue) / yMax * (y + 1))
113
+ const textL = s('text', { x: 0, y: yp, 'text-anchor': 'end', 'alignment-baseline': 'middle' }, value)
114
+ const textR = s('text', { x: 0, y: yp, 'text-anchor': 'start', 'alignment-baseline': 'middle' }, value)
115
115
 
116
- const gLeftYLabels = s('g', { transform: `translate(${left - PADDING} ${top})` },
117
- ...yPx.map((yp, y) => ['text',
118
- { x: 0, y: yp, 'text-anchor': 'end', 'alignment-baseline': 'middle' },
119
- (maxValue - (maxValue - minValue) / maxY * (y + 1)).toFixed(2)]))
116
+ s(_svg, textL, textR)
120
117
 
121
- const gRightYLabels = s('g', { transform: `translate(${left + width + PADDING} ${top})` },
122
- ...yPx.map((yp, y) => ['text',
123
- { x: 0, y: yp, 'text-anchor': 'start', 'alignment-baseline': 'middle' },
124
- (maxValue - (maxValue - minValue) / maxY * (y + 1)).toFixed(2)]))
118
+ yLabelsLeftMinWidth = Math.max(yLabelsLeftMinWidth, textL.getBBox().width)
119
+ yLabelsRightMinWidth = Math.max(yLabelsRightMinWidth, textR.getBBox().width)
125
120
 
126
- svg.push(gLeftYLabels, gRightYLabels)
121
+ s(gYLabelsL[z], textL)
122
+ s(gYLabelsR[z], textR)
123
+ })
127
124
 
128
- const zLabel = s('text', {
125
+ const text = s('text', {
129
126
  x: 0,
130
- y: gapY * (gZLabels.length - 2),
127
+ y: yGap * z,
131
128
  'text-anchor': 'start',
132
129
  'alignment-baseline': 'middle',
133
- $onclick: () => onclick(z)
130
+ $onclick: () => onclick(z),
131
+ $style: { fontWeight: 'bold' }
134
132
  },
135
133
  zLabels[z])
136
134
 
137
- gZLabels.push(zLabel)
138
- gZColors.push(['circle', { cx: 0, cy: gapY * (gZColors.length - 2), r: 5, fill }])
135
+ s(_svg, text)
139
136
 
140
- toUpdate.push([gLeftYLabels, gRightYLabels, zLabel])
137
+ zLabelsMinWidth = Math.max(zLabelsMinWidth, text.getBBox().width)
138
+
139
+ gZLabels[z] = text
140
+
141
+ s(gZColors, ['circle', { cx: 0, cy: yGap * z, r: 5, fill }])
142
+
143
+ const valuesPx = values.map(value => isNaN(value) ? value : height * (maxValue - value) / (maxValue - minValue))
141
144
 
142
145
  xPx.forEach((px, x) => {
143
146
  if (!isNaN(valuesPx[x])) {
144
- gGraph.push(['g', ['circle', { cx: px, cy: valuesPx[x], r: 5, fill }]])
147
+ s(gGraph, ['g', ['circle', { cx: px, cy: valuesPx[x], r: 5, fill }]])
145
148
 
146
149
  if (!isNaN(valuesPx[x - 1])) {
147
- gGraph.push(['line', { x1: px, x2: xPx[x - 1], y1: valuesPx[x], y2: valuesPx[x - 1], stroke: fill }])
150
+ s(gGraph, ['line', { x1: px, x2: xPx[x - 1], y1: valuesPx[x], y2: valuesPx[x - 1], stroke: fill }])
148
151
  }
149
152
  }
150
153
  })
151
154
  })
152
155
 
156
+ if (xLabels.length > 0) {
157
+ xPx.forEach((xp, x) => {
158
+ const text = s('text',
159
+ xLabelsRotate
160
+ ? { x: 0, y: -xp, 'text-anchor': 'start', 'alignment-baseline': 'middle', transform: 'rotate(90)' }
161
+ : { x: xp, y: PADDING, 'text-anchor': 'middle', 'alignment-baseline': 'middle' },
162
+ xLabels[x])
163
+
164
+ s(_svg, text)
165
+
166
+ xLabelsMinHeight = Math.max(xLabelsMinHeight, xLabelsRotate ? text.getBBox().width : text.getBBox().height)
167
+
168
+ s(gXLabels, text)
169
+ })
170
+ }
171
+
172
+ const svgW = width + yLabelsLeftMinWidth + yLabelsRightMinWidth + zLabelsMinWidth + 4 * PADDING
173
+ const svgH = height + xLabelsMinHeight + (xLabels.length > 0 ? 3 : 2) * PADDING
174
+
175
+ s(gGraph, { transform: `translate(${yLabelsLeftMinWidth + PADDING} ${PADDING})` })
176
+
177
+ gYLabelsL.forEach(g => s(g, { transform: `translate(${yLabelsLeftMinWidth} ${PADDING})` }))
178
+ gYLabelsR.forEach(g => s(g, { transform: `translate(${width + yLabelsLeftMinWidth + 2 * PADDING} ${PADDING})` }))
179
+
180
+ s(gZColors, { transform: `translate(${width + yLabelsLeftMinWidth + yLabelsRightMinWidth + 3 * PADDING} ${PADDING})` })
181
+ s(gXLabels, { transform: `translate(${yLabelsLeftMinWidth + PADDING} ${height + 2 * PADDING})` })
182
+
153
183
  onclick(0)
154
184
 
155
- return s(...svg)
185
+ return s('svg',
186
+ { viewBox: `0 0 ${svgW} ${svgH}`, width: `${svgW}px`, height: `${svgH}px`, class: 'chartable' },
187
+ gGraph,
188
+ gXLabels,
189
+ ...gYLabelsL,
190
+ ...gYLabelsR,
191
+ gZColors,
192
+ ['g', { transform: `translate(${width + yLabelsLeftMinWidth + yLabelsRightMinWidth + 4 * PADDING} ${PADDING})` }, ...gZLabels])
156
193
  }
157
194
 
158
195
  export const tests = {}
package/eq.d.ts CHANGED
@@ -4,5 +4,5 @@
4
4
  export function eq(x: any, y: any): boolean;
5
5
 
6
6
  export namespace tests {
7
- function eq(expect: import("bun:test").Expect): void;
7
+ function eq(expect: Chai.ExpectStatic): void;
8
8
  }
package/eq.js CHANGED
@@ -45,39 +45,39 @@ export const eq = /** @return {boolean} */ (/** @type {any} */ x, /** @type {any
45
45
  }
46
46
 
47
47
  export const tests = {
48
- eq: (/** @type {import('bun:test').Expect} */ expect) => {
49
- expect(eq(true, true)).toBe(true)
50
- expect(eq(NaN, NaN)).toBe(true)
51
- expect(eq(null, undefined)).toBe(false)
52
- expect(eq(42, 42)).toBe(true)
48
+ eq: (/** @type {import('chai').expect} */ expect) => {
49
+ expect(eq(true, true)).to.be.true
50
+ expect(eq(NaN, NaN)).to.be.true
51
+ expect(eq(null, undefined)).to.be.false
52
+ expect(eq(42, 42)).to.be.true
53
53
  // eslint-disable-next-line no-new-wrappers
54
- expect(eq(42, new Number(42))).toBe(true)
55
- expect(eq(42, Number(42))).toBe(true)
54
+ expect(eq(42, new Number(42))).to.be.true
55
+ expect(eq(42, Number(42))).to.be.true
56
56
  // eslint-disable-next-line no-new-wrappers
57
- expect(eq(new Number(42), Number(42))).toBe(true)
58
- expect(eq(42, '42')).toBe(false)
59
- expect(eq('42', '42')).toBe(true)
57
+ expect(eq(new Number(42), Number(42))).to.be.true
58
+ expect(eq(42, '42')).to.be.false
59
+ expect(eq('42', '42')).to.be.true
60
60
  // eslint-disable-next-line no-new-wrappers
61
- expect(eq('42', new String('42'))).toBe(true)
62
- expect(eq('42', String('42'))).toBe(true)
61
+ expect(eq('42', new String('42'))).to.be.true
62
+ expect(eq('42', String('42'))).to.be.true
63
63
  // eslint-disable-next-line no-new-wrappers
64
- expect(eq(String('42'), new String('42'))).toBe(true)
65
- expect(eq(/42/, /42/)).toBe(true)
66
- expect(eq(/42/, /42/g)).toBe(false)
67
- expect(eq(new Date(42), new Date(42))).toBe(true)
68
- expect(eq(new Date(), new Date(42))).toBe(false)
69
- expect(eq({ j: '42', c: 42 }, { c: 42, j: '42' })).toBe(true)
70
- expect(eq([42, '42'], [42, '42'])).toBe(true)
71
- expect(eq(new Set(['42', 42]), new Set([42, '42']))).toBe(true)
72
- expect(eq(new Set(['42', 42]), new Set([42]))).toBe(false)
73
- expect(eq(new Set([42, undefined]), new Set([42]))).toBe(false)
64
+ expect(eq(String('42'), new String('42'))).to.be.true
65
+ expect(eq(/42/, /42/)).to.be.true
66
+ expect(eq(/42/, /42/g)).to.be.false
67
+ expect(eq(new Date(42), new Date(42))).to.be.true
68
+ expect(eq(new Date(), new Date(42))).to.be.false
69
+ expect(eq({ j: '42', c: 42 }, { c: 42, j: '42' })).to.be.true
70
+ expect(eq([42, '42'], [42, '42'])).to.be.true
71
+ expect(eq(new Set(['42', 42]), new Set([42, '42']))).to.be.true
72
+ expect(eq(new Set(['42', 42]), new Set([42]))).to.be.false
73
+ expect(eq(new Set([42, undefined]), new Set([42]))).to.be.false
74
74
  expect(eq(
75
75
  new Map([[{ j: 42 }, { J: '42' }], [{ c: 42 }, { C: '42' }]]),
76
76
  new Map([[{ c: 42 }, { C: '42' }], [{ j: 42 }, { J: '42' }]])
77
- )).toBe(true)
77
+ )).to.be.true
78
78
  expect(eq(
79
79
  new Map([[{ j: 42 }, { J: '42' }], [{ c: 42 }, { C: '42' }]]),
80
80
  new Map([[{ j: '42' }, { J: 42 }], [{ c: '42' }, { C: 42 }]])
81
- )).toBe(false)
81
+ )).to.be.false
82
82
  }
83
83
  }
package/escape.d.ts CHANGED
@@ -14,5 +14,5 @@ export function escape(escapeMap: EscapeMap, template: TemplateStringsArray, ...
14
14
  export function escapeValues(escapeMap: EscapeMap, values: any[]): string[];
15
15
 
16
16
  export namespace tests {
17
- function escape(expect: import("bun:test").Expect): void;
17
+ function escape(expect: Chai.ExpectStatic): void;
18
18
  }
package/escape.js CHANGED
@@ -22,7 +22,7 @@ export const escape = (
22
22
  ) => String.raw(template, ...escapeValues(escapeMap, values))
23
23
 
24
24
  export const tests = {
25
- escape: (/** @type {import('bun:test').Expect} */ expect) => {
25
+ escape: (/** @type {import('chai').expect} */ expect) => {
26
26
  // @ts-expect-error
27
27
  const /** @type {EscapeMap} */ escapeMap = new Map([
28
28
  [undefined, () => 'NULL'],
@@ -46,6 +46,6 @@ export const tests = {
46
46
  FROM table_name
47
47
  WHERE column_name IN (b'1', NULL, NULL, 42, '42', '4''2', NULL, '1980-03-31 04:30:00')`
48
48
 
49
- expect(actual).toEqual(expected)
49
+ expect(actual).to.deep.equal(expected)
50
50
  }
51
51
  }
@@ -4,5 +4,5 @@
4
4
  export function fixTypography(node: Node): void;
5
5
 
6
6
  export namespace tests {
7
- function fixTypography(expect: import("bun:test").Expect): void;
7
+ function fixTypography(expect: Chai.ExpectStatic): void;
8
8
  }
package/fixTypography.js CHANGED
@@ -49,12 +49,12 @@ export const fixTypography = (/** @type {Node} */ node) => {
49
49
  }
50
50
 
51
51
  export const tests = {
52
- fixTypography: (/** @type {import('bun:test').Expect} */ expect) => {
52
+ fixTypography: (/** @type {import('chai').expect} */ expect) => {
53
53
  const p = h('p', 'Pchnąć w tę łódź jeża lub ośm skrzyń fig (zob. https://pl.wikipedia.org/wiki/Pangram).')
54
54
 
55
55
  fixTypography(p)
56
56
 
57
- expect(p.innerHTML).toEqual(
57
+ expect(p.innerHTML).to.deep.equal(
58
58
  'Pchnąć <span style="white-space:nowrap">w </span>tę łódź jeża lub ośm skrzyń fig ' +
59
59
  '(zob. https://\u200Bpl.\u200Bwikipedia.\u200Borg/\u200Bwiki/\u200BPangram).')
60
60
  }
package/h.d.ts CHANGED
@@ -47,9 +47,9 @@ export function s<N extends Node>(node: N, ...args1: HArgs1[]): N;
47
47
  export function s(tagOrNode: string | Node, ...args1: HArgs1[]): Node;
48
48
 
49
49
  export const tests: {
50
- h: (expect: import('bun:test').Expect) => void;
51
- 'h: innerText vs items': (expect: import('bun:test').Expect) => void;
52
- 'h: style': (expect: import('bun:test').Expect) => void;
53
- 'h: attributes vs properties': (expect: import('bun:test').Expect) => void;
54
- 'h: nested properties': (expect: import('bun:test').Expect) => void;
50
+ h: (expect: Chai.ExpectStatic) => void;
51
+ 'h: innerText vs items': (expect: Chai.ExpectStatic) => void;
52
+ 'h: style': (expect: Chai.ExpectStatic) => void;
53
+ 'h: attributes vs properties': (expect: Chai.ExpectStatic) => void;
54
+ 'h: nested properties': (expect: Chai.ExpectStatic) => void;
55
55
  };
package/h.js CHANGED
@@ -142,72 +142,72 @@ export const h = _h()
142
142
  export const s = _h('http://www.w3.org/2000/svg')
143
143
 
144
144
  export const tests = {
145
- h: (/** @type {import('bun:test').Expect} */ expect) => {
145
+ h: (/** @type {import('chai').expect} */ expect) => {
146
146
  const b = h('b')
147
147
 
148
- expect(b.outerHTML).toEqual('<b></b>')
148
+ expect(b.outerHTML).to.deep.equal('<b></b>')
149
149
 
150
150
  const i = h('i', 'text')
151
151
 
152
152
  h(b, i)
153
153
 
154
- expect(i.outerHTML).toEqual('<i>text</i>')
155
- expect(b.outerHTML).toEqual('<b><i>text</i></b>')
154
+ expect(i.outerHTML).to.deep.equal('<i>text</i>')
155
+ expect(b.outerHTML).to.deep.equal('<b><i>text</i></b>')
156
156
 
157
157
  h(i, { $className: 'some class' })
158
158
 
159
- expect(i.outerHTML).toEqual('<i class="some class">text</i>')
160
- expect(b.outerHTML).toEqual('<b><i class="some class">text</i></b>')
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
161
  },
162
162
 
163
- 'h: innerText vs items': (/** @type {import('bun:test').Expect} */ expect) => {
164
- expect(h('span', 'text').outerHTML).toEqual('<span>text</span>')
165
- expect(h('span', { $innerText: 'text' }).outerHTML).toEqual('<span>text</span>')
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
166
  },
167
167
 
168
- 'h: style': (/** @type {import('bun:test').Expect} */ expect) => {
168
+ 'h: style': (/** @type {import('chai').expect} */ expect) => {
169
169
  expect(h('div', { style: 'margin:0;padding:0' }).outerHTML)
170
- .toEqual('<div style="margin:0;padding:0"></div>')
170
+ .to.deep.equal('<div style="margin:0;padding:0"></div>')
171
171
  expect(h('div', { $style: 'margin:0;padding:0' }).outerHTML)
172
- .toEqual('<div style="margin: 0px; padding: 0px;"></div>')
172
+ .to.deep.equal('<div style="margin: 0px; padding: 0px;"></div>')
173
173
  expect(h('div', { $style: { margin: 0, padding: 0 } }).outerHTML)
174
- .toEqual('<div style="margin: 0px; padding: 0px;"></div>')
174
+ .to.deep.equal('<div style="margin: 0px; padding: 0px;"></div>')
175
175
  },
176
176
 
177
- 'h: attributes vs properties': (/** @type {import('bun:test').Expect} */ expect) => {
177
+ 'h: attributes vs properties': (/** @type {import('chai').expect} */ expect) => {
178
178
  const input1 = h('input', { value: 42 })
179
179
  const input2 = h('input', { $value: '42' })
180
180
 
181
- expect(input1.value).toEqual('42')
182
- expect(input2.value).toEqual('42')
181
+ expect(input1.value).to.deep.equal('42')
182
+ expect(input2.value).to.deep.equal('42')
183
183
 
184
- expect(input1.outerHTML).toEqual('<input value="42">')
185
- expect(input2.outerHTML).toEqual('<input>')
184
+ expect(input1.outerHTML).to.deep.equal('<input value="42">')
185
+ expect(input2.outerHTML).to.deep.equal('<input>')
186
186
 
187
187
  const checkbox1 = h('input', { type: 'checkbox', checked: true })
188
188
  const checkbox2 = h('input', { type: 'checkbox', $checked: true })
189
189
 
190
- expect(checkbox1.checked).toBe(true)
191
- expect(checkbox2.checked).toBe(true)
190
+ expect(checkbox1.checked).to.be.true
191
+ expect(checkbox2.checked).to.be.true
192
192
 
193
- expect(checkbox1.outerHTML).toEqual('<input type="checkbox" checked="">')
194
- expect(checkbox2.outerHTML).toEqual('<input type="checkbox">')
193
+ expect(checkbox1.outerHTML).to.deep.equal('<input type="checkbox" checked="">')
194
+ expect(checkbox2.outerHTML).to.deep.equal('<input type="checkbox">')
195
195
  },
196
196
 
197
- 'h: nested properties': (/** @type {import('bun:test').Expect} */ expect) => {
197
+ 'h: nested properties': (/** @type {import('chai').expect} */ expect) => {
198
198
  const div = h('div')
199
199
 
200
200
  // @ts-expect-error
201
- expect(div.key).toBeUndefined()
201
+ expect(div.key).to.be.undefined
202
202
 
203
203
  h(div, { $key: { one: 1 } })
204
204
 
205
205
  // @ts-expect-error
206
- expect(div.key).toEqual({ one: 1 })
206
+ expect(div.key).to.deep.equal({ one: 1 })
207
207
 
208
208
  h(div, { $key: { two: 2 } })
209
209
 
210
210
  // @ts-expect-error
211
- expect(div.key).toEqual({ one: 1, two: 2 })
211
+ expect(div.key).to.deep.equal({ one: 1, two: 2 })
212
212
  }
213
213
  }
package/has.d.ts CHANGED
@@ -4,6 +4,6 @@
4
4
  export function has(key: any, ref: any): boolean;
5
5
 
6
6
  export const tests: {
7
- has: (expect: import('bun:test').Expect) => void;
8
- 'has: null': (expect: import('bun:test').Expect) => void;
7
+ has: (expect: Chai.ExpectStatic) => void;
8
+ 'has: null': (expect: Chai.ExpectStatic) => void;
9
9
  };
package/has.js CHANGED
@@ -7,24 +7,24 @@ export const has = (/** @type {any} */ key, /** @type {any} */ ref) =>
7
7
  (is(String, key) || is(Number, key) || is(Symbol, key)) && Object.hasOwnProperty.call(ref ?? Object, key)
8
8
 
9
9
  export const tests = {
10
- has: (/** @type {import('bun:test').Expect} */ expect) => {
10
+ has: (/** @type {import('chai').expect} */ expect) => {
11
11
  const obj = { key: 'K', null: 'N' }
12
12
 
13
- expect('key' in obj).toBe(true)
14
- expect(has('key', obj)).toBe(true)
13
+ expect('key' in obj).to.be.true
14
+ expect(has('key', obj)).to.be.true
15
15
 
16
- expect('null' in obj).toBe(true)
17
- expect(has('null', obj)).toBe(true)
16
+ expect('null' in obj).to.be.true
17
+ expect(has('null', obj)).to.be.true
18
18
 
19
19
  // @ts-expect-error
20
- expect(null in obj).toBe(true)
21
- expect(has(null, obj)).toBe(false)
20
+ expect(null in obj).to.be.true
21
+ expect(has(null, obj)).to.be.false
22
22
 
23
- expect('toString' in obj).toBe(true)
24
- expect(has('toString', obj)).toBe(false)
23
+ expect('toString' in obj).to.be.true
24
+ expect(has('toString', obj)).to.be.false
25
25
  },
26
26
 
27
- 'has: null': (/** @type {import('bun:test').Expect} */ expect) => {
27
+ 'has: null': (/** @type {import('chai').expect} */ expect) => {
28
28
  let typeError
29
29
 
30
30
  try {
@@ -35,6 +35,6 @@ export const tests = {
35
35
  }
36
36
 
37
37
  expect(typeError instanceof TypeError) // Cannot use 'in' operator to search for 'key' in null
38
- expect(has('key', null)).toBe(false)
38
+ expect(has('key', null)).to.be.false
39
39
  }
40
40
  }
package/is.d.ts CHANGED
@@ -12,6 +12,6 @@ export const is: {
12
12
  };
13
13
 
14
14
  export const tests: {
15
- is: (expect: import('bun:test').Expect) => void;
16
- 'is: toString.call': (expect: import('bun:test').Expect) => void;
15
+ is: (expect: Chai.ExpectStatic) => void;
16
+ 'is: toString.call': (expect: Chai.ExpectStatic) => void;
17
17
  };