Skip to content

feat: add rich text editor integration for global variables & shortcodes plugins#757

Open
cp-bwg wants to merge 1 commit intoSonicJs-Org:mainfrom
cp-bwg:feat/rich-text-editor-plugins-global-variables-shortcodes
Open

feat: add rich text editor integration for global variables & shortcodes plugins#757
cp-bwg wants to merge 1 commit intoSonicJs-Org:mainfrom
cp-bwg:feat/rich-text-editor-plugins-global-variables-shortcodes

Conversation

@cp-bwg
Copy link
Copy Markdown

@cp-bwg cp-bwg commented Apr 8, 2026

Summary

Implements Part 2 (Rich Text Inline Tokens) from #719 and extends PR #743 with full rich text editor integration for both Quill and TinyMCE editors, plus a new Shortcodes plugin.

  • Enhanced global-variables-plugin with full CRUD admin page, Quill variable blots (blue chips), TinyMCE toolbar button, and editor integration toggle
  • New shortcodes-plugin with [[shortcode_name param="value"]] syntax, handler registry, CRUD admin with live preview, Quill shortcode blots (purple chips), and TinyMCE integration
  • Shared editor utilities for Quill (constructor Proxy, searchable picker, enhancer poller) and TinyMCE (PluginManager approach, chip CSS injection)
  • Shared admin template with Tailwind CSS, HTMX, and CSRF auto-injection

Changes

Enhanced: global-variables-plugin (3 files modified)

  • index.ts — Complete rewrite with:
    • Full CRUD admin page (add, inline edit, delete, toggle active/inactive)
    • Plugin status gating (routes return 404 when plugin inactive)
    • install/uninstall lifecycle hooks for table management
    • getVariableBlotScript() — Quill integration with custom VariableBlot (blue chip), searchable picker
    • getVariableTinyMceScript() — TinyMCE integration via PluginManager.add()
    • Rich Text Editor Integration settings card with toggle + editor auto-detection
  • manifest.json — Updated to v1.1.0 with admin menu, routes, and lifecycle hooks
  • variable-resolver.ts — Unchanged (already solid from feat: add dynamic content variables / inline tokens #743)

New: shortcodes-plugin (3 files)

  • index.ts — Full plugin with:
    • [[shortcode_name param="value"]] token syntax
    • CRUD API + admin page with handler status badges
    • Live preview endpoint (POST /api/shortcodes/preview)
    • content:read hook at priority 60 (runs after variables at 50)
    • getShortcodeBlotScript() — Quill integration with ShortcodeBlot (purple chip)
    • getShortcodeTinyMceScript() — TinyMCE integration via PluginManager.add()
  • shortcode-resolver.ts — Parser + handler registry with 5 built-in handlers:
    • current_date — Formatted date output
    • phone_link — Clickable phone link
    • cta_button — Styled call-to-action button
    • plan_count — Dynamic plan count placeholder
    • provider_rating — Star rating display
  • manifest.json — Plugin metadata

New: _shared/ directory (4 files)

  • admin-template.ts — HTML wrapper with Tailwind + HTMX + CSRF
  • quill-shared.ts — Quill constructor Proxy (custom format whitelisting), searchable picker dropdown, enhancer polling framework
  • tinymce-shared.ts — TinyMCE PluginManager approach (official API), picker dropdown, chip CSS injection into editor iframe
  • index.ts — Barrel exports

Modified: core-plugins/index.ts

  • Added exports for shortcodes plugin, editor scripts, and shared utilities
  • Added 'shortcodes' to CORE_PLUGIN_IDS

How It Works

Editor Integration Flow

  1. Plugins export self-contained HTML (styles + scripts) via get*BlotScript() / get*TinyMceScript()
  2. Host app injects these into admin content edit pages via afterAuth middleware
  3. Scripts auto-detect which editor is active (Quill or TinyMCE) and register accordingly
  4. Tokens render as styled chips in the editor; serialized back to {key} / [[name]] syntax on save

Quill Approach

  • Custom Embed blots (VariableBlot, ShortcodeBlot) registered via Quill.register()
  • Proxy wraps Quill constructor to inject custom formats into the whitelist
  • Toolbar buttons added via enhancer polling (waits for Quill instances to initialize)
  • text-change handler serializes chips → tokens in hidden input

TinyMCE Approach

  • tinymce.PluginManager.add() — the official TinyMCE plugin API
  • Server-side HTML replacement injects button names into toolbar + plugins arrays
  • SetContent handler converts {key} → chip spans; GetContent handler reverses
  • Chip CSS injected into editor iframe via editor.on('init')

Content Resolution

  • Variables resolved at priority 50 (synchronous string replacement)
  • Shortcodes resolved at priority 60 (async handler execution)
  • Opt-out: ?resolve_variables=false, ?resolve_shortcodes=false

Testing

All changes were developed and tested against a full SonicJS instance with:

  • 21 Quill editor E2E tests passing (variable + shortcode blots)
  • 9 content API resolution tests passing
  • TinyMCE PluginManager integration verified

Related

…des plugins (SonicJs-Org#756)

Implements Part 2 (Rich Text Inline Tokens) from SonicJs-Org#719:

- Enhanced global-variables-plugin with full CRUD admin page, Quill blots
  (blue chips), TinyMCE PluginManager integration, and editor toggle
- New shortcodes-plugin with [[shortcode]] syntax, handler registry,
  CRUD admin, live preview, Quill blots (purple chips), and TinyMCE support
- Shared editor utilities: Quill constructor Proxy, searchable picker
  dropdown, TinyMCE PluginManager approach, admin HTML template
- Content resolution: variables (priority 50) → shortcodes (priority 60)
- 5 built-in shortcode handlers: current_date, phone_link, cta_button,
  plan_count, provider_rating

Closes SonicJs-Org#719
Extends SonicJs-Org#743

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cp-bwg
Copy link
Copy Markdown
Author

cp-bwg commented Apr 8, 2026

Note: Filed #758 about the global-variables plugin from PR #743 having dead routes — PluginBuilder.addRoute() stores metadata but nothing mounts the Hono handlers into the running app. This PR includes the working pattern (manual route mounting via exported Hono handlers + afterAuth middleware for editor script injection).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Rich text editor integration for Global Variables & Shortcodes plugins Feature: Dynamic content variables / inline tokens in rich text

1 participant