Utils for working with text nodes in Ranges.
npm install text-range-utils
The two basic utils are:
You can use these individually, combine them yourself, or use the following composed utils:
getSelectedTextNodes
wrapRangeTextNodes
wrapSelectedTextNodes
See below for details.
Returns all text nodes that intersect with the given range.
type GetTextNodesOptions = {
/** Any text node that is a descendant of one of these tags will be ignored. */
disallowedAncestorTags?: (keyof HTMLElementTagNameMap)[];
};
const range = new Range();
const textNodes = getTextNodesInRange(range, {
disallowedAncestorTags: ["script", "style", "iframe", "noscript"],
});
- Returns all text nodes that intersect with the given selection.
- Handles selections that have multiple ranges (Firefox).
type GetTextNodesOptions = {
/** Any text node that is a descendant of one of these tags will be ignored. */
disallowedAncestorTags?: (keyof HTMLElementTagNameMap)[];
};
const selection = window.getSelection();
if (selection) {
const textNodes = getSelectedTextNodes(selection, {
disallowedAncestorTags: ["script", "style", "iframe", "noscript"],
});
}
- Wraps
node
withwrapperElement
while preserving all other children and sibling relationships. - Ignores non-text nodes.
- Returns a function to undo the wrapping.
type WrapTextNodeOptions = {
/** The character offset to start from (inclusive). If not specified, wraps from beginning of node. */
startOffset?: number;
/** The character to end at (exclusive). If not specified, wraps until end of node. */
endOffset?: number;
};
const wrapper = document.createElement("span");
wrapper.classList.add("wrapper");
const textNode = document.createTextNode("wrap me");
// wrap <span class="wrapper">m</span>e
const unwrap = wrapTextNode(textNode, wrapper, {
startOffset: 5,
endOffset: 6,
});
// wrap me
unwrap();
wrapRangeTextNodes(range: Range, wrapper: HTMLElement, options?: WrapRangeTextNodesOptions): UnwrapFn
- Wraps each text node in
range
with the given wrapper. - Returns a function to undo the wrapping for all text nodes.
type WrapRangeTextNodesOptions = GetTextNodesOptions & {
/** Optional callback to filter which text nodes are wrapped. If this function returns `true`, `node` will be wrapped; else, it will be ignored. */
shouldWrapNode?: (node: Text) => boolean;
}
const range = new Range();
const unwrap = wrapRangeTextNodes(range, wrapper);
wrapSelectedTextNodes(selection: Selection, wrapper: HTMLElement, options?: WrapRangeTextNodesOptions): UnwrapFn
- Wraps each text node in
selection
with the given wrapper. - Returns a function to undo the wrapping for all text nodes.
type WrapRangeTextNodesOptions = GetTextNodesOptions & {
/** Optional callback to filter which text nodes are wrapped. If this function returns `true`, `node` will be wrapped; else, it will be ignored. */
shouldWrapNode?: (node: Text) => boolean;
}
const selection = window.getSelection();
if (selection) {
const unwrap = wrapSelectedTextNodes(selection, wrapper);
}