A collaborative rich text editor app for Netless Whiteboard, built with Quill.js and Y.js for real-time collaboration.
- Real-time Collaboration: Multiple users can edit the same document simultaneously
- Rich Text Editing: Full-featured text editor with formatting options
- Live Cursors: See other users' cursors in real-time
- Image Upload: Support for pasting and uploading images
- Mathematical Formulas: Built-in KaTeX support for mathematical expressions
- Customizable Toolbar: Configurable toolbar with various formatting options
- Placeholder Text: Customizable placeholder text for empty editor
- Base64 Image Handling: Automatic conversion of base64 images to URLs
npm install @netless/app-quill
# or
yarn add @netless/app-quill
# or
pnpm add @netless/app-quillimport { NetlessAppQuill } from '@netless/app-quill';
import { WindowManager } from '@netless/window-manager';
// Register the app
await WindowManager.register({
  kind: 'Quill',
  src: NetlessAppQuill,
  appOptions: {
    options: {
      // Quill.js options
      modules: {
        toolbar: [
          ['bold', 'italic', 'underline'],
          ['link', 'formula'],
          ['clean']
        ]
      }
    }
  }
});
// Add a new Quill app instance
manager.addApp({
  kind: 'Quill',
  attributes: {
    placeholder: 'Start typing...'
  }
});await WindowManager.register({
  kind: 'Quill',
  src: NetlessAppQuill,
  appOptions: {
    options: {
      modules: {
        cursors: true,
        toolbar: [
          [{ header: [1, 2, false] }, 'blockquote', 'code-block'],
          [{ list: 'ordered' }, { list: 'bullet' }, { indent: '-1' }, { indent: '+1' }],
          ['bold', 'italic', 'underline', 'strike'],
          [{ color: [] }, { background: [] }, { align: [] }],
          [{ script: 'sub' }, { script: 'super' }],
          ['link', 'formula'],
          ['clean']
        ],
        history: {
          userOnly: true
        }
      }
    },
    uploadBase64Image: async (base64Image: string) => {
      // Convert base64 to file and upload to your server
      const response = await fetch('/api/upload', {
        method: 'POST',
        body: JSON.stringify({ image: base64Image })
      });
      const { url } = await response.json();
      return url;
    }
  }
});interface QuillAppAttributes {
  /**
   * Placeholder text to display when the editor is empty
   * @default ""
   */
  placeholder?: string;
}interface QuillAppOptions {
  /**
   * Options for initializing a Quill instance
   */
  options?: QuillOptions;
  
  /**
   * Upload the base64 image to the image server and return the image url
   * @param base64Image 
   * @returns image url
   */
  uploadBase64Image?: (base64Image: string) => Promise<string>;
}The app comes with sensible defaults:
- Toolbar: Includes common formatting options like bold, italic, lists, links, and formulas
- Cursors: Enabled by default for real-time collaboration
- History: User-only history to prevent conflicts
- Theme: Snow theme for a clean look
- Placeholder: "Hello, world!" as default placeholder text
- @netless/fastboard: ^0.3.16 (peer dependency)
- quill: ^2.0.2
- quill-cursors: ^4.0.3
- y-quill: ^1.0.0
- yjs: ^13.6.18
- katex: ^0.16.11
# Install dependencies
pnpm install
# Start development server
pnpm dev
# Build the project
pnpm buildSee the example/ directory for a complete working example.
MIT