现在支持的格式

-  ```svg<svg... 
  -  ```svg <svg... 
  -  ```xml<svg... 
  -  ```xml <svg... 
  -  ``` xml<svg... 
  -  ``` svg<svg... 
  -  ```<svg... (无语言标识)

  这样无论 LLM 输出哪种格式,都能正确实时绘制和复制图片到剪贴板了。
This commit is contained in:
史悦
2026-02-03 10:55:17 +08:00
parent 0f68b6d7a2
commit d74fbce137
5 changed files with 13 additions and 10 deletions

View File

@@ -1325,8 +1325,9 @@
};
}
const svgCtx = streamState.svg;
// 兼容 ```svg、```xml、``` xml、``` svg 等格式
const startPattern =
manifest.artifact?.startPattern || /```(?:svg)?\s*<svg/i;
manifest.artifact?.startPattern || /```\s*(?:svg|xml)?\s*<svg/i;
if (!svgCtx.started) {
const match = fullContent.match(startPattern);
if (match) {
@@ -1347,7 +1348,8 @@
}
const svgSection = fullContent.substring(svgCtx.startIndex);
let cleaned = svgSection.replace(/```(?:svg)?\s*/i, '');
// 兼容清理 ```svg、```xml、``` xml、``` svg 等前缀
let cleaned = svgSection.replace(/```\s*(?:svg|xml)?\s*/i, '');
cleaned = cleaned.replace(/```$/, '');
const closingIndex = cleaned.indexOf('</svg>');
if (closingIndex !== -1) {

View File

@@ -22,7 +22,7 @@
artifact: {
type: 'svg',
fence: 'svg',
startPattern: /```(?:svg)?\s*<svg/i,
startPattern: /```\s*(?:svg|xml)?\s*<svg/i,
parser: parseResponse
},
hooks: {

View File

@@ -22,7 +22,7 @@
artifact: {
type: 'svg',
fence: 'svg',
startPattern: /```(?:svg)?\s*<svg/i,
startPattern: /```\s*(?:svg|xml)?\s*<svg/i,
parser: parseResponse
},
hooks: {},

View File

@@ -64,8 +64,8 @@
// 代码围栏标识
fence: 'svg',
// SVG 开始模式匹配
startPattern: /```(?:svg)?\s*<svg/i,
// SVG 开始模式匹配(兼容 ```svg、```xml、``` xml 等格式)
startPattern: /```\s*(?:svg|xml)?\s*<svg/i,
// 内容解析器
parser: parseResponse

View File

@@ -24,7 +24,8 @@ function generateId(prefix = 'id') {
// 解析SVG响应提取SVG内容和前后文本容错缺失的结束反引号
function parseSVGResponse(response = '') {
const content = typeof response === 'string' ? response : String(response || '');
const svgFenceRegex = /```(?:svg)?\s*([\s\S]*?)```/i;
// 兼容 ```svg、```xml、``` xml、``` svg 等格式
const svgFenceRegex = /```\s*(?:svg|xml)?\s*([\s\S]*?)```/i;
const fenceMatch = content.match(svgFenceRegex);
if (fenceMatch) {
@@ -40,14 +41,14 @@ function parseSVGResponse(response = '') {
};
}
// 兼容缺失结束反引号的情况
const svgStartRegex = /```(?:svg)?\s*<svg[\s\S]*$/i;
// 兼容缺失结束反引号的情况(同样兼容 xml 格式)
const svgStartRegex = /```\s*(?:svg|xml)?\s*<svg[\s\S]*$/i;
const startMatch = content.match(svgStartRegex);
if (startMatch) {
const startIndex = startMatch.index;
const beforeText = content.substring(0, startIndex).trim();
let svgSection = content.substring(startIndex).replace(/```(?:svg)?\s*/i, '').trim();
let svgSection = content.substring(startIndex).replace(/```\s*(?:svg|xml)?\s*/i, '').trim();
// 去掉尾部残留的反引号
svgSection = svgSection.replace(/```$/, '').trim();