Security News
RubyGems.org Adds New Maintainer Role
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Satori is an npm package designed to generate SVG images from HTML and CSS. It is particularly useful for creating dynamic, server-side rendered graphics that can be used in various applications such as social media previews, charts, and more.
Generate SVG from HTML
This feature allows you to convert HTML content into an SVG image. The code sample demonstrates how to generate an SVG from a simple HTML string.
const satori = require('satori');
const html = '<div>Hello, World!</div>';
const svg = satori(html, { width: 200, height: 100 });
console.log(svg);
Support for CSS Styling
Satori supports CSS styling within the HTML content. The code sample shows how to apply CSS styles to the HTML content before converting it to an SVG.
const satori = require('satori');
const html = '<div style="color: red;">Hello, World!</div>';
const svg = satori(html, { width: 200, height: 100 });
console.log(svg);
Custom Fonts
You can use custom fonts in your HTML content when generating SVGs. The code sample demonstrates how to include a custom font in the SVG generation process.
const satori = require('satori');
const html = '<div style="font-family: CustomFont;">Hello, World!</div>';
const svg = satori(html, { width: 200, height: 100, fonts: [{ name: 'CustomFont', data: 'base64-encoded-font-data' }] });
console.log(svg);
The 'html-to-image' package allows you to convert HTML content to various image formats, including PNG and JPEG. Unlike Satori, which focuses on SVG generation, 'html-to-image' provides more flexibility in terms of output formats.
Puppeteer is a Node library that provides a high-level API to control Chrome or Chromium over the DevTools Protocol. It can be used to generate screenshots and PDFs of web pages, making it a more versatile but heavier alternative to Satori for generating images from HTML content.
The 'dom-to-image' package allows you to convert DOM nodes to images in various formats. It is similar to Satori in that it can generate images from HTML content, but it supports more output formats like PNG and JPEG.
Satori: A library that converts HTML and CSS into SVG.
Satori supports the JSX syntax, which makes it very straightforward to use. Here’s an overview of the basic usage:
// api.jsx
import satori from 'satori'
const svg = await satori(
<div style={{ color: 'black' }}>hello, world</div>,
{
width: 600,
height: 400,
fonts: [
{
name: 'Roboto',
data: robotoArrayBuffer,
weight: 400,
style: 'normal',
},
],
},
)
Satori will render the element into a 600×400 SVG, and return the SVG string:
'<svg ...><path d="..." fill="black"></path></svg>'
Under the hood, it handles layout calculation, font, typography and more, to generate a SVG that matches the exact same HTML and CSS in a browser.
https://satori-playground.vercel.app
Satori only accepts JSX elements that are pure and stateless. You can use a subset of HTML
elements (see section below), or custom React components, but React APIs such as useState
and
useEffect
are not supported.
If you don't have JSX transpiler enabled, you can simply pass React-elements-like objects that have type
, props.children
and props.style
(and other properties too) directly:
await satori(
{
type: 'div',
props: {
children: 'hello, world',
style: { color: 'black' },
},
},
options
)
Satori supports a limited subset of HTML and CSS features, due to its special use cases. In general, only these static and visible elements and properties that are implemented.
For example, the <input>
HTML element, the cursor
CSS property are not in consideration. And you can't use <style>
tags or external resources via <link>
or <script>
.
Also, Satori does not guarantee that the SVG will 100% match the browser-rendered HTML output since Satori implements its own layout engine based on the SVG 1.1 spec.
You can find the list of supported HTML elements and their preset styles here.
You can use <img>
to embed images. However, width
, and height
attributes are recommended to set:
await satori(
<img src="https://picsum.photos/200/300" width={200} height={300} />,
options
)
When using background-image
, the image will be stretched to fit the element by default if you don't specify the size.
If you want to render the generated SVG to another image format such as PNG, it would be better to use base64 encoded image data directly as props.src
so no extra I/O is needed.
Satori uses the same Flexbox layout engine as React Native, and it’s not a complete CSS implementation. However, it supports a subset of the spec that covers most common CSS features:
Property | Property Expanded | Supported Values |
---|---|---|
display | none and flex , default to flex | |
position | relative and absolute , default to relative | |
color | Supported | |
margin | ||
marginTop | Supported | |
marginRight | Supported | |
marginBottom | Supported | |
marginLeft | Supported | |
Position | ||
top | Supported | |
right | Supported | |
bottom | Supported | |
left | Supported | |
Size | ||
width | Supported | |
height | Supported | |
Min & max size | ||
min-width | Supported | |
min-height | Supported | |
max-width | Supported | |
max-height | Supported | |
border | ||
Width (borderWidth , borderTopWidth , ...) | Supported | |
Style (borderStyle , borderTopStyle , ...) | solid and dashed , default to solid | |
Color (borderColor , borderTopColor , ...) | Supported | |
Shorthand (border , borderTop , ...) | Supported, i.e. 1px solid gray | |
borderRadius | ||
borderTopLeftRadius | Supported | |
borderTopRightRadius | Supported | |
borderBottomLeftRadius | Supported | |
borderBottomRightRadius | Supported | |
Shorthand | Supported, i.e. 5px , 50% / 5px | |
Flex | ||
flexDirection | column , row , row-reverse , column-reverse , default to row | |
flexWrap | wrap , nowrap , wrap-reverse , default to wrap | |
flexGrow | Supported | |
flexShrink | Supported | |
flexBasis | Supported except for auto | |
alignItems | Supported | |
alignContent | Supported | |
alignSelf | Supported | |
justifyContent | Supported | |
Font | ||
fontFamily | Supported | |
fontSize | Supported | |
fontWeight | Supported | |
fontStyle | Supported | |
Text | ||
textAlign | start , end , left , right , center , justify , default to start | |
textTransform | none , lowercase , uppercase , capitalize , defaults to none | |
textOverflow | clip , ellipsis , defaults to clip | |
textDecoration | Support line types underline and line-through , and styles dotted , dashed , solid | |
textShadow | Support single shadow | |
lineHeight | Supported | |
letterSpacing | Supported | |
whiteSpace | normal , pre , pre-wrap , nowrap , defaults to normal | |
wordBreak | normal , break-all , break-word , keep-all , defaults to normal | |
Background | ||
backgroundColor | Supported, single value | |
backgroundImage | linear-gradient , radial-gradient , url , single value | |
backgroundPosition | Support single value | |
backgroundSize | Support two-value size i.e. `10px 20%` | |
backgroundClip | border-box , text | |
backgroundRepeat | repeat , repeat-x , repeat-y , no-repeat , defaults to repeat | |
transform | ||
Translate (translate , translateX , translateY ) | Supported | |
Rotate | Supported | |
Scale (scale , scaleX , scaleY ) | Supported | |
Skew (skew , skewX , skewY ) | Supported | |
transformOrigin | Support one-value and two-value syntax (both relative and absolute values) | |
objectFit | contain , cover , none , default to node | |
opacity | Supported | |
boxShadow | Supported | |
overflow | visible and hidden , default to visible | |
filter | Supported |
Note:
z-index
support in SVG. Elements that come later in the document will be painted on top.box-sizing
is set to border-box
for all elements.calc
isn't supported.overflow: hidden
and transform
can't be used together.Advanced typography features such as kerning, ligatures and other OpenType features are not currently supported.
RTL languages are not supported either.
Satori currently supports three font formats: TTF, OTF and WOFF. Note that WOFF2 is not supported at the moment. You must specify the font if any text is rendered with Satori, and pass the font data as ArrayBuffer (web) or Buffer (Node.js):
await satori(
<div style={{ fontFamily: 'Inter' }}>Hello</div>,
{
width: 600,
height: 400,
fonts: [
{
name: 'Inter',
data: inter,
weight: 400,
style: 'normal',
},
{
name: 'Inter',
data: interBold,
weight: 700,
style: 'normal',
},
],
}
)
Multiple fonts can be passed to Satori and used in fontFamily
.
To render custom images for specific graphemes, you can use graphemeImages
option to map the grapheme to an image source:
await satori(
<div>Next.js is 🤯!</div>,
{
...,
graphemeImages: {
'🤯': 'https://twemoji.maxcdn.com/v/13.1.0/svg/1f92f.svg',
},
}
)
The image will be resized to the current font-size (both width and height), so it must be a square.
Satori supports dynamically loading emoji images (grapheme pictures) and fonts. The loadAdditionalAsset
function will be called when a text segment is rendered but missing the image or font:
await satori(
<div>👋 你好</div>,
{
// `code` will be the detected language code, `emoji` if it's an Emoji, or `unknwon` if not able to tell.
// `segment` will be the content to render.
loadAdditionalAsset: async (code: string, segment: string) => {
if (code === 'emoji') {
// if segment is an emoji
return `data:image/svg+xml;base64,...`
}
// if segment is normal text
return loadFontFromSystem(code)
}
}
)
Satori can be used in browser, Node.js (>= 16), and Web Workers.
By default, Satori depends on asm.js for the browser runtime, and native module in Node.js. However, you can optionally load WASM instead by importing satori/wasm
and provide the initialized WASM module instance of Yoga to Satori:
import satori, { init } from 'satori/wasm'
import initYoga from 'yoga-wasm-web'
const yoga = initYoga(await fetch('/yoga.wasm').then(res => res.arrayBuffer()))
init(yoga)
await satori(...)
By default, Satori renders the text as <path>
in SVG, instead of <text>
. That means it embeds the font path data as inlined information, so succeeding processes (e.g. render the SVG on another platform) don’t need to deal with font files anymore.
You can turn off this behavior by setting embedFonts
to false
, and Satori will use <text>
instead:
const svg = await satori(
<div style={{ color: 'black' }}>hello, world</div>,
{
...,
embedFont: false,
},
)
To draw the bounding box for debugging, you can pass debug: true
as an option:
const svg = await satori(
<div style={{ color: 'black' }}>hello, world</div>,
{
...,
debug: true,
},
)
This project uses pnpm. To install dependencies, run:
pnpm install
To start the playground locally, run:
cd playground
pnpm dev
And visit localhost:3000/test.
To start the development mode, run pnpm dev
in the root directory (can be used together with the playground to view it in live).
To start and live-watch the tests, run:
pnpm dev:test
FAQs
Enlightened library to convert HTML and CSS to SVG.
The npm package satori receives a total of 135,519 weekly downloads. As such, satori popularity was classified as popular.
We found that satori demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.
Security News
Research
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.