From 78a6aeb15ad85c8be4a7e39307b7d9aa0512742c Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 29 Oct 2005 20:52:22 +0200 Subject: More work on Javascript and CSS dispatchers darcs-hash:20051029185222-7ad00-c184ab3496539f3027407c7d17e8770a1849546a.gz --- lib/exe/css.php | 165 +++++++++++++++++++++++++++ lib/exe/js.php | 331 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/exe/jscss.php | 293 ----------------------------------------------- 3 files changed, 496 insertions(+), 293 deletions(-) create mode 100644 lib/exe/css.php create mode 100644 lib/exe/js.php delete mode 100644 lib/exe/jscss.php (limited to 'lib/exe') diff --git a/lib/exe/css.php b/lib/exe/css.php new file mode 100644 index 000000000..7b6523b41 --- /dev/null +++ b/lib/exe/css.php @@ -0,0 +1,165 @@ + + */ + +if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); +define('NOSESSION',true); // we do not use a session or authentication here (better caching) +require_once(DOKU_INC.'inc/init.php'); +require_once(DOKU_INC.'inc/pageutils.php'); +require_once(DOKU_INC.'inc/io.php'); + +// Main (don't run when UNIT test) +if(!defined('SIMPLE_TEST')){ + header('Content-Type: text/css; charset=utf-8'); + css_out(); +} + + +// ---------------------- functions ------------------------------ + +/** + * Output all needed Styles + * + * @author Andreas Gohr + */ +function css_out(){ + global $conf; + global $lang; + $print = (bool) $_REQUEST['print']; //print mode? + + // The generated script depends on some dynamic options + $cache = getCacheName('styles'.$print,'.css'); + + // Array of needed files and their web locations, the latter ones + // are needed to fix relative paths in the stylesheets + $files = array(); + if($print){ + $files[DOKU_TPLINC.'print.css'] = DOKU_TPL; + // load plugin styles + $files = array_merge($files, css_pluginstyles('print')); + $files[DOKU_CONF.'userprint.css'] = ''; + }else{ + $files[DOKU_INC.'lib/styles/style.css'] = DOKU_BASE.'lib/styles/'; + //fixme spellchecker style + $files[DOKU_TPLINC.'layout.css'] = DOKU_TPL; + $files[DOKU_TPLINC.'design.css'] = DOKU_TPL; + if($lang['direction'] == 'rtl'){ + $files[DOKU_TPLINC.'rtl.css'] = DOKU_TPL; + } + // load plugin styles + $files = array_merge($files, css_pluginstyles('screen')); + $files[DOKU_CONF.'userstyle.css'] = ''; + } + + // check cache age + if(css_cacheok($cache,array_keys($files))){ + readfile($cache); + return; + } + + // start output buffering and build the stylesheet + ob_start(); + + // load files + foreach($files as $file => $location){ + print css_loadfile($file, $location); + } + + // end output buffering and get contents + $css = ob_get_contents(); + ob_end_clean(); + + // compress whitespace and comments + if($conf['compress']){ + $css = css_compress($css); + } + + // save cache file + io_saveFile($cache,$css); + + // finally send output + print $css; +} + +/** + * Checks if a CSS Cache file still is valid + * + * @author Andreas Gohr + */ +function css_cacheok($cache,$files){ + $ctime = @filemtime($cache); + if(!$ctime) return false; //There is no cache + + // some additional files to check + $files[] = DOKU_CONF.'dokuwiki.conf'; + $files[] = DOKU_CONF.'local.conf'; + $files[] = __FILE__; + + // now walk the files + foreach($files as $file){ + if(@filemtime($file) > $ctime){ + return false; + } + } + return true; +} + +/** + * Loads a given file and fixes relative URLs with the + * given location prefix + */ +function css_loadfile($file,$location=''){ + if(!@file_exists($file)) return ''; + $css = io_readFile($file); + if(!$location) return $css; + + $css = preg_replace('!(url\( *)([^/])!','\\1'.$location.'\\2',$css); + return $css; +} + +/** + * Returns a list of possible Plugin Styles (no existance check here) + * + * @author Andreas Gohr + */ +function css_pluginstyles($mode='screen'){ + $list = array(); + $plugins = plugin_list(); + foreach ($plugins as $p){ + if($mode == 'print'){ + $list[DOKU_PLUGIN."$p/print.css"] = DOKU_BASE."lib/plugins/$p/"; + }else{ + $list[DOKU_PLUGIN."$p/style.css"] = DOKU_BASE."lib/plugins/$p/"; + $list[DOKU_PLUGIN."$p/screen.css"] = DOKU_BASE."lib/plugins/$p/"; + } + } + return $list; +} + +/** + * Very simple CSS optimizer + * + * @author Andreas Gohr + */ +function css_compress($css){ + // strip whitespaces + $css = preg_replace('![\r\n\t ]+!',' ',$css); + $css = preg_replace('/ ?([:;,{}]) ?/','\\1',$css); + + // strip comments (ungreedy) + // We keep very small comments to maintain typical browser hacks + $css = preg_replace('!(/\*)(.{4,})(\*/)!U','',$css); + + // shorten colors + $css = preg_replace("/#([0-9a-fA-F]{1})\\1([0-9a-fA-F]{1})\\2([0-9a-fA-F]{1})\\3/", "#\\1\\2\\3",$css); + + return $css; +} + + +//Setup VIM: ex: et ts=4 enc=utf-8 : +?> diff --git a/lib/exe/js.php b/lib/exe/js.php new file mode 100644 index 000000000..9708dbc0d --- /dev/null +++ b/lib/exe/js.php @@ -0,0 +1,331 @@ + + */ + +if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); +define('NOSESSION',true); // we do not use a session or authentication here (better caching) +require_once(DOKU_INC.'inc/init.php'); +require_once(DOKU_INC.'inc/pageutils.php'); +require_once(DOKU_INC.'inc/io.php'); + +// Main (don't run when UNIT test) +if(!defined('SIMPLE_TEST')){ + header('Content-Type: text/javascript; charset=utf-8'); + js_out(); + js_dynamicout(); +} + + +// ---------------------- functions ------------------------------ + +/** + * Output all needed JavaScript + * + * @author Andreas Gohr + */ +function js_out(){ + global $conf; + global $lang; + $edit = (bool) $_REQUEST['edit']; // edit or preview mode? + $write = (bool) $_REQUEST['write']; // writable? + + // The generated script depends on some dynamic options + $cache = getCacheName('scripts'.$edit.$write,'.js'); + + // Array of needed files + $files = array( + DOKU_INC.'lib/scripts/events.js', + DOKU_INC.'lib/scripts/script.js', + DOKU_INC.'lib/scripts/tw-sack.js', + DOKU_INC.'lib/scripts/ajax.js', + DOKU_INC.'lib/scripts/domLib.js', + DOKU_INC.'lib/scripts/domTT.js', + ); + if($edit && $write){ + $files[] = DOKU_INC.'lib/scripts/edit.js'; + if($conf['spellchecker']){ + $files[] = DOKU_INC.'lib/scripts/spellcheck.js'; + } + } + + // get possible plugin scripts + $plugins = js_pluginscripts(); + + // check cache age here + if(js_cacheok($cache,array_merge($files,$plugins))){ + readfile($cache); + return; + } + + // start output buffering and build the script + ob_start(); + + // add some translation strings and global variables + print "var alertText = '".str_replace('\\\\n','\\n',addslashes($lang['qb_alert']))."';"; + print "var notSavedYet = '".str_replace('\\\\n','\\n',addslashes($lang['notsavedyet']))."';"; + print "var DOKU_BASE = '".DOKU_BASE."';"; + + // load files + foreach($files as $file){ + readfile($file); + } + + // init stuff + js_runonstart("ajax_qsearch.init('qsearch_in','qsearch_out')"); + js_runonstart("addEvent(document,'click',closePopups)"); + + if($edit){ + // size controls + js_runonstart("initSizeCtl('sizectl','wikitext')"); + + if($write){ + require_once(DOKU_INC.'inc/toolbar.php'); + toolbar_JSdefines('toolbar'); + js_runonstart("initToolbar('toolbar','wikitext',toolbar)"); + + // add pageleave check + js_runonstart("initChangeCheck('".js_escape($lang['notsavedyet'])."')"); + + // add lock timer + js_runonstart("init_locktimer(".($conf['locktime']-60).",'".js_escape($lang['willexpire'])."')"); + + // load spell checker + if($conf['spellchecker']){ + js_runonstart("ajax_spell.init('". + js_escape($lang['spell_start'])."','". + js_escape($lang['spell_stop'])."','". + js_escape($lang['spell_wait'])."','". + js_escape($lang['spell_noerr'])."','". + js_escape($lang['spell_nosug'])."','". + js_escape($lang['spell_change'])."')"); + } + } + } + + // load plugin scripts (suppress warnings for missing ones) + foreach($plugins as $plugin){ + @readfile($plugin); + } + + // load user script + @readfile(DOKU_CONF.'userscript.js'); + + // end output buffering and get contents + $js = ob_get_contents(); + ob_end_clean(); + + // compress whitespace and comments + if($conf['compress']){ + $js = js_compress($js); + } + + // save cache file + io_saveFile($cache,$js); + + // finally send output + print $js; +} + +/** + * Adds some dynamic JavaScript using the readonly Session + * + * @author Andreas Gohr + */ +function js_dynamicout(){ + $edit = (bool) $_REQUEST['edit']; // edit or preview mode? + $write = (bool) $_REQUEST['write']; // writable? + $sig = (bool) $_REQUEST['sig']; // show sig button? + if($edit && $write && $sig){ + require_once(DOKU_INC.'inc/toolbar.php'); + toolbar_addsigbutton('toolbar'); + } +} + +/** + * Checks if a JavaScript Cache file still is valid + * + * @author Andreas Gohr + */ +function js_cacheok($cache,$files){ + $ctime = @filemtime($cache); + if(!$ctime) return false; //There is no cache + + // some additional files to check + $files[] = DOKU_CONF.'dokuwiki.conf'; + $files[] = DOKU_CONF.'local.conf'; + $files[] = DOKU_CONF.'userscript.js'; + $files[] = __FILE__; + + // now walk the files + foreach($files as $file){ + if(@filemtime($file) > $ctime){ + return false; + } + } + return true; +} + +/** + * Returns a list of possible Plugin Scripts (no existance check here) + * + * @author Andreas Gohr + */ +function js_pluginscripts(){ + $list = array(); + $plugins = plugin_list(); + foreach ($plugins as $p){ + $list[] = DOKU_PLUGIN."$p/script.js"; + } + return $list; +} + +/** + * Escapes a String to be embedded in a JavaScript call, keeps \n + * as newline + * + * @author Andreas Gohr + */ +function js_escape($string){ + return str_replace('\\\\n','\\n',addslashes($string)); +} + +/** + * Adds the given JavaScript code to the window.onload() event + * + * @author Andreas Gohr + */ +function js_runonstart($func){ + print "addEvent(window,'load',function(){ $func; });"; +} + +/** + * Strip comments and whitespaces from given JavaScript Code + * + * This is a rewrite of Nick Galbreaths python tool jsstrip.py which is + * released under BSD license. See link for original code. + * + * @author Nick Galbreath + * @author Andreas Gohr + * @link http://modp.com/release/jsstrip/ + */ +function js_compress($s){ + $i = 0; + $line = 0; + $s .= "\n"; + $len = strlen($s); + + // items that don't need spaces next to them + $chars = '^&|!+\-*\/%=:;,{}()<>% \t\n\r'; + + ob_start(); + while($i < $len){ + $ch = $s{$i}; + + // multiline comments + if($ch == '/' && $s{$i+1} == '*'){ + $endC = strpos($s,'*/',$i+2); + if($endC === false) trigger_error('Found invalid /*..*/ comment', E_USER_ERROR); + $i = $endC + 2; + continue; + } + + // singleline + if($ch == '/' && $s{$i+1} == '/'){ + $endC = strpos($s,"\n",$i+2); + if($endC === false) trigger_error('Invalid comment', E_USER_ERROR); + $i = $endC; + continue; + } + + // tricky. might be an RE + if($ch == '/'){ + // rewind, skip white space + $j = 1; + while($s{$i-$j} == ' '){ + $j = $j + 1; + } + if( ($s{$i-$j} == '=') || ($s{$i-$j} == '(') ){ + // yes, this is an re + // now move forward and find the end of it + $j = 1; + while($s{$i+$j} != '/'){ + while( ($s{$i+$j} != '\\') && ($s{$i+$j} != '/')){ + $j = $j + 1; + } + if($s{$i+$j} == '\\') $j = $j + 2; + } + echo substr($s,$i,$j+1); + $i = $i + $j + 1; + continue; + } + } + + // double quote strings + if($ch == '"'){ + $j = 1; + while( $s{$i+$j} != '"' ){ + while( ($s{$i+$j} != '\\') && ($s{$i+$j} != '"') ){ + $j = $j + 1; + } + if($s{$i+$j} == '\\') $j = $j + 2; + } + echo substr($s,$i,$j+1); + $i = $i + $j + 1; + continue; + } + + // single quote strings + if($ch == "'"){ + $j = 1; + while( $s{$i+$j} != "'" ){ + while( ($s{$i+$j} != '\\') && ($s{$i+$j} != "'") ){ + $j = $j + 1; + } + if ($s{$i+$j} == '\\') $j = $j + 2; + } + echo substr($s,$i,$j+1); + $i = $i + $j + 1; + continue; + } + + // newlines + if($ch == "\n" || $ch == "\r"){ + $i = $i+1; + continue; + } + + // leading spaces + if( ( $ch == ' ' || + $ch == "\n" || + $ch == "\t" ) && + !preg_match('/['.$chars.']/',$s{$i+1}) ){ + $i = $i+1; + continue; + } + + // trailing spaces + if( ( $ch == ' ' || + $ch == "\n" || + $ch == "\t" ) && + !preg_match('/['.$chars.']/',$s{$i-1}) ){ + $i = $i+1; + continue; + } + + // other chars + echo $ch; + $i = $i + 1; + } + + + $out = ob_get_contents(); + ob_end_clean(); + return $out; +} + +//Setup VIM: ex: et ts=4 enc=utf-8 : +?> diff --git a/lib/exe/jscss.php b/lib/exe/jscss.php deleted file mode 100644 index 33d67eece..000000000 --- a/lib/exe/jscss.php +++ /dev/null @@ -1,293 +0,0 @@ - - */ - -if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); -define('NOSESSION',true); // we do not use a session or authentication here (better caching) -require_once(DOKU_INC.'inc/init.php'); -require_once(DOKU_INC.'inc/pageutils.php'); -require_once(DOKU_INC.'inc/io.php'); - -// Main (don't run when UNIT test) -if(!defined('SIMPLE_TEST')){ - if($_REQUEST['type'] == 'css'){ - css_out(); - }else{ - header('Content-Type: text/javascript; charset=utf-8'); - js_out(); - } -} - - -// ---------------------- functions ------------------------------ - -/** - * Output all needed JavaScript - * - * @todo Add Whitespace and Comment Compression - * @author Andreas Gohr - */ -function js_out(){ - global $conf; - global $lang; - $edit = (bool) $_REQUEST['edit']; // edit or preview mode? - $write = (bool) $_REQUEST['write']; // writable? - - // The generated script depends on some dynamic options - $cache = getCacheName($conf['lang'].$edit.$write,$ext='.js'); - - // Array of needed files - $files = array( - DOKU_INC.'lib/scripts/events.js', - DOKU_INC.'lib/scripts/script.js', - DOKU_INC.'lib/scripts/tw-sack.js', - DOKU_INC.'lib/scripts/ajax.js', - DOKU_INC.'lib/scripts/domLib.js', - DOKU_INC.'lib/scripts/domTT.js', - ); - if($edit && $write){ - $files[] = DOKU_INC.'lib/scripts/edit.js'; - if($conf['spellchecker']){ - $files[] = DOKU_INC.'lib/scripts/spellcheck.js'; - } - } - - // FIXME load plugin scripts - - // check cache age here - if(js_cacheok($cache,$files)){ - readfile($cache); - return; - } - - // start output buffering and build the script - ob_start(); - - // add some translation strings and global variables - print "var alertText = '".str_replace('\\\\n','\\n',addslashes($lang['qb_alert']))."';"; - print "var notSavedYet = '".str_replace('\\\\n','\\n',addslashes($lang['notsavedyet']))."';"; - print "var DOKU_BASE = '".DOKU_BASE."';"; - - // load files - foreach($files as $file){ - readfile($file); - } - - // init stuff - js_runonstart("ajax_qsearch.init('qsearch_in','qsearch_out')"); - js_runonstart("addEvent(document,'click',closePopups)"); - - if($edit){ - // size controls - js_runonstart("initSizeCtl('sizectl','wikitext')"); - - if($write){ - require_once(DOKU_INC.'inc/toolbar.php'); - toolbar_JSdefines('toolbar'); - js_runonstart("initToolbar('toolbar','wikitext',toolbar)"); - - // add pageleave check - js_runonstart("initChangeCheck('".js_escape($lang['notsavedyet'])."')"); - - // add lock timer - js_runonstart("init_locktimer(".($conf['locktime']-60).",'".js_escape($lang['willexpire'])."')"); - - // load spell checker - if($conf['spellchecker']){ - js_runonstart("ajax_spell.init('". - js_escape($lang['spell_start'])."','". - js_escape($lang['spell_stop'])."','". - js_escape($lang['spell_wait'])."','". - js_escape($lang['spell_noerr'])."','". - js_escape($lang['spell_nosug'])."','". - js_escape($lang['spell_change'])."')"); - } - } - } - - - // load user script - if(@file_exists(DOKU_INC.'conf/userscript.js')){ - readfile(DOKU_INC.'conf/userscript.js'); - } - - // end output buffering and get contents - $js = ob_get_contents(); - ob_end_clean(); - - // compress whitespace and comments - $js = js_compress($js); - - // save cache file - io_saveFile($cache,$js); - - // finally send output - print $js; -} - -/** - * Checks if a JavaScript Cache file still is valid - * - * @author Andreas Gohr - */ -function js_cacheok($cache,$files){ - $ctime = @filemtime($cache); - if(!$ctime) return false; //There is no cache - - // some additional files to check - $files[] = DOKU_INC.'conf/dokuwiki.conf'; - $files[] = DOKU_INC.'conf/local.conf'; - $files[] = DOKU_INC.'conf/userscript.js'; - - // now walk the files - foreach($files as $file){ - if(@filemtime($file) > $ctime){ - return false; - } - } - return true; -} - -/** - * Escapes a String to be embedded in a JavaScript call, keeps \n - * as newline - * - * @author Andreas Gohr - */ -function js_escape($string){ - return str_replace('\\\\n','\\n',addslashes($string)); -} - -/** - * Adds the given JavaScript code to the window.onload() event - * - * @author Andreas Gohr - */ -function js_runonstart($func){ - print "addEvent(window,'load',function(){ $func; });"; -} - -//http://modp.com/release/jsstrip/jsstrip.py -function js_compress($s){ - $i = 0; - $line = 0; - $s .= "\n"; - $len = strlen($s); - - // items that don't need spaces next to them - $chars = '^&|!+\-*\/%=:;,{}()<>% \t\n\r'; - - ob_start(); - while($i < $len){ - $ch = $s{$i}; - - // multiline comments - if($ch == '/' && $s{$i+1} == '*'){ - $endC = strpos($s,'*/',$i+2); - if($endC === false) trigger_error('Found invalid /*..*/ comment', E_USER_ERROR); - $i = $endC + 2; - continue; - } - - // singleline - if($ch == '/' && $s{$i+1} == '/'){ - $endC = strpos($s,"\n",$i+2); - if($endC === false) trigger_error('Invalid comment', E_USER_ERROR); - $i = $endC; - continue; - } - - // tricky. might be an RE - if($ch == '/'){ - // rewind, skip white space - $j = 1; - while($s{$i-$j} == ' '){ - $j = $j + 1; - } - if( ($s{$i-$j} == '=') || ($s{$i-$j} == '(') ){ - // yes, this is an re - // now move forward and find the end of it - $j = 1; - while($s{$i+$j} != '/'){ - while( ($s{$i+$j} != '\\') && ($s{$i+$j} != '/')){ - $j = $j + 1; - } - if($s{$i+$j} == '\\') $j = $j + 2; - } - echo substr($s,$i,$j+1); - $i = $i + $j + 1; - continue; - } - } - - // double quote strings - if($ch == '"'){ - $j = 1; - while( $s{$i+$j} != '"' ){ - while( ($s{$i+$j} != '\\') && ($s{$i+$j} != '"') ){ - $j = $j + 1; - } - if($s{$i+$j} == '\\') $j = $j + 2; - } - echo substr($s,$i,$j+1); - $i = $i + $j + 1; - continue; - } - - // single quote strings - if($ch == "'"){ - $j = 1; - while( $s{$i+$j} != "'" ){ - while( ($s{$i+$j} != '\\') && ($s{$i+$j} != "'") ){ - $j = $j + 1; - } - if ($s{$i+$j} == '\\') $j = $j + 2; - } - echo substr($s,$i,$j+1); - $i = $i + $j + 1; - continue; - } - - // newlines - if($ch == "\n" || $ch == "\r"){ - $i = $i+1; - continue; - } - - // leading spaces - if( ( $ch == ' ' || - $ch == "\n" || - $ch == "\t" ) && - !preg_match('/['.$chars.']/',$s{$i+1}) ){ - $i = $i+1; - continue; - } - - // trailing spaces - if( ( $ch == ' ' || - $ch == "\n" || - $ch == "\t" ) && - !preg_match('/['.$chars.']/',$s{$i-1}) ){ - $i = $i+1; - continue; - } - - // other chars - echo $ch; - $i = $i + 1; - } - - - $out = ob_get_contents(); - ob_end_clean(); - return $out; -} - -//http://csstidy.sourceforge.net/download.php - -//Setup VIM: ex: et ts=4 enc=utf-8 : -?> -- cgit v1.2.3