From 72f4e748e8b9b5d50f1751f36d18f285b0837224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=A5=E6=9C=88=E5=8D=83=E9=B8=AE?= <40380042+camera-2018@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:38:43 +0800 Subject: [PATCH] fix: restore T2I text template rendering (#7789) * fix: restore T2I text template rendering - keep using {{ text | safe }} instead of text_base64 - inject Shiki runtime by default for T2I templates - update built-in templates to read markdown from a hidden textarea - improve WebUI preview sample text and Shiki runtime serving - add regression tests for template rendering and runtime injection * fix: prevent injected Shiki runtime from breaking T2I templates * fix(t2i): restore raw text template rendering * test(t2i): remove test * fix(t2i): restore previewText --- astrbot/core/utils/t2i/network_strategy.py | 67 ++++++++++++++-- .../t2i/template/astrbot_powershell.html | 18 +---- .../utils/t2i/template/astrbot_vitepress.html | 19 +---- astrbot/core/utils/t2i/template/base.html | 18 +---- .../components/shared/T2ITemplateEditor.vue | 77 +++++++++++++++++-- .../src/i18n/locales/en-US/core/shared.json | 2 +- .../src/i18n/locales/ru-RU/core/shared.json | 4 +- .../src/i18n/locales/zh-CN/core/shared.json | 2 +- dashboard/vite.config.ts | 41 +++++++++- 9 files changed, 182 insertions(+), 66 deletions(-) diff --git a/astrbot/core/utils/t2i/network_strategy.py b/astrbot/core/utils/t2i/network_strategy.py index 5f9385614f..4fec121953 100644 --- a/astrbot/core/utils/t2i/network_strategy.py +++ b/astrbot/core/utils/t2i/network_strategy.py @@ -1,7 +1,7 @@ import asyncio -import base64 import logging import random +import re from functools import lru_cache from pathlib import Path @@ -15,6 +15,11 @@ from . import RenderStrategy ASTRBOT_T2I_DEFAULT_ENDPOINT = "https://t2i.soulter.top/text2img" +SHIKI_RUNTIME_SCRIPT_ID = "astrbot-t2i-shiki-runtime" +SHIKI_RUNTIME_TEMPLATE_PATTERN = re.compile(r"\{\{\s*shiki_runtime\s*\|\s*safe\s*\}\}") +JINJA_SYNTAX_PATTERN = re.compile(r"\{[{%#]") +JINJA_RAW_OPEN_PATTERN = re.compile(r"{%-?\s*raw\s*-?%}") +JINJA_RAW_CLOSE_PATTERN = re.compile(r"{%-?\s*endraw\s*-?%}") logger = logging.getLogger("astrbot") @@ -41,7 +46,49 @@ def get_shiki_runtime() -> str: ) return "" - return runtime.replace(" bool: + raw_open_index = -1 + for match in JINJA_RAW_OPEN_PATTERN.finditer(tmpl_str, 0, index): + raw_open_index = match.start() + + raw_close_index = -1 + for match in JINJA_RAW_CLOSE_PATTERN.finditer(tmpl_str, 0, index): + raw_close_index = match.start() + + return raw_open_index > raw_close_index + + +def _wrap_runtime_for_jinja(tmpl_str: str, script: str, index: int) -> str: + if not JINJA_SYNTAX_PATTERN.search(script) or _is_inside_jinja_raw_block( + tmpl_str, + index, + ): + return script + + return f"{{% raw %}}{script}{{% endraw %}}" + + +def inject_shiki_runtime(tmpl_str: str) -> str: + if SHIKI_RUNTIME_SCRIPT_ID in tmpl_str or SHIKI_RUNTIME_TEMPLATE_PATTERN.search( + tmpl_str, + ): + return tmpl_str + + runtime = get_shiki_runtime() + if not runtime: + return tmpl_str + + script = f'' + head_close = re.search(r"", tmpl_str, flags=re.IGNORECASE) + if head_close: + script = _wrap_runtime_for_jinja(tmpl_str, script, head_close.start()) + return f"{tmpl_str[: head_close.start()]} {script}\n{tmpl_str[head_close.start() :]}" + + script = _wrap_runtime_for_jinja(tmpl_str, script, 0) + return f"{script}\n{tmpl_str}" class NetworkRenderStrategy(RenderStrategy): @@ -101,11 +148,17 @@ async def render_custom_template( options: dict | None = None, ) -> str: """使用自定义文转图模板""" - default_options = {"full_page": True, "type": "jpeg", "quality": 40} + default_options = { + "full_page": True, + "type": "jpeg", + "quality": 40, + } if options: default_options |= options - tmpl_data = {"shiki_runtime": get_shiki_runtime()} | tmpl_data + if SHIKI_RUNTIME_TEMPLATE_PATTERN.search(tmpl_str): + tmpl_data = {"shiki_runtime": get_shiki_runtime()} | tmpl_data + tmpl_str = inject_shiki_runtime(tmpl_str) post_data = { "tmpl": tmpl_str, "json": return_url, @@ -158,9 +211,11 @@ async def render( if not template_name: template_name = "base" tmpl_str = await self.get_template(name=template_name) - text_base64 = base64.b64encode(text.encode("utf-8")).decode("ascii") return await self.render_custom_template( tmpl_str, - {"text_base64": text_base64, "version": f"v{VERSION}"}, + { + "text": text, + "version": f"v{VERSION}", + }, return_url, ) diff --git a/astrbot/core/utils/t2i/template/astrbot_powershell.html b/astrbot/core/utils/t2i/template/astrbot_powershell.html index 746d06fe80..3bfa014c0c 100644 --- a/astrbot/core/utils/t2i/template/astrbot_powershell.html +++ b/astrbot/core/utils/t2i/template/astrbot_powershell.html @@ -174,14 +174,14 @@
- +