A comprehensive DOM manipulation library providing type-safe, functional utilities for elements, events, properties, and selections.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Tree traversal, element querying, and hierarchical navigation utilities with type-safe parent/child relationships, CSS selector support, and comprehensive search capabilities.
Navigate the DOM tree structure with type-safe relationships and optional filtering.
/**
* Get owner document for any node
* @param element - Node to find document for
* @returns Owner document element
*/
function owner(element: SugarElement<Node>): SugarElement<Document>;
/**
* Get document or owner document (handles both cases)
* @param dos - Document or node to get document from
* @returns Document element
*/
function documentOrOwner(dos: SugarElement<Node>): SugarElement<Document>;
/**
* Get document element (html tag) for node
* @param element - Node to find document element for
* @returns Document element (html tag)
*/
function documentElement(element: SugarElement<Node>): SugarElement<HTMLElement>;
/**
* Get default view (window) for document
* @param element - Node to find window for
* @returns Window element
*/
function defaultView(element: SugarElement<Node>): SugarElement<Window>;Navigate up the DOM tree to find parents and ancestors.
/**
* Get immediate parent of element
* @param element - Element to get parent of
* @returns Parent element if it exists
*/
function parent(element: SugarElement<Node>): Optional<SugarElement<Node & ParentNode>>;
/**
* Get parent node (same as parent but different type)
* @param element - Element to get parent node of
* @returns Parent node if it exists
*/
function parentNode(element: SugarElement<Node>): Optional<SugarElement<Node>>;
/**
* Get parent element (skips non-element parents)
* @param element - Element to get parent element of
* @returns Parent element if it exists
*/
function parentElement(element: SugarElement<Node>): Optional<SugarElement<HTMLElement>>;
/**
* Get all parents up to document or optional root
* @param element - Starting element
* @param isRoot - Optional predicate to define root element
* @returns Array of parent elements from immediate parent to root
*/
function parents(element: SugarElement<Node>, isRoot?: (e: SugarElement<Node>) => boolean): SugarElement<Node>[];
/**
* Get offset parent for positioning calculations
* @param element - Element to find offset parent for
* @returns Offset parent element if found
*/
function offsetParent(element: SugarElement<HTMLElement>): Optional<SugarElement<HTMLElement>>;Usage Examples:
import { Traverse, SugarElement } from "@ephox/sugar";
const element = SugarElement.fromTag('span');
// Navigate to parent
const parentOpt = Traverse.parent(element);
parentOpt.each(parent => {
console.log('Parent tag:', parent.dom.tagName);
});
// Get all ancestors up to body
const ancestors = Traverse.parents(element, (e) => e.dom.tagName.toLowerCase() === 'body');
console.log('Ancestor chain:', ancestors.map(e => e.dom.tagName));
// Find offset parent for positioning
if (SugarNode.isHTMLElement(element)) {
const offsetParentOpt = Traverse.offsetParent(element);
offsetParentOpt.each(offsetParent => {
console.log('Offset parent:', offsetParent.dom.tagName);
});
}Navigate between sibling elements at the same level.
/**
* Get previous sibling element
* @param element - Element to find sibling for
* @returns Previous sibling if it exists
*/
function prevSibling(element: SugarElement<Node>): Optional<SugarElement<Node & ChildNode>>;
/**
* Get next sibling element
* @param element - Element to find sibling for
* @returns Next sibling if it exists
*/
function nextSibling(element: SugarElement<Node>): Optional<SugarElement<Node & ChildNode>>;
/**
* Get all previous siblings in document order
* @param element - Element to find siblings for
* @returns Array of previous siblings (nearest to furthest)
*/
function prevSiblings(element: SugarElement<Node>): SugarElement<Node & ChildNode>[];
/**
* Get all next siblings in document order
* @param element - Element to find siblings for
* @returns Array of next siblings (nearest to furthest)
*/
function nextSiblings(element: SugarElement<Node>): SugarElement<Node & ChildNode>[];
/**
* Get all siblings of element (excluding element itself)
* @param element - Element to find siblings for
* @returns Array of all sibling elements
*/
function siblings(element: SugarElement<Node>): SugarElement<Node>[];Access and navigate child elements with index-based operations.
/**
* Get all direct children of element
* @param element - Parent element
* @returns Array of child elements
*/
function children(element: SugarElement<Node>): SugarElement<Node & ChildNode>[];
/**
* Get child at specific index
* @param element - Parent element
* @param index - Zero-based index of child to retrieve
* @returns Child element at index if it exists
*/
function child(element: SugarElement<Node>, index: number): Optional<SugarElement<Node & ChildNode>>;
/**
* Get first child of element
* @param element - Parent element
* @returns First child if it exists
*/
function firstChild(element: SugarElement<Node>): Optional<SugarElement<Node & ChildNode>>;
/**
* Get last child of element
* @param element - Parent element
* @returns Last child if it exists
*/
function lastChild(element: SugarElement<Node>): Optional<SugarElement<Node & ChildNode>>;
/**
* Get total number of child nodes
* @param element - Parent element
* @returns Count of child nodes
*/
function childNodesCount(element: SugarElement<Node>): number;
/**
* Check if element has any child nodes
* @param element - Element to check
* @returns True if element has children
*/
function hasChildNodes(element: SugarElement<Node>): boolean;
/**
* Find index of element within its parent
* @param element - Element to find index for
* @returns Zero-based index within parent, if element has parent
*/
function findIndex(element: SugarElement<Node>): Optional<number>;Usage Examples:
import { Traverse, SugarElement } from "@ephox/sugar";
const list = SugarElement.fromTag('ul');
// ... add some list items ...
// Access children
const children = Traverse.children(list);
console.log(`List has ${children.length} items`);
// Get specific child
const firstItem = Traverse.firstChild(list);
const thirdItem = Traverse.child(list, 2);
// Navigate siblings
firstItem.each(item => {
const nextItem = Traverse.nextSibling(item);
nextItem.each(next => {
console.log('Next item found');
});
});
// Find element position
firstItem.each(item => {
const index = Traverse.findIndex(item);
console.log('Item index:', index.getOr(-1));
});Query elements using CSS selectors with scoping and filtering capabilities.
/**
* Find first element matching CSS selector within scope
* @param selector - CSS selector string
* @param scope - Element to search within
* @returns First matching element if found
*/
function one(selector: string, scope: SugarElement<ParentNode>): Optional<SugarElement<Element>>;
/**
* Find all elements matching CSS selector within scope
* @param selector - CSS selector string
* @param scope - Element to search within
* @returns Array of matching elements
*/
function all(selector: string, scope: SugarElement<ParentNode>): SugarElement<Element>[];
/**
* Check if element matches CSS selector
* @param element - Element to test
* @param selector - CSS selector to test against
* @returns True if element matches selector
*/
function is(element: SugarElement<Element>, selector: string): boolean;Usage Examples:
import { Selectors, SugarElement } from "@ephox/sugar";
const container = SugarElement.fromTag('div');
// ... populate with content ...
// Find specific elements
const button = Selectors.one('.submit-btn', container);
const inputs = Selectors.all('input[type="text"]', container);
// Check element matches
button.each(btn => {
if (Selectors.is(btn, '.primary')) {
console.log('Button is primary style');
}
});
// Find nested elements
const nestedSpans = Selectors.all('div > span', container);
console.log(`Found ${nestedSpans.length} direct span children of divs`);Predicate-based searching with ancestor/descendant operations.
/**
* Find ancestor element matching predicate
* @param element - Starting element
* @param predicate - Function to test elements
* @param isRoot - Optional root boundary function
* @returns First ancestor matching predicate
*/
function ancestor(
element: SugarElement<Node>,
predicate: (e: SugarElement<Node>) => boolean,
isRoot?: (e: SugarElement<Node>) => boolean
): Optional<SugarElement<Node>>;
/**
* Find descendant element matching predicate
* @param scope - Element to search within
* @param predicate - Function to test elements
* @returns First descendant matching predicate
*/
function descendant(
scope: SugarElement<Node>,
predicate: (e: SugarElement<Node>) => boolean
): Optional<SugarElement<Node>>;
/**
* Find all descendant elements matching predicate
* @param scope - Element to search within
* @param predicate - Function to test elements
* @returns Array of descendants matching predicate
*/
function descendants(
scope: SugarElement<Node>,
predicate: (e: SugarElement<Node>) => boolean
): SugarElement<Node>[];
/**
* Find closest ancestor (including self) matching predicate
* @param element - Starting element
* @param predicate - Function to test elements
* @param isRoot - Optional root boundary function
* @returns Closest element (including self) matching predicate
*/
function closest(
element: SugarElement<Node>,
predicate: (e: SugarElement<Node>) => boolean,
isRoot?: (e: SugarElement<Node>) => boolean
): Optional<SugarElement<Node>>;
/**
* Find sibling element matching predicate
* @param element - Starting element
* @param predicate - Function to test elements
* @returns First sibling matching predicate
*/
function sibling(
element: SugarElement<Node>,
predicate: (e: SugarElement<Node>) => boolean
): Optional<SugarElement<Node>>;Usage Examples:
import { PredicateExists, PredicateFilter, PredicateFind, SugarElement, SugarNode } from "@ephox/sugar";
const startElement = SugarElement.fromTag('span');
// Find ancestor with specific class
const form = Search.ancestor(startElement, (e) =>
SugarNode.isElement(e) && e.dom.classList.contains('form')
);
// Find descendant by tag name
const input = Search.descendant(form.getOrDie(), (e) =>
SugarNode.name(e) === 'input'
);
// Find all buttons in container
const buttons = Search.descendants(container, (e) =>
SugarNode.name(e) === 'button'
);
// Find closest table cell
const cell = Search.closest(startElement, (e) =>
['td', 'th'].includes(SugarNode.name(e))
);
// Find next form field sibling
const nextField = Search.sibling(input.getOrDie(), (e) =>
SugarNode.isElement(e) &&
['input', 'select', 'textarea'].includes(SugarNode.name(e))
);Navigate to specific positions within the DOM tree structure.
/**
* Navigate to deepest leaf element at specific offset
* @param element - Starting element
* @param offset - Character or child offset
* @returns Leaf element and adjusted offset
*/
function leaf(element: SugarElement<Node>, offset: number): ElementAndOffset<Node>;
interface ElementAndOffset<E> {
readonly element: SugarElement<E>;
readonly offset: number;
}Common predicates for element searching and filtering.
/**
* Predicate to match elements by tag name
* @param name - Tag name to match (case-insensitive)
* @returns Predicate function
*/
function byTag(name: string): (element: SugarElement<Node>) => boolean;
/**
* Predicate to match elements by CSS class
* @param className - CSS class name to match
* @returns Predicate function
*/
function byClass(className: string): (element: SugarElement<Node>) => boolean;
/**
* Predicate to match elements by attribute presence
* @param attribute - Attribute name to check for
* @returns Predicate function
*/
function byAttribute(attribute: string): (element: SugarElement<Node>) => boolean;
/**
* Predicate to match elements by attribute value
* @param attribute - Attribute name
* @param value - Attribute value to match
* @returns Predicate function
*/
function byAttributeValue(attribute: string, value: string): (element: SugarElement<Node>) => boolean;Usage Examples:
import { PredicateExists, PredicateFilter, PredicateFind, SugarElement } from "@ephox/sugar";
const container = SugarElement.fromTag('div');
// Use pre-built predicates
const buttons = Search.descendants(container, Predicates.byTag('button'));
const primaryBtns = Search.descendants(container, Predicates.byClass('btn-primary'));
const requiredFields = Search.descendants(container, Predicates.byAttribute('required'));
const emailInputs = Search.descendants(container, Predicates.byAttributeValue('type', 'email'));
// Combine predicates
const requiredEmailInputs = Search.descendants(container, (e) =>
Predicates.byTag('input')(e) &&
Predicates.byAttributeValue('type', 'email')(e) &&
Predicates.byAttribute('required')(e)
);Find elements using CSS selectors with comprehensive querying capabilities.
/**
* Check if element matches CSS selector
* @param element - Element to test
* @param selector - CSS selector to match against
* @returns True if element matches selector
*/
function is(element: SugarElement<Element>, selector: string): boolean;
/**
* Find first element matching selector within scope
* @param scope - Element to search within
* @param selector - CSS selector to match
* @returns First matching element, if found
*/
function one(scope: SugarElement<ParentNode>, selector: string): Optional<SugarElement<Element>>;
/**
* Find all elements matching selector within scope
* @param scope - Element to search within
* @param selector - CSS selector to match
* @returns Array of all matching elements
*/
function all(scope: SugarElement<ParentNode>, selector: string): SugarElement<Element>[];
/**
* Check if any element matching selector exists within scope
* @param scope - Element to search within
* @param selector - CSS selector to match
* @returns True if at least one match exists
*/
function exists(scope: SugarElement<ParentNode>, selector: string): boolean;
/**
* Filter elements by CSS selector
* @param elements - Elements to filter
* @param selector - CSS selector to match
* @returns Array of elements matching selector
*/
function filter(elements: SugarElement<Element>[], selector: string): SugarElement<Element>[];Calculate element positions and create addressable paths within DOM trees.
/**
* Generate address path from root to target element
* @param root - Root element to start from
* @param element - Target element to find path to
* @returns Array of indices representing path, if valid
*/
function generate(root: SugarElement<Node>, element: SugarElement<Node>): Optional<number[]>;
/**
* Follow address path from root element
* @param root - Root element to start from
* @param path - Array of indices to follow
* @returns Element at path location, if valid
*/
function follow(root: SugarElement<Node>, path: number[]): Optional<SugarElement<Node>>;
/**
* Check if element contains any matching child
* @param element - Container element
* @param predicate - Test function for children
* @returns True if any child matches predicate
*/
function has(element: SugarElement<Node>, predicate: ElementPredicate): boolean;
/**
* Check if element contains child matching selector
* @param element - Container element
* @param selector - CSS selector to match
* @returns True if any child matches selector
*/
function hasSelector(element: SugarElement<ParentNode>, selector: string): boolean;Transform-based searching and complex element location strategies.
/**
* Find element by transforming search criteria
* @param scope - Element to search within
* @param predicate - Transform function to apply
* @returns Transformed search result
*/
function scope<T>(scope: SugarElement<Node>, predicate: (e: SugarElement<Node>) => Optional<T>): Optional<T>;
/**
* Search using custom transformation function
* @param element - Starting element
* @param transform - Function to transform search
* @returns Transformed result of search
*/
function custom<T>(element: SugarElement<Node>, transform: (e: SugarElement<Node>) => Optional<T>): Optional<T>;// Position interface for leaf navigation
interface ElementAndOffset<E> {
readonly element: SugarElement<E>;
readonly offset: number;
}
// Common predicate type for element filtering
type ElementPredicate = (element: SugarElement<Node>) => boolean;
// Parent node types for selector queries
type ParentNode = Element | Document | DocumentFragment;Install with Tessl CLI
npx tessl i tessl/npm-ephox--sugar