@effing/satori 0.17.1 → 0.18.0
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/dist/chunk-LTOYRKNH.js +59 -0
- package/dist/chunk-LTOYRKNH.js.map +1 -0
- package/dist/emoji.d.ts +11 -0
- package/dist/emoji.js +15 -0
- package/dist/emoji.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -53
- package/dist/index.js.map +1 -1
- package/dist/pool/index.d.ts +1 -1
- package/package.json +5 -1
- package/dist/emoji-CtRDUFb8.d.ts +0 -6
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// src/emoji.ts
|
|
2
|
+
var emojiApis = {
|
|
3
|
+
twemoji: (code) => `https://cdnjs.cloudflare.com/ajax/libs/twemoji/16.0.1/svg/${code.toLowerCase()}.svg`,
|
|
4
|
+
openmoji: "https://cdn.jsdelivr.net/npm/@svgmoji/openmoji@2.0.0/svg/",
|
|
5
|
+
blobmoji: "https://cdn.jsdelivr.net/npm/@svgmoji/blob@2.0.0/svg/",
|
|
6
|
+
noto: "https://cdn.jsdelivr.net/gh/svgmoji/svgmoji/packages/svgmoji__noto/svg/",
|
|
7
|
+
fluent: (code) => `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${code.toLowerCase()}_color.svg`,
|
|
8
|
+
fluentFlat: (code) => `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${code.toLowerCase()}_flat.svg`
|
|
9
|
+
};
|
|
10
|
+
var U200D = String.fromCharCode(8205);
|
|
11
|
+
var UFE0Fg = /\uFE0F/g;
|
|
12
|
+
function getEmojiCode(char) {
|
|
13
|
+
return toCodePoint(char.indexOf(U200D) < 0 ? char.replace(UFE0Fg, "") : char);
|
|
14
|
+
}
|
|
15
|
+
function toCodePoint(unicodeSurrogates) {
|
|
16
|
+
const r = [];
|
|
17
|
+
let c = 0, p = 0, i = 0;
|
|
18
|
+
while (i < unicodeSurrogates.length) {
|
|
19
|
+
c = unicodeSurrogates.charCodeAt(i++);
|
|
20
|
+
if (p) {
|
|
21
|
+
r.push((65536 + (p - 55296 << 10) + (c - 56320)).toString(16));
|
|
22
|
+
p = 0;
|
|
23
|
+
} else if (55296 <= c && c <= 56319) {
|
|
24
|
+
p = c;
|
|
25
|
+
} else {
|
|
26
|
+
r.push(c.toString(16));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return r.join("-");
|
|
30
|
+
}
|
|
31
|
+
var emojiCache = {};
|
|
32
|
+
async function loadEmoji(type, code) {
|
|
33
|
+
const key = type + ":" + code;
|
|
34
|
+
if (key in emojiCache) return emojiCache[key];
|
|
35
|
+
const api = emojiApis[type];
|
|
36
|
+
if (typeof api === "function") {
|
|
37
|
+
return emojiCache[key] = fetch(api(code)).then((r) => r.text());
|
|
38
|
+
}
|
|
39
|
+
return emojiCache[key] = fetch(`${api}${code.toUpperCase()}.svg`).then(
|
|
40
|
+
(r) => r.text()
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
function makeLoadAdditionalAsset(emoji) {
|
|
44
|
+
return async (code, segment) => {
|
|
45
|
+
if (code === "emoji") {
|
|
46
|
+
return "data:image/svg+xml;base64," + btoa(await loadEmoji(emoji, getEmojiCode(segment)));
|
|
47
|
+
}
|
|
48
|
+
return segment;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
emojiApis,
|
|
54
|
+
getEmojiCode,
|
|
55
|
+
toCodePoint,
|
|
56
|
+
loadEmoji,
|
|
57
|
+
makeLoadAdditionalAsset
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=chunk-LTOYRKNH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/emoji.ts"],"sourcesContent":["/**\n * Emoji style options for rendering\n */\nexport type EmojiStyle =\n | \"twemoji\"\n | \"openmoji\"\n | \"blobmoji\"\n | \"noto\"\n | \"fluent\"\n | \"fluentFlat\";\n\nexport const emojiApis: Record<\n EmojiStyle,\n string | ((code: string) => string)\n> = {\n twemoji: (code: string) =>\n `https://cdnjs.cloudflare.com/ajax/libs/twemoji/16.0.1/svg/${code.toLowerCase()}.svg`,\n openmoji: \"https://cdn.jsdelivr.net/npm/@svgmoji/openmoji@2.0.0/svg/\",\n blobmoji: \"https://cdn.jsdelivr.net/npm/@svgmoji/blob@2.0.0/svg/\",\n noto: \"https://cdn.jsdelivr.net/gh/svgmoji/svgmoji/packages/svgmoji__noto/svg/\",\n fluent: (code: string) =>\n `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${code.toLowerCase()}_color.svg`,\n fluentFlat: (code: string) =>\n `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${code.toLowerCase()}_flat.svg`,\n};\n\nconst U200D = String.fromCharCode(8205);\nconst UFE0Fg = /\\uFE0F/g;\n\nexport function getEmojiCode(char: string): string {\n return toCodePoint(char.indexOf(U200D) < 0 ? char.replace(UFE0Fg, \"\") : char);\n}\n\nexport function toCodePoint(unicodeSurrogates: string): string {\n const r: string[] = [];\n let c = 0,\n p = 0,\n i = 0;\n\n while (i < unicodeSurrogates.length) {\n c = unicodeSurrogates.charCodeAt(i++);\n if (p) {\n r.push((65536 + ((p - 55296) << 10) + (c - 56320)).toString(16));\n p = 0;\n } else if (55296 <= c && c <= 56319) {\n p = c;\n } else {\n r.push(c.toString(16));\n }\n }\n return r.join(\"-\");\n}\n\nconst emojiCache: Record<string, Promise<string>> = {};\n\nexport async function loadEmoji(\n type: EmojiStyle,\n code: string,\n): Promise<string> {\n const key = type + \":\" + code;\n if (key in emojiCache) return emojiCache[key];\n\n const api = emojiApis[type];\n if (typeof api === \"function\") {\n return (emojiCache[key] = fetch(api(code)).then((r) => r.text()));\n }\n return (emojiCache[key] = fetch(`${api}${code.toUpperCase()}.svg`).then((r) =>\n r.text(),\n ));\n}\n\nexport function makeLoadAdditionalAsset(emoji: EmojiStyle) {\n return async (code: string, segment: string) => {\n if (code === \"emoji\") {\n return (\n \"data:image/svg+xml;base64,\" +\n btoa(await loadEmoji(emoji, getEmojiCode(segment)))\n );\n }\n return segment;\n };\n}\n"],"mappings":";AAWO,IAAM,YAGT;AAAA,EACF,SAAS,CAAC,SACR,6DAA6D,KAAK,YAAY,CAAC;AAAA,EACjF,UAAU;AAAA,EACV,UAAU;AAAA,EACV,MAAM;AAAA,EACN,QAAQ,CAAC,SACP,qEAAqE,KAAK,YAAY,CAAC;AAAA,EACzF,YAAY,CAAC,SACX,qEAAqE,KAAK,YAAY,CAAC;AAC3F;AAEA,IAAM,QAAQ,OAAO,aAAa,IAAI;AACtC,IAAM,SAAS;AAER,SAAS,aAAa,MAAsB;AACjD,SAAO,YAAY,KAAK,QAAQ,KAAK,IAAI,IAAI,KAAK,QAAQ,QAAQ,EAAE,IAAI,IAAI;AAC9E;AAEO,SAAS,YAAY,mBAAmC;AAC7D,QAAM,IAAc,CAAC;AACrB,MAAI,IAAI,GACN,IAAI,GACJ,IAAI;AAEN,SAAO,IAAI,kBAAkB,QAAQ;AACnC,QAAI,kBAAkB,WAAW,GAAG;AACpC,QAAI,GAAG;AACL,QAAE,MAAM,SAAU,IAAI,SAAU,OAAO,IAAI,QAAQ,SAAS,EAAE,CAAC;AAC/D,UAAI;AAAA,IACN,WAAW,SAAS,KAAK,KAAK,OAAO;AACnC,UAAI;AAAA,IACN,OAAO;AACL,QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAAA,IACvB;AAAA,EACF;AACA,SAAO,EAAE,KAAK,GAAG;AACnB;AAEA,IAAM,aAA8C,CAAC;AAErD,eAAsB,UACpB,MACA,MACiB;AACjB,QAAM,MAAM,OAAO,MAAM;AACzB,MAAI,OAAO,WAAY,QAAO,WAAW,GAAG;AAE5C,QAAM,MAAM,UAAU,IAAI;AAC1B,MAAI,OAAO,QAAQ,YAAY;AAC7B,WAAQ,WAAW,GAAG,IAAI,MAAM,IAAI,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC;AAAA,EACjE;AACA,SAAQ,WAAW,GAAG,IAAI,MAAM,GAAG,GAAG,GAAG,KAAK,YAAY,CAAC,MAAM,EAAE;AAAA,IAAK,CAAC,MACvE,EAAE,KAAK;AAAA,EACT;AACF;AAEO,SAAS,wBAAwB,OAAmB;AACzD,SAAO,OAAO,MAAc,YAAoB;AAC9C,QAAI,SAAS,SAAS;AACpB,aACE,+BACA,KAAK,MAAM,UAAU,OAAO,aAAa,OAAO,CAAC,CAAC;AAAA,IAEtD;AACA,WAAO;AAAA,EACT;AACF;","names":[]}
|
package/dist/emoji.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emoji style options for rendering
|
|
3
|
+
*/
|
|
4
|
+
type EmojiStyle = "twemoji" | "openmoji" | "blobmoji" | "noto" | "fluent" | "fluentFlat";
|
|
5
|
+
declare const emojiApis: Record<EmojiStyle, string | ((code: string) => string)>;
|
|
6
|
+
declare function getEmojiCode(char: string): string;
|
|
7
|
+
declare function toCodePoint(unicodeSurrogates: string): string;
|
|
8
|
+
declare function loadEmoji(type: EmojiStyle, code: string): Promise<string>;
|
|
9
|
+
declare function makeLoadAdditionalAsset(emoji: EmojiStyle): (code: string, segment: string) => Promise<string>;
|
|
10
|
+
|
|
11
|
+
export { type EmojiStyle, emojiApis, getEmojiCode, loadEmoji, makeLoadAdditionalAsset, toCodePoint };
|
package/dist/emoji.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
emojiApis,
|
|
3
|
+
getEmojiCode,
|
|
4
|
+
loadEmoji,
|
|
5
|
+
makeLoadAdditionalAsset,
|
|
6
|
+
toCodePoint
|
|
7
|
+
} from "./chunk-LTOYRKNH.js";
|
|
8
|
+
export {
|
|
9
|
+
emojiApis,
|
|
10
|
+
getEmojiCode,
|
|
11
|
+
loadEmoji,
|
|
12
|
+
makeLoadAdditionalAsset,
|
|
13
|
+
toCodePoint
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=emoji.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,59 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
makeLoadAdditionalAsset
|
|
3
|
+
} from "./chunk-LTOYRKNH.js";
|
|
4
|
+
|
|
1
5
|
// src/index.ts
|
|
2
6
|
import { Resvg } from "@resvg/resvg-js";
|
|
3
7
|
import satori from "satori";
|
|
4
|
-
|
|
5
|
-
// src/emoji.ts
|
|
6
|
-
var emojiApis = {
|
|
7
|
-
twemoji: (code) => `https://cdnjs.cloudflare.com/ajax/libs/twemoji/16.0.1/svg/${code.toLowerCase()}.svg`,
|
|
8
|
-
openmoji: "https://cdn.jsdelivr.net/npm/@svgmoji/openmoji@2.0.0/svg/",
|
|
9
|
-
blobmoji: "https://cdn.jsdelivr.net/npm/@svgmoji/blob@2.0.0/svg/",
|
|
10
|
-
noto: "https://cdn.jsdelivr.net/gh/svgmoji/svgmoji/packages/svgmoji__noto/svg/",
|
|
11
|
-
fluent: (code) => `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${code.toLowerCase()}_color.svg`,
|
|
12
|
-
fluentFlat: (code) => `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${code.toLowerCase()}_flat.svg`
|
|
13
|
-
};
|
|
14
|
-
var U200D = String.fromCharCode(8205);
|
|
15
|
-
var UFE0Fg = /\uFE0F/g;
|
|
16
|
-
function getEmojiCode(char) {
|
|
17
|
-
return toCodePoint(char.indexOf(U200D) < 0 ? char.replace(UFE0Fg, "") : char);
|
|
18
|
-
}
|
|
19
|
-
function toCodePoint(unicodeSurrogates) {
|
|
20
|
-
const r = [];
|
|
21
|
-
let c = 0, p = 0, i = 0;
|
|
22
|
-
while (i < unicodeSurrogates.length) {
|
|
23
|
-
c = unicodeSurrogates.charCodeAt(i++);
|
|
24
|
-
if (p) {
|
|
25
|
-
r.push((65536 + (p - 55296 << 10) + (c - 56320)).toString(16));
|
|
26
|
-
p = 0;
|
|
27
|
-
} else if (55296 <= c && c <= 56319) {
|
|
28
|
-
p = c;
|
|
29
|
-
} else {
|
|
30
|
-
r.push(c.toString(16));
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return r.join("-");
|
|
34
|
-
}
|
|
35
|
-
var emojiCache = {};
|
|
36
|
-
async function loadEmoji(type, code) {
|
|
37
|
-
const key = type + ":" + code;
|
|
38
|
-
if (key in emojiCache) return emojiCache[key];
|
|
39
|
-
const api = emojiApis[type];
|
|
40
|
-
if (typeof api === "function") {
|
|
41
|
-
return emojiCache[key] = fetch(api(code)).then((r) => r.text());
|
|
42
|
-
}
|
|
43
|
-
return emojiCache[key] = fetch(`${api}${code.toUpperCase()}.svg`).then(
|
|
44
|
-
(r) => r.text()
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
function makeLoadAdditionalAsset(emoji) {
|
|
48
|
-
return async (code, segment) => {
|
|
49
|
-
if (code === "emoji") {
|
|
50
|
-
return "data:image/svg+xml;base64," + btoa(await loadEmoji(emoji, getEmojiCode(segment)));
|
|
51
|
-
}
|
|
52
|
-
return segment;
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// src/index.ts
|
|
57
8
|
async function svgFromSatori(template, { width, height, fonts, emoji = "twemoji" }) {
|
|
58
9
|
return satori(template, {
|
|
59
10
|
width,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Resvg } from \"@resvg/resvg-js\";\nimport satori from \"satori\";\n\nimport { makeLoadAdditionalAsset } from \"./emoji.ts\";\nimport type { EmojiStyle } from \"./emoji.ts\";\n\nexport type { EmojiStyle } from \"./emoji.ts\";\n\n/**\n * Font data for satori rendering\n */\nexport type FontData = {\n name: string;\n data: Buffer | ArrayBuffer;\n weight: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;\n style: \"normal\" | \"italic\";\n};\n\n/**\n * Options for satori rendering functions\n */\nexport type SatoriOptions = {\n /** Frame width in pixels */\n width: number;\n /** Frame height in pixels */\n height: number;\n /** Font data for text rendering */\n fonts: FontData[];\n /** Emoji style to use (default: \"twemoji\") */\n emoji?: EmojiStyle;\n};\n\n/**\n * @deprecated Use `SatoriOptions` instead\n */\nexport type PngFromSatoriOptions = SatoriOptions;\n\n/**\n * Render a React/JSX template to an SVG string using Satori\n *\n * @param template React element to render\n * @param options Rendering options\n * @returns SVG markup as a string\n */\nexport async function svgFromSatori(\n template: Parameters<typeof satori>[0],\n { width, height, fonts, emoji = \"twemoji\" }: SatoriOptions,\n): Promise<string> {\n return satori(template, {\n width,\n height,\n fonts,\n loadAdditionalAsset: makeLoadAdditionalAsset(emoji),\n });\n}\n\n/**\n * Rasterize an SVG string to a PNG buffer using Resvg\n *\n * @param svg SVG markup string\n * @returns PNG image as a Buffer\n */\nexport function rasterizeSvg(svg: string): Buffer {\n const resvg = new Resvg(svg, { font: { loadSystemFonts: false } });\n return resvg.render().asPng();\n}\n\n/**\n * Render a React/JSX template to a PNG buffer using Satori\n *\n * @param template React element to render\n * @param options Rendering options\n * @returns PNG image as a Buffer\n *\n * @example\n * ```tsx\n * const png = await pngFromSatori(\n * <div style={{ fontSize: 48, color: \"white\" }}>Hello World</div>,\n * { width: 1080, height: 1080, fonts: [myFont] }\n * );\n * ```\n */\nexport async function pngFromSatori(\n template: Parameters<typeof satori>[0],\n options: SatoriOptions,\n): Promise<Buffer> {\n const svg = await svgFromSatori(template, options);\n return rasterizeSvg(svg);\n}\n"],"mappings":";;;;;AAAA,SAAS,aAAa;AACtB,OAAO,YAAY;AA2CnB,eAAsB,cACpB,UACA,EAAE,OAAO,QAAQ,OAAO,QAAQ,UAAU,GACzB;AACjB,SAAO,OAAO,UAAU;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBAAqB,wBAAwB,KAAK;AAAA,EACpD,CAAC;AACH;AAQO,SAAS,aAAa,KAAqB;AAChD,QAAM,QAAQ,IAAI,MAAM,KAAK,EAAE,MAAM,EAAE,iBAAiB,MAAM,EAAE,CAAC;AACjE,SAAO,MAAM,OAAO,EAAE,MAAM;AAC9B;AAiBA,eAAsB,cACpB,UACA,SACiB;AACjB,QAAM,MAAM,MAAM,cAAc,UAAU,OAAO;AACjD,SAAO,aAAa,GAAG;AACzB;","names":[]}
|
package/dist/pool/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effing/satori",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Render JSX to PNG using Satori with emoji support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
"types": "./dist/pool/index.d.ts",
|
|
17
17
|
"import": "./dist/pool/index.js"
|
|
18
18
|
},
|
|
19
|
+
"./emoji": {
|
|
20
|
+
"types": "./dist/emoji.d.ts",
|
|
21
|
+
"import": "./dist/emoji.js"
|
|
22
|
+
},
|
|
19
23
|
"./worker": {
|
|
20
24
|
"import": "./dist/worker/index.js"
|
|
21
25
|
}
|