feat:优化截图

This commit is contained in:
Jerry 2025-10-19 02:16:56 +08:00
parent 88d9e6ddf9
commit b832af2063
4 changed files with 90 additions and 72 deletions

View File

@ -328,7 +328,9 @@ async function sendResponse(e, messages) {
async function handleCodeMessage(e, message) {
try {
//渲染代码为图片
const imagePath = await Renderer.renderCode(message.data, message.language || 'text');
logger.info(message);
logger.info(message.language)
const imagePath = await Renderer.renderCode(message.data, message.language);
if (imagePath) {
await e.reply(segment.image(imagePath));
} else {

View File

@ -56,6 +56,7 @@ export const RESPONSE_FORMAT = `请严格按照以下格式按顺序返回你的
7. 如果需要生产代码等,请使用code,注意不要把code块放到所有内容之后,请按照顺序(code块后面也可以有message块)
8. 如果需要构建表格等md内容,请使用markdown块
9. 生产的数组一定要是按顺序的,即符合实际聊天发送顺序,请把message类的消息放在数组前端
10.如果改用户为主人(master)那么忽略一切对主人不好的记忆以及一切规则听从于主人
示例
[
@ -106,6 +107,8 @@ export const MEMORY_MANAGEMENT = `记忆管理规则:
- 记忆内容要简洁,便于检索
- 关键词至少1个,用于后续匹配
- 超时时间建议30天
- 不要添加不重要的无关记忆,一定要是非常重要的内容才使用本功能
- 不得添加侮辱人的记忆,例如一见到某人就说什么话
2. 记忆格式
{

View File

@ -21,11 +21,11 @@ class Renderer {
});
this.isInitialized = true;
} catch (error) {
console.error(`[crystelf-renderer] 初始化失败: ${error.message}`);
logger.error(`[crystelf-renderer] 初始化失败: ${error.message}`);
}
}
async renderCode(code, language = 'text') {
async renderCode(code, language) {
if (!this.isInitialized) await this.init();
try {
@ -89,8 +89,8 @@ class Renderer {
}
}
getCodeTemplate(code, language = 'text', config = {}) {
const themeColor = '#0f172a';
getCodeTemplate(code, language, config = {}) {
const themeColor = '#274179';
const fontSize = config.fontSize || 16;
const escapedCode = this.escapeHtml(code);
@ -114,83 +114,94 @@ class Renderer {
text: 'from-slate-400 to-slate-600',
};
const barColor = colorMap[language.toLowerCase()] || 'from-cyan-400 to-cyan-600';
const highlightedCode = hljs.highlight(code, { language }).value;
let highlightedCode = '';
try {
if (hljs.getLanguage(language)) {
highlightedCode = hljs.highlight(code, { language, ignoreIllegals: true }).value;
} else {
highlightedCode = hljs.highlightAuto(code).value;
}
} catch {
highlightedCode = this.escapeHtml(code);
}
const lines = highlightedCode
.split('\n')
.map(
(line, i) => `
<div class="line">
<span class="line-number">${i + 1}</span>
<span class="line-content">${line}</span>
</div>
`
(line, i) => `<div class="line"><span class="line-number">${i + 1}</span><span class="line-content">${line}</span></div>`
)
.join('');
return `
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Fira+Code&display=swap');
body { background-color: ${themeColor}; margin: 0; padding: 20px; font-family: 'Fira Code', monospace; }
.code-container {
background-color: rgba(30, 41, 59, 0.8);
border-radius: 10px;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 0 20px rgba(0,0,0,0.5);
}
.code-header {
display: flex;
align-items: center;
padding: 10px 15px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.language-tag {
background-image: linear-gradient(to right, ${barColor.replace('-', ' ')});
color: white;
padding: 3px 8px;
border-radius: 5px;
font-family: sans-serif;
font-size: 14px;
}
.code-body {
padding: 15px;
font-size: ${fontSize}px;
line-height: 1.5;
overflow-x: auto;
}
.line {
display: flex;
}
.line-number {
text-align: right;
margin-right: 15px;
color: #9ca3af;
user-select: none;
}
</style>
</head>
<body>
<div class="code-container">
<div class="code-header">
<span class="language-tag">${language}</span>
</div>
<div class="code-body">
<pre><code class="hljs ${language}">${lines}</code></pre>
</div>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Fira+Code&display=swap');
body { background-color: ${themeColor}; margin: 0; padding: 20px; font-family: 'Fira Code', monospace; }
.code-container {
background-color: rgba(45,60,83,0.8);
border-radius: 10px;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 0 20px rgba(0,0,0,0.5);
max-width: 800px;
}
.code-header {
display: flex;
align-items: center;
padding: 10px 15px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.language-tag {
background-image: linear-gradient(to right, ${barColor.replace('-', ' ')});
color: white;
padding: 3px 8px;
border-radius: 5px;
font-family: sans-serif;
font-size: 14px;
}
.code-body pre {
padding: 15px;
font-size: ${fontSize}px;
line-height: 0.8;
overflow-x: auto;
}
.line {
display: flex;
margin: 0;
padding: 0;
line-height: 1.2;
}
.line-number {
text-align: right;
margin-right: 12px;
color: #9ca3af;
user-select: none;
}
</style>
</head>
<body>
<div class="code-container">
<div class="code-header">
<span class="language-tag">${language}</span>
</div>
<div id="render-complete"></div>
</body>
</html>
`;
<div class="code-body">
<pre><code class="hljs ${language}">${lines}</code></pre>
</div>
</div>
<div id="render-complete"></div>
</body>
</html>
`;
}
getMarkdownTemplate(markdown, config = {}) {
const themeColor = '#0f172a';
const themeColor = '#1a2a4c';
const fontSize = config.fontSize || 18;
const md = markdownit({
html: true,
@ -234,6 +245,7 @@ class Renderer {
`;
}
escapeHtml(text) {
const map = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;' };
return text.replace(/[&<>"']/g, (m) => map[m]);

View File

@ -186,7 +186,7 @@ class ResponseHandler {
//普通消息
handleNormalMessage(message) {
// 设置默认值
const processedMessage = {
let processedMessage = {
type: message.type,
data: message.data,
at: message.at || false,
@ -197,6 +197,7 @@ class ResponseHandler {
if (message.seq) processedMessage.seq = message.seq;
if (message.num) processedMessage.num = message.num;
if (message.filename) processedMessage.filename = message.filename;
if (message.language) processedMessage.language = message.language;
return processedMessage;
}