CKEditor and GeSHi filter

Update: This approach does not involve the WYSIWYG module. It relies on the installation of CKEditor (module and editor) without a middleman management module. If you desire finer control of toolbar display by roles or HTML functionality permissions, take a closer look at the Better Formats module.

It is easier to focus on content when working with a WYSIWYG editor. I can always switch to view the source code if I need to do more complex editing. As I continue to document my Drupal experiences, I wanted to use a syntax highlighter when sharing code samples.

First, I looked at the Syntax Highlighter module. I liked the javascript functionality, ability for visitors to quickly copy the code, and other features. The drawback is that once installed, the javascript code loads on every page. Considering that only a fraction of my posts contain code, I didn't feel the performance trade-off was worth it.

Another well-reviewed solution is GeSHi (Generic Syntax Highlighter). Well supported, but little documented especially when using it with CKEditor.

An immediate interaction issue is that CKEditor correctly transcribes any special characters, such as < >, into special entities - &lt; and &gt;. Once GeSHi filter highlights the syntax, the special entities are preserved. Here is how to resolve this problem. For ease of use, I have also created a CKEditor plugin that adds five of my most used code formats to the toolbar.

Installation

Download / install / enable / configure (most recent correctly working versions indicated below):

To add shortuct buttons to the toolbar copy ckeditor.config.js from sites/all/modules/ckeditor to your site's theme directory:
Create new toolbar - copy DrupalFull and edit accordingly
Add new GeSHi toolbar buttons

['Geshi-code','Geshi-php','Geshi-bash','Geshi-html','Geshi-css'],

On line 27, the code checks for CKEditor version and activates Drupal specific plugins. Line 3 of the code activates the new plugin (for CKeditor module 6.x-1.3 and earlier)

if (Drupal.ckeditorCompareVersion('3.1')) {
  config.extraPlugins += (config.extraPlugins ? ',drupalbreaks' : 'drupalbreaks' );
  config.extraPlugins += (config.extraPlugins ? ',geshi' : 'geshi' );
}

Toolbar buttons

Functionality of the toolbar shortcut buttons:

  • In sites/all/modules/ckeditor/plugins create new directory geshi
  • Within the geshi directory, create file plugin.js
  • Within plugin.js define the button functions by inserting this code (download)
/**
* @file Geshi plugin
*/
CKEDITOR.plugins.add( 'geshi',
{
	requires : [ 'styles', 'button' ],

	init : function( editor )
	{
		// All buttons use the same code to register. So, to avoid
		// duplications, let's use this tool function.
		var addButtonCommand = function( buttonName, buttonLabel, commandName, styleDefiniton )
		{
			var style = new CKEDITOR.style( styleDefiniton );

			editor.attachStyleStateChange( style, function( state )
				{
					editor.getCommand( commandName ).setState( state );
				});

			editor.addCommand( commandName, new CKEDITOR.styleCommand( style ) );

			editor.ui.addButton( buttonName,
				{
					label : buttonLabel,
					command : commandName
				});
		};

		var config = editor.config;
//		var lang = editor.lang;

		addButtonCommand( 'Geshi-code'		, 'code'		, 'Geshi-code'	, config.coreStyles_code );
		addButtonCommand( 'Geshi-php'		, 'php'			, 'Geshi-php'		, config.coreStyles_php );
		addButtonCommand( 'Geshi-bash'		, 'bash'		, 'Geshi-bash'	, config.coreStyles_bash );
		addButtonCommand( 'Geshi-html'		, 'html'		, 'Geshi-html'		, config.coreStyles_html );
		addButtonCommand( 'Geshi-css'		, 'css'			, 'Geshi-css'	, config.coreStyles_css );
	}
});

// Basic Inline Styles.
CKEDITOR.config.coreStyles_code			= { element : 'pre' };
CKEDITOR.config.coreStyles_php			= { element : 'pre', attributes : { 'language' : 'php' } };
CKEDITOR.config.coreStyles_bash			= { element : 'pre', attributes : { 'language' : 'bash' } };
CKEDITOR.config.coreStyles_html			= { element : 'pre', attributes : { 'language' : 'html4strict' } };
CKEDITOR.config.coreStyles_css			= { element : 'pre', attributes : { 'language' : 'css' } };

Enable plugin

In your browser, go to yoursite.com/admin/settings/ckeditor and choose a profile that will be using Geshi. Under Editor Appearance enable Geshi plugin. This handling of plugins is new to the CKEditor module from version 6.x-1.4 in Drupal.

Toolbar button theme

If desired, it is possible to use icons for the buttons. The simpler solution is to edit your theme's css file and use the button label for the text. Code below assumes you are using the Kama skin.

.cke_skin_kama .cke_button_Geshi-code span.cke_icon,
.cke_skin_kama .cke_button_Geshi-php span.cke_icon,
.cke_skin_kama .cke_button_Geshi-bash span.cke_icon,
.cke_skin_kama .cke_button_Geshi-html span.cke_icon,
.cke_skin_kama .cke_button_Geshi-css span.cke_icon
{
  	display:none !important;
}

.cke_skin_kama .cke_button_Geshi-code span.cke_label,
.cke_skin_kama .cke_button_Geshi-php span.cke_label,
.cke_skin_kama .cke_button_Geshi-bash span.cke_label,
.cke_skin_kama .cke_button_Geshi-html span.cke_label,
.cke_skin_kama .cke_button_Geshi-css span.cke_label
{
  	display:inline;
  	font-size: 90%;
}

GeSHi configuration

I prefer to use the <pre> tag with an attribute. If I choose a different syntax highlighter in the future, the style will be preserved as the browser will not try to interpret the code - the default behavior for <pre> tag.

To ensure that GeSHi filter interprets the syntax within the <pre> tags, navigate to admin/settings/geshifilter/general and add pre to the Generic syntax highlighting tags. While here, enable the desired languages you want to have highlighted.

For the issue of GeSHi not converting special entities such as &lt; and &gt; open geshi.php from sites/all/modules/geshifilter/geshi and add the following code on line 2141. You can also search for "// Replace all newlines to a common form." in the existing code.

// Replace all newlines to a common form.
 = str_replace("&gt;", ">", );
 = str_replace("&lt;", "<", );
 = str_replace("&lsaquo;", "‹", );
 = str_replace("&rsaquo;", "›", );
 = str_replace("&#39;", "'", );
 = str_replace("&quot;", "\"", );
 = str_replace("&amp;", "&", );

Input formats configuration

Enable GeSHi filter in input formats. Be sure that the GeSHi filter has higher priority than URL filter.

Clear the site and browser caches and you should see 5 new buttons in your toolbar. Ready to share some code?

There are additional ideas, such as putting the different code types into a drop-down menu, or having a dialog box open up - similar to an existing solution for Pixie.

Share this post