Plugin Directory

Changeset 457449


Ignore:
Timestamp:
10/30/2011 09:06:20 PM (14 years ago)
Author:
MarcusPope
Message:

updated source to use more compatible function calling mech. supports < php5.3

Location:
preserved-html-editor-markup/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • preserved-html-editor-markup/trunk/readme.txt

    r456532 r457449  
    11=== Preserved HTML Editor Markup ===
    22Contributors: marcuspope
    3 Donate link: http://www.springbox.com/contact/
     3Donate link: http://www.marcuspope.com/
    44Tags: wpautop, editor, markup, html, white space, HTML5, WYSIWYG, visual, developer
    55Requires at least: 3.2.1
     
    2323  1. Orphaned text content will not be wrapped in any tag - so you will want to make sure your theme inherently wraps the post content in a div tag (or some other block element) for valid HTML markup.
    2424
    25   1. White space is preserved; newlines, spaces and tabs will remain in your markup for the most part.  For performance reasons, it will only preserve spaces if 4 spaces are used consecutively - i.e. an expanded tab in developer terms.  It will not preserve intra-tag white space like &lt;p&nbsp;&nbsp;&nbsp;&nbsp;&gt;. 
     25  1. White space is preserved; newlines, spaces and tabs will remain in your markup for the most part.  For performance reasons, it will only preserve spaces if 4 spaces are used consecutively - i.e. an expanded tab in developer terms.  It will not preserve intra-tag white space like &lt;p&nbsp;&nbsp;&nbsp;&nbsp;&gt;.
    2626
    27 There are a couple of bugs in the parsing logic that I'm aware of and I will work to iron them out over the coming weeks. 
     27There are a couple of bugs in the parsing logic that I'm aware of and I will work to iron them out over the coming weeks.
    2828
    2929Known issues:
     
    5959== Changelog ==
    6060
     61= 1.1 =
     62* Refactored for support of < php5.3 by replacing function references with static function array refs
    6163= 1.0 =
    6264* Initial creation of plugin
  • preserved-html-editor-markup/trunk/sb_preserved_markup.php

    r456532 r457449  
    33/*
    44Plugin Name: Preserved HTML Editor Markup
    5 Plugin URI: http://www.springbox.com/wordpress/
     5Plugin URI: http://www.marcuspope.com/wordpress/
    66Description: A Wordpress Plugin that preserves HTML markup in the TinyMCE editor, especially when switching between
    77html and visual tabs.  Also adds support for HTML5 Block Anchors.
    8 Author: Marcus E. Pope, Springbox.com, marcuspope
     8Author: Marcus E. Pope, marcuspope
    99Author URI: http://www.marcuspope.com
    1010Version: 1.0
    1111
    12 Copyright 2011 Marcus E. Pope (email : marcus.pope@springbox.com)
     12Copyright 2011 Marcus E. Pope (email : me@marcuspope.com)
    1313
    1414This program is free software; you can redistribute it and/or modify
     
    2727*/
    2828
    29 add_action('plugins_loaded', array('SB_WP_Preserved_Markup', 'init'), 1);
     29add_action('plugins_loaded', array('MP_WP_Preserved_Markup', 'init'), 1);
    3030
    31 class SB_WP_Preserved_Markup {
     31class MP_WP_Preserved_Markup {
     32
     33    public static function remove_evil() {
     34        //remove evil: wpautop will break html5 markup!
     35        remove_filter('the_content', 'wpautop');
     36    }
     37
     38    public static function init_tiny_mce($init) {
     39        //Setup tinymce editor with necessary settings for better general editing
     40        $tags = "pre[*],iframe[*],object[*],param[*]"; //add pre and iframe to allowable tags for
     41        if (isset($init['extended_valid_elements'])) {
     42            $tags = $init['extended_valid_elements'] . "," . $tags;
     43        }
     44        $init['extended_valid_elements'] = $tags;
     45        $init['forced_root_block'] = false; //prevent tinymce from wrapping a root block level element (typically a <p> tag)
     46        $init['force_p_newlines'] = false;
     47        $init['remove_linebreaks'] = false;
     48        $init['force_br_newlines'] = true;
     49        $init['remove_trailing_nbsp'] = false;
     50        $init['relative_urls'] = true;
     51        $init['convert_urls'] = false;
     52        $init['remove_linebreaks'] = false;
     53        $init['doctype'] = '<!DOCTYPE html>';
     54        $init['apply_source_formatting'] = false;
     55        $init['convert_newlines_to_brs'] = false;
     56        $init['fix_list_elements'] = false;
     57        $init['fix_table_elements'] = false;
     58        $init['verify_html'] = false;
     59
     60        /*
     61           Allow for html5 anchor tags
     62           http://dev.w3.org/html5/markup/a.html
     63           http://dev.w3.org/html5/markup/common-models.html#common.elem.phrasing
     64           http://www.tinymce.com/wiki.php/Configuration:valid_children
     65        */
     66        $init['valid_children'] = "+a[em|strong|small|mark|abbr|dfn|i|b|s|u|code|var|samp|kbd|sup|sub|q|cite|span|bdo|bdi|br|wbr|ins|del|img|embed|object|iframe|map|area|script|noscript|ruby|video|audio|input|textarea|select|button|label|output|datalist|keygen|progress|command|canvas|time|meter|p|hr|pre|ul|ol|dl|div|h1|h2|h3|h4|h5|h6|hgroup|address|blockquote|section|nav|article|aside|header|footer|figure|table|f|m|fieldset|menu|details]";
     67
     68        return $init;
     69    }
     70
     71    public static function fix_editor_content($html) {
     72        remove_filter('the_editor_content', "wp_richedit_pre");
     73        return $html;
     74    }
     75
     76    public static function content_replace_callback($a) {
     77        $s = $a[0];
     78        $s = preg_replace("/(\r\n|\n)/m", '<mep-preserve-nl>', $s);
     79        $s = preg_replace("/\t/m", '<mep-preserve-tab>', $s);
     80        $s = preg_replace("/\s/m", '<mep-preserve-space>', $s);
     81        return $s;
     82    }
     83
     84    public static function fix_wysiwyg_content($c) {
     85        //If the page is rendered with the WYSIWYG editor selected by default, content is processed in PHP land
     86        //instead of using the JS land "equivalent" logic (I quote equivalent because there are sooooo many
     87        //discrepancies between what JS wpautop and PHP wpautop functions do it's laughable.
     88        if (wp_default_editor() == "tinymce") {
     89            //First we inject temporary whitespace markers in pre and code elements because they won't
     90            //be corrupted when the user switches to html mode.*   (actually IE9 will remove the first
     91            //newline from a pre tag if there are no non-whitespace characters before the newline.)
     92            $c = preg_replace_callback(
     93                '/<(pre|code)[^>]*>[\s\S]+?<\/\\1>/m',
     94                array(
     95                    'MP_WP_Preserved_Markup',
     96                    'content_replace_callback'
     97                ),
     98                $c);
     99
     100            //Now let's preserve whitespace with html comments so that they can be converted back when switching to
     101            //the html mode.  FIXME: assuming four spaces is bad mmkay, what if I like only two spaces for a tab?
     102            //and this could produce bad markup if a user had <p    class="test">hello</p> in their markup.  So
     103            //work on a more flexible /\s/g approach when \s is inside or outside a tag definition
     104            $c = preg_replace("/(\r\n|\n)/", "<!--mep-nl-->", $c); //preserve new lines
     105            $c = preg_replace("/(\t|\s\s\s\s)/", "<!--mep-tab-->", $c); //preserve indents
     106
     107            //Now we can restore all whitespace originally escaped in pre & code tags
     108            $c = preg_replace("/<mep-preserve-nl>/m", "\n", $c);
     109            $c = preg_replace("/<mep-preserve-tab>/m", "\t", $c);
     110            $c = preg_replace("/<mep-preserve-space>/m", " ", $c);
     111
     112            //finish up with functions that WP normally calls on the_editor_content
     113            $c = convert_chars($c);
     114            $c = htmlspecialchars($c, ENT_NOQUOTES);
     115        }
     116
     117        return $c;
     118    }
     119
     120    public static function fix_post_content($post) {
     121        //If the user clicks save while in the Visual (WYSIWYG) tab, we'll need to strip the whitespace placeholders
     122        //before inserting the data into the database to prevent duplication of whitespace
     123        //WTF: ok so I ran into a problem of duplicating newlines when saving from the Visual tab, so I added this
     124        //     code to strip what I thought was my whitespace markers not being converted back in JS land before being
     125        //     sent to the server.  (in the same way that if you load the page on the Visual tab, the parsing logic
     126        //     occurs on the server instead of the client!)  But after add this code I couldn't reproduce the issue
     127        //     the post_content never contained any mep-xxx comments.  I'm leaving this code in here, because it's
     128        //     the probable explanation for duplicated newlines, but I'm also not sure how the Visual content is
     129        //     transfered from the iframe to the textarea.
     130        if (isset($post['post_content'])) {
     131            $post['post_content'] = preg_replace('/<\!--mep-nl-->/m', "\r\n", $post['post_content']);
     132            $post['post_content'] = preg_replace('/<\!--mep-tab-->/m', "    ", $post['post_content']);
     133        }
     134        return $post;
     135    }
     136
     137    public static function admin_init() {
     138        //Add full attribute support for special tags
     139        add_filter( 'tiny_mce_before_init', array(
     140            'MP_WP_Preserved_Markup',
     141            'init_tiny_mce'
     142        ));
     143
     144        /* fix WP html editor on client side */
     145        wp_enqueue_script('admin-js', WP_PLUGIN_URL.'/'.str_replace(basename( __FILE__),"",plugin_basename(__FILE__))."admin.js");
     146
     147        add_filter('the_editor', array(
     148            'MP_WP_Preserved_Markup',
     149            'fix_editor_content'
     150        ), 1);
     151
     152        add_filter('the_editor_content', array(
     153            'MP_WP_Preserved_Markup',
     154            'fix_wysiwyg_content'
     155        ), 1);
     156
     157        add_filter('wp_insert_post_data', array(
     158            'MP_WP_Preserved_Markup',
     159            'fix_post_content'
     160        ), 1);
     161    }
    32162
    33163    public static function init() {
     164        add_action('init', array(
     165            'MP_WP_Preserved_Markup',
     166            'remove_evil'
     167        ));
    34168
    35         add_action('init', function() {
    36             //remove evil: wpautop will break html5 markup!
    37             remove_filter('the_content', 'wpautop');
    38         });
    39 
    40         add_action('admin_init', function() {
    41 
    42             //Add full attribute support for special tags
    43             add_filter( 'tiny_mce_before_init', function($init) {
    44                 $tags = "pre[*],iframe[*],object[*],param[*]"; //add pre and iframe to allowable tags for
    45                 if (isset($init['extended_valid_elements'])) {
    46                     $tags = $init['extended_valid_elements'] . "," . $tags;
    47                 }
    48                 $init['extended_valid_elements'] = $tags;
    49                 $init['forced_root_block'] = false; //prevent tinymce from wrapping a root block level element (typically a <p> tag)
    50                 $init['force_p_newlines'] = false;
    51                 $init['remove_linebreaks'] = false;
    52                 $init['force_br_newlines'] = true;
    53                 $init['remove_trailing_nbsp'] = false;
    54                 $init['relative_urls'] = true;
    55                 $init['convert_urls'] = false;
    56                 $init['remove_linebreaks'] = false;
    57                 $init['doctype'] = '<!DOCTYPE html>';
    58                 $init['apply_source_formatting'] = false;
    59                 $init['convert_newlines_to_brs'] = false;
    60                 $init['fix_list_elements'] = false;
    61                 $init['fix_table_elements'] = false;
    62                 $init['verify_html'] = false;
    63 
    64                 /*
    65                    Allow for html5 anchor tags
    66                    http://dev.w3.org/html5/markup/a.html
    67                    http://dev.w3.org/html5/markup/common-models.html#common.elem.phrasing
    68                    http://www.tinymce.com/wiki.php/Configuration:valid_children
    69                 */
    70                 $init['valid_children'] = "+a[em|strong|small|mark|abbr|dfn|i|b|s|u|code|var|samp|kbd|sup|sub|q|cite|span|bdo|bdi|br|wbr|ins|del|img|embed|object|iframe|map|area|script|noscript|ruby|video|audio|input|textarea|select|button|label|output|datalist|keygen|progress|command|canvas|time|meter|p|hr|pre|ul|ol|dl|div|h1|h2|h3|h4|h5|h6|hgroup|address|blockquote|section|nav|article|aside|header|footer|figure|table|f|m|fieldset|menu|details]";
    71 
    72                 return $init;
    73             });
    74 
    75             /* fix WP html editor */
    76             wp_enqueue_script('admin-js', WP_PLUGIN_URL.'/'.str_replace(basename( __FILE__),"",plugin_basename(__FILE__))."admin.js");
    77 
    78             add_filter('the_editor', function($html) {
    79                 remove_filter('the_editor_content', "wp_richedit_pre");
    80                 return $html;
    81             }, 1);
    82 
    83             add_filter('the_editor_content', function($c) {
    84                 //If the page is rendered with the WYSIWYG editor selected by default, content is processed in PHP land
    85                 //instead of using the JS land "equivalent" logic (I quote equivalent because there are sooooo many
    86                 //discrepancies between what JS wpautop and PHP wpautop functions do it's laughable.
    87                 if (wp_default_editor() == "tinymce") {
    88                     //First we inject temporary whitespace markers in pre and code elements because they won't
    89                     //be corrupted when the user switches to html mode.*   (actually IE9 will remove the first
    90                     //newline from a pre tag if there are no non-whitespace characters before the newline.)
    91                     $c = preg_replace_callback('/<(pre|code)[^>]*>[\s\S]+?<\/\\1>/m', function($a) {
    92                         $s = $a[0];
    93                         $s = preg_replace("/(\r\n|\n)/m", '<mep-preserve-nl>', $s);
    94                         $s = preg_replace("/\t/m", '<mep-preserve-tab>', $s);
    95                         $s = preg_replace("/\s/m", '<mep-preserve-space>', $s);
    96                         return $s;
    97                     }, $c);
    98 
    99                     //Now let's preserve whitespace with html comments so that they can be converted back when switching to
    100                     //the html mode.  FIXME: assuming four spaces is bad mmkay, what if I like only two spaces for a tab?
    101                     //and this could produce bad markup if a user had <p    class="test">hello</p> in their markup.  So
    102                     //work on a more flexible /\s/g approach when \s is inside or outside a tag definition
    103                     $c = preg_replace("/(\r\n|\n)/", "<!--mep-nl-->", $c); //preserve new lines
    104                     $c = preg_replace("/(\t|\s\s\s\s)/", "<!--mep-tab-->", $c); //preserve indents
    105 
    106                     //Now we can restore all whitespace originally escaped in pre & code tags
    107                     $c = preg_replace("/<mep-preserve-nl>/m", "\n", $c);
    108                     $c = preg_replace("/<mep-preserve-tab>/m", "\t", $c);
    109                     $c = preg_replace("/<mep-preserve-space>/m", " ", $c);
    110 
    111                     //finish up with functions that WP normally calls on the_editor_content
    112                     $c = convert_chars($c);
    113                     $c = htmlspecialchars($c, ENT_NOQUOTES);
    114                 }
    115 
    116                 return $c;
    117             }, 1);
    118 
    119             add_filter('wp_insert_post_data', function($post) {
    120                 //If the user clicks save while in the Visual (WYSIWYG) tab, we'll need to strip the whitespace placeholders
    121                 //before inserting the data into the database to prevent duplication of whitespace
    122                 //WTF: ok so I ran into a problem of duplicating newlines when saving from the Visual tab, so I added this
    123                 //     code to strip what I thought was my whitespace markers not being converted back in JS land before being
    124                 //     sent to the server.  (in the same way that if you load the page on the Visual tab, the parsing logic
    125                 //     occurs on the server instead of the client!)  But after add this code I couldn't reproduce the issue
    126                 //     the post_content never contained any mep-xxx comments.  I'm leaving this code in here, because it's
    127                 //     the probable explanation for duplicated newlines, but I'm also not sure how the Visual content is
    128                 //     transfered from the iframe to the textarea.
    129                 if (isset($post['post_content'])) {
    130                     $post['post_content'] = preg_replace('/<\!--mep-nl-->/m', "\r\n", $post['post_content']);
    131                     $post['post_content'] = preg_replace('/<\!--mep-tab-->/m', "    ", $post['post_content']);
    132                 }
    133                 return $post;
    134             }, 1);
    135         });
     169        add_action('admin_init', array(
     170            'MP_WP_Preserved_Markup',
     171            'admin_init'
     172        ));
    136173    }
    137174}
Note: See TracChangeset for help on using the changeset viewer.