Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/johnfactotum/foliate-js/llms.txt

Use this file to discover all available pages before exploring further.

textWalker bridges string-based operations and DOM Range objects. It walks the text nodes of a Range, Document, or DocumentFragment, collects their string values into an array, and exposes a makeRange factory so that any index and offset computed on those strings can be converted back into a real DOM Range. This is the mechanism that lets search.js run Intl.Segmenter and Intl.Collator operations over document text while still returning selectable ranges. It is also used internally for text-to-speech segmentation.

Import

import { textWalker } from './foliate-js/text-walker.js'

textWalker(node, func, filterFunc?)

A generator function. Walks all text nodes within node, passes them to func, and yields whatever func yields.
node
Range | Document | DocumentFragment
required
The DOM node or range to walk. When a Range is passed, only text nodes within that range are collected. When a Document or DocumentFragment is passed, all text nodes in the document body are collected.
func
function
required
A generator function called with (strings, makeRange):
  • strings — an array of strings, one per text node (using the node’s nodeValue, or '' for empty nodes).
  • makeRange(startIndex, startOffset, endIndex, endOffset) — a factory that constructs a DOM Range from indices and offsets into the strings array.
func should yield results; textWalker re-yields them to the caller.
filterFunc
function
An optional custom node filter for the internal TreeWalker. Same signature as a TreeWalker acceptNode filter: (node: Node) => NodeFilter.FILTER_ACCEPT | NodeFilter.FILTER_REJECT | NodeFilter.FILTER_SKIP. When omitted, <script> and <style> elements are rejected and all other elements are skipped (only text nodes are accepted).
Yields whatever values func yields.

makeRange(startIndex, startOffset, endIndex, endOffset)

The factory passed as the second argument to func. Creates a DOM Range anchored to the text nodes collected during the walk.
startIndex
number
required
Index into the strings array for the range start.
startOffset
number
required
Character offset within strings[startIndex].
endIndex
number
required
Index into the strings array for the range end.
endOffset
number
required
Character offset within strings[endIndex].
Returns a DOM Range with its start and end set to the corresponding text nodes and offsets in the live document.

Examples

Word segmentation

Segment all text in a document into words and get a DOM Range for each word:
import { textWalker } from './foliate-js/text-walker.js'

function* getWordRanges(doc) {
    yield* textWalker(doc, function* (strings, makeRange) {
        const segmenter = new Intl.Segmenter('en', { granularity: 'word' })
        const str = strings.join('')

        let strIndex = 0
        let charCount = 0

        // Build a map from string position → [arrayIndex, offsetInNode]
        const positions = []
        for (let i = 0; i < strings.length; i++) {
            for (let j = 0; j < strings[i].length; j++) {
                positions.push([i, j])
            }
        }

        for (const { index, segment, isWordLike } of segmenter.segment(str)) {
            if (!isWordLike) continue
            const [startIndex, startOffset] = positions[index]
            const end = index + segment.length
            const [endIndex, endOffset] = positions[end - 1]
            yield makeRange(startIndex, startOffset, endIndex, endOffset + 1)
        }
    })
}

for (const range of getWordRanges(document)) {
    console.log(range.toString())
}

Searching within a Range

Pass a Range instead of a Document to restrict the walk to a specific region:
const selection = window.getSelection()
if (selection.rangeCount) {
    const selectedRange = selection.getRangeAt(0)
    for (const result of textWalker(selectedRange, function* (strings, makeRange) {
        // strings contains only text within the selection
        const joined = strings.join('')
        const idx = joined.indexOf('example')
        if (idx > -1) {
            // resolve back to a DOM Range
            // (simplified: assumes single text node)
            yield makeRange(0, idx, 0, idx + 'example'.length)
        }
    })) {
        console.log('found at', result)
    }
}

Notes

  • textWalker is a generator — the internal walk and func are both executed lazily as you consume the iterator.
  • The default filter rejects <script> and <style> subtrees entirely and skips all other elements, so only text and CDATA nodes reach func.
  • strings and the corresponding DOM nodes remain in the same order, so strings[i] always corresponds to the i-th text node collected during the walk.

Build docs developers (and LLMs) love