برنامه نویسی

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

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا