koishi-plugin-vercel-satori-png-service 0.1.9 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Satori.d.ts +6 -3
- package/lib/index.d.ts +11 -7
- package/lib/index.js +133 -65
- package/lib/og.d.ts +12 -2
- package/package.json +7 -2
- package/readme.md +11 -2
- package/lib/emoji.d.ts +0 -15
- package/lib/language.d.ts +0 -28
package/lib/Satori.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Readable } from "node:stream";
|
|
2
2
|
import * as resvg from "@resvg/resvg-wasm";
|
|
3
|
+
import Vips from "wasm-vips";
|
|
3
4
|
import { ReactElement } from "react";
|
|
4
|
-
import { ImageOptions } from "./og";
|
|
5
|
+
import { ImageOptions, Logger } from "./og";
|
|
5
6
|
export declare const initSatori: () => Promise<void>;
|
|
6
|
-
export declare const createNodejsStream: (element: ReactElement<any, any>, options: ImageOptions) => Promise<Readable>;
|
|
7
|
-
export declare const renderSvg: (element: ReactElement<any, any>, options: ImageOptions) => Promise<string>;
|
|
8
7
|
export declare const getResvg: () => new (svg: Uint8Array | string, options?: resvg.ResvgRenderOptions) => {
|
|
9
8
|
free(): void;
|
|
10
9
|
render(): {
|
|
@@ -41,3 +40,7 @@ export declare const getResvg: () => new (svg: Uint8Array | string, options?: re
|
|
|
41
40
|
readonly height: number;
|
|
42
41
|
readonly width: number;
|
|
43
42
|
};
|
|
43
|
+
export declare const getVips: () => typeof Vips;
|
|
44
|
+
export declare const createNodejsStream: (element: ReactElement<any, any>, options: ImageOptions, logger: Logger) => Promise<Readable>;
|
|
45
|
+
export declare const svgToPng: (svg: string, options: ImageOptions, logger: Logger) => Promise<Readable>;
|
|
46
|
+
export declare const renderSvg: (element: ReactElement<any, any>, options: ImageOptions, logger: Logger) => Promise<string>;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Context, Schema, Service } from "koishi";
|
|
2
2
|
import { ReactElement } from "react";
|
|
3
|
+
import SkiaCanvas from "skia-canvas";
|
|
3
4
|
import { Readable } from "stream";
|
|
4
5
|
import { Font, ImageOptions } from "./og";
|
|
5
6
|
export { Font, ImageOptions } from "./og";
|
|
@@ -14,15 +15,8 @@ declare class VercelSatoriPngService extends Service {
|
|
|
14
15
|
private fonts;
|
|
15
16
|
constructor(ctx: Context, config: VercelSatoriPngService.Config);
|
|
16
17
|
start(): Promise<void>;
|
|
17
|
-
jsxToReactElement(jsxCode: string, data?: Record<any, any>): Promise<ReactElement<any, any>>;
|
|
18
|
-
htmlToReactElement(htmlCode: string): ReactElement<any, any>;
|
|
19
18
|
addFont(fonts: Font[]): void;
|
|
20
19
|
removeFont(fonts: Font[]): void;
|
|
21
|
-
private buildOptions;
|
|
22
|
-
jsxToPng(jsxCode: string, options?: ImageOptions, data?: Record<any, any>): Promise<Readable>;
|
|
23
|
-
htmlToPng(htmlCode: string, options?: ImageOptions): Promise<Readable>;
|
|
24
|
-
reactElementToPng(reactElement: ReactElement<any, any>, options?: ImageOptions): Promise<Readable>;
|
|
25
|
-
reactElementToSvg(reactElement: ReactElement<any, any>, options?: ImageOptions): Promise<string>;
|
|
26
20
|
getResvg(): new (svg: Uint8Array | string, options?: import("@resvg/resvg-wasm").ResvgRenderOptions) => {
|
|
27
21
|
free(): void;
|
|
28
22
|
render(): {
|
|
@@ -59,6 +53,16 @@ declare class VercelSatoriPngService extends Service {
|
|
|
59
53
|
readonly height: number;
|
|
60
54
|
readonly width: number;
|
|
61
55
|
};
|
|
56
|
+
getVips(): typeof import("wasm-vips");
|
|
57
|
+
getSkiaCanvas(): typeof SkiaCanvas;
|
|
58
|
+
jsxToReactElement(jsxCode: string, data?: Record<any, any>): Promise<ReactElement<any, any>>;
|
|
59
|
+
htmlToReactElement(htmlCode: string): ReactElement<any, any>;
|
|
60
|
+
jsxToPng(jsxCode: string, options?: ImageOptions, data?: Record<any, any>): Promise<Readable>;
|
|
61
|
+
htmlToPng(htmlCode: string, options?: ImageOptions): Promise<Readable>;
|
|
62
|
+
private buildOptions;
|
|
63
|
+
reactElementToPng(reactElement: ReactElement<any, any>, options?: ImageOptions): Promise<Readable>;
|
|
64
|
+
svgToPng(svg: string, options?: ImageOptions): Promise<Readable>;
|
|
65
|
+
reactElementToSvg(reactElement: ReactElement<any, any>, options?: ImageOptions): Promise<string>;
|
|
62
66
|
}
|
|
63
67
|
declare namespace VercelSatoriPngService {
|
|
64
68
|
const usage: string;
|
package/lib/index.js
CHANGED
|
@@ -37,6 +37,7 @@ var import_koishi = require("koishi");
|
|
|
37
37
|
var import_react = __toESM(require("react"));
|
|
38
38
|
var import_sucrase = require("sucrase");
|
|
39
39
|
var import_html_react_parser = __toESM(require("html-react-parser"));
|
|
40
|
+
var import_skia_canvas2 = __toESM(require("skia-canvas"));
|
|
40
41
|
|
|
41
42
|
// src/Satori.ts
|
|
42
43
|
var import_node_path = __toESM(require("node:path"));
|
|
@@ -44,6 +45,7 @@ var import_promises = __toESM(require("node:fs/promises"));
|
|
|
44
45
|
var import_node_module = require("node:module");
|
|
45
46
|
var import_node_stream = require("node:stream");
|
|
46
47
|
var resvg = __toESM(require("@resvg/resvg-wasm"));
|
|
48
|
+
var import_wasm_vips = __toESM(require("wasm-vips"));
|
|
47
49
|
|
|
48
50
|
// src/emoji.ts
|
|
49
51
|
var U200D = String.fromCharCode(8205);
|
|
@@ -192,6 +194,9 @@ var languageFontMap = {
|
|
|
192
194
|
};
|
|
193
195
|
|
|
194
196
|
// src/og.ts
|
|
197
|
+
var import_skia_canvas = __toESM(require("skia-canvas"));
|
|
198
|
+
var import_canvg = require("canvg");
|
|
199
|
+
var import_jsdom = require("jsdom");
|
|
195
200
|
async function loadGoogleFont(font, text) {
|
|
196
201
|
if (!font || !text) return;
|
|
197
202
|
const API = `https://fonts.googleapis.com/css2?family=${font}&text=${encodeURIComponent(
|
|
@@ -250,18 +255,9 @@ var loadDynamicAsset = /* @__PURE__ */ __name(({ emoji }) => {
|
|
|
250
255
|
return asset;
|
|
251
256
|
};
|
|
252
257
|
}, "loadDynamicAsset");
|
|
253
|
-
function
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
debug: false
|
|
257
|
-
},
|
|
258
|
-
opts
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
__name(mergeOptions, "mergeOptions");
|
|
262
|
-
async function renderSvg(satori2, opts, defaultFonts, element) {
|
|
263
|
-
const options = mergeOptions(opts);
|
|
264
|
-
return await satori2(element, {
|
|
258
|
+
async function renderSvg(satori2, logger, options, defaultFonts, element) {
|
|
259
|
+
const startTime = options.showLog ? Date.now() : void 0;
|
|
260
|
+
const svg = await satori2(element, {
|
|
265
261
|
width: options.width,
|
|
266
262
|
height: options.height,
|
|
267
263
|
debug: options.debug,
|
|
@@ -270,38 +266,80 @@ async function renderSvg(satori2, opts, defaultFonts, element) {
|
|
|
270
266
|
emoji: options.emoji
|
|
271
267
|
})
|
|
272
268
|
});
|
|
269
|
+
if (options.showLog) {
|
|
270
|
+
logger(
|
|
271
|
+
`renderSvg time: ${Date.now() - startTime}ms; svg size: ${svg.length}`
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
return svg;
|
|
273
275
|
}
|
|
274
276
|
__name(renderSvg, "renderSvg");
|
|
275
|
-
async function
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
277
|
+
async function svgToPng(resvg2, vips2, logger, options, svg) {
|
|
278
|
+
const startTime = options.showLog ? Date.now() : void 0;
|
|
279
|
+
let pngBuffer;
|
|
280
|
+
switch (options.converter) {
|
|
281
|
+
case "skia-canvas-canvg": {
|
|
282
|
+
const canvas = new import_skia_canvas.default.Canvas(1, 1);
|
|
283
|
+
const ctx = canvas.getContext("2d");
|
|
284
|
+
const dom = new import_jsdom.JSDOM();
|
|
285
|
+
const v = import_canvg.Canvg.fromString(ctx, svg, {
|
|
286
|
+
window: dom.window,
|
|
287
|
+
DOMParser: dom.window.DOMParser,
|
|
288
|
+
createCanvas: /* @__PURE__ */ __name((w, h) => new import_skia_canvas.default.Canvas(w, h), "createCanvas"),
|
|
289
|
+
createImage: import_skia_canvas.default.Image,
|
|
290
|
+
ignoreDimensions: false
|
|
291
|
+
});
|
|
292
|
+
await v.render();
|
|
293
|
+
pngBuffer = await canvas.toBuffer("png");
|
|
294
|
+
break;
|
|
290
295
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
+
case "skia-canvas": {
|
|
297
|
+
const img = await import_skia_canvas.default.loadImage(Buffer.from(svg));
|
|
298
|
+
const canvas = new import_skia_canvas.default.Canvas(img.width, img.height);
|
|
299
|
+
const ctx = canvas.getContext("2d");
|
|
300
|
+
ctx.drawImage(img, 0, 0);
|
|
301
|
+
pngBuffer = await canvas.toBuffer("png");
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
case "vips": {
|
|
305
|
+
const img = vips2.Image.svgloadBuffer(Buffer.from(svg));
|
|
306
|
+
pngBuffer = img.pngsaveBuffer();
|
|
307
|
+
img.delete();
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
case "resvg":
|
|
311
|
+
default: {
|
|
312
|
+
const resvgJS = new resvg2.Resvg(svg);
|
|
313
|
+
const pngData = resvgJS.render();
|
|
314
|
+
pngBuffer = pngData.asPng();
|
|
315
|
+
pngData.free();
|
|
316
|
+
resvgJS.free();
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (options.showLog) {
|
|
321
|
+
logger(
|
|
322
|
+
`svgToPng time: ${Date.now() - startTime}ms; converter:${options.converter}; png size: ${pngBuffer.length}`
|
|
323
|
+
);
|
|
324
|
+
}
|
|
296
325
|
return pngBuffer;
|
|
297
326
|
}
|
|
327
|
+
__name(svgToPng, "svgToPng");
|
|
328
|
+
async function render(satori2, resvg2, vips2, logger, options, defaultFonts, element) {
|
|
329
|
+
const svg = await renderSvg(satori2, logger, options, defaultFonts, element);
|
|
330
|
+
return svgToPng(resvg2, vips2, logger, options, svg);
|
|
331
|
+
}
|
|
298
332
|
__name(render, "render");
|
|
299
333
|
|
|
300
334
|
// src/Satori.ts
|
|
301
335
|
var fontData;
|
|
302
336
|
var satori;
|
|
337
|
+
var vips;
|
|
303
338
|
var initSatori = /* @__PURE__ */ __name(async () => {
|
|
304
339
|
satori = (await import("satori")).default;
|
|
340
|
+
vips = await (0, import_wasm_vips.default)({
|
|
341
|
+
dynamicLibraries: ["vips-resvg.wasm"]
|
|
342
|
+
});
|
|
305
343
|
const require2 = (0, import_node_module.createRequire)("file:///" + __filename);
|
|
306
344
|
const reSvgWasm = import_node_path.default.join(
|
|
307
345
|
import_node_path.default.dirname(require2.resolve("@resvg/resvg-wasm")),
|
|
@@ -312,6 +350,12 @@ var initSatori = /* @__PURE__ */ __name(async () => {
|
|
|
312
350
|
require2.resolve("../noto-sans-v27-latin-regular.ttf")
|
|
313
351
|
);
|
|
314
352
|
}, "initSatori");
|
|
353
|
+
var getResvg = /* @__PURE__ */ __name(() => {
|
|
354
|
+
return resvg.Resvg;
|
|
355
|
+
}, "getResvg");
|
|
356
|
+
var getVips = /* @__PURE__ */ __name(() => {
|
|
357
|
+
return vips;
|
|
358
|
+
}, "getVips");
|
|
315
359
|
var getDefaultFonts = /* @__PURE__ */ __name(() => [
|
|
316
360
|
{
|
|
317
361
|
name: "sans serif",
|
|
@@ -320,22 +364,25 @@ var getDefaultFonts = /* @__PURE__ */ __name(() => [
|
|
|
320
364
|
style: "normal"
|
|
321
365
|
}
|
|
322
366
|
], "getDefaultFonts");
|
|
323
|
-
var createNodejsStream = /* @__PURE__ */ __name(async (element, options) => {
|
|
367
|
+
var createNodejsStream = /* @__PURE__ */ __name(async (element, options, logger) => {
|
|
324
368
|
const result = await render(
|
|
325
369
|
satori,
|
|
326
370
|
resvg,
|
|
371
|
+
vips,
|
|
372
|
+
logger,
|
|
327
373
|
options,
|
|
328
374
|
getDefaultFonts(),
|
|
329
375
|
element
|
|
330
376
|
);
|
|
331
377
|
return import_node_stream.Readable.from(Buffer.from(result));
|
|
332
378
|
}, "createNodejsStream");
|
|
333
|
-
var
|
|
334
|
-
|
|
379
|
+
var svgToPng2 = /* @__PURE__ */ __name(async (svg, options, logger) => {
|
|
380
|
+
const result = await svgToPng(resvg, vips, logger, options, svg);
|
|
381
|
+
return import_node_stream.Readable.from(Buffer.from(result));
|
|
382
|
+
}, "svgToPng");
|
|
383
|
+
var renderSvg2 = /* @__PURE__ */ __name(async (element, options, logger) => {
|
|
384
|
+
return renderSvg(satori, logger, options, getDefaultFonts(), element);
|
|
335
385
|
}, "renderSvg");
|
|
336
|
-
var getResvg = /* @__PURE__ */ __name(() => {
|
|
337
|
-
return resvg.Resvg;
|
|
338
|
-
}, "getResvg");
|
|
339
386
|
|
|
340
387
|
// src/index.ts
|
|
341
388
|
var serviceName = "vercelSatoriPngService";
|
|
@@ -360,6 +407,30 @@ var VercelSatoriPngService = class extends import_koishi.Service {
|
|
|
360
407
|
await initSatori();
|
|
361
408
|
initialized = true;
|
|
362
409
|
}
|
|
410
|
+
addFont(fonts) {
|
|
411
|
+
this.fonts.push(...fonts);
|
|
412
|
+
this.ctx.on("dispose", () => {
|
|
413
|
+
this.removeFont(fonts);
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
removeFont(fonts) {
|
|
417
|
+
fonts.forEach((font) => {
|
|
418
|
+
const index = this.fonts.indexOf(font);
|
|
419
|
+
if (index === -1) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
this.fonts.splice(index, 1);
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
getResvg() {
|
|
426
|
+
return getResvg();
|
|
427
|
+
}
|
|
428
|
+
getVips() {
|
|
429
|
+
return getVips();
|
|
430
|
+
}
|
|
431
|
+
getSkiaCanvas() {
|
|
432
|
+
return import_skia_canvas2.default;
|
|
433
|
+
}
|
|
363
434
|
async jsxToReactElement(jsxCode, data) {
|
|
364
435
|
const hCode = (0, import_sucrase.transform)(jsxCode, {
|
|
365
436
|
transforms: ["jsx"],
|
|
@@ -387,20 +458,14 @@ var VercelSatoriPngService = class extends import_koishi.Service {
|
|
|
387
458
|
htmlToReactElement(htmlCode) {
|
|
388
459
|
return (0, import_html_react_parser.default)(htmlCode);
|
|
389
460
|
}
|
|
390
|
-
|
|
391
|
-
this.
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
461
|
+
async jsxToPng(jsxCode, options, data) {
|
|
462
|
+
return this.reactElementToPng(
|
|
463
|
+
await this.jsxToReactElement(jsxCode, data),
|
|
464
|
+
options
|
|
465
|
+
);
|
|
395
466
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
const index = this.fonts.indexOf(font);
|
|
399
|
-
if (index === -1) {
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
this.fonts.splice(index, 1);
|
|
403
|
-
});
|
|
467
|
+
htmlToPng(htmlCode, options) {
|
|
468
|
+
return this.reactElementToPng(this.htmlToReactElement(htmlCode), options);
|
|
404
469
|
}
|
|
405
470
|
buildOptions(options) {
|
|
406
471
|
options ||= {};
|
|
@@ -410,27 +475,30 @@ var VercelSatoriPngService = class extends import_koishi.Service {
|
|
|
410
475
|
}
|
|
411
476
|
return options;
|
|
412
477
|
}
|
|
413
|
-
async
|
|
414
|
-
return
|
|
415
|
-
|
|
416
|
-
options
|
|
478
|
+
async reactElementToPng(reactElement, options) {
|
|
479
|
+
return createNodejsStream(
|
|
480
|
+
reactElement,
|
|
481
|
+
this.buildOptions(options),
|
|
482
|
+
this._ctx.logger.info.bind(this._ctx.logger)
|
|
417
483
|
);
|
|
418
484
|
}
|
|
419
|
-
|
|
420
|
-
return
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
485
|
+
async svgToPng(svg, options) {
|
|
486
|
+
return svgToPng2(
|
|
487
|
+
svg,
|
|
488
|
+
this.buildOptions(options),
|
|
489
|
+
this._ctx.logger.info.bind(this._ctx.logger)
|
|
490
|
+
);
|
|
424
491
|
}
|
|
425
492
|
async reactElementToSvg(reactElement, options) {
|
|
426
|
-
return renderSvg2(
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
493
|
+
return renderSvg2(
|
|
494
|
+
reactElement,
|
|
495
|
+
this.buildOptions(options),
|
|
496
|
+
this._ctx.logger.info.bind(this._ctx.logger)
|
|
497
|
+
);
|
|
430
498
|
}
|
|
431
499
|
};
|
|
432
500
|
((VercelSatoriPngService2) => {
|
|
433
|
-
VercelSatoriPngService2.usage = 'html to ReactElement <a target="_blank" href="https://www.npmjs.com/package/html-react-parser">html-react-parser</a
|
|
501
|
+
VercelSatoriPngService2.usage = 'html to ReactElement <a target="_blank" href="https://www.npmjs.com/package/html-react-parser">html-react-parser</a><br/>jsx to ReactElement <a target="_blank" href="https://www.npmjs.com/package/sucrase">sucrase</a><br/>ReactElement to svg <a target="_blank" href="https://github.com/vercel/satori#overview">vercel/satori</a> <a target="_blank" href="https://og-playground.vercel.app/">og-playground</a><br/><hr/>svg to png<br/><a target="_blank" href="https://www.npmjs.com/package/@resvg/resvg-wasm">@resvg/resvg-wasm</a><br/><a target="_blank" href="https://www.npmjs.com/package/wasm-vips">wasm-vips</a><br/><a target="_blank" href="https://www.npmjs.com/package/skia-canvas">skia-canvas</a> <a target="_blank" href="https://www.npmjs.com/package/canvg">canvg</a> <a target="_blank" href="https://www.npmjs.com/package/jsdom">jsdom</a><br/>';
|
|
434
502
|
VercelSatoriPngService2.Config = import_koishi.Schema.object({});
|
|
435
503
|
})(VercelSatoriPngService || (VercelSatoriPngService = {}));
|
|
436
504
|
var src_default = VercelSatoriPngService;
|
package/lib/og.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import * as Resvg from "@resvg/resvg-wasm";
|
|
|
3
3
|
import type Satori from "satori";
|
|
4
4
|
import type { SatoriOptions } from "satori";
|
|
5
5
|
import type { ReactElement } from "react";
|
|
6
|
+
import type Vips from "wasm-vips";
|
|
6
7
|
export type ImageOptions = {
|
|
7
8
|
/**
|
|
8
9
|
* The width of the image.
|
|
@@ -37,7 +38,16 @@ export type ImageOptions = {
|
|
|
37
38
|
* @default 'twemoji'
|
|
38
39
|
*/
|
|
39
40
|
emoji?: EmojiType;
|
|
41
|
+
/**
|
|
42
|
+
* The converter to use.
|
|
43
|
+
*
|
|
44
|
+
* @default 'resvg'
|
|
45
|
+
*/
|
|
46
|
+
converter?: "resvg" | "vips" | "skia-canvas" | "skia-canvas-canvg";
|
|
47
|
+
showLog?: boolean;
|
|
40
48
|
};
|
|
41
49
|
export type Font = ImageOptions["fonts"][number];
|
|
42
|
-
export
|
|
43
|
-
export
|
|
50
|
+
export type Logger = (msg: string) => void;
|
|
51
|
+
export declare function renderSvg(satori: typeof Satori, logger: Logger, options: ImageOptions, defaultFonts: Font[], element: ReactElement<any, any>): Promise<string>;
|
|
52
|
+
export declare function svgToPng(resvg: typeof Resvg, vips: typeof Vips, logger: Logger, options: ImageOptions, svg: string): Promise<Uint8Array<ArrayBufferLike>>;
|
|
53
|
+
export default function render(satori: typeof Satori, resvg: typeof Resvg, vips: typeof Vips, logger: Logger, options: ImageOptions, defaultFonts: Font[], element: ReactElement<any, any>): Promise<Uint8Array<ArrayBufferLike>>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-vercel-satori-png-service",
|
|
3
3
|
"description": "Use Vercel Satori and Resvg.js to convert html to png",
|
|
4
|
-
"version": "0.1
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
@@ -41,10 +41,14 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@resvg/resvg-wasm": "^2.6.3-alpha.2",
|
|
44
|
+
"canvg": "^4.0.3",
|
|
44
45
|
"html-react-parser": "^5.2.11",
|
|
46
|
+
"jsdom": "27.0.1",
|
|
45
47
|
"react": "^19.3.0-canary-fd524fe0-20251121",
|
|
46
48
|
"satori": "^0.16.2",
|
|
47
|
-
"
|
|
49
|
+
"skia-canvas": "^3.0.8",
|
|
50
|
+
"sucrase": "^3.35.1",
|
|
51
|
+
"wasm-vips": "^0.0.16"
|
|
48
52
|
},
|
|
49
53
|
"koishi": {
|
|
50
54
|
"service": {
|
|
@@ -54,6 +58,7 @@
|
|
|
54
58
|
}
|
|
55
59
|
},
|
|
56
60
|
"devDependencies": {
|
|
61
|
+
"@types/jsdom": "^27",
|
|
57
62
|
"@types/react": "^19"
|
|
58
63
|
}
|
|
59
64
|
}
|
package/readme.md
CHANGED
|
@@ -11,7 +11,16 @@ html to ReactElement [html-react-parser](https://www.npmjs.com/package/html-reac
|
|
|
11
11
|
jsx to ReactElement [sucrase](https://www.npmjs.com/package/sucrase)
|
|
12
12
|
|
|
13
13
|
ReactElement to svg [vercel/satori](https://github.com/vercel/satori#overview)
|
|
14
|
-
|
|
15
14
|
[og-playground](https://og-playground.vercel.app/)
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
svg to png
|
|
19
|
+
|
|
20
|
+
[@resvg/resvg-wasm](https://www.npmjs.com/package/@resvg/resvg-wasm)
|
|
21
|
+
|
|
22
|
+
[wasm-vips](https://www.npmjs.com/package/wasm-vips)
|
|
23
|
+
|
|
24
|
+
[skia-canvas](https://www.npmjs.com/package/skia-canvas)
|
|
25
|
+
[canvg](https://www.npmjs.com/package/canvg)
|
|
26
|
+
[jsdom](https://www.npmjs.com/package/jsdom)
|
package/lib/emoji.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Modified version of https://unpkg.com/twemoji@13.1.0/dist/twemoji.esm.js.
|
|
3
|
-
*/
|
|
4
|
-
export declare function getIconCode(char: string): string;
|
|
5
|
-
declare const apis: {
|
|
6
|
-
twemoji: (code: any) => string;
|
|
7
|
-
openmoji: string;
|
|
8
|
-
blobmoji: string;
|
|
9
|
-
noto: string;
|
|
10
|
-
fluent: (code: any) => string;
|
|
11
|
-
fluentFlat: (code: any) => string;
|
|
12
|
-
};
|
|
13
|
-
export type EmojiType = keyof typeof apis;
|
|
14
|
-
export declare function loadEmoji(code: string, type?: EmojiType): Promise<Response>;
|
|
15
|
-
export {};
|
package/lib/language.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export declare class FontDetector {
|
|
2
|
-
private rangesByLang;
|
|
3
|
-
detect(text: string, fonts: string[]): Promise<{
|
|
4
|
-
[lang: string]: string;
|
|
5
|
-
}>;
|
|
6
|
-
private detectSegment;
|
|
7
|
-
private load;
|
|
8
|
-
private addDetectors;
|
|
9
|
-
}
|
|
10
|
-
export declare const languageFontMap: {
|
|
11
|
-
'ja-JP': string;
|
|
12
|
-
'ko-KR': string;
|
|
13
|
-
'zh-CN': string;
|
|
14
|
-
'zh-TW': string;
|
|
15
|
-
'zh-HK': string;
|
|
16
|
-
'th-TH': string;
|
|
17
|
-
'bn-IN': string;
|
|
18
|
-
'ar-AR': string;
|
|
19
|
-
'ta-IN': string;
|
|
20
|
-
'ml-IN': string;
|
|
21
|
-
'he-IL': string;
|
|
22
|
-
'te-IN': string;
|
|
23
|
-
devanagari: string;
|
|
24
|
-
kannada: string;
|
|
25
|
-
symbol: string[];
|
|
26
|
-
math: string;
|
|
27
|
-
unknown: string;
|
|
28
|
-
};
|