|
| 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 | +} |
0 commit comments