server : (web ui) add copy btn for code blocks
This commit is contained in:
parent
6423c65aa8
commit
22160f000e
1 changed files with 20 additions and 7 deletions
|
@ -12,7 +12,7 @@
|
||||||
.markdown {
|
.markdown {
|
||||||
h1, h2, h3, h4, h5, h6, ul, ol, li { all: revert; }
|
h1, h2, h3, h4, h5, h6, ul, ol, li { all: revert; }
|
||||||
pre {
|
pre {
|
||||||
@apply whitespace-pre-wrap my-4 rounded-lg p-2;
|
@apply whitespace-pre-wrap rounded-lg p-2;
|
||||||
border: 1px solid currentColor;
|
border: 1px solid currentColor;
|
||||||
}
|
}
|
||||||
/* TODO: fix markdown table */
|
/* TODO: fix markdown table */
|
||||||
|
@ -234,9 +234,13 @@
|
||||||
import { createApp, defineComponent, shallowRef, computed, h } from './deps_vue.esm-browser.js';
|
import { createApp, defineComponent, shallowRef, computed, h } from './deps_vue.esm-browser.js';
|
||||||
import { llama } from './completion.js';
|
import { llama } from './completion.js';
|
||||||
|
|
||||||
|
// utility functions
|
||||||
const isString = (x) => !!x.toLowerCase;
|
const isString = (x) => !!x.toLowerCase;
|
||||||
const isNumeric = (n) => !isString(n) && !isNaN(n);
|
const isNumeric = (n) => !isString(n) && !isNaN(n);
|
||||||
|
const escapeAttr = (str) => str.replace(/>/g, '>').replace(/"/g, '"');
|
||||||
|
const copyStr = (str) => navigator.clipboard.writeText(str);
|
||||||
|
|
||||||
|
// constants
|
||||||
const BASE_URL = localStorage.getItem('base') // for debugging
|
const BASE_URL = localStorage.getItem('base') // for debugging
|
||||||
|| (new URL('.', document.baseURI).href).toString(); // for production
|
|| (new URL('.', document.baseURI).href).toString(); // for production
|
||||||
const CONFIG_DEFAULT = {
|
const CONFIG_DEFAULT = {
|
||||||
|
@ -259,14 +263,23 @@
|
||||||
// markdown support
|
// markdown support
|
||||||
const VueMarkdown = defineComponent(
|
const VueMarkdown = defineComponent(
|
||||||
(props) => {
|
(props) => {
|
||||||
const md = shallowRef(new markdownit(props.options ?? { breaks: true }));
|
const md = shallowRef(new markdownit({ breaks: true }));
|
||||||
for (const plugin of props.plugins ?? []) {
|
const origFenchRenderer = md.value.renderer.rules.fence;
|
||||||
md.value.use(plugin);
|
md.value.renderer.rules.fence = (tokens, idx, ...args) => {
|
||||||
}
|
const content = tokens[idx].content;
|
||||||
|
const origRendered = origFenchRenderer(tokens, idx, ...args);
|
||||||
|
return `<div class="relative my-4">
|
||||||
|
<div class="text-right sticky top-4 mb-2 mr-2 h-0">
|
||||||
|
<button class="badge btn-mini" onclick="copyStr(${escapeAttr(JSON.stringify(content))})">📋 Copy</button>
|
||||||
|
</div>
|
||||||
|
${origRendered}
|
||||||
|
</div>`;
|
||||||
|
};
|
||||||
|
window.copyStr = copyStr;
|
||||||
const content = computed(() => md.value.render(props.source));
|
const content = computed(() => md.value.render(props.source));
|
||||||
return () => h("div", { innerHTML: content.value });
|
return () => h("div", { innerHTML: content.value });
|
||||||
},
|
},
|
||||||
{ props: ["source", "options", "plugins"] }
|
{ props: ["source"] }
|
||||||
);
|
);
|
||||||
|
|
||||||
// coversations is stored in localStorage
|
// coversations is stored in localStorage
|
||||||
|
@ -512,7 +525,7 @@
|
||||||
this.generateMessage(currConvId);
|
this.generateMessage(currConvId);
|
||||||
},
|
},
|
||||||
copyMsg(msg) {
|
copyMsg(msg) {
|
||||||
navigator.clipboard.writeText(msg.content);
|
copyStr(msg.content);
|
||||||
},
|
},
|
||||||
editUserMsgAndRegenerate(msg) {
|
editUserMsgAndRegenerate(msg) {
|
||||||
if (this.isGenerating) return;
|
if (this.isGenerating) return;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue