Gathering detailed insights and metrics for easy-jsx-html-engine
Gathering detailed insights and metrics for easy-jsx-html-engine
npm install easy-jsx-html-engine
Typescript
Module System
Node Version
NPM Version
73.2
Supply Chain
98.5
Quality
84
Maintenance
100
Vulnerability
100
License
Total Downloads
931
Last Day
1
Last Week
16
Last Month
145
Last Year
931
Minified
Minified + Gzipped
Latest Version
0.1.6
Package Id
easy-jsx-html-engine@0.1.6
Unpacked Size
45.26 kB
Size
12.61 kB
File Count
32
NPM Version
10.8.1
Node Version
20.16.0
Publised On
12 Dec 2024
Cumulative downloads
Total Downloads
Last day
0%
1
Compared to previous day
Last week
23.1%
16
Compared to previous week
Last month
-52.1%
145
Compared to previous month
Last year
0%
931
Compared to previous year
2
2
Dead simple HTML engine using JSX syntax. Inspired by @kitajs/html with safety by default and WebAPI streams.
Open your terminal and run the following command:
1npm install easy-jsx-html-engine
Add the following options to your tsconfig.json file:
1{ 2 "compilerOptions": { 3 "jsx": "react-jsx", 4 "jsxImportSource": "easy-jsx-html-engine", 5 } 6}
Then, you can use the engine like this:
1const html = ( 2 <h1>Hello, World!</h1> 3).toHTML();
You can create a custom component like this:
1const MyComponent = ({ name }: { name: string }) => ( 2 <h1>Hello, {name}!</h1> 3); 4 5const html = ( 6 <MyComponent name="World" /> 7).toHTML();
It also works with async functions:
1async function MyAsyncComponent({ name }: { name: string }) { 2 return ( 3 <h1>Hello, {name}!</h1> 4 ); 5} 6 7const html = ( 8 await <div><MyAsyncComponent name="World" /></div> 9).toHTML();
ErrorBoundary is supported:
1async function BadComponent() { 2 throw new Error('Bad component'); 3} 4 5const html = ( 6 <ErrorBoundary catch={<h1>Something went wrong</h1>}> 7 <BadComponent /> 8 </ErrorBoundary> 9).toHTML();
Even Suspense is supported:
1import { renderToStream } from "easy-jsx-html-engine/stream-webapi"; 2 3async function MyAsyncComponent({ name }: { name: string }) { 4 return ( 5 <h1>Hello, {name}!</h1> 6 ); 7} 8 9const stream: ReadableStream = renderToStream( 10 (rid) => ( 11 <Suspense rid={rid} fallback={<h1>Loading...</h1>} catch={<h1>Something went wrong</h1>}> 12 <MyAsyncComponent /> 13 </Suspense> 14 ), 15);
The engine is designed to be safe by default to prevent unwanted html injections.
This relies on a simple interface with a toHTML
method that returns a string. This is what the engine uses to determine whether to escape the content or not.
However, it sometimes may be necessary to inject unescaped content. In this case, you can use the dangerouslyPreventEscaping
function:
1const html = ( 2 <div> 3 {dangerouslyPreventEscaping('<h1>Hello, World!</h1>')} 4 </div> 5).toHTML();
You may use async functions to create components and even insert promises as a child, however this causes all parent elements to become async unless a Suspense
component is used.
The engine will wait for all child promises to resolve with Promise.all
before rendering the parent element.
1const html = (
2 await (
3 <h1>Hello, {Promise.resolve("World"}!</h1>
4 )
5).toHTML();
You may use the ErrorBoundary
component to catch errors and display a fallback component.
It works great with async components and promises:
1const html = ( 2 await ( 3 <ErrorBoundary catch={(err) => <div>Something went wrong: {err.message}</div>}> 4 <h1>Hello, {Promise.reject(new Error("no"))}!</h1> 5 </ErrorBoundary> 6 ) 7).toHTML();
But needs a little extra for sync errors:
1const html = ( 2 await ( 3 <ErrorBoundary catch={(err) => <div>Something went wrong: {err.message}</div>}> 4 {() => { 5 throw new Error("no"); 6 }} 7 </ErrorBoundary> 8 ) 9).toHTML();
Suspense
is an extension of the ErrorBoundary
component that allows you to display a fallback component while waiting for async components to resolve.
This works by rendering a placeholder component in place of the actual content and then replacing it with the resolved content once it is ready.
Note that this is only effective when rendering to a stream and requires an implementation specific to your runtime environment.
There is currently only one implementation for environments with WebAPI streams (such as service workers, Bun, Deno, and Cloudflare Workers):
1import { renderToStream } from "easy-jsx-html-engine/stream-webapi"; 2 3const server = Bun.serve({ 4 port: 3000, 5 async fetch(request) { 6 return new Response( 7 await renderToStream( 8 (rid) => ( 9 <Suspense rid={rid} fallback={<h1>Loading...</h1>} catch={<h1>Something went wrong</h1>}> 10 <MyAsyncComponent /> 11 </Suspense> 12 ), 13 ) 14 ); 15 }, 16});
renderToStream
returns a string | Promise<string> | ReadableStream<Uint8Array>
depending on the component tree. If the tree contains any Suspense
elements, it will return a ReadableStream
. Otherwise, it will return a string
or Promise<string>
. While it is possible to use renderToStream
without await
ing the result, it is recommended to ensure that no errors occur if a promise is returned unexpectedly.
The rid
or request ID is used to identify the stream and is passed to the Suspense
component. This is necessary to ensure that the correct stream is resumed when the async component resolves. It is only valid for the duration of the request and should not be stored for any longer than that.
Just like @kitajs/html, there is no support for contexts for the same reasons. In short, the purpose of contexts is to avoid prop drilling, but there is no way to keep track of the context in an async environment without prop drilling, thus there is ultimately no benefit.
This library has only 2 dependencies: clsx
for class name building and html-escaper
for escaping html content, both of which are very tiny and excellent libraries with no dependencies of their own.
This library was heavily inspired by @kitajs/html as mentioned above, but is completely rewritten from scratch in Typescript with a focus to overcome some of the usability issues and limitations of the original library. Mainly, requiring the "safe" attribute to escape content and the NodeJS requirement. Additionally, it is distributed as an ES module and the stream implementation is designed to be pluggable for different runtime environments.
No vulnerabilities found.
No security vulnerabilities found.