Skip to content

Commit a7bf98b

Browse files
committed
Add tons of examples to verify frameworks work
1 parent 7dac6c4 commit a7bf98b

15 files changed

+519
-15
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44
coverage/
55
node_modules/
66
yarn.lock
7+
example/hast-util-to-jsx-runtime.min.js
78
!lib/components.d.ts

.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
coverage/
2+
example/hast-util-to-jsx-runtime.min.js
23
*.html
34
*.md

example/create-tree.js

+200
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/**
2+
* Generate a hast tree for checking.
3+
*
4+
* > 👉 **Note**: this file is actual ESM that runs in browsers.
5+
*/
6+
7+
/* eslint-env browser */
8+
9+
// @ts-expect-error: hush.
10+
import * as hastscript from 'https://esm.sh/hastscript@7?dev'
11+
12+
/** @type {typeof import('hastscript').h} */
13+
const h = hastscript.h
14+
/** @type {typeof import('hastscript').s} */
15+
const s = hastscript.s
16+
17+
export function createTree() {
18+
return h('div', [
19+
h('p', [
20+
'note: to show that state is kept, this is rerendered every second, it’s now ',
21+
h('b', new Date().toLocaleString()),
22+
'!'
23+
]),
24+
h('hr'),
25+
h('h2', 'Event handlers'),
26+
h('p', [
27+
'You should be able to click on this and print something to the console.'
28+
]),
29+
h('button', {onClick: 'console.log("it worked!")'}, 'Print to console'),
30+
h('hr'),
31+
h('h2', 'Inputs with control'),
32+
h('p', ['You should be able to change this text input:']),
33+
h('div', [
34+
h('input#text-a', {type: 'text', value: 'Some text?'}),
35+
h('label', {htmlFor: 'text-a'}, 'Text input')
36+
]),
37+
h('hr'),
38+
h('p', ['You should be able to change this range input:']),
39+
h('div', [
40+
h('input#range-a', {type: 'range', value: 5, min: 0, max: 10}),
41+
h('label', {htmlFor: 'range-a'}, 'Range input')
42+
]),
43+
h('hr'),
44+
h('p', ['You should be able to change this radio group:']),
45+
h('div', [
46+
h('input#radio-a', {
47+
type: 'radio',
48+
name: 'radios',
49+
value: 'a',
50+
checked: true
51+
}),
52+
h('label', {htmlFor: 'radio-a'}, 'Alpha'),
53+
h('input#radio-b', {type: 'radio', name: 'radios', value: 'b'}),
54+
h('label', {htmlFor: 'radio-b'}, 'Bravo'),
55+
h('input#radio-c', {type: 'radio', name: 'radios', value: 'c'}),
56+
h('label', {htmlFor: 'radio-c'}, 'Charlie')
57+
]),
58+
h('hr'),
59+
h('h2', 'Style attribute'),
60+
h(
61+
'p',
62+
{style: {color: '#0366d6'}},
63+
'is this blue? Then style objects work'
64+
),
65+
h('p', {style: 'color: #0366d6'}, 'is this blue? Then style strings work'),
66+
h(
67+
'p',
68+
{style: '-webkit-transform: rotate(0.01turn)'},
69+
'is this tilted in webkit? Then vendor prefixes in style strings work'
70+
),
71+
h(
72+
'p',
73+
{style: {'-webkit-transform': 'rotate(0.01turn)'}},
74+
'is this tilted in webkit? Then prefixes in style objects work'
75+
),
76+
h(
77+
'p',
78+
{style: {WebkitTransform: 'rotate(0.01turn)'}},
79+
'is this tilted in webkit? Then camelcased in style objects work'
80+
),
81+
h(
82+
'p',
83+
{
84+
style:
85+
'display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2'
86+
},
87+
'This should be capped at 2 lines in webkit! Lorem ipsum dolor sit amet consectetur adipisicing elit. Temporibus natus similique eum. Dolorem est at aliquam, explicabo similique repudiandae veritatis? Eum aliquam hic eaque tenetur, enim ex odio voluptatum repellendus!'
88+
),
89+
h(
90+
'p',
91+
{style: '--fg: #0366d6; color: var(--fg)'},
92+
'Is this blue? Then CSS variables work.'
93+
),
94+
h('h2', 'SVG: camel- and dash-cased attributes'),
95+
h('p', [
96+
'You should see two bright blue circles, the second skewed. ',
97+
'This checks that the ',
98+
h('code', 'gradientUnits'),
99+
' attribute (camel case), ',
100+
h('code', 'gradientTransform'),
101+
' attribute (camel case), and ',
102+
h('code', 'stop-color'),
103+
' attribute (dash case), all work. ',
104+
'It also checks that the ',
105+
h('code', 'radialGradient'),
106+
' element (camel case) works.'
107+
]),
108+
// Example based on <https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/gradientTransform>
109+
s('svg', {viewBox: '0 0 420 200', xmlns: 'http://www.w3.org/2000/svg'}, [
110+
s(
111+
'radialGradient#gradient-a',
112+
{gradientUnits: 'userSpaceOnUse', cx: 100, cy: 100, r: 100},
113+
[
114+
s('stop', {offset: '50%', stopColor: '#0366d6'}),
115+
s('stop', {offset: '50.1%', stopColor: 'transparent'})
116+
]
117+
),
118+
s(
119+
'radialGradient#gradient-b',
120+
{
121+
gradientUnits: 'userSpaceOnUse',
122+
cx: 100,
123+
cy: 100,
124+
r: 100,
125+
gradientTransform: 'skewX(25) translate(-50, 0)'
126+
},
127+
[
128+
s('stop', {offset: '50%', stopColor: '#0366d6'}),
129+
s('stop', {offset: '50.1%', stopColor: 'transparent'})
130+
]
131+
),
132+
s('rect', {
133+
x: 0,
134+
y: 0,
135+
width: 200,
136+
height: 200,
137+
fill: 'url(#gradient-a)'
138+
}),
139+
s('rect', {
140+
x: 0,
141+
y: 0,
142+
width: 200,
143+
height: 200,
144+
fill: 'url(#gradient-b)',
145+
style: {transform: 'translateX(220px)'}
146+
})
147+
]),
148+
h('h2', 'xlink:href'),
149+
h('p', [
150+
'You should see one big circle broken down over four squares. ',
151+
'The top right square is different, it instead contains one small circle. ',
152+
'This checks that the ',
153+
h('code', 'clipPathUnits'),
154+
' attribute (camel case), ',
155+
h('code', 'clip-path'),
156+
' attribute (dash case), and',
157+
h('code', 'clipPath'),
158+
' element (camel case), all work. ',
159+
'Importantly, it also checks for ',
160+
h('code', 'xlink:href'),
161+
'!'
162+
]),
163+
// Example from <https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/clipPathUnits>
164+
s('svg', {viewBox: '0 0 100 100'}, [
165+
s('clipPath#clip-a', {clipPathUnits: 'userSpaceOnUse'}, [
166+
s('circle', {cx: 50, cy: 50, r: 35})
167+
]),
168+
s('clipPath#clip-b', {clipPathUnits: 'objectBoundingBox'}, [
169+
s('circle', {cx: 0.5, cy: 0.5, r: 0.35})
170+
]),
171+
s('rect#rect-a', {x: 0, y: 0, width: 45, height: 45}),
172+
s('rect#rect-b', {x: 0, y: 55, width: 45, height: 45}),
173+
s('rect#rect-c', {x: 55, y: 55, width: 45, height: 45}),
174+
s('rect#rect-d', {x: 55, y: 0, width: 45, height: 45}),
175+
s('use', {
176+
clipPath: 'url(#clip-a)',
177+
xLinkHref: '#rect-a',
178+
fill: '#0366d6'
179+
}),
180+
s('use', {
181+
clipPath: 'url(#clip-a)',
182+
xLinkHref: '#rect-b',
183+
fill: '#0366d6'
184+
}),
185+
s('use', {
186+
clipPath: 'url(#clip-a)',
187+
xLinkHref: '#rect-c',
188+
fill: '#0366d6'
189+
}),
190+
s('use', {
191+
clipPath: 'url(#clip-b)',
192+
xLinkHref: '#rect-d',
193+
fill: '#0366d6'
194+
})
195+
]),
196+
h('h2', 'xml:lang'),
197+
h('style', ':lang(fr) { color: #0366d6; }'),
198+
h('p', {xmlLang: 'fr'}, "C'est bleu ? Ensuite ça marche")
199+
])
200+
}

example/index.css

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* Style the examples.
3+
*/
4+
5+
:root {
6+
color-scheme: light dark;
7+
background-color: hsl(0, 0%, 90%);
8+
}
9+
10+
* {
11+
line-height: calc(1em + 1ex);
12+
box-sizing: border-box;
13+
}
14+
15+
a {
16+
color: #0367d8;
17+
}
18+
19+
body {
20+
font-family: system-ui;
21+
margin: 3em auto;
22+
max-width: 30em;
23+
}
24+
25+
input {
26+
font: inherit;
27+
}
28+
29+
code {
30+
font-family: 'San Francisco Mono', 'Monaco', 'Consolas', 'Lucida Console',
31+
'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
32+
font-feature-settings: normal;
33+
font-size: smaller;
34+
background-color: rgba(0, 0, 0, 0.04);
35+
border-radius: 3px;
36+
padding: 0.2em 0.4em;
37+
}
38+
39+
@media (prefers-color-scheme: dark) {
40+
:root {
41+
background-color: hsl(214, 13%, 10%);
42+
color: hsl(214, 13%, 90%);
43+
}
44+
45+
code {
46+
background-color: rgba(0, 0, 0, 0.4);
47+
}
48+
}

example/index.html

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang=en>
3+
<meta charset=utf8>
4+
<title>hast-util-to-jsx-runtime</title>
5+
<link rel=stylesheet href=index.css />
6+
<h1><code>hast-util-to-jsx-runtime</code></h1>
7+
<p>See the following examples to check how different frameworks work:
8+
<ol>
9+
<li><a href=react.html>React</a>
10+
<li><a href=preact.html>preact</a>
11+
<li><a href=solid.html>Solid</a>
12+
<li><a href=svelte.html>Svelte</a>
13+
<li><a href=vue.html>Vue</a>

example/preact.html

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<!doctype html>
2+
<html lang=en>
3+
<meta charset=utf8>
4+
<title>preact + hast-util-to-jsx-runtime</title>
5+
<link rel=stylesheet href=index.css />
6+
<h1><code>preact</code> + <code>hast-util-to-jsx-runtime</code></h1>
7+
<p style="color:green">Note! This example is dynamic!</p>
8+
<div id=root></div>
9+
<script type=module>
10+
/* eslint-env browser */
11+
import {Fragment, jsx, jsxs} from 'https://esm.sh/preact@10/jsx-runtime?dev'
12+
import {render} from 'https://esm.sh/preact@10?dev'
13+
import {toJsxRuntime} from './hast-util-to-jsx-runtime.min.js'
14+
import {createTree} from './create-tree.js'
15+
16+
rerender()
17+
18+
function rerender() {
19+
render(
20+
toJsxRuntime(createTree(), {Fragment, jsx, jsxs, elementAttributeNameCase: 'html'}),
21+
document.getElementById('root')
22+
)
23+
setTimeout(rerender, 1000)
24+
}
25+
</script>

example/react.html

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!doctype html>
2+
<html lang=en>
3+
<meta charset=utf8>
4+
<title>React + hast-util-to-jsx-runtime</title>
5+
<link rel=stylesheet href=index.css />
6+
<h1><code>React</code> + <code>hast-util-to-jsx-runtime</code></h1>
7+
<p style="color:green">Note! This example is dynamic!</p>
8+
<div id=root></div>
9+
<script type=module>
10+
/* eslint-env browser */
11+
import {Fragment, jsx, jsxs} from 'https://esm.sh/react@18/jsx-runtime?dev'
12+
import React from 'https://esm.sh/react@18?dev'
13+
import ReactDom from 'https://esm.sh/react-dom@18/client?dev'
14+
import {toJsxRuntime} from './hast-util-to-jsx-runtime.min.js'
15+
import {createTree} from './create-tree.js'
16+
17+
const root = ReactDom.createRoot(document.getElementById('root'))
18+
19+
rerender()
20+
21+
function rerender() {
22+
root.render(React.createElement(Component))
23+
setTimeout(rerender, 1000)
24+
}
25+
26+
function Component() {
27+
return toJsxRuntime(createTree(), {Fragment, jsx, jsxs})
28+
}
29+
</script>

example/readme.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# `hast-util-to-jsx-runtime`: web examples
2+
3+
This folder contains examples that run in web browsers that check whether
4+
this utility works with different frameworks.
5+
6+
To use them, first set up the Git repo with:
7+
8+
```sh
9+
npm install
10+
npm test
11+
```
12+
13+
Then, start a simple server in this examples folder:
14+
15+
```sh
16+
python3 -m http.server
17+
```
18+
19+
Open `http://localhost:8000` in a browser to see the results.

example/solid.html

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!doctype html>
2+
<html lang=en>
3+
<meta charset=utf8>
4+
<title>Solid + hast-util-to-jsx-runtime</title>
5+
<link rel=stylesheet href=index.css />
6+
<h1><code>Solid</code> + <code>hast-util-to-jsx-runtime</code></h1>
7+
<p style="color:red">Note! This example is static! (to do: figure out a way to rerender Solid without changing everything?)</p>
8+
<div id=root></div>
9+
<script type=module>
10+
/* eslint-env browser */
11+
import {Fragment, jsx, jsxs} from 'https://esm.sh/solid-js@1/h/jsx-runtime'
12+
import {render} from 'https://esm.sh/solid-js@1/web?dev'
13+
import {toJsxRuntime} from './hast-util-to-jsx-runtime.min.js'
14+
import {createTree} from './create-tree.js'
15+
16+
render(Component, document.getElementById('root'))
17+
18+
function Component() {
19+
return toJsxRuntime(createTree(), {Fragment, jsx, jsxs, passKeys: false, elementAttributeNameCase: 'html', stylePropertyNameCase: 'css'})
20+
}
21+
</script>

example/svelte.html

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!doctype html>
2+
<html lang=en>
3+
<meta charset=utf8>
4+
<title>Svelte + hast-util-to-jsx-runtime</title>
5+
<link rel=stylesheet href=index.css />
6+
<h1><code>Svelte</code> + <code>hast-util-to-jsx-runtime</code></h1>
7+
<p style="color:red">Note! This example is static! (to do: figure out a way to rerender Svelte)</p>
8+
<p style="color:red">Note! Svelte seems completely broken: no support for style, SVG, etc.</p>
9+
<div id=root></div>
10+
<script type=module>
11+
/* eslint-env browser */
12+
import {Fragment, jsx, jsxs} from 'https://esm.sh/svelte-jsx@2/jsx-runtime'
13+
import {toJsxRuntime} from './hast-util-to-jsx-runtime.min.js'
14+
import {createTree} from './create-tree.js'
15+
16+
const Component = toJsxRuntime(createTree(), {Fragment, jsx, jsxs})
17+
18+
new Component({target: document.getElementById('root')})
19+
</script>

0 commit comments

Comments
 (0)