Kategorien

Druckansicht des Beitrags Druckansicht des Beitrags

WordPress Syntax Highlighting mit WP-Syntax

Jeder, der in seinem Blog Quellcode, Shell-Befehle und dergleichen veröffentlichen möchte, kommt meiner Meinung nach nicht um ein Plugin herum, das den Quelltext optisch aufbereitet. Inzwischen gibt es für WordPress etliche Plugins, die Syntax Highlighting anbieten. Beispielhaft seien hier SyntaxHighlighter, Code Markup und WP-Syntax genannt. SyntaxHighlighter wollte ich nicht verwenden, weil es Javascript-basiert ist und deshalb nicht sichergestellt ist, dass auch Suchmaschinen, den entsprechenden Inhalt finden. Da mir der Funktionsumfang von Code Markup zu gering erschien habe ich mich schließlich auch aufgrund der Vielfalt an unterstützten Sprachen für WP-Syntax entschieden. Dieses konvertiert Sonderzeichen (z.B. „>“) in den entsprechenden HTML-Code (z.B. „>“). Beim Schreiben von Artikeln mit der WordPress-Weboberfläche wird im WYSIWYG-Modus allerdings bereits eine entsprechende Konvertierung vorgenommen, so dass man als Resultat im Artikel den HTML-Code angezeigt bekommt. Um dieses Problem zu umgehen, habe ich eine Lösung von Gergely Hodicska gefunden, die es zudem ermöglicht, den Quellcode noch komfortabler einzugeben. Im ersten Schritt wird die wp-content/plugins/wp-syntax/wp-syntax.php analog zu dem Vorschlag von Martin bzw. Shantanu so modifiziert, dass die fälschlicherweise vom WYSIWYG-Editor in HTML-Codes konvertierten Sonderzeichen wiederhergestellt werden:

function wp_syntax_code_trim($code)
{
    // special ltrim b/c leading whitespace matters on 1st line of content
    $code = preg_replace("/^\s*\n/siU", "", $code);
    $code = rtrim($code);
	/* Insertion Code Start */
	// MRi: changes to retranslate html code tags into the normal
	// characters for geshi.
	$code = strip_tags($code);
	if (PHP_VERSION > 5.0)
	{
		$code = html_entity_decode($code, ENT_QUOTES, "UTF-8");
	}
	else
	{
		$arrSearch = array("<", ">", " ", "&");
		$arrReplace = array("<", ">", " ", "&");
		$code = str_replace($arrSearch, $arrReplace, $code);
	}
	/* Insertion Code End */
    return $code;
}

Nun müssen aber zwangsweise alle Sonderzeichen auch in die HTML-Codes konvertiert werden – also nicht nur, wenn man im WYSIWYG-Editor arbeitet. Diese Konvertierung erledigt man am Besten durch das Anlegen eines neuen Buttons namens „pre“ im HTML-Modus der Weboberfläche. Dazu müssen die Dateien wp-includes/js/quicktags.js und wp-includes/js/tinymce/tiny_mce_config.php abgeändert werden.
quicktags.js:

/* Insertion Code Start */
edButtons[edButtons.length] =
new edButton('ed_pre'
,'pre'
,'<pre>'
,'</pre>'
,'f'
);
/* Insertion Code End */
/* Insertion Code Start */
// Prompt for syntax highlighting parameter, and return the appropriate start tag.
// TODO: l10n support.
function edGetPreStartTag() {
	var syntaxInfo = prompt('Please insert syntax highlighting information:'+"\n"+'language[,line number]!', 'php,1').split(',');
	return '<pre lang="'+syntaxInfo[0]+'"'+(syntaxInfo[1] != undefined ? ' line="'+syntaxInfo[1]+'"' : '')+'>'+"\n";
}
 
function edhtmlspecialchars(p_string) {
	p_string = p_string.replace(/&/g, '&amp;');
	p_string = p_string.replace(/</g, '&lt;');
	p_string = p_string.replace(/>/g, '&gt;');
	p_string = p_string.replace(/"/g, '&quot;');
//	p_string = p_string.replace(/'/g, '&#039;');
	return p_string;
};
 
/* Insertion Code End */
 
// insertion code
 
function edInsertTag(myField, i) {
	//IE support
	if (document.selection) {
		myField.focus();
	    sel = document.selection.createRange();
		if (sel.text.length > 0) {
			/* Insertion Code Start */
			if (edButtons[i].id == 'ed_pre') {
				sel.text =edhtmlspecialchars(sel.text);
				edButtons[i].tagStart = edGetPreStartTag();
			}
			/* Insertion Code End */
			sel.text = edButtons[i].tagStart + sel.text + edButtons[i].tagEnd;
		}
		else {
			if (!edCheckOpenTags(i) || edButtons[i].tagEnd == '') {
				/* Insertion Code Start */
				if (edButtons[i].id == 'ed_pre') {
					edButtons[i].tagStart = edGetPreStartTag();
				}
				/* Insertion Code End */
				sel.text = edButtons[i].tagStart;
				edAddTag(i);
			}
			else {
				sel.text = edButtons[i].tagEnd;
				edRemoveTag(i);
			}
		}
		myField.focus();
	}
	//MOZILLA/NETSCAPE support
	else if (myField.selectionStart || myField.selectionStart == '0') {
		var startPos = myField.selectionStart;
		var endPos = myField.selectionEnd;
		var cursorPos = endPos;
		var scrollTop = myField.scrollTop;
 
		if (startPos != endPos) {
			/* Modification Code Start */
			var selectedText = myField.value.substring(startPos, endPos);
			var selectedTextLengthGrowth = 0;
			if (edButtons[i].id == 'ed_pre') {
				edButtons[i].tagStart = edGetPreStartTag();
				selectedTextLengthGrowth = selectedText.length;
				selectedText = edhtmlspecialchars(selectedText);
				selectedTextLengthGrowth = selectedText.length - selectedTextLengthGrowth;
			}
			myField.value = myField.value.substring(0, startPos)
			              + edButtons[i].tagStart
			              + selectedText
			              + edButtons[i].tagEnd
			              + myField.value.substring(endPos, myField.value.length);
			cursorPos += edButtons[i].tagStart.length + edButtons[i].tagEnd.length + selectedTextLengthGrowth;
			/* Modification Code End */
		}
		else {
			if (!edCheckOpenTags(i) || edButtons[i].tagEnd == '') {
				/* Insertion Code Start */
				if (edButtons[i].id == 'ed_pre') {
					edButtons[i].tagStart = edGetPreStartTag();
				}
				/* Insertion Code End */
				myField.value = myField.value.substring(0, startPos)
				              + edButtons[i].tagStart
				              + myField.value.substring(endPos, myField.value.length);
				edAddTag(i);
				cursorPos = startPos + edButtons[i].tagStart.length;
			}
			else {
				myField.value = myField.value.substring(0, startPos)
				              + edButtons[i].tagEnd
				              + myField.value.substring(endPos, myField.value.length);
				edRemoveTag(i);
				cursorPos = startPos + edButtons[i].tagEnd.length;
			}
		}
		myField.focus();
		myField.selectionStart = cursorPos;
		myField.selectionEnd = cursorPos;
		myField.scrollTop = scrollTop;
	}
	else {
		if (!edCheckOpenTags(i) || edButtons[i].tagEnd == '') {
			/* Insertion Code Start */
			if (edButtons[i].id == 'ed_pre') {
				edButtons[i].tagStart = edGetPreStartTag();
			}
			/* Insertion Code End */
			myField.value += edButtons[i].tagStart;
			edAddTag(i);
		}
		else {
			myField.value += edButtons[i].tagEnd;
			edRemoveTag(i);
		}
		myField.focus();
	}
}

tiny_mce_config.php:

/* Code Modification Start */
/* 'pre' button added for wp-syntax */
$mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', '|', 'bullist', 'numlist', 'blockquote', 'pre', '|', 'justifyleft', 'justifycenter', 'justifyright', '|', 'link', 'unlink', 'wp_more', '|', 'spellchecker', 'fullscreen', 'wp_adv' ));
$mce_buttons = implode($mce_buttons, ',');
/* Code Modification End */

Die eingefügten/veränderten Abschnitte sind zwar jeweils durch Kommentare kenntlich gemacht, aber mit entsprechenden diff-Dateien lassen sich die Dateien doch am Besten patchen. Die diff-Dateien wurden unter Verwendung der von WordPress 2.6.5 und WP-Syntax 0.9.1 erstellt. Bitte unbedingt beachten, dass die durchgeführten Modifikationen beim Update von WordPress bzw. WP-Syntax nochmals durchgeführt werden müssen.

Meinen Quellcode füge ich nach den Modifikationen immer so ein:

  1. Quellcode in Zwischenablage kopieren
  2. In der WordPress-Weboberfläche in den HTML-Modus wechseln
  3. Quellcode aus der Zwischenablage einfügen
  4. Eingefügten Quellcode markieren
  5. Auf den Button pre klicken
  6. Im erscheinenden Dialog die Programmiersprache und falls gewünscht die Zeilennummer durch Komma getrennt angeben
  7. Zurück in den visuellen Modus wechseln

Eine alternative Lösung für das Konvertierungsproblem in HTML-Entititäten ist der Ersatz des pre-Tags durch div-Tags.

2 comments to WordPress Syntax Highlighting mit WP-Syntax

  • […] Button im visuellen Editor (TinyMCE) als auch im HTML-Editor hinzufügt. Zuvor hatte ich immer die quicktag.php editiert, was aber auf Dauer sehr mühsam war, da man dies bei jedem WordPress Update machen musste. Das […]

  • Gerade ist mir im Zusammenhang mit WP-Syntax etwas aufgefallen. Beim Aufruf einer Blog-Seite erhielt ich "The first argument should be an array in ../wp-content/plugins/wp-syntax/geshi/geshi.php on line 1904". Diese Fehlermeldung ist darauf zurückzuführen, dass man irgendwo einen <pre> Tag hat, bei dem das Attribut escaped oder line gesetzt ist, so dass wp-syntax versucht die Daten zu interpretieren. Aber da vergessen wurde, das lang Attribut anzugeben, gibt es beim Aufruf von GeShi diese Fehlermeldung. Abhilfe: Die Syntaxsprache definieren, z.B. mit <pre lang="text" escaped="true">

Leave a Reply to Markus Effinger Cancel reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>