尝试构建插件以在ckEditor5中设置ol
的开始属性。
据我所知,该模型包含listItems
的集合。
需要在ol
上设置start属性,但是,列表项的父级而不是列表项本身..有一种方法可以从模型中访问ol
?
我可以通过获取当前的li
first(editor.model.document.selection.getSelectedBlocks())
是否可以在ol
元素上设置属性?
编辑-获取LI属性的代码:
editor.model.schema.extend('listItem', { allowAttributes: 'listStart' });
editor.conversion.attributeToAttribute({
model: 'listStart',
view: 'start'
});
在模型中启用:<listItem type="numbered" listStart="4">
,它将在视图中转换为:
<ol>
<li start="4">words</li>
</ol>
我想要实现的是
<ol start="4">
<li>words</li>
</ol>
当我检查源代码时,看起来ol
(或ul
)是在此处自动创建的:
function generateLiInUl( modelItem, conversionApi ) {
const mapper = conversionApi.mapper;
const viewWriter = conversionApi.writer;
const listType = modelItem.getAttribute( 'listType' ) == 'numbered' ? 'ol' : 'ul';
const viewItem = createViewListItemElement( viewWriter );
// ** OL or UL created here -->
const viewList = viewWriter.createContainerElement( listType, null );
viewWriter.insert( ViewPosition.createAt( viewList ), viewItem );
mapper.bindElements( modelItem, viewItem );
return viewItem;
}
我可以观察到一个事件吗?还是转换定义中有一种方法可以将属性定位到父级?
更新2
如果我们要使用mod源,我们可以通过将其添加到generateLiInUl
函数中(通过MTilsted)来拦截向下转换:
const listStart = modelItem.getAttribute('listStart');
if (listStart) {
viewWriter.setAttribute('start', listStart, viewList);
}
并为了方便上传,请将其添加到viewModelConverter
函数
const listStart = data.viewItem.parent.getAttribute('start');
if (listStart) {
writer.setAttribute( 'listStart', listStart, listItem );
}
这有点丑陋,因为我们正在修改源代码(用于维护的皮塔饼),并且在泛滥中,我们向模型中的每个listStart
元素添加了listItem
属性。.但这是一个开始
我简要地考虑了添加调度程序。例如:
data.upcastDispatcher.on( 'element:li', myCustomUpcastFunction );
但无法弄清楚如何获得对上述listItem
函数中添加到模型的viewModelConverter
元素的引用。
答案 0 :(得分:1)
已更新: 好的,生成列表的工作方式很奇怪。这可能与列表的合并方式和更改类型有关。我必须承认我不太了解那部分的工作原理。
我无法找到一种根据需要向下转换属性的方法,因此,除非Cksource的某个人来临,否则我唯一能找到的解决方案就是修补列表代码。而且我不确定这与上播效果如何。 (仅经过轻轻测试)。
但是在文件node_modules/@ckeditor/ckeditor5-list/src/converters.js
只需尝试添加以下行:
viewWriter.setAttribute('start',model.getAttribute('listStart'),viewList);
方法
function generateLiInUl( modelItem, conversionApi ) {
在我的ckeditor版本(最新版本)中,应将其添加到第810行。
原始答案(完整但不用于列表)。
哦,是的。您对模型是正确的。但是ckeditor 5中的整个设计要点是,您不必修改现有插件即可添加属性。您可以在架构中注册额外的属性,然后在自己的插件中添加匹配的DowncastElementToElement。
这是我用来向图像类添加额外属性的代码。改为在listItems上工作应该是微不足道的。 (从代码的不同位置剪切/粘贴,所以我可能忘记了一些东西,但是请尝试一下。如果您无法使它正常工作,我将在星期一制作一个可以正常工作的示例:)
model.schema.extend('image', {
allowAttributes: ['displaywidth','ignorecolumns','fullpagepicture']
} );
editor.conversion.for('upcast')
.add(upcastAttributeToAttribute( { model: 'isvisible', view: 'isvisible' }))
.add(upcastAttributeToAttribute( { model: 'displaywidth', view: 'displaywidth' }))
.add(upcastAttributeToAttribute( { model: 'fullpagepicture', view: 'fullpagepicture' }))
editor.conversion.for('downcast')
.add(downcastAttributeToAttribute( { model: 'isvisible', view: 'isvisible' }))
.add(downcastAttributeToAttribute( { model: 'displaywidth', view: 'displaywidth' }))
.add(downcastAttributeToAttribute( { model: 'fullpagepicture', view: 'fullpagepicture' }))
答案 1 :(得分:1)
对我有用的答案很简单,我觉得很早就看不到它了:使用LI value
属性而不是OL start
属性。
<ol>
<li value="4">words</li>
</ol>
代替:
<ol start="4">
<li>words</li>
</ol>
这会将属性保留在listItem上,并避免了所有麻烦(我在最初的尝试中完全错过了LI的value属性的存在):
editor.model.schema.extend('listItem', { allowAttributes: 'value' });
editor.conversion.attributeToAttribute({
model: 'value',
view: 'value'
});
应用值的命令:
execute(arg) {
let val = arg.value;
const model = this.editor.model;
const block = first(model.document.selection.getSelectedBlocks());
model.change(writer => {
if (+val) {
writer.setAttribute('value', val, block);
} else {
writer.removeAttribute('value', block);
}
});
}
并在输入时防止将值复制到下一个LI:
editor.commands.get('enter').on('afterExecute', () => {
const block = first(editor.model.document.selection.getSelectedBlocks());
if ( block.name == 'listItem' && block.hasAttribute('value')) {
editor.model.change( writer => {
writer.removeAttribute('value', block);
});
}
});
答案 2 :(得分:0)
我猜@Steve 已经解决了他的问题,但他的问题帮助我理解了我自己的问题。因此,我想帮助像我一样需要帮助的人。
首先,我注意到按照之前的建议更改内置插件并这样做是不正常的。 CKEditor 创建者鼓励我们使用覆盖内置逻辑的自定义插件。因此,请使用 CKEditor API 来更改编辑器行为。
我的解决方案是
// @ckeditor/ckeditor5-core@25.0.0
import Plugin from '@ckeditor/ckeditor5-core/src/plugin'
export class ListStartAttribute extends Plugin {
init() {
console.log('ListStartAttribute is init')
const editor = this.editor
// 1.extend schema
editor.model.schema.extend('listItem', { allowAttributes: 'start' })
// 2.set conversion up/down
editor.conversion.for('downcast').add(dispatcher => {
dispatcher.on('attribute', (evt, data, conversionApi) => {
if (data.item.name != 'listItem') {
return
}
const viewWriter = conversionApi.writer
const viewElement = conversionApi.mapper.toViewElement(
data.item
)
const containerElement = viewElement.parent
if (
data.attributeNewValue &&
!containerElement.getAttribute('start')
) {
viewWriter.setAttribute(
data.attributeKey,
data.attributeNewValue,
containerElement
)
}
})
})
editor.conversion.for('upcast').attributeToAttribute({
model: {
name: 'listItem',
key: 'start',
},
view: {
name: 'ol',
key: 'start',
},
converterPriority: 'low',
})
}
}