koishi-plugin-ll-mc 3.1.5 → 3.1.7

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.
Files changed (2) hide show
  1. package/lib/index.js +25 -8
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -357,6 +357,7 @@ async function apply(ctx, config) {
357
357
  const fontsPath = import_path.default.join(messageCounterRoot, "fonts");
358
358
  const avatarsPath = import_path.default.join(messageCounterRoot, "avatars");
359
359
  const emptyHtmlPath = import_path.default.join(messageCounterRoot, "emptyHtml.html").replace(/\\/g, "/");
360
+ const templateHtmlPath = import_path.default.join(messageCounterRoot, "leaderboard-template.html").replace(/\\/g, "/");
360
361
  const oldIconsPath = import_path.default.join(dataRoot, "messageCounterIcons");
361
362
  const oldBarBgImgsPath = import_path.default.join(dataRoot, "messageCounterBarBgImgs");
362
363
  await fs.mkdir(fontsPath, { recursive: true });
@@ -2559,7 +2560,7 @@ ${targetUserRecord[0].username}
2559
2560
  </div>`;
2560
2561
  }
2561
2562
  __name(buildLeaderboardRow, "buildLeaderboardRow");
2562
- function buildLeaderboardHtml(title, date, items, backgroundCss) {
2563
+ function buildLeaderboardHtml(title, date, items, backgroundCss, fontFaces) {
2563
2564
  const maxCount = Math.max(1, ...items.map((item) => item.count || 0));
2564
2565
  const rows = items.map((item, index) => buildLeaderboardRow(item, index, maxCount)).join("\n");
2565
2566
  return `<!DOCTYPE html>
@@ -2568,6 +2569,7 @@ ${targetUserRecord[0].username}
2568
2569
  <meta charset="UTF-8">
2569
2570
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
2570
2571
  <style>
2572
+ ${fontFaces || ""}
2571
2573
  * { box-sizing: border-box; margin: 0; padding: 0; }
2572
2574
  html, body {
2573
2575
  width: 900px;
@@ -2576,7 +2578,7 @@ ${targetUserRecord[0].username}
2576
2578
  background-color: #F5F7FA;
2577
2579
  }
2578
2580
  body {
2579
- font-family: "PingFang SC", "Microsoft YaHei", "Noto Sans SC", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
2581
+ font-family: "PingFang SC", "Microsoft YaHei", "Noto Sans SC", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "NotoEmoji", "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji";
2580
2582
  -webkit-font-smoothing: antialiased;
2581
2583
  }
2582
2584
  .card {
@@ -2592,8 +2594,7 @@ ${targetUserRecord[0].username}
2592
2594
  .row { display: flex; align-items: center; gap: 12px; width: 100%; }
2593
2595
  .avatar { width: 40px; height: 40px; flex-shrink: 0; }
2594
2596
  .avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; box-shadow: 0 1px 2px rgba(0,0,0,0.08); background: #fff; padding: 2px; }
2595
- .bar { position: relative; flex-grow: 1; height: 40px; border-radius: 8px; overflow: hidden; display: flex; align-items: center; justify-content: space-between; padding: 0 12px; background: rgba(255,255,255,0.34); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,0.45); box-shadow: 0 1px 2px rgba(0,0,0,0.04); }
2596
- .bar::after { content: ''; position: absolute; inset: 0; background-image: linear-gradient(to right, transparent 99%, rgba(255,255,255,0.2) 100%); background-size: 10% 100%; pointer-events: none; }
2597
+ .bar { position: relative; flex-grow: 1; height: 40px; border-radius: 8px; overflow: hidden; display: flex; align-items: center; justify-content: space-between; padding: 0 12px; background: transparent; }
2597
2598
  .fill { position: absolute; left: 0; top: 0; height: 100%; border-radius: 8px 0 0 8px; z-index: 0; }
2598
2599
  .bar-content { position: relative; z-index: 1; display: flex; align-items: center; justify-content: space-between; width: 100%; }
2599
2600
  .row-name { font-size: 16px; font-weight: 700; display: flex; align-items: center; gap: 5px; max-width: 78%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@@ -2621,14 +2622,30 @@ ${rows}
2621
2622
  if (typeof ctx.puppeteer?.page !== "function") return null;
2622
2623
  let page;
2623
2624
  try {
2624
- const html = buildLeaderboardHtml(title, date, items, backgroundCss);
2625
+ // 复用图表的内置字体(含纯 emoji NotoEmoji),以相对路径 fonts/<file> 加载,
2626
+ // 所以必须把模板写到 data/messageCounter/ 目录里再用 file:// 访问,相对路径才能解析。
2627
+ const fontFaces = generateFontFacesCSS(["HarmonyOS_Sans_Medium.ttf", "NotoEmoji.ttf"]);
2628
+ const html = buildLeaderboardHtml(title, date, items, backgroundCss, fontFaces);
2625
2629
  page = await ctx.puppeteer.page();
2626
2630
  await page.setViewport({ width: 900, height: 400, deviceScaleFactor: 2 });
2631
+ const pageUrl = templateHtmlPath.includes(":") ? `file:///${templateHtmlPath}` : `file://${templateHtmlPath}`;
2627
2632
  try {
2628
- await page.setContent(html, { waitUntil: "networkidle0", timeout: 20000 });
2629
- } catch (e) {
2630
- logger.warn("Leaderboard template wait timed out, screenshotting current content.");
2633
+ await fs.writeFile(templateHtmlPath, html);
2634
+ } catch (writeError) {
2635
+ logger.warn("无法写入排行榜模板文件,改用 setContent:", writeError?.message);
2631
2636
  }
2637
+ if (typeof page.goto === "function") {
2638
+ try {
2639
+ await page.goto(pageUrl, { waitUntil: "load", timeout: 20000 });
2640
+ } catch (e) {
2641
+ logger.warn("Leaderboard template goto failed, using setContent:", e?.message);
2642
+ await page.setContent(html, { waitUntil: "networkidle0", timeout: 20000 }).catch(() => {});
2643
+ }
2644
+ } else {
2645
+ await page.setContent(html, { waitUntil: "networkidle0", timeout: 20000 }).catch(() => {});
2646
+ }
2647
+ // 确保 emoji 字体就绪再截图
2648
+ await page.evaluate(() => document.fonts.ready).catch(() => {});
2632
2649
  await page.waitForSelector(".card").catch(() => {});
2633
2650
  // 背景(自定义 CSS/API 背景)是加在 html 上的,必须截整页才能把卡片外的背景一起截进来;
2634
2651
  // body 高度由内容撑开(无 min-height),所以 fullPage 不会产生多余空白。
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-ll-mc",
3
3
  "description": "消息数量统计插件(基于 koishi-plugin-message-counter 重做,官方QQ机器人兼容)",
4
- "version": "3.1.5",
4
+ "version": "3.1.7",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [