A simple jsx to DOM Node
parser.
To create a DOM element in JavaScript, we could use document.createElement
:
const div = document.createElement('div');
div.classList.add('example');
div.innerText = 'hello there';
div.addEventListener('click', () => console.log('clicked!'));
Texsaur lets you do this with jsx instead:
import jsx from 'texsaur';
const div = (
<div class="example"
onclick={() => console.log('clicked!')}>
Hello there
</div>
) as HTMLElement;
You can create a reusable component by creating a function:
function Header({ title }: { title: string }) {
return <header>
<h1>{title}</h1>
</header>
}
document.body.appendChild(
<div>
<Header title="Hello there" />
{/* Same as */}
{Header({ title: 'Hello there.' })}
</div>
)
To work with JSX, the function must implement Component
:
interface Component {
(properties?: { [key: string]: any }, children?: Node | Node[]): Element
}
JSX requires a compiler/bundler. Here are a few example set-ups (note: checkout the examples/ directory for corresponding sample projects):
In vite.config.js
, add the esbuild.jsx
property:
export default {
esbuild: {
jsxFactory: 'jsx',
jsxFragment: 'jsx.Fragment', // optional - enables fragments (<></>)
}
}
However, if your project contains a tsconfig, vite should read these properties from there as of version 4 - no vite configuration required!
Examples:
Texsaur supports a few models of JSX code generation (determined the jsx
property in your tsconfig):
"react"
,"react-jsx"
,- and
"preserve"
.
The differences between these are outlined in the following sections.
First, configure your tsconfig.json
:
"compilerOptions": {
"jsx": "react",
"jsxFactory": "jsx",
"jsxFragmentFactory": "jsx.Fragment" // optional - enables fragments (<></>)
}
Then, import Texsaur in any .tsx file:
import jsx from 'texsaur'
const div = <div>Hello there.</div>
This method comes with a few more quirks, but it allows you to drop the import jsx
statements in your tsx
files.
In your tsconfig.json
:
"compilerOptions": {
"moduleResolution": "node16", // or nodenext
"jsx": "react-jsx",
"jsxImportSource": "texsaur"
}
By using node16
module resolution, your package will be able to take advantage of the exports
field in texsaur's package.json. However, this requires you use the file suffix in imports:
import Foo from './components/foo'
// becomes
import Foo from './components/foo.js' // .js even if it's .tsx or .ts
Please note that this repository does not contain any examples of this, nor have we tested it. In theory, this should work.
Configure your tsconfig.json
:
"compilerOptions": {
"jsx": "preserve",
}
This will output the jsx code as-is. You will need another bundler/compiler (e.g. babel) to transform it before it can be used in a browser.
Add custom elements to the JSX.IntrinsicElements
interface:
namespace JSX {
interface IntrinsicElements {
['my-element']: HTMLElement // or another type representing your custom element
}
}