Skip to content
This repository has been archived by the owner on Sep 23, 2024. It is now read-only.

fix: language label of code #83

Merged
merged 1 commit into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions src/home/chat-window/compnent/my-text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,32 @@ import mifoot from "markdown-it-footnote"
import './widget/highlightjs-plugins/copy-button-plugin.css'
import {LanguageLabelPlugin} from "./widget/highlightjs-plugins/language-label-plugin.tsx";
import {CopyButtonPlugin} from "./widget/highlightjs-plugins/copy-button-plugin.tsx";
import {throttle} from "lodash";

hljs.configure({
ignoreUnescapedHTML: true
ignoreUnescapedHTML: true,
});
hljs.addPlugin(new CopyButtonPlugin());
hljs.addPlugin(new LanguageLabelPlugin());
hljs.addPlugin(new CopyButtonPlugin());

// to improve performance
const ha: () => void = throttle(() => {
hljs.highlightAll()
}, 500)

interface TextProps {
messageSnap: Message
theme: Theme
}


export const MyText: React.FC<TextProps> = ({messageSnap, theme}) => {
// console.info("MyText rendered, messageSnap.id:", messageSnap.id, new Date().toLocaleString())
// console.info("messageSnap.text", messageSnap.text)
useEffect(() => {
// apply plugins only if message is fully received to improve performance
setTimeout(() => messageSnap.status === 'received' && hljs.highlightAll(), 500)
if (messageSnap.status === 'received') {
ha()
}
}, [messageSnap.status]);

return <div
Expand All @@ -53,8 +60,7 @@ export const MyText: React.FC<TextProps> = ({messageSnap, theme}) => {
)}>

<div className={cx("leading-snug",
// remove default padding and only use padding applied by hljs.highlightAll()
messageSnap.status === 'received' && "prose-pre:p-0"
"prose-pre:p-0 prose-pre:pt-3"
)}>
{messageSnap.role === 'assistant' ?
<MDText text={messageSnap.text}/>
Expand Down Expand Up @@ -86,17 +92,17 @@ const md = new MarkdownIt({
linkify: true,
typographer: true,
highlight: (str, lang) => {
if (lang && hljs.getLanguage(lang)) {
try {
return `<pre class="hljs">`+
"<code>"+
`${hljs.highlight(str, {language: lang, ignoreIllegals: true}).value}`+
"</code>"+
"</pre>"
} catch (_) { /* empty */
}
if (!lang || !hljs.getLanguage(lang)) {
lang = "plaintext"
}
try {
return `<pre class="hljs">` +
`<code class='hljs language-${lang}'>` +
`${hljs.highlight(str, {language: lang, ignoreIllegals: true}).value}` +
"</code>" +
"</pre>"
} catch (_) { /* empty */
}
return `<pre class="hljs"><code>${md.utils.escapeHtml(str)}</code></pre>`
},
})
.use(taskList, {enabled: true, label: true})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
.hljs-copy-button {
position: absolute;
transform: translateX(calc(100% + 1.125em));
top: 1em;
top: 1.5em;
right: 1em;
width: 2rem;
height: 2rem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@
*/
export class CopyButtonPlugin {

language: string | undefined

constructor() {
}

"before:highlight"({language}: { code: string, language: string | undefined }) {
this.language = language
}

"after:highlightElement"({el, text}: { el: Element, text: string }) {
if (!el.parentElement) {
Expand All @@ -29,8 +21,8 @@ export class CopyButtonPlugin {

// Create the copy button and append it to the codeblock.
const button = Object.assign(document.createElement("button"), {
innerHTML: locales[this.language!]?.[0] ?? "Copy",
className: "hljs-copy-button",
innerHTML: "Copy",
className: "hljs-copy-button px-2 select-none",
});

button.dataset.copied = 'false';
Expand All @@ -44,14 +36,13 @@ export class CopyButtonPlugin {
window.getComputedStyle(el).backgroundColor
);

const lang = this.language!
const parentElement = el.parentElement
button.onclick = function () {
if (!navigator.clipboard) return;
navigator.clipboard
.writeText(text)
.then(function () {
button.innerHTML = locales[lang]?.[1] || "Copied!";
button.innerHTML = "Copied!";
button.dataset.copied = 'true';

let alert: HTMLDivElement & {
Expand All @@ -61,13 +52,13 @@ export class CopyButtonPlugin {
} | undefined = Object.assign(document.createElement("div"), {
role: "status",
className: "hljs-copy-alert",
innerHTML: locales[lang]?.[2] || "Copied to clipboard",
innerHTML: "Copied to clipboard",
});

parentElement.appendChild(alert);

setTimeout(() => {
button.innerHTML = locales[lang]?.[0] || "Copy";
button.innerHTML = "Copy";
button.dataset.copied = 'false';
if (alert) {
parentElement.removeChild(alert);
Expand All @@ -79,21 +70,4 @@ export class CopyButtonPlugin {
});
};
}
}

/**
* Basic support for localization. Please submit a PR
* to help add more languages.
* https://github.com/arronhunt/highlightjs-copy/pulls
*/
const locales: Record<string, string[]> = {
"en": ["Copy", "Copied!", "Copied to clipboard"],
"es": ["Copiar", "¡Copiado!", "Copiado al portapapeles"],
"fr": ["Copier", "Copié !", "Copié dans le presse-papier"],
"de": ["Kopieren", "Kopiert!", "In die Zwischenablage kopiert"],
"ja": ["コピー", "コピーしました!", "クリップボードにコピーしました"],
"ko": ["복사", "복사됨!", "클립보드에 복사됨"],
"ru": ["Копировать", "Скопировано!", "Скопировано в буфер обмена"],
"zh": ["复制", "已复制!", "已复制到剪贴板"],
"zh-tw": ["複製", "已複製!", "已複製到剪貼簿"],
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
import hljs, {HighlightResult} from "highlight.js";

/**
* Adds a language label to highlightjs code blocks
*/
export class LanguageLabelPlugin {

language: string | undefined

constructor() {
}

"before:highlight"({language}: { code: string, language: string | undefined }) {
this.language = language
}
"after:highlightElement"({el, result}: { el: Element, result: HighlightResult }) {
if (!el.parentElement) {
return;
}

"after:highlightElement"({el}: { el: Element, text: string }) {
if (!this.language || el.classList.contains("language-label-added")) {
if (!result.language || el.parentElement.classList.contains("lang-label-added")) {
return;
}
el.classList.add("language-label-added")

let langeName = result.language
if(result.language){
langeName = hljs.getLanguage(result.language)?.name ?? result.language
}

el.parentElement.classList.add("lang-label-added")
const label = Object.assign(document.createElement("label"), {
innerHTML: this.language,
className: "language-label hljs-string absolute top-0 right-1 opacity-50",
innerHTML: langeName,
className: "language-label hljs-string select-none absolute top-1 right-1 opacity-70 text-xs",
});
el.parentElement!.appendChild(label);
}
Expand Down