Contribute to this guide

guide向上转型助手 - 视图到模型转换

本文列出了 向上转型转换 中可用的所有编辑器助手。

# 元素到元素转换助手

将视图元素转换为模型元素是转换中最常见的用例。它用于处理需要转换为模型元素的视图元素,例如 <p><h1>

使用 elementToElement() 助手,一个单个视图元素将被转换为一个单个模型元素。此视图元素的子元素需要有自己的转换器定义,引擎将递归地转换它们并将它们插入到创建的模型元素中。

# 基本元素到元素转换

最简单的元素到元素转换,其中视图元素变为模型元素,可以通过在转换器中简单地提供它们的名称来实现

editor.conversion
    .for( 'upcast' )
    .elementToElement( {
        view: 'p',
        model: 'paragraph'
    } );

上面的示例从每个 <p> 视图元素创建模型元素 <paragraph>

# 使用视图元素定义

可以通过指定它们的属性(例如类名)来限制符合转换条件的视图元素。要实现这一点,请在 view 属性中提供所需的元素定义,如下例所示

editor.conversion
    .for( 'upcast' )
    .elementToElement( {
        view: {
            name: 'p',
            classes: 'fancy'
        },
        model: 'fancyParagraph'
    } );

查看 ElementDefinition 文档 以了解更多详细信息。

# 使用回调创建模型元素

可以手动使用作为 model 属性提供的回调来创建转换后的模型元素。

editor.conversion
    .for( 'upcast' )
    .elementToElement( {
        view: {
            name: 'p',
            classes: 'heading'
        },
        model: ( viewElement, { writer } ) => {
            return writer.createElement( 'heading' );
        }
    } );

在上面的示例中,模型元素仅从 <p class="heading"> 视图元素创建。所有其他没有 heading 类名的 <p> 元素将被过滤掉,不会被转换。

模型回调的第二个参数是 UpcastConversionApi 对象,它包含许多在编写更复杂的转换器时有用的属性和方法。

# 处理带有属性的视图元素

如果模型元素不仅取决于视图元素本身,还取决于它的属性,则需要在 view 属性中指定这些属性。

editor.conversion
    .for( 'upcast' )
    .elementToElement( {
        view: {
            name: 'p',
            attributes: [ 'data-level' ]
        },
        model: ( viewElement, { writer } ) => {
            return writer.createElement( 'heading', { level: viewElement.getAttribute( 'data-level' ) } );
        }
    } );

如果忘记指定这些属性,另一个转换器(例如,来自 通用 HTML 支持功能)也可能处理这些属性,从而导致模型中出现重复的属性。

# 更改转换器优先级

如果已存在具有重叠 view 模式的多个转换器,则可以优先考虑自己的转换器以覆盖它们。为此,请使用 converterPriority 属性

editor.conversion
    .for( 'upcast' )
    .elementToElement( {
        view: 'div',
        model: 'mainContent',
    } );

editor.conversion
    .for( 'upcast' )
    .elementToElement( {
        view: 'div',
        model: 'sideContent',
        converterPriority: 'high'
    } );

在上面的示例中,第一个转换器具有默认优先级 normal(不需要显式设置)。第二个转换器覆盖了它,它的优先级设置为 high。同时使用这两个转换器会导致 <div> 视图元素被转换为 sideContent

此解决方案的另一个实际应用是让您的转换器在针对给定元素的其他转换器不存在的情况下(例如,插件未加载)充当后备。可以通过将 converterProperty 设置为 low 来轻松实现。

# 元素到属性转换助手

元素到属性转换用于处理需要转换为文本属性的格式化视图元素,例如 <b><span style="font-family: ...">。重要的是要注意,诸如粗体或字体大小之类的文本格式应在模型中表示为文本节点属性。

一般来说,模型没有实现“内联元素”的概念(在 CSS 中定义的方式)。内联元素可以使用的唯一场景是自包含对象,例如软换行符 (<br>) 或内联图像。

# 基本元素到属性转换

editor.conversion
    .for( 'upcast' )
    .elementToAttribute( {
        view: 'strong',
        model: 'bold'
    } );

在上面的示例中,视图 <strong>CKEditor&nbsp;5</strong> 将变为具有 bold 属性设置为 trueCKEditor&nbsp;5 模型文本节点。

# 转换特定视图元素中的属性

您可能只想转换具有特定类名或其他属性的视图元素。要实现这一点,可以在 view 属性中提供 元素定义

editor.conversion
    .for( 'upcast' )
    .elementToAttribute( {
        view: {
            name: 'span',
            classes: 'bold'
        },
        model: 'bold'
    } );

查看 ElementDefinition 文档 以了解更多详细信息。

# 将预定义值设置为模型属性

您可以指定模型属性将采用哪个值。要实现这一点,请在 model 属性对象中提供结果模型属性的名称作为 key,并提供其所需的值作为 value

editor.conversion
    .for( 'upcast' )
    .elementToAttribute( {
        view: {
            name: 'span',
            classes: [ 'styled', 'styled-dark' ]
        },
        model: {
            key: 'styled',
            value: 'dark'
        }
    } );

上面的代码将 <span class="styled styled-dark">CKEditor5</span> 转换为具有 styled 属性设置为 dark 的模型文本节点 CKEditor5

# 通过回调处理属性值

在属性值需要额外处理(例如映射、过滤等)的情况下,可以将 model.value 定义为回调。

editor.conversion
    .for( 'upcast' )
    .elementToAttribute( {
        view: {
            name: 'span',
            styles: {
                'font-size': /[\s\S]+/
            }
        },
        model: {
            key: 'fontSize',
            value: ( viewElement, conversionApi ) => {
                const fontSize = viewElement.getStyle( 'font-size' );
                const value = fontSize.substr( 0, fontSize.length - 2 );

                if ( value <= 10 ) {
                    return 'small';
                } else if ( value > 12 ) {
                    return 'big';
                }

                return null;
            }
        }
    } );

在上面的示例中,我们将数值 font-size 内联样式转换为 smallbig 模型属性,具体取决于定义的标准。

# 更改转换器优先级

您可以通过指定更高的优先级来覆盖现有的转换器,如下例所示

editor.conversion
    .for( 'upcast' )
    .elementToAttribute( {
        view: 'strong',
        model: 'bold'
    } );

editor.conversion
    .for( 'upcast' )
    .elementToAttribute( {
        view: 'strong',
        model: 'important',
        converterPriority: 'high'
    } );

在此示例中,第一个转换器具有默认优先级 normal。第二个转换器覆盖了它,它的优先级设置为 high。同时使用这两个转换器会导致 <strong> 视图元素被转换为 important 模型属性。

# 属性到属性转换助手

attributeToAttribute() 助手允许注册一个转换器来处理特定属性,并将其转换为模型元素的属性。

通常,在注册元素的转换器时(例如,通过使用 elementToElement()),您会希望在处理元素本身时处理它们的属性。

当您出于某种原因无法在 elementToElement() 中涵盖特定属性时,attributeToAttribute() 助手会派上用场。例如,当您扩展其他人的插件时,可能会发生这种情况。

这种类型的转换器助手仅在已提供元素转换器时才有效。尝试在没有接收模型元素的情况下转换为属性会导致错误。

# 基本属性到属性转换

此转换导致向模型元素添加属性,该属性基于视图元素中的属性。例如,<img src="foo.jpg"> 中的 src 属性将被转换为 <imageInline source="foo.jpg"></imageInline> 中的 source

editor.conversion
    .for( 'upcast' )
    .attributeToAttribute( {
        view: 'src',
        model: 'source'
    } );

构建此转换器的另一种方法是提供 view.key 属性。您可以在下面的示例中看到它的执行

editor.conversion
    .for( 'upcast' )
    .attributeToAttribute( {
        view: {
            key: 'src'
        },
        model: 'source'
    } );

这两个转换器都会产生完全相同的结果。

# 转换特定视图元素的属性

您可以限制包含属性的元素以及该属性的值。此转换器仅在完全匹配的情况下执行。

editor.conversion
    .for( 'upcast' )
    .attributeToAttribute( {
        view: {
            name: 'p',
            key: 'class',
            value: 'styled-dark'
        },
        model: {
            key: 'styled',
            value: 'dark'
        }
    } );

在上面的示例中,只有 <p> 元素的 styled-dark 类将被转换为具有预定义值 dark 的模型属性 styled

# 转换与更复杂模式匹配的视图属性

view 属性中提供的模式可以更加复杂。除了字符串之外,您还可以提供一个正则表达式或一个函数,该函数接受属性值并返回 truefalse

editor.conversion
    .for( 'upcast' )
    .attributeToAttribute( {
        view: {
            key: 'data-style',
            value: /\S+/
        },
        model: 'styled'
    } );

在上面的示例中,我们使用正则表达式来匹配仅选定的 data-style 属性,该属性在它的值中没有空格字符。只有与该表达式匹配的属性才会将其值分配给 styled 模型属性。

# 通过回调处理属性

如果属性值需要额外处理(例如映射、过滤等),可以将 model.value 定义为回调。

editor.conversion
    .for( 'upcast' )
    .attributeToAttribute( {
        view: {
            key: 'class',
            value: /styled-[\S]+/
        },
        model: {
            key: 'styled'
            value: viewElement => {
                const regexp = /styled-([\S]+)/;
                const match = viewElement.getAttribute( 'class' ).match( regexp );

                return match[ 1 ];
            }
        }
    } );

上面的示例中,转换器会从每个以styled-开头的class属性中提取样式名称,并将其分配给模型属性styled

# 更改转换器优先级

您可以通过指定更高的优先级来覆盖现有的转换器,如下例所示

editor.conversion
    .for( 'upcast' )
    .attributeToAttribute( {
        view: 'src',
        model: 'source'
    } );

editor.conversion
    .for( 'upcast' )
    .attributeToAttribute( {
        view: 'src',
        model: 'sourceAddress',
        converterPriority: 'high'
    } );

第一个转换器具有默认的normal优先级。第二个转换器由于其更高的优先级,将被更早地调用,因此src视图属性将被转换为sourceAddress模型属性(而不是source)。

# 进一步阅读

查看带有完整列表的 专用指南,该列表包含补充的 下行转换帮助程序