Paul Odeon
Paul Odeon

Reputation: 4524

Adding classes to links in CKeditor

I have some specific requirements around adding classes to links in ckeditor5 - I have read the docs and tried numerous approaches but I'm still struggling to achieve what I want here. My requirements are:

  1. All links added (whether using the link UI, or via paste) must have a class assigned. That class should be set to defaultClass if no class is assigned or the class assigned is not in the list of valid classes

  2. Link classes must be in the list of valid link classes

I have built a dropdown containing a list of the valid classes and added it to the link interfaceLink class dropdown

Here is the code I have so far:

    const { editor } = this

    const linkClasses = editor.config.get('link.options.classes')
    const defaultLinkClass = editor.config.get('link.options.defaultClass')

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

    editor.conversion.for('downcast').attributeToElement({
      model: 'linkClass',
      view: (attributeValue, writer) => writer.createAttributeElement('a', { class: attributeValue }, { priority: 5 }),
      converterPriority: 'low'
    })

    editor.conversion.for('upcast').attributeToAttribute({
      view: {
        name: 'a',
        key: 'class'
      },
      model: 'linkClass',
      converterPriority: 'low'
    })

Upvotes: 9

Views: 6644

Answers (3)

Paul Odeon
Paul Odeon

Reputation: 4524

The key to the solution is in the upcast converter - I eventually stumbled on to: https://stackoverflow.com/a/55019124/803804

This led me to realise you can pass a callback into the attributeToAttribute converter https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_conversion_upcasthelpers-UpcastHelpers.html#function-attributeToAttribute

Really simple in the end:

editor.conversion.for('upcast').attributeToAttribute({
  view: {
    name: 'a',
    key: 'class'
  },
  model: {
    key: 'linkClass',
    value: viewElement => {
      if(this.classes.includes(viewElement.getAttribute('class'))) {
        return viewElement.getAttribute('class')
      } else {
        return this.defaultClass
      }
    }
  },
  converterPriority: 'low'
})

Upvotes: 3

Nishal K.R
Nishal K.R

Reputation: 1130

Use callback function in decorators and inside the callback, use setTimeout function to check the valid class list in the urls.

Check the jsFiddle. Refer CKEditor5 manual decorators in Links for more and please confirm the Link plugin installed @ckeditor/ckeditor5-link

Hope this will help.

Thank You

Upvotes: 2

Sreeram Nair
Sreeram Nair

Reputation: 2387

If you are looking to define custom class, look for Custom Editor JS Styles Set in the field configuration and enter a path for .js file.

In this file you can define your custom styles like this:

CKEDITOR.stylesSet.add
( 'mystyles', 
    [ 
        { name: 'Bootstrap Blockquote', 
          element: 'blockquote', 
          attributes: { 'class': 'blockquote' }
        },
    ] 
);

Also make sure you have Styles toolbar item enabled

You should also check out styling using the Styles features of the editor here

Upvotes: 1

Related Questions