Skip to content
This repository was archived by the owner on Aug 9, 2023. It is now read-only.

Commit 206e762

Browse files
committed
Refactor code-style
* Add support for `null` as input in API types * Refactor some code * Add more docs to JSDoc
1 parent e081fda commit 206e762

File tree

3 files changed

+99
-54
lines changed

3 files changed

+99
-54
lines changed

lib/index.js

Lines changed: 82 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,50 @@
11
/**
2+
* @typedef {import('property-information').Schema} Schema
3+
* @typedef {import('hast').Content} Content
24
* @typedef {import('hast').Element} Element
35
* @typedef {import('hast').Root} Root
4-
* @typedef {import('hast').Text} Text
5-
* @typedef {import('hast').Root|import('hast').Content} Node
6+
*/
7+
8+
/**
9+
* @typedef {Root | Content} Node
610
*
711
* @callback CreateElementLike
12+
* Function that works somewhat like `React.createElement`.
813
* @param {string} name
14+
* Element name.
915
* @param {any} attributes
16+
* Properties.
1017
* @param {Array<any>} [children]
18+
* Children.
1119
* @returns {any}
20+
* Something.
1221
*
13-
* @typedef Context
14-
* @property {html|svg} schema
15-
* @property {string|null} prefix
22+
* @typedef State
23+
* Info passed around.
24+
* @property {Schema} schema
25+
* Current schema.
26+
* @property {string | undefined} prefix
27+
* Prefix to use.
1628
* @property {number} key
29+
* Current key.
1730
* @property {boolean} react
31+
* Looks like React.
1832
* @property {boolean} vue
33+
* Looks like Vue.
1934
* @property {boolean} vdom
35+
* Looks like vdom.
2036
* @property {boolean} hyperscript
37+
* Looks like `hyperscript`.
2138
*
2239
* @typedef Options
23-
* Configuration (optional).
24-
* @property {string|null} [prefix]
40+
* Configuration.
41+
* @property {string | null | undefined} [prefix]
2542
* Prefix to use as a prefix for keys passed in `props` to `h()`, this
2643
* behavior is turned off by passing `false` and turned on by passing a
2744
* `string`.
2845
* By default, `h-` is used as a prefix if the given `h` is detected as being
2946
* `virtual-dom/h` or `React.createElement`
30-
* @property {'html'|'svg'} [space]
47+
* @property {'html' | 'svg' | null | undefined} [space]
3148
* Whether `node` is in the `'html'` or `'svg'` space.
3249
* If an `<svg>` element is found when inside the HTML space, `toH`
3350
* automatically switches to the SVG space when entering the element, and
@@ -44,19 +61,19 @@ import {webNamespaces} from 'web-namespaces'
4461
/** @type {(value: string, replacer: ((key: string, value: string) => void)) => void} */
4562
const style = styleToObject
4663

47-
const toReact = /** @type {Record<string, string>} */ (hastToReact)
48-
4964
const own = {}.hasOwnProperty
5065

5166
/**
5267
* @template {CreateElementLike} H
68+
* Type of hyperscript function.
5369
* @param {H} h
5470
* HyperScript function.
5571
* @param {Node} tree
5672
* Tree to transform.
57-
* @param {string|boolean|Options} [options]
73+
* @param {string | boolean | Options | null | undefined} [options]
5874
* Configuration (optional).
5975
* @returns {ReturnType<H>}
76+
* Return type of the hyperscript function.
6077
*/
6178
// eslint-disable-next-line complexity
6279
export function toH(h, tree, options) {
@@ -106,12 +123,12 @@ export function toH(h, tree, options) {
106123
prefix === undefined || prefix === null
107124
? r || v || vd
108125
? 'h-'
109-
: null
126+
: undefined
110127
: typeof prefix === 'string'
111128
? prefix
112129
: prefix
113130
? 'h-'
114-
: null,
131+
: undefined,
115132
key: 0,
116133
react: r,
117134
vue: v,
@@ -124,12 +141,18 @@ export function toH(h, tree, options) {
124141
* Transform a hast node through a hyperscript interface to *anything*!
125142
*
126143
* @template {CreateElementLike} H
144+
* Type of hyperscript function.
127145
* @param {H} h
146+
* HyperScript function.
128147
* @param {Element} node
129-
* @param {Context} ctx
148+
* Node to transform.
149+
* @param {State} state
150+
* Info passed around.
151+
* @returns {ReturnType<H>}
152+
* Return type of the hyperscript function.
130153
*/
131-
function transform(h, node, ctx) {
132-
const parentSchema = ctx.schema
154+
function transform(h, node, state) {
155+
const parentSchema = state.schema
133156
let schema = parentSchema
134157
let name = node.tagName
135158
/** @type {Record<string, unknown>} */
@@ -142,42 +165,42 @@ function transform(h, node, ctx) {
142165

143166
if (parentSchema.space === 'html' && name.toLowerCase() === 'svg') {
144167
schema = svg
145-
ctx.schema = schema
168+
state.schema = schema
146169
}
147170

148171
for (key in node.properties) {
149172
if (node.properties && own.call(node.properties, key)) {
150-
addAttribute(attributes, key, node.properties[key], ctx, name)
173+
addAttribute(attributes, key, node.properties[key], state, name)
151174
}
152175
}
153176

154-
if (ctx.vdom) {
177+
if (state.vdom) {
155178
if (schema.space === 'html') {
156179
name = name.toUpperCase()
157180
} else if (schema.space) {
158181
attributes.namespace = webNamespaces[schema.space]
159182
}
160183
}
161184

162-
if (ctx.prefix) {
163-
ctx.key++
164-
attributes.key = ctx.prefix + ctx.key
185+
if (state.prefix) {
186+
state.key++
187+
attributes.key = state.prefix + state.key
165188
}
166189

167190
if (node.children) {
168191
while (++index < node.children.length) {
169192
const value = node.children[index]
170193

171194
if (value.type === 'element') {
172-
nodes.push(transform(h, value, ctx))
195+
nodes.push(transform(h, value, state))
173196
} else if (value.type === 'text') {
174197
nodes.push(value.value)
175198
}
176199
}
177200
}
178201

179202
// Restore parent schema.
180-
ctx.schema = parentSchema
203+
state.schema = parentSchema
181204

182205
// Ensure no React warnings are triggered for void elements having children
183206
// passed in.
@@ -187,16 +210,25 @@ function transform(h, node, ctx) {
187210
}
188211

189212
/**
213+
* Add an attribute to `props`.
214+
*
190215
* @param {Record<string, unknown>} props
216+
* Map.
191217
* @param {string} prop
218+
* Key.
192219
* @param {unknown} value
193-
* @param {Context} ctx
220+
* Value.
221+
* @param {State} state
222+
* Info passed around.
194223
* @param {string} name
224+
* Element name.
225+
* @returns {void}
226+
* Nothing.
195227
*/
196228
// eslint-disable-next-line complexity, max-params
197-
function addAttribute(props, prop, value, ctx, name) {
198-
const info = find(ctx.schema, prop)
199-
/** @type {string|undefined} */
229+
function addAttribute(props, prop, value, state, name) {
230+
const info = find(state.schema, prop)
231+
/** @type {string | undefined} */
200232
let subprop
201233

202234
// Ignore nullish and `NaN` values.
@@ -205,8 +237,8 @@ function addAttribute(props, prop, value, ctx, name) {
205237
value === undefined ||
206238
value === null ||
207239
(typeof value === 'number' && Number.isNaN(value)) ||
208-
(value === false && (ctx.vue || ctx.vdom || ctx.hyperscript)) ||
209-
(!value && info.boolean && (ctx.vue || ctx.vdom || ctx.hyperscript))
240+
(value === false && (state.vue || state.vdom || state.hyperscript)) ||
241+
(!value && info.boolean && (state.vue || state.vdom || state.hyperscript))
210242
) {
211243
return
212244
}
@@ -218,28 +250,28 @@ function addAttribute(props, prop, value, ctx, name) {
218250
}
219251

220252
// Treat `true` and truthy known booleans.
221-
if (info.boolean && ctx.hyperscript) {
253+
if (info.boolean && state.hyperscript) {
222254
value = ''
223255
}
224256

225257
// VDOM, Vue, and React accept `style` as object.
226258
if (
227259
info.property === 'style' &&
228260
typeof value === 'string' &&
229-
(ctx.react || ctx.vue || ctx.vdom)
261+
(state.react || state.vue || state.vdom)
230262
) {
231263
value = parseStyle(value, name)
232264
}
233265

234266
// Vue 3 (used in our tests) doesn’t need this anymore.
235267
// Some major in the future we can drop Vue 2 support.
236268
/* c8 ignore next 2 */
237-
if (ctx.vue) {
269+
if (state.vue) {
238270
if (info.property !== 'style') subprop = 'attrs'
239271
} else if (!info.mustUseProperty) {
240-
if (ctx.vdom) {
272+
if (state.vdom) {
241273
if (info.property !== 'style') subprop = 'attributes'
242-
} else if (ctx.hyperscript) {
274+
} else if (state.hyperscript) {
243275
subprop = 'attrs'
244276
}
245277
}
@@ -248,8 +280,8 @@ function addAttribute(props, prop, value, ctx, name) {
248280
props[subprop] = Object.assign(props[subprop] || {}, {
249281
[info.attribute]: value
250282
})
251-
} else if (info.space && ctx.react) {
252-
props[toReact[info.property] || info.property] = value
283+
} else if (info.space && state.react) {
284+
props[hastToReact[info.property] || info.property] = value
253285
} else {
254286
props[info.attribute] = value
255287
}
@@ -259,7 +291,9 @@ function addAttribute(props, prop, value, ctx, name) {
259291
* Check if `h` is `react.createElement`.
260292
*
261293
* @param {CreateElementLike} h
294+
* HyperScript function.
262295
* @returns {boolean}
296+
* Looks like React.
263297
*/
264298
function react(h) {
265299
const node = /** @type {unknown} */ (h('div', {}))
@@ -276,7 +310,9 @@ function react(h) {
276310
* Check if `h` is `hyperscript`.
277311
*
278312
* @param {CreateElementLike} h
313+
* HyperScript function.
279314
* @returns {boolean}
315+
* Looks like `hyperscript`.
280316
*/
281317
function hyperscript(h) {
282318
return 'context' in h && 'cleanup' in h
@@ -286,7 +322,9 @@ function hyperscript(h) {
286322
* Check if `h` is `virtual-dom/h`.
287323
*
288324
* @param {CreateElementLike} h
325+
* HyperScript function.
289326
* @returns {boolean}
327+
* Looks like `virtual-dom`
290328
*/
291329
function vdom(h) {
292330
const node = /** @type {unknown} */ (h('div', {}))
@@ -298,7 +336,9 @@ function vdom(h) {
298336
* Check if `h` is Vue.
299337
*
300338
* @param {CreateElementLike} h
339+
* HyperScript function.
301340
* @returns {boolean}
341+
* Looks like Vue.
302342
*/
303343
function vue(h) {
304344
// Vue 3 (used in our tests) doesn’t need this anymore.
@@ -310,9 +350,14 @@ function vue(h) {
310350
}
311351

312352
/**
353+
* Parse a declaration into an object.
354+
*
313355
* @param {string} value
356+
* CSS declarations.
314357
* @param {string} tagName
358+
* Tag name.
315359
* @returns {Record<string, string>}
360+
* Properties.
316361
*/
317362
function parseStyle(value, tagName) {
318363
/** @type {Record<string, string>} */

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@
5656
"@types/tape": "^4.0.0",
5757
"@types/virtual-dom": "^2.0.0",
5858
"c8": "^7.0.0",
59+
"hast-util-from-html": "^1.0.0",
5960
"hyperscript": "^2.0.0",
6061
"prettier": "^2.0.0",
6162
"react": "^18.0.0",
6263
"react-dom": "^18.0.0",
63-
"rehype": "^12.0.0",
6464
"remark-cli": "^11.0.0",
6565
"remark-preset-wooorm": "^9.0.0",
6666
"tape": "^5.0.0",

0 commit comments

Comments
 (0)