@ohos-ports/hast-to-hyperscript 10.0.1-beta.0

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 (5) hide show
  1. package/index.d.ts +38 -0
  2. package/index.js +337 -0
  3. package/license +22 -0
  4. package/package.json +116 -0
  5. package/readme.md +253 -0
package/index.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @template {CreateElementLike} H
3
+ * @param {H} h
4
+ * @param {Element|Root} tree
5
+ * @param {string|boolean|Options} [options]
6
+ * @returns {ReturnType<H>}
7
+ */
8
+ export function toH<H extends CreateElementLike>(
9
+ h: H,
10
+ tree: Element | Root,
11
+ options?: string | boolean | Options | undefined
12
+ ): ReturnType<H>
13
+ export type Element = import('hast').Element
14
+ export type Root = import('hast').Root
15
+ export type Text = import('hast').Text
16
+ export type AssertElement = import('unist-util-is').AssertPredicate<Element>
17
+ export type AssertText = import('unist-util-is').AssertPredicate<Text>
18
+ export type AssertRoot = import('unist-util-is').AssertPredicate<Root>
19
+ export type CreateElementLike = (
20
+ name: string,
21
+ attributes: any,
22
+ children?: any[] | undefined
23
+ ) => any
24
+ export type Context = {
25
+ schema:
26
+ | import('property-information/lib/util/schema').Schema
27
+ | import('property-information/lib/util/schema').Schema
28
+ prefix: string | null
29
+ key: number
30
+ react: boolean
31
+ vue: boolean
32
+ vdom: boolean
33
+ hyperscript: boolean
34
+ }
35
+ export type Options = {
36
+ prefix?: string | null | undefined
37
+ space?: 'html' | 'svg' | undefined
38
+ }
package/index.js ADDED
@@ -0,0 +1,337 @@
1
+ /**
2
+ * @typedef {import('hast').Element} Element
3
+ * @typedef {import('hast').Root} Root
4
+ * @typedef {import('hast').Text} Text
5
+ *
6
+ * @typedef {import('unist-util-is').AssertPredicate<Element>} AssertElement
7
+ * @typedef {import('unist-util-is').AssertPredicate<Text>} AssertText
8
+ * @typedef {import('unist-util-is').AssertPredicate<Root>} AssertRoot
9
+ *
10
+ * @callback CreateElementLike
11
+ * @param {string} name
12
+ * @param {any} attributes
13
+ * @param {Array.<string|any>} [children]
14
+ * @returns {any}
15
+ *
16
+ * @typedef Context
17
+ * @property {html|svg} schema
18
+ * @property {string|null} prefix
19
+ * @property {number} key
20
+ * @property {boolean} react
21
+ * @property {boolean} vue
22
+ * @property {boolean} vdom
23
+ * @property {boolean} hyperscript
24
+ *
25
+ * @typedef Options
26
+ * @property {string|null} [prefix]
27
+ * @property {'html'|'svg'} [space]
28
+ */
29
+
30
+ import {html, svg, find, hastToReact} from 'property-information'
31
+ import {stringify as spaces} from 'space-separated-tokens'
32
+ import {stringify as commas} from 'comma-separated-tokens'
33
+ import style from 'style-to-object'
34
+ import {webNamespaces} from 'web-namespaces'
35
+ import {convert} from 'unist-util-is'
36
+
37
+ const ns = /** @type {Record<string, string>} */ (webNamespaces)
38
+ const toReact = /** @type {Record<string, string>} */ (hastToReact)
39
+
40
+ const own = {}.hasOwnProperty
41
+
42
+ /** @type {AssertRoot} */
43
+ // @ts-expect-error it’s correct.
44
+ const root = convert('root')
45
+ /** @type {AssertElement} */
46
+ // @ts-expect-error it’s correct.
47
+ const element = convert('element')
48
+ /** @type {AssertText} */
49
+ // @ts-expect-error it’s correct.
50
+ const text = convert('text')
51
+
52
+ /**
53
+ * @template {CreateElementLike} H
54
+ * @param {H} h
55
+ * @param {Element|Root} tree
56
+ * @param {string|boolean|Options} [options]
57
+ * @returns {ReturnType<H>}
58
+ */
59
+ export function toH(h, tree, options) {
60
+ if (typeof h !== 'function') {
61
+ throw new TypeError('h is not a function')
62
+ }
63
+
64
+ const r = react(h)
65
+ const v = vue(h)
66
+ const vd = vdom(h)
67
+ /** @type {string|boolean|null|undefined} */
68
+ let prefix
69
+ /** @type {Element} */
70
+ let node
71
+
72
+ if (typeof options === 'string' || typeof options === 'boolean') {
73
+ prefix = options
74
+ options = {}
75
+ } else {
76
+ if (!options) options = {}
77
+ prefix = options.prefix
78
+ }
79
+
80
+ if (root(tree)) {
81
+ // @ts-expect-error Allow `doctypes` in there, we’ll filter them out later.
82
+ node =
83
+ tree.children.length === 1 && element(tree.children[0])
84
+ ? tree.children[0]
85
+ : {
86
+ type: 'element',
87
+ tagName: 'div',
88
+ properties: {},
89
+ children: tree.children
90
+ }
91
+ } else if (element(tree)) {
92
+ node = tree
93
+ } else {
94
+ throw new Error(
95
+ // @ts-expect-error runtime.
96
+ 'Expected root or element, not `' + ((tree && tree.type) || tree) + '`'
97
+ )
98
+ }
99
+
100
+ return transform(h, node, {
101
+ schema: options.space === 'svg' ? svg : html,
102
+ prefix:
103
+ prefix === undefined || prefix === null
104
+ ? r || v || vd
105
+ ? 'h-'
106
+ : null
107
+ : typeof prefix === 'string'
108
+ ? prefix
109
+ : prefix
110
+ ? 'h-'
111
+ : null,
112
+ key: 0,
113
+ react: r,
114
+ vue: v,
115
+ vdom: vd,
116
+ hyperscript: hyperscript(h)
117
+ })
118
+ }
119
+
120
+ /**
121
+ * Transform a hast node through a hyperscript interface to *anything*!
122
+ *
123
+ * @template {CreateElementLike} H
124
+ * @param {H} h
125
+ * @param {Element} node
126
+ * @param {Context} ctx
127
+ */
128
+ function transform(h, node, ctx) {
129
+ const parentSchema = ctx.schema
130
+ let schema = parentSchema
131
+ let name = node.tagName
132
+ /** @type {Record<string, unknown>} */
133
+ const attributes = {}
134
+ /** @type {Array.<ReturnType<H>|string>} */
135
+ const nodes = []
136
+ let index = -1
137
+ /** @type {string} */
138
+ let key
139
+
140
+ if (parentSchema.space === 'html' && name.toLowerCase() === 'svg') {
141
+ schema = svg
142
+ ctx.schema = schema
143
+ }
144
+
145
+ for (key in node.properties) {
146
+ if (node.properties && own.call(node.properties, key)) {
147
+ addAttribute(attributes, key, node.properties[key], ctx, name)
148
+ }
149
+ }
150
+
151
+ if (ctx.vdom) {
152
+ if (schema.space === 'html') {
153
+ name = name.toUpperCase()
154
+ } else if (schema.space) {
155
+ attributes.namespace = ns[schema.space]
156
+ }
157
+ }
158
+
159
+ if (ctx.prefix) {
160
+ ctx.key++
161
+ attributes.key = ctx.prefix + ctx.key
162
+ }
163
+
164
+ if (node.children) {
165
+ while (++index < node.children.length) {
166
+ const value = node.children[index]
167
+
168
+ if (element(value)) {
169
+ nodes.push(transform(h, value, ctx))
170
+ } else if (text(value)) {
171
+ nodes.push(value.value)
172
+ }
173
+ }
174
+ }
175
+
176
+ // Restore parent schema.
177
+ ctx.schema = parentSchema
178
+
179
+ // Ensure no React warnings are triggered for void elements having children
180
+ // passed in.
181
+ return nodes.length > 0
182
+ ? h.call(node, name, attributes, nodes)
183
+ : h.call(node, name, attributes)
184
+ }
185
+
186
+ /**
187
+ * @param {Record<string, unknown>} props
188
+ * @param {string} prop
189
+ * @param {unknown} value
190
+ * @param {Context} ctx
191
+ * @param {string} name
192
+ */
193
+ // eslint-disable-next-line complexity, max-params
194
+ function addAttribute(props, prop, value, ctx, name) {
195
+ const info = find(ctx.schema, prop)
196
+ /** @type {string|undefined} */
197
+ let subprop
198
+
199
+ // Ignore nullish and `NaN` values.
200
+ // Ignore `false` and falsey known booleans for hyperlike DSLs.
201
+ if (
202
+ value === undefined ||
203
+ value === null ||
204
+ (typeof value === 'number' && Number.isNaN(value)) ||
205
+ (value === false && (ctx.vue || ctx.vdom || ctx.hyperscript)) ||
206
+ (!value && info.boolean && (ctx.vue || ctx.vdom || ctx.hyperscript))
207
+ ) {
208
+ return
209
+ }
210
+
211
+ if (Array.isArray(value)) {
212
+ // Accept `array`.
213
+ // Most props are space-separated.
214
+ value = info.commaSeparated ? commas(value) : spaces(value)
215
+ }
216
+
217
+ // Treat `true` and truthy known booleans.
218
+ if (info.boolean && ctx.hyperscript) {
219
+ value = ''
220
+ }
221
+
222
+ // VDOM, Vue, and React accept `style` as object.
223
+ if (
224
+ info.property === 'style' &&
225
+ typeof value === 'string' &&
226
+ (ctx.react || ctx.vue || ctx.vdom)
227
+ ) {
228
+ value = parseStyle(value, name)
229
+ }
230
+
231
+ if (ctx.vue) {
232
+ if (info.property !== 'style') subprop = 'attrs'
233
+ } else if (!info.mustUseProperty) {
234
+ if (ctx.vdom) {
235
+ if (info.property !== 'style') subprop = 'attributes'
236
+ } else if (ctx.hyperscript) {
237
+ subprop = 'attrs'
238
+ }
239
+ }
240
+
241
+ if (subprop) {
242
+ props[subprop] = Object.assign(props[subprop] || {}, {
243
+ [info.attribute]: value
244
+ })
245
+ } else if (info.space && ctx.react) {
246
+ props[toReact[info.property] || info.property] = value
247
+ } else {
248
+ props[info.attribute] = value
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Check if `h` is `react.createElement`.
254
+ *
255
+ * @param {CreateElementLike} h
256
+ * @returns {boolean}
257
+ */
258
+ function react(h) {
259
+ /** @type {unknown} */
260
+ const node = h('div', {})
261
+ return Boolean(
262
+ node &&
263
+ // @ts-expect-error Looks like a React node.
264
+ ('_owner' in node || '_store' in node) &&
265
+ // @ts-expect-error Looks like a React node.
266
+ (node.key === undefined || node.key === null)
267
+ )
268
+ }
269
+
270
+ /**
271
+ * Check if `h` is `hyperscript`.
272
+ *
273
+ * @param {CreateElementLike} h
274
+ * @returns {boolean}
275
+ */
276
+ function hyperscript(h) {
277
+ return 'context' in h && 'cleanup' in h
278
+ }
279
+
280
+ /**
281
+ * Check if `h` is `virtual-dom/h`.
282
+ *
283
+ * @param {CreateElementLike} h
284
+ * @returns {boolean}
285
+ */
286
+ function vdom(h) {
287
+ /** @type {unknown} */
288
+ const node = h('div', {})
289
+ // @ts-expect-error Looks like a vnode.
290
+ return node.type === 'VirtualNode'
291
+ }
292
+
293
+ /**
294
+ * Check if `h` is Vue.
295
+ *
296
+ * @param {CreateElementLike} h
297
+ * @returns {boolean}
298
+ */
299
+ function vue(h) {
300
+ /** @type {unknown} */
301
+ const node = h('div', {})
302
+ // @ts-expect-error Looks like a Vue node.
303
+ return Boolean(node && node.context && node.context._isVue)
304
+ }
305
+
306
+ /**
307
+ * @param {string} value
308
+ * @param {string} tagName
309
+ * @returns {Record<string, string>}
310
+ */
311
+ function parseStyle(value, tagName) {
312
+ /** @type {Record<string, string>} */
313
+ const result = {}
314
+
315
+ try {
316
+ style(value, (name, value) => {
317
+ if (name.slice(0, 4) === '-ms-') name = 'ms-' + name.slice(4)
318
+
319
+ result[
320
+ name.replace(
321
+ /-([a-z])/g,
322
+ /**
323
+ * @param {string} _
324
+ * @param {string} $1
325
+ * @returns {string}
326
+ */ (_, $1) => $1.toUpperCase()
327
+ )
328
+ ] = value
329
+ })
330
+ } catch (error) {
331
+ error.message =
332
+ tagName + '[style]' + error.message.slice('undefined'.length)
333
+ throw error
334
+ }
335
+
336
+ return result
337
+ }
package/license ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2016 Titus Wormer <tituswormer@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/package.json ADDED
@@ -0,0 +1,116 @@
1
+ {
2
+ "name": "@ohos-ports/hast-to-hyperscript",
3
+ "version": "10.0.1-beta.0",
4
+ "description": "hast utility to transform to something else (react, vue, etc) through a hyperscript DSL",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "unist",
8
+ "hast",
9
+ "hast-util",
10
+ "util",
11
+ "utility",
12
+ "html",
13
+ "change",
14
+ "transform",
15
+ "rehype",
16
+ "vdom",
17
+ "virtual",
18
+ "dom",
19
+ "hyperscript",
20
+ "dsl"
21
+ ],
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/ohos-ports/ohos-ports.git",
25
+ "directory": "ports/hast-to-hyperscript/10.0.1"
26
+ },
27
+ "bugs": {
28
+ "url": "https://github.com/ohos-ports/ohos-ports/issues"
29
+ },
30
+ "funding": {
31
+ "type": "opencollective",
32
+ "url": "https://opencollective.com/unified"
33
+ },
34
+ "author": "Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)",
35
+ "contributors": [
36
+ "Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)",
37
+ "Jannis Redmann <mail@jannisr.de>",
38
+ "Koto Hajime <toxictoxer@gmail.com>",
39
+ "Christian Murphy <christian.murphy.42@gmail.com>"
40
+ ],
41
+ "sideEffects": false,
42
+ "type": "module",
43
+ "main": "index.js",
44
+ "types": "index.d.ts",
45
+ "files": [
46
+ "index.d.ts",
47
+ "index.js"
48
+ ],
49
+ "dependencies": {
50
+ "@types/unist": "^2.0.0",
51
+ "comma-separated-tokens": "^2.0.0",
52
+ "property-information": "^6.0.0",
53
+ "space-separated-tokens": "^2.0.0",
54
+ "style-to-object": "^0.3.0",
55
+ "unist-util-is": "^5.0.0",
56
+ "web-namespaces": "^2.0.0"
57
+ },
58
+ "devDependencies": {
59
+ "@types/hyperscript": "0.0.4",
60
+ "@types/react": "^17.0.0",
61
+ "@types/react-dom": "^17.0.0",
62
+ "@types/tape": "^4.0.0",
63
+ "@types/virtual-dom": "^2.0.0",
64
+ "c8": "^7.0.0",
65
+ "hyperscript": "^2.0.0",
66
+ "prettier": "^2.0.0",
67
+ "react": "^17.0.0",
68
+ "react-dom": "^17.0.0",
69
+ "rehype": "^11.0.0",
70
+ "remark-cli": "^9.0.0",
71
+ "remark-preset-wooorm": "^8.0.0",
72
+ "rimraf": "^3.0.0",
73
+ "tape": "^5.0.0",
74
+ "type-coverage": "^2.0.0",
75
+ "typescript": "^4.0.0",
76
+ "unist-builder": "^3.0.0",
77
+ "vdom-to-html": "^2.0.0",
78
+ "virtual-dom": "^2.0.0",
79
+ "vue": "^2.0.0",
80
+ "vue-server-renderer": "^2.0.0",
81
+ "xo": "^0.42.0"
82
+ },
83
+ "scripts": {
84
+ "prepack": "npm run build && npm run format",
85
+ "build": "rimraf \"*.d.ts\" && tsc && type-coverage",
86
+ "format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix",
87
+ "test-api": "node test.js",
88
+ "test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node test.js",
89
+ "test": "npm run build && npm run format && npm run test-coverage"
90
+ },
91
+ "prettier": {
92
+ "tabWidth": 2,
93
+ "useTabs": false,
94
+ "singleQuote": true,
95
+ "bracketSpacing": false,
96
+ "semi": false,
97
+ "trailingComma": "none"
98
+ },
99
+ "xo": {
100
+ "prettier": true
101
+ },
102
+ "remarkConfig": {
103
+ "plugins": [
104
+ "preset-wooorm"
105
+ ]
106
+ },
107
+ "typeCoverage": {
108
+ "atLeast": 100,
109
+ "detail": true,
110
+ "strict": true,
111
+ "ignoreCatch": true,
112
+ "ignoreFiles": [
113
+ "index.d.ts"
114
+ ]
115
+ }
116
+ }
package/readme.md ADDED
@@ -0,0 +1,253 @@
1
+ # hast-to-hyperscript
2
+
3
+ [![Build][build-badge]][build]
4
+ [![Coverage][coverage-badge]][coverage]
5
+ [![Downloads][downloads-badge]][downloads]
6
+ [![Size][size-badge]][size]
7
+ [![Sponsors][sponsors-badge]][collective]
8
+ [![Backers][backers-badge]][collective]
9
+ [![Chat][chat-badge]][chat]
10
+
11
+ [**hast**][hast] utility to transform a [*tree*][tree] to something else through
12
+ a [hyperscript][] interface.
13
+
14
+ ## Install
15
+
16
+ This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c):
17
+ Node 12+ is needed to use it and it must be `import`ed instead of `require`d.
18
+
19
+ [npm][]:
20
+
21
+ ```sh
22
+ npm install hast-to-hyperscript
23
+ ```
24
+
25
+ ## Use
26
+
27
+ ```js
28
+ import {toH} from 'hast-to-hyperscript'
29
+ import h from 'hyperscript'
30
+
31
+ const tree = {
32
+ type: 'element',
33
+ tagName: 'p',
34
+ properties: {id: 'alpha', className: ['bravo']},
35
+ children: [
36
+ {type: 'text', value: 'charlie '},
37
+ {
38
+ type: 'element',
39
+ tagName: 'strong',
40
+ properties: {style: 'color: red;'},
41
+ children: [{type: 'text', value: 'delta'}]
42
+ },
43
+ {type: 'text', value: ' echo.'}
44
+ ]
45
+ }
46
+
47
+ // Transform (`hyperscript` needs `outerHTML` to serialize):
48
+ const doc = toH(h, tree).outerHTML
49
+
50
+ console.log(doc)
51
+ ```
52
+
53
+ Yields:
54
+
55
+ ```html
56
+ <p class="bravo" id="alpha">charlie <strong>delta</strong> echo.</p>
57
+ ```
58
+
59
+ ## API
60
+
61
+ This package exports the following identifiers: `toH`.
62
+ There is no default export.
63
+
64
+ ### `toH(h, tree[, options|prefix])`
65
+
66
+ Transform a [**hast**][hast] [*tree*][tree] to something else through a
67
+ [hyperscript][] interface.
68
+
69
+ ###### Parameters
70
+
71
+ * `h` ([`Function`][h]) — Hyperscript function
72
+ * `tree` ([`Node`][node]) — [*Tree*][tree] to transform
73
+ * `prefix` — Treated as `{prefix: prefix}`
74
+ * `options.prefix` (`string` or `boolean`, optional)
75
+ — Prefix to use as a prefix for keys passed in `attrs` to `h()`,
76
+ this behavior is turned off by passing `false`, turned on by passing
77
+ a `string`.
78
+ By default, `h-` is used as a prefix if the given `h` is detected as being
79
+ `virtual-dom/h` or `React.createElement`
80
+ * `options.space` (enum, `'svg'` or `'html'`, default: `'html'`)
81
+ — Whether `node` is in the `'html'` or `'svg'` space.
82
+ If an `svg` element is found when inside the HTML space, `toH` automatically
83
+ switches to the SVG space when entering the element, and switches back when
84
+ exiting
85
+
86
+ ###### Returns
87
+
88
+ `*` — Anything returned by invoking `h()`.
89
+
90
+ ### `function h(name, attrs, children)`
91
+
92
+ Create an [*element*][element] from the given values.
93
+
94
+ ###### Content
95
+
96
+ `h` is called with the node that is currently compiled as the context object
97
+ (`this`).
98
+
99
+ ###### Parameters
100
+
101
+ * `name` (`string`) — Tag-name of element to create
102
+ * `attrs` (`Object.<string>`) — Attributes to set
103
+ * `children` (`Array.<* | string>`) — List of children (results of previously
104
+ invoking `h()`)
105
+
106
+ ###### Returns
107
+
108
+ `*` — Anything.
109
+
110
+ ##### Caveats
111
+
112
+ ###### Nodes
113
+
114
+ Most hyperscript implementations only support [*elements*][element] and
115
+ [*texts*][text].
116
+ [**hast**][hast] supports [*doctype*][doctype], [*comment*][comment], and
117
+ [*root*][root] as well.
118
+
119
+ * If anything other than an `element` or `root` node is given, `toH` throws
120
+ * If a [*root*][root] is given with no [*children*][child], an empty `div`
121
+ [*element*][element] is returned
122
+ * If a [*root*][root] is given with one [*element*][element] [*child*][child],
123
+ that element is transformed
124
+ * Otherwise, the children are wrapped in a `div` [*element*][element]
125
+
126
+ If unknown nodes (a node with a [*type*][type] not defined by [**hast**][hast])
127
+ are found as [*descendants*][descendant] of the given [*tree*][tree], they are
128
+ ignored: only [*text*][text] and [*element*][element] are transformed.
129
+
130
+ ###### Support
131
+
132
+ Although there are lots of libraries mentioning support for a hyperscript-like
133
+ interface, there are significant differences between them.
134
+ For example, [`hyperscript`][hyperscript] doesn’t support classes in `attrs` and
135
+ [`virtual-dom/h`][vdom] needs an `attributes` object inside `attrs` most of the
136
+ time.
137
+ `toH` works around these differences for:
138
+
139
+ * [`React.createElement`][react]
140
+ * Vue’s [`createElement`][vue]
141
+ * [`virtual-dom/h`][vdom]
142
+ * [`hyperscript`][hyperscript]
143
+
144
+ ## Security
145
+
146
+ Use of `hast-to-hyperscript` can open you up to a
147
+ [cross-site scripting (XSS)][xss] attack if the hast tree is unsafe.
148
+ Use [`hast-util-sanitize`][sanitize] to make the hast tree safe.
149
+
150
+ ## Related
151
+
152
+ * [`hastscript`][hastscript]
153
+ — Hyperscript compatible interface for creating nodes
154
+ * [`hast-util-sanitize`][sanitize]
155
+ — Sanitize nodes
156
+ * [`hast-util-from-dom`](https://github.com/syntax-tree/hast-util-from-dom)
157
+ — Transform a DOM tree to hast
158
+ * [`unist-builder`](https://github.com/syntax-tree/unist-builder)
159
+ — Create any unist tree
160
+ * [`xastscript`](https://github.com/syntax-tree/xastscript)
161
+ — Create a xast tree
162
+
163
+ ## Contribute
164
+
165
+ See [`contributing.md` in `syntax-tree/.github`][contributing] for ways to get
166
+ started.
167
+ See [`support.md`][support] for ways to get help.
168
+
169
+ This project has a [code of conduct][coc].
170
+ By interacting with this repository, organization, or community you agree to
171
+ abide by its terms.
172
+
173
+ ## License
174
+
175
+ [MIT][license] © [Titus Wormer][author]
176
+
177
+ <!-- Definitions -->
178
+
179
+ [build-badge]: https://github.com/syntax-tree/hast-to-hyperscript/workflows/main/badge.svg
180
+
181
+ [build]: https://github.com/syntax-tree/hast-to-hyperscript/actions
182
+
183
+ [coverage-badge]: https://img.shields.io/codecov/c/github/syntax-tree/hast-to-hyperscript.svg
184
+
185
+ [coverage]: https://codecov.io/github/syntax-tree/hast-to-hyperscript
186
+
187
+ [downloads-badge]: https://img.shields.io/npm/dm/hast-to-hyperscript.svg
188
+
189
+ [downloads]: https://www.npmjs.com/package/hast-to-hyperscript
190
+
191
+ [size-badge]: https://img.shields.io/bundlephobia/minzip/hast-to-hyperscript.svg
192
+
193
+ [size]: https://bundlephobia.com/result?p=hast-to-hyperscript
194
+
195
+ [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
196
+
197
+ [backers-badge]: https://opencollective.com/unified/backers/badge.svg
198
+
199
+ [collective]: https://opencollective.com/unified
200
+
201
+ [chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg
202
+
203
+ [chat]: https://github.com/syntax-tree/unist/discussions
204
+
205
+ [npm]: https://docs.npmjs.com/cli/install
206
+
207
+ [license]: license
208
+
209
+ [author]: https://wooorm.com
210
+
211
+ [contributing]: https://github.com/syntax-tree/.github/blob/HEAD/contributing.md
212
+
213
+ [support]: https://github.com/syntax-tree/.github/blob/HEAD/support.md
214
+
215
+ [coc]: https://github.com/syntax-tree/.github/blob/HEAD/code-of-conduct.md
216
+
217
+ [vdom]: https://github.com/Matt-Esch/virtual-dom/tree/HEAD/virtual-hyperscript
218
+
219
+ [hyperscript]: https://github.com/hyperhype/hyperscript
220
+
221
+ [react]: https://reactjs.org/docs/glossary.html#react-elements
222
+
223
+ [vue]: https://vuejs.org/v2/guide/render-function.html#createElement-Arguments
224
+
225
+ [hastscript]: https://github.com/syntax-tree/hastscript
226
+
227
+ [tree]: https://github.com/syntax-tree/unist#tree
228
+
229
+ [child]: https://github.com/syntax-tree/unist#child
230
+
231
+ [type]: https://github.com/syntax-tree/unist#type
232
+
233
+ [descendant]: https://github.com/syntax-tree/unist#descendant
234
+
235
+ [hast]: https://github.com/syntax-tree/hast
236
+
237
+ [node]: https://github.com/syntax-tree/hast#nodes
238
+
239
+ [text]: https://github.com/syntax-tree/hast#text
240
+
241
+ [doctype]: https://github.com/syntax-tree/hast#doctype
242
+
243
+ [root]: https://github.com/syntax-tree/hast#root
244
+
245
+ [comment]: https://github.com/syntax-tree/hast#comment
246
+
247
+ [element]: https://github.com/syntax-tree/hast#element
248
+
249
+ [h]: #function-hname-attrs-children
250
+
251
+ [xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
252
+
253
+ [sanitize]: https://github.com/syntax-tree/hast-util-sanitize