Mention Node Type

Category: Custom • Detailed implementation guide with view integration notes

Schema Definition

Schema definition for the Mention node type:

{
  mention: {
    inline: true,
    attrs: {
      id: { default: '' },
      label: { default: '' }
    },
  }
}

Model Representation

Example model representation:

{
  type: 'mention',
  attrs: {
    id: 'user123',
    label: '@username'
  }
}

HTML Serialization

Converting model to HTML:

function serializeMention(node) {
  return '<span data-type="mention" data-id="' + escapeHtml(node.attrs.id) + 
         '">' + escapeHtml(node.attrs.label) + '</span>';
}

HTML Deserialization

Parsing HTML to model:

function parseMention(domNode) {
  return {
    type: 'mention',
    attrs: {
      id: domNode.getAttribute('data-id') || '',
      label: domNode.textContent || ''
    }
  };
}

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 mention
const mention = document.createElement('span');
mention.setAttribute('data-type', 'mention');
mention.setAttribute('data-id', node.attrs.id);
mention.textContent = node.attrs.label;
mention.className = 'mention';
mention.contentEditable = 'false'; // Mentions are typically not directly editable

Common Issues

Common Pitfalls: These are issues frequently encountered when implementing this node type. Review carefully before implementation.

Common issues and solutions:

// Issue: Mention autocomplete
// Solution: Implement mention autocomplete
function handleMentionInput(e) {
  const query = e.target.value;
  if (query.startsWith('@')) {
    showMentionSuggestions(query.slice(1));
  }
}

// Issue: Mention deletion
// Solution: Handle mention deletion as a unit
function handleMentionDeletion(mention) {
  // Delete entire mention, not just part of it
  mention.remove();
}

Implementation

Complete implementation example:

class MentionNode {
  constructor(attrs) {
    this.type = 'mention';
    this.attrs = {
      id: attrs?.id || '',
      label: attrs?.label || ''
    };
  }
  
  toDOM() {
    const mention = document.createElement('span');
    mention.setAttribute('data-type', 'mention');
    mention.setAttribute('data-id', this.attrs.id);
    mention.textContent = this.attrs.label;
    mention.className = 'mention';
    return mention;
  }
  
  static fromDOM(domNode) {
    return new MentionNode({
      id: domNode.getAttribute('data-id') || '',
      label: domNode.textContent || ''
    });
  }
}