source: documentation/trunk/packages/dokuwiki-2011-05-25a/lib/exe/js.php@ 25027

Last change on this file since 25027 was 25027, checked in by jmt12, 12 years ago

Adding the packages directory, and within it a configured version of dokuwiki all ready to run

File size: 12.3 KB
Line 
1<?php
2/**
3 * DokuWiki JavaScript creator
4 *
5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author Andreas Gohr <[email protected]>
7 */
8
9if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../');
10if(!defined('NOSESSION')) define('NOSESSION',true); // we do not use a session or authentication here (better caching)
11if(!defined('NL')) define('NL',"\n");
12if(!defined('DOKU_DISABLE_GZIP_OUTPUT')) define('DOKU_DISABLE_GZIP_OUTPUT',1); // we gzip ourself here
13require_once(DOKU_INC.'inc/init.php');
14
15// Main (don't run when UNIT test)
16if(!defined('SIMPLE_TEST')){
17 header('Content-Type: text/javascript; charset=utf-8');
18 js_out();
19}
20
21
22// ---------------------- functions ------------------------------
23
24/**
25 * Output all needed JavaScript
26 *
27 * @author Andreas Gohr <[email protected]>
28 */
29function js_out(){
30 global $conf;
31 global $lang;
32 global $config_cascade;
33
34 // The generated script depends on some dynamic options
35 $cache = getCacheName('scripts'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'],'.js');
36
37 // array of core files
38 $files = array(
39 DOKU_INC.'lib/scripts/helpers.js',
40 DOKU_INC.'lib/scripts/events.js',
41 DOKU_INC.'lib/scripts/delay.js',
42 DOKU_INC.'lib/scripts/cookie.js',
43 DOKU_INC.'lib/scripts/script.js',
44 DOKU_INC.'lib/scripts/tw-sack.js',
45 DOKU_INC.'lib/scripts/ajax.js',
46 DOKU_INC.'lib/scripts/index.js',
47 DOKU_INC.'lib/scripts/drag.js',
48 DOKU_INC.'lib/scripts/textselection.js',
49 DOKU_INC.'lib/scripts/toolbar.js',
50 DOKU_INC.'lib/scripts/edit.js',
51 DOKU_INC.'lib/scripts/locktimer.js',
52 DOKU_INC.'lib/scripts/linkwiz.js',
53 DOKU_INC.'lib/scripts/media.js',
54 DOKU_INC.'lib/scripts/subscriptions.js',
55# disabled for FS#1958 DOKU_INC.'lib/scripts/hotkeys.js',
56 DOKU_TPLINC.'script.js',
57 );
58
59 // add possible plugin scripts and userscript
60 $files = array_merge($files,js_pluginscripts());
61 if(isset($config_cascade['userscript']['default'])){
62 $files[] = $config_cascade['userscript']['default'];
63 }
64
65 // check cache age & handle conditional request
66 header('Cache-Control: public, max-age=3600');
67 header('Pragma: public');
68 if(js_cacheok($cache,$files)){
69 http_conditionalRequest(filemtime($cache));
70 if($conf['allowdebug']) header("X-CacheUsed: $cache");
71
72 // finally send output
73 if ($conf['gzip_output'] && http_gzip_valid($cache)) {
74 header('Vary: Accept-Encoding');
75 header('Content-Encoding: gzip');
76 readfile($cache.".gz");
77 } else {
78 if (!http_sendfile($cache)) readfile($cache);
79 }
80 return;
81 } else {
82 http_conditionalRequest(time());
83 }
84
85 // start output buffering and build the script
86 ob_start();
87
88 // add some global variables
89 print "var DOKU_BASE = '".DOKU_BASE."';";
90 print "var DOKU_TPL = '".DOKU_TPL."';";
91 print "var DOKU_UHN = ".((int) useHeading('navigation')).";";
92 print "var DOKU_UHC = ".((int) useHeading('content')).";";
93
94 // load JS specific translations
95 $json = new JSON();
96 $lang['js']['plugins'] = js_pluginstrings();
97 echo 'LANG = '.$json->encode($lang['js']).";\n";
98
99 // load toolbar
100 toolbar_JSdefines('toolbar');
101
102 // load files
103 foreach($files as $file){
104 echo "\n\n/* XXXXXXXXXX begin of ".str_replace(DOKU_INC, '', $file) ." XXXXXXXXXX */\n\n";
105 js_load($file);
106 echo "\n\n/* XXXXXXXXXX end of " . str_replace(DOKU_INC, '', $file) . " XXXXXXXXXX */\n\n";
107 }
108
109
110 // init stuff
111 js_runonstart("addEvent(document,'click',closePopups)");
112 js_runonstart('addTocToggle()');
113 js_runonstart("initSizeCtl('size__ctl','wiki__text')");
114 js_runonstart("initToolbar('tool__bar','wiki__text',toolbar)");
115 if($conf['locktime'] != 0){
116 js_runonstart("locktimer.init(".($conf['locktime'] - 60).",'".js_escape($lang['willexpire'])."',".$conf['usedraft'].", 'wiki__text')");
117 }
118 js_runonstart('scrollToMarker()');
119 js_runonstart('focusMarker()');
120 // init hotkeys - must have been done after init of toolbar
121# disabled for FS#1958 js_runonstart('initializeHotkeys()');
122
123 // end output buffering and get contents
124 $js = ob_get_contents();
125 ob_end_clean();
126
127 // compress whitespace and comments
128 if($conf['compress']){
129 $js = js_compress($js);
130 }
131
132 $js .= "\n"; // https://bugzilla.mozilla.org/show_bug.cgi?id=316033
133
134 // save cache file
135 io_saveFile($cache,$js);
136 if(function_exists('gzopen')) io_saveFile("$cache.gz",$js);
137
138 // finally send output
139 if ($conf['gzip_output']) {
140 header('Vary: Accept-Encoding');
141 header('Content-Encoding: gzip');
142 print gzencode($js,9,FORCE_GZIP);
143 } else {
144 print $js;
145 }
146}
147
148/**
149 * Load the given file, handle include calls and print it
150 *
151 * @author Andreas Gohr <[email protected]>
152 */
153function js_load($file){
154 if(!@file_exists($file)) return;
155 static $loaded = array();
156
157 $data = io_readFile($file);
158 while(preg_match('#/\*\s*DOKUWIKI:include(_once)?\s+([\w\.\-_/]+)\s*\*/#',$data,$match)){
159 $ifile = $match[2];
160
161 // is it a include_once?
162 if($match[1]){
163 $base = basename($ifile);
164 if($loaded[$base]) continue;
165 $loaded[$base] = true;
166 }
167
168 if($ifile{0} != '/') $ifile = dirname($file).'/'.$ifile;
169
170 if(@file_exists($ifile)){
171 $idata = io_readFile($ifile);
172 }else{
173 $idata = '';
174 }
175 $data = str_replace($match[0],$idata,$data);
176 }
177 echo $data;
178}
179
180/**
181 * Checks if a JavaScript Cache file still is valid
182 *
183 * @author Andreas Gohr <[email protected]>
184 */
185function js_cacheok($cache,$files){
186 if(isset($_REQUEST['purge'])) return false; //support purge request
187
188 $ctime = @filemtime($cache);
189 if(!$ctime) return false; //There is no cache
190
191 global $config_cascade;
192
193 // some additional files to check
194 $files = array_merge($files, getConfigFiles('main'));
195 $files[] = $config_cascade['userscript']['default'];
196 $files[] = __FILE__;
197
198 // now walk the files
199 foreach($files as $file){
200 if(@filemtime($file) > $ctime){
201 return false;
202 }
203 }
204 return true;
205}
206
207/**
208 * Returns a list of possible Plugin Scripts (no existance check here)
209 *
210 * @author Andreas Gohr <[email protected]>
211 */
212function js_pluginscripts(){
213 $list = array();
214 $plugins = plugin_list();
215 foreach ($plugins as $p){
216 $list[] = DOKU_PLUGIN."$p/script.js";
217 }
218 return $list;
219}
220
221/**
222 * Return an two-dimensional array with strings from the language file of each plugin.
223 *
224 * - $lang['js'] must be an array.
225 * - Nothing is returned for plugins without an entry for $lang['js']
226 *
227 * @author Gabriel Birke <[email protected]>
228 */
229function js_pluginstrings()
230{
231 global $conf;
232 $pluginstrings = array();
233 $plugins = plugin_list();
234 foreach ($plugins as $p){
235 if (isset($lang)) unset($lang);
236 if (@file_exists(DOKU_PLUGIN."$p/lang/en/lang.php")) {
237 include DOKU_PLUGIN."$p/lang/en/lang.php";
238 }
239 if (isset($conf['lang']) && $conf['lang']!='en' && @file_exists(DOKU_PLUGIN."$p/lang/".$conf['lang']."/lang.php")) {
240 include DOKU_PLUGIN."$p/lang/".$conf['lang']."/lang.php";
241 }
242 if (isset($lang['js'])) {
243 $pluginstrings[$p] = $lang['js'];
244 }
245 }
246 return $pluginstrings;
247}
248
249/**
250 * Escapes a String to be embedded in a JavaScript call, keeps \n
251 * as newline
252 *
253 * @author Andreas Gohr <[email protected]>
254 */
255function js_escape($string){
256 return str_replace('\\\\n','\\n',addslashes($string));
257}
258
259/**
260 * Adds the given JavaScript code to the window.onload() event
261 *
262 * @author Andreas Gohr <[email protected]>
263 */
264function js_runonstart($func){
265 echo "addInitEvent(function(){ $func; });".NL;
266}
267
268/**
269 * Strip comments and whitespaces from given JavaScript Code
270 *
271 * This is a port of Nick Galbreath's python tool jsstrip.py which is
272 * released under BSD license. See link for original code.
273 *
274 * @author Nick Galbreath <[email protected]>
275 * @author Andreas Gohr <[email protected]>
276 * @link http://code.google.com/p/jsstrip/
277 */
278function js_compress($s){
279 $s = ltrim($s); // strip all initial whitespace
280 $s .= "\n";
281 $i = 0; // char index for input string
282 $j = 0; // char forward index for input string
283 $line = 0; // line number of file (close to it anyways)
284 $slen = strlen($s); // size of input string
285 $lch = ''; // last char added
286 $result = ''; // we store the final result here
287
288 // items that don't need spaces next to them
289 $chars = "^&|!+\-*\/%=\?:;,{}()<>% \t\n\r'\"[]";
290
291 $regex_starters = array("(", "=", "[", "," , ":");
292
293 $whitespaces_chars = array(" ", "\t", "\n", "\r", "\0", "\x0B");
294
295 while($i < $slen){
296 // skip all "boring" characters. This is either
297 // reserved word (e.g. "for", "else", "if") or a
298 // variable/object/method (e.g. "foo.color")
299 while ($i < $slen && (strpos($chars,$s[$i]) === false) ){
300 $result .= $s{$i};
301 $i = $i + 1;
302 }
303
304 $ch = $s{$i};
305 // multiline comments (keeping IE conditionals)
306 if($ch == '/' && $s{$i+1} == '*' && $s{$i+2} != '@'){
307 $endC = strpos($s,'*/',$i+2);
308 if($endC === false) trigger_error('Found invalid /*..*/ comment', E_USER_ERROR);
309 $i = $endC + 2;
310 continue;
311 }
312
313 // singleline
314 if($ch == '/' && $s{$i+1} == '/'){
315 $endC = strpos($s,"\n",$i+2);
316 if($endC === false) trigger_error('Invalid comment', E_USER_ERROR);
317 $i = $endC;
318 continue;
319 }
320
321 // tricky. might be an RE
322 if($ch == '/'){
323 // rewind, skip white space
324 $j = 1;
325 while(in_array($s{$i-$j}, $whitespaces_chars)){
326 $j = $j + 1;
327 }
328 if( in_array($s{$i-$j}, $regex_starters) ){
329 // yes, this is an re
330 // now move forward and find the end of it
331 $j = 1;
332 while($s{$i+$j} != '/'){
333 while( ($s{$i+$j} != '\\') && ($s{$i+$j} != '/')){
334 $j = $j + 1;
335 }
336 if($s{$i+$j} == '\\') $j = $j + 2;
337 }
338 $result .= substr($s,$i,$j+1);
339 $i = $i + $j + 1;
340 continue;
341 }
342 }
343
344 // double quote strings
345 if($ch == '"'){
346 $j = 1;
347 while( $s{$i+$j} != '"' && ($i+$j < $slen)){
348 if( $s{$i+$j} == '\\' && ($s{$i+$j+1} == '"' || $s{$i+$j+1} == '\\') ){
349 $j += 2;
350 }else{
351 $j += 1;
352 }
353 }
354 $result .= substr($s,$i,$j+1);
355 $i = $i + $j + 1;
356 continue;
357 }
358
359 // single quote strings
360 if($ch == "'"){
361 $j = 1;
362 while( $s{$i+$j} != "'" && ($i+$j < $slen)){
363 if( $s{$i+$j} == '\\' && ($s{$i+$j+1} == "'" || $s{$i+$j+1} == '\\') ){
364 $j += 2;
365 }else{
366 $j += 1;
367 }
368 }
369 $result .= substr($s,$i,$j+1);
370 $i = $i + $j + 1;
371 continue;
372 }
373
374 // whitespaces
375 if( $ch == ' ' || $ch == "\r" || $ch == "\n" || $ch == "\t" ){
376 // leading spaces
377 if($i+1 < $slen && (strpos($chars,$s[$i+1]) !== false)){
378 $i = $i + 1;
379 continue;
380 }
381 // trailing spaces
382 // if this ch is space AND the last char processed
383 // is special, then skip the space
384 $lch = substr($result,-1);
385 if($lch && (strpos($chars,$lch) !== false)){
386 $i = $i + 1;
387 continue;
388 }
389 // else after all of this convert the "whitespace" to
390 // a single space. It will get appended below
391 $ch = ' ';
392 }
393
394 // other chars
395 $result .= $ch;
396 $i = $i + 1;
397 }
398
399 return trim($result);
400}
401
402//Setup VIM: ex: et ts=4 :
Note: See TracBrowser for help on using the repository browser.