feat: add code wrapping option on mobile devices (#3196)

* feat: add code wrapping option on mobile devices

* Minor changes

* oopsie
This commit is contained in:
Dubzer 2024-04-10 17:03:47 +03:00 committed by GitHub
parent 71c39ed554
commit 8ee56bd29f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 52 additions and 25 deletions

View file

@ -1,7 +1,11 @@
import { Checkbox } from "@mui/joy";
import classNames from "classnames";
import copy from "copy-to-clipboard";
import hljs from "highlight.js";
import { useCallback, useMemo, useState } from "react";
import toast from "react-hot-toast";
import useResponsiveWidth from "@/hooks/useResponsiveWidth";
import { useTranslate } from "@/utils/i18n";
import Icon from "../Icon";
import MermaidBlock from "./MermaidBlock";
import { BaseProps } from "./types";
@ -18,7 +22,8 @@ interface Props extends BaseProps {
}
const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
const formatedLanguage = (language || "").toLowerCase() || "text";
const formatedLanguage = useMemo(() => (language || "").toLowerCase() || "text", [language]);
// Users can set Markdown code blocks as `__html` to render HTML directly.
if (formatedLanguage === SpecialLanguage.HTML) {
return <div className="w-full overflow-auto !my-2" dangerouslySetInnerHTML={{ __html: content }} />;
@ -26,38 +31,58 @@ const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
return <MermaidBlock content={content} />;
}
let highlightedCode = content;
const { md } = useResponsiveWidth();
const t = useTranslate();
const [wrap, setWrap] = useState(true);
const handleWrapChange = useCallback(() => setWrap(!wrap), [setWrap, wrap]);
const highlightedCode: string = useMemo(() => {
try {
const lang = hljs.getLanguage(formatedLanguage);
if (lang) {
const temp = hljs.highlight(content, {
return hljs.highlight(content, {
language: formatedLanguage,
}).value;
highlightedCode = temp;
}
} catch (error) {
// Skip error and use default highlighted code.
}
const handleCopyButtonClick = () => {
return content;
}, [formatedLanguage, content]);
const handleCopyButtonClick = useCallback(() => {
copy(content);
toast.success("Copied to clipboard!");
};
}, [content]);
return (
<div className="w-full my-1 bg-amber-100 border-l-4 border-amber-400 rounded overflow-clip hover:shadow dark:bg-zinc-600 dark:border-zinc-400">
<div className="w-full my-1 bg-amber-100 border-l-4 border-amber-400 rounded hover:shadow dark:bg-zinc-600 dark:border-zinc-400 relative">
<div className="w-full px-2 py-1 flex flex-row justify-between items-center text-amber-500 dark:text-zinc-400">
<span className="text-sm font-mono">{formatedLanguage}</span>
<Icon.Copy className="w-4 h-auto cursor-pointer hover:opacity-80" onClick={handleCopyButtonClick} />
{md && <Icon.Copy className="w-4 h-auto cursor-pointer hover:opacity-80" onClick={handleCopyButtonClick} />}
</div>
<pre className="w-full p-2 bg-amber-50 dark:bg-zinc-700 whitespace-pre-wrap relative">
<div className="overflow-auto">
<pre
className={classNames(wrap ? "whitespace-pre-wrap" : "no-wrap overflow-auto", "w-full p-2 bg-amber-50 dark:bg-zinc-700 relative")}
>
<code
className={classNames(`language-${formatedLanguage}`, "block text-sm leading-5")}
dangerouslySetInnerHTML={{ __html: highlightedCode }}
></code>
</pre>
</div>
{!md && (
<div className="sticky flex px-2 h-8 bottom-0 bg-amber-100 dark:bg-zinc-600 rounded items-center">
<div className="grow h-full">
<Checkbox className="h-full items-center" label={t("memo.wrapping")} size="sm" checked={wrap} onChange={handleWrapChange} />
</div>
<Icon.Copy className="w-4 h-full cursor-pointer hover:opacity-80" onClick={handleCopyButtonClick} />
</div>
)}
</div>
);
};

View file

@ -105,7 +105,8 @@
"self": "Comments",
"no-comment": "No comment"
},
"show-more": "Show more"
"show-more": "Show more",
"wrapping": "Wrapping"
},
"reference": {
"add-references": "Add references",

View file

@ -122,7 +122,8 @@
"private": "Видно только вам",
"protected": "Видно только пользователям",
"public": "Видно всем"
}
},
"wrapping": "Перенос"
},
"message": {
"change-memo-created-time": "Изменить время создания записи",