summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/wp-syntax/wp-syntax.php')
-rw-r--r--plugins/wp-syntax/wp-syntax.php563
1 files changed, 364 insertions, 199 deletions
diff --git a/plugins/wp-syntax/wp-syntax.php b/plugins/wp-syntax/wp-syntax.php
index 3d195ead..d3a95ffe 100644
--- a/plugins/wp-syntax/wp-syntax.php
+++ b/plugins/wp-syntax/wp-syntax.php
@@ -1,207 +1,372 @@
<?php
/*
Plugin Name: WP-Syntax
-Plugin URI: http://wordpress.org/extend/plugins/wp-syntax/
-Description: Syntax highlighting using <a href="http://qbnz.com/highlighter/">GeSHi</a> supporting a wide range of popular languages. Wrap code blocks with <code>&lt;pre lang="LANGUAGE" line="1"&gt;</code> and <code>&lt;/pre&gt;</code> where <code>LANGUAGE</code> is a geshi supported language syntax. The <code>line</code> attribute is optional.
+Plugin URI: http://www.connections-pro.com
+Description: Syntax highlighting using <a href="http://qbnz.com/highlighter/">GeSHi</a> supporting a wide range of popular languages.
+Version: 1.0
Author: Steven A. Zahm
-Version: 0.9.12
-Author URI: http://connections-pro.com
+Author URI: http://www.connections-pro.com
+License: GPL2
+Text Domain: wp_syntax
+Domain Path: /lang
+
+Original Author: Ryan McGeary
+
+Copyright 2013 Steven A. Zahm (email : helpdesk@connections-pro.com)
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License, version 2, as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-# Original Author: Ryan McGeary
-
-#
-# Copyright (c) 2007-2009 Ryan McGeary 2010 Steven A. Zahm
-#
-# This file is part of WP-Syntax.
-#
-# WP-Syntax is free software; you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free
-# Software Foundation; either version 2 of the License, or (at your option)
-# any later version.
-#
-# WP-Syntax is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along
-# with WP-Syntax; if not, write to the Free Software Foundation, Inc., 59
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-// Override allowed attributes for pre tags in order to use <pre lang=""> in
-// comments. For more info see wp-includes/kses.php
-if (!CUSTOM_TAGS) {
- $allowedposttags['pre'] = array(
- 'lang' => array(),
- 'line' => array(),
- 'escaped' => array(),
- 'style' => array(),
- 'width' => array(),
- 'highlight' => array()
- );
- //Allow plugin use in comments
- $allowedtags['pre'] = array(
- 'lang' => array(),
- 'line' => array(),
- 'escaped' => array(),
- 'highlight' => array()
- );
-}
-
-include_once("geshi/geshi.php");
-
-if (!defined("WP_CONTENT_URL")) define("WP_CONTENT_URL", get_option("siteurl") . "/wp-content");
-if (!defined("WP_PLUGIN_URL")) define("WP_PLUGIN_URL", WP_CONTENT_URL . "/plugins");
-
-function wp_syntax_head()
-{
- /*$css_url = WP_PLUGIN_URL . "/wp-syntax/wp-syntax.css";
- if (file_exists(TEMPLATEPATH . "/wp-syntax.css"))
- {
- $css_url = get_bloginfo("template_url") . "/wp-syntax.css";
- }
- echo "\n".'<link rel="stylesheet" href="' . $css_url . '" type="text/css" media="screen" />'."\n";*/
-
- $css_url = WP_PLUGIN_URL . "/wp-syntax/wp-syntax.css";
- if (file_exists(STYLESHEETPATH . "/wp-syntax.css"))
- {
- $css_url = get_bloginfo("stylesheet_directory") . "/wp-syntax.css";
- }
- echo "\n".'<link rel="stylesheet" href="' . $css_url . '" type="text/css" media="screen" />'."\n";
-}
-
-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);
- return $code;
-}
-
-function wp_syntax_substitute(&$match)
-{
- global $wp_syntax_token, $wp_syntax_matches;
-
- $i = count($wp_syntax_matches);
- $wp_syntax_matches[$i] = $match;
-
- return "\n\n<p>" . $wp_syntax_token . sprintf("%03d", $i) . "</p>\n\n";
-}
-
-function wp_syntax_line_numbers($code, $start)
-{
- $line_count = count(explode("\n", $code));
- $output = "<pre>";
- for ($i = 0; $i < $line_count; $i++)
- {
- $output .= ($start + $i) . "\n";
- }
- $output .= "</pre>";
- return $output;
-}
-
-function wp_syntax_highlight($match)
-{
- global $wp_syntax_matches;
-
- $i = intval($match[1]);
- $match = $wp_syntax_matches[$i];
-
- $language = strtolower(trim($match[1]));
- $line = trim($match[2]);
- $escaped = trim($match[3]);
-
- $code = wp_syntax_code_trim($match[5]);
- if ($escaped == "true") $code = htmlspecialchars_decode($code);
-
- $geshi = new GeSHi($code, $language);
- $geshi->enable_keyword_links(false);
- do_action_ref_array('wp_syntax_init_geshi', array(&$geshi));
-
- //START LINE HIGHLIGHT SUPPORT
- $highlight = array();
- if ( !empty($match[4]) )
- {
- $highlight = strpos($match[4],',') == false ? array($match[4]) : explode(',', $match[4]);
-
- $h_lines = array();
- for( $i=0; $i<sizeof($highlight); $i++ )
- {
- $h_range = explode('-', $highlight[$i]);
-
- if( sizeof($h_range) == 2 )
- $h_lines = array_merge( $h_lines, range($h_range[0], $h_range[1]) );
- else
- array_push($h_lines, $highlight[$i]);
+/*
+@todo integrate TinyMCE button support using one of these as a base:
+ http://wordpress.org/extend/plugins/wp-syntax-integration/
+ http://wordpress.org/extend/plugins/wp-syntax-button/
+@todo Merge this add-on plugin functionality: http://wordpress.org/extend/plugins/wp-syntax-download-extension/
+
+Look at these: http://wordpress.org/extend/plugins/wp-synhighlight/
+ http://wordpress.org/extend/plugins/wp-codebox/
+ */
+
+if ( ! class_exists( 'WP_Syntax' ) ) {
+
+ class WP_Syntax {
+
+ /**
+ * @var (object) WP_Syntax stores the instance of this class.
+ */
+ private static $instance;
+
+ private static $token;
+
+ private static $matches;
+
+ /**
+ * A dummy constructor to prevent WP_Syntax from being loaded more than once.
+ *
+ * @access private
+ * @since 1.0
+ * @see WP_Syntax::instance()
+ * @see WP_Syntax();
+ */
+ private function __construct() { /* Do nothing here */ }
+
+ /**
+ * Main WP_Syntax Instance
+ *
+ * Insures that only one instance of WP_Syntax exists in memory at any one time.
+ *
+ * @access public
+ * @since 1.0
+ * @return object WP_Syntax
+ */
+ public static function getInstance() {
+ if ( ! isset( self::$instance ) ) {
+ self::$instance = new self;
+ self::$instance->init();
+ }
+ return self::$instance;
+ }
+
+ /**
+ * Initiate the plugin.
+ *
+ * @access private
+ * @since 1.0
+ * @return void
+ */
+ private function init() {
+
+ self::defineConstants();
+ self::inludeDependencies();
+
+ self::$token = md5( uniqid( rand() ) );
+
+ self::$matches = array();
+
+ // Nothing to do during activation/deactivation yet...
+ // register_activation_hook( dirname(__FILE__) . '/wp-syntax.php', array( __CLASS__, 'activate' ) );
+ // register_deactivation_hook( dirname(__FILE__) . '/wp-syntax.php', array( __CLASS__, 'deactivate' ) );
+
+ // Nothing to translate presently.
+ // load_plugin_textdomain( 'wp_syntax' , false , WPS__DIR_NAME . 'lang' );
+
+ add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueueScripts' ) );
+
+ // Update config for WYSIWYG editor to accept the pre tag and its attributes.
+ add_filter( 'tiny_mce_before_init', array( __CLASS__,'tinyMCEConfig') );
+
+ // We want to run before other filters; hence, a priority of 0 was chosen.
+ // The lower the number, the higher the priority. 10 is the default and
+ // several formatting filters run at or around 6.
+ add_filter( 'the_content', array( __CLASS__, 'beforeFilter' ), 0);
+ add_filter( 'the_excerpt', array( __CLASS__, 'beforeFilter' ), 0);
+ add_filter( 'comment_text', array( __CLASS__, 'beforeFilter' ), 0);
+
+ // We want to run after other filters; hence, a priority of 99.
+ add_filter( 'the_content', array( __CLASS__, 'afterFilter' ), 99);
+ add_filter( 'the_excerpt', array( __CLASS__, 'afterFilter' ), 99);
+ add_filter( 'comment_text', array( __CLASS__, 'afterFilter' ), 99);
+
+ }
+
+ /**
+ * Define the constants.
+ *
+ * @access private
+ * @since 1.0
+ * @return void
+ */
+ private static function defineConstants() {
+
+ define( 'WPS_VERSION', '1.0' );
+
+ define( 'WPS_DIR_NAME', plugin_basename( dirname( __FILE__ ) ) );
+ define( 'WPS_BASE_NAME', plugin_basename( __FILE__ ) );
+ define( 'WPS_BASE_PATH', plugin_dir_path( __FILE__ ) );
+ define( 'WPS_BASE_URL', plugin_dir_url( __FILE__ ) );
+
+ }
+
+ private static function inludeDependencies() {
+
+ include_once( 'geshi/geshi.php' );
+
+ }
+
+ /**
+ * Called when activating via the activation hook.
+ *
+ * @access private
+ * @since 1.0
+ * @return void
+ */
+ public static function activate() {
+
+ }
+
+ /**
+ * Called when deactivating via the deactivation hook.
+ *
+ * @access private
+ * @since 1.0
+ * @return void
+ */
+ public static function deactivate() {
+
+ }
+
+ /**
+ * Enqueue the CSS and JavaScripts.
+ *
+ * @access private
+ * @since 1.0
+ * @return void
+ */
+ public static function enqueueScripts() {
+
+ // If a wp-syntax.css file exists in the theme folder use it instead.
+ $url = file_exists( STYLESHEETPATH . '/wp-syntax.css' ) ? get_bloginfo( 'stylesheet_directory' ) . '/wp-syntax.css' : WPS_BASE_URL . 'css/wp-syntax.css';
+
+ // Enqueue the CSS
+ wp_enqueue_style( 'wp-syntax-css', $url, array(), WPS_VERSION );
+
+ // Enqueue the JavaScript
+ // wp_enqueue_script( 'wp-syntax-js', WPS_BASE_URL . 'js/wp-syntax.js', array( 'jquery' ), WPS_VERSION, TRUE );
+
+ }
+
+ /**
+ * Update the TinyMCE config to add support for the pre tag and its attributes.
+ *
+ * @access private
+ * @since 0.9.13
+ * @param (array) $init The TinyMCE config.
+ * @return (array)
+ */
+ public static function tinyMCEConfig( $init ) {
+
+ $ext = 'pre[id|name|class|style|lang|line|escaped|highlight|src]';
+
+ if ( isset( $init['extended_valid_elements'] ) ) {
+ $init['extended_valid_elements'] .= "," . $ext;
+ } else {
+ $init['extended_valid_elements'] = $ext;
+ }
+
+ return $init;
+ }
+
+ // special ltrim b/c leading whitespace matters on 1st line of content
+ public static function trimCode( $code ) {
+ $code = preg_replace("/^\s*\n/siU", '', $code);
+ $code = rtrim ($code );
+ return $code;
+ }
+
+ public static function substituteToken( &$match ) {
+ // global $wp_syntax_token, $wp_syntax_matches;
+
+ $i = count( self::$matches );
+ self::$matches[ $i ] = $match;
+
+ return "\n\n<p>" . self::$token . sprintf( '%03d', $i ) . "</p>\n\n";
+ }
+
+ public static function lineNumbers( $code, $start ) {
+
+ $line_count = count( explode( "\n", $code ) );
+ $output = '<pre>';
+
+ for ( $i = 0; $i < $line_count; $i++ ) {
+ $output .= ( $start + $i ) . "\n";
+ }
+
+ $output .= '</pre>';
+
+ return $output;
+ }
+
+ public static function caption( $url ) {
+
+ $parsed = parse_url( $url );
+ $path = pathinfo( $parsed['path'] );
+ $caption = '';
+
+ if ( ! isset( $path['filename'] ) ) {
+ return;
+ }
+
+ if ( isset( $parsed['scheme'] ) ) {
+ $caption .= '<a href="' . $url . '">';
+ }
+
+ if ( isset( $parsed["host"] ) && $parsed["host"] == 'github.com' )
+ {
+ $caption .= substr( $parsed['path'], strpos( $parsed['path'], '/', 1 ) ); /* strip github.com username */
+ } else {
+ $caption .= $parsed['path'];
+ }
+
+ /* $caption . $path["filename"];
+ if (isset($path["extension"])) {
+ $caption .= "." . $path["extension"];
+ }*/
+
+ if ( isset($parsed['scheme']) ) {
+ $caption .= '</a>';
+ }
+
+ return $caption;
+ }
+
+ public static function highlight( $match ) {
+ // global $wp_syntax_matches;
+
+ $i = intval( $match[1] );
+ $match = self::$matches[ $i ];
+
+ $language = strtolower( trim( $match[1] ) );
+ $line = trim( $match[2] );
+ $escaped = trim( $match[3] );
+ $caption = self::caption( $match[5] );
+ $code = self::trimCode( $match[6] );
+
+ if ( $escaped == 'true' ) $code = htmlspecialchars_decode( $code );
+
+ $geshi = new GeSHi( $code, $language );
+ $geshi->enable_keyword_links( FALSE );
+
+ do_action_ref_array( 'wp_syntax_init_geshi', array( &$geshi ) );
+
+ if ( ! empty( $match[4] ) ) {
+
+ $linespecs = strpos( $match[4], ",") == FALSE ? array( $match[4] ) : explode( ',', $match[4] );
+ $lines = array();
+
+ foreach ( $linespecs as $spec ) {
+ $range = explode( '-', $spec );
+ $lines = array_merge( $lines, ( count( $range ) == 2) ? range( $range[0], $range[1]) : $range );
+ }
+
+ $geshi->highlight_lines_extra( $lines );
+ }
+
+ $output = "\n" . '<div class="wp_syntax">';
+ $output .= '<table>';
+
+ if ( ! empty( $caption ) ) {
+ $output .= '<caption>' . $caption . '</caption>';
+ }
+
+ $output .= '<tr>';
+
+ if ( $line ) {
+ $output .='<td class="line_numbers">' . self::lineNumbers( $code, $line ) . '</td>';
+ }
+
+ $output .= '<td class="code">';
+ $output .= $geshi->parse_code();
+ $output .= '</td></tr></table>';
+ $output .= '</div>' . "\n";
+
+ return $output;
+ }
+
+ public static function beforeFilter( $content ) {
+
+ return preg_replace_callback(
+ "/\s*<pre(?:lang=[\"']([\w-]+)[\"']|line=[\"'](\d*)[\"']|escaped=[\"'](true|false)?[\"']|highlight=[\"']((?:\d+[,-])*\d+)[\"']|src=[\"']([^\"']+)[\"']|\s)+>(.*)<\/pre>\s*/siU",
+ array( __CLASS__, 'substituteToken' ),
+ $content
+ );
+
+ }
+
+ public static function afterFilter( $content ) {
+ // global $wp_syntax_token;
+
+ $content = preg_replace_callback(
+ '/<p>\s*' . self::$token . '(\d{3})\s*<\/p>/si',
+ array( __CLASS__, 'highlight' ),
+ $content
+ );
+
+ return $content;
+ }
+
}
- $geshi->highlight_lines_extra( $h_lines );
- }
- //END LINE HIGHLIGHT SUPPORT
-
- $output = "\n<div class=\"wp_syntax\">";
-
- if ($line)
- {
- $output .= "<table><tr><td class=\"line_numbers\">";
- $output .= wp_syntax_line_numbers($code, $line);
- $output .= "</td><td class=\"code\">";
- $output .= $geshi->parse_code();
- $output .= "</td></tr></table>";
- }
- else
- {
- $output .= "<div class=\"code\">";
- $output .= $geshi->parse_code();
- $output .= "</div>";
- }
- return
-
- $output .= "</div>\n";
-
- return $output;
-}
-
-function wp_syntax_before_filter($content)
-{
- return preg_replace_callback(
- "/\s*<pre(?:lang=[\"']([\w-]+)[\"']|line=[\"'](\d*)[\"']|escaped=[\"'](true|false)?[\"']|highlight=[\"']((?:\d+[,-])*\d+)[\"']|\s)+>(.*)<\/pre>\s*/siU",
- "wp_syntax_substitute",
- $content
- );
-}
-
-function wp_syntax_after_filter($content)
-{
- global $wp_syntax_token;
-
- $content = preg_replace_callback(
- "/<p>\s*".$wp_syntax_token."(\d{3})\s*<\/p>/si",
- "wp_syntax_highlight",
- $content
- );
-
- return $content;
-}
-
-$wp_syntax_token = md5(uniqid(rand()));
-$wp_syntax_matches = array();
-
-// Add styling
-add_action('wp_head', 'wp_syntax_head');
-
-// We want to run before other filters; hence, a priority of 0 was chosen.
-// The lower the number, the higher the priority. 10 is the default and
-// several formatting filters run at or around 6.
-add_filter('the_content', 'wp_syntax_before_filter', 0);
-add_filter('the_excerpt', 'wp_syntax_before_filter', 0);
-add_filter('comment_text', 'wp_syntax_before_filter', 0);
-
-// We want to run after other filters; hence, a priority of 99.
-add_filter('the_content', 'wp_syntax_after_filter', 99);
-add_filter('the_excerpt', 'wp_syntax_after_filter', 99);
-add_filter('comment_text', 'wp_syntax_after_filter', 99);
-
-?>
+ /**
+ * The main function responsible for returning the WP_Syntax instance
+ * to functions everywhere.
+ *
+ * Use this function like you would a global variable, except without needing
+ * to declare the global.
+ *
+ * Example: <?php $wp_syntex = WP_Syntax(); ?>
+ *
+ * @access public
+ * @since 1.0
+ * @return mixed (object)
+ */
+ function WP_Syntax() {
+ return WP_Syntax::getInstance();
+ }
+
+ /**
+ * Start the plugin.
+ */
+ add_action( 'plugins_loaded', 'WP_Syntax' );
+
+} \ No newline at end of file