gpt4 book ai didi

ckeditor5 - 如何在ckeditor5中的 “target”标签中添加 `a`属性?

转载 作者:行者123 更新时间:2023-12-04 16:38:12 27 4
gpt4 key购买 nike

我已经为链接创建了自己的插件。现在,我想向插件生成的a标签添加其他一些属性,例如targetrel

但是我无法完成它。这是转换器的我的插件代码。
我应该添加哪些转换器,以便a标记可以支持其他属性?

/**
* @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/

/**
* @module link/linkediting
*/

import LinkEditing from '@ckeditor/ckeditor5-link/src/linkediting';
import {
downcastAttributeToElement
} from '@ckeditor/ckeditor5-engine/src/conversion/downcast-converters';
import { upcastElementToAttribute } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';
import LinkCommand from './uclinkcommand';
import UnlinkCommand from './ucunlinkcommand';
import { createLinkElement } from '@ckeditor/ckeditor5-link/src/utils';
import { ensureSafeUrl } from './utils';
import bindTwoStepCaretToAttribute from '@ckeditor/ckeditor5-engine/src/utils/bindtwostepcarettoattribute';

/**
* The link engine feature.
*
* It introduces the `linkHref="url"` attribute in the model which renders to the view as a `<a href="url">` element.
*
* @extends module:core/plugin~Plugin
*/
export default class UcLinkEditing extends LinkEditing {
/**
* @inheritDoc
*/
init() {
const editor = this.editor;

// Allow link attribute on all inline nodes.
editor.model.schema.extend( '$text', { allowAttributes: 'linkHref' } );

editor.conversion.for( 'dataDowncast' )
.add( downcastAttributeToElement( { model: 'linkHref', view: createLinkElement } ) );

editor.conversion.for( 'editingDowncast' )
.add( downcastAttributeToElement( { model: 'linkHref', view: ( href, writer ) => {
return createLinkElement( ensureSafeUrl( href ), writer );
} } ) );

editor.conversion.for( 'upcast' )
.add( upcastElementToAttribute( {
view: {
name: 'a',
attribute: {
href: true
}
},
model: {
key: 'linkHref',
value: viewElement => viewElement.getAttribute( 'href' )
}
} ) );

// Create linking commands.
editor.commands.add( 'ucLink', new LinkCommand( editor ) );
editor.commands.add( 'ucUnlink', new UnlinkCommand( editor ) );

// Enable two-step caret movement for `linkHref` attribute.
bindTwoStepCaretToAttribute( editor.editing.view, editor.model, this, 'linkHref' );

// Setup highlight over selected link.
this._setupLinkHighlight();
}
}

最佳答案

介绍

在阅读代码之前,我想先介绍一下CKEditor 5对内联元素(例如<a>)的处理方法,以便使解决方案更易于理解。有了这些知识,将来不会遇到类似的问题。以下内容旨在作为一个全面的教程,因此请耐心阅读。

即使您可能了解理论部分的大部分内容,我还是建议您阅读它以全面了解CKEditor 5中的工作原理。

另外,请注意,我将为原始CKEditor 5插件提供一个解决方案,因为它对于寻求该问题的教程的其他社区成员来说更有值(value)。不过,我希望借助本教程的见解,您可以将代码示例调整为自定义插件。

另外,请记住,本教程不讨论该插件的UI部分,而只是讨论应如何配置事物以进行转换。添加和删​​除属性是UI或代码其他部分的工作。在这里,我仅讨论引擎内容。

CKEditor 5中的内联元素

首先,让我们确定哪些元素是内联的。通过内联元素,我了解<strong><a><span>之类的元素。与<p><blockquote><div>不同,内联元素不构成数据。相反,它们以特定的(视觉和语义)方式标记某些文本。因此,从某种意义上说,这些元素是文本给定部分的特征。结果,我们说文本的给定部分为粗体,或者文本的给定部分为/具有链接。

同样,在模型中,我们不直接将<a><strong>表示为元素。相反,我们允许将属性添加到文本的一部分。这就是文本特征(粗体,斜体或链接)的表示方式。

例如,在模型中,我们可能有一个带有<paragraph>文本的Foo bar元素,其中barbold属性设置为true。我们会这样记录:<paragraph>Foo <$text bold="true">bar</$text></paragraph>。看到那里没有<strong>或任何其他附加元素。只是一些带有属性的文本。稍后,bold属性将转换为<strong>元素。

顺便说一句:来自模型属性的 View 元素具有自己的类: view.AttributeElement ,而不是内联元素也可以称为属性元素。可悲的是,名称与作为 View 元素属性的“属性”冲突(更糟糕的是,允许属性元素具有属性)。

当然,文本可能具有多个属性,并且所有属性都将转换为它们各自的 View 内联元素。请记住,在模型中,属性没有任何设置顺序。这与 View 或HTML相反,在 View 或HTML中,内联元素彼此嵌套。嵌套发生在从模型到 View 的转换期间。这使模型的工作变得更简单,因为要素不需要照顾到破坏或重新布置模型中的元素的情况。

考虑以下模型字符串:

<paragraph>
<$text bold="true">Foo </$text>
<$text bold="true" linkHref="bar.html">bar</$text>
<$text bold="true"> baz</$text>
</paragraph>

这是一个带有 Foo bar baz链接的粗体 bar文本。在转换过程中,它将转换为:

<p>
<strong>Foo </strong><a href="bar.html"><strong>bar</strong></a><strong> baz</strong>
</p>

注意, <a>元素的转换方式始终是最顶层的元素。这是有意的,因此任何元素都不会破坏 <a>元素。看到以下错误的 View /HTML字符串:

<p>
<a href="bar.html">Foo </a><strong><a href="bar.html">bar</a></strong>
</p>

生成的 View /HTML具有彼此相邻的两个链接元素,这是错误的。

我们使用 priority view.AttributeElement 属性来定义哪个元素应位于其他元素之上。大多数元素,例如 <strong>都不关心它,并保留默认优先级。但是, <a>元素更改了优先级,以保证 View /HTML中的正确顺序。

复杂的内联元素和合并

到目前为止,我们主要讨论了更简单的内联元素,即没有属性的元素。示例为 <strong><em>。相反, <a>具有其他属性。

很容易想到需要对文本的一部分进行标记/样式设置但足够自定义的功能,以至于仅使用标签是不够的。一个示例是字体系列功能。使用时,它将 fontFamily属性添加到文本中,然后使用适当的 <span>属性将其转换为 style元素。

此时,您需要询问如果在文本的同一部分设置了多个这样的属性会发生什么情况?以这个模型为例:

<paragraph>
<$text fontFamily="Tahoma" fontSize="big">Foo</$text>
</paragraph>

上面的属性转换如下:
  • fontFamily="value"转换为<span style="font-family: value;">
  • fontSize="value"转换为<span class="text-value">

  • 那么,我们可以期望什么样的 View /HTML?

    <p>
    <span style="font-family: Tahoma;">
    <span class="text-big">Foo</span>
    </span>
    </p>

    但是,这似乎是错误的。为什么不只有一个 <span>元素?这样会更好吗?

    <p>
    <span style="font-family: Tahoma;" class="text-big">Foo</span>
    </p>

    为了解决这种情况,实际上,在CKEditor 5转换机制中,我们引入了合并机制。

    在上述情况下,我们有两个属性可以转换为 <span>。当第一个属性(例如,转换 fontFamily时, View 中还没有 <span>。因此 <span>被添加了 style属性。但是,当转换 fontSize时, View 中已经存在 <span>view.Writer可以识别并检查这些元素是否可以合并。规则为三个:
  • 元素必须具有相同的view.Element#name
  • 元素必须具有相同的view.AttributeElement#priority
  • 这两个元素都不能设置view.AttributeElement#id

  • 我们还没有讨论 id属性,但是出于简单原因,我现在不再讨论它。可以说,对于某些属性元素而言,防止它们合并很重要。

    向链接添加另一个属性

    此时,应该很清楚如何向 <a>元素添加另一个属性。

    只需定义一个新的模型属性( linkTargetlinkRel),然后将其转换为具有所需属性( <a>target="...")的 rel="..."元素。然后,它将与原始 <a href="...">元素合并。

    请记住,原始CKEditor 5链接插件中的 <a>元素已指定了自定义 priority。这意味着由新插件生成的元素需要具有指定的相同优先级才能正确合并。

    向上转换合并的属性元素

    目前,我们仅讨论向下转换(即从模型转换为 View )。现在,我们来谈谈向上转换(即,从 View 转换为模型)。幸运的是,它比上一部分要容易。

    有两个可以“转换”的“事物”-元素和属性。这里没有魔术-元素是元素( <p><a><strong>等),而属性是属性( class=""href=""等)。

    元素可以向上转换为元素( <p>-> <paragraph>)或属性( <strong>-> bold<a>-> linkHref)。可以将属性上载到属性。

    我们的示例显然需要从元素到属性的转换。实际上, <a>元素被转换为 linkHref属性,并且 linkHref属性值取自 href=""元素的 <a>属性。

    自然地,将为其新的 linkTargetlinkRel属性定义相同的转换。但是,这里有一个陷阱。 View 的每个部分只能转换一次(“消耗”)一次(向下转换时该模型也是如此)。

    这是什么意思?简而言之,如果一个功能已经转换了给定的元素名称或给定的元素属性,那么这两个功能都无法转换。这样,功能就可以正确地相互覆盖。这也意味着可以引入通用转换器(例如,如果没有其他功能将 <div>识别为可以由该功能转换的功能,则 <paragraph>可以转换为 <div>)。这也有助于发现有冲突的转换器。

    回到我们的例子。我们不能定义两个元素到属性转换器来转换同一元素( <a>)并期望它们同时工作。一个将覆盖另一个。

    由于我们不想更改原始链接插件,因此需要将该转换器保持原样。但是,新插件的转换转换器将是一个属性到属性转换器。由于该转换器不会转换元素(或元素名称),因此它将与原始转换器一起使用。

    代码样例

    这是链接目标插件的代码示例。下面我将解释它的某些部分。

    import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
    import { downcastAttributeToElement } from '@ckeditor/ckeditor5-engine/src/conversion/downcast-converters';
    import { upcastAttributeToAttribute } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';

    class LinkTarget extends Plugin {
    init() {
    const editor = this.editor;

    editor.model.schema.extend( '$text', { allowAttributes: 'linkTarget' } );

    editor.conversion.for( 'downcast' ).add( downcastAttributeToElement( {
    model: 'linkTarget',
    view: ( attributeValue, writer ) => {
    return writer.createAttributeElement( 'a', { target: attributeValue }, { priority: 5 } );
    },
    converterPriority: 'low'
    } ) );

    editor.conversion.for( 'upcast' ).add( upcastAttributeToAttribute( {
    view: {
    name: 'a',
    key: 'target'
    },
    model: 'linkTarget',
    converterPriority: 'low'
    } ) );
    }
    }

    对于这么长的教程,它肯定是一个小片段。希望其中大多数是不言自明的。

    首先,我们通过定义文本上允许的新属性 Schema来扩展 linkTarget

    然后,我们定义向下转换。使用 downcastAttributeToElement 是因为我们要创建 <a target="...">元素,该元素将与原始 <a>元素合并。请记住,此处创建的 <a>元素具有定义为 5的优先级,就像在原始链接插件中一样。

    最后一步是转换转换。如前所述,使用 upcastAttributeToAttribute 帮助程序。在 view配置中,指定仅应转换 target元素的 <a>属性( name: 'a')。这并不意味着 <a>元素将被转换!这只是转换器的过滤配置,因此不会转换其他元素的 target属性。

    最后,两个转换器的优先级都低于原始转换器,以防止出现任何假想的问题。

    上面的示例对我适用于 ckeditor5-engineckeditor5-link的当前母版。

    关于ckeditor5 - 如何在ckeditor5中的 “target”标签中添加 `a`属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51303892/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com