feat: guide 引入github markdown樣式
This commit is contained in:
parent
58d578fc16
commit
dd1387a528
|
@ -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 (
|
||||||
|
|
|
@ -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" }}>
|
||||||
|
|
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
1108
apps/web/src/view/CourseDetail/components/Guide/index.less
Normal file
1108
apps/web/src/view/CourseDetail/components/Guide/index.less
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -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>
|
||||||
) : (
|
) : (
|
||||||
|
|
27
apps/web/src/view/CourseDetail/components/Guide/util.tsx
Normal file
27
apps/web/src/view/CourseDetail/components/Guide/util.tsx
Normal 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;
|
||||||
|
};
|
|
@ -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),
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue
Block a user