Install
Works with Drupal: ^11Using Composer to manage Drupal site dependencies
Alternative installation files
Release notes
Microedit lets authorized users highlight a word, phrase, or sentence in a node's body and edit its whole containing text block in a CKEditor 5 modal. It keeps the original block's inline HTML (<strong>, <em>, links, etc.) intact. The originally highlighted phrase is shown with the same pale-yellow background used for the post-save page highlight. The editor highlight uses the browser's CSS Custom Highlight API and is never inserted into saved HTML.
Requirements
- Drupal 11.
- The node
bodyfield with a text format that uses CKEditor 5.
Workflow
- Select part of a paragraph, heading or another supported text block on a node's canonical page. Triple-clicking a paragraph also works.
- The full block to be edited receives a temporary light-grey text background while the Edit button is visible. The preview disappears when you clear the selection or open the dialog. Click the small Edit button. The whole block opens in the modal, with existing markup preserved.
- The original selected passage is temporarily highlighted pale yellow in the editor; the highlight is not stored and disappears when you start editing.
- Make changes, including new paragraphs and allowed block elements, and click Save text.
- The node is saved with a new revision, the page reloads, and the module attempts to scroll to and highlight the changed text.
Technical behavior
- Supported content blocks include
p,h1–h6,blockquote,pre, leafdivelements, simpleli,dt,dd, andfigcaptionelements. Adivcontaining paragraphs is treated as a structural container, not the edit target. Selections crossing two different editable blocks are rejected. - Before showing the Edit button, the client looks up the selected text and a sufficiently long adjacent literal text fragment only in the unfiltered stored body blocks. It does not compare rendered block contents, use rendered block positions, or trust HTML IDs or source-index attributes.
- The client sends the chosen stored block tag/index/normalized prefix/suffix/length. The server independently finds that same block in the unfiltered body value and verifies the selected phrase occurs in the stored block. Ambiguous or weak matches are rejected.
- A changed body since the dialog opened is rejected via SHA-256 comparison. Server-side edit permissions and text-format access are rechecked during submission.
- Replacement HTML is parsed and takes the place of the complete original block, not just the selected characters. This avoids splitting nested inline elements. For simple list items, the surrounding list and original
<li>attributes remain intact. Edits to structurally complicated nested tables/lists are intentionally limited. - A separate CSS Custom Highlight (
::highlight(microedit-target-block)) previews the entire target block on the page with a light-grey background. It is removed when the selection is cleared or the dialog opens, and never changes saved HTML. - A CSS Custom Highlight (
::highlight(microedit-editor-selection)) temporarily marks the original selection within CKEditor's editable DOM. It does not add spans, marks, CKEditor model attributes, or persisted HTML. In browsers without CSS Custom Highlight API, editing still works but the temporary marking may be absent. - CKEditor's existing format defines which HTML constructs can be edited and retained. Save/reload/scroll, modal focus/Escape, and dialog CSS classes are retained. The outer modal has class
.microedit-modaland the inner form.microedit-dialog.
Caveats
- The module targets only the single-value
bodyfield on canonical node pages and requires CKEditor 5 for that text format. - Drupal text filters may substantially change rendered markup or text; when a block cannot be mapped safely to stored HTML, editing is rejected.
- DOMDocument serialization may normalize HTML entities, whitespace, and element casing across the saved body. Test with embedded media and site-specific markup.
- The yellow highlight is best effort if CKEditor transforms the originally selected text (e.g., whitespace normalization). It is cosmetic only.
CKEditor link visibility
The module scopes link-color styling to the CKEditor editing surface inside the Microedit modal. It makes existing links visibly blue and underlined without changing their saved HTML or the normal site theme.
Stored-body-only selection guard
The original body.value from the node is the only source used to build candidate
editable blocks. No markers or IDs are injected into the text-filter pipeline.
The browser reads the text the user actually selected and nearby contiguous
text as a lookup key into that raw value. It never identifies a source block by
comparing the entire rendered paragraph to a source paragraph. Shortcodes,
BBCode and embedded directives remain part of the raw block loaded into CKEditor.
For safety, blocks with no unique raw-source match are not editable. A minimum
surrounding context is required for long raw paragraphs to avoid allowing a
single common word inside generated content. Some very short or heavily
transformed selections will therefore not offer editing.
Provenance limitation: a browser selection necessarily originates from the
rendered DOM. If a filter generates text that is indistinguishable from a
literal sequence in the original body, raw-string matching alone cannot prove
which node it came from. Absolute exclusion of such generated text requires
integration with the text filter or a separately rendered raw editing surface.
Console diagnostics
Console logging is off by default. To enable selection-decision logs,
set const LOG_DEBUG = true; near the top of js/microedit.js
and clear Drupal caches. Set it back to false to disable the logs.
The manually invoked microeditInspectLinks() diagnostic remains
available if you explicitly call it from the console.