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 | 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 +16 -0
- Functions/Update_Admin_Databases.php +6 -0
- Main.php +3 -3
- Shortcodes/DisplayFAQs.php +115 -105
- css/Admin.css +19 -1
- css/CSSTidy/class.csstidy.php +1001 -1001
- css/CSSTidy/class.csstidy_optimise.php +810 -810
- css/CSSTidy/class.csstidy_print.php +349 -349
- html/OptionsPage.php +18 -0
- js/Admin.js +18 -2
- readme.txt +11 -12
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:
|
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.
|
11 |
*/
|
12 |
|
13 |
global $ewd_ufaq_message;
|
14 |
global $UFAQ_Full_Version;
|
15 |
global $EWD_UFAQ_Version;
|
16 |
|
17 |
-
$EWD_UFAQ_Version = '1.6.
|
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 |
-
|
321 |
-
$
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
|
|
329 |
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
$
|
336 |
-
|
337 |
-
$
|
338 |
-
$
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
|
|
|
|
|
|
|
|
344 |
}
|
345 |
-
|
346 |
}
|
347 |
-
$ReturnString .= "</div>";
|
348 |
-
}
|
349 |
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
}
|
361 |
-
if (sizeOf($Category_Terms) > 0) {$ReturnString = substr($ReturnString, 0, strlen($ReturnString)-2);}
|
362 |
-
$ReturnString .= "</div>";
|
363 |
-
}
|
364 |
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
$ReturnString .= "
|
|
|
|
|
|
|
|
|
375 |
}
|
376 |
-
if (sizeOf($Tag_Terms) > 0) {$ReturnString = substr($ReturnString, 0, strlen($ReturnString)-2);}
|
377 |
-
$ReturnString .= "</div>";
|
378 |
-
}
|
379 |
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
|
|
395 |
|
396 |
-
|
397 |
-
|
398 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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'> ";
|
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 |
-
|
25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
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
|
10 |
|
11 |
== Description ==
|
12 |
|
|
|
13 |
|
14 |
-
|
15 |
|
16 |
-
|
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
|
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
|
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/>
|
|
|
|
|
|