CKEditor and GeSHi filter

Sat, 02/20/2010 - 01:04 -- Peter Petrik

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.

Comments

Submitted by worldfallz (not verified) on

Just a little variation on this-- you can easily add geshi styles using pre tags by:

  1. add 'Styles' to the toolbar you use
  2. copy ckeditor.styles.js from sites/all/modules/ckeditor to your theme's directory
  3. edit the ckeditor.styles.js file as desired. I removed most of the styles already there and added a bunch of lines like the following for each language I wanted to list:
    { name : 'Geshi: php'   , element : 'pre', attributes : { 'language' : 'php' } },

Works great and you don't need all those extra buttons.

Submitted by JamZiur (not verified) on

Hello,

It is a really good mini tutorial. However, I am still having problem to replace special characters ("<",">",""") for some reason the geshifilter is not working. Do you have any idea what could be happening?

Regards
JamZiur

Submitted by Peter Petrik on

I have now adjusted the code above and put the following line at the end of the code block:

$code = str_replace("&amp;", "&", $code);

This allows for entering special character markup, such as &#39; without it being interpreted by the browser or GeSHi filter and turning them back into the special character in the code block.

Submitted by Steve (not verified) on

Peter,

I got this to work (almost) perfectly, so thanks a ton for this.

The only problem I have is that when I apply the highlighting, a blank line gets added between each line of code. It still gets treated as a code block as a whole, but the syntax highlighting doesn't take effect. If I go in and manually delete the blank lines, then the syntax highlighting takes effect. Any ideas on what would cause that or how to fix it?

Thanks.

Submitted by Peter Petrik on

I think you are pasting in the code, which converts the line breaks into paragraphs <p>, then applying the code highlighting. Apply the highlighting first, then paste the code. Once you past into a <pre> block, the line breaks will not convert to a paragraph.

Updating to the latest CKEditor module (6.x-1.1) will also give you the option to force "Paste as plain text" which may help to strip out the formatting.

Submitted by SkullSplitter (not verified) on

hmm i see no Icons in the ckEditor :(

whats wrong ? i do all in the tutorial :/

Cheers

Skull

Submitted by Peter Petrik on

It would be helpful to know your setup. Are you running Drupal? Which version? CKEditor module? Geshifilter module? CKEditor code? GeSHi code? Which versions? All installed in correct directories? Does it all work as expected and only giving you trouble with this particular modification?

Hello!

This is a great and rare tutorial. Thank you for writing it.

I am having the same problem as the previous comment.

All of the ckeditor buttons are blank; they are not labeled with text.

I have followed the instructions here to the letter. I can see in my plugin.js file that there are buttonLabels being added, but nothing appears? It is a blank row.

(But geshi works great!)

Submitted by Wouter (not verified) on

I've tried implementing your solution a couple of times, but without success. I've now tried the new geshi bridge, again, without success. It shows up in the wysiwyg - ckeditor, but not on the actual blog pages. Also, when I use it as code, it doesn't work. I've posted a question about it on the drupal groups pages, but no help yet. http://groups.drupal.org/node/65398#comment-198023

Any chance that you have some advice?

Submitted by Peter Petrik on

Based on those comments it seems that you are depending on the WYSIWYG module to manage the CKEditor interface. The steps outlined above are for a straight installation of CKEditor; in the installations I manage I also use the Better Formats module for finer control of HTML and toolbar permissions.

Submitted by Jan Brinkmann (not verified) on

Hey. First of all thank you for this great tutorial. I followed all steps and also implemented the "styles hint" suggested by "worldfallz". However, like a few others I have the problem that highlighted code is surrounded by span-tags which are somehow related to bookmarks of the ckeditor (_fck_bookmark). All I've found so far is a ticket which is about changing this to _ck_... because the "_fck" prefix was related to the fckeditor .
It' possibly related to the modification which was suggested by "worldfallz", since span tags and a _fck_bookmark attributes can be found:

"sites/all/modules/ckeditor/ckeditor/ckeditor/_source/plugins/styles/plugin.js"

I'm still trying to solve this on my own and would love to share a possible answer. If anybody can tell me how to solve this though, I would also like to avoid investigating this on my own since I'm not a JavaScript expert (yet ;).

- Versions:
* ckeditor module 6.x-1.x-dev (without wysiwyg api and without the bridge)
* latest ckeditor 3.4
* drupal core 6.19
* geshi 1.0.8.8 (using 1.0.8.4 doesnt make a difference)

- Modifications made
* geshi.php modified, special chars are translated correctly (thanks Peter!)
* Styles modification (Posted by worldfallz (not verified) on Mar 17, 2010 at 11:34)

For a description also see:
- http://drupal.org/node/890080

Any ideas about this issue?

Submitted by Peter Petrik on

Based on the comments and the issue posted at drupal.org I assume you are using the WYSIWYG module. The solution outlined above utilizes only the CKEditor and GeSHi module. The WYSIWYG module has some advantages, but once configured the above solution works great without need to tweak it continuously.

Submitted by Peter Petrik on

As I mentioned at drupal.org, this is an issue with newer versions of CKEditor. I posted on the CKEditor forums asking for insight, but received no answer. I've even tried the newest version 3.4.1, but it only changes the content of span tags.

Version 3.2, 3.3, and 3.4

<span _fck_bookmark="1" style="display: none;"> </span>

Version 3.4.1

<span style="display: none;"> </span>

Unfortunately, the working solution is to stay with version 3.1 for now.

As a sidenote, the newer versions also break the ckeditor module features such as inserting the Drupal teaser break.

Hi Peter,
I'm Tony, the guy who wrote the GeSHi filter for Pixie you mentioned.
Nice article; V informative.
Although I believe my implementation is _best_ (I would, haha) your implementation is safer when untrusted users are involved.
So there's a trade off involved in both ways for developers looking for syntax highlighting plugins for CKEditor.
The two questions developers need to ask themselves are :
Can you afford the extra server load of parsing all those code blocks through GeSHi every time a visitor requests it?
And :
Can you really leave that GeSHi input dialog sitting there for a potential attacker to exploit?

So my point really is that for trusted users, I use my way but for untrusted (Site facing) user input; I'd choose your way because it's safer.

Related to syntax highlighting CKEditor plugins, I just put up a syntax highlighting source mode demo here : http://heydojo.co.cc/ckeditor-codemirror/index.html
Mainly to gauge my knowledge of the CKEditor API at this point and to show others how I implement CKEditor.

Thanks,
Tony

Submitted by Peter Petrik on

Thanks for your comments! I agree with the assessment that the pop-up opens up potential issues with untrusted users. As mentioned elsewhere in the comments, there has been effort to streamline the installation and configuration through the WYSIWYG module, but so far the above remains the widely used solution, especially when external users are involved.

Submitted by Visitor (not verified) on

after doing all above i have these span tags like above user .Can you help me in getting rid of them .Thanks for your article.

Submitted by Peter Petrik on

Tough to respond directly when you don't leave a valid email.

Check your ckeditor.config.js file and make sure that <span> tags are NOT protected (should be in/around lines 16-23)

Submitted by Visitor (not verified) on

Can you please elaborate this a little i didnt find anything that protect tags in the ckeditor.config.js .Also i cant find the source files which can change the way ckeditor applies formatting to the tags.

Submitted by Peter Petrik on

Check your sites/all/modules/ckeditor/ckeditor.config.js around line 16:

// Protect PHP code tags (<?...?>) so CKEditor will not break them when
// switching from Source to WYSIWYG.
// Uncommenting this line doesn't mean the user will not be able to type PHP
// code in the source. This kind of prevention must be done in the server
// side
// (as does Drupal), so just leave this line as is.
config.protectedSource.push(/<\?[\s\S]*?\?>/g); // PHP Code

If you have a line with span tags designated as protectedSource, you will experience the issue described

config.protectedSource.push( /<span[\s\S]*?\/span>/g );

So far, every time someone spoke of this issue it was a configuration error. If it still persists, I'd be glad to look at your setup if you contact me.

Submitted by Visitor (not verified) on

:( my post didn't get approved.Can you please look into the ckeditor.config.js file since there is nothing that protects span tag and after digging into source file i couldn't find anything to filter that out.

Submitted by Domenom (not verified) on

Hello from Ukraine & Sorry bad English.

When i try highlite code

require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
$return = menu_execute_active_handler();

I have

require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
$return = menu_execute_active_handler();

I use Drupal 6.19 & CKEditor 3.4.1

Submitted by rovr138 (not verified) on

I tried implementing this but have a problem.

When I add the code to activates the new plugin, CKEditor doesn't appear when creating or editing a node.

With what version of the ckeditor module was this done? I'm using version 6.x-1.2 of the module and ckeditor v3.1.

Looking forward to any insight you can bring!

Submitted by Peter Petrik on

Those are the correct versions. I would check admin/settings/ckeditor/edit/Default (Default being the name of the profile) and verify the Visibility Settings. Set that to 1, as to eliminate the dependency while you verify that's not causing an issue.

Submitted by Peter Petrik on

Due to the popularity of this post, I have updated the most recent versions of respective pieces that this configuration is known to work with.

Submitted by Peter Petrik on

I have not tested this under D7 yet, but I am open to contributions from the community.

Hi Peter,
I did just what you told step by step. Finally, I have the text buttons on the toolbar. But when I click one of the buttons, there is no dialog box poping up. I input some code in textarea, but the code is not highlighted. Did I miss some configuration? You may take a look at the issue at http://mynoteweb.com
Thanks a lot for your tutorial.

Henry

Submitted by Peter Petrik on

Checked out your site - it works very nicely there! This approach doesn't provide for a pop out a dialog box, nor does it automatically format the text in the CKEditor. However, as soon as you preview / save it displays correctly. Take a look at node 12726 on your site.

Submitted by Visitor (not verified) on

Thank you very much! Yes, you're right. After saving, I can see the highlight results. You're amazing:)

Submitted by Visitor (not verified) on

I ask if you can show me how you installed the various modules and libraries you are referring to in the article.
Because when i installed and i search to configure the geshi filter, i recived one error: "Geshi not found the library"

Thank you for some help
and sorry for my bad english.

Submitted by Peter Petrik on

Sounds like you are installing the module, but not the geshi library - be sure to look at bullet #4 under the Installation heading above.

Submitted by Visitor (not verified) on

i have installed every bullets, but the geshi module not found libraries.

I download geshi from main sites: http://qbnz.com/highlighter/

unziped and put into directory ../sites/all/modules/geshifilter/

my situation is:

../sites/all/libraries/ckeditor
../sites/all/modules/ckeditor
../sites/all/modules/geshifilter
../sites/all/modules/geshifilter/geshi

when i try to configure geshifilter modules, i saw one main error: "Geshi not found the library" and i no can edit configuration.

How you installed and configure geshi filter and library? How you dispose the directory geshifilter and geshi library

Submitted by Peter Petrik on

Check the ../sites/all/modules/geshifilter/geshi directory to see if your geshi library is present. Seems that your installation is not finding it correctly. Next place to search would be the geshi module issues queue on D.O.

Also note I have updated the notes above to reflect how plugins are handled by the CKEditor module from version 6.x-1.4 forward.

I am using Drupal 7 with Wysiwyg module, Ckeditor and geshi filter.
I had problem with editing geshified nodes thats why i've removed ckeditor from geshi filter profile and using it with plain textbox.
I can not edit or create nodes as intented ... There unwanted "" and disappearing codes problem.

Are there any solution for this issue ?
I've tried to change filter orders and so ...

Submitted by Peter Petrik on

I'd check ckeditor.config.js in sites/all/modules/ckeditor or in your theme directory to see if CKEditor has any special config.protectedSource.push entries.

Also lookup the section above with // Replace all newlines to a common form. to ensure you have made those entries.

Thanks for the tutorial. Haven't been able to get it working yet but I don't think I'm far from a solution. I had a couple questions. Just so everyone is on the same page:

Drupal 7-4, and latest module (7.x) of everything else required.

When I look under GeSHi filter config, it is finding the 1.0.8 version, so I don't think the problem is there.

Questions:

1) When it says to copy ckeditor.config.js to site theme, is that the theme root or the 'js' directory. FYI, I'm using a subtheme of Zen. I changed the ckeditor to use this .js file in the theme dir but no difference.

2) With "Create new toolbar - copy DrupalFull and edit accordingly" - what is "DrupalFull"? And where to add "['Geshi-code','Geshi-php','Geshi-bash','Geshi-html','Geshi-css'],"

--> In D7 under Editor Appearance there is a textarea to modify the tool bar (that is where I added IMCE) successfully.

3) The plugin doesn't show under CKEditor configuration. Everything is in the right place there so not sure what is missing. Is it related to this: requires : [ 'styles', 'button' ], --> Are style/buttons modules that need to be installed?

Thanks for any help!

Submitted by Peter Petrik on

Thanks for your feedback. I'll be implementing this on a D7 install within the next 4-6 weeks, so expect an updated blog post.

Put the ckeditor.config.js in your subtheme directory, same place as where the theme_name.info file is located.

The newest CKEditor module in both D6 and D7 has created quite a mess with the way they handle the toolbar specifications. You could try adding the ['Geshi-code','Geshi-php','Geshi-bash','Geshi-html','Geshi-css'], code there.

Submitted by ssm2017 (not verified) on

hello
thank you for your tutorial.
i don't know if you still take care about it and if yes, i would like to inform you about the actual status using :
- drupal 6.25
- ckeditor 6.x-1.8 / 3.6.2
- geshifilter 6.x-1.4 / 1.0.8.10

here are the steps i have followed :

- download, install the drupal modules and copy the javascript libraries to the desired place
(all is fine and javascript libraries are recognized by the drupal modules)

- copy the file : ckeditor.config.js to the theme folder
(testing on a fresh drupal install, im using garland so i have copied it to /sites/all/themes/garland/ckeditor.config.js)

- edit the file and copy the DrupalFull toolbar.
(what name should we give to this new toolbar ? ok i have renamed it to : Drupal.settings.cke_toolbar_DrupalTest = [.... and added the toolbar buttons code at the end. And after tests i have copied the toolbar buttons to every toolbar to see any changement and still nothing appears.)

- on line 27 the code....
(the line 27 is : config.extraPlugins = '';)

- line 3 of the code...
(the line 3 of the code is : For licensing, see LICENSE.html or http://ckeditor.com/license )

so we don't know what to do with the code you have given :
if (Drupal.ckeditorCompareVersion....
we see that it speaks about the config.extraPlugins but what to do with that ? should we replace the line 27 with your 4 lines code ? im not using ckeditor 3.1 so it is not clear.
i have changed it to :
config.extraPlugins = 'geshi';
but no success.

- create a directory called geshi inside /sites/all/modules/ckeditor/plugins and create a new file called plugin.js and add the code inside
(ok, done)

- go to admin/settings/ckeditor and choose a profile that will be using geshi and under appearance enable the plugin
(ok, i can see the checkbox speaking about geshi plugin and i enable it)

- to enable buttons for the toolbar, copy the css code to the theme css file (for kama theme)
(done (kama theme is the default one so i keep the kama theme too))

- to keep using the "pre" tag, go to admin/settings/geshifilter/general and add pre to the generic syntax highlighting tag
(done)

- for the issue of converting special entities as <.....copy the code to line 2141 of geshi.php
(done the line number is still the good one)

- enable geshi filter in input formats and be sure to have a higher priority than url filter
(not clear about the priority you speak about : let's admit that url filter has a weight of 0, geshi should have -1 or +1 ?)

- clear the site and browser cache and you should see the new 5 buttons.
(done (browser and site caches cleared but no buttons))

now, i don't see any button and i don't know how to use this tutorial so im doing like i do since long time, im not using a wysiwyg to input some code and im writing html by hand using <code lang="bash"> for example.

i have mentionned what is not clear in my comments but there is also something missing.
how to insert code ?
as i can imagine, pushing the buttons should show a pop up allowing to insert code (im dreaming about it :) )
but sadly, no buttons appear.
maybe i have forgotten a step or maybe the problem is coming from the step about : config.extraPlugins, i don't know

if you still have the patience to update this tutorial, maybe you can save some kittens :)
good luck and thanks for attention