دوباره شماره 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