# <img src="./logo.svg" width="150px">

svg2png-wasm

[![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/ssssota/svg2png-wasm/Checks/main)](https://github.com/ssssota/svg2png-wasm/actions/workflows/checks.yml)
[![npm](https://img.shields.io/npm/v/svg2png-wasm)](https://npmjs.com/svg2png-wasm)
[![NPM](https://img.shields.io/npm/l/svg2png-wasm)](https://npmjs.com/svg2png-wasm)

**[Demo site](https://ssssota.github.io/svg2png-wasm/)**

SVG to PNG converter JS library made with WASM + [resvg](https://crates.io/crates/resvg).

See [resvg](https://github.com/RazrFalcon/resvg#svg-support) for SVG support status.

## 📊 Benchmark

[Benchmark result](./benchmark/README.md)

## 💻 Usage

### Installation

#### Node.js / Browser

```sh
npm install svg2png-wasm
# yarn add svg2png-wasm
# pnpm add svg2png-wasm
```

Or, using a script tag in the browser and load from unpkg.

```html
<script src="https://unpkg.com/svg2png-wasm@0.6.1"></script>

<!-- Or, latest -->
<script src="https://unpkg.com/svg2png-wasm"></script>
```

#### Deno

```ts
// from esm.sh
export * from 'https://esm.sh/svg2png-wasm@0.6.1';
// from skypack.dev
export * from 'https://cdn.skypack.dev/svg2png-wasm@0.6.1?dts';
```

### Examples

- Use in Web Worker [Demo site](https://ssssota.github.io/svg2png-wasm/) ([source](./site/))
- Use with Cloudflare Workers [ssssota/svg2png-worker](https://github.com/ssssota/svg2png-worker)
- Use with Deno Deploy [ssssota/svg2png-deno-deploy](https://github.com/ssssota/svg2png-deno-deploy)
- Or [test directory](./test/)

#### Node.js

```js
import { svg2png, initialize } from 'svg2png-wasm';
// const { svg2png, initialize } = require('svg2png-wasm');
import { readFileSync, writeFileSync } from 'fs';

await initialize(
  readFileSync('./node_modules/svg2png-wasm/svg2png_wasm_bg.wasm'),
);

/** @type {Uint8Array} */
const png = await svg2png(
  '<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"> ... </svg>',
  {
    scale: 2, // optional
    width: 400, // optional
    height: 400, // optional
    backgroundColor: 'white', // optional
    fonts: [
      // optional
      readFileSync('./Roboto.ttf'), // require, If you use text in svg
    ],
    defaultFontFamily: {
      // optional
      sansSerif: 'Roboto',
    },
  },
);
writeFileSync('./output.png', png);
```

#### Browser

```js
import { createSvg2png, initialize } from 'svg2png-wasm';

// put wasm to your assets directory
await initialize(fetch('/assets/svg2png_wasm_bg.wasm'));
const svgs = [
  '<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"> ... </svg>',
  '<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"> ... </svg>',
  '<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"> ... </svg>',
  // and more ...
];
const font = await fetch('./Roboto.ttf').then((res) => res.arrayBuffer());
const svg2png = createSvg2png({
  fonts: [new Uint8Array(font)], // require, If you use text in svg
});
/** @type {Uint8Array[]} */
const pngs = await Promise.all(svgs.map((svg) => svg2png(svg, { scale: 2 })));
svg2png.dispose(); // You should dispose svg2png, if you will not use it in the future
```

Or, using a script tag in the browser and load from unpkg.

```html
<script src="https://unpkg.com/svg2png-wasm"></script>
<script>
  await svg2pngWasm.initialize(fetch('https://unpkg.com/svg2png-wasm/svg2png_wasm_bg.wasm'))
  const font = await fetch('./Roboto.ttf').then((res) => res.arrayBuffer());
  /** @type {Uint8Array} */
  const png = await svg2pngWasm.svg2png(
    '<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"> ... </svg>',
  );
  document.getElementById('output').src = URL.createObjectURL(
    new Blob([png], { type: 'image/png' }),
  );
</script>
```

### API

The library has two main APIs (`svg2png` and `createSvg2png`).

Basically, you can use `svg2png`, but if you want to process a lot of data continuously, consider using `createSvg2png`.
It can reduce the overhead of font loading.
Converters generated by `createSvg2png` should be disposed of after use by calling the `dispose` method.

```ts
export type InitInput =
  | RequestInfo
  | URL
  | Response
  | BufferSource
  | WebAssembly.Module;
export type DefaultFontFamily = {
  serifFamily?: string;
  sansSerifFamily?: string;
  cursiveFamily?: string;
  fantasyFamily?: string;
  monospaceFamily?: string;
};
export type ConverterOptions = {
  fonts?: Uint8Array[];
  defaultFontFamily?: DefaultFontFamily;
};
export type ConvertOptions = {
  scale?: number;
  width?: number;
  height?: number;
  backgroundColor?: string;
};
export type Svg2png = ((
  svg: string,
  options?: ConvertOptions,
) => Promise<Uint8Array>) & {
  dispose: () => void;
};
/**
 * Initialize WASM module
 * @param mod WebAssembly Module or WASM url
 */
export const initialize: (mod: Promise<InitInput> | InitInput) => Promise<void>;
/**
 * @param opts Converter options (e.g. font settings)
 * @returns svg2png converter
 */
export const createSvg2png: (opts?: ConverterOptions | undefined) => Svg2png;
export const svg2png: (
  svg: string,
  opts?: (ConverterOptions & ConvertOptions) | undefined,
) => Promise<Uint8Array>;
```

## 📄 LICENSE

MIT

This library uses [resvg](https://github.com/RazrFalcon/resvg), which is licensed unser MPL-2.0.
The source code for resvg can be found [here](https://github.com/RazrFalcon/resvg).

## 🙋‍♂️ Contributing

WELCOME!
