Schema Definition
Schema definition for the Color mark type:
{
color: {
attrs: {
color: { default: '#000000' }
},
}
}Model Representation
Example model representation:
{
type: 'text',
text: 'Colored text',
marks: [{
type: 'color',
attrs: { color: '#ff0000' }
}]
}HTML Serialization
Converting model to HTML:
function serializeColorMark(text, mark) {
const color = mark.attrs?.color || '#000000';
return '<span style="color: ' + escapeHtml(color) + '">' + text + '</span>';
}HTML Deserialization
Parsing HTML to model:
function extractColorMark(element) {
if (element.tagName === 'SPAN' && element.style.color) {
return {
type: 'color',
attrs: { color: element.style.color }
};
}
return null;
}
function extractColorFromStyle(colorString) {
// Convert rgb/rgba to hex if needed
return colorString;
}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:
// Applying color
function applyColor(color) {
addMark({
type: 'color',
attrs: { color }
});
}
// Color picker integration
function showColorPicker() {
const picker = createColorPicker();
picker.onChange = (color) => {
applyColor(color);
};
}Common Issues
Common Pitfalls: These are issues frequently encountered when implementing this node type. Review carefully before implementation.
Common issues and solutions:
// Issue: Color format normalization
// Solution: Normalize to hex format
function normalizeColor(color) {
if (color.startsWith('rgb')) {
return rgbToHex(color);
}
return color;
}
// Issue: Color with other marks
// Solution: Color can coexist with other marks
function applyColorWithMarks(text, color, otherMarks) {
let html = text;
html = '<span style="color: ' + color + '">' + html + '</span>';
otherMarks.forEach(mark => {
html = wrapWithMark(html, mark);
});
return html;
}Implementation
Complete implementation example:
class ColorMark {
constructor(attrs) {
this.type = 'color';
this.attrs = { color: attrs?.color || '#000000' };
}
toDOM() {
return ['span', { style: 'color: ' + this.attrs.color }, 0];
}
static fromDOM(element) {
if (element.tagName === 'SPAN' && element.style.color) {
return new ColorMark({ color: element.style.color });
}
return null;
}
}