Ultimate FAQ - Version 1.6.8

Version Description

  • Fixed a conflict with other plugins that use CSSTidy for CSS sanitization
  • Added the ability to link to the search shortcode with a term preloaded
Download this release

Release Info

Developer Rustaurius
Plugin Icon 128x128 Ultimate FAQ
Version 1.6.8
Comparing to
See all releases

Code changes from version 1.6.7 to 1.6.8

Functions/Full_Upgrade.php CHANGED
@@ -18,6 +18,9 @@ function EWD_UFAQ_Upgrade_To_Full() {
18
  $context = stream_context_create($opts);
19
  $Response = unserialize(file_get_contents("http://www.etoilewebdesign.com/UPCP-Key-Check/Register_Trial.php?Plugin=UFAQ&Admin_Email=" . $Admin_Email . "&Site=" . get_bloginfo('wpurl'), false, $context));
20
  }
 
 
 
21
  elseif ($Key != "EWD Trial") {
22
  $opts = array('http'=>array('method'=>"GET"));
23
  $context = stream_context_create($opts);
18
  $context = stream_context_create($opts);
19
  $Response = unserialize(file_get_contents("http://www.etoilewebdesign.com/UPCP-Key-Check/Register_Trial.php?Plugin=UFAQ&Admin_Email=" . $Admin_Email . "&Site=" . get_bloginfo('wpurl'), false, $context));
20
  }
21
+ elseif (strlen($Key) < 18 or strlen($Key) > 22) {
22
+ $ewd_ufaq_message = array("Message_Type" => "Error", "Message" => 'Invalid Product Key');
23
+ }
24
  elseif ($Key != "EWD Trial") {
25
  $opts = array('http'=>array('method'=>"GET"));
26
  $context = stream_context_create($opts);
Functions/Update_Admin_Databases.php CHANGED
@@ -44,6 +44,7 @@ function EWD_UFAQ_UpdateOptions() {
44
 
45
  if (isset($_POST['display_style']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_Display_Style', sanitize_text_field($_POST['display_style']));}
46
  if (isset($_POST['color_block_shape']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_Color_Block_Shape', sanitize_text_field($_POST['color_block_shape']));}
 
47
  if (isset($_POST['faq_ratings']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_FAQ_Ratings', sanitize_text_field($_POST['faq_ratings']));}
48
  if (isset($_POST['woocommerce_faqs']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_WooCommerce_FAQs', sanitize_text_field($_POST['woocommerce_faqs']));}
49
  if (isset($_POST['use_product']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_Use_Product', sanitize_text_field($_POST['use_product']));}
44
 
45
  if (isset($_POST['display_style']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_Display_Style', sanitize_text_field($_POST['display_style']));}
46
  if (isset($_POST['color_block_shape']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_Color_Block_Shape', sanitize_text_field($_POST['color_block_shape']));}
47
+ if (isset($_POST['Options_Submit']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_FAQs_Per_Page', sanitize_text_field($_POST['faqs_per_page']));}
48
  if (isset($_POST['faq_ratings']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_FAQ_Ratings', sanitize_text_field($_POST['faq_ratings']));}
49
  if (isset($_POST['woocommerce_faqs']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_WooCommerce_FAQs', sanitize_text_field($_POST['woocommerce_faqs']));}
50
  if (isset($_POST['use_product']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_Use_Product', sanitize_text_field($_POST['use_product']));}
Main.php CHANGED
@@ -7,7 +7,7 @@ Author: Etoile Web Design
7
  Author URI: http://www.EtoileWebDesign.com/wordpress-plugins/
8
  Terms and Conditions: http://www.etoilewebdesign.com/plugin-terms-and-conditions/
9
  Text Domain: ultimate-faqs
10
- Version: 1.6.7
11
  */
12
 
13
  global $ewd_ufaq_message;
7
  Author URI: http://www.EtoileWebDesign.com/wordpress-plugins/
8
  Terms and Conditions: http://www.etoilewebdesign.com/plugin-terms-and-conditions/
9
  Text Domain: ultimate-faqs
10
+ Version: 1.6.8
11
  */
12
 
13
  global $ewd_ufaq_message;
Shortcodes/Display_FAQ_Search.php CHANGED
@@ -52,7 +52,7 @@ function UFAQ_AJAX_Search($atts) {
52
  $ReturnString .= "<input type='hidden' name='order' value='" . $order . "' id='ufaq-order' />";
53
  $ReturnString .= "<input type='hidden' name='post_count' value='" . $post_count . "' id='ufaq-post-count' />";
54
  $ReturnString .= "<input type='hidden' name='current_url' value='" . $_SERVER['REQUEST_URI'] . "' id='ufaq-current-url' />";
55
- $ReturnString .= "<input type='text' id='ufaq-ajax-text-input' class='ufaq-text-input' name='Question ' placeholder='" . $Enter_Question_Label . "...'>";
56
  $ReturnString .= "</div>";
57
  if ($Auto_Complete_Titles != "Yes" and $show_on_load == "No") {$ReturnString .= "<label for='Submit'></label><input type='button' id='ufaq-ajax-search-btn' class='ewd-otp-submit pure-button pure-button-primary' name='Search' value='" . $Search_Label . "'>";}
58
  $ReturnString .= "</form>";
52
  $ReturnString .= "<input type='hidden' name='order' value='" . $order . "' id='ufaq-order' />";
53
  $ReturnString .= "<input type='hidden' name='post_count' value='" . $post_count . "' id='ufaq-post-count' />";
54
  $ReturnString .= "<input type='hidden' name='current_url' value='" . $_SERVER['REQUEST_URI'] . "' id='ufaq-current-url' />";
55
+ $ReturnString .= "<input type='text' id='ufaq-ajax-text-input' class='ufaq-text-input' name='Question ' placeholder='" . $Enter_Question_Label . "...' value='" . (isset($_GET['faq_search_term']) ? esc_attr($_GET['faq_search_term']) : '') . "'>";
56
  $ReturnString .= "</div>";
57
  if ($Auto_Complete_Titles != "Yes" and $show_on_load == "No") {$ReturnString .= "<label for='Submit'></label><input type='button' id='ufaq-ajax-search-btn' class='ewd-otp-submit pure-button pure-button-primary' name='Search' value='" . $Search_Label . "'>";}
58
  $ReturnString .= "</form>";
css/CSSTidy/class.csstidy.php CHANGED
@@ -58,942 +58,944 @@ require('class.csstidy_optimise.php');
58
  * @author Florian Schmitz (floele at gmail dot com) 2005-2006
59
  * @version 1.3
60
  */
61
- class csstidy {
62
-
63
- /**
64
- * Saves the parsed CSS
65
- * @var array
66
- * @access public
67
- */
68
- var $css = array();
69
-
70
- /**
71
- * Saves the parsed CSS (raw)
72
- * @var array
73
- * @access private
74
- */
75
- var $tokens = array();
76
-
77
- /**
78
- * Printer class
79
- * @see csstidy_print
80
- * @var object
81
- * @access public
82
- */
83
- var $print;
84
-
85
- /**
86
- * Optimiser class
87
- * @see csstidy_optimise
88
- * @var object
89
- * @access private
90
- */
91
- var $optimise;
92
-
93
- /**
94
- * Saves the CSS charset (@charset)
95
- * @var string
96
- * @access private
97
- */
98
- var $charset = '';
99
-
100
- /**
101
- * Saves all @import URLs
102
- * @var array
103
- * @access private
104
- */
105
- var $import = array();
106
-
107
- /**
108
- * Saves the namespace
109
- * @var string
110
- * @access private
111
- */
112
- var $namespace = '';
113
-
114
- /**
115
- * Contains the version of csstidy
116
- * @var string
117
- * @access private
118
- */
119
- var $version = '1.3';
120
-
121
- /**
122
- * Stores the settings
123
- * @var array
124
- * @access private
125
- */
126
- var $settings = array();
127
-
128
- /**
129
- * Saves the parser-status.
130
- *
131
- * Possible values:
132
- * - is = in selector
133
- * - ip = in property
134
- * - iv = in value
135
- * - instr = in string (started at " or ' or ( )
136
- * - ic = in comment (ignore everything)
137
- * - at = in @-block
138
- *
139
- * @var string
140
- * @access private
141
- */
142
- var $status = 'is';
143
-
144
-
145
- /**
146
- * Saves the current at rule (@media)
147
- * @var string
148
- * @access private
149
- */
150
- var $at = '';
151
-
152
- /**
153
- * Saves the current selector
154
- * @var string
155
- * @access private
156
- */
157
- var $selector = '';
158
-
159
- /**
160
- * Saves the current property
161
- * @var string
162
- * @access private
163
- */
164
- var $property = '';
165
-
166
- /**
167
- * Saves the position of , in selectors
168
- * @var array
169
- * @access private
170
- */
171
- var $sel_separate = array();
172
-
173
- /**
174
- * Saves the current value
175
- * @var string
176
- * @access private
177
- */
178
- var $value = '';
179
-
180
- /**
181
- * Saves the current sub-value
182
- *
183
- * Example for a subvalue:
184
- * background:url(foo.png) red no-repeat;
185
- * "url(foo.png)", "red", and "no-repeat" are subvalues,
186
- * seperated by whitespace
187
- * @var string
188
- * @access private
189
- */
190
- var $sub_value = '';
191
-
192
- /**
193
- * Array which saves all subvalues for a property.
194
- * @var array
195
- * @see sub_value
196
- * @access private
197
- */
198
- var $sub_value_arr = array();
199
-
200
- /**
201
- * Saves the char which opened the last string
202
- * @var string
203
- * @access private
204
- */
205
- var $str_char = '';
206
- var $cur_string = '';
207
-
208
- /**
209
- * Status from which the parser switched to ic or instr
210
- * @var string
211
- * @access private
212
- */
213
- var $from = '';
214
-
215
- /**
216
- * Variable needed to manage string-in-strings, for example url("foo.png")
217
- * @var string
218
- * @access private
219
- */
220
- var $str_in_str = false;
221
-
222
- /**
223
- * =true if in invalid at-rule
224
- * @var bool
225
- * @access private
226
- */
227
- var $invalid_at = false;
228
-
229
- /**
230
- * =true if something has been added to the current selector
231
- * @var bool
232
- * @access private
233
- */
234
- var $added = false;
235
-
236
- /**
237
- * Array which saves the message log
238
- * @var array
239
- * @access private
240
- */
241
- var $log = array();
242
-
243
- /**
244
- * Saves the line number
245
- * @var integer
246
- * @access private
247
- */
248
- var $line = 1;
249
-
250
- /**
251
- * Loads standard template and sets default settings
252
- * @access private
253
- * @version 1.3
254
- */
255
- function __construct()
256
- {
257
- $this->settings['remove_bslash'] = true;
258
- $this->settings['compress_colors'] = true;
259
- $this->settings['compress_font-weight'] = true;
260
- $this->settings['lowercase_s'] = false;
261
- $this->settings['optimise_shorthands'] = 1;
262
- $this->settings['remove_last_;'] = false;
263
- $this->settings['case_properties'] = 1;
264
- $this->settings['sort_properties'] = false;
265
- $this->settings['sort_selectors'] = false;
266
- $this->settings['merge_selectors'] = 2;
267
- $this->settings['discard_invalid_properties'] = false;
268
- $this->settings['css_level'] = 'CSS2.1';
269
- $this->settings['preserve_css'] = false;
270
- $this->settings['timestamp'] = false;
271
-
272
- $this->load_template('default');
273
- $this->print = new csstidy_print($this);
274
- $this->optimise = new csstidy_optimise($this);
275
- }
276
-
277
- /**
278
- * Get the value of a setting.
279
- * @param string $setting
280
- * @access public
281
- * @return mixed
282
- * @version 1.0
283
- */
284
- function get_cfg($setting)
285
- {
286
- if(isset($this->settings[$setting]))
287
- {
288
- return $this->settings[$setting];
289
- }
290
- return false;
291
- }
292
-
293
- /**
294
- * Set the value of a setting.
295
- * @param string $setting
296
- * @param mixed $value
297
- * @access public
298
- * @return bool
299
- * @version 1.0
300
- */
301
- function set_cfg($setting,$value)
302
- {
303
- if(isset($this->settings[$setting]) && $value !== '')
304
- {
305
- $this->settings[$setting] = $value;
306
- return true;
307
- }
308
- return false;
309
- }
310
-
311
- /**
312
- * Adds a token to $this->tokens
313
- * @param mixed $type
314
- * @param string $data
315
- * @param bool $do add a token even if preserve_css is off
316
- * @access private
317
- * @version 1.0
318
- */
319
- function _add_token($type, $data, $do = false) {
320
- if($this->get_cfg('preserve_css') || $do) {
321
- $this->tokens[] = array($type, ($type == COMMENT) ? $data : trim($data));
322
  }
323
- }
324
-
325
- /**
326
- * Add a message to the message log
327
- * @param string $message
328
- * @param string $type
329
- * @param integer $line
330
- * @access private
331
- * @version 1.0
332
- */
333
- function log($message,$type,$line = -1)
334
- {
335
- if($line === -1)
336
- {
337
- $line = $this->line;
338
- }
339
- $line = intval($line);
340
- $add = array('m' => $message, 't' => $type);
341
- if(!isset($this->log[$line]) || !in_array($add,$this->log[$line]))
342
- {
343
- $this->log[$line][] = $add;
344
- }
345
- }
346
-
347
- /**
348
- * Parse unicode notations and find a replacement character
349
- * @param string $string
350
- * @param integer $i
351
- * @access private
352
- * @return string
353
- * @version 1.2
354
- */
355
- function _unicode(&$string, &$i)
356
- {
357
- ++$i;
358
- $add = '';
359
- $tokens =& $GLOBALS['csstidy']['tokens'];
360
- $replaced = false;
361
-
362
- while($i < strlen($string) && (ctype_xdigit($string{$i}) || ctype_space($string{$i})) && strlen($add) < 6)
363
- {
364
- $add .= $string{$i};
365
-
366
- if(ctype_space($string{$i})) {
367
- break;
368
- }
369
- $i++;
370
- }
371
-
372
- if(hexdec($add) > 47 && hexdec($add) < 58 || hexdec($add) > 64 && hexdec($add) < 91 || hexdec($add) > 96 && hexdec($add) < 123)
373
- {
374
- $this->log('Replaced unicode notation: Changed \\'. $add .' to ' . chr(hexdec($add)),'Information');
375
- $add = chr(hexdec($add));
376
- $replaced = true;
377
- }
378
- else {
379
- $add = trim('\\'.$add);
380
- }
381
-
382
- if(@ctype_xdigit($string{$i+1}) && ctype_space($string{$i})
383
- && !$replaced || !ctype_space($string{$i})) {
384
- $i--;
385
- }
386
-
387
- if($add != '\\' || !$this->get_cfg('remove_bslash') || strpos($tokens, $string{$i+1}) !== false) {
388
- return $add;
389
- }
390
-
391
- if($add == '\\') {
392
- $this->log('Removed unnecessary backslash','Information');
393
- }
394
- return '';
395
- }
396
-
397
- /**
398
- * Loads a new template
399
- * @param string $content either filename (if $from_file == true), content of a template file, "high_compression", "highest_compression", "low_compression", or "default"
400
- * @param bool $from_file uses $content as filename if true
401
- * @access public
402
- * @version 1.1
403
- * @see http://csstidy.sourceforge.net/templates.php
404
- */
405
- function load_template($content, $from_file=true)
406
- {
407
- $predefined_templates =& $GLOBALS['csstidy']['predefined_templates'];
408
- if($content == 'high_compression' || $content == 'default' || $content == 'highest_compression' || $content == 'low_compression')
409
- {
410
- $this->template = $predefined_templates[$content];
411
- return;
412
- }
413
-
414
- if($from_file)
415
- {
416
- $content = strip_tags(file_get_contents($content),'<span>');
417
- }
418
- $content = str_replace("\r\n","\n",$content); // Unify newlines (because the output also only uses \n)
419
- $template = explode('|',$content);
420
-
421
- for ($i = 0; $i < count($template); $i++ )
422
- {
423
- $this->template[$i] = $template[$i];
424
- }
425
- }
426
-
427
- /**
428
- * Starts parsing from URL
429
- * @param string $url
430
- * @access public
431
- * @version 1.0
432
- */
433
- function parse_from_url($url)
434
- {
435
- return $this->parse(@file_get_contents($url));
436
- }
437
-
438
- /**
439
- * Checks if there is a token at the current position
440
- * @param string $string
441
- * @param integer $i
442
- * @access public
443
- * @version 1.11
444
- */
445
- function is_token(&$string, $i)
446
- {
447
- $tokens =& $GLOBALS['csstidy']['tokens'];
448
- return (strpos($tokens, $string{$i}) !== false && !csstidy::escaped($string,$i));
449
- }
450
-
451
-
452
- /**
453
- * Parses CSS in $string. The code is saved as array in $this->css
454
- * @param string $string the CSS code
455
- * @access public
456
- * @return bool
457
- * @version 1.1
458
- */
459
- function parse($string) {
460
- // PHP bug? Settings need to be refreshed in PHP4
461
- $this->print = new csstidy_print($this);
462
- $this->optimise = new csstidy_optimise($this);
463
-
464
- $all_properties =& $GLOBALS['csstidy']['all_properties'];
465
- $at_rules =& $GLOBALS['csstidy']['at_rules'];
466
-
467
- $this->css = array();
468
- $this->print->input_css = $string;
469
- $string = str_replace("\r\n","\n",$string) . ' ';
470
- $cur_comment = '';
471
-
472
- for ($i = 0, $size = strlen($string); $i < $size; $i++ )
473
  {
474
- if($string{$i} == "\n" || $string{$i} == "\r")
475
- {
476
- ++$this->line;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
477
  }
478
-
479
- switch($this->status)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480
  {
481
- /* Case in at-block */
482
- case 'at':
483
- if(csstidy::is_token($string,$i))
484
  {
485
- if($string{$i} == '/' && @$string{$i+1} == '*')
486
- {
487
- $this->status = 'ic'; ++$i;
488
- $this->from = 'at';
489
- }
490
- elseif($string{$i} == '{')
491
- {
492
- $this->status = 'is';
493
- $this->_add_token(AT_START, $this->at);
494
- }
495
- elseif($string{$i} == ',')
496
- {
497
- $this->at = trim($this->at).',';
498
- }
499
- elseif($string{$i} == '\\')
500
- {
501
- $this->at .= $this->_unicode($string,$i);
502
- }
503
  }
504
- else
 
505
  {
506
- $lastpos = strlen($this->at)-1;
507
- if(!( (ctype_space($this->at{$lastpos}) || csstidy::is_token($this->at,$lastpos) && $this->at{$lastpos} == ',') && ctype_space($string{$i})))
 
508
  {
509
- $this->at .= $string{$i};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
510
  }
511
- }
512
- break;
513
-
514
- /* Case in-selector */
515
- case 'is':
516
- if(csstidy::is_token($string,$i))
517
- {
518
- if($string{$i} == '/' && @$string{$i+1} == '*' && trim($this->selector) == '')
519
  {
520
- $this->status = 'ic'; ++$i;
521
- $this->from = 'is';
 
 
 
522
  }
523
- elseif($string{$i} == '@' && trim($this->selector) == '')
 
 
 
 
524
  {
525
- // Check for at-rule
526
- $this->invalid_at = true;
527
- foreach($at_rules as $name => $type)
528
  {
529
- if(!strcasecmp(substr($string,$i+1,strlen($name)),$name))
530
- {
531
- ($type == 'at') ? $this->at = '@'.$name : $this->selector = '@'.$name;
532
- $this->status = $type;
533
- $i += strlen($name);
534
- $this->invalid_at = false;
535
- }
536
  }
537
-
538
- if($this->invalid_at)
539
  {
540
- $this->selector = '@';
541
- $invalid_at_name = '';
542
- for($j = $i+1; $j < $size; ++$j)
 
 
 
 
 
 
 
 
 
 
 
543
  {
544
- if(!ctype_alpha($string{$j}))
 
 
545
  {
546
- break;
 
 
 
 
547
  }
548
- $invalid_at_name .= $string{$j};
549
  }
550
- $this->log('Invalid @-rule: '.$invalid_at_name.' (removed)','Warning');
551
  }
552
- }
553
- elseif(($string{$i} == '"' || $string{$i} == "'"))
554
- {
555
- $this->cur_string = $string{$i};
556
- $this->status = 'instr';
557
- $this->str_char = $string{$i};
558
- $this->from = 'is';
559
- }
560
- elseif($this->invalid_at && $string{$i} == ';')
561
- {
562
- $this->invalid_at = false;
563
- $this->status = 'is';
564
- }
565
- elseif($string{$i} == '{')
566
- {
567
- $this->status = 'ip';
568
- $this->_add_token(SEL_START, $this->selector);
569
- $this->added = false;
570
- }
571
- elseif($string{$i} == '}')
572
- {
573
- $this->_add_token(AT_END, $this->at);
574
- $this->at = '';
575
- $this->selector = '';
576
- $this->sel_separate = array();
577
- }
578
- elseif($string{$i} == ',')
579
- {
580
- $this->selector = trim($this->selector).',';
581
- $this->sel_separate[] = strlen($this->selector);
582
- }
583
- elseif($string{$i} == '\\')
584
- {
585
- $this->selector .= $this->_unicode($string,$i);
586
- }
587
- // remove unnecessary universal selector, FS#147
588
- else if(!($string{$i} == '*' && @in_array($string{$i+1}, array('.', '#', '[', ':')))) {
589
- $this->selector .= $string{$i};
590
- }
591
- }
592
- else
593
- {
594
- $lastpos = strlen($this->selector)-1;
595
- if($lastpos == -1 || !( (ctype_space($this->selector{$lastpos}) || csstidy::is_token($this->selector,$lastpos) && $this->selector{$lastpos} == ',') && ctype_space($string{$i})))
596
- {
597
- $this->selector .= $string{$i};
598
- }
599
- }
600
- break;
601
-
602
- /* Case in-property */
603
- case 'ip':
604
- if(csstidy::is_token($string,$i))
605
- {
606
- if(($string{$i} == ':' || $string{$i} == '=') && $this->property != '')
607
- {
608
- $this->status = 'iv';
609
- if(!$this->get_cfg('discard_invalid_properties') || csstidy::property_is_valid($this->property)) {
610
- $this->_add_token(PROPERTY, $this->property);
611
  }
612
  }
613
- elseif($string{$i} == '/' && @$string{$i+1} == '*' && $this->property == '')
614
- {
615
- $this->status = 'ic'; ++$i;
616
- $this->from = 'ip';
617
- }
618
- elseif($string{$i} == '}')
619
- {
620
- $this->explode_selectors();
621
- $this->status = 'is';
622
- $this->invalid_at = false;
623
- $this->_add_token(SEL_END, $this->selector);
624
- $this->selector = '';
625
- $this->property = '';
626
- }
627
- elseif($string{$i} == ';')
628
- {
629
- $this->property = '';
630
- }
631
- elseif($string{$i} == '\\')
632
- {
633
- $this->property .= $this->_unicode($string,$i);
634
- }
635
- }
636
- elseif(!ctype_space($string{$i}))
637
- {
638
- $this->property .= $string{$i};
639
- }
640
- break;
641
-
642
- /* Case in-value */
643
- case 'iv':
644
- $pn = (($string{$i} == "\n" || $string{$i} == "\r") && $this->property_is_next($string,$i+1) || $i == strlen($string)-1);
645
- if(csstidy::is_token($string,$i) || $pn)
646
- {
647
- if($string{$i} == '/' && @$string{$i+1} == '*')
648
- {
649
- $this->status = 'ic'; ++$i;
650
- $this->from = 'iv';
651
- }
652
- elseif(($string{$i} == '"' || $string{$i} == "'" || $string{$i} == '('))
653
- {
654
- $this->cur_string = $string{$i};
655
- $this->str_char = ($string{$i} == '(') ? ')' : $string{$i};
656
- $this->status = 'instr';
657
- $this->from = 'iv';
658
- }
659
- elseif($string{$i} == ',')
660
- {
661
- $this->sub_value = trim($this->sub_value).',';
662
- }
663
- elseif($string{$i} == '\\')
664
  {
665
- $this->sub_value .= $this->_unicode($string,$i);
 
 
 
 
666
  }
667
- elseif($string{$i} == ';' || $pn)
 
 
 
 
668
  {
669
- if($this->selector{0} == '@' && isset($at_rules[substr($this->selector,1)]) && $at_rules[substr($this->selector,1)] == 'iv')
670
  {
671
- $this->sub_value_arr[] = trim($this->sub_value);
672
-
673
- $this->status = 'is';
674
-
675
- switch($this->selector)
676
- {
677
- case '@charset': $this->charset = $this->sub_value_arr[0]; break;
678
- case '@namespace': $this->namespace = implode(' ',$this->sub_value_arr); break;
679
- case '@import': $this->import[] = implode(' ',$this->sub_value_arr); break;
680
  }
681
-
682
- $this->sub_value_arr = array();
683
- $this->sub_value = '';
 
 
 
 
 
 
 
 
 
684
  $this->selector = '';
685
- $this->sel_separate = array();
686
  }
687
- else
688
  {
689
- $this->status = 'ip';
 
 
 
 
690
  }
691
  }
692
- elseif($string{$i} != '}')
693
  {
694
- $this->sub_value .= $string{$i};
695
- }
696
- if(($string{$i} == '}' || $string{$i} == ';' || $pn) && !empty($this->selector))
 
 
 
 
 
697
  {
698
- if($this->at == '')
699
  {
700
- $this->at = DEFAULT_AT;
 
701
  }
702
-
703
- // case settings
704
- if($this->get_cfg('lowercase_s'))
705
  {
706
- $this->selector = strtolower($this->selector);
 
 
 
707
  }
708
- $this->property = strtolower($this->property);
709
-
710
- $this->optimise->subvalue();
711
- if($this->sub_value != '') {
712
- $this->sub_value_arr[] = $this->sub_value;
713
- $this->sub_value = '';
714
  }
715
-
716
- $this->value = implode(' ',$this->sub_value_arr);
717
-
718
- $this->selector = trim($this->selector);
719
-
720
- $this->optimise->value();
721
-
722
- $valid = csstidy::property_is_valid($this->property);
723
- if((!$this->invalid_at || $this->get_cfg('preserve_css')) && (!$this->get_cfg('discard_invalid_properties') || $valid))
724
  {
725
- $this->css_add_property($this->at,$this->selector,$this->property,$this->value);
726
- $this->_add_token(VALUE, $this->value);
727
- $this->optimise->shorthands();
728
  }
729
- if(!$valid)
730
  {
731
- if($this->get_cfg('discard_invalid_properties'))
732
  {
733
- $this->log('Removed invalid property: '.$this->property,'Warning');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
734
  }
735
  else
736
  {
737
- $this->log('Invalid property in '.strtoupper($this->get_cfg('css_level')).': '.$this->property,'Warning');
738
  }
739
  }
740
-
741
- $this->property = '';
742
- $this->sub_value_arr = array();
743
- $this->value = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
744
  }
745
- if($string{$i} == '}')
746
  {
747
- $this->explode_selectors();
748
- $this->_add_token(SEL_END, $this->selector);
749
- $this->status = 'is';
750
- $this->invalid_at = false;
751
- $this->selector = '';
 
 
 
 
 
752
  }
753
- }
754
- elseif(!$pn)
755
- {
756
- $this->sub_value .= $string{$i};
757
-
758
- if(ctype_space($string{$i}))
759
  {
760
- $this->optimise->subvalue();
761
- if($this->sub_value != '') {
762
- $this->sub_value_arr[] = $this->sub_value;
763
- $this->sub_value = '';
764
- }
765
  }
766
- }
767
- break;
768
-
769
- /* Case in string */
770
- case 'instr':
771
- if($this->str_char == ')' && ($string{$i} == '"' || $string{$i} == '\'') && !$this->str_in_str && !csstidy::escaped($string,$i))
772
- {
773
- $this->str_in_str = true;
774
- }
775
- elseif($this->str_char == ')' && ($string{$i} == '"' || $string{$i} == '\'') && $this->str_in_str && !csstidy::escaped($string,$i))
776
- {
777
- $this->str_in_str = false;
778
- }
779
- $temp_add = $string{$i}; // ...and no not-escaped backslash at the previous position
780
- if( ($string{$i} == "\n" || $string{$i} == "\r") && !($string{$i-1} == '\\' && !csstidy::escaped($string,$i-1)) )
781
- {
782
- $temp_add = "\\A ";
783
- $this->log('Fixed incorrect newline in string','Warning');
784
- }
785
- if (!($this->str_char == ')' && in_array($string{$i}, $GLOBALS['csstidy']['whitespace']) && !$this->str_in_str)) {
786
- $this->cur_string .= $temp_add;
787
- }
788
- if($string{$i} == $this->str_char && !csstidy::escaped($string,$i) && !$this->str_in_str)
789
- {
790
- $this->status = $this->from;
791
- if (!preg_match('|[' . implode('', $GLOBALS['csstidy']['whitespace']) . ']|uis', $this->cur_string) && $this->property != 'content') {
792
- if ($this->str_char == '"' || $this->str_char == '\'') {
793
- $this->cur_string = substr($this->cur_string, 1, -1);
794
- } else if (strlen($this->cur_string) > 3 && ($this->cur_string[1] == '"' || $this->cur_string[1] == '\'')) /* () */ {
795
- $this->cur_string = $this->cur_string[0] . substr($this->cur_string, 2, -2) . substr($this->cur_string, -1);
796
- }
797
  }
798
- if($this->from == 'iv')
 
 
 
 
799
  {
800
- $this->sub_value .= $this->cur_string;
 
 
 
801
  }
802
- elseif($this->from == 'is')
803
  {
804
- $this->selector .= $this->cur_string;
805
  }
 
806
  }
807
- break;
808
-
809
- /* Case in-comment */
810
- case 'ic':
811
- if($string{$i} == '*' && $string{$i+1} == '/')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
812
  {
813
- $this->status = $this->from;
814
- $i++;
815
- $this->_add_token(COMMENT, $cur_comment);
816
- $cur_comment = '';
 
 
817
  }
818
- else
 
819
  {
820
- $cur_comment .= $string{$i};
 
 
 
 
821
  }
822
- break;
823
  }
 
824
  }
825
-
826
- $this->optimise->postparse();
827
-
828
- $this->print->_reset();
829
-
830
- return !(empty($this->css) && empty($this->import) && empty($this->charset) && empty($this->tokens) && empty($this->namespace));
831
- }
832
-
833
- /**
834
- * Explodes selectors
835
- * @access private
836
- * @version 1.0
837
- */
838
- function explode_selectors()
839
- {
840
- // Explode multiple selectors
841
- if($this->get_cfg('merge_selectors') == 1)
842
  {
843
- $new_sels = array();
844
- $lastpos = 0;
845
- $this->sel_separate[] = strlen($this->selector);
846
- foreach($this->sel_separate as $num => $pos)
847
- {
848
- if($num == count($this->sel_separate)-1) {
849
- $pos += 1;
850
- }
851
-
852
- $new_sels[] = substr($this->selector,$lastpos,$pos-$lastpos-1);
853
- $lastpos = $pos;
 
 
 
 
 
854
  }
855
-
856
- if(count($new_sels) > 1)
 
857
  {
858
- foreach($new_sels as $selector)
859
  {
860
- $this->merge_css_blocks($this->at,$selector,$this->css[$this->at][$this->selector]);
 
861
  }
862
- unset($this->css[$this->at][$this->selector]);
863
  }
864
- }
865
- $this->sel_separate = array();
866
- }
867
-
868
- /**
869
- * Checks if a character is escaped (and returns true if it is)
870
- * @param string $string
871
- * @param integer $pos
872
- * @access public
873
- * @return bool
874
- * @version 1.02
875
- */
876
- function escaped(&$string,$pos)
877
- {
878
- return !(@($string{$pos-1} != '\\') || csstidy::escaped($string,$pos-1));
879
- }
880
-
881
- /**
882
- * Adds a property with value to the existing CSS code
883
- * @param string $media
884
- * @param string $selector
885
- * @param string $property
886
- * @param string $new_val
887
- * @access private
888
- * @version 1.2
889
- */
890
- function css_add_property($media,$selector,$property,$new_val)
891
- {
892
- if($this->get_cfg('preserve_css') || trim($new_val) == '') {
893
- return;
894
- }
895
-
896
- $this->added = true;
897
- if(isset($this->css[$media][$selector][$property]))
898
- {
899
- if((csstidy::is_important($this->css[$media][$selector][$property]) && csstidy::is_important($new_val)) || !csstidy::is_important($this->css[$media][$selector][$property]))
900
  {
901
- unset($this->css[$media][$selector][$property]);
902
  $this->css[$media][$selector][$property] = trim($new_val);
903
  }
904
  }
905
- else
 
 
 
 
 
 
 
 
 
906
  {
907
- $this->css[$media][$selector][$property] = trim($new_val);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
908
  }
909
- }
910
-
911
- /**
912
- * Adds CSS to an existing media/selector
913
- * @param string $media
914
- * @param string $selector
915
- * @param array $css_add
916
- * @access private
917
- * @version 1.1
918
- */
919
- function merge_css_blocks($media,$selector,$css_add)
920
- {
921
- foreach($css_add as $property => $value)
922
- {
923
- $this->css_add_property($media,$selector,$property,$value,false);
924
- }
925
- }
926
-
927
- /**
928
- * Checks if $value is !important.
929
- * @param string $value
930
- * @return bool
931
- * @access public
932
- * @version 1.0
933
- */
934
- function is_important(&$value)
935
- {
936
- return (!strcasecmp(substr(str_replace($GLOBALS['csstidy']['whitespace'],'',$value),-10,10),'!important'));
937
- }
938
-
939
- /**
940
- * Returns a value without !important
941
- * @param string $value
942
- * @return string
943
- * @access public
944
- * @version 1.0
945
- */
946
- function gvw_important($value)
947
- {
948
- if(csstidy::is_important($value))
949
- {
950
- $value = trim($value);
951
- $value = substr($value,0,-9);
952
- $value = trim($value);
953
- $value = substr($value,0,-1);
954
- $value = trim($value);
955
- return $value;
956
- }
957
- return $value;
958
- }
959
-
960
- /**
961
- * Checks if the next word in a string from pos is a CSS property
962
- * @param string $istring
963
- * @param integer $pos
964
- * @return bool
965
- * @access private
966
- * @version 1.2
967
- */
968
- function property_is_next($istring, $pos)
969
- {
970
- $all_properties =& $GLOBALS['csstidy']['all_properties'];
971
- $istring = substr($istring,$pos,strlen($istring)-$pos);
972
- $pos = strpos($istring,':');
973
- if($pos === false)
974
- {
975
- return false;
976
- }
977
- $istring = strtolower(trim(substr($istring,0,$pos)));
978
- if(isset($all_properties[$istring]))
979
- {
980
- $this->log('Added semicolon to the end of declaration','Warning');
981
- return true;
982
- }
983
- return false;
984
- }
985
-
986
- /**
987
- * Checks if a property is valid
988
- * @param string $property
989
- * @return bool;
990
- * @access public
991
- * @version 1.0
992
- */
993
- function property_is_valid($property) {
994
- $all_properties =& $GLOBALS['csstidy']['all_properties'];
995
- return (isset($all_properties[$property]) && strpos($all_properties[$property],strtoupper($this->get_cfg('css_level'))) !== false );
996
- }
997
-
998
  }
999
  ?>
58
  * @author Florian Schmitz (floele at gmail dot com) 2005-2006
59
  * @version 1.3
60
  */
61
+ if (!class_exists('csstidy')) {
62
+ class csstidy {
63
+
64
+ /**
65
+ * Saves the parsed CSS
66
+ * @var array
67
+ * @access public
68
+ */
69
+ var $css = array();
70
+
71
+ /**
72
+ * Saves the parsed CSS (raw)
73
+ * @var array
74
+ * @access private
75
+ */
76
+ var $tokens = array();
77
+
78
+ /**
79
+ * Printer class
80
+ * @see csstidy_print
81
+ * @var object
82
+ * @access public
83
+ */
84
+ var $print;
85
+
86
+ /**
87
+ * Optimiser class
88
+ * @see csstidy_optimise
89
+ * @var object
90
+ * @access private
91
+ */
92
+ var $optimise;
93
+
94
+ /**
95
+ * Saves the CSS charset (@charset)
96
+ * @var string
97
+ * @access private
98
+ */
99
+ var $charset = '';
100
+
101
+ /**
102
+ * Saves all @import URLs
103
+ * @var array
104
+ * @access private
105
+ */
106
+ var $import = array();
107
+
108
+ /**
109
+ * Saves the namespace
110
+ * @var string
111
+ * @access private
112
+ */
113
+ var $namespace = '';
114
+
115
+ /**
116
+ * Contains the version of csstidy
117
+ * @var string
118
+ * @access private
119
+ */
120
+ var $version = '1.3';
121
+
122
+ /**
123
+ * Stores the settings
124
+ * @var array
125
+ * @access private
126
+ */
127
+ var $settings = array();
128
+
129
+ /**
130
+ * Saves the parser-status.
131
+ *
132
+ * Possible values:
133
+ * - is = in selector
134
+ * - ip = in property
135
+ * - iv = in value
136
+ * - instr = in string (started at " or ' or ( )
137
+ * - ic = in comment (ignore everything)
138
+ * - at = in @-block
139
+ *
140
+ * @var string
141
+ * @access private
142
+ */
143
+ var $status = 'is';
144
+
145
+
146
+ /**
147
+ * Saves the current at rule (@media)
148
+ * @var string
149
+ * @access private
150
+ */
151
+ var $at = '';
152
+
153
+ /**
154
+ * Saves the current selector
155
+ * @var string
156
+ * @access private
157
+ */
158
+ var $selector = '';
159
+
160
+ /**
161
+ * Saves the current property
162
+ * @var string
163
+ * @access private
164
+ */
165
+ var $property = '';
166
+
167
+ /**
168
+ * Saves the position of , in selectors
169
+ * @var array
170
+ * @access private
171
+ */
172
+ var $sel_separate = array();
173
+
174
+ /**
175
+ * Saves the current value
176
+ * @var string
177
+ * @access private
178
+ */
179
+ var $value = '';
180
+
181
+ /**
182
+ * Saves the current sub-value
183
+ *
184
+ * Example for a subvalue:
185
+ * background:url(foo.png) red no-repeat;
186
+ * "url(foo.png)", "red", and "no-repeat" are subvalues,
187
+ * seperated by whitespace
188
+ * @var string
189
+ * @access private
190
+ */
191
+ var $sub_value = '';
192
+
193
+ /**
194
+ * Array which saves all subvalues for a property.
195
+ * @var array
196
+ * @see sub_value
197
+ * @access private
198
+ */
199
+ var $sub_value_arr = array();
200
+
201
+ /**
202
+ * Saves the char which opened the last string
203
+ * @var string
204
+ * @access private
205
+ */
206
+ var $str_char = '';
207
+ var $cur_string = '';
208
+
209
+ /**
210
+ * Status from which the parser switched to ic or instr
211
+ * @var string
212
+ * @access private
213
+ */
214
+ var $from = '';
215
+
216
+ /**
217
+ * Variable needed to manage string-in-strings, for example url("foo.png")
218
+ * @var string
219
+ * @access private
220
+ */
221
+ var $str_in_str = false;
222
+
223
+ /**
224
+ * =true if in invalid at-rule
225
+ * @var bool
226
+ * @access private
227
+ */
228
+ var $invalid_at = false;
229
+
230
+ /**
231
+ * =true if something has been added to the current selector
232
+ * @var bool
233
+ * @access private
234
+ */
235
+ var $added = false;
236
+
237
+ /**
238
+ * Array which saves the message log
239
+ * @var array
240
+ * @access private
241
+ */
242
+ var $log = array();
243
+
244
+ /**
245
+ * Saves the line number
246
+ * @var integer
247
+ * @access private
248
+ */
249
+ var $line = 1;
250
+
251
+ /**
252
+ * Loads standard template and sets default settings
253
+ * @access private
254
+ * @version 1.3
255
+ */
256
+ function __construct()
257
+ {
258
+ $this->settings['remove_bslash'] = true;
259
+ $this->settings['compress_colors'] = true;
260
+ $this->settings['compress_font-weight'] = true;
261
+ $this->settings['lowercase_s'] = false;
262
+ $this->settings['optimise_shorthands'] = 1;
263
+ $this->settings['remove_last_;'] = false;
264
+ $this->settings['case_properties'] = 1;
265
+ $this->settings['sort_properties'] = false;
266
+ $this->settings['sort_selectors'] = false;
267
+ $this->settings['merge_selectors'] = 2;
268
+ $this->settings['discard_invalid_properties'] = false;
269
+ $this->settings['css_level'] = 'CSS2.1';
270
+ $this->settings['preserve_css'] = false;
271
+ $this->settings['timestamp'] = false;
272
+
273
+ $this->load_template('default');
274
+ $this->print = new csstidy_print($this);
275
+ $this->optimise = new csstidy_optimise($this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  }
277
+
278
+ /**
279
+ * Get the value of a setting.
280
+ * @param string $setting
281
+ * @access public
282
+ * @return mixed
283
+ * @version 1.0
284
+ */
285
+ function get_cfg($setting)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  {
287
+ if(isset($this->settings[$setting]))
288
+ {
289
+ return $this->settings[$setting];
290
+ }
291
+ return false;
292
+ }
293
+
294
+ /**
295
+ * Set the value of a setting.
296
+ * @param string $setting
297
+ * @param mixed $value
298
+ * @access public
299
+ * @return bool
300
+ * @version 1.0
301
+ */
302
+ function set_cfg($setting,$value)
303
+ {
304
+ if(isset($this->settings[$setting]) && $value !== '')
305
+ {
306
+ $this->settings[$setting] = $value;
307
+ return true;
308
+ }
309
+ return false;
310
+ }
311
+
312
+ /**
313
+ * Adds a token to $this->tokens
314
+ * @param mixed $type
315
+ * @param string $data
316
+ * @param bool $do add a token even if preserve_css is off
317
+ * @access private
318
+ * @version 1.0
319
+ */
320
+ function _add_token($type, $data, $do = false) {
321
+ if($this->get_cfg('preserve_css') || $do) {
322
+ $this->tokens[] = array($type, ($type == COMMENT) ? $data : trim($data));
323
  }
324
+ }
325
+
326
+ /**
327
+ * Add a message to the message log
328
+ * @param string $message
329
+ * @param string $type
330
+ * @param integer $line
331
+ * @access private
332
+ * @version 1.0
333
+ */
334
+ function log($message,$type,$line = -1)
335
+ {
336
+ if($line === -1)
337
+ {
338
+ $line = $this->line;
339
+ }
340
+ $line = intval($line);
341
+ $add = array('m' => $message, 't' => $type);
342
+ if(!isset($this->log[$line]) || !in_array($add,$this->log[$line]))
343
+ {
344
+ $this->log[$line][] = $add;
345
+ }
346
+ }
347
+
348
+ /**
349
+ * Parse unicode notations and find a replacement character
350
+ * @param string $string
351
+ * @param integer $i
352
+ * @access private
353
+ * @return string
354
+ * @version 1.2
355
+ */
356
+ function _unicode(&$string, &$i)
357
+ {
358
+ ++$i;
359
+ $add = '';
360
+ $tokens =& $GLOBALS['csstidy']['tokens'];
361
+ $replaced = false;
362
+
363
+ while($i < strlen($string) && (ctype_xdigit($string{$i}) || ctype_space($string{$i})) && strlen($add) < 6)
364
+ {
365
+ $add .= $string{$i};
366
+
367
+ if(ctype_space($string{$i})) {
368
+ break;
369
+ }
370
+ $i++;
371
+ }
372
+
373
+ if(hexdec($add) > 47 && hexdec($add) < 58 || hexdec($add) > 64 && hexdec($add) < 91 || hexdec($add) > 96 && hexdec($add) < 123)
374
+ {
375
+ $this->log('Replaced unicode notation: Changed \\'. $add .' to ' . chr(hexdec($add)),'Information');
376
+ $add = chr(hexdec($add));
377
+ $replaced = true;
378
+ }
379
+ else {
380
+ $add = trim('\\'.$add);
381
+ }
382
+
383
+ if(@ctype_xdigit($string{$i+1}) && ctype_space($string{$i})
384
+ && !$replaced || !ctype_space($string{$i})) {
385
+ $i--;
386
+ }
387
+
388
+ if($add != '\\' || !$this->get_cfg('remove_bslash') || strpos($tokens, $string{$i+1}) !== false) {
389
+ return $add;
390
+ }
391
+
392
+ if($add == '\\') {
393
+ $this->log('Removed unnecessary backslash','Information');
394
+ }
395
+ return '';
396
+ }
397
+
398
+ /**
399
+ * Loads a new template
400
+ * @param string $content either filename (if $from_file == true), content of a template file, "high_compression", "highest_compression", "low_compression", or "default"
401
+ * @param bool $from_file uses $content as filename if true
402
+ * @access public
403
+ * @version 1.1
404
+ * @see http://csstidy.sourceforge.net/templates.php
405
+ */
406
+ function load_template($content, $from_file=true)
407
+ {
408
+ $predefined_templates =& $GLOBALS['csstidy']['predefined_templates'];
409
+ if($content == 'high_compression' || $content == 'default' || $content == 'highest_compression' || $content == 'low_compression')
410
+ {
411
+ $this->template = $predefined_templates[$content];
412
+ return;
413
+ }
414
+
415
+ if($from_file)
416
+ {
417
+ $content = strip_tags(file_get_contents($content),'<span>');
418
+ }
419
+ $content = str_replace("\r\n","\n",$content); // Unify newlines (because the output also only uses \n)
420
+ $template = explode('|',$content);
421
+
422
+ for ($i = 0; $i < count($template); $i++ )
423
+ {
424
+ $this->template[$i] = $template[$i];
425
+ }
426
+ }
427
+
428
+ /**
429
+ * Starts parsing from URL
430
+ * @param string $url
431
+ * @access public
432
+ * @version 1.0
433
+ */
434
+ function parse_from_url($url)
435
+ {
436
+ return $this->parse(@file_get_contents($url));
437
+ }
438
+
439
+ /**
440
+ * Checks if there is a token at the current position
441
+ * @param string $string
442
+ * @param integer $i
443
+ * @access public
444
+ * @version 1.11
445
+ */
446
+ function is_token(&$string, $i)
447
+ {
448
+ $tokens =& $GLOBALS['csstidy']['tokens'];
449
+ return (strpos($tokens, $string{$i}) !== false && !csstidy::escaped($string,$i));
450
+ }
451
+
452
+
453
+ /**
454
+ * Parses CSS in $string. The code is saved as array in $this->css
455
+ * @param string $string the CSS code
456
+ * @access public
457
+ * @return bool
458
+ * @version 1.1
459
+ */
460
+ function parse($string) {
461
+ // PHP bug? Settings need to be refreshed in PHP4
462
+ $this->print = new csstidy_print($this);
463
+ $this->optimise = new csstidy_optimise($this);
464
+
465
+ $all_properties =& $GLOBALS['csstidy']['all_properties'];
466
+ $at_rules =& $GLOBALS['csstidy']['at_rules'];
467
+
468
+ $this->css = array();
469
+ $this->print->input_css = $string;
470
+ $string = str_replace("\r\n","\n",$string) . ' ';
471
+ $cur_comment = '';
472
+
473
+ for ($i = 0, $size = strlen($string); $i < $size; $i++ )
474
  {
475
+ if($string{$i} == "\n" || $string{$i} == "\r")
 
 
476
  {
477
+ ++$this->line;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  }
479
+
480
+ switch($this->status)
481
  {
482
+ /* Case in at-block */
483
+ case 'at':
484
+ if(csstidy::is_token($string,$i))
485
  {
486
+ if($string{$i} == '/' && @$string{$i+1} == '*')
487
+ {
488
+ $this->status = 'ic'; ++$i;
489
+ $this->from = 'at';
490
+ }
491
+ elseif($string{$i} == '{')
492
+ {
493
+ $this->status = 'is';
494
+ $this->_add_token(AT_START, $this->at);
495
+ }
496
+ elseif($string{$i} == ',')
497
+ {
498
+ $this->at = trim($this->at).',';
499
+ }
500
+ elseif($string{$i} == '\\')
501
+ {
502
+ $this->at .= $this->_unicode($string,$i);
503
+ }
504
  }
505
+ else
 
 
 
 
 
 
 
506
  {
507
+ $lastpos = strlen($this->at)-1;
508
+ if(!( (ctype_space($this->at{$lastpos}) || csstidy::is_token($this->at,$lastpos) && $this->at{$lastpos} == ',') && ctype_space($string{$i})))
509
+ {
510
+ $this->at .= $string{$i};
511
+ }
512
  }
513
+ break;
514
+
515
+ /* Case in-selector */
516
+ case 'is':
517
+ if(csstidy::is_token($string,$i))
518
  {
519
+ if($string{$i} == '/' && @$string{$i+1} == '*' && trim($this->selector) == '')
 
 
520
  {
521
+ $this->status = 'ic'; ++$i;
522
+ $this->from = 'is';
 
 
 
 
 
523
  }
524
+ elseif($string{$i} == '@' && trim($this->selector) == '')
 
525
  {
526
+ // Check for at-rule
527
+ $this->invalid_at = true;
528
+ foreach($at_rules as $name => $type)
529
+ {
530
+ if(!strcasecmp(substr($string,$i+1,strlen($name)),$name))
531
+ {
532
+ ($type == 'at') ? $this->at = '@'.$name : $this->selector = '@'.$name;
533
+ $this->status = $type;
534
+ $i += strlen($name);
535
+ $this->invalid_at = false;
536
+ }
537
+ }
538
+
539
+ if($this->invalid_at)
540
  {
541
+ $this->selector = '@';
542
+ $invalid_at_name = '';
543
+ for($j = $i+1; $j < $size; ++$j)
544
  {
545
+ if(!ctype_alpha($string{$j}))
546
+ {
547
+ break;
548
+ }
549
+ $invalid_at_name .= $string{$j};
550
  }
551
+ $this->log('Invalid @-rule: '.$invalid_at_name.' (removed)','Warning');
552
  }
 
553
  }
554
+ elseif(($string{$i} == '"' || $string{$i} == "'"))
555
+ {
556
+ $this->cur_string = $string{$i};
557
+ $this->status = 'instr';
558
+ $this->str_char = $string{$i};
559
+ $this->from = 'is';
560
+ }
561
+ elseif($this->invalid_at && $string{$i} == ';')
562
+ {
563
+ $this->invalid_at = false;
564
+ $this->status = 'is';
565
+ }
566
+ elseif($string{$i} == '{')
567
+ {
568
+ $this->status = 'ip';
569
+ $this->_add_token(SEL_START, $this->selector);
570
+ $this->added = false;
571
+ }
572
+ elseif($string{$i} == '}')
573
+ {
574
+ $this->_add_token(AT_END, $this->at);
575
+ $this->at = '';
576
+ $this->selector = '';
577
+ $this->sel_separate = array();
578
+ }
579
+ elseif($string{$i} == ',')
580
+ {
581
+ $this->selector = trim($this->selector).',';
582
+ $this->sel_separate[] = strlen($this->selector);
583
+ }
584
+ elseif($string{$i} == '\\')
585
+ {
586
+ $this->selector .= $this->_unicode($string,$i);
587
+ }
588
+ // remove unnecessary universal selector, FS#147
589
+ else if(!($string{$i} == '*' && @in_array($string{$i+1}, array('.', '#', '[', ':')))) {
590
+ $this->selector .= $string{$i};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
591
  }
592
  }
593
+ else
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
594
  {
595
+ $lastpos = strlen($this->selector)-1;
596
+ if($lastpos == -1 || !( (ctype_space($this->selector{$lastpos}) || csstidy::is_token($this->selector,$lastpos) && $this->selector{$lastpos} == ',') && ctype_space($string{$i})))
597
+ {
598
+ $this->selector .= $string{$i};
599
+ }
600
  }
601
+ break;
602
+
603
+ /* Case in-property */
604
+ case 'ip':
605
+ if(csstidy::is_token($string,$i))
606
  {
607
+ if(($string{$i} == ':' || $string{$i} == '=') && $this->property != '')
608
  {
609
+ $this->status = 'iv';
610
+ if(!$this->get_cfg('discard_invalid_properties') || csstidy::property_is_valid($this->property)) {
611
+ $this->_add_token(PROPERTY, $this->property);
 
 
 
 
 
 
612
  }
613
+ }
614
+ elseif($string{$i} == '/' && @$string{$i+1} == '*' && $this->property == '')
615
+ {
616
+ $this->status = 'ic'; ++$i;
617
+ $this->from = 'ip';
618
+ }
619
+ elseif($string{$i} == '}')
620
+ {
621
+ $this->explode_selectors();
622
+ $this->status = 'is';
623
+ $this->invalid_at = false;
624
+ $this->_add_token(SEL_END, $this->selector);
625
  $this->selector = '';
626
+ $this->property = '';
627
  }
628
+ elseif($string{$i} == ';')
629
  {
630
+ $this->property = '';
631
+ }
632
+ elseif($string{$i} == '\\')
633
+ {
634
+ $this->property .= $this->_unicode($string,$i);
635
  }
636
  }
637
+ elseif(!ctype_space($string{$i}))
638
  {
639
+ $this->property .= $string{$i};
640
+ }
641
+ break;
642
+
643
+ /* Case in-value */
644
+ case 'iv':
645
+ $pn = (($string{$i} == "\n" || $string{$i} == "\r") && $this->property_is_next($string,$i+1) || $i == strlen($string)-1);
646
+ if(csstidy::is_token($string,$i) || $pn)
647
  {
648
+ if($string{$i} == '/' && @$string{$i+1} == '*')
649
  {
650
+ $this->status = 'ic'; ++$i;
651
+ $this->from = 'iv';
652
  }
653
+ elseif(($string{$i} == '"' || $string{$i} == "'" || $string{$i} == '('))
 
 
654
  {
655
+ $this->cur_string = $string{$i};
656
+ $this->str_char = ($string{$i} == '(') ? ')' : $string{$i};
657
+ $this->status = 'instr';
658
+ $this->from = 'iv';
659
  }
660
+ elseif($string{$i} == ',')
661
+ {
662
+ $this->sub_value = trim($this->sub_value).',';
 
 
 
663
  }
664
+ elseif($string{$i} == '\\')
 
 
 
 
 
 
 
 
665
  {
666
+ $this->sub_value .= $this->_unicode($string,$i);
 
 
667
  }
668
+ elseif($string{$i} == ';' || $pn)
669
  {
670
+ if($this->selector{0} == '@' && isset($at_rules[substr($this->selector,1)]) && $at_rules[substr($this->selector,1)] == 'iv')
671
  {
672
+ $this->sub_value_arr[] = trim($this->sub_value);
673
+
674
+ $this->status = 'is';
675
+
676
+ switch($this->selector)
677
+ {
678
+ case '@charset': $this->charset = $this->sub_value_arr[0]; break;
679
+ case '@namespace': $this->namespace = implode(' ',$this->sub_value_arr); break;
680
+ case '@import': $this->import[] = implode(' ',$this->sub_value_arr); break;
681
+ }
682
+
683
+ $this->sub_value_arr = array();
684
+ $this->sub_value = '';
685
+ $this->selector = '';
686
+ $this->sel_separate = array();
687
  }
688
  else
689
  {
690
+ $this->status = 'ip';
691
  }
692
  }
693
+ elseif($string{$i} != '}')
694
+ {
695
+ $this->sub_value .= $string{$i};
696
+ }
697
+ if(($string{$i} == '}' || $string{$i} == ';' || $pn) && !empty($this->selector))
698
+ {
699
+ if($this->at == '')
700
+ {
701
+ $this->at = DEFAULT_AT;
702
+ }
703
+
704
+ // case settings
705
+ if($this->get_cfg('lowercase_s'))
706
+ {
707
+ $this->selector = strtolower($this->selector);
708
+ }
709
+ $this->property = strtolower($this->property);
710
+
711
+ $this->optimise->subvalue();
712
+ if($this->sub_value != '') {
713
+ $this->sub_value_arr[] = $this->sub_value;
714
+ $this->sub_value = '';
715
+ }
716
+
717
+ $this->value = implode(' ',$this->sub_value_arr);
718
+
719
+ $this->selector = trim($this->selector);
720
+
721
+ $this->optimise->value();
722
+
723
+ $valid = csstidy::property_is_valid($this->property);
724
+ if((!$this->invalid_at || $this->get_cfg('preserve_css')) && (!$this->get_cfg('discard_invalid_properties') || $valid))
725
+ {
726
+ $this->css_add_property($this->at,$this->selector,$this->property,$this->value);
727
+ $this->_add_token(VALUE, $this->value);
728
+ $this->optimise->shorthands();
729
+ }
730
+ if(!$valid)
731
+ {
732
+ if($this->get_cfg('discard_invalid_properties'))
733
+ {
734
+ $this->log('Removed invalid property: '.$this->property,'Warning');
735
+ }
736
+ else
737
+ {
738
+ $this->log('Invalid property in '.strtoupper($this->get_cfg('css_level')).': '.$this->property,'Warning');
739
+ }
740
+ }
741
+
742
+ $this->property = '';
743
+ $this->sub_value_arr = array();
744
+ $this->value = '';
745
+ }
746
+ if($string{$i} == '}')
747
+ {
748
+ $this->explode_selectors();
749
+ $this->_add_token(SEL_END, $this->selector);
750
+ $this->status = 'is';
751
+ $this->invalid_at = false;
752
+ $this->selector = '';
753
+ }
754
  }
755
+ elseif(!$pn)
756
  {
757
+ $this->sub_value .= $string{$i};
758
+
759
+ if(ctype_space($string{$i}))
760
+ {
761
+ $this->optimise->subvalue();
762
+ if($this->sub_value != '') {
763
+ $this->sub_value_arr[] = $this->sub_value;
764
+ $this->sub_value = '';
765
+ }
766
+ }
767
  }
768
+ break;
769
+
770
+ /* Case in string */
771
+ case 'instr':
772
+ if($this->str_char == ')' && ($string{$i} == '"' || $string{$i} == '\'') && !$this->str_in_str && !csstidy::escaped($string,$i))
 
773
  {
774
+ $this->str_in_str = true;
 
 
 
 
775
  }
776
+ elseif($this->str_char == ')' && ($string{$i} == '"' || $string{$i} == '\'') && $this->str_in_str && !csstidy::escaped($string,$i))
777
+ {
778
+ $this->str_in_str = false;
779
+ }
780
+ $temp_add = $string{$i}; // ...and no not-escaped backslash at the previous position
781
+ if( ($string{$i} == "\n" || $string{$i} == "\r") && !($string{$i-1} == '\\' && !csstidy::escaped($string,$i-1)) )
782
+ {
783
+ $temp_add = "\\A ";
784
+ $this->log('Fixed incorrect newline in string','Warning');
785
+ }
786
+ if (!($this->str_char == ')' && in_array($string{$i}, $GLOBALS['csstidy']['whitespace']) && !$this->str_in_str)) {
787
+ $this->cur_string .= $temp_add;
788
+ }
789
+ if($string{$i} == $this->str_char && !csstidy::escaped($string,$i) && !$this->str_in_str)
790
+ {
791
+ $this->status = $this->from;
792
+ if (!preg_match('|[' . implode('', $GLOBALS['csstidy']['whitespace']) . ']|uis', $this->cur_string) && $this->property != 'content') {
793
+ if ($this->str_char == '"' || $this->str_char == '\'') {
794
+ $this->cur_string = substr($this->cur_string, 1, -1);
795
+ } else if (strlen($this->cur_string) > 3 && ($this->cur_string[1] == '"' || $this->cur_string[1] == '\'')) /* () */ {
796
+ $this->cur_string = $this->cur_string[0] . substr($this->cur_string, 2, -2) . substr($this->cur_string, -1);
797
+ }
798
+ }
799
+ if($this->from == 'iv')
800
+ {
801
+ $this->sub_value .= $this->cur_string;
802
+ }
803
+ elseif($this->from == 'is')
804
+ {
805
+ $this->selector .= $this->cur_string;
806
+ }
807
  }
808
+ break;
809
+
810
+ /* Case in-comment */
811
+ case 'ic':
812
+ if($string{$i} == '*' && $string{$i+1} == '/')
813
  {
814
+ $this->status = $this->from;
815
+ $i++;
816
+ $this->_add_token(COMMENT, $cur_comment);
817
+ $cur_comment = '';
818
  }
819
+ else
820
  {
821
+ $cur_comment .= $string{$i};
822
  }
823
+ break;
824
  }
825
+ }
826
+
827
+ $this->optimise->postparse();
828
+
829
+ $this->print->_reset();
830
+
831
+ return !(empty($this->css) && empty($this->import) && empty($this->charset) && empty($this->tokens) && empty($this->namespace));
832
+ }
833
+
834
+ /**
835
+ * Explodes selectors
836
+ * @access private
837
+ * @version 1.0
838
+ */
839
+ function explode_selectors()
840
+ {
841
+ // Explode multiple selectors
842
+ if($this->get_cfg('merge_selectors') == 1)
843
+ {
844
+ $new_sels = array();
845
+ $lastpos = 0;
846
+ $this->sel_separate[] = strlen($this->selector);
847
+ foreach($this->sel_separate as $num => $pos)
848
  {
849
+ if($num == count($this->sel_separate)-1) {
850
+ $pos += 1;
851
+ }
852
+
853
+ $new_sels[] = substr($this->selector,$lastpos,$pos-$lastpos-1);
854
+ $lastpos = $pos;
855
  }
856
+
857
+ if(count($new_sels) > 1)
858
  {
859
+ foreach($new_sels as $selector)
860
+ {
861
+ $this->merge_css_blocks($this->at,$selector,$this->css[$this->at][$this->selector]);
862
+ }
863
+ unset($this->css[$this->at][$this->selector]);
864
  }
 
865
  }
866
+ $this->sel_separate = array();
867
  }
868
+
869
+ /**
870
+ * Checks if a character is escaped (and returns true if it is)
871
+ * @param string $string
872
+ * @param integer $pos
873
+ * @access public
874
+ * @return bool
875
+ * @version 1.02
876
+ */
877
+ function escaped(&$string,$pos)
 
 
 
 
 
 
 
878
  {
879
+ return !(@($string{$pos-1} != '\\') || csstidy::escaped($string,$pos-1));
880
+ }
881
+
882
+ /**
883
+ * Adds a property with value to the existing CSS code
884
+ * @param string $media
885
+ * @param string $selector
886
+ * @param string $property
887
+ * @param string $new_val
888
+ * @access private
889
+ * @version 1.2
890
+ */
891
+ function css_add_property($media,$selector,$property,$new_val)
892
+ {
893
+ if($this->get_cfg('preserve_css') || trim($new_val) == '') {
894
+ return;
895
  }
896
+
897
+ $this->added = true;
898
+ if(isset($this->css[$media][$selector][$property]))
899
  {
900
+ if((csstidy::is_important($this->css[$media][$selector][$property]) && csstidy::is_important($new_val)) || !csstidy::is_important($this->css[$media][$selector][$property]))
901
  {
902
+ unset($this->css[$media][$selector][$property]);
903
+ $this->css[$media][$selector][$property] = trim($new_val);
904
  }
 
905
  }
906
+ else
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
907
  {
 
908
  $this->css[$media][$selector][$property] = trim($new_val);
909
  }
910
  }
911
+
912
+ /**
913
+ * Adds CSS to an existing media/selector
914
+ * @param string $media
915
+ * @param string $selector
916
+ * @param array $css_add
917
+ * @access private
918
+ * @version 1.1
919
+ */
920
+ function merge_css_blocks($media,$selector,$css_add)
921
  {
922
+ foreach($css_add as $property => $value)
923
+ {
924
+ $this->css_add_property($media,$selector,$property,$value,false);
925
+ }
926
+ }
927
+
928
+ /**
929
+ * Checks if $value is !important.
930
+ * @param string $value
931
+ * @return bool
932
+ * @access public
933
+ * @version 1.0
934
+ */
935
+ function is_important(&$value)
936
+ {
937
+ return (!strcasecmp(substr(str_replace($GLOBALS['csstidy']['whitespace'],'',$value),-10,10),'!important'));
938
+ }
939
+
940
+ /**
941
+ * Returns a value without !important
942
+ * @param string $value
943
+ * @return string
944
+ * @access public
945
+ * @version 1.0
946
+ */
947
+ function gvw_important($value)
948
+ {
949
+ if(csstidy::is_important($value))
950
+ {
951
+ $value = trim($value);
952
+ $value = substr($value,0,-9);
953
+ $value = trim($value);
954
+ $value = substr($value,0,-1);
955
+ $value = trim($value);
956
+ return $value;
957
+ }
958
+ return $value;
959
+ }
960
+
961
+ /**
962
+ * Checks if the next word in a string from pos is a CSS property
963
+ * @param string $istring
964
+ * @param integer $pos
965
+ * @return bool
966
+ * @access private
967
+ * @version 1.2
968
+ */
969
+ function property_is_next($istring, $pos)
970
+ {
971
+ $all_properties =& $GLOBALS['csstidy']['all_properties'];
972
+ $istring = substr($istring,$pos,strlen($istring)-$pos);
973
+ $pos = strpos($istring,':');
974
+ if($pos === false)
975
+ {
976
+ return false;
977
+ }
978
+ $istring = strtolower(trim(substr($istring,0,$pos)));
979
+ if(isset($all_properties[$istring]))
980
+ {
981
+ $this->log('Added semicolon to the end of declaration','Warning');
982
+ return true;
983
+ }
984
+ return false;
985
+ }
986
+
987
+ /**
988
+ * Checks if a property is valid
989
+ * @param string $property
990
+ * @return bool;
991
+ * @access public
992
+ * @version 1.0
993
+ */
994
+ function property_is_valid($property) {
995
+ $all_properties =& $GLOBALS['csstidy']['all_properties'];
996
+ return (isset($all_properties[$property]) && strpos($all_properties[$property],strtoupper($this->get_cfg('css_level'))) !== false );
997
+ }
998
+
999
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1000
  }
1001
  ?>
css/CSSTidy/class.csstidy_optimise.php CHANGED
@@ -36,774 +36,776 @@
36
  * @version 1.0
37
  */
38
 
39
- class csstidy_optimise
40
- {
41
- /**
42
- * Constructor
43
- * @param array $css contains the class csstidy
44
- * @access private
45
- * @version 1.0
46
- */
47
- function __construct(&$css)
48
  {
49
- $this->parser =& $css;
50
- $this->css =& $css->css;
51
- $this->sub_value =& $css->sub_value;
52
- $this->at =& $css->at;
53
- $this->selector =& $css->selector;
54
- $this->property =& $css->property;
55
- $this->value =& $css->value;
56
- }
57
-
58
- /**
59
- * Optimises $css after parsing
60
- * @access public
61
- * @version 1.0
62
- */
63
- function postparse()
64
- {
65
- if ($this->parser->get_cfg('preserve_css')) {
66
- return;
67
- }
68
-
69
- if ($this->parser->get_cfg('merge_selectors') == 2)
70
- {
71
- foreach ($this->css as $medium => $value)
 
 
 
 
 
 
72
  {
73
- $this->merge_selectors($this->css[$medium]);
 
 
 
74
  }
75
- }
76
-
77
- if ($this->parser->get_cfg('optimise_shorthands') > 0)
78
- {
79
- foreach ($this->css as $medium => $value)
80
  {
81
- foreach ($value as $selector => $value1)
82
  {
83
- $this->css[$medium][$selector] = csstidy_optimise::merge_4value_shorthands($this->css[$medium][$selector]);
84
-
85
- if ($this->parser->get_cfg('optimise_shorthands') < 2) {
86
- continue;
87
- }
88
-
89
- $this->css[$medium][$selector] = csstidy_optimise::merge_bg($this->css[$medium][$selector]);
90
- if (empty($this->css[$medium][$selector])) {
91
- unset($this->css[$medium][$selector]);
 
 
 
92
  }
93
  }
94
  }
95
  }
96
- }
97
-
98
- /**
99
- * Optimises values
100
- * @access public
101
- * @version 1.0
102
- */
103
- function value()
104
- {
105
- $shorthands =& $GLOBALS['csstidy']['shorthands'];
106
-
107
- // optimise shorthand properties
108
- if(isset($shorthands[$this->property]))
109
  {
110
- $temp = csstidy_optimise::shorthand($this->value); // FIXME - move
111
- if($temp != $this->value)
 
 
112
  {
113
- $this->parser->log('Optimised shorthand notation ('.$this->property.'): Changed "'.$this->value.'" to "'.$temp.'"','Information');
 
 
 
 
 
114
  }
115
- $this->value = $temp;
116
- }
117
-
118
- // Remove whitespace at ! important
119
- if($this->value != $this->compress_important($this->value))
120
- {
121
- $this->parser->log('Optimised !important','Information');
122
- }
123
- }
124
-
125
- /**
126
- * Optimises shorthands
127
- * @access public
128
- * @version 1.0
129
- */
130
- function shorthands()
131
- {
132
- $shorthands =& $GLOBALS['csstidy']['shorthands'];
133
-
134
- if(!$this->parser->get_cfg('optimise_shorthands') || $this->parser->get_cfg('preserve_css')) {
135
- return;
136
- }
137
-
138
- if($this->property == 'background' && $this->parser->get_cfg('optimise_shorthands') > 1)
139
- {
140
- unset($this->css[$this->at][$this->selector]['background']);
141
- $this->parser->merge_css_blocks($this->at,$this->selector,csstidy_optimise::dissolve_short_bg($this->value));
142
- }
143
- if(isset($shorthands[$this->property]))
144
- {
145
- $this->parser->merge_css_blocks($this->at,$this->selector,csstidy_optimise::dissolve_4value_shorthands($this->property,$this->value));
146
- if(is_array($shorthands[$this->property]))
147
  {
148
- unset($this->css[$this->at][$this->selector][$this->property]);
149
  }
150
  }
151
- }
152
-
153
- /**
154
- * Optimises a sub-value
155
- * @access public
156
- * @version 1.0
157
- */
158
- function subvalue()
159
- {
160
- $replace_colors =& $GLOBALS['csstidy']['replace_colors'];
161
-
162
- $this->sub_value = trim($this->sub_value);
163
- if($this->sub_value == '') // caution : '0'
164
- {
165
- return;
166
- }
167
-
168
- $important = '';
169
- if(csstidy::is_important($this->sub_value))
170
- {
171
- $important = '!important';
172
- }
173
- $this->sub_value = csstidy::gvw_important($this->sub_value);
174
-
175
- // Compress font-weight
176
- if($this->property == 'font-weight' && $this->parser->get_cfg('compress_font-weight'))
177
  {
178
- if($this->sub_value == 'bold')
179
- {
180
- $this->sub_value = '700';
181
- $this->parser->log('Optimised font-weight: Changed "bold" to "700"','Information');
182
  }
183
- else if($this->sub_value == 'normal')
 
184
  {
185
- $this->sub_value = '400';
186
- $this->parser->log('Optimised font-weight: Changed "normal" to "400"','Information');
187
- }
188
- }
189
-
190
- $temp = $this->compress_numbers($this->sub_value);
191
- if($temp != $this->sub_value)
192
- {
193
- if(strlen($temp) > strlen($this->sub_value)) {
194
- $this->parser->log('Fixed invalid number: Changed "'.$this->sub_value.'" to "'.$temp.'"','Warning');
195
- } else {
196
- $this->parser->log('Optimised number: Changed "'.$this->sub_value.'" to "'.$temp.'"','Information');
197
  }
198
- $this->sub_value = $temp;
199
- }
200
- if($this->parser->get_cfg('compress_colors'))
201
- {
202
- $temp = $this->cut_color($this->sub_value);
203
- if($temp !== $this->sub_value)
204
  {
205
- if(isset($replace_colors[$this->sub_value])) {
206
- $this->parser->log('Fixed invalid color name: Changed "'.$this->sub_value.'" to "'.$temp.'"','Warning');
207
- } else {
208
- $this->parser->log('Optimised color: Changed "'.$this->sub_value.'" to "'.$temp.'"','Information');
209
  }
210
- $this->sub_value = $temp;
211
  }
212
  }
213
- $this->sub_value .= $important;
214
- }
215
-
216
- /**
217
- * Compresses shorthand values. Example: margin:1px 1px 1px 1px -> margin:1px
218
- * @param string $value
219
- * @access public
220
- * @return string
221
- * @version 1.0
222
- */
223
- function shorthand($value)
224
- {
225
- $important = '';
226
- if(csstidy::is_important($value))
227
  {
228
- $values = csstidy::gvw_important($value);
229
- $important = '!important';
230
- }
231
- else $values = $value;
232
-
233
- $values = explode(' ',$values);
234
- switch(count($values))
235
- {
236
- case 4:
237
- if($values[0] == $values[1] && $values[0] == $values[2] && $values[0] == $values[3])
238
- {
239
- return $values[0].$important;
240
- }
241
- elseif($values[1] == $values[3] && $values[0] == $values[2])
242
- {
243
- return $values[0].' '.$values[1].$important;
244
- }
245
- elseif($values[1] == $values[3])
246
- {
247
- return $values[0].' '.$values[1].' '.$values[2].$important;
248
- }
249
- break;
250
-
251
- case 3:
252
- if($values[0] == $values[1] && $values[0] == $values[2])
253
  {
254
- return $values[0].$important;
255
  }
256
- elseif($values[0] == $values[2])
 
 
257
  {
258
- return $values[0].' '.$values[1].$important;
259
  }
260
- break;
261
-
262
- case 2:
263
- if($values[0] == $values[1])
264
- {
265
- return $values[0].$important;
266
- }
267
- break;
268
- }
269
-
270
- return $value;
271
- }
272
-
273
- /**
274
- * Removes unnecessary whitespace in ! important
275
- * @param string $string
276
- * @return string
277
- * @access public
278
- * @version 1.1
279
- */
280
- function compress_important(&$string)
281
- {
282
- if(csstidy::is_important($string))
283
- {
284
- $string = csstidy::gvw_important($string) . '!important';
285
- }
286
- return $string;
287
- }
288
-
289
- /**
290
- * Color compression function. Converts all rgb() values to #-values and uses the short-form if possible. Also replaces 4 color names by #-values.
291
- * @param string $color
292
- * @return string
293
- * @version 1.1
294
- */
295
- function cut_color($color)
296
- {
297
- $replace_colors =& $GLOBALS['csstidy']['replace_colors'];
298
-
299
- // rgb(0,0,0) -> #000000 (or #000 in this case later)
300
- if(strtolower(substr($color,0,4)) == 'rgb(')
301
- {
302
- $color_tmp = substr($color,4,strlen($color)-5);
303
- $color_tmp = explode(',',$color_tmp);
304
- for ( $i = 0; $i < count($color_tmp); $i++ )
305
  {
306
- $color_tmp[$i] = trim ($color_tmp[$i]);
307
- if(substr($color_tmp[$i],-1) == '%')
308
  {
309
- $color_tmp[$i] = round((255*$color_tmp[$i])/100);
 
 
 
 
 
 
310
  }
311
- if($color_tmp[$i]>255) $color_tmp[$i] = 255;
312
  }
313
- $color = '#';
314
- for ($i = 0; $i < 3; $i++ )
 
315
  {
316
- if($color_tmp[$i]<16) {
317
- $color .= '0' . dechex($color_tmp[$i]);
318
  } else {
319
- $color .= dechex($color_tmp[$i]);
320
  }
 
321
  }
322
- }
323
-
324
- // Fix bad color names
325
- if(isset($replace_colors[strtolower($color)]))
326
- {
327
- $color = $replace_colors[strtolower($color)];
328
- }
329
-
330
- // #aabbcc -> #abc
331
- if(strlen($color) == 7)
332
- {
333
- $color_temp = strtolower($color);
334
- if($color_temp{0} == '#' && $color_temp{1} == $color_temp{2} && $color_temp{3} == $color_temp{4} && $color_temp{5} == $color_temp{6})
335
  {
336
- $color = '#'.$color{1}.$color{3}.$color{5};
 
 
 
 
 
 
 
 
 
337
  }
 
338
  }
339
-
340
- switch(strtolower($color))
341
- {
342
- /* color name -> hex code */
343
- case 'black': return '#000';
344
- case 'fuchsia': return '#F0F';
345
- case 'white': return '#FFF';
346
- case 'yellow': return '#FF0';
347
-
348
- /* hex code -> color name */
349
- case '#800000': return 'maroon';
350
- case '#ffa500': return 'orange';
351
- case '#808000': return 'olive';
352
- case '#800080': return 'purple';
353
- case '#008000': return 'green';
354
- case '#000080': return 'navy';
355
- case '#008080': return 'teal';
356
- case '#c0c0c0': return 'silver';
357
- case '#808080': return 'gray';
358
- case '#f00': return 'red';
359
- }
360
-
361
- return $color;
362
- }
363
-
364
- /**
365
- * Compresses numbers (ie. 1.0 becomes 1 or 1.100 becomes 1.1 )
366
- * @param string $subvalue
367
- * @return string
368
- * @version 1.2
369
- */
370
- function compress_numbers($subvalue)
371
- {
372
- $units =& $GLOBALS['csstidy']['units'];
373
- $unit_values =& $GLOBALS['csstidy']['unit_values'];
374
- $color_values =& $GLOBALS['csstidy']['color_values'];
375
-
376
- // for font:1em/1em sans-serif...;
377
- if($this->property == 'font')
378
- {
379
- $temp = explode('/',$subvalue);
380
- }
381
- else
382
- {
383
- $temp = array($subvalue);
384
- }
385
- for ($l = 0; $l < count($temp); $l++)
386
  {
387
- // continue if no numeric value
388
- if (!(strlen($temp[$l]) > 0 && ( is_numeric($temp[$l]{0}) || $temp[$l]{0} == '+' || $temp[$l]{0} == '-' ) ))
389
  {
390
- continue;
 
391
  }
392
-
393
- // Fix bad colors
394
- if (in_array($this->property, $color_values))
395
- {
396
- $temp[$l] = '#'.$temp[$l];
397
- }
398
-
399
- if (floatval($temp[$l]) == 0)
400
  {
401
- $temp[$l] = '0';
402
- }
403
- else
404
- {
405
- $unit_found = FALSE;
406
- for ($m = 0, $size_4 = count($units); $m < $size_4; $m++)
407
  {
408
- if (strpos(strtolower($temp[$l]),$units[$m]) !== FALSE)
409
- {
410
- $temp[$l] = floatval($temp[$l]).$units[$m];
411
- $unit_found = TRUE;
412
- break;
413
- }
414
  }
415
- if (!$unit_found && in_array($this->property,$unit_values,TRUE))
416
  {
417
- $temp[$l] = floatval($temp[$l]).'px';
418
  }
419
- else if (!$unit_found)
420
  {
421
- $temp[$l] = floatval($temp[$l]);
422
  }
423
- // Remove leading zero
424
- if (abs(floatval($temp[$l])) < 1) {
425
- if (floatval($temp[$l]) < 0) {
426
- $temp[$l] = '-' . substr($temp[$l], 2);
427
- } else {
428
- $temp[$l] = substr($temp[$l], 1);
429
- }
430
  }
 
 
 
 
 
 
 
 
 
 
 
 
431
  }
 
 
432
  }
433
-
434
- return ((count($temp) > 1) ? $temp[0].'/'.$temp[1] : $temp[0]);
435
- }
436
-
437
- /**
438
- * Merges selectors with same properties. Example: a{color:red} b{color:red} -> a,b{color:red}
439
- * Very basic and has at least one bug. Hopefully there is a replacement soon.
440
- * @param array $array
441
- * @return array
442
- * @access public
443
- * @version 1.2
444
- */
445
- function merge_selectors(&$array)
446
- {
447
- $css = $array;
448
- foreach($css as $key => $value)
449
  {
450
- if(!isset($css[$key]))
451
  {
452
- continue;
453
- }
454
- $newsel = '';
455
-
456
- // Check if properties also exist in another selector
457
- $keys = array();
458
- // PHP bug (?) without $css = $array; here
459
- foreach($css as $selector => $vali)
 
 
 
 
 
 
 
 
 
460
  {
461
- if($selector == $key)
 
 
462
  {
463
- continue;
 
 
 
 
 
464
  }
465
-
466
- if($css[$key] === $vali)
467
  {
468
- $keys[] = $selector;
 
 
 
 
469
  }
470
  }
471
-
472
- if(!empty($keys))
 
473
  {
474
- $newsel = $key;
475
- unset($css[$key]);
476
- foreach($keys as $selector)
 
 
 
 
 
477
  {
478
- unset($css[$selector]);
479
- $newsel .= ','.$selector;
480
  }
481
- $css[$newsel] = $value;
482
  }
483
- }
484
- $array = $css;
485
- }
486
-
487
- /**
488
- * Dissolves properties like padding:10px 10px 10px to padding-top:10px;padding-bottom:10px;...
489
- * @param string $property
490
- * @param string $value
491
- * @return array
492
- * @version 1.0
493
- * @see merge_4value_shorthands()
494
- */
495
- function dissolve_4value_shorthands($property,$value)
496
- {
497
- $shorthands =& $GLOBALS['csstidy']['shorthands'];
498
- if(!is_array($shorthands[$property]))
499
- {
500
- $return[$property] = $value;
501
- return $return;
502
- }
503
-
504
- $important = '';
505
- if(csstidy::is_important($value))
506
- {
507
- $value = csstidy::gvw_important($value);
508
- $important = '!important';
509
- }
510
- $values = explode(' ',$value);
511
-
512
-
513
- $return = array();
514
- if(count($values) == 4)
515
- {
516
- for($i=0;$i<4;$i++)
517
  {
518
- $return[$shorthands[$property][$i]] = $values[$i].$important;
519
- }
520
- }
521
- elseif(count($values) == 3)
522
- {
523
- $return[$shorthands[$property][0]] = $values[0].$important;
524
- $return[$shorthands[$property][1]] = $values[1].$important;
525
- $return[$shorthands[$property][3]] = $values[1].$important;
526
- $return[$shorthands[$property][2]] = $values[2].$important;
527
- }
528
- elseif(count($values) == 2)
529
- {
530
- for($i=0;$i<4;$i++)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
531
  {
532
- $return[$shorthands[$property][$i]] = (($i % 2 != 0)) ? $values[1].$important : $values[0].$important;
533
  }
534
- }
535
- else
536
- {
537
- for($i=0;$i<4;$i++)
538
  {
539
- $return[$shorthands[$property][$i]] = $values[0].$important;
540
  }
541
- }
542
-
543
- return $return;
544
- }
545
-
546
- /**
547
- * Explodes a string as explode() does, however, not if $sep is escaped or within a string.
548
- * @param string $sep seperator
549
- * @param string $string
550
- * @return array
551
- * @version 1.0
552
- */
553
- function explode_ws($sep,$string)
554
- {
555
- $status = 'st';
556
- $to = '';
557
-
558
- $output = array();
559
- $num = 0;
560
- for($i = 0, $len = strlen($string);$i < $len; $i++)
561
- {
562
- switch($status)
563
  {
564
- case 'st':
565
- if($string{$i} == $sep && !csstidy::escaped($string,$i))
566
  {
567
- ++$num;
568
- }
569
- elseif($string{$i} == '"' || $string{$i} == '\'' || $string{$i} == '(' && !csstidy::escaped($string,$i))
570
- {
571
- $status = 'str';
572
- $to = ($string{$i} == '(') ? ')' : $string{$i};
573
- (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
574
  }
575
- else
 
 
576
  {
577
- (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
578
  }
579
- break;
580
-
581
- case 'str':
582
- if($string{$i} == $to && !csstidy::escaped($string,$i))
583
  {
584
- $status = 'st';
585
  }
586
- (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
587
- break;
588
- }
589
- }
590
-
591
- if(isset($output[0]))
592
- {
593
- return $output;
594
- }
595
- else
596
- {
597
- return array($output);
598
- }
599
- }
600
-
601
- /**
602
- * Merges Shorthand properties again, the opposite of dissolve_4value_shorthands()
603
- * @param array $array
604
- * @return array
605
- * @version 1.2
606
- * @see dissolve_4value_shorthands()
607
- */
608
- function merge_4value_shorthands($array)
609
- {
610
- $return = $array;
611
- $shorthands =& $GLOBALS['csstidy']['shorthands'];
612
-
613
- foreach($shorthands as $key => $value)
614
- {
615
- if(isset($array[$value[0]]) && isset($array[$value[1]])
616
- && isset($array[$value[2]]) && isset($array[$value[3]]) && $value !== 0)
617
- {
618
- $return[$key] = '';
619
-
620
- $important = '';
621
- for($i = 0; $i < 4; $i++)
622
  {
623
- $val = $array[$value[$i]];
624
- if(csstidy::is_important($val))
625
  {
626
- $important = '!important';
627
- $return[$key] .= csstidy::gvw_important($val).' ';
 
 
 
 
628
  }
629
- else
630
  {
631
- $return[$key] .= $val.' ';
 
 
 
 
 
 
 
 
 
 
 
 
632
  }
633
- unset($return[$value[$i]]);
634
  }
635
- $return[$key] = csstidy_optimise::shorthand(trim($return[$key].$important));
636
  }
637
- }
638
- return $return;
639
- }
640
-
641
- /**
642
- * Dissolve background property
643
- * @param string $str_value
644
- * @return array
645
- * @version 1.0
646
- * @see merge_bg()
647
- * @todo full CSS 3 compliance
648
- */
649
- function dissolve_short_bg($str_value)
650
- {
651
- $background_prop_default =& $GLOBALS['csstidy']['background_prop_default'];
652
- $repeat = array('repeat','repeat-x','repeat-y','no-repeat','space');
653
- $attachment = array('scroll','fixed','local');
654
- $clip = array('border','padding');
655
- $origin = array('border','padding','content');
656
- $pos = array('top','center','bottom','left','right');
657
- $important = '';
658
- $return = array('background-image' => NULL,'background-size' => NULL,'background-repeat' => NULL,'background-position' => NULL,'background-attachment'=>NULL,'background-clip' => NULL,'background-origin' => NULL,'background-color' => NULL);
659
-
660
- if(csstidy::is_important($str_value))
661
- {
662
- $important = ' !important';
663
- $str_value = csstidy::gvw_important($str_value);
664
- }
665
-
666
- $str_value = csstidy_optimise::explode_ws(',',$str_value);
667
- for($i = 0; $i < count($str_value); $i++)
668
- {
669
- $have['clip'] = FALSE; $have['pos'] = FALSE;
670
- $have['color'] = FALSE; $have['bg'] = FALSE;
671
-
672
- $str_value[$i] = csstidy_optimise::explode_ws(' ',trim($str_value[$i]));
673
-
674
- for($j = 0; $j < count($str_value[$i]); $j++)
675
  {
676
- if($have['bg'] === FALSE && (substr($str_value[$i][$j],0,4) == 'url(' || $str_value[$i][$j] === 'none'))
677
  {
678
- $return['background-image'] .= $str_value[$i][$j].',';
679
- $have['bg'] = TRUE;
680
  }
681
- elseif(in_array($str_value[$i][$j],$repeat,TRUE))
 
 
 
 
 
682
  {
683
- $return['background-repeat'] .= $str_value[$i][$j].',';
 
 
 
 
 
 
 
 
684
  }
685
- elseif(in_array($str_value[$i][$j],$attachment,TRUE))
 
686
  {
687
- $return['background-attachment'] .= $str_value[$i][$j].',';
 
 
 
 
 
 
 
688
  }
689
- elseif(in_array($str_value[$i][$j],$clip,TRUE) && !$have['clip'])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
690
  {
691
- $return['background-clip'] .= $str_value[$i][$j].',';
692
- $have['clip'] = TRUE;
693
  }
694
- elseif(in_array($str_value[$i][$j],$origin,TRUE))
 
 
 
 
 
 
 
 
 
 
695
  {
696
- $return['background-origin'] .= $str_value[$i][$j].',';
697
  }
698
- elseif($str_value[$i][$j]{0} == '(')
 
 
 
699
  {
700
- $return['background-size'] .= substr($str_value[$i][$j],1,-1).',';
701
  }
702
- elseif(in_array($str_value[$i][$j],$pos,TRUE) || is_numeric($str_value[$i][$j]{0}) || $str_value[$i][$j]{0} === NULL)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
703
  {
704
- $return['background-position'] .= $str_value[$i][$j];
705
- if(!$have['pos']) $return['background-position'] .= ' '; else $return['background-position'].= ',';
706
- $have['pos'] = TRUE;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
707
  }
708
- elseif(!$have['color'])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
709
  {
710
- $return['background-color'] .= $str_value[$i][$j].',';
711
- $have['color'] = TRUE;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
712
  }
713
  }
 
714
  }
715
-
716
- foreach($background_prop_default as $bg_prop => $default_value)
717
- {
718
- if($return[$bg_prop] !== NULL)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
719
  {
720
- $return[$bg_prop] = substr($return[$bg_prop],0,-1).$important;
 
721
  }
722
- else $return[$bg_prop] = $default_value.$important;
723
- }
724
- return $return;
725
- }
726
-
727
- /**
728
- * Merges all background properties
729
- * @param array $input_css
730
- * @return array
731
- * @version 1.0
732
- * @see dissolve_short_bg()
733
- * @todo full CSS 3 compliance
734
- */
735
- function merge_bg($input_css)
736
- {
737
- $background_prop_default =& $GLOBALS['csstidy']['background_prop_default'];
738
- // Max number of background images. CSS3 not yet fully implemented
739
- $number_of_values = @max(count(csstidy_optimise::explode_ws(',',$input_css['background-image'])),count(csstidy_optimise::explode_ws(',',$input_css['background-color'])),1);
740
- // Array with background images to check if BG image exists
741
- $bg_img_array = @csstidy_optimise::explode_ws(',',csstidy::gvw_important($input_css['background-image']));
742
- $new_bg_value = '';
743
- $important = '';
744
-
745
- for($i = 0; $i < $number_of_values; $i++)
746
- {
747
- foreach($background_prop_default as $bg_property => $default_value)
748
  {
749
- // Skip if property does not exist
750
- if(!isset($input_css[$bg_property]))
751
- {
752
- continue;
753
- }
754
-
755
- $cur_value = $input_css[$bg_property];
756
-
757
- // Skip some properties if there is no background image
758
- if((!isset($bg_img_array[$i]) || $bg_img_array[$i] === 'none')
759
- && ($bg_property === 'background-size' || $bg_property === 'background-position'
760
- || $bg_property === 'background-attachment' || $bg_property === 'background-repeat'))
761
  {
762
- continue;
763
- }
764
-
765
- // Remove !important
766
- if(csstidy::is_important($cur_value))
767
- {
768
- $important = ' !important';
769
- $cur_value = csstidy::gvw_important($cur_value);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
770
  }
771
-
772
- // Do not add default values
773
- if($cur_value === $default_value)
 
 
774
  {
775
- continue;
776
  }
777
-
778
- $temp = csstidy_optimise::explode_ws(',',$cur_value);
779
-
780
- if(isset($temp[$i]))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
781
  {
782
- if($bg_property == 'background-size')
 
783
  {
784
- $new_bg_value .= '('.$temp[$i].') ';
785
  }
786
- else
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
787
  {
788
- $new_bg_value .= $temp[$i].' ';
 
 
 
 
 
 
 
789
  }
790
  }
 
 
 
791
  }
792
-
793
- $new_bg_value = trim($new_bg_value);
794
- if($i != $number_of_values-1) $new_bg_value .= ',';
795
- }
796
-
797
- // Delete all background-properties
798
- foreach($background_prop_default as $bg_property => $default_value)
799
- {
800
- unset($input_css[$bg_property]);
 
 
801
  }
802
-
803
- // Add new background property
804
- if($new_bg_value !== '') $input_css['background'] = $new_bg_value.$important;
805
-
806
- return $input_css;
807
- }
808
  }
809
  ?>
36
  * @version 1.0
37
  */
38
 
39
+ if (!class_exists('csstidy_optimise')){
40
+ class csstidy_optimise
 
 
 
 
 
 
 
41
  {
42
+ /**
43
+ * Constructor
44
+ * @param array $css contains the class csstidy
45
+ * @access private
46
+ * @version 1.0
47
+ */
48
+ function __construct(&$css)
49
+ {
50
+ $this->parser =& $css;
51
+ $this->css =& $css->css;
52
+ $this->sub_value =& $css->sub_value;
53
+ $this->at =& $css->at;
54
+ $this->selector =& $css->selector;
55
+ $this->property =& $css->property;
56
+ $this->value =& $css->value;
57
+ }
58
+
59
+ /**
60
+ * Optimises $css after parsing
61
+ * @access public
62
+ * @version 1.0
63
+ */
64
+ function postparse()
65
+ {
66
+ if ($this->parser->get_cfg('preserve_css')) {
67
+ return;
68
+ }
69
+
70
+ if ($this->parser->get_cfg('merge_selectors') == 2)
71
  {
72
+ foreach ($this->css as $medium => $value)
73
+ {
74
+ $this->merge_selectors($this->css[$medium]);
75
+ }
76
  }
77
+
78
+ if ($this->parser->get_cfg('optimise_shorthands') > 0)
 
 
 
79
  {
80
+ foreach ($this->css as $medium => $value)
81
  {
82
+ foreach ($value as $selector => $value1)
83
+ {
84
+ $this->css[$medium][$selector] = csstidy_optimise::merge_4value_shorthands($this->css[$medium][$selector]);
85
+
86
+ if ($this->parser->get_cfg('optimise_shorthands') < 2) {
87
+ continue;
88
+ }
89
+
90
+ $this->css[$medium][$selector] = csstidy_optimise::merge_bg($this->css[$medium][$selector]);
91
+ if (empty($this->css[$medium][$selector])) {
92
+ unset($this->css[$medium][$selector]);
93
+ }
94
  }
95
  }
96
  }
97
  }
98
+
99
+ /**
100
+ * Optimises values
101
+ * @access public
102
+ * @version 1.0
103
+ */
104
+ function value()
 
 
 
 
 
 
105
  {
106
+ $shorthands =& $GLOBALS['csstidy']['shorthands'];
107
+
108
+ // optimise shorthand properties
109
+ if(isset($shorthands[$this->property]))
110
  {
111
+ $temp = csstidy_optimise::shorthand($this->value); // FIXME - move
112
+ if($temp != $this->value)
113
+ {
114
+ $this->parser->log('Optimised shorthand notation ('.$this->property.'): Changed "'.$this->value.'" to "'.$temp.'"','Information');
115
+ }
116
+ $this->value = $temp;
117
  }
118
+
119
+ // Remove whitespace at ! important
120
+ if($this->value != $this->compress_important($this->value))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  {
122
+ $this->parser->log('Optimised !important','Information');
123
  }
124
  }
125
+
126
+ /**
127
+ * Optimises shorthands
128
+ * @access public
129
+ * @version 1.0
130
+ */
131
+ function shorthands()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  {
133
+ $shorthands =& $GLOBALS['csstidy']['shorthands'];
134
+
135
+ if(!$this->parser->get_cfg('optimise_shorthands') || $this->parser->get_cfg('preserve_css')) {
136
+ return;
137
  }
138
+
139
+ if($this->property == 'background' && $this->parser->get_cfg('optimise_shorthands') > 1)
140
  {
141
+ unset($this->css[$this->at][$this->selector]['background']);
142
+ $this->parser->merge_css_blocks($this->at,$this->selector,csstidy_optimise::dissolve_short_bg($this->value));
 
 
 
 
 
 
 
 
 
 
143
  }
144
+ if(isset($shorthands[$this->property]))
 
 
 
 
 
145
  {
146
+ $this->parser->merge_css_blocks($this->at,$this->selector,csstidy_optimise::dissolve_4value_shorthands($this->property,$this->value));
147
+ if(is_array($shorthands[$this->property]))
148
+ {
149
+ unset($this->css[$this->at][$this->selector][$this->property]);
150
  }
 
151
  }
152
  }
153
+
154
+ /**
155
+ * Optimises a sub-value
156
+ * @access public
157
+ * @version 1.0
158
+ */
159
+ function subvalue()
 
 
 
 
 
 
 
160
  {
161
+ $replace_colors =& $GLOBALS['csstidy']['replace_colors'];
162
+
163
+ $this->sub_value = trim($this->sub_value);
164
+ if($this->sub_value == '') // caution : '0'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  {
166
+ return;
167
  }
168
+
169
+ $important = '';
170
+ if(csstidy::is_important($this->sub_value))
171
  {
172
+ $important = '!important';
173
  }
174
+ $this->sub_value = csstidy::gvw_important($this->sub_value);
175
+
176
+ // Compress font-weight
177
+ if($this->property == 'font-weight' && $this->parser->get_cfg('compress_font-weight'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  {
179
+ if($this->sub_value == 'bold')
 
180
  {
181
+ $this->sub_value = '700';
182
+ $this->parser->log('Optimised font-weight: Changed "bold" to "700"','Information');
183
+ }
184
+ else if($this->sub_value == 'normal')
185
+ {
186
+ $this->sub_value = '400';
187
+ $this->parser->log('Optimised font-weight: Changed "normal" to "400"','Information');
188
  }
 
189
  }
190
+
191
+ $temp = $this->compress_numbers($this->sub_value);
192
+ if($temp != $this->sub_value)
193
  {
194
+ if(strlen($temp) > strlen($this->sub_value)) {
195
+ $this->parser->log('Fixed invalid number: Changed "'.$this->sub_value.'" to "'.$temp.'"','Warning');
196
  } else {
197
+ $this->parser->log('Optimised number: Changed "'.$this->sub_value.'" to "'.$temp.'"','Information');
198
  }
199
+ $this->sub_value = $temp;
200
  }
201
+ if($this->parser->get_cfg('compress_colors'))
 
 
 
 
 
 
 
 
 
 
 
 
202
  {
203
+ $temp = $this->cut_color($this->sub_value);
204
+ if($temp !== $this->sub_value)
205
+ {
206
+ if(isset($replace_colors[$this->sub_value])) {
207
+ $this->parser->log('Fixed invalid color name: Changed "'.$this->sub_value.'" to "'.$temp.'"','Warning');
208
+ } else {
209
+ $this->parser->log('Optimised color: Changed "'.$this->sub_value.'" to "'.$temp.'"','Information');
210
+ }
211
+ $this->sub_value = $temp;
212
+ }
213
  }
214
+ $this->sub_value .= $important;
215
  }
216
+
217
+ /**
218
+ * Compresses shorthand values. Example: margin:1px 1px 1px 1px -> margin:1px
219
+ * @param string $value
220
+ * @access public
221
+ * @return string
222
+ * @version 1.0
223
+ */
224
+ function shorthand($value)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  {
226
+ $important = '';
227
+ if(csstidy::is_important($value))
228
  {
229
+ $values = csstidy::gvw_important($value);
230
+ $important = '!important';
231
  }
232
+ else $values = $value;
233
+
234
+ $values = explode(' ',$values);
235
+ switch(count($values))
 
 
 
 
236
  {
237
+ case 4:
238
+ if($values[0] == $values[1] && $values[0] == $values[2] && $values[0] == $values[3])
 
 
 
 
239
  {
240
+ return $values[0].$important;
 
 
 
 
 
241
  }
242
+ elseif($values[1] == $values[3] && $values[0] == $values[2])
243
  {
244
+ return $values[0].' '.$values[1].$important;
245
  }
246
+ elseif($values[1] == $values[3])
247
  {
248
+ return $values[0].' '.$values[1].' '.$values[2].$important;
249
  }
250
+ break;
251
+
252
+ case 3:
253
+ if($values[0] == $values[1] && $values[0] == $values[2])
254
+ {
255
+ return $values[0].$important;
 
256
  }
257
+ elseif($values[0] == $values[2])
258
+ {
259
+ return $values[0].' '.$values[1].$important;
260
+ }
261
+ break;
262
+
263
+ case 2:
264
+ if($values[0] == $values[1])
265
+ {
266
+ return $values[0].$important;
267
+ }
268
+ break;
269
  }
270
+
271
+ return $value;
272
  }
273
+
274
+ /**
275
+ * Removes unnecessary whitespace in ! important
276
+ * @param string $string
277
+ * @return string
278
+ * @access public
279
+ * @version 1.1
280
+ */
281
+ function compress_important(&$string)
 
 
 
 
 
 
 
282
  {
283
+ if(csstidy::is_important($string))
284
  {
285
+ $string = csstidy::gvw_important($string) . '!important';
286
+ }
287
+ return $string;
288
+ }
289
+
290
+ /**
291
+ * Color compression function. Converts all rgb() values to #-values and uses the short-form if possible. Also replaces 4 color names by #-values.
292
+ * @param string $color
293
+ * @return string
294
+ * @version 1.1
295
+ */
296
+ function cut_color($color)
297
+ {
298
+ $replace_colors =& $GLOBALS['csstidy']['replace_colors'];
299
+
300
+ // rgb(0,0,0) -> #000000 (or #000 in this case later)
301
+ if(strtolower(substr($color,0,4)) == 'rgb(')
302
  {
303
+ $color_tmp = substr($color,4,strlen($color)-5);
304
+ $color_tmp = explode(',',$color_tmp);
305
+ for ( $i = 0; $i < count($color_tmp); $i++ )
306
  {
307
+ $color_tmp[$i] = trim ($color_tmp[$i]);
308
+ if(substr($color_tmp[$i],-1) == '%')
309
+ {
310
+ $color_tmp[$i] = round((255*$color_tmp[$i])/100);
311
+ }
312
+ if($color_tmp[$i]>255) $color_tmp[$i] = 255;
313
  }
314
+ $color = '#';
315
+ for ($i = 0; $i < 3; $i++ )
316
  {
317
+ if($color_tmp[$i]<16) {
318
+ $color .= '0' . dechex($color_tmp[$i]);
319
+ } else {
320
+ $color .= dechex($color_tmp[$i]);
321
+ }
322
  }
323
  }
324
+
325
+ // Fix bad color names
326
+ if(isset($replace_colors[strtolower($color)]))
327
  {
328
+ $color = $replace_colors[strtolower($color)];
329
+ }
330
+
331
+ // #aabbcc -> #abc
332
+ if(strlen($color) == 7)
333
+ {
334
+ $color_temp = strtolower($color);
335
+ if($color_temp{0} == '#' && $color_temp{1} == $color_temp{2} && $color_temp{3} == $color_temp{4} && $color_temp{5} == $color_temp{6})
336
  {
337
+ $color = '#'.$color{1}.$color{3}.$color{5};
 
338
  }
 
339
  }
340
+
341
+ switch(strtolower($color))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  {
343
+ /* color name -> hex code */
344
+ case 'black': return '#000';
345
+ case 'fuchsia': return '#F0F';
346
+ case 'white': return '#FFF';
347
+ case 'yellow': return '#FF0';
348
+
349
+ /* hex code -> color name */
350
+ case '#800000': return 'maroon';
351
+ case '#ffa500': return 'orange';
352
+ case '#808000': return 'olive';
353
+ case '#800080': return 'purple';
354
+ case '#008000': return 'green';
355
+ case '#000080': return 'navy';
356
+ case '#008080': return 'teal';
357
+ case '#c0c0c0': return 'silver';
358
+ case '#808080': return 'gray';
359
+ case '#f00': return 'red';
360
+ }
361
+
362
+ return $color;
363
+ }
364
+
365
+ /**
366
+ * Compresses numbers (ie. 1.0 becomes 1 or 1.100 becomes 1.1 )
367
+ * @param string $subvalue
368
+ * @return string
369
+ * @version 1.2
370
+ */
371
+ function compress_numbers($subvalue)
372
+ {
373
+ $units =& $GLOBALS['csstidy']['units'];
374
+ $unit_values =& $GLOBALS['csstidy']['unit_values'];
375
+ $color_values =& $GLOBALS['csstidy']['color_values'];
376
+
377
+ // for font:1em/1em sans-serif...;
378
+ if($this->property == 'font')
379
  {
380
+ $temp = explode('/',$subvalue);
381
  }
382
+ else
 
 
 
383
  {
384
+ $temp = array($subvalue);
385
  }
386
+ for ($l = 0; $l < count($temp); $l++)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
  {
388
+ // continue if no numeric value
389
+ if (!(strlen($temp[$l]) > 0 && ( is_numeric($temp[$l]{0}) || $temp[$l]{0} == '+' || $temp[$l]{0} == '-' ) ))
390
  {
391
+ continue;
 
 
 
 
 
 
392
  }
393
+
394
+ // Fix bad colors
395
+ if (in_array($this->property, $color_values))
396
  {
397
+ $temp[$l] = '#'.$temp[$l];
398
  }
399
+
400
+ if (floatval($temp[$l]) == 0)
 
 
401
  {
402
+ $temp[$l] = '0';
403
  }
404
+ else
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  {
406
+ $unit_found = FALSE;
407
+ for ($m = 0, $size_4 = count($units); $m < $size_4; $m++)
408
  {
409
+ if (strpos(strtolower($temp[$l]),$units[$m]) !== FALSE)
410
+ {
411
+ $temp[$l] = floatval($temp[$l]).$units[$m];
412
+ $unit_found = TRUE;
413
+ break;
414
+ }
415
  }
416
+ if (!$unit_found && in_array($this->property,$unit_values,TRUE))
417
  {
418
+ $temp[$l] = floatval($temp[$l]).'px';
419
+ }
420
+ else if (!$unit_found)
421
+ {
422
+ $temp[$l] = floatval($temp[$l]);
423
+ }
424
+ // Remove leading zero
425
+ if (abs(floatval($temp[$l])) < 1) {
426
+ if (floatval($temp[$l]) < 0) {
427
+ $temp[$l] = '-' . substr($temp[$l], 2);
428
+ } else {
429
+ $temp[$l] = substr($temp[$l], 1);
430
+ }
431
  }
 
432
  }
 
433
  }
434
+
435
+ return ((count($temp) > 1) ? $temp[0].'/'.$temp[1] : $temp[0]);
436
+ }
437
+
438
+ /**
439
+ * Merges selectors with same properties. Example: a{color:red} b{color:red} -> a,b{color:red}
440
+ * Very basic and has at least one bug. Hopefully there is a replacement soon.
441
+ * @param array $array
442
+ * @return array
443
+ * @access public
444
+ * @version 1.2
445
+ */
446
+ function merge_selectors(&$array)
447
+ {
448
+ $css = $array;
449
+ foreach($css as $key => $value)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
  {
451
+ if(!isset($css[$key]))
452
  {
453
+ continue;
 
454
  }
455
+ $newsel = '';
456
+
457
+ // Check if properties also exist in another selector
458
+ $keys = array();
459
+ // PHP bug (?) without $css = $array; here
460
+ foreach($css as $selector => $vali)
461
  {
462
+ if($selector == $key)
463
+ {
464
+ continue;
465
+ }
466
+
467
+ if($css[$key] === $vali)
468
+ {
469
+ $keys[] = $selector;
470
+ }
471
  }
472
+
473
+ if(!empty($keys))
474
  {
475
+ $newsel = $key;
476
+ unset($css[$key]);
477
+ foreach($keys as $selector)
478
+ {
479
+ unset($css[$selector]);
480
+ $newsel .= ','.$selector;
481
+ }
482
+ $css[$newsel] = $value;
483
  }
484
+ }
485
+ $array = $css;
486
+ }
487
+
488
+ /**
489
+ * Dissolves properties like padding:10px 10px 10px to padding-top:10px;padding-bottom:10px;...
490
+ * @param string $property
491
+ * @param string $value
492
+ * @return array
493
+ * @version 1.0
494
+ * @see merge_4value_shorthands()
495
+ */
496
+ function dissolve_4value_shorthands($property,$value)
497
+ {
498
+ $shorthands =& $GLOBALS['csstidy']['shorthands'];
499
+ if(!is_array($shorthands[$property]))
500
+ {
501
+ $return[$property] = $value;
502
+ return $return;
503
+ }
504
+
505
+ $important = '';
506
+ if(csstidy::is_important($value))
507
+ {
508
+ $value = csstidy::gvw_important($value);
509
+ $important = '!important';
510
+ }
511
+ $values = explode(' ',$value);
512
+
513
+
514
+ $return = array();
515
+ if(count($values) == 4)
516
+ {
517
+ for($i=0;$i<4;$i++)
518
  {
519
+ $return[$shorthands[$property][$i]] = $values[$i].$important;
 
520
  }
521
+ }
522
+ elseif(count($values) == 3)
523
+ {
524
+ $return[$shorthands[$property][0]] = $values[0].$important;
525
+ $return[$shorthands[$property][1]] = $values[1].$important;
526
+ $return[$shorthands[$property][3]] = $values[1].$important;
527
+ $return[$shorthands[$property][2]] = $values[2].$important;
528
+ }
529
+ elseif(count($values) == 2)
530
+ {
531
+ for($i=0;$i<4;$i++)
532
  {
533
+ $return[$shorthands[$property][$i]] = (($i % 2 != 0)) ? $values[1].$important : $values[0].$important;
534
  }
535
+ }
536
+ else
537
+ {
538
+ for($i=0;$i<4;$i++)
539
  {
540
+ $return[$shorthands[$property][$i]] = $values[0].$important;
541
  }
542
+ }
543
+
544
+ return $return;
545
+ }
546
+
547
+ /**
548
+ * Explodes a string as explode() does, however, not if $sep is escaped or within a string.
549
+ * @param string $sep seperator
550
+ * @param string $string
551
+ * @return array
552
+ * @version 1.0
553
+ */
554
+ function explode_ws($sep,$string)
555
+ {
556
+ $status = 'st';
557
+ $to = '';
558
+
559
+ $output = array();
560
+ $num = 0;
561
+ for($i = 0, $len = strlen($string);$i < $len; $i++)
562
+ {
563
+ switch($status)
564
  {
565
+ case 'st':
566
+ if($string{$i} == $sep && !csstidy::escaped($string,$i))
567
+ {
568
+ ++$num;
569
+ }
570
+ elseif($string{$i} == '"' || $string{$i} == '\'' || $string{$i} == '(' && !csstidy::escaped($string,$i))
571
+ {
572
+ $status = 'str';
573
+ $to = ($string{$i} == '(') ? ')' : $string{$i};
574
+ (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
575
+ }
576
+ else
577
+ {
578
+ (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
579
+ }
580
+ break;
581
+
582
+ case 'str':
583
+ if($string{$i} == $to && !csstidy::escaped($string,$i))
584
+ {
585
+ $status = 'st';
586
+ }
587
+ (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
588
+ break;
589
  }
590
+ }
591
+
592
+ if(isset($output[0]))
593
+ {
594
+ return $output;
595
+ }
596
+ else
597
+ {
598
+ return array($output);
599
+ }
600
+ }
601
+
602
+ /**
603
+ * Merges Shorthand properties again, the opposite of dissolve_4value_shorthands()
604
+ * @param array $array
605
+ * @return array
606
+ * @version 1.2
607
+ * @see dissolve_4value_shorthands()
608
+ */
609
+ function merge_4value_shorthands($array)
610
+ {
611
+ $return = $array;
612
+ $shorthands =& $GLOBALS['csstidy']['shorthands'];
613
+
614
+ foreach($shorthands as $key => $value)
615
+ {
616
+ if(isset($array[$value[0]]) && isset($array[$value[1]])
617
+ && isset($array[$value[2]]) && isset($array[$value[3]]) && $value !== 0)
618
  {
619
+ $return[$key] = '';
620
+
621
+ $important = '';
622
+ for($i = 0; $i < 4; $i++)
623
+ {
624
+ $val = $array[$value[$i]];
625
+ if(csstidy::is_important($val))
626
+ {
627
+ $important = '!important';
628
+ $return[$key] .= csstidy::gvw_important($val).' ';
629
+ }
630
+ else
631
+ {
632
+ $return[$key] .= $val.' ';
633
+ }
634
+ unset($return[$value[$i]]);
635
+ }
636
+ $return[$key] = csstidy_optimise::shorthand(trim($return[$key].$important));
637
  }
638
  }
639
+ return $return;
640
  }
641
+
642
+ /**
643
+ * Dissolve background property
644
+ * @param string $str_value
645
+ * @return array
646
+ * @version 1.0
647
+ * @see merge_bg()
648
+ * @todo full CSS 3 compliance
649
+ */
650
+ function dissolve_short_bg($str_value)
651
+ {
652
+ $background_prop_default =& $GLOBALS['csstidy']['background_prop_default'];
653
+ $repeat = array('repeat','repeat-x','repeat-y','no-repeat','space');
654
+ $attachment = array('scroll','fixed','local');
655
+ $clip = array('border','padding');
656
+ $origin = array('border','padding','content');
657
+ $pos = array('top','center','bottom','left','right');
658
+ $important = '';
659
+ $return = array('background-image' => NULL,'background-size' => NULL,'background-repeat' => NULL,'background-position' => NULL,'background-attachment'=>NULL,'background-clip' => NULL,'background-origin' => NULL,'background-color' => NULL);
660
+
661
+ if(csstidy::is_important($str_value))
662
  {
663
+ $important = ' !important';
664
+ $str_value = csstidy::gvw_important($str_value);
665
  }
666
+
667
+ $str_value = csstidy_optimise::explode_ws(',',$str_value);
668
+ for($i = 0; $i < count($str_value); $i++)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
669
  {
670
+ $have['clip'] = FALSE; $have['pos'] = FALSE;
671
+ $have['color'] = FALSE; $have['bg'] = FALSE;
672
+
673
+ $str_value[$i] = csstidy_optimise::explode_ws(' ',trim($str_value[$i]));
674
+
675
+ for($j = 0; $j < count($str_value[$i]); $j++)
 
 
 
 
 
 
676
  {
677
+ if($have['bg'] === FALSE && (substr($str_value[$i][$j],0,4) == 'url(' || $str_value[$i][$j] === 'none'))
678
+ {
679
+ $return['background-image'] .= $str_value[$i][$j].',';
680
+ $have['bg'] = TRUE;
681
+ }
682
+ elseif(in_array($str_value[$i][$j],$repeat,TRUE))
683
+ {
684
+ $return['background-repeat'] .= $str_value[$i][$j].',';
685
+ }
686
+ elseif(in_array($str_value[$i][$j],$attachment,TRUE))
687
+ {
688
+ $return['background-attachment'] .= $str_value[$i][$j].',';
689
+ }
690
+ elseif(in_array($str_value[$i][$j],$clip,TRUE) && !$have['clip'])
691
+ {
692
+ $return['background-clip'] .= $str_value[$i][$j].',';
693
+ $have['clip'] = TRUE;
694
+ }
695
+ elseif(in_array($str_value[$i][$j],$origin,TRUE))
696
+ {
697
+ $return['background-origin'] .= $str_value[$i][$j].',';
698
+ }
699
+ elseif($str_value[$i][$j]{0} == '(')
700
+ {
701
+ $return['background-size'] .= substr($str_value[$i][$j],1,-1).',';
702
+ }
703
+ elseif(in_array($str_value[$i][$j],$pos,TRUE) || is_numeric($str_value[$i][$j]{0}) || $str_value[$i][$j]{0} === NULL)
704
+ {
705
+ $return['background-position'] .= $str_value[$i][$j];
706
+ if(!$have['pos']) $return['background-position'] .= ' '; else $return['background-position'].= ',';
707
+ $have['pos'] = TRUE;
708
+ }
709
+ elseif(!$have['color'])
710
+ {
711
+ $return['background-color'] .= $str_value[$i][$j].',';
712
+ $have['color'] = TRUE;
713
+ }
714
  }
715
+ }
716
+
717
+ foreach($background_prop_default as $bg_prop => $default_value)
718
+ {
719
+ if($return[$bg_prop] !== NULL)
720
  {
721
+ $return[$bg_prop] = substr($return[$bg_prop],0,-1).$important;
722
  }
723
+ else $return[$bg_prop] = $default_value.$important;
724
+ }
725
+ return $return;
726
+ }
727
+
728
+ /**
729
+ * Merges all background properties
730
+ * @param array $input_css
731
+ * @return array
732
+ * @version 1.0
733
+ * @see dissolve_short_bg()
734
+ * @todo full CSS 3 compliance
735
+ */
736
+ function merge_bg($input_css)
737
+ {
738
+ $background_prop_default =& $GLOBALS['csstidy']['background_prop_default'];
739
+ // Max number of background images. CSS3 not yet fully implemented
740
+ $number_of_values = @max(count(csstidy_optimise::explode_ws(',',$input_css['background-image'])),count(csstidy_optimise::explode_ws(',',$input_css['background-color'])),1);
741
+ // Array with background images to check if BG image exists
742
+ $bg_img_array = @csstidy_optimise::explode_ws(',',csstidy::gvw_important($input_css['background-image']));
743
+ $new_bg_value = '';
744
+ $important = '';
745
+
746
+ for($i = 0; $i < $number_of_values; $i++)
747
+ {
748
+ foreach($background_prop_default as $bg_property => $default_value)
749
  {
750
+ // Skip if property does not exist
751
+ if(!isset($input_css[$bg_property]))
752
  {
753
+ continue;
754
  }
755
+
756
+ $cur_value = $input_css[$bg_property];
757
+
758
+ // Skip some properties if there is no background image
759
+ if((!isset($bg_img_array[$i]) || $bg_img_array[$i] === 'none')
760
+ && ($bg_property === 'background-size' || $bg_property === 'background-position'
761
+ || $bg_property === 'background-attachment' || $bg_property === 'background-repeat'))
762
+ {
763
+ continue;
764
+ }
765
+
766
+ // Remove !important
767
+ if(csstidy::is_important($cur_value))
768
+ {
769
+ $important = ' !important';
770
+ $cur_value = csstidy::gvw_important($cur_value);
771
+ }
772
+
773
+ // Do not add default values
774
+ if($cur_value === $default_value)
775
+ {
776
+ continue;
777
+ }
778
+
779
+ $temp = csstidy_optimise::explode_ws(',',$cur_value);
780
+
781
+ if(isset($temp[$i]))
782
  {
783
+ if($bg_property == 'background-size')
784
+ {
785
+ $new_bg_value .= '('.$temp[$i].') ';
786
+ }
787
+ else
788
+ {
789
+ $new_bg_value .= $temp[$i].' ';
790
+ }
791
  }
792
  }
793
+
794
+ $new_bg_value = trim($new_bg_value);
795
+ if($i != $number_of_values-1) $new_bg_value .= ',';
796
  }
797
+
798
+ // Delete all background-properties
799
+ foreach($background_prop_default as $bg_property => $default_value)
800
+ {
801
+ unset($input_css[$bg_property]);
802
+ }
803
+
804
+ // Add new background property
805
+ if($new_bg_value !== '') $input_css['background'] = $new_bg_value.$important;
806
+
807
+ return $input_css;
808
  }
809
+ }
 
 
 
 
 
810
  }
811
  ?>
css/CSSTidy/class.csstidy_print.php CHANGED
@@ -35,314 +35,315 @@
35
  * @author Florian Schmitz (floele at gmail dot com) 2005-2006
36
  * @version 1.0
37
  */
38
-
39
- class csstidy_print
40
- {
41
- /**
42
- * Saves the input CSS string
43
- * @var string
44
- * @access private
45
- */
46
- var $input_css = '';
47
-
48
- /**
49
- * Saves the formatted CSS string
50
- * @var string
51
- * @access public
52
- */
53
- var $output_css = '';
54
-
55
- /**
56
- * Saves the formatted CSS string (plain text)
57
- * @var string
58
- * @access public
59
- */
60
- var $output_css_plain = '';
61
-
62
- /**
63
- * Constructor
64
- * @param array $css contains the class csstidy
65
- * @access private
66
- * @version 1.0
67
- */
68
- function __construct(&$css)
69
- {
70
- $this->parser =& $css;
71
- $this->css =& $css->css;
72
- $this->template =& $css->template;
73
- $this->tokens =& $css->tokens;
74
- $this->charset =& $css->charset;
75
- $this->import =& $css->import;
76
- $this->namespace =& $css->namespace;
77
- }
78
-
79
- /**
80
- * Resets output_css and output_css_plain (new css code)
81
- * @access private
82
- * @version 1.0
83
- */
84
- function _reset()
85
- {
86
- $this->output_css = '';
87
- $this->output_css_plain = '';
88
- }
89
-
90
- /**
91
- * Returns the CSS code as plain text
92
- * @return string
93
- * @access public
94
- * @version 1.0
95
- */
96
- function plain()
97
- {
98
- $this->_print(true);
99
- return $this->output_css_plain;
100
- }
101
-
102
- /**
103
- * Returns the formatted CSS code
104
- * @return string
105
- * @access public
106
- * @version 1.0
107
- */
108
- function formatted()
109
  {
110
- $this->_print(false);
111
- return $this->output_css;
112
- }
113
-
114
- /**
115
- * Returns the formatted CSS Code and saves it into $this->output_css and $this->output_css_plain
116
- * @param bool $plain plain text or not
117
- * @access private
118
- * @version 2.0
119
- */
120
- function _print($plain = false)
121
- {
122
- if ($this->output_css && $this->output_css_plain) {
123
- return;
124
- }
125
-
126
- $output = '';
127
- if (!$this->parser->get_cfg('preserve_css')) {
128
- $this->_convert_raw_css();
129
- }
130
-
131
- $template =& $this->template;
132
-
133
- if ($plain) {
134
- $template = array_map('strip_tags', $template);
135
- }
136
-
137
- if ($this->parser->get_cfg('timestamp')) {
138
- array_unshift($this->tokens, array(COMMENT, ' CSSTidy ' . $this->parser->version . ': ' . date('r') . ' '));
139
- }
140
-
141
- if (!empty($this->charset)) {
142
- $output .= $template[0].'@charset '.$template[5].$this->charset.$template[6];
143
- }
144
-
145
- if (!empty($this->import)) {
146
- for ($i = 0, $size = count($this->import); $i < $size; $i ++) {
147
- $output .= $template[0].'@import '.$template[5].$this->import[$i].$template[6];
148
- }
149
- }
150
-
151
- if (!empty($this->namespace)) {
152
- $output .= $template[0].'@namespace '.$template[5].$this->namespace.$template[6];
153
  }
154
-
155
- $output .= $template[13];
156
- $in_at_out = '';
157
- $out =& $output;
158
-
159
- foreach ($this->tokens as $key => $token)
 
160
  {
161
- switch ($token[0])
162
- {
163
- case AT_START:
164
- $out .= $template[0].$this->_htmlsp($token[1], $plain).$template[1];
165
- $out =& $in_at_out;
166
- break;
167
-
168
- case SEL_START:
169
- if($this->parser->get_cfg('lowercase_s')) $token[1] = strtolower($token[1]);
170
- $out .= ($token[1]{0} !== '@') ? $template[2].$this->_htmlsp($token[1], $plain) : $template[0].$this->_htmlsp($token[1], $plain);
171
- $out .= $template[3];
172
- break;
173
-
174
- case PROPERTY:
175
- if($this->parser->get_cfg('case_properties') == 2) $token[1] = strtoupper($token[1]);
176
- if($this->parser->get_cfg('case_properties') == 1) $token[1] = strtolower($token[1]);
177
- $out .= $template[4] . $this->_htmlsp($token[1], $plain) . ':' . $template[5];
178
- break;
179
-
180
- case VALUE:
181
- $out .= $this->_htmlsp($token[1], $plain);
182
- if($this->_seeknocomment($key, 1) == SEL_END && $this->parser->get_cfg('remove_last_;')) {
183
- $out .= str_replace(';', '', $template[6]);
184
- } else {
185
- $out .= $template[6];
186
- }
187
- break;
188
-
189
- case SEL_END:
190
- $out .= $template[7];
191
- if($this->_seeknocomment($key, 1) != AT_END) $out .= $template[8];
192
- break;
193
-
194
- case AT_END:
195
- $out =& $output;
196
- $out .= $template[10] . str_replace("\n", "\n" . $template[10], $in_at_out);
197
- $in_at_out = '';
198
- $out .= $template[9];
199
- break;
200
-
201
- case COMMENT:
202
- $out .= $template[11] . '/*' . $this->_htmlsp($token[1], $plain) . '*/' . $template[12];
203
- break;
204
- }
205
  }
206
-
207
- $output = trim($output);
208
-
209
- if (!$plain) {
210
- $this->output_css = $output;
 
 
 
 
211
  $this->_print(true);
212
- } else {
213
- $this->output_css_plain = $output;
214
  }
215
- }
216
-
217
- /**
218
- * Gets the next token type which is $move away from $key, excluding comments
219
- * @param integer $key current position
220
- * @param integer $move move this far
221
- * @return mixed a token type
222
- * @access private
223
- * @version 1.0
224
- */
225
- function _seeknocomment($key, $move) {
226
- $go = ($move > 0) ? 1 : -1;
227
- for ($i = $key + 1; abs($key-$i)-1 < abs($move); $i += $go) {
228
- if (!isset($this->tokens[$i])) {
 
 
 
 
 
 
 
 
229
  return;
230
  }
231
- if ($this->tokens[$i][0] == COMMENT) {
232
- $move += 1;
233
- continue;
 
234
  }
235
- return $this->tokens[$i][0];
236
- }
237
- }
238
-
239
- /**
240
- * Converts $this->css array to a raw array ($this->tokens)
241
- * @access private
242
- * @version 1.0
243
- */
244
- function _convert_raw_css()
245
- {
246
- $this->tokens = array();
247
-
248
- foreach ($this->css as $medium => $val)
249
- {
250
- if ($this->parser->get_cfg('sort_selectors')) ksort($val);
251
- if ($medium != DEFAULT_AT) {
252
- $this->parser->_add_token(AT_START, $medium, true);
253
  }
254
-
255
- foreach ($val as $selector => $vali)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  {
257
- if ($this->parser->get_cfg('sort_properties')) ksort($vali);
258
- $this->parser->_add_token(SEL_START, $selector, true);
259
-
260
- foreach ($vali as $property => $valj)
261
  {
262
- $this->parser->_add_token(PROPERTY, $property, true);
263
- $this->parser->_add_token(VALUE, $valj, true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  }
265
-
266
- $this->parser->_add_token(SEL_END, $selector, true);
267
  }
268
-
269
- if ($medium != DEFAULT_AT) {
270
- $this->parser->_add_token(AT_END, $medium, true);
 
 
 
 
 
271
  }
272
  }
273
- }
274
-
275
- /**
276
- * Same as htmlspecialchars, only that chars are not replaced if $plain !== true. This makes print_code() cleaner.
277
- * @param string $string
278
- * @param bool $plain
279
- * @return string
280
- * @see csstidy_print::_print()
281
- * @access private
282
- * @version 1.0
283
- */
284
- function _htmlsp($string, $plain)
285
- {
286
- if (!$plain) {
287
- return htmlspecialchars($string);
 
 
 
 
 
 
288
  }
289
- return $string;
290
- }
291
-
292
- /**
293
- * Get compression ratio
294
- * @access public
295
- * @return float
296
- * @version 1.2
297
- */
298
- function get_ratio()
299
- {
300
- if (!$this->output_css_plain) {
301
- $this->formatted();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  }
303
- return round((strlen($this->input_css) - strlen($this->output_css_plain)) / strlen($this->input_css), 3) * 100;
304
- }
305
-
306
- /**
307
- * Get difference between the old and new code in bytes and prints the code if necessary.
308
- * @access public
309
- * @return string
310
- * @version 1.1
311
- */
312
- function get_diff()
313
- {
314
- if (!$this->output_css_plain) {
315
- $this->formatted();
 
 
 
316
  }
317
-
318
- $diff = strlen($this->output_css_plain) - strlen($this->input_css);
319
-
320
- if ($diff > 0) {
321
- return '+' . $diff;
322
- } elseif ($diff == 0) {
323
- return '+-' . $diff;
 
 
 
 
 
 
324
  }
325
-
326
- return $diff;
327
- }
328
-
329
- /**
330
- * Get the size of either input or output CSS in KB
331
- * @param string $loc default is "output"
332
- * @access public
333
- * @return integer
334
- * @version 1.0
335
- */
336
- function size($loc = 'output')
337
- {
338
- if ($loc == 'output' && !$this->output_css) {
339
- $this->formatted();
 
 
 
 
 
 
 
340
  }
341
-
342
- if ($loc == 'input') {
343
- return (strlen($this->input_css) / 1000);
344
- } else {
345
- return (strlen($this->output_css_plain) / 1000);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  }
347
  }
348
  }
35
  * @author Florian Schmitz (floele at gmail dot com) 2005-2006
36
  * @version 1.0
37
  */
38
+ if (!class_exists('csstidy_print')) {
39
+ class csstidy_print
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  {
41
+ /**
42
+ * Saves the input CSS string
43
+ * @var string
44
+ * @access private
45
+ */
46
+ var $input_css = '';
47
+
48
+ /**
49
+ * Saves the formatted CSS string
50
+ * @var string
51
+ * @access public
52
+ */
53
+ var $output_css = '';
54
+
55
+ /**
56
+ * Saves the formatted CSS string (plain text)
57
+ * @var string
58
+ * @access public
59
+ */
60
+ var $output_css_plain = '';
61
+
62
+ /**
63
+ * Constructor
64
+ * @param array $css contains the class csstidy
65
+ * @access private
66
+ * @version 1.0
67
+ */
68
+ function __construct(&$css)
69
+ {
70
+ $this->parser =& $css;
71
+ $this->css =& $css->css;
72
+ $this->template =& $css->template;
73
+ $this->tokens =& $css->tokens;
74
+ $this->charset =& $css->charset;
75
+ $this->import =& $css->import;
76
+ $this->namespace =& $css->namespace;
 
 
 
 
 
 
 
77
  }
78
+
79
+ /**
80
+ * Resets output_css and output_css_plain (new css code)
81
+ * @access private
82
+ * @version 1.0
83
+ */
84
+ function _reset()
85
  {
86
+ $this->output_css = '';
87
+ $this->output_css_plain = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  }
89
+
90
+ /**
91
+ * Returns the CSS code as plain text
92
+ * @return string
93
+ * @access public
94
+ * @version 1.0
95
+ */
96
+ function plain()
97
+ {
98
  $this->_print(true);
99
+ return $this->output_css_plain;
 
100
  }
101
+
102
+ /**
103
+ * Returns the formatted CSS code
104
+ * @return string
105
+ * @access public
106
+ * @version 1.0
107
+ */
108
+ function formatted()
109
+ {
110
+ $this->_print(false);
111
+ return $this->output_css;
112
+ }
113
+
114
+ /**
115
+ * Returns the formatted CSS Code and saves it into $this->output_css and $this->output_css_plain
116
+ * @param bool $plain plain text or not
117
+ * @access private
118
+ * @version 2.0
119
+ */
120
+ function _print($plain = false)
121
+ {
122
+ if ($this->output_css && $this->output_css_plain) {
123
  return;
124
  }
125
+
126
+ $output = '';
127
+ if (!$this->parser->get_cfg('preserve_css')) {
128
+ $this->_convert_raw_css();
129
  }
130
+
131
+ $template =& $this->template;
132
+
133
+ if ($plain) {
134
+ $template = array_map('strip_tags', $template);
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  }
136
+
137
+ if ($this->parser->get_cfg('timestamp')) {
138
+ array_unshift($this->tokens, array(COMMENT, ' CSSTidy ' . $this->parser->version . ': ' . date('r') . ' '));
139
+ }
140
+
141
+ if (!empty($this->charset)) {
142
+ $output .= $template[0].'@charset '.$template[5].$this->charset.$template[6];
143
+ }
144
+
145
+ if (!empty($this->import)) {
146
+ for ($i = 0, $size = count($this->import); $i < $size; $i ++) {
147
+ $output .= $template[0].'@import '.$template[5].$this->import[$i].$template[6];
148
+ }
149
+ }
150
+
151
+ if (!empty($this->namespace)) {
152
+ $output .= $template[0].'@namespace '.$template[5].$this->namespace.$template[6];
153
+ }
154
+
155
+ $output .= $template[13];
156
+ $in_at_out = '';
157
+ $out =& $output;
158
+
159
+ foreach ($this->tokens as $key => $token)
160
  {
161
+ switch ($token[0])
 
 
 
162
  {
163
+ case AT_START:
164
+ $out .= $template[0].$this->_htmlsp($token[1], $plain).$template[1];
165
+ $out =& $in_at_out;
166
+ break;
167
+
168
+ case SEL_START:
169
+ if($this->parser->get_cfg('lowercase_s')) $token[1] = strtolower($token[1]);
170
+ $out .= ($token[1]{0} !== '@') ? $template[2].$this->_htmlsp($token[1], $plain) : $template[0].$this->_htmlsp($token[1], $plain);
171
+ $out .= $template[3];
172
+ break;
173
+
174
+ case PROPERTY:
175
+ if($this->parser->get_cfg('case_properties') == 2) $token[1] = strtoupper($token[1]);
176
+ if($this->parser->get_cfg('case_properties') == 1) $token[1] = strtolower($token[1]);
177
+ $out .= $template[4] . $this->_htmlsp($token[1], $plain) . ':' . $template[5];
178
+ break;
179
+
180
+ case VALUE:
181
+ $out .= $this->_htmlsp($token[1], $plain);
182
+ if($this->_seeknocomment($key, 1) == SEL_END && $this->parser->get_cfg('remove_last_;')) {
183
+ $out .= str_replace(';', '', $template[6]);
184
+ } else {
185
+ $out .= $template[6];
186
+ }
187
+ break;
188
+
189
+ case SEL_END:
190
+ $out .= $template[7];
191
+ if($this->_seeknocomment($key, 1) != AT_END) $out .= $template[8];
192
+ break;
193
+
194
+ case AT_END:
195
+ $out =& $output;
196
+ $out .= $template[10] . str_replace("\n", "\n" . $template[10], $in_at_out);
197
+ $in_at_out = '';
198
+ $out .= $template[9];
199
+ break;
200
+
201
+ case COMMENT:
202
+ $out .= $template[11] . '/*' . $this->_htmlsp($token[1], $plain) . '*/' . $template[12];
203
+ break;
204
  }
 
 
205
  }
206
+
207
+ $output = trim($output);
208
+
209
+ if (!$plain) {
210
+ $this->output_css = $output;
211
+ $this->_print(true);
212
+ } else {
213
+ $this->output_css_plain = $output;
214
  }
215
  }
216
+
217
+ /**
218
+ * Gets the next token type which is $move away from $key, excluding comments
219
+ * @param integer $key current position
220
+ * @param integer $move move this far
221
+ * @return mixed a token type
222
+ * @access private
223
+ * @version 1.0
224
+ */
225
+ function _seeknocomment($key, $move) {
226
+ $go = ($move > 0) ? 1 : -1;
227
+ for ($i = $key + 1; abs($key-$i)-1 < abs($move); $i += $go) {
228
+ if (!isset($this->tokens[$i])) {
229
+ return;
230
+ }
231
+ if ($this->tokens[$i][0] == COMMENT) {
232
+ $move += 1;
233
+ continue;
234
+ }
235
+ return $this->tokens[$i][0];
236
+ }
237
  }
238
+
239
+ /**
240
+ * Converts $this->css array to a raw array ($this->tokens)
241
+ * @access private
242
+ * @version 1.0
243
+ */
244
+ function _convert_raw_css()
245
+ {
246
+ $this->tokens = array();
247
+
248
+ foreach ($this->css as $medium => $val)
249
+ {
250
+ if ($this->parser->get_cfg('sort_selectors')) ksort($val);
251
+ if ($medium != DEFAULT_AT) {
252
+ $this->parser->_add_token(AT_START, $medium, true);
253
+ }
254
+
255
+ foreach ($val as $selector => $vali)
256
+ {
257
+ if ($this->parser->get_cfg('sort_properties')) ksort($vali);
258
+ $this->parser->_add_token(SEL_START, $selector, true);
259
+
260
+ foreach ($vali as $property => $valj)
261
+ {
262
+ $this->parser->_add_token(PROPERTY, $property, true);
263
+ $this->parser->_add_token(VALUE, $valj, true);
264
+ }
265
+
266
+ $this->parser->_add_token(SEL_END, $selector, true);
267
+ }
268
+
269
+ if ($medium != DEFAULT_AT) {
270
+ $this->parser->_add_token(AT_END, $medium, true);
271
+ }
272
+ }
273
  }
274
+
275
+ /**
276
+ * Same as htmlspecialchars, only that chars are not replaced if $plain !== true. This makes print_code() cleaner.
277
+ * @param string $string
278
+ * @param bool $plain
279
+ * @return string
280
+ * @see csstidy_print::_print()
281
+ * @access private
282
+ * @version 1.0
283
+ */
284
+ function _htmlsp($string, $plain)
285
+ {
286
+ if (!$plain) {
287
+ return htmlspecialchars($string);
288
+ }
289
+ return $string;
290
  }
291
+
292
+ /**
293
+ * Get compression ratio
294
+ * @access public
295
+ * @return float
296
+ * @version 1.2
297
+ */
298
+ function get_ratio()
299
+ {
300
+ if (!$this->output_css_plain) {
301
+ $this->formatted();
302
+ }
303
+ return round((strlen($this->input_css) - strlen($this->output_css_plain)) / strlen($this->input_css), 3) * 100;
304
  }
305
+
306
+ /**
307
+ * Get difference between the old and new code in bytes and prints the code if necessary.
308
+ * @access public
309
+ * @return string
310
+ * @version 1.1
311
+ */
312
+ function get_diff()
313
+ {
314
+ if (!$this->output_css_plain) {
315
+ $this->formatted();
316
+ }
317
+
318
+ $diff = strlen($this->output_css_plain) - strlen($this->input_css);
319
+
320
+ if ($diff > 0) {
321
+ return '+' . $diff;
322
+ } elseif ($diff == 0) {
323
+ return '+-' . $diff;
324
+ }
325
+
326
+ return $diff;
327
  }
328
+
329
+ /**
330
+ * Get the size of either input or output CSS in KB
331
+ * @param string $loc default is "output"
332
+ * @access public
333
+ * @return integer
334
+ * @version 1.0
335
+ */
336
+ function size($loc = 'output')
337
+ {
338
+ if ($loc == 'output' && !$this->output_css) {
339
+ $this->formatted();
340
+ }
341
+
342
+ if ($loc == 'input') {
343
+ return (strlen($this->input_css) / 1000);
344
+ } else {
345
+ return (strlen($this->output_css_plain) / 1000);
346
+ }
347
  }
348
  }
349
  }
html/OptionsPage.php CHANGED
@@ -18,6 +18,7 @@
18
 
19
  $Display_Style = get_option("EWD_UFAQ_Display_Style");
20
  $Color_Block_Shape = get_option("EWD_UFAQ_Color_Block_Shape");
 
21
  $FAQ_Ratings = get_option("EWD_UFAQ_FAQ_Ratings");
22
  $WooCommerce_FAQs = get_option("EWD_UFAQ_WooCommerce_FAQs");
23
  $Use_Product = get_option("EWD_UFAQ_Use_Product");
@@ -349,7 +350,7 @@
349
 
350
  <select name="reveal_effect" <?php if ($UFAQ_Full_Version != "Yes") {echo "disabled";} ?> >
351
  <option value="none" <?php if($Reveal_Effect == "none") {echo "selected=selected";} ?> >None</option>
352
- <option value="blind" <?php if($Reveal_Effect == "blind") {echo "selected=selected";} ?> >Blind</option>
353
  <option value="bounce" <?php if($Reveal_Effect == "bounce") {echo "selected=selected";} ?> >Bounce</option>
354
  <option value="clip" <?php if($Reveal_Effect == "clip") {echo "selected=selected";} ?> >Clip</option>
355
  <option value="drop" <?php if($Reveal_Effect == "drop") {echo "selected=selected";} ?> >Drop</option>
@@ -368,6 +369,15 @@
368
  </fieldset>
369
  </td>
370
  </tr>
 
 
 
 
 
 
 
 
 
371
  </table>
372
 
373
  <br />
18
 
19
  $Display_Style = get_option("EWD_UFAQ_Display_Style");
20
  $Color_Block_Shape = get_option("EWD_UFAQ_Color_Block_Shape");
21
+ $FAQs_Per_Page = get_option("EWD_UFAQ_FAQs_Per_Page");
22
  $FAQ_Ratings = get_option("EWD_UFAQ_FAQ_Ratings");
23
  $WooCommerce_FAQs = get_option("EWD_UFAQ_WooCommerce_FAQs");
24
  $Use_Product = get_option("EWD_UFAQ_Use_Product");
350
 
351
  <select name="reveal_effect" <?php if ($UFAQ_Full_Version != "Yes") {echo "disabled";} ?> >
352
  <option value="none" <?php if($Reveal_Effect == "none") {echo "selected=selected";} ?> >None</option>
353
+ <option value="blind" <?php if($Reveal_Effect == "blind") {echo "selected=selected";} ?> >Blind</option>
354
  <option value="bounce" <?php if($Reveal_Effect == "bounce") {echo "selected=selected";} ?> >Bounce</option>
355
  <option value="clip" <?php if($Reveal_Effect == "clip") {echo "selected=selected";} ?> >Clip</option>
356
  <option value="drop" <?php if($Reveal_Effect == "drop") {echo "selected=selected";} ?> >Drop</option>
369
  </fieldset>
370
  </td>
371
  </tr>
372
+ <!--<tr>
373
+ <th scope="row">FAQs Per Page</th>
374
+ <td>
375
+ <fieldset><legend class="screen-reader-text"><span>FAQ Per Page</span></legend>
376
+ <input type='text' name='faqs_per_page' value='<?php echo $FAQs_Per_Page; ?>' <?php if ($UFAQ_Full_Version != "Yes") {echo "disabled";} ?> size='60'/>
377
+ <p>How many FAQs should be displayed on each page? (Leave blank to display all FAQs)</p>
378
+ </fieldset>
379
+ </td>
380
+ </tr>-->
381
  </table>
382
 
383
  <br />
js/ewd-ufaq-js.js CHANGED
@@ -143,6 +143,10 @@ jQuery(document).ready(function() {
143
  Ufaq_Ajax_Reload();
144
  });
145
 
 
 
 
 
146
  if (typeof(Display_FAQ_ID) != "undefined" && Display_FAQ_ID !== null) {
147
  Display_FAQ_ID_Pos = Display_FAQ_ID.indexOf('-');
148
  Display_FAQ_ID = Display_FAQ_ID.substring(0, Display_FAQ_ID_Pos);
143
  Ufaq_Ajax_Reload();
144
  });
145
 
146
+ if (jQuery('#ufaq-ajax-text-input').length) {
147
+ if (jQuery('#ufaq-ajax-text-input').val() != "") {Ufaq_Ajax_Reload();}
148
+ }
149
+
150
  if (typeof(Display_FAQ_ID) != "undefined" && Display_FAQ_ID !== null) {
151
  Display_FAQ_ID_Pos = Display_FAQ_ID.indexOf('-');
152
  Display_FAQ_ID = Display_FAQ_ID.substring(0, Display_FAQ_ID_Pos);
readme.txt CHANGED
@@ -10,6 +10,7 @@ FAQ plugin that lets you easily create, order and publicize FAQs, insert 3 style
10
 
11
  == Description ==
12
 
 
13
  <a href='http://www.etoilewebdesign.com/ultimate-faq-demo/'>FAQ Demo</a>
14
 
15
  FAQ plugin that lets you create FAQ (frequently asked questions), organize FAQs and publicize your FAQ in no time through your Wordpress admin panel. Select from multiple FAQ styles and FAQ layouts.
@@ -265,16 +266,19 @@ Video 3 - FAQs Ordering
265
  26. FAQ widgets
266
 
267
 
268
-
269
  == Changelog ==
 
 
 
 
270
  = 1.6.7 =
271
  - Fixed the settings page for those using PHP7
272
  - Fixed the faq_id attribute of the select-faq shortcode
273
 
274
  = 1.6.6 =
275
  - Added in a captcha option for the submit question shortcode
276
- - Fixed an HTML validation error
277
-
278
  = 1.6.5 =
279
  - Updated color select sanitizing function
280
 
@@ -610,4 +614,7 @@ Video 3 - FAQs Ordering
610
  - Fix for the FAQ ordering bug
611
 
612
  = 1.0.0 =
613
- - Premium version release, check out our website for all of the details <http://www.etoilewebdesign.com/ultimate-faq/>
 
 
 
10
 
11
  == Description ==
12
 
13
+
14
  <a href='http://www.etoilewebdesign.com/ultimate-faq-demo/'>FAQ Demo</a>
15
 
16
  FAQ plugin that lets you create FAQ (frequently asked questions), organize FAQs and publicize your FAQ in no time through your Wordpress admin panel. Select from multiple FAQ styles and FAQ layouts.
266
  26. FAQ widgets
267
 
268
 
 
269
  == Changelog ==
270
+ = 1.6.8 =
271
+ - Fixed a conflict with other plugins that use CSSTidy for CSS sanitization
272
+ - Added the ability to link to the search shortcode with a term preloaded
273
+
274
  = 1.6.7 =
275
  - Fixed the settings page for those using PHP7
276
  - Fixed the faq_id attribute of the select-faq shortcode
277
 
278
  = 1.6.6 =
279
  - Added in a captcha option for the submit question shortcode
280
+ - Fixed an HTML validation error
281
+
282
  = 1.6.5 =
283
  - Updated color select sanitizing function
284
 
614
  - Fix for the FAQ ordering bug
615
 
616
  = 1.0.0 =
617
+ - Premium version release, check out our website for all of the details <http://www.etoilewebdesign.com/ultimate-faq/>
618
+
619
+
620
+