Schema Definition
Schema definition for the Embed node type:
{
embed: {
group: 'block',
attrs: {
url: { default: '' },
type: { default: 'unknown' }
},
}
}Model Representation
Example model representation:
{
type: 'embed',
attrs: {
url: 'https://example.com/embed',
type: 'youtube'
}
}HTML Serialization
Converting model to HTML:
function serializeEmbed(node) {
return '<div data-type="embed" data-embed-type="' + node.attrs.type +
'" data-url="' + escapeHtml(node.attrs.url) + '"></div>';
}HTML Deserialization
Parsing HTML to model:
function parseEmbed(domNode) {
return {
type: 'embed',
attrs: {
url: domNode.getAttribute('data-url') || '',
type: domNode.getAttribute('data-embed-type') || 'unknown'
}
};
}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 embed
const embed = document.createElement('div');
embed.setAttribute('data-type', 'embed');
embed.setAttribute('data-embed-type', node.attrs.type);
embed.setAttribute('data-url', node.attrs.url);
embed.contentEditable = 'false'; // Embeds are typically renderedCommon Issues
Common Pitfalls: These are issues frequently encountered when implementing this node type. Review carefully before implementation.
Common issues and solutions:
// Issue: Embed URL validation
// Solution: Validate embed URLs
function validateEmbedUrl(url, type) {
const patterns = {
youtube: /youtube.com|youtu.be/,
vimeo: /vimeo.com/,
twitter: /twitter.com|tweet/
};
return patterns[type]?.test(url) || false;
}
// Issue: Embed type detection
// Solution: Auto-detect embed type from URL
function detectEmbedType(url) {
if (/youtube|youtu.be/.test(url)) return 'youtube';
if (/vimeo/.test(url)) return 'vimeo';
if (/twitter|tweet/.test(url)) return 'twitter';
return 'unknown';
}Implementation
Complete implementation example:
class EmbedNode {
constructor(attrs) {
this.type = 'embed';
this.attrs = {
url: attrs?.url || '',
type: attrs?.type || 'unknown'
};
}
toDOM() {
const embed = document.createElement('div');
embed.setAttribute('data-type', 'embed');
embed.setAttribute('data-embed-type', this.attrs.type);
embed.setAttribute('data-url', this.attrs.url);
return embed;
}
static fromDOM(domNode) {
return new EmbedNode({
url: domNode.getAttribute('data-url') || '',
type: domNode.getAttribute('data-embed-type') || 'unknown'
});
}
}