diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 00000000..0ef8dc61 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,268 @@ +# Architecture Overview + +This document describes the high-level architecture of @gravity-ui/markdown-editor. + +## System Diagram + +```mermaid +flowchart TB + subgraph Public API + useMarkdownEditor[useMarkdownEditor Hook] + MarkdownEditorView[MarkdownEditorView Component] + end + + subgraph Bundle Layer + BundleEditor[Editor Instance] + Config[Toolbar & Preset Config] + end + + subgraph Core Engine + WysiwygEditor[WysiwygEditor] + ContentHandler[ContentHandler] + ExtensionsManager[ExtensionsManager] + end + + subgraph Editor Modes + ProseMirror[ProseMirror\nWYSIWYG Mode] + CodeMirror[CodeMirror 6\nMarkup Mode] + end + + subgraph Extensions + MarkdownExt[Markdown Extensions\nheadings, lists, code, tables] + YFMExt[YFM Extensions\nalerts, tabs, notes, cuts] + BehaviorExt[Behavior Extensions\nhistory, clipboard, drag-drop] + end + + subgraph Parsing Layer + MarkdownIt[markdown-it\nParser/Serializer] + end + + useMarkdownEditor --> BundleEditor + MarkdownEditorView --> BundleEditor + BundleEditor --> Config + BundleEditor --> WysiwygEditor + WysiwygEditor --> ContentHandler + WysiwygEditor --> ExtensionsManager + ExtensionsManager --> MarkdownExt + ExtensionsManager --> YFMExt + ExtensionsManager --> BehaviorExt + ContentHandler --> MarkdownIt + WysiwygEditor --> ProseMirror + BundleEditor --> CodeMirror + MarkdownIt --> ProseMirror + MarkdownIt --> CodeMirror +``` + +## Main Components + +### 1. Public API (`/src/bundle`) + +The consumer-facing React API: + +| Export | Purpose | +|--------|---------| +| `useMarkdownEditor(options)` | Hook that creates and configures an editor instance | +| `MarkdownEditorView` | React component that renders the editor UI | +| `Editor` | Bundle-level editor class wrapping the core | + +### 2. Core Engine (`/src/core`) + +The heart of the editor: + +| Component | Purpose | +|-----------|---------| +| `WysiwygEditor` | ProseMirror editor wrapper with state management | +| `ContentHandler` | Converts between Markdown ↔ ProseMirror document | +| `ExtensionBuilder` | Configures extensions during initialization | +| `ExtensionsManager` | Manages active extensions at runtime | + +### 3. Editor Modes + +```mermaid +flowchart LR + subgraph WYSIWYG Mode + PM[ProseMirror] + PMDoc[Document Model] + PMView[Editor View] + PM --> PMDoc --> PMView + end + + subgraph Markup Mode + CM[CodeMirror 6] + CMState[Editor State] + CMView[Editor View] + CM --> CMState --> CMView + end + + subgraph Split Mode + Both[Both editors\nside-by-side] + end + + ContentHandler[ContentHandler\nMarkdown Serialization] + + PMDoc <--> ContentHandler + CMState <--> ContentHandler +``` + +| Mode | Engine | Description | +|------|--------|-------------| +| WYSIWYG | ProseMirror | Rich text editing with toolbar | +| Markup | CodeMirror 6 | Raw markdown with syntax highlighting | +| Split | Both | Side-by-side with synchronized content | + +### 4. Extension System (`/src/extensions`) + +Extensions are modular plugins that add functionality: + +```mermaid +flowchart TB + subgraph Extension Structure + Spec[Extension Spec] + Node[Node Type] + Mark[Mark Type] + Commands[Commands] + Keymap[Keymaps] + Toolbar[Toolbar Items] + Parser[Parser Rules] + Serializer[Serializer Rules] + end + + Spec --> Node + Spec --> Mark + Spec --> Commands + Spec --> Keymap + Spec --> Toolbar + Spec --> Parser + Spec --> Serializer +``` + +**Extension Categories:** + +| Category | Location | Examples | +|----------|----------|----------| +| Markdown | `/extensions/markdown` | Heading, Bold, Italic, Link, Image, CodeBlock, Table | +| YFM | `/extensions/yfm` | Alerts (Note/Tip/Warning), Tabs, Cuts, File | +| Behavior | `/extensions/behavior` | History, Clipboard, Placeholder, Selection | +| Additional | `/extensions/additional` | HTML, LaTeX, Mermaid, GPT | + +### 5. Presets (`/src/presets`) + +Pre-configured extension bundles: + +| Preset | Description | +|--------|-------------| +| `zero` | Minimal - just paragraphs and line breaks | +| `commonmark` | Standard CommonMark syntax | +| `default` | CommonMark + common extras | +| `yfm` | Yandex Flavored Markdown | +| `full` | All available extensions | + +### 6. UI Components + +```mermaid +flowchart TB + subgraph Toolbar + FlexToolbar[FlexToolbar] + ToolbarButton[ToolbarButton] + ToolbarGroup[ToolbarGroup] + ToolbarListButton[ToolbarListButton] + end + + subgraph Forms + LinkForm[LinkForm] + ImageForm[ImageForm] + FileForm[FileForm] + end + + subgraph View + EditorComponent[Editor Component] + ModeSwitch[Mode Switcher] + SplitView[Split View] + end + + FlexToolbar --> ToolbarButton + FlexToolbar --> ToolbarGroup + FlexToolbar --> ToolbarListButton + EditorComponent --> FlexToolbar + EditorComponent --> ModeSwitch + EditorComponent --> SplitView + ToolbarButton --> Forms +``` + +## Data Flow + +### Content Flow + +```mermaid +sequenceDiagram + participant User + participant View as MarkdownEditorView + participant Editor as Editor Instance + participant PM as ProseMirror + participant Handler as ContentHandler + participant MD as markdown-it + + User->>View: Type in WYSIWYG + View->>PM: Input event + PM->>PM: Update document + PM->>Editor: State change + + User->>View: Switch to Markup mode + View->>Editor: Mode change + Editor->>Handler: Serialize + Handler->>MD: ProseMirror → Markdown + MD-->>Handler: Markdown string + Handler-->>Editor: Content for CodeMirror + + User->>View: getValue() + View->>Editor: getValue() + Editor->>Handler: Serialize current state + Handler-->>Editor: Markdown string + Editor-->>View: Return markdown +``` + +### Event System + +The editor emits events for external integration: + +| Event | Trigger | +|-------|---------| +| `change` | Content modified | +| `submit` | Ctrl/Cmd+Enter pressed | +| `cancel` | Escape pressed | +| `toolbar-action` | Toolbar button clicked | +| `mode-change` | WYSIWYG ↔ Markup switch | + +## Directory Structure + +``` +src/ +├── bundle/ # Public React API +│ ├── Editor.ts +│ ├── useMarkdownEditor.ts +│ ├── MarkdownEditorView.tsx +│ └── config/ # Toolbar configurations +│ +├── core/ # Editor engine +│ ├── Editor.ts # WysiwygEditor +│ ├── ContentHandler.ts +│ ├── ExtensionBuilder.ts +│ ├── ExtensionsManager.ts +│ └── markdown/ # Parsing utilities +│ +├── extensions/ # Plugin system +│ ├── base/ # Base implementations +│ ├── markdown/ # Standard markdown +│ ├── yfm/ # YFM-specific +│ ├── behavior/ # Editor behaviors +│ └── additional/ # Optional (HTML, LaTeX, etc.) +│ +├── presets/ # Extension bundles +├── toolbar/ # Toolbar components +├── forms/ # Dialog components +├── view/ # React utilities +├── pm/ # ProseMirror re-exports +├── cm/ # CodeMirror re-exports +├── utils/ # Shared utilities +└── styles/ # SCSS stylesheets +``` diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..c64a0c8a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,83 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +@gravity-ui/markdown-editor is a React-based markdown editor component that combines WYSIWYG and Markup modes. It uses ProseMirror for rich text editing and CodeMirror for markup editing. Supports standard Markdown and YFM (Yandex Flavored Markdown) syntax. + +## Common Commands + +```bash +npm start # Start Storybook dev server (port 8888) +npm run build # Build for production +npm run typecheck # TypeScript type checking +npm run lint # Run all linters (ESLint, Stylelint, Prettier) +npm test # Run Jest unit tests +npm run test:watch # Run tests in watch mode +npm run playwright # Run Playwright E2E tests +``` + +## Architecture + +### Core Modules (`/src`) + +- **`/bundle`** - High-level React API + - `useMarkdownEditor()` hook creates editor instance + - `MarkdownEditorView` component renders the editor + - `/config` contains toolbar and preset configurations + +- **`/core`** - Core editor engine + - `Editor.ts` - WysiwygEditor class (ProseMirror-based) + - `ContentHandler.ts` - Markdown serialization/deserialization + - `ExtensionBuilder.ts` / `ExtensionsManager.ts` - Extension system + +- **`/extensions`** - Built-in extensions organized by category + - `/base` - Base extension implementations + - `/markdown` - Standard markdown features (headings, lists, code blocks, tables) + - `/yfm` - YFM-specific features (alerts, tabs, notes) + - `/behavior` - Editor behaviors (history, links, images) + +- **`/pm`** - ProseMirror abstraction layer (re-exports prosemirror-* modules) +- **`/cm`** - CodeMirror 6 abstraction layer (re-exports @codemirror/* modules) + +- **`/presets`** - Editor configurations: `default`, `full`, `yfm`, `commonmark`, `zero` + +- **`/toolbar`** - Toolbar UI components +- **`/forms`** - Dialog/form components for links, images, files +- **`/view`** - React view layer (components, hooks, HOCs) + +### Package Exports + +The package provides subpath exports for tree-shaking: +- `@gravity-ui/markdown-editor` - Main bundle +- `@gravity-ui/markdown-editor/core` - Core engine only +- `@gravity-ui/markdown-editor/extensions` - Extension system +- `@gravity-ui/markdown-editor/view` - React components +- `@gravity-ui/markdown-editor/cm/*` - CodeMirror utilities +- `@gravity-ui/markdown-editor/pm/*` - ProseMirror utilities + +### Editor Modes + +- **WYSIWYG**: ProseMirror-based rich editing +- **Markup**: CodeMirror-based raw markdown editing +- **Split**: Both modes side-by-side with synchronized content + +### Basic Usage Pattern + +```tsx +import {useMarkdownEditor, MarkdownEditorView} from '@gravity-ui/markdown-editor'; + +function Editor() { + const editor = useMarkdownEditor({allowHTML: false}); + return ; +} +``` + +## Tech Stack + +- React 16-19, TypeScript, SCSS +- ProseMirror (WYSIWYG), CodeMirror 6 (Markup) +- markdown-it (parsing), @gravity-ui/* UI components +- Jest (unit tests), Playwright (E2E tests) +- Gulp (build), Storybook (development/docs)