Compare commits

..

7 Commits

Author SHA1 Message Date
lanxinmob
d7993a3362 🍻 publish plugin nonebot-plugin-memory (#3700) 2025-10-08 17:46:22 +08:00
noneflow[bot]
fa0bfa7346 📝 Update changelog
Some checks failed
Code Coverage / Test Coverage (pydantic-v1, macos-latest, 3.9) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.10) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.11) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.12) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.12) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.13) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.13) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.10) (push) Failing after 3s
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.11) (push) Failing after 3s
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.12) (push) Failing after 3s
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.9) (push) Failing after 2s
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.13) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.9) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.10) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.11) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.9) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.10) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.11) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.12) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.9) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.13) (push) Failing after 3s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.10) (push) Failing after 2s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.11) (push) Failing after 2s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.12) (push) Failing after 2s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.13) (push) Failing after 2s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.9) (push) Failing after 2s
Pyright Lint / Pyright Lint (pydantic-v1) (push) Failing after 2s
Pyright Lint / Pyright Lint (pydantic-v2) (push) Failing after 2s
Ruff Lint / Ruff Lint (push) Failing after 2s
Site Deploy / publish (push) Failing after 2s
2025-10-08 09:40:33 +00:00
worldmozara
29720bada8 Feature: 更新 NB-CLI 新版插件加载格式与文档 (#3614) 2025-10-08 17:39:11 +08:00
dependabot[bot]
67e5126f6a ⬆️ Bump astral-sh/setup-uv from 6 to 7 in /.github/actions/setup-python in the actions group (#3710)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Ju4tCode <42488585+yanyongyu@users.noreply.github.com>
2025-10-08 14:14:36 +08:00
noneflow[bot]
0212247694 📝 Update changelog 2025-10-08 03:41:31 +00:00
Nyuan Zhang
34aef36bac 📝 Docs: 添加 htmlkit 文档至最佳实践 (#3682)
Co-authored-by: StarHeart <starheart233@gmail.com>
2025-10-08 11:40:22 +08:00
pre-commit-ci[bot]
8ea2d4b81f ⬆️ auto update by pre-commit hooks (#3709)
Some checks failed
Code Coverage / Test Coverage (pydantic-v1, macos-latest, 3.10) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.10) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.11) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.12) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.13) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v1, windows-latest, 3.9) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.10) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.11) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.12) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.13) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, macos-latest, 3.9) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.10) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.11) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.12) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.13) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v2, windows-latest, 3.9) (push) Waiting to run
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.10) (push) Failing after 3s
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.11) (push) Failing after 3s
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.12) (push) Failing after 2s
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.13) (push) Failing after 2s
Code Coverage / Test Coverage (pydantic-v1, ubuntu-latest, 3.9) (push) Failing after 2s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.10) (push) Failing after 2s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.11) (push) Failing after 2s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.12) (push) Failing after 2s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.13) (push) Failing after 2s
Code Coverage / Test Coverage (pydantic-v2, ubuntu-latest, 3.9) (push) Failing after 2s
Pyright Lint / Pyright Lint (pydantic-v1) (push) Failing after 2s
Pyright Lint / Pyright Lint (pydantic-v2) (push) Failing after 2s
Ruff Lint / Ruff Lint (push) Failing after 2s
Site Deploy / publish (push) Failing after 2s
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-10-08 11:02:18 +08:00
17 changed files with 1039 additions and 17 deletions

View File

@@ -14,7 +14,7 @@ inputs:
runs: runs:
using: "composite" using: "composite"
steps: steps:
- uses: astral-sh/setup-uv@v6 - uses: astral-sh/setup-uv@v7
with: with:
python-version: ${{ inputs.python-version }} python-version: ${{ inputs.python-version }}
cache-suffix: ${{ inputs.env-group }} cache-suffix: ${{ inputs.env-group }}

View File

@@ -7,7 +7,7 @@ ci:
autoupdate_commit_msg: ":arrow_up: auto update by pre-commit hooks" autoupdate_commit_msg: ":arrow_up: auto update by pre-commit hooks"
repos: repos:
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.11 rev: v0.13.3
hooks: hooks:
- id: ruff-check - id: ruff-check
args: [--fix] args: [--fix]

View File

@@ -9750,7 +9750,7 @@
"color": "#199579" "color": "#199579"
} }
], ],
"is_official": false "is_official": true
}, },
{ {
"module_name": "nonebot_plugin_mhcodes", "module_name": "nonebot_plugin_mhcodes",
@@ -9765,13 +9765,17 @@
"is_official": false "is_official": false
}, },
{ {
"module_name": "nonebot_plugin_kookcardmessage", "module_name": "nonebot_plugin_memory",
"project_link": "nonebot-plugin-kookcardmessage", "project_link": "nonebot-plugin-memory",
"author_id": 174641131, "author_id": 175703143,
"tags": [ "tags": [
{ {
"label": "kook", "label": "log",
"color": "#ea5252" "color": "#336daf"
},
{
"label": "func",
"color": "#5bd0a2"
} }
], ],
"is_official": false "is_official": false

View File

@@ -8,11 +8,13 @@ FrontMatter:
""" """
from collections.abc import Iterable from collections.abc import Iterable
from itertools import chain
import json import json
from pathlib import Path from pathlib import Path
from types import ModuleType from types import ModuleType
from typing import Optional, Union from typing import Optional, Union
from nonebot.log import logger
from nonebot.utils import path_to_module_name from nonebot.utils import path_to_module_name
from . import _managers, _module_name_to_plugin_id, get_plugin from . import _managers, _module_name_to_plugin_id, get_plugin
@@ -108,6 +110,19 @@ def load_from_toml(file_path: str, encoding: str = "utf-8") -> set[Plugin]:
encoding: 指定 toml 文件编码 encoding: 指定 toml 文件编码
用法: 用法:
新格式:
```toml title=pyproject.toml
[tool.nonebot]
plugin_dirs = ["some_dir"]
[tool.nonebot.plugins]
some-store-plugin = ["some_store_plugin"]
"@local" = ["some_local_plugin"]
```
旧格式:
```toml title=pyproject.toml ```toml title=pyproject.toml
[tool.nonebot] [tool.nonebot]
plugins = ["some_plugin"] plugins = ["some_plugin"]
@@ -126,11 +141,22 @@ def load_from_toml(file_path: str, encoding: str = "utf-8") -> set[Plugin]:
raise ValueError("Cannot find '[tool.nonebot]' in given toml file!") raise ValueError("Cannot find '[tool.nonebot]' in given toml file!")
if not isinstance(nonebot_data, dict): if not isinstance(nonebot_data, dict):
raise TypeError("'[tool.nonebot]' must be a Table!") raise TypeError("'[tool.nonebot]' must be a Table!")
plugins = nonebot_data.get("plugins", []) plugins = nonebot_data.get("plugins", {})
plugin_dirs = nonebot_data.get("plugin_dirs", []) plugin_dirs = nonebot_data.get("plugin_dirs", [])
assert isinstance(plugins, list), "plugins must be a list of plugin name" assert isinstance(plugins, (list, dict)), (
"plugins must be a list or a dict of plugin name"
)
assert isinstance(plugin_dirs, list), "plugin_dirs must be a list of directories" assert isinstance(plugin_dirs, list), "plugin_dirs must be a list of directories"
return load_all_plugins(plugins, plugin_dirs) if isinstance(plugins, list):
logger.warning("Legacy project format found! Upgrade with `nb upgrade-format`.")
return load_all_plugins(
set(
chain.from_iterable(plugins.values())
if isinstance(plugins, dict)
else plugins
),
plugin_dirs,
)
def load_builtin_plugin(name: str) -> Optional[Plugin]: def load_builtin_plugin(name: str) -> Optional[Plugin]:

View File

@@ -89,7 +89,7 @@ def origin_is_annotated(origin: t.Optional[type[t.Any]]) -> bool:
return origin is t_ext.Annotated return origin is t_ext.Annotated
NONE_TYPES = {None, type(None), t.Literal[None], t_ext.Literal[None]} NONE_TYPES = {None, type(None), t.Literal[None], t_ext.Literal[None]} # noqa: PYI061
if sys.version_info >= (3, 10): if sys.version_info >= (3, 10):
NONE_TYPES.add(types.NoneType) NONE_TYPES.add(types.NoneType)

View File

@@ -0,0 +1,3 @@
[tool.nonebot]
plugins = []
plugin_dirs = []

View File

@@ -1,3 +1,5 @@
[tool.nonebot] [tool.nonebot]
plugins = []
plugin_dirs = [] plugin_dirs = []
[tool.nonebot.plugins]
"@local" = []

View File

@@ -93,6 +93,8 @@ def test_load_json():
@_recover @_recover
def test_load_toml(): def test_load_toml():
nonebot.load_from_toml("./plugins.legacy.toml")
nonebot.load_from_toml("./plugins.toml") nonebot.load_from_toml("./plugins.toml")
with pytest.raises(ValueError, match="Cannot find"): with pytest.raises(ValueError, match="Cannot find"):

View File

@@ -0,0 +1,229 @@
---
sidebar_position: 8
description: 轻量化 HTML 绘图
---
# 轻量化 HTML 绘图
图片是机器人交互中不可或缺的一部分,对于信息展示的直观性、美观性有很大的作用。
基于 PIL 直接绘制图片具有良好的性能和存储开销,但是难以调试、维护过程式的绘图代码。
使用浏览器渲染类插件可以方便地绘制网页,且能够直接通过 JS 对网页效果进行编程,但是它占用的存储和内存空间相对可观。
NoneBot 提供的 `nonebot-plugin-htmlkit` 提供了另一种基于 HTML 和 CSS 语法的轻量化绘图选择:它基于 `litehtml` 解析库,无须安装额外的依赖即可使用,没有进程间通信带来的额外开销,且在支持 `webp` `avif` 等丰富图片格式的前提下,安装用的 wheel 文件大小仅有约 10 MB。
作为粗略的性能参考,在一台 Ryzen 7 9700X 的 Windows 电脑上,渲染 [PEP 7](https://peps.python.org/pep-0007/) 的 HTML 页面(分辨率为 800x5788大小约 1.4MB,从本地文件系统读取 CSS大约需要 100ms每个渲染任务内存最高占用约为 40MB.
## 安装插件
在使用前请先安装 `nonebot-plugin-htmlkit` 插件至项目环境中,可参考[获取商店插件](../tutorial/store.mdx#安装插件)来了解并选择安装插件的方式。如:
在**项目目录**下执行以下命令:
```bash
nb plugin install nonebot-plugin-htmlkit
```
`nonebot-plugin-htmlkit` 插件目前兼容以下系统架构:
- Windows x64
- macOS arm64M-系列芯片)
- Linux x64 (非 Alpine 等 musl 系发行版)
- Linux arm64 (非 Alpine 等 musl 系发行版)
:::caution 访问网络内容
如果需要访问网络资源(如 http(s) 网页内容NoneBot 需要客户端型驱动器Forward。内置的驱动器有 `~httpx``~aiohttp`
详见[选择驱动器](../advanced/driver.md)。
:::
## 使用插件
### 加载插件
在使用本插件前同样需要使用 `require` 方法进行**加载**并**导入**需要使用的方法,可参考 [跨插件访问](../advanced/requiring.md) 一节进行了解,如:
```python
from nonebot import require
require("nonebot_plugin_htmlkit")
from nonebot_plugin_htmlkit import html_to_pic, md_to_pic, template_to_pic, text_to_pic
```
插件会自动使用[配置中的参数](#配置-fontconfig)初始化 `fontconfig` 以提供字体查找功能。
### 渲染 API
`nonebot-plugin-htmlkit` 主要提供以下**异步**渲染函数:
#### html_to_pic
```python
async def html_to_pic(
html: str,
*,
base_url: str = "",
dpi: float = 144.0,
max_width: float = 800.0,
device_height: float = 600.0,
default_font_size: float = 12.0,
font_name: str = "sans-serif",
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
lang: str = "zh",
culture: str = "CN",
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
css_fetch_fn: CSSFetchFn = combined_css_fetcher,
urljoin_fn: Callable[[str, str], str] = urllib3.parse.urljoin,
) -> bytes:
...
```
最核心的渲染函数。
`base_url``urljoin_fn` 控制着传入 `image_fetch_fn``css_fetch_fn` 回调的 url 内容。
`allow_refit` 如果为真,渲染时会自动缩小产出图片的宽度到最适合的宽度,否则必定产出 `max_width` 宽度的图片。
`max_width``device_height` 会在 `@media` 判断中被使用。
`img_fetch_fn` 预期为一个异步可调用对象(函数),接收图片 url 并返回对应 url 的 jpeg 或 png 二进制数据(`bytes`),可在拒绝加载时返回 `None`.
`css_fetch_fn` 预期为一个异步可调用对象(函数),接收目标 CSS url 并返回对应 url 的 CSS 文本(`str`),可在拒绝加载时返回 `None`.
以下为辅助的封装函数,关键字参数若未特殊说明均与 `html_to_pic` 含义相同。
#### text_to_pic
```python
async def text_to_pic(
text: str,
css_path: str = "",
*,
max_width: int = 500,
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
) -> bytes:
...
```
可用于渲染多行文本。
`text` 会被放置于 `<div id="main" class="main-box"> <div class="text">` 中,可据此编写 CSS 来改变文本表现。
#### md_to_pic
```python
async def md_to_pic(
md: str = "",
md_path: str = "",
css_path: str = "",
*,
max_width: int = 500,
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
) -> bytes:
...
```
可用于渲染 Markdown 文本。默认为 GitHub Markdown Light 风格,支持基于 `pygments` 的代码高亮。
`md``md_path` 二选一,前者设置时应为 Markdown 的文本,后者设置时应为指向 Markdown 文本文件的路径。
#### template_to_pic
```python
async def template_to_pic(
template_path: str | PathLike[str] | Sequence[str | PathLike[str]],
template_name: str,
templates: Mapping[Any, Any],
filters: None | Mapping[str, Any] = None,
*,
max_width: int = 500,
device_height: int = 600,
base_url: str | None = None,
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
css_fetch_fn: CSSFetchFn = combined_css_fetcher,
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
) -> bytes:
...
```
渲染 jinja2 模板。
`template_path` 为 jinja2 环境的路径,`template_name` 是环境中要加载模板的名字,`templates` 为传入模板的参数,`filters` 为过滤器名 -> 自定义过滤器的映射。
### 控制外部资源获取
通过传入 `img_fetch_fn``css_fetch_fn`,我们可以在实际访问资源前进行审查,修改资源的来源,或是对 IO 操作进行缓存。
`img_fetch_fn` 预期为一个异步可调用对象(函数),接收图片 url 并返回对应 url 的 jpeg 或 png 二进制数据(`bytes`),可在拒绝加载时返回 `None`.
`css_fetch_fn` 预期为一个异步可调用对象(函数),接收目标 CSS url 并返回对应 url 的 CSS 文本(`str`),可在拒绝加载时返回 `None`.
如果你想要禁用外部资源加载/只从文件系统加载/只从网络加载,可以使用 `none_fetcher` `filesystem_***_fetcher` `network_***_fetcher`
默认的 fetcher 行为(对于 `file://` 从文件系统加载,其余从网络加载)位于 `combined_***_fetcher`,可以通过对其封装实现缓存等操作。
## 配置项
### 配置 fontconfig
`htmlkit` 使用 `fontconfig` 查找字体,请参阅 [`fontconfig 用户手册`](https://fontconfig.pages.freedesktop.org/fontconfig/fontconfig-user) 了解环境变量的具体含义、如何通过编写配置文件修改字体配置等。
#### fontconfig_file
- **类型**: `str | None`
- **默认值**: `None`
覆盖默认的配置文件路径。
#### fontconfig_path
- **类型**: `str | None`
- **默认值**: `None`
覆盖默认的配置目录。
#### fontconfig_sysroot
- **类型**: `str | None`
- **默认值**: `None`
覆盖默认的 sysroot。
#### fc_debug
- **类型**: `str | None`
- **默认值**: `None`
设置 Fontconfig 的 debug 级别。
#### fc_dbg_match_filter
- **类型**: `str | None`
- **默认值**: `None`
`FC_DEBUG` 设置为 `MATCH2` 时,过滤 debug 输出。
#### fc_lang
- **类型**: `str | None`
- **默认值**: `None`
设置默认语言,否则从 `LOCALE` 环境变量获取。
#### fontconfig_use_mmap
- **类型**: `str | None`
- **默认值**: `None`
是否使用 `mmap(2)` 读取字体缓存。

View File

@@ -7,6 +7,61 @@ description: 配置编辑器以获得最佳体验
框架基于 [PEP 484](https://www.python.org/dev/peps/pep-0484/)、[PEP 561](https://www.python.org/dev/peps/pep-0561/)、[PEP 8](https://www.python.org/dev/peps/pep-0008/) 等规范进行开发并且**拥有完整类型注解**。框架使用 PyrightPylance工具进行类型检查确保代码可以被编辑器正确解析。 框架基于 [PEP 484](https://www.python.org/dev/peps/pep-0484/)、[PEP 561](https://www.python.org/dev/peps/pep-0561/)、[PEP 8](https://www.python.org/dev/peps/pep-0008/) 等规范进行开发并且**拥有完整类型注解**。框架使用 PyrightPylance工具进行类型检查确保代码可以被编辑器正确解析。
## CLI 脚手架提供的编辑器工具支持
在使用 NB-CLI [创建项目](./quick-start.mdx#创建项目)时,如果选择了用于插件开发的 `simple` 模板,其会根据选择的开发工具,**自动配置项目根目录下的 `.vscode/extensions.json` 文件**,以推荐最匹配的 VS Code 插件,同时自动将相应的预设配置项写入 `pyproject.toml` 作为“开箱即用”配置,从而提升开发体验。
```bash
[?] 选择一个要使用的模板: simple (插件开发者)
...
[?] 要使用哪些开发工具?
```
### 支持的开发工具
1. Pyright (Pylance)
[VS Code 插件](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance) | [项目](https://github.com/microsoft/pyright) | [文档](https://microsoft.github.io/pyright/)
由微软开发的 Python 静态类型检查器和语言服务器,提供智能感知、跳转定义、查找引用、实时错误检查等强大功能。
作为 VS Code 官方推荐的 Python 语言服务器,与 Pylance 扩展配合使用,能提供最流畅、最准确的代码补全和类型推断体验,是绝大多数开发者的首选。
2. Ruff
[VS Code 插件](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff) | [项目](https://github.com/astral-sh/ruff) | [文档](https://docs.astral.sh/ruff/)
一个用 Rust 编写的超快 Python 代码格式化和 lint 工具,完全兼容 `black``isort``flake8` 等主流工具的规则。
速度极快(比 `black``flake8` 快 100 倍以上),配置简单,能自动格式化代码并检测潜在错误、代码风格问题(尤其是误用同步网络请求库),是提升代码质量和开发效率的必备利器。
3. MyPy
[VS Code 插件](https://marketplace.visualstudio.com/items?itemName=matangover.mypy) | [项目](https://github.com/python/mypy) | [文档](https://mypy.readthedocs.io/en/stable/index.html)
一个官方实现的 Python 静态类型检查器,通过分析代码中的类型注解来发现类型错误。
4. BasedPyright
[VS Code 插件](https://marketplace.visualstudio.com/items?itemName=detachhead.basedpyright) | [项目](https://github.com/DetachHead/basedpyright) | [文档](https://docs.basedpyright.com/)
一个基于 Pyright 的、由社区维护的替代性 Python 语言服务器,旨在提供更优的类型检查支持与接近 Pylance 的更好的使用体验。
相较于 PylanceBasedPyright 允许配合 VS Code 之外的其他编辑器使用,同时也复刻了部分 Pylance 限定的功能。
如果您是高级用户,希望尝试 Pylance 的替代方案,或遇到 Pylance 在特定环境下的兼容性问题,可以考虑使用 BasedPyright。
:::caution 提示
为避免 `Pylance``BasedPyright` 相互冲突导致配置混乱甚至异常,脚手架默认不允许在创建项目时同时配置这两者。
如果确实需要同时使用,请在创建项目时选择 Pylance/Pyright 并根据[相关文档](https://docs.basedpyright.com/latest/installation/ides/#vscode-vscodium)进行手动配置。
:::
### 配置效果
选择上述工具后NB-CLI 会在您的项目根目录下生成一个 `.vscode/extensions.json` 文件并在 `pyproject.toml` 文件中写入相应的配置项。当您在 VS Code 中打开此项目时IDE
会自动弹出提示,建议您安装这些推荐的扩展,一键即可完成开发环境的初始化,让您可以立即开始编写代码,无需手动搜索和安装插件。
## 编辑器推荐配置 ## 编辑器推荐配置
### Visual Studio Code ### Visual Studio Code

View File

@@ -81,8 +81,9 @@ nb create
请注意,多选项使用**空格**选中或取消,**回车**确认。 请注意,多选项使用**空格**选中或取消,**回车**确认。
```bash ```bash
[?] 要使用哪些驱动器? FastAPI (FastAPI 驱动器)
[?] 要使用哪些适配器? Console (基于终端的交互式适配器) [?] 要使用哪些适配器? Console (基于终端的交互式适配器)
[?] 要使用哪些驱动器? FastAPI (FastAPI 驱动器)
[?] 要使用什么本地存储策略? 用户全局 (默认,适用于单用户下单实例)
[?] 立即安装依赖? (Y/n) Yes [?] 立即安装依赖? (Y/n) Yes
[?] 创建虚拟环境? (Y/n) Yes [?] 创建虚拟环境? (Y/n) Yes
``` ```

View File

@@ -189,12 +189,16 @@ nonebot.load_from_json("plugin_config.json", encoding="utf-8")
### `load_from_toml` ### `load_from_toml`
通过 TOML 文件加载插件,是 [`load_all_plugins`](#load_all_plugins) 的 TOML 变种。通过读取 TOML 文件中的 `[tool.nonebot]` Table 中的 `plugins` 和 `plugin_dirs` Array 进行加载。例如: 通过 TOML 文件加载插件,是 [`load_all_plugins`](#load_all_plugins) 的 TOML 变种。通过读取 TOML 文件中的 `[tool.nonebot]` Table 中的 `plugin_dirs` Array
`[tool.nonebot.plugins]` Table 中的多个 Array 进行加载。例如:
```toml title=plugin_config.toml ```toml title=plugin_config.toml
[tool.nonebot] [tool.nonebot]
plugins = ["path.to.your.plugin"]
plugin_dirs = ["path/to/your/plugins"] plugin_dirs = ["path/to/your/plugins"]
[tool.nonebot.plugins]
"@local" = ["path.to.your.plugin"] # 本地插件等非插件商店来源的插件
"nonebot-plugin-someplugin" = ["nonebot_plugin_someplugin"] # 插件商店来源的插件
``` ```
```python ```python

View File

@@ -24,6 +24,9 @@ NoneBot 提供了一个[商店](/store/plugins),商店内容均由社区开发
商店中每个内容的卡片都包含了其名称和简介等信息,点击**卡片右上角**链接图标即可跳转到其主页。 商店中每个内容的卡片都包含了其名称和简介等信息,点击**卡片右上角**链接图标即可跳转到其主页。
与此同时NB-CLI 也提供了一个 TUI 版本的商店界面,可通过 `nb adapter store`、`nb plugin store`、`nb driver store` 命令或 CLI
交互式界面进入。其提供了接近网页商店的体验,同时允许快捷安装到当前项目。
## 安装插件 ## 安装插件
<Asciinema <Asciinema

View File

@@ -7,8 +7,14 @@ toc_max_heading_level: 2
## 最近更新 ## 最近更新
### 🚀 新功能
- Feature: 更新 NB-CLI 新版插件加载格式与文档 [@NCBM](https://github.com/NCBM) ([#3614](https://github.com/nonebot/nonebot2/pull/3614))
### 📝 文档 ### 📝 文档
- Feature: 更新 NB-CLI 新版插件加载格式与文档 [@NCBM](https://github.com/NCBM) ([#3614](https://github.com/nonebot/nonebot2/pull/3614))
- Docs: 添加 htmlkit 文档至最佳实践 [@BlueGlassBlock](https://github.com/BlueGlassBlock) ([#3682](https://github.com/nonebot/nonebot2/pull/3682))
- Docs: 修复 userinfo 插件链接 [@XieXiLin2](https://github.com/XieXiLin2) ([#3660](https://github.com/nonebot/nonebot2/pull/3660)) - Docs: 修复 userinfo 插件链接 [@XieXiLin2](https://github.com/XieXiLin2) ([#3660](https://github.com/nonebot/nonebot2/pull/3660))
- Docs: 升级 docusaurus 3.8.1 [@StarHeartHunt](https://github.com/StarHeartHunt) ([#3649](https://github.com/nonebot/nonebot2/pull/3649)) - Docs: 升级 docusaurus 3.8.1 [@StarHeartHunt](https://github.com/StarHeartHunt) ([#3649](https://github.com/nonebot/nonebot2/pull/3649))
- Docs: 更新文档《手动创建项目》 [@Chen-Luan](https://github.com/Chen-Luan) ([#3623](https://github.com/nonebot/nonebot2/pull/3623)) - Docs: 更新文档《手动创建项目》 [@Chen-Luan](https://github.com/Chen-Luan) ([#3623](https://github.com/nonebot/nonebot2/pull/3623))

View File

@@ -0,0 +1,229 @@
---
sidebar_position: 8
description: 轻量化 HTML 绘图
---
# 轻量化 HTML 绘图
图片是机器人交互中不可或缺的一部分,对于信息展示的直观性、美观性有很大的作用。
基于 PIL 直接绘制图片具有良好的性能和存储开销,但是难以调试、维护过程式的绘图代码。
使用浏览器渲染类插件可以方便地绘制网页,且能够直接通过 JS 对网页效果进行编程,但是它占用的存储和内存空间相对可观。
NoneBot 提供的 `nonebot-plugin-htmlkit` 提供了另一种基于 HTML 和 CSS 语法的轻量化绘图选择:它基于 `litehtml` 解析库,无须安装额外的依赖即可使用,没有进程间通信带来的额外开销,且在支持 `webp` `avif` 等丰富图片格式的前提下,安装用的 wheel 文件大小仅有约 10 MB。
作为粗略的性能参考,在一台 Ryzen 7 9700X 的 Windows 电脑上,渲染 [PEP 7](https://peps.python.org/pep-0007/) 的 HTML 页面(分辨率为 800x5788大小约 1.4MB,从本地文件系统读取 CSS大约需要 100ms每个渲染任务内存最高占用约为 40MB.
## 安装插件
在使用前请先安装 `nonebot-plugin-htmlkit` 插件至项目环境中,可参考[获取商店插件](../tutorial/store.mdx#安装插件)来了解并选择安装插件的方式。如:
在**项目目录**下执行以下命令:
```bash
nb plugin install nonebot-plugin-htmlkit
```
`nonebot-plugin-htmlkit` 插件目前兼容以下系统架构:
- Windows x64
- macOS arm64M-系列芯片)
- Linux x64 (非 Alpine 等 musl 系发行版)
- Linux arm64 (非 Alpine 等 musl 系发行版)
:::caution 访问网络内容
如果需要访问网络资源(如 http(s) 网页内容NoneBot 需要客户端型驱动器Forward。内置的驱动器有 `~httpx``~aiohttp`
详见[选择驱动器](../advanced/driver.md)。
:::
## 使用插件
### 加载插件
在使用本插件前同样需要使用 `require` 方法进行**加载**并**导入**需要使用的方法,可参考 [跨插件访问](../advanced/requiring.md) 一节进行了解,如:
```python
from nonebot import require
require("nonebot_plugin_htmlkit")
from nonebot_plugin_htmlkit import html_to_pic, md_to_pic, template_to_pic, text_to_pic
```
插件会自动使用[配置中的参数](#配置-fontconfig)初始化 `fontconfig` 以提供字体查找功能。
### 渲染 API
`nonebot-plugin-htmlkit` 主要提供以下**异步**渲染函数:
#### html_to_pic
```python
async def html_to_pic(
html: str,
*,
base_url: str = "",
dpi: float = 144.0,
max_width: float = 800.0,
device_height: float = 600.0,
default_font_size: float = 12.0,
font_name: str = "sans-serif",
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
lang: str = "zh",
culture: str = "CN",
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
css_fetch_fn: CSSFetchFn = combined_css_fetcher,
urljoin_fn: Callable[[str, str], str] = urllib3.parse.urljoin,
) -> bytes:
...
```
最核心的渲染函数。
`base_url``urljoin_fn` 控制着传入 `image_fetch_fn``css_fetch_fn` 回调的 url 内容。
`allow_refit` 如果为真,渲染时会自动缩小产出图片的宽度到最适合的宽度,否则必定产出 `max_width` 宽度的图片。
`max_width``device_height` 会在 `@media` 判断中被使用。
`img_fetch_fn` 预期为一个异步可调用对象(函数),接收图片 url 并返回对应 url 的 jpeg 或 png 二进制数据(`bytes`),可在拒绝加载时返回 `None`.
`css_fetch_fn` 预期为一个异步可调用对象(函数),接收目标 CSS url 并返回对应 url 的 CSS 文本(`str`),可在拒绝加载时返回 `None`.
以下为辅助的封装函数,关键字参数若未特殊说明均与 `html_to_pic` 含义相同。
#### text_to_pic
```python
async def text_to_pic(
text: str,
css_path: str = "",
*,
max_width: int = 500,
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
) -> bytes:
...
```
可用于渲染多行文本。
`text` 会被放置于 `<div id="main" class="main-box"> <div class="text">` 中,可据此编写 CSS 来改变文本表现。
#### md_to_pic
```python
async def md_to_pic(
md: str = "",
md_path: str = "",
css_path: str = "",
*,
max_width: int = 500,
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
) -> bytes:
...
```
可用于渲染 Markdown 文本。默认为 GitHub Markdown Light 风格,支持基于 `pygments` 的代码高亮。
`md``md_path` 二选一,前者设置时应为 Markdown 的文本,后者设置时应为指向 Markdown 文本文件的路径。
#### template_to_pic
```python
async def template_to_pic(
template_path: str | PathLike[str] | Sequence[str | PathLike[str]],
template_name: str,
templates: Mapping[Any, Any],
filters: None | Mapping[str, Any] = None,
*,
max_width: int = 500,
device_height: int = 600,
base_url: str | None = None,
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
css_fetch_fn: CSSFetchFn = combined_css_fetcher,
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
) -> bytes:
...
```
渲染 jinja2 模板。
`template_path` 为 jinja2 环境的路径,`template_name` 是环境中要加载模板的名字,`templates` 为传入模板的参数,`filters` 为过滤器名 -> 自定义过滤器的映射。
### 控制外部资源获取
通过传入 `img_fetch_fn``css_fetch_fn`,我们可以在实际访问资源前进行审查,修改资源的来源,或是对 IO 操作进行缓存。
`img_fetch_fn` 预期为一个异步可调用对象(函数),接收图片 url 并返回对应 url 的 jpeg 或 png 二进制数据(`bytes`),可在拒绝加载时返回 `None`.
`css_fetch_fn` 预期为一个异步可调用对象(函数),接收目标 CSS url 并返回对应 url 的 CSS 文本(`str`),可在拒绝加载时返回 `None`.
如果你想要禁用外部资源加载/只从文件系统加载/只从网络加载,可以使用 `none_fetcher` `filesystem_***_fetcher` `network_***_fetcher`
默认的 fetcher 行为(对于 `file://` 从文件系统加载,其余从网络加载)位于 `combined_***_fetcher`,可以通过对其封装实现缓存等操作。
## 配置项
### 配置 fontconfig
`htmlkit` 使用 `fontconfig` 查找字体,请参阅 [`fontconfig 用户手册`](https://fontconfig.pages.freedesktop.org/fontconfig/fontconfig-user) 了解环境变量的具体含义、如何通过编写配置文件修改字体配置等。
#### fontconfig_file
- **类型**: `str | None`
- **默认值**: `None`
覆盖默认的配置文件路径。
#### fontconfig_path
- **类型**: `str | None`
- **默认值**: `None`
覆盖默认的配置目录。
#### fontconfig_sysroot
- **类型**: `str | None`
- **默认值**: `None`
覆盖默认的 sysroot。
#### fc_debug
- **类型**: `str | None`
- **默认值**: `None`
设置 Fontconfig 的 debug 级别。
#### fc_dbg_match_filter
- **类型**: `str | None`
- **默认值**: `None`
`FC_DEBUG` 设置为 `MATCH2` 时,过滤 debug 输出。
#### fc_lang
- **类型**: `str | None`
- **默认值**: `None`
设置默认语言,否则从 `LOCALE` 环境变量获取。
#### fontconfig_use_mmap
- **类型**: `str | None`
- **默认值**: `None`
是否使用 `mmap(2)` 读取字体缓存。

View File

@@ -0,0 +1,229 @@
---
sidebar_position: 8
description: 轻量化 HTML 绘图
---
# 轻量化 HTML 绘图
图片是机器人交互中不可或缺的一部分,对于信息展示的直观性、美观性有很大的作用。
基于 PIL 直接绘制图片具有良好的性能和存储开销,但是难以调试、维护过程式的绘图代码。
使用浏览器渲染类插件可以方便地绘制网页,且能够直接通过 JS 对网页效果进行编程,但是它占用的存储和内存空间相对可观。
NoneBot 提供的 `nonebot-plugin-htmlkit` 提供了另一种基于 HTML 和 CSS 语法的轻量化绘图选择:它基于 `litehtml` 解析库,无须安装额外的依赖即可使用,没有进程间通信带来的额外开销,且在支持 `webp` `avif` 等丰富图片格式的前提下,安装用的 wheel 文件大小仅有约 10 MB。
作为粗略的性能参考,在一台 Ryzen 7 9700X 的 Windows 电脑上,渲染 [PEP 7](https://peps.python.org/pep-0007/) 的 HTML 页面(分辨率为 800x5788大小约 1.4MB,从本地文件系统读取 CSS大约需要 100ms每个渲染任务内存最高占用约为 40MB.
## 安装插件
在使用前请先安装 `nonebot-plugin-htmlkit` 插件至项目环境中,可参考[获取商店插件](../tutorial/store.mdx#安装插件)来了解并选择安装插件的方式。如:
在**项目目录**下执行以下命令:
```bash
nb plugin install nonebot-plugin-htmlkit
```
`nonebot-plugin-htmlkit` 插件目前兼容以下系统架构:
- Windows x64
- macOS arm64M-系列芯片)
- Linux x64 (非 Alpine 等 musl 系发行版)
- Linux arm64 (非 Alpine 等 musl 系发行版)
:::caution 访问网络内容
如果需要访问网络资源(如 http(s) 网页内容NoneBot 需要客户端型驱动器Forward。内置的驱动器有 `~httpx``~aiohttp`
详见[选择驱动器](../advanced/driver.md)。
:::
## 使用插件
### 加载插件
在使用本插件前同样需要使用 `require` 方法进行**加载**并**导入**需要使用的方法,可参考 [跨插件访问](../advanced/requiring.md) 一节进行了解,如:
```python
from nonebot import require
require("nonebot_plugin_htmlkit")
from nonebot_plugin_htmlkit import html_to_pic, md_to_pic, template_to_pic, text_to_pic
```
插件会自动使用[配置中的参数](#配置-fontconfig)初始化 `fontconfig` 以提供字体查找功能。
### 渲染 API
`nonebot-plugin-htmlkit` 主要提供以下**异步**渲染函数:
#### html_to_pic
```python
async def html_to_pic(
html: str,
*,
base_url: str = "",
dpi: float = 144.0,
max_width: float = 800.0,
device_height: float = 600.0,
default_font_size: float = 12.0,
font_name: str = "sans-serif",
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
lang: str = "zh",
culture: str = "CN",
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
css_fetch_fn: CSSFetchFn = combined_css_fetcher,
urljoin_fn: Callable[[str, str], str] = urllib3.parse.urljoin,
) -> bytes:
...
```
最核心的渲染函数。
`base_url``urljoin_fn` 控制着传入 `image_fetch_fn``css_fetch_fn` 回调的 url 内容。
`allow_refit` 如果为真,渲染时会自动缩小产出图片的宽度到最适合的宽度,否则必定产出 `max_width` 宽度的图片。
`max_width``device_height` 会在 `@media` 判断中被使用。
`img_fetch_fn` 预期为一个异步可调用对象(函数),接收图片 url 并返回对应 url 的 jpeg 或 png 二进制数据(`bytes`),可在拒绝加载时返回 `None`.
`css_fetch_fn` 预期为一个异步可调用对象(函数),接收目标 CSS url 并返回对应 url 的 CSS 文本(`str`),可在拒绝加载时返回 `None`.
以下为辅助的封装函数,关键字参数若未特殊说明均与 `html_to_pic` 含义相同。
#### text_to_pic
```python
async def text_to_pic(
text: str,
css_path: str = "",
*,
max_width: int = 500,
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
) -> bytes:
...
```
可用于渲染多行文本。
`text` 会被放置于 `<div id="main" class="main-box"> <div class="text">` 中,可据此编写 CSS 来改变文本表现。
#### md_to_pic
```python
async def md_to_pic(
md: str = "",
md_path: str = "",
css_path: str = "",
*,
max_width: int = 500,
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
) -> bytes:
...
```
可用于渲染 Markdown 文本。默认为 GitHub Markdown Light 风格,支持基于 `pygments` 的代码高亮。
`md``md_path` 二选一,前者设置时应为 Markdown 的文本,后者设置时应为指向 Markdown 文本文件的路径。
#### template_to_pic
```python
async def template_to_pic(
template_path: str | PathLike[str] | Sequence[str | PathLike[str]],
template_name: str,
templates: Mapping[Any, Any],
filters: None | Mapping[str, Any] = None,
*,
max_width: int = 500,
device_height: int = 600,
base_url: str | None = None,
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
css_fetch_fn: CSSFetchFn = combined_css_fetcher,
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
) -> bytes:
...
```
渲染 jinja2 模板。
`template_path` 为 jinja2 环境的路径,`template_name` 是环境中要加载模板的名字,`templates` 为传入模板的参数,`filters` 为过滤器名 -> 自定义过滤器的映射。
### 控制外部资源获取
通过传入 `img_fetch_fn``css_fetch_fn`,我们可以在实际访问资源前进行审查,修改资源的来源,或是对 IO 操作进行缓存。
`img_fetch_fn` 预期为一个异步可调用对象(函数),接收图片 url 并返回对应 url 的 jpeg 或 png 二进制数据(`bytes`),可在拒绝加载时返回 `None`.
`css_fetch_fn` 预期为一个异步可调用对象(函数),接收目标 CSS url 并返回对应 url 的 CSS 文本(`str`),可在拒绝加载时返回 `None`.
如果你想要禁用外部资源加载/只从文件系统加载/只从网络加载,可以使用 `none_fetcher` `filesystem_***_fetcher` `network_***_fetcher`
默认的 fetcher 行为(对于 `file://` 从文件系统加载,其余从网络加载)位于 `combined_***_fetcher`,可以通过对其封装实现缓存等操作。
## 配置项
### 配置 fontconfig
`htmlkit` 使用 `fontconfig` 查找字体,请参阅 [`fontconfig 用户手册`](https://fontconfig.pages.freedesktop.org/fontconfig/fontconfig-user) 了解环境变量的具体含义、如何通过编写配置文件修改字体配置等。
#### fontconfig_file
- **类型**: `str | None`
- **默认值**: `None`
覆盖默认的配置文件路径。
#### fontconfig_path
- **类型**: `str | None`
- **默认值**: `None`
覆盖默认的配置目录。
#### fontconfig_sysroot
- **类型**: `str | None`
- **默认值**: `None`
覆盖默认的 sysroot。
#### fc_debug
- **类型**: `str | None`
- **默认值**: `None`
设置 Fontconfig 的 debug 级别。
#### fc_dbg_match_filter
- **类型**: `str | None`
- **默认值**: `None`
`FC_DEBUG` 设置为 `MATCH2` 时,过滤 debug 输出。
#### fc_lang
- **类型**: `str | None`
- **默认值**: `None`
设置默认语言,否则从 `LOCALE` 环境变量获取。
#### fontconfig_use_mmap
- **类型**: `str | None`
- **默认值**: `None`
是否使用 `mmap(2)` 读取字体缓存。

View File

@@ -0,0 +1,229 @@
---
sidebar_position: 8
description: 轻量化 HTML 绘图
---
# 轻量化 HTML 绘图
图片是机器人交互中不可或缺的一部分,对于信息展示的直观性、美观性有很大的作用。
基于 PIL 直接绘制图片具有良好的性能和存储开销,但是难以调试、维护过程式的绘图代码。
使用浏览器渲染类插件可以方便地绘制网页,且能够直接通过 JS 对网页效果进行编程,但是它占用的存储和内存空间相对可观。
NoneBot 提供的 `nonebot-plugin-htmlkit` 提供了另一种基于 HTML 和 CSS 语法的轻量化绘图选择:它基于 `litehtml` 解析库,无须安装额外的依赖即可使用,没有进程间通信带来的额外开销,且在支持 `webp` `avif` 等丰富图片格式的前提下,安装用的 wheel 文件大小仅有约 10 MB。
作为粗略的性能参考,在一台 Ryzen 7 9700X 的 Windows 电脑上,渲染 [PEP 7](https://peps.python.org/pep-0007/) 的 HTML 页面(分辨率为 800x5788大小约 1.4MB,从本地文件系统读取 CSS大约需要 100ms每个渲染任务内存最高占用约为 40MB.
## 安装插件
在使用前请先安装 `nonebot-plugin-htmlkit` 插件至项目环境中,可参考[获取商店插件](../tutorial/store.mdx#安装插件)来了解并选择安装插件的方式。如:
在**项目目录**下执行以下命令:
```bash
nb plugin install nonebot-plugin-htmlkit
```
`nonebot-plugin-htmlkit` 插件目前兼容以下系统架构:
- Windows x64
- macOS arm64M-系列芯片)
- Linux x64 (非 Alpine 等 musl 系发行版)
- Linux arm64 (非 Alpine 等 musl 系发行版)
:::caution 访问网络内容
如果需要访问网络资源(如 http(s) 网页内容NoneBot 需要客户端型驱动器Forward。内置的驱动器有 `~httpx``~aiohttp`
详见[选择驱动器](../advanced/driver.md)。
:::
## 使用插件
### 加载插件
在使用本插件前同样需要使用 `require` 方法进行**加载**并**导入**需要使用的方法,可参考 [跨插件访问](../advanced/requiring.md) 一节进行了解,如:
```python
from nonebot import require
require("nonebot_plugin_htmlkit")
from nonebot_plugin_htmlkit import html_to_pic, md_to_pic, template_to_pic, text_to_pic
```
插件会自动使用[配置中的参数](#配置-fontconfig)初始化 `fontconfig` 以提供字体查找功能。
### 渲染 API
`nonebot-plugin-htmlkit` 主要提供以下**异步**渲染函数:
#### html_to_pic
```python
async def html_to_pic(
html: str,
*,
base_url: str = "",
dpi: float = 144.0,
max_width: float = 800.0,
device_height: float = 600.0,
default_font_size: float = 12.0,
font_name: str = "sans-serif",
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
lang: str = "zh",
culture: str = "CN",
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
css_fetch_fn: CSSFetchFn = combined_css_fetcher,
urljoin_fn: Callable[[str, str], str] = urllib3.parse.urljoin,
) -> bytes:
...
```
最核心的渲染函数。
`base_url``urljoin_fn` 控制着传入 `image_fetch_fn``css_fetch_fn` 回调的 url 内容。
`allow_refit` 如果为真,渲染时会自动缩小产出图片的宽度到最适合的宽度,否则必定产出 `max_width` 宽度的图片。
`max_width``device_height` 会在 `@media` 判断中被使用。
`img_fetch_fn` 预期为一个异步可调用对象(函数),接收图片 url 并返回对应 url 的 jpeg 或 png 二进制数据(`bytes`),可在拒绝加载时返回 `None`.
`css_fetch_fn` 预期为一个异步可调用对象(函数),接收目标 CSS url 并返回对应 url 的 CSS 文本(`str`),可在拒绝加载时返回 `None`.
以下为辅助的封装函数,关键字参数若未特殊说明均与 `html_to_pic` 含义相同。
#### text_to_pic
```python
async def text_to_pic(
text: str,
css_path: str = "",
*,
max_width: int = 500,
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
) -> bytes:
...
```
可用于渲染多行文本。
`text` 会被放置于 `<div id="main" class="main-box"> <div class="text">` 中,可据此编写 CSS 来改变文本表现。
#### md_to_pic
```python
async def md_to_pic(
md: str = "",
md_path: str = "",
css_path: str = "",
*,
max_width: int = 500,
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
) -> bytes:
...
```
可用于渲染 Markdown 文本。默认为 GitHub Markdown Light 风格,支持基于 `pygments` 的代码高亮。
`md``md_path` 二选一,前者设置时应为 Markdown 的文本,后者设置时应为指向 Markdown 文本文件的路径。
#### template_to_pic
```python
async def template_to_pic(
template_path: str | PathLike[str] | Sequence[str | PathLike[str]],
template_name: str,
templates: Mapping[Any, Any],
filters: None | Mapping[str, Any] = None,
*,
max_width: int = 500,
device_height: int = 600,
base_url: str | None = None,
img_fetch_fn: ImgFetchFn = combined_img_fetcher,
css_fetch_fn: CSSFetchFn = combined_css_fetcher,
allow_refit: bool = True,
image_format: Literal["png", "jpeg"] = "png",
jpeg_quality: int = 100,
) -> bytes:
...
```
渲染 jinja2 模板。
`template_path` 为 jinja2 环境的路径,`template_name` 是环境中要加载模板的名字,`templates` 为传入模板的参数,`filters` 为过滤器名 -> 自定义过滤器的映射。
### 控制外部资源获取
通过传入 `img_fetch_fn``css_fetch_fn`,我们可以在实际访问资源前进行审查,修改资源的来源,或是对 IO 操作进行缓存。
`img_fetch_fn` 预期为一个异步可调用对象(函数),接收图片 url 并返回对应 url 的 jpeg 或 png 二进制数据(`bytes`),可在拒绝加载时返回 `None`.
`css_fetch_fn` 预期为一个异步可调用对象(函数),接收目标 CSS url 并返回对应 url 的 CSS 文本(`str`),可在拒绝加载时返回 `None`.
如果你想要禁用外部资源加载/只从文件系统加载/只从网络加载,可以使用 `none_fetcher` `filesystem_***_fetcher` `network_***_fetcher`
默认的 fetcher 行为(对于 `file://` 从文件系统加载,其余从网络加载)位于 `combined_***_fetcher`,可以通过对其封装实现缓存等操作。
## 配置项
### 配置 fontconfig
`htmlkit` 使用 `fontconfig` 查找字体,请参阅 [`fontconfig 用户手册`](https://fontconfig.pages.freedesktop.org/fontconfig/fontconfig-user) 了解环境变量的具体含义、如何通过编写配置文件修改字体配置等。
#### fontconfig_file
- **类型**: `str | None`
- **默认值**: `None`
覆盖默认的配置文件路径。
#### fontconfig_path
- **类型**: `str | None`
- **默认值**: `None`
覆盖默认的配置目录。
#### fontconfig_sysroot
- **类型**: `str | None`
- **默认值**: `None`
覆盖默认的 sysroot。
#### fc_debug
- **类型**: `str | None`
- **默认值**: `None`
设置 Fontconfig 的 debug 级别。
#### fc_dbg_match_filter
- **类型**: `str | None`
- **默认值**: `None`
`FC_DEBUG` 设置为 `MATCH2` 时,过滤 debug 输出。
#### fc_lang
- **类型**: `str | None`
- **默认值**: `None`
设置默认语言,否则从 `LOCALE` 环境变量获取。
#### fontconfig_use_mmap
- **类型**: `str | None`
- **默认值**: `None`
是否使用 `mmap(2)` 读取字体缓存。