CKEditor doesn't allow Custom Headings

Created on 14 March 2024, 2 months ago
Updated 4 May 2024, 14 days ago

Problem/Motivation

CKEditor5 allows adding custom headings to the Headings plugins.

This is done by setting the 'view' of a heading to an array/object of HTML element name and custom classes instead of the default of just HTML element name

Default:

view: 'h2'

Custom:

view: {
    name: 'h2',
    classes: 'fancy'
},

However the current Heading plugin code only accepts a string value for view.

Steps to reproduce

1. Implement the ckeditor5_plugin_info_alter hook to add a new custom plugin.

function hook_ckeditor5_plugin_info_alter(array &$plugin_definitions) {
  $heading_plugin_definition = $plugin_definitions['ckeditor5_heading']
    ->toArray();
    
  // Add custom heading.
  $heading_plugin_definition['ckeditor5']['config']['heading']['options'][] = [
    'model' => 'custom_heading',
    'title' => t('Custom Heading'),
    'view' => [
      'name' => 'div',
      'classes' => 'custom-heading-class',
    ],
    'class' => 'ck-heading_custom-heading',
  ];

  $plugin_definitions['ckeditor5_heading'] = new CKEditor5PluginDefinition($heading_plugin_definition);
}

2. Enable this plugin in Text Format config:

3. Get the following error:

Warning: Array to string conversion in Drupal\ckeditor5\Plugin\CKEditor5Plugin\Heading->enabledHeadingsToTags() (line 216 of core/modules/ckeditor5/src/Plugin/CKEditor5Plugin/Heading.php).

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

šŸ’¬ Support request
Status

Fixed

Version

11.0 šŸ”„

Component
CKEditor 5Ā  ā†’

Last updated about 4 hours ago

Created by

šŸ‡®šŸ‡³India dipakmdhrm

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @dipakmdhrm
  • Pipeline finished with Success
    2 months ago
    Total: 477s
    #118873
  • Status changed to Fixed 2 months ago
  • šŸ‡§šŸ‡ŖBelgium Wim Leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    This is not a bug report but at best a feature request. You're altering code. Code that is NOT an API. šŸ˜… (\Drupal\ckeditor5\Plugin\CKEditor5Plugin\Heading)

    We have āœØ [upstream] [Style] Allow CKEditor 5 to *create* a directly (instead of first , then adding a class) Needs work for the <h2 class="fancy"> scenario. If you wish to do the customizations that you're doing here, you can do that but then it's up to you to maintain this forever in contrib.

    If you really want to provide configuration UI support for this too, then you'll need to subclass \Drupal\ckeditor5\Plugin\CKEditor5Plugin\Heading and override some methods, because otherwise \Drupal\ckeditor5\Plugin\CKEditor5Plugin\Heading::validChoices() will fail validation. Note that this class is marked @internal so it's NOT an API.

    I personally would go for a much simpler approach, avoid all of the above, and create a custom module that literally only contains a *.info.yml file and a *.ckeditor5.yml file that looks like this:

    MYMODULE_customHeadings:
      ckeditor5:
        plugins: []
        config:
          heading:
            options:
              - { model: 'custom_heading', title: 'Custom Heading', view: { model: 'div', class: 'custom-heading-class'}, 'ck-heading_custom-heading' }
      drupal:
        label: My Custom Headings
        elements:
          - <div class="custom-heading-class'">
        conditions:
          plugins:
            - ckeditor5_heading
    

    šŸ‘† This would append that one additional option and have no UI at all.

  • Automatically closed - issue fixed for 2 weeks with no activity.

  • šŸ‘† This would append that one additional option and have no UI at all.

    This part:
    - { model: 'custom_heading', title: 'Custom Heading', view: { model: 'div', class: 'custom-heading-class'}, 'ck-heading_custom-heading' }
    doesn't seem to work for me. It somehow breaks the CKEditor (toolbar is visible, but text editing part is not. JS console prints "CKEditorError: e is undefined")

    I managed to fix it with:
    - { model: 'custom_heading', title: 'Custom Heading', view: { name: 'div', classes: [ 'custom-heading-class' ] }, class: 'ck-heading_custom-heading' }

    Also changed the
    - <div class="custom-heading-class'">
    to
    - <div class="custom-heading-class">
    (removed the ' character.)

    So leaving this comment just in case someone else tries to use the example, because it's nice starting point.

Production build 0.67.2 2024