How to implement a placeholder plugin that works with plain text placeholders?

左心房为你撑大大i 提交于 2019-12-11 08:25:55

问题


I'am trying to implement a plugin that translates plaintext placeholders of type __firstName__ into a model like <placeholder key="__firstName__"></placeholder> and vice versa.

I followed the tutorial on implementing an inline widget which really helped to get started.

I got the upcast part working which parses the text, splits it up and creates text- and placeholder-elements. So:

<p>Hi __firstName__,</p>

becomes:

<$root>
    <paragraph>
        "Hi "
        <placeholder key="__firstName__">
        </placeholder>
        ","
    </paragraph>
</$root>

I'am now struggling to get the dataDowncast part working. I made these changes regarding only the dataDowncast, returning a text instead of an element with a text inside:

conversion.for('dataDowncast').elementToElement({
    model: 'placeholder',
    view: (modelItem, viewWriter) => {
        var key = modelItem.getAttribute('key');

        return viewWriter.createText(key);
    }
});

I'm now facing two problems.

1.: The dataDowncast results in this:

<p>Hi _,_firstName__</p>

Everything following the placeholder seems to be shifted to the left or in other words seems to ignore the placeholder-length (-1) completely. Is the elementToElement even meant to except a text instead of an element? Or do i simply have to inform the writer about the length of the text somehow?

2.: If there are more than two placeholders one after another in the model:

<$root>
    <paragraph>
        <placeholder key="__firstName__">
        </placeholder>
        <placeholder key="__lastName__">
        </placeholder>
        <placeholder key="__salutation__">
        </placeholder>
    </paragraph>
</$root>

the dataDowncast raises this error:

Uncaught TypeError: Cannot read property 'name' of undefined
at Mapper.getModelLength (mapper.js:428)
at Mapper._findPositionIn (mapper.js:493)
at Mapper.on (mapper.js:94)
at Mapper.fire (emittermixin.js:211)
at Mapper.toViewPosition (mapper.js:277)
at DowncastDispatcher.modelViewSplitOnInsert (converters.js:214)
at DowncastDispatcher.fire (emittermixin.js:211)
at DowncastDispatcher._testAndFire (downcastdispatcher.js:473)
at DowncastDispatcher.convertInsert (downcastdispatcher.js:184)
at DataController.toView (datacontroller.js:207)

This could be a consequential error.

Dependencies uses:

"@ckeditor/ckeditor5-editor-inline": "12.0.0",    
"@ckeditor/ckeditor5-widget": "11.0.0",

No plugins active.


回答1:


Is the elementToElement() even meant to except a text instead of an element?

All 3 elementToElement() helpers (two-way, upcast and downcast) are expecting that on both ends (in the model and in the view) you have elements. They convert one element to another.

In general, there are 4 basic types of converters:

  • between model and view elements,
  • between a model attribute and a view element (must be AttributeElement then),
  • between model and view attributes,
  • from model markers to a view highlight or element.

It's possible to write custom converters for bigger chunks of view structures (when a bigger chunk of view is represented by a single thing in the model) but this applies to non-editable part of the view (e.g. the body of a widget). In the editable part of the content, everything in the view must map well to something in the model because every position in the view must map to some position in the model. And vice versa.

In your case, the problem is that when you converted a model element to a view text, that model element is not mapped to anything in the view. That breaks a series of things – starting from position mapping to some other pieces of code which will expect that they can map elements too.

Theoretically, it might be possible to override how positions and elements map here. CKEditor 5's Mapper offers some mechanisms for that (check out the events), but I would not go this way. It requires really deep knowledge and tests (even I'm unsure how much work it requires 😅).

So, do follow the placeholder guide where a model element is converted to a view element and vice versa.



来源:https://stackoverflow.com/questions/55247198/how-to-implement-a-placeholder-plugin-that-works-with-plain-text-placeholders

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!