styles = array( 'decimal' => '1,2...10', 'decimal-leading-zero' => '01, 02...10', 'lower-alpha' => 'a,b...j', 'upper-alpha' => 'A,B...J', 'lower-roman' => 'i,ii...x', 'upper-roman' => 'I,II...X', 'symbol' => 'Symbol' ); // Define default options $this->default_options = array( 'pre_backlink'=>' [', 'backlink'=>'↩', 'post_backlink'=>']', 'pre_identifier'=>'', 'list_style_type'=>'decimal', 'list_style_symbol'=>'†', 'post_identifier'=>'', 'pre_footnotes'=>'', 'post_footnotes'=>'' ); // Get the current settings or setup some defaults if needed $this->options = get_option('mp_wp_cpp_options'); if (!$this->options) { $this->options = $this->default_options; update_option('mp_wp_cpp_options', $this->options); } else { // Set any unset options $updated = false; foreach ($this->default_options as $key => $value) { if (!isset($this->options[$key])) { $this->options[$key] = $value; $updated = true; } } if ($updated) { update_option('mp_wp_cpp_options', $this->options); } } // Hook me up add_action('the_content', array($this, 'process_codeblocks'), self::MP_WP_CODEBLOCKS_PRIORITY); add_action('the_content', array($this, 'process_footnotes'), self::MP_WP_FOOTNOTES_PRIORITY); add_filter('the_content', array($this, 'server_side_selection')); add_action('wp_head', array($this, 'insert_styles')); } /** * Finds the selection from the query params. * @param $data string The content of the post. * @return string The new content with the highlighted selection. */ function server_side_selection($data) { //bookend code goes here $b_code = ''; $b_code .= $_GET["b"]; $e_code = $_GET["e"].''; //change page ; last to first to preserve indexes. $b_pos = strpos($data,$_GET["b"]); $e_pos = strpos($data,$_GET["e"], $b_pos); if ($e_pos>0) $data = substr_replace($data, $e_code, $e_pos, strlen($_GET["e"])); if ($b_pos>0) $data = substr_replace($data, $b_code, $b_pos, strlen($_GET["b"])); return $data; } /** * Searches the text and apply markup to codeblocks. * Adds line number links and diff syntax highlighting. * @param $data string The content of the post. * @return string The new content with formatted codeblocks. */ function process_codeblocks($data) { global $post; // Regex extraction of all codeblocks (or return if there are none) if ( !preg_match_all("/\[([a-z]+)\[(.*)(\]\])/Us", $data, $codeblocks, PREG_SET_ORDER) ) { return $data; } for ($i = 0; $i < count($codeblocks); $i++) { $codeblocks[$i]['snippet'] = $this->format_snippet($codeblocks[$i][2], $codeblocks[$i][1], $i+1); } foreach ($codeblocks as $key => $value) { $data = substr_replace($data, $value['snippet'], strpos($data,$value[0]),strlen($value[0])); } return $data; } function format_snippet($snippet, $syntax, $snippet_number) { $highlighting_functions = array( 'plaintext' => 'highlight_as_plain_text', 'diff' => 'highlight_as_diff' ); if (is_null($highlighting_functions[$syntax])) { $syntax = 'plaintext'; } $code_lines = explode("\r\n", $snippet); foreach ($code_lines as $idx => $line) { $line_number = sprintf('S%d-L%d', $snippet_number, $idx+1); $line_link = sprintf('%d', $line_number, $line_number, $idx+1); $line_open = sprintf('%s', $line_link); $line_close = ''; $code_lines[$idx] = $this->$highlighting_functions[$syntax]($line_open, $line, $line_close); } $formatted_snippet = implode("\n", $code_lines); $formatted_snippet = sprintf( '%s%s%s', '
', $formatted_snippet, '
' ); return $formatted_snippet; } function highlight_as_plain_text($line_open, $line, $line_close) { return sprintf('%s%s%s', $line_open, $line, $line_close); } function highlight_as_diff($line_open, $line, $line_close) { if (substr($line, 0, 5) == 'diff ') { $highlighted_line = sprintf('%s%s%s', $line_open, $line, $line_close); } elseif (substr($line, 0, 4) == '--- ' || substr($line, 0, 4) == '+++ ' || substr($line, 0, 3) == '@@ ') { $highlighted_line = sprintf('%s%s%s', $line_open, $line, $line_close); } elseif (substr($line, 0, 1) == '-') { $highlighted_line = sprintf('%s%s%s', $line_open, $line, $line_close); } elseif (substr($line, 0, 1) == '+') { $highlighted_line = sprintf('%s%s%s', $line_open, $line, $line_close); } else { $highlighted_line = sprintf('%s%s%s', $line_open, $line, $line_close); } return $highlighted_line; } /** * Searches the text and extracts footnotes. * Adds the identifier links and creats footnotes list. * @param $data string The content of the post. * @return string The new content with footnotes generated. */ function process_footnotes($data) { global $post; // Check for and setup the starting number $start_number = (preg_match("||",$data,$start_number_array)==1) ? $start_number_array[1] : 1; // Regex extraction of all footnotes (or return if there are none) if (!preg_match_all("/(".preg_quote(self::MP_WP_FOOTNOTES_OPEN)."|)(.*)(".preg_quote(self::MP_WP_FOOTNOTES_CLOSE)."|<\/footnote>)/Us", $data, $identifiers, PREG_SET_ORDER)) { return $data; } $footnotes = array(); // Check if this post is using a different list style to the settings if ( array_key_exists(get_post_meta($post->ID, 'footnote_style', true), $this->styles) ) { $style = get_post_meta($post->ID, 'footnote_style', true); } else { $style = $this->options['list_style_type']; } // Create 'em for ($i=0; $i $value) { $id_id = "identifier_".$key."_".$post->ID; $id_num = ($style == 'decimal') ? $value['use_footnote']+$start_number : $this->convert_num($value['use_footnote']+$start_number, $style, count($footnotes)); $id_href = ( ($use_full_link) ? get_permalink($post->ID) : '' ) . "#footnote_".$value['use_footnote']."_".$post->ID; $id_title = str_replace('"', '`', strip_tags($value['text'])); $id_replace = ''.$this->options['pre_identifier'].''.$id_num.''.$this->options['post_identifier'].''; $data = substr_replace($data, $id_replace, strpos($data,$value[0]),strlen($value[0])); } // Display footnotes $start = ($start_number != 1) ? 'start="'.$start_number.'" ' : ''; $data = $data.$this->options['pre_footnotes']; $data = $data . '
    '; foreach ($footnotes as $key => $value) { $data = $data.'
  1. options['list_style_type']) { $data = $data . ' style="list-style-type:' . $style . ';"'; } $data = $data . '>'; if ($style == 'symbol') { $data = $data . '' . $this->convert_num($key+$start_number, $style, count($footnotes)) . ' '; } $data = $data.$value['text']; if (!is_feed()){ foreach($value['identifiers'] as $identifier){ $data = $data.$this->options['pre_backlink'].''.$this->options['backlink'].''.$this->options['post_backlink']; } } $data = $data . '
  2. '; } $data = $data . '
' . $this->options['post_footnotes']; return $data; } function insert_styles() { ?> roman($num, 'lower'); case 'upper-roman' : return $this->roman($num); case 'lower-alpha' : return $this->alpha($num, 'lower'); case 'upper-alpha' : return $this->alpha($num); case 'symbol' : $sym = ''; for ($i = 0; $i<$num; $i++) { $sym .= $this->options['list_style_symbol']; } return $sym; } } /** * Convert to a roman numeral. * * Thanks to Indi.in.the.Wired for the improved algorithm. * http://plugins.trac.wordpress.org/ticket/1177 * * @param int $num The number to convert. * @param string $case Upper or lower case. * @return string The roman numeral */ function roman($num, $case= 'upper') { $num = (int) $num; $conversion = array('M'=>1000, 'CM'=>900, 'D'=>500, 'CD'=>400, 'C'=>100, 'XC'=>90, 'L'=>50, 'XL'=>40, 'X'=>10, 'IX'=>9, 'V'=>5, 'IV'=>4, 'I'=>1); $roman = ''; foreach ($conversion as $r => $d){ $roman .= str_repeat($r, (int)($num / $d)); $num %= $d; } return ($case == 'lower') ? strtolower($roman) : $roman; } function alpha($num, $case='upper') { $j = 1; for ($i = 'A'; $i <= 'ZZ'; $i++){ if ($j == $num){ if ($case == 'lower') return strtolower($i); else return $i; } $j++; } } }