koishi-plugin-group-analysis-mx 1.3.2 → 1.3.4

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.
@@ -8,6 +8,7 @@ const koishi_1 = require("koishi");
8
8
  const fs_1 = require("fs");
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const nunjucks = require("nunjucks");
11
+ const twemoji = require("twemoji");
11
12
  const utils_1 = require("../utils");
12
13
  const skins_1 = require("../skins");
13
14
  /** 来自原项目 astrbot_plugin_qq_group_daily_analysis 的皮肤(Jinja2 模板,用 nunjucks 渲染) */
@@ -72,38 +73,32 @@ class RendererService extends koishi_1.Service {
72
73
  return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';
73
74
  }
74
75
  }
75
- /** 往渲染 HTML 注入 emoji 字体 @font-face 与字体栈,避免 puppeteer 截图时 emoji 显示为方框/问号。 */
76
+ /** HTML 中的 emoji 字符替换成 <img>(Twemoji 在线 CDN 图片),避免 Chromium 缺 emoji 字体时渲染成方框。 */
76
77
  async injectEmojiFont(html) {
77
78
  if (!html || typeof html !== 'string')
78
79
  return html;
79
- const emojiCss = this.buildEmojiFontCss();
80
- const style = `<style>${emojiCss}html,body{font-family:-apple-system,'Segoe UI','Segoe UI Emoji','Noto Color Emoji','NotoEmoji','Apple Color Emoji','Microsoft YaHei','Hiragino Sans GB',sans-serif !important;}</style>`;
81
- let out = html.includes('</head>')
82
- ? html.replace('</head>', style + '</head>')
83
- : html;
84
- // 预加载 span:@font-face 默认懒加载,用隐藏的 emoji 文本强制 Chromium 加载 NotoEmoji 字体,避免截图时字体未就绪
85
- const preload = `<span style="font-family:'NotoEmoji';position:absolute;left:-9999px;top:-9999px;opacity:0;font-size:40px;pointer-events:none;">&#x1F60A;&#x1F4FA;&#x1F3A5;&#x1F923;&#x1F600;</span>`;
86
- if (out.includes('<body>'))
87
- out = out.replace('<body>', '<body>' + preload);
88
- return out;
89
- }
90
- /**
91
- * 生成引用同层 fonts/NotoEmoji.ttf 的 @font-face(单文件 ttf,Chromium 稳定加载)。
92
- * 注意:必须与渲染 HTML 处于同一目录树(HTML 在 <skin>/,字体在 <skin>/fonts/),跨目录 file:// 加载会被 Chromium 拒绝。
93
- */
94
- buildEmojiFontCss() {
95
- return `@font-face{font-family:'NotoEmoji';font-style:normal;font-weight:400;src:url('fonts/NotoEmoji.ttf') format('truetype');}`;
80
+ try {
81
+ const base = 'https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/';
82
+ let out = twemoji.parse(html, { base, folder: 'svg', ext: '.svg', className: 'twemoji' });
83
+ const sizeCss = '<style>.twemoji{height:1em;width:1em;vertical-align:middle;display:inline-block;}</style>';
84
+ return out.includes('</head>')
85
+ ? out.replace('</head>', sizeCss + '</head>')
86
+ : out;
87
+ }
88
+ catch (e) {
89
+ this.ctx.logger.warn('emoji 图片替换失败:', e);
90
+ return html;
91
+ }
96
92
  }
97
93
  async init() {
98
94
  const resourcesDir = __dirname + '/../../resources';
99
95
  const templateDir = this.templateDir;
100
96
  const skin = this.config.skin || 'md3';
101
- // 拷贝内嵌的 emoji 字体到当前皮肤目录的 fonts/ 子目录(与渲染 HTML 同层;跨目录 file:// 加载会被 Chromium 拒绝)
102
- const skinFontsDir = ORIGINAL_SKINS.includes(skin)
103
- ? path_1.default.resolve(templateDir, 'original', skin, 'fonts')
104
- : path_1.default.resolve(templateDir, skin, 'fonts');
105
- await fs_1.promises.mkdir(skinFontsDir, { recursive: true });
106
- await fs_1.promises.cp(path_1.default.resolve(resourcesDir, 'fonts'), skinFontsDir, { recursive: true });
97
+ // 拷贝内嵌的 Twemoji 图片到 data 目录(emoji <img> 渲染,不走 Chromium 字体系统,跨环境可靠)
98
+ const twemojiSrcDir = path_1.default.resolve(resourcesDir, 'twemoji');
99
+ const twemojiDestDir = path_1.default.resolve(templateDir, 'twemoji');
100
+ await fs_1.promises.mkdir(twemojiDestDir, { recursive: true });
101
+ await fs_1.promises.cp(twemojiSrcDir, twemojiDestDir, { recursive: true });
107
102
  // 创建空 HTML 占位:渲染时先 goto 它(建立 file:// base),再 setContent 注入内容,@font-face 相对字体才能被加载
108
103
  const emptyHtmlPath = ORIGINAL_SKINS.includes(skin)
109
104
  ? path_1.default.resolve(templateDir, 'original', skin, 'emptyHtml.html')
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-group-analysis-mx",
3
3
  "description": "群聊分析插件 - 生成精美群聊统计报告,支持 AI 话题总结(独立版,不依赖 ChatLuna)",
4
- "version": "1.3.2",
4
+ "version": "1.3.4",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/index.mjs",
7
7
  "typings": "lib/index.d.ts",
@@ -26,7 +26,8 @@
26
26
  "js-yaml": "^4.1.0",
27
27
  "zod": "^3.25.0",
28
28
  "cron-parser": "^5.5.0",
29
- "nunjucks": "^3.2.4"
29
+ "nunjucks": "^3.2.4",
30
+ "twemoji": "^14.0.2"
30
31
  },
31
32
  "devDependencies": {
32
33
  "koishi": "^4.18.0",
Binary file