This is kind of an academic question because I've all but given up, but maybe we can learn a few things about CKEditor5 by trying to solve it!
I'm using a pretty bare-bones installation of CKEditor from https://ckeditor.com/ckeditor-5/online-builder with just some basic styling features.
My use case is pretty basic but my users need to enter certain special characters and I want to include support for material icons (from Google)
Something along these lines
If you're not familiar with material icons, they use a special font and some CSS wizardry to display icons similar to font awesome. They are here: https://fonts.google.com/icons?icon.set=Material+Icons they come in two varieties, icons and symbols which are very similar but we're concerned with icons in this case.
The syntax for the icons is
<span class="material-icons-outlined">
emoji_emotions
</span>
and it uses some font wizardry to make that turn into something like
You can also use a single entity such as 
to accomplish the same behaviour and it's the option I've opted for in my implementation.
My chosen markup is
<material-icon class='material-icons'></material-icon>
A little redundant I know but I wanted to separate them from just spans.
Anyway, out of the box CKEditor doesn't allow pasting unknown elements and strips it down to just the html entity so you need to add a new schema, something like this
export default function schemaCustomization(editor) {
// Extend schema with custom HTML elements.
const dataFilter = editor.plugins.get('DataFilter');
const dataSchema = editor.plugins.get('DataSchema');
// Inline element
dataSchema.registerInlineElement({
view: 'material-icon',
model: 'materialIcon',
modelSchema: {
inheritAllFrom: '$inlineBlock'
},
attributeProperties: {
copyOnEnter: true,
},
});
// // Custom elements need to be registered using direct API instead of config.
dataFilter.allowElement('material-icon');
dataFilter.allowAttributes({ name: 'element-inline', classes: /^.*$/ });
}
This will register the element with the editor and allow it to be accepted into the document.
Then you add it to your options, alongside the previous htmlSupport plugin and you're good to go!
options = {
toolbar: {
items: [],
},
htmlSupport: {
allow: [
{
name: 'material-icon',
classes: /^.*$/,
},
],
disallow: [
/* HTML features to disallow */
],
},
extraPlugins: [schemaCustomization],
removePlugins: []
};
A lot of documentation I used comes from here: https://ckeditor.com/docs/ckeditor5/latest/framework/guides/deep-dive/schema.html
However, there's one problem!!
The element remains editable and if someone clicks inside the material-icon
tag and starts entering text, it gets messed up.
I need a way to make the material-icon element be somehow self-contained or atomic and only allow a single character inside.
I've been playing around with all kinds of settings but I'm not sure which are the correct ones and where they're even meant to go.
For now I've switched to just using unicode emoji but they really don't look as nice.
I've tried a lot of the settings and options from https://ckeditor.com/docs/ckeditor5/latest/framework/guides/deep-dive/schema.html and I think there are multiple ways to register these sorts of elements.
I was expecting it to work somehow but the ability to edit within the tags and break the layout is an unintended side effect.
Does anyone have any experience with the latest version of CKEditor and performing these sorts of low-level mechanics? Any help is appreciated!