Skip to main content

No project description provided

Project description

Datalayer

Become a Sponsor

โœ๏ธ ๐Ÿฆœ Lexical Loro - Collaborative Plugin for Lexical with Loro CRDT

A collaborative editing plugin for Lexical Rich Editor built with Loro CRDT, providing real-time collaborative editing capabilities with conflict-free synchronization.

Core Components

This package provides three main components for building collaborative text editors:

  1. LoroCollaborativePlugin.tsx - A Lexical plugin that integrates Loro CRDT for real-time collaborative editing
  2. LexicalModel Python Library - A standalone document model for Lexical content with CRDT capabilities
  3. lexical-loro WebSocket Server - A Python server using loro-py for real-time collaboration

Quick Start

Using the Lexical Plugin

import { LoroCollaborativePlugin } from './src/LoroCollaborativePlugin';

function MyEditor() {
  return (
    <LexicalComposer initialConfig={editorConfig}>
      <RichTextPlugin />
      <LoroCollaborativePlugin 
        websocketUrl="ws://localhost:8081"
        docId="my-document"
        username="user1"
      />
    </LexicalComposer>
  );
}

Using the LexicalModel Library

from lexical_loro import LexicalModel

# Create a new document
model = LexicalModel.create_document("my-document")

# Add content
model.add_block({
    "text": "My Document",
    "format": 0,
    "style": ""
}, "heading1")

model.add_block({
    "text": "This is a paragraph.",
    "format": 0,
    "style": ""
}, "paragraph")

# Save to file
model.save_to_file("document.json")

# Load from file
loaded_model = LexicalModel.load_from_file("document.json")

Using the Python Server

# Install the Python package
pip install -e .

# Start the server
lexical-loro-server --port 8081

Examples

For complete working examples, see the src/examples/ directory which contains:

  • Full React application with dual editor support
  • Server selection interface
  • Connection status indicators
  • Rich text formatting examples

DISCLAIMER Collaborative Cursors still need fixes, see this issue.

Core Features

  • ๐Ÿ”„ Real-time Collaboration: Multiple users can edit the same document simultaneously
  • ๐Ÿš€ Conflict-free: Uses Loro CRDT to automatically resolve conflicts
  • ๐Ÿ“ Lexical Integration: Seamless integration with Lexical rich text editor
  • ๐Ÿ“š Standalone Library: Use LexicalModel independently for document management
  • ๐ŸŒ WebSocket Server: Python server for maintaining document state
  • ๐Ÿ“ก Connection Management: Robust WebSocket connection handling
  • โœจ Rich Text Support: Preserves formatting during collaborative editing
  • ๐Ÿ’พ Serialization: JSON export/import and file persistence
  • ๐Ÿ”ง Extensible: Plugin-based architecture for easy customization

Technology Stack

Core Dependencies:

  • Lexical: v0.33.1 (Facebook's extensible text editor framework)
  • Loro CRDT: v1.5.10 (Conflict-free replicated data types)
  • React: 18/19 (for plugin hooks and components)
  • Python: 3.8+ with loro-py and websockets

Development Dependencies:

  • TypeScript: For type safety
  • Vite: For building and development (examples only)
  • pytest: Python testing
  • ESLint: Code linting

Installation

Core Plugin

The Lexical plugin is a single TypeScript/React component that you can copy into your project:

# Copy the plugin file
cp src/LoroCollaborativePlugin.tsx your-project/src/

Dependencies required:

npm install lexical @lexical/react @lexical/selection loro-crdt react react-dom

Python Server

Install the Python WebSocket server:

# Install from this repository
pip install -e .

# Or install specific dependencies
pip install websockets click loro

Usage

1. Lexical Plugin Integration

Add the plugin to your Lexical editor:

import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
import { LoroCollaborativePlugin } from './LoroCollaborativePlugin';

const editorConfig = {
  namespace: 'MyEditor',
  theme: {},
  onError: console.error,
};

function CollaborativeEditor() {
  return (
    <LexicalComposer initialConfig={editorConfig}>
      <div className="editor-container">
        <RichTextPlugin
          contentEditable={<ContentEditable className="editor-input" />}
          placeholder={<div className="editor-placeholder">Start typing...</div>}
          ErrorBoundary={() => <div>Error occurred</div>}
        />
        <LoroCollaborativePlugin 
          websocketUrl="ws://localhost:8081"
          docId="shared-document"
          username="user123"
        />
      </div>
    </LexicalComposer>
  );
}

2. Standalone LexicalModel Library

Use the LexicalModel library independently for document management:

from lexical_loro import LexicalModel

# Create a new document
model = LexicalModel.create_document("my-document")

# Add different types of content
model.add_block({
    "text": "My Document",
    "format": 0,
    "style": ""
}, "heading1")

model.add_block({
    "text": "This is a paragraph with **bold** text.",
    "format": 0,
    "style": ""
}, "paragraph")

model.add_block({
    "text": "",
    "format": 0,
    "style": ""
}, "list")

# Serialize to JSON
json_data = model.to_json()

# Save to file
model.save_to_file("document.json")

# Load from file
loaded_model = LexicalModel.load_from_file("document.json")

# Access blocks
for block in loaded_model.get_blocks():
    print(f"{block['type']}: {block.get('text', '')}")

For more examples, see:

  • examples/memory_only_example.py - Basic document creation and manipulation
  • examples/file_sync_example.py - File persistence and batch operations
  • examples/collaboration_example.py - Simulating collaborative editing
  • docs/LEXICAL_MODEL_GUIDE.md - Comprehensive documentation

3. Python Server Setup

Start the WebSocket server:

# Default port (8081)
lexical-loro-server

# Custom port
lexical-loro-server --port 8082

# With debug logging
lexical-loro-server --port 8081 --log-level DEBUG

4. Programmatic Server Usage

import asyncio
from lexical_loro import LoroWebSocketServer

async def main():
    server = LoroWebSocketServer(port=8081)
    await server.start()
    print("Server running on ws://localhost:8081")

if __name__ == "__main__":
    asyncio.run(main())

Plugin API

For detailed API documentation, see docs/API.md.

Quick Reference

interface LoroCollaborativePluginProps {
  websocketUrl: string;          // WebSocket server URL
  docId: string;                 // Unique document identifier
  username: string;              // User identifier
  userColor?: string;            // User cursor color (optional)
  debug?: boolean;               // Enable debug logging (optional)
}

Initialization Best Practices

โš ๏ธ Important: Always wait for collaboration initialization before enabling other plugins.

See docs/INITIALIZATION_GUIDE.md for comprehensive guidance on:

  • Proper plugin ordering
  • Initialization callbacks
  • Error handling
  • Common anti-patterns to avoid

Examples

For complete working examples and demonstrations, see the src/examples/ directory:

# Run the example application
npm install
npm run example

# This starts both Node.js and Python servers plus a React demo app
# Open http://localhost:5173 to see dual editor interface

The examples include:

  • Complete React App: Full collaborative editor with UI
  • Server Selection: Switch between Node.js and Python backends
  • Dual Editors: Simple text area and rich Lexical editor
  • Real-time Demo: Multi-user collaboration testing

See src/examples/README.md for detailed example documentation.

Project Structure

Core Components

src/
โ”œโ”€โ”€ LoroCollaborativePlugin.tsx         # Main Lexical plugin for collaboration
โ””โ”€โ”€ vite-env.d.ts                       # TypeScript definitions

lexical_loro/                           # Python WebSocket server package
โ”œโ”€โ”€ __init__.py                         # Package exports
โ”œโ”€โ”€ server.py                           # WebSocket server implementation  
โ”œโ”€โ”€ cli.py                              # Command line interface
โ”œโ”€โ”€ model/
โ”‚   โ””โ”€โ”€ lexical_model.py                # Standalone LexicalModel library
โ””โ”€โ”€ tests/                              # Python test suite

docs/
โ””โ”€โ”€ LEXICAL_MODEL_GUIDE.md              # Comprehensive library documentation

examples/
โ”œโ”€โ”€ memory_only_example.py              # Basic LexicalModel usage
โ”œโ”€โ”€ file_sync_example.py                # File persistence example
โ”œโ”€โ”€ collaboration_example.py            # Collaborative editing simulation
โ””โ”€โ”€ README.md                           # Examples documentation

pyproject.toml                          # Python package configuration

Examples Directory

src/examples/                           # Complete demo application
โ”œโ”€โ”€ App.tsx                             # Demo app with dual editors
โ”œโ”€โ”€ LexicalCollaborativeEditor.tsx      # Rich text editor example
โ”œโ”€โ”€ TextAreaCollaborativeEditor.tsx     # Simple text editor example
โ”œโ”€โ”€ ServerSelector.tsx                  # Server selection UI
โ”œโ”€โ”€ LexicalToolbar.tsx                  # Rich text toolbar
โ”œโ”€โ”€ main.tsx                            # Demo app entry point
โ””โ”€โ”€ *.css                               # Styling for examples

servers/
โ””โ”€โ”€ server.ts                           # Node.js server (for comparison)

Archive

src/archive/                            # Historical plugin implementations
โ”œโ”€โ”€ LoroCollaborativePlugin0.tsx        # Previous versions for reference
โ”œโ”€โ”€ LoroCollaborativePlugin1.tsx
โ”œโ”€โ”€ LoroCollaborativePlugin2.tsx
โ”œโ”€โ”€ LoroCollaborativePlugin3.tsx
โ”œโ”€โ”€ LoroCollaborativePlugin4.tsx
โ””โ”€โ”€ LoroCollaborativePlugin5.tsx

Architecture

For detailed architecture documentation, see docs/ARCHITECTURE.md.

System Overview

The collaboration system consists of three main components:

  1. LoroCollaborativePlugin (Client-side) - Lexical integration
  2. LoroWebSocketServer (Server-side) - Real-time synchronization
  3. LexicalModel (Standalone Library) - Independent document model

Data Flow

User Types โ†’ Lexical Editor โ†’ Plugin โ†’ Loro CRDT โ†’ WebSocket
                                                        โ†“
WebSocket โ† Loro CRDT โ† Plugin โ† Lexical Editor โ† Other Users

Configuration

For detailed configuration options, see docs/API.md.

Quick Configuration

// Plugin configuration
<LoroCollaborativePlugin 
  websocketUrl="ws://localhost:8081"
  docId="my-document"
  username="user123"
  debug={true}
/>
# Server configuration
lexical-loro-server --port 8081 --log-level DEBUG

Development

For comprehensive development guidelines, see docs/DEVELOPMENT.md.

Quick Start

# Install dependencies
npm install
pip install -e ".[dev]"

# Run tests
npm test
npm run test:py

# Start development server
lexical-loro-server --log-level DEBUG

Contributing

We welcome contributions! Please see docs/DEVELOPMENT.md for detailed guidelines.

Quick Contributing Guide

  1. Fork the repository
  2. Create a feature branch
  3. Focus changes on core components
  4. Add tests for new functionality
  5. Update documentation as needed
  6. Submit a pull request

Documentation

License

This project is open source and available under the MIT License.

Acknowledgments

  • Loro CRDT - The CRDT library powering collaborative editing
  • Lexical - Facebook's extensible text editor framework
  • React - UI library for plugin hooks
  • WebSocket - Real-time communication

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lexical_loro-0.0.7-py3-none-any.whl (66.4 kB view details)

Uploaded Python 3

File details

Details for the file lexical_loro-0.0.7-py3-none-any.whl.

File metadata

  • Download URL: lexical_loro-0.0.7-py3-none-any.whl
  • Upload date:
  • Size: 66.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.12

File hashes

Hashes for lexical_loro-0.0.7-py3-none-any.whl
Algorithm Hash digest
SHA256 05d6f6cabdba58c6ee55a4bfa4d0605e8ad7bf443585c7c23f7b56134c83895c
MD5 3dbfd88ab876263e0fc2b138bbe15aa9
BLAKE2b-256 4d00090e7f1259e291b53d40f7343ccd3fa185056eb5d8d03d86757c75bd8c52

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page