docs: generate og information

This commit is contained in:
LongYinan 2022-04-25 15:25:53 +08:00
parent 8bccc89f54
commit 9c19dfbed4
10 changed files with 350 additions and 44 deletions

View File

@ -55,7 +55,7 @@ export const enum ChromaSubsampling {
* What if the chroma subsampling model is 4:0:0?
* That says to use every pixel of luma data, but that each row has 0 chroma samples applied to it. The resulting image, then, is comprised solely of the luminance dataa greyscale image.
*/
Yuv400 = 3,
Yuv400 = 3
}
export interface JpegCompressOptions {
/** Output quality, default is 100 (lossless) */
@ -67,11 +67,7 @@ export interface JpegCompressOptions {
optimizeScans?: boolean | undefined | null
}
export function compressJpegSync(input: Buffer, options?: JpegCompressOptions | undefined | null): Buffer
export function compressJpeg(
input: Buffer,
options?: JpegCompressOptions | undefined | null,
signal?: AbortSignal | undefined | null,
): Promise<Buffer>
export function compressJpeg(input: Buffer, options?: JpegCompressOptions | undefined | null, signal?: AbortSignal | undefined | null): Promise<Buffer>
export const enum CompressionType {
/** Default compression level */
Default = 0,
@ -82,7 +78,7 @@ export const enum CompressionType {
/** Huffman coding compression */
Huffman = 3,
/** Run-length encoding compression */
Rle = 4,
Rle = 4
}
export const enum FilterType {
/**
@ -102,7 +98,7 @@ export const enum FilterType {
* Uses a heuristic to select one of the preceding filters for each
* scanline rather than one filter for the entire image
*/
Adaptive = 5,
Adaptive = 5
}
export interface PngEncodeOptions {
/** Default is `CompressionType::Default` */
@ -155,11 +151,7 @@ export interface PNGLosslessOptions {
useHeuristics?: boolean | undefined | null
}
export function losslessCompressPngSync(input: Buffer, options?: PNGLosslessOptions | undefined | null): Buffer
export function losslessCompressPng(
input: Buffer,
options?: PNGLosslessOptions | undefined | null,
signal?: AbortSignal | undefined | null,
): Promise<Buffer>
export function losslessCompressPng(input: Buffer, options?: PNGLosslessOptions | undefined | null, signal?: AbortSignal | undefined | null): Promise<Buffer>
export interface PngQuantOptions {
/** default is 70 */
minQuality?: number | undefined | null
@ -178,11 +170,7 @@ export interface PngQuantOptions {
posterization?: number | undefined | null
}
export function pngQuantizeSync(input: Buffer, options?: PngQuantOptions | undefined | null): Buffer
export function pngQuantize(
input: Buffer,
options?: PngQuantOptions | undefined | null,
signal?: AbortSignal | undefined | null,
): Promise<Buffer>
export function pngQuantize(input: Buffer, options?: PngQuantOptions | undefined | null, signal?: AbortSignal | undefined | null): Promise<Buffer>
export const enum Orientation {
/** Normal */
Horizontal = 1,
@ -192,7 +180,7 @@ export const enum Orientation {
MirrorHorizontalAndRotate270Cw = 5,
Rotate90Cw = 6,
MirrorHorizontalAndRotate90Cw = 7,
Rotate270Cw = 8,
Rotate270Cw = 8
}
/**
* Available Sampling Filters.
@ -272,7 +260,7 @@ export const enum ResizeFilterType {
/** Gaussian Filter */
Gaussian = 3,
/** Lanczos with window 3 */
Lanczos3 = 4,
Lanczos3 = 4
}
export const enum JsColorType {
/** Pixel is 8-bit luminance */
@ -294,7 +282,7 @@ export const enum JsColorType {
/** Pixel is 32-bit float RGB */
Rgb32F = 8,
/** Pixel is 32-bit float RGBA */
Rgba32F = 9,
Rgba32F = 9
}
export interface Metadata {
width: number
@ -362,6 +350,8 @@ export class Transformer {
* just like the css webkit filter hue-rotate(180)
*/
huerotate(hue: number): this
/** Crop a cut-out of this image delimited by the bounding rectangle. */
crop(x: number, y: number, width: number, height: number): this
/**
* The quality factor `quality_factor` ranges from 0 to 100 and controls the loss and quality during compression.
* The value 0 corresponds to low quality and small output sizes, whereas 100 is the highest quality and largest output size.

1
website/.gitignore vendored
View File

@ -3,3 +3,4 @@
public/img/example.mjs
public/img/sharp.mjs
public/img/*.manipulated.webp
public/img/og.png

View File

@ -14,6 +14,7 @@ await fs.writeFile('public/img/sharp.mjs', await fs.readFile('../sharp.mjs'))
if (process.env.VERCEL) {
const gnuBinary = await fetch(`https://unpkg.com/@napi-rs/image-linux-x64-gnu`, {
redirect: 'follow',
follow: 10,
}).then((res) => res.arrayBuffer())
console.info(chalk.greenBright(`Installed @napi-rs/image.linux-x64-gnu, size: ${gnuBinary.byteLength}`))
@ -34,3 +35,8 @@ execSync('node manipulate.mjs', {
cwd: __dirname,
stdio: 'inherit',
})
execSync(`node og-image`, {
cwd: join(__dirname, '..', '..'),
stdio: 'inherit',
})

View File

@ -29,10 +29,13 @@ export default {
</>
)
},
head: ({ meta }) => {
head: ({ title, meta }) => {
return (
<>
{/* Favicons, meta */}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@Brooooook_lyn" />
<meta name="twitter:creator" content="@Brooooook_lyn" />
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png" />
@ -40,6 +43,12 @@ export default {
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta httpEquiv="Content-Language" content="en" />
<meta name="description" content={meta.description || 'Fast image processing library'} />
<meta property="og:title" content={title} />
<meta property="og:image" content={`https://${process.env.VERCEL_URL ?? 'image.napi.rs'}/img/og.png`} />
<meta property="og:description" content={meta.description || 'Fast image processing library'} />
<meta property="og:url" content="https://image.napi.rs" />
<meta property="og:site_name" content="Image" />
<meta property="og:type" content="website" />
<script async src="https://www.googletagmanager.com/gtag/js?id=G-50ZQKJLY5K"></script>
<script
dangerouslySetInnerHTML={{
@ -61,7 +70,7 @@ export default {
return (
<p>
<a href="https://vercel.com?utm_source=napi-rs&utm_campaign=oss">
<img src="assets/powered-by-vercel.svg" />
<img src="/img/powered-by-vercel.svg" />
</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Powered by{' '}
<a href="https://nextra.vercel.app" target="_blank">

176
website/og-image.js Normal file
View File

@ -0,0 +1,176 @@
import { promises as fs } from 'fs'
import { createCanvas, GlobalFonts, Image } from '@napi-rs/canvas'
import { pngQuantize } from '@napi-rs/image'
import fetch from 'node-fetch'
const canvas = createCanvas(1200, 700)
const ctx = canvas.getContext('2d')
ctx.globalCompositeOperation = 'destination-over'
const FONT_URL = `https://github.com/Brooooooklyn/canvas/raw/main/__test__/fonts/iosevka-slab-regular.ttf`
if (!GlobalFonts.families.some(({ family }) => family === 'Iosevka Slab')) {
const font = await fetch(FONT_URL, {
redirect: 'follow',
follow: 10,
}).then((res) => res.arrayBuffer())
GlobalFonts.register(Buffer.from(font))
}
ctx.fillStyle = 'white'
ctx.font = '48px Iosevka Slab'
const Title = '@napi-rs/image'
ctx.fillText(Title, 80, 100)
const Arrow = new Image()
Arrow.src = Buffer.from(`
<svg viewBox="0 0 1088 615" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke-width="1" fill="none" fill-rule="evenodd">
<text font-family="'Iosevka Slab', sans-serif" font-size="18" font-weight="600" fill="#00e676">
<tspan x="900" y="459">Optimized Images</tspan>
</text>
<g transform="translate(1002, 326)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-1"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="84" height="84" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="18.891" y="46.7096774">.png</tspan>
</text>
</g>
<g transform="translate(1002, 214)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-2"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="84" height="84" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="15" y="46.7096774">.avif</tspan>
</text>
</g>
<g transform="translate(894, 326)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-3"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="84" height="84" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="21.817" y="46.7096774">.jpg</tspan>
</text>
</g>
<g transform="translate(894, 214)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-4"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="84" height="84" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="9" y="46.7096774">.webp</tspan>
</text>
</g>
<g transform="translate(342, 225)" stroke="#73e8ff" stroke-width="4">
<path d="M499.558824,86.52 C499.558824,86.52 484.852941,81.02 439.908088,109.436667 C394.963235,137.853333 380.992647,164.436667 380.992647,164.436667" stroke-dasharray="7"></path>
<path d="M499.558824,86.0616667 C499.558824,86.0616667 484.852941,91.5616667 439.908088,63.145 C394.963235,34.7283333 380.992647,8.145 380.992647,8.145" stroke-dasharray="7"></path>
<path d="M0.477941176,170.395 C0.477941176,170.395 169.382939,98.895 447.847936,98.895" stroke-dasharray="6"></path>
<path d="M0.477941176,72.395 C0.477941176,72.395 169.382939,0.895 447.847936,0.895" stroke-dasharray="6" transform="translate(224.162939, 36.645000) scale(1, -1) translate(-224.162939, -36.645000) "></path>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="18" font-weight="600" fill="#ffcc80">
<tspan x="24.934" y="562">Raw Images</tspan>
</text>
<g transform="translate(228, 335)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-5"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.jpg</tspan>
</text>
</g>
<g transform="translate(228, 223)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-6"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.png</tspan>
</text>
</g>
<g transform="translate(116, 391)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-7"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.tiff</tspan>
</text>
</g>
<g transform="translate(116, 279)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-8"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.ico</tspan>
</text>
</g>
<g transform="translate(116, 167)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-9"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.pnm</tspan>
</text>
</g>
<g transform="translate(4, 447)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-10"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.bmp</tspan>
</text>
</g>
<g transform="translate(4, 335)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-11"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.tga</tspan>
</text>
</g>
<g transform="translate(4, 223)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-12"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.hdr</tspan>
</text>
</g>
<g transform="translate(4, 111)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-13"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.dxt</tspan>
</text>
</g>
</g>
</svg>`)
ctx.drawImage(Arrow, 80, 60)
const ViceCityGradient = ctx.createLinearGradient(0, 0, 1200, 0)
ViceCityGradient.addColorStop(0, '#3494e6')
ViceCityGradient.addColorStop(1, '#EC6EAD')
ctx.fillStyle = ViceCityGradient
ctx.fillRect(0, 0, 1200, 700)
fs.writeFile(
'public/img/og.png',
await pngQuantize(await canvas.encode('png'), {
maxQuality: 90,
minQuality: 75,
}),
)

View File

@ -4,6 +4,7 @@
"version": "0.0.0",
"type": "module",
"dependencies": {
"@napi-rs/canvas": "^0.1.21",
"@napi-rs/image": "^1.1.1",
"chalk": "^5.0.1",
"markdown-to-jsx": "^7.1.7",

View File

@ -553,6 +553,15 @@ huerotate(hue: number): this
| ------------------------- | ----------------------------------- |
| ![](img/un-optimized.png) | ![](img/huerotate.manipulated.webp) |
#### `crop`
> Crop a cut-out of this image delimited by the bounding rectangle.
`crop(270, 40, 500, 500)`
| Image | Output |
| ------------------------- | ----------------------------------- |
| ![](img/un-optimized.png) | ![](img/crop.manipulated.webp) |
## Optimize PNG
### Lossless compression

View File

@ -6,39 +6,47 @@ import chalk from 'chalk'
const PNG = await fs.readFile('./un-optimized.png')
const TAJ_ORIG = await fs.readFile('./taj_orig.jpg')
await fs.writeFile('grayscale.manipulated.webp', await new Transformer(PNG).grayscale().webp())
try {
await fs.writeFile('grayscale.manipulated.webp', await new Transformer(PNG).grayscale().webp())
console.info(chalk.cyanBright(`Grayscale PNG done`))
console.info(chalk.cyanBright(`Grayscale PNG done`))
await fs.writeFile('invert.manipulated.webp', await new Transformer(PNG).invert().webp())
await fs.writeFile('invert.manipulated.webp', await new Transformer(PNG).invert().webp())
console.info(chalk.cyanBright(`Invert PNG done`))
console.info(chalk.cyanBright(`Invert PNG done`))
await fs.writeFile('blur.manipulated.webp', await new Transformer(PNG).blur(10).webp())
await fs.writeFile('blur.manipulated.webp', await new Transformer(PNG).blur(10).webp())
console.info(chalk.cyanBright(`Blur PNG done`))
console.info(chalk.cyanBright(`Blur PNG done`))
await fs.writeFile('unsharpen.manipulated.webp', await new Transformer(TAJ_ORIG).unsharpen(10, 10).webp())
await fs.writeFile('unsharpen.manipulated.webp', await new Transformer(TAJ_ORIG).unsharpen(10, 10).webp())
console.info(chalk.cyanBright(`Unsharpen PNG done`))
console.info(chalk.cyanBright(`Unsharpen PNG done`))
// https://en.wikipedia.org/wiki/Kernel_(image_processing)#Details
// Sharpen:
await fs.writeFile(
'filter3x3.manipulated.webp',
await new Transformer(PNG).filter3x3([0, -1, 0, -1, 5, -1, 0, -1, 0]).webp(),
)
// https://en.wikipedia.org/wiki/Kernel_(image_processing)#Details
// Sharpen:
await fs.writeFile(
'filter3x3.manipulated.webp',
await new Transformer(PNG).filter3x3([0, -1, 0, -1, 5, -1, 0, -1, 0]).webp(),
)
console.info(chalk.cyanBright(`filter3x3 PNG done`))
console.info(chalk.cyanBright(`filter3x3 PNG done`))
await fs.writeFile('contrast.manipulated.webp', await new Transformer(PNG).adjustContrast(50).webp())
await fs.writeFile('contrast.manipulated.webp', await new Transformer(PNG).adjustContrast(50).webp())
console.info(chalk.cyanBright(`AdjustContrast PNG done`))
console.info(chalk.cyanBright(`AdjustContrast PNG done`))
await fs.writeFile('brighten.manipulated.webp', await new Transformer(PNG).brighten(30).webp())
await fs.writeFile('brighten.manipulated.webp', await new Transformer(PNG).brighten(30).webp())
console.info(chalk.cyanBright(`Brighten PNG done`))
console.info(chalk.cyanBright(`Brighten PNG done`))
await fs.writeFile('huerotate.manipulated.webp', await new Transformer(PNG).huerotate(90).webp())
await fs.writeFile('huerotate.manipulated.webp', await new Transformer(PNG).huerotate(90).webp())
console.info(chalk.cyanBright(`Huerotate PNG done`))
console.info(chalk.cyanBright(`Huerotate PNG done`))
await fs.writeFile('crop.manipulated.webp', await new Transformer(PNG).crop(270, 40, 500, 500).webp())
console.info(chalk.cyanBright(`Crop PNG done`))
} catch (e) {
console.error(e)
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.2 KiB

100
yarn.lock
View File

@ -891,6 +891,105 @@ __metadata:
languageName: node
linkType: hard
"@napi-rs/canvas-android-arm64@npm:0.1.21":
version: 0.1.21
resolution: "@napi-rs/canvas-android-arm64@npm:0.1.21"
conditions: os=android & cpu=arm64
languageName: node
linkType: hard
"@napi-rs/canvas-darwin-arm64@npm:0.1.21":
version: 0.1.21
resolution: "@napi-rs/canvas-darwin-arm64@npm:0.1.21"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"@napi-rs/canvas-darwin-x64@npm:0.1.21":
version: 0.1.21
resolution: "@napi-rs/canvas-darwin-x64@npm:0.1.21"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"@napi-rs/canvas-linux-arm-gnueabihf@npm:0.1.21":
version: 0.1.21
resolution: "@napi-rs/canvas-linux-arm-gnueabihf@npm:0.1.21"
conditions: os=linux & cpu=arm
languageName: node
linkType: hard
"@napi-rs/canvas-linux-arm64-gnu@npm:0.1.21":
version: 0.1.21
resolution: "@napi-rs/canvas-linux-arm64-gnu@npm:0.1.21"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
"@napi-rs/canvas-linux-arm64-musl@npm:0.1.21":
version: 0.1.21
resolution: "@napi-rs/canvas-linux-arm64-musl@npm:0.1.21"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
"@napi-rs/canvas-linux-x64-gnu@npm:0.1.21":
version: 0.1.21
resolution: "@napi-rs/canvas-linux-x64-gnu@npm:0.1.21"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
"@napi-rs/canvas-linux-x64-musl@npm:0.1.21":
version: 0.1.21
resolution: "@napi-rs/canvas-linux-x64-musl@npm:0.1.21"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
"@napi-rs/canvas-win32-x64-msvc@npm:0.1.21":
version: 0.1.21
resolution: "@napi-rs/canvas-win32-x64-msvc@npm:0.1.21"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
"@napi-rs/canvas@npm:^0.1.21":
version: 0.1.21
resolution: "@napi-rs/canvas@npm:0.1.21"
dependencies:
"@napi-rs/canvas-android-arm64": 0.1.21
"@napi-rs/canvas-darwin-arm64": 0.1.21
"@napi-rs/canvas-darwin-x64": 0.1.21
"@napi-rs/canvas-linux-arm-gnueabihf": 0.1.21
"@napi-rs/canvas-linux-arm64-gnu": 0.1.21
"@napi-rs/canvas-linux-arm64-musl": 0.1.21
"@napi-rs/canvas-linux-x64-gnu": 0.1.21
"@napi-rs/canvas-linux-x64-musl": 0.1.21
"@napi-rs/canvas-win32-x64-msvc": 0.1.21
dependenciesMeta:
"@napi-rs/canvas-android-arm64":
optional: true
"@napi-rs/canvas-darwin-arm64":
optional: true
"@napi-rs/canvas-darwin-x64":
optional: true
"@napi-rs/canvas-linux-arm-gnueabihf":
optional: true
"@napi-rs/canvas-linux-arm64-gnu":
optional: true
"@napi-rs/canvas-linux-arm64-musl":
optional: true
"@napi-rs/canvas-linux-x64-gnu":
optional: true
"@napi-rs/canvas-linux-x64-musl":
optional: true
"@napi-rs/canvas-win32-x64-msvc":
optional: true
checksum: 0ea06942864be35b145d58ebbb3b15fa1c80b0c9838f8cbed3c1708c0d7094d05f2c3e937075e801c71a70652854474b78d747aaccc431819941e36548d6a9e2
languageName: node
linkType: hard
"@napi-rs/cli@npm:^2.6.2":
version: 2.6.2
resolution: "@napi-rs/cli@npm:2.6.2"
@ -9279,6 +9378,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "website@workspace:website"
dependencies:
"@napi-rs/canvas": ^0.1.21
"@napi-rs/image": ^1.1.1
chalk: ^5.0.1
markdown-to-jsx: ^7.1.7