npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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

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 – a Lightning.Component that 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 on document and html2canvas.


Installation

npm install lightningjs-html-paragraph-image html2canvas
# or
yarn add lightningjs-html-paragraph-image html2canvas

Your 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:

  1. Injects a <link rel="stylesheet"> into the <head>.
  2. Waits for the stylesheet to finish loading.
  3. Ensures the fonts are available before rendering.
  4. 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 sometimes blob: URLs) produced by html2canvas.
LightningJS’s Image Worker cannot load data: or blob: 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: URLs
  • blob: 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: URLs
  • blob: 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.