Code syntax highlighting in Drupal using CKEditor's new features

CKEditor introduced widgets in 4.3 and with this, an entire new set of plugins emerged who use widget in order to embed special types of "rich" content. One of the plugins is CodeSnippet.

Using CodeSnippet we are able to highlighted syntax in an CKEditor editor and keep our normal "filtered html" settings. So you can create lines like these:

echo "hello world!";

Note: There are older techniques available for CKEditor 3.x , or you can use the codefilter module without a wysiwyg editor. But I think this new approach is much more user-friendly and elegant.

What you'll need:

The easiest way to make sure you have all the plugin is by using the Content Delivery Network url in the "CKEditor path" field in "CKEditor global" settings. The full-all distributions contains all the plugins you need.

//cdn.ckeditor.com/4.4.5/full-all

Now, you should see the "Plugin for inserting Code Snippets" in the list of detected plugins in your CKEditor profile, under "Editor appearance". Mark the checkbox and drag the new button to your toolbar.

If you have any other filters enabled (you should have "Limit allowed HTML tags" or perhaps "wysiwy_filter"), make sure that the <pre> and <code> tags are allowed. 

Save your settings and fire up a node which has a CKEditor field to enter some code with the new button!

Note: Changing CKEditor configurations requires clearing all caches AND clearing your browser cache. Tip: if you are using chrome dev-tools (inspector) you can choose in the settings to never cache while DevTools is open.

Syntax highlighting

Optionally, but recommended, you'll want to highlight (color-code) the embedded syntacx. In the CKEditor editor, this is done automatically by the codesnippet plugin which uses the highlightjs.org library. But for the output you will need a server-side processor, the recommended one is GeSHi.

The Drupal GeSHi module provides an input filter and works beautifully together with the output generated by CKEditor + codesnippet.

Note: as mentioned in the comments, there is also a CodeSnippet GeSHi plugin available for CKEditor that uses GeSHi instead of highlightjs. This should lead to better consistency between the editor display and Drupal output display as both would be using the same library.

Configuring GeSHifilter

In order to make it work, you will need to make a couple of configuration changes from the default settings. First, choose the languages and change the tag/language attribute value which is used to determine the code language.

CodeSnippet generates code like this:

<code class="language-php">echo "hello world!";

So make sure your attributes are matching:

GeSHi filter language settings in Drupal

Note: CKEditor codesnippet will replace HTML in a code snippet with HTML entities (the CKEditor setting to turn this off does not apply for code snippets). As a result the entity code is also shown in the ouput instead of the original HTML. This makes sense, otherwise the HTML would get rendered by CKEditor but in order to view it as proper HTML when rendered in the frontend, we need to decode it in the geshifilter module. Patching geshifilter.module does the trick but the patch is not 100% fullproof.

Make sure the GeSHI filter is enabled for your textformat and the order is after filters like wysiwyg_filter or "Limit allowed HTML tag".

CKEditor localy:

If you want to host CKEditor locally instead of using the CDN in above example, make sure you have these plugins:

Another thing that can be tricky getting CKEditor to recognize your CodeSnippet plugin. (the plugin discovery system is being improved in this patch) but placing the plugins in your plugins is not enough.

In that case will need to implement a hook in order to get the button working:

/**
 * Implementation of hook_ckeditor_plugin
 */
function mymodule_ckeditor_plugin() {
  $plugins = array(
    'codesnippet' => array(
      'name' => 'codesnippet',
      // Description of the plugin - it would be displayed in the plugins management section of profile settings.
        'desc' => t('Plugin for inserting Code Snippets. See !link for more details. See !help for additional instructions.', array(
          '!link' => l(t('addon page'), 'http://ckeditor.com/addon/codesnippet'),
          '!help' => l(t('help'), 'admin/help/ckeditor', array('fragment' => 'codesnippet'))
        )),
      // The full path to the location of the plugin.js
      // Note: base_path is only required if you apply this patch: https://www.drupal.org/node/2159403
      'path' => base_path() . drupal_get_path('module', 'mymodule') . '/plugins/codesnippet/',
      'buttons' => array(
        // Beware of the CamelCase syntax!
        'CodeSnippet' => array(
          'icon' => 'icons/codesnippet.png',
          'label' => 'Insert Code Snippet',
        )
      )
    ),
  );
  return $plugins;
}

GeSHi has a lot of other options, like numbering lines and various way for styling. I prefer only to let GeSHi add classes and add the required CSS to my own stylesheets.

Notes DrupalCon Amsterdam 2014

Read More »

About

This is the company blog of
Drupal specialist Merge.nl

We are located in Breda (Netherlands) and build websites using Drupal. More about us.

Content on this blog is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Netherlands License.

Creative Commons License

Recent Comments

Social