nonebot-plugin-htmlrender 0.7.0a3__py3-none-any.whl → 0.7.2__py3-none-any.whl

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 (58) hide show
  1. nonebot_plugin_htmlrender/__init__.py +146 -22
  2. nonebot_plugin_htmlrender/_bootstrap.py +122 -0
  3. nonebot_plugin_htmlrender/_compat.py +308 -0
  4. nonebot_plugin_htmlrender/backend/__init__.py +39 -0
  5. nonebot_plugin_htmlrender/backend/base.py +217 -0
  6. nonebot_plugin_htmlrender/backend/factory.py +222 -0
  7. nonebot_plugin_htmlrender/backend/playwright/__init__.py +9 -0
  8. nonebot_plugin_htmlrender/backend/playwright/_page.py +258 -0
  9. nonebot_plugin_htmlrender/backend/playwright/config.py +244 -0
  10. nonebot_plugin_htmlrender/backend/playwright/data_source.py +90 -0
  11. nonebot_plugin_htmlrender/backend/playwright/install.py +161 -0
  12. nonebot_plugin_htmlrender/backend/playwright/models.py +432 -0
  13. nonebot_plugin_htmlrender/backend/playwright/operations.py +707 -0
  14. nonebot_plugin_htmlrender/backend/playwright/render.py +772 -0
  15. nonebot_plugin_htmlrender/backend/playwright/runtime.py +441 -0
  16. nonebot_plugin_htmlrender/backend/playwright/telemetry.py +240 -0
  17. nonebot_plugin_htmlrender/backend/playwright/types.py +280 -0
  18. nonebot_plugin_htmlrender/browser.py +31 -290
  19. nonebot_plugin_htmlrender/config.py +35 -86
  20. nonebot_plugin_htmlrender/consts.py +109 -23
  21. nonebot_plugin_htmlrender/data_source.py +36 -312
  22. nonebot_plugin_htmlrender/py.typed +0 -0
  23. nonebot_plugin_htmlrender/render.py +720 -0
  24. nonebot_plugin_htmlrender/resources/__init__.py +34 -0
  25. nonebot_plugin_htmlrender/resources/config.py +66 -0
  26. nonebot_plugin_htmlrender/resources/filehost/__init__.py +162 -0
  27. nonebot_plugin_htmlrender/resources/filehost/cache.py +258 -0
  28. nonebot_plugin_htmlrender/resources/filehost/guard.py +159 -0
  29. nonebot_plugin_htmlrender/resources/filehost/warmup.py +256 -0
  30. nonebot_plugin_htmlrender/resources/resolve.py +348 -0
  31. nonebot_plugin_htmlrender/resources/template.py +313 -0
  32. nonebot_plugin_htmlrender/templates/{markdown.html → markdown/markdown.html} +3 -3
  33. nonebot_plugin_htmlrender/templates/{text.html → text/text.html} +1 -1
  34. nonebot_plugin_htmlrender/utils/__init__.py +48 -0
  35. nonebot_plugin_htmlrender/utils/install.py +172 -0
  36. nonebot_plugin_htmlrender/utils/process.py +292 -0
  37. nonebot_plugin_htmlrender/utils/signal.py +165 -0
  38. nonebot_plugin_htmlrender/utils/telemetry/__init__.py +91 -0
  39. nonebot_plugin_htmlrender/utils/telemetry/common.py +160 -0
  40. nonebot_plugin_htmlrender/utils/telemetry/prometheus.py +199 -0
  41. nonebot_plugin_htmlrender/utils/telemetry/sentry.py +228 -0
  42. nonebot_plugin_htmlrender-0.7.2.dist-info/METADATA +205 -0
  43. nonebot_plugin_htmlrender-0.7.2.dist-info/RECORD +52 -0
  44. {nonebot_plugin_htmlrender-0.7.0a3.dist-info → nonebot_plugin_htmlrender-0.7.2.dist-info}/WHEEL +1 -1
  45. nonebot_plugin_htmlrender/install.py +0 -251
  46. nonebot_plugin_htmlrender/process.py +0 -193
  47. nonebot_plugin_htmlrender/signal.py +0 -138
  48. nonebot_plugin_htmlrender/utils.py +0 -222
  49. nonebot_plugin_htmlrender-0.7.0a3.dist-info/METADATA +0 -222
  50. nonebot_plugin_htmlrender-0.7.0a3.dist-info/RECORD +0 -22
  51. /nonebot_plugin_htmlrender/templates/{github-markdown-light.css → markdown/github-markdown-light.css} +0 -0
  52. /nonebot_plugin_htmlrender/templates/{katex → markdown/katex}/katex.min.b64_fonts.css +0 -0
  53. /nonebot_plugin_htmlrender/templates/{katex → markdown/katex}/katex.min.js +0 -0
  54. /nonebot_plugin_htmlrender/templates/{katex → markdown/katex}/mathtex-script-type.min.js +0 -0
  55. /nonebot_plugin_htmlrender/templates/{katex → markdown/katex}/mhchem.min.js +0 -0
  56. /nonebot_plugin_htmlrender/templates/{pygments-default.css → markdown/pygments-default.css} +0 -0
  57. /nonebot_plugin_htmlrender/templates/{text.css → text/text.css} +0 -0
  58. {nonebot_plugin_htmlrender-0.7.0a3.dist-info → nonebot_plugin_htmlrender-0.7.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,64 +1,188 @@
1
+ from importlib import import_module
2
+ from typing import Any
3
+
1
4
  import nonebot
2
5
  from nonebot import require
3
-
4
- require("nonebot_plugin_localstore")
5
6
  from nonebot.log import logger
6
7
  from nonebot.plugin import PluginMetadata
7
8
 
8
- from nonebot_plugin_htmlrender.browser import (
9
- get_new_page,
10
- shutdown_htmlrender,
11
- startup_htmlrender,
9
+ require("nonebot_plugin_localstore")
10
+
11
+ from nonebot_plugin_htmlrender._bootstrap import (
12
+ _bootstrap_filehost_guard_on_import as _bootstrap_filehost_guard_on_import,
13
+ )
14
+ from nonebot_plugin_htmlrender._bootstrap import (
15
+ _bootstrap_optional_plugins_on_import as _bootstrap_optional_plugins_on_import,
16
+ )
17
+ from nonebot_plugin_htmlrender._bootstrap import (
18
+ _patch_filehost_request_headers_validator as _patch_filehost_request_headers_validator,
19
+ )
20
+
21
+ _bootstrap_optional_plugins_on_import()
22
+ _bootstrap_filehost_guard_on_import()
23
+
24
+ from nonebot_plugin_htmlrender._compat import (
25
+ capture_element as capture_element,
26
+ )
27
+ from nonebot_plugin_htmlrender._compat import (
28
+ get_new_page as get_new_page,
29
+ )
30
+ from nonebot_plugin_htmlrender._compat import (
31
+ html_to_pic as html_to_pic,
32
+ )
33
+ from nonebot_plugin_htmlrender._compat import (
34
+ md_to_pic as md_to_pic,
12
35
  )
36
+ from nonebot_plugin_htmlrender._compat import (
37
+ shutdown_htmlrender as shutdown_htmlrender,
38
+ )
39
+ from nonebot_plugin_htmlrender._compat import (
40
+ startup_htmlrender as startup_htmlrender,
41
+ )
42
+ from nonebot_plugin_htmlrender._compat import (
43
+ template_to_html as template_to_html,
44
+ )
45
+ from nonebot_plugin_htmlrender._compat import (
46
+ template_to_pic as template_to_pic,
47
+ )
48
+ from nonebot_plugin_htmlrender._compat import (
49
+ text_to_pic as text_to_pic,
50
+ )
51
+ from nonebot_plugin_htmlrender.backend.factory import ensure_backend_loaded
13
52
  from nonebot_plugin_htmlrender.config import Config, plugin_config
14
- from nonebot_plugin_htmlrender.data_source import (
15
- capture_element,
16
- html_to_pic,
17
- md_to_pic,
18
- template_to_html,
19
- template_to_pic,
20
- text_to_pic,
53
+ from nonebot_plugin_htmlrender.consts import RenderBackend, RenderStartupMode
54
+ from nonebot_plugin_htmlrender.render import (
55
+ available_render_backends,
56
+ capture_html_element,
57
+ get_default_render,
58
+ get_render,
59
+ get_render_backend_status,
60
+ get_render_context,
61
+ is_render_backend_available,
62
+ is_render_backend_registered,
63
+ list_render_backend_statuses,
64
+ probe_render,
65
+ registered_render_backends,
66
+ render_html,
67
+ render_markdown,
68
+ render_template,
69
+ render_template_html,
70
+ render_text,
71
+ shutdown_render,
72
+ startup_render,
73
+ unavailable_render_backends,
74
+ )
75
+ from nonebot_plugin_htmlrender.resources import (
76
+ ResourceResolveError,
77
+ resolve_template_vars,
78
+ to_resource_url,
21
79
  )
22
- from nonebot_plugin_htmlrender.utils import _clear_playwright_env_vars
23
80
 
24
81
  __plugin_meta__ = PluginMetadata(
25
82
  name="nonebot-plugin-htmlrender",
26
83
  description="通过浏览器渲染图片",
27
- usage="",
84
+ usage=(
85
+ "提供 HTML/Markdown/模板渲染为图片的能力,作为库插件供其他插件调用。\n"
86
+ "主要接口:render_html, render_text, render_markdown, render_template 等。"
87
+ ),
28
88
  type="library",
29
89
  config=Config,
30
90
  homepage="https://github.com/kexue-z/nonebot-plugin-htmlrender",
31
- extra={},
91
+ supported_adapters=None,
32
92
  )
33
93
 
34
94
  driver = nonebot.get_driver()
35
95
 
36
96
 
97
+ def _prepare_playwright_startup() -> None:
98
+ ensure_backend_loaded(RenderBackend.PLAYWRIGHT)
99
+ page_module = import_module("nonebot_plugin_htmlrender.backend.playwright._page")
100
+ register_render_context_provider = page_module.register_render_context_provider
101
+ register_render_context_provider(get_render_context)
102
+
103
+
37
104
  @driver.on_startup
38
- async def init(**kwargs):
105
+ async def init(**kwargs: Any) -> None:
106
+ """插件启动时初始化渲染后端。"""
39
107
  logger.info("HTMLRender Starting...")
40
- await startup_htmlrender(**kwargs)
108
+ if plugin_config.render_backend is None:
109
+ logger.info("No render backend selected; startup skipped.")
110
+ return
111
+
112
+ try:
113
+ startup_mode = plugin_config.render_startup_mode
114
+ if startup_mode == RenderStartupMode.OFF:
115
+ logger.info("Render startup skipped by configuration.")
116
+ return
117
+ if plugin_config.render_backend == RenderBackend.PLAYWRIGHT:
118
+ filehost_module = import_module(
119
+ "nonebot_plugin_htmlrender.resources.filehost"
120
+ )
121
+ ensure_filehost_runtime_ready = (
122
+ filehost_module.ensure_filehost_runtime_ready
123
+ )
124
+
125
+ _prepare_playwright_startup()
126
+ await ensure_filehost_runtime_ready(reason="plugin_startup")
127
+ if startup_mode == RenderStartupMode.WARMUP:
128
+ await startup_render(**kwargs)
129
+ else:
130
+ await startup_render(**kwargs)
131
+ await probe_render()
132
+ except Exception as e:
133
+ logger.exception("Failed to start render runtime.")
134
+ raise RuntimeError("Render runtime startup failed.") from e
135
+
41
136
  logger.opt(colors=True).info(
42
- f"HTMLRender Started with <cyan>{plugin_config.htmlrender_browser}</cyan>."
137
+ f"HTMLRender Started with backend <cyan>{plugin_config.render_backend}</cyan>."
43
138
  )
44
139
 
45
140
 
46
141
  @driver.on_shutdown
47
- async def shutdown():
142
+ async def shutdown() -> None:
143
+ """插件关闭时清理渲染资源。"""
48
144
  logger.info("HTMLRender Shutting down...")
49
- await shutdown_htmlrender()
50
- _clear_playwright_env_vars()
145
+ await shutdown_render()
146
+ if plugin_config.render_backend == RenderBackend.PLAYWRIGHT:
147
+ runtime_module = import_module(
148
+ "nonebot_plugin_htmlrender.backend.playwright.runtime"
149
+ )
150
+ clear_playwright_env_vars = runtime_module.clear_playwright_env_vars
151
+
152
+ clear_playwright_env_vars()
51
153
  logger.info("HTMLRender Shut down.")
52
154
 
53
155
 
54
156
  __all__ = [
157
+ "ResourceResolveError",
158
+ "available_render_backends",
55
159
  "capture_element",
160
+ "capture_html_element",
161
+ "get_default_render",
56
162
  "get_new_page",
163
+ "get_render",
164
+ "get_render_backend_status",
165
+ "get_render_context",
57
166
  "html_to_pic",
167
+ "is_render_backend_available",
168
+ "is_render_backend_registered",
169
+ "list_render_backend_statuses",
58
170
  "md_to_pic",
171
+ "probe_render",
172
+ "registered_render_backends",
173
+ "render_html",
174
+ "render_markdown",
175
+ "render_template",
176
+ "render_template_html",
177
+ "render_text",
178
+ "resolve_template_vars",
59
179
  "shutdown_htmlrender",
180
+ "shutdown_render",
60
181
  "startup_htmlrender",
182
+ "startup_render",
61
183
  "template_to_html",
62
184
  "template_to_pic",
63
185
  "text_to_pic",
186
+ "to_resource_url",
187
+ "unavailable_render_backends",
64
188
  ]
@@ -0,0 +1,122 @@
1
+ """Bootstrap helpers executed at plugin import time."""
2
+
3
+ from importlib import import_module
4
+ from importlib.util import find_spec
5
+
6
+ from nonebot import require
7
+ from nonebot.log import logger
8
+
9
+ from nonebot_plugin_htmlrender.config import plugin_config
10
+ from nonebot_plugin_htmlrender.consts import (
11
+ LocalLocalResourcePolicy,
12
+ RemoteLocalResourcePolicy,
13
+ RenderBackend,
14
+ ResourceResolveMode,
15
+ )
16
+
17
+ _OPTIONAL_PLUGIN_IDS = (
18
+ "nonebot_plugin_sentry",
19
+ "nonebot_plugin_prometheus",
20
+ )
21
+
22
+
23
+ def _enum_value(raw: object) -> str:
24
+ """Return the string value for enum-like configuration entries."""
25
+ return getattr(raw, "value", str(raw))
26
+
27
+
28
+ def _playwright_filehost_policy_enabled() -> bool:
29
+ """Check whether Playwright config explicitly needs filehost bootstrap."""
30
+ try:
31
+ config_module = import_module(
32
+ "nonebot_plugin_htmlrender.backend.playwright.config"
33
+ )
34
+ get_playwright_config = config_module.get_playwright_config
35
+ cfg = get_playwright_config()
36
+ except Exception as e:
37
+ logger.warning(f"Skipping filehost import bootstrap: invalid config: {e}")
38
+ return False
39
+
40
+ if _enum_value(cfg.resource_resolve_mode) == ResourceResolveMode.OFF.value:
41
+ return False
42
+
43
+ return (
44
+ _enum_value(cfg.remote_local_resource_policy)
45
+ == RemoteLocalResourcePolicy.FILEHOST.value
46
+ or _enum_value(cfg.local_local_resource_policy)
47
+ == LocalLocalResourcePolicy.FILEHOST.value
48
+ )
49
+
50
+
51
+ def _patch_filehost_request_headers_validator() -> None:
52
+ """修补 filehost 请求头验证器以兼容 pydantic。"""
53
+ try:
54
+ # TODO: Open an upstream issue for nonebot-plugin-filehost to replace
55
+ # __get_validators__ with __get_pydantic_core_schema__.
56
+ filehost_models = import_module("nonebot_plugin_filehost.models")
57
+ request_headers = getattr(filehost_models, "RequestHeaders", None)
58
+ request_scope_info = getattr(filehost_models, "RequestScopeInfo", None)
59
+ if request_headers is None or request_scope_info is None:
60
+ return
61
+ if bool(getattr(request_headers, "__htmlrender_validator_patched__", False)):
62
+ return
63
+
64
+ raw_validate = request_headers.__dict__.get("validate")
65
+ if not isinstance(raw_validate, classmethod):
66
+ return
67
+
68
+ validate_func = raw_validate.__func__
69
+
70
+ def _compat_validate(cls, value, *args, **kwargs): # type: ignore[no-untyped-def]
71
+ """兼容性验证包装器。"""
72
+ del args, kwargs
73
+ return validate_func(cls, value)
74
+
75
+ request_headers.validate = classmethod(_compat_validate)
76
+ request_headers.__htmlrender_validator_patched__ = True
77
+ model_rebuild = getattr(request_scope_info, "model_rebuild", None)
78
+ if callable(model_rebuild):
79
+ model_rebuild(force=True)
80
+ logger.opt(colors=True).info(
81
+ "Patched <c>nonebot_plugin_filehost</c> websocket scope validator for pydantic compatibility."
82
+ )
83
+ except Exception as e:
84
+ logger.opt(colors=True).warning(
85
+ "Failed to patch <c>nonebot_plugin_filehost</c> validator compatibility: <r>{e}</r>",
86
+ e=e,
87
+ )
88
+
89
+
90
+ def _bootstrap_optional_plugins_on_import() -> None:
91
+ """在导入时引导可选插件。"""
92
+ for plugin_name in _OPTIONAL_PLUGIN_IDS:
93
+ if find_spec(plugin_name) is None:
94
+ logger.opt(colors=True).info(
95
+ "Optional plugin <d>{plugin_name}</d> not installed, skip bootstrap.",
96
+ plugin_name=plugin_name,
97
+ )
98
+ continue
99
+ require(plugin_name)
100
+ logger.opt(colors=True).info(
101
+ "Optional plugin <c>{plugin_name}</c> bootstrapped on import.",
102
+ plugin_name=plugin_name,
103
+ )
104
+
105
+
106
+ def _bootstrap_filehost_guard_on_import() -> None:
107
+ """在导入时安装 filehost 请求守卫。"""
108
+
109
+ if plugin_config.render_backend != RenderBackend.PLAYWRIGHT:
110
+ return
111
+ if not _playwright_filehost_policy_enabled():
112
+ return
113
+
114
+ filehost_module = import_module("nonebot_plugin_htmlrender.resources.filehost")
115
+ ensure_filehost_plugin_loaded = filehost_module.ensure_filehost_plugin_loaded
116
+ ensure_filehost_request_guard_installed = (
117
+ filehost_module.ensure_filehost_request_guard_installed
118
+ )
119
+
120
+ if not ensure_filehost_plugin_loaded(reason="plugin_import"):
121
+ return
122
+ ensure_filehost_request_guard_installed(reason="plugin_import")
@@ -0,0 +1,308 @@
1
+ # ruff: noqa: A002, FBT001, FBT002, PTH109
2
+ """Backward-compatible deprecated API surface.
3
+
4
+ All deprecated top-level functions are defined here. Other modules
5
+ (``data_source``, ``browser``, ``__init__``) re-export from this
6
+ module so that old import paths keep working.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from contextlib import asynccontextmanager
12
+ from importlib import import_module
13
+ from os import getcwd
14
+ from typing import TYPE_CHECKING, Any, Literal, cast
15
+ from typing_extensions import deprecated
16
+
17
+ from nonebot_plugin_htmlrender.render import (
18
+ capture_html_element,
19
+ get_render,
20
+ get_render_context,
21
+ render_html,
22
+ render_markdown,
23
+ render_template,
24
+ render_template_html,
25
+ render_text,
26
+ shutdown_render,
27
+ startup_render,
28
+ )
29
+
30
+ if TYPE_CHECKING:
31
+ from collections.abc import AsyncIterator
32
+ from typing_extensions import Unpack
33
+
34
+ from playwright.async_api import Browser
35
+
36
+ from nonebot_plugin_htmlrender.backend.playwright.types import (
37
+ BrowserSessionKwargs,
38
+ GotoKwargs,
39
+ HtmlPageKwargs,
40
+ LocatorScreenshotKwargs,
41
+ PageContextKwargs,
42
+ TemplatePageKwargs,
43
+ )
44
+
45
+
46
+ async def read_file(path: str) -> str:
47
+ operations = import_module(
48
+ "nonebot_plugin_htmlrender.backend.playwright.operations"
49
+ )
50
+ read_file_fn = operations.read_file
51
+
52
+ return await read_file_fn(path)
53
+
54
+
55
+ async def read_tpl(path: str) -> str:
56
+ operations = import_module(
57
+ "nonebot_plugin_htmlrender.backend.playwright.operations"
58
+ )
59
+ read_tpl_fn = operations.read_tpl
60
+
61
+ return await read_tpl_fn(path)
62
+
63
+
64
+ def _require_browser(session: object) -> Browser:
65
+ """从渲染会话中提取 Browser 实例。
66
+
67
+ Args:
68
+ session: 渲染会话对象,需包含 ``handle`` 属性。
69
+
70
+ Returns:
71
+ 会话中的 :class:`Browser` 实例。
72
+
73
+ Raises:
74
+ RuntimeError: 当前渲染目标不是 Browser 实例时抛出。
75
+ """
76
+ playwright_api = import_module("playwright.async_api")
77
+ browser_type = playwright_api.Browser
78
+
79
+ browser = getattr(session, "handle", None)
80
+ if isinstance(browser, browser_type):
81
+ return cast("Browser", browser)
82
+ raise RuntimeError("Current render target is not a Browser instance.")
83
+
84
+
85
+ @deprecated("`text_to_pic` is deprecated. Use `render_text` instead.")
86
+ async def text_to_pic(
87
+ text: str,
88
+ css_path: str = "",
89
+ width: int = 500,
90
+ type: Literal["jpeg", "png"] = "png",
91
+ quality: int | None = None,
92
+ device_scale_factor: float = 2,
93
+ screenshot_timeout: float | None = 30_000,
94
+ ) -> bytes:
95
+ """已弃用:将文本渲染为图片,请使用 ``render_text``。"""
96
+ return await render_text(
97
+ text,
98
+ css_path=css_path,
99
+ width=width,
100
+ image_type=type,
101
+ quality=quality,
102
+ device_scale_factor=device_scale_factor,
103
+ screenshot_timeout=screenshot_timeout,
104
+ )
105
+
106
+
107
+ @deprecated("`md_to_pic` is deprecated. Use `render_markdown` instead.")
108
+ async def md_to_pic(
109
+ md: str = "",
110
+ md_path: str = "",
111
+ css_path: str = "",
112
+ width: int = 500,
113
+ type: Literal["jpeg", "png"] = "png",
114
+ quality: int | None = None,
115
+ device_scale_factor: float = 2,
116
+ screenshot_timeout: float | None = 30_000,
117
+ ) -> bytes:
118
+ """已弃用:将 Markdown 渲染为图片,请使用 ``render_markdown``。"""
119
+ return await render_markdown(
120
+ md,
121
+ md_path=md_path,
122
+ css_path=css_path,
123
+ width=width,
124
+ image_type=type,
125
+ quality=quality,
126
+ device_scale_factor=device_scale_factor,
127
+ screenshot_timeout=screenshot_timeout,
128
+ )
129
+
130
+
131
+ @deprecated("`template_to_html` is deprecated. Use `render_template_html` instead.")
132
+ async def template_to_html(
133
+ template_path: str,
134
+ template_name: str,
135
+ filters: dict[str, Any] | None = None,
136
+ **kwargs: Any,
137
+ ) -> str:
138
+ """已弃用:将模板渲染为 HTML,请使用 ``render_template_html``。"""
139
+ return await render_template_html(
140
+ template_path,
141
+ template_name=template_name,
142
+ filters=filters,
143
+ **kwargs,
144
+ )
145
+
146
+
147
+ @deprecated("`html_to_pic` is deprecated. Use `render_html` instead.")
148
+ async def html_to_pic(
149
+ html: str,
150
+ wait: int = 0,
151
+ template_path: str | None = None,
152
+ type: Literal["jpeg", "png"] = "png",
153
+ quality: int | None = None,
154
+ device_scale_factor: float = 2,
155
+ screenshot_timeout: float | None = 30_000,
156
+ full_page: bool = True,
157
+ **kwargs: Unpack[HtmlPageKwargs],
158
+ ) -> bytes:
159
+ """已弃用:将 HTML 渲染为图片,请使用 ``render_html``。"""
160
+ return await render_html(
161
+ html,
162
+ wait=wait,
163
+ template_path=template_path,
164
+ image_type=type,
165
+ quality=quality,
166
+ device_scale_factor=device_scale_factor,
167
+ screenshot_timeout=screenshot_timeout,
168
+ full_page=full_page,
169
+ **kwargs,
170
+ )
171
+
172
+
173
+ @deprecated("`template_to_pic` is deprecated. Use `render_template` instead.")
174
+ async def template_to_pic(
175
+ template_path: str,
176
+ template_name: str,
177
+ templates: dict[str, Any],
178
+ filters: dict[str, Any] | None = None,
179
+ pages: TemplatePageKwargs | None = None,
180
+ wait: int = 0,
181
+ type: Literal["jpeg", "png"] = "png",
182
+ quality: int | None = None,
183
+ device_scale_factor: float = 2,
184
+ screenshot_timeout: float | None = 30_000,
185
+ ) -> bytes:
186
+ """已弃用:将模板渲染为图片,请使用 ``render_template``。"""
187
+ default_pages: TemplatePageKwargs = {
188
+ "viewport": {"width": 500, "height": 10},
189
+ "base_url": f"file://{getcwd()}",
190
+ }
191
+ return await render_template(
192
+ template_path,
193
+ template_name=template_name,
194
+ templates=templates,
195
+ filters=filters,
196
+ pages=pages or default_pages,
197
+ wait=wait,
198
+ image_type=type,
199
+ quality=quality,
200
+ device_scale_factor=device_scale_factor,
201
+ screenshot_timeout=screenshot_timeout,
202
+ )
203
+
204
+
205
+ @deprecated("`capture_element` is deprecated. Use `capture_html_element` instead.")
206
+ async def capture_element(
207
+ url: str,
208
+ element: str,
209
+ page_kwargs: PageContextKwargs | None = None,
210
+ goto_kwargs: GotoKwargs | None = None,
211
+ screenshot_kwargs: LocatorScreenshotKwargs | None = None,
212
+ ) -> bytes:
213
+ """已弃用:捕获页面元素截图,请使用 ``capture_html_element``。"""
214
+ return await capture_html_element(
215
+ url,
216
+ element,
217
+ page_kwargs=page_kwargs,
218
+ goto_kwargs=goto_kwargs,
219
+ screenshot_kwargs=screenshot_kwargs,
220
+ )
221
+
222
+
223
+ @deprecated("`get_new_page` is deprecated. Use `get_render_context` instead.")
224
+ @asynccontextmanager
225
+ async def get_new_page(
226
+ device_scale_factor: float = 2,
227
+ **kwargs: Unpack[HtmlPageKwargs],
228
+ ) -> AsyncIterator[object]:
229
+ """已弃用:获取新的浏览器页面,请使用 ``get_render_context``。"""
230
+ async with get_render_context(
231
+ device_scale_factor=device_scale_factor,
232
+ **kwargs,
233
+ ) as page:
234
+ yield page
235
+
236
+
237
+ @deprecated("`get_browser` is deprecated. Use `get_render` instead.")
238
+ async def get_browser(**kwargs: Unpack[BrowserSessionKwargs]) -> Browser:
239
+ """已弃用:获取浏览器实例,请使用 ``get_render``。"""
240
+ session = await get_render(**kwargs)
241
+ return _require_browser(session)
242
+
243
+
244
+ @deprecated("`startup_htmlrender` is deprecated. Use `startup_render` instead.")
245
+ async def startup_htmlrender(**kwargs: Unpack[BrowserSessionKwargs]) -> Browser:
246
+ """已弃用:启动 HTML 渲染引擎,请使用 ``startup_render``。"""
247
+ session = await startup_render(**kwargs)
248
+ return _require_browser(session)
249
+
250
+
251
+ @deprecated("`shutdown_htmlrender` is deprecated. Use `shutdown_render` instead.")
252
+ async def shutdown_htmlrender() -> None:
253
+ """已弃用:关闭 HTML 渲染引擎,请使用 ``shutdown_render``。"""
254
+ await shutdown_render()
255
+
256
+
257
+ @deprecated("`_launch` is deprecated. Use `startup_render` instead.")
258
+ async def _launch(
259
+ browser_type: str,
260
+ **kwargs: Unpack[BrowserSessionKwargs],
261
+ ) -> Browser:
262
+ """已弃用:启动浏览器,请使用 ``startup_render``。"""
263
+ _ = browser_type
264
+ return await startup_htmlrender(**kwargs)
265
+
266
+
267
+ @deprecated(
268
+ "`clean_playwright_cache` from `nonebot_plugin_htmlrender.browser` is deprecated. "
269
+ "Use `nonebot_plugin_htmlrender.backend.playwright.runtime.reconcile_legacy_playwright_cache` instead."
270
+ )
271
+ def clean_playwright_cache(*, cleanup: bool) -> None:
272
+ """已弃用:清理 Playwright 缓存。"""
273
+ runtime = import_module("nonebot_plugin_htmlrender.backend.playwright.runtime")
274
+ clean_cache = runtime.clean_playwright_cache
275
+
276
+ clean_cache(cleanup=cleanup)
277
+
278
+
279
+ @deprecated(
280
+ "`reconcile_legacy_playwright_cache` from `nonebot_plugin_htmlrender.browser` "
281
+ "is deprecated. Use "
282
+ "`nonebot_plugin_htmlrender.backend.playwright.runtime.reconcile_legacy_playwright_cache` instead."
283
+ )
284
+ def reconcile_legacy_playwright_cache(*, cleanup: bool) -> None:
285
+ """已弃用:协调旧版 Playwright 缓存目录。"""
286
+ runtime = import_module("nonebot_plugin_htmlrender.backend.playwright.runtime")
287
+ reconcile_cache = runtime.reconcile_legacy_playwright_cache
288
+
289
+ reconcile_cache(cleanup=cleanup)
290
+
291
+
292
+ __all__ = [
293
+ "_launch",
294
+ "capture_element",
295
+ "clean_playwright_cache",
296
+ "get_browser",
297
+ "get_new_page",
298
+ "html_to_pic",
299
+ "md_to_pic",
300
+ "read_file",
301
+ "read_tpl",
302
+ "reconcile_legacy_playwright_cache",
303
+ "shutdown_htmlrender",
304
+ "startup_htmlrender",
305
+ "template_to_html",
306
+ "template_to_pic",
307
+ "text_to_pic",
308
+ ]
@@ -0,0 +1,39 @@
1
+ from .base import (
2
+ Backend,
3
+ BackendCapability,
4
+ RenderRuntime,
5
+ RenderSession,
6
+ SupportsHtmlRenderBackend,
7
+ )
8
+ from .factory import (
9
+ BackendAvailability,
10
+ BackendStatus,
11
+ available_backends,
12
+ backend_statuses,
13
+ build_backend,
14
+ get_backend_status,
15
+ is_backend_available,
16
+ is_backend_registered,
17
+ register_backend,
18
+ registered_backends,
19
+ unavailable_backends,
20
+ )
21
+
22
+ __all__ = [
23
+ "Backend",
24
+ "BackendAvailability",
25
+ "BackendCapability",
26
+ "BackendStatus",
27
+ "RenderRuntime",
28
+ "RenderSession",
29
+ "SupportsHtmlRenderBackend",
30
+ "available_backends",
31
+ "backend_statuses",
32
+ "build_backend",
33
+ "get_backend_status",
34
+ "is_backend_available",
35
+ "is_backend_registered",
36
+ "register_backend",
37
+ "registered_backends",
38
+ "unavailable_backends",
39
+ ]