Skip to content

Commit f03a8bc

Browse files
committed
Add support for automatic JSX runtime
1 parent 82bf759 commit f03a8bc

17 files changed

+431
-372
lines changed

index.d.ts

-45
This file was deleted.

index.js

+1-293
Original file line numberDiff line numberDiff line change
@@ -1,293 +1 @@
1-
/**
2-
* @typedef {import('hast').Root} HastRoot
3-
* @typedef {import('hast').Element} HastElement
4-
* @typedef {import('hast').Properties} Properties
5-
* @typedef {HastRoot['children'][number]} HastChild
6-
* @typedef {import('property-information').html['property'][string]} Info
7-
* @typedef {html|svg} Schema
8-
*/
9-
10-
/**
11-
* @typedef {string|number} HStyleValue
12-
* @typedef {Object.<string, HStyleValue>} HStyle
13-
* @typedef {string|number|boolean|null|undefined} HPrimitiveValue
14-
* @typedef {Array.<string|number>} HArrayValue
15-
* @typedef {HPrimitiveValue|HArrayValue} HPropertyValue
16-
* @typedef {{[property: string]: HPropertyValue|HStyle}} HProperties
17-
*
18-
* @typedef {string|number|null|undefined} HPrimitiveChild
19-
* @typedef {HastChild|HastRoot} HNodeChild
20-
* @typedef {Array.<HPrimitiveChild|HNodeChild>} HArrayChild
21-
* @typedef {HPrimitiveChild|HNodeChild|HArrayChild} HChild
22-
*/
23-
24-
import {html, svg, find, normalize} from 'property-information'
25-
import {parseSelector} from 'hast-util-parse-selector'
26-
import {parse as spaces} from 'space-separated-tokens'
27-
import {parse as commas} from 'comma-separated-tokens'
28-
import {svgCaseSensitiveTagNames} from './svg-case-sensitive-tag-names.js'
29-
30-
var buttonTypes = new Set(['menu', 'submit', 'reset', 'button'])
31-
32-
var own = {}.hasOwnProperty
33-
34-
export const h = factory(html, 'div')
35-
36-
export const s = factory(svg, 'g', svgCaseSensitiveTagNames)
37-
38-
/**
39-
* @param {Schema} schema
40-
* @param {string} defaultTagName
41-
* @param {Array.<string>} [caseSensitive]
42-
*/
43-
function factory(schema, defaultTagName, caseSensitive) {
44-
var adjust = caseSensitive && createAdjustMap(caseSensitive)
45-
46-
const h =
47-
/**
48-
* @type {{
49-
* (): HastRoot
50-
* (selector: null|undefined, ...children: HChild[]): HastRoot
51-
* (selector: string, properties: HProperties, ...children: HChild[]): HastElement
52-
* (selector: string, ...children: HChild[]): HastElement
53-
* }}
54-
*/
55-
(
56-
/**
57-
* Hyperscript compatible DSL for creating virtual hast trees.
58-
*
59-
* @param {string|null} [selector]
60-
* @param {HProperties|HChild} [properties]
61-
* @param {...HChild} [children]
62-
*/
63-
function (selector, properties, ...children) {
64-
var index = -1
65-
/** @type {HastRoot|HastElement} */
66-
var node
67-
/** @type {string} */
68-
var name
69-
/** @type {string} */
70-
var key
71-
72-
if (selector === undefined || selector === null) {
73-
node = {type: 'root', children: []}
74-
// @ts-ignore Properties are not supported for roots.
75-
children.unshift(properties)
76-
} else {
77-
node = parseSelector(selector, defaultTagName)
78-
// Normalize the name.
79-
name = node.tagName.toLowerCase()
80-
if (adjust && own.call(adjust, name)) name = adjust[name]
81-
node.tagName = name
82-
83-
// Handle props.
84-
if (isProperties(properties, name)) {
85-
for (key in properties) {
86-
if (own.call(properties, key)) {
87-
addProperty(schema, node.properties, key, properties[key])
88-
}
89-
}
90-
} else {
91-
children.unshift(properties)
92-
}
93-
}
94-
95-
// Handle children.
96-
while (++index < children.length) {
97-
addChild(node.children, children[index])
98-
}
99-
100-
if (name === 'template') {
101-
node.content = {type: 'root', children: node.children}
102-
node.children = []
103-
}
104-
105-
return node
106-
}
107-
)
108-
109-
return h
110-
}
111-
112-
/**
113-
* @param {HProperties|HChild} value
114-
* @param {string} name
115-
* @returns {value is HProperties}
116-
*/
117-
function isProperties(value, name) {
118-
if (
119-
value === null ||
120-
value === undefined ||
121-
typeof value !== 'object' ||
122-
Array.isArray(value)
123-
) {
124-
return false
125-
}
126-
127-
if (name === 'input' || !value.type || typeof value.type !== 'string') {
128-
return true
129-
}
130-
131-
if (Array.isArray(value.children)) {
132-
return false
133-
}
134-
135-
if (name === 'button') {
136-
return buttonTypes.has(value.type.toLowerCase())
137-
}
138-
139-
return !('value' in value)
140-
}
141-
142-
/**
143-
* @param {Schema} schema
144-
* @param {Properties} properties
145-
* @param {string} key
146-
* @param {HStyle|HPropertyValue} value
147-
* @returns {void}
148-
*/
149-
function addProperty(schema, properties, key, value) {
150-
var info = find(schema, key)
151-
var index = -1
152-
/** @type {HPropertyValue} */
153-
var result
154-
/** @type {Array.<string|number>} */
155-
var finalResult
156-
157-
// Ignore nullish and NaN values.
158-
if (value === undefined || value === null) return
159-
160-
if (typeof value === 'number') {
161-
// Ignore NaN.
162-
if (Number.isNaN(value)) return
163-
164-
result = value
165-
}
166-
// Booleans.
167-
else if (typeof value === 'boolean') {
168-
result = value
169-
}
170-
// Handle list values.
171-
else if (typeof value === 'string') {
172-
if (info.spaceSeparated) {
173-
result = spaces(value)
174-
} else if (info.commaSeparated) {
175-
result = commas(value)
176-
} else if (info.commaOrSpaceSeparated) {
177-
result = spaces(commas(value).join(' '))
178-
} else {
179-
result = parsePrimitive(info, info.property, value)
180-
}
181-
} else if (Array.isArray(value)) {
182-
result = value.concat()
183-
} else {
184-
result = info.property === 'style' ? style(value) : String(value)
185-
}
186-
187-
if (Array.isArray(result)) {
188-
finalResult = []
189-
190-
while (++index < result.length) {
191-
// @ts-ignore Assume no booleans in array.
192-
finalResult[index] = parsePrimitive(info, info.property, result[index])
193-
}
194-
195-
result = finalResult
196-
}
197-
198-
// Class names (which can be added both on the `selector` and here).
199-
if (info.property === 'className' && Array.isArray(properties.className)) {
200-
// @ts-ignore Assume no booleans in `className`.
201-
result = properties.className.concat(result)
202-
}
203-
204-
properties[info.property] = result
205-
}
206-
207-
/**
208-
* @param {Array.<HastChild>} nodes
209-
* @param {HChild} value
210-
* @returns {void}
211-
*/
212-
function addChild(nodes, value) {
213-
var index = -1
214-
215-
if (value === undefined || value === null) {
216-
// Empty.
217-
} else if (typeof value === 'string' || typeof value === 'number') {
218-
nodes.push({type: 'text', value: String(value)})
219-
} else if (Array.isArray(value)) {
220-
while (++index < value.length) {
221-
addChild(nodes, value[index])
222-
}
223-
} else if (typeof value === 'object' && 'type' in value) {
224-
if (value.type === 'root') {
225-
// @ts-ignore it looks like a root, TS…
226-
addChild(nodes, value.children)
227-
} else {
228-
nodes.push(value)
229-
}
230-
} else {
231-
throw new Error('Expected node, nodes, or string, got `' + value + '`')
232-
}
233-
}
234-
235-
/**
236-
* Parse a single primitives.
237-
*
238-
* @param {Info} info
239-
* @param {string} name
240-
* @param {HPrimitiveValue} value
241-
* @returns {HPrimitiveValue}
242-
*/
243-
function parsePrimitive(info, name, value) {
244-
if (typeof value === 'string') {
245-
if (info.number && value && !Number.isNaN(Number(value))) {
246-
return Number(value)
247-
}
248-
249-
if (
250-
(info.boolean || info.overloadedBoolean) &&
251-
(value === '' || normalize(value) === normalize(name))
252-
) {
253-
return true
254-
}
255-
}
256-
257-
return value
258-
}
259-
260-
/**
261-
* @param {HStyle} value
262-
* @returns {string}
263-
*/
264-
function style(value) {
265-
/** @type {Array.<string>} */
266-
var result = []
267-
/** @type {string} */
268-
var key
269-
270-
for (key in value) {
271-
if (own.call(value, key)) {
272-
result.push([key, value[key]].join(': '))
273-
}
274-
}
275-
276-
return result.join('; ')
277-
}
278-
279-
/**
280-
* @param {Array.<string>} values
281-
* @returns {Object.<string, string>}
282-
*/
283-
function createAdjustMap(values) {
284-
/** @type {Object.<string, string>} */
285-
var result = {}
286-
var index = -1
287-
288-
while (++index < values.length) {
289-
result[values[index].toLowerCase()] = values[index]
290-
}
291-
292-
return result
293-
}
1+
export {h, s} from './lib/index.js'

0 commit comments

Comments
 (0)