@zhin.js/html-renderer 1.0.4 → 2.0.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/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { createHtmlRenderer } from './renderer.js';
1
+ export { createHtmlRenderer, serializeJsxToHtml } from './renderer.js';
2
2
  export { registerAiTextAsImageOutput, extractPlainTextForImage } from './ai-text-as-image.js';
3
3
  export type { FontConfig, HtmlRendererAiTextAsImageConfig, HtmlRendererConfig, HtmlRendererLogger, HtmlRendererService, OutputFormat, RenderOptions, RenderResult, } from './types.js';
4
4
  /** 动态 import 时使用的包名(与 package.json name 一致) */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAC9F,YAAY,EACV,UAAU,EACV,+BAA+B,EAC/B,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,+CAA+C;AAC/C,eAAO,MAAM,qBAAqB,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAC9F,YAAY,EACV,UAAU,EACV,+BAA+B,EAC/B,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,+CAA+C;AAC/C,eAAO,MAAM,qBAAqB,2BAA2B,CAAC"}
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { createHtmlRenderer } from './renderer.js';
1
+ export { createHtmlRenderer, serializeJsxToHtml } from './renderer.js';
2
2
  export { registerAiTextAsImageOutput, extractPlainTextForImage } from './ai-text-as-image.js';
3
3
  /** 动态 import 时使用的包名(与 package.json name 一致) */
4
4
  export const HTML_RENDERER_PACKAGE = '@zhin.js/html-renderer';
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAY9F,+CAA+C;AAC/C,MAAM,CAAC,MAAM,qBAAqB,GAAG,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAY9F,+CAA+C;AAC/C,MAAM,CAAC,MAAM,qBAAqB,GAAG,wBAAwB,CAAC"}
package/lib/renderer.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  import type { HtmlRendererConfig, HtmlRendererLogger, HtmlRendererService } from './types.js';
2
+ export declare function serializeJsxToHtml(element: unknown): string;
2
3
  export declare function createHtmlRenderer(config?: HtmlRendererConfig, logger?: HtmlRendererLogger): HtmlRendererService;
3
4
  //# sourceMappingURL=renderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EAGpB,MAAM,YAAY,CAAC;AA0MpB,wBAAgB,kBAAkB,CAChC,MAAM,GAAE,kBAAuB,EAC/B,MAAM,CAAC,EAAE,kBAAkB,GAC1B,mBAAmB,CA6ErB"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EAGpB,MAAM,YAAY,CAAC;AA4MpB,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CA8C3D;AAED,wBAAgB,kBAAkB,CAChC,MAAM,GAAE,kBAAuB,EAC/B,MAAM,CAAC,EAAE,kBAAkB,GAC1B,mBAAmB,CA4GrB"}
package/lib/renderer.js CHANGED
@@ -1,14 +1,20 @@
1
- import { htmlToSvg, getAllBuiltinFonts, h } from '@zhin.js/satori';
1
+ import { htmlToSvg, getAllBuiltinFonts, h, e } from '@zhin.js/satori';
2
2
  import { Resvg } from '@resvg/resvg-js';
3
3
  const DEFAULT_CONFIG = {
4
4
  defaultWidth: 800,
5
5
  defaultFonts: [],
6
6
  defaultBackgroundColor: '#ffffff',
7
- cacheFonts: true,
8
- fontUrls: [],
9
7
  };
8
+ /** 外部资源(twemoji CDN)拉取超时 */
9
+ const EMOJI_FETCH_TIMEOUT_MS = 10_000;
10
+ /** 渲染并发上限,防止渲染任务堆积拖垮进程 */
11
+ const MAX_CONCURRENT_RENDERS = 2;
10
12
  const fontCache = new Map();
11
13
  let defaultFontLoaded = false;
14
+ /** fontCache 键:name + weight + style(缺 style 会让 italic 覆盖 normal) */
15
+ function fontCacheKey(name, weight, style) {
16
+ return `${name}-${weight ?? 400}-${style ?? 'normal'}`;
17
+ }
12
18
  function toFontConfig(f) {
13
19
  return { name: f.name, data: f.data, weight: f.weight, style: f.style };
14
20
  }
@@ -34,7 +40,7 @@ function ensureBuiltinFontsCached(logger) {
34
40
  if (builtinFonts.length > 0) {
35
41
  for (const font of builtinFonts) {
36
42
  const fc = toFontConfig(font);
37
- fontCache.set(`${font.name}-${font.weight}`, fc);
43
+ fontCache.set(fontCacheKey(font.name, font.weight, font.style), fc);
38
44
  logger?.debug?.(`Builtin font: ${font.name} (${Math.round(font.data.byteLength / 1024)}KB)`);
39
45
  }
40
46
  fontCache.set('default', toFontConfig(builtinFonts[0]));
@@ -60,7 +66,7 @@ function emojiToTwemojiUrl(emoji) {
60
66
  async function loadEmojiImage(emoji, logger) {
61
67
  try {
62
68
  const url = emojiToTwemojiUrl(emoji);
63
- const response = await fetch(url);
69
+ const response = await fetch(url, { signal: AbortSignal.timeout(EMOJI_FETCH_TIMEOUT_MS) });
64
70
  if (!response.ok) {
65
71
  logger?.debug?.(`Failed to load emoji ${emoji}: ${response.status}`);
66
72
  return null;
@@ -73,14 +79,42 @@ async function loadEmojiImage(emoji, logger) {
73
79
  return null;
74
80
  }
75
81
  }
82
+ const EMOJI_CACHE_MAX = 200;
83
+ /** 失败(null)结果的负缓存 TTL,避免每次渲染都重试失败的 emoji */
84
+ const EMOJI_NEGATIVE_TTL_MS = 60_000;
85
+ /** LRU:Map 迭代顺序即插入顺序,命中时移到末尾,超容量时淘汰最旧项 */
76
86
  const emojiCache = new Map();
87
+ function getCachedEmoji(segment) {
88
+ const entry = emojiCache.get(segment);
89
+ if (!entry)
90
+ return { hit: false, value: null };
91
+ if (entry.value === null && Date.now() - entry.ts > EMOJI_NEGATIVE_TTL_MS) {
92
+ emojiCache.delete(segment);
93
+ return { hit: false, value: null };
94
+ }
95
+ // LRU touch:重新插入到末尾
96
+ emojiCache.delete(segment);
97
+ emojiCache.set(segment, entry);
98
+ return { hit: true, value: entry.value };
99
+ }
100
+ function setCachedEmoji(segment, value) {
101
+ emojiCache.delete(segment);
102
+ emojiCache.set(segment, { value, ts: Date.now() });
103
+ while (emojiCache.size > EMOJI_CACHE_MAX) {
104
+ const oldest = emojiCache.keys().next().value;
105
+ if (oldest === undefined)
106
+ break;
107
+ emojiCache.delete(oldest);
108
+ }
109
+ }
77
110
  async function loadAdditionalAsset(languageCode, segment, logger) {
78
111
  if (languageCode === 'emoji') {
79
- if (emojiCache.has(segment))
80
- return emojiCache.get(segment);
112
+ const cached = getCachedEmoji(segment);
113
+ if (cached.hit)
114
+ return cached.value;
81
115
  const result = await loadEmojiImage(segment, logger);
82
- if (result)
83
- emojiCache.set(segment, result);
116
+ // 失败也缓存(短 TTL 负缓存),防止同一 emoji 反复打爆 CDN
117
+ setCachedEmoji(segment, result);
84
118
  return result;
85
119
  }
86
120
  return null;
@@ -90,7 +124,7 @@ function wrapHtmlFragment(html, backgroundColor) {
90
124
  return html;
91
125
  return `<div style="display:flex;flex-direction:column;width:100%;height:100%;margin:0;padding:0;box-sizing:border-box;background-color:${backgroundColor};font-family:Noto Sans SC,sans-serif">${html}</div>`;
92
126
  }
93
- async function renderHtmlToSvg(html, width, height, fonts, backgroundColor, logger) {
127
+ async function renderHtmlToSvg(html, width, height, fonts, backgroundColor, logger, enableEmoji = true) {
94
128
  ensureBuiltinFontsCached(logger);
95
129
  const finalFonts = mergeFontLists(getAllBuiltinFonts().map(toFontConfig), fonts);
96
130
  if (finalFonts.length === 0) {
@@ -105,7 +139,7 @@ async function renderHtmlToSvg(html, width, height, fonts, backgroundColor, logg
105
139
  weight: f.weight,
106
140
  style: f.style,
107
141
  })),
108
- loadAdditionalAsset: async (code, seg) => (await loadAdditionalAsset(code, seg, logger)) ?? '',
142
+ loadAdditionalAsset: async (code, seg) => enableEmoji ? ((await loadAdditionalAsset(code, seg, logger)) ?? '') : '',
109
143
  });
110
144
  const wm = svg.match(/width="(\d+)"/);
111
145
  const hm = svg.match(/height="(\d+)"/);
@@ -127,11 +161,13 @@ function svgToPng(svg, scale = 1) {
127
161
  const pngData = resvg.render();
128
162
  return Buffer.from(pngData.asPng());
129
163
  }
130
- function serializeJsxToHtml(element) {
131
- if (typeof element === 'string' || typeof element === 'number') {
164
+ export function serializeJsxToHtml(element) {
165
+ if (typeof element === 'string')
166
+ return e(element);
167
+ if (typeof element === 'number')
132
168
  return String(element);
133
- }
134
- if (element == null)
169
+ // boolean / null / undefined 一律渲染为空串
170
+ if (element == null || typeof element === 'boolean')
135
171
  return '';
136
172
  if (Array.isArray(element)) {
137
173
  return element.map(serializeJsxToHtml).join('');
@@ -146,15 +182,16 @@ function serializeJsxToHtml(element) {
146
182
  .join('; ');
147
183
  }
148
184
  const attrs = Object.entries(restProps)
149
- .filter(([key]) => key !== 'dangerouslySetInnerHTML')
150
- .map(([key, value]) => `${key}="${value}"`)
185
+ .filter(([key, value]) => key !== 'dangerouslySetInnerHTML' && value != null && value !== false)
186
+ .map(([key, value]) => `${key}="${e(String(value))}"`)
151
187
  .join(' ');
152
- const styleAttr = styleStr ? ` style="${styleStr}"` : '';
188
+ const styleAttr = styleStr ? ` style="${e(styleStr)}"` : '';
153
189
  const attrStr = attrs ? ` ${attrs}` : '';
190
+ // Raw HTML 只走显式通道 dangerouslySetInnerHTML
154
191
  if (dangerouslySetInnerHTML?.__html) {
155
192
  return `<${type}${attrStr}${styleAttr}>${dangerouslySetInnerHTML.__html}</${type}>`;
156
193
  }
157
- const childrenHtml = children ? serializeJsxToHtml(children) : '';
194
+ const childrenHtml = serializeJsxToHtml(children);
158
195
  const selfClosingTags = ['img', 'br', 'hr', 'input', 'meta', 'link'];
159
196
  if (selfClosingTags.includes(type) && !childrenHtml) {
160
197
  return `<${type}${attrStr}${styleAttr} />`;
@@ -165,33 +202,57 @@ function serializeJsxToHtml(element) {
165
202
  }
166
203
  export function createHtmlRenderer(config = {}, logger) {
167
204
  const mergedConfig = { ...DEFAULT_CONFIG, ...config };
205
+ function cacheDefaultFonts() {
206
+ for (const font of mergedConfig.defaultFonts) {
207
+ fontCache.set(fontCacheKey(font.name, font.weight, font.style), font);
208
+ }
209
+ }
168
210
  ensureBuiltinFontsCached(logger);
169
- for (const font of mergedConfig.defaultFonts) {
170
- fontCache.set(`${font.name}-${font.weight || 400}`, font);
211
+ cacheDefaultFonts();
212
+ // 渲染并发闸:最多 MAX_CONCURRENT_RENDERS 个并发,其余排队
213
+ let activeRenders = 0;
214
+ const renderQueue = [];
215
+ async function acquireRenderSlot() {
216
+ if (activeRenders >= MAX_CONCURRENT_RENDERS) {
217
+ await new Promise((resolve) => renderQueue.push(resolve));
218
+ }
219
+ activeRenders++;
220
+ }
221
+ function releaseRenderSlot() {
222
+ activeRenders--;
223
+ const next = renderQueue.shift();
224
+ if (next)
225
+ next();
171
226
  }
172
227
  return {
173
228
  async render(html, options = {}) {
174
- const { width = mergedConfig.defaultWidth, height, format = 'png', backgroundColor = mergedConfig.defaultBackgroundColor, fonts = [], scale = 1, } = options;
175
- ensureBuiltinFontsCached(logger);
176
- const allFonts = uniqueFontsForRender([...fontCache.values(), ...fonts]);
177
- const { svg, width: actualWidth, height: actualHeight } = await renderHtmlToSvg(html, width, height, allFonts, backgroundColor, logger);
178
- if (format === 'svg') {
229
+ const { width = mergedConfig.defaultWidth, height, format = 'png', backgroundColor = mergedConfig.defaultBackgroundColor, fonts = [], enableEmoji = true, scale = 1, } = options;
230
+ await acquireRenderSlot();
231
+ try {
232
+ ensureBuiltinFontsCached(logger);
233
+ const allFonts = uniqueFontsForRender([...fontCache.values(), ...fonts]);
234
+ const { svg, width: actualWidth, height: actualHeight } = await renderHtmlToSvg(html, width, height, allFonts, backgroundColor, logger, enableEmoji);
235
+ if (format === 'svg') {
236
+ return {
237
+ data: svg,
238
+ format: 'svg',
239
+ width: actualWidth,
240
+ height: actualHeight,
241
+ mimeType: 'image/svg+xml',
242
+ };
243
+ }
244
+ const png = svgToPng(svg, scale);
179
245
  return {
180
- data: svg,
181
- format: 'svg',
182
- width: actualWidth,
183
- height: actualHeight,
184
- mimeType: 'image/svg+xml',
246
+ data: png,
247
+ format: 'png',
248
+ width: Math.round(actualWidth * scale),
249
+ height: Math.round(actualHeight * scale),
250
+ mimeType: 'image/png',
185
251
  };
186
252
  }
187
- const png = svgToPng(svg, scale);
188
- return {
189
- data: png,
190
- format: 'png',
191
- width: Math.round(actualWidth * scale),
192
- height: Math.round(actualHeight * scale),
193
- mimeType: 'image/png',
194
- };
253
+ finally {
254
+ releaseRenderSlot();
255
+ }
195
256
  },
196
257
  async renderJsx(element, options = {}) {
197
258
  return this.render(serializeJsxToHtml(element), options);
@@ -200,7 +261,7 @@ export function createHtmlRenderer(config = {}, logger) {
200
261
  return this.render(h(component, props), options);
201
262
  },
202
263
  registerFont(font) {
203
- fontCache.set(`${font.name}-${font.weight || 400}`, font);
264
+ fontCache.set(fontCacheKey(font.name, font.weight, font.style), font);
204
265
  logger?.debug?.(`Font registered: ${font.name}`);
205
266
  },
206
267
  getFonts() {
@@ -209,6 +270,8 @@ export function createHtmlRenderer(config = {}, logger) {
209
270
  clearFonts() {
210
271
  fontCache.clear();
211
272
  defaultFontLoaded = false;
273
+ // clear 后重新合并 defaultFonts,避免用户配置的默认字体永久丢失
274
+ cacheDefaultFonts();
212
275
  logger?.debug?.('Font cache cleared');
213
276
  },
214
277
  };
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
package/lib/types.d.ts CHANGED
@@ -41,8 +41,6 @@ export interface HtmlRendererConfig {
41
41
  defaultWidth?: number;
42
42
  defaultFonts?: FontConfig[];
43
43
  defaultBackgroundColor?: string;
44
- cacheFonts?: boolean;
45
- fontUrls?: string[];
46
44
  aiTextAsImage?: boolean | HtmlRendererAiTextAsImageConfig;
47
45
  }
48
46
  export interface HtmlRendererService {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/html-renderer",
3
- "version": "1.0.4",
3
+ "version": "2.0.1",
4
4
  "description": "HTML to PNG/SVG for Zhin.js (satori + resvg); optional peer of zhin.js",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -34,10 +34,10 @@
34
34
  "license": "MIT",
35
35
  "dependencies": {
36
36
  "@resvg/resvg-js": "^2.6.2",
37
- "@zhin.js/satori": "1.0.16"
37
+ "@zhin.js/satori": "1.0.17"
38
38
  },
39
39
  "peerDependencies": {
40
- "@zhin.js/core": "1.3.5"
40
+ "@zhin.js/core": "1.4.1"
41
41
  },
42
42
  "peerDependenciesMeta": {
43
43
  "@zhin.js/core": {
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "devDependencies": {
48
48
  "typescript": "^6.0.3",
49
- "@zhin.js/core": "1.3.5"
49
+ "@zhin.js/core": "1.4.1"
50
50
  },
51
51
  "repository": {
52
52
  "type": "git",
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { createHtmlRenderer } from './renderer.js';
1
+ export { createHtmlRenderer, serializeJsxToHtml } from './renderer.js';
2
2
  export { registerAiTextAsImageOutput, extractPlainTextForImage } from './ai-text-as-image.js';
3
3
  export type {
4
4
  FontConfig,
package/src/renderer.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { htmlToSvg, getAllBuiltinFonts, h, type HtmlComponent } from '@zhin.js/satori';
1
+ import { htmlToSvg, getAllBuiltinFonts, h, e, type HtmlComponent } from '@zhin.js/satori';
2
2
 
3
3
  import { Resvg } from '@resvg/resvg-js';
4
4
  import type {
@@ -14,13 +14,26 @@ const DEFAULT_CONFIG: Required<Omit<HtmlRendererConfig, 'aiTextAsImage'>> = {
14
14
  defaultWidth: 800,
15
15
  defaultFonts: [],
16
16
  defaultBackgroundColor: '#ffffff',
17
- cacheFonts: true,
18
- fontUrls: [],
19
17
  };
20
18
 
19
+ /** 外部资源(twemoji CDN)拉取超时 */
20
+ const EMOJI_FETCH_TIMEOUT_MS = 10_000;
21
+
22
+ /** 渲染并发上限,防止渲染任务堆积拖垮进程 */
23
+ const MAX_CONCURRENT_RENDERS = 2;
24
+
21
25
  const fontCache: Map<string, FontConfig> = new Map();
22
26
  let defaultFontLoaded = false;
23
27
 
28
+ /** fontCache 键:name + weight + style(缺 style 会让 italic 覆盖 normal) */
29
+ function fontCacheKey(
30
+ name: string,
31
+ weight?: FontConfig['weight'],
32
+ style?: FontConfig['style'],
33
+ ): string {
34
+ return `${name}-${weight ?? 400}-${style ?? 'normal'}`;
35
+ }
36
+
24
37
  function toFontConfig(f: {
25
38
  name: string;
26
39
  data: ArrayBuffer | Buffer;
@@ -53,7 +66,7 @@ function ensureBuiltinFontsCached(logger?: HtmlRendererLogger): void {
53
66
  if (builtinFonts.length > 0) {
54
67
  for (const font of builtinFonts) {
55
68
  const fc = toFontConfig(font);
56
- fontCache.set(`${font.name}-${font.weight}`, fc);
69
+ fontCache.set(fontCacheKey(font.name, font.weight, font.style), fc);
57
70
  logger?.debug?.(`Builtin font: ${font.name} (${Math.round(font.data.byteLength / 1024)}KB)`);
58
71
  }
59
72
  fontCache.set('default', toFontConfig(builtinFonts[0]));
@@ -79,7 +92,7 @@ function emojiToTwemojiUrl(emoji: string): string {
79
92
  async function loadEmojiImage(emoji: string, logger?: HtmlRendererLogger): Promise<string | null> {
80
93
  try {
81
94
  const url = emojiToTwemojiUrl(emoji);
82
- const response = await fetch(url);
95
+ const response = await fetch(url, { signal: AbortSignal.timeout(EMOJI_FETCH_TIMEOUT_MS) });
83
96
  if (!response.ok) {
84
97
  logger?.debug?.(`Failed to load emoji ${emoji}: ${response.status}`);
85
98
  return null;
@@ -92,7 +105,40 @@ async function loadEmojiImage(emoji: string, logger?: HtmlRendererLogger): Promi
92
105
  }
93
106
  }
94
107
 
95
- const emojiCache: Map<string, string> = new Map();
108
+ const EMOJI_CACHE_MAX = 200;
109
+ /** 失败(null)结果的负缓存 TTL,避免每次渲染都重试失败的 emoji */
110
+ const EMOJI_NEGATIVE_TTL_MS = 60_000;
111
+
112
+ interface EmojiCacheEntry {
113
+ value: string | null;
114
+ ts: number;
115
+ }
116
+
117
+ /** LRU:Map 迭代顺序即插入顺序,命中时移到末尾,超容量时淘汰最旧项 */
118
+ const emojiCache: Map<string, EmojiCacheEntry> = new Map();
119
+
120
+ function getCachedEmoji(segment: string): { hit: boolean; value: string | null } {
121
+ const entry = emojiCache.get(segment);
122
+ if (!entry) return { hit: false, value: null };
123
+ if (entry.value === null && Date.now() - entry.ts > EMOJI_NEGATIVE_TTL_MS) {
124
+ emojiCache.delete(segment);
125
+ return { hit: false, value: null };
126
+ }
127
+ // LRU touch:重新插入到末尾
128
+ emojiCache.delete(segment);
129
+ emojiCache.set(segment, entry);
130
+ return { hit: true, value: entry.value };
131
+ }
132
+
133
+ function setCachedEmoji(segment: string, value: string | null): void {
134
+ emojiCache.delete(segment);
135
+ emojiCache.set(segment, { value, ts: Date.now() });
136
+ while (emojiCache.size > EMOJI_CACHE_MAX) {
137
+ const oldest = emojiCache.keys().next().value;
138
+ if (oldest === undefined) break;
139
+ emojiCache.delete(oldest);
140
+ }
141
+ }
96
142
 
97
143
  async function loadAdditionalAsset(
98
144
  languageCode: string,
@@ -100,9 +146,11 @@ async function loadAdditionalAsset(
100
146
  logger?: HtmlRendererLogger,
101
147
  ): Promise<string | null> {
102
148
  if (languageCode === 'emoji') {
103
- if (emojiCache.has(segment)) return emojiCache.get(segment)!;
149
+ const cached = getCachedEmoji(segment);
150
+ if (cached.hit) return cached.value;
104
151
  const result = await loadEmojiImage(segment, logger);
105
- if (result) emojiCache.set(segment, result);
152
+ // 失败也缓存(短 TTL 负缓存),防止同一 emoji 反复打爆 CDN
153
+ setCachedEmoji(segment, result);
106
154
  return result;
107
155
  }
108
156
  return null;
@@ -120,6 +168,7 @@ async function renderHtmlToSvg(
120
168
  fonts: FontConfig[],
121
169
  backgroundColor: string | undefined,
122
170
  logger?: HtmlRendererLogger,
171
+ enableEmoji: boolean = true,
123
172
  ): Promise<{ svg: string; width: number; height: number }> {
124
173
  ensureBuiltinFontsCached(logger);
125
174
  const finalFonts = mergeFontLists(getAllBuiltinFonts().map(toFontConfig), fonts);
@@ -137,7 +186,7 @@ async function renderHtmlToSvg(
137
186
  style: f.style,
138
187
  })),
139
188
  loadAdditionalAsset: async (code, seg) =>
140
- (await loadAdditionalAsset(code, seg, logger)) ?? '',
189
+ enableEmoji ? ((await loadAdditionalAsset(code, seg, logger)) ?? '') : '',
141
190
  });
142
191
 
143
192
  const wm = svg.match(/width="(\d+)"/);
@@ -163,11 +212,11 @@ function svgToPng(svg: string, scale: number = 1): Buffer {
163
212
  return Buffer.from(pngData.asPng());
164
213
  }
165
214
 
166
- function serializeJsxToHtml(element: unknown): string {
167
- if (typeof element === 'string' || typeof element === 'number') {
168
- return String(element);
169
- }
170
- if (element == null) return '';
215
+ export function serializeJsxToHtml(element: unknown): string {
216
+ if (typeof element === 'string') return e(element);
217
+ if (typeof element === 'number') return String(element);
218
+ // boolean / null / undefined 一律渲染为空串
219
+ if (element == null || typeof element === 'boolean') return '';
171
220
  if (Array.isArray(element)) {
172
221
  return element.map(serializeJsxToHtml).join('');
173
222
  }
@@ -187,18 +236,19 @@ function serializeJsxToHtml(element: unknown): string {
187
236
  }
188
237
 
189
238
  const attrs = Object.entries(restProps)
190
- .filter(([key]) => key !== 'dangerouslySetInnerHTML')
191
- .map(([key, value]) => `${key}="${value}"`)
239
+ .filter(([key, value]) => key !== 'dangerouslySetInnerHTML' && value != null && value !== false)
240
+ .map(([key, value]) => `${key}="${e(String(value))}"`)
192
241
  .join(' ');
193
242
 
194
- const styleAttr = styleStr ? ` style="${styleStr}"` : '';
243
+ const styleAttr = styleStr ? ` style="${e(styleStr)}"` : '';
195
244
  const attrStr = attrs ? ` ${attrs}` : '';
196
245
 
246
+ // Raw HTML 只走显式通道 dangerouslySetInnerHTML
197
247
  if (dangerouslySetInnerHTML?.__html) {
198
248
  return `<${type}${attrStr}${styleAttr}>${dangerouslySetInnerHTML.__html}</${type}>`;
199
249
  }
200
250
 
201
- const childrenHtml = children ? serializeJsxToHtml(children) : '';
251
+ const childrenHtml = serializeJsxToHtml(children);
202
252
  const selfClosingTags = ['img', 'br', 'hr', 'input', 'meta', 'link'];
203
253
  if (selfClosingTags.includes(type) && !childrenHtml) {
204
254
  return `<${type}${attrStr}${styleAttr} />`;
@@ -215,9 +265,31 @@ export function createHtmlRenderer(
215
265
  logger?: HtmlRendererLogger,
216
266
  ): HtmlRendererService {
217
267
  const mergedConfig = { ...DEFAULT_CONFIG, ...config };
268
+
269
+ function cacheDefaultFonts(): void {
270
+ for (const font of mergedConfig.defaultFonts) {
271
+ fontCache.set(fontCacheKey(font.name, font.weight, font.style), font);
272
+ }
273
+ }
274
+
218
275
  ensureBuiltinFontsCached(logger);
219
- for (const font of mergedConfig.defaultFonts) {
220
- fontCache.set(`${font.name}-${font.weight || 400}`, font);
276
+ cacheDefaultFonts();
277
+
278
+ // 渲染并发闸:最多 MAX_CONCURRENT_RENDERS 个并发,其余排队
279
+ let activeRenders = 0;
280
+ const renderQueue: Array<() => void> = [];
281
+
282
+ async function acquireRenderSlot(): Promise<void> {
283
+ if (activeRenders >= MAX_CONCURRENT_RENDERS) {
284
+ await new Promise<void>((resolve) => renderQueue.push(resolve));
285
+ }
286
+ activeRenders++;
287
+ }
288
+
289
+ function releaseRenderSlot(): void {
290
+ activeRenders--;
291
+ const next = renderQueue.shift();
292
+ if (next) next();
221
293
  }
222
294
 
223
295
  return {
@@ -228,39 +300,46 @@ export function createHtmlRenderer(
228
300
  format = 'png',
229
301
  backgroundColor = mergedConfig.defaultBackgroundColor,
230
302
  fonts = [],
303
+ enableEmoji = true,
231
304
  scale = 1,
232
305
  } = options;
233
306
 
234
- ensureBuiltinFontsCached(logger);
235
- const allFonts = uniqueFontsForRender([...fontCache.values(), ...fonts]);
236
-
237
- const { svg, width: actualWidth, height: actualHeight } = await renderHtmlToSvg(
238
- html,
239
- width,
240
- height,
241
- allFonts,
242
- backgroundColor,
243
- logger,
244
- );
245
-
246
- if (format === 'svg') {
307
+ await acquireRenderSlot();
308
+ try {
309
+ ensureBuiltinFontsCached(logger);
310
+ const allFonts = uniqueFontsForRender([...fontCache.values(), ...fonts]);
311
+
312
+ const { svg, width: actualWidth, height: actualHeight } = await renderHtmlToSvg(
313
+ html,
314
+ width,
315
+ height,
316
+ allFonts,
317
+ backgroundColor,
318
+ logger,
319
+ enableEmoji,
320
+ );
321
+
322
+ if (format === 'svg') {
323
+ return {
324
+ data: svg,
325
+ format: 'svg',
326
+ width: actualWidth,
327
+ height: actualHeight,
328
+ mimeType: 'image/svg+xml',
329
+ };
330
+ }
331
+
332
+ const png = svgToPng(svg, scale);
247
333
  return {
248
- data: svg,
249
- format: 'svg',
250
- width: actualWidth,
251
- height: actualHeight,
252
- mimeType: 'image/svg+xml',
334
+ data: png,
335
+ format: 'png',
336
+ width: Math.round(actualWidth * scale),
337
+ height: Math.round(actualHeight * scale),
338
+ mimeType: 'image/png',
253
339
  };
340
+ } finally {
341
+ releaseRenderSlot();
254
342
  }
255
-
256
- const png = svgToPng(svg, scale);
257
- return {
258
- data: png,
259
- format: 'png',
260
- width: Math.round(actualWidth * scale),
261
- height: Math.round(actualHeight * scale),
262
- mimeType: 'image/png',
263
- };
264
343
  },
265
344
 
266
345
  async renderJsx(element: unknown, options: RenderOptions = {}): Promise<RenderResult> {
@@ -276,7 +355,7 @@ export function createHtmlRenderer(
276
355
  },
277
356
 
278
357
  registerFont(font: FontConfig): void {
279
- fontCache.set(`${font.name}-${font.weight || 400}`, font);
358
+ fontCache.set(fontCacheKey(font.name, font.weight, font.style), font);
280
359
  logger?.debug?.(`Font registered: ${font.name}`);
281
360
  },
282
361
 
@@ -287,6 +366,8 @@ export function createHtmlRenderer(
287
366
  clearFonts(): void {
288
367
  fontCache.clear();
289
368
  defaultFontLoaded = false;
369
+ // clear 后重新合并 defaultFonts,避免用户配置的默认字体永久丢失
370
+ cacheDefaultFonts();
290
371
  logger?.debug?.('Font cache cleared');
291
372
  },
292
373
  };
package/src/types.ts CHANGED
@@ -47,8 +47,6 @@ export interface HtmlRendererConfig {
47
47
  defaultWidth?: number;
48
48
  defaultFonts?: FontConfig[];
49
49
  defaultBackgroundColor?: string;
50
- cacheFonts?: boolean;
51
- fontUrls?: string[];
52
50
  aiTextAsImage?: boolean | HtmlRendererAiTextAsImageConfig;
53
51
  }
54
52