# overtype **Repository Path**: mirrors_trending/overtype ## Basic Information - **Project Name**: overtype - **Description**: The markdown editor that's just a textarea https://overtype.dev - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-08-23 - **Last Updated**: 2026-01-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # OverType A lightweight markdown editor library with perfect WYSIWYG alignment using an invisible textarea overlay technique. Includes optional toolbar. ~95KB minified with all features. ## Live Examples ๐ฎ **Try it out**: [Interactive demos on overtype.dev](https://overtype.dev) - [Basic Editor](https://overtype.dev/#basic-editor) - Minimal setup with live preview - [With Toolbar](https://overtype.dev/#toolbar) - Full formatting toolbar - [Multiple Instances](https://overtype.dev/demo.html#multiple-instances) - Several editors on one page - [View Modes](https://overtype.dev/demo.html#view-modes) - Preview synchronization - [Themes](https://overtype.dev/demo.html#themes) - Light/dark theme switching - [All Features](https://overtype.dev/demo.html#markdown-features) - Complete markdown showcase ## Features - ๐ป **Invisible textarea overlay** - Transparent input layer overlaid on styled preview for seamless editing - ๐จ **Global theming** - Solar (light) and Cave (dark) themes that apply to all instances - โจ๏ธ **Keyboard shortcuts** - Common markdown shortcuts (Cmd/Ctrl+B for bold, etc.) - ๐ฑ **Mobile optimized** - Responsive design with mobile-specific styles - ๐ **DOM persistence aware** - Recovers from existing DOM (perfect for HyperClay and similar platforms) - ๐ **Lightweight** - ~95KB minified - ๐ฏ **Optional toolbar** - Clean, minimal toolbar with all essential formatting - โจ **Smart shortcuts** - Keyboard shortcuts with selection preservation - ๐ **Smart list continuation** - GitHub-style automatic list continuation on Enter - ๐ง **Framework agnostic** - Works with React, Vue, vanilla JS, and more ## How it works  We overlap an invisible textarea on top of styled output, giving the illusion of editing styled text using a plain textarea. ## Comparisons | Feature | OverType | HyperMD | Milkdown | TUI Editor | EasyMDE | |---------|----------|---------|----------|------------|---------| | **Size** | ~95KB | 364.02 KB | 344.51 KB | 560.99 KB | 323.69 KB | | **Dependencies** | Bundled | CodeMirror | ProseMirror + plugins | Multiple libs | CodeMirror | | **Setup** | Single file | Complex config | Build step required | Complex config | Moderate | | **Approach** | Invisible textarea | ContentEditable | ContentEditable | ContentEditable | CodeMirror | | **Mobile** | Perfect native | Issues common | Issues common | Issues common | Limited | | **Markdown syntax** | Visible | Hidden | Hidden | Toggle | Visible | | **Advanced features** | Basic | Full | Full | Full | Moderate | | **Best for** | Simple, fast, mobile | Full WYSIWYG | Modern frameworks | Enterprise apps | Classic editing | **Choose OverType when you need:** - Tiny bundle size (10x smaller than alternatives) - Zero dependencies - single file that works immediately - Perfect native browser features (undo/redo, mobile keyboards, spellcheck) - Dead-simple integration without build tools - Easy to understand, modify, and extend - Excellent mobile support with visible markdown syntax **Choose other editors when you need:** - Full WYSIWYG with hidden markdown syntax - Advanced features like tables, diagrams, or collaborative editing - Rich plugin ecosystems - Enterprise features and extensive customization - Framework-specific integration (React, Vue, etc.) - Complex multi-layered architecture for deep customization ## Installation ### NPM ```bash npm install overtype ``` ### CDN ```html ``` ## Quick Start ```javascript // Create a single editor const [editor] = new OverType('#editor', { value: '# Hello World', theme: 'solar' }); // Get/set content editor.getValue(); editor.setValue('# New Content'); // Change theme for this instance editor.setTheme('cave'); ``` ## Usage ### Basic Editor ```html
``` ### Toolbar ```javascript // Enable default toolbar with all formatting buttons const [editor] = new OverType('#editor', { toolbar: true, value: '# Document\n\nSelect text and use the toolbar!' }); // Default toolbar: Bold, Italic, Code | Link | H1, H2, H3 | Lists, Tasks | Quote | View Mode ``` **Custom Toolbar (v2.0):** ```javascript import OverType, { toolbarButtons } from 'overtype'; const [editor] = new OverType('#editor', { toolbar: true, toolbarButtons: [ toolbarButtons.bold, toolbarButtons.italic, toolbarButtons.separator, { name: 'save', icon: '', title: 'Save', action: ({ editor, getValue }) => { localStorage.setItem('draft', getValue()); } } ] }); // Available: bold, italic, code, link, h1, h2, h3, bulletList, // orderedList, taskList, quote, separator, viewMode ``` See [examples/custom-toolbar.html](examples/custom-toolbar.html) for complete examples. ### View Modes Three modes available via toolbar dropdown or programmatically: ```javascript editor.showNormalEditMode(); // Default WYSIWYG editing editor.showPlainTextarea(); // Raw markdown, no preview editor.showPreviewMode(); // Read-only preview with clickable links ``` ### Task Lists GitHub-style checkboxes render in preview mode: ```javascript const [editor] = new OverType('#editor', { value: '- [ ] Todo\n- [x] Done', toolbar: true // Use view mode dropdown to see checkboxes }); // Edit mode: Shows `- [ ]` and `- [x]` syntax (preserves alignment) // Preview mode: Renders actual checkbox inputs ``` ### Syntax Highlighting ```javascript import { codeToHtml } from 'shiki'; // Global highlighter (all instances) OverType.setCodeHighlighter((code, lang) => codeToHtml(code, { lang, theme: 'nord' }) ); // Per-instance override const [editor] = new OverType('#editor', { codeHighlighter: (code, lang) => myHighlighter(code, lang) }); ``` See [docs/SYNTAX_HIGHLIGHTING.md](docs/SYNTAX_HIGHLIGHTING.md) for complete guide. ### Keyboard Shortcuts The toolbar and keyboard shortcuts work together seamlessly: - **Cmd/Ctrl + B** - Bold - **Cmd/Ctrl + I** - Italic - **Cmd/Ctrl + K** - Insert link - **Cmd/Ctrl + Shift + 7** - Numbered list - **Cmd/Ctrl + Shift + 8** - Bullet list All shortcuts preserve text selection, allowing you to apply multiple formats quickly. ### Multiple Editors ```javascript // Initialize multiple editors at once const editors = OverType.init('.markdown-editor', { theme: 'cave', fontSize: '16px' }); // Each editor is independent editors.forEach((editor, index) => { editor.setValue(`# Editor ${index + 1}`); }); ``` ### Form Integration ```javascript // Use with form validation const [editor] = new OverType('#message', { placeholder: 'Your message...', textareaProps: { required: true, maxLength: 500, name: 'message' } }); // The textarea will work with native form validation document.querySelector('form').addEventListener('submit', (e) => { const content = editor.getValue(); // Form will automatically validate required field }); ``` ### Custom Theme ```javascript const [editor] = new OverType('#editor', { theme: { name: 'my-theme', colors: { bgPrimary: '#faf0ca', bgSecondary: '#ffffff', text: '#0d3b66', h1: '#f95738', h2: '#ee964b', h3: '#3d8a51', strong: '#ee964b', em: '#f95738', link: '#0d3b66', code: '#0d3b66', codeBg: 'rgba(244, 211, 94, 0.2)', blockquote: '#5a7a9b', hr: '#5a7a9b', syntaxMarker: 'rgba(13, 59, 102, 0.52)', cursor: '#f95738', selection: 'rgba(244, 211, 94, 0.4)' } } }); ``` ### Preview & HTML Export Generate HTML previews or export the rendered content: ```javascript const [editor] = new OverType('#editor', { value: '# Title\n\n**Bold** text with [links](https://example.com)' }); // Get the raw markdown const markdown = editor.getValue(); // Returns: "# Title\n\n**Bold** text with [links](https://example.com)" // Get rendered HTML with syntax markers (for debugging/inspection) const html = editor.getRenderedHTML(); // Returns HTML with elements visible // Get clean HTML for export (no OverType-specific markup) const cleanHTML = editor.getRenderedHTML({ cleanHTML: true }); // Returns clean HTML suitable for saving/exporting // Convenience method for clean HTML const exportHTML = editor.getCleanHTML(); // Same as getRenderedHTML({ cleanHTML: true }) // Get the current preview element's HTML (actual DOM content) const previewHTML = editor.getPreviewHTML(); // Returns exactly what's shown in the editor's preview layer // Example: Export clean HTML to server const htmlToSave = editor.getCleanHTML(); // No syntax markers // Example: Clone exact preview appearance document.getElementById('clone').innerHTML = editor.getPreviewHTML(); ``` ### Stats Bar Enable a built-in stats bar that shows character, word, and line counts: ```javascript // Enable stats bar on initialization const [editor] = new OverType('#editor', { showStats: true }); // Show or hide stats bar dynamically editor.showStats(true); // Show editor.showStats(false); // Hide // Custom stats format const [editor] = new OverType('#editor', { showStats: true, statsFormatter: (stats) => { // stats object contains: { chars, words, lines, line, column } return `${stats.chars} characters ${stats.words} words ${stats.lines} lines Line ${stats.line}, Col ${stats.column}`; } }); ``` The stats bar automatically adapts to your theme colors using CSS variables. ### React Component ```jsx function MarkdownEditor({ value, onChange }) { const ref = useRef(); const editorRef = useRef(); useEffect(() => { const [instance] = OverType.init(ref.current, { value, onChange }); editorRef.current = instance; return () => editorRef.current?.destroy(); }, []); useEffect(() => { if (editorRef.current && value !== editorRef.current.getValue()) { editorRef.current.setValue(value); } }, [value]); return ; } ``` ### Standalone Parser Import and use the markdown parser without the full editor for server-side rendering, static site generation, or browser extensions: ```javascript // Import just the parser import { MarkdownParser } from 'overtype/parser'; // Parse markdown to HTML const html = MarkdownParser.parse('# Hello World\n\nThis is **bold** text.'); // Use in Node.js for SSR app.get('/preview', (req, res) => { const markdown = req.body.content; const html = MarkdownParser.parse(markdown); res.json({ html }); }); // Use in static site generator const posts = markdownFiles.map(file => ({ content: MarkdownParser.parse(file.content), metadata: file.metadata })); // Use in browser extension chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.markdown) { const html = MarkdownParser.parse(request.markdown); sendResponse({ html }); } }); ``` **Benefits:** - No DOM dependencies required - Smaller bundle when you only need parsing - Same markdown rendering as the editor - Perfect for headless/server-side use cases ## API ### Constructor ```javascript new OverType(target, options) ``` **Parameters:** - `target` - Selector string, Element, NodeList, or Array of elements - `options` - Configuration object (see below) **Returns:** Array of OverType instances (always an array, even for single element) ### Options ```javascript { // Typography fontSize: '14px', lineHeight: 1.6, fontFamily: 'monospace', padding: '16px', // Theme - 'solar', 'cave', or custom theme object theme: 'solar', // Custom colors (override theme colors) colors: { h1: '#e63946', h2: '#457b9d', // ... any color variable }, // Mobile styles (applied at <= 640px) mobile: { fontSize: '16px', padding: '12px', lineHeight: 1.5 }, // Behavior autofocus: false, placeholder: 'Start typing...', value: '', // Auto-resize autoResize: false, // Auto-expand height with content minHeight: '100px', // Minimum height when autoResize is enabled maxHeight: null, // Maximum height (null = unlimited) // Native textarea properties textareaProps: { required: true, maxLength: 500, name: 'content', // Any HTML textarea attribute }, // Toolbar toolbar: false, // Enable/disable toolbar toolbarButtons: [], // Custom button array (v2.0) // Defaults to all built-in buttons when toolbar: true // Syntax highlighting codeHighlighter: null, // Function: (code, lang) => html // Overrides global OverType.setCodeHighlighter() // Smart lists smartLists: true, // Enable GitHub-style list continuation on Enter // Stats bar showStats: false, // Enable/disable stats bar statsFormatter: (stats) => { // Custom stats format return `${stats.chars} chars | ${stats.words} words`; }, // Callbacks onChange: (value, instance) => {}, onKeydown: (event, instance) => {} } ``` ### Instance Methods ```javascript // Get current markdown content editor.getValue() // Set markdown content editor.setValue(markdown) // Get rendered HTML of the current content editor.getRenderedHTML() // With syntax markers (for debugging) editor.getRenderedHTML({ cleanHTML: true }) // Clean HTML without OverType markup editor.getCleanHTML() // Alias for getRenderedHTML({ cleanHTML: true }) // Get the current preview element's HTML editor.getPreviewHTML() // Actual DOM content from preview layer // Change theme (instance-specific, overrides global theme) editor.setTheme('cave') // Built-in theme name editor.setTheme(customThemeObject) // Custom theme // Set code highlighter (instance-specific) editor.setCodeHighlighter((code, lang) => highlightedHTML) editor.setCodeHighlighter(null) // Disable for this instance // View modes editor.showNormalEditMode() // Switch to normal edit mode (default) editor.showPlainTextarea() // Switch to plain textarea mode editor.showPreviewMode() // Switch to preview mode // Focus/blur editor.focus() editor.blur() // Show or hide stats bar editor.showStats(true) // Show stats editor.showStats(false) // Hide stats // Check if initialized editor.isInitialized() // Re-initialize with new options editor.reinit(options) // Destroy the editor editor.destroy() ``` ### Static Methods ```javascript // Set global theme (affects all instances without instance themes) OverType.setTheme('cave') // Built-in theme OverType.setTheme(customTheme) // Custom theme object OverType.setTheme('solar', { h1: '#custom' }) // Override specific colors // Set global code highlighter (affects all instances without instance highlighter) OverType.setCodeHighlighter((code, lang) => highlightedHTML) OverType.setCodeHighlighter(null) // Disable global highlighting // Extend parsing with custom syntax (footnotes, directives, etc.) // IMPORTANT: You must maintain 1-to-1 character alignment - wrap text, don't change it // See: https://panphora.github.io/overtype/examples/custom-syntax.html OverType.setCustomSyntax((html) => { return html.replace(/\[\^(\w+)\]/g, '$&'); }) // Note: Instance methods override global settings // Initialize multiple editors (same as constructor) OverType.init(target, options) // Initialize with per-element config via data-ot-* attributes // Uses kebab-case: data-ot-show-stats="true" โ showStats: true OverType.initFromData('.editor', { /* defaults */ }) // Get instance from element OverType.getInstance(element) // Destroy all instances OverType.destroyAll() // Access themes OverType.themes.solar OverType.themes.cave ``` ## Keyboard Shortcuts | Shortcut | Action | |----------|--------| | Cmd/Ctrl + B | Toggle bold | | Cmd/Ctrl + I | Toggle italic | | Cmd/Ctrl + K | Wrap in code | | Cmd/Ctrl + Shift + K | Insert link | | Cmd/Ctrl + Shift + 7 | Toggle numbered list | | Cmd/Ctrl + Shift + 8 | Toggle bullet list | ## Supported Markdown - **Headers** - `# H1`, `## H2`, `### H3` - **Bold** - `**text**` or `__text__` - **Italic** - `*text*` or `_text_` - **Strikethrough** - `~~text~~` or `~text~` (GFM) - **Code** - `` `inline code` `` - **Code blocks** - ` ```language ` - **Links** - `[text](url)` - **Lists** - `- item`, `* item`, `1. item` - **Task lists** - `- [ ] todo`, `- [x] done` (GFM, renders in preview mode) - **Blockquotes** - `> quote` - **Horizontal rule** - `---`, `***`, or `___` **Note:** Syntax remains visible in edit mode (e.g., `**bold**` shows markers). Use preview mode for full rendering. ## Web Component OverType provides a fully-featured native Web Component `--- Built with the radical idea that sometimes dumb ideas work. **Ready for another radical idea?** Let's remove every layer of the web application stack. ### Hyperclay [Hyperclay](https://hyperclay.com) by @panphora allows you to make a web app in a single, portable, self-updating, vanilla HTML file. No frameworks, no build steps, no deployment pipelines. Just a single HTML file that persists its own state and can be edited live. Think of it as a Google Document for interactive code, where the UI, logic, and data all live in one self-modifying file. Share apps instantly, edit them directly, use them offline.