Flexible configuration interfaces for customizing heading options, view mappings, styling, and behavior. The configuration system allows complete customization of how headings are structured, displayed, and converted.
Main configuration interface for the heading feature that defines available heading options and their properties.
/**
* Configuration interface for heading feature.
*/
interface HeadingConfig {
/** Array of available heading options */
options?: Array<HeadingOption>;
}Usage Examples:
import type { HeadingConfig } from '@ckeditor/ckeditor5-heading';
// Basic configuration
const config: HeadingConfig = {
options: [
{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
{ model: 'heading1', view: 'h2', title: 'Heading 1', class: 'ck-heading_heading1' },
{ model: 'heading2', view: 'h3', title: 'Heading 2', class: 'ck-heading_heading2' }
]
};
ClassicEditor.create(document.querySelector('#editor'), {
plugins: [Heading],
heading: config
});Union type that encompasses all possible heading option configurations.
/**
* Union type for heading option descriptors.
*/
type HeadingOption = HeadingElementOption | HeadingParagraphOption;Configuration for heading elements (H1-H6) with comprehensive customization options.
/**
* Configuration for heading elements (h1-h6).
*/
interface HeadingElementOption {
/** Model element name - predefined or custom heading levels */
model: 'heading1' | 'heading2' | 'heading3' | 'heading4' | 'heading5' | 'heading6' | `heading${string}`;
/** View element definition - HTML element and attributes */
view: ViewElementDefinition;
/** User-readable option title displayed in UI */
title: string;
/** CSS class for dropdown item styling */
class: string;
/** Optional icon for HeadingButtonsUI buttons */
icon?: string;
/** Additional elements to accept during upcast conversion */
upcastAlso?: ArrayOrItem<ViewElementDefinition | MatcherPattern>;
/** Converter priority for handling conflicts */
converterPriority?: 'low' | 'normal' | 'high';
}Usage Examples:
// Standard heading configuration
const headingOption: HeadingElementOption = {
model: 'heading1',
view: 'h2', // Maps to <h2> element
title: 'Heading 1',
class: 'ck-heading_heading1'
};
// Advanced heading with custom view and attributes
const advancedHeading: HeadingElementOption = {
model: 'heading1',
view: {
name: 'h1',
classes: ['main-title', 'highlight'],
attributes: {
'data-level': '1',
'role': 'heading'
}
},
title: 'Main Title',
class: 'ck-heading_main',
icon: '<svg>...</svg>',
converterPriority: 'high'
};
// Custom heading level
const customHeading: HeadingElementOption = {
model: 'headingCustom',
view: {
name: 'h3',
classes: 'custom-heading'
},
title: 'Custom Section',
class: 'ck-heading_custom',
upcastAlso: [
{ name: 'div', classes: 'section-title' }, // Also convert divs with this class
{ name: 'strong', styles: { 'font-size': '1.5em' } } // And large bold text
]
};Configuration for the paragraph option in heading dropdowns.
/**
* Configuration for paragraph option in heading dropdown.
*/
interface HeadingParagraphOption {
/** Model element name - must be 'paragraph' */
model: 'paragraph';
/** User-readable option title displayed in UI */
title: string;
/** CSS class for dropdown item styling */
class: string;
/** Optional icon for HeadingButtonsUI buttons */
icon?: string;
/** Additional elements to accept during upcast conversion */
upcastAlso?: ArrayOrItem<ViewElementDefinition | MatcherPattern>;
}Usage Examples:
// Standard paragraph option
const paragraphOption: HeadingParagraphOption = {
model: 'paragraph',
title: 'Paragraph',
class: 'ck-heading_paragraph'
};
// Custom paragraph with icon and upcast rules
const customParagraph: HeadingParagraphOption = {
model: 'paragraph',
title: 'Normal Text',
class: 'ck-heading_normal',
icon: 'paragraph',
upcastAlso: [
{ name: 'div', classes: 'text-content' },
{ name: 'span', styles: { display: 'block' } }
]
};Minimal Setup:
const minimalConfig = {
heading: {
options: [
{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
{ model: 'heading1', view: 'h1', title: 'Title', class: 'ck-heading_heading1' }
]
}
};Blog/Article Setup:
const blogConfig = {
heading: {
options: [
{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
{ model: 'heading1', view: 'h1', title: 'Article Title', class: 'ck-heading_title' },
{ model: 'heading2', view: 'h2', title: 'Section', class: 'ck-heading_section' },
{ model: 'heading3', view: 'h3', title: 'Subsection', class: 'ck-heading_subsection' }
]
}
};Documentation Setup:
const docsConfig = {
heading: {
options: [
{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
{
model: 'heading1',
view: { name: 'h1', classes: 'doc-title' },
title: 'Document Title',
class: 'ck-heading_doc-title',
converterPriority: 'high'
},
{
model: 'heading2',
view: { name: 'h2', classes: 'section-title' },
title: 'Section',
class: 'ck-heading_section',
icon: 'heading2'
},
{
model: 'heading3',
view: { name: 'h3', classes: 'subsection-title' },
title: 'Subsection',
class: 'ck-heading_subsection',
icon: 'heading3'
},
{
model: 'headingCode',
view: { name: 'h4', classes: 'code-section' },
title: 'Code Section',
class: 'ck-heading_code',
upcastAlso: [
{ name: 'div', classes: 'code-title' }
]
}
]
}
};The view property accepts various formats for maximum flexibility:
Simple String:
view: 'h2' // Creates <h2> elementElement Object:
view: {
name: 'h2',
classes: ['title', 'highlight'],
attributes: {
'data-level': '2',
'role': 'heading'
},
styles: {
'color': 'blue',
'font-weight': 'bold'
}
}Function (Advanced):
view: (modelElement, { writer }) => {
return writer.createContainerElement('h2', {
class: 'dynamic-heading',
'data-id': modelElement.getAttribute('headingId')
});
}The upcastAlso property allows accepting additional HTML patterns during content import:
const flexibleHeading = {
model: 'heading1',
view: 'h2',
title: 'Heading 1',
class: 'ck-heading_heading1',
upcastAlso: [
// Accept divs with title class as heading1
{ name: 'div', classes: 'title' },
// Accept paragraphs with specific styling
{
name: 'p',
styles: {
'font-size': '24px',
'font-weight': 'bold'
}
},
// Accept any element with heading-1 class
{ classes: 'heading-1' },
// Pattern matching function
(element) => {
return element.name === 'span' &&
element.getStyle('display') === 'block' &&
parseFloat(element.getStyle('font-size')) > 20;
}
]
};Use converterPriority to resolve conflicts when multiple converters match the same content:
// High priority converter takes precedence
const primaryHeading = {
model: 'heading1',
view: 'h1',
title: 'Primary Title',
class: 'ck-heading_primary',
converterPriority: 'high'
};
// Low priority fallback
const fallbackHeading = {
model: 'heading1',
view: { name: 'div', classes: 'title' },
title: 'Title Div',
class: 'ck-heading_div',
converterPriority: 'low'
};The configuration system provides full TypeScript support:
import type {
HeadingConfig,
HeadingOption,
HeadingElementOption,
HeadingParagraphOption
} from '@ckeditor/ckeditor5-heading';
// Type-safe configuration
const config: HeadingConfig = {
options: [
// TypeScript will validate all properties
{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
{ model: 'heading1', view: 'h1', title: 'Title', class: 'ck-heading_title' }
]
};
// Custom option builder with type safety
function createHeadingOption(
level: number,
htmlTag: string,
title: string
): HeadingElementOption {
return {
model: `heading${level}` as const,
view: htmlTag,
title,
class: `ck-heading_heading${level}`
};
}