Coralite DOM Structure
Coralite uses a server-side DOM structure that mimics the standard browser DOM but is optimized for static site
generation. This DOM is exposed to developers when writing plugins, specifically in lifecycle hooks like
onPageSet and when processing slots in components.
While the underlying structure is compatible with domhandler, Coralite enhances these nodes with a
standard DOM-like API (getters and setters) to make manipulation more intuitive.
The Coralite DOM consists of several node types, all inheriting from a base node structure:
- CoraliteElement (Type 1): Represents HTML tags (e.g.,
<div>,<span>). - CoraliteTextNode (Type 3): Represents text content.
- CoraliteComment (Type 8): Represents HTML comments.
- CoraliteComponentRoot (Type 9): The root node of a document.
- CoraliteDirective (Type 10): Directives like
<!DOCTYPE html>.
Elements are the most common nodes you will interact with. They are standard objects enhanced with the following options:
| Property | Type | Access | Description |
|---|---|---|---|
tagName |
string |
Read/Write | The uppercase tag name of the element (e.g., "DIV"). Setting it updates name (lowercase).
|
nodeName |
string |
Read-only | Same as tagName. |
attributes |
Object |
Read/Write | Key-value pair of attributes. Alias for attribs. |
childNodes |
Array |
Read/Write | Live collection (array) of child nodes. Alias for children. |
parentNode |
Node |
Read/Write | The parent node of this element. Alias for parent. |
textContent |
string |
Read/Write | Getting returns concatenated text of all descendants. Setting replaces all children with a single text node. |
id |
string |
Read/Write | Convenience accessor for the id attribute. |
className |
string |
Read/Write | Convenience accessor for the class attribute. |
firstChild |
Node|null |
Read-only | The first child node. |
lastChild |
Node|null |
Read-only | The last child node. |
previousSibling |
Node|null |
Read-only | The node immediately preceding this one. |
nextSibling |
Node|null |
Read-only | The node immediately following this one. |
Text nodes represent the text content within elements.
| Property | Type | Access | Description |
|---|---|---|---|
data |
string |
Read/Write | The actual text content. |
nodeValue |
string |
Read/Write | Alias for data. |
textContent |
string |
Read/Write | Alias for data. |
parentNode |
Node |
Read/Write | The parent node. |
You can traverse the DOM tree using the relationship options defined above.
// Example: Walking the tree
function walk(node) {
console.log(node.nodeName);
if (node.childNodes) {
node.childNodes.forEach(child => walk(child));
}
}
// Example: Finding a sibling
if (element.nextSibling) {
console.log('Next element is:', element.nextSibling.tagName);
}
Since Coralite nodes are JavaScript objects, you can manipulate them directly. However, for adding or removing
nodes, you interact with the childNodes (or children) array.
// Change text content
element.textContent = "New text content";
// Change an attribute
element.attributes.class = "active";
// element.setAttribute('data-id', '123'); // Error: setAttribute is not a function
// Use the attributes object (or its alias attribs) directly:
element.attributes['data-id'] = '123';
Coralite does not implement methods like appendChild, removeChild or setAttribute. Instead, use
standard Array methods on childNodes and direct access to attributes.
// Append a child
parent.childNodes.push(newElement);
// Remove a child
const index = parent.childNodes.indexOf(childToRemove);
if (index > -1) {
parent.childNodes.splice(index, 1);
}
// Insert before
parent.childNodes.splice(index, 0, newElement);
To create new nodes that are correctly enhanced with the Coralite API, use the helper functions exported by the
coralite or coralite/utils package.
import { createElement, createTextNode } from 'coralite/utils';
// Create a new DIV attached to parent
const newDiv = createElement({
name: 'div',
attributes: { class: 'container' },
parent: parentElement
});
// Create a text node attached to the new DIV
createTextNode('Hello World', newDiv);
name(string): The tag name (e.g., 'div').attributes(object): Key-value pairs of attributes.parent(Node): The parent node to attach to.
You will encounter the Coralite DOM in several places when developing plugins.
In hooks like onPageSet, you receive the full document tree.
// coralite.config.js
definePlugin({
name: 'my-plugin',
onPageSet: async (context) => {
const root = context.elements.root;
// Traverse root.childNodes to find and modify elements
}
})
When using defineComponent, the slots block allows you to intercept and modify
slot content. The content is passed as an array of DOM nodes.
The slot function can return an array of nodes, a string, null (to clear the slot), or undefined to bypass processing and preserve existing content.
// component.html script
import { defineComponent } from 'coralite'
import { createElement } from 'coralite/utils'
export default defineComponent({
slots: {
default: (slotNodes, state) => {
// Bypass client-side hydration to preserve SSR-rendered content
if (typeof window !== 'undefined') return undefined;
// Example: Wrap content in a div (Server-side only)
const wrapper = createElement({
name: 'div',
attributes: { class: 'wrapper' },
parent: null
});
wrapper.children = slotNodes;
slotNodes.forEach(node => node.parent = wrapper);
return [wrapper];
}
}
})