Image loading & emoji
Load remote, pre-fetched, and raw-pixel images, render emoji, and tune fetch limits and caches in Takumi.
Takumi fetches the remote images your markup references, accepts images you fetch or decode yourself, and turns emoji into images. Fetch limits, retries, caches, and decode limits come after these, at the end of the page.
External images
render() and ImageResponse fetch every remote http:// or https:// image the tree draws once its styles apply:
- an
<img>src background-image,mask-image, andlist-style-image, whetherstyle,tw,css, a<style>element, or a::beforerule sets them- images an animation's
@keyframesswitch to
An image under display: none is not fetched. A relative URL such as /logo.png is fetched only through your own fetch, which can resolve it.
When user input can reach the markup, set allowUrl, as URLs from user input describes.
Share a fetchCache across renders to reuse downloaded bytes and pending requests:
import { } from "takumi-js";
const = < ="https://example.com/image.png" />;
const = new <string, <>>();
const = await (, {
: {
,
},
});fetchCache takes a Map<string, Promise<ArrayBuffer>> or any object with the same get, set, and delete methods. Values are promises, not raw buffers.
Emoji images from the emoji option are cached across renders without a fetchCache, up to 8 MB per fetch function.
A plain Map never evicts entries. If each render uses a different URL, pass a bounded cache such
as an LRU, or leave fetchCache out.
Pre-fetched images
Give images a key so the renderer never fetches them. Use the key in any src or CSS url().
import { } from "takumi-js/response";
export function (: ) {
return new (< />, {
: [
{
: "my-logo",
: () => (new ("/logo.png", .)).(() => .()),
},
{
: "background",
: () => (new ("/background.png", .)).(() => .()),
},
],
});
}
function () {
return (
<
={{
: "url(background)",
}}
>
< ="my-logo" />
</>
);
}data is raw bytes or a function that returns them. Takumi skips fetching any remote URL that already has an entry.
Raw pixels
Pass raw RGBA pixels instead of encoding a PNG first, and Takumi skips decoding. The Bitmap helper renders a row-major buffer of width * height * 4 bytes as an <img>. This example fills a 64 × 64 image with opaque blue:
import { } from "takumi-js";
import { } from "takumi-js/helpers/jsx";
const = new (64 * 64 * 4);
for (let = 0; < .; += 4) {
.([59, 130, 246, 255], );
}
const = await (< ={64} ={64} ={} />, {
: 64,
: 64,
});Set premultiplied when the bytes already have premultiplied alpha. Takumi then uses them as they are. Outside JSX, an image node's src takes the same { width, height, data, premultiplied? } object.
Emoji
takumi-js turns emoji into images by default. It splits each emoji out of the text and fetches its SVG from a CDN, using Twemoji unless you pick another set.
Dynamic fetching
Set emoji to choose the set. render, renderSvg, renderAnimation, measure, and ImageResponse all take it, and the CDN values match satori's. Each emoji's SVG comes from jsDelivr, at the version the table lists:
| Value | Emoji set | Fetched from |
|---|---|---|
twemoji (default) | Twemoji | jdecked/twemoji 17.0.2 |
blobmoji | Blobmoji | @svgmoji/blob 2.0.0 |
noto | Noto Emoji | googlefonts/noto-emoji v2.051 |
openmoji | OpenMoji | @svgmoji/openmoji 2.0.0 |
fluent | Fluent Emoji, color | shuding/fluentui-emoji-unicode 7a40f1a |
fluentFlat | Fluent Emoji, flat | shuding/fluentui-emoji-unicode 7a40f1a |
from-font | Glyphs from a color font you load | No fetch. See COLR / bitmap fonts |
import { } from "takumi-js/response";
export function () {
return new (< ="flex justify-center items-center text-3xl">Hello 👋😁</>, {
: "noto",
});
}Emoji detection follows the Unicode presentation rules. A pictograph that defaults to text presentation, such as ‼ or ▶, stays text and renders with your fonts. Add U+FE0F after it to force the emoji image. Add U+FE0E after an emoji to keep the text glyph.
On your own renderer, prepare() splits emoji and fetches their images the same way.
COLR / bitmap fonts
Takumi draws emoji from color fonts, either COLR fonts such as Twemoji-COLR or bitmap fonts such as Noto Color Emoji. A COLR file is much smaller than a bitmap font. The glyphs come from the loaded font, so no emoji request goes out.
To use a color font, do both of these:
- Register the font through
fonts. - Set
emoji: "from-font".
Variation selectors take priority over font order. A code point followed by U+FE0F renders as a color emoji, even when a text font comes first in the stack. A code point followed by U+FE0E renders as a monochrome glyph, even when a color font comes first. Bare code points follow stack order, as in browsers.
Prepare on your own renderer
A Renderer from takumi-js/node or @takumi-rs/wasm fetches nothing on its own. renderer.prepare() does what render() does before drawing. It styles the source, fetches the images it draws, emoji included, and loads the font subsets its text uses. Pass the result to render, renderSvg, or measure:
const = new ();
const = new <string, <>>();
const = await .(, {
: 1200,
: 630,
: "twemoji",
: { },
});
const = await .(, { : "webp" });preparetakes the layout options ofrender, such as the size,css,lang,emoji, andfonts, plusimageswith the same fetch limits. Rendering a prepared source takes only the output format, so the layout cannot change between the two calls.- With your own
fetch, a relative URL such as/logo.pngreaches it, so it can resolve the path and apply its own checks. Without one, onlyhttp://andhttps://URLs are fetched. - A prepared source renders on any renderer from the same package. A renderer that no longer holds its fonts loads them again.
takumi-pdf and takumi-paint have no prepare yet. For them, call extractEmojis and prepareImages before rendering:
import { } from "@takumi-rs/helpers";
import { } from "@takumi-rs/helpers/emoji";
import { } from "@takumi-rs/helpers/jsx";
import { } from "takumi-pdf";
let { } = await (< ="flex justify-center items-center text-3xl">Hello 👋😁</>);
= (, "twemoji");
const = await (, { : await ({ }) });prepareImages reads src, inline styles, and tw classes, so pass images that a stylesheet or a <style> element names through sources yourself. It returns the supplied sources and the fetched entries together.
Fetch limits
import { } from "takumi-js";
const = < ="https://example.com/image.png" />;
const = await (, {
: {
: 3000,
: 4 * 1024 * 1024,
: () => new (). === "example.com",
},
});... (+124 lines) [see remaining: rtk proxy git show feat/render-needs-bindings:docs/content/docs/images.mdx | tail -n +188]
Last updated on