allow copy original text instead of renderend text
This commit is contained in:
@@ -3,7 +3,8 @@ import re
|
|||||||
import os
|
import os
|
||||||
import math
|
import math
|
||||||
import html
|
import html
|
||||||
|
import base64
|
||||||
|
import gzip
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
@@ -325,6 +326,14 @@ def markdown_convertion_for_file(txt):
|
|||||||
# cat them together
|
# cat them together
|
||||||
return pre + convert_stage_5 + suf
|
return pre + convert_stage_5 + suf
|
||||||
|
|
||||||
|
def compress_string(s):
|
||||||
|
compress_string = gzip.compress(s.encode('utf-8'))
|
||||||
|
return base64.b64encode(compress_string).decode()
|
||||||
|
|
||||||
|
def decompress_string(s):
|
||||||
|
decoded_string = base64.b64decode(s)
|
||||||
|
return gzip.decompress(decoded_string).decode('utf-8')
|
||||||
|
|
||||||
@lru_cache(maxsize=128) # 使用 lru缓存 加快转换速度
|
@lru_cache(maxsize=128) # 使用 lru缓存 加快转换速度
|
||||||
def markdown_convertion(txt):
|
def markdown_convertion(txt):
|
||||||
"""
|
"""
|
||||||
@@ -336,6 +345,12 @@ def markdown_convertion(txt):
|
|||||||
# print('警告,输入了已经经过转化的字符串,二次转化可能出问题')
|
# print('警告,输入了已经经过转化的字符串,二次转化可能出问题')
|
||||||
return txt # 已经被转化过,不需要再次转化
|
return txt # 已经被转化过,不需要再次转化
|
||||||
|
|
||||||
|
# 在文本中插入一个base64编码的原始文本,以便在复制时能够获得原始文本
|
||||||
|
raw_text_encoded = compress_string(txt)
|
||||||
|
raw_text_node = f'<div class="raw_text">{raw_text_encoded}</div>'
|
||||||
|
suf = raw_text_node + "</div>"
|
||||||
|
|
||||||
|
# 用于查找数学公式的正则表达式
|
||||||
find_equation_pattern = r'<script type="math/tex(?:.*?)>(.*?)</script>'
|
find_equation_pattern = r'<script type="math/tex(?:.*?)>(.*?)</script>'
|
||||||
|
|
||||||
txt = fix_markdown_indent(txt)
|
txt = fix_markdown_indent(txt)
|
||||||
@@ -493,6 +508,7 @@ def simple_markdown_convertion(text):
|
|||||||
suf = "</div>"
|
suf = "</div>"
|
||||||
if text.startswith(pre) and text.endswith(suf):
|
if text.startswith(pre) and text.endswith(suf):
|
||||||
return text # 已经被转化过,不需要再次转化
|
return text # 已经被转化过,不需要再次转化
|
||||||
|
|
||||||
text = compat_non_markdown_input(text) # 兼容非markdown输入
|
text = compat_non_markdown_input(text) # 兼容非markdown输入
|
||||||
text = markdown.markdown(
|
text = markdown.markdown(
|
||||||
text,
|
text,
|
||||||
|
|||||||
@@ -332,3 +332,7 @@
|
|||||||
text-wrap: wrap;
|
text-wrap: wrap;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.raw_text {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
@@ -259,7 +259,24 @@ function cancel_loading_status() {
|
|||||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
// 第 2 部分: 复制按钮
|
// 第 2 部分: 复制按钮
|
||||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
|
// 解压缩函数
|
||||||
|
function decompressString(compressedString) {
|
||||||
|
// 第1步:Base64解码
|
||||||
|
const binaryString = atob(compressedString);
|
||||||
|
|
||||||
|
// 第2步:将二进制字符串转换为Uint8Array
|
||||||
|
const bytes = new Uint8Array(binaryString.length);
|
||||||
|
for (let i = 0; i < binaryString.length; i++) {
|
||||||
|
bytes[i] = binaryString.charCodeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第3步:使用DecompressionStream (基于Web Streams API)进行gzip解压缩
|
||||||
|
const ds = new DecompressionStream('gzip');
|
||||||
|
const decompressedStream = new Response(new Blob([bytes])).body.pipeThrough(ds);
|
||||||
|
|
||||||
|
// 第4步:获取解压后的数据并转换为字符串
|
||||||
|
return new Response(decompressedStream).text();
|
||||||
|
}
|
||||||
|
|
||||||
var allow_auto_read_continously = true;
|
var allow_auto_read_continously = true;
|
||||||
var allow_auto_read_tts_flag = false;
|
var allow_auto_read_tts_flag = false;
|
||||||
@@ -283,19 +300,56 @@ function addCopyButton(botElement, index, is_last_in_arr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var copyButton = document.createElement('button');
|
// var copyButton = document.createElement('button');
|
||||||
copyButton.classList.add('copy-bot-btn');
|
// copyButton.classList.add('copy-bot-btn');
|
||||||
copyButton.setAttribute('aria-label', 'Copy');
|
// copyButton.setAttribute('aria-label', 'Copy');
|
||||||
copyButton.innerHTML = copyIcon;
|
// copyButton.innerHTML = copyIcon;
|
||||||
copyButton.addEventListener('click', async () => {
|
// copyButton.addEventListener('click', async () => {
|
||||||
const textToCopy = botElement.innerText;
|
// const textToCopy = botElement.innerText;
|
||||||
|
// try {
|
||||||
|
// // push_text_to_audio(textToCopy).catch(console.error);
|
||||||
|
// if ("clipboard" in navigator) {
|
||||||
|
// await navigator.clipboard.writeText(textToCopy);
|
||||||
|
// copyButton.innerHTML = copiedIcon;
|
||||||
|
// setTimeout(() => {
|
||||||
|
// copyButton.innerHTML = copyIcon;
|
||||||
|
// }, 1500);
|
||||||
|
// } else {
|
||||||
|
// const textArea = document.createElement("textarea");
|
||||||
|
// textArea.value = textToCopy;
|
||||||
|
// document.body.appendChild(textArea);
|
||||||
|
// textArea.select();
|
||||||
|
// try {
|
||||||
|
// document.execCommand('copy');
|
||||||
|
// copyButton.innerHTML = copiedIcon;
|
||||||
|
// setTimeout(() => {
|
||||||
|
// copyButton.innerHTML = copyIcon;
|
||||||
|
// }, 1500);
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("Copy failed: ", error);
|
||||||
|
// }
|
||||||
|
// document.body.removeChild(textArea);
|
||||||
|
// }
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("Copy failed: ", error);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// 原始文本拷贝
|
||||||
|
var copyButtonOrig = document.createElement('button');
|
||||||
|
copyButtonOrig.classList.add('copy-bot-btn');
|
||||||
|
copyButtonOrig.setAttribute('aria-label', 'Copy');
|
||||||
|
copyButtonOrig.innerHTML = copyIcon;
|
||||||
|
copyButtonOrig.addEventListener('click', async () => {
|
||||||
try {
|
try {
|
||||||
|
const base64gzipcode = botElement.getElementsByClassName('raw_text')[0].innerText;
|
||||||
|
const textToCopy = await decompressString(base64gzipcode);
|
||||||
// push_text_to_audio(textToCopy).catch(console.error);
|
// push_text_to_audio(textToCopy).catch(console.error);
|
||||||
if ("clipboard" in navigator) {
|
if ("clipboard" in navigator) {
|
||||||
await navigator.clipboard.writeText(textToCopy);
|
await navigator.clipboard.writeText(textToCopy);
|
||||||
copyButton.innerHTML = copiedIcon;
|
copyButtonOrig.innerHTML = copiedIcon;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
copyButton.innerHTML = copyIcon;
|
copyButtonOrig.innerHTML = copyIcon;
|
||||||
}, 1500);
|
}, 1500);
|
||||||
} else {
|
} else {
|
||||||
const textArea = document.createElement("textarea");
|
const textArea = document.createElement("textarea");
|
||||||
@@ -304,9 +358,9 @@ function addCopyButton(botElement, index, is_last_in_arr) {
|
|||||||
textArea.select();
|
textArea.select();
|
||||||
try {
|
try {
|
||||||
document.execCommand('copy');
|
document.execCommand('copy');
|
||||||
copyButton.innerHTML = copiedIcon;
|
copyButtonOrig.innerHTML = copiedIcon;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
copyButton.innerHTML = copyIcon;
|
copyButtonOrig.innerHTML = copyIcon;
|
||||||
}, 1500);
|
}, 1500);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Copy failed: ", error);
|
console.error("Copy failed: ", error);
|
||||||
@@ -345,7 +399,8 @@ function addCopyButton(botElement, index, is_last_in_arr) {
|
|||||||
|
|
||||||
var messageBtnColumn = document.createElement('div');
|
var messageBtnColumn = document.createElement('div');
|
||||||
messageBtnColumn.classList.add('message-btn-row');
|
messageBtnColumn.classList.add('message-btn-row');
|
||||||
messageBtnColumn.appendChild(copyButton);
|
// messageBtnColumn.appendChild(copyButton);
|
||||||
|
messageBtnColumn.appendChild(copyButtonOrig);
|
||||||
if (enable_tts) {
|
if (enable_tts) {
|
||||||
messageBtnColumn.appendChild(audioButton);
|
messageBtnColumn.appendChild(audioButton);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user