Ultimate FAQ - Version 1.6.9

Version Description

  • Added in the option to re-order the elements of an FAQ (body, date/author, categories, etc.)
Download this release

Release Info

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

Code changes from version 1.6.8 to 1.6.9

Functions/EWD_UFAQ_Version_Update.php CHANGED
@@ -26,6 +26,22 @@ function EWD_UFAQ_Version_Update() {
26
  }
27
  }
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  if (get_option("EWD_UFAQ_Toggle") == "") {update_option("EWD_UFAQ_Toggle", "Yes");}
30
  if (get_option("EWD_UFAQ_Display_Back_To_Top") == "") {update_option("EWD_UFAQ_Display_Back_To_Top", "No");}
31
  if (get_option("EWD_UFAQ_Comments_On") == "") {update_option("EWD_UFAQ_Comments_On", "No");}
26
  }
27
  }
28
 
29
+ if (get_option("EWD_UFAQ_FAQ_Elements") == "") {
30
+ $FAQ_Elements = array();
31
+ $FAQ_Elements[0] = "Author_Date";
32
+ $FAQ_Elements[1] = "Body";
33
+ $FAQ_Elements[2] = "Custom_Fields";
34
+ $FAQ_Elements[3] = "Categories";
35
+ $FAQ_Elements[4] = "Tags";
36
+ $FAQ_Elements[5] = "Ratings";
37
+ $FAQ_Elements[6] = "Social_Media";
38
+ $FAQ_Elements[7] = "Permalink";
39
+ $FAQ_Elements[8] = "Comments";
40
+ $FAQ_Elements[9] = "Back_To_Top";
41
+
42
+ update_option("EWD_UFAQ_FAQ_Elements", $FAQ_Elements);
43
+ }
44
+
45
  if (get_option("EWD_UFAQ_Toggle") == "") {update_option("EWD_UFAQ_Toggle", "Yes");}
46
  if (get_option("EWD_UFAQ_Display_Back_To_Top") == "") {update_option("EWD_UFAQ_Display_Back_To_Top", "No");}
47
  if (get_option("EWD_UFAQ_Comments_On") == "") {update_option("EWD_UFAQ_Comments_On", "No");}
Functions/Update_Admin_Databases.php CHANGED
@@ -58,6 +58,12 @@ function EWD_UFAQ_UpdateOptions() {
58
  if (isset($_POST['slug_base']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_Slug_Base', $_POST['slug_base']);}
59
  if (isset($_POST['Socialmedia']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_Social_Media', $Social_Media);}
60
 
 
 
 
 
 
 
61
  if (isset($_POST['group_by_category'])) {update_option('EWD_UFAQ_Group_By_Category', sanitize_text_field($_POST['group_by_category']));}
62
  if (isset($_POST['group_by_category_count'])) {update_option('EWD_UFAQ_Group_By_Category_Count', sanitize_text_field($_POST['group_by_category_count']));}
63
  if (isset($_POST['group_by_order_by'])) {update_option('EWD_UFAQ_Group_By_Order_By', sanitize_text_field($_POST['group_by_order_by']));}
58
  if (isset($_POST['slug_base']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_Slug_Base', $_POST['slug_base']);}
59
  if (isset($_POST['Socialmedia']) and $UFAQ_Full_Version == "Yes") {update_option('EWD_UFAQ_Social_Media', $Social_Media);}
60
 
61
+ $FAQ_Elements = array();
62
+ for ($i=0; $i<=9; $i++) {
63
+ $FAQ_Elements[] = $_POST['Element_' . $i];
64
+ }
65
+ if (isset($_POST['Options_Submit'])) {update_option('EWD_UFAQ_FAQ_Elements', $FAQ_Elements);}
66
+
67
  if (isset($_POST['group_by_category'])) {update_option('EWD_UFAQ_Group_By_Category', sanitize_text_field($_POST['group_by_category']));}
68
  if (isset($_POST['group_by_category_count'])) {update_option('EWD_UFAQ_Group_By_Category_Count', sanitize_text_field($_POST['group_by_category_count']));}
69
  if (isset($_POST['group_by_order_by'])) {update_option('EWD_UFAQ_Group_By_Order_By', sanitize_text_field($_POST['group_by_order_by']));}
Main.php CHANGED
@@ -2,19 +2,19 @@
2
  /*
3
  Plugin Name: Ultimate FAQ
4
  Plugin URI: http://www.EtoileWebDesign.com/wordpress-plugins/
5
- Description: A plugin that lets you create FAQs (frequently asked questions), organize them, publicize them, etc.
6
  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.8
11
  */
12
 
13
  global $ewd_ufaq_message;
14
  global $UFAQ_Full_Version;
15
  global $EWD_UFAQ_Version;
16
 
17
- $EWD_UFAQ_Version = '1.6.4';
18
  if (get_option("EWD_UFAQ_Version") == "") {update_option("EWD_UFAQ_Version", $EWD_UFAQ_Version);}
19
 
20
  define( 'EWD_UFAQ_CD_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
2
  /*
3
  Plugin Name: Ultimate FAQ
4
  Plugin URI: http://www.EtoileWebDesign.com/wordpress-plugins/
5
+ Description: FAQ plugin that lets you easily create, order and publicize FAQs using shortcodes, with many unique styles, WooCommerce FAQs and AJAX FAQ search
6
  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.9
11
  */
12
 
13
  global $ewd_ufaq_message;
14
  global $UFAQ_Full_Version;
15
  global $EWD_UFAQ_Version;
16
 
17
+ $EWD_UFAQ_Version = '1.6.9a';
18
  if (get_option("EWD_UFAQ_Version") == "") {update_option("EWD_UFAQ_Version", $EWD_UFAQ_Version);}
19
 
20
  define( 'EWD_UFAQ_CD_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );
Shortcodes/DisplayFAQs.php CHANGED
@@ -25,6 +25,8 @@ function Display_FAQs($atts) {
25
  $Display_All_Answers = get_option("EWD_UFAQ_Display_All_Answers");
26
  $Socialmedia_String = get_option("EWD_UFAQ_Social_Media");
27
  $Socialmedia = explode(",", $Socialmedia_String);
 
 
28
 
29
  $Group_By_Category = get_option("EWD_UFAQ_Group_By_Category");
30
  $Group_By_Category_Count = get_option("EWD_UFAQ_Group_By_Category_Count");
@@ -317,121 +319,129 @@ function Display_FAQs($atts) {
317
  if ($Display_All_Answers != "Yes") {$ReturnString .= " ewd-ufaq-hidden";}
318
  $ReturnString .= "' id='ufaq-body-" . $Unique_ID . "-" . $faq->ID . "-" . $Counter . "' itemprop='suggestedAnswer acceptedAnswer' itemscope itemtype='http://schema.org/Answer'>";
319
 
320
- if ($Display_Author == "Yes" or $Display_Date == "Yes") {
321
- $Display_Author_Value = get_post_meta($faq->ID, "EWD_UFAQ_Post_Author", true);
322
- $Display_Date_Value = get_the_date("", $faq->ID);
323
- $ReturnString .= "<div class='ewd-ufaq-author-date' itemprop='author' itemscope itemtype='http://schema.org/Person'>";
324
- $ReturnString .= $Posted_Label . " " ;
325
- if ($Display_Author == "Yes" and $Display_Author_Value != "") {$ReturnString .= $By_Label . " <span class='ewd-ufaq-author' itemprop='name'>" . $Display_Author_Value . "</span> ";}
326
- if ($Display_Date == "Yes") {$ReturnString .= $On_Label . " <span class='ewd-ufaq-date'>" . $Display_Date_Value . "</span> ";}
327
- $ReturnString .= "</div>";
328
- }
 
329
 
330
- $ReturnString .= "<div class='ewd-ufaq-post-margin ufaq-faq-post' id='ufaq-post-" . $faq->ID . "' itemprop='text'>" . apply_filters('the_content', html_entity_decode($faq->post_content)) . "</div>";
331
-
332
- if (sizeOf($FAQ_Fields_Array) > 0) {
333
- $ReturnString .= "<div class='ufaq-faq-custom-fields' id='ufaq-custom-fields-" . $faq->ID . "'>";
334
- foreach ($FAQ_Fields_Array as $FAQ_Field_Item) {
335
- $Value = get_post_meta($faq->ID, "Custom_Field_" . $FAQ_Field_Item['FieldID'], true);
336
- if ($Hide_Blank_Fields != "Yes" or $Value != "") {
337
- $ReturnString .= "<div class='ufaq-custom-field-label'>" . $FAQ_Field_Item['FieldName'] . ": </div>";
338
- $ReturnString .= "<div class='ufaq-custom-field-value'>&nbsp;";
339
- if ($FAQ_Field_Item['FieldType'] == "file") {$ReturnString .= "<a href='" . $Value . "'>" . substr($Value, strrpos($Value, "/"+1)) . "</a>";}
340
- elseif ($FAQ_Field_Item['FieldType'] == "link") {$ReturnString .= "<a href='" . $Value . "' target='_blank'>" . $Value ."</a>";}
341
- else {$ReturnString .= $Value;}
342
- $ReturnString .= "</div>";
343
- $ReturnString .= "<div class='ewd-ufaq-clear'></div>";
 
 
 
 
344
  }
345
- unset($Value);
346
  }
347
- $ReturnString .= "</div>";
348
- }
349
 
350
- if ($Hide_Categories == "No" and sizeOf($Category_Terms) > 0) {
351
- $ReturnString .= "<div class='ufaq-faq-categories' id='ufaq-categories-" . $faq->ID . "'>";
352
- if ($Category_Label == ""){
353
- if (sizeOf($Category_Terms) > 1) {$ReturnString .= __("Categories: ", 'ultimate-faqs');}
354
- else {$ReturnString .= __("Category: ", 'ultimate-faqs');}}
355
- else {$ReturnString .= $Category_Label . ": ";}
356
- foreach ($Category_Terms as $Category_Term) {
357
- if ($Pretty_Permalinks == "Yes") {$Category_URL = $current_url . "faq-category/" . $Category_Term->slug . "/";}
358
- else {$Category_URL = $current_url . "?include_category=" . $Category_Term->slug;}
359
- $ReturnString .= "<a href='" . $Category_URL ."'>" .$Category_Term->name . "</a>, ";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
360
  }
361
- if (sizeOf($Category_Terms) > 0) {$ReturnString = substr($ReturnString, 0, strlen($ReturnString)-2);}
362
- $ReturnString .= "</div>";
363
- }
364
 
365
- if ($Hide_Tags == "No" and sizeOf($Tag_Terms) > 0) {
366
- $ReturnString .= "<div class='ufaq-faq-tags' id='ufaq-tags-" . $faq->ID . "'>";
367
- if ($Tag_Label == ""){
368
- if (sizeOf($Tag_Terms) > 1) {$ReturnString .= "Tags: ";}
369
- else {$ReturnString .= "Tag: ";}}
370
- else {$ReturnString .= $Tag_Label . ": ";}
371
- foreach ($Tag_Terms as $Tag_Term) {
372
- if ($Pretty_Permalinks == "Yes") {$Tag_URL = $current_url . "faq-tag/" . $Tag_Term->slug . "/";}
373
- else {$Tag_URL = $current_url . "?include_tag=" . $Tag_Term->slug;}
374
- $ReturnString .= "<a href='" . $Tag_URL . "'>" .$Tag_Term->name . "</a>, ";
 
 
 
 
375
  }
376
- if (sizeOf($Tag_Terms) > 0) {$ReturnString = substr($ReturnString, 0, strlen($ReturnString)-2);}
377
- $ReturnString .= "</div>";
378
- }
379
 
380
- if ($FAQ_Ratings == "Yes") {
381
- $Up_Votes = get_post_meta($faq->ID, "FAQ_Up_Votes", true);
382
- if ($Up_Votes == "") {$Up_Votes = 0;}
383
- $Down_Votes = get_post_meta($faq->ID, "FAQ_Down_Votes", true);
384
- if ($Down_Votes == "") {$Down_Votes = 0;}
385
-
386
- $ReturnString .= "<div class='ewd-ufaq-ratings'>";
387
- $ReturnString .= "<div class='ewd-ufaq-ratings-label'>";
388
- $ReturnString .= __("Did you find this FAQ helpful?", 'ultimate-faqs');
389
- $ReturnString .= "</div>";
390
- $ReturnString .= "<div class='ewd-ufaq-rating-button ewd-ufaq-up-vote' data-ratingfaqid='" . $faq->ID . "' itemprop='upvoteCount'>" . $Up_Votes . "</div>";
391
- $ReturnString .= "<div class='ewd-ufaq-rating-button ewd-ufaq-down-vote' data-ratingfaqid='" . $faq->ID . "' itemprop='downvoteCount'>" . $Down_Votes . "</div>";
392
- $ReturnString .= "</div>";
393
- $ReturnString .= "<div class='ewd-ufaq-clear'></div>";
394
- }
 
395
 
396
- if ($Socialmedia[0] != "Blank" and $Socialmedia[0] != "") {
397
- $ReturnString .= "<div class='ufaq-social-links'>Share: ";
398
- $ReturnString .= "<ul class='rrssb-buttons'>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
399
  }
400
- if(in_array("Facebook", $Socialmedia)) {$ReturnString .= EWD_UFAQ_Add_Social_Media_Buttons("Facebook", get_permalink($faq->ID), $faq->post_title);}
401
- if(in_array("Google", $Socialmedia)) {$ReturnString .= EWD_UFAQ_Add_Social_Media_Buttons("Google", $FAQ_Permalink, $faq->post_title);}
402
- if(in_array("Twitter", $Socialmedia)) {$ReturnString .= EWD_UFAQ_Add_Social_Media_Buttons("Twitter", $FAQ_Permalink, $faq->post_title);}
403
- if(in_array("Linkedin", $Socialmedia)) {$ReturnString .= EWD_UFAQ_Add_Social_Media_Buttons("Linkedin", $FAQ_Permalink, $faq->post_title);}
404
- if(in_array("Pinterest", $Socialmedia)) {$ReturnString .= EWD_UFAQ_Add_Social_Media_Buttons("Pinterest", $FAQ_Permalink, $faq->post_title);}
405
- if(in_array("Email", $Socialmedia)) {$ReturnString .= EWD_UFAQ_Add_Social_Media_Buttons("Email", $FAQ_Permalink, $faq->post_title);}
406
- if ($Socialmedia[0] != "Blank" and $Socialmedia[0] != "") {
407
- $ReturnString .= "</ul>";
408
- $ReturnString .= "</div>";
409
- }
410
-
411
- if ($Include_Permalink == "Yes" and $ajax == "No") {
412
- $ReturnString .= "<div class='ufaq-permalink'>" . $Permalink_Label;
413
- $ReturnString .= "<a href='" . $FAQ_Permalink . "'>";
414
- $ReturnString .= "<div class='ufaq-permalink-image'></div>";
415
- $ReturnString .= "</a>";
416
- $ReturnString .= "</div>";
417
- }
418
-
419
- if (comments_open($faq->ID) and $no_comments != "Yes" and $Comments_On == "Yes") {
420
- ob_start();
421
- $Comments = get_comments(array('post_id' => $faq->ID));
422
- wp_list_comments(array(), $Comments);
423
- comment_form(array(), $faq->ID);
424
- $ReturnString .= ob_get_contents();
425
- ob_end_clean();
426
- }
427
-
428
- if ($Display_Back_To_Top == "Yes") {
429
- $ReturnString .= "<div class='ufaq-back-to-top'>";
430
- $ReturnString .= "<a class='ufaq-back-to-top-link'>";
431
- $ReturnString .= $Back_To_Top_Label;
432
- $ReturnString .= "</a>";
433
- $ReturnString .= "</div>";
434
- }
435
 
436
  $ReturnString .= "</div>";
437
  $ReturnString .= "</div>";
25
  $Display_All_Answers = get_option("EWD_UFAQ_Display_All_Answers");
26
  $Socialmedia_String = get_option("EWD_UFAQ_Social_Media");
27
  $Socialmedia = explode(",", $Socialmedia_String);
28
+ $FAQ_Elements = get_option("EWD_UFAQ_FAQ_Elements");
29
+ if (!is_array($FAQ_Elements)) {$FAQ_Elements = array();}
30
 
31
  $Group_By_Category = get_option("EWD_UFAQ_Group_By_Category");
32
  $Group_By_Category_Count = get_option("EWD_UFAQ_Group_By_Category_Count");
319
  if ($Display_All_Answers != "Yes") {$ReturnString .= " ewd-ufaq-hidden";}
320
  $ReturnString .= "' id='ufaq-body-" . $Unique_ID . "-" . $faq->ID . "-" . $Counter . "' itemprop='suggestedAnswer acceptedAnswer' itemscope itemtype='http://schema.org/Answer'>";
321
 
322
+ foreach ($FAQ_Elements as $FAQ_Element) {
323
+ if ($FAQ_Element == "Author_Date" and ($Display_Author == "Yes" or $Display_Date == "Yes")) {
324
+ $Display_Author_Value = get_post_meta($faq->ID, "EWD_UFAQ_Post_Author", true);
325
+ $Display_Date_Value = get_the_date("", $faq->ID);
326
+ $ReturnString .= "<div class='ewd-ufaq-author-date' itemprop='author' itemscope itemtype='http://schema.org/Person'>";
327
+ $ReturnString .= $Posted_Label . " " ;
328
+ if ($Display_Author == "Yes" and $Display_Author_Value != "") {$ReturnString .= $By_Label . " <span class='ewd-ufaq-author' itemprop='name'>" . $Display_Author_Value . "</span> ";}
329
+ if ($Display_Date == "Yes") {$ReturnString .= $On_Label . " <span class='ewd-ufaq-date'>" . $Display_Date_Value . "</span> ";}
330
+ $ReturnString .= "</div>";
331
+ }
332
 
333
+ if ($FAQ_Element == "Body") {
334
+ $ReturnString .= "<div class='ewd-ufaq-post-margin ufaq-faq-post' id='ufaq-post-" . $faq->ID . "' itemprop='text'>" . apply_filters('the_content', html_entity_decode($faq->post_content)) . "</div>";
335
+ }
336
+
337
+ if ($FAQ_Element == "Custom_Fields" and sizeOf($FAQ_Fields_Array) > 0) {
338
+ $ReturnString .= "<div class='ufaq-faq-custom-fields' id='ufaq-custom-fields-" . $faq->ID . "'>";
339
+ foreach ($FAQ_Fields_Array as $FAQ_Field_Item) {
340
+ $Value = get_post_meta($faq->ID, "Custom_Field_" . $FAQ_Field_Item['FieldID'], true);
341
+ if ($Hide_Blank_Fields != "Yes" or $Value != "") {
342
+ $ReturnString .= "<div class='ufaq-custom-field-label'>" . $FAQ_Field_Item['FieldName'] . ": </div>";
343
+ $ReturnString .= "<div class='ufaq-custom-field-value'>&nbsp;";
344
+ if ($FAQ_Field_Item['FieldType'] == "file") {$ReturnString .= "<a href='" . $Value . "'>" . substr($Value, strrpos($Value, "/"+1)) . "</a>";}
345
+ elseif ($FAQ_Field_Item['FieldType'] == "link") {$ReturnString .= "<a href='" . $Value . "' target='_blank'>" . $Value ."</a>";}
346
+ else {$ReturnString .= $Value;}
347
+ $ReturnString .= "</div>";
348
+ $ReturnString .= "<div class='ewd-ufaq-clear'></div>";
349
+ }
350
+ unset($Value);
351
  }
352
+ $ReturnString .= "</div>";
353
  }
 
 
354
 
355
+ if ($FAQ_Element == "Categories" and $Hide_Categories == "No" and sizeOf($Category_Terms) > 0) {
356
+ $ReturnString .= "<div class='ufaq-faq-categories' id='ufaq-categories-" . $faq->ID . "'>";
357
+ if ($Category_Label == ""){
358
+ if (sizeOf($Category_Terms) > 1) {$ReturnString .= __("Categories: ", 'ultimate-faqs');}
359
+ else {$ReturnString .= __("Category: ", 'ultimate-faqs');}
360
+ }
361
+ else {$ReturnString .= $Category_Label . ": ";}
362
+ foreach ($Category_Terms as $Category_Term) {
363
+ if ($Pretty_Permalinks == "Yes") {$Category_URL = $current_url . "faq-category/" . $Category_Term->slug . "/";}
364
+ else {$Category_URL = $current_url . "?include_category=" . $Category_Term->slug;}
365
+ $ReturnString .= "<a href='" . $Category_URL ."'>" .$Category_Term->name . "</a>, ";
366
+ }
367
+ $ReturnString = substr($ReturnString, 0, strlen($ReturnString)-2);
368
+ $ReturnString .= "</div>";
369
+ }
370
+
371
+ if ($FAQ_Element == "Tags" and $Hide_Tags == "No" and sizeOf($Tag_Terms) > 0) {
372
+ $ReturnString .= "<div class='ufaq-faq-tags' id='ufaq-tags-" . $faq->ID . "'>";
373
+ if ($Tag_Label == ""){
374
+ if (sizeOf($Tag_Terms) > 1) {$ReturnString .= "Tags: ";}
375
+ else {$ReturnString .= "Tag: ";}
376
+ }
377
+ else {$ReturnString .= $Tag_Label . ": ";}
378
+ foreach ($Tag_Terms as $Tag_Term) {
379
+ if ($Pretty_Permalinks == "Yes") {$Tag_URL = $current_url . "faq-tag/" . $Tag_Term->slug . "/";}
380
+ else {$Tag_URL = $current_url . "?include_tag=" . $Tag_Term->slug;}
381
+ $ReturnString .= "<a href='" . $Tag_URL . "'>" .$Tag_Term->name . "</a>, ";
382
+ }
383
+ $ReturnString = substr($ReturnString, 0, strlen($ReturnString)-2);
384
+ $ReturnString .= "</div>";
385
  }
 
 
 
386
 
387
+ if ($FAQ_Element == "Ratings" and $FAQ_Ratings == "Yes") {
388
+ $Up_Votes = get_post_meta($faq->ID, "FAQ_Up_Votes", true);
389
+ if ($Up_Votes == "") {$Up_Votes = 0;}
390
+ $Down_Votes = get_post_meta($faq->ID, "FAQ_Down_Votes", true);
391
+ if ($Down_Votes == "") {$Down_Votes = 0;}
392
+
393
+ $ReturnString .= "<div class='ewd-ufaq-ratings'>";
394
+ $ReturnString .= "<div class='ewd-ufaq-ratings-label'>";
395
+ $ReturnString .= __("Did you find this FAQ helpful?", 'ultimate-faqs');
396
+ $ReturnString .= "</div>";
397
+ $ReturnString .= "<div class='ewd-ufaq-rating-button ewd-ufaq-up-vote' data-ratingfaqid='" . $faq->ID . "' itemprop='upvoteCount'>" . $Up_Votes . "</div>";
398
+ $ReturnString .= "<div class='ewd-ufaq-rating-button ewd-ufaq-down-vote' data-ratingfaqid='" . $faq->ID . "' itemprop='downvoteCount'>" . $Down_Votes . "</div>";
399
+ $ReturnString .= "</div>";
400
+ $ReturnString .= "<div class='ewd-ufaq-clear'></div>";
401
  }
 
 
 
402
 
403
+ if ($FAQ_Element == "Social_Media") {
404
+ if ($Socialmedia[0] != "Blank" and $Socialmedia[0] != "") {
405
+ $ReturnString .= "<div class='ufaq-social-links'>Share: ";
406
+ $ReturnString .= "<ul class='rrssb-buttons'>";
407
+ }
408
+ if(in_array("Facebook", $Socialmedia)) {$ReturnString .= EWD_UFAQ_Add_Social_Media_Buttons("Facebook", get_permalink($faq->ID), $faq->post_title);}
409
+ if(in_array("Google", $Socialmedia)) {$ReturnString .= EWD_UFAQ_Add_Social_Media_Buttons("Google", $FAQ_Permalink, $faq->post_title);}
410
+ if(in_array("Twitter", $Socialmedia)) {$ReturnString .= EWD_UFAQ_Add_Social_Media_Buttons("Twitter", $FAQ_Permalink, $faq->post_title);}
411
+ if(in_array("Linkedin", $Socialmedia)) {$ReturnString .= EWD_UFAQ_Add_Social_Media_Buttons("Linkedin", $FAQ_Permalink, $faq->post_title);}
412
+ if(in_array("Pinterest", $Socialmedia)) {$ReturnString .= EWD_UFAQ_Add_Social_Media_Buttons("Pinterest", $FAQ_Permalink, $faq->post_title);}
413
+ if(in_array("Email", $Socialmedia)) {$ReturnString .= EWD_UFAQ_Add_Social_Media_Buttons("Email", $FAQ_Permalink, $faq->post_title);}
414
+ if ($Socialmedia[0] != "Blank" and $Socialmedia[0] != "") {
415
+ $ReturnString .= "</ul>";
416
+ $ReturnString .= "</div>";
417
+ }
418
+ }
419
 
420
+ if ($FAQ_Element == "Permalink" and $Include_Permalink == "Yes" and $ajax == "No") {
421
+ $ReturnString .= "<div class='ufaq-permalink'>" . $Permalink_Label;
422
+ $ReturnString .= "<a href='" . $FAQ_Permalink . "'>";
423
+ $ReturnString .= "<div class='ufaq-permalink-image'></div>";
424
+ $ReturnString .= "</a>";
425
+ $ReturnString .= "</div>";
426
+ }
427
+
428
+ if ($FAQ_Element == "Comments" and comments_open($faq->ID) and $no_comments != "Yes" and $Comments_On == "Yes") {
429
+ ob_start();
430
+ $Comments = get_comments(array('post_id' => $faq->ID));
431
+ wp_list_comments(array(), $Comments);
432
+ comment_form(array(), $faq->ID);
433
+ $ReturnString .= ob_get_contents();
434
+ ob_end_clean();
435
+ }
436
+
437
+ if ($FAQ_Element == "Back_To_Top" and $Display_Back_To_Top == "Yes") {
438
+ $ReturnString .= "<div class='ufaq-back-to-top'>";
439
+ $ReturnString .= "<a class='ufaq-back-to-top-link'>";
440
+ $ReturnString .= $Back_To_Top_Label;
441
+ $ReturnString .= "</a>";
442
+ $ReturnString .= "</div>";
443
+ }
444
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
 
446
  $ReturnString .= "</div>";
447
  $ReturnString .= "</div>";
css/Admin.css CHANGED
@@ -231,7 +231,25 @@ EXTRA
231
  padding: 20px 10px 20px 10px !important;
232
  }
233
 
234
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
 
236
 
237
 
231
  padding: 20px 10px 20px 10px !important;
232
  }
233
 
234
+ .ewd-ufaq-elements-table {
235
+ width: 100%;
236
+ border-collapse: collapse;
237
+ }
238
+ .ewd-ufaq-elements-table th, .ewd-ufaq-elements-table td {
239
+ background: #f3f3f3;
240
+ margin: 0;
241
+ padding: 8px 16px;
242
+ width: calc(100% - 32px);
243
+ }
244
+ .ewd-ufaq-elements-table td {
245
+ border-bottom: 1px solid #ccc;
246
+ cursor: all-scroll;
247
+ }
248
+ .ewd-ufaq-elements-table th {
249
+ background: #662D91;
250
+ color: #fff;
251
+ text-align: left;
252
+ }
253
 
254
 
255
 
css/CSSTidy/class.csstidy.php CHANGED
@@ -1,1001 +1,1001 @@
1
- <?php
2
- /**
3
- * CSSTidy - CSS Parser and Optimiser
4
- *
5
- * CSS Parser class
6
- *
7
- * This file is part of CSSTidy.
8
- *
9
- * CSSTidy is free software; you can redistribute it and/or modify
10
- * it under the terms of the GNU General Public License as published by
11
- * the Free Software Foundation; either version 2 of the License, or
12
- * (at your option) any later version.
13
- *
14
- * CSSTidy is distributed in the hope that it will be useful,
15
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
- * GNU General Public License for more details.
18
- *
19
- * You should have received a copy of the GNU General Public License
20
- * along with CSSTidy; if not, write to the Free Software
21
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
- *
23
- * @license http://opensource.org/licenses/gpl-license.php GNU Public License
24
- * @package csstidy
25
- * @author Florian Schmitz (floele at gmail dot com) 2005-2006
26
- */
27
-
28
- /**
29
- * Various CSS data needed for correct optimisations etc.
30
- *
31
- * @version 1.3
32
- */
33
- require('data.inc.php');
34
-
35
- /**
36
- * Contains a class for printing CSS code
37
- *
38
- * @version 1.0
39
- */
40
- require('class.csstidy_print.php');
41
-
42
- /**
43
- * Contains a class for optimising CSS code
44
- *
45
- * @version 1.0
46
- */
47
- require('class.csstidy_optimise.php');
48
-
49
- /**
50
- * CSS Parser class
51
- *
52
- * This class represents a CSS parser which reads CSS code and saves it in an array.
53
- * In opposite to most other CSS parsers, it does not use regular expressions and
54
- * thus has full CSS2 support and a higher reliability.
55
- * Additional to that it applies some optimisations and fixes to the CSS code.
56
- * An online version should be available here: http://cdburnerxp.se/cssparse/css_optimiser.php
57
- * @package csstidy
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
- ?>
1
+ <?php
2
+ /**
3
+ * CSSTidy - CSS Parser and Optimiser
4
+ *
5
+ * CSS Parser class
6
+ *
7
+ * This file is part of CSSTidy.
8
+ *
9
+ * CSSTidy is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation; either version 2 of the License, or
12
+ * (at your option) any later version.
13
+ *
14
+ * CSSTidy is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with CSSTidy; if not, write to the Free Software
21
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
+ *
23
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
24
+ * @package csstidy
25
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2006
26
+ */
27
+
28
+ /**
29
+ * Various CSS data needed for correct optimisations etc.
30
+ *
31
+ * @version 1.3
32
+ */
33
+ require('data.inc.php');
34
+
35
+ /**
36
+ * Contains a class for printing CSS code
37
+ *
38
+ * @version 1.0
39
+ */
40
+ require('class.csstidy_print.php');
41
+
42
+ /**
43
+ * Contains a class for optimising CSS code
44
+ *
45
+ * @version 1.0
46
+ */
47
+ require('class.csstidy_optimise.php');
48
+
49
+ /**
50
+ * CSS Parser class
51
+ *
52
+ * This class represents a CSS parser which reads CSS code and saves it in an array.
53
+ * In opposite to most other CSS parsers, it does not use regular expressions and
54
+ * thus has full CSS2 support and a higher reliability.
55
+ * Additional to that it applies some optimisations and fixes to the CSS code.
56
+ * An online version should be available here: http://cdburnerxp.se/cssparse/css_optimiser.php
57
+ * @package csstidy
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
@@ -1,811 +1,811 @@
1
- <?php
2
- /**
3
- * CSSTidy - CSS Parser and Optimiser
4
- *
5
- * CSS Optimising Class
6
- * This class optimises CSS data generated by csstidy.
7
- *
8
- * This file is part of CSSTidy.
9
- *
10
- * CSSTidy is free software; you can redistribute it and/or modify
11
- * it under the terms of the GNU General Public License as published by
12
- * the Free Software Foundation; either version 2 of the License, or
13
- * (at your option) any later version.
14
- *
15
- * CSSTidy is distributed in the hope that it will be useful,
16
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
- * GNU General Public License for more details.
19
- *
20
- * You should have received a copy of the GNU General Public License
21
- * along with CSSTidy; if not, write to the Free Software
22
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
- *
24
- * @license http://opensource.org/licenses/gpl-license.php GNU Public License
25
- * @package csstidy
26
- * @author Florian Schmitz (floele at gmail dot com) 2005-2006
27
- */
28
-
29
- /**
30
- * CSS Optimising Class
31
- *
32
- * This class optimises CSS data generated by csstidy.
33
- *
34
- * @package csstidy
35
- * @author Florian Schmitz (floele at gmail dot com) 2005-2006
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
  ?>
1
+ <?php
2
+ /**
3
+ * CSSTidy - CSS Parser and Optimiser
4
+ *
5
+ * CSS Optimising Class
6
+ * This class optimises CSS data generated by csstidy.
7
+ *
8
+ * This file is part of CSSTidy.
9
+ *
10
+ * CSSTidy is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version.
14
+ *
15
+ * CSSTidy is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License
21
+ * along with CSSTidy; if not, write to the Free Software
22
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
+ *
24
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
25
+ * @package csstidy
26
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2006
27
+ */
28
+
29
+ /**
30
+ * CSS Optimising Class
31
+ *
32
+ * This class optimises CSS data generated by csstidy.
33
+ *
34
+ * @package csstidy
35
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2006
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
@@ -1,350 +1,350 @@
1
- <?php
2
- /**
3
- * CSSTidy - CSS Parser and Optimiser
4
- *
5
- * CSS Printing class
6
- * This class prints CSS data generated by csstidy.
7
- *
8
- * This file is part of CSSTidy.
9
- *
10
- * CSSTidy is free software; you can redistribute it and/or modify
11
- * it under the terms of the GNU General Public License as published by
12
- * the Free Software Foundation; either version 2 of the License, or
13
- * (at your option) any later version.
14
- *
15
- * CSSTidy is distributed in the hope that it will be useful,
16
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
- * GNU General Public License for more details.
19
- *
20
- * You should have received a copy of the GNU General Public License
21
- * along with CSSTidy; if not, write to the Free Software
22
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
- *
24
- * @license http://opensource.org/licenses/gpl-license.php GNU Public License
25
- * @package csstidy
26
- * @author Florian Schmitz (floele at gmail dot com) 2005-2006
27
- */
28
-
29
- /**
30
- * CSS Printing class
31
- *
32
- * This class prints CSS data generated by csstidy.
33
- *
34
- * @package csstidy
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
- }
350
  ?>
1
+ <?php
2
+ /**
3
+ * CSSTidy - CSS Parser and Optimiser
4
+ *
5
+ * CSS Printing class
6
+ * This class prints CSS data generated by csstidy.
7
+ *
8
+ * This file is part of CSSTidy.
9
+ *
10
+ * CSSTidy is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version.
14
+ *
15
+ * CSSTidy is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License
21
+ * along with CSSTidy; if not, write to the Free Software
22
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
+ *
24
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
25
+ * @package csstidy
26
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2006
27
+ */
28
+
29
+ /**
30
+ * CSS Printing class
31
+ *
32
+ * This class prints CSS data generated by csstidy.
33
+ *
34
+ * @package csstidy
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
+ }
350
  ?>
html/OptionsPage.php CHANGED
@@ -32,6 +32,7 @@
32
  $Slug_Base = get_option("EWD_UFAQ_Slug_Base");
33
  $Socialmedia_String = get_option("EWD_UFAQ_Social_Media");
34
  $Socialmedia = explode(",", $Socialmedia_String);
 
35
 
36
  $Group_By_Category = get_option("EWD_UFAQ_Group_By_Category");
37
  $Group_By_Category_Count = get_option("EWD_UFAQ_Group_By_Category_Count");
@@ -509,6 +510,23 @@
509
  </td>
510
  </tr>
511
  </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
512
  </div>
513
 
514
  <div id='Order' class='ufaq-option-set ufaq-hidden'>
32
  $Slug_Base = get_option("EWD_UFAQ_Slug_Base");
33
  $Socialmedia_String = get_option("EWD_UFAQ_Social_Media");
34
  $Socialmedia = explode(",", $Socialmedia_String);
35
+ $FAQ_Elements = get_option("EWD_UFAQ_FAQ_Elements");
36
 
37
  $Group_By_Category = get_option("EWD_UFAQ_Group_By_Category");
38
  $Group_By_Category_Count = get_option("EWD_UFAQ_Group_By_Category_Count");
510
  </td>
511
  </tr>
512
  </table>
513
+
514
+ <h3 id="premium-faq-element-ordering-options" class="ufaq-options-page-tab-title"><?php _e('FAQ Elements Order', 'ultimate-faqs'); ?></h3>
515
+
516
+ <table class='ewd-ufaq-elements-table'>
517
+ <thead>
518
+ <tr>
519
+ <th><?php _e("Element (if toggled on)", 'ultimate-faqs'); ?></th>
520
+ </tr>
521
+ </thead>
522
+ <tbody>
523
+ <?php foreach ($FAQ_Elements as $Order => $FAQ_Element) { ?>
524
+ <tr class='ewd-ufaq-element'>
525
+ <td><input type='hidden' name='Element_<?php echo $Order; ?>' value='<?php echo $FAQ_Element; ?>' /><span class='ewd-ufaq-element-name'><?php echo $FAQ_Element; ?></span></td>
526
+ </tr>
527
+ <?php } ?>
528
+ </tbody>
529
+ </table>
530
  </div>
531
 
532
  <div id='Order' class='ufaq-option-set ufaq-hidden'>
js/Admin.js CHANGED
@@ -21,8 +21,24 @@ jQuery(document).ready(function() {
21
  cursor: 'move',
22
  axis: 'y',
23
  update: function() {
24
- var order = jQuery(this).sortable('serialize') + '&action=UFAQ_update_order';
25
- jQuery.post(ajaxurl, order, function(response) {});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
27
  });
28
  });
21
  cursor: 'move',
22
  axis: 'y',
23
  update: function() {
24
+ var order = jQuery(this).sortable('serialize') + '&action=UFAQ_update_order';
25
+ jQuery.post(ajaxurl, order, function(response) {});
26
+ }
27
+ });
28
+ });
29
+
30
+ /* This code is required to make changing the FAQ order a drag-and-drop affair */
31
+ jQuery(document).ready(function() {
32
+ jQuery('.ewd-ufaq-elements-table').sortable({
33
+ items: '.ewd-ufaq-element',
34
+ opacity: 0.6,
35
+ cursor: 'move',
36
+ axis: 'y',
37
+ update: function() {
38
+ jQuery('.ewd-ufaq-element td').each(function(index, el) {
39
+ var Element_Name = jQuery(this).find('.ewd-ufaq-element-name').html();
40
+ jQuery(this).find('input').val(Element_Name).attr('name', 'Element_' + index);
41
+ });
42
  }
43
  });
44
  });
readme.txt CHANGED
@@ -2,20 +2,19 @@
2
  Contributors: Rustaurius, EtoileWebDesign
3
  Tags: faq, faqs, woocommerce faq, frequently asked questions, faq widget
4
  Requires at least: 3.9.0
5
- Tested up to: 4.8
6
  License: GPLv3
7
  License URI:http://www.gnu.org/licenses/gpl-3.0.html
8
 
9
- FAQ plugin that lets you easily create, order and publicize FAQs, insert 3 styles of FAQs on a page or WooCommerce product, and use AJAX FAQ search using FAQ shortcodes
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.
17
-
18
- = Key FAQ Features =
19
  * Unlimited FAQ, unlimited FAQ tag and unlimited FAQ category support
20
  * Create FAQ categories
21
  * Create FAQ posts and assign categories to them
@@ -25,7 +24,7 @@ FAQ plugin that lets you create FAQ (frequently asked questions), organize FAQs
25
 
26
  [youtube https://www.youtube.com/watch?v=xeGVZnVrZ6I]
27
 
28
- <strong>With WooCommerce Integration!</strong> See the "WooCommerce FAQ" section below for full details and features.
29
 
30
  `
31
  [ultimate-faqs]
@@ -39,7 +38,7 @@ FAQ features include frequently asked question statistics that show how many tim
39
 
40
  Ultimate FAQ isn't just for frequently asked questions. It also works great for any content that works similarly to FAQ and that needs to be hidden until it is clicked, like job postings, recipes, etc.!
41
 
42
- = WooCommerce FAQ =
43
 
44
  Using WooCommerce to sell your products? Easily add an FAQ tab to each product page, so your customers can see answers to common FAQ questions about the products they're browsing. It's the most comprehensive WooCommerce FAQs solution!
45
 
@@ -51,7 +50,7 @@ Want to decide exactly what order your FAQs are displayed in? Use our simple FAQ
51
 
52
  With the smart [submit-question] FAQ shortcode (premium), you can let your customers add to your custom FAQ list by submitting an FAQ question and even proposing an FAQ answer for it!
53
 
54
- = Additional Features =
55
  * Select FAQ animation options for displaying FAQ posts
56
  * Toggle FAQ accordion (close open FAQ when a new one is opened) behaviour on/off
57
  * Allow people to comment on individual FAQ
@@ -267,6 +266,9 @@ Video 3 - FAQs Ordering
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
@@ -615,6 +617,3 @@ Video 3 - FAQs Ordering
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
-
2
  Contributors: Rustaurius, EtoileWebDesign
3
  Tags: faq, faqs, woocommerce faq, frequently asked questions, faq widget
4
  Requires at least: 3.9.0
5
+ Tested up to: 4.9
6
  License: GPLv3
7
  License URI:http://www.gnu.org/licenses/gpl-3.0.html
8
 
9
+ FAQ plugin that lets you easily create, order and publicize FAQs using shortcodes, with many unique styles, WooCommerce FAQs and AJAX FAQ search
10
 
11
  == Description ==
12
 
13
+ FAQ plugin that lets you create FAQs (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.
14
 
15
+ [FAQ Demo](https://www.etoilewebdesign.com/ultimate-faq-demo/)
16
 
17
+ = FAQ Key Features =
 
 
18
  * Unlimited FAQ, unlimited FAQ tag and unlimited FAQ category support
19
  * Create FAQ categories
20
  * Create FAQ posts and assign categories to them
24
 
25
  [youtube https://www.youtube.com/watch?v=xeGVZnVrZ6I]
26
 
27
+ <strong>With WooCommerce Integration!</strong> See the "FAQ for WooCommerce" section below for full details and features.
28
 
29
  `
30
  [ultimate-faqs]
38
 
39
  Ultimate FAQ isn't just for frequently asked questions. It also works great for any content that works similarly to FAQ and that needs to be hidden until it is clicked, like job postings, recipes, etc.!
40
 
41
+ = FAQ for WooCommerce =
42
 
43
  Using WooCommerce to sell your products? Easily add an FAQ tab to each product page, so your customers can see answers to common FAQ questions about the products they're browsing. It's the most comprehensive WooCommerce FAQs solution!
44
 
50
 
51
  With the smart [submit-question] FAQ shortcode (premium), you can let your customers add to your custom FAQ list by submitting an FAQ question and even proposing an FAQ answer for it!
52
 
53
+ = Additional FAQ Features =
54
  * Select FAQ animation options for displaying FAQ posts
55
  * Toggle FAQ accordion (close open FAQ when a new one is opened) behaviour on/off
56
  * Allow people to comment on individual FAQ
266
 
267
 
268
  == Changelog ==
269
+ = 1.6.9 =
270
+ - Added in the option to re-order the elements of an FAQ (body, date/author, categories, etc.)
271
+
272
  = 1.6.8 =
273
  - Fixed a conflict with other plugins that use CSSTidy for CSS sanitization
274
  - Added the ability to link to the search shortcode with a term preloaded
617
 
618
  = 1.0.0 =
619
  - Premium version release, check out our website for all of the details <http://www.etoilewebdesign.com/ultimate-faq/>