npm package: @reeverdev/editor
Description: Reever Editor - Modern, extensible rich text editor framework
Author: Reever Team
Latest version: 1.0.2

# Reever Editor

A headless, extensible rich text editor framework built on ProseMirror. Inspired by Tiptap, designed for flexibility.

## Features

- **Headless Architecture** - Full control over UI, bring your own components
- **Extensible** - Modular extension system for nodes, marks, and plugins
- **Framework Agnostic** - Core is vanilla JS, with first-class React bindings
- **TypeScript First** - Written in TypeScript with full type coverage
- **ProseMirror Foundation** - Built on battle-tested ProseMirror

## Installation

```bash
# npm
npm install @reeverdev/editor

# pnpm
pnpm add @reeverdev/editor

# yarn
yarn add @reeverdev/editor
```

## Quick Start

### Vanilla JavaScript

```typescript
import { Editor } from '@reeverdev/editor';
import { StarterKit } from '@reeverdev/editor/starter-kit';

const editor = new Editor({
  element: document.querySelector('#editor'),
  extensions: [StarterKit],
  content: '<p>Hello World!</p>',
});

// Use commands
editor.chain().focus().toggleBold().run();

// Get content
const html = editor.getHTML();
const json = editor.getJSON();
```

### React

```tsx
import { useEditor, EditorContent } from '@reeverdev/editor/react';
import { StarterKit } from '@reeverdev/editor/starter-kit';

function MyEditor() {
  const editor = useEditor({
    extensions: [StarterKit],
    content: '<p>Hello World!</p>',
  });

  return <EditorContent editor={editor} />;
}
```

## Packages

| Package | Description |
|---------|-------------|
| `@reeverdev/core` | Core editor, extension system, commands |
| `@reeverdev/react` | React hooks and components |
| `@reeverdev/starter-kit` | Pre-configured bundle of essential extensions |
| `@reeverdev/pm` | ProseMirror re-exports |

### Extensions

| Extension | Description |
|-----------|-------------|
| `@reeverdev/extension-bold` | Bold text formatting |
| `@reeverdev/extension-italic` | Italic text formatting |
| `@reeverdev/extension-underline` | Underline text formatting |
| `@reeverdev/extension-strike` | Strikethrough text |
| `@reeverdev/extension-code` | Inline code |
| `@reeverdev/extension-code-block` | Code blocks |
| `@reeverdev/extension-heading` | Headings (h1-h6) |
| `@reeverdev/extension-paragraph` | Paragraphs |
| `@reeverdev/extension-blockquote` | Block quotes |
| `@reeverdev/extension-bullet-list` | Bullet lists |
| `@reeverdev/extension-ordered-list` | Numbered lists |
| `@reeverdev/extension-task-list` | Task/checkbox lists |
| `@reeverdev/extension-task-item` | Task list items |
| `@reeverdev/extension-link` | Hyperlinks |
| `@reeverdev/extension-image` | Images with resize support |
| `@reeverdev/extension-highlight` | Text highlighting |
| `@reeverdev/extension-color` | Text color |
| `@reeverdev/extension-text-style` | Text styling base |
| `@reeverdev/extension-history` | Undo/redo |
| `@reeverdev/extension-placeholder` | Placeholder text |
| `@reeverdev/extension-bubble-menu` | Selection-based floating menu |
| `@reeverdev/extension-floating-menu` | Empty line floating menu |
| `@reeverdev/extension-horizontal-rule` | Horizontal dividers |
| `@reeverdev/extension-hard-break` | Line breaks |
| `@reeverdev/extension-subscript` | Subscript text |
| `@reeverdev/extension-superscript` | Superscript text |

## Creating Custom Extensions

### Basic Extension

```typescript
import { Extension } from '@reeverdev/core';

const MyExtension = Extension.create({
  name: 'myExtension',

  addCommands() {
    return {
      myCommand: () => ({ commands }) => {
        // Your command logic
        return true;
      },
    };
  },

  addKeyboardShortcuts() {
    return {
      'Mod-Shift-x': () => this.editor.commands.myCommand(),
    };
  },
});
```

### Custom Node

```typescript
import { Node } from '@reeverdev/core';

const CustomNode = Node.create({
  name: 'customNode',
  group: 'block',
  content: 'inline*',

  parseHTML() {
    return [{ tag: 'div[data-custom]' }];
  },

  renderHTML({ HTMLAttributes }) {
    return ['div', { 'data-custom': '', ...HTMLAttributes }, 0];
  },
});
```

### Custom Mark

```typescript
import { Mark } from '@reeverdev/core';

const CustomMark = Mark.create({
  name: 'customMark',

  parseHTML() {
    return [{ tag: 'span[data-custom-mark]' }];
  },

  renderHTML({ HTMLAttributes }) {
    return ['span', { 'data-custom-mark': '', ...HTMLAttributes }, 0];
  },

  addCommands() {
    return {
      toggleCustomMark: () => ({ commands }) => {
        return commands.toggleMark(this.name);
      },
    };
  },
});
```

## Configuration

### StarterKit Options

```typescript
import { StarterKit } from '@reeverdev/editor/starter-kit';

const editor = new Editor({
  extensions: [
    StarterKit.configure({
      // Disable specific extensions
      history: false,
      codeBlock: false,

      // Configure extensions
      heading: {
        levels: [1, 2, 3],
      },
      link: {
        validate: (href) => href.startsWith('https://'),
      },
      image: {
        allowResize: true,
      },
    }),
  ],
});
```

### Editor Events

```typescript
const editor = new Editor({
  extensions: [StarterKit],
  onUpdate: ({ editor }) => {
    console.log('Content updated:', editor.getHTML());
  },
  onSelectionUpdate: ({ editor }) => {
    console.log('Selection changed');
  },
  onCreate: ({ editor }) => {
    console.log('Editor created');
  },
  onDestroy: () => {
    console.log('Editor destroyed');
  },
  onFocus: ({ editor }) => {
    console.log('Editor focused');
  },
  onBlur: ({ editor }) => {
    console.log('Editor blurred');
  },
});
```

## React Components

### BubbleMenu

A floating menu that appears when text is selected.

```tsx
import { BubbleMenu } from '@reeverdev/editor/react';

function MyEditor() {
  const editor = useEditor({ extensions: [StarterKit] });

  return (
    <>
      <EditorContent editor={editor} />
      <BubbleMenu editor={editor}>
        <button onClick={() => editor.chain().focus().toggleBold().run()}>
          Bold
        </button>
        <button onClick={() => editor.chain().focus().toggleItalic().run()}>
          Italic
        </button>
      </BubbleMenu>
    </>
  );
}
```

### FloatingMenu

A menu that appears on empty lines.

```tsx
import { FloatingMenu } from '@reeverdev/editor/react';

function MyEditor() {
  const editor = useEditor({ extensions: [StarterKit] });

  return (
    <>
      <EditorContent editor={editor} />
      <FloatingMenu editor={editor}>
        <button onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}>
          H1
        </button>
        <button onClick={() => editor.chain().focus().toggleBulletList().run()}>
          List
        </button>
      </FloatingMenu>
    </>
  );
}
```

## Commands

Commands are chainable and provide a fluent API:

```typescript
// Chain multiple commands
editor
  .chain()
  .focus()
  .selectAll()
  .toggleBold()
  .run();

// Check if command can execute
if (editor.can().toggleBold()) {
  editor.commands.toggleBold();
}

// Available commands (varies by extensions)
editor.commands.setBold();
editor.commands.unsetBold();
editor.commands.toggleBold();
editor.commands.setItalic();
editor.commands.toggleHeading({ level: 1 });
editor.commands.setLink({ href: 'https://example.com' });
editor.commands.insertContent('<p>New content</p>');
editor.commands.setContent('<p>Replace all</p>');
editor.commands.clearContent();
editor.commands.undo();
editor.commands.redo();
```

## Working with Content

```typescript
// Get content
const html = editor.getHTML();
const json = editor.getJSON();
const text = editor.getText();

// Set content
editor.commands.setContent('<p>New content</p>');
editor.commands.setContent({ type: 'doc', content: [...] });

// Insert content
editor.commands.insertContent('<p>Inserted</p>');
editor.commands.insertContentAt(10, '<p>At position</p>');

// Clear content
editor.commands.clearContent();
```

## Development

```bash
# Install dependencies
pnpm install

# Run development server
pnpm dev

# Build all packages
pnpm build

# Run tests
pnpm test

# Lint
pnpm lint
```

## Project Structure

```
packages/
├── core/                    # Core editor
├── react/                   # React bindings
├── starter-kit/             # Pre-configured extensions
├── pm/                      # ProseMirror re-exports
├── extension-bold/          # Bold extension
├── extension-italic/        # Italic extension
├── extension-*/             # Other extensions
examples/
└── react-basic/             # React example app
```

## License

MIT

## Contributing

Contributions are welcome! Please read our contributing guidelines before submitting a PR.

## Links

- [GitHub Repository](https://github.com/ReeverApp/Reever.Editor)
- [Homepage](https://reever.dev)