Back to Top

Better WordPress Syntax (based on GeSHi)

Better WordPress Syntax (based on GeSHi)

This plugin allows you to highlight code syntax in your posts. It is simple, lightweight, and very easy to use with plenty of options to choose.

Yet another syntax highlighting plugin for WordPress you might say, but there’s always a reason why things are made, right? As the title has told you, this plugin utilizes the popular PHP syntax highlighting library – GeSHi. Why should you choose a server-side parser over a client-side (Javascript, or Syntax Highlighter in particular)? The answer is the number of languages supported and the reliance on Javascript. Okay, enough babbling, let me tell you how this plugin is different and, hopefully, better:

Plugin Features

  • Load the plugin only when you need it
  • Option to load media files (CSS, JS, etc.) only when needed
  • Built-in hooks for easier customization
  • A lot of options to choose (I bet you don’t need them all!)
  • Preview any snipplet of code to match your preference
  • Possibility to add more languages
  • Parse code within <pre> tag, <code> tag or using shortcode
  • Parse code within comments
  • Editor button to add code
  • Two output methods, Table or Ordered list
  • Style code globally or language-based
  • Toolbar with toggle button and view source button
  • Work with major browsers, including the all time driving-developers-crazy Internet Explorer 6
  • WordPress Multi-site compatible (not tested with WPMU)
  • Actively developed
  • … And more :D

Plugin Usage

Basic Usage

Most of the time, you will only need this:

<pre lang="lang">your code;</pre>

where lang is the language you want the plugin to parse, it can be php, css, js, etc. As of version 1.0.4, this plugin provides 17 languages, including: PHP, Perl, Python, Ruby, C, Java, Javascript, CSS, VBscript, XML, HTML4, Bash, CSharp, Apache, ActionScript, ActionScript3, and MySQL. This is done to make sure that BWP Syntax only parses what is allowed. You can of course add more or remove any as you please, please refer to the customization section for more details.

Currently supported attributes for use with <pre> tag and shortcode are:

'lang'   — The language you want to parse, if none specified, this plugin will use the default language.
'toggle' — Whether or not to toggle the codeblock, default to 'yes', 'no' to disable
'start'  — Start counting line numbers from this number, default to 1
'extra'  — Highlight one or several lines, useful when you are writing a tutorial
'inline' — Output inline element instead of a codeblock, default to 'no', 'yes' to enable
'nested' — Whether or not to treat this codeblock as nested, i.e. it will be bypassed, default to 'no', 'yes' to enable, only apply to shortcode
'parse'  — Parse this codeblock or leave as-is, default to 'yes'
'strict' — Only parse codes inside appropriate wrapper, for example <?php "only parse here" ?>, set to 'yes'

You can also post inline code, such as <code>your code;</code>, or if you want, you can also do this: <pre inline="yes">your code</pre>, which will basically do the same thing. Please keep in mind that the <code> tag will only accept two attributes: ‘lang’ and ‘parse’.

What if you have already used some other plugins that utilize the shortcode [code lang="etc"]? This plugin by default does not parse such shortcode, but you can enable that feature if you want; however you should keep in mind these notes.

Advanced Usage

This section will just show you many examples that you can use, you can combine any if you wish, it’s up to you :). Please note that all attributes are affected by options you choose in the configuration page. For example you can choose to add toggle button to all codeblocks by default. When you don’t want to add that button to a specific block, simply add the attribute toggle with the value “no”.

1. Posting a codeblock without a toggle button<pre lang="php" toggle="no"></pre>:

  1. function add_hooks()
  2. {
  3.     // For html related shortcode, parse shortcode before it got wpautoped
  4.     if ($this->options['enable_shortcode'] == 'yes')
  5.     {
  6.         if ($this->options['enable_nested_remove'] == 'yes')
  7.         {
  8.             // Format content to avoid nesting problems
  9.             add_filter('the_content', array($this, 'pre_format_content'), 6);
  10.             add_filter('comment_text', array($this, 'pre_format_content'), 6);
  11.         }
  12.         // Parse the shortcode, @see $this->shortcode_tag
  13.         add_filter('the_content', array($this, 'pre_parse_shortcodes'), 7);
  14.         // Bring back square bracket, after the normal do_shortcode hook
  15.         add_filter('the_content', array($this, 'after_parse_shortcodes'), 12);
  16.     }
  17. }
function add_hooks()
{
	// For html related shortcode, parse shortcode before it got wpautoped
	if ($this->options['enable_shortcode'] == 'yes')
	{
		if ($this->options['enable_nested_remove'] == 'yes')
		{
			// Format content to avoid nesting problems
			add_filter('the_content', array($this, 'pre_format_content'), 6);
			add_filter('comment_text', array($this, 'pre_format_content'), 6);
		}
		// Parse the shortcode, @see $this->shortcode_tag
		add_filter('the_content', array($this, 'pre_parse_shortcodes'), 7);
		// Bring back square bracket, after the normal do_shortcode hook
		add_filter('the_content', array($this, 'after_parse_shortcodes'), 12);
	}
}

2. Posting a codeblock with a starting line of 5 and highlight line 11, 14, and 20<pre start="5" extra="11, 14, 20">code</pre> – Note that it doesn’t matter what line you starts from, highlighted lines are counted from zero.

  1. /**
  2.  * Constructor
  3.  *
  4.  * @param   array   $args   The alias array, you can filter this using WordPress add_filter function to define your own.
  5.  */
  6. function __construct($args = array())
  7. {
  8.     // The default options
  9.     $options = array(
  10.         'only_singular' => 'yes',
  11.         'enable_pre'    => 'yes',
  12.         'enable_shortcode' => '',
  13.         'enable_lines'  => 'yes',
  14.         'enable_toggle' => 'yes',
  15.         'enable_code_tag' => '',
  16.         'enable_nested_remove'  => '',
  17.         'enable_comment'=> 'yes',
  18.         'enable_credit' => '',
  19.         'input_lines'               => 15,
  20.         'input_line_height'         => 16.8,
  21.         'input_width'               => 0,
  22.         'input_tab'                 => 4,
  23.         'select_output_method'      => 'table',
  24.         'select_style_method'       => 'lang',
  25.         'select_source_position'    => 'overlay',
  26.         'select_default_language'   => 'php'
  27.     );
  28.  
  29.     /* BWP FRAMEWORK CODE */
  30.     $this->build_properties('BWP_SYNTAX', 'bwp-syntax', $options, __('BetterWP Syntax', 'bwp-syntax'), dirname(dirname(__FILE__)) . '/bwp-syntax.php', 'http://betterwp.net/wordpress-plugins/bwp-syntax/', false);
  31.     $this->add_option_key('BWP_SYNTAX_OPTION_GENERAL', 'bwp_syntax_general', __('General Options', 'bwp-syntax'));
  32.     $this->add_option_key('BWP_SYNTAX_OPTION_THEME', 'bwp_syntax_template', __('Theme Options', 'bwp-syntax'));
  33.     /* BWP FRAMEWORK CODE */
  34.  
  35.     $defaults = array(
  36.         'php'   => 'php',
  37.         'html'  => 'html4strict',
  38.         'java'  => 'java',
  39.         'js'    => 'javascript',
  40.         'css'   => 'css',
  41.         'perl'  => 'perl',
  42.         'py'    => 'python',
  43.         'ruby'  => 'ruby',
  44.         'c'     => 'c',
  45.         'vb'    => 'vb',
  46.         'xml'   => 'xml'
  47.     );
  48. }
/**
 * Constructor
 *
 * @param	array	$args	The alias array, you can filter this using WordPress add_filter function to define your own.
 */
function __construct($args = array())
{
	// The default options
	$options = array(
		'only_singular' => 'yes',
		'enable_pre'	=> 'yes',
		'enable_shortcode' => '',
		'enable_lines'	=> 'yes',
		'enable_toggle' => 'yes',
		'enable_code_tag' => '',
		'enable_nested_remove'	=> '',
		'enable_comment'=> 'yes',
		'enable_credit'	=> '',
		'input_lines'				=> 15,
		'input_line_height'			=> 16.8,
		'input_width'				=> 0,
		'input_tab'					=> 4,
		'select_output_method'		=> 'table',
		'select_style_method'		=> 'lang',
		'select_source_position'	=> 'overlay',
		'select_default_language'	=> 'php'
	);

	/* BWP FRAMEWORK CODE */
	$this->build_properties('BWP_SYNTAX', 'bwp-syntax', $options, __('BetterWP Syntax', 'bwp-syntax'), dirname(dirname(__FILE__)) . '/bwp-syntax.php', 'http://betterwp.net/wordpress-plugins/bwp-syntax/', false);
	$this->add_option_key('BWP_SYNTAX_OPTION_GENERAL', 'bwp_syntax_general', __('General Options', 'bwp-syntax'));
	$this->add_option_key('BWP_SYNTAX_OPTION_THEME', 'bwp_syntax_template', __('Theme Options', 'bwp-syntax'));
	/* BWP FRAMEWORK CODE */

	$defaults = array(
		'php'	=> 'php',
		'html' 	=> 'html4strict',
		'java'	=> 'java',
		'js' 	=> 'javascript',
		'css' 	=> 'css',
		'perl'	=> 'perl',
		'py'	=> 'python',
		'ruby'	=> 'ruby',
		'c'		=> 'c',
		'vb'	=> 'vb',
		'xml'	=> 'xml'
	);
}

3. A codeblock that will not be parsed<pre parse="no">code</pre>

// This is not parsed

4. Let’s put them all together<pre lang="php" toggle="no" start="3" extra="6,8,10">code</pre>

  1. function enqueue_media()
  2. {
  3.     global $wp_styles;
  4.     // Enqueue needed media, only if needed
  5.     if((!is_admin() && 'yes' != $this->options['enable_selective']) || ('yes' == $this->options['only_singular'] && is_singular()) || (empty($this->options['only_singular']) && !is_admin()) || $this->is_admin_page())
  6.     {
  7.         if ($this->options['select_style_method'] == 'lang')
  8.         {
  9.             if ('classes' == $this->options['select_output_style'])
  10.                 wp_enqueue_style('bwp-syntax', apply_filters('bwp_syntax_lang_style', BWP_SYNTAX_CSS . '/bwp-syntax.css'));
  11.             else
  12.                 wp_enqueue_style('bwp-syntax', apply_filters('bwp_syntax_lang_style', BWP_SYNTAX_CSS . '/bwp-syntax-inline.css'));
  13.         }
  14.         else
  15.             wp_enqueue_style('bwp-syntax', apply_filters('bwp_syntax_global_style', BWP_SYNTAX_CSS . '/bwp-syntax-global.css'));
  16.         wp_enqueue_script('bwp-syntax-js', BWP_SYNTAX_JS . '/bwp-syntax.js', array('jquery'));
  17.     }
  18. }
function enqueue_media()
{
	global $wp_styles;
	// Enqueue needed media, only if needed
	if((!is_admin() && 'yes' != $this->options['enable_selective']) || ('yes' == $this->options['only_singular'] && is_singular()) || (empty($this->options['only_singular']) && !is_admin()) || $this->is_admin_page())
	{
		if ($this->options['select_style_method'] == 'lang')
		{
			if ('classes' == $this->options['select_output_style'])
				wp_enqueue_style('bwp-syntax', apply_filters('bwp_syntax_lang_style', BWP_SYNTAX_CSS . '/bwp-syntax.css'));
			else
				wp_enqueue_style('bwp-syntax', apply_filters('bwp_syntax_lang_style', BWP_SYNTAX_CSS . '/bwp-syntax-inline.css'));
		}
		else
			wp_enqueue_style('bwp-syntax', apply_filters('bwp_syntax_global_style', BWP_SYNTAX_CSS . '/bwp-syntax-global.css'));
		wp_enqueue_script('bwp-syntax-js', BWP_SYNTAX_JS . '/bwp-syntax.js', array('jquery'));
	}
}

Customization

A plugin should always allow users to customize things, and in my opinion, this plugin does that quite well.

Adding custom languages

To add more languages, there are two things you must do with the first being adding a filter and the second being generating some CSS (in case you choose to style globally or using inline styles, you do not need to generate any CSS). Please don’t worry if you don’t know what a filter is, because it will be just like “copy and paste”.

1. To add a filter, open your theme’s functions.php file and add these lines in any place you wish, preferably at the end of that file:

  1. add_filter('bwp_syntax_languages', 'bwp_add_custom_langs');
  2.  
  3. function bwp_add_custom_langs()
  4. {
  5.     $custom_lang = array(
  6.         'language alias' => 'language key name'
  7.     );
  8.     return $custom_lang;
  9. }
add_filter('bwp_syntax_languages', 'bwp_add_custom_langs');

function bwp_add_custom_langs()
{
	$custom_lang = array(
		'language alias' => 'language key name'
	);
	return $custom_lang;
}

Language alias is simply a short name for a language, this is used so that you can type lang="js" instead of lang="javascript", which is a huge time saver. Language key name, on the contrary, must be the same as the name of a parser file included with the GeSHi package (most of the time the key name will be identical to the language’s name, e.g. pascal is the key name for Pascal). Now for example you want to find the key name for Action Script 3, open the this plugin’s folder and navigate to /includes/geshi/geshi/. In this folder, you can see actionscript.php and actionscript3.php, simply copy “actionscript3″ as your language key name. Now we will have 'as3' => 'actionscript3' for example. Please note that currently you can not have the same alias for two key names, this will be improved in future versions.

2. To generate CSS for a custom language, open the Theme Options in this plugin’s configuration page, scroll to the bottom, type in the language key name you have just found above, press Save changes, and voila, your CSS is generated; now copy it into your own CSS files, for example, style.css, and the new language is successfully added! If you need more than one language, simply repeat those two steps.

Ouput methods and custom CSS

Basically, you can choose between two output methods, Table or Ordered List. Table is recommended over Ordered List simply because it is much easier to style and requires almost no hack to look the same on every browser. The catch is that you can not style each line differently, for example, two adjacent lines can not have different colors. The Ordered List approach allows you to do that (as you can see in those example above) but the problem is it will be harder to style and there’s no easy way to give background color to the number without breaking the codeblock in some browsers (to my surprise, IE6 displays just fine, while Google Chrome, Safari and Opera fails, some time the buggy one wins, who knows?) Whether you choose Table or Ordered List, to override the CSS file used by this plugin, you have two options:

1. Replace that CSS file. To do this, add one of these lines to your theme’s functions.php, preferably at the end:

  1. add_filter('bwp_syntax_lang_style', create_function('', 'return "";')); // for language-based style
  2. add_filter('bwp_syntax_global_style', create_function('', 'return "";')); // for global style
add_filter('bwp_syntax_lang_style', create_function('', 'return "";')); // for language-based style
add_filter('bwp_syntax_global_style', create_function('', 'return "";')); // for global style

Now if you refresh your blog, you should see all default codeblock styles vanish (well, not actually vanish, but no longer being used). Please be careful with this approach because it can hurt your layout badly if you haven’t prepared an alternative stylesheet to style the codeblocks (I would just copy the entire CSS provided by this plugin, and then make changes to it.)

2. (safer, and easier): Override just the CSS rules you want while leaving all other rules untouched. To do so, you would enqueue a style normally, but with bwp-syntax as the parent (or required) stylesheet, like so:

  1. wp_enqueue_style('your-handle', 'url-to-your-css-file', array('bwp-syntax'));
  2. // the last bit, array('bwp-syntax'), indicates that your style will be loaded after this plugin's style
wp_enqueue_style('your-handle', 'url-to-your-css-file', array('bwp-syntax'));
// the last bit, array('bwp-syntax'), indicates that your style will be loaded after this plugin's style

Now in your CSS file you can override a rule very easily. Let’s say you want to have border for your codeblock, you simply add this:

  1. .bwp-syntax-block {
  2.     border: 1px solid #cccccc;
  3. }
.bwp-syntax-block {
	border: 1px solid #cccccc;
}

or you might want the Ordered List to wrap your codes, add this:

  1. .bwp-syntax-wrapper li, #comments .bwp-syntax-wrapper li, #content .bwp-syntax-wrapper li {
  2.     white-space: normal;
  3. }
.bwp-syntax-wrapper li, #comments .bwp-syntax-wrapper li, #content .bwp-syntax-wrapper li {
	white-space: normal;
}

A sample CSS file is attached below, or you can click here to download.

Important Notes

Language-based styling vs. Global styling

- Language-based: Since language-based styling varies from language to language, the size of CSS files can be noticeable. With each language added, approximately 1-2KB will be added to the size of the a CSS file. Languages that are not available will not get parsed.

- Global: You don’t have to generate any CSS for each custom language and you do not have to worry about the size of any CSS file. The only drawback is all codeblocks will likely have the same color scheme. Unlike language-based styling, languages that are not available will still get parsed. CodeColorer, another syntax highlighting plugin, offers a very nice global stylesheet that can be applied to this plugin if you want. I even include the Dawn color scheme from that plugin in the bwp-syntax-global.css. If you feel like you need more, follow what I have written in the customization section to add your custom CSS file. Oh, and if you feel so lazy about downloading another plugin just to take the CSS, you can take it in the codeblock below:

  1. /* "Slush & Poppies" color scheme */
  2. /* Comment */
  3. .codecolorer .co0, .codecolorer .co1, .codecolorer .co2, .codecolorer .co3, .codecolorer .co4, .codecolorer .coMULTI { color: #406040; font-style: italic; }
  4. /* Constant */
  5. .codecolorer .nu0, .codecolorer .re3 { color: #0080A0; }
  6. /* String */
  7. .codecolorer .st0, .codecolorer .st_h, .codecolorer .es0, .codecolorer .es1 { color: #C03030; }
  8. /* Entity */
  9. .codecolorer .me1, .codecolorer .me2 { color: #0080FF; }
  10. /* Keyword */
  11. .codecolorer .kw1, .codecolorer .kw2, .codecolorer .sy1 { color: #2060A0; }
  12. /* Storage */
  13. .codecolorer .kw3, .codecolorer .kw4, .codecolorer .kw5, .codecolorer .re2 { color: #008080; }
  14. /* Variable */
  15. .codecolorer .re0, .codecolorer .re1 { color: #A08000; }
  16. /* Global color */
  17. .codecolorer .br0, .codecolorer .sy0 { color: #000000; }
  18. /* Storage */
  19. .codecolorer .xml .re1 { color: #008080; }
  20. /* Constant */
  21. .codecolorer .xml .re0 { color: #0080A0; }
  22. /* Highlight lines */
  23. .codecolorer .ln-xtra { background-color: #ffff66; }
  24.  
  25. /* "Twitlight" color scheme */
  26. .twitlight, .twitlight .codecolorer { color: #F8F8F8; background-color: #141414; }
  27. .twitlight .codecolorer .co0, .twitlight .codecolorer .co1, .twitlight .codecolorer .co2, .twitlight .codecolorer .co3, .twitlight .codecolorer .co4, .twitlight .codecolorer .coMULTI,
  28.     code.twitlight .co0, code.twitlight .co1, code.twitlight .co2, code.twitlight .co3, code.twitlight .co4, code.twitlight .coMULTI
  29.     { color: #5F5A60; font-style: italic; }
  30. .twitlight .codecolorer .nu0, .twitlight .codecolorer .re3,
  31.     code.twitlight .nu0, code.twitlight .re3
  32.     { color: #CF6A4C; }
  33. .twitlight .codecolorer .nu0, .twitlight .codecolorer .re3,
  34.     code.twitlight .nu0, code.twitlight .re3
  35.     { color: #8F9D6A; }
  36. .twitlight .codecolorer .me1, .twitlight .codecolorer .me2,
  37.     code.twitlight .me1, code.twitlight .me2
  38.     { color: #9B703F; }
  39. .twitlight .codecolorer .kw1, .twitlight .codecolorer .kw2, .twitlight .codecolorer .sy1,
  40.     code.twitlight .kw1, code.twitlight .kw2, code.twitlight .sy1
  41.     { color: #CDA869; }
  42. .twitlight .codecolorer .kw3, .twitlight .codecolorer .kw4, .twitlight .codecolorer .kw5, .twitlight .codecolorer .re2,
  43.     code.twitlight .kw3, code.twitlight .kw4, code.twitlight .kw5, code.twitlight .re2
  44.     { color: #F9EE98; }
  45. .twitlight .codecolorer .re0, .twitlight .codecolorer .re1,
  46.     code.twitlight .re0, code.twitlight .re1
  47.     { color: #7587A6; }
  48. .twitlight .codecolorer .br0, .twitlight .codecolorer .sy0,
  49.     code.twitlight .br0, code.twitlight .sy0
  50.     { color: #F8F8F8; }
  51. .twitlight .xml .re1 { color: #F9EE98; }
  52. .twitlight .xml .re0 { color: #CF6A4C; }
  53.  
  54. /* "Blackboard" color scheme */
  55. .blackboard, .blackboard .codecolorer { color: #F8F8F8; background-color: #0C1021; }
  56. .blackboard .codecolorer .co0, .blackboard .codecolorer .co1, .blackboard .codecolorer .co2, .blackboard .codecolorer .co3, .blackboard .codecolorer .co4, .blackboard .codecolorer .coMULTI,
  57.     code.blackboard .co0, code.blackboard .co1, code.blackboard .co2, code.blackboard .co3, code.blackboard .co4, code.blackboard .coMULTI
  58.     { color: #AEAEAE; font-style: italic; }
  59. .blackboard .codecolorer .nu0, .blackboard .codecolorer .re3,
  60.     code.blackboard .nu0, code.blackboard .re3
  61.     { color: #D8FA3C; }
  62. .blackboard .codecolorer .st0, .blackboard .codecolorer .st_h, .blackboard .codecolorer .es0, .blackboard .codecolorer .es1,
  63.     code.blackboard .st0, code.blackboard .st_h, code.blackboard .es0, code.blackboard .es1
  64.     { color: #61CE3C; }
  65. .blackboard .codecolorer .me1, .blackboard .codecolorer .me2,
  66.     code.blackboard .me1, code.blackboard .me2
  67.     { color: #FF6400; }
  68. .blackboard .codecolorer .kw1, .blackboard .codecolorer .kw2, .blackboard .codecolorer .sy1,
  69.     code.blackboard .kw1, code.blackboard .kw2, code.blackboard .sy1
  70.     { color: #FBDE2D; }
  71. .blackboard .codecolorer .kw3, .blackboard .codecolorer .kw4, .blackboard .codecolorer .kw5, .blackboard .codecolorer .re2,
  72.     code.blackboard .kw3, code.blackboard .kw4, code.blackboard .kw5, code.blackboard .re2
  73.     { color: #FBDE2D; }
  74. .blackboard .codecolorer .re0, .blackboard .codecolorer .re1,
  75.     code.blackboard .re0, code.blackboard .re1
  76.     { color: #F8F8F8; }
  77. .blackboard .codecolorer .br0, .blackboard .codecolorer .sy0,
  78.     code.blackboard .br0, code.blackboard .sy0
  79.     { color: #F8F8F8; }
  80. .blackboard .xml .re1 { color: #FBDE2D; }
  81. .blackboard .xml .re0 { color: #D8FA3C; }
  82.  
  83. /* "Mac Classic" color scheme */
  84. .mac-classic, .mac-classic .codecolorer { color: #000000; background-color: #FFFFFF; }
  85. .mac-classic .codecolorer .co0, .mac-classic .codecolorer .co1, .mac-classic .codecolorer .co2, .mac-classic .codecolorer .co3, .mac-classic .codecolorer .co4, .mac-classic .codecolorer .coMULTI,
  86.     code.mac-classic .co0, code.mac-classic .co1, code.mac-classic .co2, code.mac-classic .co3, code.mac-classic .co4, code.mac-classic .coMULTI
  87.     { color: #0066FF; font-style: italic; }
  88. .mac-classic .codecolorer .nu0, .mac-classic .codecolorer .re3,
  89.     code.mac-classic .nu0, code.mac-classic .re3
  90.     { color: #0000CD; }
  91. .mac-classic .codecolorer .st0, .mac-classic .codecolorer .st_h, .mac-classic .codecolorer .es0, .mac-classic .codecolorer .es1,
  92.     code.mac-classic .st0, code.mac-classic .st_h, code.mac-classic .es0, code.mac-classic .es1
  93.     { color: #036A07; }
  94. .mac-classic .codecolorer .me1, .mac-classic .codecolorer .me2,
  95.     code.mac-classic .me1, code.mac-classic .me2
  96.     { color: #0000A2; }
  97. .mac-classic .codecolorer .kw1, .mac-classic .codecolorer .kw2, .mac-classic .codecolorer .sy1,
  98.     code.mac-classic .kw1, code.mac-classic .kw2, code.mac-classic .sy1
  99.     { color: #0000FF; }
  100. .mac-classic .codecolorer .kw3, .mac-classic .codecolorer .kw4, .mac-classic .codecolorer .kw5, .mac-classic .codecolorer .re2,
  101.     code.mac-classic .kw3, code.mac-classic .kw4, code.mac-classic .kw5, code.mac-classic .re2
  102.     { color: #0000FF; }
  103. .mac-classic .codecolorer .re0, .mac-classic .codecolorer .re1,
  104.     code.mac-classic .re0, code.mac-classic .re1
  105.     { color: #318495; }
  106. .mac-classic .codecolorer .br0, .mac-classic .codecolorer .sy0,
  107.     code.mac-classic .br0, code.mac-classic .sy0
  108.     { color: #000000; }
  109. .mac-classic .xml .re1 { color: #0000FF; }
  110. .mac-classic .xml .re0 { color: #0000CD; }
  111.  
  112. /* "Vibrant Ink" color scheme */
  113. .vibrant, .vibrant .codecolorer { color: #FFFFFF; background-color: #000000; }
  114. .vibrant .codecolorer .co0, .vibrant .codecolorer .co1, .vibrant .codecolorer .co2, .vibrant .codecolorer .co3, .vibrant .codecolorer .co4, .vibrant .codecolorer .coMULTI,
  115.     code.vibrant .co0, code.vibrant .co1, code.vibrant .co2, code.vibrant .co3, code.vibrant .co4, code.vibrant .coMULTI
  116.     { color: #9933CC; font-style: italic; }
  117. .vibrant .codecolorer .nu0, .vibrant .codecolorer .re3,
  118.     code.vibrant .nu0, code.vibrant .re3
  119.     { color: #339999; }
  120. .vibrant .codecolorer .st0, .vibrant .codecolorer .st_h, .vibrant .codecolorer .es0, .vibrant .codecolorer .es1,
  121.     code.vibrant .st0, code.vibrant .st_h, code.vibrant .es0, code.vibrant .es1
  122.     { color: #66FF00; }
  123. .vibrant .codecolorer .me1, .vibrant .codecolorer .me2,
  124.     code.vibrant .me1, code.vibrant .me2
  125.     { color: #FFCC00; }
  126. .vibrant .codecolorer .kw1, .vibrant .codecolorer .kw2, .vibrant .codecolorer .sy1,
  127.     code.vibrant .kw1, code.vibrant .kw2, code.vibrant .sy1
  128.     { color: #FF6600; }
  129. .vibrant .codecolorer .kw3, .vibrant .codecolorer .kw4, .vibrant .codecolorer .kw5, .vibrant .codecolorer .re2,
  130.     code.vibrant .kw3, code.vibrant .kw4, code.vibrant .kw5, code.vibrant .re2
  131.     { color: #FFCC00; }
  132. .vibrant .codecolorer .re0, .vibrant .codecolorer .re1,
  133.     code.vibrant .re0, code.vibrant .re1
  134.     { color: #FFFFFF; }
  135. .vibrant .codecolorer .br0, .vibrant .codecolorer .sy0,
  136.     code.vibrant .br0, code.vibrant .sy0
  137.     { color: #FFFFFF; }
  138. .vibrant .xml .re1 { color: #FFCC00; }
  139. .vibrant .xml .re0 { color: #339999; }
/* "Slush & Poppies" color scheme */
/* Comment */
.codecolorer .co0, .codecolorer .co1, .codecolorer .co2, .codecolorer .co3, .codecolorer .co4, .codecolorer .coMULTI { color: #406040; font-style: italic; }
/* Constant */
.codecolorer .nu0, .codecolorer .re3 { color: #0080A0; }
/* String */
.codecolorer .st0, .codecolorer .st_h, .codecolorer .es0, .codecolorer .es1 { color: #C03030; }
/* Entity */
.codecolorer .me1, .codecolorer .me2 { color: #0080FF; }
/* Keyword */
.codecolorer .kw1, .codecolorer .kw2, .codecolorer .sy1 { color: #2060A0; }
/* Storage */
.codecolorer .kw3, .codecolorer .kw4, .codecolorer .kw5, .codecolorer .re2 { color: #008080; }
/* Variable */
.codecolorer .re0, .codecolorer .re1 { color: #A08000; }
/* Global color */
.codecolorer .br0, .codecolorer .sy0 { color: #000000; }
/* Storage */
.codecolorer .xml .re1 { color: #008080; }
/* Constant */
.codecolorer .xml .re0 { color: #0080A0; }
/* Highlight lines */
.codecolorer .ln-xtra { background-color: #ffff66; }

/* "Twitlight" color scheme */
.twitlight, .twitlight .codecolorer { color: #F8F8F8; background-color: #141414; }
.twitlight .codecolorer .co0, .twitlight .codecolorer .co1, .twitlight .codecolorer .co2, .twitlight .codecolorer .co3, .twitlight .codecolorer .co4, .twitlight .codecolorer .coMULTI,
	code.twitlight .co0, code.twitlight .co1, code.twitlight .co2, code.twitlight .co3, code.twitlight .co4, code.twitlight .coMULTI
	{ color: #5F5A60; font-style: italic; }
.twitlight .codecolorer .nu0, .twitlight .codecolorer .re3,
	code.twitlight .nu0, code.twitlight .re3
	{ color: #CF6A4C; }
.twitlight .codecolorer .nu0, .twitlight .codecolorer .re3,
	code.twitlight .nu0, code.twitlight .re3
	{ color: #8F9D6A; }
.twitlight .codecolorer .me1, .twitlight .codecolorer .me2,
	code.twitlight .me1, code.twitlight .me2
	{ color: #9B703F; }
.twitlight .codecolorer .kw1, .twitlight .codecolorer .kw2, .twitlight .codecolorer .sy1,
	code.twitlight .kw1, code.twitlight .kw2, code.twitlight .sy1
	{ color: #CDA869; }
.twitlight .codecolorer .kw3, .twitlight .codecolorer .kw4, .twitlight .codecolorer .kw5, .twitlight .codecolorer .re2,
	code.twitlight .kw3, code.twitlight .kw4, code.twitlight .kw5, code.twitlight .re2
	{ color: #F9EE98; }
.twitlight .codecolorer .re0, .twitlight .codecolorer .re1,
	code.twitlight .re0, code.twitlight .re1
	{ color: #7587A6; }
.twitlight .codecolorer .br0, .twitlight .codecolorer .sy0,
	code.twitlight .br0, code.twitlight .sy0
	{ color: #F8F8F8; }
.twitlight .xml .re1 { color: #F9EE98; }
.twitlight .xml .re0 { color: #CF6A4C; }

/* "Blackboard" color scheme */
.blackboard, .blackboard .codecolorer { color: #F8F8F8; background-color: #0C1021; }
.blackboard .codecolorer .co0, .blackboard .codecolorer .co1, .blackboard .codecolorer .co2, .blackboard .codecolorer .co3, .blackboard .codecolorer .co4, .blackboard .codecolorer .coMULTI,
	code.blackboard .co0, code.blackboard .co1, code.blackboard .co2, code.blackboard .co3, code.blackboard .co4, code.blackboard .coMULTI
	{ color: #AEAEAE; font-style: italic; }
.blackboard .codecolorer .nu0, .blackboard .codecolorer .re3,
	code.blackboard .nu0, code.blackboard .re3
	{ color: #D8FA3C; }
.blackboard .codecolorer .st0, .blackboard .codecolorer .st_h, .blackboard .codecolorer .es0, .blackboard .codecolorer .es1,
	code.blackboard .st0, code.blackboard .st_h, code.blackboard .es0, code.blackboard .es1
	{ color: #61CE3C; }
.blackboard .codecolorer .me1, .blackboard .codecolorer .me2,
	code.blackboard .me1, code.blackboard .me2
	{ color: #FF6400; }
.blackboard .codecolorer .kw1, .blackboard .codecolorer .kw2, .blackboard .codecolorer .sy1,
	code.blackboard .kw1, code.blackboard .kw2, code.blackboard .sy1
	{ color: #FBDE2D; }
.blackboard .codecolorer .kw3, .blackboard .codecolorer .kw4, .blackboard .codecolorer .kw5, .blackboard .codecolorer .re2,
	code.blackboard .kw3, code.blackboard .kw4, code.blackboard .kw5, code.blackboard .re2
	{ color: #FBDE2D; }
.blackboard .codecolorer .re0, .blackboard .codecolorer .re1,
	code.blackboard .re0, code.blackboard .re1
	{ color: #F8F8F8; }
.blackboard .codecolorer .br0, .blackboard .codecolorer .sy0,
	code.blackboard .br0, code.blackboard .sy0
	{ color: #F8F8F8; }
.blackboard .xml .re1 { color: #FBDE2D; }
.blackboard .xml .re0 { color: #D8FA3C; }

/* "Mac Classic" color scheme */
.mac-classic, .mac-classic .codecolorer { color: #000000; background-color: #FFFFFF; }
.mac-classic .codecolorer .co0, .mac-classic .codecolorer .co1, .mac-classic .codecolorer .co2, .mac-classic .codecolorer .co3, .mac-classic .codecolorer .co4, .mac-classic .codecolorer .coMULTI,
	code.mac-classic .co0, code.mac-classic .co1, code.mac-classic .co2, code.mac-classic .co3, code.mac-classic .co4, code.mac-classic .coMULTI
	{ color: #0066FF; font-style: italic; }
.mac-classic .codecolorer .nu0, .mac-classic .codecolorer .re3,
	code.mac-classic .nu0, code.mac-classic .re3
	{ color: #0000CD; }
.mac-classic .codecolorer .st0, .mac-classic .codecolorer .st_h, .mac-classic .codecolorer .es0, .mac-classic .codecolorer .es1,
	code.mac-classic .st0, code.mac-classic .st_h, code.mac-classic .es0, code.mac-classic .es1
	{ color: #036A07; }
.mac-classic .codecolorer .me1, .mac-classic .codecolorer .me2,
	code.mac-classic .me1, code.mac-classic .me2
	{ color: #0000A2; }
.mac-classic .codecolorer .kw1, .mac-classic .codecolorer .kw2, .mac-classic .codecolorer .sy1,
	code.mac-classic .kw1, code.mac-classic .kw2, code.mac-classic .sy1
	{ color: #0000FF; }
.mac-classic .codecolorer .kw3, .mac-classic .codecolorer .kw4, .mac-classic .codecolorer .kw5, .mac-classic .codecolorer .re2,
	code.mac-classic .kw3, code.mac-classic .kw4, code.mac-classic .kw5, code.mac-classic .re2
	{ color: #0000FF; }
.mac-classic .codecolorer .re0, .mac-classic .codecolorer .re1,
	code.mac-classic .re0, code.mac-classic .re1
	{ color: #318495; }
.mac-classic .codecolorer .br0, .mac-classic .codecolorer .sy0,
	code.mac-classic .br0, code.mac-classic .sy0
	{ color: #000000; }
.mac-classic .xml .re1 { color: #0000FF; }
.mac-classic .xml .re0 { color: #0000CD; }

/* "Vibrant Ink" color scheme */
.vibrant, .vibrant .codecolorer { color: #FFFFFF; background-color: #000000; }
.vibrant .codecolorer .co0, .vibrant .codecolorer .co1, .vibrant .codecolorer .co2, .vibrant .codecolorer .co3, .vibrant .codecolorer .co4, .vibrant .codecolorer .coMULTI,
	code.vibrant .co0, code.vibrant .co1, code.vibrant .co2, code.vibrant .co3, code.vibrant .co4, code.vibrant .coMULTI
	{ color: #9933CC; font-style: italic; }
.vibrant .codecolorer .nu0, .vibrant .codecolorer .re3,
	code.vibrant .nu0, code.vibrant .re3
	{ color: #339999; }
.vibrant .codecolorer .st0, .vibrant .codecolorer .st_h, .vibrant .codecolorer .es0, .vibrant .codecolorer .es1,
	code.vibrant .st0, code.vibrant .st_h, code.vibrant .es0, code.vibrant .es1
	{ color: #66FF00; }
.vibrant .codecolorer .me1, .vibrant .codecolorer .me2,
	code.vibrant .me1, code.vibrant .me2
	{ color: #FFCC00; }
.vibrant .codecolorer .kw1, .vibrant .codecolorer .kw2, .vibrant .codecolorer .sy1,
	code.vibrant .kw1, code.vibrant .kw2, code.vibrant .sy1
	{ color: #FF6600; }
.vibrant .codecolorer .kw3, .vibrant .codecolorer .kw4, .vibrant .codecolorer .kw5, .vibrant .codecolorer .re2,
	code.vibrant .kw3, code.vibrant .kw4, code.vibrant .kw5, code.vibrant .re2
	{ color: #FFCC00; }
.vibrant .codecolorer .re0, .vibrant .codecolorer .re1,
	code.vibrant .re0, code.vibrant .re1
	{ color: #FFFFFF; }
.vibrant .codecolorer .br0, .vibrant .codecolorer .sy0,
	code.vibrant .br0, code.vibrant .sy0
	{ color: #FFFFFF; }
.vibrant .xml .re1 { color: #FFCC00; }
.vibrant .xml .re0 { color: #339999; }

To actually use a color scheme from this stylesheet, you must change the leading classes. For example, if you want to use the “Slush & Poppies” color scheme, you must replace .codecolorer with .bwp-syntax-wrapper; or if you want to use the “Mac Classic” color scheme, you must replace .mac-classic .codecolorer with .bwp-syntax-wrapper.

Why isn’t using [code] recommended?

This shortcode is very popular I must say because it somehow reminds us of <code>. The problem is once you deactivate this plugin, for example, the shortcode will be visible to your visitors. You can, of course, add a "fake" shortcode in your theme telling WordPress to return only the content for that shortcode without showing the shortcode tag, but why do we need that when <pre> will work just fine? There are two benefits for using shortcode that I can think of is the ability to edit attributes in the Visual Editor and the ability to strip entire content in shortcode later on your website using strip_shortcodes. This can not be done yet using the PHP function strip_tags for <pre>, which will just expose all the content inside the tag, making the stripped content looks ugly. If you are a developer, you might try adding this to your file to strip even the contents inside <pre>, although not tested:

  1. // strip also the contents inside <pre>
  2. $content = preg_replace('/<pre[^>]*>.*?<\/pre>/isu', '', $content);
// strip also the contents inside <pre>
$content = preg_replace('/<pre[^>]*>.*?<\/pre>/isu', '', $content);

The <pre> has many advantages, some of which are:

  • Easy fallback when deactivate plugin
  • Automatically protect tabs and spaces
  • Using this plugin, WordPress functions, such as wpautop() will leave <pre> tags alone.
  • <pre> tags allow faster parsing, about 30% faster than using shortcode. Why? As stated above, <pre> tags are not affected by WordPress's formatting functions, thus is parsed much faster.

The Editor Button

This plugin adds a button to your Visual Editor to allow easier code adding. Your code will be wrapped in <pre>your code</pre> if you choose HTML <pre> tag or in [code]your code[/code] if you choose Shortcode tag, this is to ensure that the Visual Editor won't mess up your tabs and such. One thing to note is this button will also convert & > < to their HTML entities, which is basically what the Visual Editor would do anyway. One of the cool feature of the Editor Button is you can select some text and then click the button and leave the Code's content empty before hit Insert, the button will wrap your selected text into appropriate tags.

Nested tags

Writing nested tags will break your layout immediately, therefore they should be avoided at all cost. Normally if you do not use shortcode, there would be no problem writing <pre>[code]something[/code]</pre> . Now if you enable both tags to be parsed, the shortcode will be parsed first, leaving you with this <pre>parsed shortcode</pre>, not what you want for sure. To avoid such behaviour, this plugin provides a way to bypass all inside shortcode tags. This function is not enabled by default, and you can enable it in the configuration page. However, this function might render long post fail to show anything, this is a known issue and I do not know a solution at the moment. A safer approach is to add the attribute nested="yes" to the tags inside, for example, <pre>[code nested="yes "][/code]</pre> (please ignore the space). This allows you to bypass that shortcode tag only, and thus make the post parse-safe.

This only applies to the shortcode tag you define (default is [code]), other shortcodes will not have this problem at all. My recommendation is just choose one tag, <pre> or [code], and then stick with it and never use nested tags, unless for demonstration purposes (like I have done several times in this post).

Known issues

I try my best to make this plugin perform well, but there are always things we can not control, can we?

- Using Ordered List output method, can not give background to the line number, unless break the codeblock in some (major) browsers such as Chrome, Opera and Safari, latest versions.

- There's a bug when viewing codeblocks in Apple Safari: the vertical scrollbar seems to always appear. I don't know how to fix this at the moment but such bug will be addressed in future versions.

- In rare occasions, your codeblock will show nothing, this might be caused by the limitation of PCRE which is configured differently from companies to companies. You should just reduce the number of lines and words in your codeblock. For example, in my test environment, using Table output method along with the shortcode tag (again this is why to avoid using shortcode) with above 400 lines of code, the codeblock will not show (it actually shows on live environment, though). This is caused by the built-in WordPress function wpautop() and thus can not be changed. The Ordered List output method, however, renders just fine (even with 1000 lines of codes). So it's a matter of what suits you best, test the maximum number of lines your website can handle and don't go over that limit and you're fine (who would need more than 400 lines of codes anyway, put them in a file!!!)

- GeSHi itself is slow, if you are parsing about 700 lines of codes using pre tag, the parser will take from about 0.4s to 0.6s to complete, which can be problematic for sites with heavy traffic (not to mention if you enable parsing in comments). A cache plugin can be utilized here and I do plan on implementing a built-in cache feature for this plugin in future versions.

- (This section needs comments from you, my beloved visitors)

Alternatives

So for some reasons you do not want to use this plugin (please tell me why instead of leaving :() and would like some alternatives? Below are my recommendations:

To-do List

  • (planned) Allows users to customize other components
  • (planned) Allows users to edit codeblock using editor button
  • (idea) Add a built-in cache feature
  • (This section is open for feature request)

Hook References

  • bwp_syntax_languages - Used to add custom languages (filter)
  • bwp_syntax_shortcode_tag - Used to change the shortcode tag (filter)
  • bwp_syntax_lang_style - Replace the language-based CSS file (filter)
  • bwp_syntax_global_style - Replace the global CSS file (filter)

Contribute to this Plugin

This plugin is licensed under GPL version 3, and it needs contributions from the community.

Buy me some special coffees!

My plugins and support for them are free. If you like my work and could buy me some (special) coffees, I would be much appreciated! They might help with some overnight times debugging my plugins, you know.

Support, Feedback, and Code Improvement

i18n (Translate the plugin)

If you are a translator, please help translating this plugin. Even if you aren't, you can become one, it is very easy and fun! If you want to know how, please read here: Create a .pot or .po File using Poedit.

Attached Files

  • Sample CSS File (CSS) – 2.727 kB – 384 downloadsA sample CSS file that overrides some rules in the default style sheet.
Print Article Watch Log