دوباره شماره 5: ساختن یک ویرایشگر Markdown با Codemirror و React

ساخت مجدد: ویرایشگر Markdown با Codemirror و React
ایجاد یک برنامه React با Vite و Bun
برای جبهه ، ما قصد داریم از React استفاده کنیم. من Vite و Bun را برای تنظیم برنامه React در فهرست اصلی پروژه ما انتخاب کردم. کد Frontend در پوشه Frontend زندگی خواهد کرد ، که بعداً با استفاده از سرور GO ارائه خواهیم داد
برای تنظیم برنامه Vite ، من دویدم:
bun create vite@latest
من همچنین از Tailwind CSS و UI Shadcn برای یک ظاهر طراحی شده استفاده می کنم ، بنابراین راهنماهای آنها را دنبال کردم تا همه چیز را تنظیم کنم ، از جمله اجرای حالت تاریک به عنوان هدایت اسناد UI Shadcn.
ساختن ویرایشگر Markdown
حال ، بیایید روی ساخت ویرایشگر Markdown تمرکز کنیم. ما از Codemirror ، یک مؤلفه ویرایشگر کد قدرتمند و انعطاف پذیر برای وب استفاده خواهیم کرد. این همراه با برجسته سازی نحو ، گزینه های سفارشی سازی و ادغام React Smooth است.
نصب وابستگی ها
من استفاده خواهم کرد @uiw/react-codemirror که جزء Codemirror برای React است. بیایید با استفاده از آن نصب کنیم bun همراه با موضوع و سایر وابستگی ها. ما استفاده خواهیم کرد react-markdown برای پیش نمایش و remark-gfm برای حمایت از نشانه گذاری با طعم GitHub.
bun add @uiw/codemirror-theme-github @uiw/react-codemirror @codemirror/lang-markdown @codemirror/language-data react-markdown remark-gfm github-markdown-css
تنظیم Codemirror
اکنون که وابستگی ها نصب شده اند ، بیایید یک src/components/markdown-editor.tsx پرونده را وارد کنید و وابستگی ها را به پروژه بیاورید و ویرایشگر را تنظیم کنید.
import { useCodeMirror, basicSetup, EditorView } from "@uiw/react-codemirror";
import { markdown, markdownLanguage } from "@codemirror/lang-markdown";
import { languages } from "@codemirror/language-data";
import { githubDark, githubLight } from "@uiw/codemirror-theme-github";
Codemirror از برجسته سازی نحو از طریق پشتیبانی می کند HighlightStyleبشر من یک سبک برجسته را برای عناوین Markdown تعریف کردم تا آنها را برجسته کند.
import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
import { tags as t } from "@lezer/highlight";
const markdownHighlightStyle = HighlightStyle.define([
{ tag: t.heading1, fontSize: "2em", fontWeight: "bold" },
{ tag: t.heading2, fontSize: "1.75em", fontWeight: "bold" },
{ tag: t.heading3, fontSize: "1.5em", fontWeight: "bold" },
]);
ما پس زمینه ویرایشگر شفاف را شفاف می کنیم تا با موضوع سایت مخلوط شود.
const myTheme = EditorView.theme({
"&": {
backgroundColor: "transparent !important",
},
});
مؤلفه ویرایشگر
هسته ویرایشگر در یک مؤلفه React عملکردی ساخته شده است. استفاده می کند useState برای ذخیره محتوای Markdown و useCallback برای رسیدگی به تغییرات متن. در اینجا ، ما نیز استفاده می کنیم useTheme قلاب برای به دست آوردن اطلاعات موضوع برای اطمینان از موضوع سایت نیز برای ویرایشگر اعمال می شود.
import { useCallback, useState } from "react";
import { useTheme } from "./theme-provider";
function Editor() {
const { theme } = useTheme();
const resolvedTheme =
theme === "system"
? window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light"
: theme;
const [value, setValue] = useState<string>("# Welcome to Redoed!");
const handleChange = useCallback((val: string) => setValue(val), []);
اولیه سازی Codemirror
اکنون که موضوع ، نحو برجسته و تنظیم دولت را در اختیار داریم ، وقت آن است که همه را کنار هم قرار دهیم. ما استفاده خواهیم کرد useCodeMirror برای ایجاد ویرایشگر و اعمال هر آنچه که تاکنون پیکربندی کرده ایم.
const { setContainer } = useCodeMirror({
value, // Uses the state we set earlier to store the Markdown content
height: "90vh", // Sets a fixed height for the editor
extensions: [
basicSetup(), // Adds essential features like line numbers and bracket matching
markdown({
base: markdownLanguage, // Enables Markdown syntax support
codeLanguages: languages, // Adds syntax highlighting for code blocks
addKeymap: true, // Enables useful keyboard shortcuts
}),
syntaxHighlighting(markdownHighlightStyle), // Applies our custom Markdown styling
EditorView.lineWrapping, // Enables line wrapping
myTheme, // Uses our transparent background theme
],
theme: resolvedTheme === "dark" ? githubDark : githubLight, // Adjusts the theme dynamically
onChange: handleChange, // Updates the state when the user types
});
آخرین مرحله ارائه ویرایشگر با پیوست کردن setContainer به div، که به Codemirror مکانی می دهد تا خود را سوار کند.
ارائه پیش نمایش Markdown
اکنون که ویرایشگر تنظیم شده است ، وقت آن رسیده است که Markdown Rendered را نمایش دهید. من از ReactMarkDown برای تبدیل متن Markdown به HTML و MARM-GFM برای پشتیبانی از پسوندهای سبک GitHub مانند جداول و اعتصاب استفاده می کنم.
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import "github-markdown-css";
return (
<div className="w-screen sm:grid sm:grid-cols-2 py-2">
<div>
<div ref={setContainer} className="border-r-1" />
div>
<div>
<div className="h-[90vh] markdown-body p-2 markdown-preview overflow-y-auto scrollbar hidden sm:block !bg-background">
<ReactMarkdown remarkPlugins={[remarkGfm]}>{value}ReactMarkdown>
div>
div>
div>
);
);
این طرح ویرایشگر و پیش نمایش را در کنار هم در صفحه های بزرگتر نگه می دارد و در حالی که UI را تمیز نگه می دارد. هر متنی که در ویرایشگر تایپ شود ، فوراً بدون نیاز به تازه کردن دستی در پیش نمایش منعکس می شود.
اضافه کردن یک جزء هدر
بیایید هم ایجاد کنیم header.tsx و این کد را اضافه کنید. در حال حاضر ، این فقط برای نمایش است که هیچ یک از دکمه ها کار نمی کنند ، اما بعداً تکامل می یابد.
import { Save, SquarePen } from "lucide-react";
import { ModeToggle } from "./mode-toggle";
import { Button } from "./ui/button";
function Header() {
return (
<header className="bg-background flex h-12 w-screen items-center justify-between border px-4 py-2">
<div className="flex items-center gap-1">
<Button variant={"outline"} className="cursor-pointer">
<SquarePen />
Button>
<div className="w-25 sm:w-auto">
<p className="truncate font-medium">Untitledp>
div>
div>
<div className="flex gap-1">
<Button className="cursor-pointer" variant={"outline"}>
<Save />
Save
Button>
<Button className="cursor-pointer">LoginButton>
<Button className="cursor-pointer" variant={"secondary"}>
Sign Up
Button>
<ModeToggle />
div>
header>
);
}
export default Header;
همه چیز را کنار هم قرار دهید
اکنون که ما هم ویرایشگر و هم از عنوان هدر داریم ، بیایید آنها را وارد کنیم App.tsxبشر
import Editor from "@/components/markdown-editor";
import Header from "@/components/header";
import { ThemeProvider } from "./components/theme-provider";
function App() {
return (
<ThemeProvider>
<main className="h-fit">
<Header />
<Editor />
main>
ThemeProvider>
);
}
export default App;
برای شروع سرور توسعه ، اجرا کنید:
bun run dev
در اینجا چگونه ویرایشگر Markdown در عمل به نظر می رسد

در اینجا آورده شده است که ما تا این مرحله دوباره پیشرفت کرده ایم: شعبه Github-Ui-MD-Editor



