docs/guides/Custom-HTML-parser.md
If your GrapesJS integration needs to parse HTML in environments where DOM APIs are not available, you can register a custom HTML code parser and let GrapesJS compile the returned parsed nodes into components.
This is useful for:
::: warning This guide requires GrapesJS v0.23.1 or higher :::
[[toc]]
Code parsers are managed by the Parser module.
const { Parser } = editor;
Parser.addParserCode(
'my-parser',
(input) => {
return [
{
nodeType: 1,
tagName: 'section',
attributes: { class: 'hero' },
childNodes: [{ nodeType: 3, textContent: 'Hello world' }],
},
];
}
);
The parser function must always return an array of parsed nodes.
You can select the active parser globally:
Parser.parserCode = 'my-parser';
const result = Parser.parseHtml('<section>Hello world</section>');
Or for a single call:
const result = Parser.parseHtml('<section>Hello world</section>', {
parserCode: 'my-parser',
});
Passing parserCode: '' forces the built-in DOM parser path for that call.
Custom parsers return nodes shaped like this:
interface ParsedNode {
nodeType?: number;
tagName?: string;
namespaceURI?: string;
attributes?: Record<string, string>;
childNodes?: ParsedNode[];
textContent?: string;
}
Supported node types in the current implementation are:
1 for elements3 for text nodes8 for comments9 for documents11 for document fragmentsWhen asDocument: true is used, GrapesJS normalizes the parser output to a document-like root so root, head, and body can still be compiled.
For headless parsing, component types can implement isParsedNode:
editor.Components.addType('my-component', {
isParsedNode(node, opts) {
if (node.tagName === 'my-component') {
return { type: 'my-component' };
}
},
});
When parserCode is active, isParsedNode is preferred over isComponent.
isComponent fallbackExisting components that only implement isComponent continue to work with parserCode.
GrapesJS passes a read-only synthetic element that exposes the most common DOM-like properties:
nodeTypetagNamenodeNamenamespaceURItextContentnodeValueparentNodechildNodeschildrengetAttributehasAttributeIf you need more DOM-like helpers, extend the base synthetic element:
editor.Parser.config.customSyntheticElement = (SyntheticElement) =>
class MySyntheticElement extends SyntheticElement {
get foo() {
return this.getAttribute('data-foo') || '';
}
};
You can inspect and manage the registry at runtime:
const parser = Parser.getParserCode('my-parser');
const removed = Parser.removeParserCode('my-parser');
const registry = Parser.parsersCode;
Removing the selected parser clears Parser.parserCode.