Section Node Type

Category: Structural • Detailed implementation guide with view integration notes

Schema Definition

Schema definition for the Section node type:

{
  section: {
    content: 'block+',
    group: 'block',
    attrs: {
      level: { default: 1 }
    },
  }
}

Model Representation

Example model representation:

{
  type: 'section',
  attrs: { level: 1 },
  children: [
    {
      type: 'heading',
      level: 2,
      children: [{ type: 'text', text: 'Section Title' }]
    },
    {
      type: 'paragraph',
      children: [{ type: 'text', text: 'Section content' }]
    }
  ]
}

HTML Serialization

Converting model to HTML:

function serializeSection(node) {
  return '<section data-level="' + node.attrs.level + '">' + 
         serializeChildren(node.children) + '</section>';
}

HTML Deserialization

Parsing HTML to model:

function parseSection(domNode) {
  return {
    type: 'section',
    attrs: { level: parseInt(domNode.getAttribute('data-level')) || 1 },
    children: Array.from(domNode.childNodes)
      .map(node => parseNode(node))
      .filter(Boolean)
  };
}

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 section
const section = document.createElement('section');
section.setAttribute('data-level', node.attrs.level);
section.contentEditable = 'true';
node.children.forEach(child => {
  section.appendChild(renderNode(child));
});

Common Issues

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

Common issues and solutions:

// Issue: Section nesting
// Solution: Handle nested sections
function validateSectionNesting(section, parent) {
  const level = parseInt(section.getAttribute('data-level'));
  const parentLevel = parent ? parseInt(parent.getAttribute('data-level')) : 0;
  return level > parentLevel;
}

// Issue: Section structure
// Solution: Ensure proper section structure
function validateSectionStructure(section) {
  // Ensure section has at least one heading
  return section.querySelector('h1, h2, h3, h4, h5, h6') !== null;
}

Implementation

Complete implementation example:

class SectionNode {
  constructor(attrs, children) {
    this.type = 'section';
    this.attrs = { level: attrs?.level || 1 };
    this.children = children || [];
  }
  
  toDOM() {
    const section = document.createElement('section');
    section.setAttribute('data-level', this.attrs.level);
    this.children.forEach(child => {
      section.appendChild(child.toDOM());
    });
    return section;
  }
  
  static fromDOM(domNode) {
    return new SectionNode(
      { level: parseInt(domNode.getAttribute('data-level')) || 1 },
      Array.from(domNode.childNodes)
        .map(node => parseNode(node))
        .filter(Boolean)
    );
  }
}