<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to Plugin API</title><link>https://sourceforge.net/p/neiki-editor/wiki/Plugin%2520API/</link><description>Recent changes to Plugin API</description><atom:link href="https://sourceforge.net/p/neiki-editor/wiki/Plugin%20API/feed" rel="self"/><language>en</language><lastBuildDate>Tue, 09 Jun 2026 08:15:04 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/neiki-editor/wiki/Plugin%20API/feed" rel="self" type="application/rss+xml"/><item><title>Plugin API modified by neikiri</title><link>https://sourceforge.net/p/neiki-editor/wiki/Plugin%2520API/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v4
+++ v5
@@ -251,13 +251,13 @@

 | | |
 |---|---|
-| [⚙️ Configuration](Configuration) | Editor configuration &amp;amp; toolbar array |
-| [🔧 Toolbar Reference](Toolbar-Reference) | Built-in toolbar button identifiers |
-| [📋 API Reference](API-Reference) | `insertHTML`, `setContent`, `getContent` and all other methods |
-| [🧩 Advanced Features](Advanced-Features) | Tables, images, themes, autosave |
+| [⚙️ Configuration](/p/neiki-editor/wiki/Configuration) | Editor configuration &amp;amp; toolbar array |
+| [🔧 Toolbar Reference](/p/neiki-editor/wiki/Toolbar%20Reference) | Built-in toolbar button identifiers |
+| [📋 API Reference](/p/neiki-editor/wiki/API%20Reference) | `insertHTML`, `setContent`, `getContent` and all other methods |
+| [🧩 Advanced Features](/p/neiki-editor/wiki/Advanced%20Features) | Tables, images, themes, autosave |

 ---

 &lt;div align="center"&gt;

-  &lt;sub&gt;&lt;a href="./Home"&gt;← Back to Home&lt;/a&gt;&lt;/sub&gt;
+  &lt;sub&gt;&lt;a href="/p/neiki-editor/wiki/Home"&gt;← Back to Home&lt;/a&gt;&lt;/sub&gt;
 &lt;/div&gt;
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">neikiri</dc:creator><pubDate>Tue, 09 Jun 2026 08:15:04 -0000</pubDate><guid>https://sourceforge.neta0be84223fadda3561f1da58aebbc1ec0bb40bed</guid></item><item><title>Plugin API modified by neikiri</title><link>https://sourceforge.net/p/neiki-editor/wiki/Plugin%2520API/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v3
+++ v4
@@ -1,19 +1,19 @@
 # 🔌 Plugin API

-Extend Neiki's Editor with custom functionality using the Plugin API. Plugins can add toolbar buttons, hook into initialization, and interact with the editor programmatically.
+&amp;gt; Extend Neiki's Editor with custom toolbar buttons, init hooks, and programmatic actions.

 ---

 ## 🧩 Overview

-Plugins are registered **globally** before or after editor initialization. Each plugin can optionally:
-
-- Add a **toolbar button** with a custom icon
+Plugins are registered **globally** via `NeikiEditor.registerPlugin()` before or after editor initialization. A plugin can:
+
+- Add a **toolbar button** with a custom SVG icon

 - Run an **action** when the button is clicked
-- Run an **init** function when the editor starts
+- Run an **init** function when the editor starts up

 &amp;gt; [!NOTE]
-&amp;gt; Plugins are registered globally via `NeikiEditor.registerPlugin()` and are available to **all** editor instances on the page.
+&amp;gt; Plugins are global — they are available to **all** editor instances on the page.

 ---

@@ -21,15 +21,22 @@

     :::javascript
     NeikiEditor.registerPlugin({

-        name: 'my-plugin',
-        icon: '&lt;svg viewBox="0 0 24 24"&gt;...&lt;/svg&gt;',
-        tooltip: 'My Custom Action',
+        name: 'my-plugin',            // unique identifier (required)
+        icon: '&lt;svg viewBox="0 0 24 24"&gt;...&lt;/svg&gt;',  // toolbar icon SVG
+        tooltip: 'My Custom Action',  // tooltip on hover
         action: function(editor) {
             // Called when toolbar button is clicked
         },
         init: function(editor) {
-            // Called once when editor initializes
-        }
+            // Called once when the editor initializes
+        }
+    });
+
+Then include it in the `toolbar` config:
+
+    :::javascript
+    new NeikiEditor('#editor', {
+        toolbar: ['bold', 'italic', '|', 'my-plugin', '|', 'moreMenu']
     });

 ---
@@ -37,15 +44,15 @@
 ## 📊 Plugin Properties

 | Property | Type | Required | Description |
-|----------|------|----------|-------------|
-| `name` | `string` | ✅ | Unique identifier for the plugin |
-| `icon` | `string` | ❌ | SVG icon markup for the toolbar button |
-| `tooltip` | `string` | ❌ | Tooltip text shown on hover |
-| `action` | `function(editor)` | ❌ | Handler called on toolbar button click |
-| `init` | `function(editor)` | ❌ | Handler called once during editor initialization |
+|---|---|---|---|
+| `name` | `string` | ✅ | Unique identifier. Referenced in the `toolbar` array. |
+| `icon` | `string` | ❌ | SVG markup for the toolbar button |
+| `tooltip` | `string` | ❌ | Hover tooltip text |
+| `action` | `function(editor)` | ❌ | Handler called when the toolbar button is clicked |
+| `init` | `function(editor)` | ❌ | Handler called once when the editor initializes |

 &amp;gt; [!IMPORTANT]
-&amp;gt; The `name` must be unique across all registered plugins. If you register two plugins with the same name, the second will overwrite the first.
+&amp;gt; Plugin names must be **unique**. Registering a second plugin with the same name overwrites the first.

 ---

@@ -53,7 +60,7 @@

 ### Word Counter Alert

-A simple plugin that shows a word count alert:
+Show a word and character count dialog:

     :::javascript
     NeikiEditor.registerPlugin({
@@ -61,7 +68,7 @@
         icon: '&lt;svg viewBox="0 0 24 24"&gt;&lt;path d="M3 18h12v-2H3v2zM3 6v2h18V6H3zm0 7h18v-2H3v2z"&gt;&lt;/path&gt;&lt;/svg&gt;',
         tooltip: 'Show Word Count',
         action: function(editor) {

-            const text = editor.getContent().replace(/&amp;lt;[^&amp;gt;]*&amp;gt;/g, '');
+            const text = editor.getText();
             const words = text.trim().split(/\s+/).filter(Boolean).length;
             const chars = text.length;
             alert(`Words: ${words}\nCharacters: ${chars}`);
@@ -72,7 +79,7 @@

 ### Insert Timestamp

-Insert the current date and time at the cursor position:
+Insert current date/time at the cursor position:

     :::javascript
     NeikiEditor.registerPlugin({
@@ -88,9 +95,42 @@

 ---

-### Auto-Capitalize Headings
-
-A plugin that automatically capitalizes the first letter of every heading on init:
+### Insert Styled Divider
+

+    :::javascript
+    NeikiEditor.registerPlugin({
+        name: 'styled-divider',
+        icon: '&lt;svg viewBox="0 0 24 24"&gt;&lt;path d="M2 12h4v1H2v-1zm6 0h4v1H8v-1zm6 0h4v1h-4v-1zm6 0h2v1h-2v-1z"&gt;&lt;/path&gt;&lt;/svg&gt;',
+        tooltip: 'Insert Styled Divider',
+        action: function(editor) {
+            editor.insertHTML(
+                '&lt;div style="text-align: center; margin: 1.5em 0; color: #d1d5db; letter-spacing: 0.5em; font-size: 1.2em;"&gt;• • •&lt;/div&gt;'
+            );
+        }
+    });
+
+---
+
+### Clear All Formatting
+
+Strip inline styles and attributes from content:
+
+    :::javascript
+    NeikiEditor.registerPlugin({
+        name: 'clean-paste',
+        icon: '&lt;svg viewBox="0 0 24 24"&gt;&lt;path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"&gt;&lt;/path&gt;&lt;/svg&gt;',
+        tooltip: 'Clean All Formatting',
+        action: function(editor) {
+            const text = editor.contentArea.innerText;
+            editor.setContent('&lt;p&gt;' + text.split('\n\n').join('&lt;/p&gt;&lt;p&gt;') + '&lt;/p&gt;');
+        }
+    });
+
+---
+
+### Auto-Capitalize Headings (init hook)
+
+Run code on every input event using the `init` hook:

     :::javascript
     NeikiEditor.registerPlugin({
@@ -102,7 +142,6 @@
                     if (h.textContent.length &amp;gt; 0) {
                         const first = h.textContent.charAt(0);
                         if (first !== first.toUpperCase()) {

-                            // Use selection-safe approach
                             h.textContent = first.toUpperCase() + h.textContent.slice(1);
                         }
                     }
@@ -112,46 +151,60 @@
     });

 &amp;gt; [!CAUTION]
-&amp;gt; Be careful with `init` plugins that modify content on every input event — they can interfere with the user's typing and cursor position. Always test thoroughly.
-
----
-
-### Insert Divider with Style
-

-    :::javascript
-    NeikiEditor.registerPlugin({
-        name: 'styled-divider',
-        icon: '&lt;svg viewBox="0 0 24 24"&gt;&lt;path d="M2 12h4v1H2v-1zm6 0h4v1H8v-1zm6 0h4v1h-4v-1zm6 0h2v1h-2v-1z"&gt;&lt;/path&gt;&lt;/svg&gt;',
-        tooltip: 'Insert Styled Divider',
-        action: function(editor) {
-            editor.insertHTML(
-                '&lt;div style="text-align: center; margin: 1.5em 0; color: #d1d5db; letter-spacing: 0.5em; font-size: 1.2em;"&gt;• • •&lt;/div&gt;'
-            );
-        }
-    });
-
----
-
-### Clear Formatting &amp;amp; Normalize
-
-A cleanup plugin that strips all inline styles and extra attributes:
-
-    :::javascript
-    NeikiEditor.registerPlugin({
-        name: 'clean-paste',
-        icon: '&lt;svg viewBox="0 0 24 24"&gt;&lt;path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"&gt;&lt;/path&gt;&lt;/svg&gt;',
-        tooltip: 'Clean All Formatting',
-        action: function(editor) {
-            const text = editor.contentArea.innerText;
-            editor.setContent('&lt;p&gt;' + text.split('\n\n').join('&lt;/p&gt;&lt;p&gt;') + '&lt;/p&gt;');
-        }
-    });
-
----
-
-## 📋 Listing Plugins
-
-Retrieve all registered plugins:
+&amp;gt; Be careful with `init` plugins that modify the DOM on every input — they can interfere with cursor position. Always test thoroughly and handle edge cases.
+
+---
+
+### Character Limit
+
+Enforce a maximum character count:
+
+    :::javascript
+    NeikiEditor.registerPlugin({
+        name: 'char-limit',
+        init: function(editor) {
+            const MAX = 5000;
+            editor.contentArea.addEventListener('input', function() {
+                const text = editor.getText();
+                if (text.length &amp;gt; MAX) {
+                    // truncate to limit
+                    const truncated = text.slice(0, MAX);
+                    editor.setContent('&lt;p&gt;' + truncated + '&lt;/p&gt;');
+                    alert(`Character limit of ${MAX} reached.`);
+                }
+            });
+        }
+    });
+
+---
+
+### Export as Markdown (action plugin)
+
+    :::javascript
+    NeikiEditor.registerPlugin({
+        name: 'export-markdown',
+        icon: '&lt;svg viewBox="0 0 24 24"&gt;&lt;path d="M20.56 18H3.44C2.65 18 2 17.37 2 16.59V7.41C2 6.63 2.65 6 3.44 6h17.12C21.35 6 22 6.63 22 7.41v9.18c0 .78-.65 1.41-1.44 1.41zM9.5 16v-4.5l2.5 3 2.5-3V16H16V8h-1.5l-2.5 3-2.5-3H8v8h1.5zm-5-3v-2H6V9H4.5v2H3l2 2 2-2H5.5zm11.75.25L18 11.5h-1.25V9h-1.5v2.5H14l2.25 2.25z"&gt;&lt;/path&gt;&lt;/svg&gt;',
+        tooltip: 'Copy as Markdown',
+        action: function(editor) {
+            // Simple HTML-to-markdown conversion
+            let md = editor.getContent()
+                .replace(/&lt;h1&gt;(.*?)&amp;lt;\/h1&amp;gt;/gi, '# $1\n')
+                .replace(/&lt;/h1&gt;&lt;h2&gt;(.*?)&amp;lt;\/h2&amp;gt;/gi, '## $1\n')
+                .replace(/&lt;/h2&gt;&lt;h3&gt;(.*?)&amp;lt;\/h3&amp;gt;/gi, '### $1\n')
+                .replace(/&lt;strong&gt;(.*?)&amp;lt;\/strong&amp;gt;/gi, '**$1**')
+                .replace(/&lt;em&gt;(.*?)&amp;lt;\/em&amp;gt;/gi, '*$1*')
+                .replace(/&lt;/em&gt;&lt;/strong&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;(.*?)&amp;lt;\/p&amp;gt;/gi, '$1\n\n')
+                .replace(/&amp;lt;[^&amp;gt;]+&amp;gt;/g, '');
+    
+            navigator.clipboard.writeText(md.trim()).then(() =&amp;gt; {
+                alert('Copied as Markdown!');
+            });
+        }
+    });
+
+---
+
+## 📋 Listing Registered Plugins

     :::javascript
     const plugins = NeikiEditor.getPlugins();
@@ -170,32 +223,38 @@
         A --&amp;gt; C[Content Area]
         A --&amp;gt; D[Status Bar]
         B --&amp;gt; E[Plugin Buttons]

-        E --&amp;gt; F[Word Counter]
-        E --&amp;gt; G[Timestamp]
-        E --&amp;gt; H[Divider]
+        E --&amp;gt; F[word-counter]
+        E --&amp;gt; G[timestamp]
+        E --&amp;gt; H[custom-plugin]
         A --&amp;gt; I[Plugin Init Hooks]
-        I --&amp;gt; J["auto-capitalize ​#8594; addEventListener"]
+        I --&amp;gt; J[auto-capitalize → addEventListener]
+        I --&amp;gt; K[char-limit → addEventListener]

 ---

 ## 🔒 Best Practices

 &amp;gt; [!TIP]
-&amp;gt; Follow these guidelines for reliable plugins:
-
-1. **Use unique names** — prefix with your project name if needed (e.g., `myapp-timestamp`)
-2. **Keep actions focused** — one plugin, one responsibility
-3. **Don't modify `contentArea` directly in `init`** — use editor API methods when possible
-4. **Test with built-in themes** — ensure your plugin UI works in Light, Dark, Blue, and Dark Blue modes
-5. **Handle edge cases** — check for empty selection before operating on it
+&amp;gt; Follow these guidelines for reliable, maintainable plugins:
+
+1. **Use unique names** — prefix with your project name to avoid collisions (e.g., `myapp-word-counter`)
+2. **One plugin, one responsibility** — keep actions focused and simple
+3. **Prefer editor API methods** — use `editor.insertHTML()`, `editor.setContent()`, etc. over manipulating `contentArea` directly
+4. **Test with all 4 themes** — ensure your plugin's UI looks correct in Light, Dark, Blue, and Dark Blue
+5. **Handle empty selections** — check `editor.isEmpty()` or selection state before operating
+6. **Clean up in destroy** — if your `init` adds event listeners outside the editor, remove them when needed
+7. **Don't block the main thread** — for heavy operations in `action`, use `setTimeout` or async patterns

 ---

 ## 🔗 Related Pages

-- **[⚙️ Configuration](Configuration)** — Editor configuration options
-- **[🔧 Toolbar Reference](Toolbar-Reference)** — Built-in toolbar buttons
-- **[🧩 Advanced Features](Advanced-Features)** — Tables, images, themes
+| | |
+|---|---|
+| [⚙️ Configuration](Configuration) | Editor configuration &amp;amp; toolbar array |
+| [🔧 Toolbar Reference](Toolbar-Reference) | Built-in toolbar button identifiers |
+| [📋 API Reference](API-Reference) | `insertHTML`, `setContent`, `getContent` and all other methods |
+| [🧩 Advanced Features](Advanced-Features) | Tables, images, themes, autosave |

 ---

&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/h3&gt;&lt;/pre&gt;&lt;strong&gt;&lt;em&gt;
&lt;/em&gt;&lt;/strong&gt;&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">neikiri</dc:creator><pubDate>Tue, 09 Jun 2026 06:07:53 -0000</pubDate><guid>https://sourceforge.net8cb267c4fb2e4873a98d420191c68dc3c6dd9c3b</guid></item><item><title>Plugin API modified by neikiri</title><link>https://sourceforge.net/p/neiki-editor/wiki/Plugin%2520API/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v2
+++ v3
@@ -186,7 +186,7 @@

 1. **Use unique names** — prefix with your project name if needed (e.g., `myapp-timestamp`)
 2. **Keep actions focused** — one plugin, one responsibility
 3. **Don't modify `contentArea` directly in `init`** — use editor API methods when possible
-4. **Test with both themes** — ensure your plugin UI works in Light and Dark mode
+4. **Test with built-in themes** — ensure your plugin UI works in Light, Dark, Blue, and Dark Blue modes
 5. **Handle edge cases** — check for empty selection before operating on it

 ---
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">neikiri</dc:creator><pubDate>Tue, 09 Jun 2026 06:07:52 -0000</pubDate><guid>https://sourceforge.net6d039fecb26f2b43724a9b83abfb0dd7d34e2fa2</guid></item><item><title>Plugin API modified by neikiri</title><link>https://sourceforge.net/p/neiki-editor/wiki/Plugin%2520API/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v1
+++ v2
@@ -1,6 +1,6 @@
 # 🔌 Plugin API

-Extend Neiki Editor with custom functionality using the Plugin API. Plugins can add toolbar buttons, hook into initialization, and interact with the editor programmatically.
+Extend Neiki's Editor with custom functionality using the Plugin API. Plugins can add toolbar buttons, hook into initialization, and interact with the editor programmatically.

 ---

&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">neikiri</dc:creator><pubDate>Tue, 09 Jun 2026 06:07:50 -0000</pubDate><guid>https://sourceforge.net088b4bffa89e863ccd6181b139dd8baf3677a2fe</guid></item><item><title>Plugin API modified by neikiri</title><link>https://sourceforge.net/p/neiki-editor/wiki/Plugin%2520API/</link><description>&lt;div class="markdown_content"&gt;&lt;h1 id="h-plugin-api"&gt;🔌 Plugin API&lt;/h1&gt;
&lt;p&gt;Extend Neiki Editor with custom functionality using the Plugin API. Plugins can add toolbar buttons, hook into initialization, and interact with the editor programmatically.&lt;/p&gt;
&lt;hr/&gt;
&lt;h2 id="h-overview"&gt;🧩 Overview&lt;/h2&gt;
&lt;p&gt;Plugins are registered &lt;strong&gt;globally&lt;/strong&gt; before or after editor initialization. Each plugin can optionally:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add a &lt;strong&gt;toolbar button&lt;/strong&gt; with a custom icon&lt;/li&gt;
&lt;li&gt;Run an &lt;strong&gt;action&lt;/strong&gt; when the button is clicked&lt;/li&gt;
&lt;li&gt;Run an &lt;strong&gt;init&lt;/strong&gt; function when the editor starts&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span&gt;[!NOTE]&lt;/span&gt;&lt;br/&gt;
Plugins are registered globally via &lt;code&gt;NeikiEditor.registerPlugin()&lt;/code&gt; and are available to &lt;strong&gt;all&lt;/strong&gt; editor instances on the page.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr/&gt;
&lt;h2 id="h-registering-a-plugin"&gt;📝 Registering a Plugin&lt;/h2&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;NeikiEditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'my-plugin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;svg viewBox="0 0 24 24"&amp;gt;...&amp;lt;/svg&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;tooltip&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'My Custom Action'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Called when toolbar button is clicked&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Called once when editor initializes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr/&gt;
&lt;h2 id="h-plugin-properties"&gt;📊 Plugin Properties&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Unique identifier for the plugin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;icon&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;SVG icon markup for the toolbar button&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tooltip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Tooltip text shown on hover&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;action&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function(editor)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Handler called on toolbar button click&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;init&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function(editor)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Handler called once during editor initialization&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span&gt;[!IMPORTANT]&lt;/span&gt;&lt;br/&gt;
The &lt;code&gt;name&lt;/code&gt; must be unique across all registered plugins. If you register two plugins with the same name, the second will overwrite the first.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr/&gt;
&lt;h2 id="h-plugin-examples"&gt;💡 Plugin Examples&lt;/h2&gt;
&lt;h3 id="h-word-counter-alert"&gt;Word Counter Alert&lt;/h3&gt;
&lt;p&gt;A simple plugin that shows a word count alert:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;NeikiEditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'word-counter'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;svg viewBox="0 0 24 24"&amp;gt;&amp;lt;path d="M3 18h12v-2H3v2zM3 6v2h18V6H3zm0 7h18v-2H3v2z"/&amp;gt;&amp;lt;/svg&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;tooltip&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Show Word Count'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;lt;[^&amp;gt;]*&amp;gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;words&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/\s+/&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;chars&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`Words: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;words&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;\nCharacters: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;chars&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr/&gt;
&lt;h3 id="h-insert-timestamp"&gt;Insert Timestamp&lt;/h3&gt;
&lt;p&gt;Insert the current date and time at the cursor position:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;NeikiEditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'timestamp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;svg viewBox="0 0 24 24"&amp;gt;&amp;lt;path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67V7z"/&amp;gt;&amp;lt;/svg&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;tooltip&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Insert Timestamp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;formatted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&amp;lt;span style="color:#6b7280;font-size:0.9em"&amp;gt;[&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;formatted&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;]&amp;lt;/span&amp;gt;&amp;amp;nbsp;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr/&gt;
&lt;h3 id="h-auto-capitalize-headings"&gt;Auto-Capitalize Headings&lt;/h3&gt;
&lt;p&gt;A plugin that automatically capitalizes the first letter of every heading on init:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;NeikiEditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'auto-capitalize'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentArea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'input'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;headings&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentArea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'h1, h2, h3, h4, h5, h6'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nx"&gt;headings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="c1"&gt;// Use selection-safe approach&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;span&gt;[!CAUTION]&lt;/span&gt;&lt;br/&gt;
Be careful with &lt;code&gt;init&lt;/code&gt; plugins that modify content on every input event — they can interfere with the user's typing and cursor position. Always test thoroughly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr/&gt;
&lt;h3 id="h-insert-divider-with-style"&gt;Insert Divider with Style&lt;/h3&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;NeikiEditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'styled-divider'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;svg viewBox="0 0 24 24"&amp;gt;&amp;lt;path d="M2 12h4v1H2v-1zm6 0h4v1H8v-1zm6 0h4v1h-4v-1zm6 0h2v1h-2v-1z"/&amp;gt;&amp;lt;/svg&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;tooltip&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Insert Styled Divider'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;div style="text-align:center;margin:1.5em 0;color:#d1d5db;letter-spacing:0.5em;font-size:1.2em"&amp;gt;• • •&amp;lt;/div&amp;gt;'&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr/&gt;
&lt;h3 id="h-clear-formatting-normalize"&gt;Clear Formatting &amp;amp; Normalize&lt;/h3&gt;
&lt;p&gt;A cleanup plugin that strips all inline styles and extra attributes:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;NeikiEditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'clean-paste'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;svg viewBox="0 0 24 24"&amp;gt;&amp;lt;path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/&amp;gt;&amp;lt;/svg&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;tooltip&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Clean All Formatting'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentArea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;p&amp;gt;'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'\n\n'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;/p&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr/&gt;
&lt;h2 id="h-listing-plugins"&gt;📋 Listing Plugins&lt;/h2&gt;
&lt;p&gt;Retrieve all registered plugins:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;NeikiEditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getPlugins&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Plugin:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr/&gt;
&lt;h2 id="h-plugin-architecture"&gt;🏗️ Plugin Architecture&lt;/h2&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TD&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NeikiEditor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Instance&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Toolbar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Area&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Area&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Bar&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Plugin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Buttons&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Word&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Timestamp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Divider&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Plugin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Init&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Hooks&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;J&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"auto-capitalize ​#8594; addEventListener"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr/&gt;
&lt;h2 id="h-best-practices"&gt;🔒 Best Practices&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span&gt;[!TIP]&lt;/span&gt;&lt;br/&gt;
Follow these guidelines for reliable plugins:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Use unique names&lt;/strong&gt; — prefix with your project name if needed (e.g., &lt;code&gt;myapp-timestamp&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep actions focused&lt;/strong&gt; — one plugin, one responsibility&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Don't modify &lt;code&gt;contentArea&lt;/code&gt; directly in &lt;code&gt;init&lt;/code&gt;&lt;/strong&gt; — use editor API methods when possible&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test with both themes&lt;/strong&gt; — ensure your plugin UI works in Light and Dark mode&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Handle edge cases&lt;/strong&gt; — check for empty selection before operating on it&lt;/li&gt;
&lt;/ol&gt;
&lt;hr/&gt;
&lt;h2 id="h-related-pages"&gt;🔗 Related Pages&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="/p/neiki-editor/wiki/Configuration/"&gt;⚙️ Configuration&lt;/a&gt;&lt;/strong&gt; — Editor configuration options&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="./Toolbar-Reference"&gt;🔧 Toolbar Reference&lt;/a&gt;&lt;/strong&gt; — Built-in toolbar buttons&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="./Advanced-Features"&gt;🧩 Advanced Features&lt;/a&gt;&lt;/strong&gt; — Tables, images, themes&lt;/li&gt;
&lt;/ul&gt;
&lt;hr/&gt;
&lt;div align="center"&gt;
  &lt;sub&gt;&lt;a href="./Home"&gt;← Back to Home&lt;/a&gt;&lt;/sub&gt;
&lt;/div&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">neikiri</dc:creator><pubDate>Tue, 09 Jun 2026 06:07:46 -0000</pubDate><guid>https://sourceforge.net90db35968cf5b37fde7ada5c21f9bdf35e8657b6</guid></item></channel></rss>