Skip to content

Commit 34aef36

Browse files
📝 Docs: 添加 htmlkit 文档至最佳实践 (#3682)
Co-authored-by: StarHeart <starheart233@gmail.com>
1 parent 8ea2d4b commit 34aef36

File tree

5 files changed

+921
-1
lines changed

5 files changed

+921
-1
lines changed

assets/plugins.json5

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9750,7 +9750,7 @@
97509750
"color": "#199579"
97519751
}
97529752
],
9753-
"is_official": false
9753+
"is_official": true
97549754
},
97559755
{
97569756
"module_name": "nonebot_plugin_mhcodes",
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
---
2+
sidebar_position: 8
3+
description: 轻量化 HTML 绘图
4+
---
5+
6+
# 轻量化 HTML 绘图
7+
8+
图片是机器人交互中不可或缺的一部分,对于信息展示的直观性、美观性有很大的作用。
9+
基于 PIL 直接绘制图片具有良好的性能和存储开销,但是难以调试、维护过程式的绘图代码。
10+
使用浏览器渲染类插件可以方便地绘制网页,且能够直接通过 JS 对网页效果进行编程,但是它占用的存储和内存空间相对可观。
11+
12+
NoneBot 提供的 `nonebot-plugin-htmlkit` 提供了另一种基于 HTML 和 CSS 语法的轻量化绘图选择:它基于 `litehtml` 解析库,无须安装额外的依赖即可使用,没有进程间通信带来的额外开销,且在支持 `webp` `avif` 等丰富图片格式的前提下,安装用的 wheel 文件大小仅有约 10 MB。
13+
14+
作为粗略的性能参考,在一台 Ryzen 7 9700X 的 Windows 电脑上,渲染 [PEP 7](https://peps.python.org/pep-0007/) 的 HTML 页面(分辨率为 800x5788,大小约 1.4MB,从本地文件系统读取 CSS)大约需要 100ms,每个渲染任务内存最高占用约为 40MB.
15+
16+
## 安装插件
17+
18+
19+
在使用前请先安装 `nonebot-plugin-htmlkit` 插件至项目环境中,可参考[获取商店插件](../tutorial/store.mdx#安装插件)来了解并选择安装插件的方式。如:
20+
21+
**项目目录**下执行以下命令:
22+
23+
```bash
24+
nb plugin install nonebot-plugin-htmlkit
25+
```
26+
27+
`nonebot-plugin-htmlkit` 插件目前兼容以下系统架构:
28+
29+
- Windows x64
30+
- macOS arm64(M-系列芯片)
31+
- Linux x64 (非 Alpine 等 musl 系发行版)
32+
- Linux arm64 (非 Alpine 等 musl 系发行版)
33+
34+
:::caution 访问网络内容
35+
36+
如果需要访问网络资源(如 http(s) 网页内容),NoneBot 需要客户端型驱动器(Forward)。内置的驱动器有 `~httpx``~aiohttp`
37+
38+
详见[选择驱动器](../advanced/driver.md)
39+
40+
:::
41+
42+
## 使用插件
43+
44+
### 加载插件
45+
46+
在使用本插件前同样需要使用 `require` 方法进行**加载****导入**需要使用的方法,可参考 [跨插件访问](../advanced/requiring.md) 一节进行了解,如:
47+
48+
```python
49+
from nonebot import require
50+
51+
require("nonebot_plugin_htmlkit")
52+
53+
from nonebot_plugin_htmlkit import html_to_pic, md_to_pic, template_to_pic, text_to_pic
54+
```
55+
56+
插件会自动使用[配置中的参数](#配置-fontconfig)初始化 `fontconfig` 以提供字体查找功能。
57+
58+
### 渲染 API
59+
60+
`nonebot-plugin-htmlkit` 主要提供以下**异步**渲染函数:
61+
62+
#### html_to_pic
63+
64+
``` python
65+
async def html_to_pic(
66+
html: str,
67+
*,
68+
base_url: str = "",
69+
dpi: float = 144.0,
70+
max_width: float = 800.0,
71+
device_height: float = 600.0,
72+
default_font_size: float = 12.0,
73+
font_name: str = "sans-serif",
74+
allow_refit: bool = True,
75+
image_format: Literal["png", "jpeg"] = "png",
76+
jpeg_quality: int = 100,
77+
lang: str = "zh",
78+
culture: str = "CN",
79+
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
80+
css_fetch_fn: CSSFetchFn = combined_css_fetcher,
81+
urljoin_fn: Callable[[str, str], str] = urllib3.parse.urljoin,
82+
) -> bytes:
83+
...
84+
```
85+
86+
最核心的渲染函数。
87+
88+
`base_url``urljoin_fn` 控制着传入 `image_fetch_fn``css_fetch_fn` 回调的 url 内容。
89+
90+
`allow_refit` 如果为真,渲染时会自动缩小产出图片的宽度到最适合的宽度,否则必定产出 `max_width` 宽度的图片。
91+
92+
`max_width``device_height` 会在 `@media` 判断中被使用。
93+
94+
`img_fetch_fn` 预期为一个异步可调用对象(函数),接收图片 url 并返回对应 url 的 jpeg 或 png 二进制数据(`bytes`),可在拒绝加载时返回 `None`.
95+
96+
`css_fetch_fn` 预期为一个异步可调用对象(函数),接收目标 CSS url 并返回对应 url 的 CSS 文本(`str`),可在拒绝加载时返回 `None`.
97+
98+
以下为辅助的封装函数,关键字参数若未特殊说明均与 `html_to_pic` 含义相同。
99+
100+
#### text_to_pic
101+
102+
```python
103+
async def text_to_pic(
104+
text: str,
105+
css_path: str = "",
106+
*,
107+
max_width: int = 500,
108+
allow_refit: bool = True,
109+
image_format: Literal["png", "jpeg"] = "png",
110+
jpeg_quality: int = 100,
111+
) -> bytes:
112+
...
113+
```
114+
115+
可用于渲染多行文本。
116+
117+
`text` 会被放置于 `<div id="main" class="main-box"> <div class="text">` 中,可据此编写 CSS 来改变文本表现。
118+
119+
#### md_to_pic
120+
121+
```python
122+
async def md_to_pic(
123+
md: str = "",
124+
md_path: str = "",
125+
css_path: str = "",
126+
*,
127+
max_width: int = 500,
128+
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
129+
allow_refit: bool = True,
130+
image_format: Literal["png", "jpeg"] = "png",
131+
jpeg_quality: int = 100,
132+
) -> bytes:
133+
...
134+
```
135+
136+
可用于渲染 Markdown 文本。默认为 GitHub Markdown Light 风格,支持基于 `pygments` 的代码高亮。
137+
138+
`md``md_path` 二选一,前者设置时应为 Markdown 的文本,后者设置时应为指向 Markdown 文本文件的路径。
139+
140+
#### template_to_pic
141+
142+
```python
143+
async def template_to_pic(
144+
template_path: str | PathLike[str] | Sequence[str | PathLike[str]],
145+
template_name: str,
146+
templates: Mapping[Any, Any],
147+
filters: None | Mapping[str, Any] = None,
148+
*,
149+
max_width: int = 500,
150+
device_height: int = 600,
151+
base_url: str | None = None,
152+
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
153+
css_fetch_fn: CSSFetchFn = combined_css_fetcher,
154+
allow_refit: bool = True,
155+
image_format: Literal["png", "jpeg"] = "png",
156+
jpeg_quality: int = 100,
157+
) -> bytes:
158+
...
159+
```
160+
161+
渲染 jinja2 模板。
162+
163+
`template_path` 为 jinja2 环境的路径,`template_name` 是环境中要加载模板的名字,`templates` 为传入模板的参数,`filters` 为过滤器名 -> 自定义过滤器的映射。
164+
165+
### 控制外部资源获取
166+
167+
通过传入 `img_fetch_fn``css_fetch_fn`,我们可以在实际访问资源前进行审查,修改资源的来源,或是对 IO 操作进行缓存。
168+
169+
`img_fetch_fn` 预期为一个异步可调用对象(函数),接收图片 url 并返回对应 url 的 jpeg 或 png 二进制数据(`bytes`),可在拒绝加载时返回 `None`.
170+
171+
`css_fetch_fn` 预期为一个异步可调用对象(函数),接收目标 CSS url 并返回对应 url 的 CSS 文本(`str`),可在拒绝加载时返回 `None`.
172+
173+
如果你想要禁用外部资源加载/只从文件系统加载/只从网络加载,可以使用 `none_fetcher` `filesystem_***_fetcher` `network_***_fetcher`
174+
175+
默认的 fetcher 行为(对于 `file://` 从文件系统加载,其余从网络加载)位于 `combined_***_fetcher`,可以通过对其封装实现缓存等操作。
176+
177+
## 配置项
178+
179+
### 配置 fontconfig
180+
181+
`htmlkit` 使用 `fontconfig` 查找字体,请参阅 [`fontconfig 用户手册`](https://fontconfig.pages.freedesktop.org/fontconfig/fontconfig-user) 了解环境变量的具体含义、如何通过编写配置文件修改字体配置等。
182+
183+
#### fontconfig_file
184+
185+
- **类型**: `str | None`
186+
- **默认值**: `None`
187+
188+
覆盖默认的配置文件路径。
189+
190+
#### fontconfig_path
191+
192+
- **类型**: `str | None`
193+
- **默认值**: `None`
194+
195+
覆盖默认的配置目录。
196+
197+
#### fontconfig_sysroot
198+
199+
- **类型**: `str | None`
200+
- **默认值**: `None`
201+
202+
覆盖默认的 sysroot。
203+
204+
#### fc_debug
205+
206+
- **类型**: `str | None`
207+
- **默认值**: `None`
208+
209+
设置 Fontconfig 的 debug 级别。
210+
211+
#### fc_dbg_match_filter
212+
213+
- **类型**: `str | None`
214+
- **默认值**: `None`
215+
216+
`FC_DEBUG` 设置为 `MATCH2` 时,过滤 debug 输出。
217+
218+
#### fc_lang
219+
220+
- **类型**: `str | None`
221+
- **默认值**: `None`
222+
223+
设置默认语言,否则从 `LOCALE` 环境变量获取。
224+
225+
#### fontconfig_use_mmap
226+
227+
- **类型**: `str | None`
228+
- **默认值**: `None`
229+
230+
是否使用 `mmap(2)` 读取字体缓存。

0 commit comments

Comments
 (0)