Respectful contenteditable: avoids <div>, respects white-space: pre* styles line breaks
npm install @itrocks/contenteditable




Respectful `` ` document.querySelectorAll('[contenteditable]') More examples are available in the demo This feature manages a contenteditable The last line break is preserved as well. The line break characters inserted in your contenteditable Any content ending with a line break will have a trailing This module deliberately avoids inserting block-level elements such as This makes the editable content: The following properties and methods are publicly available in the The element associated with the Applies the Invokes activate() for initialisation. Starts a mutation observer to: #### Parameters - Sets the Enables a keydown event listener Determines and returns the current line break string used for your Creates a node that matches the current line break string. Removes the Deactivates the now unnecessary If the value contains no line break, removes the trailing Handles the keydown event #### Extending This method is designed to be extensible #### Why extend 2. Avoid unintended interference: #### Example: Preventing multiline input using AOP The following example demonstrates how to extend #### Key Points - By overriding This makes it easier to apply different behaviours to individual Returns the effective value of the edited content.contenteditable: avoids , respects white-space: pre* styles line breaks.Installation
bash`
npm install @itrocks/contenteditableUsage
ts
import { ContentEditable } from '@itrocks/contenteditable'
.forEach(element => new ContentEditable(element))
` folder of the
GitHub repository.Behaviour
element during typing to maintain clean and consistent text.$3
elementwhite-space
depend on its style attribute:pre
- , pre-line or pre-wrap: inserts a \n character,white-space
- other values result in a element. added to ensure proper display in your browser.$3
inside the editable content.contenteditable elements tend to introduce wrappers when handling line breaks,Enter
especially when pressing .@itrocks/contenteditable
This leads to inconsistent DOM structures, harder text processing,
and unexpected rendering differences across browsers. enforces a simpler and predictable model:\n
- Line breaks are represented only by newline characters () when the computed white-space starts with pre,
elements otherwiseContentEditable
- No block-level elements are created inside the editable content
- The resulting DOM remains flat and text-oriented
- easier to parse and serialise
- consistent across browsers
- closer to plain text semantics while preserving visual line breaksContentEditable API
class.`$3
ts`
element: HTMLEditableElementContentEditable,HTMLEditableElement
extended as an with an editable property referencing the ContentEditable instance.`$3
ts`
new ContentEditable(element)@itrocks/contenteditable feature to an element.contenteditable
- automatically invoke deactivate() when the attribute is removed,contenteditable
- automatically invoke activate() when the attribute is re-added.element An HTMLElement to apply the feature to.`$3
ts`
activate()contenteditable attribute on your element if it's not already set,`
to keep line breaks in sync with a clean content structure following the
line break matching white-space rule.$3
ts`
br()contenteditable element,`
in accordance with the line break matching white-space rule.$3
ts`
brNode()`
Result is either a TextNode containing '\n'
or an HTMLBRElement.$3
ts`
deactivate()contenteditable attribute from your element.
keydown event listener..`$3
ts`
onKeyDown(event)contenteditable
for the element, ensuring the correct behaviour when the 'Enter' key is pressed.'Enter'
By default, this method determines the appropriate action for the keyonKeyDown
based on the library's implementation of line break management.onKeyDown
using Aspect-Oriented Programming (AOP) principles.
Developers can intercept and augment the behaviour of to customize keyboard event handlingonKeyDown
while carefully managing execution priority relative to the library's default behaviour.
This extension can be performed before, after, or even instead of the default behaviour. instead of adding a keydown listener?keydownaddEventListener
event listener via does not provide fine-grained control over execution priorityonKeyDown
relative to the library's built-in handling. Extending allows you to execute your logic either before,'Enter'
after, or instead of the library's processing of the event.
Preventing the library's default key behaviour by stopping event propagationevent.stopPropagation()
( or event.preventDefault())onKeyDown
may inadvertently interfere with other components or listeners unrelated to this library.
By extending , you ensure your changes are isolated and do not disrupt other listeners.onKeyDown for a specific ContentEditable instance'Enter'
to prevent the default behaviour of the key when the element does not have a data-multiline attribute:`ts`
const contentEditable = new ContentEditable(document.querySelector('#my-editable'))
const superOnKeyDown = contentEditable.onKeyDown
contentEditable.onKeyDown = function (event: KeyboardEvent): void {
if ((event.key === 'Enter') && !this.element?.hasAttribute('data-multiline')) {
event.preventDefault()
return
}
superOnKeyDown.call(this, event)
}onKeyDown, you can implement custom behaviours tailored to your requirements.superOnKeyDown
- Ensure you call the original method () when appropriate to preserve the default functionality,contentEditable
unless you intend to completely replace it.
- This approach provides precise control over execution order without impacting unrelated components or listeners.
- Using this pattern, multiple plugins can safely and independently modify the behaviour of the same instance. instances`
without relying on inheritance or risking conflicts with other plugins.$3
ts`
value()innerHTML
This corresponds to the of the content,
excluding the trailing
` added to display the final empty line in the browser
(see Line break matching white-space rule).