{"_id":"@aminulidev/tinytext","_rev":"3-6dc3c29c4d4d34795d4b33ce838b2129","name":"@aminulidev/tinytext","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"@aminulidev/tinytext","version":"1.0.0","keywords":["editor","rich-text","wysiwyg","contenteditable","typescript"],"author":{"name":"Antigravity"},"license":"MIT","_id":"@aminulidev/tinytext@1.0.0","maintainers":[{"name":"aminulidev","email":"aminulds61@gmail.com"}],"dist":{"shasum":"8509c72f305f94853450348b68d462c52da85eb3","tarball":"https://registry.npmjs.org/@aminulidev/tinytext/-/tinytext-1.0.0.tgz","fileCount":27,"integrity":"sha512-QprS9TEz6ik2k1GNBoAh/QIzaHcO5p0paOS//8ffOsfHtYPbZ1/YxQFZkIn0ocx8013lJvLY8X0ZvSMq8YUrYQ==","signatures":[{"sig":"MEUCIQD0PgixvvA0Iq9XAC7yyECAR3QU0FshW8eE5VNg6cwNfwIgaNx2Hw+DQHo9ytvj5/EIx65W/Su5BXuETNsxYn7Xb3w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":446141},"main":"dist/tinytext.cjs.js","types":"dist/types/index.d.ts","module":"dist/tinytext.esm.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/tinytext.esm.js","require":"./dist/tinytext.cjs.js"},"./dist/tinytext.css":"./dist/tinytext.css"},"gitHead":"39366067b122965aa9a9033bc370897e16b97289","scripts":{"dev":"rollup -c rollup.config.js -w","lint":"eslint src --ext .ts,.tsx","test":"jest","build":"rollup -c rollup.config.js","build:types":"tsc --emitDeclarationOnly --outDir dist/types","prepublishOnly":"npm run build"},"_npmUser":{"name":"aminulidev","email":"aminulds61@gmail.com"},"_npmVersion":"11.6.2","description":"A modern, lightweight, feature-rich WYSIWYG rich text editor","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.11.1","_hasShrinkwrap":false,"devDependencies":{"tslib":"^2.6.0","rollup":"^3.29.4","typescript":"^5.0.0","@types/node":"^20.0.0","rollup-plugin-postcss":"^4.0.2","@rollup/plugin-commonjs":"^25.0.0","@rollup/plugin-typescript":"^11.0.0","@rollup/plugin-node-resolve":"^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/tinytext_1.0.0_1771689687698_0.10926187246676644","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@aminulidev/tinytext","version":"1.0.1","keywords":["editor","rich-text","wysiwyg","contenteditable","typescript"],"author":{"name":"aminulidev"},"license":"MIT","_id":"@aminulidev/tinytext@1.0.1","maintainers":[{"name":"aminulidev","email":"aminulds61@gmail.com"}],"dist":{"shasum":"c1eae00c0e76c9506d357e03bbbf12c54ff30011","tarball":"https://registry.npmjs.org/@aminulidev/tinytext/-/tinytext-1.0.1.tgz","fileCount":27,"integrity":"sha512-AqFlfBMK0ycPIUqJkmNL3mlG69CBERu6bAkF1QVRW0Xkd0gLsOMV5h/QKXiETlbcWLboLdcTIQECb68M/NrsMg==","signatures":[{"sig":"MEYCIQDZy0nEcA2NteDV7P1D6Fy1p6mkfy5MoTzVz+LHuDTeywIhAMf+RIXcLBNGEn1vOkW/U5a5OwRzcTH/xchfmrsaAy9b","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":446565},"main":"dist/tinytext.cjs.js","type":"module","types":"dist/types/index.d.ts","module":"dist/tinytext.esm.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/tinytext.esm.js","require":"./dist/tinytext.cjs.js"},"./dist/tinytext.css":"./dist/tinytext.css"},"gitHead":"39366067b122965aa9a9033bc370897e16b97289","scripts":{"dev":"rollup -c rollup.config.js -w","lint":"eslint src --ext .ts,.tsx","test":"jest","build":"rollup -c rollup.config.js","build:types":"tsc --emitDeclarationOnly --outDir dist/types","prepublishOnly":"npm run build"},"_npmUser":{"name":"aminulidev","email":"aminulds61@gmail.com"},"_npmVersion":"11.6.2","description":"A modern, lightweight, feature-rich WYSIWYG rich text editor","directories":{},"sideEffects":["*.css"],"_nodeVersion":"24.11.1","_hasShrinkwrap":false,"devDependencies":{"tslib":"^2.6.0","rollup":"^3.29.4","typescript":"^5.0.0","@types/node":"^20.0.0","rollup-plugin-postcss":"^4.0.2","@rollup/plugin-commonjs":"^25.0.0","@rollup/plugin-typescript":"^11.0.0","@rollup/plugin-node-resolve":"^15.0.0"},"_npmOperationalInternal":{"tmp":"tmp/tinytext_1.0.1_1771695388811_0.6414210061462484","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@aminulidev/tinytext","version":"1.0.2","type":"module","description":"A modern, lightweight, feature-rich WYSIWYG rich text editor","author":{"name":"aminulidev"},"license":"MIT","keywords":["editor","rich-text","wysiwyg","contenteditable","typescript"],"main":"dist/tinytext.cjs.js","module":"dist/tinytext.esm.js","types":"dist/types/index.d.ts","exports":{".":{"import":"./dist/tinytext.esm.js","require":"./dist/tinytext.cjs.js","types":"./dist/types/index.d.ts"},"./dist/tinytext.css":"./dist/tinytext.css"},"sideEffects":["*.css"],"scripts":{"dev":"rollup -c rollup.config.js -w","serve":"sirv . --dev --port 3001 --host","demo":"npm run serve & npm run dev","build":"rollup -c rollup.config.js","build:types":"tsc --emitDeclarationOnly --outDir dist/types","lint":"eslint src --ext .ts,.tsx","test":"jest","prepublishOnly":"npm run build"},"devDependencies":{"@rollup/plugin-commonjs":"^25.0.0","@rollup/plugin-node-resolve":"^15.0.0","@rollup/plugin-typescript":"^11.0.0","@types/node":"^20.0.0","rollup":"^3.29.4","rollup-plugin-postcss":"^4.0.2","sirv-cli":"^3.0.1","tslib":"^2.6.0","typescript":"^5.0.0"},"gitHead":"f25e97309ac1391c5288b821ae74fcedf33077c3","_id":"@aminulidev/tinytext@1.0.2","_nodeVersion":"24.11.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-unRpazh+qVLGKu2eF+dynSH0EfJ6tieYIkCHwhS14cnbXmSS2vHrMAXtVKdC4aENeY+FLIzvCP13QKqjUmK51g==","shasum":"4494efa9d8eae9c47269abb048b5e19603666f44","tarball":"https://registry.npmjs.org/@aminulidev/tinytext/-/tinytext-1.0.2.tgz","fileCount":28,"unpackedSize":486341,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDbeChhcMDNMTXeOFBfQnchpelnaqM/z5M1DFpi7BxgzQIgauuKyXaHIFB3JUXrIiboMyxM6qGWZZRG+iXJY9+WiKk="}]},"_npmUser":{"name":"aminulidev","email":"aminulds61@gmail.com"},"directories":{},"maintainers":[{"name":"aminulidev","email":"aminulds61@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/tinytext_1.0.2_1771861662801_0.17876703520239445"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-21T16:01:27.549Z","modified":"2026-02-23T15:47:43.085Z","1.0.0":"2026-02-21T16:01:27.914Z","1.0.1":"2026-02-21T17:36:28.986Z","1.0.2":"2026-02-23T15:47:42.980Z"},"author":{"name":"aminulidev"},"license":"MIT","keywords":["editor","rich-text","wysiwyg","contenteditable","typescript"],"description":"A modern, lightweight, feature-rich WYSIWYG rich text editor","maintainers":[{"name":"aminulidev","email":"aminulds61@gmail.com"}],"readme":"# TinyText Editor\r\n\r\n<div align=\"center\">\r\n  <h3>A modern, lightweight, feature-rich WYSIWYG rich text editor</h3>\r\n  <p>TypeScript · Vanilla JS · ContentEditable · Plugin Architecture · Zero Dependencies</p>\r\n\r\n  [![npm version](https://img.shields.io/npm/v/@aminulidev/tinytext.svg)](https://www.npmjs.com/package/@aminulidev/tinytext)\r\n  [![License: MIT](https://img.shields.io/badge/License-MIT-indigo.svg)](https://opensource.org/licenses/MIT)\r\n  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0-blue.svg)](https://www.typescriptlang.org/)\r\n</div>\r\n\r\n---\r\n\r\n## ✨ Features\r\n\r\n### Core Formatting\r\n- **Bold**, *Italic*, Underline, ~~Strikethrough~~\r\n- Headings H1–H6\r\n- Text alignment (left, center, right, justify)\r\n- Lists (ordered & unordered)\r\n- Blockquote\r\n- Code block with syntax styling\r\n- Text & highlight color pickers\r\n\r\n### Rich Content\r\n- 🔗 Link insert/edit with target options\r\n- 🖼 Image upload (URL or base64/file upload with drag & drop)\r\n- 📊 Table support with context menu (insert rows/cols, delete)\r\n\r\n### Editor Capabilities\r\n- ↩ Undo / ↪ Redo with debounced history\r\n- ⌨️ Full keyboard shortcuts\r\n- 📝 Placeholder support\r\n- 🔢 Character & word counter\r\n- 💾 Auto-save to localStorage\r\n- 🧹 HTML sanitization\r\n- 📖 Markdown import/export (via plugin)\r\n- 🔒 Read-only mode\r\n- 📱 Mobile responsive\r\n\r\n### Developer Experience\r\n- 🧩 Plugin system (`registerPlugin` API)\r\n- 🎨 Custom toolbar configuration\r\n- 🌙 Dark mode (manual or `'auto'`)\r\n- 🎭 CSS variable theming\r\n- 📦 ESM + CJS + TypeScript types\r\n- 🌲 Tree-shakable\r\n\r\n---\r\n\r\n## 📦 Installation\r\n\r\n```bash\r\nnpm install @aminulidev/tinytext\r\n```\r\n\r\n---\r\n\r\n## 🚀 Quick Start\r\n\r\n### HTML\r\n\r\n```html\r\n<link rel=\"stylesheet\" href=\"node_modules/@aminulidev/tinytext/dist/tinytext.css\">\r\n<div id=\"editor\"></div>\r\n```\r\n\r\n### JavaScript / TypeScript\r\n\r\n```ts\r\nimport { TinyTextEditor } from '@aminulidev/tinytext';\r\nimport '@aminulidev/tinytext/dist/tinytext.css';\r\n\r\nconst editor = new TinyTextEditor({\r\n  selector: '#editor',\r\n  toolbar: 'full',\r\n  placeholder: 'Start writing...',\r\n});\r\n\r\n// Get HTML output\r\nconst html = editor.getHTML();\r\n\r\n// Set HTML content\r\neditor.setHTML('<p>Hello, <strong>world</strong>!</p>');\r\n```\r\n\r\n### Or use the factory function\r\n\r\n```ts\r\nimport { createEditor } from '@aminulidev/tinytext';\r\n\r\nconst editor = createEditor({ selector: '#editor' });\r\n```\r\n\r\n---\r\n\r\n## ⚙️ Configuration\r\n\r\n```ts\r\nconst editor = new TinyTextEditor({\r\n  // Required\r\n  selector: '#editor',           // CSS selector or HTMLElement\r\n\r\n  // Toolbar\r\n  toolbar: 'full',               // 'full' | 'minimal' | 'none' | ToolbarItem[]\r\n\r\n  // Content\r\n  content: '<p>Initial content</p>',\r\n  placeholder: 'Start writing...',\r\n\r\n  // Behavior\r\n  readOnly: false,\r\n  sanitize: true,                // Sanitize HTML input/output\r\n  markdownMode: false,\r\n\r\n  // Appearance\r\n  darkMode: 'auto',              // true | false | 'auto'\r\n  theme: 'default',\r\n  minHeight: '200px',\r\n  maxHeight: '600px',\r\n\r\n  // Features\r\n  charCounter: true,             // Show word/char count\r\n  maxLength: 0,                  // 0 = unlimited\r\n  autoSave: {\r\n    interval: 30000,             // ms\r\n    key: 'my_editor_save',       // localStorage key\r\n  },\r\n\r\n  // Plugins\r\n  plugins: [TablePlugin, MarkdownPlugin],\r\n\r\n  // Events\r\n  onChange: (html, text) => console.log('Changed:', html),\r\n  onFocus: (e) => console.log('Focused'),\r\n  onBlur: (e) => console.log('Blurred'),\r\n  onReady: (editor) => console.log('Ready!', editor),\r\n});\r\n```\r\n\r\n---\r\n\r\n## 🛠 Custom Toolbar\r\n\r\n```ts\r\nimport { TinyTextEditor } from '@aminulidev/tinytext';\r\n\r\nconst editor = new TinyTextEditor({\r\n  selector: '#editor',\r\n  toolbar: [\r\n    'bold', 'italic', 'underline', 'strikethrough', 'separator',\r\n    'h1', 'h2', 'h3', 'separator',\r\n    'align-left', 'align-center', 'align-right', 'separator',\r\n    'unordered-list', 'ordered-list', 'blockquote', 'separator',\r\n    'link', 'image', 'table', 'separator',\r\n    'undo', 'redo',\r\n  ],\r\n});\r\n```\r\n\r\n**All available toolbar items:**  \r\n`bold` `italic` `underline` `strikethrough` `h1`–`h6` `paragraph`  \r\n`align-left` `align-center` `align-right` `align-justify`  \r\n`ordered-list` `unordered-list` `blockquote` `code-block`  \r\n`link` `image` `table` `undo` `redo` `forecolor` `hilitecolor` `separator`\r\n\r\n---\r\n\r\n## 🧩 Plugin System\r\n\r\n```ts\r\nimport type { PluginDefinition } from '@aminulidev/tinytext';\r\n\r\nconst MyPlugin: PluginDefinition = {\r\n  name: 'my-plugin',\r\n  version: '1.0.0',\r\n\r\n  init(ctx) {\r\n    // ctx.editor   — Editor instance\r\n    // ctx.toolbar  — Toolbar API\r\n    // ctx.events   — EventBus API\r\n    // ctx.commands — Command API\r\n\r\n    // Register a custom command\r\n    ctx.commands.register({\r\n      id: 'my-command',\r\n      execute: () => console.log('Executed!'),\r\n      isActive: () => false,\r\n      isEnabled: () => true,\r\n    });\r\n\r\n    // Add a toolbar button\r\n    ctx.toolbar.addButton('my-btn', {\r\n      icon: '<svg>...</svg>',\r\n      label: 'My Button',\r\n      command: 'my-command',\r\n    });\r\n\r\n    // Listen to events\r\n    ctx.events.on('change', ({ html, text }) => {\r\n      console.log('Content changed:', text.length, 'chars');\r\n    });\r\n\r\n    // Register a keyboard shortcut\r\n    ctx.editor.addShortcut('ctrl+shift+m', () => {\r\n      ctx.editor.execCommand('my-command');\r\n    });\r\n  },\r\n\r\n  destroy() {\r\n    // Cleanup\r\n  },\r\n};\r\n\r\n// Use it\r\nconst editor = new TinyTextEditor({\r\n  selector: '#editor',\r\n  plugins: [MyPlugin],\r\n});\r\n```\r\n\r\n---\r\n\r\n## 📡 Event System\r\n\r\n```ts\r\neditor.on('change', ({ html, text }) => {\r\n  console.log('New content:', html);\r\n});\r\n\r\neditor.on('focus', ({ event }) => {});\r\neditor.on('blur',  ({ event }) => {});\r\neditor.on('selection-change', ({ selection }) => {});\r\neditor.on('history:undo', () => {});\r\neditor.on('history:redo', () => {});\r\neditor.on('autosave', ({ html }) => {});\r\neditor.on('ready', ({ editor }) => {});\r\neditor.on('plugin:registered', ({ name }) => {});\r\n\r\n// Remove listener\r\neditor.off('change', myHandler);\r\n```\r\n\r\n---\r\n\r\n## 🔌 Built-in Plugins\r\n\r\n### TablePlugin\r\nAdds right-click context menu to tables:  \r\nInsert/delete rows and columns, Tab navigation, keyboard shortcuts.\r\n\r\n```ts\r\nimport { TinyTextEditor, TablePlugin } from '@aminulidev/tinytext';\r\n\r\nconst editor = new TinyTextEditor({\r\n  selector: '#editor',\r\n  plugins: [TablePlugin],\r\n});\r\n```\r\n\r\n### MarkdownPlugin\r\n- Live Markdown shortcut conversion (type `## ` for headings, `` ``` `` for code blocks, etc.)\r\n- Export HTML as `.md` file\r\n- Import `.md` files\r\n\r\n```ts\r\nimport { TinyTextEditor, MarkdownPlugin } from '@aminulidev/tinytext';\r\n\r\nconst editor = new TinyTextEditor({\r\n  selector: '#editor',\r\n  plugins: [MarkdownPlugin],\r\n});\r\n```\r\n\r\n---\r\n\r\n## 🎨 Theming\r\n\r\nTinyText uses CSS custom properties — override any token:\r\n\r\n```css\r\n#my-editor .tt-editor {\r\n  --tt-accent: #10b981;           /* Green theme */\r\n  --tt-border-focus: #10b981;\r\n  --tt-btn-active-bg: #10b981;\r\n  --tt-blockquote-border: #10b981;\r\n  --tt-font: 'Georgia', serif;\r\n  --tt-radius: 4px;               /* Sharper corners */\r\n}\r\n```\r\n\r\n**Dark mode** is applied by adding `data-theme=\"dark\"` to the container:\r\n\r\n```ts\r\neditor.enableDarkMode();   // Enable\r\neditor.disableDarkMode();  // Disable\r\neditor.toggleDarkMode();   // Toggle\r\n// Or: darkMode: 'auto' — respects prefers-color-scheme\r\n```\r\n\r\n---\r\n\r\n## ⌨️ Keyboard Shortcuts\r\n\r\n| Shortcut             | Action              |\r\n|----------------------|---------------------|\r\n| `Ctrl+B`             | Bold                |\r\n| `Ctrl+I`             | Italic              |\r\n| `Ctrl+U`             | Underline           |\r\n| `Ctrl+Shift+S`       | Strikethrough       |\r\n| `Ctrl+Z`             | Undo                |\r\n| `Ctrl+Y` / `Ctrl+Shift+Z` | Redo         |\r\n| `Ctrl+Shift+L`       | Align Left          |\r\n| `Ctrl+Shift+E`       | Align Center        |\r\n| `Ctrl+Shift+R`       | Align Right         |\r\n| `Ctrl+Shift+J`       | Justify             |\r\n| `` Ctrl+` ``         | Code Block          |\r\n| `Ctrl+Shift+.`       | Blockquote          |\r\n| `Ctrl+Shift+7`       | Ordered List        |\r\n| `Ctrl+Shift+8`       | Unordered List      |\r\n| `Ctrl+A`             | Select All          |\r\n\r\n---\r\n\r\n## 📐 Project Structure\r\n\r\n```\r\ntinytext/\r\n├── src/\r\n│   ├── core/\r\n│   │   ├── types.ts             # All TypeScript types\r\n│   │   ├── Editor.ts            # Core Editor class\r\n│   │   ├── EventBus.ts          # Type-safe event system\r\n│   │   ├── SelectionManager.ts  # Selection API wrapper\r\n│   │   ├── CommandManager.ts    # Command registry\r\n│   │   ├── HistoryManager.ts    # Undo/redo stack\r\n│   │   ├── PluginManager.ts     # Plugin lifecycle\r\n│   │   ├── SchemaValidator.ts   # HTML sanitizer\r\n│   │   └── commands.ts          # Built-in command registrations\r\n│   ├── ui/\r\n│   │   ├── Toolbar.ts           # Toolbar renderer + icons\r\n│   │   └── modals/\r\n│   │       ├── BaseModal.ts     # Modal base class\r\n│   │       ├── LinkModal.ts     # Link insert/edit modal\r\n│   │       ├── ImageModal.ts    # Image modal (URL + upload)\r\n│   │       └── TableModal.ts    # Table insert modal\r\n│   ├── plugins/\r\n│   │   ├── TablePlugin.ts       # Table context menu + tab nav\r\n│   │   └── MarkdownPlugin.ts    # Markdown mode + import/export\r\n│   ├── themes/\r\n│   │   └── tinytext.css         # Complete editor stylesheet\r\n│   ├── utils/\r\n│   │   ├── dom.ts               # DOM helpers\r\n│   │   └── markdown.ts          # MD ↔ HTML converter\r\n│   └── index.ts                 # Package entry point\r\n├── examples/\r\n│   └── WordCountPlugin.ts       # Example custom plugin\r\n├── demo/\r\n│   └── index.html               # Interactive demo page\r\n├── rollup.config.js\r\n├── tsconfig.json\r\n├── package.json\r\n└── README.md\r\n```\r\n\r\n---\r\n\r\n## 🔨 Building from Source\r\n\r\n```bash\r\n# Install dependencies\r\nnpm install\r\n\r\n# Development (watch mode)\r\nnpm run dev\r\n\r\n# Production build\r\nnpm run build\r\n\r\n# Generate type declarations only\r\nnpm run build:types\r\n```\r\n\r\n---\r\n\r\n## 📤 Publishing to npm\r\n\r\n```bash\r\n# 1. Build the package\r\nnpm run build\r\n\r\n# 2. Check what will be published\r\nnpm pack --dry-run\r\n\r\n# 3. Login to npm\r\nnpm login\r\n\r\n# 4. Publish\r\nnpm publish --access public\r\n```\r\n\r\n---\r\n\r\n## 📄 License\r\n\r\nMIT © [aminulidev](https://www.npmjs.com/~aminulidev)\r\n","readmeFilename":"README.md"}