@francbonet/lightningjs-html-paragraph-image
v0.1.6
Published
Render HTML/text into a bitmap and use it as an ImageTexture in LightningJS 2 components.
Downloads
51
Maintainers
Readme
lightningjs-html-paragraph-image
Small helper library for LightningJS 2 that lets you render HTML/text
paragraphs to a bitmap using html2canvas, and then use that bitmap as an
ImageTexture inside a Lightning component.
It provides two main APIs:
renderParagraphToDataUrl(opts)– a low-level function that returns a PNG data URL.HtmlParagraphImage– aLightning.Componentthat wraps the above, renders HTML/text into a bitmap, and automatically sets its own texture/size.
⚠️ This library is meant to be used in the browser (inside a LightningJS app).
It relies ondocumentandhtml2canvas.
Installation
npm install lightningjs-html-paragraph-image html2canvas
# or
yarn add lightningjs-html-paragraph-image html2canvasYour project must also include @lightningjs/sdk (declared as a peer dependency).
Basic Usage
Option A — Using childList.a()
import { HtmlParagraphImage } from "lightningjs-html-paragraph-image";
// inside a LightningJS component
this.tag("content").childList.a({
type: HtmlParagraphImage,
x: 120,
y: 220,
content: {
html: `
<div style="margin-bottom:24px;">
<p style="margin-bottom: 16px;">Your watchlist is empty 😢</p>
<ul style="padding-left:32px; margin:0;">
<li>Add series and films you want to watch</li>
<li>They will appear here to continue later</li>
<li>Keep track of your favorites easily</li>
</ul>
</div>
`,
width: 900,
fontFamily: "RelaxAI-SoraRegular",
style: {
fontSize: "32px",
lineHeight: "1.6",
color: "#FFFFFF",
textAlign: "left",
},
},
});Option B — Using the Component via Template
static override _template() {
return {
Content: {
type: HtmlParagraphImage,
x: 0,
y: 40,
w: 1920,
visible: true,
},
};
}Then update it like this:
const content = this.tag("Content");
await content.setContent({
html: "<p>Your watchlist is empty 😢</p>",
width: 1920,
fontFamily: "RelaxAI-SoraMedium",
style: {
fontSize: "40px",
lineHeight: "1.6",
color: "#FFFFFF",
},
});Low-Level Usage (no Lightning component)
import { renderParagraphToDataUrl } from "lightningjs-html-paragraph-image";
const dataUrl = await renderParagraphToDataUrl({
text: "Hello LightningJS!",
width: 600,
fontFamily: "RelaxAI-SoraRegular",
style: {
fontSize: "32px",
color: "#ffffff",
},
});You may use dataUrl in any ImageTexture.
Types
type HtmlParagraphRenderOptions = {
text?: string;
html?: string;
width?: number; // default: 800
fontFamily?: string;
style?: Partial<CSSStyleDeclaration>;
containerStyle?: Partial<CSSStyleDeclaration>;
fontsStylesheetHref?: string; // default: "./static/fonts.css"
};
type HtmlContentInput =
| string
| (HtmlParagraphRenderOptions & {});How to Register Custom Fonts (fonts.css)
This library uses an internal loader function called ensureFontsStylesheet():
export function ensureFontsStylesheet(href = "./static/fonts.css"): Promise<void>This means you must create a fonts.css file inside the static/ folder of your LightningJS project containing all the fonts you want to use.
LightningJS does not automatically load fonts, so if this file is missing, html2canvas will fall back to default system fonts and your rendered text will not match your design.
📁 Recommended Project Structure
your-lightning-app/
static/
fonts.css
fonts/
Sora-Bold.ttf
Sora-Regular.ttf
Sora-Medium.ttf
Sora-SemiBold.ttf✨ Example static/fonts.css
@font-face {
font-family: "RelaxAI-SoraBold";
src: url("./fonts/Sora-Bold.ttf") format("truetype");
font-weight: 700;
font-display: swap;
}
@font-face {
font-family: "RelaxAI-SoraRegular";
src: url("./fonts/Sora-Regular.ttf") format("truetype");
font-weight: 400;
font-display: swap;
}
@font-face {
font-family: "RelaxAI-SoraMedium";
src: url("./fonts/Sora-Medium.ttf") format("truetype");
font-weight: 500;
font-display: swap;
}
@font-face {
font-family: "RelaxAI-SoraSemiBold";
src: url("./fonts/Sora-SemiBold.ttf") format("truetype");
font-weight: 600;
font-display: swap;
}🧩 How the Library Uses These Fonts
When you call:
await renderParagraphToDataUrl({
html: "<p>Hello Lightning!</p>",
fontFamily: "RelaxAI-SoraRegular",
width: 900,
});The library internally executes:
ensureFontsStylesheet("./static/fonts.css");This:
- Injects a
<link rel="stylesheet">into the<head>. - Waits for the stylesheet to finish loading.
- Ensures the fonts are available before rendering.
- Loads only once per application.
🔍 Using a Custom Stylesheet Path
If your fonts.css lives somewhere else:
await renderParagraphToDataUrl({
html: "...",
fontFamily: "RelaxAI-SoraMedium",
fontsStylesheetHref: "/assets/styles/fonts.css",
});🎯 Result
Once your fonts are correctly registered:
content: { fontFamily: "RelaxAI-SoraRegular" }style: { fontFamily: "RelaxAI-SoraBold" }<p style="font-family: RelaxAI-SoraMedium">…</p>
will all render exactly with your custom fonts, both inside html2canvas and in the final LightningJS ImageTexture.
IMPORTANT: Disable Image Worker in LightningJS (Required for data:/blob Textures)
⚠️ IMPORTANT: This library generates textures using
data:URLs (and sometimesblob:URLs) produced byhtml2canvas.
LightningJS’s Image Worker cannot loaddata:orblob:URLs, so you must disable it.
Required configuration
Add this to your Lightning app settings:
{
"appSettings": {
"stage": {
"useImageWorker": false
}
}
}Why is this required?
LightningJS includes an optimization called the Image Worker.
When enabled, all images and textures are loaded inside a Web Worker instead of the main thread.
However:
❌ The worker pipeline does not accept:
data:URLsblob:URLs- dynamically created in‑memory images
These URL types are exactly what html2canvas produces:
const dataUrl = canvas.toDataURL("image/png"); // -> data:image/png;base64,...When the worker is enabled, Lightning’s internal image loader filters out these URLs because workers cannot handle them.
Result:
- The texture fails to load
- Lightning logs “unsupported source” or silently drops the texture
- The paragraph image never appears
✔️ What happens when useImageWorker: false?
With the worker disabled, Lightning uses the main-thread image loader, which fully supports:
data:URLsblob:URLs- dynamically generated PNGs
- canvas snapshots
This is the expected environment for html2canvas-generated textures and is required for this library to work.
Summary
| Feature | Image Worker ON | Image Worker OFF |
|---------------------------------|------------------|-------------------|
| Supports data: URL textures | ❌ No | ✔️ Yes |
| Supports blob: URL textures | ❌ No | ✔️ Yes |
| Compatible with html2canvas | ❌ No | ✔️ Yes |
| Required for this library | ❌ Not possible | ✔️ Required |
Final note
If you do not disable the worker, all paragraph images will fail silently because LightningJS filters out data:/blob: texture sources in worker mode.
Always set:
"stage": { "useImageWorker": false }to ensure compatibility.
