====== Highlight Plugin ====== ---- plugin ---- description: Enables a simple mark-up syntax for highlighting text in various colors. author : Joseph Nahmias email : joe@nahmias.net type : syntax lastupdate : 2006-09-06 compatible : depends : conflicts : similar : changemarks, emphasis tags : colors, marking, highlight securityissue: XSS vulnerability allows arbitrary JavaScript insertion. Author informed on 2008-02-07. ---- ===== Recent changes ===== I've made security fix in function ''_isValid'' to prevent XSS vulnerability. All unrecognized as color input now is ignored. If you want to fix your installation, just apply the patch.--- //[[kibizoid@gmail.com|Alexander Sorkin aka Kibi]] 2009/01/22 13:01// // old code function _isValid($c) { $c = trim($c); $pattern = "/ ([a-zA-z]+)| #colorname - not verified (\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}))| #colorvalue (rgb\(([0-9]{1,3}%?,){2}[0-9]{1,3}%?\)) #rgb triplet /x"; if (preg_match($pattern, $c)) return true; return false; } // new code function _isValid($c) { $c = trim($c); $pattern = "/ (^[a-zA-Z]+$)| #colorname - not verified (^\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$)| #colorvalue (^rgb\(([0-9]{1,3}%?,){2}[0-9]{1,3}%?\)$) #rgb triplet /x"; return (preg_match($pattern, $c)); } ===== Background ===== Although [[wikidesign@gmail.com|Esther Brunner]] already created the [[plugin:Hilited]] plugin, [[joe@nahmias.net|I]] felt it was limiting since it didn't allow the user to define the color of the highlighting. This plugin addresses that shortcoming and adds a nice toolbar menu to choose from various predefined colors. You can also customize the toolbar to add additional colors if you wish. You can try out this plugin on [[ncc@staddle.net|Neal]]'s wiki at [[http://www.staddle.net/wiki/plugins/highlight]]. He has also packaged a version for installation via the plugin manager. FIXED :-P Version for download includes all the corrections on this page - //[[ncc@staddle.net|Neal]] 2009-11-30// ===== Installation ===== - Install via [[plugin:Plugin]] Manager - Visit [[http://www.staddle.net/wiki/plugins/highlight|Neal's site]] for the [[plugin:Plugin]] Manager packaged version - Manual Installation - Create a directory ''lib/plugins/highlight'' - Place the PHP code below in a file called ''syntax.php'' in that directory - Place the JavaScript code below in a file called ''script.js'' in that directory - Create a file called ''toolbar_icon.png'' size 16x16. You can use this [[http://www.staddle.net/dokuwiki/_media/plugins/toolbar_icon.png|image]] (//not found// April 2008) -- make sure to save it as ''toolbar_icon.png'' - //Optional// Add additional colors to your [[tips:javascript|conf/userscript.js]] file (see [[#additional_colors|below]] for more details) - Enjoy! :-) ===== Syntax ===== You surround the text that you would like to highlight with the tags '''' and ''''. Here //color// can be any of: - A three or six hexadecimal color value [ e.g. //#E8E// or //#7fffd4// ] - One of the standard color names [ e.g. //white//, //black//, //aqua// ] - An decimal or percentage RGB color [ e.g. //rgb(55%, 35%, 25%)//, //rgb(255, 0, 255)// ] * __Note 1__: If //color// is omitted, a default of yellow (//#FF0//) will be used. * __Note 2__: This follows the W3C CSS standard for colors. See: [[http://www.w3.org/TR/CSS21/syndata.html#color-units|the CSS2.1 spec]] for more detail. ===== Example ===== named cyan highlight \\ default highlight with **some bold** text \\ 3-hex magenta highlight \\ cyan with pink in the middle of the highlight --- doesn't work :-( \\ \\ you need to do it this way you need to do it this way ===== Plugin ===== ==== PHP ==== Put this code into ''lib/plugins/highlight/syntax.php'': * @link http://www.dokuwiki.org/plugin:highlight * @version 3.1 */ if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'syntax.php'); /** * All DokuWiki plugins to extend the parser/rendering mechanism * need to inherit from this class */ class syntax_plugin_highlight extends DokuWiki_Syntax_Plugin { function getInfo(){ // return some info return array( 'author' => 'Joseph Nahmias', 'email' => 'joe@nahmias.net', 'date' => '2006-09-06', 'name' => 'Color Highlight Plugin', 'desc' => 'Highlight text with a specific color Syntax: highlighted content', 'url' => 'http://www.dokuwiki.org/plugin:highlight', ); } // What kind of syntax are we? function getType(){ return 'formatting'; } // What kind of syntax do we allow (optional) function getAllowedTypes() { return array('formatting', 'substition', 'disabled'); } // What about paragraphs? (optional) function getPType(){ return 'normal'; } // Where to sort in? function getSort(){ return 90; } // Connect pattern to lexer function connectTo($mode) { $this->Lexer->addEntryPattern('(?i)(?=.+)',$mode,'plugin_highlight'); } function postConnect() { $this->Lexer->addExitPattern('(?i)','plugin_highlight'); } // Handle the match function handle($match, $state, $pos, &$handler){ switch ($state) { case DOKU_LEXER_ENTER : preg_match("/(?i)/", $match, $color); // get the color if ( $this->_isValid($color[1]) ) return array($state, $color[1]); break; case DOKU_LEXER_MATCHED : break; case DOKU_LEXER_UNMATCHED : return array($state, $match); break; case DOKU_LEXER_EXIT : break; case DOKU_LEXER_SPECIAL : break; } return array($state, "#ff0"); } // Create output function render($mode, &$renderer, $data) { if($mode == 'xhtml'){ list($state, $color) = $data; switch ($state) { case DOKU_LEXER_ENTER : $renderer->doc .= ""; break; case DOKU_LEXER_MATCHED : break; case DOKU_LEXER_UNMATCHED : $renderer->doc .= $renderer->_xmlEntities($color); break; case DOKU_LEXER_EXIT : $renderer->doc .= ""; break; case DOKU_LEXER_SPECIAL : break; } return true; } return false; } // validate color value $c // this is cut price validation - only to ensure the basic format is // correct and there is nothing harmful // three basic formats "colorname", "#fff[fff]", "rgb(255[%],255[%],255[%])" function _isValid($c) { $c = trim($c); $pattern = "/ (^[a-zA-Z]+$)| #colorname - not verified (^\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$)| #colorvalue (^rgb\(([0-9]{1,3}%?,){2}[0-9]{1,3}%?\)$) #rgb triplet /x"; return (preg_match($pattern, $c)); } } //Setup VIM: ex: et ts=4 sw=4 enc=utf-8 : ==== JavaScript ==== Put this code into ''lib/plugins/highlight/script.js'': /* JavaScript function to create highlight toolbar in DokuwKki */ /* see http://www.dokuwiki.org/plugin:highlight for more info */ var plugin_highlight_colors = { "Yellow": "#ffff00", "Red": "#ff0000", "Orange": "#ffa500", "Salmon": "#fa8072", "Pink": "#ffc0cb", "Plum": "#dda0dd", "Purple": "#800080", "Fuchsia": "#ff00ff", "Silver": "#c0c0c0", "Aqua": "#00ffff", "Teal": "#008080", "Cornflower": "#6495ed", "Sky Blue": "#87ceeb", "Aquamarine": "#7fffd4", "Pale Green": "#98fb98", "Lime": "#00ff00", "Green": "#008000", "Olive": "#808000" }; function plugin_highlight_make_color_button(name, value) { var btn = document.createElement('button'); btn.className = 'pickerbutton'; btn.value = ' '; btn.title = name; btn.style.height = '2em'; btn.style.padding = '1em'; btn.style.backgroundColor = value; var open = ""; var close ="<\/hi>"; var sample = name + " Highlighted Text"; eval("btn.onclick = function(){ insertTags( '" + jsEscape('wiki__text') + "','" + jsEscape(open) + "','" + jsEscape(close)+"','" + jsEscape(sample) + "'); return false; } " ); return(btn); } function plugin_highlight_toolbar_picker() { var toolbar = document.getElementById('tool__bar'); if (!toolbar) return; // Create the picker button var p_id = 'picker_plugin_highlight'; // picker id that we're creating var p_ico = document.createElement('img'); p_ico.src = DOKU_BASE + 'lib/plugins/highlight/toolbar_icon.png'; var p_btn = document.createElement('button'); p_btn.className = 'toolbutton'; p_btn.title = 'Highlight Text'; p_btn.appendChild(p_ico); eval("p_btn.onclick = function() { showPicker('" + p_id + "',this); return false; }"); // Create the picker
var picker = document.createElement('div'); picker.className = 'picker'; picker.id = p_id; picker.style.position = 'absolute'; picker.style.display = 'none'; // Add a button to the picker
for each of the colors for( var color in plugin_highlight_colors ) { var btn = plugin_highlight_make_color_button(color, plugin_highlight_colors[color]); picker.appendChild(btn); } if (typeof user_highlight_colors != 'undefined') { for( var color in user_highlight_colors ) { var btn = plugin_highlight_make_color_button(color, user_highlight_colors[color]); picker.appendChild(btn); } } var body = document.getElementsByTagName('body')[0]; body.appendChild(picker); // attach the picker
to the page body toolbar.appendChild(p_btn); // attach the picker button to the toolbar } addInitEvent(plugin_highlight_toolbar_picker); //Setup VIM: ex: et ts=2 sw=2 enc=utf-8 : ==== Additional Colors ==== To add more colors to the toolbar picker, add the following code to the ''conf/userscript.js'' file (create it if it doesn't exist already): // Additional user-defined highlighting colors var user_highlight_colors = { "Indian Red": "#cd5c5c", "Khaki": "#f0e68c", "Powder Blue": "#b0e0e6", "Sandy Brown": "#f4a460", "Steel Blue": "#4682b4", "Thistle": "#d8bfd8", "Yellow Green":"#9acd32", "Dark Violet": "#9400d3", "Maroon": "#800000" }; For additional colors (with names) check out the page at: [[http://www.w3schools.com/css/css_colornames.asp|W3Schools]]. ===== Changelog ===== * Version 3.1: Fix bug in IE when no user-defined colors exists; thanks [[ncc@staddle.net|Neal]]! --- //[[joe+dokuwiki@nahmias.net|Joseph Nahmias]] 2006-09-06 15:39// * Version 3.0: Added support for user-defined colors --- //[[joe+dokuwiki@nahmias.net|Joseph Nahmias]] 2006-09-06 00:40// * Version 2.2: Changed script.js to __not__ use a data: URL (No IE support), added Raw 3 * Version 2.1: Changed toolbar icon to use a data: URL for ease of installation * Version 2.0: Added javascript toolbar picker * Version 1.0: Added highlight syntax code ===== TODO ===== * Figure out how users can add colors to the toolbar in ''conf/userscript.js'' * Done?! :-) ===== Bugs ===== * You can't nest highlights (anyone know how to fix this? --- I thought making the second glob greedy would help, but it doesn't :-() FIXME. ===== Discussion ===== * __NOTE__: Please [[joe+dokuwiki@nahmias.net|email me]] if you change the page; for some reason I can't subscribe to changes... * I have modified your plugin to change only the colour of the font (not the background). I didn't want to use inline HTML because it conflicts with many other plugins (notes, styler, draw, etc.). * Here's the modified **plugins/colour/syntax.php** */ if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'syntax.php'); /** * All DokuWiki plugins to extend the parser/rendering mechanism * need to inherit from this class */ class syntax_plugin_colour extends DokuWiki_Syntax_Plugin { /** * return some info */ function getInfo(){ return array( 'author' => 'Joseph Nahmias', 'email' => 'joe@nahmias.net', 'date' => '2006-07-27', 'name' => 'Colour Plugin', 'desc' => 'Colour text with a specific color. Modified by alex@seidlitz.ca', 'url' => 'http://www.dokuwiki.org/plugin:highlight', ); } /** * What kind of syntax are we? */ function getType(){ return 'formatting'; } /** * What kind of syntax do we allow (optional) */ function getAllowedTypes() { return array('formatting', 'substition', 'disabled'); } /** * What about paragraphs? (optional) */ function getPType(){ return 'normal'; } /** * Where to sort in? */ function getSort(){ return 90; } /** * Connect pattern to lexer */ function connectTo($mode) { $this->Lexer->addEntryPattern('(?i)(?=.+)',$mode,'plugin_colour'); } function postConnect() { $this->Lexer->addExitPattern('(?i)','plugin_colour'); } /** * Handle the match */ function handle($match, $state, $pos, &$handler){ switch ($state) { case DOKU_LEXER_ENTER : preg_match("/(?i)/", $match, $color); // get the color if ( $this->_isValid($color[1]) ) return array($state, $color[1]); break; case DOKU_LEXER_MATCHED : break; case DOKU_LEXER_UNMATCHED : return array($state, $match); break; case DOKU_LEXER_EXIT : break; case DOKU_LEXER_SPECIAL : break; } return array($state, "#ff0"); } /** * Create output */ function render($mode, &$renderer, $data) { if($mode == 'xhtml'){ list($state, $color) = $data; switch ($state) { case DOKU_LEXER_ENTER : $renderer->doc .= ""; break; case DOKU_LEXER_MATCHED : break; case DOKU_LEXER_UNMATCHED : $renderer->doc .= $renderer->_xmlEntities($color); break; case DOKU_LEXER_EXIT : $renderer->doc .= ""; break; case DOKU_LEXER_SPECIAL : break; } return true; } return false; } // validate color value $c // this is cut price validation - only to ensure the basic format is // correct and there is nothing harmful // three basic formats "colorname", "#fff[fff]", "rgb(255[%],255[%],255[%])" function _isValid($c) { $c = trim($c); $pattern = "/ ([a-zA-z]+)| #colorname - not verified (\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}))| #colorvalue (rgb\(([0-9]{1,3}%?,){2}[0-9]{1,3}%?\)) #rgb triplet /x"; if (preg_match($pattern, $c)) return true; return false; } } //Setup VIM: ex: et ts=4 enc=utf-8 : ...and I have updated the script.js file to correspond * Here's the modified **plugins/colour/script.js** /* javascript function to create colour toolbar in dokuwiki */ /* see http://www.dokuwiki.org/plugin:colour for more info */ var plugin_colour_colors = { "Yellow": "#ffff00", "Red": "#ff0000", "Orange": "#ffa500", "Salmon": "#fa8072", "Pink": "#ffc0cb", "Plum": "#dda0dd", "Purple": "#800080", "Fuchsia": "#ff00ff", "Silver": "#c0c0c0", "Aqua": "#00ffff", "Teal": "#008080", "Cornflower": "#6495ed", "Sky Blue": "#87ceeb", "Aquamarine": "#7fffd4", "Pale Green": "#98fb98", "Lime": "#00ff00", "Green": "#008000", "Olive": "#808000" }; function plugin_colour_make_color_button(name, value) { var btn = document.createElement('button'); btn.className = 'pickerbutton'; btn.value = ' '; btn.title = name; btn.style.height = '2em'; btn.style.padding = '1em'; btn.style.backgroundColor = value; var open = ""; var close ="<\/col>"; var sample = name + " Colour Text"; eval("btn.onclick = function(){ insertTags( '" + jsEscape('wiki__text') + "','" + jsEscape(open) + "','" + jsEscape(close)+"','" + jsEscape(sample) + "'); return false; } " ); return(btn); } function plugin_colour_toolbar_picker() { // Check that we are editing the page - is there a better way to do this? var edbtn = document.getElementById('edbtn__save'); if (!edbtn) return; var toolbar = document.getElementById('tool__bar'); if (!toolbar) return; // Create the picker button var p_id = 'picker_plugin_colour'; // picker id that we're creating var p_ico = document.createElement('img'); p_ico.src = DOKU_BASE + 'lib/plugins/colour/colour_toolbar_icon.png'; var p_btn = document.createElement('button'); p_btn.className = 'toolbutton'; p_btn.title = 'Colour Text'; p_btn.appendChild(p_ico); eval("p_btn.onclick = function() { showPicker('" + p_id + "',this); return false; }"); // Create the picker
var picker = document.createElement('div'); picker.className = 'picker'; picker.id = p_id; picker.style.position = 'absolute'; picker.style.display = 'none'; // Add a button to the picker
for each of the colors for( var color in plugin_colour_colors ) { var btn = plugin_colour_make_color_button(color, plugin_colour_colors[color]); picker.appendChild(btn); } if (typeof user_colour_colors != 'undefined') { for( var color in user_colour_colors ) { var btn = plugin_colour_make_color_button(color, user_colour_colors[color]); picker.appendChild(btn); } } var body = document.getElementsByTagName('body')[0]; body.appendChild(picker); // attach the picker
to the page body toolbar.appendChild(p_btn); // attach the picker button to the toolbar } addInitEvent(plugin_colour_toolbar_picker); //Setup VIM: ex: et ts=2 sw=2 enc=utf-8 : ...and, finally the colour_toolbar_icon.png : (oops, can't upload the file) === Toolbar button missing === Any tips on making the toolbar button show up? Everything works, except the button isn't there. Thanks. -Richard Jupp, I'm having the same problem here ... any help welcome! - Kristine Changing script.js line 60 **from:** p_ico.src = DOKU_BASE + 'lib/plugins/highlight/toolbar_icon.png'; **to:** p_ico.src = DOKU_BASE + 'lib/plugins/highlight/images/toolbar_icon.png'; And placing the image inside the images folder solved the problem. The icon for highlighting shows in the page source when not logged in to the wiki. ADD \\ if (!document.getElementById('spell__action')) return; \\ below function plugin_highlight_toolbar_picker() { **Toolbar button isn't added to the toolbar.... ** ==== Adding button to toolbar ==== Does anybody know which changes need to be made in order to have the button displayed in the toolbar?