Repository files navigation

Nova Editor

License: MITVersionBuilt with ReactSlate.jsPRs WelcomeGitHub Stars

A configurable, themeable rich text editor for the web, built with React and Slate.js. Drop-in ready for Django templates, plain HTML, PHP, or any project that can include a JS/CSS file.


Features

  • Neutral base theme with paired light/dark named presets — base, valiux, notion, midnight, forest, aurora, newsprint, social, terminal
  • Three toolbar presets: minimal, standard, full — or build a custom config
  • Responsive single-row toolbar — all tool groups are trigger buttons that open slide-down sub-toolbars. No overflow, no wrapping, no JavaScript measurement
  • Full UI configurability — border radius, toolbar size, compact mode, fonts, shadows, all surface colours
  • Light / Dark / System color mode baked into named themes
  • Markdown paste — headings, lists, tables, code blocks, checklists, bold/italic/strikethrough
  • HTML ↔ Slate serialisation — outputs clean indented HTML; accepts HTML as initial content
  • Rich formatting tools — Bold, Italic, Underline, Strikethrough, Inline Code, Subscript, Superscript, Clear Formatting
  • Typography tools — Font Family selector, Font Size selector (10px–64px)
  • Colour tools — Text Colour and Highlight Colour with 48-swatch palette + hex input
  • Link insertion — href, display text, and new-tab toggle via popover
  • Image insertion — URL-based with alt text
  • Special characters — categorised grid of symbols
  • Emoji picker — categorised with search
  • Hidden input sync — wire directly to a <textarea> or <input> for form submission
  • Footer branding — optional logo + name with click-to-collapse animation
  • Fullscreen mode — CSS-based, no native API, works in all contexts
  • Sticky toolbar — stays visible on scroll; sub-toolbars stick with it
  • Max height + internal scroll — cap editor height with styled scrollbar
  • Accessible — keyboard navigation, ARIA roles, focus rings, shortcut labels
  • Standalone build — one JS + one CSS file, no React required on the page

Presets

UI Themes (uiConfig.preset)

NameModeAppearance
base-lightLightNeutral, no colour personality
base-darkDarkNeutral dark
valiux-darkDarkAmber on deep dark (Brand Nova identity)
valiux-lightLightAmber light variant
notion-lightLightBlue accent, document-first, system font
notion-darkDarkBlue accent dark
midnight-darkDarkIndigo accent, Linear/Vercel-inspired
midnight-lightLightIndigo light variant
forest-lightLightGreen accent, serif font, writing-focused
forest-darkDarkGreen accent dark
aurora-darkDarkTeal accent, design-tool-inspired
newsprint-lightLightRed accent, editorial serif, square corners
social-lightLightBlue accent, rounded, composer-inspired
terminal-darkDarkPhosphor green, monospace everything

Toolbar Presets (preset prop)

NameGroups included
minimalFormatting (Bold/Italic/Underline), Headings (H1/¶), Actions
standard+ Strikethrough, Clear, H2/H3, Lists, Blockquote
fullAll groups including Alignment, Blocks, Insert (link/image/emoji)

Installation

npm install
npm run dev # dev server
npm run build # production React build
npm run build:standalone # standalone JS + CSS

Usage

Full usage documentation: USAGE.md

Quick example for plain HTML:

<!-- 1. Include the standalone build --><linkrel="stylesheet" href="path/to/nova-editor.css"><scriptsrc="path/to/nova-editor.umd.js" defer></script><!-- 2. Add a mount point --><divid="my-editor"
data-nova-editordata-toolbar="full"
data-ui-preset="notion-light"
data-placeholder="Start writing…"
></div><!-- 3. Read the output --><script>consteditor=NovaEditor.init({elementId: "my-editor",toolbar: "full",uiPreset: "notion-light",onHTMLChange: (html)=>console.log(html),})</script>

File Structure

src/
├── components/NovaEditor/
│ ├── NovaEditor.jsx # Main editor — state, hotkeys, renderers
│ ├── Toolbar.jsx # All group trigger buttons + sub-toolbar wiring
│ ├── SubToolbar.jsx # Slide-down sub-toolbar panel component
│ ├── useToolbarCollapse.js # Toolbar ref (simplified — no measurement needed)
│ ├── serializers.js # HTML ↔ Slate + pretty-printer
│ ├── markdown.js # Markdown paste parser
│ ├── index.js # Re-exports
│ └── tools/
│ ├── ColourPicker.jsx # Reusable colour picker with palette + hex input
│ ├── FontFamilySelect.jsx
│ ├── FontSizeSelect.jsx
│ ├── LinkTool.jsx # Link insertion popover
│ ├── ImageTool.jsx # Image URL insertion
│ ├── SpecialChars.jsx # Special characters grid
│ └── EmojiPicker.jsx # Emoji picker with search
├── theme-config.js # Named themes + CSS variable resolver
├── presets.js # Toolbar preset definitions
├── standalone.js # window.NovaEditor bundle entry
├── App.jsx # Dev playground
└── index.css # All editor styles
public/
├── index.html # Standalone demo / GitHub Pages landing
└── logo.png

Contributing

Contributions are welcome. Please read CONTRIBUTING.md for guidelines on how to report bugs, propose new themes, add toolbar tools, or improve documentation.

For significant changes, open an issue first to discuss what you'd like to change.


License

MIT License © 2026 Brand Nova.
For full legal terms and ownership details, see the LICENSE file.

About

A highly customizable rich text editor for the web. Built with React and Slate.js, featuring easy integration for Django, PHP, and standalone HTML projects.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Nova Editor

License: MITVersionBuilt with ReactSlate.jsPRs WelcomeGitHub Stars

A configurable, themeable rich text editor for the web, built with React and Slate.js. Drop-in ready for Django templates, plain HTML, PHP, or any project that can include a JS/CSS file.


Features

  • Neutral base theme with paired light/dark named presets — base, valiux, notion, midnight, forest, aurora, newsprint, social, terminal
  • Three toolbar presets: minimal, standard, full — or build a custom config
  • Responsive single-row toolbar — all tool groups are trigger buttons that open slide-down sub-toolbars. No overflow, no wrapping, no JavaScript measurement
  • Full UI configurability — border radius, toolbar size, compact mode, fonts, shadows, all surface colours
  • Light / Dark / System color mode baked into named themes
  • Markdown paste — headings, lists, tables, code blocks, checklists, bold/italic/strikethrough
  • HTML ↔ Slate serialisation — outputs clean indented HTML; accepts HTML as initial content
  • Rich formatting tools — Bold, Italic, Underline, Strikethrough, Inline Code, Subscript, Superscript, Clear Formatting
  • Typography tools — Font Family selector, Font Size selector (10px–64px)
  • Colour tools — Text Colour and Highlight Colour with 48-swatch palette + hex input
  • Link insertion — href, display text, and new-tab toggle via popover
  • Image insertion — URL-based with alt text
  • Special characters — categorised grid of symbols
  • Emoji picker — categorised with search
  • Hidden input sync — wire directly to a <textarea> or <input> for form submission
  • Footer branding — optional logo + name with click-to-collapse animation
  • Fullscreen mode — CSS-based, no native API, works in all contexts
  • Sticky toolbar — stays visible on scroll; sub-toolbars stick with it
  • Max height + internal scroll — cap editor height with styled scrollbar
  • Accessible — keyboard navigation, ARIA roles, focus rings, shortcut labels
  • Standalone build — one JS + one CSS file, no React required on the page

Presets

UI Themes (uiConfig.preset)

NameModeAppearance
base-lightLightNeutral, no colour personality
base-darkDarkNeutral dark
valiux-darkDarkAmber on deep dark (Brand Nova identity)
valiux-lightLightAmber light variant
notion-lightLightBlue accent, document-first, system font
notion-darkDarkBlue accent dark
midnight-darkDarkIndigo accent, Linear/Vercel-inspired
midnight-lightLightIndigo light variant
forest-lightLightGreen accent, serif font, writing-focused
forest-darkDarkGreen accent dark
aurora-darkDarkTeal accent, design-tool-inspired
newsprint-lightLightRed accent, editorial serif, square corners
social-lightLightBlue accent, rounded, composer-inspired
terminal-darkDarkPhosphor green, monospace everything

Toolbar Presets (preset prop)

NameGroups included
minimalFormatting (Bold/Italic/Underline), Headings (H1/¶), Actions
standard+ Strikethrough, Clear, H2/H3, Lists, Blockquote
fullAll groups including Alignment, Blocks, Insert (link/image/emoji)

Installation

npm install
npm run dev # dev server
npm run build # production React build
npm run build:standalone # standalone JS + CSS

Usage

Full usage documentation: USAGE.md

Quick example for plain HTML:

<!-- 1. Include the standalone build --><linkrel="stylesheet" href="path/to/nova-editor.css"><scriptsrc="path/to/nova-editor.umd.js" defer></script><!-- 2. Add a mount point --><divid="my-editor"
data-nova-editordata-toolbar="full"
data-ui-preset="notion-light"
data-placeholder="Start writing…"
></div><!-- 3. Read the output --><script>consteditor=NovaEditor.init({elementId: "my-editor",toolbar: "full",uiPreset: "notion-light",onHTMLChange: (html)=>console.log(html),})</script>

File Structure

src/
├── components/NovaEditor/
│ ├── NovaEditor.jsx # Main editor — state, hotkeys, renderers
│ ├── Toolbar.jsx # All group trigger buttons + sub-toolbar wiring
│ ├── SubToolbar.jsx # Slide-down sub-toolbar panel component
│ ├── useToolbarCollapse.js # Toolbar ref (simplified — no measurement needed)
│ ├── serializers.js # HTML ↔ Slate + pretty-printer
│ ├── markdown.js # Markdown paste parser
│ ├── index.js # Re-exports
│ └── tools/
│ ├── ColourPicker.jsx # Reusable colour picker with palette + hex input
│ ├── FontFamilySelect.jsx
│ ├── FontSizeSelect.jsx
│ ├── LinkTool.jsx # Link insertion popover
│ ├── ImageTool.jsx # Image URL insertion
│ ├── SpecialChars.jsx # Special characters grid
│ └── EmojiPicker.jsx # Emoji picker with search
├── theme-config.js # Named themes + CSS variable resolver
├── presets.js # Toolbar preset definitions
├── standalone.js # window.NovaEditor bundle entry
├── App.jsx # Dev playground
└── index.css # All editor styles
public/
├── index.html # Standalone demo / GitHub Pages landing
└── logo.png

Contributing

Contributions are welcome. Please read CONTRIBUTING.md for guidelines on how to report bugs, propose new themes, add toolbar tools, or improve documentation.

For significant changes, open an issue first to discuss what you'd like to change.


License

MIT License © 2026 Brand Nova.
For full legal terms and ownership details, see the LICENSE file.

About

A highly customizable rich text editor for the web. Built with React and Slate.js, featuring easy integration for Django, PHP, and standalone HTML projects.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Nova Editor

License: MITVersionBuilt with ReactSlate.jsPRs WelcomeGitHub Stars

A configurable, themeable rich text editor for the web, built with React and Slate.js. Drop-in ready for Django templates, plain HTML, PHP, or any project that can include a JS/CSS file.


Features

  • Neutral base theme with paired light/dark named presets — base, valiux, notion, midnight, forest, aurora, newsprint, social, terminal
  • Three toolbar presets: minimal, standard, full — or build a custom config
  • Responsive single-row toolbar — all tool groups are trigger buttons that open slide-down sub-toolbars. No overflow, no wrapping, no JavaScript measurement
  • Full UI configurability — border radius, toolbar size, compact mode, fonts, shadows, all surface colours
  • Light / Dark / System color mode baked into named themes
  • Markdown paste — headings, lists, tables, code blocks, checklists, bold/italic/strikethrough
  • HTML ↔ Slate serialisation — outputs clean indented HTML; accepts HTML as initial content
  • Rich formatting tools — Bold, Italic, Underline, Strikethrough, Inline Code, Subscript, Superscript, Clear Formatting
  • Typography tools — Font Family selector, Font Size selector (10px–64px)
  • Colour tools — Text Colour and Highlight Colour with 48-swatch palette + hex input
  • Link insertion — href, display text, and new-tab toggle via popover
  • Image insertion — URL-based with alt text
  • Special characters — categorised grid of symbols
  • Emoji picker — categorised with search
  • Hidden input sync — wire directly to a <textarea> or <input> for form submission
  • Footer branding — optional logo + name with click-to-collapse animation
  • Fullscreen mode — CSS-based, no native API, works in all contexts
  • Sticky toolbar — stays visible on scroll; sub-toolbars stick with it
  • Max height + internal scroll — cap editor height with styled scrollbar
  • Accessible — keyboard navigation, ARIA roles, focus rings, shortcut labels
  • Standalone build — one JS + one CSS file, no React required on the page

Presets

UI Themes (uiConfig.preset)

NameModeAppearance
base-lightLightNeutral, no colour personality
base-darkDarkNeutral dark
valiux-darkDarkAmber on deep dark (Brand Nova identity)
valiux-lightLightAmber light variant
notion-lightLightBlue accent, document-first, system font
notion-darkDarkBlue accent dark
midnight-darkDarkIndigo accent, Linear/Vercel-inspired
midnight-lightLightIndigo light variant
forest-lightLightGreen accent, serif font, writing-focused
forest-darkDarkGreen accent dark
aurora-darkDarkTeal accent, design-tool-inspired
newsprint-lightLightRed accent, editorial serif, square corners
social-lightLightBlue accent, rounded, composer-inspired
terminal-darkDarkPhosphor green, monospace everything

Toolbar Presets (preset prop)

NameGroups included
minimalFormatting (Bold/Italic/Underline), Headings (H1/¶), Actions
standard+ Strikethrough, Clear, H2/H3, Lists, Blockquote
fullAll groups including Alignment, Blocks, Insert (link/image/emoji)

Installation

npm install
npm run dev # dev server
npm run build # production React build
npm run build:standalone # standalone JS + CSS

Usage

Full usage documentation: USAGE.md

Quick example for plain HTML:

<!-- 1. Include the standalone build --><linkrel="stylesheet" href="path/to/nova-editor.css"><scriptsrc="path/to/nova-editor.umd.js" defer></script><!-- 2. Add a mount point --><divid="my-editor"
data-nova-editordata-toolbar="full"
data-ui-preset="notion-light"
data-placeholder="Start writing…"
></div><!-- 3. Read the output --><script>consteditor=NovaEditor.init({elementId: "my-editor",toolbar: "full",uiPreset: "notion-light",onHTMLChange: (html)=>console.log(html),})</script>

File Structure

src/
├── components/NovaEditor/
│ ├── NovaEditor.jsx # Main editor — state, hotkeys, renderers
│ ├── Toolbar.jsx # All group trigger buttons + sub-toolbar wiring
│ ├── SubToolbar.jsx # Slide-down sub-toolbar panel component
│ ├── useToolbarCollapse.js # Toolbar ref (simplified — no measurement needed)
│ ├── serializers.js # HTML ↔ Slate + pretty-printer
│ ├── markdown.js # Markdown paste parser
│ ├── index.js # Re-exports
│ └── tools/
│ ├── ColourPicker.jsx # Reusable colour picker with palette + hex input
│ ├── FontFamilySelect.jsx
│ ├── FontSizeSelect.jsx
│ ├── LinkTool.jsx # Link insertion popover
│ ├── ImageTool.jsx # Image URL insertion
│ ├── SpecialChars.jsx # Special characters grid
│ └── EmojiPicker.jsx # Emoji picker with search
├── theme-config.js # Named themes + CSS variable resolver
├── presets.js # Toolbar preset definitions
├── standalone.js # window.NovaEditor bundle entry
├── App.jsx # Dev playground
└── index.css # All editor styles
public/
├── index.html # Standalone demo / GitHub Pages landing
└── logo.png

Contributing

Contributions are welcome. Please read CONTRIBUTING.md for guidelines on how to report bugs, propose new themes, add toolbar tools, or improve documentation.

For significant changes, open an issue first to discuss what you'd like to change.


License

MIT License © 2026 Brand Nova.
For full legal terms and ownership details, see the LICENSE file.

About

A highly customizable rich text editor for the web. Built with React and Slate.js, featuring easy integration for Django, PHP, and standalone HTML projects.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Nova Editor

License: MITVersionBuilt with ReactSlate.jsPRs WelcomeGitHub Stars

A configurable, themeable rich text editor for the web, built with React and Slate.js. Drop-in ready for Django templates, plain HTML, PHP, or any project that can include a JS/CSS file.


Features

  • Neutral base theme with paired light/dark named presets — base, valiux, notion, midnight, forest, aurora, newsprint, social, terminal
  • Three toolbar presets: minimal, standard, full — or build a custom config
  • Responsive single-row toolbar — all tool groups are trigger buttons that open slide-down sub-toolbars. No overflow, no wrapping, no JavaScript measurement
  • Full UI configurability — border radius, toolbar size, compact mode, fonts, shadows, all surface colours
  • Light / Dark / System color mode baked into named themes
  • Markdown paste — headings, lists, tables, code blocks, checklists, bold/italic/strikethrough
  • HTML ↔ Slate serialisation — outputs clean indented HTML; accepts HTML as initial content
  • Rich formatting tools — Bold, Italic, Underline, Strikethrough, Inline Code, Subscript, Superscript, Clear Formatting
  • Typography tools — Font Family selector, Font Size selector (10px–64px)
  • Colour tools — Text Colour and Highlight Colour with 48-swatch palette + hex input
  • Link insertion — href, display text, and new-tab toggle via popover
  • Image insertion — URL-based with alt text
  • Special characters — categorised grid of symbols
  • Emoji picker — categorised with search
  • Hidden input sync — wire directly to a <textarea> or <input> for form submission
  • Footer branding — optional logo + name with click-to-collapse animation
  • Fullscreen mode — CSS-based, no native API, works in all contexts
  • Sticky toolbar — stays visible on scroll; sub-toolbars stick with it
  • Max height + internal scroll — cap editor height with styled scrollbar
  • Accessible — keyboard navigation, ARIA roles, focus rings, shortcut labels
  • Standalone build — one JS + one CSS file, no React required on the page

Presets

UI Themes (uiConfig.preset)

NameModeAppearance
base-lightLightNeutral, no colour personality
base-darkDarkNeutral dark
valiux-darkDarkAmber on deep dark (Brand Nova identity)
valiux-lightLightAmber light variant
notion-lightLightBlue accent, document-first, system font
notion-darkDarkBlue accent dark
midnight-darkDarkIndigo accent, Linear/Vercel-inspired
midnight-lightLightIndigo light variant
forest-lightLightGreen accent, serif font, writing-focused
forest-darkDarkGreen accent dark
aurora-darkDarkTeal accent, design-tool-inspired
newsprint-lightLightRed accent, editorial serif, square corners
social-lightLightBlue accent, rounded, composer-inspired
terminal-darkDarkPhosphor green, monospace everything

Toolbar Presets (preset prop)

NameGroups included
minimalFormatting (Bold/Italic/Underline), Headings (H1/¶), Actions
standard+ Strikethrough, Clear, H2/H3, Lists, Blockquote
fullAll groups including Alignment, Blocks, Insert (link/image/emoji)

Installation

npm install
npm run dev # dev server
npm run build # production React build
npm run build:standalone # standalone JS + CSS

Usage

Full usage documentation: USAGE.md

Quick example for plain HTML:

<!-- 1. Include the standalone build --><linkrel="stylesheet" href="path/to/nova-editor.css"><scriptsrc="path/to/nova-editor.umd.js" defer></script><!-- 2. Add a mount point --><divid="my-editor"
data-nova-editordata-toolbar="full"
data-ui-preset="notion-light"
data-placeholder="Start writing…"
></div><!-- 3. Read the output --><script>consteditor=NovaEditor.init({elementId: "my-editor",toolbar: "full",uiPreset: "notion-light",onHTMLChange: (html)=>console.log(html),})</script>

File Structure

src/
├── components/NovaEditor/
│ ├── NovaEditor.jsx # Main editor — state, hotkeys, renderers
│ ├── Toolbar.jsx # All group trigger buttons + sub-toolbar wiring
│ ├── SubToolbar.jsx # Slide-down sub-toolbar panel component
│ ├── useToolbarCollapse.js # Toolbar ref (simplified — no measurement needed)
│ ├── serializers.js # HTML ↔ Slate + pretty-printer
│ ├── markdown.js # Markdown paste parser
│ ├── index.js # Re-exports
│ └── tools/
│ ├── ColourPicker.jsx # Reusable colour picker with palette + hex input
│ ├── FontFamilySelect.jsx
│ ├── FontSizeSelect.jsx
│ ├── LinkTool.jsx # Link insertion popover
│ ├── ImageTool.jsx # Image URL insertion
│ ├── SpecialChars.jsx # Special characters grid
│ └── EmojiPicker.jsx # Emoji picker with search
├── theme-config.js # Named themes + CSS variable resolver
├── presets.js # Toolbar preset definitions
├── standalone.js # window.NovaEditor bundle entry
├── App.jsx # Dev playground
└── index.css # All editor styles
public/
├── index.html # Standalone demo / GitHub Pages landing
└── logo.png

Contributing

Contributions are welcome. Please read CONTRIBUTING.md for guidelines on how to report bugs, propose new themes, add toolbar tools, or improve documentation.

For significant changes, open an issue first to discuss what you'd like to change.


License

MIT License © 2026 Brand Nova.
For full legal terms and ownership details, see the LICENSE file.

About

A highly customizable rich text editor for the web. Built with React and Slate.js, featuring easy integration for Django, PHP, and standalone HTML projects.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Nova Editor

License: MITVersionBuilt with ReactSlate.jsPRs WelcomeGitHub Stars

A configurable, themeable rich text editor for the web, built with React and Slate.js. Drop-in ready for Django templates, plain HTML, PHP, or any project that can include a JS/CSS file.


Features

  • Neutral base theme with paired light/dark named presets — base, valiux, notion, midnight, forest, aurora, newsprint, social, terminal
  • Three toolbar presets: minimal, standard, full — or build a custom config
  • Responsive single-row toolbar — all tool groups are trigger buttons that open slide-down sub-toolbars. No overflow, no wrapping, no JavaScript measurement
  • Full UI configurability — border radius, toolbar size, compact mode, fonts, shadows, all surface colours
  • Light / Dark / System color mode baked into named themes
  • Markdown paste — headings, lists, tables, code blocks, checklists, bold/italic/strikethrough
  • HTML ↔ Slate serialisation — outputs clean indented HTML; accepts HTML as initial content
  • Rich formatting tools — Bold, Italic, Underline, Strikethrough, Inline Code, Subscript, Superscript, Clear Formatting
  • Typography tools — Font Family selector, Font Size selector (10px–64px)
  • Colour tools — Text Colour and Highlight Colour with 48-swatch palette + hex input
  • Link insertion — href, display text, and new-tab toggle via popover
  • Image insertion — URL-based with alt text
  • Special characters — categorised grid of symbols
  • Emoji picker — categorised with search
  • Hidden input sync — wire directly to a <textarea> or <input> for form submission
  • Footer branding — optional logo + name with click-to-collapse animation
  • Fullscreen mode — CSS-based, no native API, works in all contexts
  • Sticky toolbar — stays visible on scroll; sub-toolbars stick with it
  • Max height + internal scroll — cap editor height with styled scrollbar
  • Accessible — keyboard navigation, ARIA roles, focus rings, shortcut labels
  • Standalone build — one JS + one CSS file, no React required on the page

Presets

UI Themes (uiConfig.preset)

NameModeAppearance
base-lightLightNeutral, no colour personality
base-darkDarkNeutral dark
valiux-darkDarkAmber on deep dark (Brand Nova identity)
valiux-lightLightAmber light variant
notion-lightLightBlue accent, document-first, system font
notion-darkDarkBlue accent dark
midnight-darkDarkIndigo accent, Linear/Vercel-inspired
midnight-lightLightIndigo light variant
forest-lightLightGreen accent, serif font, writing-focused
forest-darkDarkGreen accent dark
aurora-darkDarkTeal accent, design-tool-inspired
newsprint-lightLightRed accent, editorial serif, square corners
social-lightLightBlue accent, rounded, composer-inspired
terminal-darkDarkPhosphor green, monospace everything

Toolbar Presets (preset prop)

NameGroups included
minimalFormatting (Bold/Italic/Underline), Headings (H1/¶), Actions
standard+ Strikethrough, Clear, H2/H3, Lists, Blockquote
fullAll groups including Alignment, Blocks, Insert (link/image/emoji)

Installation

npm install
npm run dev # dev server
npm run build # production React build
npm run build:standalone # standalone JS + CSS

Usage

Full usage documentation: USAGE.md

Quick example for plain HTML:

<!-- 1. Include the standalone build --><linkrel="stylesheet" href="path/to/nova-editor.css"><scriptsrc="path/to/nova-editor.umd.js" defer></script><!-- 2. Add a mount point --><divid="my-editor"
data-nova-editordata-toolbar="full"
data-ui-preset="notion-light"
data-placeholder="Start writing…"
></div><!-- 3. Read the output --><script>consteditor=NovaEditor.init({elementId: "my-editor",toolbar: "full",uiPreset: "notion-light",onHTMLChange: (html)=>console.log(html),})</script>

File Structure

src/
├── components/NovaEditor/
│ ├── NovaEditor.jsx # Main editor — state, hotkeys, renderers
│ ├── Toolbar.jsx # All group trigger buttons + sub-toolbar wiring
│ ├── SubToolbar.jsx # Slide-down sub-toolbar panel component
│ ├── useToolbarCollapse.js # Toolbar ref (simplified — no measurement needed)
│ ├── serializers.js # HTML ↔ Slate + pretty-printer
│ ├── markdown.js # Markdown paste parser
│ ├── index.js # Re-exports
│ └── tools/
│ ├── ColourPicker.jsx # Reusable colour picker with palette + hex input
│ ├── FontFamilySelect.jsx
│ ├── FontSizeSelect.jsx
│ ├── LinkTool.jsx # Link insertion popover
│ ├── ImageTool.jsx # Image URL insertion
│ ├── SpecialChars.jsx # Special characters grid
│ └── EmojiPicker.jsx # Emoji picker with search
├── theme-config.js # Named themes + CSS variable resolver
├── presets.js # Toolbar preset definitions
├── standalone.js # window.NovaEditor bundle entry
├── App.jsx # Dev playground
└── index.css # All editor styles
public/
├── index.html # Standalone demo / GitHub Pages landing
└── logo.png

Contributing

Contributions are welcome. Please read CONTRIBUTING.md for guidelines on how to report bugs, propose new themes, add toolbar tools, or improve documentation.

For significant changes, open an issue first to discuss what you'd like to change.


License

MIT License © 2026 Brand Nova.
For full legal terms and ownership details, see the LICENSE file.

About

A highly customizable rich text editor for the web. Built with React and Slate.js, featuring easy integration for Django, PHP, and standalone HTML projects.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Nova Editor

License: MITVersionBuilt with ReactSlate.jsPRs WelcomeGitHub Stars

A configurable, themeable rich text editor for the web, built with React and Slate.js. Drop-in ready for Django templates, plain HTML, PHP, or any project that can include a JS/CSS file.


Features

  • Neutral base theme with paired light/dark named presets — base, valiux, notion, midnight, forest, aurora, newsprint, social, terminal
  • Three toolbar presets: minimal, standard, full — or build a custom config
  • Responsive single-row toolbar — all tool groups are trigger buttons that open slide-down sub-toolbars. No overflow, no wrapping, no JavaScript measurement
  • Full UI configurability — border radius, toolbar size, compact mode, fonts, shadows, all surface colours
  • Light / Dark / System color mode baked into named themes
  • Markdown paste — headings, lists, tables, code blocks, checklists, bold/italic/strikethrough
  • HTML ↔ Slate serialisation — outputs clean indented HTML; accepts HTML as initial content
  • Rich formatting tools — Bold, Italic, Underline, Strikethrough, Inline Code, Subscript, Superscript, Clear Formatting
  • Typography tools — Font Family selector, Font Size selector (10px–64px)
  • Colour tools — Text Colour and Highlight Colour with 48-swatch palette + hex input
  • Link insertion — href, display text, and new-tab toggle via popover
  • Image insertion — URL-based with alt text
  • Special characters — categorised grid of symbols
  • Emoji picker — categorised with search
  • Hidden input sync — wire directly to a <textarea> or <input> for form submission
  • Footer branding — optional logo + name with click-to-collapse animation
  • Fullscreen mode — CSS-based, no native API, works in all contexts
  • Sticky toolbar — stays visible on scroll; sub-toolbars stick with it
  • Max height + internal scroll — cap editor height with styled scrollbar
  • Accessible — keyboard navigation, ARIA roles, focus rings, shortcut labels
  • Standalone build — one JS + one CSS file, no React required on the page

Presets

UI Themes (uiConfig.preset)

NameModeAppearance
base-lightLightNeutral, no colour personality
base-darkDarkNeutral dark
valiux-darkDarkAmber on deep dark (Brand Nova identity)
valiux-lightLightAmber light variant
notion-lightLightBlue accent, document-first, system font
notion-darkDarkBlue accent dark
midnight-darkDarkIndigo accent, Linear/Vercel-inspired
midnight-lightLightIndigo light variant
forest-lightLightGreen accent, serif font, writing-focused
forest-darkDarkGreen accent dark
aurora-darkDarkTeal accent, design-tool-inspired
newsprint-lightLightRed accent, editorial serif, square corners
social-lightLightBlue accent, rounded, composer-inspired
terminal-darkDarkPhosphor green, monospace everything

Toolbar Presets (preset prop)

NameGroups included
minimalFormatting (Bold/Italic/Underline), Headings (H1/¶), Actions
standard+ Strikethrough, Clear, H2/H3, Lists, Blockquote
fullAll groups including Alignment, Blocks, Insert (link/image/emoji)

Installation

npm install
npm run dev # dev server
npm run build # production React build
npm run build:standalone # standalone JS + CSS

Usage

Full usage documentation: USAGE.md

Quick example for plain HTML:

<!-- 1. Include the standalone build --><linkrel="stylesheet" href="path/to/nova-editor.css"><scriptsrc="path/to/nova-editor.umd.js" defer></script><!-- 2. Add a mount point --><divid="my-editor"
data-nova-editordata-toolbar="full"
data-ui-preset="notion-light"
data-placeholder="Start writing…"
></div><!-- 3. Read the output --><script>consteditor=NovaEditor.init({elementId: "my-editor",toolbar: "full",uiPreset: "notion-light",onHTMLChange: (html)=>console.log(html),})</script>

File Structure

src/
├── components/NovaEditor/
│ ├── NovaEditor.jsx # Main editor — state, hotkeys, renderers
│ ├── Toolbar.jsx # All group trigger buttons + sub-toolbar wiring
│ ├── SubToolbar.jsx # Slide-down sub-toolbar panel component
│ ├── useToolbarCollapse.js # Toolbar ref (simplified — no measurement needed)
│ ├── serializers.js # HTML ↔ Slate + pretty-printer
│ ├── markdown.js # Markdown paste parser
│ ├── index.js # Re-exports
│ └── tools/
│ ├── ColourPicker.jsx # Reusable colour picker with palette + hex input
│ ├── FontFamilySelect.jsx
│ ├── FontSizeSelect.jsx
│ ├── LinkTool.jsx # Link insertion popover
│ ├── ImageTool.jsx # Image URL insertion
│ ├── SpecialChars.jsx # Special characters grid
│ └── EmojiPicker.jsx # Emoji picker with search
├── theme-config.js # Named themes + CSS variable resolver
├── presets.js # Toolbar preset definitions
├── standalone.js # window.NovaEditor bundle entry
├── App.jsx # Dev playground
└── index.css # All editor styles
public/
├── index.html # Standalone demo / GitHub Pages landing
└── logo.png

Contributing

Contributions are welcome. Please read CONTRIBUTING.md for guidelines on how to report bugs, propose new themes, add toolbar tools, or improve documentation.

For significant changes, open an issue first to discuss what you'd like to change.


License

MIT License © 2026 Brand Nova.
For full legal terms and ownership details, see the LICENSE file.

About

A highly customizable rich text editor for the web. Built with React and Slate.js, featuring easy integration for Django, PHP, and standalone HTML projects.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Nova Editor

License: MITVersionBuilt with ReactSlate.jsPRs WelcomeGitHub Stars

A configurable, themeable rich text editor for the web, built with React and Slate.js. Drop-in ready for Django templates, plain HTML, PHP, or any project that can include a JS/CSS file.


Features

  • Neutral base theme with paired light/dark named presets — base, valiux, notion, midnight, forest, aurora, newsprint, social, terminal
  • Three toolbar presets: minimal, standard, full — or build a custom config
  • Responsive single-row toolbar — all tool groups are trigger buttons that open slide-down sub-toolbars. No overflow, no wrapping, no JavaScript measurement
  • Full UI configurability — border radius, toolbar size, compact mode, fonts, shadows, all surface colours
  • Light / Dark / System color mode baked into named themes
  • Markdown paste — headings, lists, tables, code blocks, checklists, bold/italic/strikethrough
  • HTML ↔ Slate serialisation — outputs clean indented HTML; accepts HTML as initial content
  • Rich formatting tools — Bold, Italic, Underline, Strikethrough, Inline Code, Subscript, Superscript, Clear Formatting
  • Typography tools — Font Family selector, Font Size selector (10px–64px)
  • Colour tools — Text Colour and Highlight Colour with 48-swatch palette + hex input
  • Link insertion — href, display text, and new-tab toggle via popover
  • Image insertion — URL-based with alt text
  • Special characters — categorised grid of symbols
  • Emoji picker — categorised with search
  • Hidden input sync — wire directly to a <textarea> or <input> for form submission
  • Footer branding — optional logo + name with click-to-collapse animation
  • Fullscreen mode — CSS-based, no native API, works in all contexts
  • Sticky toolbar — stays visible on scroll; sub-toolbars stick with it
  • Max height + internal scroll — cap editor height with styled scrollbar
  • Accessible — keyboard navigation, ARIA roles, focus rings, shortcut labels
  • Standalone build — one JS + one CSS file, no React required on the page

Presets

UI Themes (uiConfig.preset)

NameModeAppearance
base-lightLightNeutral, no colour personality
base-darkDarkNeutral dark
valiux-darkDarkAmber on deep dark (Brand Nova identity)
valiux-lightLightAmber light variant
notion-lightLightBlue accent, document-first, system font
notion-darkDarkBlue accent dark
midnight-darkDarkIndigo accent, Linear/Vercel-inspired
midnight-lightLightIndigo light variant
forest-lightLightGreen accent, serif font, writing-focused
forest-darkDarkGreen accent dark
aurora-darkDarkTeal accent, design-tool-inspired
newsprint-lightLightRed accent, editorial serif, square corners
social-lightLightBlue accent, rounded, composer-inspired
terminal-darkDarkPhosphor green, monospace everything

Toolbar Presets (preset prop)

NameGroups included
minimalFormatting (Bold/Italic/Underline), Headings (H1/¶), Actions
standard+ Strikethrough, Clear, H2/H3, Lists, Blockquote
fullAll groups including Alignment, Blocks, Insert (link/image/emoji)

Installation

npm install
npm run dev # dev server
npm run build # production React build
npm run build:standalone # standalone JS + CSS

Usage

Full usage documentation: USAGE.md

Quick example for plain HTML:

<!-- 1. Include the standalone build --><linkrel="stylesheet" href="path/to/nova-editor.css"><scriptsrc="path/to/nova-editor.umd.js" defer></script><!-- 2. Add a mount point --><divid="my-editor"
data-nova-editordata-toolbar="full"
data-ui-preset="notion-light"
data-placeholder="Start writing…"
></div><!-- 3. Read the output --><script>consteditor=NovaEditor.init({elementId: "my-editor",toolbar: "full",uiPreset: "notion-light",onHTMLChange: (html)=>console.log(html),})</script>

File Structure

src/
├── components/NovaEditor/
│ ├── NovaEditor.jsx # Main editor — state, hotkeys, renderers
│ ├── Toolbar.jsx # All group trigger buttons + sub-toolbar wiring
│ ├── SubToolbar.jsx # Slide-down sub-toolbar panel component
│ ├── useToolbarCollapse.js # Toolbar ref (simplified — no measurement needed)
│ ├── serializers.js # HTML ↔ Slate + pretty-printer
│ ├── markdown.js # Markdown paste parser
│ ├── index.js # Re-exports
│ └── tools/
│ ├── ColourPicker.jsx # Reusable colour picker with palette + hex input
│ ├── FontFamilySelect.jsx
│ ├── FontSizeSelect.jsx
│ ├── LinkTool.jsx # Link insertion popover
│ ├── ImageTool.jsx # Image URL insertion
│ ├── SpecialChars.jsx # Special characters grid
│ └── EmojiPicker.jsx # Emoji picker with search
├── theme-config.js # Named themes + CSS variable resolver
├── presets.js # Toolbar preset definitions
├── standalone.js # window.NovaEditor bundle entry
├── App.jsx # Dev playground
└── index.css # All editor styles
public/
├── index.html # Standalone demo / GitHub Pages landing
└── logo.png

Contributing

Contributions are welcome. Please read CONTRIBUTING.md for guidelines on how to report bugs, propose new themes, add toolbar tools, or improve documentation.

For significant changes, open an issue first to discuss what you'd like to change.


License

MIT License © 2026 Brand Nova.
For full legal terms and ownership details, see the LICENSE file.

About

A highly customizable rich text editor for the web. Built with React and Slate.js, featuring easy integration for Django, PHP, and standalone HTML projects.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Nova Editor

License: MITVersionBuilt with ReactSlate.jsPRs WelcomeGitHub Stars

A configurable, themeable rich text editor for the web, built with React and Slate.js. Drop-in ready for Django templates, plain HTML, PHP, or any project that can include a JS/CSS file.


Features

  • Neutral base theme with paired light/dark named presets — base, valiux, notion, midnight, forest, aurora, newsprint, social, terminal
  • Three toolbar presets: minimal, standard, full — or build a custom config
  • Responsive single-row toolbar — all tool groups are trigger buttons that open slide-down sub-toolbars. No overflow, no wrapping, no JavaScript measurement
  • Full UI configurability — border radius, toolbar size, compact mode, fonts, shadows, all surface colours
  • Light / Dark / System color mode baked into named themes
  • Markdown paste — headings, lists, tables, code blocks, checklists, bold/italic/strikethrough
  • HTML ↔ Slate serialisation — outputs clean indented HTML; accepts HTML as initial content
  • Rich formatting tools — Bold, Italic, Underline, Strikethrough, Inline Code, Subscript, Superscript, Clear Formatting
  • Typography tools — Font Family selector, Font Size selector (10px–64px)
  • Colour tools — Text Colour and Highlight Colour with 48-swatch palette + hex input
  • Link insertion — href, display text, and new-tab toggle via popover
  • Image insertion — URL-based with alt text
  • Special characters — categorised grid of symbols
  • Emoji picker — categorised with search
  • Hidden input sync — wire directly to a <textarea> or <input> for form submission
  • Footer branding — optional logo + name with click-to-collapse animation
  • Fullscreen mode — CSS-based, no native API, works in all contexts
  • Sticky toolbar — stays visible on scroll; sub-toolbars stick with it
  • Max height + internal scroll — cap editor height with styled scrollbar
  • Accessible — keyboard navigation, ARIA roles, focus rings, shortcut labels
  • Standalone build — one JS + one CSS file, no React required on the page

Presets

UI Themes (uiConfig.preset)

NameModeAppearance
base-lightLightNeutral, no colour personality
base-darkDarkNeutral dark
valiux-darkDarkAmber on deep dark (Brand Nova identity)
valiux-lightLightAmber light variant
notion-lightLightBlue accent, document-first, system font
notion-darkDarkBlue accent dark
midnight-darkDarkIndigo accent, Linear/Vercel-inspired
midnight-lightLightIndigo light variant
forest-lightLightGreen accent, serif font, writing-focused
forest-darkDarkGreen accent dark
aurora-darkDarkTeal accent, design-tool-inspired
newsprint-lightLightRed accent, editorial serif, square corners
social-lightLightBlue accent, rounded, composer-inspired
terminal-darkDarkPhosphor green, monospace everything

Toolbar Presets (preset prop)

NameGroups included
minimalFormatting (Bold/Italic/Underline), Headings (H1/¶), Actions
standard+ Strikethrough, Clear, H2/H3, Lists, Blockquote
fullAll groups including Alignment, Blocks, Insert (link/image/emoji)

Installation

npm install
npm run dev # dev server
npm run build # production React build
npm run build:standalone # standalone JS + CSS

Usage

Full usage documentation: USAGE.md

Quick example for plain HTML:

<!-- 1. Include the standalone build --><linkrel="stylesheet" href="path/to/nova-editor.css"><scriptsrc="path/to/nova-editor.umd.js" defer></script><!-- 2. Add a mount point --><divid="my-editor"
data-nova-editordata-toolbar="full"
data-ui-preset="notion-light"
data-placeholder="Start writing…"
></div><!-- 3. Read the output --><script>consteditor=NovaEditor.init({elementId: "my-editor",toolbar: "full",uiPreset: "notion-light",onHTMLChange: (html)=>console.log(html),})</script>

File Structure

src/
├── components/NovaEditor/
│ ├── NovaEditor.jsx # Main editor — state, hotkeys, renderers
│ ├── Toolbar.jsx # All group trigger buttons + sub-toolbar wiring
│ ├── SubToolbar.jsx # Slide-down sub-toolbar panel component
│ ├── useToolbarCollapse.js # Toolbar ref (simplified — no measurement needed)
│ ├── serializers.js # HTML ↔ Slate + pretty-printer
│ ├── markdown.js # Markdown paste parser
│ ├── index.js # Re-exports
│ └── tools/
│ ├── ColourPicker.jsx # Reusable colour picker with palette + hex input
│ ├── FontFamilySelect.jsx
│ ├── FontSizeSelect.jsx
│ ├── LinkTool.jsx # Link insertion popover
│ ├── ImageTool.jsx # Image URL insertion
│ ├── SpecialChars.jsx # Special characters grid
│ └── EmojiPicker.jsx # Emoji picker with search
├── theme-config.js # Named themes + CSS variable resolver
├── presets.js # Toolbar preset definitions
├── standalone.js # window.NovaEditor bundle entry
├── App.jsx # Dev playground
└── index.css # All editor styles
public/
├── index.html # Standalone demo / GitHub Pages landing
└── logo.png

Contributing

Contributions are welcome. Please read CONTRIBUTING.md for guidelines on how to report bugs, propose new themes, add toolbar tools, or improve documentation.

For significant changes, open an issue first to discuss what you'd like to change.


License

MIT License © 2026 Brand Nova.
For full legal terms and ownership details, see the LICENSE file.

About

A highly customizable rich text editor for the web. Built with React and Slate.js, featuring easy integration for Django, PHP, and standalone HTML projects.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages