Schema Definition
Schema definition for the Math node type:
{
math: {
group: 'block',
attrs: {
formula: { default: '' },
display: { default: false }
},
}
}Model Representation
Example model representation:
{
type: 'math',
attrs: {
formula: 'E = mc^2',
display: true
}
}HTML Serialization
Converting model to HTML:
function serializeMath(node) {
return '<div data-type="math" data-display="' + node.attrs.display + '">' +
escapeHtml(node.attrs.formula) + '</div>';
}HTML Deserialization
Parsing HTML to model:
function parseMath(domNode) {
return {
type: 'math',
attrs: {
formula: domNode.textContent || '',
display: domNode.getAttribute('data-display') === 'true'
}
};
}View Integration
View Integration Notes: Pay special attention to contenteditable behavior, selection handling, and event management when implementing this node type in your view layer.
View integration code:
// Rendering math
const math = document.createElement('div');
math.setAttribute('data-type', 'math');
math.setAttribute('data-display', node.attrs.display);
math.textContent = node.attrs.formula;
math.contentEditable = 'false'; // Math is typically rendered, not edited directly
// Render with MathJax or KaTeX
function renderMath(element) {
if (window.MathJax) {
MathJax.typesetPromise([element]);
} else if (window.katex) {
katex.render(element.textContent, element, { displayMode: element.getAttribute('data-display') === 'true' });
}
}Common Issues
Common Pitfalls: These are issues frequently encountered when implementing this node type. Review carefully before implementation.
Common issues and solutions:
// Issue: Math rendering library
// Solution: Use MathJax or KaTeX
function initMathRenderer() {
if (window.MathJax) {
MathJax.startup.defaultReady();
}
}
// Issue: Math formula validation
// Solution: Validate LaTeX syntax
function validateMathFormula(formula) {
// Basic validation or use a LaTeX parser
return formula.length > 0;
}Implementation
Complete implementation example:
class MathNode {
constructor(attrs) {
this.type = 'math';
this.attrs = {
formula: attrs?.formula || '',
display: attrs?.display || false
};
}
toDOM() {
const math = document.createElement('div');
math.setAttribute('data-type', 'math');
math.setAttribute('data-display', this.attrs.display);
math.textContent = this.attrs.formula;
return math;
}
static fromDOM(domNode) {
return new MathNode({
formula: domNode.textContent || '',
display: domNode.getAttribute('data-display') === 'true'
});
}
}