koishi-plugin-bns-fortune 1.0.1 → 1.0.2

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,6 +1,8 @@
1
1
  /**
2
2
  * koishi-plugin-bns-fortune
3
3
  * 剑灵风格每日好运签 —— Canvas 绘制,每日一签,文字可变
4
+ *
5
+ * 直接使用 node-canvas 包绘制,不依赖 Koishi 的 canvas 服务(避免与其他插件的服务名冲突)。
4
6
  */
5
7
  import { Context, Schema } from 'koishi';
6
8
  import { Fortune } from './fortunes';
package/lib/index.js CHANGED
@@ -5,6 +5,8 @@ exports.apply = apply;
5
5
  /**
6
6
  * koishi-plugin-bns-fortune
7
7
  * 剑灵风格每日好运签 —— Canvas 绘制,每日一签,文字可变
8
+ *
9
+ * 直接使用 node-canvas 包绘制,不依赖 Koishi 的 canvas 服务(避免与其他插件的服务名冲突)。
8
10
  */
9
11
  const koishi_1 = require("koishi");
10
12
  const node_path_1 = require("node:path");
@@ -55,18 +57,6 @@ exports.Config = koishi_1.Schema.intersect([
55
57
  exports.config = exports.Config;
56
58
  exports.name = 'bns-fortune';
57
59
  exports.reusable = true;
58
- /**
59
- * 获取 canvas 服务。
60
- * koishi-plugin-canvas(基于 skia-canvas)会注入 ctx.canvas。
61
- */
62
- function getCanvas(ctx) {
63
- // koishi-plugin-canvas 注入的服务挂载在 ctx.canvas
64
- const canvas = ctx.canvas;
65
- if (!canvas) {
66
- throw new Error('未检测到 canvas 服务。请在 Koishi 中安装并启用 "koishi-plugin-canvas" 插件,本插件依赖它来绘制签图。');
67
- }
68
- return canvas;
69
- }
70
60
  /** 注册字体目录下的 ttf/otf(若提供) */
71
61
  function tryRegisterFonts(dir) {
72
62
  if (!dir)
@@ -84,8 +74,6 @@ function tryRegisterFonts(dir) {
84
74
  logger.warn('读取字体目录失败:%o', e);
85
75
  return;
86
76
  }
87
- // skia-canvas 提供 Fontlibrary.use;node-canvas 提供 registerFont。
88
- // 两者都尝试,命中其一即可。
89
77
  for (const f of files) {
90
78
  const lower = f.toLowerCase();
91
79
  if (!lower.endsWith('.ttf') && !lower.endsWith('.otf'))
@@ -93,19 +81,10 @@ function tryRegisterFonts(dir) {
93
81
  const full = (0, node_path_1.resolve)(abs, f);
94
82
  const family = f.replace(/\.(ttf|otf)$/i, '');
95
83
  try {
96
- // skia-canvas
97
- const skia = globalThis.FontLibrary;
98
- if (skia?.use) {
99
- skia.use(family, [full]);
100
- continue;
101
- }
102
- }
103
- catch { /* ignore */ }
104
- try {
105
- // node-canvas
106
- const nodeCanvas = require('canvas');
107
- if (typeof nodeCanvas.registerFont === 'function') {
108
- nodeCanvas.registerFont(full, { family });
84
+ // @napi-rs/canvas 的 GlobalFonts.register
85
+ const { GlobalFonts } = require('@napi-rs/canvas');
86
+ if (GlobalFonts?.register) {
87
+ GlobalFonts.register(full, { family });
109
88
  }
110
89
  }
111
90
  catch { /* ignore */ }
@@ -123,12 +102,7 @@ function apply(ctx, config) {
123
102
  ? config.results
124
103
  : fortunes_1.FORTUNES;
125
104
  const theme = render_1.THEMES[config.theme] ?? render_1.THEMES.ink;
126
- let renderer;
127
- function getRenderer() {
128
- if (!renderer)
129
- renderer = new render_1.FortuneRenderer(getCanvas(ctx));
130
- return renderer;
131
- }
105
+ const renderer = new render_1.FortuneRenderer();
132
106
  // 每日每用户渲染缓存:key = `${date}|${userId}`
133
107
  const renderCache = new Map();
134
108
  // 每天换日时清理
@@ -148,7 +122,7 @@ function apply(ctx, config) {
148
122
  return koishi_1.h.image(cached, 'image/png');
149
123
  try {
150
124
  const { fortune } = (0, fortune_1.drawFortune)(date, session.userId, config.masterKey, library);
151
- const png = await getRenderer().render({
125
+ const png = await renderer.render({
152
126
  fortune,
153
127
  date,
154
128
  nickname: session.username || session.author?.nickname,
package/lib/render.d.ts CHANGED
@@ -6,23 +6,10 @@
6
6
  * 支持 customBackground 配置项替换为外部图片。
7
7
  * - 动态文字(签等级/签诗/解签/运势/日期/昵称/签号)每次叠加在背景之上。
8
8
  * - 配色用剑灵水墨风(墨黑 / 朱砂红 / 赤金 / 米色),装饰加入剑气、符文元素。
9
+ *
10
+ * 直接使用 node-canvas 包,不依赖 Koishi 的 canvas 服务(避免服务名冲突)。
9
11
  */
10
12
  import { Fortune } from './fortunes';
11
- export interface CanvasLike {
12
- width: number;
13
- height: number;
14
- getContext(type: '2d'): CanvasRenderingContext2D;
15
- /** 兼容 skia-canvas / node-canvas:不传参数时两者都默认返回 PNG Buffer */
16
- toBuffer(format?: string, config?: unknown): Buffer;
17
- }
18
- export interface ImageLike {
19
- width: number;
20
- height: number;
21
- }
22
- export interface CanvasService {
23
- createCanvas(width: number, height: number): CanvasLike;
24
- loadImage(source: string | Buffer): Promise<ImageLike>;
25
- }
26
13
  export interface Theme {
27
14
  /** 主题名 */
28
15
  name: string;
@@ -58,14 +45,12 @@ export interface RenderInput {
58
45
  customBackground?: string;
59
46
  }
60
47
  export declare class FortuneRenderer {
61
- private canvas;
62
48
  /** 背景缓存:key = `${themeName}|${customBg ?? 'builtin'}` */
63
49
  private bgCache;
64
50
  /** 自定义背景图缓存:key = url */
65
51
  private imageCache;
66
52
  /** 缓存条数上限 */
67
53
  private static MAX_CACHE;
68
- constructor(canvas: CanvasService);
69
54
  private evict;
70
55
  /** 字体声明字符串,含中文回退 */
71
56
  private fontStack;
package/lib/render.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FortuneRenderer = exports.H = exports.W = exports.THEMES = void 0;
4
+ const canvas_1 = require("@napi-rs/canvas");
4
5
  exports.THEMES = {
5
6
  /** 剑灵·水墨:墨黑朱砂赤金 */
6
7
  ink: {
@@ -31,8 +32,7 @@ exports.THEMES = {
31
32
  exports.W = 600;
32
33
  exports.H = 860;
33
34
  class FortuneRenderer {
34
- constructor(canvas) {
35
- this.canvas = canvas;
35
+ constructor() {
36
36
  /** 背景缓存:key = `${themeName}|${customBg ?? 'builtin'}` */
37
37
  this.bgCache = new Map();
38
38
  /** 自定义背景图缓存:key = url */
@@ -61,11 +61,11 @@ class FortuneRenderer {
61
61
  // 自定义背景:加载图片并缩放绘制到画布
62
62
  let img = this.imageCache.get(customBg);
63
63
  if (!img) {
64
- img = await this.canvas.loadImage(customBg);
64
+ img = await (0, canvas_1.loadImage)(customBg);
65
65
  this.imageCache.set(customBg, img);
66
66
  this.evict(this.imageCache);
67
67
  }
68
- bg = this.canvas.createCanvas(exports.W, exports.H);
68
+ bg = (0, canvas_1.createCanvas)(exports.W, exports.H);
69
69
  const ctx = bg.getContext('2d');
70
70
  // 先填底色,避免透明
71
71
  ctx.fillStyle = theme.bg;
@@ -80,7 +80,7 @@ class FortuneRenderer {
80
80
  drawBorder(ctx, exports.W, exports.H, theme);
81
81
  }
82
82
  else {
83
- bg = this.canvas.createCanvas(exports.W, exports.H);
83
+ bg = (0, canvas_1.createCanvas)(exports.W, exports.H);
84
84
  const ctx = bg.getContext('2d');
85
85
  drawBackground(ctx, exports.W, exports.H, theme);
86
86
  }
@@ -92,8 +92,9 @@ class FortuneRenderer {
92
92
  async render(input) {
93
93
  const { fortune, date, nickname, fontFamily, theme, customBackground } = input;
94
94
  const bg = await this.getBackground(theme, customBackground);
95
- const canvas = this.canvas.createCanvas(exports.W, exports.H);
95
+ const canvas = (0, canvas_1.createCanvas)(exports.W, exports.H);
96
96
  const ctx = canvas.getContext('2d');
97
+ // 1. 复制缓存背景
97
98
  ctx.drawImage(bg, 0, 0);
98
99
  // 2. 顶部绸带 + 签等级标题(动态)
99
100
  drawRibbon(ctx, exports.W / 2, 78, theme);
@@ -108,8 +109,8 @@ class FortuneRenderer {
108
109
  drawLuckTags(ctx, exports.W / 2, 638, fortune.luck, this.fontStack(fontFamily), theme);
109
110
  // 7. 底部:日期 / 昵称 / 签号
110
111
  drawFooter(ctx, exports.W, exports.H, date, nickname, fortune.number, this.fontStack(fontFamily), theme);
111
- // 不传参数:skia-canvas node-canvas 均默认返回 PNG,兼容性最好
112
- return canvas.toBuffer();
112
+ // @napi-rs/canvas 需要传 mime type
113
+ return canvas.toBuffer('image/png');
113
114
  }
114
115
  }
115
116
  exports.FortuneRenderer = FortuneRenderer;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-bns-fortune",
3
3
  "description": "剑灵风格每日好运签:每日一签,Canvas 绘制签图,文字可变,支持自定义背景与主题。",
4
- "version": "1.0.1",
4
+ "version": "1.0.2",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
@@ -10,11 +10,6 @@
10
10
  "koishi": {
11
11
  "description": {
12
12
  "zh": "剑灵好运签(每日一签)"
13
- },
14
- "manifest": {
15
- "services": [
16
- "canvas"
17
- ]
18
13
  }
19
14
  },
20
15
  "keywords": [
@@ -35,17 +30,15 @@
35
30
  },
36
31
  "peerDependencies": {
37
32
  "koishi": "^4.15.0",
38
- "koishi-plugin-canvas": "^0.2.2",
39
- "canvas": "^2.0.0"
33
+ "@napi-rs/canvas": "^0.1.0"
40
34
  },
41
35
  "peerDependenciesMeta": {
42
- "canvas": {
43
- "optional": true
36
+ "@napi-rs/canvas": {
37
+ "optional": false
44
38
  }
45
39
  },
46
40
  "devDependencies": {
47
41
  "koishi": "^4.15.0",
48
- "koishi-plugin-canvas": "^0.2.2",
49
42
  "rimraf": "^5.0.0",
50
43
  "typescript": "^5.4.0"
51
44
  }