Spaces:
Sleeping
Sleeping
feat: 增加代码块复制功能, resolve #241 (#324)
Browse files* feat: 增加js支持
* fix: 修正缩进,增加本地js读取
Co-authored-by: Chen Zirui <[email protected]>
Co-authored-by: Tuchuanhuhuhu <[email protected]>
Co-authored-by: mzlegion <[email protected]>
* feat: 增加代码块复制功能
---------
Co-authored-by: Chen Zirui <[email protected]>
Co-authored-by: Tuchuanhuhuhu <[email protected]>
Co-authored-by: mzlegion <[email protected]>
- ChuanhuChatbot.py +1 -0
- assets/Kelpy-Codos.js +76 -0
- assets/custom.js +1 -0
- overwrites.py +17 -0
ChuanhuChatbot.py
CHANGED
|
@@ -434,6 +434,7 @@ logging.info(
|
|
| 434 |
demo.title = "川虎ChatGPT 🚀"
|
| 435 |
|
| 436 |
if __name__ == "__main__":
|
|
|
|
| 437 |
# if running in Docker
|
| 438 |
if dockerflag:
|
| 439 |
if authflag:
|
|
|
|
| 434 |
demo.title = "川虎ChatGPT 🚀"
|
| 435 |
|
| 436 |
if __name__ == "__main__":
|
| 437 |
+
reload_javascript()
|
| 438 |
# if running in Docker
|
| 439 |
if dockerflag:
|
| 440 |
if authflag:
|
assets/Kelpy-Codos.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// ==UserScript==
|
| 2 |
+
// @name Kelpy Codos
|
| 3 |
+
// @namespace https://github.com/Keldos-Li/Kelpy-Codos
|
| 4 |
+
// @version 1.0.5
|
| 5 |
+
// @author Keldos; https://keldos.me/
|
| 6 |
+
// @description Add copy button to PRE tags before CODE tag, for Chuanhu ChatGPT especially.
|
| 7 |
+
// Based on Chuanhu ChatGPT version: ac04408 (2023-3-22)
|
| 8 |
+
// @license GPL-3.0
|
| 9 |
+
// @grant none
|
| 10 |
+
// ==/UserScript==
|
| 11 |
+
|
| 12 |
+
(function () {
|
| 13 |
+
'use strict';
|
| 14 |
+
|
| 15 |
+
function addCopyButton(pre) {
|
| 16 |
+
var code = pre.querySelector('code');
|
| 17 |
+
if (!code) {
|
| 18 |
+
return; // 如果没有找到 <code> 元素,则不添加按钮
|
| 19 |
+
}
|
| 20 |
+
var firstChild = code.firstChild;
|
| 21 |
+
if (!firstChild) {
|
| 22 |
+
return; // 如果 <code> 元素没有子节点,则不添加按钮
|
| 23 |
+
}
|
| 24 |
+
var button = document.createElement('button');
|
| 25 |
+
button.textContent = '\uD83D\uDCCE'; // 使用 📎 符号作为“复制”按钮的文本
|
| 26 |
+
button.style.position = 'relative';
|
| 27 |
+
button.style.float = 'right';
|
| 28 |
+
button.style.fontSize = '1em'; // 可选:调整按钮大小
|
| 29 |
+
button.style.background = 'none'; // 可选:去掉背景颜色
|
| 30 |
+
button.style.border = 'none'; // 可选:去掉边框
|
| 31 |
+
button.style.cursor = 'pointer'; // 可选:显示指针样式
|
| 32 |
+
button.addEventListener('click', function () {
|
| 33 |
+
var range = document.createRange();
|
| 34 |
+
range.selectNodeContents(code);
|
| 35 |
+
range.setStartBefore(firstChild); // 将范围设置为第一个子节点之前
|
| 36 |
+
var selection = window.getSelection();
|
| 37 |
+
selection.removeAllRanges();
|
| 38 |
+
selection.addRange(range);
|
| 39 |
+
|
| 40 |
+
try {
|
| 41 |
+
var success = document.execCommand('copy');
|
| 42 |
+
if (success) {
|
| 43 |
+
button.textContent = '\u2714';
|
| 44 |
+
setTimeout(function () {
|
| 45 |
+
button.textContent = '\uD83D\uDCCE'; // 恢复按钮为“复制”
|
| 46 |
+
}, 2000);
|
| 47 |
+
} else {
|
| 48 |
+
button.textContent = '\u2716';
|
| 49 |
+
}
|
| 50 |
+
} catch (e) {
|
| 51 |
+
console.error(e);
|
| 52 |
+
button.textContent = '\u2716';
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
selection.removeAllRanges();
|
| 56 |
+
});
|
| 57 |
+
code.insertBefore(button, firstChild); // 将按钮插入到第一个子元素之前
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
function handleNewElements(mutationsList, observer) {
|
| 61 |
+
for (var mutation of mutationsList) {
|
| 62 |
+
if (mutation.type === 'childList') {
|
| 63 |
+
for (var node of mutation.addedNodes) {
|
| 64 |
+
if (node.nodeName === 'PRE') {
|
| 65 |
+
addCopyButton(node);
|
| 66 |
+
}
|
| 67 |
+
}
|
| 68 |
+
}
|
| 69 |
+
}
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
var observer = new MutationObserver(handleNewElements);
|
| 73 |
+
observer.observe(document.documentElement, { childList: true, subtree: true });
|
| 74 |
+
|
| 75 |
+
document.querySelectorAll('pre').forEach(addCopyButton);
|
| 76 |
+
})();
|
assets/custom.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
// custom javascript here
|
overwrites.py
CHANGED
|
@@ -36,3 +36,20 @@ def postprocess(
|
|
| 36 |
else:
|
| 37 |
y[-1] = (convert_user(y[-1][0]), convert_mdtext(y[-1][1]))
|
| 38 |
return y
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
else:
|
| 37 |
y[-1] = (convert_user(y[-1][0]), convert_mdtext(y[-1][1]))
|
| 38 |
return y
|
| 39 |
+
|
| 40 |
+
with open("./assets/custom.js", "r", encoding="utf-8") as f, open("./assets/Kelpy-Codos.js", "r", encoding="utf-8") as f2:
|
| 41 |
+
customJS = f.read()
|
| 42 |
+
kelpyCodos = f2.read()
|
| 43 |
+
|
| 44 |
+
def reload_javascript():
|
| 45 |
+
print("Reloading javascript...")
|
| 46 |
+
js = f'<script>{customJS}</script><script>{kelpyCodos}</script>'
|
| 47 |
+
def template_response(*args, **kwargs):
|
| 48 |
+
res = GradioTemplateResponseOriginal(*args, **kwargs)
|
| 49 |
+
res.body = res.body.replace(b'</html>', f'{js}</html>'.encode("utf8"))
|
| 50 |
+
res.init_headers()
|
| 51 |
+
return res
|
| 52 |
+
|
| 53 |
+
gr.routes.templates.TemplateResponse = template_response
|
| 54 |
+
|
| 55 |
+
GradioTemplateResponseOriginal = gr.routes.templates.TemplateResponse
|