feat: guide 引入github markdown樣式

This commit is contained in:
mozzie 2023-03-24 15:12:06 +08:00
parent 58d578fc16
commit dd1387a528
8 changed files with 1171 additions and 37 deletions

View File

@ -69,7 +69,7 @@ const toolbar = [
]; ];
export default function Guide(props: IProps) { export default function Guide(props: IProps) {
const vditorRef = useRef<Vditor>(); const vditorRef = useRef<Vditor | null>(null);
const submitTool = { const submitTool = {
name: "submit", name: "submit",
@ -84,9 +84,9 @@ export default function Guide(props: IProps) {
}, },
}; };
useEffect(() => { const renderEditor = () => {
vditorRef.current = new Vditor("vditor", { vditorRef.current = new Vditor("vditor", {
height: 600, height: "100%",
cache: { cache: {
id: props.id, id: props.id,
enable: false, enable: false,
@ -113,37 +113,20 @@ export default function Guide(props: IProps) {
}, },
}, },
}); });
};
const destroyEditor = () => {
vditorRef.current = null;
};
useEffect(() => {
renderEditor();
return () => destroyEditor();
}, []); }, []);
useEffect(() => { useEffect(() => {
vditorRef.current = new Vditor("vditor", { renderEditor();
height: 600, return () => destroyEditor();
cache: {
id: props.id,
enable: false,
},
toolbar: [...toolbar, "|", submitTool],
value: props.defaultValue ?? "",
hint: { delay: 200, emoji },
counter: { enable: true },
preview: { actions: ["desktop", "mobile"] },
after: () => console.log("[info] vditor init success..."),
upload: {
accept: "image/*",
url: "/api/vod/oss/image/upload",
multiple: false,
success(_, res) {
const { code, data, msg } = JSON.parse(res);
if (code === 10000) {
message.success("上传成功");
const { name, url } = data;
vditorRef.current?.insertValue(`![${name}](${url})`);
} else {
message.error(msg);
}
},
},
});
}, [props.defaultValue]); }, [props.defaultValue]);
return ( return (

View File

@ -104,7 +104,10 @@ const CourseCreate = () => {
<Guide <Guide
id="createCourseEditor" id="createCourseEditor"
onChange={onGuideChange} onChange={onGuideChange}
styles={{ display: current === 2 ? "block" : "none" }} styles={{
display: current === 2 ? "block" : "none",
height: "600px",
}}
/> />
</div> </div>
<div style={{ textAlign: "right", marginTop: "40px" }}> <div style={{ textAlign: "right", marginTop: "40px" }}>

View File

@ -560,7 +560,7 @@ export default function List() {
> >
<Guide <Guide
onChange={onGuideChange} onChange={onGuideChange}
styles={{ display: "block" }} styles={{ display: "block", height: "100%" }}
id="editGuideEditor" id="editGuideEditor"
defaultValue={editGuide.guide_value} defaultValue={editGuide.guide_value}
/> />

View File

@ -196,6 +196,17 @@ input {
background: transparent; background: transparent;
} }
} }
&.code-block {
.var {
color: #00b800;
}
.comment {
color: #ccc;
}
.func {
color: red;
}
}
} }
@keyframes tooltip-appear { @keyframes tooltip-appear {

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,8 @@
import { useEffect, useState } from "react"; import { Fragment, useEffect, useState } from "react";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm"; import remarkGfm from "remark-gfm";
import "./index.less";
import { LangCompiler } from "./util";
interface IProps { interface IProps {
mdText: string; mdText: string;
@ -19,7 +21,7 @@ function Guide(props: IProps) {
maxWidth: 1120, maxWidth: 1120,
margin: "0 auto", margin: "0 auto",
overflow: "hidden", overflow: "hidden",
padding: "0 24px", padding: 24,
}} }}
> >
<ReactMarkdown <ReactMarkdown
@ -28,7 +30,7 @@ function Guide(props: IProps) {
components={{ components={{
code({ node, inline, className, children, ...props }) { code({ node, inline, className, children, ...props }) {
return !inline ? ( return !inline ? (
<code className={`${className} bs code`} {...props}> <code className={`${className} bs code-block`} {...props}>
{children} {children}
</code> </code>
) : ( ) : (

View File

@ -0,0 +1,27 @@
export const LangCompiler = (code: string) => {
console.log(code);
const tdxFuncs = ["SUM", "IF", "MIN", "SUMBARS"];
const rules = {
comment: /{[^{}]+}/gim,
var: /^[a-zA-Z0-9_\u4e00-\u9fa5]+(?=:)/gim,
func: new RegExp(tdxFuncs.join("|"), "gmi"),
};
console.log(code);
const comments = code.match(rules.comment);
console.log(comments);
const vars = code.match(rules.var);
vars?.forEach((variable) => {
const re = new RegExp(variable, "gi");
console.log(re);
code = code.replace(re, `<span class="var">$&</span>`);
});
// const compose = code
// // .replace(rules.var, `<span class="var">$&</span>`)
// .replace(rules.comment, `<span class="comment">$&</span>`)
// .replace(rules.func, `<span class="func">$&</span>`);
// // 变量名全局替换
return code;
};

View File

@ -88,7 +88,7 @@ function CourseDetail() {
<DocumentChevronDouble20Regular /> <DocumentChevronDouble20Regular />
</Icon> </Icon>
), ),
view: <Guide mdText={guide.guide_html} />, view: <Guide mdText={guide.guide_value} />,
}, },
...chapters2toc(chapterList), ...chapters2toc(chapterList),
], ],