Skip to content

easylogic/contenteditable

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

63 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

⌨️ contenteditable.lab

A living catalog of contenteditable behavior across browsers, operating systems, and input methods.


Why This Project Exists

The contenteditable attribute is deceptively simpleβ€”add it to any HTML element and users can edit its contents. But beneath this simplicity lies a minefield of browser-specific quirks, OS-dependent behaviors, and IME complications that have frustrated developers for decades.

The Reality of contenteditable

When you use contenteditable in production, you quickly discover that:

  • The same code behaves differently across Chrome, Firefox, Safari, and Edge
  • IME (Input Method Editor) behavior varies dramatically between Windows, macOS, and Linux
  • Event sequences (beforeinput, input, compositionstart, etc.) fire in different orders depending on the browser
  • Selection and Range APIs have subtle but critical differences that break editor features
  • Undo/redo stacks are cleared unexpectedly or don't include programmatic changes
  • Paste behavior is inconsistent, sometimes preserving formatting, sometimes stripping it
  • Mobile browsers introduce entirely new sets of quirks with touch interactions

These aren't edge casesβ€”they're the daily reality of building rich text editors. Major projects like ProseMirror, Slate, and Lexical have spent years working around these issues, but their solutions are often proprietary or too complex for smaller projects.

contenteditable.lab exists to document these behaviors systematically so that:

  • πŸ” You can observe β€” Real-world edge cases captured with precise reproduction steps and environment details
  • πŸ“š You can search β€” Cases organized by environment (OS Γ— Browser Γ— Input Method) so you can find issues specific to your users
  • πŸ§ͺ You can reproduce β€” Interactive playground to verify behaviors in your own environment before shipping code
  • πŸ“– You can learn β€” Comprehensive documentation on events, Selection API, and proven workarounds

What You'll Find Here

πŸ“‹ Cases

Each case documents a specific contenteditable behavior observed in a particular environment. A case includes:

Case: ce-0002-ime-enter-breaks
β”œβ”€β”€ Environment: Windows Γ— Chrome Γ— Korean IME
β”œβ”€β”€ Title: Composition is cancelled when pressing Enter
β”œβ”€β”€ Description: Detailed explanation of what happens and why
β”œβ”€β”€ Reproduction Steps: Step-by-step instructions to trigger it
β”œβ”€β”€ Expected Behavior: What should happen according to specs
β”œβ”€β”€ Observed Behavior: What actually happens in this environment
β”œβ”€β”€ Analysis: Technical explanation if known
β”œβ”€β”€ DOM Steps: Visual representation of DOM changes
└── Status: confirmed (verified) / draft (needs verification)

Why cases matter: When a user reports "the editor breaks when I type Korean," you can search for cases with Korean IME tag and find the exact scenario, reproduction steps, and potential workarounds. Cases are searchable by:

  • OS (Windows, macOS, Linux, iOS, Android)
  • Browser (Chrome, Firefox, Safari, Edge)
  • Device (Desktop, Mobile, Tablet)
  • Keyboard layout (US QWERTY, Korean IME, Japanese IME, etc.)
  • Tags (ime, composition, selection, paste, undo, etc.)

🎭 Scenarios

Scenarios group related cases that describe the same phenomenon across different environments. This helps you understand:

  1. Which environments are affected β€” Is this a Chrome-only issue or does it affect all browsers?
  2. Which environments need testing β€” Are there gaps in our coverage?
  3. The scope of the problem β€” Is this a universal issue or environment-specific?

Example scenario:

"IME composition cancelled on Enter"

This scenario groups cases where pressing Enter during IME composition cancels the composition unexpectedly:

  • Windows + Chrome + Korean IME βœ“ (confirmed)
  • macOS + Safari + Japanese IME βœ“ (confirmed)
  • Linux + Firefox + Chinese IME ? (needs testing)
  • iOS Safari + Chinese IME ? (needs testing)

Each scenario page includes:

  • Description of the phenomenon
  • Impact on user experience and development
  • Browser comparison showing which browsers are most/least affected
  • Workarounds and solutions that have been tested
  • Related cases with links to specific environment combinations
  • Graph visualization showing relationships between cases, scenarios, and tags

πŸ§ͺ Playground

An interactive testing ground where you can:

  • Type and observe β€” Type in a contenteditable region and watch events fire in real-time
  • Visualize ranges β€” See selection, composition, and beforeinput ranges overlaid on the editor
  • Track DOM changes β€” Visualize deleted and added text regions with color-coded highlights
  • Detect invisible characters β€” See ZWNBSP, NBSP, LF, CR, TAB, and other invisible characters
  • Identify non-editable areas β€” Highlight contenteditable="false" regions within selections
  • Capture snapshots β€” Automatically save snapshots when anomalies are detected, with full event logs and environment info
  • Browse event history β€” View detailed event logs with timing, DOM structure, and getTargetRanges() data
  • Test with presets β€” Choose from 23+ sample HTML presets covering various scenarios (CJK, RTL, tables, code blocks, emoji, etc.)
  • Export reports β€” Copy comprehensive event analysis reports for GitHub issues

πŸ“– Documentation

Comprehensive guides covering all aspects of contenteditable:

  • What is contenteditable? β€” Fundamentals, use cases, and when to use (or avoid) it
  • Events β€” Deep dive into the event lifecycle (beforeinput, input, compositionstart/update/end, selectionchange) and how they differ across browsers
  • IME & Composition β€” How input methods (Korean, Japanese, Chinese, etc.) interact with contenteditable, common issues, and solutions
  • Selection API β€” Working with Selection and Range objects, common pitfalls, and reliable patterns
  • Range API β€” Advanced range manipulation, boundary detection, and cross-browser compatibility
  • Clipboard API β€” Copy, paste, and clipboard event handling
  • execCommand alternatives β€” Why execCommand is deprecated and modern approaches (Input Events, Selection API, custom implementations)
  • Practical Patterns β€” Real-world patterns for building editors, with code examples
  • Common Pitfalls & Debugging β€” Frequent mistakes and how to debug contenteditable issues
  • Performance β€” Optimizing contenteditable performance for large documents
  • Accessibility β€” Making contenteditable accessible to screen readers and keyboard navigation
  • Browser compatibility β€” Detailed support matrix and known issues per browser

The Problem We're Solving

Building a rich text editor? You'll encounter questions like:

  • "Why does Enter behave differently in Safari?" β€” Safari inserts <div> while Chrome inserts <br>, breaking your formatting logic
  • "Why does my Korean IME lose characters on certain key combos?" β€” Composition events fire in different orders, causing character loss
  • "Why does paste formatting vary between browsers?" β€” Chrome preserves HTML structure, Firefox strips it, Safari does something else entirely
  • "Why does undo/redo break after programmatic DOM changes?" β€” The undo stack is cleared or doesn't include your changes, making undo/redo unreliable
  • "Why does my selection disappear after I wrap text in a <strong> tag?" β€” Selection restoration is inconsistent across browsers
  • "Why does typing in a table cell break the table structure?" β€” Table editing behavior varies dramatically between browsers
  • "Why does my code block lose indentation when users type?" β€” Whitespace preservation in <pre><code> is unreliable

These aren't theoreticalβ€”they're real issues developers face daily. Each one can take hours or days to debug, often requiring:

  1. Reproducing the issue in multiple browsers and OS combinations
  2. Understanding the event sequence by adding extensive logging
  3. Finding workarounds through trial and error or reading obscure forum posts
  4. Testing edge cases to ensure the workaround doesn't break other features

contenteditable.lab collects these "incidents" with:

  • Exact reproduction steps so you can verify the issue immediately
  • Environment details so you know if it affects your users
  • Event logs showing the exact sequence of events
  • Proven workarounds that have been tested across environments
  • Related cases so you can see if similar issues exist in other environments

You don't have to rediscover these problems the hard way.


Who This Is For

  • Rich text editor developers β€” ProseMirror, Slate, Lexical, Tiptap users
  • Web application developers β€” Anyone using contenteditable in production
  • Browser engineers β€” Understanding cross-browser behavior differences
  • Accessibility specialists β€” Documenting input method behaviors
  • Curious developers β€” Learning how the web platform really works

Contributing

Report a New Case

Found a weird contenteditable behavior?

  1. Go to the Playground
  2. Select an appropriate sample HTML preset or use your own content
  3. Reproduce the issue and observe the event log, range visualizations, and DOM changes
  4. If an anomaly is detected, a snapshot will be automatically saved
  5. Click "πŸ“‹ Copy report" to get a comprehensive event analysis
  6. Open an issue with your findings

Verify Existing Cases

Many cases need confirmation across different environments. Pick a case marked as "draft" and test it in your environment.

Translate

The UI supports multiple languages. See TRANSLATION.md for contribution guidelines.


Philosophy

Precision over assumptions. Each case documents exactly what happens, not what "should" happen according to specs.

Environment matters. The same code produces different results on Windows Chrome vs macOS Safari vs mobile browsers. We capture these differences.

Reproducibility is key. Every case includes steps to reproduce. If you can't reproduce it, we refine the case until you can.

Community-driven. No single person has tested every OS Γ— Browser Γ— IME combination. This catalog grows through collective documentation.


Features

Playground Capabilities

  • Real-time event monitoring β€” Track selectionchange, compositionstart/update/end, beforeinput, and input events
  • Visual range indicators β€” Color-coded overlays for selection (blue), composition (purple), beforeinput (orange), deleted areas (yellow), and added areas (green)
  • DOM change tracking β€” Compare text node states before and after input events
  • Invisible character detection β€” Visual markers for ZWNBSP, NBSP, line breaks, tabs, and other non-visible characters
  • Automatic snapshot capture β€” Snapshots are saved when anomalies are detected, preserving full event context
  • Comprehensive event logs β€” Detailed information including:
    • Event timing and sequence
    • DOM node structure and hierarchy
    • Selection ranges and offsets
    • getTargetRanges() data from beforeinput events
    • Boundary detection (inline element boundaries)
    • Sibling node information
  • Sample HTML presets β€” 23+ presets covering:
    • Language-specific IME testing (Korean, Japanese, Chinese, Thai, Vietnamese, Arabic, Hindi)
    • Complex structures (nested inline, tables, code blocks)
    • Edge cases (HTML entities, RTL/LTR mixed, emoji, empty elements, long text wrapping)
    • Special characters and invisible characters

Tech Stack

This project is built with modern web technologies chosen for performance, developer experience, and maintainability:

  • Astro β€” Static site generator that generates fast, SEO-friendly pages. Perfect for documentation sites with minimal JavaScript by default, while allowing React components where needed (like the Playground).

  • React β€” Used for interactive components, specifically the Playground where real-time event monitoring and visualization require dynamic updates. React's component model makes it easy to manage complex state (event logs, snapshots, visualizations).

  • Tailwind CSS β€” Utility-first CSS framework for rapid UI development. Enables consistent styling across the site and makes dark mode theming straightforward with CSS variables.

  • React Flow + Dagre β€” Graph visualization library for displaying relationships between cases, scenarios, tags, and environments. Dagre provides automatic layout algorithms so the graphs are readable without manual positioning.

  • TypeScript β€” Type safety across the entire codebase. Critical for maintaining correctness in a project with complex data structures (event logs, DOM snapshots, case metadata).

  • IndexedDB β€” Client-side database for storing Playground snapshots. Allows users to save and restore editor states with full event context, even after page reloads. Snapshots are stored locally and don't require server infrastructure.

Quick Start

Local Development

# Clone the repository
git clone https://github.com/easylogic/contenteditable.git
cd contenteditable

# Install dependencies
pnpm install

# Start development server
pnpm dev

The dev server runs at http://localhost:4321 with hot module replacement enabled.

Available Commands

  • pnpm dev β€” Start development server at http://localhost:4321
  • pnpm build β€” Build production site to ./dist/
  • pnpm preview β€” Preview the production build locally before deploying
  • pnpm astro ... β€” Run Astro CLI commands directly

Project Structure

src/
β”œβ”€β”€ components/       # Astro & React components
β”‚   β”œβ”€β”€ Playground.tsx    # Interactive testing playground
β”‚   β”œβ”€β”€ ScenarioFlow.tsx  # Graph visualization
β”‚   └── ...
β”œβ”€β”€ content/         # Markdown content
β”‚   β”œβ”€β”€ cases/       # Individual case files
β”‚   └── scenarios/   # Scenario files
β”œβ”€β”€ data/
β”‚   └── presets/     # Sample HTML presets for Playground
β”œβ”€β”€ i18n/
β”‚   └── translations.ts  # UI translations for 7 languages
β”œβ”€β”€ pages/           # Route pages
β”‚   β”œβ”€β”€ cases/       # Case detail pages
β”‚   β”œβ”€β”€ scenarios/   # Scenario detail pages
β”‚   β”œβ”€β”€ docs/        # Documentation pages
β”‚   └── [locale]/    # Localized routes
└── styles/
    └── global.css   # Global styles with CSS variables

See DEVELOPMENT.md for detailed development setup, content management, and deployment instructions.

Internationalization

The site is fully internationalized to serve a global audience of developers working with contenteditable across different languages and input methods.

Supported Languages

  • πŸ‡ΊπŸ‡Έ English (default) β€” Primary language, all content available
  • πŸ‡°πŸ‡· Korean β€” Full UI translation, important for Korean IME testing
  • πŸ‡―πŸ‡΅ Japanese β€” Full UI translation, important for Japanese IME testing
  • πŸ‡¨πŸ‡³ Chinese β€” Full UI translation, important for Chinese IME testing
  • πŸ‡ͺπŸ‡Έ Spanish β€” Full UI translation
  • πŸ‡©πŸ‡ͺ German β€” Full UI translation
  • πŸ‡«πŸ‡· French β€” Full UI translation

What's Translated

  • UI elements β€” Navigation, buttons, labels, tooltips
  • Navigation β€” Menu items, breadcrumbs, page titles
  • Documentation β€” All documentation pages are available in all languages
  • Case and scenario content β€” Cases and scenarios can be written in any supported language

Language Detection

The site automatically detects the user's browser language and serves content in the appropriate locale. Users can also manually switch languages using the language selector in the navigation.

Contributing Translations

See TRANSLATION.md for detailed guidelines on:

  • Adding new languages
  • Translating UI strings
  • Translating content (cases, scenarios, documentation)
  • Maintaining translation quality

Links

About

contenteditable real error case

Resources

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published