@ckeditor/ckeditor5-html-support
Version:
HTML Support feature for CKEditor 5.
986 lines (985 loc) • 25.1 kB
JavaScript
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
/**
* @module html-support/schemadefinitions
*/
/**
* Skipped elements due to HTML deprecation:
* * noframes (not sure if we should provide support for this element. CKE4 is not supporting frameset and frame,
* but it will unpack <frameset><noframes>foobar</noframes></frameset> to <noframes>foobar</noframes>, so there
* may be some content loss. Although using noframes as a standalone element seems invalid)
* * keygen (this one is also empty)
* * applet (support is limited mostly to old IE)
* * basefont (this one is also empty)
* * isindex (basically no support for modern browsers at all)
*
* Skipped elements due to lack empty element support:
* * hr
* * area
* * br
* * command
* * map
* * wbr
* * colgroup -> col
*
* Skipped elements due to complexity:
* * datalist with option elements used as a data source for input[list] element
*
* Skipped elements as they are handled as an object content:
* * track
* * source
* * option
* * param
* * optgroup
*
* Skipped full page HTML elements:
* * body
* * html
* * title
* * head
* * meta
* * link
* * etc...
*
* Skipped hidden elements:
* noscript
*
* When adding elements to this list, update the feature guide listing, too.
*
* @internal
*/
export const defaultConfig = {
block: [
// Existing features.
{
model: 'codeBlock',
view: 'pre'
},
{
model: 'paragraph',
view: 'p'
},
{
model: 'blockQuote',
view: 'blockquote'
},
{
model: 'listItem',
view: 'li'
},
{
model: 'pageBreak',
view: 'div'
},
{
model: 'rawHtml',
view: 'div'
},
{
model: 'table',
view: 'table'
},
{
model: 'tableRow',
view: 'tr'
},
{
model: 'tableCell',
view: 'td'
},
{
model: 'tableCell',
view: 'th'
},
{
model: 'tableColumnGroup',
view: 'colgroup'
},
{
model: 'tableColumn',
view: 'col'
},
{
model: 'caption',
view: 'caption'
},
{
model: 'caption',
view: 'figcaption'
},
{
model: 'imageBlock',
view: 'img'
},
{
model: 'imageInline',
view: 'img'
},
{
model: 'horizontalLine',
view: 'hr'
},
// Compatibility features.
{
model: 'htmlP',
view: 'p',
modelSchema: {
inheritAllFrom: '$block'
}
},
{
model: 'htmlBlockquote',
view: 'blockquote',
modelSchema: {
inheritAllFrom: '$container'
}
},
{
model: 'htmlTable',
view: 'table',
modelSchema: {
allowWhere: '$block',
isBlock: true
}
},
{
model: 'htmlTbody',
view: 'tbody',
modelSchema: {
allowIn: 'htmlTable',
isBlock: false
}
},
{
model: 'htmlThead',
view: 'thead',
modelSchema: {
allowIn: 'htmlTable',
isBlock: false
}
},
{
model: 'htmlTfoot',
view: 'tfoot',
modelSchema: {
allowIn: 'htmlTable',
isBlock: false
}
},
{
model: 'htmlCaption',
view: 'caption',
modelSchema: {
allowIn: 'htmlTable',
allowChildren: '$text',
isBlock: false
}
},
{
model: 'htmlColgroup',
view: 'colgroup',
modelSchema: {
allowIn: 'htmlTable',
allowChildren: 'col',
isBlock: false
}
},
{
model: 'htmlCol',
view: 'col',
modelSchema: {
allowIn: 'htmlColgroup',
isBlock: false
}
},
{
model: 'htmlTr',
view: 'tr',
modelSchema: {
allowIn: ['htmlTable', 'htmlThead', 'htmlTbody'],
isLimit: true
}
},
// TODO can also include text.
{
model: 'htmlTd',
view: 'td',
modelSchema: {
allowIn: 'htmlTr',
allowContentOf: '$container',
isLimit: true,
isBlock: false
}
},
// TODO can also include text.
{
model: 'htmlTh',
view: 'th',
modelSchema: {
allowIn: 'htmlTr',
allowContentOf: '$container',
isLimit: true,
isBlock: false
}
},
// TODO can also include text.
{
model: 'htmlFigure',
view: 'figure',
modelSchema: {
inheritAllFrom: '$container',
isBlock: false
}
},
// TODO can also include other block elements.
{
model: 'htmlFigcaption',
view: 'figcaption',
modelSchema: {
allowIn: 'htmlFigure',
allowChildren: '$text',
isBlock: false
}
},
// TODO can also include text.
{
model: 'htmlAddress',
view: 'address',
modelSchema: {
inheritAllFrom: '$container',
isBlock: false
}
},
// TODO can also include text.
{
model: 'htmlAside',
view: 'aside',
modelSchema: {
inheritAllFrom: '$container',
isBlock: false
}
},
// TODO can also include text.
{
model: 'htmlMain',
view: 'main',
modelSchema: {
inheritAllFrom: '$container',
isBlock: false
}
},
// TODO can also include text.
{
model: 'htmlDetails',
view: 'details',
modelSchema: {
inheritAllFrom: '$container',
isBlock: false
}
},
{
model: 'htmlSummary',
view: 'summary',
modelSchema: {
allowChildren: [
'htmlH1',
'htmlH2',
'htmlH3',
'htmlH4',
'htmlH5',
'htmlH6',
'$text'
],
allowIn: 'htmlDetails',
isBlock: false
}
},
{
model: 'htmlDiv',
view: 'div',
paragraphLikeModel: 'htmlDivParagraph',
modelSchema: {
inheritAllFrom: '$container'
}
},
// TODO can also include text.
{
model: 'htmlFieldset',
view: 'fieldset',
modelSchema: {
inheritAllFrom: '$container',
isBlock: false
}
},
// TODO can also include h1-h6.
{
model: 'htmlLegend',
view: 'legend',
modelSchema: {
allowIn: 'htmlFieldset',
allowChildren: '$text'
}
},
// TODO can also include text.
{
model: 'htmlHeader',
view: 'header',
modelSchema: {
inheritAllFrom: '$container',
isBlock: false
}
},
// TODO can also include text.
{
model: 'htmlFooter',
view: 'footer',
modelSchema: {
inheritAllFrom: '$container',
isBlock: false
}
},
// TODO can also include text.
{
model: 'htmlForm',
view: 'form',
modelSchema: {
inheritAllFrom: '$container',
isBlock: true
}
},
{
model: 'htmlHgroup',
view: 'hgroup',
modelSchema: {
allowIn: ['$root', '$container'],
allowChildren: [
'paragraph',
'htmlP',
'htmlH1',
'htmlH2',
'htmlH3',
'htmlH4',
'htmlH5',
'htmlH6'
],
isBlock: false
}
},
{
model: 'htmlH1',
view: 'h1',
modelSchema: {
inheritAllFrom: '$block'
}
},
{
model: 'htmlH2',
view: 'h2',
modelSchema: {
inheritAllFrom: '$block'
}
},
{
model: 'htmlH3',
view: 'h3',
modelSchema: {
inheritAllFrom: '$block'
}
},
{
model: 'htmlH4',
view: 'h4',
modelSchema: {
inheritAllFrom: '$block'
}
},
{
model: 'htmlH5',
view: 'h5',
modelSchema: {
inheritAllFrom: '$block'
}
},
{
model: 'htmlH6',
view: 'h6',
modelSchema: {
inheritAllFrom: '$block'
}
},
{
model: '$htmlList',
modelSchema: {
allowWhere: '$container',
allowChildren: ['$htmlList', 'htmlLi'],
isBlock: false
}
},
{
model: 'htmlDir',
view: 'dir',
modelSchema: {
inheritAllFrom: '$htmlList'
}
},
{
model: 'htmlMenu',
view: 'menu',
modelSchema: {
inheritAllFrom: '$htmlList'
}
},
{
model: 'htmlUl',
view: 'ul',
modelSchema: {
inheritAllFrom: '$htmlList'
}
},
{
model: 'htmlOl',
view: 'ol',
modelSchema: {
inheritAllFrom: '$htmlList'
}
},
// TODO can also include other block elements.
{
model: 'htmlLi',
view: 'li',
modelSchema: {
allowIn: '$htmlList',
allowChildren: '$text',
isBlock: false
}
},
{
model: 'htmlPre',
view: 'pre',
modelSchema: {
inheritAllFrom: '$block'
}
},
{
model: 'htmlArticle',
view: 'article',
modelSchema: {
inheritAllFrom: '$container',
isBlock: false
}
},
{
model: 'htmlSection',
view: 'section',
modelSchema: {
inheritAllFrom: '$container',
isBlock: false
}
},
// TODO can also include text.
{
model: 'htmlNav',
view: 'nav',
modelSchema: {
inheritAllFrom: '$container',
isBlock: false
}
},
{
model: 'htmlDivDl',
view: 'div',
modelSchema: {
allowChildren: ['htmlDt', 'htmlDd'],
allowIn: 'htmlDl'
}
},
{
model: 'htmlDl',
view: 'dl',
modelSchema: {
allowWhere: '$container',
allowChildren: ['htmlDt', 'htmlDd', 'htmlDivDl'],
isBlock: false
}
},
{
model: 'htmlDt',
view: 'dt',
modelSchema: {
allowChildren: '$block',
isBlock: false
}
},
{
model: 'htmlDd',
view: 'dd',
modelSchema: {
allowChildren: '$block',
isBlock: false
}
},
{
model: 'htmlCenter',
view: 'center',
modelSchema: {
inheritAllFrom: '$container',
isBlock: false
}
},
{
model: 'htmlHr',
view: 'hr',
isEmpty: true,
modelSchema: {
inheritAllFrom: '$blockObject'
}
}
],
inline: [
// Existing features (attribute set on an existing model element).
{
model: 'htmlLiAttributes',
view: 'li',
appliesToBlock: true,
coupledAttribute: 'listItemId'
},
{
model: 'htmlOlAttributes',
view: 'ol',
appliesToBlock: true,
coupledAttribute: 'listItemId'
},
{
model: 'htmlUlAttributes',
view: 'ul',
appliesToBlock: true,
coupledAttribute: 'listItemId'
},
{
model: 'htmlFigureAttributes',
view: 'figure',
appliesToBlock: 'table'
},
{
model: 'htmlTheadAttributes',
view: 'thead',
appliesToBlock: 'table'
},
{
model: 'htmlTbodyAttributes',
view: 'tbody',
appliesToBlock: 'table'
},
{
model: 'htmlFigureAttributes',
view: 'figure',
appliesToBlock: 'imageBlock'
},
// Compatibility features.
{
model: 'htmlAcronym',
view: 'acronym',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlTt',
view: 'tt',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlFont',
view: 'font',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlTime',
view: 'time',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlVar',
view: 'var',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlBig',
view: 'big',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlSmall',
view: 'small',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlSamp',
view: 'samp',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlQ',
view: 'q',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlOutput',
view: 'output',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlKbd',
view: 'kbd',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlBdi',
view: 'bdi',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlBdo',
view: 'bdo',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlAbbr',
view: 'abbr',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlA',
view: 'a',
priority: 5,
coupledAttribute: 'linkHref',
attributeProperties: {
isFormatting: true
}
},
{
model: 'htmlStrong',
view: 'strong',
coupledAttribute: 'bold',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlB',
view: 'b',
coupledAttribute: 'bold',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlI',
view: 'i',
coupledAttribute: 'italic',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlEm',
view: 'em',
coupledAttribute: 'italic',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlS',
view: 's',
coupledAttribute: 'strikethrough',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
// TODO According to HTML-spec can behave as div-like element, although CKE4 only handles it as an inline element.
{
model: 'htmlDel',
view: 'del',
coupledAttribute: 'strikethrough',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
// TODO According to HTML-spec can behave as div-like element, although CKE4 only handles it as an inline element.
{
model: 'htmlIns',
view: 'ins',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlU',
view: 'u',
coupledAttribute: 'underline',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlSub',
view: 'sub',
coupledAttribute: 'subscript',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlSup',
view: 'sup',
coupledAttribute: 'superscript',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlCode',
view: 'code',
coupledAttribute: 'code',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlMark',
view: 'mark',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlSpan',
view: 'span',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlCite',
view: 'cite',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlLabel',
view: 'label',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
{
model: 'htmlDfn',
view: 'dfn',
attributeProperties: {
copyOnEnter: true,
isFormatting: true
}
},
// Objects.
{
model: 'htmlObject',
view: 'object',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
{
model: 'htmlIframe',
view: 'iframe',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
{
model: 'htmlInput',
view: 'input',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
{
model: 'htmlButton',
view: 'button',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
{
model: 'htmlTextarea',
view: 'textarea',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
{
model: 'htmlSelect',
view: 'select',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
{
model: 'htmlVideo',
view: 'video',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
{
model: 'htmlEmbed',
view: 'embed',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
{
model: 'htmlOembed',
view: 'oembed',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
{
model: 'htmlAudio',
view: 'audio',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
{
model: 'htmlImg',
view: 'img',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
{
model: 'htmlCanvas',
view: 'canvas',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
// TODO it could be probably represented as non-object element, although it has graphical representation,
// so probably makes more sense to keep it as an object.
{
model: 'htmlMeter',
view: 'meter',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
// TODO it could be probably represented as non-object element, although it has graphical representation,
// so probably makes more sense to keep it as an object.
{
model: 'htmlProgress',
view: 'progress',
isObject: true,
modelSchema: {
inheritAllFrom: '$inlineObject'
}
},
{
model: 'htmlScript',
view: 'script',
modelSchema: {
allowWhere: ['$text', '$block'],
isInline: true
}
},
{
model: 'htmlStyle',
view: 'style',
modelSchema: {
allowWhere: ['$text', '$block'],
isInline: true
}
},
{
model: 'htmlCustomElement',
view: '$customElement',
modelSchema: {
allowWhere: ['$text', '$block'],
allowAttributesOf: '$inlineObject',
isInline: true
}
}
]
};