Responsive Menu - Version 4.0.0

Version Description

(7th Dec 2020) = * New and improved admin user interface * Added menu customizer with live preview features * Added feature to create menu templates * Improved menu themes * Added support for multiple menus * Added support for WordPress core version 5.6 and PHP 8.0 * Added support for twenty twenty one theme * Fixed several bugs in older version

Download this release

Release Info

Developer expresstech
Plugin Icon 128x128 Responsive Menu
Version 4.0.0
Comparing to
See all releases

Code changes from version 3.1.30 to 4.0.0

Files changed (111) hide show
  1. app/Walkers/Walker.php +6 -0
  2. config/routing.php +12 -0
  3. config/wp/scripts.php +22 -7
  4. public/css/admin/base.css +17 -2
  5. public/js/admin/additional.js +20 -1
  6. public/js/admin/base.js +1 -1
  7. readme.txt +13 -3
  8. responsive-menu.php +124 -2
  9. v4.0.0/.babelrc +3 -0
  10. v4.0.0/.distignore +20 -0
  11. v4.0.0/.editorconfig +37 -0
  12. v4.0.0/.eslintignore +4 -0
  13. v4.0.0/.eslintrc.json +40 -0
  14. v4.0.0/.gitignore +8 -0
  15. v4.0.0/.stylelintrc +29 -0
  16. v4.0.0/assets/admin/fonts/product-sans/Product Sans Bold Italic.ttf +0 -0
  17. v4.0.0/assets/admin/fonts/product-sans/Product Sans Bold.ttf +0 -0
  18. v4.0.0/assets/admin/fonts/product-sans/Product Sans Italic.ttf +0 -0
  19. v4.0.0/assets/admin/fonts/product-sans/Product Sans Medium.ttf +0 -0
  20. v4.0.0/assets/admin/fonts/product-sans/Product Sans Regular.ttf +0 -0
  21. v4.0.0/assets/admin/fonts/product-sans/google-product-sans.jpg +0 -0
  22. v4.0.0/assets/admin/icons/svg/advanced.svg +3 -0
  23. v4.0.0/assets/admin/icons/svg/container.svg +3 -0
  24. v4.0.0/assets/admin/icons/svg/desktop.svg +3 -0
  25. v4.0.0/assets/admin/icons/svg/dropdowns.svg +3 -0
  26. v4.0.0/assets/admin/icons/svg/general.svg +3 -0
  27. v4.0.0/assets/admin/icons/svg/header.svg +3 -0
  28. v4.0.0/assets/admin/icons/svg/image-placeholder.svg +13 -0
  29. v4.0.0/assets/admin/icons/svg/mobile.svg +3 -0
  30. v4.0.0/assets/admin/icons/svg/tablet.svg +3 -0
  31. v4.0.0/assets/admin/icons/svg/toggle.svg +3 -0
  32. v4.0.0/assets/admin/js/rmp-admin.js +775 -0
  33. v4.0.0/assets/admin/js/rmp-editor.js +95 -0
  34. v4.0.0/assets/admin/js/rmp-icon.js +142 -0
  35. v4.0.0/assets/admin/js/rmp-preview.js +1008 -0
  36. v4.0.0/assets/admin/js/selectize.js +3 -0
  37. v4.0.0/assets/admin/js/wp-color-alpha.js +416 -0
  38. v4.0.0/assets/admin/scss/admin.css +2622 -0
  39. v4.0.0/assets/admin/scss/glyphicons.css +810 -0
  40. v4.0.0/assets/admin/scss/selectize.css +324 -0
  41. v4.0.0/assets/images/no-preview.jpeg +0 -0
  42. v4.0.0/assets/images/placeholder.png +0 -0
  43. v4.0.0/assets/images/rmp-logo.png +0 -0
  44. v4.0.0/assets/js/rmp-menu.js +354 -0
  45. v4.0.0/assets/scss/common.scss +232 -0
  46. v4.0.0/assets/scss/main.scss +624 -0
  47. v4.0.0/inc/classes/class-admin.php +576 -0
  48. v4.0.0/inc/classes/class-assets.php +209 -0
  49. v4.0.0/inc/classes/class-control-manager.php +1271 -0
  50. v4.0.0/inc/classes/class-editor-manager.php +169 -0
  51. v4.0.0/inc/classes/class-editor.php +201 -0
  52. v4.0.0/inc/classes/class-option-manager.php +130 -0
  53. v4.0.0/inc/classes/class-plugin.php +147 -0
  54. v4.0.0/inc/classes/class-preview.php +74 -0
  55. v4.0.0/inc/classes/class-rmp-menu.php +442 -0
  56. v4.0.0/inc/classes/class-rmp-migration.php +301 -0
  57. v4.0.0/inc/classes/class-style-manager.php +1497 -0
  58. v4.0.0/inc/classes/class-theme-manager.php +572 -0
  59. v4.0.0/inc/classes/class-ui-manager.php +278 -0
  60. v4.0.0/inc/classes/class-walker.php +339 -0
  61. v4.0.0/inc/helpers/autoloader.php +91 -0
  62. v4.0.0/inc/helpers/custom-functions.php +192 -0
  63. v4.0.0/inc/helpers/default-options.php +1130 -0
  64. v4.0.0/inc/traits/trait-singleton.php +89 -0
  65. v4.0.0/languages/responsive-menu.pot +1546 -0
  66. v4.0.0/libs/scssphp/composer.json +5 -0
  67. v4.0.0/libs/scssphp/composer.lock +79 -0
  68. v4.0.0/libs/scssphp/vendor/autoload.php +7 -0
  69. v4.0.0/libs/scssphp/vendor/bin/pscss +14 -0
  70. v4.0.0/libs/scssphp/vendor/bin/pscss.bat +4 -0
  71. v4.0.0/libs/scssphp/vendor/composer/ClassLoader.php +445 -0
  72. v4.0.0/libs/scssphp/vendor/composer/LICENSE +21 -0
  73. v4.0.0/libs/scssphp/vendor/composer/autoload_classmap.php +9 -0
  74. v4.0.0/libs/scssphp/vendor/composer/autoload_namespaces.php +9 -0
  75. v4.0.0/libs/scssphp/vendor/composer/autoload_psr4.php +10 -0
  76. v4.0.0/libs/scssphp/vendor/composer/autoload_real.php +52 -0
  77. v4.0.0/libs/scssphp/vendor/composer/autoload_static.php +31 -0
  78. v4.0.0/libs/scssphp/vendor/composer/installed.json +65 -0
  79. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/LICENSE.md +20 -0
  80. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/README.md +46 -0
  81. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/bin/pscss +215 -0
  82. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/composer.json +51 -0
  83. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/scss.inc.php +34 -0
  84. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Base/Range.php +47 -0
  85. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Block.php +70 -0
  86. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Cache.php +239 -0
  87. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Colors.php +241 -0
  88. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Compiler.php +7838 -0
  89. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Compiler/Environment.php +45 -0
  90. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Exception/CompilerException.php +21 -0
  91. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Exception/ParserException.php +21 -0
  92. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Exception/RangeException.php +21 -0
  93. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Exception/ServerException.php +21 -0
  94. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter.php +331 -0
  95. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/Compact.php +45 -0
  96. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/Compressed.php +81 -0
  97. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/Crunched.php +79 -0
  98. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/Debug.php +121 -0
  99. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/Expanded.php +68 -0
  100. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/Nested.php +229 -0
  101. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/OutputBlock.php +65 -0
  102. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Node.php +40 -0
  103. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Node/Number.php +390 -0
  104. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Parser.php +3404 -0
  105. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/SourceMap/Base64.php +184 -0
  106. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/SourceMap/Base64VLQ.php +146 -0
  107. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/SourceMap/SourceMapGenerator.php +348 -0
  108. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Type.php +70 -0
  109. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Util.php +70 -0
  110. v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Version.php +22 -0
  111. v4.0.0/package-lock.json +141 -0
app/Walkers/Walker.php CHANGED
@@ -94,6 +94,12 @@ class Walker extends \Walker_Nav_Menu {
94
 
95
  $item_output .= '</a>';
96
 
 
 
 
 
 
 
97
  $output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
98
 
99
  }
94
 
95
  $item_output .= '</a>';
96
 
97
+ // Theme support for twenty twenty one.
98
+ if ( function_exists( 'twenty_twenty_one_add_sub_menu_toggle' ) ) {
99
+ remove_filter( 'walker_nav_menu_start_el', 'twenty_twenty_one_add_sub_menu_toggle', 10 );
100
+ remove_filter( 'walker_nav_menu_start_el', 'twenty_twenty_one_nav_menu_social_icons', 10 );
101
+ }
102
+
103
  $output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
104
 
105
  }
config/routing.php CHANGED
@@ -59,6 +59,18 @@ if(is_admin()):
59
  },
60
  'dashicons-menu');
61
  });
 
 
 
 
 
 
 
 
 
 
 
 
62
  else:
63
  add_action('template_redirect', function() {
64
  $controller = get_responsive_menu_service('front_controller');
59
  },
60
  'dashicons-menu');
61
  });
62
+
63
+ /** Function to move to the new version */
64
+ add_action('wp_ajax_rmp_switch_version', function() {
65
+
66
+ if ( empty ( update_option( 'is_rmp_new_version', 1 ) ) ) {
67
+ add_option( 'is_rmp_new_version', 1 );
68
+ }
69
+
70
+ wp_send_json_success( ['redirect' => admin_url('edit.php?post_type=rmp_menu')] );
71
+
72
+ });
73
+
74
  else:
75
  add_action('template_redirect', function() {
76
  $controller = get_responsive_menu_service('front_controller');
config/wp/scripts.php CHANGED
@@ -28,10 +28,10 @@ if(isset($_GET['page']) && $_GET['page'] == 'responsive-menu'):
28
  wp_enqueue_script('jquery-ui-sortable');
29
  wp_enqueue_script('jquery-ui-draggable');
30
 
31
- wp_register_style('responsive-menu-base-css', plugin_dir_url(dirname(dirname(__FILE__))) . 'public/css/admin/base.css', false, null);
32
  wp_enqueue_style('responsive-menu-base-css');
33
 
34
- wp_register_style('responsive-menu-additional-css', plugin_dir_url(dirname(dirname(__FILE__))) . 'public/css/admin/additional.css', false, null);
35
  wp_enqueue_style('responsive-menu-additional-css');
36
 
37
  $options = get_responsive_menu_service('option_manager')->all();
@@ -41,13 +41,28 @@ if(isset($_GET['page']) && $_GET['page'] == 'responsive-menu'):
41
  wp_enqueue_style('responsive-menu-admin-css-theme' . $theme);
42
  endif;
43
 
44
- wp_register_script('responsive-menu-base-js', plugin_dir_url(dirname(dirname(__FILE__))) . 'public/js/admin/base.js', 'jquery', null);
45
- wp_localize_script('responsive-menu-base-js', 'WP_HOME_URL', home_url('/'));
46
- wp_localize_script('responsive-menu-base-js', 'THEMES_FOLDER_URL', wp_upload_dir()['baseurl'] . '/responsive-menu-themes/');
 
 
 
 
 
 
 
 
 
 
 
47
  wp_enqueue_script('responsive-menu-base-js');
48
 
49
- wp_register_script('responsive-menu-additional-js', plugin_dir_url(dirname(dirname(__FILE__))) . 'public/js/admin/additional.js', 'jquery', null);
50
- wp_localize_script('responsive-menu-additional-js', 'WP_HOME_URL', home_url('/'));
 
 
 
 
51
  wp_enqueue_script('responsive-menu-additional-js');
52
 
53
  });
28
  wp_enqueue_script('jquery-ui-sortable');
29
  wp_enqueue_script('jquery-ui-draggable');
30
 
31
+ wp_register_style('responsive-menu-base-css', plugin_dir_url(dirname(dirname(__FILE__))) . 'public/css/admin/base.css', false, RMP_PLUGIN_VERSION );
32
  wp_enqueue_style('responsive-menu-base-css');
33
 
34
+ wp_register_style('responsive-menu-additional-css', plugin_dir_url(dirname(dirname(__FILE__))) . 'public/css/admin/additional.css', false, RMP_PLUGIN_VERSION );
35
  wp_enqueue_style('responsive-menu-additional-css');
36
 
37
  $options = get_responsive_menu_service('option_manager')->all();
41
  wp_enqueue_style('responsive-menu-admin-css-theme' . $theme);
42
  endif;
43
 
44
+ wp_register_script('responsive-menu-base-js', plugin_dir_url(dirname(dirname(__FILE__))) . 'public/js/admin/base.js', 'jquery', RMP_PLUGIN_VERSION );
45
+
46
+ wp_localize_script(
47
+ 'responsive-menu-base-js',
48
+ 'WP_RMP',
49
+ [ 'HOME_URL' => home_url('/') ]
50
+ );
51
+
52
+ wp_localize_script(
53
+ 'responsive-menu-base-js',
54
+ 'WP_RMP_THEME',
55
+ [ 'FOLDER_URL' => wp_upload_dir()['baseurl'] . '/responsive-menu-themes/' ]
56
+ );
57
+
58
  wp_enqueue_script('responsive-menu-base-js');
59
 
60
+ wp_register_script('responsive-menu-additional-js', plugin_dir_url(dirname(dirname(__FILE__))) . 'public/js/admin/additional.js', 'jquery', RMP_PLUGIN_VERSION );
61
+ wp_localize_script(
62
+ 'responsive-menu-additional-js',
63
+ 'WP_RMP',
64
+ [ 'HOME_URL' => home_url('/') ]
65
+ );
66
  wp_enqueue_script('responsive-menu-additional-js');
67
 
68
  });
public/css/admin/base.css CHANGED
@@ -324,7 +324,8 @@
324
 
325
  #responsive-menu-admin #upgrade-banner,
326
  #responsive-menu-admin #docs-banner,
327
- #responsive-menu-admin #themes-banner {
 
328
  background: #FAB719;
329
  padding: 35px;
330
  color: #333;
@@ -336,7 +337,8 @@
336
 
337
  #responsive-menu-admin #upgrade-banner .button,
338
  #responsive-menu-admin #docs-banner .button,
339
- #responsive-menu-admin #themes-banner .button {
 
340
  background: white;
341
  padding: 0 25px;
342
  height: 50px;
@@ -351,6 +353,19 @@
351
  margin-top: 15px;
352
  }
353
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
  #responsive-menu-admin #themes-banner {
355
  background: #15a4fa;
356
  color: white;
324
 
325
  #responsive-menu-admin #upgrade-banner,
326
  #responsive-menu-admin #docs-banner,
327
+ #responsive-menu-admin #themes-banner,
328
+ #responsive-menu-admin #new-version-banner {
329
  background: #FAB719;
330
  padding: 35px;
331
  color: #333;
337
 
338
  #responsive-menu-admin #upgrade-banner .button,
339
  #responsive-menu-admin #docs-banner .button,
340
+ #responsive-menu-admin #themes-banner .button,
341
+ #responsive-menu-admin #new-version-banner .button {
342
  background: white;
343
  padding: 0 25px;
344
  height: 50px;
353
  margin-top: 15px;
354
  }
355
 
356
+ #responsive-menu-admin #new-version-banner {
357
+ margin-bottom: 10px;
358
+ background: #3e4960;
359
+ color: #ffffff;
360
+ border: dashed #ffffff 2px;
361
+ }
362
+
363
+ #responsive-menu-admin #new-version-banner .button{
364
+ background: #0db932;
365
+ color: #fff;
366
+ border: solid 1px green;
367
+ }
368
+
369
  #responsive-menu-admin #themes-banner {
370
  background: #15a4fa;
371
  color: white;
public/js/admin/additional.js CHANGED
@@ -40,7 +40,7 @@ jQuery(function($) {
40
  $(document).on('click', '.responsive-menu-preview', function(e) {
41
  e.preventDefault();
42
  var form = $('#responsive-menu-form');
43
- form.attr('action', WP_HOME_URL + '?responsive-menu-preview=true');
44
  form.attr('target', '_blank');
45
  form.submit();
46
  form.attr('action', '');
@@ -48,4 +48,23 @@ jQuery(function($) {
48
  });
49
  /* <-- End Preview Options */
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  });
40
  $(document).on('click', '.responsive-menu-preview', function(e) {
41
  e.preventDefault();
42
  var form = $('#responsive-menu-form');
43
+ form.attr('action', WP_RMP.HOME_URL + '?responsive-menu-preview=true');
44
  form.attr('target', '_blank');
45
  form.submit();
46
  form.attr('action', '');
48
  });
49
  /* <-- End Preview Options */
50
 
51
+ /** Move to new version */
52
+ jQuery('#rmp-rollback-version').click( function(e) {
53
+ e.preventDefault();
54
+ jQuery.ajax({
55
+ url: ajaxurl,
56
+ data: { action : 'rmp_switch_version' },
57
+ type: 'POST',
58
+ dataType: 'json',
59
+ error: function( error ) {
60
+ jQuery(this).prop('disabled', false);
61
+ },
62
+ success: function( response ) {
63
+ if ( response.data.redirect ) {
64
+ location.href = response.data.redirect;
65
+ }
66
+ }
67
+ });
68
+ });
69
+
70
  });
public/js/admin/base.js CHANGED
@@ -193,7 +193,7 @@ jQuery(function($) {
193
  /* --> Theme Selector Script */
194
  $('#responsive-menu-menu-theme').on('changed.bs.select', function() {
195
  var selected_theme_key = $(this).val();
196
- var preview_image_url = THEMES_FOLDER_URL + selected_theme_key + '/preview.png';
197
  var $preview_image = $('#responsive-menu-theme-preview');
198
 
199
  $preview_image.attr('src', preview_image_url);
193
  /* --> Theme Selector Script */
194
  $('#responsive-menu-menu-theme').on('changed.bs.select', function() {
195
  var selected_theme_key = $(this).val();
196
+ var preview_image_url = WP_RMP_THEME.FOLDER_URL + selected_theme_key + '/preview.png';
197
  var $preview_image = $('#responsive-menu-theme-preview');
198
 
199
  $preview_image.attr('src', preview_image_url);
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: expresstech,responsivemenu
3
  Tags: responsive, mega menu, navigation, mobile, hamburger
4
  Requires at least: 3.6
5
- Tested up to: 5.5
6
- Stable tag: 3.1.30
7
- Requires PHP: 5.5
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -111,6 +111,16 @@ To view our FAQ, please go to [https://responsive.menu/faq/](https://responsive.
111
 
112
  == Changelog ==
113
 
 
 
 
 
 
 
 
 
 
 
114
  = 3.1.30 (23rd July 2020) =
115
  * Bug: Fixed menu arial-label
116
 
2
  Contributors: expresstech,responsivemenu
3
  Tags: responsive, mega menu, navigation, mobile, hamburger
4
  Requires at least: 3.6
5
+ Tested up to: 5.6
6
+ Stable tag: 4.0.0
7
+ Requires PHP: 5.6
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
111
 
112
  == Changelog ==
113
 
114
+ = 4.0.0 (7th Dec 2020) =
115
+ * New and improved admin user interface
116
+ * Added menu customizer with live preview features
117
+ * Added feature to create menu templates
118
+ * Improved menu themes
119
+ * Added support for multiple menus
120
+ * Added support for WordPress core version 5.6 and PHP 8.0
121
+ * Added support for twenty twenty one theme
122
+ * Fixed several bugs in older version
123
+
124
  = 3.1.30 (23rd July 2020) =
125
  * Bug: Fixed menu arial-label
126
 
responsive-menu.php CHANGED
@@ -4,7 +4,7 @@
4
  Plugin Name: Responsive Menu
5
  Plugin URI: https://expresstech.io
6
  Description: Highly Customisable Responsive Menu Plugin for WordPress
7
- Version: 3.1.30
8
  Author: ExpressTech
9
  Text Domain: responsive-menu
10
  Author URI: https://responsive.menu
@@ -12,6 +12,13 @@ License: GPL2
12
  Tags: responsive, menu, responsive menu, mega menu, max mega menu, max menu
13
  */
14
 
 
 
 
 
 
 
 
15
  add_action('admin_init', 'check_responsive_menu_php_version');
16
  function check_responsive_menu_php_version() {
17
  if(version_compare(PHP_VERSION, '5.4', '<')):
@@ -32,6 +39,8 @@ function responsive_menu_deactivation_text() {
32
  if(version_compare(PHP_VERSION, '5.4', '<'))
33
  return;
34
 
 
 
35
  add_action( 'admin_notices', 'og_pro_deactivate_pro_version_notice');
36
 
37
  function og_pro_deactivate_pro_version_notice() {
@@ -60,7 +69,6 @@ function og_deactivate_responsive_menu_pro() {
60
  //to check weather another plugin is acivated or not.
61
  register_activation_hook( __FILE__, 'og_deactivate_responsive_menu_pro');
62
 
63
-
64
  include dirname(__FILE__) . '/vendor/autoload.php';
65
  include dirname(__FILE__) . '/config/default_options.php';
66
  include dirname(__FILE__) . '/config/services.php';
@@ -68,3 +76,117 @@ include dirname(__FILE__) . '/config/wp/scripts.php';
68
  include dirname(__FILE__) . '/config/routing.php';
69
  include dirname(__FILE__) . '/migration.php';
70
  include dirname(__FILE__) . '/config/polylang.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  Plugin Name: Responsive Menu
5
  Plugin URI: https://expresstech.io
6
  Description: Highly Customisable Responsive Menu Plugin for WordPress
7
+ Version: 4.0.0
8
  Author: ExpressTech
9
  Text Domain: responsive-menu
10
  Author URI: https://responsive.menu
12
  Tags: responsive, menu, responsive menu, mega menu, max mega menu, max menu
13
  */
14
 
15
+ /**
16
+ * Constant as plugin version.
17
+ */
18
+ if ( ! defined( 'RMP_PLUGIN_VERSION' ) ) {
19
+ define( 'RMP_PLUGIN_VERSION', '4.0.0' );
20
+ }
21
+
22
  add_action('admin_init', 'check_responsive_menu_php_version');
23
  function check_responsive_menu_php_version() {
24
  if(version_compare(PHP_VERSION, '5.4', '<')):
39
  if(version_compare(PHP_VERSION, '5.4', '<'))
40
  return;
41
 
42
+ if ( empty( get_option( 'is_rmp_new_version') ) && ! empty( get_option('responsive_menu_version') ) ) {
43
+
44
  add_action( 'admin_notices', 'og_pro_deactivate_pro_version_notice');
45
 
46
  function og_pro_deactivate_pro_version_notice() {
69
  //to check weather another plugin is acivated or not.
70
  register_activation_hook( __FILE__, 'og_deactivate_responsive_menu_pro');
71
 
 
72
  include dirname(__FILE__) . '/vendor/autoload.php';
73
  include dirname(__FILE__) . '/config/default_options.php';
74
  include dirname(__FILE__) . '/config/services.php';
76
  include dirname(__FILE__) . '/config/routing.php';
77
  include dirname(__FILE__) . '/migration.php';
78
  include dirname(__FILE__) . '/config/polylang.php';
79
+
80
+ } else {
81
+
82
+ // If this file called directly then abort.
83
+ if ( ! defined( 'WPINC' ) ) {
84
+ die;
85
+ }
86
+
87
+ /**
88
+ * Constant as plugin file.
89
+ */
90
+ if ( ! defined( 'RMP_PLUGIN_FILE' ) ) {
91
+ define('RMP_PLUGIN_FILE', plugin_dir_path( __FILE__ ) . 'responsive-menu.php');
92
+ }
93
+
94
+ /**
95
+ * Constant as dir of plugin.
96
+ */
97
+ if ( ! defined( 'RMP_PLUGIN_DIR_NAME' ) ) {
98
+ define( 'RMP_PLUGIN_DIR_NAME', untrailingslashit ( dirname( plugin_basename( __FILE__ ) ) ) );
99
+ }
100
+
101
+ /**
102
+ * Constant as plugin path.
103
+ */
104
+ if ( ! defined( 'RMP_PLUGIN_PATH' ) ) {
105
+ define( 'RMP_PLUGIN_PATH', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
106
+ }
107
+
108
+ /**
109
+ * Constant as plugin URL.
110
+ */
111
+ if ( ! defined( 'RMP_PLUGIN_URL' ) ) {
112
+ define( 'RMP_PLUGIN_URL', untrailingslashit( plugin_dir_url( __FILE__ ) ) );
113
+ }
114
+
115
+ /**
116
+ * Constant as URI of assets build.
117
+ */
118
+ if ( ! defined( 'RMP_PLUGIN_BUILD_URI' ) ) {
119
+ define( 'RMP_PLUGIN_BUILD_URI', untrailingslashit( plugin_dir_url( __FILE__ ) ) . '/assets/build' );
120
+ }
121
+
122
+ /**
123
+ * Constant as dir of assets build.
124
+ */
125
+ if ( ! defined( 'RMP_PLUGIN_BUILD_DIR' ) ) {
126
+ define( 'RMP_PLUGIN_BUILD_DIR', untrailingslashit( plugin_dir_path( __FILE__ ) ) . '/assets/build' );
127
+ }
128
+
129
+ /**
130
+ * Constant as path of template file.
131
+ */
132
+ if ( ! defined( 'RMP_PLUGIN_TEMPLATE_PATH' ) ) {
133
+ define( 'RMP_PLUGIN_TEMPLATE_PATH', untrailingslashit( plugin_dir_path( __FILE__ ) ) . '/templates/' );
134
+ }
135
+
136
+ if ( ! defined( 'RMP_PLUGIN_PATH_V4' ) ) {
137
+ define ( 'RMP_PLUGIN_PATH_V4', RMP_PLUGIN_PATH . '/v4.0.0' );
138
+ }
139
+
140
+ if ( ! defined( 'RMP_PLUGIN_URL_V4' ) ) {
141
+ define ( 'RMP_PLUGIN_URL_V4', RMP_PLUGIN_URL . '/v4.0.0' );
142
+ }
143
+
144
+ /** Include the required files only*/
145
+ require_once RMP_PLUGIN_PATH_V4 . '/inc/helpers/autoloader.php';
146
+ require_once RMP_PLUGIN_PATH_V4 . '/inc/helpers/custom-functions.php';
147
+ require_once RMP_PLUGIN_PATH_V4 . '/inc/helpers/default-options.php';
148
+ require_once RMP_PLUGIN_PATH_V4 . '/libs/scssphp/vendor/autoload.php';
149
+
150
+ /**
151
+ * To load plugin manifest class.
152
+ *
153
+ * @return void
154
+ */
155
+ function responsive_menu_features_plugin_loader() {
156
+ \RMP\Features\Inc\Plugin::get_instance();
157
+ }
158
+
159
+ responsive_menu_features_plugin_loader();
160
+
161
+ // Active and de-active plugin hook.
162
+ register_activation_hook( __FILE__, 'responsive_menu_plugin_activation' );
163
+ register_deactivation_hook( __FILE__, 'responsive_menu_plugin_deactivation' );
164
+
165
+ /**
166
+ * Activation of plugin.
167
+ *
168
+ * @return void
169
+ */
170
+ function responsive_menu_plugin_activation() {
171
+
172
+ $plugin = 'responsive-menu-pro/responsive-menu-pro.php';
173
+
174
+ // Check if responsive menu (paid version) is activate then deactivate it.
175
+ if( is_plugin_active( $plugin ) ) {
176
+ deactivate_plugins( $plugin );
177
+ set_transient( 'og-admin-notice-activation-pro', true, 5 );
178
+ }
179
+
180
+ flush_rewrite_rules();
181
+ }
182
+
183
+ /**
184
+ * Deactivation of plugin.
185
+ *
186
+ * @return void
187
+ */
188
+ function responsive_menu_plugin_deactivation() {
189
+ flush_rewrite_rules();
190
+ }
191
+
192
+ }
v4.0.0/.babelrc ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ {
2
+ "presets": [ "@babel/preset-env" ]
3
+ }
v4.0.0/.distignore ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .gitignore
2
+ yarn.lock
3
+ webpack.config.js
4
+ .vscode/
5
+ .stylelintrc
6
+ postcss.config.js
7
+ _phpcs.xml
8
+ package.json
9
+ npm-debug.log
10
+ node_modules/
11
+ .eslintrc.json
12
+ .eslintignore
13
+ .editorconfig
14
+ .babelrc
15
+ ~/.vscode-root/
16
+ readme.md
17
+ readme.txt
18
+ yarn-error.log
19
+ .distignore
20
+ bin/
v4.0.0/.editorconfig ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is for unifying the coding style for different editors and IDEs
2
+ # editorconfig.org
3
+ #
4
+ # Indent Brace Style:
5
+ # https://en.wikipedia.org/wiki/Indent_style#Placement_of_braces
6
+
7
+ root = true
8
+
9
+ [*]
10
+ end_of_line = lf
11
+ charset = utf-8
12
+ trim_trailing_whitespace = true
13
+ insert_final_newline = true
14
+
15
+ [**.js]
16
+ indent_style = tab
17
+ indent_size = 4
18
+ spaces_around_brackets = both
19
+ indent_brace_style = K&R
20
+
21
+ [**.css]
22
+ indent_style = tab
23
+ indent_size = 4
24
+
25
+ [**.scss]
26
+ indent_style = tab
27
+ indent_size = 4
28
+
29
+ [**.php]
30
+ indent_style = tab
31
+ indent_size = 4
32
+ spaces_around_brackets = both
33
+ indent_brace_style = K&R
34
+
35
+ [**.html]
36
+ indent_style = tab
37
+ indent_size = 4
v4.0.0/.eslintignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ **/*.min.js
2
+ **/node_modules/**
3
+ **/vendor/**
4
+ **/build/**
v4.0.0/.eslintrc.json ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "extends": "wordpress",
3
+ "parserOptions": {
4
+ "ecmaVersion": 6,
5
+ "ecmaFeatures": {
6
+ "jsx": true,
7
+ "arrowFunctions": true,
8
+ "blockBindings": true,
9
+ "classes": true,
10
+ "defaultParams": true,
11
+ "modules": true
12
+ },
13
+ "sourceType": "module"
14
+ },
15
+ "env": {
16
+ "es6": true,
17
+ "browser": true,
18
+ "node": true,
19
+ "commonjs": true,
20
+ "jquery": true
21
+ },
22
+ "rules": {
23
+ "camelcase": [1],
24
+ "space-in-parens": [1, "always"],
25
+ "no-trailing-spaces": [1],
26
+ "spaced-comment": [0],
27
+ "padded-blocks": [0],
28
+ "prefer-template": [0],
29
+ "max-len": [0],
30
+ "no-else-return": [0],
31
+ "func-names": [0],
32
+ "object-shorthand": [0],
33
+ "indent": ["error", "tab"],
34
+ "space-before-function-paren": 0,
35
+ "no-tabs": 0,
36
+ "prefer-destructuring": 0,
37
+ "no-undef": 0,
38
+ "no-param-reassign": 0
39
+ }
40
+ }
v4.0.0/.gitignore ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ .idea/
2
+ .vscode/
3
+ \~/.vscode-root
4
+ /node_modules
5
+ npm-debug.log
6
+ node_modules
7
+ *.DS_Store
8
+ .DS_Store
v4.0.0/.stylelintrc ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "ignoreFiles": "",
3
+ "rules": {
4
+ "at-rule-empty-line-before": null,
5
+ "block-no-empty": true,
6
+ "color-hex-case": "lower",
7
+ "color-no-invalid-hex": true,
8
+ "comment-no-empty": true,
9
+ "declaration-block-no-shorthand-property-overrides": true,
10
+ "declaration-colon-space-before": "never",
11
+ "declaration-no-important": true,
12
+ "font-family-name-quotes": "always-where-recommended",
13
+ "font-weight-notation": "numeric",
14
+ "function-url-quotes": "always",
15
+ "indentation": "tab",
16
+ "max-empty-lines": 1,
17
+ "no-missing-end-of-source-newline": true,
18
+ "number-leading-zero": "always",
19
+ "property-case": "lower",
20
+ "rule-empty-line-before": null,
21
+ "selector-combinator-space-after": "always",
22
+ "selector-list-comma-newline-after": null,
23
+ "selector-max-specificity": "0,3,1",
24
+ "selector-pseudo-element-case": "lower",
25
+ "selector-pseudo-element-colon-notation": "double",
26
+ "unit-case": "lower",
27
+ "unit-no-unknown": true
28
+ }
29
+ }
v4.0.0/assets/admin/fonts/product-sans/Product Sans Bold Italic.ttf ADDED
Binary file
v4.0.0/assets/admin/fonts/product-sans/Product Sans Bold.ttf ADDED
Binary file
v4.0.0/assets/admin/fonts/product-sans/Product Sans Italic.ttf ADDED
Binary file
v4.0.0/assets/admin/fonts/product-sans/Product Sans Medium.ttf ADDED
Binary file
v4.0.0/assets/admin/fonts/product-sans/Product Sans Regular.ttf ADDED
Binary file
v4.0.0/assets/admin/fonts/product-sans/google-product-sans.jpg ADDED
Binary file
v4.0.0/assets/admin/icons/svg/advanced.svg ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <svg width="16" height="15" viewBox="0 0 16 15" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M12.5 9.74414V11.9941H10.25V9.74414H12.5ZM12.5 8.25H10.25C9.83984 8.25 9.48828 8.39648 9.19531 8.68945C8.90234 8.98242 8.75586 9.33398 8.75586 9.74414V11.9941C8.75586 12.416 8.90234 12.7734 9.19531 13.0664C9.48828 13.3594 9.83984 13.5059 10.25 13.5059H12.5C12.9102 13.5059 13.2617 13.3594 13.5547 13.0664C13.8477 12.7734 13.9941 12.416 13.9941 11.9941V9.74414C13.9941 9.33398 13.8477 8.98242 13.5547 8.68945C13.2617 8.39648 12.9102 8.25 12.5 8.25ZM5.75 1.5V5.24414H2.00586V1.5H5.75ZM5.75 0.00585938H2.00586C1.58398 0.00585938 1.22656 0.152344 0.933594 0.445312C0.640625 0.738281 0.494141 1.08984 0.494141 1.5V5.24414C0.494141 5.66602 0.640625 6.02344 0.933594 6.31641C1.22656 6.60938 1.58398 6.75586 2.00586 6.75586H5.75C6.16016 6.75586 6.51172 6.60938 6.80469 6.31641C7.09766 6.02344 7.24414 5.66602 7.24414 5.24414V1.5C7.24414 1.08984 7.09766 0.738281 6.80469 0.445312C6.51172 0.152344 6.16016 0.00585938 5.75 0.00585938ZM13.9941 1.5V5.24414H10.25V1.5H13.9941ZM13.9941 0.00585938H10.25C9.83984 0.00585938 9.48828 0.152344 9.19531 0.445312C8.90234 0.738281 8.75586 1.08984 8.75586 1.5V5.24414C8.75586 5.66602 8.90234 6.02344 9.19531 6.31641C9.48828 6.60938 9.83984 6.75586 10.25 6.75586H13.9941C14.416 6.75586 14.7734 6.60938 15.0664 6.31641C15.3594 6.02344 15.5059 5.66602 15.5059 5.24414V1.5C15.5059 1.08984 15.3594 0.738281 15.0664 0.445312C14.7734 0.152344 14.416 0.00585938 13.9941 0.00585938ZM5.75 9.74414V13.5059H2.00586V9.74414H5.75ZM5.75 8.25H2.00586C1.58398 8.25 1.22656 8.39648 0.933594 8.68945C0.640625 8.98242 0.494141 9.33398 0.494141 9.74414V13.5059C0.494141 13.916 0.640625 14.2676 0.933594 14.5605C1.22656 14.8535 1.58398 15 2.00586 15H5.75C6.16016 15 6.51172 14.8535 6.80469 14.5605C7.09766 14.2676 7.24414 13.916 7.24414 13.5059V9.74414C7.24414 9.33398 7.09766 8.98242 6.80469 8.68945C6.51172 8.39648 6.16016 8.25 5.75 8.25Z" fill="#56606D"/>
3
+ </svg>
v4.0.0/assets/admin/icons/svg/container.svg ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <svg width="14" height="15" viewBox="0 0 14 15" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M11.1309 15H2.86914C2.1543 15 1.53906 14.7422 1.02344 14.2266C0.507812 13.7109 0.25 13.0957 0.25 12.3809V2.625C0.25 1.89844 0.507812 1.2832 1.02344 0.779297C1.53906 0.263672 2.1543 0.00585938 2.86914 0.00585938H11.1309C11.8457 0.00585938 12.4609 0.263672 12.9766 0.779297C13.4922 1.2832 13.75 1.89844 13.75 2.625V12.3809C13.75 13.0957 13.4922 13.7109 12.9766 14.2266C12.4609 14.7422 11.8457 15 11.1309 15ZM2.86914 1.5C2.56445 1.5 2.30078 1.61133 2.07812 1.83398C1.85547 2.05664 1.74414 2.32031 1.74414 2.625V12.3809C1.74414 12.6855 1.85547 12.9492 2.07812 13.1719C2.30078 13.3945 2.56445 13.5059 2.86914 13.5059H11.1309C11.4355 13.5059 11.6992 13.3945 11.9219 13.1719C12.1445 12.9492 12.2559 12.6855 12.2559 12.3809V2.625C12.2559 2.32031 12.1445 2.05664 11.9219 1.83398C11.6992 1.61133 11.4355 1.5 11.1309 1.5H2.86914ZM10.5684 10.5C10.5684 10.3477 10.5098 10.2188 10.3926 10.1133C10.2871 9.99609 10.1582 9.9375 10.0059 9.9375H3.99414C3.8418 9.9375 3.70703 9.99609 3.58984 10.1133C3.48438 10.2188 3.43164 10.3477 3.43164 10.5C3.43164 10.6523 3.48438 10.7871 3.58984 10.9043C3.70703 11.0098 3.8418 11.0625 3.99414 11.0625H10.0059C10.1582 11.0625 10.2871 11.0098 10.3926 10.9043C10.5098 10.7871 10.5684 10.6523 10.5684 10.5ZM10.5684 7.49414C10.5684 7.3418 10.5098 7.21289 10.3926 7.10742C10.2871 6.99023 10.1582 6.93164 10.0059 6.93164H3.99414C3.8418 6.93164 3.70703 6.99023 3.58984 7.10742C3.48438 7.21289 3.43164 7.3418 3.43164 7.49414C3.43164 7.6582 3.48438 7.79297 3.58984 7.89844C3.70703 8.00391 3.8418 8.05664 3.99414 8.05664H10.0059C10.1582 8.05664 10.2871 8.00391 10.3926 7.89844C10.5098 7.79297 10.5684 7.6582 10.5684 7.49414ZM10.5684 4.50586C10.5684 4.3418 10.5098 4.20703 10.3926 4.10156C10.2871 3.99609 10.1582 3.94336 10.0059 3.94336H3.99414C3.8418 3.94336 3.70703 3.99609 3.58984 4.10156C3.48438 4.20703 3.43164 4.3418 3.43164 4.50586C3.43164 4.6582 3.48438 4.79297 3.58984 4.91016C3.70703 5.01562 3.8418 5.06836 3.99414 5.06836H10.0059C10.1582 5.06836 10.2871 5.01562 10.3926 4.91016C10.5098 4.79297 10.5684 4.6582 10.5684 4.50586Z" fill="#56606D"/>
3
+ </svg>
v4.0.0/assets/admin/icons/svg/desktop.svg ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <svg width="20" height="19" viewBox="0 0 20 19" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M15.9512 0.673828H4.04883C3.16081 0.673828 2.40169 0.988932 1.77148 1.61914C1.14128 2.23503 0.826172 2.98698 0.826172 3.875V12.125C0.826172 13.013 1.14128 13.7721 1.77148 14.4023C2.40169 15.0182 3.16081 15.3262 4.04883 15.3262H9.07617V17.1738H6.32617C6.08268 17.1738 5.86784 17.2669 5.68164 17.4531C5.50977 17.625 5.42383 17.8327 5.42383 18.0762C5.42383 18.334 5.50977 18.556 5.68164 18.7422C5.86784 18.9141 6.08268 19 6.32617 19H13.6738C13.9173 19 14.125 18.9141 14.2969 18.7422C14.4831 18.556 14.5762 18.334 14.5762 18.0762C14.5762 17.8327 14.4831 17.625 14.2969 17.4531C14.125 17.2669 13.9173 17.1738 13.6738 17.1738H10.9238V15.3262H15.9512C16.8392 15.3262 17.5983 15.0182 18.2285 14.4023C18.8587 13.7721 19.1738 13.013 19.1738 12.125V3.875C19.1738 2.98698 18.8587 2.23503 18.2285 1.61914C17.5983 0.988932 16.8392 0.673828 15.9512 0.673828ZM17.3262 12.125C17.3262 12.4974 17.1901 12.8197 16.918 13.0918C16.6602 13.3639 16.3379 13.5 15.9512 13.5H4.04883C3.66211 13.5 3.33268 13.3639 3.06055 13.0918C2.80273 12.8197 2.67383 12.4974 2.67383 12.125V3.875C2.67383 3.5026 2.80273 3.18034 3.06055 2.9082C3.33268 2.63607 3.66211 2.5 4.04883 2.5H15.9512C16.3379 2.5 16.6602 2.63607 16.918 2.9082C17.1901 3.18034 17.3262 3.5026 17.3262 3.875V12.125ZM7.76562 3.83203C7.83724 3.90365 7.88737 3.98242 7.91602 4.06836C7.95898 4.13997 7.98047 4.22591 7.98047 4.32617C7.98047 4.42643 7.95898 4.51953 7.91602 4.60547C7.88737 4.67708 7.83724 4.7487 7.76562 4.82031L5.01562 7.57031C4.95833 7.6276 4.88672 7.67057 4.80078 7.69922C4.72917 7.72786 4.64323 7.74219 4.54297 7.74219C4.35677 7.74219 4.19206 7.67773 4.04883 7.54883C3.91992 7.41992 3.85547 7.25521 3.85547 7.05469C3.85547 6.96875 3.86979 6.88997 3.89844 6.81836C3.94141 6.73242 3.99154 6.65365 4.04883 6.58203L6.79883 3.83203C6.85612 3.77474 6.92773 3.73177 7.01367 3.70312C7.09961 3.66016 7.19271 3.63867 7.29297 3.63867C7.37891 3.63867 7.46484 3.66016 7.55078 3.70312C7.63672 3.73177 7.70833 3.77474 7.76562 3.83203Z" fill="white"/>
3
+ </svg>
v4.0.0/assets/admin/icons/svg/dropdowns.svg ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <svg width="18" height="17" viewBox="0 0 18 17" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M9 16.6504C8.08594 16.6387 7.18359 16.5742 6.29297 16.457C5.41406 16.3516 4.55273 16.1934 3.70898 15.9824L3.86719 16C3.30469 15.8242 2.8125 15.5312 2.39062 15.1211C1.98047 14.7109 1.6875 14.2305 1.51172 13.6797L1.49414 13.6445C1.29492 12.8711 1.13672 12.0508 1.01953 11.1836C0.914062 10.3047 0.861328 9.4082 0.861328 8.49414C0.861328 7.58008 0.914062 6.68359 1.01953 5.80469C1.13672 4.92578 1.30664 4.06445 1.5293 3.2207L1.49414 3.36133C1.68164 2.79883 1.98047 2.3125 2.39062 1.90234C2.80078 1.48047 3.28125 1.18164 3.83203 1.00586L3.84961 0.988281H3.86719C4.62891 0.789062 5.44336 0.636719 6.31055 0.53125C7.18945 0.414063 8.08594 0.355469 9 0.355469C9.91406 0.355469 10.8105 0.414063 11.6895 0.53125C12.5801 0.648437 13.4473 0.8125 14.291 1.02344L14.1328 0.988281C14.6953 1.17578 15.1816 1.47461 15.5918 1.88477C16.0137 2.29492 16.3125 2.77539 16.4883 3.32617L16.5059 3.34375C16.7051 4.11719 16.8574 4.94336 16.9629 5.82227C17.0801 6.68945 17.1387 7.58008 17.1387 8.49414C17.1387 9.4082 17.0801 10.3105 16.9629 11.2012C16.8574 12.0801 16.6934 12.9414 16.4707 13.7852L16.5059 13.6445C16.3184 14.207 16.0195 14.6934 15.6094 15.1035C15.1992 15.5137 14.7188 15.8125 14.168 16H14.1504C13.377 16.1992 12.5508 16.3516 11.6719 16.457C10.8047 16.5742 9.91406 16.6328 9 16.6328V16.6504ZM4.23633 2.44727C3.93164 2.56445 3.66797 2.73438 3.44531 2.95703C3.22266 3.16797 3.05859 3.41992 2.95312 3.71289V3.73047C2.76562 4.44531 2.61914 5.20703 2.51367 6.01562C2.4082 6.82422 2.35547 7.65039 2.35547 8.49414C2.35547 9.34961 2.4082 10.1875 2.51367 11.0078C2.61914 11.8281 2.77734 12.6309 2.98828 13.416L2.95312 13.2754C3.05859 13.5684 3.22266 13.8262 3.44531 14.0488C3.66797 14.2715 3.92578 14.4355 4.21875 14.541L4.23633 14.5586C4.95117 14.7461 5.71289 14.8926 6.52148 14.998C7.33008 15.0918 8.15625 15.1387 9 15.1387C9.84375 15.1387 10.6758 15.0859 11.4961 14.9805C12.3281 14.875 13.1367 14.7227 13.9219 14.5234L13.7812 14.541C14.0742 14.4355 14.332 14.2715 14.5547 14.0488C14.7773 13.8262 14.9414 13.5684 15.0469 13.2754C15.2344 12.5488 15.3809 11.7871 15.4863 10.9902C15.5918 10.1816 15.6445 9.34961 15.6445 8.49414C15.6445 7.65039 15.5918 6.81836 15.4863 5.99805C15.3809 5.17773 15.2227 4.375 15.0117 3.58984L15.0469 3.73047C14.9414 3.42578 14.7773 3.16797 14.5547 2.95703C14.332 2.73438 14.0742 2.56445 13.7812 2.44727H13.7637C13.0488 2.25977 12.2871 2.11328 11.4785 2.00781C10.6699 1.90234 9.84375 1.84961 9 1.84961C8.15625 1.84961 7.32422 1.90234 6.50391 2.00781C5.68359 2.11328 4.88086 2.27148 4.0957 2.48242L4.23633 2.44727ZM9.52734 10.3398L12.1465 7.7207C12.2168 7.65039 12.2695 7.57422 12.3047 7.49219C12.3398 7.39844 12.3574 7.29883 12.3574 7.19336C12.3574 6.99414 12.2812 6.82422 12.1289 6.68359C11.9883 6.53125 11.8184 6.45508 11.6191 6.45508C11.5137 6.45508 11.4141 6.47266 11.3203 6.50781C11.2383 6.54297 11.1621 6.5957 11.0918 6.66602L9 8.75781L6.9082 6.66602C6.83789 6.58398 6.75586 6.52539 6.66211 6.49023C6.56836 6.44336 6.46875 6.41992 6.36328 6.41992C6.15234 6.41992 5.9707 6.49609 5.81836 6.64844C5.67773 6.78906 5.60742 6.96484 5.60742 7.17578C5.60742 7.28125 5.625 7.38086 5.66016 7.47461C5.70703 7.56836 5.76562 7.65039 5.83594 7.7207L8.47266 10.3398C8.54297 10.4102 8.61914 10.4688 8.70117 10.5156C8.79492 10.5508 8.89453 10.5684 9 10.5684C9.10547 10.5684 9.19922 10.5508 9.28125 10.5156C9.375 10.4688 9.45703 10.4102 9.52734 10.3398Z" fill="#56606D"/>
3
+ </svg>
v4.0.0/assets/admin/icons/svg/general.svg ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <svg width="18" height="17" viewBox="0 0 18 17" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M6.8418 16.9941C6.80273 16.9941 6.77018 16.9941 6.74414 16.9941C6.7181 16.9941 6.69206 16.9941 6.66602 16.9941C6.37956 16.9811 6.11263 16.929 5.86523 16.8379C5.61784 16.7467 5.38997 16.623 5.18164 16.4668L3.63867 15.334C3.32617 15.0866 3.07878 14.7871 2.89648 14.4355C2.71419 14.071 2.62305 13.6803 2.62305 13.2637C2.62305 12.9772 2.66211 12.7103 2.74023 12.4629C2.83138 12.2025 2.94857 11.9681 3.0918 11.7598C3.13086 11.7077 3.1569 11.6491 3.16992 11.584C3.19596 11.5189 3.20898 11.4473 3.20898 11.3691C3.20898 11.3301 3.20247 11.291 3.18945 11.252C3.18945 11.2129 3.18294 11.1738 3.16992 11.1348L3.11133 11.0176C3.09831 10.9395 3.06576 10.8678 3.01367 10.8027C2.97461 10.7376 2.92904 10.6855 2.87695 10.6465H2.85742C2.83138 10.6465 2.79883 10.64 2.75977 10.627C2.73372 10.6139 2.70117 10.6074 2.66211 10.6074H2.68164C2.16081 10.4251 1.73112 10.1126 1.39258 9.66992C1.06706 9.21419 0.904297 8.70638 0.904297 8.14648C0.904297 8.00326 0.917318 7.86654 0.943359 7.73633C0.969401 7.5931 1.00195 7.45638 1.04102 7.32617V7.3457L1.64648 5.41211C1.78971 4.87826 2.07617 4.44206 2.50586 4.10352C2.94857 3.76497 3.45638 3.5957 4.0293 3.5957C4.17253 3.5957 4.30924 3.60872 4.43945 3.63477C4.56966 3.64779 4.69987 3.68034 4.83008 3.73242L4.81055 3.71289C4.84961 3.72591 4.88216 3.73893 4.9082 3.75195C4.93424 3.75195 4.9668 3.75195 5.00586 3.75195C5.07096 3.75195 5.13607 3.74544 5.20117 3.73242C5.26628 3.70638 5.32487 3.67383 5.37695 3.63477L5.47461 3.55664C5.53971 3.50456 5.5918 3.43945 5.63086 3.36133C5.66992 3.27018 5.68945 3.17904 5.68945 3.08789V2.91211C5.68945 2.19596 5.93685 1.59049 6.43164 1.0957C6.92643 0.587891 7.52539 0.333984 8.22852 0.333984H10.1621C10.5137 0.333984 10.8392 0.399089 11.1387 0.529297C11.4512 0.659505 11.7181 0.841797 11.9395 1.07617C12.1738 1.31055 12.3561 1.58398 12.4863 1.89648C12.6296 2.20898 12.7012 2.54102 12.7012 2.89258C12.7012 2.9056 12.7012 2.91862 12.7012 2.93164V3.12695C12.7012 3.12695 12.7012 3.13346 12.7012 3.14648C12.7012 3.22461 12.7142 3.30273 12.7402 3.38086C12.7793 3.44596 12.8249 3.49805 12.877 3.53711H12.8965L12.9551 3.5957C12.9941 3.62174 13.0397 3.64779 13.0918 3.67383C13.1439 3.68685 13.196 3.69336 13.248 3.69336C13.2741 3.69336 13.3001 3.69336 13.3262 3.69336C13.3522 3.68034 13.3783 3.67383 13.4043 3.67383L13.6582 3.57617C13.7754 3.53711 13.8991 3.51107 14.0293 3.49805C14.1595 3.47201 14.2962 3.45898 14.4395 3.45898C14.9993 3.45898 15.4941 3.62174 15.9238 3.94727C16.3665 4.25977 16.6725 4.66992 16.8418 5.17773V5.19727C16.8418 5.19727 16.8418 5.21029 16.8418 5.23633C16.8548 5.26237 16.8613 5.27539 16.8613 5.27539L17.4668 7.15039C17.4928 7.26758 17.5189 7.39128 17.5449 7.52148C17.571 7.65169 17.584 7.78841 17.584 7.93164C17.584 8.49154 17.4212 8.99284 17.0957 9.43555C16.7702 9.87825 16.36 10.1908 15.8652 10.373H15.8457L15.6895 10.4316C15.5983 10.4577 15.5137 10.5098 15.4355 10.5879C15.3704 10.653 15.3249 10.7311 15.2988 10.8223V10.8418C15.2858 10.8678 15.2793 10.9004 15.2793 10.9395C15.2793 10.9655 15.2793 10.9915 15.2793 11.0176C15.2793 11.0827 15.2858 11.1478 15.2988 11.2129C15.3249 11.278 15.3509 11.3366 15.377 11.3887L15.5723 11.6621C15.7155 11.8704 15.8262 12.0983 15.9043 12.3457C15.9824 12.5931 16.0215 12.86 16.0215 13.1465C16.0215 13.5632 15.9303 13.9538 15.748 14.3184C15.5658 14.6699 15.3249 14.9629 15.0254 15.1973L15.0059 15.2168L13.502 16.3691C13.2936 16.5384 13.0592 16.6686 12.7988 16.7598C12.5384 16.8509 12.265 16.8965 11.9785 16.8965C11.5749 16.8965 11.1973 16.8053 10.8457 16.623C10.5072 16.4408 10.2207 16.2064 9.98633 15.9199V15.9004L9.81055 15.666C9.75846 15.6009 9.69336 15.5488 9.61523 15.5098C9.55013 15.4577 9.472 15.4316 9.38086 15.4316C9.30273 15.4316 9.22461 15.4577 9.14648 15.5098C9.08138 15.5488 9.02279 15.5944 8.9707 15.6465V15.666L8.81445 15.9004C8.61914 16.1868 8.37826 16.4212 8.0918 16.6035C7.80534 16.7858 7.49284 16.9095 7.1543 16.9746H7.13477C7.0957 16.9876 7.05013 16.9941 6.99805 16.9941C6.94596 16.9941 6.89388 16.9941 6.8418 16.9941ZM3.0918 8.98633C3.14388 8.98633 3.18945 8.99284 3.22852 9.00586C3.2806 9.00586 3.32617 9.01237 3.36523 9.02539H3.3457C3.68424 9.1556 3.9707 9.35091 4.20508 9.61133C4.43945 9.85872 4.60221 10.1517 4.69336 10.4902V10.5098L4.73242 10.5488C4.77148 10.679 4.80404 10.8158 4.83008 10.959C4.85612 11.0892 4.86914 11.2259 4.86914 11.3691C4.86914 11.6165 4.83008 11.8574 4.75195 12.0918C4.68685 12.3132 4.58919 12.5215 4.45898 12.7168C4.4069 12.7819 4.36133 12.8665 4.32227 12.9707C4.29622 13.0618 4.2832 13.153 4.2832 13.2441C4.2832 13.4004 4.31576 13.5436 4.38086 13.6738C4.44596 13.804 4.53711 13.9147 4.6543 14.0059L6.19727 15.1387C6.26237 15.1908 6.34049 15.2363 6.43164 15.2754C6.52279 15.3014 6.61393 15.3145 6.70508 15.3145C6.7181 15.3145 6.73112 15.321 6.74414 15.334C6.75716 15.334 6.77018 15.334 6.7832 15.334C6.79622 15.334 6.80924 15.334 6.82227 15.334C6.83529 15.334 6.8418 15.334 6.8418 15.334C6.85482 15.334 6.86784 15.334 6.88086 15.334C6.89388 15.334 6.9069 15.334 6.91992 15.334C7.02409 15.3079 7.11523 15.2624 7.19336 15.1973C7.28451 15.1322 7.36263 15.054 7.42773 14.9629L7.60352 14.709C7.81185 14.4225 8.06576 14.1947 8.36523 14.0254C8.67773 13.8561 9.02279 13.7715 9.40039 13.7715C9.76497 13.7715 10.1035 13.8626 10.416 14.0449C10.7285 14.2142 10.9824 14.4355 11.1777 14.709V14.7285L11.2559 14.8457C11.334 14.9368 11.4186 15.0215 11.5098 15.0996C11.6139 15.1647 11.7311 15.2038 11.8613 15.2168C11.8743 15.2168 11.8874 15.2168 11.9004 15.2168C11.9264 15.2168 11.9525 15.2168 11.9785 15.2168C12.0697 15.2168 12.1608 15.2038 12.252 15.1777C12.3431 15.1517 12.4212 15.1061 12.4863 15.041V15.0605L13.9902 13.8887C14.1074 13.7975 14.1986 13.6868 14.2637 13.5566C14.3288 13.4264 14.3613 13.2897 14.3613 13.1465C14.3613 13.0423 14.3418 12.9447 14.3027 12.8535C14.2767 12.7624 14.2376 12.6777 14.1855 12.5996L13.9902 12.3066C13.873 12.1243 13.7754 11.929 13.6973 11.7207C13.6322 11.4993 13.5996 11.265 13.5996 11.0176C13.5996 10.9004 13.6061 10.7897 13.6191 10.6855C13.6452 10.5684 13.6712 10.4577 13.6973 10.3535V10.373C13.8014 10.0085 13.9772 9.69596 14.2246 9.43555C14.485 9.16211 14.791 8.97331 15.1426 8.86914L15.1621 8.84961L15.2988 8.81055C15.4811 8.74544 15.6243 8.63477 15.7285 8.47852C15.8457 8.30924 15.9043 8.12695 15.9043 7.93164C15.9043 7.87956 15.8978 7.83398 15.8848 7.79492C15.8848 7.74284 15.8783 7.69076 15.8652 7.63867L15.2793 5.76367C15.2402 5.64648 15.1816 5.54232 15.1035 5.45117C15.0254 5.34701 14.9342 5.26888 14.8301 5.2168C14.778 5.19076 14.7194 5.17122 14.6543 5.1582C14.5892 5.13216 14.5176 5.11914 14.4395 5.11914C14.4004 5.11914 14.3548 5.12565 14.3027 5.13867C14.2507 5.13867 14.2051 5.15169 14.166 5.17773V5.1582L13.9121 5.25586C13.8079 5.2819 13.6973 5.30794 13.5801 5.33398C13.4759 5.34701 13.3652 5.35352 13.248 5.35352C13.0007 5.35352 12.7663 5.32096 12.5449 5.25586C12.3366 5.17773 12.1413 5.06706 11.959 4.92383L11.8809 4.88477C11.6204 4.67643 11.4121 4.42253 11.2559 4.12305C11.0996 3.82357 11.0215 3.49805 11.0215 3.14648C11.0215 3.13346 11.0215 3.12044 11.0215 3.10742V2.91211C11.0215 2.7819 10.9954 2.6582 10.9434 2.54102C10.9043 2.42383 10.8457 2.32617 10.7676 2.24805C10.6895 2.16992 10.5983 2.11133 10.4941 2.07227C10.39 2.02018 10.2728 1.99414 10.1426 1.99414H8.24805C8.00065 1.99414 7.78581 2.08529 7.60352 2.26758C7.43424 2.43685 7.34961 2.64518 7.34961 2.89258C7.34961 2.89258 7.34961 2.89909 7.34961 2.91211V3.08789C7.34961 3.45247 7.27148 3.79102 7.11523 4.10352C6.97201 4.40299 6.77018 4.6569 6.50977 4.86523L6.39258 4.96289C6.19727 5.10612 5.98242 5.2168 5.74805 5.29492C5.51367 5.37305 5.26628 5.41211 5.00586 5.41211C4.87565 5.41211 4.74544 5.4056 4.61523 5.39258C4.49805 5.36654 4.38086 5.33398 4.26367 5.29492H4.2832C4.24414 5.2819 4.19857 5.27539 4.14648 5.27539C4.10742 5.26237 4.06836 5.25586 4.0293 5.25586C3.96419 5.25586 3.89909 5.26237 3.83398 5.27539C3.76888 5.28841 3.71029 5.30794 3.6582 5.33398C3.56706 5.38607 3.48242 5.45768 3.4043 5.54883C3.33919 5.63997 3.28711 5.74414 3.24805 5.86133L2.62305 7.85352C2.61003 7.9056 2.59701 7.95768 2.58398 8.00977C2.58398 8.04883 2.58398 8.0944 2.58398 8.14648C2.58398 8.32878 2.62956 8.49805 2.7207 8.6543C2.81185 8.79753 2.93555 8.9082 3.0918 8.98633ZM9.24414 11.9941C8.31966 11.9941 7.5319 11.6686 6.88086 11.0176C6.22982 10.3665 5.9043 9.57878 5.9043 8.6543C5.9043 7.74284 6.22982 6.96159 6.88086 6.31055C7.5319 5.65951 8.31966 5.33398 9.24414 5.33398C10.1686 5.33398 10.9564 5.65951 11.6074 6.31055C12.2585 6.96159 12.584 7.74284 12.584 8.6543C12.584 9.57878 12.2585 10.3665 11.6074 11.0176C10.9564 11.6686 10.1686 11.9941 9.24414 11.9941ZM9.24414 6.99414C8.78841 6.99414 8.39779 7.1569 8.07227 7.48242C7.74674 7.80794 7.58398 8.19857 7.58398 8.6543C7.58398 9.12305 7.74674 9.52018 8.07227 9.8457C8.39779 10.1712 8.78841 10.334 9.24414 10.334C9.69987 10.334 10.0905 10.1712 10.416 9.8457C10.7415 9.52018 10.9043 9.12305 10.9043 8.6543C10.9043 8.19857 10.7415 7.80794 10.416 7.48242C10.0905 7.1569 9.69987 6.99414 9.24414 6.99414Z" fill="#56606D"/>
3
+ </svg>
v4.0.0/assets/admin/icons/svg/header.svg ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M13.4102 0.160156H2.58984C2.01693 0.160156 1.52214 0.36849 1.10547 0.785156C0.701823 1.1888 0.5 1.67708 0.5 2.25V13.0898C0.5 13.6628 0.701823 14.151 1.10547 14.5547C1.52214 14.9583 2.01693 15.1602 2.58984 15.1602H13.4102C13.9831 15.1602 14.4714 14.9583 14.875 14.5547C15.2917 14.151 15.5 13.6628 15.5 13.0898V2.25C15.5 1.67708 15.2917 1.1888 14.875 0.785156C14.4714 0.36849 13.9831 0.160156 13.4102 0.160156ZM2.16016 2.25C2.16016 2.13281 2.19922 2.03516 2.27734 1.95703C2.36849 1.87891 2.47266 1.83984 2.58984 1.83984H13.4102C13.5273 1.83984 13.625 1.87891 13.7031 1.95703C13.7943 2.03516 13.8398 2.13281 13.8398 2.25V3.5H2.16016V2.25ZM13.8398 13.0898C13.8398 13.194 13.7943 13.2917 13.7031 13.3828C13.625 13.4609 13.5273 13.5 13.4102 13.5H2.58984C2.47266 13.5 2.36849 13.4609 2.27734 13.3828C2.19922 13.2917 2.16016 13.194 2.16016 13.0898V5.16016H13.8398V13.0898Z" fill="#56606D"/>
3
+ </svg>
v4.0.0/assets/admin/icons/svg/image-placeholder.svg ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <svg width="23" height="22" viewBox="0 0 23 22" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g opacity="0.7">
3
+ <path d="M20.97 9.44678L18.2903 19.2319C18.0012 20.2869 16.8815 20.9043 15.7959 20.608L2.22618 16.8974C2.13863 16.8736 2.05317 16.8414 1.9771 16.811C1.08818 16.4491 0.570175 15.5212 0.747891 14.6C0.75259 14.5468 0.766863 14.4955 0.781136 14.4442L3.46096 4.65996C3.74903 3.6049 4.86876 2.98668 5.95437 3.28388L19.5241 6.99355C20.6107 7.28988 21.2589 8.39155 20.97 9.44678Z" fill="#F5F6FA"/>
4
+ <path d="M23 2.15624V13.1771C23 14.3654 22.0366 15.3334 20.8538 15.3334H6.0687C5.97334 15.3334 5.87798 15.3237 5.79204 15.3141C4.79054 15.1896 4.00842 14.3654 3.93209 13.3496C3.92249 13.2921 3.92249 13.2345 3.92249 13.1771V2.15624C3.92249 0.96792 4.88591 0 6.0687 0H20.8538C22.0366 0 23 0.96792 23 2.15624Z" fill="white"/>
5
+ <path d="M9.98455 4.81396C9.98455 5.60166 9.3459 6.24032 8.5582 6.24032C7.77032 6.24032 7.13184 5.60166 7.13184 4.81396C7.13184 4.02626 7.77032 3.3876 8.5582 3.3876C9.3459 3.3876 9.98455 4.02626 9.98455 4.81396Z" fill="#FFC107"/>
6
+ <path d="M21.5736 10.6444V13.0502C21.5736 14.1114 20.8353 14.9768 19.9284 14.9768H8.59141C8.51806 14.9768 8.44558 14.9682 8.37974 14.9597L15.9128 6.14187C16.4098 5.55997 17.2291 5.55997 17.727 6.14187L21.5736 10.6444Z" fill="#DFF6FF"/>
7
+ <path d="M15.5115 14.3801L6.36686 14.6202C6.29704 14.6202 6.22827 14.6135 6.16615 14.6058C5.43785 14.5155 4.86931 13.916 4.81384 13.1772L9.06272 9.6265C9.53378 9.15296 10.3107 9.15296 10.782 9.6265L15.5115 14.3801Z" fill="#DFF6FF"/>
8
+ <path d="M16.9937 21.0388C16.8123 21.0388 16.6271 21.016 16.4436 20.9684L1.59866 17.0272C0.453491 16.714 -0.229043 15.5396 0.0704773 14.4052L1.70237 8.2009C1.80221 7.82012 2.19489 7.58887 2.58072 7.69081C2.96479 7.7898 3.19611 8.17998 3.09539 8.56163L1.46332 14.7669C1.3626 15.1495 1.59199 15.5444 1.97605 15.6491L16.8123 19.5884C17.1934 19.6883 17.587 19.4636 17.6868 19.0877L18.1936 17.0605C18.2897 16.678 18.6794 16.4457 19.0652 16.5391C19.4512 16.6342 19.6864 17.0206 19.5913 17.4031L19.0826 19.4399C18.8262 20.404 17.9508 21.0388 16.9937 21.0388Z" fill="#36BEF7"/>
9
+ <path d="M20.8538 15.3334H6.0687C4.88504 15.3334 3.92249 14.3663 3.92249 13.1771V2.15624C3.92249 0.967043 4.88504 0 6.0687 0H20.8538C22.0375 0 23 0.967043 23 2.15624V13.1771C23 14.3663 22.0375 15.3334 20.8538 15.3334ZM6.0687 1.43749C5.6738 1.43749 5.3533 1.75949 5.3533 2.15624V13.1771C5.3533 13.5739 5.6738 13.8959 6.0687 13.8959H20.8538C21.2487 13.8959 21.5692 13.5739 21.5692 13.1771V2.15624C21.5692 1.75949 21.2487 1.43749 20.8538 1.43749H6.0687Z" fill="#36BEF7"/>
10
+ <path d="M8.64745 6.77518C7.61495 6.77518 6.77527 5.89556 6.77527 4.81394C6.77527 3.73232 7.61495 2.85269 8.64745 2.85269C9.67995 2.85269 10.5195 3.73232 10.5195 4.81394C10.5195 5.89556 9.67995 6.77518 8.64745 6.77518ZM8.64745 4.32358C8.38898 4.32358 8.17936 4.54335 8.17936 4.81394C8.17936 5.08452 8.38898 5.30429 8.64745 5.30429C8.90575 5.30429 9.11537 5.08452 9.11537 4.81394C9.11537 4.54335 8.90575 4.32358 8.64745 4.32358Z" fill="#36BEF7"/>
11
+ <path d="M4.63832 14.2636C4.45508 14.2636 4.27166 14.195 4.1323 14.0571C3.85255 13.782 3.85255 13.3358 4.1323 13.0607L8.44846 8.81637C9.1017 8.174 10.1644 8.174 10.8166 8.81637L11.9711 9.95169L15.5176 5.76547C15.8346 5.39167 16.2997 5.17571 16.7935 5.17296C17.3243 5.1439 17.7541 5.38135 18.0739 5.75051L22.8275 11.2043C23.0853 11.4992 23.0499 11.9443 22.7501 12.1977C22.4493 12.4514 21.9977 12.4166 21.7398 12.1217L16.9844 6.66609C16.9213 6.59181 16.844 6.59559 16.801 6.58235C16.7601 6.58235 16.6807 6.59456 16.6178 6.66781L12.569 11.4476C12.4399 11.5996 12.252 11.6917 12.0514 11.7001C11.847 11.7113 11.6541 11.6343 11.5127 11.4945L9.80354 9.81362C9.6822 9.6943 9.58201 9.6943 9.46066 9.81362L5.14451 14.0571C5.00498 14.195 4.82174 14.2636 4.63832 14.2636Z" fill="#36BEF7"/>
12
+ </g>
13
+ </svg>
v4.0.0/assets/admin/icons/svg/mobile.svg ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <svg width="15" height="20" viewBox="0 0 15 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M7.5 5.625C7.5 5.625 7.49251 5.625 7.47754 5.625C7.28288 5.625 7.10319 5.57259 6.93848 5.46777C6.78874 5.34798 6.68392 5.20573 6.62402 5.04102C6.59408 4.98112 6.57161 4.92122 6.55664 4.86133C6.54167 4.80143 6.53418 4.74154 6.53418 4.68164C6.53418 4.68164 6.53418 4.67415 6.53418 4.65918C6.53418 4.62923 6.53418 4.59928 6.53418 4.56934C6.54915 4.53939 6.55664 4.50195 6.55664 4.45703V4.47949C6.57161 4.44954 6.5791 4.4196 6.5791 4.38965C6.59408 4.3597 6.60905 4.32975 6.62402 4.2998C6.639 4.26986 6.64648 4.23991 6.64648 4.20996C6.66146 4.18001 6.68392 4.15007 6.71387 4.12012C6.72884 4.10514 6.74382 4.08268 6.75879 4.05273C6.77376 4.02279 6.79622 4.00033 6.82617 3.98535C6.90104 3.89551 6.99837 3.82812 7.11816 3.7832C7.23796 3.73828 7.36523 3.71582 7.5 3.71582C7.52995 3.71582 7.5599 3.71582 7.58984 3.71582C7.61979 3.71582 7.64974 3.72331 7.67969 3.73828C7.70964 3.73828 7.73958 3.74577 7.76953 3.76074C7.81445 3.76074 7.8444 3.76823 7.85938 3.7832C7.88932 3.79818 7.91927 3.81315 7.94922 3.82812C7.97917 3.8431 8.00911 3.85807 8.03906 3.87305C8.06901 3.88802 8.09147 3.91048 8.10645 3.94043C8.13639 3.9554 8.15885 3.97038 8.17383 3.98535C8.20378 4.00033 8.22624 4.02279 8.24121 4.05273C8.25618 4.08268 8.27116 4.10514 8.28613 4.12012C8.31608 4.15007 8.33105 4.18001 8.33105 4.20996C8.34603 4.23991 8.361 4.26986 8.37598 4.2998C8.39095 4.32975 8.39844 4.3597 8.39844 4.38965C8.41341 4.4196 8.42839 4.44954 8.44336 4.47949C8.44336 4.50944 8.44336 4.53939 8.44336 4.56934C8.45833 4.59928 8.46582 4.62923 8.46582 4.65918C8.46582 4.73405 8.45833 4.80143 8.44336 4.86133C8.42839 4.92122 8.40592 4.98112 8.37598 5.04102C8.361 5.10091 8.33105 5.16081 8.28613 5.2207C8.25618 5.26562 8.21875 5.31055 8.17383 5.35547C8.08398 5.43034 7.97917 5.49772 7.85938 5.55762C7.75456 5.60254 7.63477 5.625 7.5 5.625ZM9.40918 16.1592C9.40918 15.9046 9.31185 15.6875 9.11719 15.5078C8.9375 15.3132 8.72038 15.2158 8.46582 15.2158H6.53418C6.27962 15.2158 6.05501 15.3132 5.86035 15.5078C5.68066 15.6875 5.59082 15.9046 5.59082 16.1592C5.59082 16.4287 5.68066 16.6608 5.86035 16.8555C6.05501 17.0352 6.27962 17.125 6.53418 17.125H8.46582C8.72038 17.125 8.9375 17.0352 9.11719 16.8555C9.31185 16.6608 9.40918 16.4287 9.40918 16.1592ZM14.2158 16.6533V4.1875C14.2158 3.25911 13.8864 2.47298 13.2275 1.8291C12.5687 1.17025 11.7751 0.84082 10.8467 0.84082H4.15332C3.22493 0.84082 2.43132 1.17025 1.77246 1.8291C1.11361 2.47298 0.78418 3.25911 0.78418 4.1875V16.6533C0.78418 17.5667 1.11361 18.3529 1.77246 19.0117C2.43132 19.6706 3.22493 20 4.15332 20H10.8467C11.7751 20 12.5687 19.6706 13.2275 19.0117C13.8864 18.3529 14.2158 17.5667 14.2158 16.6533ZM10.8467 2.75C11.251 2.75 11.5879 2.89225 11.8574 3.17676C12.1419 3.46126 12.2842 3.79818 12.2842 4.1875V16.6533C12.2842 17.0426 12.1419 17.3796 11.8574 17.6641C11.5879 17.9486 11.251 18.0908 10.8467 18.0908H4.15332C3.74902 18.0908 3.40462 17.9486 3.12012 17.6641C2.85059 17.3796 2.71582 17.0426 2.71582 16.6533V4.1875C2.71582 3.79818 2.85059 3.46126 3.12012 3.17676C3.40462 2.89225 3.74902 2.75 4.15332 2.75H10.8467Z" fill="#56606D"/>
3
+ </svg>
v4.0.0/assets/admin/icons/svg/tablet.svg ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <svg width="16" height="19" viewBox="0 0 16 19" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M12.125 19H3.875C2.98698 19 2.22786 18.6849 1.59766 18.0547C0.981771 17.4245 0.673828 16.6725 0.673828 15.7988V3.875C0.673828 2.98698 0.981771 2.23503 1.59766 1.61914C2.22786 0.988932 2.98698 0.673828 3.875 0.673828H12.125C13.013 0.673828 13.765 0.988932 14.3809 1.61914C15.0111 2.23503 15.3262 2.98698 15.3262 3.875V15.7988C15.3262 16.6725 15.0111 17.4245 14.3809 18.0547C13.765 18.6849 13.013 19 12.125 19ZM3.875 2.5C3.5026 2.5 3.18034 2.63607 2.9082 2.9082C2.63607 3.18034 2.5 3.5026 2.5 3.875V15.7988C2.5 16.1712 2.63607 16.4935 2.9082 16.7656C3.18034 17.0378 3.5026 17.1738 3.875 17.1738H12.125C12.4974 17.1738 12.8197 17.0378 13.0918 16.7656C13.3639 16.4935 13.5 16.1712 13.5 15.7988V3.875C13.5 3.5026 13.3639 3.18034 13.0918 2.9082C12.8197 2.63607 12.4974 2.5 12.125 2.5H3.875ZM8.64453 15.9922C8.73047 15.9062 8.79492 15.806 8.83789 15.6914C8.89518 15.5768 8.92383 15.4622 8.92383 15.3477C8.92383 15.3333 8.92383 15.3262 8.92383 15.3262C8.92383 15.0827 8.83073 14.875 8.64453 14.7031C8.47266 14.5169 8.25781 14.4238 8 14.4238C7.74219 14.4238 7.52018 14.5169 7.33398 14.7031C7.16211 14.875 7.07617 15.0827 7.07617 15.3262C7.07617 15.584 7.16211 15.806 7.33398 15.9922C7.52018 16.1641 7.74219 16.25 8 16.25C8.12891 16.25 8.24349 16.2285 8.34375 16.1855C8.45833 16.1283 8.55859 16.0638 8.64453 15.9922Z" fill="#56606D"/>
3
+ </svg>
v4.0.0/assets/admin/icons/svg/toggle.svg ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <svg width="16" height="11" viewBox="0 0 16 11" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M14.6719 6H1.32812C1.15104 6 0.994792 5.9375 0.859375 5.8125C0.734375 5.67708 0.671875 5.51562 0.671875 5.32812C0.671875 5.15104 0.734375 5 0.859375 4.875C0.994792 4.73958 1.15104 4.67188 1.32812 4.67188H14.6719C14.849 4.67188 15 4.73958 15.125 4.875C15.2604 5 15.3281 5.15104 15.3281 5.32812C15.3281 5.51562 15.2604 5.67708 15.125 5.8125C15 5.9375 14.849 6 14.6719 6ZM15.3281 0.671875C15.3281 0.484375 15.2604 0.328125 15.125 0.203125C15 0.0677083 14.849 0 14.6719 0H1.32812C1.15104 0 0.994792 0.0677083 0.859375 0.203125C0.734375 0.328125 0.671875 0.484375 0.671875 0.671875C0.671875 0.848958 0.734375 1.00521 0.859375 1.14062C0.994792 1.26562 1.15104 1.32812 1.32812 1.32812H14.6719C14.849 1.32812 15 1.26562 15.125 1.14062C15.2604 1.00521 15.3281 0.848958 15.3281 0.671875ZM15.3281 10C15.3281 9.8125 15.2604 9.65625 15.125 9.53125C15 9.39583 14.849 9.32812 14.6719 9.32812H1.32812C1.15104 9.32812 0.994792 9.39583 0.859375 9.53125C0.734375 9.65625 0.671875 9.8125 0.671875 10C0.671875 10.1875 0.734375 10.349 0.859375 10.4844C0.994792 10.6094 1.15104 10.6719 1.32812 10.6719H14.6719C14.849 10.6719 15 10.6094 15.125 10.4844C15.2604 10.349 15.3281 10.1875 15.3281 10Z" fill="#56606D"/>
3
+ </svg>
v4.0.0/assets/admin/js/rmp-admin.js ADDED
@@ -0,0 +1,775 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This is admin scripts file which contain the admin actions.
3
+ *
4
+ * @version 4.0.0
5
+ *
6
+ * @author Expresstech System
7
+ *
8
+ */
9
+
10
+ jQuery( document ).ready( function( jQuery ) {
11
+
12
+ /**
13
+ * Open new create menu wizard on click event.
14
+ *
15
+ * @since 4.0.0
16
+ *
17
+ * @fires Click
18
+ */
19
+ jQuery( document ).on( 'click', 'a.page-title-action', function( e ) {
20
+ e.preventDefault();
21
+ jQuery( '#rmp-new-menu-wizard' ).show();
22
+ } );
23
+
24
+ /**
25
+ * Close the new menu wizard.
26
+ *
27
+ * @since 4.0.0
28
+ *
29
+ * @fires Click
30
+ */
31
+ jQuery( '#rmp-new-menu-wizard .rmp-dialog-header button.close' ).on( 'click', function() {
32
+ jQuery( '#rmp-new-menu-wizard' ).hide();
33
+ } );
34
+
35
+ /**
36
+ * Move on next tab content for theme selection.
37
+ */
38
+ jQuery( '#rmp-create-menu-first-step' ).on( 'click', () => {
39
+ jQuery( '#rmp-create-menu-first-step' ).hide();
40
+ jQuery( '#rmp-create-new-menu' ).show();
41
+ jQuery( 'a[href="#select-themes"]' ).trigger( 'click' );
42
+ } );
43
+
44
+ // Handle next and create button visibility.
45
+ jQuery( 'a[href="#select-themes"]' ).on( 'click', ()=> {
46
+ jQuery( '#rmp-create-new-menu' ).show();
47
+ jQuery( '#rmp-create-menu-first-step' ).hide();
48
+ } );
49
+
50
+ // Handle next and create button visibility.
51
+ jQuery( 'a[href="#menu-settings"]' ).on( 'click', () => {
52
+ jQuery( '#rmp-create-new-menu' ).hide();
53
+ jQuery( '#rmp-create-menu-first-step' ).show();
54
+ } );
55
+
56
+ /**
57
+ * Call ajax to save the new create menu.
58
+ *
59
+ * @version 4.0.0
60
+ *
61
+ * @fires Click
62
+ */
63
+ jQuery( '#rmp-create-new-menu' ).on( 'click', function( e ) {
64
+ e.preventDefault();
65
+ let menuName = jQuery( '#rmp-menu-name' );
66
+ let themeName = jQuery( '.rmp-theme-option:checked' ).val();
67
+
68
+ if ( themeName == undefined ) {
69
+ themeName = '';
70
+ }
71
+
72
+ jQuery.ajax( {
73
+ url: rmpObject.ajaxURL,
74
+ data: {
75
+ 'action': 'rmp_create_new_menu',
76
+ 'ajax_nonce': rmpObject.ajax_nonce,
77
+ 'menu_name': menuName.val(),
78
+ 'menu_to_use': jQuery( '#rmp-menu-to-use' ).val(),
79
+ 'menu_show_on_pages': jQuery( '#rmp-menu-display-on-pages' ).val(),
80
+ 'menu_show_on': jQuery( '.rmp-menu-display-option' ).val(),
81
+ 'menu_theme': themeName,
82
+ 'theme_type': jQuery( '.rmp-theme-option:checked' ).attr( 'theme-type' )
83
+ },
84
+ type: 'POST',
85
+ dataType: 'json',
86
+ beforeSend: function() {
87
+ jQuery( '#rmp-create-new-menu' ).prop( 'disabled', true );
88
+ jQuery( '.spinner' ).addClass( 'is-active' );
89
+ },
90
+ error: function( error ) {
91
+ console.log( 'Internal Error !' );
92
+ jQuery( '#rmp-create-new-menu' ).prop( 'disabled', false );
93
+ jQuery( '.spinner' ).removeClass( 'is-active' );
94
+ },
95
+ success: function( response ) {
96
+ jQuery( '#rmp-create-new-menu' ).prop( 'disabled', false );
97
+ noticeClass = 'notice-error';
98
+ if ( true == response.success ) {
99
+ isSuccess = 'notice-success';
100
+ }
101
+
102
+ jQuery( '.rmp-new-menu-elements' ).prepend(
103
+ '<div class="notice ' + noticeClass + ' settings-error is-dismissible"> <p>' + response.data.message + '</p></div>'
104
+ );
105
+
106
+ setTimeout( function() {
107
+ jQuery( '.rmp-new-menu-elements' ).find( '.notice' ).remove();
108
+ }, 3000 );
109
+ }
110
+ } ).always( function( response ) {
111
+ jQuery( '.spinner' ).removeClass( 'is-active' );
112
+ } ).done( function( response ) {
113
+ if ( response.success ) {
114
+ location.reload();
115
+ }
116
+ } );
117
+
118
+ } );
119
+
120
+ /**
121
+ * Rollback the plugin version.
122
+ *
123
+ * @version 4.0.0
124
+ *
125
+ * @fires Click
126
+ */
127
+ jQuery( '#rmp-rollback-version' ).on( 'click', function( e ) {
128
+ e.preventDefault();
129
+
130
+ const version = jQuery( '#rmp-versions' ).val();
131
+
132
+ if ( '3.1.29' === version ) {
133
+ jQuery.ajax( {
134
+ url: rmpObject.ajaxURL,
135
+ data: { action: 'rmp_rollback_version' },
136
+ type: 'POST',
137
+ dataType: 'json',
138
+ error: function( error ) {
139
+ jQuery( this ).prop( 'disabled', false );
140
+ },
141
+ success: function( response ) {
142
+ if ( response.data.redirect ) {
143
+ location.href = response.data.redirect;
144
+ }
145
+ }
146
+ } );
147
+ }
148
+ } );
149
+
150
+ /**
151
+ * Iframe loader and contents show/hide.
152
+ */
153
+ jQuery('#rmp-preview-iframe').on('load', function() {
154
+ jQuery( '#rmp-preview-iframe-loader' ).hide();
155
+ jQuery( '#rmp-menu-update-notification').remove();
156
+ jQuery('#rmp-preview-iframe').show();
157
+ });
158
+
159
+ /**
160
+ * Save the theme as template.
161
+ *
162
+ * @since 4.0.0
163
+ *
164
+ * @fires Click
165
+ */
166
+ jQuery( 'button#rmp-save-theme' ).on( 'click', function( e ) {
167
+ e.stopPropagation();
168
+ e.preventDefault();
169
+
170
+ const themeName = jQuery( '#rmp-save-theme-name' ).val();
171
+
172
+ if ( 3 > themeName.length ) {
173
+ alert( 'Please give meaning full name to this theme' );
174
+ return;
175
+ }
176
+
177
+ jQuery.ajax( {
178
+ url: rmpObject.ajaxURL,
179
+ data: {
180
+ 'action': 'rmp_save_theme',
181
+ 'ajax_nonce': rmpObject.ajax_nonce,
182
+ 'theme_name': themeName,
183
+ 'menu_id': jQuery( '#menu_id' ).val(),
184
+ 'form': jQuery( '#rmp-editor-form' ).serialize()
185
+ },
186
+ type: 'POST',
187
+ dataType: 'json',
188
+ error: function( error ) {
189
+ console.log( error.statusText );
190
+ },
191
+ success: function( response ) {
192
+ jQuery( e.target ).parents( '.rmp-dialog-contents' )
193
+ .append( '<div class="notice notice-success settings-error is-dismissible"><p>' + response.data.message + '</p></div>' );
194
+ }
195
+ } );
196
+ } );
197
+
198
+ /**
199
+ * Ajax call to save the menu settings when click on update.
200
+ *
201
+ * @version 4.0.0
202
+ *
203
+ * @fires click
204
+ */
205
+ jQuery(document).on( 'click', 'button#rmp-save-menu-options,#rmp-menu-quick-update-button', function( e ) {
206
+
207
+ jQuery.ajax( {
208
+ url: rmpObject.ajaxURL,
209
+ data: {
210
+ 'action': 'rmp_save_menu_action',
211
+ 'ajax_nonce': rmpObject.ajax_nonce,
212
+ 'form': jQuery( '#rmp-editor-form' ).serialize()
213
+ },
214
+ type: 'POST',
215
+ dataType: 'json',
216
+ beforeSend: function() {
217
+ jQuery( '#rmp-preview-iframe-loader' ).show();
218
+ },
219
+ error: function( error ) {
220
+ console.log( error.statusText );
221
+ jQuery( '#rmp-preview-iframe-loader' ).hide();
222
+ },
223
+ success: function( response ) {
224
+ // If options is updated successfully then reload the iframe.
225
+ if ( response.success ) {
226
+ const url = jQuery( '#rmp-preview-iframe' ).attr('src');
227
+ jQuery('#rmp-preview-iframe').attr('src', url );
228
+ }
229
+ }
230
+ } );
231
+ } );
232
+
233
+ // Initiate the color picker instances.
234
+ jQuery( '.rmp-color-input' ).wpColorPicker();
235
+
236
+ // Fix events glitch on color textbox.
237
+ jQuery('.rmp-color-input').removeAttr( 'style' );
238
+ jQuery('.rmp-color-input').off( 'focus' );
239
+
240
+ // Initiate the tab elements.
241
+ jQuery( '.tabs,#rmp-setting-tabs' ).tabs( {
242
+ hide: { effect: 'explode', duration: 1000 },
243
+ show: { effect: 'explode', duration: 800 },
244
+ active: 0
245
+ } );
246
+
247
+ // Active tabs under ordering elements.
248
+ jQuery( '.nav-tab-wrapper' ).on( 'click', '.nav-tab', function( e ) {
249
+ jQuery( '.nav-tab-wrapper .nav-tab' ).removeClass( 'nav-tab-active' );
250
+ jQuery( this ) .addClass( 'nav-tab-active' );
251
+ } );
252
+
253
+
254
+
255
+ /**
256
+ * Check open/close of device options switcher.
257
+ *
258
+ * @version 4.0.0
259
+ *
260
+ * @fires click
261
+ */
262
+ jQuery( '.rmp-device-switcher' ).on( 'click', function() {
263
+ var isOpen = jQuery( this ).hasClass( 'open' );
264
+
265
+ if ( isOpen ) {
266
+ jQuery( this ).removeClass( 'open' );
267
+ } else {
268
+ jQuery( '.rmp-device-switcher' ).removeClass( 'open' );
269
+ jQuery( this ).addClass( 'open' );
270
+ }
271
+
272
+ } );
273
+
274
+ /**
275
+ * Change the option when select a device.
276
+ *
277
+ * @version 4.0.0
278
+ *
279
+ * @fires click
280
+ */
281
+ jQuery( '.rmp-device-switcher li' ).on( 'click', function() {
282
+ var selectedDevice = jQuery( this ).attr( 'data-device' );
283
+ var firstDevice = jQuery( '.rmp-device-switcher li:first-child' ).attr( 'data-device' );
284
+ if ( selectedDevice != firstDevice ) {
285
+ activeDeviceOptions( selectedDevice );
286
+ if ( 'desktop' == selectedDevice ) {
287
+ jQuery( '#rmp-preview-desktop' ).trigger( 'click' );
288
+ } else if ( 'tablet' == selectedDevice ) {
289
+ jQuery( '#rmp-preview-tablet' ).trigger( 'click' );
290
+ } else {
291
+ jQuery( '#rmp-preview-mobile' ).trigger( 'click' );
292
+ }
293
+ }
294
+ } );
295
+
296
+
297
+ /**
298
+ * Active all the device options in editor.
299
+ *
300
+ * @version 4.0.0;
301
+ * @param {string} selectedDevice This device name which is active.
302
+ */
303
+ function activeDeviceOptions( selectedDevice ) {
304
+ const firstDevice = jQuery( '.rmp-device-switcher li:first-child' ).attr( 'data-device' );
305
+ const selectedIcon = jQuery( '.rmp-device-switcher li[data-device=' + selectedDevice + ']' ).html();
306
+ const firstIcon = jQuery( '.rmp-device-switcher li:first-child' ).html();
307
+
308
+ jQuery( '.rmp-device-switcher li' ).each( function() {
309
+ if ( jQuery( this ).attr( 'data-device' ) === selectedDevice ) {
310
+ jQuery( this ).html( firstIcon );
311
+ jQuery( this ).attr( 'data-device', firstDevice );
312
+ } else if ( jQuery( this ).attr( 'data-device' ) === firstDevice ) {
313
+ jQuery( this ).html( selectedIcon );
314
+ jQuery( this ).attr( 'data-device', selectedDevice );
315
+ }
316
+ } );
317
+ }
318
+
319
+ /**
320
+ * Close the device switcher when mouseup other places.
321
+ *
322
+ * @version 4.0.0
323
+ *
324
+ * @fires mouseup
325
+ */
326
+ jQuery( document ).on( 'mouseup', function( event ) {
327
+ var target = event.target;
328
+ var deviceSwitcher = jQuery( '.rmp-device-switcher' );
329
+
330
+ if ( ! deviceSwitcher.is( target ) && 0 === deviceSwitcher.has( target ).length ) {
331
+ deviceSwitcher.removeClass( 'open' );
332
+ }
333
+
334
+ } );
335
+
336
+ /**
337
+ * Active preview as per clicked device.
338
+ *
339
+ * @version 4.0.0
340
+ *
341
+ * @fires Click
342
+ */
343
+ jQuery( '#rmp-editor-footer .rmp-preview-device-wrapper' ).on( 'click', 'button', function( e ) {
344
+ jQuery( '#rmp-editor-footer' ).find( '.rmp-preview-device-wrapper button' ).removeClass( 'active' );
345
+ jQuery( '#rmp-editor-footer' ).find( '.rmp-preview-device-wrapper button' ).attr( 'aria-pressed', 'false' );
346
+ jQuery( this ).addClass( 'active' );
347
+ jQuery( this ).attr( 'aria-pressed', 'true' );
348
+ const device = jQuery( this ).data( 'device' );
349
+ const deviceEditor = jQuery( '#rmp-editor-wrapper' );
350
+ const allClasses = deviceEditor.attr( 'class' ).split( ' ' );
351
+
352
+ allClasses.forEach( function( value ) {
353
+ if ( value.includes( 'rmp-preview-' ) ) {
354
+ deviceEditor.removeClass( value );
355
+ }
356
+ } );
357
+
358
+ deviceEditor.addClass( 'rmp-preview-' + device );
359
+ activeDeviceOptions( device );
360
+ } );
361
+
362
+ /**
363
+ * Instantiate the accordion elements.
364
+ * @version 4.0.0
365
+ */
366
+ jQuery( '.rmp-accordion-container,.rmp-sub-accordion-container' ).accordion( {
367
+ collapsible: true,
368
+ heightStyle: 'content',
369
+ animate: 200,
370
+ active: 0,
371
+ } );
372
+
373
+ /**
374
+ * Instantiate the draggable and sortable menu item order elements.
375
+ * @version 4.0.0
376
+ */
377
+ jQuery( '#rmp-menu-ordering-items' ).accordion().sortable( {
378
+ placeholder: 'sortable-placeholder',
379
+ opacity: 0.9,
380
+ cursor: 'move',
381
+ delay: 150,
382
+ forcePlaceholderSize: true,
383
+ active: false
384
+ } );
385
+
386
+ /**
387
+ * Stop propagating when click on item control element.
388
+ */
389
+ jQuery( '#tab-container .item-controls, #tab-header-bar .item-controls' ).on( 'click', function( event ) {
390
+ event.stopPropagation();
391
+ } );
392
+
393
+ /**
394
+ * Show/Hide tooltip for option description.
395
+ *
396
+ * @version 4.0.0
397
+ *
398
+ * @fires click,mouseleave
399
+ */
400
+ jQuery( '.rmp-tooltip-icon' ).on( 'click', function(e) {
401
+
402
+ if ( jQuery(this).hasClass('show-tooltip') ) {
403
+ return;
404
+ } else {
405
+ jQuery( this ).addClass('show-tooltip');
406
+ }
407
+
408
+ var toolTipContents = jQuery( this ).find( '.rmp-tooltip-content' );
409
+ toolTipContents.css({
410
+ 'left': e.pageX - ( ( toolTipContents.width() / 100 ) * 60 ),
411
+ 'position': 'fixed',
412
+ 'top': ( e.pageY - toolTipContents.height() - 10 ),
413
+ 'bottom': 'unset'
414
+ });
415
+
416
+ toolTipContents.fadeIn();
417
+
418
+ } ).on( 'mouseleave', function() {
419
+ jQuery(this).removeClass('show-tooltip');
420
+ jQuery( this ).find( '.rmp-tooltip-content' ).fadeOut();
421
+ } );
422
+
423
+ /**
424
+ * Remove image from image picker
425
+ *
426
+ * @version 4.0.0
427
+ *
428
+ * @fires Click
429
+ */
430
+ jQuery( '.rmp-image-picker ' ).on( 'click', '.rmp-image-picker-trash', function( e ) {
431
+ e.stopPropagation();
432
+ e.preventDefault();
433
+ jQuery( this ).parent( '.rmp-image-picker' ).siblings( 'input.rmp-image-url-input' ).val( '' );
434
+ jQuery( this ).parent( '.rmp-image-picker' ).removeAttr( 'style' );
435
+ jQuery( this ).remove();
436
+ } );
437
+
438
+ /**
439
+ * Show/Hide the theme uploader section in theme page.
440
+ */
441
+ jQuery( '#rmp-upload-new-theme' ).on( 'click', function() {
442
+ jQuery( '#rmp-menu-library-import' ).toggleClass( 'hide' );
443
+ } );
444
+
445
+ /**
446
+ * Hide theme uploader section when click on cancel.
447
+ */
448
+ jQuery( '#rmp-menu-library-import-form' ).on( 'click', '.cancel', function( e ) {
449
+ jQuery( '#rmp-menu-library-import' ).addClass( 'hide' );
450
+ } );
451
+
452
+ /**
453
+ * Upload the theme file using dropzone.
454
+ *
455
+ * @version 4.0.0
456
+ */
457
+ jQuery( '#rmp-menu-library-import-form' ).dropzone( {
458
+ clickable: true,
459
+ acceptedFiles: '.zip',
460
+ uploadMultiple: false,
461
+ success: function ( file, response ) {
462
+ location.reload();
463
+ }
464
+ } );
465
+
466
+ /**
467
+ * Open theme options in editor footer.
468
+ */
469
+ jQuery( '#rmp-theme-action' ).on( 'click', function( e ) {
470
+ jQuery( '#rmp-footer-theme-options' ).toggleClass('open');
471
+ } );
472
+
473
+ /**
474
+ * Show/Hide the save theme wizard.
475
+ */
476
+ jQuery( '.rmp-theme-save-button, #rmp-menu-save-theme-wizard .rmp-dialog-wrap .close' ).on( 'click', function( e ) {
477
+ jQuery( '#rmp-menu-save-theme-wizard' ).toggle();
478
+ } );
479
+
480
+ /**
481
+ * Show/Hide change theme wizard.
482
+ */
483
+ jQuery( '.rmp-theme-change-button' ).on( 'click', function( e ) {
484
+ jQuery( '#rmp-new-menu-wizard' ).toggle();
485
+ } );
486
+
487
+ /**
488
+ * Delete the theme from theme page.
489
+ */
490
+ jQuery( '.rmp-theme-delete' ).on( 'click', function( e ) {
491
+ e.preventDefault();
492
+
493
+ /** Ask for delete confirmation */
494
+ const isConfirm = confirm( 'Are you sure, you want delete this theme ?' );
495
+
496
+ if ( ! isConfirm ) {
497
+ return;
498
+ }
499
+
500
+ let themeName = jQuery( this ).attr( 'data-theme' );
501
+ let themeType = jQuery( this ).attr( 'data-theme-type' ).toLowerCase();
502
+
503
+ jQuery.ajax( {
504
+ url: rmpObject.ajaxURL,
505
+ data: {
506
+ 'action': 'rmp_theme_delete',
507
+ 'ajax_nonce': rmpObject.ajax_nonce,
508
+ 'theme_name': themeName,
509
+ 'theme_type': themeType
510
+ },
511
+ type: 'POST',
512
+ dataType: 'json',
513
+ error: function( error ) {
514
+ console.log( error.statusText );
515
+ },
516
+ success: function( response ) {
517
+ location.reload();
518
+ }
519
+ } );
520
+
521
+ } );
522
+
523
+ /**
524
+ * Apply the selected theme in current active menu in editor.
525
+ *
526
+ * @version 4.0.0
527
+ *
528
+ * @fires 4.0.0
529
+ */
530
+ jQuery( '.rmp-theme-apply' ).on( 'click', function( e ) {
531
+
532
+ jQuery.ajax( {
533
+ url: rmpObject.ajaxURL,
534
+ data: {
535
+ 'action': 'rmp_theme_apply',
536
+ 'ajax_nonce': rmpObject.ajax_nonce,
537
+ 'theme_name': jQuery( this ).attr( 'theme-name' ),
538
+ 'theme_type': jQuery( this ).attr( 'theme-type' ).toLowerCase(),
539
+ 'menu_id': jQuery( '#menu_id' ).val(),
540
+ 'menu_to_use' : jQuery('#rmp-menu-to-use').val()
541
+ },
542
+ type: 'POST',
543
+ dataType: 'json',
544
+ error: function( error ) {
545
+ console.log( error.statusText );
546
+ },
547
+ success: function( response ) {
548
+ location.reload();
549
+ }
550
+ } );
551
+
552
+ } );
553
+
554
+ /**
555
+ * Save the global settings on click.
556
+ *
557
+ * @version 4.0.0
558
+ *
559
+ * @fires click
560
+ */
561
+ jQuery( '.rmp-save-global-settings-button' ).on( 'click', function( e ) {
562
+ e.preventDefault();
563
+
564
+ jQuery.ajax( {
565
+ url: rmpObject.ajaxURL,
566
+ data: {
567
+ 'action': 'rmp_save_global_settings',
568
+ 'ajax_nonce': rmpObject.ajax_nonce,
569
+ 'form': jQuery( '#rmp-global-settings' ).serialize()
570
+ },
571
+ type: 'POST',
572
+ dataType: 'json',
573
+ beforeSend: function() {
574
+ jQuery( this ).prop( 'disabled', true );
575
+ jQuery( '.spinner' ).addClass( 'is-active' );
576
+ },
577
+ error: function( error ) {
578
+ console.log( 'Internal Error !' + error );
579
+ },
580
+ success: function( response ) {
581
+ jQuery( '.spinner' ).removeClass( 'is-active' );
582
+ jQuery( this ).prop( 'disabled', false );
583
+ }
584
+ } );
585
+ } );
586
+
587
+ /**
588
+ * Initiate multiple selectize option of editor.
589
+ */
590
+ jQuery( '#rmp-keyboard-shortcut-close-menu,#rmp-keyboard-shortcut-open-menu' ).selectize( {
591
+ maxItems : 2,
592
+ plugins: [ 'remove_button' ]
593
+ } );
594
+
595
+ /**
596
+ * Event to linked the group inputs.
597
+ *
598
+ * @fires Click
599
+ */
600
+ jQuery( document ).on( 'click', 'button.rmp-group-input-linked', function() {
601
+ jQuery(this).toggleClass( 'is-linked' );
602
+ });
603
+
604
+ /**
605
+ * Event to type on all sibblings input if linked.
606
+ *
607
+ * @fires keyup
608
+ */
609
+ jQuery( document ).on( 'keyup', 'input.rmp-group-input', function( event ) {
610
+ var pressedKeys = this.value.toLocaleLowerCase();
611
+ const parent = jQuery(this).parents('.rmp-input-group-control');
612
+ const isLinked = parent.find( '.is-linked' );
613
+
614
+ if ( isLinked.length ) {
615
+ parent.find( 'input.rmp-group-input' ).val( pressedKeys);
616
+ } else {
617
+ jQuery( this ).val(pressedKeys);
618
+ }
619
+
620
+ });
621
+
622
+ /**
623
+ * Function to add the notification and update button.
624
+ */
625
+ function addUpdateNotification() {
626
+
627
+ if ( ! jQuery('#rmp-editor-main').find('#rmp-menu-update-notification').length ) {
628
+ jQuery( '#rmp-editor-main' ).prepend(
629
+ '<div id="rmp-menu-update-notification" class="rmp-order-item rmp-order-item-description">' +
630
+ '<span> <span class="rmp-font-icon dashicons dashicons-warning "></span> Update Required </span>' +
631
+ '<a href="javascript:void(0)" id="rmp-menu-quick-update-button">UPDATE</a>' +
632
+ '</div>'
633
+ );
634
+ }
635
+ }
636
+
637
+ jQuery( 'form#rmp-editor-form' ).on(
638
+ 'keyup change paste',
639
+ 'input, select, textarea, radio, checkbox',
640
+ function() {
641
+ if ( ! jQuery(this).hasClass('no-updates') ) {
642
+ addUpdateNotification();
643
+ }
644
+ }
645
+ );
646
+
647
+ jQuery(document).on(
648
+ 'click',
649
+ '#rmp-icon-dialog-select,.media-button-select,.rmp-icon-picker,.rmp-image-picker',
650
+ function() {
651
+ if ( ! jQuery('#rmp-editor-main').find('#rmp-menu-update-notification').length ) {
652
+ addUpdateNotification();
653
+ }
654
+ });
655
+
656
+ /**
657
+ * Event to download exported menu settings as json file.
658
+ *
659
+ * @version 4.0.0
660
+ */
661
+ jQuery( '#rmp-export-menu-button' ).on( 'click', function( e ) {
662
+ e.preventDefault();
663
+
664
+ let menu_id = jQuery('#rmp_export_menu_list').val();
665
+
666
+ jQuery.ajax( {
667
+ url: rmpObject.ajaxURL,
668
+ data: {
669
+ 'action': 'rmp_export_menu',
670
+ 'ajax_nonce': rmpObject.ajax_nonce,
671
+ 'menu_id': menu_id
672
+ },
673
+ type: 'POST',
674
+ dataType: 'json',
675
+ beforeSend: function() {
676
+ jQuery( '#rmp-export-menu-button' ).prop( 'disabled', true );
677
+ },
678
+ error: function( error ) {
679
+ console.log( error.statusText );
680
+ jQuery( '#rmp-export-menu-button' ).prop( 'disabled', false );
681
+ },
682
+ success: function( response ) {
683
+ jQuery( '#rmp-export-menu-button' ).prop( 'disabled', false );
684
+ if( response.data ) {
685
+ let menu_name = jQuery('#rmp_export_menu_list').children(":selected").text().trim().toLocaleLowerCase().split(' ').join('-');
686
+ download_file( response.data , menu_name + '.json' , 'application/json' );
687
+ }
688
+ }
689
+ });
690
+
691
+ });
692
+
693
+ /**
694
+ * Function to download the content as file.
695
+ *
696
+ * @since 4.0.0
697
+ *
698
+ * @param {String} content Contents for file
699
+ * @param {String} name Name of the file.
700
+ * @param {String} type File type
701
+ */
702
+ function download_file(content, name, type ) {
703
+ const link = document.body.appendChild( document.createElement('a') );
704
+ const file = new Blob([content], {
705
+ type: type
706
+ });
707
+ link.href = URL.createObjectURL(file);
708
+ link.download = name;
709
+ link.click();
710
+ }
711
+
712
+ /**
713
+ * Event to download exported menu settings as json file.
714
+ *
715
+ * @version 4.0.0
716
+ */
717
+ jQuery( '#rmp-import-menu-button' ).on( 'click', function( e ) {
718
+ e.preventDefault();
719
+
720
+ let menu_id = jQuery('#rmp_import_menu_list').val();
721
+
722
+ if( ! menu_id ) {
723
+ alert( 'Please create menu first ! ');
724
+ return;
725
+ }
726
+
727
+ let file_data = jQuery('#rmp_input_import_file')[0].files[0];
728
+
729
+ if( ! file_data ) {
730
+ alert( 'Choose export file ! ');
731
+ return;
732
+ }
733
+
734
+ var form_data = new FormData();
735
+ form_data.append( 'file', file_data );
736
+ form_data.append( 'ajax_nonce', rmpObject.ajax_nonce );
737
+ form_data.append( 'menu_id', menu_id );
738
+ form_data.append( 'action', 'rmp_import_menu' );
739
+
740
+ jQuery.ajax( {
741
+ url: rmpObject.ajaxURL,
742
+ data: form_data,
743
+ type: 'POST',
744
+ cache: false,
745
+ contentType: false,
746
+ processData: false,
747
+ dataType: 'json',
748
+ beforeSend: function() {
749
+ jQuery( '#rmp-import-menu-button' ).prop( 'disabled', true );
750
+ },
751
+ error: function( error ) {
752
+ console.log( error.statusText );
753
+ jQuery( '#rmp-import-menu-button' ).prop( 'disabled', false );
754
+ },
755
+ success: function( response ) {
756
+ jQuery( '#rmp-import-menu-button' ).prop( 'disabled', false );
757
+ noticeClass = 'notice-error';
758
+ if ( response.success ) {
759
+ noticeClass = 'notice-success';
760
+ jQuery('#rmp_input_import_file').val('');
761
+ }
762
+
763
+ jQuery( '#rmp-global-settings' ).before(
764
+ '<div class="notice ' + noticeClass + ' settings-error is-dismissible"> <p>' + response.data.message + '</p></div>'
765
+ );
766
+
767
+ setTimeout( function() {
768
+ jQuery( '#rmp-global-settings' ).parent().find( '.notice' ).remove();
769
+ }, 3000 );
770
+ }
771
+ });
772
+
773
+ });
774
+
775
+ } );
v4.0.0/assets/admin/js/rmp-editor.js ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This file container the editor multi level features.
3
+ *
4
+ * @version 4.0.0
5
+ *
6
+ * @type {Object}
7
+ */
8
+ const rmpEditor = {
9
+ editorSidebar: '#rmp-editor-wrapper',
10
+ sidebarDrawer: 'button.collapse-sidebar',
11
+ mainForm: '#rmp-editor-form',
12
+ editorContainer: '#rmp-editor-main',
13
+ topParentNav: '#rmp-editor-nav',
14
+ topParentTab: '#rmp-editor-pane',
15
+ childTabs: '.rmp-accordions',
16
+ tabItem: 'li.rmp-tab-item',
17
+ titleLogo: '.rmp-editor-header-logo',
18
+ closeButton: '.rmp-editor-header-close',
19
+ titleText: '.rmp-editor-header-title',
20
+ backButton: '.rmp-editor-header-back',
21
+ tabId: null,
22
+ level: 0,
23
+ close: function () {
24
+ jQuery( window ).bind( 'beforeunload', function() {
25
+ return;
26
+ } );
27
+ },
28
+ triggerBack: function() {
29
+
30
+ this.level--;
31
+ parentId = jQuery( '#' + this.tabId ).attr( 'aria-parent' );
32
+ jQuery( '#' + parentId ).show();
33
+
34
+ let title = jQuery( '#' + parentId ).attr( 'aria-label' );
35
+ this.updateHeader( title );
36
+
37
+ jQuery( '#' + this.tabId ).hide();
38
+ this.tabId = parentId;
39
+ },
40
+ updatePanel: function( current ) {
41
+ this.tabId = current.attr( 'aria-owns' );
42
+ jQuery( '#' + this.tabId ).show();
43
+ parentId = current.parent( 'ul' ).parent( 'div' ).attr( 'id' );
44
+ jQuery( '#' + this.tabId ).attr( 'aria-parent', parentId );
45
+ jQuery( '#' + parentId ).hide();
46
+ },
47
+ updateHeader: function( title ) {
48
+
49
+ if ( 0 == this.level ) {
50
+ jQuery( this.titleLogo ).find( 'img' ).show();
51
+ jQuery( this.closeButton ).show();
52
+ jQuery( this.backButton ).hide();
53
+ } else if ( 1 == this.level ) {
54
+ jQuery( this.backButton ).css( 'display', 'flex' );
55
+ jQuery( this.titleLogo ).find( 'img' ).hide();
56
+ jQuery( this.closeButton ).hide();
57
+ }
58
+
59
+ jQuery( this.titleText ).text( title );
60
+ },
61
+ init: function() {
62
+ var self = this;
63
+
64
+ // Move on next panel when click on item.
65
+ jQuery( self.editorContainer ).on( 'click', self.tabItem, function( e ) {
66
+ e.stopPropagation();
67
+ e.preventDefault();
68
+ current = jQuery( this );
69
+ self.level++;
70
+ self.updateHeader( current.text() );
71
+ self.updatePanel( current );
72
+ } );
73
+
74
+ // Back from inner panel when click on back button.
75
+ jQuery( self.backButton ).on( 'click', function( e ) {
76
+ e.stopPropagation();
77
+ self.triggerBack();
78
+ } );
79
+
80
+ // Close the editor and back to menu admin.
81
+ jQuery( this.closeButton ).on( 'click', function( e ) {
82
+ e.stopPropagation();
83
+ self.close();
84
+ } );
85
+
86
+ // Open/Close the editor setting sidebar.
87
+ jQuery( self.sidebarDrawer ).on( 'click', function(e) {
88
+ jQuery( self.editorSidebar ).toggleClass( 'expanded collapsed' );
89
+ } );
90
+ }
91
+ };
92
+
93
+ rmpEditor.init();
94
+
95
+
v4.0.0/assets/admin/js/rmp-icon.js ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This file contain the script to handle the icon wizard and it's operation.
3
+ *
4
+ * @version 4.0.0
5
+ */
6
+ jQuery( document ).ready( function() {
7
+
8
+ var RMP_Icon = {
9
+ iconSelect: '#rmp-icon-dialog-select',
10
+ iconContainer: '.rmp-menu-icons-dialog',
11
+ clearSelector: '#rmp-icon-dialog-clear',
12
+ closeSelector: '.rmp-menu-icons-dialog .rmp-dialog-header span.close',
13
+ clear: function () {
14
+ var self = this;
15
+ jQuery( self.clearSelector ).on( 'click', function() {
16
+ jQuery( self.iconContainer ).find( 'input' ).prop( 'checked', false );
17
+ } );
18
+ },
19
+ closeDialog : function() {
20
+ var self = this;
21
+ jQuery(self.closeSelector).on( 'click' ,function(){
22
+ jQuery(self.iconContainer).hide();
23
+ });
24
+ },
25
+ openDialog : function(iconChooser) {
26
+ var self = this;
27
+ jQuery(iconChooser).on( 'click', function(e) {
28
+ e.stopPropagation();
29
+ jQuery(self.iconContainer).show();
30
+ jQuery(self.iconSelect).attr('data-click',jQuery(e.target).attr('id'));
31
+ });
32
+ },
33
+ getIconElementWrap :function( icon_class ) {
34
+
35
+ if( icon_class.includes('material-icons') ) {
36
+ icon_class = icon_class.replace('material-icons','');
37
+ return '<span class="rmp-font-icon material-icons">'+ icon_class +'</span>';
38
+ }
39
+
40
+ return '<span class="rmp-font-icon '+ icon_class +' "></span>';
41
+ },
42
+ removeIcon : function(iconChooser) {
43
+ jQuery( iconChooser ).on( 'click', '.rmp-icon-picker-trash', function(e) {
44
+ e.preventDefault();
45
+ e.stopPropagation();
46
+ jQuery(this).parent('.rmp-icon-picker').siblings('input.rmp-icon-hidden-input').val('');
47
+ jQuery(this).siblings('.rmp-font-icon').remove();
48
+ jQuery(this).parent('.rmp-icon-picker').removeAttr('data-icon');
49
+ jQuery(this).remove();
50
+ });
51
+ },
52
+ getIcon : function() {
53
+ var self = this;
54
+ jQuery(document).on( 'click', this.iconSelect, function() {
55
+
56
+ icon_class = jQuery(self.iconContainer).find('input:checked').val();
57
+
58
+ clicker = '#' + jQuery(self.iconSelect).attr('data-click');
59
+
60
+ icon_wrap = self.getIconElementWrap(icon_class);
61
+ jQuery(clicker).find('.rmp-font-icon').remove();
62
+ jQuery(clicker).prev('input.rmp-icon-hidden-input').val(icon_wrap);
63
+ jQuery(clicker).append( icon_wrap );
64
+ jQuery(clicker).attr('data-icon',true);
65
+
66
+ jQuery(clicker).find('.rmp-icon-picker-trash').remove();
67
+ jQuery(clicker).append('<i class="rmp-icon-picker-trash dashicons dashicons-trash" aria-hidden="true"></i>');
68
+
69
+ jQuery(self.iconSelect).removeAttr('data-click');
70
+ jQuery(self.closeSelector).click();
71
+ jQuery(clicker).prev('input').first().focus();
72
+ });
73
+ },
74
+ init: function( iconChooser ) {
75
+ this.openDialog(iconChooser);
76
+ this.removeIcon(iconChooser);
77
+ this.getIcon();
78
+ this.clear();
79
+ this.closeDialog();
80
+
81
+ jQuery('#rmp-icon-search').on( 'keyup', _.debounce( this.searchIcon, 500 ) );
82
+
83
+ jQuery('#rmp-icon-search').on( 'keyup', function () {
84
+
85
+ var query_string = this.value.toLocaleLowerCase();
86
+ if ( query_string.length ) {
87
+ if ( ! jQuery('#rmp-icon-search-typing-message').length ) {
88
+ jQuery(this).after('<span id="rmp-icon-search-typing-message"> Waiting for more keystrokes... </span>');
89
+ } else {
90
+ jQuery('#rmp-icon-search-typing-message').html('Waiting for more keystrokes...');
91
+ }
92
+ }
93
+
94
+ });
95
+
96
+ /**
97
+ * Create menu item icon selector.
98
+ */
99
+ jQuery( document ).on( 'click' , '.delete-menu-item-icon', function() {
100
+ jQuery(this).closest('.rmp-menu-item-icon-container').remove();
101
+ } );
102
+
103
+ },
104
+ searchIcon: function(e) {
105
+
106
+ jQuery('#rmp-icon-search-typing-message').html('Please wait moment..');
107
+
108
+ var query_string = this.value.toLocaleLowerCase();
109
+
110
+
111
+ var activeTab = jQuery('.rmp-menu-icons-dialog').find('.nav-tab-active');
112
+ if ( ! activeTab.length ) {
113
+ activeTab = jQuery('.rmp-menu-icons-dialog').find('.nav-tab').first();
114
+ }
115
+
116
+ icon_container = activeTab.attr('href');
117
+
118
+ var icon_selector = jQuery( icon_container + ' .font-icon');
119
+ var is_exist = false;
120
+ icon_selector.each( function() {
121
+ var icon_label = jQuery(this).children('input').val().toLocaleLowerCase();
122
+ if ( icon_label.includes(query_string) ) {
123
+ jQuery(this).show();
124
+ is_exist = true;
125
+ } else {
126
+ jQuery(this).hide();
127
+ }
128
+ });
129
+
130
+ if ( is_exist ) {
131
+ jQuery('#rmp-icon-search-typing-message').html('Done, Check results..');
132
+ } else {
133
+ jQuery('#rmp-icon-search-typing-message').html('Sorry, Not found..');
134
+ }
135
+
136
+ }
137
+
138
+ };
139
+
140
+ RMP_Icon.init( '.rmp-icon-picker' );
141
+
142
+ });
v4.0.0/assets/admin/js/rmp-preview.js ADDED
@@ -0,0 +1,1008 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function(jQuery) {
2
+
3
+ /**
4
+ * Hooks class.
5
+ *
6
+ * @since 4.0.0
7
+ */
8
+ var rmpHook = {
9
+ hooks: [ ],
10
+ is_break: false,
11
+
12
+ /**
13
+ * Function to register the hook.
14
+ *
15
+ * @since 4.0.0
16
+ *
17
+ * @param String name Hook Name.
18
+ * @param function callback Associated function.
19
+ */
20
+ register: function( name, callback ) {
21
+ if ( 'undefined' == typeof ( rmpHook.hooks[name] ) ) {
22
+ rmpHook.hooks[name] = [ ];
23
+ }
24
+ rmpHook.hooks[name].push( callback );
25
+ },
26
+
27
+ /**
28
+ * Function to call the hook.
29
+ *
30
+ * @since 4.0.0
31
+ *
32
+ * @param String name Hook Name.
33
+ * @param function arguments Paramter list.
34
+ */
35
+ call: function( name, arguments ) {
36
+ if ( 'undefined' != typeof ( rmpHook.hooks[name] ) ) {
37
+ for ( i = 0; i < rmpHook.hooks[name].length; ++i ) {
38
+ output = rmpHook.hooks[name][i]( arguments );
39
+ if ( false == output ) {
40
+ rmpHook.is_break = true;
41
+ return false;
42
+ }
43
+
44
+ return output;
45
+ }
46
+ }
47
+ return true;
48
+ }
49
+ };
50
+
51
+ /**
52
+ * Register function to color the menu elements.
53
+ *
54
+ * @since 4.0.0
55
+ *
56
+ * @param {Object} args List of inputs.
57
+ * @return {String}
58
+ */
59
+ rmpHook.register( 'rmp_color_style', function ( args ) {
60
+
61
+ if ( ! args ) {
62
+ return false;
63
+ }
64
+
65
+ // Set the state/pseudo class.
66
+ if ( 'hover' == args.state ) {
67
+ args.outputSelector = args.outputSelector + ':hover';
68
+ } else if( 'placeholder' == args.state ) {
69
+ args.outputSelector = args.outputSelector + '::placeholder';
70
+ }
71
+
72
+ //Prepare css string and return.
73
+ return args.outputSelector + '{ ' + args.attr +' : ' + args.value + ';}';
74
+ } );
75
+
76
+ var RMP_Preview = {
77
+ iframe : '#rmp-preview-iframe',
78
+ menuId : jQuery('#menu_id').val(),
79
+ mobile_breakpoint : jQuery('#rmp-menu-mobile-breakpoint').val() + 'px',
80
+ tablet_breakpoint : jQuery('#rmp-menu-tablet-breakpoint').val() + 'px',
81
+ active_device: jQuery('#rmp_device_mode'),
82
+ menuContainer : '#rmp-container-'+ self.menuId,
83
+
84
+ onTyping: function( inputSelector, outputSelector, type) {
85
+ var self = this;
86
+ var iframe = jQuery(self.iframe);
87
+ jQuery(inputSelector).on( 'keyup change paste', function() {
88
+ switch( type ) {
89
+ case 'border-radius':
90
+ var value = jQuery(this).val();
91
+ css = outputSelector + '{ border-radius : '+ ( value ) +'px;}';
92
+ self.inlineCssInjector(css);
93
+ break;
94
+ case 'section-padding':
95
+ var value = jQuery(this).val();
96
+ var is_linked = jQuery(this).parents('.rmp-input-group-control').find('.rmp-group-input-linked').hasClass('is-linked');
97
+ var attr = 'padding';
98
+ if( ! is_linked ) {
99
+ pos = jQuery(this).attr('data-input');
100
+ attr = attr + '-' + pos;
101
+ }
102
+ css = outputSelector + '{ '+ attr +' : '+ ( value ) +';}';
103
+ self.inlineCssInjector(css);
104
+
105
+ break;
106
+ case 'trigger-line-width':
107
+ var unit = jQuery(this).next('.is-unit').val();
108
+ css = outputSelector + '{ width : '+ ( this.value + unit ) +';}';
109
+ self.inlineCssInjector(css);
110
+ break;
111
+ case 'trigger-line-height':
112
+ var unit = jQuery(this).next('.is-unit').val();
113
+ css = outputSelector + '{ height : '+ ( this.value + unit ) +';}';
114
+ self.inlineCssInjector(css);
115
+ break;
116
+ case 'trigger-text':
117
+ if ( iframe.contents().find(outputSelector).length ) {
118
+ iframe.contents().find(outputSelector).html(this.value);
119
+ } else {
120
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box' ).before('<div class="rmp-trigger-label rmp-trigger-label-top"><span class="rmp-trigger-text">"'+ this.value + '"</span></div>')
121
+ }
122
+ break;
123
+
124
+ case 'trigger-text-open':
125
+ if ( iframe.contents().find(outputSelector).length ) {
126
+ iframe.contents().find(outputSelector).html(this.value);
127
+ } else {
128
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box' ).before('<div class="rmp-trigger-label rmp-trigger-label-top"><span class="rmp-trigger-text-open">"'+ this.value + '"</span></div>')
129
+ }
130
+ break;
131
+
132
+ case 'text' :
133
+ iframe.contents().find( outputSelector ).html(this.value);
134
+ break;
135
+
136
+ case 'placeholder' :
137
+ iframe.contents().find(outputSelector).attr('placeholder', this.value );
138
+ break;
139
+ case 'href' :
140
+ iframe.contents().find(outputSelector).attr('href', this.value );
141
+ break;
142
+
143
+ case 'font-size':
144
+ var unit = jQuery(this).next( '.is-unit' ).val();
145
+
146
+ if ( ! unit.length ) {
147
+ unit = 'px';
148
+ }
149
+
150
+ var value = jQuery(this).val();
151
+ css = outputSelector + '{ font-size : '+ ( value + unit ) + '!important;}';
152
+
153
+ if ( jQuery(this).attr( 'multi-device') ) {
154
+ css = self.mediaQuery( css );
155
+ }
156
+
157
+ self.inlineCssInjector(css);
158
+
159
+ break;
160
+
161
+ case 'width':
162
+ var unit = jQuery(this).next('.is-unit').val();
163
+
164
+ if ( ! unit ) {
165
+ unit = 'px';
166
+ }
167
+
168
+ css = outputSelector + '{ width : '+ (this.value + unit) +';}';
169
+ self.inlineCssInjector(css);
170
+
171
+ break;
172
+
173
+ case 'height':
174
+ var unit = jQuery(this).next('.is-unit').val();
175
+
176
+ if ( ! unit.length ) {
177
+ unit = 'px';
178
+ }
179
+
180
+ css = outputSelector + '{ height : '+ ( this.value + unit ) + ';}';
181
+
182
+ if ( jQuery(this).attr( 'multi-device') ) {
183
+ css = self.mediaQuery( css );
184
+ }
185
+
186
+ self.inlineCssInjector(css);
187
+
188
+ break;
189
+ case 'line-height':
190
+ var unit = jQuery(this).next('.is-unit').val();
191
+
192
+ if ( ! unit.length ) {
193
+ unit = 'px';
194
+ }
195
+
196
+ css = outputSelector + '{ line-height : '+ ( this.value + unit ) + ';}';
197
+
198
+ if ( jQuery(this).attr( 'multi-device') ) {
199
+ css = self.mediaQuery( css );
200
+ }
201
+
202
+ self.inlineCssInjector(css);
203
+
204
+ break;
205
+ case 'min-width':
206
+ var unit = jQuery(this).next('.is-unit').val();
207
+
208
+ if ( ! unit.length ) {
209
+ unit = 'px';
210
+ }
211
+
212
+ css = outputSelector + '{ min-width : '+ (this.value + unit) +';}';
213
+
214
+ self.inlineCssInjector(css);
215
+
216
+ break;
217
+ case 'max-width':
218
+ var unit = jQuery(this).next('.is-unit').val();
219
+
220
+ if ( ! unit.length ) {
221
+ unit = 'px';
222
+ }
223
+ css = outputSelector + '{ max-width : '+ (this.value + unit) +';}';
224
+ self.inlineCssInjector(css);
225
+
226
+ break;
227
+ }
228
+ });
229
+ },
230
+ bindImage : function(inputSelector, outputSelector, type ) {
231
+ var self = this;
232
+ var iframe = jQuery(self.iframe);
233
+ jQuery(document).on( 'click', inputSelector, function(e) {
234
+ e.preventDefault();
235
+ var button = jQuery(this),
236
+
237
+ custom_uploader = wp.media({
238
+ title: 'Select image',
239
+ library : {
240
+ type : 'image'
241
+ },
242
+ button: {
243
+ text: 'Use this image'
244
+ },
245
+ multiple: false,
246
+ }).on('select', function() {
247
+ var attachment = custom_uploader.state().get('selection').first().toJSON();
248
+
249
+ jQuery(e.target).prev('input.rmp-image-url-input').val(attachment.url);
250
+ jQuery(e.target).css('background-image', 'url(' + attachment.url + ')');
251
+ jQuery(e.target).append('<i class="rmp-image-picker-trash dashicons dashicons-trash" aria-hidden="true"></i>');
252
+
253
+ if ( type == 'img-src') {
254
+ iframe.contents().find(outputSelector).attr('src', attachment.url );
255
+ } else if( type == 'background' ) {
256
+ css = outputSelector + '{ background-image : url('+ attachment.url + ');}';
257
+ self.inlineCssInjector(css);
258
+ } else if( type == 'trigger-icon' ) {
259
+
260
+ if ( iframe.contents().find(outputSelector).length ) {
261
+ iframe.contents().find(outputSelector).attr('src', attachment.url );
262
+ } else {
263
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box .responsive-menu-pro-inner' ).hide();
264
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box' ).append('<img class="rmp-trigger-icon rmp-trigger-icon-inactive" src="'+ attachment.url +'"/>')
265
+ }
266
+ } else if( type == 'trigger-icon-open' ) {
267
+
268
+ if ( iframe.contents().find(outputSelector).length ) {
269
+ iframe.contents().find(outputSelector).attr('src', attachment.url );
270
+ } else {
271
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box .responsive-menu-pro-inner' ).hide();
272
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box' ).append('<img class="rmp-trigger-icon rmp-trigger-icon-active" src="'+ attachment.url +'"/>')
273
+ }
274
+ }
275
+ }).open();
276
+
277
+ });
278
+ },
279
+ toggleElements: function( inputSelector, outputSelector ) {
280
+ var self = this;
281
+ jQuery(inputSelector).on( 'change', function(e) {
282
+ e.preventDefault();
283
+ e.stopPropagation();
284
+ var iframe = jQuery(self.iframe);
285
+ if ( iframe.contents().find(outputSelector).length ) {
286
+ if ( jQuery(this).is(':checked') ) {
287
+ iframe.contents().find(outputSelector).fadeIn(500);
288
+ } else {
289
+ iframe.contents().find(outputSelector).fadeOut(500);
290
+ }
291
+ } else {
292
+ e.preventDefault();
293
+ var menuId = jQuery('#menu_id').val(),
294
+ toggle_on = jQuery(this).data('toggle');
295
+
296
+ jQuery.ajax({
297
+ url: rmpObject.ajaxURL,
298
+ data: {
299
+ 'action' : 'rmp_enable_menu_item',
300
+ 'ajax_nonce' : rmpObject.ajax_nonce,
301
+ 'menu_id' : menuId,
302
+ 'menu_element' : toggle_on,
303
+ },
304
+ type: 'POST',
305
+ dataType: 'json',
306
+ beforeSend: function(){
307
+ jQuery(this).prop('disabled' , true);
308
+ jQuery('#iframe-spinner').show();
309
+ },
310
+ error: function( error ) {
311
+ console.log('Internal Error !');
312
+ jQuery(this).prop('disabled', false);
313
+ jQuery('#iframe-spinner').hide();
314
+ },
315
+ success: function( response ) {
316
+
317
+ if ( response.data.markup ) {
318
+ iframe.contents().find( '#rmp-container-'+ self.menuId ).append(response.data.markup);
319
+ self.orderMenuElements();
320
+ }
321
+
322
+ jQuery(this).prop('disabled', false);
323
+ jQuery('#iframe-spinner').hide();
324
+ }
325
+ });
326
+ }
327
+ });
328
+ },
329
+ orderMenuElements: function() {
330
+ var list = [];
331
+ var self = this;
332
+ var iframeContents = jQuery(self.iframe).contents();
333
+ jQuery('#tab-container .item-title').each(function () {
334
+ var val = jQuery(this).text().toLocaleLowerCase().trim();
335
+
336
+ if ( val=='title') {
337
+ list.push( iframeContents.find( self.menuTitle ) );
338
+ iframeContents.find( self.menuTitle ).remove();
339
+ } else if( val=='search' ) {
340
+ list.push( iframeContents.find( self.menuSearch ) );
341
+ iframeContents.find( self.menuSearch ).remove();
342
+ } else if( val == 'menu' ) {
343
+ list.push( iframeContents.find( self.menuWrap ) );
344
+ iframeContents.find( self.menuWrap ).remove();
345
+ } else {
346
+ list.push( iframeContents.find( self.menuContents ) );
347
+ iframeContents.find( self.menuContents ).remove();
348
+ }
349
+ } );
350
+
351
+ list.forEach( function( menuElement ) {
352
+ iframeContents.find( self.menuContainer ).append( menuElement );
353
+ });
354
+
355
+ },
356
+ /**
357
+ * Function to bind the color input with option and elements.
358
+ *
359
+ * @version 4.0.0
360
+ *
361
+ * @param {String} inputSelector
362
+ * @param {String} outputSelector
363
+ * @param {String} attr
364
+ * @param {String} state
365
+ */
366
+ bindColor: function( inputSelector, outputSelector, attr, state ) {
367
+ var self = this;
368
+ jQuery( inputSelector ).wpColorPicker( {
369
+ change: function(event, ui) {
370
+ var value = ui.color.toString();
371
+ var css = rmpHook.call(
372
+ 'rmp_color_style', {
373
+ 'outputSelector' : outputSelector,
374
+ 'attr' : attr,
375
+ 'value': value,
376
+ 'state': state
377
+ } );
378
+
379
+ if ( jQuery( inputSelector ).attr( 'multi-device') ) {
380
+ css = self.mediaQuery( css );
381
+ }
382
+
383
+ self.inlineCssInjector(css);
384
+ }
385
+ });
386
+ },
387
+ mediaQuery: function( css ) {
388
+
389
+ var self = this;
390
+
391
+ self.mobile_breakpoint = jQuery('#rmp-menu-mobile-breakpoint').val() + 'px';
392
+ self.tablet_breakpoint = jQuery('#rmp-menu-tablet-breakpoint').val() + 'px';
393
+ self.active_device = jQuery('#rmp_device_mode');
394
+
395
+ if( 'desktop' === self.active_device.val() ) {
396
+ $css = '@media screen and (min-width: '+ self.tablet_breakpoint +' ) {' + css + '}';
397
+ return $css;
398
+ } else if( 'tablet' === self.active_device.val() ) {
399
+ $css = '@media screen and (max-width: '+ self.tablet_breakpoint +') and (min-width : '+ self.mobile_breakpoint +') {' + css + '}';
400
+ return $css;
401
+ } else if( 'mobile' === self.active_device.val() ) {
402
+ $css = '@media screen and (max-width: '+ self.mobile_breakpoint +' ) {' + css + '}';
403
+ return $css;
404
+ }
405
+
406
+ return css;
407
+ },
408
+ inlineCssInjector: function( css ) {
409
+ var self = this;
410
+ var iframe = jQuery(self.iframe);
411
+ var styleElement = iframe.contents().find( '#rmp-inline-css-' + self.menuId );
412
+ if ( styleElement.length ) {
413
+ styleElement.append(css);
414
+ } else {
415
+ style = '<style id="rmp-inline-css-'+ self.menuId +'">'+ css + '</style>';
416
+ iframe.contents().find('head').append(style);
417
+ }
418
+ },
419
+ changeInput: function( inputSelector, outputSelector , attr, meta = '' ) {
420
+ var self = this;
421
+ var iframe = jQuery(self.iframe);
422
+ jQuery(inputSelector).on( 'change', function(e) {
423
+ switch (attr) {
424
+ case 'height-unit':
425
+ value = jQuery(this).prev('input').val();
426
+ unit = jQuery(this).val();
427
+
428
+ css = outputSelector + '{ height : '+ ( value + unit ) + ';}';
429
+ if ( jQuery(this).attr( 'multi-device') ) {
430
+ css = self.mediaQuery( css );
431
+ }
432
+
433
+ self.inlineCssInjector(css);
434
+ break;
435
+ case 'line-height-unit':
436
+ value = jQuery(this).prev('input').val();
437
+ unit = jQuery(this).val();
438
+
439
+ css = outputSelector + '{ line-height : '+ ( value+unit ) + ';}';
440
+
441
+ if ( jQuery(this).attr( 'multi-device') ) {
442
+ css = self.mediaQuery( css );
443
+ }
444
+
445
+ self.inlineCssInjector(css);
446
+ break;
447
+ case 'width-unit':
448
+ value = jQuery(this).prev('input').val();
449
+ unit = jQuery(this).val();
450
+ iframe.contents().find( outputSelector ).css({
451
+ 'width' : value+unit,
452
+ } );
453
+ break;
454
+ case 'font-size':
455
+ value = jQuery(this).prev('input').val();
456
+ unit = jQuery(this).val();
457
+ css = outputSelector + '{ font-size :' + value + unit + ' !important;}';
458
+
459
+ if ( jQuery(this).attr( 'multi-device') ) {
460
+ css = self.mediaQuery( css );
461
+ }
462
+
463
+ self.inlineCssInjector(css);
464
+ break;
465
+ case 'font-family':
466
+ value = jQuery(this).val();
467
+ css = outputSelector + '{ font-family :' + value +' !important;}';
468
+
469
+ if ( jQuery(this).attr( 'multi-device') ) {
470
+ css = self.mediaQuery( css );
471
+ }
472
+
473
+ self.inlineCssInjector(css);
474
+ break;
475
+ case 'font-weight':
476
+ value = jQuery(this).val();
477
+ css = outputSelector + '{ font-weight :' + value +';}';
478
+ self.inlineCssInjector(css);
479
+ break;
480
+ case 'padding':
481
+ var unit = jQuery(this).next('.is-unit').val();
482
+
483
+ if ( ! unit ) {
484
+ unit = 'px';
485
+ }
486
+
487
+ if( meta == 'lr') {
488
+ css = outputSelector + '{ padding : 0 '+ (this.value + unit) +';}';
489
+ }
490
+
491
+ self.inlineCssInjector(css);
492
+ break;
493
+ case 'letter-spacing':
494
+ value = jQuery(this).val();
495
+ css = outputSelector + '{ letter-spacing :' + value +'px; }';
496
+ self.inlineCssInjector(css);
497
+ break;
498
+ case 'position-alignment':
499
+
500
+ if ( iframe.contents().find( outputSelector ).length ) {
501
+ position = jQuery(this).val();
502
+ var rmpTriggerBox = iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box' );
503
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box' ).remove();
504
+ if ( position == 'top' || position == 'left' ) {
505
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId ).append(rmpTriggerBox);
506
+ } else {
507
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId ).prepend(rmpTriggerBox);
508
+ }
509
+
510
+ }
511
+ break;
512
+ case 'trigger-animation':
513
+ value = jQuery(this).val();
514
+ var new_class = 'rmp-menu-trigger-' + value;
515
+ all_class = iframe.contents().find( outputSelector ).attr('class').split(" ");
516
+ all_class.forEach( function( value ) {
517
+ if ( value.includes( 'rmp-menu-trigger-' ) ) {
518
+ iframe.contents().find( outputSelector ).removeClass(value);
519
+ iframe.contents().find( outputSelector ).addClass(new_class);
520
+ }
521
+ });
522
+ break;
523
+ case 'top':
524
+ value = jQuery(this).val();
525
+ unit = jQuery('#rmp-menu-button-top-unit').val();
526
+ css = outputSelector + '{ top :' + (value + unit) +' !important;}';
527
+ self.inlineCssInjector(css);
528
+ break;
529
+ case 'trigger-side-position':
530
+ side = jQuery('#rmp-menu-button-left-or-right').val();
531
+ unit = jQuery('#rmp-menu-button-distance-from-side-unit').val();
532
+ value = jQuery('#rmp-menu-button-distance-from-side').val();
533
+ css = outputSelector + '{ '+ side +' :'+ (value + unit) +' !important;}';
534
+ self.inlineCssInjector(css);
535
+ break;
536
+ case 'trigger-side':
537
+ side = jQuery(this).val();
538
+ value = jQuery('#rmp-menu-button-distance-from-side').val();
539
+ unit = jQuery('#rmp-menu-button-distance-from-side-unit').val();
540
+
541
+ if( side == 'left' ) {
542
+ css = outputSelector + '{' + side + ':'+ ( value + unit ) +' !important;right:unset !important}';
543
+ } else {
544
+ css = outputSelector + '{' + side + ':'+ ( value + unit ) +' !important;left:unset !important}';
545
+ }
546
+
547
+ self.inlineCssInjector(css);
548
+
549
+ break;
550
+ case 'position':
551
+ value = jQuery(this).val();
552
+ css = outputSelector + '{ position :'+ value +' !important;}';
553
+ self.inlineCssInjector(css);
554
+ break;
555
+ case 'trigger-background' :
556
+ if ( jQuery(this).is(':checked') ) {
557
+ iframe.contents().find( outputSelector ).attr('style', 'background:unset !important;');
558
+ } else {
559
+ iframe.contents().find( outputSelector ).removeAttr( 'style' );
560
+ }
561
+ break;
562
+ case 'target':
563
+ if ( jQuery(this).is(':checked') ) {
564
+ iframe.contents().find(outputSelector).attr('target', '_blank' );
565
+ } else {
566
+ iframe.contents().find(outputSelector).attr('target', '_self' );
567
+ }
568
+ break;
569
+ case 'text-align':
570
+ var value = jQuery(this).val();
571
+ iframe.contents().find( outputSelector ).css({
572
+ 'text-align' : value,
573
+ } );
574
+ break;
575
+ case 'border-width':
576
+ var unit = jQuery(this).next('.is-unit').val();
577
+
578
+ if ( ! unit ) {
579
+ unit = 'px';
580
+ }
581
+
582
+ css = outputSelector + '{ border-width : '+ (this.value + unit) +';}';
583
+ self.inlineCssInjector(css);
584
+
585
+ break;
586
+ }
587
+ });
588
+ },
589
+
590
+ init: function() {
591
+ var self = this;
592
+
593
+ //Mobile menu elements.
594
+ self.menuContainer = '#rmp-container-'+ self.menuId;
595
+ self.menuTitle = '#rmp-menu-title-' + self.menuId;
596
+ self.menuSearch = '#rmp-search-box-' + self.menuId;
597
+ self.menuWrap = '#rmp-menu-wrap-' + self.menuId;
598
+ self.menuContents = '#rmp-menu-additional-content-' + self.menuId;
599
+
600
+ //Menu container background color.
601
+ self.bindColor(
602
+ '#rmp-container-background-colour',
603
+ '#rmp-container-' + self.menuId ,
604
+ 'background',
605
+ ''
606
+ );
607
+
608
+ //Menu background.
609
+ self.bindColor(
610
+ '#rmp-menu-background-colour',
611
+ '#rmp-menu-wrap-' + self.menuId ,
612
+ 'background'
613
+ );
614
+
615
+ //Menu title section background color.
616
+ self.bindColor(
617
+ '#rmp-menu-title-background-colour',
618
+ '#rmp-menu-title-' + self.menuId ,
619
+ 'background'
620
+ );
621
+
622
+ //Menu title section background hover color.
623
+ self.bindColor(
624
+ '#rmp-menu-title-background-hover-colour',
625
+ '#rmp-menu-title-' + self.menuId ,
626
+ 'background',
627
+ 'hover'
628
+ );
629
+
630
+ // Menu item trigger
631
+
632
+ self.bindColor(
633
+ '#rmp-menu-sub-arrow-shape-colour',
634
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow',
635
+ 'color'
636
+ );
637
+
638
+ self.bindColor(
639
+ '#rmp-menu-sub-arrow-shape-hover-colour',
640
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow',
641
+ 'color',
642
+ 'hover'
643
+ );
644
+
645
+ self.bindColor(
646
+ '#rmp-menu-sub-arrow-shape-colour-active',
647
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow.rmp-menu-subarrow-active',
648
+ 'color'
649
+ );
650
+
651
+ self.bindColor(
652
+ '#rmp-menu-sub-arrow-shape-hover-colour-active',
653
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow.rmp-menu-subarrow-active',
654
+ 'color',
655
+ 'hover'
656
+ );
657
+
658
+ self.bindColor(
659
+ '#rmp-menu-sub-arrow-border-colour',
660
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow',
661
+ 'border-color'
662
+ );
663
+
664
+ self.bindColor(
665
+ '#rmp-menu-sub-arrow-border-hover-colour',
666
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow',
667
+ 'border-color',
668
+ 'hover'
669
+ );
670
+
671
+ self.bindColor(
672
+ '#rmp-menu-sub-arrow-border-colour-active',
673
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow.rmp-menu-subarrow-active',
674
+ 'border-color'
675
+ );
676
+
677
+
678
+ self.bindColor(
679
+ '#rmp-menu-sub-arrow-border-hover-colour-active',
680
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow.rmp-menu-subarrow-active',
681
+ 'border-color',
682
+ 'hover'
683
+ );
684
+
685
+ self.bindColor(
686
+ '#rmp-menu-sub-arrow-background-color',
687
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow',
688
+ 'background'
689
+ );
690
+
691
+ self.bindColor(
692
+ '#rmp-menu-sub-arrow-background-hover-colour',
693
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow',
694
+ 'background',
695
+ 'hover'
696
+ );
697
+
698
+ self.bindColor(
699
+ '#rmp-menu-sub-arrow-background-colour-active',
700
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow.rmp-menu-subarrow-active',
701
+ 'background'
702
+ );
703
+
704
+ self.bindColor(
705
+ '#rmp-menu-sub-arrow-background-hover-colour-active',
706
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow.rmp-menu-subarrow-active',
707
+ 'background',
708
+ 'hover'
709
+ );
710
+
711
+ //Legacy options
712
+ self.bindColor(
713
+ '#rmp-submenu-sub-arrow-shape-colour',
714
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-subarrow',
715
+ 'color'
716
+ );
717
+
718
+ self.bindColor(
719
+ '#rmp-submenu-item-border-colour-hover',
720
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-subarrow',
721
+ 'color',
722
+ 'hover'
723
+ );
724
+
725
+
726
+ self.bindColor(
727
+ '#rmp-submenu-sub-arrow-shape-colour-active',
728
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-subarrow.rmp-menu-subarrow-active',
729
+ 'color'
730
+ );
731
+
732
+
733
+ self.bindColor(
734
+ '#rmp-submenu-sub-arrow-shape-hover-colour-active',
735
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-subarrow.rmp-menu-subarrow-active',
736
+ 'color',
737
+ 'hover'
738
+ );
739
+
740
+ self.bindColor(
741
+ '#rmp-submenu-sub-arrow-border-colour',
742
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-subarrow',
743
+ 'border-color'
744
+ );
745
+
746
+ self.bindColor(
747
+ '#rmp-submenu-sub-arrow-border-hover-colour',
748
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-subarrow',
749
+ 'border-color',
750
+ 'hover'
751
+ );
752
+
753
+ self.bindColor(
754
+ '#rmp-submenu-sub-arrow-border-colour-active',
755
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-subarrow.rmp-menu-subarrow-active',
756
+ 'border-color'
757
+ );
758
+
759
+ self.bindColor(
760
+ '#rmp-submenu-sub-arrow-border-hover-colour-active',
761
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-subarrow.rmp-menu-subarrow-active',
762
+ 'border-color',
763
+ 'hover'
764
+ );
765
+
766
+ self.bindColor(
767
+ '#rmp-submenu-sub-arrow-background-color',
768
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-subarrow',
769
+ 'background'
770
+ );
771
+
772
+ self.bindColor(
773
+ '#rmp-submenu-sub-arrow-background-hover-colour',
774
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-subarrow',
775
+ 'background',
776
+ 'hover'
777
+ );
778
+
779
+ self.bindColor(
780
+ '#rmp-submenu-sub-arrow-background-colour-active',
781
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-subarrow.rmp-menu-subarrow-active',
782
+ 'background'
783
+ );
784
+
785
+ self.bindColor(
786
+ '#rmp-submenu-sub-arrow-background-hover-colour-active',
787
+ '#rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-subarrow.rmp-menu-subarrow-active',
788
+ 'background',
789
+ 'hover'
790
+ );
791
+
792
+ self.bindColor('#rmp-menu-title-colour', '#rmp-menu-title-' + self.menuId + ' > a' , 'color');
793
+ self.bindColor('#rmp-menu-title-hover-colour', '#rmp-menu-title-' + self.menuId + ' > a' , 'color','hover');
794
+ self.bindColor('#rmp-menu-additional-content-color', '#rmp-container-'+ self.menuId + ' #rmp-menu-additional-content-' + self.menuId , 'color');
795
+ self.bindColor('#rmp-menu-search-box-text-colour', '#rmp-container-'+ self.menuId + ' #rmp-search-box-'+ self.menuId + ' .rmp-search-box' , 'color');
796
+ self.bindColor('#rmp-menu-search-box-background-colour', '#rmp-search-box-'+ self.menuId + ' .rmp-search-box' , 'background');
797
+ self.bindColor('#rmp-menu-search-box-border-colour', '#rmp-search-box-'+ self.menuId + ' .rmp-search-box' , 'border-color');
798
+ self.bindColor('#rmp-menu-search-box-placeholder-colour', '#rmp-search-box-'+ self.menuId + ' .rmp-search-box' , 'color', 'placeholder');
799
+
800
+ //Menu Trigger
801
+ self.bindColor('#rmp-menu-button-background-colour', '#rmp_menu_trigger-' + self.menuId , 'background', '' );
802
+ self.bindColor('#rmp-menu-button-background-colour-hover', '#rmp_menu_trigger-' + self.menuId , 'background-color', 'hover' );
803
+ self.bindColor('#rmp-menu-button-background-colour-active', '#rmp_menu_trigger-' + self.menuId + '.is-active' , 'background', '' );
804
+
805
+ self.bindColor('#rmp-menu-button-line-colour', '#rmp_menu_trigger-' + self.menuId + ' .responsive-menu-pro-inner,#rmp_menu_trigger-' + self.menuId +' .responsive-menu-pro-inner:after,#rmp_menu_trigger-' + self.menuId +' .responsive-menu-pro-inner:before', 'background', '' );
806
+ self.bindColor('#rmp-menu-button-line-colour-active', '.is-active#rmp_menu_trigger-' + self.menuId + ' .responsive-menu-pro-inner,.is-active#rmp_menu_trigger-' + self.menuId +' .responsive-menu-pro-inner:after,.is-active#rmp_menu_trigger-' + self.menuId +' .responsive-menu-pro-inner:before', 'background','' );
807
+ self.bindColor('#rmp-menu-button-line-colour-hover', '#rmp_menu_trigger-' + self.menuId + ':hover .responsive-menu-pro-inner,#rmp_menu_trigger-' + self.menuId +':hover .responsive-menu-pro-inner:after,#rmp_menu_trigger-' + self.menuId +':hover .responsive-menu-pro-inner:before', 'background','' );
808
+ self.bindColor('#rmp-menu-button-text-colour', '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-label', 'color' );
809
+
810
+ self.onTyping('.rmp-menu-container-padding','#rmp-container-'+ self.menuId , 'section-padding' );
811
+ self.onTyping('.rmp-menu-title-section-padding','#rmp-menu-title-'+ self.menuId , 'section-padding' );
812
+ self.onTyping('.rmp-menu-section-padding','#rmp-menu-wrap-'+ self.menuId , 'section-padding' );
813
+ self.onTyping('.rmp-menu-search-section-padding','#rmp-search-box-'+ self.menuId , 'section-padding' );
814
+ self.onTyping('.rmp-menu-additional-section-padding','#rmp-menu-additional-content-'+ self.menuId , 'section-padding' );
815
+
816
+ // CONTENT BASED ELEMENTS.
817
+
818
+ self.onTyping('#rmp-menu-search-box-height','#rmp-search-box-'+ self.menuId + ' .rmp-search-box','height' );
819
+ self.changeInput('#rmp-menu-search-box-height-unit','#rmp-search-box-'+ self.menuId + ' .rmp-search-box','height-unit' );
820
+
821
+
822
+ self.onTyping('#rmp-menu-search-box-border-radius','#rmp-search-box-'+ self.menuId + ' .rmp-search-box','border-radius' );
823
+
824
+
825
+ self.onTyping('#rmp-menu-menu-title','#rmp-menu-title-'+ self.menuId +' #rmp-menu-title-link span', 'text' );
826
+ self.onTyping('#rmp-menu-additional-content','#rmp-menu-additional-content-'+ self.menuId,'text');
827
+ self.onTyping('#rmp-menu-search-box-text','#rmp-search-box-'+ self.menuId + ' .rmp-search-box','placeholder');
828
+ self.onTyping('#rmp-menu-title-link', '#rmp-menu-title-' + self.menuId + ' #rmp-menu-title-link','href');
829
+ self.onTyping('#rmp-menu-title-image-alt', '#rmp-menu-title-' + self.menuId + ' .rmp-menu-title-image','alt');
830
+ self.onTyping('#rmp-menu-title-font-size', '#rmp-menu-title-' + self.menuId + ' > a','font-size');
831
+ self.changeInput('#rmp-menu-title-font-size-unit', '#rmp-menu-title-' + self.menuId + ' > a','font-size' );
832
+ self.changeInput('#rmp-menu-additional-content-font-size-unit', '#rmp-menu-additional-content-' + self.menuId ,'font-size' );
833
+
834
+ self.onTyping('#rmp-menu-title-image-width', '#rmp-menu-title-' + self.menuId + ' .rmp-menu-title-image','width');
835
+ self.onTyping('#rmp-menu-title-image-height', '#rmp-menu-title-' + self.menuId + ' .rmp-menu-title-image','height');
836
+ self.bindImage('#rmp-menu-title-image-selector', '#rmp-menu-title-' + self.menuId + ' .rmp-menu-title-image', 'img-src' );
837
+
838
+ self.onTyping('#rmp-menu-additional-content-font-size', '#rmp-menu-additional-content-' + self.menuId ,'font-size' );
839
+
840
+ self.onTyping('#rmp-menu-container-width', '#rmp-container-'+ self.menuId, 'width' );
841
+ self.changeInput('#rmp-menu-container-width-unit', '#rmp-container-'+ self.menuId, 'width-unit' );
842
+ self.changeInput('#rmp-menu-button-width-unit', '#rmp_menu_trigger-' + self.menuId, 'width-unit' );
843
+
844
+ self.changeInput('#rmp-menu-button-height-unit', '#rmp_menu_trigger-' + self.menuId , 'height-unit');
845
+
846
+
847
+ self.onTyping('#rmp-menu-container-min-width', '#rmp-container-'+ self.menuId, 'min-width' );
848
+ self.onTyping('#rmp-menu-container-max-width', '#rmp-container-'+ self.menuId, 'max-width' );
849
+
850
+ self.onTyping('#rmp-menu-button-image-alt-when-clicked', '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-icon-active', 'alt' );
851
+ self.onTyping('#rmp-menu-button-image-alt', '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-icon-inactive', 'alt' );
852
+
853
+ self.onTyping('#rmp-menu-button-title-open', '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-text-open', 'trigger-text-open' );
854
+ self.onTyping('#rmp-menu-button-title', '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-text', 'trigger-text' );
855
+ self.onTyping('#rmp-menu-button-font-size', '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-label', 'font-size' );
856
+ self.changeInput('#rmp-menu-button-font-size-unit', '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-label', 'font-size' );
857
+
858
+ self.onTyping('#rmp-menu-button-title-line-height', '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-label', 'line-height' );
859
+ self.changeInput('#rmp-menu-button-title-line-height-unit', '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-label', 'line-height-unit' );
860
+
861
+ //Menu Trigger
862
+ self.onTyping('#rmp-menu-button-width', '#rmp_menu_trigger-' + self.menuId, 'width' );
863
+ self.onTyping('#rmp-menu-button-height', '#rmp_menu_trigger-' + self.menuId , 'height');
864
+
865
+ self.onTyping('#rmp-menu-button-line-width', '#rmp_menu_trigger-' + self.menuId +' .responsive-menu-pro-inner', 'trigger-line-width' );
866
+ self.onTyping('#rmp-menu-button-line-width', '#rmp_menu_trigger-' + self.menuId +' .responsive-menu-pro-inner:after', 'trigger-line-width' );
867
+ self.onTyping('#rmp-menu-button-line-width', '#rmp_menu_trigger-' + self.menuId +' .responsive-menu-pro-inner:before', 'trigger-line-width' );
868
+ self.onTyping('#rmp-menu-button-line-height', '#rmp_menu_trigger-' + self.menuId +' .responsive-menu-pro-inner', 'trigger-line-height' );
869
+ self.onTyping('#rmp-menu-button-line-height', '#rmp_menu_trigger-' + self.menuId +' .responsive-menu-pro-inner:after', 'trigger-line-height' );
870
+ self.onTyping('#rmp-menu-button-line-height', '#rmp_menu_trigger-' + self.menuId +' .responsive-menu-pro-inner:before', 'trigger-line-height' );
871
+
872
+ self.bindImage('#rmp-button-title-image', '#rmp-menu-title-' + self.menuId + ' .rmp-menu-title-image', 'img-src' );
873
+ self.bindImage('#rmp-menu-background-image-selector', '#rmp-container-'+ self.menuId, 'background' );
874
+
875
+ self.bindImage('#rmp-menu-button-image-when-clicked-selector', '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-icon-active', 'trigger-icon-open' );
876
+ self.bindImage('#rmp-menu-button-image-selector', '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-icon-inactive', 'trigger-icon' );
877
+
878
+
879
+
880
+
881
+ self.changeInput('#rmp-menu-title-link-location', '#rmp-menu-title-' + self.menuId + ' #rmp-menu-title-link','target');
882
+ self.changeInput('.rmp-menu-title-alignment', '#rmp-menu-title-' + self.menuId ,'text-align');
883
+ self.changeInput('.rmp-menu-additional-content-alignment', '#rmp-menu-additional-content-'+ self.menuId,'text-align');
884
+
885
+ //Top menu item links
886
+ self.onTyping('#rmp-menu-links-height', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'height');
887
+ self.onTyping('#rmp-menu-links-line-height', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'line-height');
888
+ self.onTyping('#rmp-menu-font-size', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'font-size');
889
+ self.changeInput('#rmp-menu-font-size-unit', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'font-size');
890
+
891
+
892
+ self.changeInput('#rmp-menu-font', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'font-family' );
893
+ self.changeInput('#rmp-menu-font-weight', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'font-weight' );
894
+ self.changeInput('.rmp-menu-text-alignment', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'text-align' );
895
+ self.changeInput('#rmp-menu-text-letter-spacing', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'letter-spacing' );
896
+ self.changeInput('#rmp-menu-depth-level-0', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'padding', 'lr' );
897
+
898
+ self.changeInput('#rmp-menu-border-width', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'border-width' );
899
+ self.changeInput('#rmp-menu-sub-arrow-border-width', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow', 'border-width' );
900
+ self.changeInput('#rmp-submenu-sub-arrow-border-width', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-sub-level-item .rmp-menu-subarrow', 'border-width' );
901
+
902
+ self.bindColor('#rmp-menu-link-color', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'color');
903
+ self.bindColor('#rmp-menu-link-hover-color', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'color','hover');
904
+ self.bindColor('#rmp-menu-current-link-active-color', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item.rmp-menu-current-item .rmp-menu-item-link', 'color');
905
+ self.bindColor('#rmp-menu-current-link-active-hover-color', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item.rmp-menu-current-item .rmp-menu-item-link', 'color','hover');
906
+
907
+ self.bindColor('#rmp-menu-item-background-colour', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'background');
908
+ self.bindColor('#rmp-menu-item-background-hover-color', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'background','hover');
909
+ self.bindColor('#rmp-menu-current-item-background-color', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item.rmp-menu-current-item .rmp-menu-item-link', 'background');
910
+ self.bindColor('#rmp-menu-current-item-background-hover-color', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item.rmp-menu-current-item .rmp-menu-item-link', 'background','hover');
911
+
912
+ self.bindColor('#rmp-menu-item-border-colour', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-item-link', 'border-color');
913
+
914
+ // Trigger of top level
915
+ self.bindImage('#rmp-menu-inactive-arrow-image-selector', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-subarrow', 'background' );
916
+ self.bindImage('#rmp-menu-active-arrow-image-selector', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-subarrow-active', 'background' );
917
+
918
+ self.onTyping('#rmp-submenu-arrow-height', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow', 'height');
919
+ self.onTyping('#rmp-submenu-arrow-width', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow', 'width');
920
+ self.changeInput('#rmp-submenu-arrow-width-unit', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow', 'width-unit');
921
+ self.changeInput('#rmp-submenu-arrow-height-unit', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-subarrow', 'height-unit');
922
+
923
+ self.onTyping('#rmp-submenu-child-arrow-height', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-sub-level-item .rmp-menu-subarrow', 'height');
924
+ self.onTyping('#rmp-submenu-child-arrow-width', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-sub-level-item .rmp-menu-subarrow', 'width');
925
+ self.changeInput('#rmp-submenu-child-arrow-width-unit', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-sub-level-item .rmp-menu-subarrow', 'width-unit');
926
+ self.changeInput('#rmp-submenu-child-arrow-height-unit', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-sub-level-item .rmp-menu-subarrow', 'height-unit');
927
+
928
+
929
+ self.bindColor('#rmp-menu-sub-arrow-background-color', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-subarrow', 'background');
930
+ self.bindColor('#rmp-menu-sub-arrow-background-hover-colour', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-subarrow', 'background','hover');
931
+ self.bindColor('#rmp-menu-sub-arrow-background-colour-active', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-subarrow-active', 'background');
932
+ self.bindColor('#rmp-menu-sub-arrow-background-hover-colour-active', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-menu-top-level-item .rmp-menu-subarrow-active', 'background','hover' );
933
+
934
+ //sub menu item links
935
+ self.onTyping('#rmp-submenu-links-height', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-item-link', 'height');
936
+ self.onTyping('#rmp-submenu-links-line-height', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-item-link', 'line-height');
937
+ self.onTyping('#rmp-submenu-font-size', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-item-link', 'font-size');
938
+ self.changeInput('#rmp-submenu-font', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-item-link', 'font-family' );
939
+ self.changeInput('#rmp-submenu-font-weight', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-item-link', 'font-weight' );
940
+ self.changeInput('.rmp-submenu-text-alignment', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-item-link', 'text-align' );
941
+ self.changeInput('#rmp-submenu-text-letter-spacing', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-item-link', 'letter-spacing' );
942
+
943
+ self.changeInput('#rmp-submenu-border-width', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-item-link', 'border-width' );
944
+ self.bindColor('#rmp-submenu-item-border-colour', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-item-link', 'border-color');
945
+
946
+ self.bindColor('#rmp-submenu-link-color', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-item-link', 'color');
947
+ self.bindColor('#rmp-submenu-link-hover-color', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-item-link', 'color','hover');
948
+ self.bindColor('#rmp-submenu-link-colour-active', '#rmp-container-' + self.menuId +' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-current-item .rmp-menu-item-link', 'color');
949
+ self.bindColor('#rmp-submenu-link-active-hover-color', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-current-item .rmp-menu-item-link', 'color','hover');
950
+
951
+ self.bindColor('#rmp-submenu-item-background-color', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-item-link', 'background');
952
+ self.bindColor('#rmp-submenu-item-background-hover-color', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-item-link', 'background','hover');
953
+ self.bindColor('#rmp-submenu-current-item-background-color', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-current-item .rmp-menu-item-link', 'background');
954
+ self.bindColor('#rmp-submenu-current-item-background-hover-color', ' #rmp-menu-wrap-' + self.menuId + ' .rmp-submenu .rmp-menu-current-item .rmp-menu-item-link', 'background','hover');
955
+
956
+ //Menu Trigger
957
+ self.changeInput('.rmp-menu-button-transparent-background', '#rmp_menu_trigger-' + self.menuId , 'background','');
958
+ self.changeInput('#rmp-menu-button-position-type', '#rmp_menu_trigger-' + self.menuId , 'position');
959
+ self.changeInput('.rmp-menu-button-left-or-right', '#rmp_menu_trigger-' + self.menuId , 'trigger-side');
960
+ self.changeInput('#rmp-menu-button-distance-from-side', '#rmp_menu_trigger-' + self.menuId , 'trigger-side-position');
961
+ self.changeInput('#rmp-menu-button-top', '#rmp_menu_trigger-' + self.menuId , 'top');
962
+ self.changeInput('#rmp-menu-button-click-animation', '#rmp_menu_trigger-' + self.menuId , 'trigger-animation');
963
+ self.changeInput('#rmp-menu-button-font', '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-label', 'font-family' );
964
+ self.changeInput('.rmp-menu-button-title-position', '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-label', 'position-alignment' );
965
+
966
+ jQuery("#rmp-menu-button-font-icon").focus(function() {
967
+ var outputSelector = '#rmp_menu_trigger-' + self.menuId + ' span.rmp-trigger-icon-inactive';
968
+ value = jQuery(this).val();
969
+ var iframe = jQuery(self.iframe);
970
+ if ( iframe.contents().find(outputSelector).length ) {
971
+ iframe.contents().find( outputSelector ).addClass(value);
972
+ } else {
973
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box img.rmp-trigger-icon' ).hide();
974
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box .responsive-menu-pro-inner' ).hide();
975
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box' ).append('<span class="rmp-trigger-icon rmp-trigger-icon-inactive ' + value +'"></span>')
976
+ }
977
+ });
978
+
979
+ jQuery("#rmp-menu-button-font-icon-when-clicked").focus(function() {
980
+ var outputSelector = '#rmp_menu_trigger-' + self.menuId + ' span.rmp-trigger-icon-active';
981
+ value = jQuery(this).val();
982
+ var iframe = jQuery(self.iframe);
983
+ if ( iframe.contents().find(outputSelector).length ) {
984
+ iframe.contents().find( outputSelector ).addClass(value);
985
+ } else {
986
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box img.rmp-trigger-icon' ).hide();
987
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box .responsive-menu-pro-inner' ).hide();
988
+ iframe.contents().find( '#rmp_menu_trigger-' + self.menuId + ' .rmp-trigger-box' ).append('<span class="rmp-trigger-icon rmp-trigger-icon-active ' + value +'"></span>')
989
+ }
990
+ });
991
+
992
+ // Ordering elements
993
+ self.toggleElements('#rmp-item-order-title','#rmp-menu-title-' + self.menuId );
994
+ self.toggleElements('#rmp-item-order-additional-content','#rmp-menu-additional-content-' + self.menuId );
995
+ self.toggleElements('#rmp-item-order-search','#rmp-search-box-'+ self.menuId);
996
+ self.toggleElements('#rmp-item-order-menu','#rmp-menu-wrap-' + self.menuId );
997
+
998
+ jQuery( '#rmp-menu-ordering-items' ).sortable( {
999
+ update: function( event, ui ) {
1000
+ self.orderMenuElements();
1001
+ }
1002
+ });
1003
+ }
1004
+ };
1005
+
1006
+ RMP_Preview.init();
1007
+ });
1008
+
v4.0.0/assets/admin/js/selectize.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! selectize.js - v0.12.4 | https://github.com/selectize/selectize.js | Apache License (v2) */
2
+ !function(a,b){"function"==typeof define&&define.amd?define("sifter",b):"object"==typeof exports?module.exports=b():a.Sifter=b()}(this,function(){var a=function(a,b){this.items=a,this.settings=b||{diacritics:!0}};a.prototype.tokenize=function(a){if(a=e(String(a||"").toLowerCase()),!a||!a.length)return[];var b,c,d,g,i=[],j=a.split(/ +/);for(b=0,c=j.length;b<c;b++){if(d=f(j[b]),this.settings.diacritics)for(g in h)h.hasOwnProperty(g)&&(d=d.replace(new RegExp(g,"g"),h[g]));i.push({string:j[b],regex:new RegExp(d,"i")})}return i},a.prototype.iterator=function(a,b){var c;c=g(a)?Array.prototype.forEach||function(a){for(var b=0,c=this.length;b<c;b++)a(this[b],b,this)}:function(a){for(var b in this)this.hasOwnProperty(b)&&a(this[b],b,this)},c.apply(a,[b])},a.prototype.getScoreFunction=function(a,b){var c,e,f,g,h;c=this,a=c.prepareSearch(a,b),f=a.tokens,e=a.options.fields,g=f.length,h=a.options.nesting;var i=function(a,b){var c,d;return a?(a=String(a||""),d=a.search(b.regex),d===-1?0:(c=b.string.length/a.length,0===d&&(c+=.5),c)):0},j=function(){var a=e.length;return a?1===a?function(a,b){return i(d(b,e[0],h),a)}:function(b,c){for(var f=0,g=0;f<a;f++)g+=i(d(c,e[f],h),b);return g/a}:function(){return 0}}();return g?1===g?function(a){return j(f[0],a)}:"and"===a.options.conjunction?function(a){for(var b,c=0,d=0;c<g;c++){if(b=j(f[c],a),b<=0)return 0;d+=b}return d/g}:function(a){for(var b=0,c=0;b<g;b++)c+=j(f[b],a);return c/g}:function(){return 0}},a.prototype.getSortFunction=function(a,c){var e,f,g,h,i,j,k,l,m,n,o;if(g=this,a=g.prepareSearch(a,c),o=!a.query&&c.sort_empty||c.sort,m=function(a,b){return"$score"===a?b.score:d(g.items[b.id],a,c.nesting)},i=[],o)for(e=0,f=o.length;e<f;e++)(a.query||"$score"!==o[e].field)&&i.push(o[e]);if(a.query){for(n=!0,e=0,f=i.length;e<f;e++)if("$score"===i[e].field){n=!1;break}n&&i.unshift({field:"$score",direction:"desc"})}else for(e=0,f=i.length;e<f;e++)if("$score"===i[e].field){i.splice(e,1);break}for(l=[],e=0,f=i.length;e<f;e++)l.push("desc"===i[e].direction?-1:1);return j=i.length,j?1===j?(h=i[0].field,k=l[0],function(a,c){return k*b(m(h,a),m(h,c))}):function(a,c){var d,e,f;for(d=0;d<j;d++)if(f=i[d].field,e=l[d]*b(m(f,a),m(f,c)))return e;return 0}:null},a.prototype.prepareSearch=function(a,b){if("object"==typeof a)return a;b=c({},b);var d=b.fields,e=b.sort,f=b.sort_empty;return d&&!g(d)&&(b.fields=[d]),e&&!g(e)&&(b.sort=[e]),f&&!g(f)&&(b.sort_empty=[f]),{options:b,query:String(a||"").toLowerCase(),tokens:this.tokenize(a),total:0,items:[]}},a.prototype.search=function(a,b){var c,d,e,f,g=this;return d=this.prepareSearch(a,b),b=d.options,a=d.query,f=b.score||g.getScoreFunction(d),a.length?g.iterator(g.items,function(a,e){c=f(a),(b.filter===!1||c>0)&&d.items.push({score:c,id:e})}):g.iterator(g.items,function(a,b){d.items.push({score:1,id:b})}),e=g.getSortFunction(d,b),e&&d.items.sort(e),d.total=d.items.length,"number"==typeof b.limit&&(d.items=d.items.slice(0,b.limit)),d};var b=function(a,b){return"number"==typeof a&&"number"==typeof b?a>b?1:a<b?-1:0:(a=i(String(a||"")),b=i(String(b||"")),a>b?1:b>a?-1:0)},c=function(a,b){var c,d,e,f;for(c=1,d=arguments.length;c<d;c++)if(f=arguments[c])for(e in f)f.hasOwnProperty(e)&&(a[e]=f[e]);return a},d=function(a,b,c){if(a&&b){if(!c)return a[b];for(var d=b.split(".");d.length&&(a=a[d.shift()]););return a}},e=function(a){return(a+"").replace(/^\s+|\s+$|/g,"")},f=function(a){return(a+"").replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")},g=Array.isArray||"undefined"!=typeof $&&$.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)},h={a:"[aḀḁĂăÂâǍǎȺⱥȦȧẠạÄäÀàÁáĀāÃãÅåąĄÃąĄ]",b:"[b␢βΒB฿𐌁ᛒ]",c:"[cĆćĈĉČčĊċC̄c̄ÇçḈḉȻȼƇƈɕᴄCc]",d:"[dĎďḊḋḐḑḌḍḒḓḎḏĐđD̦d̦ƉɖƊɗƋƌᵭᶁᶑȡᴅDdð]",e:"[eÉéÈèÊêḘḙĚěĔĕẼẽḚḛẺẻĖėËëĒēȨȩĘęᶒɆɇȄȅẾếỀềỄễỂểḜḝḖḗḔḕȆȇẸẹỆệⱸᴇEeɘǝƏƐε]",f:"[fƑƒḞḟ]",g:"[gɢ₲ǤǥĜĝĞğĢģƓɠĠġ]",h:"[hĤĥĦħḨḩẖẖḤḥḢḣɦʰǶƕ]",i:"[iÍíÌìĬĭÎîǏǐÏïḮḯĨĩĮįĪīỈỉȈȉȊȋỊịḬḭƗɨɨ̆ᵻᶖİiIıɪIi]",j:"[jȷĴĵɈɉʝɟʲ]",k:"[kƘƙꝀꝁḰḱǨǩḲḳḴḵκϰ₭]",l:"[lŁłĽľĻļĹĺḶḷḸḹḼḽḺḻĿŀȽƚⱠⱡⱢɫɬᶅɭȴʟLl]",n:"[nŃńǸǹŇňÑñṄṅŅņṆṇṊṋṈṉN̈n̈ƝɲȠƞᵰᶇɳȵɴNnŊŋ]",o:"[oØøÖöÓóÒòÔôǑǒŐőŎŏȮȯỌọƟɵƠơỎỏŌōÕõǪǫȌȍՕօ]",p:"[pṔṕṖṗⱣᵽƤƥᵱ]",q:"[qꝖꝗʠɊɋꝘꝙq̃]",r:"[rŔŕɌɍŘřŖŗṘṙȐȑȒȓṚṛⱤɽ]",s:"[sŚśṠṡṢṣꞨꞩŜŝŠšŞşȘșS̈s̈]",t:"[tŤťṪṫŢţṬṭƮʈȚțṰṱṮṯƬƭ]",u:"[uŬŭɄʉỤụÜüÚúÙùÛûǓǔŰűŬŭƯưỦủŪūŨũŲųȔȕ∪]",v:"[vṼṽṾṿƲʋꝞꝟⱱʋ]",w:"[wẂẃẀẁŴŵẄẅẆẇẈẉ]",x:"[xẌẍẊẋχ]",y:"[yÝýỲỳŶŷŸÿỸỹẎẏỴỵɎɏƳƴ]",z:"[zŹźẐẑŽžŻżẒẓẔẕƵƶ]"},i=function(){var a,b,c,d,e="",f={};for(c in h)if(h.hasOwnProperty(c))for(d=h[c].substring(2,h[c].length-1),e+=d,a=0,b=d.length;a<b;a++)f[d.charAt(a)]=c;var g=new RegExp("["+e+"]","g");return function(a){return a.replace(g,function(a){return f[a]}).toLowerCase()}}();return a}),function(a,b){"function"==typeof define&&define.amd?define("microplugin",b):"object"==typeof exports?module.exports=b():a.MicroPlugin=b()}(this,function(){var a={};a.mixin=function(a){a.plugins={},a.prototype.initializePlugins=function(a){var c,d,e,f=this,g=[];if(f.plugins={names:[],settings:{},requested:{},loaded:{}},b.isArray(a))for(c=0,d=a.length;c<d;c++)"string"==typeof a[c]?g.push(a[c]):(f.plugins.settings[a[c].name]=a[c].options,g.push(a[c].name));else if(a)for(e in a)a.hasOwnProperty(e)&&(f.plugins.settings[e]=a[e],g.push(e));for(;g.length;)f.require(g.shift())},a.prototype.loadPlugin=function(b){var c=this,d=c.plugins,e=a.plugins[b];if(!a.plugins.hasOwnProperty(b))throw new Error('Unable to find "'+b+'" plugin');d.requested[b]=!0,d.loaded[b]=e.fn.apply(c,[c.plugins.settings[b]||{}]),d.names.push(b)},a.prototype.require=function(a){var b=this,c=b.plugins;if(!b.plugins.loaded.hasOwnProperty(a)){if(c.requested[a])throw new Error('Plugin has circular dependency ("'+a+'")');b.loadPlugin(a)}return c.loaded[a]},a.define=function(b,c){a.plugins[b]={name:b,fn:c}}};var b={isArray:Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)}};return a}),function(a,b){"function"==typeof define&&define.amd?define("selectize",["jquery","sifter","microplugin"],b):"object"==typeof exports?module.exports=b(require("jquery"),require("sifter"),require("microplugin")):a.Selectize=b(a.jQuery,a.Sifter,a.MicroPlugin)}(this,function(a,b,c){"use strict";var d=function(a,b){if("string"!=typeof b||b.length){var c="string"==typeof b?new RegExp(b,"i"):b,d=function(a){var b=0;if(3===a.nodeType){var e=a.data.search(c);if(e>=0&&a.data.length>0){var f=a.data.match(c),g=document.createElement("span");g.className="highlight";var h=a.splitText(e),i=(h.splitText(f[0].length),h.cloneNode(!0));g.appendChild(i),h.parentNode.replaceChild(g,h),b=1}}else if(1===a.nodeType&&a.childNodes&&!/(script|style)/i.test(a.tagName))for(var j=0;j<a.childNodes.length;++j)j+=d(a.childNodes[j]);return b};return a.each(function(){d(this)})}};a.fn.removeHighlight=function(){return this.find("span.highlight").each(function(){this.parentNode.firstChild.nodeName;var a=this.parentNode;a.replaceChild(this.firstChild,this),a.normalize()}).end()};var e=function(){};e.prototype={on:function(a,b){this._events=this._events||{},this._events[a]=this._events[a]||[],this._events[a].push(b)},off:function(a,b){var c=arguments.length;return 0===c?delete this._events:1===c?delete this._events[a]:(this._events=this._events||{},void(a in this._events!=!1&&this._events[a].splice(this._events[a].indexOf(b),1)))},trigger:function(a){if(this._events=this._events||{},a in this._events!=!1)for(var b=0;b<this._events[a].length;b++)this._events[a][b].apply(this,Array.prototype.slice.call(arguments,1))}},e.mixin=function(a){for(var b=["on","off","trigger"],c=0;c<b.length;c++)a.prototype[b[c]]=e.prototype[b[c]]};var f=/Mac/.test(navigator.userAgent),g=65,h=13,i=27,j=37,k=38,l=80,m=39,n=40,o=78,p=8,q=46,r=16,s=f?91:17,t=f?18:17,u=9,v=1,w=2,x=!/android/i.test(window.navigator.userAgent)&&!!document.createElement("input").validity,y=function(a){return"undefined"!=typeof a},z=function(a){return"undefined"==typeof a||null===a?null:"boolean"==typeof a?a?"1":"0":a+""},A=function(a){return(a+"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")},B={};B.before=function(a,b,c){var d=a[b];a[b]=function(){return c.apply(a,arguments),d.apply(a,arguments)}},B.after=function(a,b,c){var d=a[b];a[b]=function(){var b=d.apply(a,arguments);return c.apply(a,arguments),b}};var C=function(a){var b=!1;return function(){b||(b=!0,a.apply(this,arguments))}},D=function(a,b){var c;return function(){var d=this,e=arguments;window.clearTimeout(c),c=window.setTimeout(function(){a.apply(d,e)},b)}},E=function(a,b,c){var d,e=a.trigger,f={};a.trigger=function(){var c=arguments[0];return b.indexOf(c)===-1?e.apply(a,arguments):void(f[c]=arguments)},c.apply(a,[]),a.trigger=e;for(d in f)f.hasOwnProperty(d)&&e.apply(a,f[d])},F=function(a,b,c,d){a.on(b,c,function(b){for(var c=b.target;c&&c.parentNode!==a[0];)c=c.parentNode;return b.currentTarget=c,d.apply(this,[b])})},G=function(a){var b={};if("selectionStart"in a)b.start=a.selectionStart,b.length=a.selectionEnd-b.start;else if(document.selection){a.focus();var c=document.selection.createRange(),d=document.selection.createRange().text.length;c.moveStart("character",-a.value.length),b.start=c.text.length-d,b.length=d}return b},H=function(a,b,c){var d,e,f={};if(c)for(d=0,e=c.length;d<e;d++)f[c[d]]=a.css(c[d]);else f=a.css();b.css(f)},I=function(b,c){if(!b)return 0;var d=a("<test>").css({position:"absolute",top:-99999,left:-99999,width:"auto",padding:0,whiteSpace:"pre"}).text(b).appendTo("body");H(c,d,["letterSpacing","fontSize","fontFamily","fontWeight","textTransform"]);var e=d.width();return d.remove(),e},J=function(a){var b=null,c=function(c,d){var e,f,g,h,i,j,k,l;c=c||window.event||{},d=d||{},c.metaKey||c.altKey||(d.force||a.data("grow")!==!1)&&(e=a.val(),c.type&&"keydown"===c.type.toLowerCase()&&(f=c.keyCode,g=f>=97&&f<=122||f>=65&&f<=90||f>=48&&f<=57||32===f,f===q||f===p?(l=G(a[0]),l.length?e=e.substring(0,l.start)+e.substring(l.start+l.length):f===p&&l.start?e=e.substring(0,l.start-1)+e.substring(l.start+1):f===q&&"undefined"!=typeof l.start&&(e=e.substring(0,l.start)+e.substring(l.start+1))):g&&(j=c.shiftKey,k=String.fromCharCode(c.keyCode),k=j?k.toUpperCase():k.toLowerCase(),e+=k)),h=a.attr("placeholder"),!e&&h&&(e=h),i=I(e,a)+4,i!==b&&(b=i,a.width(i),a.triggerHandler("resize")))};a.on("keydown keyup update blur",c),c()},K=function(a){var b=document.createElement("div");return b.appendChild(a.cloneNode(!0)),b.innerHTML},L=function(a,b){b||(b={});var c="Selectize";console.error(c+": "+a),b.explanation&&(console.group&&console.group(),console.error(b.explanation),console.group&&console.groupEnd())},M=function(c,d){var e,f,g,h,i=this;h=c[0],h.selectize=i;var j=window.getComputedStyle&&window.getComputedStyle(h,null);if(g=j?j.getPropertyValue("direction"):h.currentStyle&&h.currentStyle.direction,g=g||c.parents("[dir]:first").attr("dir")||"",a.extend(i,{order:0,settings:d,$input:c,tabIndex:c.attr("tabindex")||"",tagType:"select"===h.tagName.toLowerCase()?v:w,rtl:/rtl/i.test(g),eventNS:".selectize"+ ++M.count,highlightedValue:null,isOpen:!1,isDisabled:!1,isRequired:c.is("[required]"),isInvalid:!1,isLocked:!1,isFocused:!1,isInputHidden:!1,isSetup:!1,isShiftDown:!1,isCmdDown:!1,isCtrlDown:!1,ignoreFocus:!1,ignoreBlur:!1,ignoreHover:!1,hasOptions:!1,currentResults:null,lastValue:"",caretPos:0,loading:0,loadedSearches:{},$activeOption:null,$activeItems:[],optgroups:{},options:{},userOptions:{},items:[],renderCache:{},onSearchChange:null===d.loadThrottle?i.onSearchChange:D(i.onSearchChange,d.loadThrottle)}),i.sifter=new b(this.options,{diacritics:d.diacritics}),i.settings.options){for(e=0,f=i.settings.options.length;e<f;e++)i.registerOption(i.settings.options[e]);delete i.settings.options}if(i.settings.optgroups){for(e=0,f=i.settings.optgroups.length;e<f;e++)i.registerOptionGroup(i.settings.optgroups[e]);delete i.settings.optgroups}i.settings.mode=i.settings.mode||(1===i.settings.maxItems?"single":"multi"),"boolean"!=typeof i.settings.hideSelected&&(i.settings.hideSelected="multi"===i.settings.mode),i.initializePlugins(i.settings.plugins),i.setupCallbacks(),i.setupTemplates(),i.setup()};return e.mixin(M),"undefined"!=typeof c?c.mixin(M):L("Dependency MicroPlugin is missing",{explanation:'Make sure you either: (1) are using the "standalone" version of Selectize, or (2) require MicroPlugin before you load Selectize.'}),a.extend(M.prototype,{setup:function(){var b,c,d,e,g,h,i,j,k,l,m=this,n=m.settings,o=m.eventNS,p=a(window),q=a(document),u=m.$input;if(i=m.settings.mode,j=u.attr("class")||"",b=a("<div>").addClass(n.wrapperClass).addClass(j).addClass(i),c=a("<div>").addClass(n.inputClass).addClass("items").appendTo(b),d=a('<input type="text" autocomplete="off" />').appendTo(c).attr("tabindex",u.is(":disabled")?"-1":m.tabIndex),h=a(n.dropdownParent||b),e=a("<div>").addClass(n.dropdownClass).addClass(i).hide().appendTo(h),g=a("<div>").addClass(n.dropdownContentClass).appendTo(e),(l=u.attr("id"))&&(d.attr("id",l+"-selectized"),a("label[for='"+l+"']").attr("for",l+"-selectized")),m.settings.copyClassesToDropdown&&e.addClass(j),b.css({width:u[0].style.width}),m.plugins.names.length&&(k="plugin-"+m.plugins.names.join(" plugin-"),b.addClass(k),e.addClass(k)),(null===n.maxItems||n.maxItems>1)&&m.tagType===v&&u.attr("multiple","multiple"),m.settings.placeholder&&d.attr("placeholder",n.placeholder),!m.settings.splitOn&&m.settings.delimiter){var w=m.settings.delimiter.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&");m.settings.splitOn=new RegExp("\\s*"+w+"+\\s*")}u.attr("autocorrect")&&d.attr("autocorrect",u.attr("autocorrect")),u.attr("autocapitalize")&&d.attr("autocapitalize",u.attr("autocapitalize")),m.$wrapper=b,m.$control=c,m.$control_input=d,m.$dropdown=e,m.$dropdown_content=g,e.on("mouseenter","[data-selectable]",function(){return m.onOptionHover.apply(m,arguments)}),e.on("mousedown click","[data-selectable]",function(){return m.onOptionSelect.apply(m,arguments)}),F(c,"mousedown","*:not(input)",function(){return m.onItemSelect.apply(m,arguments)}),J(d),c.on({mousedown:function(){return m.onMouseDown.apply(m,arguments)},click:function(){return m.onClick.apply(m,arguments)}}),d.on({mousedown:function(a){a.stopPropagation()},keydown:function(){return m.onKeyDown.apply(m,arguments)},keyup:function(){return m.onKeyUp.apply(m,arguments)},keypress:function(){return m.onKeyPress.apply(m,arguments)},resize:function(){m.positionDropdown.apply(m,[])},blur:function(){return m.onBlur.apply(m,arguments)},focus:function(){return m.ignoreBlur=!1,m.onFocus.apply(m,arguments)},paste:function(){return m.onPaste.apply(m,arguments)}}),q.on("keydown"+o,function(a){m.isCmdDown=a[f?"metaKey":"ctrlKey"],m.isCtrlDown=a[f?"altKey":"ctrlKey"],m.isShiftDown=a.shiftKey}),q.on("keyup"+o,function(a){a.keyCode===t&&(m.isCtrlDown=!1),a.keyCode===r&&(m.isShiftDown=!1),a.keyCode===s&&(m.isCmdDown=!1)}),q.on("mousedown"+o,function(a){if(m.isFocused){if(a.target===m.$dropdown[0]||a.target.parentNode===m.$dropdown[0])return!1;m.$control.has(a.target).length||a.target===m.$control[0]||m.blur(a.target)}}),p.on(["scroll"+o,"resize"+o].join(" "),function(){m.isOpen&&m.positionDropdown.apply(m,arguments)}),p.on("mousemove"+o,function(){m.ignoreHover=!1}),this.revertSettings={$children:u.children().detach(),tabindex:u.attr("tabindex")},u.attr("tabindex",-1).hide().after(m.$wrapper),a.isArray(n.items)&&(m.setValue(n.items),delete n.items),x&&u.on("invalid"+o,function(a){a.preventDefault(),m.isInvalid=!0,m.refreshState()}),m.updateOriginalInput(),m.refreshItems(),m.refreshState(),m.updatePlaceholder(),m.isSetup=!0,u.is(":disabled")&&m.disable(),m.on("change",this.onChange),u.data("selectize",m),u.addClass("selectized"),m.trigger("initialize"),n.preload===!0&&m.onSearchChange("")},setupTemplates:function(){var b=this,c=b.settings.labelField,d=b.settings.optgroupLabelField,e={optgroup:function(a){return'<div class="optgroup">'+a.html+"</div>"},optgroup_header:function(a,b){return'<div class="optgroup-header">'+b(a[d])+"</div>"},option:function(a,b){return'<div class="option">'+b(a[c])+"</div>"},item:function(a,b){return'<div class="item">'+b(a[c])+"</div>"},option_create:function(a,b){return'<div class="create">Add <strong>'+b(a.input)+"</strong>&hellip;</div>"}};b.settings.render=a.extend({},e,b.settings.render)},setupCallbacks:function(){var a,b,c={initialize:"onInitialize",change:"onChange",item_add:"onItemAdd",item_remove:"onItemRemove",clear:"onClear",option_add:"onOptionAdd",option_remove:"onOptionRemove",option_clear:"onOptionClear",optgroup_add:"onOptionGroupAdd",optgroup_remove:"onOptionGroupRemove",optgroup_clear:"onOptionGroupClear",dropdown_open:"onDropdownOpen",dropdown_close:"onDropdownClose",type:"onType",load:"onLoad",focus:"onFocus",blur:"onBlur"};for(a in c)c.hasOwnProperty(a)&&(b=this.settings[c[a]],b&&this.on(a,b))},onClick:function(a){var b=this;b.isFocused||(b.focus(),a.preventDefault())},onMouseDown:function(b){var c=this,d=b.isDefaultPrevented();a(b.target);if(c.isFocused){if(b.target!==c.$control_input[0])return"single"===c.settings.mode?c.isOpen?c.close():c.open():d||c.setActiveItem(null),!1}else d||window.setTimeout(function(){c.focus()},0)},onChange:function(){this.$input.trigger("change")},onPaste:function(b){var c=this;return c.isFull()||c.isInputHidden||c.isLocked?void b.preventDefault():void(c.settings.splitOn&&setTimeout(function(){var b=c.$control_input.val();if(b.match(c.settings.splitOn))for(var d=a.trim(b).split(c.settings.splitOn),e=0,f=d.length;e<f;e++)c.createItem(d[e])},0))},onKeyPress:function(a){if(this.isLocked)return a&&a.preventDefault();var b=String.fromCharCode(a.keyCode||a.which);return this.settings.create&&"multi"===this.settings.mode&&b===this.settings.delimiter?(this.createItem(),a.preventDefault(),!1):void 0},onKeyDown:function(a){var b=(a.target===this.$control_input[0],this);if(b.isLocked)return void(a.keyCode!==u&&a.preventDefault());switch(a.keyCode){case g:if(b.isCmdDown)return void b.selectAll();break;case i:return void(b.isOpen&&(a.preventDefault(),a.stopPropagation(),b.close()));case o:if(!a.ctrlKey||a.altKey)break;case n:if(!b.isOpen&&b.hasOptions)b.open();else if(b.$activeOption){b.ignoreHover=!0;var c=b.getAdjacentOption(b.$activeOption,1);c.length&&b.setActiveOption(c,!0,!0)}return void a.preventDefault();case l:if(!a.ctrlKey||a.altKey)break;case k:if(b.$activeOption){b.ignoreHover=!0;var d=b.getAdjacentOption(b.$activeOption,-1);d.length&&b.setActiveOption(d,!0,!0)}return void a.preventDefault();case h:return void(b.isOpen&&b.$activeOption&&(b.onOptionSelect({currentTarget:b.$activeOption}),a.preventDefault()));case j:return void b.advanceSelection(-1,a);case m:return void b.advanceSelection(1,a);case u:return b.settings.selectOnTab&&b.isOpen&&b.$activeOption&&(b.onOptionSelect({currentTarget:b.$activeOption}),b.isFull()||a.preventDefault()),void(b.settings.create&&b.createItem()&&a.preventDefault());case p:case q:return void b.deleteSelection(a)}return!b.isFull()&&!b.isInputHidden||(f?a.metaKey:a.ctrlKey)?void 0:void a.preventDefault()},onKeyUp:function(a){var b=this;if(b.isLocked)return a&&a.preventDefault();var c=b.$control_input.val()||"";b.lastValue!==c&&(b.lastValue=c,b.onSearchChange(c),b.refreshOptions(),b.trigger("type",c))},onSearchChange:function(a){var b=this,c=b.settings.load;c&&(b.loadedSearches.hasOwnProperty(a)||(b.loadedSearches[a]=!0,b.load(function(d){c.apply(b,[a,d])})))},onFocus:function(a){var b=this,c=b.isFocused;return b.isDisabled?(b.blur(),a&&a.preventDefault(),!1):void(b.ignoreFocus||(b.isFocused=!0,"focus"===b.settings.preload&&b.onSearchChange(""),c||b.trigger("focus"),b.$activeItems.length||(b.showInput(),b.setActiveItem(null),b.refreshOptions(!!b.settings.openOnFocus)),b.refreshState()))},onBlur:function(a,b){var c=this;if(c.isFocused&&(c.isFocused=!1,!c.ignoreFocus)){if(!c.ignoreBlur&&document.activeElement===c.$dropdown_content[0])return c.ignoreBlur=!0,void c.onFocus(a);var d=function(){c.close(),c.setTextboxValue(""),c.setActiveItem(null),c.setActiveOption(null),c.setCaret(c.items.length),c.refreshState(),b&&b.focus&&b.focus(),c.ignoreFocus=!1,c.trigger("blur")};c.ignoreFocus=!0,c.settings.create&&c.settings.createOnBlur?c.createItem(null,!1,d):d()}},onOptionHover:function(a){this.ignoreHover||this.setActiveOption(a.currentTarget,!1)},onOptionSelect:function(b){var c,d,e=this;b.preventDefault&&(b.preventDefault(),b.stopPropagation()),d=a(b.currentTarget),d.hasClass("create")?e.createItem(null,function(){e.settings.closeAfterSelect&&e.close()}):(c=d.attr("data-value"),"undefined"!=typeof c&&(e.lastQuery=null,e.setTextboxValue(""),e.addItem(c),e.settings.closeAfterSelect?e.close():!e.settings.hideSelected&&b.type&&/mouse/.test(b.type)&&e.setActiveOption(e.getOption(c))))},onItemSelect:function(a){var b=this;b.isLocked||"multi"===b.settings.mode&&(a.preventDefault(),b.setActiveItem(a.currentTarget,a))},load:function(a){var b=this,c=b.$wrapper.addClass(b.settings.loadingClass);b.loading++,a.apply(b,[function(a){b.loading=Math.max(b.loading-1,0),a&&a.length&&(b.addOption(a),b.refreshOptions(b.isFocused&&!b.isInputHidden)),b.loading||c.removeClass(b.settings.loadingClass),b.trigger("load",a)}])},setTextboxValue:function(a){var b=this.$control_input,c=b.val()!==a;c&&(b.val(a).triggerHandler("update"),this.lastValue=a)},getValue:function(){return this.tagType===v&&this.$input.attr("multiple")?this.items:this.items.join(this.settings.delimiter)},setValue:function(a,b){var c=b?[]:["change"];E(this,c,function(){this.clear(b),this.addItems(a,b)})},setActiveItem:function(b,c){var d,e,f,g,h,i,j,k,l=this;if("single"!==l.settings.mode){if(b=a(b),!b.length)return a(l.$activeItems).removeClass("active"),l.$activeItems=[],void(l.isFocused&&l.showInput());if(d=c&&c.type.toLowerCase(),"mousedown"===d&&l.isShiftDown&&l.$activeItems.length){for(k=l.$control.children(".active:last"),g=Array.prototype.indexOf.apply(l.$control[0].childNodes,[k[0]]),h=Array.prototype.indexOf.apply(l.$control[0].childNodes,[b[0]]),g>h&&(j=g,g=h,h=j),e=g;e<=h;e++)i=l.$control[0].childNodes[e],l.$activeItems.indexOf(i)===-1&&(a(i).addClass("active"),l.$activeItems.push(i));c.preventDefault()}else"mousedown"===d&&l.isCtrlDown||"keydown"===d&&this.isShiftDown?b.hasClass("active")?(f=l.$activeItems.indexOf(b[0]),l.$activeItems.splice(f,1),b.removeClass("active")):l.$activeItems.push(b.addClass("active")[0]):(a(l.$activeItems).removeClass("active"),l.$activeItems=[b.addClass("active")[0]]);l.hideInput(),this.isFocused||l.focus()}},setActiveOption:function(b,c,d){var e,f,g,h,i,j=this;j.$activeOption&&j.$activeOption.removeClass("active"),j.$activeOption=null,b=a(b),b.length&&(j.$activeOption=b.addClass("active"),!c&&y(c)||(e=j.$dropdown_content.height(),f=j.$activeOption.outerHeight(!0),c=j.$dropdown_content.scrollTop()||0,g=j.$activeOption.offset().top-j.$dropdown_content.offset().top+c,h=g,i=g-e+f,g+f>e+c?j.$dropdown_content.stop().animate({scrollTop:i},d?j.settings.scrollDuration:0):g<c&&j.$dropdown_content.stop().animate({scrollTop:h},d?j.settings.scrollDuration:0)))},selectAll:function(){var a=this;"single"!==a.settings.mode&&(a.$activeItems=Array.prototype.slice.apply(a.$control.children(":not(input)").addClass("active")),a.$activeItems.length&&(a.hideInput(),a.close()),a.focus())},hideInput:function(){var a=this;a.setTextboxValue(""),a.$control_input.css({opacity:0,position:"absolute",left:a.rtl?1e4:-1e4}),a.isInputHidden=!0},showInput:function(){this.$control_input.css({opacity:1,position:"relative",left:0}),this.isInputHidden=!1},focus:function(){var a=this;a.isDisabled||(a.ignoreFocus=!0,a.$control_input[0].focus(),window.setTimeout(function(){a.ignoreFocus=!1,a.onFocus()},0))},blur:function(a){this.$control_input[0].blur(),this.onBlur(null,a)},getScoreFunction:function(a){return this.sifter.getScoreFunction(a,this.getSearchOptions())},getSearchOptions:function(){var a=this.settings,b=a.sortField;return"string"==typeof b&&(b=[{field:b}]),{fields:a.searchField,conjunction:a.searchConjunction,sort:b}},search:function(b){var c,d,e,f=this,g=f.settings,h=this.getSearchOptions();if(g.score&&(e=f.settings.score.apply(this,[b]),"function"!=typeof e))throw new Error('Selectize "score" setting must be a function that returns a function');if(b!==f.lastQuery?(f.lastQuery=b,d=f.sifter.search(b,a.extend(h,{score:e})),f.currentResults=d):d=a.extend(!0,{},f.currentResults),g.hideSelected)for(c=d.items.length-1;c>=0;c--)f.items.indexOf(z(d.items[c].id))!==-1&&d.items.splice(c,1);return d},refreshOptions:function(b){var c,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s;"undefined"==typeof b&&(b=!0);var t=this,u=a.trim(t.$control_input.val()),v=t.search(u),w=t.$dropdown_content,x=t.$activeOption&&z(t.$activeOption.attr("data-value"));for(g=v.items.length,"number"==typeof t.settings.maxOptions&&(g=Math.min(g,t.settings.maxOptions)),h={},i=[],c=0;c<g;c++)for(j=t.options[v.items[c].id],k=t.render("option",j),l=j[t.settings.optgroupField]||"",m=a.isArray(l)?l:[l],e=0,f=m&&m.length;e<f;e++)l=m[e],t.optgroups.hasOwnProperty(l)||(l=""),h.hasOwnProperty(l)||(h[l]=document.createDocumentFragment(),i.push(l)),h[l].appendChild(k);for(this.settings.lockOptgroupOrder&&i.sort(function(a,b){var c=t.optgroups[a].$order||0,d=t.optgroups[b].$order||0;return c-d}),n=document.createDocumentFragment(),c=0,g=i.length;c<g;c++)l=i[c],t.optgroups.hasOwnProperty(l)&&h[l].childNodes.length?(o=document.createDocumentFragment(),o.appendChild(t.render("optgroup_header",t.optgroups[l])),o.appendChild(h[l]),n.appendChild(t.render("optgroup",a.extend({},t.optgroups[l],{html:K(o),dom:o})))):n.appendChild(h[l]);if(w.html(n),t.settings.highlight&&v.query.length&&v.tokens.length)for(w.removeHighlight(),c=0,g=v.tokens.length;c<g;c++)d(w,v.tokens[c].regex);if(!t.settings.hideSelected)for(c=0,g=t.items.length;c<g;c++)t.getOption(t.items[c]).addClass("selected");p=t.canCreate(u),p&&(w.prepend(t.render("option_create",{input:u})),s=a(w[0].childNodes[0])),t.hasOptions=v.items.length>0||p,t.hasOptions?(v.items.length>0?(r=x&&t.getOption(x),r&&r.length?q=r:"single"===t.settings.mode&&t.items.length&&(q=t.getOption(t.items[0])),q&&q.length||(q=s&&!t.settings.addPrecedence?t.getAdjacentOption(s,1):w.find("[data-selectable]:first"))):q=s,t.setActiveOption(q),b&&!t.isOpen&&t.open()):(t.setActiveOption(null),b&&t.isOpen&&t.close())},addOption:function(b){var c,d,e,f=this;if(a.isArray(b))for(c=0,d=b.length;c<d;c++)f.addOption(b[c]);else(e=f.registerOption(b))&&(f.userOptions[e]=!0,f.lastQuery=null,f.trigger("option_add",e,b))},registerOption:function(a){var b=z(a[this.settings.valueField]);return"undefined"!=typeof b&&null!==b&&!this.options.hasOwnProperty(b)&&(a.$order=a.$order||++this.order,this.options[b]=a,b)},registerOptionGroup:function(a){var b=z(a[this.settings.optgroupValueField]);return!!b&&(a.$order=a.$order||++this.order,this.optgroups[b]=a,b)},addOptionGroup:function(a,b){b[this.settings.optgroupValueField]=a,(a=this.registerOptionGroup(b))&&this.trigger("optgroup_add",a,b)},removeOptionGroup:function(a){this.optgroups.hasOwnProperty(a)&&(delete this.optgroups[a],this.renderCache={},this.trigger("optgroup_remove",a))},clearOptionGroups:function(){this.optgroups={},this.renderCache={},this.trigger("optgroup_clear")},updateOption:function(b,c){var d,e,f,g,h,i,j,k=this;if(b=z(b),f=z(c[k.settings.valueField]),null!==b&&k.options.hasOwnProperty(b)){if("string"!=typeof f)throw new Error("Value must be set in option data");j=k.options[b].$order,f!==b&&(delete k.options[b],g=k.items.indexOf(b),g!==-1&&k.items.splice(g,1,f)),c.$order=c.$order||j,k.options[f]=c,h=k.renderCache.item,i=k.renderCache.option,h&&(delete h[b],delete h[f]),i&&(delete i[b],delete i[f]),k.items.indexOf(f)!==-1&&(d=k.getItem(b),e=a(k.render("item",c)),d.hasClass("active")&&e.addClass("active"),d.replaceWith(e)),k.lastQuery=null,k.isOpen&&k.refreshOptions(!1)}},removeOption:function(a,b){var c=this;a=z(a);var d=c.renderCache.item,e=c.renderCache.option;d&&delete d[a],e&&delete e[a],delete c.userOptions[a],delete c.options[a],c.lastQuery=null,c.trigger("option_remove",a),c.removeItem(a,b)},clearOptions:function(){var a=this;a.loadedSearches={},a.userOptions={},a.renderCache={},a.options=a.sifter.items={},a.lastQuery=null,a.trigger("option_clear"),a.clear()},getOption:function(a){return this.getElementWithValue(a,this.$dropdown_content.find("[data-selectable]"))},getAdjacentOption:function(b,c){var d=this.$dropdown.find("[data-selectable]"),e=d.index(b)+c;return e>=0&&e<d.length?d.eq(e):a()},getElementWithValue:function(b,c){if(b=z(b),"undefined"!=typeof b&&null!==b)for(var d=0,e=c.length;d<e;d++)if(c[d].getAttribute("data-value")===b)return a(c[d]);return a()},getItem:function(a){return this.getElementWithValue(a,this.$control.children())},addItems:function(b,c){for(var d=a.isArray(b)?b:[b],e=0,f=d.length;e<f;e++)this.isPending=e<f-1,this.addItem(d[e],c)},addItem:function(b,c){var d=c?[]:["change"];E(this,d,function(){var d,e,f,g,h,i=this,j=i.settings.mode;return b=z(b),i.items.indexOf(b)!==-1?void("single"===j&&i.close()):void(i.options.hasOwnProperty(b)&&("single"===j&&i.clear(c),"multi"===j&&i.isFull()||(d=a(i.render("item",i.options[b])),h=i.isFull(),i.items.splice(i.caretPos,0,b),i.insertAtCaret(d),(!i.isPending||!h&&i.isFull())&&i.refreshState(),i.isSetup&&(f=i.$dropdown_content.find("[data-selectable]"),i.isPending||(e=i.getOption(b),g=i.getAdjacentOption(e,1).attr("data-value"),i.refreshOptions(i.isFocused&&"single"!==j),g&&i.setActiveOption(i.getOption(g))),!f.length||i.isFull()?i.close():i.positionDropdown(),i.updatePlaceholder(),i.trigger("item_add",b,d),i.updateOriginalInput({silent:c})))))})},removeItem:function(b,c){var d,e,f,g=this;d=b instanceof a?b:g.getItem(b),b=z(d.attr("data-value")),e=g.items.indexOf(b),e!==-1&&(d.remove(),d.hasClass("active")&&(f=g.$activeItems.indexOf(d[0]),g.$activeItems.splice(f,1)),g.items.splice(e,1),g.lastQuery=null,!g.settings.persist&&g.userOptions.hasOwnProperty(b)&&g.removeOption(b,c),e<g.caretPos&&g.setCaret(g.caretPos-1),g.refreshState(),g.updatePlaceholder(),g.updateOriginalInput({silent:c}),g.positionDropdown(),g.trigger("item_remove",b,d))},createItem:function(b,c){var d=this,e=d.caretPos;b=b||a.trim(d.$control_input.val()||"");var f=arguments[arguments.length-1];if("function"!=typeof f&&(f=function(){}),"boolean"!=typeof c&&(c=!0),!d.canCreate(b))return f(),!1;d.lock();var g="function"==typeof d.settings.create?this.settings.create:function(a){var b={};return b[d.settings.labelField]=a,b[d.settings.valueField]=a,b},h=C(function(a){if(d.unlock(),!a||"object"!=typeof a)return f();var b=z(a[d.settings.valueField]);return"string"!=typeof b?f():(d.setTextboxValue(""),d.addOption(a),d.setCaret(e),d.addItem(b),d.refreshOptions(c&&"single"!==d.settings.mode),void f(a))}),i=g.apply(this,[b,h]);return"undefined"!=typeof i&&h(i),!0},refreshItems:function(){this.lastQuery=null,this.isSetup&&this.addItem(this.items),this.refreshState(),this.updateOriginalInput()},refreshState:function(){this.refreshValidityState(),this.refreshClasses()},refreshValidityState:function(){if(!this.isRequired)return!1;var a=!this.items.length;this.isInvalid=a,this.$control_input.prop("required",a),this.$input.prop("required",!a)},refreshClasses:function(){var b=this,c=b.isFull(),d=b.isLocked;b.$wrapper.toggleClass("rtl",b.rtl),b.$control.toggleClass("focus",b.isFocused).toggleClass("disabled",b.isDisabled).toggleClass("required",b.isRequired).toggleClass("invalid",b.isInvalid).toggleClass("locked",d).toggleClass("full",c).toggleClass("not-full",!c).toggleClass("input-active",b.isFocused&&!b.isInputHidden).toggleClass("dropdown-active",b.isOpen).toggleClass("has-options",!a.isEmptyObject(b.options)).toggleClass("has-items",b.items.length>0),b.$control_input.data("grow",!c&&!d)},isFull:function(){return null!==this.settings.maxItems&&this.items.length>=this.settings.maxItems},updateOriginalInput:function(a){var b,c,d,e,f=this;if(a=a||{},f.tagType===v){for(d=[],b=0,c=f.items.length;b<c;b++)e=f.options[f.items[b]][f.settings.labelField]||"",d.push('<option value="'+A(f.items[b])+'" selected="selected">'+A(e)+"</option>");d.length||this.$input.attr("multiple")||d.push('<option value="" selected="selected"></option>'),
3
+ f.$input.html(d.join(""))}else f.$input.val(f.getValue()),f.$input.attr("value",f.$input.val());f.isSetup&&(a.silent||f.trigger("change",f.$input.val()))},updatePlaceholder:function(){if(this.settings.placeholder){var a=this.$control_input;this.items.length?a.removeAttr("placeholder"):a.attr("placeholder",this.settings.placeholder),a.triggerHandler("update",{force:!0})}},open:function(){var a=this;a.isLocked||a.isOpen||"multi"===a.settings.mode&&a.isFull()||(a.focus(),a.isOpen=!0,a.refreshState(),a.$dropdown.css({visibility:"hidden",display:"block"}),a.positionDropdown(),a.$dropdown.css({visibility:"visible"}),a.trigger("dropdown_open",a.$dropdown))},close:function(){var a=this,b=a.isOpen;"single"===a.settings.mode&&a.items.length&&(a.hideInput(),a.$control_input.blur()),a.isOpen=!1,a.$dropdown.hide(),a.setActiveOption(null),a.refreshState(),b&&a.trigger("dropdown_close",a.$dropdown)},positionDropdown:function(){var a=this.$control,b="body"===this.settings.dropdownParent?a.offset():a.position();b.top+=a.outerHeight(!0),this.$dropdown.css({width:a.outerWidth(),top:b.top,left:b.left})},clear:function(a){var b=this;b.items.length&&(b.$control.children(":not(input)").remove(),b.items=[],b.lastQuery=null,b.setCaret(0),b.setActiveItem(null),b.updatePlaceholder(),b.updateOriginalInput({silent:a}),b.refreshState(),b.showInput(),b.trigger("clear"))},insertAtCaret:function(b){var c=Math.min(this.caretPos,this.items.length);0===c?this.$control.prepend(b):a(this.$control[0].childNodes[c]).before(b),this.setCaret(c+1)},deleteSelection:function(b){var c,d,e,f,g,h,i,j,k,l=this;if(e=b&&b.keyCode===p?-1:1,f=G(l.$control_input[0]),l.$activeOption&&!l.settings.hideSelected&&(i=l.getAdjacentOption(l.$activeOption,-1).attr("data-value")),g=[],l.$activeItems.length){for(k=l.$control.children(".active:"+(e>0?"last":"first")),h=l.$control.children(":not(input)").index(k),e>0&&h++,c=0,d=l.$activeItems.length;c<d;c++)g.push(a(l.$activeItems[c]).attr("data-value"));b&&(b.preventDefault(),b.stopPropagation())}else(l.isFocused||"single"===l.settings.mode)&&l.items.length&&(e<0&&0===f.start&&0===f.length?g.push(l.items[l.caretPos-1]):e>0&&f.start===l.$control_input.val().length&&g.push(l.items[l.caretPos]));if(!g.length||"function"==typeof l.settings.onDelete&&l.settings.onDelete.apply(l,[g])===!1)return!1;for("undefined"!=typeof h&&l.setCaret(h);g.length;)l.removeItem(g.pop());return l.showInput(),l.positionDropdown(),l.refreshOptions(!0),i&&(j=l.getOption(i),j.length&&l.setActiveOption(j)),!0},advanceSelection:function(a,b){var c,d,e,f,g,h,i=this;0!==a&&(i.rtl&&(a*=-1),c=a>0?"last":"first",d=G(i.$control_input[0]),i.isFocused&&!i.isInputHidden?(f=i.$control_input.val().length,g=a<0?0===d.start&&0===d.length:d.start===f,g&&!f&&i.advanceCaret(a,b)):(h=i.$control.children(".active:"+c),h.length&&(e=i.$control.children(":not(input)").index(h),i.setActiveItem(null),i.setCaret(a>0?e+1:e))))},advanceCaret:function(a,b){var c,d,e=this;0!==a&&(c=a>0?"next":"prev",e.isShiftDown?(d=e.$control_input[c](),d.length&&(e.hideInput(),e.setActiveItem(d),b&&b.preventDefault())):e.setCaret(e.caretPos+a))},setCaret:function(b){var c=this;if(b="single"===c.settings.mode?c.items.length:Math.max(0,Math.min(c.items.length,b)),!c.isPending){var d,e,f,g;for(f=c.$control.children(":not(input)"),d=0,e=f.length;d<e;d++)g=a(f[d]).detach(),d<b?c.$control_input.before(g):c.$control.append(g)}c.caretPos=b},lock:function(){this.close(),this.isLocked=!0,this.refreshState()},unlock:function(){this.isLocked=!1,this.refreshState()},disable:function(){var a=this;a.$input.prop("disabled",!0),a.$control_input.prop("disabled",!0).prop("tabindex",-1),a.isDisabled=!0,a.lock()},enable:function(){var a=this;a.$input.prop("disabled",!1),a.$control_input.prop("disabled",!1).prop("tabindex",a.tabIndex),a.isDisabled=!1,a.unlock()},destroy:function(){var b=this,c=b.eventNS,d=b.revertSettings;b.trigger("destroy"),b.off(),b.$wrapper.remove(),b.$dropdown.remove(),b.$input.html("").append(d.$children).removeAttr("tabindex").removeClass("selectized").attr({tabindex:d.tabindex}).show(),b.$control_input.removeData("grow"),b.$input.removeData("selectize"),a(window).off(c),a(document).off(c),a(document.body).off(c),delete b.$input[0].selectize},render:function(b,c){var d,e,f="",g=!1,h=this;return"option"!==b&&"item"!==b||(d=z(c[h.settings.valueField]),g=!!d),g&&(y(h.renderCache[b])||(h.renderCache[b]={}),h.renderCache[b].hasOwnProperty(d))?h.renderCache[b][d]:(f=a(h.settings.render[b].apply(this,[c,A])),"option"===b||"option_create"===b?f.attr("data-selectable",""):"optgroup"===b&&(e=c[h.settings.optgroupValueField]||"",f.attr("data-group",e)),"option"!==b&&"item"!==b||f.attr("data-value",d||""),g&&(h.renderCache[b][d]=f[0]),f[0])},clearCache:function(a){var b=this;"undefined"==typeof a?b.renderCache={}:delete b.renderCache[a]},canCreate:function(a){var b=this;if(!b.settings.create)return!1;var c=b.settings.createFilter;return a.length&&("function"!=typeof c||c.apply(b,[a]))&&("string"!=typeof c||new RegExp(c).test(a))&&(!(c instanceof RegExp)||c.test(a))}}),M.count=0,M.defaults={options:[],optgroups:[],plugins:[],delimiter:",",splitOn:null,persist:!0,diacritics:!0,create:!1,createOnBlur:!1,createFilter:null,highlight:!0,openOnFocus:!0,maxOptions:1e3,maxItems:null,hideSelected:null,addPrecedence:!1,selectOnTab:!1,preload:!1,allowEmptyOption:!1,closeAfterSelect:!1,scrollDuration:60,loadThrottle:300,loadingClass:"loading",dataAttr:"data-data",optgroupField:"optgroup",valueField:"value",labelField:"text",optgroupLabelField:"label",optgroupValueField:"value",lockOptgroupOrder:!1,sortField:"$order",searchField:["text"],searchConjunction:"and",mode:null,wrapperClass:"selectize-control",inputClass:"selectize-input",dropdownClass:"selectize-dropdown",dropdownContentClass:"selectize-dropdown-content",dropdownParent:null,copyClassesToDropdown:!0,render:{}},a.fn.selectize=function(b){var c=a.fn.selectize.defaults,d=a.extend({},c,b),e=d.dataAttr,f=d.labelField,g=d.valueField,h=d.optgroupField,i=d.optgroupLabelField,j=d.optgroupValueField,k=function(b,c){var h,i,j,k,l=b.attr(e);if(l)for(c.options=JSON.parse(l),h=0,i=c.options.length;h<i;h++)c.items.push(c.options[h][g]);else{var m=a.trim(b.val()||"");if(!d.allowEmptyOption&&!m.length)return;for(j=m.split(d.delimiter),h=0,i=j.length;h<i;h++)k={},k[f]=j[h],k[g]=j[h],c.options.push(k);c.items=j}},l=function(b,c){var k,l,m,n,o=c.options,p={},q=function(a){var b=e&&a.attr(e);return"string"==typeof b&&b.length?JSON.parse(b):null},r=function(b,e){b=a(b);var i=z(b.val());if(i||d.allowEmptyOption)if(p.hasOwnProperty(i)){if(e){var j=p[i][h];j?a.isArray(j)?j.push(e):p[i][h]=[j,e]:p[i][h]=e}}else{var k=q(b)||{};k[f]=k[f]||b.text(),k[g]=k[g]||i,k[h]=k[h]||e,p[i]=k,o.push(k),b.is(":selected")&&c.items.push(i)}},s=function(b){var d,e,f,g,h;for(b=a(b),f=b.attr("label"),f&&(g=q(b)||{},g[i]=f,g[j]=f,c.optgroups.push(g)),h=a("option",b),d=0,e=h.length;d<e;d++)r(h[d],f)};for(c.maxItems=b.attr("multiple")?null:1,n=b.children(),k=0,l=n.length;k<l;k++)m=n[k].tagName.toLowerCase(),"optgroup"===m?s(n[k]):"option"===m&&r(n[k])};return this.each(function(){if(!this.selectize){var e,f=a(this),g=this.tagName.toLowerCase(),h=f.attr("placeholder")||f.attr("data-placeholder");h||d.allowEmptyOption||(h=f.children('option[value=""]').text());var i={placeholder:h,options:[],optgroups:[],items:[]};"select"===g?l(f,i):k(f,i),e=new M(f,a.extend(!0,{},c,i,b))}})},a.fn.selectize.defaults=M.defaults,a.fn.selectize.support={validity:x},M.define("drag_drop",function(b){if(!a.fn.sortable)throw new Error('The "drag_drop" plugin requires jQuery UI "sortable".');if("multi"===this.settings.mode){var c=this;c.lock=function(){var a=c.lock;return function(){var b=c.$control.data("sortable");return b&&b.disable(),a.apply(c,arguments)}}(),c.unlock=function(){var a=c.unlock;return function(){var b=c.$control.data("sortable");return b&&b.enable(),a.apply(c,arguments)}}(),c.setup=function(){var b=c.setup;return function(){b.apply(this,arguments);var d=c.$control.sortable({items:"[data-value]",forcePlaceholderSize:!0,disabled:c.isLocked,start:function(a,b){b.placeholder.css("width",b.helper.css("width")),d.css({overflow:"visible"})},stop:function(){d.css({overflow:"hidden"});var b=c.$activeItems?c.$activeItems.slice():null,e=[];d.children("[data-value]").each(function(){e.push(a(this).attr("data-value"))}),c.setValue(e),c.setActiveItem(b)}})}}()}}),M.define("dropdown_header",function(b){var c=this;b=a.extend({title:"Untitled",headerClass:"selectize-dropdown-header",titleRowClass:"selectize-dropdown-header-title",labelClass:"selectize-dropdown-header-label",closeClass:"selectize-dropdown-header-close",html:function(a){return'<div class="'+a.headerClass+'"><div class="'+a.titleRowClass+'"><span class="'+a.labelClass+'">'+a.title+'</span><a href="javascript:void(0)" class="'+a.closeClass+'">&times;</a></div></div>'}},b),c.setup=function(){var d=c.setup;return function(){d.apply(c,arguments),c.$dropdown_header=a(b.html(b)),c.$dropdown.prepend(c.$dropdown_header)}}()}),M.define("optgroup_columns",function(b){var c=this;b=a.extend({equalizeWidth:!0,equalizeHeight:!0},b),this.getAdjacentOption=function(b,c){var d=b.closest("[data-group]").find("[data-selectable]"),e=d.index(b)+c;return e>=0&&e<d.length?d.eq(e):a()},this.onKeyDown=function(){var a=c.onKeyDown;return function(b){var d,e,f,g;return!this.isOpen||b.keyCode!==j&&b.keyCode!==m?a.apply(this,arguments):(c.ignoreHover=!0,g=this.$activeOption.closest("[data-group]"),d=g.find("[data-selectable]").index(this.$activeOption),g=b.keyCode===j?g.prev("[data-group]"):g.next("[data-group]"),f=g.find("[data-selectable]"),e=f.eq(Math.min(f.length-1,d)),void(e.length&&this.setActiveOption(e)))}}();var d=function(){var a,b=d.width,c=document;return"undefined"==typeof b&&(a=c.createElement("div"),a.innerHTML='<div style="width:50px;height:50px;position:absolute;left:-50px;top:-50px;overflow:auto;"><div style="width:1px;height:100px;"></div></div>',a=a.firstChild,c.body.appendChild(a),b=d.width=a.offsetWidth-a.clientWidth,c.body.removeChild(a)),b},e=function(){var e,f,g,h,i,j,k;if(k=a("[data-group]",c.$dropdown_content),f=k.length,f&&c.$dropdown_content.width()){if(b.equalizeHeight){for(g=0,e=0;e<f;e++)g=Math.max(g,k.eq(e).height());k.css({height:g})}b.equalizeWidth&&(j=c.$dropdown_content.innerWidth()-d(),h=Math.round(j/f),k.css({width:h}),f>1&&(i=j-h*(f-1),k.eq(f-1).css({width:i})))}};(b.equalizeHeight||b.equalizeWidth)&&(B.after(this,"positionDropdown",e),B.after(this,"refreshOptions",e))}),M.define("remove_button",function(b){b=a.extend({label:"&times;",title:"Remove",className:"remove",append:!0},b);var c=function(b,c){c.className="remove-single";var d=b,e='<a href="javascript:void(0)" class="'+c.className+'" tabindex="-1" title="'+A(c.title)+'">'+c.label+"</a>",f=function(a,b){return a+b};b.setup=function(){var g=d.setup;return function(){if(c.append){var h=a(d.$input.context).attr("id"),i=(a("#"+h),d.settings.render.item);d.settings.render.item=function(a){return f(i.apply(b,arguments),e)}}g.apply(b,arguments),b.$control.on("click","."+c.className,function(a){a.preventDefault(),d.isLocked||d.clear()})}}()},d=function(b,c){var d=b,e='<a href="javascript:void(0)" class="'+c.className+'" tabindex="-1" title="'+A(c.title)+'">'+c.label+"</a>",f=function(a,b){var c=a.search(/(<\/[^>]+>\s*)$/);return a.substring(0,c)+b+a.substring(c)};b.setup=function(){var g=d.setup;return function(){if(c.append){var h=d.settings.render.item;d.settings.render.item=function(a){return f(h.apply(b,arguments),e)}}g.apply(b,arguments),b.$control.on("click","."+c.className,function(b){if(b.preventDefault(),!d.isLocked){var c=a(b.currentTarget).parent();d.setActiveItem(c),d.deleteSelection()&&d.setCaret(d.items.length)}})}}()};return"single"===this.settings.mode?void c(this,b):void d(this,b)}),M.define("restore_on_backspace",function(a){var b=this;a.text=a.text||function(a){return a[this.settings.labelField]},this.onKeyDown=function(){var c=b.onKeyDown;return function(b){var d,e;return b.keyCode===p&&""===this.$control_input.val()&&!this.$activeItems.length&&(d=this.caretPos-1,d>=0&&d<this.items.length)?(e=this.options[this.items[d]],this.deleteSelection(b)&&(this.setTextboxValue(a.text.apply(this,[e])),this.refreshOptions(!0)),void b.preventDefault()):c.apply(this,arguments)}}()}),M});
v4.0.0/assets/admin/js/wp-color-alpha.js ADDED
@@ -0,0 +1,416 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**!
2
+ * wp-color-picker-alpha
3
+ *
4
+ * Overwrite Automattic Iris for enabled Alpha Channel in wpColorPicker
5
+ * Only run in input and is defined data alpha in true
6
+ *
7
+ * Version: 2.1.4
8
+ * https://github.com/kallookoo/wp-color-picker-alpha
9
+ * Licensed under the GPLv2 license or later.
10
+ */
11
+ ( function( $ ) {
12
+ // Prevent double-init.
13
+ if ( $.wp.wpColorPicker.prototype._hasAlpha ) {
14
+ return;
15
+ }
16
+
17
+ // Variable for some backgrounds ( grid )
18
+ var image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAAHnlligAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHJJREFUeNpi+P///4EDBxiAGMgCCCAGFB5AADGCRBgYDh48CCRZIJS9vT2QBAggFBkmBiSAogxFBiCAoHogAKIKAlBUYTELAiAmEtABEECk20G6BOmuIl0CIMBQ/IEMkO0myiSSraaaBhZcbkUOs0HuBwDplz5uFJ3Z4gAAAABJRU5ErkJggg==',
19
+ //Dtml stuff for wpColorPicker copy of the original color-picker.js
20
+ _after = '<div class="wp-picker-holder" />',
21
+ _wrap = '<div class="wp-picker-container" />',
22
+ _before = '<button type="button" class="button wp-color-result" aria-expanded="false"></button>',
23
+ _wrappingLabel = '<label></label>',
24
+ _wrappingLabelText = '<span class="screen-reader-text"></span>';
25
+
26
+ /**
27
+ * Overwrite Color
28
+ * for enable support rbga
29
+ */
30
+ Color.fn.toString = function() {
31
+ if ( this._alpha < 1 )
32
+ return this.toCSS( 'rgba', this._alpha ).replace( /\s+/g, '' );
33
+
34
+ var hex = parseInt( this._color, 10 ).toString( 16 );
35
+
36
+ if ( this.error )
37
+ return '';
38
+
39
+ if ( hex.length < 6 )
40
+ hex = ( '00000' + hex ).substr( -6 );
41
+
42
+ return '#' + hex;
43
+ };
44
+
45
+ /**
46
+ * Overwrite wpColorPicker
47
+ */
48
+ $.widget( 'wp.wpColorPicker', $.wp.wpColorPicker, {
49
+ _hasAlpha: true,
50
+ /**
51
+ * @summary Creates the color picker.
52
+ *
53
+ * Creates the color picker, sets default values, css classes and wraps it all in HTML.
54
+ *
55
+ * @since 3.5.0
56
+ *
57
+ * @access private
58
+ *
59
+ * @returns {void}
60
+ */
61
+ _create: function() {
62
+ // Return early if Iris support is missing.
63
+ if ( ! $.support.iris ) {
64
+ return;
65
+ }
66
+
67
+ var self = this,
68
+ el = self.element;
69
+
70
+ // Override default options with options bound to the element.
71
+ $.extend( self.options, el.data() );
72
+
73
+ // Create a color picker which only allows adjustments to the hue.
74
+ if ( self.options.type === 'hue' ) {
75
+ return self._createHueOnly();
76
+ }
77
+
78
+ // Bind the close event.
79
+ self.close = $.proxy( self.close, self );
80
+
81
+ self.initialValue = el.val();
82
+
83
+ // Add a CSS class to the input field.
84
+ el.addClass( 'wp-color-picker' );
85
+
86
+
87
+ /*
88
+ * Check if there's already a wrapping label, e.g. in the Customizer.
89
+ * If there's no label, add a default one to match the Customizer template.
90
+ */
91
+ if ( ! el.parent( 'label' ).length ) {
92
+ // Wrap the input field in the default label.
93
+ el.wrap( _wrappingLabel );
94
+ // Insert the default label text.
95
+ self.wrappingLabelText = $( _wrappingLabelText )
96
+ .insertBefore( el )
97
+ .text('Color Picker' );
98
+ }
99
+
100
+ /*
101
+ * At this point, either it's the standalone version or the Customizer
102
+ * one, we have a wrapping label to use as hook in the DOM, let's store it.
103
+ */
104
+ self.wrappingLabel = el.parent();
105
+
106
+ // Wrap the label in the main wrapper.
107
+ self.wrappingLabel.wrap( _wrap );
108
+ // Store a reference to the main wrapper.
109
+ self.wrap = self.wrappingLabel.parent();
110
+ // Set up the toggle button and insert it before the wrapping label.
111
+ self.toggler = $( _before )
112
+ .insertBefore( self.wrappingLabel )
113
+ .css( { backgroundColor: self.initialValue } );
114
+ // Set up the Iris container and insert it after the wrapping label.
115
+ self.pickerContainer = $( _after ).insertAfter( self.wrappingLabel );
116
+
117
+ // Wrap the wrapping label in its wrapper and append the Clear/Default button.
118
+ self.wrappingLabel
119
+ .wrap( '<span class="wp-picker-input-wrap hidden rmp-color-input-wrap" />' );
120
+
121
+
122
+ /*
123
+ * The input wrapper now contains the label+input+Clear/Default button.
124
+ * Store a reference to the input wrapper: we'll use this to toggle
125
+ * the controls visibility.
126
+ */
127
+ self.inputWrapper = el.closest( '.wp-picker-input-wrap' );
128
+
129
+
130
+ el.iris( {
131
+ target: self.pickerContainer,
132
+ hide: self.options.hide,
133
+ width: 240,
134
+ mode: self.options.mode,
135
+ palettes: self.options.palettes,
136
+ /**
137
+ * @summary Handles the onChange event if one has been defined in the options.
138
+ *
139
+ * Handles the onChange event if one has been defined in the options and additionally
140
+ * sets the background color for the toggler element.
141
+ *
142
+ * @since 3.5.0
143
+ *
144
+ * @param {Event} event The event that's being called.
145
+ * @param {HTMLElement} ui The HTMLElement containing the color picker.
146
+ *
147
+ * @returns {void}
148
+ */
149
+ change: function( event, ui ) {
150
+ if ( self.options.alpha ) {
151
+ self.toggler.css( { 'background-image' : 'url(' + image + ')' } );
152
+
153
+ self.toggler.css( {
154
+ 'position' : 'relative'
155
+ } );
156
+ if ( self.toggler.find('span.color-alpha').length == 0 ) {
157
+ self.toggler.append('<span class="color-alpha" />');
158
+ }
159
+
160
+ self.toggler.find( 'span.color-alpha' ).css( {
161
+ 'width' : '38px',
162
+ 'height' : '100%',
163
+ 'position' : 'absolute',
164
+ 'top' : 0,
165
+ 'left' : 0,
166
+ 'background' : ui.color.toString()
167
+ } );
168
+ } else {
169
+ self.toggler.css( { backgroundColor : ui.color.toString() } );
170
+ }
171
+
172
+ if ( $.isFunction( self.options.change ) ) {
173
+ self.options.change.call( this, event, ui );
174
+ }
175
+ }
176
+ } );
177
+
178
+ el.val( self.initialValue );
179
+ self._addListeners();
180
+
181
+ // Force the color picker to always be closed on initial load.
182
+ if ( ! self.options.hide ) {
183
+ self.toggler.click();
184
+ }
185
+ },
186
+ /**
187
+ * @summary Binds event listeners to the color picker.
188
+ *
189
+ * @since 3.5.0
190
+ *
191
+ * @access private
192
+ *
193
+ * @returns {void}
194
+ */
195
+ _addListeners: function() {
196
+ var self = this;
197
+
198
+ /**
199
+ * @summary Prevent any clicks inside this widget from leaking to the top and closing it.
200
+ *
201
+ * @since 3.5.0
202
+ *
203
+ * @param {Event} event The event that's being called.
204
+ *
205
+ * @returs {void}
206
+ */
207
+ self.wrap.on( 'click.wpcolorpicker', function( event ) {
208
+ event.stopPropagation();
209
+ });
210
+
211
+ /**
212
+ * @summary Open or close the color picker depending on the class.
213
+ *
214
+ * @since 3.5
215
+ */
216
+ self.toggler.click( function() {
217
+ if ( self.toggler.hasClass( 'wp-picker-open' ) ) {
218
+ self.close();
219
+ } else {
220
+ self.open();
221
+ }
222
+ } );
223
+
224
+ /**
225
+ * @summary Checks if value is empty when changing the color in the color picker.
226
+ *
227
+ * Checks if value is empty when changing the color in the color picker.
228
+ * If so, the background color is cleared.
229
+ *
230
+ * @since 3.5.0
231
+ *
232
+ * @param {Event} event The event that's being called.
233
+ *
234
+ * @returns {void}
235
+ */
236
+ self.element.on( 'change', function( event ) {
237
+ // Empty or Error = clear
238
+ if ( $( this ).val() === '' || self.element.hasClass( 'iris-error' ) ) {
239
+ if ( self.options.alpha ) {
240
+ self.toggler.find( 'span.color-alpha' ).css( 'backgroundColor', '' );
241
+ } else {
242
+ self.toggler.css( 'backgroundColor', '' );
243
+ }
244
+
245
+ // fire clear callback if we have one
246
+ if ( $.isFunction( self.options.clear ) )
247
+ self.options.clear.call( this, event );
248
+ }
249
+ } );
250
+
251
+ },
252
+ });
253
+
254
+ /**
255
+ * Overwrite iris
256
+ */
257
+ $.widget( 'a8c.iris', $.a8c.iris, {
258
+ _create: function() {
259
+ this._super();
260
+
261
+ // Global option for check is mode rbga is enabled
262
+ this.options.alpha = this.element.data( 'alpha' ) || false;
263
+
264
+ // Is not input disabled
265
+ if ( ! this.element.is( ':input' ) )
266
+ this.options.alpha = false;
267
+
268
+ if ( typeof this.options.alpha !== 'undefined' && this.options.alpha ) {
269
+ var self = this,
270
+ el = self.element,
271
+ _html = '<div class="iris-strip iris-slider iris-alpha-slider"><div class="iris-slider-offset iris-slider-offset-alpha"></div></div>',
272
+ aContainer = $( _html ).appendTo( self.picker.find( '.iris-picker-inner' ) ),
273
+ aSlider = aContainer.find( '.iris-slider-offset-alpha' ),
274
+ controls = {
275
+ aContainer : aContainer,
276
+ aSlider : aSlider
277
+ };
278
+
279
+ if ( typeof el.data( 'custom-width' ) !== 'undefined' ) {
280
+ self.options.customWidth = parseInt( el.data( 'custom-width' ) ) || 0;
281
+ } else {
282
+ self.options.customWidth = 100;
283
+ }
284
+
285
+ // Set default width for input reset
286
+ self.options.defaultWidth = el.width();
287
+
288
+ // Update width for input
289
+ if ( self._color._alpha < 1 || self._color.toString().indexOf('rgb') != -1 )
290
+ el.width( parseInt( self.options.defaultWidth + self.options.customWidth ) );
291
+
292
+ // Push new controls
293
+ $.each( controls, function( k, v ) {
294
+ self.controls[k] = v;
295
+ } );
296
+
297
+ // Change size strip and add margin for sliders
298
+ self.controls.square.css( { 'margin-right': '0' } );
299
+ var emptyWidth = ( self.picker.width() - self.controls.square.width() - 20 ),
300
+ stripsMargin = ( emptyWidth / 6 ),
301
+ stripsWidth = ( ( emptyWidth / 2 ) - stripsMargin );
302
+
303
+ $.each( [ 'aContainer', 'strip' ], function( k, v ) {
304
+ self.controls[v].width( stripsWidth ).css( { 'margin-left' : stripsMargin + 'px' } );
305
+ } );
306
+
307
+ // Add new slider
308
+ self._initControls();
309
+
310
+ // For updated widget
311
+ self._change();
312
+ }
313
+ },
314
+ _initControls: function() {
315
+ this._super();
316
+
317
+ if ( this.options.alpha ) {
318
+ var self = this,
319
+ controls = self.controls;
320
+
321
+ controls.aSlider.slider({
322
+ orientation : 'vertical',
323
+ min : 0,
324
+ max : 100,
325
+ step : 1,
326
+ value : parseInt( self._color._alpha * 100 ),
327
+ slide : function( event, ui ) {
328
+ // Update alpha value
329
+ self._color._alpha = parseFloat( ui.value / 100 );
330
+ self._change.apply( self, arguments );
331
+ }
332
+ });
333
+ }
334
+ },
335
+ _change: function() {
336
+ this._super();
337
+
338
+ var self = this,
339
+ el = self.element;
340
+
341
+ if ( this.options.alpha ) {
342
+ var controls = self.controls,
343
+ alpha = parseInt( self._color._alpha * 100 ),
344
+ color = self._color.toRgb(),
345
+ gradient = [
346
+ 'rgb(' + color.r + ',' + color.g + ',' + color.b + ') 0%',
347
+ 'rgba(' + color.r + ',' + color.g + ',' + color.b + ', 0) 100%'
348
+ ],
349
+ defaultWidth = self.options.defaultWidth,
350
+ customWidth = self.options.customWidth,
351
+ target = self.picker.closest( '.wp-picker-container' ).find( '.wp-color-result' );
352
+
353
+ // Generate background slider alpha, only for CSS3 old browser fuck!! :)
354
+ controls.aContainer.css( { 'background' : 'linear-gradient(to bottom, ' + gradient.join( ', ' ) + '), url(' + image + ')' } );
355
+
356
+ if ( target.hasClass( 'wp-picker-open' ) ) {
357
+ // Update alpha value
358
+ controls.aSlider.slider( 'value', alpha );
359
+
360
+ /**
361
+ * Disabled change opacity in default slider Saturation ( only is alpha enabled )
362
+ * and change input width for view all value
363
+ */
364
+ // if ( self._color._alpha < 1 ) {
365
+ // controls.strip.attr( 'style', controls.strip.attr( 'style' ).replace( /rgba\(([0-9]+,)(\s+)?([0-9]+,)(\s+)?([0-9]+)(,(\s+)?[0-9\.]+)\)/g, 'rgb($1$3$5)' ) );
366
+ // el.width( parseInt( defaultWidth + customWidth ) );
367
+ // } else {
368
+ // el.width( defaultWidth );
369
+ // }
370
+ }
371
+ }
372
+
373
+ var reset = el.data( 'reset-alpha' ) || false;
374
+
375
+ if ( reset ) {
376
+ self.picker.find( '.iris-palette-container' ).on( 'click.palette', '.iris-palette', function() {
377
+ self._color._alpha = 1;
378
+ self.active = 'external';
379
+ self._change();
380
+ } );
381
+ }
382
+ el.trigger( 'change' );
383
+ },
384
+ _addInputListeners: function( input ) {
385
+ var self = this,
386
+ debounceTimeout = 100,
387
+ callback = function( event ) {
388
+ var color = new Color( input.val() ),
389
+ val = input.val();
390
+
391
+ input.removeClass( 'iris-error' );
392
+ // we gave a bad color
393
+ if ( color.error ) {
394
+ // don't error on an empty input
395
+ if ( val !== '' )
396
+ input.addClass( 'iris-error' );
397
+ } else {
398
+ if ( color.toString() !== self._color.toString() ) {
399
+ // let's not do this on keyup for hex shortcodes
400
+ if ( ! ( event.type === 'keyup' && val.match( /^[0-9a-fA-F]{3}$/ ) ) )
401
+ self._setOption( 'color', color.toString() );
402
+ }
403
+ }
404
+ };
405
+
406
+ input.on( 'change', callback ).on( 'keyup', self._debounce( callback, debounceTimeout ) );
407
+
408
+ // If we initialized hidden, show on first focus. The rest is up to you.
409
+ if ( self.options.hide ) {
410
+ input.on( 'focus', function() {
411
+ self.show();
412
+ } );
413
+ }
414
+ }
415
+ } );
416
+ }( jQuery ) );
v4.0.0/assets/admin/scss/admin.css ADDED
@@ -0,0 +1,2622 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ /* Admin scss file */
3
+
4
+ body,
5
+ h1,
6
+ h2,
7
+ h3,
8
+ h4,
9
+ h4,
10
+ h6,
11
+ p,
12
+ ul,
13
+ ol,
14
+ label{
15
+ padding: 0;
16
+ margin: 0;
17
+ }
18
+
19
+ ul,
20
+ ol,
21
+ ul li,
22
+ ol li{
23
+ margin: 0;
24
+ padding: 0;
25
+ list-style-type: none;
26
+ }
27
+
28
+ @font-face {
29
+ font-family: 'Product Sans';
30
+ src: url("../fonts/product-sans/Product\ Sans\ Regular.ttf") format( 'truetype' );
31
+ font-display: fallback;
32
+ }
33
+
34
+ @font-face {
35
+ font-family: 'Product Sans Bold';
36
+ src: url("../fonts/product-sans/Product\ Sans\ Bold.ttf") format( 'truetype' );
37
+ font-display: fallback;
38
+ }
39
+
40
+ @font-face {
41
+ font-family: "Product Sans Medium";
42
+ src: url("../fonts/product-sans/Product\ Sans\ Medium.ttf") format( 'truetype' );
43
+ font-display: fallback;
44
+ }
45
+
46
+ .rmp-editor-overlay a{
47
+ text-decoration: none;
48
+ }
49
+
50
+ .rmp-editor-active input[type="text"],
51
+ .rmp-editor-active input[type="password"],
52
+ .rmp-editor-active input[type="email"],
53
+ .rmp-editor-active input[type="url"],
54
+ .rmp-editor-active input[type="date"],
55
+ .rmp-editor-active input[type="month"],
56
+ .rmp-editor-active input[type="time"],
57
+ .rmp-editor-active input[type="datetime"],
58
+ .rmp-editor-active input[type="datetime-local"],
59
+ .rmp-editor-active input[type="week"],
60
+ .rmp-editor-active input[type="number"],
61
+ .rmp-editor-active input[type="search"],
62
+ .rmp-editor-active input[type="tel"],
63
+ .rmp-editor-active input[type="color"],
64
+ .rmp-editor-active textarea {
65
+ -webkit-appearance: none;
66
+ -moz-appearance: none;
67
+ background: #fff;
68
+ border-radius: 0;
69
+ border-style: solid;
70
+ border-width: 0.1rem;
71
+ box-shadow: none;
72
+ font-size: 14px;
73
+ letter-spacing: -0.015em;
74
+ margin: 0;
75
+ max-width: 100%;
76
+ padding: 0.25rem 0.5rem;
77
+ width: 100%;
78
+ }
79
+
80
+ #rmp-required-footer{
81
+ display: none;
82
+ }
83
+
84
+ .rmp-editor-overlay input[type="text"],
85
+ .rmp-editor-overlay input[type="password"],
86
+ .rmp-editor-overlay input[type="color"]{
87
+ height: 30px;
88
+ padding: 0 5px;
89
+ border: solid 1px #ddd;
90
+ max-width: 120px;
91
+ font-size: 12px;
92
+ }
93
+
94
+ #rmp-editor-wrapper input[type="checkbox"]:disabled,
95
+ #rmp-editor-wrapper input[type="checkbox"].disabled,
96
+ #rmp-editor-wrapper input[type="radio"]:disabled,
97
+ #rmp-editor-wrapper input[type="radio"].disabled,
98
+ #rmp-editor-wrapper input[type="checkbox"]:disabled:checked:before,
99
+ #rmp-editor-wrapper input[type="checkbox"].disabled:checked:before,
100
+ #rmp-editor-wrapper input[type="radio"]:disabled:checked:before,
101
+ #rmp-editor-wrapper input[type="radio"].disabled:checked:before {
102
+ opacity: 0.5;
103
+ }
104
+
105
+ input[type="text"]:focus,
106
+ input[type="password"]:focus,
107
+ input[type="color"]:focus,
108
+ input[type="date"]:focus,
109
+ input[type="datetime"]:focus,
110
+ input[type="datetime-local"]:focus,
111
+ input[type="email"]:focus, input[type="month"]:focus, input[type="number"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="time"]:focus, input[type="url"]:focus, input[type="week"]:focus, input[type="checkbox"]:focus, input[type="radio"]:focus, select:focus, textarea:focus {
112
+ border-color: #0085ba;
113
+ box-shadow: 0 0 0 1px #0085ba;
114
+
115
+ }
116
+
117
+ .rmp-editor-active input[type="checkbox"], input[type="radio"] {
118
+ height: 16px;
119
+ width: 16px;
120
+ min-width: 16px;
121
+ margin-right: 5px;
122
+ border: solid 1px #d5dadf;
123
+ }
124
+
125
+ .rmp-editor-active input[type="radio"]:checked{
126
+ border: solid 1px #0085ba;
127
+ }
128
+
129
+ .rmp-editor-active input[type="radio"]:checked::before {
130
+ content: "";
131
+ border-radius: 50%;
132
+ width: 8px;
133
+ height: 8px;
134
+ margin: 3px;
135
+ background-color: #0085ba;
136
+ line-height: 1.14285714;
137
+ }
138
+
139
+ .rmp-editor-active input[type="checkbox"]:checked::before {
140
+ content: url(data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.83%204.89l1.34.94-5.81%208.38H9.02L5.78%209.67l1.34-1.25%202.57%202.4z%27%20fill%3D%27%23000000%27%2F%3E%3C%2Fsvg%3E);
141
+ position: absolute;
142
+ display: inline-block;
143
+ margin: -1px 0 0 -8px;
144
+ height: 16px;
145
+ width: 16px;
146
+ }
147
+
148
+
149
+ .rmp-admin-page {
150
+ color:#000;
151
+ width: auto;
152
+ }
153
+
154
+ .rmp-row {
155
+ display: flex;
156
+ }
157
+
158
+ .rmp-row .col-1 {width: 8.33%;}
159
+ .rmp-row .col-2 {width: 16.66%;}
160
+ .rmp-row .col-3 {width: 25%;}
161
+ .rmp-row .col-4 {width: 33.33%;}
162
+ .rmp-row .col-5 {width: 41.66%;}
163
+ .rmp-row .col-6 {width: 50%;}
164
+ .rmp-row .col-7 {width: 58.33%;}
165
+ .rmp-row .col-8 {width: 66.66%;}
166
+ .rmp-row .col-9 {width: 75%;}
167
+ .rmp-row .col-10 {width: 83.33%;}
168
+ .rmp-row .col-11 {width: 91.66%;}
169
+ .rmp-row .col-12 {width: 100%;}
170
+ .rmp-row .col {width: auto;}
171
+
172
+ .rmp-menu-setting-box,
173
+ .rmp-global-setting-box,
174
+ .rmp-preview-setting-box {
175
+ border:solid 1px #ddd;
176
+ background: #fff;
177
+ margin-bottom: 30px;
178
+ height: max-content;
179
+ position: relative;
180
+ }
181
+
182
+ #iframe-spinner {
183
+ position: absolute;
184
+ width: 100%;
185
+ height: 100%;
186
+ top: 0;
187
+ left: 0;
188
+ display: none;
189
+ z-index: 99999999;
190
+ background: rgba(255,255,255,0.9);
191
+ }
192
+
193
+ /* Medium devices (tablets, 768px and up) */
194
+ @media only screen and ( max-width: 782px ) {
195
+ .rmp-row {
196
+ flex-direction: column;
197
+ }
198
+
199
+ .rmp-row .col-sm-1 {width: 8.33%;}
200
+ .rmp-row .col-sm-2 {width: 16.66%;}
201
+ .rmp-row .col-sm-3 {width: 25%;}
202
+ .rmp-row .col-sm-4 {width: 33.33%;}
203
+ .rmp-row .col-sm-5 {width: 41.66%;}
204
+ .rmp-row .col-sm-6 {width: 50%;}
205
+ .rmp-row .col-sm-7 {width: 58.33%;}
206
+ .rmp-row .col-sm-8 {width: 66.66%;}
207
+ .rmp-row .col-sm-9 {width: 75%;}
208
+ .rmp-row .col-sm-10 {width: 83.33%;}
209
+ .rmp-row .col-sm-11 {width: 91.66%;}
210
+ .rmp-row .col-sm-12 {width: 100%;}
211
+ .rmp-row .col {width: auto;}
212
+
213
+ #rmp-tablet-preview,
214
+ #rmp-desktop-preview,
215
+ .rmp-preview-size {
216
+ display: none;
217
+ }
218
+
219
+ }
220
+
221
+ .rmp-preview-size {
222
+ display: none;
223
+ }
224
+
225
+ /* Large devices (desktops, 992px and up) */
226
+ @media only screen and ( max-width: 960px ) {
227
+
228
+ }
229
+
230
+ /* Extra large devices (large desktops, 1200px and up) */
231
+ @media only screen and ( max-width: 1140px ) {
232
+
233
+ }
234
+
235
+ .rmp-box-header {
236
+ background: #f5f6fa;
237
+ padding: 10px;
238
+ color:#2d405a;
239
+ border-bottom:solid 2px #ddd;
240
+ }
241
+
242
+ .rmp-menu-setting-box {
243
+ margin-right: 20px;
244
+ }
245
+
246
+ .rmp-preview-setting-box .rmp-box-header {
247
+ padding: 16px 10px;
248
+ }
249
+
250
+ .rmp-preview-setting-box .button {
251
+ line-height: unset;
252
+ }
253
+
254
+ .rmp-global-setting-options {
255
+ flex-direction: column;
256
+ }
257
+
258
+
259
+ .active {
260
+ display: block !important;
261
+ }
262
+
263
+ .tab-contents {
264
+ display: none;
265
+ padding: 20px;
266
+ }
267
+
268
+ .rmp-accordions .rmp-accordion-container input[type="checkbox"],
269
+ .rmp-accordions .rmp-accordion-container input[type="checkbox"]:checked::before{
270
+ -webkit-appearance: none;
271
+ -moz-appearance: none;
272
+ appearance: none;
273
+ -webkit-tap-highlight-color: transparent;
274
+ cursor: pointer;
275
+ }
276
+
277
+
278
+ .rmp-accordions .rmp-accordion-container .toggle {
279
+ height: 20px;
280
+ width: 36px;
281
+ border-radius: 25px;
282
+ display: inline-block;
283
+ position: relative;
284
+ margin: 0;
285
+ background: #99A6B9;
286
+ border: solid 1px #99A6B9;
287
+ /* -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.12), inset 0 0 2px rgba(0, 0, 0, 0.15); */
288
+ /* box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.12), inset 0 0 2px rgba(0, 0, 0, 0.15); */
289
+ /* -webkit-transition: 0.15s ease-out; */
290
+ -o-transition: 0.15s ease-out;
291
+ transition: 0.15s ease-out;
292
+ }
293
+
294
+
295
+ .rmp-accordions .rmp-accordion-container .toggle:after {
296
+ content: '';
297
+ position: absolute;
298
+ top: 1px;
299
+ left: 2px;
300
+ width: 16px;
301
+ height: 16px;
302
+ border-radius: 50%;
303
+ background: #ffffff;
304
+ transition: all .2s cubic-bezier(0.5,0.1,0.75,1.35);
305
+ }
306
+
307
+ .rmp-accordions .rmp-accordion-container .toggle:checked{
308
+ background:#36BEF7;
309
+ border: solid 1px #36BEF7;
310
+ }
311
+
312
+ .rmp-accordions .rmp-accordion-container .toggle:checked::before {
313
+ content: '';
314
+ position: absolute;
315
+ }
316
+
317
+ .rmp-accordions .rmp-accordion-container .toggle:checked::after{
318
+ transform: translateX(14px);
319
+ }
320
+
321
+
322
+ /* Text align icons */
323
+
324
+ .align-icons-group {
325
+ width: max-content;
326
+ overflow: hidden;
327
+ background: #FFFFFF;
328
+ border: 1px solid #E7EFF0;
329
+ box-sizing: border-box;
330
+ border-radius: 4px;
331
+ display: flex;
332
+ }
333
+
334
+ .align-icons-group input[type="radio"] {
335
+ -webkit-appearance: none;
336
+ -moz-appearance: none;
337
+ appearance: none;
338
+ visibility: hidden;
339
+ display: none;
340
+ }
341
+
342
+ .align-icons-group input[type="radio"]:focus{
343
+ outline: none;
344
+ border-color:unset;
345
+ box-shadow:unset;
346
+ }
347
+
348
+ .align-icons-group label {
349
+ background: #ffffff;
350
+ padding: 0px 7px;
351
+ color: #99A6B9;
352
+ height: 36px;
353
+ display: inline-flex;
354
+ align-items: center;
355
+ }
356
+
357
+ .align-icons-group input[type="radio"]:checked + label {
358
+ background: #e7eff0;
359
+ color: #56606D;
360
+ }
361
+
362
+
363
+
364
+ .rmp-theme-setting-options {
365
+ overflow-y: scroll;
366
+ max-height: 600px;
367
+ }
368
+
369
+ .rmp-preview-iframe-container {
370
+ background: #191e23;
371
+ text-align: center;
372
+ }
373
+
374
+
375
+
376
+ .rmp-global-setting-options{
377
+ padding: 20px;
378
+ }
379
+
380
+ /** Scrolling bar in menu setting box **/
381
+ * ::-webkit-scrollbar {
382
+ width: 4px;
383
+ }
384
+
385
+ * ::-webkit-scrollbar-track {
386
+ box-shadow: inset 0 0 5px transparent;
387
+ }
388
+
389
+ * ::-webkit-scrollbar-thumb {
390
+ background: #d5dadf;
391
+ }
392
+
393
+ * ::-webkit-scrollbar-thumb:hover {
394
+ background: #2d405a;
395
+ }
396
+
397
+ .rmp-menu-tab-container .nav-tab-wrapper,
398
+ .rmp-accordion-container .nav-tab-wrapper{
399
+ padding: 0;
400
+ border-bottom: unset;
401
+ margin: 5% auto;
402
+ background: #2D405A;
403
+ border-radius: 25px;
404
+ width: max-content;
405
+ display: flex;
406
+ }
407
+
408
+
409
+ .rmp-accordion-container .rmp-tab-items .nav-tab,
410
+ .rmp-accordion-container .nav-tab-wrapper .nav-tab {
411
+ max-width: calc(100% / 2);
412
+ text-align: center;
413
+ border: unset;
414
+ font-size: 12px;
415
+ background: transparent;
416
+ border-radius: 26px;
417
+ color: #fff;
418
+ padding: 0.5rem 2rem;
419
+ width: max-content;
420
+ margin: 0 -1px;
421
+ }
422
+
423
+ /* #title-contents{
424
+ border:1px solid #ccc;
425
+ } */
426
+
427
+ .rmp-dialog-overlay .nav-tab-active,
428
+ .rmp-menu-tab-container .nav-tab-wrapper .nav-tab-active,
429
+ .rmp-accordion-container .nav-tab-wrapper .nav-tab-active,
430
+ .rmp-accordion-container .nav-tab-wrapper .ui-tabs-active .nav-tab {
431
+ background: #36BEF7;
432
+ color: #fff;
433
+ transition: all 300ms;
434
+ }
435
+
436
+ .rmp-menu-tab-container {
437
+ border-left: solid 1px #ddd;
438
+ border-right: solid 1px #ddd;
439
+ border-bottom: solid 1px #ddd;
440
+ }
441
+
442
+ .rmp-menu-tab-container .rmp-menu-tab-contents{
443
+ padding: 20px;
444
+ }
445
+
446
+
447
+
448
+ /* New Menu create dialog */
449
+ @media only screen and (min-width: 1140px) {
450
+ .rmp-dialog-overlay .rmp-dialog-wrap {
451
+ width: 1140px;
452
+ margin: 0 auto;
453
+ }
454
+ }
455
+
456
+ .rmp-dialog-overlay .rmp-dialog-backdrop {
457
+ position: fixed;
458
+ left: -20px;
459
+ right: 0;
460
+ top: 0;
461
+ bottom: 0;
462
+ background: #f5f6fa;
463
+ background: #0d133d82;
464
+ z-index: 999999;
465
+ }
466
+
467
+ .rmp-dialog-overlay .rmp-dialog-wrap {
468
+ clear: both;
469
+ position: absolute;
470
+ top: 10%;
471
+ left: 0;
472
+ right: 0;
473
+ bottom: 3%;
474
+ background: #fff;
475
+ box-shadow: 0 1px 20px 5px rgba(0, 0, 0, 0.1);
476
+ z-index: 999999;
477
+ box-sizing: border-box;
478
+ -webkit-overflow-scrolling: touch;
479
+ height: fit-content;
480
+ font-family: 'Product Sans';
481
+ }
482
+
483
+ .rmp-dialog-overlay .rmp-dialog-header {
484
+ height: 64px;
485
+ border-bottom: 1px solid #ddd;
486
+ color: #2d405a;
487
+ background: #f5f6fa;
488
+ overflow: hidden;
489
+ font-family: 'Product Sans';
490
+ font-size: 14px;
491
+ }
492
+
493
+ .rmp-dialog-overlay .rmp-dialog-header .close {
494
+ cursor: pointer;
495
+ font-size: 30px;
496
+ width: 64px;
497
+ color: #2d405a;
498
+ height: 64px;
499
+ text-align: center;
500
+ float: right;
501
+ border: 0;
502
+ border-left: 1px solid #ddd;
503
+ background-color: transparent;
504
+ transition: color .1s ease-in-out;
505
+ padding: 15px 0;
506
+ }
507
+
508
+ .rmp-dialog-overlay .rmp-dialog-footer {
509
+ position: relative;
510
+ text-align: right;
511
+ bottom: 0;
512
+ left: 0;
513
+ right: 0;
514
+ padding: 1rem;
515
+ box-sizing: border-box;
516
+ border-top: 1px solid #eee;
517
+ }
518
+
519
+ .rmp-dialog-overlay .rmp-dialog-header .title {
520
+ font-size: 18px;
521
+ float: left;
522
+ height: 64px;
523
+ display: flex;
524
+ align-items: center;
525
+ padding: 0 20px;
526
+ text-transform: capitalize;
527
+ font-family: 'Product Sans Medium';
528
+ font-weight: normal;
529
+ }
530
+
531
+
532
+
533
+ .rmp-dialog-overlay .rmp-dialog-contents {
534
+ display: flex;
535
+ }
536
+
537
+ /* Icons dialog */
538
+
539
+ .rmp-menu-icons-dialog .icon-tabs {
540
+ display: flex;
541
+ }
542
+
543
+ .rmp-menu-icons-dialog .nav-tab-wrapper {
544
+ border: unset;
545
+ height: 100%;
546
+ border-right: 1px solid #ddd;
547
+ background: #fff;
548
+ }
549
+
550
+ .rmp-menu-icons-dialog .icon-tabs .nav-tab {
551
+ margin: 0;
552
+ width: -webkit-fill-available;
553
+ padding: 8px 15px;
554
+ font-size: 12px;
555
+ border: unset;
556
+ min-width: 220px;
557
+ font-weight: normal;
558
+ background: #fff;
559
+ color: #333;
560
+ font-family: 'Product Sans Medium';
561
+ }
562
+
563
+ .rmp-icon-tab-contents {
564
+ padding: 0;
565
+ width: 100%;
566
+ max-height: 520px;
567
+ min-height: 480px;
568
+ overflow-y: scroll;
569
+ }
570
+
571
+ .rmp-icon-tab-contents .font-icon {
572
+ float: left;
573
+ padding: 0 20px 20px 0;
574
+ width: 24px;
575
+ height: 24px;
576
+ box-sizing: initial;
577
+ }
578
+
579
+ .rmp-icon-tab-contents .font-icon label:before {
580
+ width: 24px;
581
+ height: 24px;
582
+ display: inline-block;
583
+ content: attr(rel);
584
+ border: 1px solid #e5e5e5;
585
+ padding: 6px;
586
+ background: #f5f6fa;
587
+ color: #768392;
588
+ position: relative;
589
+ cursor: pointer;
590
+ font-family: dashicons;
591
+ font-weight: 400;
592
+ font-size: 24px;
593
+ line-height: 1;
594
+ }
595
+
596
+ .rmp-icon-tab-contents .dash label:before {
597
+ font-family: dashicons;
598
+ }
599
+
600
+ .rmp-icon-tab-contents .font-icon input.radio:empty {
601
+ visibility: hidden;
602
+ }
603
+
604
+ .rmp-icon-tab-contents .font-icon input.radio:checked ~ label:before {
605
+ border: 1px solid #36BEF7;
606
+ color: #fff;
607
+ background: #36BEF7;
608
+ }
609
+
610
+ #rmp-icon-search{
611
+ max-width: 300px;
612
+ padding: 0 5px;
613
+ font-size: 12px;
614
+ display: inline;
615
+ min-height: 35px;
616
+ border: solid 1px #ddd;
617
+ }
618
+
619
+ #rmp-icon-search-typing-message {
620
+ margin: 0 10px;
621
+ font-size: 14px;
622
+ color: #007cba;
623
+ }
624
+
625
+ @media only screen and (max-width: 780px) {
626
+ .rmp-dialog-overlay .rmp-dialog-wrap, .rmp-dialog-overlay .rmp-dialog-wrap {
627
+ top: 0;
628
+ right: 0;
629
+ bottom: 0;
630
+ left: 0;
631
+ border: none;
632
+ z-index: 999999;
633
+ position: absolute;
634
+ }
635
+
636
+ #rmp-new-menu-wizard .new_menu_tab_items{
637
+ width: auto;
638
+ border:unset;
639
+ }
640
+
641
+ .rmp-dialog-contents .rmp-new-menu-elements{
642
+ padding: 0;
643
+ }
644
+
645
+ .rmp-dialog-overlay .rmp-dialog-contents {
646
+ flex-direction: column;
647
+ }
648
+
649
+ .rmp-dialog-overlay .rmp-dialog-contents .rmp-new-menu-themes {
650
+ width: 100%;
651
+ border-right:unset;
652
+ margin-bottom: 10px;
653
+ }
654
+
655
+ .rmp-dialog-overlay .rmp-dialog-contents .rmp-new-menu-elements {
656
+ width: auto;
657
+ }
658
+
659
+ .rmp-menu-icons-dialog .icon-tabs {
660
+ flex-direction: column;
661
+ }
662
+ }
663
+
664
+ .theme-overlay .theme-header button {
665
+ padding: 0;
666
+ }
667
+
668
+ .rmp-dialog-contents .rmp-new-menu-themes {
669
+ width: 100%;
670
+ padding: 2%;
671
+ max-height: 480px;
672
+ overflow-y: overlay;
673
+ }
674
+
675
+ .rmp-new-menu-themes .rmp-themes{
676
+ margin: 30px 0;
677
+ }
678
+
679
+ .rmp-new-menu-themes .rmp-themes .rmp-theme-title {
680
+ position: relative;
681
+ font-size: 12px;
682
+ display: block;
683
+ margin: 10px;
684
+ border: solid 1px #ddd;
685
+ cursor: auto;
686
+ background-color: #fafafa;
687
+ padding: 10px;
688
+ line-height: 1.55;
689
+ font-size: 16px;
690
+ font-weight: 400;
691
+ color: #2d405a;
692
+ font-weight: bold;
693
+ margin: 5px 0px;
694
+ cursor: pointer;
695
+ background-color: #fff;
696
+ border-bottom: 1px solid #ddd;
697
+ font-family: 'Product Sans';
698
+ font-size: 13px;
699
+ text-transform: capitalize;
700
+ transition: .15s color ease-in-out, .15s background-color ease-in-out, .15s border-color ease-in-out;
701
+ }
702
+
703
+ .rmp-new-menu-themes .rmp-themes .rmp-theme-option {
704
+ -webkit-appearance: none;
705
+ -moz-appearance: none;
706
+ appearance: none;
707
+ visibility: hidden;
708
+ display: none;
709
+ }
710
+
711
+ .rmp-new-menu-themes .rmp-themes .rmp-theme-option:checked + label{
712
+ background: #0085ba;
713
+ border: solid 2px #0085ba;
714
+ color: #fff;
715
+ }
716
+
717
+ .rmp-new-menu-themes #tabs .nav-tab-wrapper{
718
+ border: unset;
719
+ display: flex;
720
+ justify-content: center;
721
+ }
722
+
723
+ .rmp-new-menu-themes #tabs .nav-tab-wrapper .nav-tab {
724
+ margin: 0;
725
+ border: solid 1px #ffffff;
726
+ padding: 5px 20px;
727
+ box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
728
+ }
729
+
730
+ #tabs .nav-tab-wrapper .nav-tab {
731
+ background: #fff;
732
+ color: #2d405a;
733
+ font-weight: normal;
734
+ font-family: 'Product Sans';
735
+ font-size: 12px;
736
+ }
737
+
738
+ #rmp-new-menu-wizard #tabs .nav-tab-wrapper .ui-tabs-active .nav-tab,
739
+ #tabs .nav-tab-wrapper .nav-tab.nav-tab-active {
740
+ color:white;
741
+ background: #0085ba;
742
+ transition: all 500ms linear;
743
+ }
744
+
745
+ #rmp-new-menu-wizard .rmp-dialog-contents{
746
+ background: #f3f3f3;
747
+ }
748
+
749
+ #rmp-new-menu-wizard .rmp-dialog-header,
750
+ #rmp-new-menu-wizard .rmp-dialog-footer{
751
+ background: #fff;
752
+ border-color: #ddd;
753
+ }
754
+
755
+
756
+ #rmp-new-menu-wizard .rmp-menu-condition-options {
757
+ margin: 10px 0;
758
+ }
759
+
760
+ #rmp-new-menu-wizard .rmp-menu-condition-options span{
761
+ margin-right: 15px;
762
+ }
763
+
764
+ .rmp-dialog-contents .rmp-new-menu-elements {
765
+ width: 100%;
766
+ padding: 2%;
767
+ }
768
+
769
+ .rmp-dialog-contents .rmp-new-menu-elements input[type="text"],
770
+ .rmp-dialog-contents .rmp-new-menu-elements select{
771
+ width: 100%;
772
+ max-width: 100%;
773
+ height: 35px;
774
+ border: solid 1px #dddddd;
775
+ }
776
+
777
+ .rmp-new-menu-elements label {
778
+ display: block;
779
+ font-size: 14px;
780
+ margin-bottom: 5px;
781
+ font-family: inherit;
782
+ }
783
+
784
+ .rmp-new-menu-elements .input-group {
785
+ margin-bottom: 10px;
786
+ background: white;
787
+ padding: 3% 4%;
788
+ position: relative;
789
+ }
790
+
791
+
792
+
793
+ .rmp-dialog-contents .tabs{
794
+ width: 100%;
795
+ }
796
+
797
+ .dropzone {
798
+ max-width: 400px;
799
+ background: #f3f3f3;
800
+ border: 1px solid #ddd;
801
+ padding: 30px;
802
+ text-align: center;
803
+ margin-bottom: 20px;
804
+ }
805
+
806
+ #tabs .nav-tab-wrapper {
807
+ padding: unset;
808
+ }
809
+
810
+ /* Spinner */
811
+ .spinner {
812
+ float: unset;
813
+ }
814
+
815
+ .notice {
816
+ margin: 5px 0px 10px;
817
+ }
818
+
819
+
820
+ /** New Design style */
821
+ #rmp-preview-wrapper{
822
+ height: 100%;
823
+ position: relative;
824
+ }
825
+
826
+ .rmp-preview-mobile #rmp-preview-wrapper,
827
+ .rmp-preview-tablet #rmp-preview-wrapper {
828
+ border: 40px solid #333;
829
+ border-width: 55px 7px;
830
+ border-radius: 40px;
831
+ transition: all 0.5s ease;
832
+ transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
833
+ position: relative;
834
+ box-shadow: 0px 3px 0 #BBB, 0px 4px 0 #BBB, 0px 5px 0 #BBB, 0px 7px 0 #BBB, 1px 6px 15px #2d405a;
835
+ }
836
+
837
+ #rmp-preview-iframe,
838
+ #rmp-preview-iframe-loader {
839
+ height: 100%;
840
+ width: 100%;
841
+ background: rgb(255 255 255 / 0.8);
842
+ display: block;
843
+ }
844
+
845
+ #rmp-preview-iframe-loader{
846
+ position: absolute;
847
+ display:none;
848
+ }
849
+
850
+ #rmp-preview-iframe-loader img {
851
+ position: absolute;
852
+ left: 50%;
853
+ top: 50%;
854
+ -webkit-transform: translate(-50%, -50%);
855
+ transform: translate(-50%, -50%);
856
+ }
857
+
858
+
859
+ #rmp-save-menu-options,
860
+ #rmp-theme-action {
861
+ height: 100%;
862
+ width: max-content;
863
+ padding: 0 2rem;
864
+ background: #36BEF7;
865
+ border: unset;
866
+ color: #fff;
867
+ font-size: 16px;
868
+ cursor: pointer;
869
+ font-family: 'Product Sans Medium';
870
+ }
871
+
872
+ #rmp-theme-action {
873
+ padding: 0 0.5rem;
874
+ margin-left: 2px;
875
+ color: white;
876
+ }
877
+
878
+ #rmp-theme-action .dashicons {
879
+ font-size: 24px;
880
+ display: contents;
881
+ }
882
+
883
+ .rmp-editor-header {
884
+ background: #0D133D;
885
+ position: relative;
886
+ display: flex;
887
+ align-items: center;
888
+ height: 55px;
889
+ z-index: 10;
890
+ overflow: hidden;
891
+ }
892
+
893
+ .rmp-action-button {
894
+ display: block;
895
+ position: absolute;
896
+ top: 0;
897
+ right: 0;
898
+ width: 45px;
899
+ height: 100%;
900
+ padding: 0 2px 0 0;
901
+ background: #0085ba;
902
+ border: none;
903
+ color: #fff;
904
+ text-align: center;
905
+ text-decoration: none;
906
+ cursor: pointer;
907
+ transition: color .15s ease-in-out, border-color .15s ease-in-out, background .15s ease-in-out;
908
+ box-sizing: content-box;
909
+ }
910
+
911
+
912
+ .rmp-editor-header-logo {
913
+ display: inline-flex;
914
+ height: 55px;
915
+ width: 55px;
916
+ align-items: center;
917
+ }
918
+
919
+ .rmp-editor-header-logo img{
920
+ max-width: 35px;
921
+ max-height: 35px;
922
+ margin: 5px auto;
923
+ }
924
+
925
+ .rmp-editor-header-back{
926
+ width: 100%;
927
+ height: 100%;
928
+ vertical-align: bottom;
929
+ display: flex;
930
+ justify-content: center;
931
+ align-items: center;
932
+ display: none;
933
+ background: #F80668;
934
+ color: #fff;
935
+ font-weight: 900;
936
+ }
937
+
938
+ .rmp-editor-header-close {
939
+ width: 55px;
940
+ height: 55px;
941
+ position: absolute;
942
+ right: 0;
943
+ display: flex;
944
+ align-items: inherit;
945
+ justify-content: center;
946
+ font-weight: 900;
947
+ font-size: 1.2rem;
948
+ background: #F80668;
949
+ color: #fff;
950
+ }
951
+
952
+ .rmp-editor-header-close:hover,
953
+ .rmp-editor-header-close:focus{
954
+ color: #fff;
955
+ }
956
+
957
+ .rmp-editor-header-title {
958
+ display: inline-block;
959
+ font-family: 'Product Sans';
960
+ font-size: 16px;
961
+ font-weight: 500;
962
+ color: #fff;
963
+ padding: 0 1rem;
964
+ text-transform: capitalize;
965
+ transition: .15s color ease-in-out, .15s background-color ease-in-out, .15s border-color ease-in-out;
966
+ }
967
+
968
+ #rmp-editor-footer {
969
+ position: absolute;
970
+ bottom: 0;
971
+ left: 0;
972
+ width: 100%;
973
+ height: 45px;
974
+ border-top: 1px solid #ddd;
975
+ background: #fff;
976
+ display: flex;
977
+ align-items: center;
978
+ }
979
+
980
+ #rmp-editor-footer .rmp-preview-device-wrapper {
981
+ position: relative;
982
+ background: #fff;
983
+ display: flex;
984
+ width: max-content;
985
+ float: right;
986
+ height: 100%;
987
+ align-items: center;
988
+ padding: 0 2rem;
989
+ }
990
+
991
+ .rmp-editor-overlay .collapse-sidebar {
992
+ position: fixed;
993
+ width: 48px;
994
+ height: 48px;
995
+ bottom: 50%;
996
+ padding: 10px 0px 10px 15px;
997
+ color: #eee;
998
+ outline: 0;
999
+ left: -20px;
1000
+ line-height: 1;
1001
+ background: #ffffff;
1002
+ border: none;
1003
+ border-radius: 25px;
1004
+ cursor: pointer;
1005
+ box-shadow: 0px 0 3px 3px #0d133d14;
1006
+ }
1007
+
1008
+ .rmp-preview-device-wrapper button:hover,
1009
+ .rmp-preview-device-wrapper button:focus {
1010
+ background: unset;
1011
+ border:unset;
1012
+ outline:unset;
1013
+ box-shadow:unset;
1014
+ }
1015
+
1016
+ .rmp-editor-overlay .collapse-sidebar-arrow:before {
1017
+ display: block;
1018
+ content: "\f141";
1019
+ font: normal 28px/1 dashicons;
1020
+ color: #36BEF7;
1021
+ padding: 0;
1022
+ }
1023
+
1024
+ .rmp-editor-overlay.collapsed .collapse-sidebar-arrow:before{
1025
+ transform: rotate(180deg);
1026
+ }
1027
+
1028
+ #rmp-editor-footer .rmp-preview-device-wrapper .rmp-device-preview {
1029
+ display: flex;
1030
+ align-items: center;
1031
+ justify-content: center;
1032
+ cursor: pointer;
1033
+ background: transparent;
1034
+ border: none;
1035
+ height: 35px;
1036
+ width: 35px;
1037
+ margin-left: 10px;
1038
+ transition: .15s color ease-in-out, .15s background-color ease-in-out, .15s border-color ease-in-out;
1039
+ }
1040
+
1041
+ #rmp-editor-footer .rmp-preview-device-wrapper .rmp-device-preview.active {
1042
+ background: #56606d;
1043
+ border-radius: 4px;
1044
+ }
1045
+
1046
+ #rmp-editor-footer .rmp-device-preview.active svg path,
1047
+ .rmp-device-switcher-holder svg path {
1048
+ fill : #fff;
1049
+ }
1050
+
1051
+ .rmp-tab-item svg path,
1052
+ #rmp-editor-footer svg path,
1053
+ .device-icons-group svg path {
1054
+ fill : #56606D;
1055
+ }
1056
+
1057
+
1058
+ .rmp-editor-footer .rmp-preview-device-wrapper button:before {
1059
+ display: inline-block;
1060
+ -webkit-font-smoothing: antialiased;
1061
+ font: normal 20px/30px "dashicons";
1062
+ vertical-align: top;
1063
+ margin: 3px 0;
1064
+ padding: 4px 8px;
1065
+ color: #656a6f;
1066
+ }
1067
+
1068
+ .rmp-editor-overlay,
1069
+ .rmp-editor-sidebar,
1070
+ .rmp-editor-overlay .collapse-sidebar,
1071
+ .rmp-editor-preview-main {
1072
+ transition-property: left, right, top, bottom, width, margin;
1073
+ transition-duration: 0.2s;
1074
+ }
1075
+
1076
+ .rmp-editor-sidebar {
1077
+ box-sizing: border-box;
1078
+ position: fixed;
1079
+ width: 350px;
1080
+ height: 100%;
1081
+ top: 0;
1082
+ bottom: 0;
1083
+ left: 0;
1084
+ padding: 0;
1085
+ margin: 0;
1086
+ z-index: 999999;
1087
+ background: #fff;
1088
+ overflow: hidden;
1089
+ box-shadow: 0px 0 3px 3px #0d133d14;
1090
+ }
1091
+
1092
+ .rmp-editor-overlay.expanded {
1093
+ margin-left: 350px;
1094
+ }
1095
+
1096
+ .rmp-editor-overlay.collapsed .rmp-editor-sidebar {
1097
+ margin-left: -350px;
1098
+ }
1099
+
1100
+
1101
+ .rmp-editor-overlay {
1102
+ height: 100%;
1103
+ background: #f1f1f1;
1104
+ overflow-y: scroll;
1105
+ }
1106
+
1107
+ .rmp-editor-overlay.expanded .collapse-sidebar {
1108
+ left: 325px;
1109
+ }
1110
+
1111
+ @media screen and (max-width: 1024px) {
1112
+ .rmp-editor-overlay-footer .rmp-preview-device-wrapper {
1113
+ display: none;
1114
+ }
1115
+ }
1116
+
1117
+ .collapsed .rmp-editor-overlay-footer .rmp-preview-device-wrapper button:before {
1118
+ display: none;
1119
+ }
1120
+
1121
+ .rmp-preview-mobile #rmp-preview-wrapper {
1122
+ margin: 100px auto;
1123
+ width: 380px;
1124
+ height: 600px;
1125
+ max-height: 600px;
1126
+ max-width: 480px;
1127
+ }
1128
+
1129
+ .rmp-preview-tablet #rmp-preview-wrapper {
1130
+ margin: 50px auto;
1131
+ width: 740px;
1132
+ height: 800px;
1133
+ max-height: 800px;
1134
+ max-width: 100%;
1135
+ }
1136
+
1137
+ .rmp-editor-preview-main {
1138
+ height: 100%;
1139
+ }
1140
+
1141
+ .rmp-editor-sidebar .rmp-editor-sidebar-content {
1142
+ position: absolute;
1143
+ top: 45px;
1144
+ bottom: 45px;
1145
+ left: 0;
1146
+ right: 0;
1147
+ overflow: auto;
1148
+ }
1149
+
1150
+ .rtl .rmp-editor-overlay.collapsed .collapse-sidebar-arrow:before {
1151
+ transform: none;
1152
+ }
1153
+
1154
+ #rmp-editor-main {
1155
+ color: #333333;
1156
+ height: calc(100% - 100px);
1157
+ overflow-y: auto;
1158
+ overflow-y: overlay;
1159
+ scrollbar-width: none;
1160
+ }
1161
+
1162
+ #rmp-editor-form #rmp-editor-main .rmp-order-item {
1163
+ margin: 5%;
1164
+ width: auto;
1165
+ font-family: Roboto;
1166
+ font-size: 14px;
1167
+ color: #464646;
1168
+ font-style: normal;
1169
+ background: #f5f6fa;
1170
+ }
1171
+
1172
+ #rmp-editor-form #rmp-editor-main .rmp-order-item-description{
1173
+ padding: 3% 5%;
1174
+ background: #FFF8D3;
1175
+ color: #E8862B;
1176
+ font-family: Product Sans;
1177
+ font-style: normal;
1178
+ font-weight: normal;
1179
+ font-size: 14px;
1180
+ line-height: 21px;
1181
+ }
1182
+
1183
+ #rmp-editor-form .rmp-editor-pane-parent,
1184
+ #rmp-editor-form .rmp-accordion-container{
1185
+ margin: 0;
1186
+ padding: 0;
1187
+ list-style-type: none;
1188
+ -webkit-touch-callout: none;
1189
+ -webkit-user-select: none;
1190
+ -khtml-user-select: none;
1191
+ -moz-user-select: none;
1192
+ -ms-user-select: none;
1193
+ user-select: none;
1194
+ }
1195
+
1196
+ #rmp-editor-form .rmp-editor-pane-parent .rmp-tab-item {
1197
+ padding: 0 5%;
1198
+ }
1199
+
1200
+
1201
+ #rmp-editor-form .rmp-accordion-container .rmp-accordion-item {
1202
+ margin: 5%;
1203
+ }
1204
+
1205
+ #rmp-editor-form .rmp-accordion-container .rmp-accordion-item .rmp-accordion-title{
1206
+ padding: 10px;
1207
+ font-family: 'Product Sans Medium';
1208
+ }
1209
+
1210
+ #rmp-editor-form .rmp-sub-accordion-container .rmp-accordion-item .rmp-accordion-title {
1211
+ background: #FFFFFF;
1212
+ border-radius: 4px;
1213
+ }
1214
+
1215
+ #rmp-editor-form .rmp-editor-pane-parent .rmp-tab-item-title,
1216
+ #rmp-editor-form .rmp-accordion-container .rmp-accordion-title,
1217
+ #rmp-editor-main .rmp-accordion-container .rmp-theme-title {
1218
+ position: relative;
1219
+ line-height: 1.5;
1220
+ padding: 1rem 0;
1221
+ color: #2d405a;
1222
+ display: block;
1223
+ font-weight: 600;
1224
+ cursor: pointer;
1225
+ background-color: #F5F6FA;
1226
+ border-radius: 4px;
1227
+ font-family: 'Product Sans';
1228
+ font-style: normal;
1229
+ font-weight: normal;
1230
+ font-size: 14px;
1231
+ line-height: 24px;
1232
+ }
1233
+
1234
+ #rmp-editor-form .rmp-accordion-container .rmp-accordion-title::after {
1235
+ content: "\f543";
1236
+ color: #2D405A;
1237
+ font: normal 20px/1 dashicons;
1238
+ speak: none;
1239
+ display: inline-block;
1240
+ -webkit-font-smoothing: antialiased;
1241
+ -moz-osx-font-smoothing: grayscale;
1242
+ text-decoration: none;
1243
+ position: absolute;
1244
+ right: 1rem;
1245
+ top: 12px;
1246
+ }
1247
+
1248
+ #rmp-editor-form .rmp-accordion-container .rmp-accordion-title.rmp-item-placeholder::after {
1249
+ display: none;
1250
+ }
1251
+
1252
+ #rmp-editor-form .rmp-accordion-container .rmp-accordion-title.ui-accordion-header-active::after{
1253
+ content: "\f460";
1254
+ }
1255
+
1256
+ #rmp-editor-form #rmp-editor-main .rmp-editor-pane-parent .rmp-tab-item {
1257
+ display: flex;
1258
+ align-items: center;
1259
+ }
1260
+
1261
+ #rmp-editor-form .rmp-editor-pane-parent .rmp-tab-item .rmp-tab-item-title {
1262
+ display: inline-block;
1263
+ background: #fff;
1264
+ width: 90%;
1265
+ }
1266
+
1267
+ #rmp-editor-form .rmp-editor-pane-parent .rmp-tab-item .rmp-tab-item-icon {
1268
+ width: 10%;
1269
+ }
1270
+
1271
+ #rmp-editor-form .rmp-accordion-container .rmp-accordion-content,
1272
+ #rmp-editor-form .rmp-sub-accordion-container .rmp-accordion-content{
1273
+ background: #F5F6FA;
1274
+ font-weight: 400;
1275
+ font-family: 'Product Sans';
1276
+ font-size: 12px;
1277
+ border-top: 1px #E7EFF0 solid;
1278
+ padding: 4% 0;
1279
+ }
1280
+
1281
+ #rmp-editor-form .rmp-sub-accordion-container .rmp-accordion-content{
1282
+ background-color:#fff;
1283
+ }
1284
+
1285
+ #rmp-editor-form .rmp-accordions{
1286
+ display: none;
1287
+ }
1288
+
1289
+ /* #rmp-editor-form .rmp-accordion-container .rmp-accordion-content .rmp-accordion-content {
1290
+ padding: 0;
1291
+ } */
1292
+
1293
+ #rmp-editor-form .rmp-editor-pane-parent .rmp-tab-item-title:after {
1294
+ content: "\f345";
1295
+ color: #56606D;
1296
+ font: normal 20px/1 dashicons;
1297
+ speak: none;
1298
+ display: block;
1299
+ -webkit-font-smoothing: antialiased;
1300
+ -moz-osx-font-smoothing: grayscale;
1301
+ text-decoration: none;
1302
+ }
1303
+
1304
+ #rmp-editor-form .rmp-editor-pane-parent .rmp-tab-item-title:after{
1305
+ float: right;
1306
+ }
1307
+
1308
+ #rmp-editor-form *:focus {
1309
+ outline: unset;
1310
+ box-shadow: unset;
1311
+ }
1312
+
1313
+ .rmp-menu-controls .rmp-input-control-group {
1314
+ display: flex;
1315
+ flex-direction: row;
1316
+ padding: 0 5%;
1317
+ justify-content: space-between;
1318
+ }
1319
+
1320
+ .rmp-menu-controls .rmp-input-control-group .rmp-input-control-wrapper{
1321
+ width: 48%;
1322
+ padding: 0;
1323
+ }
1324
+
1325
+ .rmp-menu-controls .rmp-input-control-wrapper {
1326
+ position: relative;
1327
+ display: flex;
1328
+ flex-direction: column;
1329
+ margin-bottom: 15px;
1330
+ padding: 0 5%;
1331
+ }
1332
+
1333
+ .rmp-menu-controls .rmp-input-control-wrapper.rmp-input-control-switcher {
1334
+ flex-direction: row;
1335
+ justify-content: space-between;
1336
+ }
1337
+
1338
+ .rmp-input-control-label{
1339
+ font-weight: normal;
1340
+ font-family: 'Product Sans';
1341
+ font-style: normal;
1342
+ font-weight: normal;
1343
+ font-size: 12px;
1344
+ line-height: 16px;
1345
+ color: #56606D;
1346
+ display: inline-block;
1347
+ margin-bottom: 0.5rem;
1348
+ }
1349
+
1350
+ .rmp-menu-controls .rmp-input-control-wrapper .rmp-input-control {
1351
+ display: flex;
1352
+ }
1353
+
1354
+ .rmp-menu-controls .rmp-input-control-wrapper .rmp-input-control input[type="text"],
1355
+ .rmp-menu-controls .rmp-input-control-wrapper .rmp-input-control input[type="number"],
1356
+ .rmp-menu-controls .rmp-input-control-wrapper .rmp-input-control select {
1357
+ border-radius: 3px;
1358
+ height: 38px;
1359
+ width: 140px;
1360
+ padding: 0.2rem 0.5rem;
1361
+ border: 1px solid #E7EFF0;
1362
+ box-sizing: border-box;
1363
+ border-radius: 4px;
1364
+ font-family: 'Product Sans';
1365
+ font-style: normal;
1366
+ font-weight: 500;
1367
+ font-size: 12px;
1368
+ line-height: 15px;
1369
+ margin: 0;
1370
+ }
1371
+
1372
+ #rmp-editor-form .rmp-input-control-wrapper .button {
1373
+ background: #36bef7;
1374
+ border-color: #36bef7;
1375
+ border-radius: 4px;
1376
+ }
1377
+
1378
+ #rmp-editor-form .rmp-input-control-wrapper.full-size .button {
1379
+ width: 100%
1380
+ }
1381
+
1382
+ .rmp-menu-controls .rmp-input-control-wrapper .rmp-input-control input[type="number"]{
1383
+ width: 100%;
1384
+ }
1385
+
1386
+ /* .rmp-menu-controls .rmp-input-control-wrapper.full-size.multi-device .rmp-input-control input[type="number"] {
1387
+
1388
+ max-width: 70%;
1389
+ } */
1390
+
1391
+ .rmp-menu-controls .rmp-input-control-wrapper.full-size .rmp-input-control input[type="number"]{
1392
+ width: calc( 100% - 36px);
1393
+ max-width: 100%;
1394
+ }
1395
+
1396
+ .rmp-menu-controls .full-size .rmp-input-control input[type="text"],
1397
+ .rmp-menu-controls .full-size .rmp-input-control select,
1398
+ .rmp-order-item .full-size .rmp-input-control input[type="text"] {
1399
+ min-width: 100%;
1400
+ }
1401
+
1402
+ .rmp-menu-controls .full-size .rmp-input-control select.is-unit {
1403
+ max-width: 36px;
1404
+ min-width: 36px;
1405
+ }
1406
+
1407
+ .rmp-menu-controls .rmp-input-control-wrapper .rmp-input-group-control {
1408
+ display: flex;
1409
+ align-items: flex-end;
1410
+ }
1411
+
1412
+ .rmp-menu-controls .rmp-input-control-wrapper .rmp-input-control .rmp-group-input-wrapper {
1413
+ min-width: calc(100% / 5);
1414
+ font-size: 12px;
1415
+ text-align: center;
1416
+ font-weight: normal;
1417
+ font-family: 'Product Sans';
1418
+ text-transform: capitalize;
1419
+ }
1420
+
1421
+ .rmp-menu-controls .rmp-input-control-wrapper .rmp-input-control .rmp-group-input-wrapper input[type="text"] {
1422
+ max-width: 100%;
1423
+ }
1424
+
1425
+ .rmp-menu-controls .rmp-input-control button.rmp-group-input-linked.is-linked {
1426
+ padding: 0;
1427
+ font-size: 12px;
1428
+ border: solid 1px #36bef7;
1429
+ background: #36bef7;
1430
+ color: white;
1431
+ cursor: pointer;
1432
+ }
1433
+
1434
+ .rmp-menu-controls .rmp-input-control button.rmp-group-input-linked{
1435
+ border: solid 1px #e7eff0;
1436
+ background: #2d405a;
1437
+ color: #ffffff;
1438
+ width: 100%;
1439
+ height: 38px;
1440
+ }
1441
+
1442
+ #rmp-menu-page-selector {
1443
+ display: none;
1444
+ }
1445
+
1446
+ .rmp-menu-controls .selectize-input{
1447
+ border: 1px solid #E7EFF0;
1448
+ -webkit-box-shadow: unset;
1449
+ box-shadow: unset;
1450
+ }
1451
+
1452
+ .rmp-menu-controls .selectize-control{
1453
+ width: 100%
1454
+ }
1455
+
1456
+ .selectize-control.multi .selectize-input > div,
1457
+ .selectize-control.multi .selectize-input > div.active {
1458
+ font-family: 'Product Sans Medium';
1459
+ font-style: normal;
1460
+ font-weight: 500;
1461
+ font-size: 12px;
1462
+ line-height: 24px;
1463
+ color: #FFFFFF;
1464
+ padding: 0 3rem 0 1rem;
1465
+ background: #99A6B9;
1466
+ border-radius: 4px;
1467
+ width: max-content;
1468
+ margin: 0px 20px 10px 0;
1469
+ }
1470
+
1471
+ .rmp-input-control .selectize-control.plugin-remove_button [data-value] .remove{
1472
+ background: #E7EFF0;
1473
+ color: #2d405a;
1474
+ height: 24px;
1475
+ width: 24px;
1476
+ padding: 0;
1477
+ right: -15px;
1478
+ }
1479
+
1480
+ .rmp-accordion-container .rmp-accordion-title .ui-accordion-header-icon{
1481
+ display: inline-block;
1482
+ text-indent: 0;
1483
+ }
1484
+
1485
+ #tab-container .rmp-order-item-title .ui-accordion-header-icon,
1486
+ #tab-header-bar .rmp-order-item-title .ui-accordion-header-icon {
1487
+ width: 20px;
1488
+ cursor: move;
1489
+ }
1490
+
1491
+ #tab-container .rmp-order-item-title .ui-accordion-header-icon::before,
1492
+ #tab-header-bar .rmp-order-item-title .ui-accordion-header-icon::before {
1493
+ content: "\e068";
1494
+ color: #99A6B9;
1495
+ font-size: 1rem;
1496
+ position: absolute;
1497
+ top: 1rem;
1498
+ display: inline-block;
1499
+ font-family: 'Glyphicons Halflings';
1500
+ font-style: normal;
1501
+ font-weight: 400;
1502
+ line-height: 1;
1503
+ -webkit-font-smoothing: antialiased;
1504
+ cursor: move;
1505
+ }
1506
+
1507
+ .rmp-tooltip-icon {
1508
+ width: 1.5rem;
1509
+ color: #99A6B9;
1510
+ position: relative;
1511
+ font-size: 1rem;
1512
+ line-height: 16px;
1513
+ height: 1rem;
1514
+ }
1515
+
1516
+ .rmp-accordion-title .rmp-tooltip-icon{
1517
+ line-height: 24px;
1518
+ }
1519
+
1520
+ .rmp-tooltip-icon .rmp-tooltip-content {
1521
+ background: #0d133d;
1522
+ color: #fff;
1523
+ position: absolute;
1524
+ min-width: 140px;
1525
+ max-width: 200px;
1526
+ display: none;
1527
+ padding: 8px;
1528
+ box-shadow: 0 0 2px #0d133d;
1529
+ z-index: 999;
1530
+ text-align: center;
1531
+ right: -70px;
1532
+ bottom: 25px;
1533
+ font-family: 'Product Sans';
1534
+ font-style: normal;
1535
+ font-weight: normal;
1536
+ font-size: 12px;
1537
+ line-height: 16px;
1538
+ border-radius: 5px;
1539
+ }
1540
+
1541
+ .rmp-tooltip-icon .rmp-tooltip-content a{
1542
+ color: #f80668;
1543
+ }
1544
+
1545
+ .rmp-tooltip-icon .rmp-tooltip-content:before {
1546
+ content: '';
1547
+ height: 5px;
1548
+ width: 5px;
1549
+ border: 8px solid #b7414100;
1550
+ border-bottom-color: #0d133d;
1551
+ position: absolute;
1552
+ transform: rotate(180deg);
1553
+ bottom: -20px;
1554
+ left: 40%;
1555
+ }
1556
+
1557
+ .rmp-h-separator {
1558
+ border-bottom: solid 1px #E7EFF0;
1559
+ width: 100%;
1560
+ margin-bottom: 15px;
1561
+ }
1562
+
1563
+ .device-icons-group {
1564
+ width: 100%;
1565
+ text-align: center;
1566
+ display: flex;
1567
+ justify-content: flex-start;
1568
+ }
1569
+
1570
+ .device-icons-group .device-icon {
1571
+ display: inline;
1572
+ width: 60px;
1573
+ position: relative;
1574
+ color: #717171;
1575
+ margin-right: 15px;
1576
+ }
1577
+
1578
+ .device-icons-group .device-icon .corner-icon {
1579
+ position: absolute;
1580
+ top: -4px;
1581
+ font-size: 18px;
1582
+ right: -4px;
1583
+ color: #36bef7;
1584
+ display:none;
1585
+ background: #fff;
1586
+ border-radius: 50%;
1587
+ }
1588
+
1589
+ .device-icons-group .device-icon .device {
1590
+ top: 15px;
1591
+ right: 0px;
1592
+ font-size: 30px;
1593
+ position: relative;
1594
+ line-height: normal;
1595
+ }
1596
+
1597
+ .device-icons-group .device-icon .device svg{
1598
+ width: 24px;
1599
+ height: 24px;
1600
+ }
1601
+
1602
+ .device-icons-group .device-icon .device-title{
1603
+ margin-top: 7px;
1604
+ display: block !important;
1605
+ }
1606
+
1607
+ .device-icons-group .device-icon label {
1608
+ height: 60px;
1609
+ display: block;
1610
+ margin: 0;
1611
+ color: #2d405a;
1612
+ overflow: hidden;
1613
+ border: 1px solid #E7EFF0;
1614
+ box-sizing: border-box;
1615
+ border-radius: 4px;
1616
+ background: #fff;
1617
+ }
1618
+
1619
+ .device-icons-group .device-icon .checkbox {
1620
+ -webkit-appearance: none;
1621
+ -moz-appearance: none;
1622
+ appearance: none;
1623
+ visibility: hidden;
1624
+ display: none;
1625
+ }
1626
+
1627
+ .device-icons-group .device-icon .checkbox:checked + label {
1628
+ background: #FFFFFF;
1629
+ border: 1px solid #36BEF7;
1630
+ box-sizing: border-box;
1631
+ border-radius: 4px;
1632
+ }
1633
+
1634
+ .device-icons-group .device-icon .checkbox:checked + label .corner-icon{
1635
+ display:block;
1636
+ }
1637
+
1638
+ #tab-container .item-controls,
1639
+ #tab-header-bar .item-controls{
1640
+ font-size: 12px;
1641
+ position: relative;
1642
+ right: 2rem;
1643
+ float: right;
1644
+ }
1645
+
1646
+ #rmp-editor-main .item-controls {
1647
+ top:unset;
1648
+ }
1649
+
1650
+ .rmp-menu-controls .rmp-input-control-wrapper select.is-unit,
1651
+ .rmp-menu-controls .rmp-input-control-wrapper .unit-px,
1652
+ .rmp-menu-controls .unit-ms,
1653
+ .rmp-menu-controls .unit-s {
1654
+ width: 2.25rem;
1655
+ margin-left: -5px;
1656
+ display: inline-block;
1657
+ font-family: 'Product Sans';
1658
+ font-style: normal;
1659
+ font-weight: normal;
1660
+ font-size: 12px;
1661
+ line-height: 24px;
1662
+ text-align: center;
1663
+ color: #56606D;
1664
+ background: #E7EFF0;
1665
+ border-radius: 0px 4px 4px 0px;
1666
+ }
1667
+
1668
+ .rmp-menu-controls .rmp-input-control-wrapper .unit-px,
1669
+ .rmp-menu-controls .unit-ms,
1670
+ .rmp-menu-controls .unit-s{
1671
+ padding: 5px 0;
1672
+ border-top-right-radius: 4px;
1673
+ border-bottom-right-radius: 4px;
1674
+ }
1675
+
1676
+ .rmp-input-control-group .unit-s {
1677
+ margin-left: -36px;
1678
+ }
1679
+
1680
+ .rmp-input-control-group .rmp-input-control-wrapper:nth-child(2) .wp-picker-holder {
1681
+ right: 5px;
1682
+ }
1683
+
1684
+ .wp-picker-holder{
1685
+ position: absolute;
1686
+ z-index: 999;
1687
+ margin-top: 38px;
1688
+ }
1689
+
1690
+ .wp-picker-container .iris-picker {
1691
+ margin-top: 0;
1692
+ border: solid 1px #d5dadf;
1693
+ }
1694
+
1695
+ .rmp-editor-active .wp-picker-container,
1696
+ #rmp-editor-form .wp-picker-container {
1697
+ display: flex;
1698
+ }
1699
+
1700
+ .rmp-editor-active .rmp-input-control-wrapper .wp-picker-container .wp-color-result.button,
1701
+ #rmp-editor-form .rmp-input-control-wrapper .wp-picker-container .wp-color-result.button {
1702
+ border: solid 1px #e7eff0;
1703
+ height: 38px;
1704
+ padding: 0 0 0 36px;
1705
+ margin: 0;
1706
+ background: unset;
1707
+ }
1708
+
1709
+ .rmp-editor-active .wp-picker-container .wp-color-result.button .color-alpha{
1710
+ border-right: solid 1PX #e7eff0;
1711
+ }
1712
+
1713
+ .rmp-input-control .rmp-color-input-wrap.hidden {
1714
+ display: inline-block !important;
1715
+ }
1716
+
1717
+
1718
+ .rmp-menu-controls .rmp-input-control-wrapper .wp-picker-container input[type="text"].wp-color-picker {
1719
+ width: 100%;
1720
+ max-width: 100%;
1721
+ font-family: 'Product Sans';
1722
+ font-style: normal;
1723
+ font-weight: normal;
1724
+ font-size: 12px;
1725
+ line-height: 16px;
1726
+ color: #99A6B9;
1727
+ border-top-left-radius: unset;
1728
+ border-bottom-left-radius: unset;
1729
+ margin-left: -2px;
1730
+ }
1731
+
1732
+ .rmp-editor-active .rmp-input-control .wp-picker-container .wp-picker-clear{
1733
+ height: 30px;
1734
+ border: solid 1px #36BEF7;
1735
+ margin-left: -4px;
1736
+ border-bottom-left-radius: unset;
1737
+ border-top-left-radius: unset;
1738
+ background: #36BEF7;
1739
+ color: #ffff;
1740
+ }
1741
+
1742
+ .wp-picker-container .wp-picker-clear:hover{
1743
+ background:#36BEF7;
1744
+ border-color: #36BEF7;
1745
+ color: #fff;
1746
+ }
1747
+
1748
+ #rmp-menu-additional-content,
1749
+ #rmp-menu-header-html-content {
1750
+ width: 100%;
1751
+ padding: 5px;
1752
+ font-family: 'Product Sans';
1753
+ font-size: 12px;
1754
+ max-height: 120px;
1755
+ border:solid 1px #ddd;
1756
+ min-height: 100px;
1757
+ }
1758
+
1759
+ .rmp-editor-active .media-modal {
1760
+ z-index: 99999999;
1761
+ }
1762
+
1763
+ .rmp-image-picker-container,
1764
+ .rmp-icon-picker-container {
1765
+ padding: 8%;
1766
+ background: #FFFFFF;
1767
+ border-radius: 4px;
1768
+ }
1769
+
1770
+ #rmp-button-title-image,
1771
+ #rmp-button-background-image,
1772
+ .rmp-image-picker,
1773
+ .rmp-icon-picker {
1774
+ width: 100%;
1775
+ height: 90px;
1776
+ cursor: pointer;
1777
+ background-size: 100%;
1778
+ position: relative;
1779
+ overflow: hidden;
1780
+ background: #FFFFFF;
1781
+ border: 1px dashed #C9DBDD;
1782
+ box-sizing: border-box;
1783
+ border-radius: 4px;
1784
+ background-position: center;
1785
+ background-repeat: no-repeat;
1786
+ }
1787
+
1788
+ .rmp-image-picker .rmp-image-picker-trash,
1789
+ .rmp-icon-picker .rmp-icon-picker-trash,
1790
+ .rmp-icon-picker .rmp-font-icon {
1791
+ display: flex;
1792
+ justify-content: center;
1793
+ align-items: center;
1794
+ width: 100%;
1795
+ height: 100%;
1796
+ color: #56606d;
1797
+ font-size: 24px;
1798
+ z-index: 99;
1799
+ }
1800
+
1801
+ .rmp-icon-picker .rmp-font-icon {
1802
+ font-size: 80px;
1803
+ pointer-events: none;
1804
+ color: #32373c;
1805
+ }
1806
+
1807
+ .rmp-image-picker .rmp-image-picker-trash,
1808
+ .rmp-icon-picker .rmp-icon-picker-trash {
1809
+ margin: 0.4rem;
1810
+ background: #f5f6fa;
1811
+ width: 2rem;
1812
+ height: 2rem;
1813
+ position: absolute;
1814
+ right: 0;
1815
+ top: 0;
1816
+ border-radius: 4px;
1817
+ font-size: 16px;
1818
+ visibility: hidden;
1819
+ z-index: 999;
1820
+ pointer-events: initial;
1821
+ cursor: pointer;
1822
+ }
1823
+
1824
+ .rmp-image-picker .rmp-image-picker-placeholder,
1825
+ .rmp-icon-picker .rmp-icon-picker-placeholder {
1826
+ width: 5rem;
1827
+ height: 2.5rem;
1828
+ padding: 0;
1829
+ position: absolute;
1830
+ transition: all 0.3s;
1831
+ pointer-events: none;
1832
+ z-index: 0;
1833
+ border: unset;
1834
+ font-family: 'Product Sans';
1835
+ font-style: normal;
1836
+ font-weight: normal;
1837
+ font-size: 12px;
1838
+ line-height: 15px;
1839
+ text-align: center;
1840
+ color: #99A6B9;
1841
+ top: 50%;
1842
+ left: 50%;
1843
+ transform: translate(-50%,-50%);
1844
+ display: inline;
1845
+ }
1846
+
1847
+ .rmp-image-picker[style*="background-image"] > .rmp-image-picker-placeholder {
1848
+ display: none;
1849
+ }
1850
+
1851
+ .rmp-icon-picker[data-icon="true"] > .rmp-icon-picker-placeholder {
1852
+ display: none;
1853
+ }
1854
+
1855
+ .rmp-image-picker .rmp-image-picker-placeholder label,
1856
+ .rmp-icon-picker .rmp-icon-picker-placeholder label {
1857
+ display: block;
1858
+ }
1859
+
1860
+ .rmp-image-picker:hover > .rmp-image-picker-trash,
1861
+ .rmp-icon-picker:hover > .rmp-icon-picker-trash {
1862
+ visibility: visible;
1863
+ }
1864
+
1865
+ /* Device Switcher Holder */
1866
+
1867
+ #rmp-editor-form .rmp-device-switcher-holder {
1868
+ margin-right: 8px;
1869
+ position: relative;
1870
+ background: #36bef7;
1871
+ border-radius: 4px;
1872
+ }
1873
+
1874
+ #rmp-editor-form .rmp-device-switcher {
1875
+ -webkit-transition: 0.2s;
1876
+ -o-transition: 0.2s;
1877
+ transition: 0.2s;
1878
+ position: relative;
1879
+ width: 38px;
1880
+ height: 38px;
1881
+ }
1882
+
1883
+ #rmp-editor-form .rmp-device-switcher li {
1884
+ display: none;
1885
+ cursor: pointer;
1886
+ background: #36bef7;
1887
+ }
1888
+
1889
+ #rmp-editor-form .rmp-device-switcher li:first-child {
1890
+ display: flex;
1891
+ border-radius: 4px;
1892
+ height: 38px;
1893
+ align-items: center;
1894
+ justify-content: center;
1895
+ }
1896
+
1897
+ #rmp-editor-form .rmp-device-switcher.open {
1898
+ box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
1899
+ z-index: 999;
1900
+ display: flex;
1901
+ justify-content: flex-start;
1902
+ }
1903
+
1904
+ #rmp-editor-form .rmp-device-switcher.open li {
1905
+ display: -ms-flexbox;
1906
+ display: flex;
1907
+ -webkit-box-align: center;
1908
+ -ms-flex-align: center;
1909
+ align-items: center;
1910
+ -webkit-box-pack: center;
1911
+ -ms-flex-pack: center;
1912
+ justify-content: center;
1913
+ position: relative;
1914
+ cursor: pointer;
1915
+ -webkit-transition: 0.2s;
1916
+ -o-transition: 0.2s;
1917
+ transition: 0.2s;
1918
+ border-radius:unset;
1919
+ min-width: 38px;
1920
+ }
1921
+
1922
+ #rmp-editor-form .rmp-menu-controls .rmp-input-control-wrapper select.rmp-device-switcher option {
1923
+ font-size: 20px;
1924
+ }
1925
+
1926
+ #rmp-editor-main .rmp-saved-themes {
1927
+ padding: 5px 0;
1928
+ }
1929
+
1930
+ #rmp-editor-main .rmp-accordion-container .rmp-theme-title {
1931
+ font-family: Product Sans Medium;
1932
+ font-style: normal;
1933
+ font-weight: 500;
1934
+ font-size: 14px;
1935
+ line-height: 24px;
1936
+ color: #2D405A;
1937
+ margin: 2% 5%;
1938
+ border: solid 1px #eeeeee;
1939
+ cursor: auto;
1940
+ background-color: #ffffff !important;
1941
+ padding: 3% 5%;
1942
+ }
1943
+
1944
+ #rmp-editor-main .rmp-accordion-container .rmp-accordion-sub-heading {
1945
+ margin-bottom: 10px;
1946
+ font-family: 'Product Sans';
1947
+ font-style: normal;
1948
+ font-weight: normal;
1949
+ font-size: 14px;
1950
+ line-height: 14px;
1951
+ color: #2d405a;
1952
+ padding: 0 5%;
1953
+ text-transform: capitalize;
1954
+ }
1955
+
1956
+ button.menu-save {
1957
+ box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
1958
+ }
1959
+
1960
+ .shortcode_place code{
1961
+ vertical-align: sub;
1962
+ padding: 5px 10px;
1963
+ border: solid 1px #ccd0d4;
1964
+ background: #72777c33;
1965
+ }
1966
+
1967
+
1968
+ .theme_filters{
1969
+ margin: 20px 0;
1970
+ display: flex;
1971
+ justify-content: space-between;
1972
+ align-items: center;
1973
+ }
1974
+
1975
+ .rmp-new-menu-wizard .new_menu_tab_items {
1976
+ width: 40%;
1977
+ border: unset;
1978
+ border-right: 2px solid #dddddd;
1979
+ min-width: 300px;
1980
+ display: flex;
1981
+ flex-direction: column;
1982
+ padding: 20px !important;
1983
+ }
1984
+
1985
+ .rmp-new-menu-wizard .new_menu_tab_items li{
1986
+ margin-bottom: 20px;
1987
+ }
1988
+
1989
+ .rmp-new-menu-wizard .new_menu_tab_items .nav-tab{
1990
+ padding: 0;
1991
+ margin: 0;
1992
+ border: solid 1px #dddddd;
1993
+ width: 100%;
1994
+ white-space: normal;
1995
+ }
1996
+
1997
+ .rmp-new-menu-wizard .device-icons-group {
1998
+ justify-content: flex-start;
1999
+ margin-top: 10px;
2000
+ }
2001
+
2002
+ .rmp-new-menu-wizard .device-icons-group .device-icon {
2003
+ margin-right: 20px;
2004
+ }
2005
+
2006
+ .nav-item-label{
2007
+ padding: 10px 15px;
2008
+ display: flex;
2009
+ align-items: center;
2010
+ line-height: 1.3;
2011
+ }
2012
+
2013
+ .nav-item-label .nav-item-label-icon {
2014
+ font-size: 32px;
2015
+ margin-right: 20px;
2016
+ line-height: 20px;
2017
+ }
2018
+
2019
+ .nav-item-label .nav-item-label-content span{
2020
+ font-size: 12px;
2021
+ font-weight: normal;
2022
+ }
2023
+
2024
+ #rmp-new-menu-wizard .rmp-dialog-wrap {
2025
+ height: fit-content;
2026
+
2027
+ }
2028
+
2029
+ #rmp-new-menu-wizard .rmp-dialog-wrap,
2030
+ #rmp-new-menu-wizard .rmp-dialog-header .title,
2031
+ #rmp-new-menu-wizard #tabs .nav-tab-wrapper .nav-tab,
2032
+ #rmp-new-menu-wizard .rmp-item-card_contents h4,
2033
+ #rmp-new-menu-wizard .rmp-item-card_action .button {
2034
+ font-family: inherit;
2035
+ }
2036
+
2037
+ #rmp-new-menu-wizard .rmp_theme_grids,
2038
+ .rmp-theme-page .rmp_theme_grids{
2039
+ display: flex;
2040
+ justify-content: flex-start;
2041
+ flex-wrap: wrap;
2042
+ }
2043
+
2044
+ .rmp-item-card {
2045
+ display: block;
2046
+ background: white;
2047
+ margin-bottom: 15px;
2048
+ margin-right: 15px;
2049
+ max-width: 170px;
2050
+ position: relative;
2051
+ cursor: pointer;
2052
+ border: solid 1px #eee;
2053
+ overflow: hidden;
2054
+ box-shadow: 0 1px 3px rgb(0 0 0 / 0%), 0 1px 2px rgb(0 0 0 / 10%);
2055
+ }
2056
+
2057
+ .default-item {
2058
+ width: 165px;
2059
+ height: 295px;
2060
+ display: flex;
2061
+ justify-content: center;
2062
+ align-items: center;
2063
+ flex-direction: column;
2064
+ border: 2px dashed #0085ba;
2065
+ background: unset;
2066
+ }
2067
+
2068
+ .rmp-theme-page .rmp-item-card {
2069
+ width: 180px;
2070
+ max-width: 100%;
2071
+ border: solid 1px #ccc;
2072
+ box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.1);
2073
+ box-sizing: border-box;
2074
+ }
2075
+
2076
+ .item-selected{
2077
+ border:5px solid red;
2078
+ }
2079
+
2080
+ .rmp-item-card_image{
2081
+ padding: 0;
2082
+ margin: 0;
2083
+ line-height: inherit;
2084
+ }
2085
+
2086
+ .rmp-item-card_image img {
2087
+ width: 100%;
2088
+ height: 210px;
2089
+ }
2090
+
2091
+ .rmp-item-card_contents{
2092
+ padding: 5px 10px;
2093
+ font-weight: 600;
2094
+ font-size: 12px;
2095
+ display: inline-flex;
2096
+ background: #fff;
2097
+ transition: all .5s;
2098
+ width: -webkit-fill-available;
2099
+ }
2100
+
2101
+ .rmp-item-card_contents h4{
2102
+ margin: 0;
2103
+ font-size: 14px;
2104
+ color: #191e23;
2105
+ background: #fff;
2106
+ font-family: 'Product Sans Medium';
2107
+ font-weight: normal;
2108
+ text-transform: capitalize;
2109
+ }
2110
+
2111
+
2112
+ .rmp-item-card_action {
2113
+ padding:10px;
2114
+ background: #fff;
2115
+ position: relative;
2116
+ bottom: 0;
2117
+ z-index: 9;
2118
+ display: flex;
2119
+ }
2120
+
2121
+ .rmp-item-card_action .button{
2122
+ width: 100%;
2123
+ display: inline-block;
2124
+ text-decoration: none;
2125
+ font-size: 12px;
2126
+ line-height: normal;
2127
+ margin: 0;
2128
+ text-align: center;
2129
+ padding: 10px;
2130
+ margin: 0 5px;
2131
+ cursor: pointer;
2132
+ border-width: 1px;
2133
+ border-style: solid;
2134
+ -webkit-appearance: none;
2135
+ border-radius: 4px;
2136
+ white-space: nowrap;
2137
+ box-sizing: border-box;
2138
+ color: #0085ba;
2139
+ border-color: #007cba;
2140
+ background: #fff;
2141
+ font-family: 'Product Sans Medium';
2142
+ }
2143
+
2144
+ .rmp-item-card a.favorite-heart{
2145
+ text-decoration: none;
2146
+ color: gray;
2147
+ }
2148
+
2149
+ .rmp-item-card a.favorite-heart.liked{
2150
+ color: #e56060;
2151
+ }
2152
+
2153
+ .rmp-item-card a.favorite-heart:focus{
2154
+ box-shadow: unset;
2155
+ }
2156
+
2157
+ .rmp-item-card .rmp-item-card_label {
2158
+ position: absolute;
2159
+ top: 10px;
2160
+ background: #f46242;
2161
+ color: white;
2162
+ left: 10px;
2163
+ margin: 0;
2164
+ line-height: 1.5;
2165
+ font-size: 12px;
2166
+ font-weight: 600;
2167
+ padding: 2px 8px;
2168
+ text-transform: uppercase;
2169
+ border-radius: 3px;
2170
+ box-shadow: 0 1px 3px rgb(0 0 0 / 31%), 0 1px 2px rgb(0 0 0 / 28%);
2171
+ }
2172
+
2173
+ .rmp-item-card .rmp-item-card_label.Pro{
2174
+ background: #f46242;
2175
+ }
2176
+
2177
+ .rmp-item-card .rmp-item-card_label.Free{
2178
+ background: #17c326;
2179
+ }
2180
+
2181
+ .rmp-item-card .rmp-item-card_label span.dashicons {
2182
+ font-size: 14px;
2183
+ width: 14px;
2184
+ height: 18px;
2185
+ }
2186
+
2187
+ #rmp-menu-library-import {
2188
+ margin: 40px auto;
2189
+ display: flex;
2190
+ justify-content: center;
2191
+ text-align: center;
2192
+ }
2193
+
2194
+ #rmp-menu-library-import.hide{
2195
+ display: none;
2196
+ }
2197
+
2198
+ #rmp-menu-library-import-form {
2199
+ border: 2px dashed #d5dadf;
2200
+ background: #f9f9f9;
2201
+ width: 50%;
2202
+ max-width: 480px;
2203
+ padding: 2%;
2204
+ min-width: 420px;
2205
+ cursor: pointer;
2206
+ position: relative;
2207
+ }
2208
+
2209
+ #rmp-menu-library-import-form .upload-button {
2210
+ pointer-events: none;
2211
+ }
2212
+
2213
+ #rmp-menu-library-import-form .cancel{
2214
+ position: absolute;
2215
+ top: 10px;
2216
+ right: 10px;
2217
+ }
2218
+
2219
+ .rmp-theme-page {
2220
+ margin: 2% 0;
2221
+ }
2222
+
2223
+ .rmp-theme-page .pagination {
2224
+ display: inline-flex;
2225
+ }
2226
+
2227
+ #rmp-upload-new-theme {
2228
+ padding: 4px 8px;
2229
+ position: relative;
2230
+ top: -3px;
2231
+ text-decoration: none;
2232
+ border: 1px solid #0071a1;
2233
+ border-radius: 2px;
2234
+ text-shadow: none;
2235
+ font-weight: 600;
2236
+ font-size: 13px;
2237
+ line-height: normal;
2238
+ color: #0071a1;
2239
+ background: #f3f5f6;
2240
+ cursor: pointer;
2241
+ }
2242
+
2243
+ #rmp-menu-library-import-form .upload-button {
2244
+ background: #0085ba;
2245
+ color: #fff;
2246
+ text-transform: uppercase;
2247
+ margin-top: 20px;
2248
+ padding: 8px 28px;
2249
+ display: inline-block;
2250
+ border-color: currentColor;
2251
+ }
2252
+
2253
+ #rmp-menu-library-import-form-input {
2254
+ display: none;
2255
+ }
2256
+
2257
+ .rmp-menu-library-blank-icon {
2258
+ font-size: 70px;
2259
+ display: contents;
2260
+ margin-bottom: 10px;
2261
+ color: #f80668;
2262
+ }
2263
+
2264
+ .rmp-menu-library-title {
2265
+ font-size: 18px;
2266
+ margin: 10px 0;
2267
+ font-weight: normal;
2268
+ }
2269
+
2270
+ #rmp-menu-library-import-form .dz-error-mark{
2271
+ display: none;
2272
+ }
2273
+
2274
+ #rmp-menu-library-import-form .dz-success-mark svg{
2275
+ width: 24px;
2276
+ }
2277
+
2278
+ #rmp-menu-library-import-form .dz-success-mark svg path {
2279
+ fill: currentColor;
2280
+ color: #1ac538;
2281
+ }
2282
+
2283
+ .rmp-footer-sub-menu-wrapper {
2284
+ position: absolute;
2285
+ bottom: 100%;
2286
+ width: -webkit-fill-available;
2287
+ background-color: #56606d;
2288
+ padding: 1rem;
2289
+ -webkit-box-shadow: -2px -5px 8px rgba(0, 0, 0, 0.1);
2290
+ box-shadow: -2px -5px 8px rgba(0, 0, 0, 0.1);
2291
+ cursor: default;
2292
+ transition: all 0.3s;
2293
+ visibility: hidden;
2294
+ opacity: 0;
2295
+ -webkit-touch-callout: none;
2296
+ -webkit-user-select: none;
2297
+ -khtml-user-select: none;
2298
+ -moz-user-select: none;
2299
+ -ms-user-select: none;
2300
+ user-select: none;
2301
+ transform: translateY(-10px);
2302
+ }
2303
+
2304
+ .rmp-footer-sub-menu-wrapper.open {
2305
+ opacity: 1;
2306
+ transform: translateY(0px);
2307
+ transition: all 0.3s;
2308
+ z-index: 999;
2309
+ visibility: visible;
2310
+ }
2311
+
2312
+ .rmp-footer-sub-menu {
2313
+ overflow: hidden;
2314
+ border-radius: 10px;
2315
+ }
2316
+
2317
+ .rmp-footer-sub-menu a{
2318
+ padding: 0.8rem;
2319
+ background: #f5f6fa;
2320
+ border-bottom: solid 2px #56606d;
2321
+ display: block;
2322
+ color: #56606d;
2323
+ font-weight: 600;
2324
+ font-size: 14px;
2325
+ text-align: left;
2326
+ cursor: pointer;
2327
+ text-transform: capitalize;
2328
+ }
2329
+
2330
+ #rmp-menu-save-theme-wizard .rmp-dialog-wrap {
2331
+ width: 640px;
2332
+ margin: 0 auto;
2333
+ padding: 3% 0 4%;
2334
+ }
2335
+
2336
+ #rmp-menu-save-theme-wizard .rmp-dialog-wrap .close{
2337
+ position: absolute;
2338
+ right: 20px;
2339
+ top: 20px;
2340
+ background: #fff;
2341
+ border-radius: 50%;
2342
+ padding: 10px;
2343
+ color: #56606d;
2344
+ border: solid 1px #0d133d;
2345
+ cursor: pointer;
2346
+ }
2347
+
2348
+ #rmp-menu-save-theme-wizard .rmp-dialog-contents {
2349
+ display: flex;
2350
+ justify-content: center;
2351
+ align-items: center;
2352
+ flex-direction: column;
2353
+ }
2354
+
2355
+ #rmp-editor-main .theme-thumbnail{
2356
+ width: 90%;
2357
+ margin: 5%;
2358
+ }
2359
+
2360
+
2361
+ .rmp-save-menu-input {
2362
+ display: inline-flex;
2363
+ margin-top: 20px;
2364
+ }
2365
+
2366
+ #rmp-menu-save-theme-wizard #rmp-save-theme {
2367
+ background: #0d133d;
2368
+ color: white;
2369
+ border: solid 1px #0d133d;
2370
+ border-radius: unset;
2371
+ font-size: 14px;
2372
+ }
2373
+
2374
+
2375
+ #rmp-menu-save-theme-wizard #rmp-save-theme-name {
2376
+ width: 300px;
2377
+ border: 2px solid #0d133d;
2378
+ }
2379
+
2380
+
2381
+ .rmp-dialog-overlay .rmp-theme-title .item-controls{
2382
+ top: unset;
2383
+ }
2384
+
2385
+ .rmp-theme-page .rmp-item-card_image img{
2386
+ width: 100%;
2387
+ max-height: 240px;
2388
+ }
2389
+
2390
+ .rmp-setting-page #rmp-setting-tabs .nav-tab-wrapper{
2391
+ border-bottom: 1px solid #ccc;
2392
+ margin: 0;
2393
+ padding-top: 10px;
2394
+ padding-bottom: 0;
2395
+ line-height: inherit;
2396
+ }
2397
+
2398
+ .rmp-setting-page #rmp-custom-css {
2399
+ min-height: 420px;
2400
+ max-width: 820px;
2401
+ margin-top: 20px;
2402
+ min-width: 300px;
2403
+ }
2404
+
2405
+ .rmp-setting-page .form-table td fieldset label {
2406
+ margin: 0 !important;
2407
+ }
2408
+
2409
+ .rmp-import-file-container {
2410
+ padding: 10px;
2411
+ background: #fff;
2412
+ max-width: fit-content;
2413
+ border: solid 1px #cccccc;
2414
+ margin-bottom: 1rem;
2415
+ }
2416
+
2417
+ .rmp-menu-item-icon-container {
2418
+ position: relative;
2419
+ }
2420
+
2421
+ .delete-menu-item-icon {
2422
+ cursor: pointer;
2423
+ position: absolute;
2424
+ right: 20px;
2425
+ top: 0;
2426
+ }
2427
+
2428
+ .rmp-menu-item-icon-container .rmp-icon-picker-container{
2429
+ padding: 0;
2430
+ margin-left: 8px;
2431
+ }
2432
+
2433
+ .rmp-menu-item-icon-container .rmp-icon-picker {
2434
+ height: 38px;
2435
+ border: 1px solid #e7eff0;
2436
+ }
2437
+
2438
+ .rmp-menu-item-icon-container .rmp-icon-picker .rmp-font-icon{
2439
+ font-size: 2rem;
2440
+ }
2441
+
2442
+ .rmp-menu-controls .rmp-menu-item-icon-container .rmp-input-control-group{
2443
+ align-items: flex-end;
2444
+ }
2445
+
2446
+ .rmp-menu-item-icon-container .rmp-icon-picker .rmp-icon-picker-placeholder{
2447
+ display: flex;
2448
+ width: 100%;
2449
+ justify-content: space-evenly;
2450
+ transform: translate(-50%,-25%);
2451
+ }
2452
+
2453
+ .rmp-menu-item-icon-container .rmp-icon-picker[data-icon="true"] > .rmp-icon-picker-placeholder {
2454
+ display: none;
2455
+ }
2456
+
2457
+ .rmp-menu-item-icon-container .rmp-icon-picker .rmp-icon-picker-trash {
2458
+ margin: 2px;
2459
+ }
2460
+
2461
+ @keyframes shake {
2462
+ 0% { transform: translate(1px, 1px) rotate(0deg); }
2463
+ 10% { transform: translate(-1px, -2px) rotate(-1deg); }
2464
+ 20% { transform: translate(-3px, 0px) rotate(1deg); }
2465
+ 30% { transform: translate(3px, 2px) rotate(0deg); }
2466
+ 40% { transform: translate(1px, -1px) rotate(1deg); }
2467
+ 50% { transform: translate(-1px, 2px) rotate(-1deg); }
2468
+ 60% { transform: translate(-3px, 1px) rotate(0deg); }
2469
+ 70% { transform: translate(3px, 1px) rotate(-1deg); }
2470
+ 80% { transform: translate(-1px, -1px) rotate(1deg); }
2471
+ 90% { transform: translate(1px, 2px) rotate(0deg); }
2472
+ 100% { transform: translate(1px, -2px) rotate(-1deg); }
2473
+ }
2474
+
2475
+ #rmp-menu-update-notification{
2476
+ text-align: center;
2477
+ display: flex;
2478
+ justify-content: space-between;
2479
+ }
2480
+
2481
+ #rmp-menu-update-notification:hover {
2482
+ animation: shake 0.5s;
2483
+ animation-iteration-count: 5;
2484
+ }
2485
+
2486
+ #rmp-menu-update-notification a{
2487
+ color: #36bef7;
2488
+ font-family: Product Sans Medium;
2489
+ }
2490
+
2491
+ /* These below styles on admin notice */
2492
+ div.notice-responsive-menu {
2493
+ display: flex;
2494
+ align-items: center;
2495
+ border-left-color: #15a4fa;
2496
+ padding: 10px;
2497
+ }
2498
+
2499
+ div.notice-responsive-menu .notice-responsive-menu-logo {
2500
+ margin-right: 10px;
2501
+ }
2502
+
2503
+ div.notice-responsive-menu .notice-responsive-menu-message h4,
2504
+ div.notice-responsive-menu .notice-responsive-menu-message p {
2505
+ margin: 0;
2506
+ }
2507
+
2508
+ div.notice-responsive-menu .notice-responsive-menu-action {
2509
+ position: absolute;
2510
+ right: 40px;
2511
+ }
2512
+
2513
+ @media screen and (max-width: 1150px) {
2514
+ div.notice-responsive-menu {
2515
+ flex-direction: column;
2516
+ align-items: flex-start;
2517
+ }
2518
+ div.notice-responsive-menu .notice-responsive-menu-action {
2519
+ margin-top: 20px;
2520
+ }
2521
+ }
2522
+
2523
+ div.notice-responsive-menu .notice-responsive-menu-action a {
2524
+ text-decoration: none;
2525
+ color: #fff;
2526
+ padding: 8px 15px;
2527
+ background: #36bef7;
2528
+ font-size: 15px;
2529
+ font-weight: 700;
2530
+ border:1px solid #1d9cd2;
2531
+ }
2532
+
2533
+ div.notice-responsive-menu .notice-responsive-menu-action a:hover {
2534
+ opacity: 0.8;
2535
+ }
2536
+
2537
+
2538
+ /* Free version related */
2539
+
2540
+ .upgrade-tooltip {
2541
+ background: #f80668;
2542
+ padding: 4px 0.5rem;
2543
+ color: #fff;
2544
+ font-size: 10px;
2545
+ border-radius: 3px;
2546
+ position: relative;
2547
+ margin-left: 10px;
2548
+ font-weight: 600;
2549
+ text-decoration: none;
2550
+ text-transform: uppercase;
2551
+ line-height: normal;
2552
+ }
2553
+
2554
+ .rmp-editor-overlay .rmp-input-control .upgrade-tooltip {
2555
+ position: absolute;
2556
+ top: -30px;
2557
+ right: 5%;
2558
+
2559
+ }
2560
+
2561
+ .rmp-editor-overlay .rmp-input-control-label .upgrade-tooltip {
2562
+ position: absolute;
2563
+ top: -2px;
2564
+ }
2565
+
2566
+ .rmp-editor-overlay .rmp-input-control-label .upgrade-tooltip,
2567
+ .rmp-editor-overlay .rmp-input-control .upgrade-tooltip {
2568
+ display: none;
2569
+ }
2570
+
2571
+ .rmp-editor-overlay .rmp-input-control-wrapper:hover > .rmp-input-control-label .upgrade-tooltip,
2572
+ .rmp-editor-overlay .rmp-input-control-wrapper:hover > .rmp-input-control .upgrade-tooltip {
2573
+ display: inline-block;
2574
+ }
2575
+
2576
+ .rmp-input-control .upgrade-tooltip::before{
2577
+ left: 10px;
2578
+ bottom: -18px;
2579
+ transform: rotate(180deg);
2580
+ }
2581
+
2582
+ .upgrade-tooltip:hover,
2583
+ .upgrade-tooltip:focus,
2584
+ .upgrade-tooltip:active{
2585
+ color: #fff;
2586
+ }
2587
+
2588
+ .upgrade-tooltip::before {
2589
+ content: '';
2590
+ height: 4px;
2591
+ width: 0px;
2592
+ border: 7px solid #b7414100;
2593
+ border-bottom-color: #f80668;
2594
+ position: absolute;
2595
+ transform: rotate(270deg);
2596
+ left: -16px;
2597
+ bottom: 1px;
2598
+ }
2599
+
2600
+ #rmp-editor-form .rmp-accordion-container .upgrade-notice-contents {
2601
+ background: #fcf1f1;
2602
+ }
2603
+
2604
+ .upgrade-options {
2605
+ background: #fcf1f1;
2606
+ display: flex;
2607
+ justify-content: center;
2608
+ align-items: center;
2609
+ text-align: center;
2610
+ padding: 10% 5%;
2611
+ }
2612
+
2613
+ .upgrade-options .upgrade-notes .button{
2614
+ color: #fff;
2615
+ background: #f80668;
2616
+ border: solid 1px #f80668;
2617
+ margin-top: 1rem;
2618
+ }
2619
+
2620
+ .upgrade-options .upgrade-notes p {
2621
+ font-size: 14px;
2622
+ }
v4.0.0/assets/admin/scss/glyphicons.css ADDED
@@ -0,0 +1,810 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @font-face {
2
+ font-family: 'Glyphicons Halflings';
3
+ src: url('//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/fonts/glyphicons-halflings-regular.eot');
4
+ src: url('//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),
5
+ url('//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/fonts/glyphicons-halflings-regular.woff2') format('woff2'),
6
+ url('//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/fonts/glyphicons-halflings-regular.woff') format('woff'),
7
+ url('//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/fonts/glyphicons-halflings-regular.ttf') format('truetype'),
8
+ url('//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
9
+ }
10
+
11
+
12
+ .glyphicon{
13
+ position:relative;
14
+ top:1px;
15
+ display:inline-block;
16
+ font-family:'Glyphicons Halflings';
17
+ font-style:normal;
18
+ font-weight:400;
19
+ line-height:1;
20
+ -webkit-font-smoothing:antialiased;
21
+ -moz-osx-font-smoothing:grayscale
22
+ }
23
+
24
+ .glyphicon-asterisk:before{
25
+ content:"\002a"
26
+ }
27
+ .glyphicon-plus:before{
28
+ content:"\002b"
29
+ }
30
+ .glyphicon-eur:before,.glyphicon-euro:before{
31
+ content:"\20ac"
32
+ }
33
+ .glyphicon-minus:before{
34
+ content:"\2212"
35
+ }
36
+ .glyphicon-cloud:before{
37
+ content:"\2601"
38
+ }
39
+ .glyphicon-envelope:before{
40
+ content:"\2709"
41
+ }
42
+ .glyphicon-pencil:before{
43
+ content:"\270f"
44
+ }
45
+ .glyphicon-glass:before{
46
+ content:"\e001"
47
+ }
48
+ .glyphicon-music:before{
49
+ content:"\e002"
50
+ }
51
+ .glyphicon-search:before{
52
+ content:"\e003"
53
+ }
54
+ .glyphicon-heart:before{
55
+ content:"\e005"
56
+ }
57
+ .glyphicon-star:before{
58
+ content:"\e006"
59
+ }
60
+ .glyphicon-star-empty:before{
61
+ content:"\e007"
62
+ }
63
+ .glyphicon-user:before{
64
+ content:"\e008"
65
+ }
66
+ .glyphicon-film:before{
67
+ content:"\e009"
68
+ }
69
+ .glyphicon-th-large:before{
70
+ content:"\e010"
71
+ }
72
+ .glyphicon-th:before{
73
+ content:"\e011"
74
+ }
75
+ .glyphicon-th-list:before{
76
+ content:"\e012"
77
+ }
78
+ .glyphicon-ok:before{
79
+ content:"\e013"
80
+ }
81
+ .glyphicon-remove:before{
82
+ content:"\e014"
83
+ }
84
+ .glyphicon-zoom-in:before{
85
+ content:"\e015"
86
+ }
87
+ .glyphicon-zoom-out:before{
88
+ content:"\e016"
89
+ }
90
+ .glyphicon-off:before{
91
+ content:"\e017"
92
+ }
93
+ .glyphicon-signal:before{
94
+ content:"\e018"
95
+ }
96
+ .glyphicon-cog:before{
97
+ content:"\e019"
98
+ }
99
+ .glyphicon-trash:before{
100
+ content:"\e020"
101
+ }
102
+ .glyphicon-home:before{
103
+ content:"\e021"
104
+ }
105
+ .glyphicon-file:before{
106
+ content:"\e022"
107
+ }
108
+ .glyphicon-time:before{
109
+ content:"\e023"
110
+ }
111
+ .glyphicon-road:before{
112
+ content:"\e024"
113
+ }
114
+ .glyphicon-download-alt:before{
115
+ content:"\e025"
116
+ }
117
+ .glyphicon-download:before{
118
+ content:"\e026"
119
+ }
120
+ .glyphicon-upload:before{
121
+ content:"\e027"
122
+ }
123
+ .glyphicon-inbox:before{
124
+ content:"\e028"
125
+ }
126
+ .glyphicon-play-circle:before{
127
+ content:"\e029"
128
+ }
129
+ .glyphicon-repeat:before{
130
+ content:"\e030"
131
+ }
132
+ .glyphicon-refresh:before{
133
+ content:"\e031"
134
+ }
135
+ .glyphicon-list-alt:before{
136
+ content:"\e032"
137
+ }
138
+ .glyphicon-lock:before{
139
+ content:"\e033"
140
+ }
141
+ .glyphicon-flag:before{
142
+ content:"\e034"
143
+ }
144
+ .glyphicon-headphones:before{
145
+ content:"\e035"
146
+ }
147
+ .glyphicon-volume-off:before{
148
+ content:"\e036"
149
+ }
150
+ .glyphicon-volume-down:before{
151
+ content:"\e037"
152
+ }
153
+ .glyphicon-volume-up:before{
154
+ content:"\e038"
155
+ }
156
+ .glyphicon-qrcode:before{
157
+ content:"\e039"
158
+ }
159
+ .glyphicon-barcode:before{
160
+ content:"\e040"
161
+ }
162
+ .glyphicon-tag:before{
163
+ content:"\e041"
164
+ }
165
+ .glyphicon-tags:before{
166
+ content:"\e042"
167
+ }
168
+ .glyphicon-book:before{
169
+ content:"\e043"
170
+ }
171
+ .glyphicon-bookmark:before{
172
+ content:"\e044"
173
+ }
174
+ .glyphicon-print:before{
175
+ content:"\e045"
176
+ }
177
+ .glyphicon-camera:before{
178
+ content:"\e046"
179
+ }
180
+ .glyphicon-font:before{
181
+ content:"\e047"
182
+ }
183
+ .glyphicon-bold:before{
184
+ content:"\e048"
185
+ }
186
+ .glyphicon-italic:before{
187
+ content:"\e049"
188
+ }
189
+ .glyphicon-text-height:before{
190
+ content:"\e050"
191
+ }
192
+ .glyphicon-text-width:before{
193
+ content:"\e051"
194
+ }
195
+ .glyphicon-align-left:before{
196
+ content:"\e052"
197
+ }
198
+ .glyphicon-align-center:before{
199
+ content:"\e053"
200
+ }
201
+ .glyphicon-align-right:before{
202
+ content:"\e054"
203
+ }
204
+ .glyphicon-align-justify:before{
205
+ content:"\e055"
206
+ }
207
+ .glyphicon-list:before{
208
+ content:"\e056"
209
+ }
210
+ .glyphicon-indent-left:before{
211
+ content:"\e057"
212
+ }
213
+ .glyphicon-indent-right:before{
214
+ content:"\e058"
215
+ }
216
+ .glyphicon-facetime-video:before{
217
+ content:"\e059"
218
+ }
219
+ .glyphicon-picture:before{
220
+ content:"\e060"
221
+ }
222
+ .glyphicon-map-marker:before{
223
+ content:"\e062"
224
+ }
225
+ .glyphicon-adjust:before{
226
+ content:"\e063"
227
+ }
228
+ .glyphicon-tint:before{
229
+ content:"\e064"
230
+ }
231
+ .glyphicon-edit:before{
232
+ content:"\e065"
233
+ }
234
+ .glyphicon-share:before{
235
+ content:"\e066"
236
+ }
237
+ .glyphicon-check:before{
238
+ content:"\e067"
239
+ }
240
+ .glyphicon-move:before{
241
+ content:"\e068"
242
+ }
243
+ .glyphicon-step-backward:before{
244
+ content:"\e069"
245
+ }
246
+ .glyphicon-fast-backward:before{
247
+ content:"\e070"
248
+ }
249
+ .glyphicon-backward:before{
250
+ content:"\e071"
251
+ }
252
+ .glyphicon-play:before{
253
+ content:"\e072"
254
+ }
255
+ .glyphicon-pause:before{
256
+ content:"\e073"
257
+ }
258
+ .glyphicon-stop:before{
259
+ content:"\e074"
260
+ }
261
+ .glyphicon-forward:before{
262
+ content:"\e075"
263
+ }
264
+ .glyphicon-fast-forward:before{
265
+ content:"\e076"
266
+ }
267
+ .glyphicon-step-forward:before{
268
+ content:"\e077"
269
+ }
270
+ .glyphicon-eject:before{
271
+ content:"\e078"
272
+ }
273
+ .glyphicon-chevron-left:before{
274
+ content:"\e079"
275
+ }
276
+ .glyphicon-chevron-right:before{
277
+ content:"\e080"
278
+ }
279
+ .glyphicon-plus-sign:before{
280
+ content:"\e081"
281
+ }
282
+ .glyphicon-minus-sign:before{
283
+ content:"\e082"
284
+ }
285
+ .glyphicon-remove-sign:before{
286
+ content:"\e083"
287
+ }
288
+ .glyphicon-ok-sign:before{
289
+ content:"\e084"
290
+ }
291
+ .glyphicon-question-sign:before{
292
+ content:"\e085"
293
+ }
294
+ .glyphicon-info-sign:before{
295
+ content:"\e086"
296
+ }
297
+ .glyphicon-screenshot:before{
298
+ content:"\e087"
299
+ }
300
+ .glyphicon-remove-circle:before{
301
+ content:"\e088"
302
+ }
303
+ .glyphicon-ok-circle:before{
304
+ content:"\e089"
305
+ }
306
+ .glyphicon-ban-circle:before{
307
+ content:"\e090"
308
+ }
309
+ .glyphicon-arrow-left:before{
310
+ content:"\e091"
311
+ }
312
+ .glyphicon-arrow-right:before{
313
+ content:"\e092"
314
+ }
315
+ .glyphicon-arrow-up:before{
316
+ content:"\e093"
317
+ }
318
+ .glyphicon-arrow-down:before{
319
+ content:"\e094"
320
+ }
321
+ .glyphicon-share-alt:before{
322
+ content:"\e095"
323
+ }
324
+ .glyphicon-resize-full:before{
325
+ content:"\e096"
326
+ }
327
+ .glyphicon-resize-small:before{
328
+ content:"\e097"
329
+ }
330
+ .glyphicon-exclamation-sign:before{
331
+ content:"\e101"
332
+ }
333
+ .glyphicon-gift:before{
334
+ content:"\e102"
335
+ }
336
+ .glyphicon-leaf:before{
337
+ content:"\e103"
338
+ }
339
+ .glyphicon-fire:before{
340
+ content:"\e104"
341
+ }
342
+ .glyphicon-eye-open:before{
343
+ content:"\e105"
344
+ }
345
+ .glyphicon-eye-close:before{
346
+ content:"\e106"
347
+ }
348
+ .glyphicon-warning-sign:before{
349
+ content:"\e107"
350
+ }
351
+ .glyphicon-plane:before{
352
+ content:"\e108"
353
+ }
354
+ .glyphicon-calendar:before{
355
+ content:"\e109"
356
+ }
357
+ .glyphicon-random:before{
358
+ content:"\e110"
359
+ }
360
+ .glyphicon-comment:before{
361
+ content:"\e111"
362
+ }
363
+ .glyphicon-magnet:before{
364
+ content:"\e112"
365
+ }
366
+ .glyphicon-chevron-up:before{
367
+ content:"\e113"
368
+ }
369
+ .glyphicon-chevron-down:before{
370
+ content:"\e114"
371
+ }
372
+ .glyphicon-retweet:before{
373
+ content:"\e115"
374
+ }
375
+ .glyphicon-shopping-cart:before{
376
+ content:"\e116"
377
+ }
378
+ .glyphicon-folder-close:before{
379
+ content:"\e117"
380
+ }
381
+ .glyphicon-folder-open:before{
382
+ content:"\e118"
383
+ }
384
+ .glyphicon-resize-vertical:before{
385
+ content:"\e119"
386
+ }
387
+ .glyphicon-resize-horizontal:before{
388
+ content:"\e120"
389
+ }
390
+ .glyphicon-hdd:before{
391
+ content:"\e121"
392
+ }
393
+ .glyphicon-bullhorn:before{
394
+ content:"\e122"
395
+ }
396
+ .glyphicon-bell:before{
397
+ content:"\e123"
398
+ }
399
+ .glyphicon-certificate:before{
400
+ content:"\e124"
401
+ }
402
+ .glyphicon-thumbs-up:before{
403
+ content:"\e125"
404
+ }
405
+ .glyphicon-thumbs-down:before{
406
+ content:"\e126"
407
+ }
408
+ .glyphicon-hand-right:before{
409
+ content:"\e127"
410
+ }
411
+ .glyphicon-hand-left:before{
412
+ content:"\e128"
413
+ }
414
+ .glyphicon-hand-up:before{
415
+ content:"\e129"
416
+ }
417
+ .glyphicon-hand-down:before{
418
+ content:"\e130"
419
+ }
420
+ .glyphicon-circle-arrow-right:before{
421
+ content:"\e131"
422
+ }
423
+ .glyphicon-circle-arrow-left:before{
424
+ content:"\e132"
425
+ }
426
+ .glyphicon-circle-arrow-up:before{
427
+ content:"\e133"
428
+ }
429
+ .glyphicon-circle-arrow-down:before{
430
+ content:"\e134"
431
+ }
432
+ .glyphicon-globe:before{
433
+ content:"\e135"
434
+ }
435
+ .glyphicon-wrench:before{
436
+ content:"\e136"
437
+ }
438
+ .glyphicon-tasks:before{
439
+ content:"\e137"
440
+ }
441
+ .glyphicon-filter:before{
442
+ content:"\e138"
443
+ }
444
+ .glyphicon-briefcase:before{
445
+ content:"\e139"
446
+ }
447
+ .glyphicon-fullscreen:before{
448
+ content:"\e140"
449
+ }
450
+ .glyphicon-dashboard:before{
451
+ content:"\e141"
452
+ }
453
+ .glyphicon-paperclip:before{
454
+ content:"\e142"
455
+ }
456
+ .glyphicon-heart-empty:before{
457
+ content:"\e143"
458
+ }
459
+ .glyphicon-link:before{
460
+ content:"\e144"
461
+ }
462
+ .glyphicon-phone:before{
463
+ content:"\e145"
464
+ }
465
+ .glyphicon-pushpin:before{
466
+ content:"\e146"
467
+ }
468
+ .glyphicon-usd:before{
469
+ content:"\e148"
470
+ }
471
+ .glyphicon-gbp:before{
472
+ content:"\e149"
473
+ }
474
+ .glyphicon-sort:before{
475
+ content:"\e150"
476
+ }
477
+ .glyphicon-sort-by-alphabet:before{
478
+ content:"\e151"
479
+ }
480
+ .glyphicon-sort-by-alphabet-alt:before{
481
+ content:"\e152"
482
+ }
483
+ .glyphicon-sort-by-order:before{
484
+ content:"\e153"
485
+ }
486
+ .glyphicon-sort-by-order-alt:before{
487
+ content:"\e154"
488
+ }
489
+ .glyphicon-sort-by-attributes:before{
490
+ content:"\e155"
491
+ }
492
+ .glyphicon-sort-by-attributes-alt:before{
493
+ content:"\e156"
494
+ }
495
+ .glyphicon-unchecked:before{
496
+ content:"\e157"
497
+ }
498
+ .glyphicon-expand:before{
499
+ content:"\e158"
500
+ }
501
+ .glyphicon-collapse-down:before{
502
+ content:"\e159"
503
+ }
504
+ .glyphicon-collapse-up:before{
505
+ content:"\e160"
506
+ }
507
+ .glyphicon-log-in:before{
508
+ content:"\e161"
509
+ }
510
+ .glyphicon-flash:before{
511
+ content:"\e162"
512
+ }
513
+ .glyphicon-log-out:before{
514
+ content:"\e163"
515
+ }
516
+ .glyphicon-new-window:before{
517
+ content:"\e164"
518
+ }
519
+ .glyphicon-record:before{
520
+ content:"\e165"
521
+ }
522
+ .glyphicon-save:before{
523
+ content:"\e166"
524
+ }
525
+ .glyphicon-open:before{
526
+ content:"\e167"
527
+ }
528
+ .glyphicon-saved:before{
529
+ content:"\e168"
530
+ }
531
+ .glyphicon-import:before{
532
+ content:"\e169"
533
+ }
534
+ .glyphicon-export:before{
535
+ content:"\e170"
536
+ }
537
+ .glyphicon-send:before{
538
+ content:"\e171"
539
+ }
540
+ .glyphicon-floppy-disk:before{
541
+ content:"\e172"
542
+ }
543
+ .glyphicon-floppy-saved:before{
544
+ content:"\e173"
545
+ }
546
+ .glyphicon-floppy-remove:before{
547
+ content:"\e174"
548
+ }
549
+ .glyphicon-floppy-save:before{
550
+ content:"\e175"
551
+ }
552
+ .glyphicon-floppy-open:before{
553
+ content:"\e176"
554
+ }
555
+ .glyphicon-credit-card:before{
556
+ content:"\e177"
557
+ }
558
+ .glyphicon-transfer:before{
559
+ content:"\e178"
560
+ }
561
+ .glyphicon-cutlery:before{
562
+ content:"\e179"
563
+ }
564
+ .glyphicon-header:before{
565
+ content:"\e180"
566
+ }
567
+ .glyphicon-compressed:before{
568
+ content:"\e181"
569
+ }
570
+ .glyphicon-earphone:before{
571
+ content:"\e182"
572
+ }
573
+ .glyphicon-phone-alt:before{
574
+ content:"\e183"
575
+ }
576
+ .glyphicon-tower:before{
577
+ content:"\e184"
578
+ }
579
+ .glyphicon-stats:before{
580
+ content:"\e185"
581
+ }
582
+ .glyphicon-sd-video:before{
583
+ content:"\e186"
584
+ }
585
+ .glyphicon-hd-video:before{
586
+ content:"\e187"
587
+ }
588
+ .glyphicon-subtitles:before{
589
+ content:"\e188"
590
+ }
591
+ .glyphicon-sound-stereo:before{
592
+ content:"\e189"
593
+ }
594
+ .glyphicon-sound-dolby:before{
595
+ content:"\e190"
596
+ }
597
+ .glyphicon-sound-5-1:before{
598
+ content:"\e191"
599
+ }
600
+ .glyphicon-sound-6-1:before{
601
+ content:"\e192"
602
+ }
603
+ .glyphicon-sound-7-1:before{
604
+ content:"\e193"
605
+ }
606
+ .glyphicon-copyright-mark:before{
607
+ content:"\e194"
608
+ }
609
+ .glyphicon-registration-mark:before{
610
+ content:"\e195"
611
+ }
612
+ .glyphicon-cloud-download:before{
613
+ content:"\e197"
614
+ }
615
+ .glyphicon-cloud-upload:before{
616
+ content:"\e198"
617
+ }
618
+ .glyphicon-tree-conifer:before{
619
+ content:"\e199"
620
+ }
621
+ .glyphicon-tree-deciduous:before{
622
+ content:"\e200"
623
+ }
624
+ .glyphicon-cd:before{
625
+ content:"\e201"
626
+ }
627
+ .glyphicon-save-file:before{
628
+ content:"\e202"
629
+ }
630
+ .glyphicon-open-file:before{
631
+ content:"\e203"
632
+ }
633
+ .glyphicon-level-up:before{
634
+ content:"\e204"
635
+ }
636
+ .glyphicon-copy:before{
637
+ content:"\e205"
638
+ }
639
+ .glyphicon-paste:before{
640
+ content:"\e206"
641
+ }
642
+ .glyphicon-alert:before{
643
+ content:"\e209"
644
+ }
645
+ .glyphicon-equalizer:before{
646
+ content:"\e210"
647
+ }
648
+ .glyphicon-king:before{
649
+ content:"\e211"
650
+ }
651
+ .glyphicon-queen:before{
652
+ content:"\e212"
653
+ }
654
+ .glyphicon-pawn:before{
655
+ content:"\e213"
656
+ }
657
+ .glyphicon-bishop:before{
658
+ content:"\e214"
659
+ }
660
+ .glyphicon-knight:before{
661
+ content:"\e215"
662
+ }
663
+ .glyphicon-baby-formula:before{
664
+ content:"\e216"
665
+ }
666
+ .glyphicon-tent:before{
667
+ content:"\26fa"
668
+ }
669
+ .glyphicon-blackboard:before{
670
+ content:"\e218"
671
+ }
672
+ .glyphicon-bed:before{
673
+ content:"\e219"
674
+ }
675
+ .glyphicon-apple:before{
676
+ content:"\f8ff"
677
+ }
678
+ .glyphicon-erase:before{
679
+ content:"\e221"
680
+ }
681
+ .glyphicon-hourglass:before{
682
+ content:"\231b"
683
+ }
684
+ .glyphicon-lamp:before{
685
+ content:"\e223"
686
+ }
687
+ .glyphicon-duplicate:before{
688
+ content:"\e224"
689
+ }
690
+ .glyphicon-piggy-bank:before{
691
+ content:"\e225"
692
+ }
693
+ .glyphicon-scissors:before{
694
+ content:"\e226"
695
+ }
696
+ .glyphicon-bitcoin:before{
697
+ content:"\e227"
698
+ }
699
+ .glyphicon-btc:before{
700
+ content:"\e227"
701
+ }
702
+ .glyphicon-xbt:before{
703
+ content:"\e227"
704
+ }
705
+ .glyphicon-yen:before{
706
+ content:"\00a5"
707
+ }
708
+ .glyphicon-jpy:before{
709
+ content:"\00a5"
710
+ }
711
+ .glyphicon-ruble:before{
712
+ content:"\20bd"
713
+ }
714
+ .glyphicon-rub:before{
715
+ content:"\20bd"
716
+ }
717
+ .glyphicon-scale:before{
718
+ content:"\e230"
719
+ }
720
+ .glyphicon-ice-lolly:before{
721
+ content:"\e231"
722
+ }
723
+ .glyphicon-ice-lolly-tasted:before{
724
+ content:"\e232"
725
+ }
726
+ .glyphicon-education:before{
727
+ content:"\e233"
728
+ }
729
+ .glyphicon-option-horizontal:before{
730
+ content:"\e234"
731
+ }
732
+ .glyphicon-option-vertical:before{
733
+ content:"\e235"
734
+ }
735
+ .glyphicon-menu-hamburger:before{
736
+ content:"\e236"
737
+ }
738
+ .glyphicon-modal-window:before{
739
+ content:"\e237"
740
+ }
741
+ .glyphicon-oil:before{
742
+ content:"\e238"
743
+ }
744
+ .glyphicon-grain:before{
745
+ content:"\e239"
746
+ }
747
+ .glyphicon-sunglasses:before{
748
+ content:"\e240"
749
+ }
750
+ .glyphicon-text-size:before{
751
+ content:"\e241"
752
+ }
753
+ .glyphicon-text-color:before{
754
+ content:"\e242"
755
+ }
756
+ .glyphicon-text-background:before{
757
+ content:"\e243"
758
+ }
759
+ .glyphicon-object-align-top:before{
760
+ content:"\e244"
761
+ }
762
+ .glyphicon-object-align-bottom:before{
763
+ content:"\e245"
764
+ }
765
+ .glyphicon-object-align-horizontal:before{
766
+ content:"\e246"
767
+ }
768
+ .glyphicon-object-align-left:before{
769
+ content:"\e247"
770
+ }
771
+ .glyphicon-object-align-vertical:before{
772
+ content:"\e248"
773
+ }
774
+ .glyphicon-object-align-right:before{
775
+ content:"\e249"
776
+ }
777
+ .glyphicon-triangle-right:before{
778
+ content:"\e250"
779
+ }
780
+ .glyphicon-triangle-left:before{
781
+ content:"\e251"
782
+ }
783
+ .glyphicon-triangle-bottom:before{
784
+ content:"\e252"
785
+ }
786
+ .glyphicon-triangle-top:before{
787
+ content:"\e253"
788
+ }
789
+ .glyphicon-console:before{
790
+ content:"\e254"
791
+ }
792
+ .glyphicon-superscript:before{
793
+ content:"\e255"
794
+ }
795
+ .glyphicon-subscript:before{
796
+ content:"\e256"
797
+ }
798
+ .glyphicon-menu-left:before{
799
+ content:"\e257"
800
+ }
801
+ .glyphicon-menu-right:before{
802
+ content:"\e258"
803
+ }
804
+ .glyphicon-menu-down:before{
805
+ content:"\e259"
806
+ }
807
+ .glyphicon-menu-up:before{
808
+ content:"\e260"
809
+ }
810
+
v4.0.0/assets/admin/scss/selectize.css ADDED
@@ -0,0 +1,324 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * selectize.css (v0.12.4)
3
+ * Copyright (c) 2013–2015 Brian Reavis & contributors
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
6
+ * file except in compliance with the License. You may obtain a copy of the License at:
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under
10
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ * ANY KIND, either express or implied. See the License for the specific language
12
+ * governing permissions and limitations under the License.
13
+ *
14
+ * @author Brian Reavis <brian@thirdroute.com>
15
+ */
16
+
17
+ .selectize-control.plugin-drag_drop.multi > .selectize-input > div.ui-sortable-placeholder {
18
+ visibility: visible !important;
19
+ background: #f2f2f2 !important;
20
+ background: rgba(0, 0, 0, 0.06) !important;
21
+ border: 0 none !important;
22
+ -webkit-box-shadow: inset 0 0 12px 4px #ffffff;
23
+ box-shadow: inset 0 0 12px 4px #ffffff;
24
+ }
25
+ .selectize-control.plugin-drag_drop .ui-sortable-placeholder::after {
26
+ content: '!';
27
+ visibility: hidden;
28
+ }
29
+ .selectize-control.plugin-drag_drop .ui-sortable-helper {
30
+ -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
31
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
32
+ }
33
+ .selectize-dropdown-header {
34
+ position: relative;
35
+ padding: 5px 8px;
36
+ border-bottom: 1px solid #d0d0d0;
37
+ background: #f8f8f8;
38
+ -webkit-border-radius: 3px 3px 0 0;
39
+ -moz-border-radius: 3px 3px 0 0;
40
+ border-radius: 3px 3px 0 0;
41
+ }
42
+ .selectize-dropdown-header-close {
43
+ position: absolute;
44
+ right: 8px;
45
+ top: 50%;
46
+ color: #303030;
47
+ opacity: 0.4;
48
+ margin-top: -12px;
49
+ line-height: 20px;
50
+ font-size: 20px !important;
51
+ }
52
+ .selectize-dropdown-header-close:hover {
53
+ color: #000000;
54
+ }
55
+ .selectize-dropdown.plugin-optgroup_columns .optgroup {
56
+ border-right: 1px solid #f2f2f2;
57
+ border-top: 0 none;
58
+ float: left;
59
+ -webkit-box-sizing: border-box;
60
+ -moz-box-sizing: border-box;
61
+ box-sizing: border-box;
62
+ }
63
+ .selectize-dropdown.plugin-optgroup_columns .optgroup:last-child {
64
+ border-right: 0 none;
65
+ }
66
+ .selectize-dropdown.plugin-optgroup_columns .optgroup:before {
67
+ display: none;
68
+ }
69
+ .selectize-dropdown.plugin-optgroup_columns .optgroup-header {
70
+ border-top: 0 none;
71
+ }
72
+ .selectize-control.plugin-remove_button [data-value] {
73
+ position: relative;
74
+ padding-right: 24px !important;
75
+ }
76
+ .selectize-control.plugin-remove_button [data-value] .remove {
77
+ z-index: 1;
78
+ /* fixes ie bug (see #392) */
79
+ position: absolute;
80
+ top: 0;
81
+ right: 0;
82
+ bottom: 0;
83
+ width: 17px;
84
+ text-align: center;
85
+ font-weight: bold;
86
+ font-size: 12px;
87
+ color: inherit;
88
+ text-decoration: none;
89
+ vertical-align: middle;
90
+ display: inline-block;
91
+ padding: 2px 0 0 0;
92
+ border-left: 1px solid #d0d0d0;
93
+ -webkit-border-radius: 0 2px 2px 0;
94
+ -moz-border-radius: 0 2px 2px 0;
95
+ border-radius: 0 2px 2px 0;
96
+ -webkit-box-sizing: border-box;
97
+ -moz-box-sizing: border-box;
98
+ box-sizing: border-box;
99
+ }
100
+ .selectize-control.plugin-remove_button [data-value] .remove:hover {
101
+ background: rgba(0, 0, 0, 0.05);
102
+ }
103
+ .selectize-control.plugin-remove_button [data-value].active .remove {
104
+ border-left-color: #cacaca;
105
+ }
106
+ .selectize-control.plugin-remove_button .disabled [data-value] .remove:hover {
107
+ background: none;
108
+ }
109
+ .selectize-control.plugin-remove_button .disabled [data-value] .remove {
110
+ border-left-color: #ffffff;
111
+ }
112
+ .selectize-control.plugin-remove_button .remove-single {
113
+ position: absolute;
114
+ right: 28px;
115
+ top: 6px;
116
+ font-size: 23px;
117
+ }
118
+ .selectize-control {
119
+ position: relative;
120
+ }
121
+ .selectize-dropdown,
122
+ .selectize-input,
123
+ .selectize-input input {
124
+ color: #303030;
125
+ font-family: inherit;
126
+ font-size: 13px;
127
+ line-height: 18px;
128
+ -webkit-font-smoothing: inherit;
129
+ }
130
+ .selectize-input,
131
+ .selectize-control.single .selectize-input.input-active {
132
+ background: #ffffff;
133
+ cursor: text;
134
+ display: inline-block;
135
+ }
136
+ .selectize-input {
137
+ border: 1px solid #d0d0d0;
138
+ padding: 8px 8px;
139
+ display: inline-block;
140
+ width: 100%;
141
+ overflow: hidden;
142
+ position: relative;
143
+ z-index: 1;
144
+ -webkit-box-sizing: border-box;
145
+ -moz-box-sizing: border-box;
146
+ box-sizing: border-box;
147
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
148
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
149
+ -webkit-border-radius: 3px;
150
+ -moz-border-radius: 3px;
151
+ border-radius: 3px;
152
+ }
153
+ .selectize-control.multi .selectize-input.has-items {
154
+ padding: 6px 8px 3px;
155
+ }
156
+ .selectize-input.full {
157
+ background-color: #ffffff;
158
+ }
159
+ .selectize-input.disabled,
160
+ .selectize-input.disabled * {
161
+ cursor: default !important;
162
+ }
163
+ .selectize-input.focus {
164
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15);
165
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15);
166
+ }
167
+ .selectize-input.dropdown-active {
168
+ -webkit-border-radius: 3px 3px 0 0;
169
+ -moz-border-radius: 3px 3px 0 0;
170
+ border-radius: 3px 3px 0 0;
171
+ }
172
+ .selectize-input > * {
173
+ vertical-align: baseline;
174
+ display: -moz-inline-stack;
175
+ display: inline-block;
176
+ zoom: 1;
177
+ *display: inline;
178
+ }
179
+ .selectize-control.multi .selectize-input > div {
180
+ cursor: pointer;
181
+ margin: 0 3px 3px 0;
182
+ padding: 2px 6px;
183
+ background: #f2f2f2;
184
+ color: #303030;
185
+ border: 0 solid #d0d0d0;
186
+ }
187
+ .selectize-control.multi .selectize-input > div.active {
188
+ background: #e8e8e8;
189
+ color: #303030;
190
+ border: 0 solid #cacaca;
191
+ }
192
+ .selectize-control.multi .selectize-input.disabled > div,
193
+ .selectize-control.multi .selectize-input.disabled > div.active {
194
+ color: #7d7d7d;
195
+ background: #ffffff;
196
+ border: 0 solid #ffffff;
197
+ }
198
+ .selectize-input > input {
199
+ display: inline-block !important;
200
+ padding: 0 !important;
201
+ min-height: 0 !important;
202
+ max-height: none !important;
203
+ max-width: 100% !important;
204
+ margin: 0 2px 0 0 !important;
205
+ text-indent: 0 !important;
206
+ border: 0 none !important;
207
+ background: none !important;
208
+ line-height: inherit !important;
209
+ -webkit-user-select: auto !important;
210
+ -webkit-box-shadow: none !important;
211
+ box-shadow: none !important;
212
+ }
213
+ .selectize-input > input::-ms-clear {
214
+ display: none;
215
+ }
216
+ .selectize-input > input:focus {
217
+ outline: none !important;
218
+ }
219
+ .selectize-input::after {
220
+ content: ' ';
221
+ display: block;
222
+ clear: left;
223
+ }
224
+ .selectize-input.dropdown-active::before {
225
+ content: ' ';
226
+ display: block;
227
+ position: absolute;
228
+ background: #f0f0f0;
229
+ height: 1px;
230
+ bottom: 0;
231
+ left: 0;
232
+ right: 0;
233
+ }
234
+ .selectize-dropdown {
235
+ position: absolute;
236
+ z-index: 10;
237
+ border: 1px solid #d0d0d0;
238
+ background: #ffffff;
239
+ margin: -1px 0 0 0;
240
+ border-top: 0 none;
241
+ -webkit-box-sizing: border-box;
242
+ -moz-box-sizing: border-box;
243
+ box-sizing: border-box;
244
+ -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
245
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
246
+ -webkit-border-radius: 0 0 3px 3px;
247
+ -moz-border-radius: 0 0 3px 3px;
248
+ border-radius: 0 0 3px 3px;
249
+ }
250
+ .selectize-dropdown [data-selectable] {
251
+ cursor: pointer;
252
+ overflow: hidden;
253
+ }
254
+ .selectize-dropdown [data-selectable] .highlight {
255
+ background: rgba(125, 168, 208, 0.2);
256
+ -webkit-border-radius: 1px;
257
+ -moz-border-radius: 1px;
258
+ border-radius: 1px;
259
+ }
260
+ .selectize-dropdown [data-selectable],
261
+ .selectize-dropdown .optgroup-header {
262
+ padding: 5px 8px;
263
+ }
264
+ .selectize-dropdown .optgroup:first-child .optgroup-header {
265
+ border-top: 0 none;
266
+ }
267
+ .selectize-dropdown .optgroup-header {
268
+ color: #303030;
269
+ background: #ffffff;
270
+ cursor: default;
271
+ }
272
+ .selectize-dropdown .active {
273
+ background-color: #f5fafd;
274
+ color: #495c68;
275
+ }
276
+ .selectize-dropdown .active.create {
277
+ color: #495c68;
278
+ }
279
+ .selectize-dropdown .create {
280
+ color: rgba(48, 48, 48, 0.5);
281
+ }
282
+ .selectize-dropdown-content {
283
+ overflow-y: auto;
284
+ overflow-x: hidden;
285
+ max-height: 200px;
286
+ -webkit-overflow-scrolling: touch;
287
+ }
288
+ .selectize-control.single .selectize-input,
289
+ .selectize-control.single .selectize-input input {
290
+ cursor: pointer;
291
+ }
292
+ .selectize-control.single .selectize-input.input-active,
293
+ .selectize-control.single .selectize-input.input-active input {
294
+ cursor: text;
295
+ }
296
+ .selectize-control.single .selectize-input:after {
297
+ content: ' ';
298
+ display: block;
299
+ position: absolute;
300
+ top: 50%;
301
+ right: 15px;
302
+ margin-top: -3px;
303
+ width: 0;
304
+ height: 0;
305
+ border-style: solid;
306
+ border-width: 5px 5px 0 5px;
307
+ border-color: #808080 transparent transparent transparent;
308
+ }
309
+ .selectize-control.single .selectize-input.dropdown-active:after {
310
+ margin-top: -4px;
311
+ border-width: 0 5px 5px 5px;
312
+ border-color: transparent transparent #808080 transparent;
313
+ }
314
+ .selectize-control.rtl.single .selectize-input:after {
315
+ left: 15px;
316
+ right: auto;
317
+ }
318
+ .selectize-control.rtl .selectize-input > input {
319
+ margin: 0 4px 0 -2px !important;
320
+ }
321
+ .selectize-control .selectize-input.disabled {
322
+ opacity: 0.5;
323
+ background-color: #fafafa;
324
+ }
v4.0.0/assets/images/no-preview.jpeg ADDED
Binary file
v4.0.0/assets/images/placeholder.png ADDED
Binary file
v4.0.0/assets/images/rmp-logo.png ADDED
Binary file
v4.0.0/assets/js/rmp-menu.js ADDED
@@ -0,0 +1,354 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This file contain the scrips for menu frontend.
3
+ * @author ExpressTech System
4
+ *
5
+ * @since 4.0.0
6
+ */
7
+
8
+ jQuery( document ).ready( function( jQuery ) {
9
+
10
+ /**
11
+ * RmpMenu Class
12
+ * This RMP class is handling the frontend events and action on menu elements.
13
+ * @since 4.0.0
14
+ * @access public
15
+ *
16
+ * @class RmpMenu
17
+ */
18
+ class RmpMenu {
19
+
20
+ /**
21
+ * This is constructor function which is initialize the elements and options.
22
+ * @access public
23
+ * @since 4.0.0
24
+ * @param {Array} options List of options.
25
+ */
26
+ constructor( options ) {
27
+ RmpMenu.activeToggleClass = 'is-active';
28
+ RmpMenu.openContainerClass = 'rmp-menu-open';
29
+ RmpMenu.activeSubMenuArrowClass = 'rmp-menu-subarrow-active';
30
+ RmpMenu.subMenuClass = '.rmp-submenu';
31
+
32
+ this.options = options;
33
+ this.menuId = this.options['menu_id'];
34
+ this.trigger = '#rmp_menu_trigger-' + this.menuId;
35
+
36
+ this.isOpen = false;
37
+
38
+ this.container = '#rmp-container-' + this.menuId;
39
+ this.headerBar = '#rmp-header-bar-' + this.menuId;
40
+ this.menuWrap = 'ul#rmp-menu-'+ this.menuId;
41
+ this.subMenuArrow = '.rmp-menu-subarrow';
42
+ this.wrapper = '.rmp-container';
43
+ this.linkElement = '.rmp-menu-item-link';
44
+ this.pageWrapper = this.options['page_wrapper'];
45
+ this.use_desktop_menu = this.options['use_desktop_menu'];
46
+ this.originalHeight = '',
47
+ this.animationSpeed = this.options['animation_speed'] * 1000;
48
+ this.hamburgerBreakpoint = this.options['tablet_breakpoint'];
49
+ this.subMenuTransitionTime = this.options['sub_menu_speed'] * 1000;
50
+
51
+ if ( this.options['button_click_trigger'].length > 0 ) {
52
+ this.trigger = this.trigger +' , '+ this.options['button_click_trigger'];
53
+ }
54
+
55
+ this.init();
56
+ }
57
+
58
+ /**
59
+ * This function register the events and initiate the menu settings.
60
+ */
61
+ init() {
62
+ const self = this;
63
+
64
+ /**
65
+ * Register click event of trigger.
66
+ * @fires click
67
+ */
68
+ jQuery( this.trigger ).on( 'click', function( e ) {
69
+ e.stopPropagation();
70
+ self.triggerMenu();
71
+ } );
72
+
73
+
74
+
75
+ // Show/Hide sub menu item when click on item toggle.
76
+ jQuery( self.container ).find( self.subMenuArrow ).on( 'click', function( e ) {
77
+ e.preventDefault();
78
+ e.stopPropagation();
79
+ self.triggerSubArrow( this );
80
+ });
81
+
82
+ if ( 'on' == self.options['menu_close_on_body_click'] ) {
83
+ jQuery( document ).on( 'click', 'body', function ( e ) {
84
+ if ( jQuery( window ).width() < self.hamburgerBreakpoint ) {
85
+ if ( self.isOpen ) {
86
+ if ( jQuery( e.target ).closest( self.container ).length || jQuery( e.target ).closest( self.target ).length ) {
87
+ return;
88
+ }
89
+ }
90
+ self.closeMenu();
91
+ }
92
+ });
93
+ }
94
+
95
+ /**
96
+ * Close the menu when click on menu item link before load.
97
+ */
98
+ if ( self.options['menu_close_on_link_click'] == 'on') {
99
+
100
+ jQuery( self.linkElement ).on( 'click', function(e) {
101
+
102
+ if( jQuery(window).width() < self.hamburgerBreakpoint ) {
103
+ e.preventDefault();
104
+
105
+ // When close menu on parent clicks is on.
106
+ if ( self.options['menu_item_click_to_trigger_submenu'] == 'on' ) {
107
+ if( jQuery(this).is( '.rmp-menu-item-has-children > ' + self.linkElement ) ) {
108
+ return;
109
+ }
110
+ }
111
+
112
+ let _href = jQuery(this).attr('href');
113
+ let _target = ( typeof jQuery(this).attr('target') ) == 'undefined' ? '_self' : jQuery(this).attr('target');
114
+
115
+ if( self.isOpen ) {
116
+ if( jQuery(e.target).closest(this.subMenuArrow).length) {
117
+ return;
118
+ }
119
+ if( typeof _href != 'undefined' ) {
120
+ self.closeMenu();
121
+ setTimeout(function() {
122
+ window.open( _href, _target);
123
+ }, self.animationSpeed);
124
+ }
125
+ }
126
+ }
127
+ });
128
+ }
129
+
130
+ // Expand Sub items on Parent Item Click.
131
+ if ( 'on' == self.options['menu_item_click_to_trigger_submenu'] ) {
132
+ jQuery( '.rmp-menu-item-has-children > ' + self.linkElement ).on( 'click', function(e) {
133
+ if ( jQuery(window).width() < self.hamburgerBreakpoint ) {
134
+ e.preventDefault();
135
+ self.triggerSubArrow(
136
+ jQuery(this).children( '.rmp-menu-subarrow' ).first()
137
+ );
138
+ }
139
+ });
140
+ }
141
+ }
142
+ /**
143
+ * Set push translate for toggle and page wrapper.
144
+ */
145
+ setWrapperTranslate() {
146
+ let translate = '';
147
+ switch( this.options['menu_appear_from'] ) {
148
+ case 'left':
149
+ translate = 'translateX(' + this.menuWidth() + 'px)';
150
+ break;
151
+ case 'right':
152
+ translate = 'translateX(-' + this.menuWidth() + 'px)';
153
+ break;
154
+ case 'top':
155
+ translate = 'translateY(' + this.wrapperHeight() + 'px)';
156
+ break;
157
+ case 'bottom':
158
+ translate = 'translateY(-' + this.menuHeight() + 'px)';
159
+ break;
160
+ }
161
+
162
+ if ( this.options['animation_type'] == 'push' ) {
163
+ jQuery(this.pageWrapper).css( { 'transform':translate } );
164
+ }
165
+
166
+ if ( this.options['button_push_with_animation'] == 'on' ) {
167
+ jQuery( this.trigger ).css( { 'transform' : translate } );
168
+ }
169
+
170
+ }
171
+
172
+ /**
173
+ * Clear push translate on button and page wrapper.
174
+ */
175
+ clearWrapperTranslate() {
176
+
177
+ if ( this.options['animation_type'] == 'push' ) {
178
+ jQuery(this.pageWrapper).css( { 'transform' : '' } );
179
+ }
180
+
181
+ if ( this.options['button_push_with_animation'] == 'on' ) {
182
+ jQuery( this.trigger ).css( { 'transform' : '' } );
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Function to fadeIn the hamburger menu container.
188
+ */
189
+ fadeMenuIn() {
190
+ jQuery(this.container).fadeIn(this.animationSpeed);
191
+ }
192
+
193
+ /**
194
+ * Function to fadeOut the hamburger menu container.
195
+ */
196
+ fadeMenuOut() {
197
+ jQuery(this.container)
198
+ .fadeOut(this.animationSpeed, function() {
199
+ jQuery(this).css('display', '');
200
+ });
201
+ }
202
+
203
+ /**
204
+ * Function is use to open the hamburger menu.
205
+ *
206
+ * @since 4.0.0
207
+ */
208
+ openMenu() {
209
+ var self = this;
210
+ jQuery(this.trigger).addClass(RmpMenu.activeToggleClass);
211
+ jQuery(this.container).addClass(RmpMenu.openContainerClass);
212
+
213
+ //this.pushMenuTrigger();
214
+
215
+ if ( this.options['animation_type'] == 'fade'){
216
+ this.fadeMenuIn();
217
+ } else {
218
+ this.setWrapperTranslate();
219
+ }
220
+
221
+ this.isOpen = true;
222
+ }
223
+
224
+ /**
225
+ * Function is use to close the hamburger menu.
226
+ *
227
+ * @since 4.0.0
228
+ */
229
+ closeMenu() {
230
+ jQuery(this.trigger).removeClass(RmpMenu.activeToggleClass);
231
+ jQuery(this.container).removeClass(RmpMenu.openContainerClass);
232
+
233
+ if ( this.options['animation_type'] == 'fade') {
234
+ this.fadeMenuOut();
235
+ } else {
236
+ this.clearWrapperTranslate();
237
+ }
238
+
239
+ this.isOpen = false;
240
+ }
241
+
242
+ /**
243
+ * Function is responsible for checking the menu is open or close.
244
+ *
245
+ * @since 4.0.0
246
+ * @param {Event} e
247
+ */
248
+ triggerMenu() {
249
+ this.isOpen ? this.closeMenu() : this.openMenu();
250
+ }
251
+
252
+ triggerSubArrow( subArrow ) {
253
+ var self = this;
254
+ var sub_menu = jQuery( subArrow ).parent().siblings( RmpMenu.subMenuClass );
255
+
256
+ //Accordion animation.
257
+ if ( self.options['accordion_animation'] == 'on' ) {
258
+ // Get Top Most Parent and the siblings.
259
+ var top_siblings = sub_menu.parents('.rmp-menu-item-has-children').last().siblings('.rmp-menu-item-has-children');
260
+ var first_siblings = sub_menu.parents('.rmp-menu-item-has-children').first().siblings('.rmp-menu-item-has-children');
261
+
262
+ // Close up just the top level parents to key the rest as it was.
263
+ top_siblings.children('.rmp-submenu').slideUp(self.subMenuTransitionTime, 'linear').removeClass('rmp-submenu-open');
264
+
265
+ // Set each parent arrow to inactive.
266
+ top_siblings.each(function() {
267
+ jQuery(this).find(self.subMenuArrow).first().html(self.options['inactive_toggle_contents']);
268
+ jQuery(this).find(self.subMenuArrow).first().removeClass(RmpMenu.activeSubMenuArrowClass);
269
+ });
270
+
271
+ // Now Repeat for the current item siblings.
272
+ first_siblings.children('.rmp-submenu').slideUp(self.subMenuTransitionTime, 'linear').removeClass('rmp-submenu-open');
273
+ first_siblings.each(function() {
274
+ jQuery(this).find(self.subMenuArrow).first().html(self.options['inactive_toggle_contents']);
275
+ jQuery(this).find(self.subMenuArrow).first().removeClass(RmpMenu.activeSubMenuArrowClass);
276
+ });
277
+ }
278
+
279
+ // Active sub menu as default behavior.
280
+ if( sub_menu.hasClass('rmp-submenu-open') ) {
281
+ sub_menu.slideUp(self.subMenuTransitionTime, 'linear',function() {
282
+ jQuery(this).css( 'display', '' );
283
+ } ).removeClass('rmp-submenu-open');
284
+ jQuery( subArrow ).html( self.options['inactive_toggle_contents'] );
285
+ jQuery( subArrow ).removeClass(RmpMenu.activeSubMenuArrowClass);
286
+ } else {
287
+ sub_menu.slideDown(self.subMenuTransitionTime, 'linear').addClass( 'rmp-submenu-open' );
288
+ jQuery( subArrow ).html(self.options['active_toggle_contents'] );
289
+ jQuery( subArrow ).addClass(RmpMenu.activeSubMenuArrowClass);
290
+ }
291
+
292
+ }
293
+
294
+ /**
295
+ * Function to add tranform style on trigger.
296
+ *
297
+ * @version 4.0.0
298
+ *
299
+ * @param {Event} e Event object.
300
+ */
301
+ pushMenuTrigger( e ) {
302
+ if ( 'on' == this.options['button_push_with_animation'] ) {
303
+ jQuery( this.trigger ).css( { 'transform' : this.menuWidth() } );
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Returns the height of container.
309
+ *
310
+ * @version 4.0.0
311
+ *
312
+ * @return Number
313
+ */
314
+ menuHeight() {
315
+ return jQuery( this.container ).height();
316
+ }
317
+
318
+ /**
319
+ * Returns the width of the container.
320
+ *
321
+ * @version 4.0.0
322
+ *
323
+ * @return Number
324
+ */
325
+ menuWidth() {
326
+ return jQuery( this.container ).width();
327
+ }
328
+
329
+ wrapperHeight() {
330
+ return jQuery( this.wrapper ).height();
331
+ }
332
+
333
+ backUpSlide( backButton ) {
334
+ let translateTo = parseInt( jQuery( this.menuWrap )[0].style.transform.replace( /^\D+/g, '' ) ) - 100;
335
+ jQuery( this.menuWrap ).css( { 'transform': 'translateX(-' + translateTo + '%)' } );
336
+ let previousSubmenuHeight = jQuery( backButton ).parent( 'ul' ).parent( 'li' ).parent( '.rmp-submenu' ).height();
337
+ if ( ! previousSubmenuHeight ) {
338
+ jQuery( this.menuWrap ).css( { 'height': this.originalHeight } );
339
+ } else {
340
+ jQuery( this.menuWrap + this.menuId ).css( { 'height': previousSubmenuHeight + 'px' } );
341
+ }
342
+ }
343
+ }
344
+
345
+ /**
346
+ * Create multiple instance of menu and pass the options.
347
+ *
348
+ * @version 4.0.0
349
+ */
350
+ for ( let index = 0; index < rmp_menu.menu.length; index++ ) {
351
+ let rmp = new RmpMenu( rmp_menu.menu[index] );
352
+ }
353
+
354
+ } );
v4.0.0/assets/scss/common.scss ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ This file contents common styling of menus.
3
+ */
4
+ .rmp-container {
5
+ display: none;
6
+ visibility: visible;
7
+ padding: 0px 0px 0px 0px;
8
+ z-index: 99998;
9
+ transition: all 0.3s;
10
+
11
+ &.rmp-fade-top,
12
+ &.rmp-fade-left,
13
+ &.rmp-fade-right,
14
+ &.rmp-fade-bottom {
15
+ display: none;
16
+ }
17
+
18
+ &.rmp-slide-left,
19
+ &.rmp-push-left {
20
+ transform: translateX(-100%);
21
+ -ms-transform: translateX(-100%);
22
+ -webkit-transform: translateX(-100%);
23
+ -moz-transform: translateX(-100%);
24
+ }
25
+
26
+ &.rmp-slide-left.rmp-menu-open,
27
+ &.rmp-push-left.rmp-menu-open {
28
+ transform: translateX(0);
29
+ -ms-transform: translateX(0);
30
+ -webkit-transform: translateX(0);
31
+ -moz-transform: translateX(0);
32
+ }
33
+
34
+ &.rmp-slide-right,
35
+ &.rmp-push-right {
36
+ transform: translateX(100%);
37
+ -ms-transform: translateX(100%);
38
+ -webkit-transform: translateX(100%);
39
+ -moz-transform: translateX(100%);
40
+ }
41
+
42
+ &.rmp-slide-right.rmp-menu-open,
43
+ &.rmp-push-right.rmp-menu-open {
44
+ transform: translateX(0);
45
+ -ms-transform: translateX(0);
46
+ -webkit-transform: translateX(0);
47
+ -moz-transform: translateX(0);
48
+ }
49
+
50
+ &.rmp-slide-top,
51
+ &.rmp-push-top {
52
+ transform: translateY(-100%);
53
+ -ms-transform: translateY(-100%);
54
+ -webkit-transform: translateY(-100%);
55
+ -moz-transform: translateY(-100%);
56
+ }
57
+
58
+ &.rmp-slide-top.rmp-menu-open,
59
+ &.rmp-push-top.rmp-menu-open {
60
+ transform: translateY(0);
61
+ -ms-transform: translateY(0);
62
+ -webkit-transform: translateY(0);
63
+ -moz-transform: translateY(0);
64
+ }
65
+
66
+ &.rmp-slide-bottom,
67
+ &.rmp-push-bottom {
68
+ transform: translateY(100%);
69
+ -ms-transform: translateY(100%);
70
+ -webkit-transform: translateY(100%);
71
+ -moz-transform: translateY(100%);
72
+ }
73
+
74
+ &.rmp-slide-bottom.rmp-menu-open,
75
+ &.rmp-push-bottom.rmp-menu-open {
76
+ transform: translateX(0);
77
+ -ms-transform: translateX(0);
78
+ -webkit-transform: translateX(0);
79
+ -moz-transform: translateX(0);
80
+ }
81
+
82
+
83
+ /** Scrolling bar in menu setting box **/
84
+ &::-webkit-scrollbar {
85
+ width: 0px;
86
+ }
87
+
88
+ & ::-webkit-scrollbar-track {
89
+ box-shadow: inset 0 0 5px transparent;
90
+ }
91
+
92
+ & ::-webkit-scrollbar-thumb {
93
+ background: transparent;
94
+ }
95
+
96
+ & ::-webkit-scrollbar-thumb:hover {
97
+ background: transparent;
98
+ }
99
+
100
+ .rmp-menu-wrap .rmp-menu {
101
+ transition: none;
102
+ border-radius: 0;
103
+ box-shadow: none;
104
+ background: none;
105
+ border: 0;
106
+ bottom: auto;
107
+ box-sizing: border-box;
108
+ clip: auto;
109
+ color: #666;
110
+ display: block;
111
+ float: none;
112
+ font-family: inherit;
113
+ font-size: 14px;
114
+ height: auto;
115
+ left: auto;
116
+ line-height: 1.7;
117
+ list-style-type: none;
118
+ margin: 0;
119
+ min-height: auto;
120
+ max-height: none;
121
+ opacity: 1;
122
+ outline: none;
123
+ overflow: visible;
124
+ padding: 0;
125
+ position: relative;
126
+ pointer-events: auto;
127
+ right: auto;
128
+ text-align: left;
129
+ text-decoration: none;
130
+ text-indent: 0;
131
+ text-transform: none;
132
+ transform: none;
133
+ top: auto;
134
+ visibility: inherit;
135
+ width: auto;
136
+ word-wrap: break-word;
137
+ white-space: normal;
138
+ }
139
+
140
+ .rmp-menu-additional-content {
141
+ display: block;
142
+ word-break: break-word;
143
+ }
144
+
145
+ .rmp-menu-title{
146
+ display: flex;
147
+ flex-direction: column;
148
+
149
+ .rmp-menu-title-image {
150
+ max-width: 100%;
151
+ margin-bottom: 15px;
152
+ display:block;
153
+ margin: auto;
154
+ margin-bottom: 15px;
155
+ }
156
+ }
157
+ }
158
+
159
+
160
+ button.rmp_menu_trigger {
161
+ z-index: 999999;
162
+ overflow: hidden;
163
+ outline:none;
164
+ border: 0;
165
+ display: none;
166
+ margin: 0;
167
+ transition: transform 0.5s, background-color 0.5s;
168
+ padding: 0;
169
+ .responsive-menu-pro-inner::before,
170
+ .responsive-menu-pro-inner::after {
171
+ content: "";
172
+ display: block;
173
+ }
174
+
175
+ .responsive-menu-pro-inner::before {
176
+ top: 10px;
177
+ }
178
+
179
+ .responsive-menu-pro-inner::after {
180
+ bottom: 10px;
181
+ }
182
+
183
+ .rmp-trigger-box {
184
+ width: 40px;
185
+ display: inline-block;
186
+ position: relative;
187
+ pointer-events: none;
188
+ vertical-align: middle;
189
+ }
190
+
191
+ }
192
+
193
+
194
+ @if $menu_adjust_for_wp_admin_bar == 'adjust' {
195
+ .admin-bar .rmp-container,
196
+ .admin-bar .rmp_menu_trigger {
197
+ margin-top: 32px !important;
198
+ }
199
+
200
+ @media screen and (max-width: 782px) {
201
+ .admin-bar .rmp-container,
202
+ .admin-bar .rmp_menu_trigger {
203
+ margin-top: 46px !important;
204
+ }
205
+ }
206
+ }
207
+
208
+ /* Menu Trigger Boring Animation */
209
+ .rmp-menu-trigger-boring {
210
+ .responsive-menu-pro-inner {
211
+ transition-property: none;
212
+ &::after,
213
+ &::before{
214
+ transition-property: none;
215
+ }
216
+ }
217
+
218
+ &.is-active {
219
+ .responsive-menu-pro-inner {
220
+ transform: rotate(45deg);
221
+ &:before{
222
+ top: 0;
223
+ opacity: 0;
224
+ }
225
+ &:after{
226
+ bottom: 0;
227
+ transform: rotate(-90deg);
228
+ }
229
+ }
230
+ }
231
+ }
232
+
v4.0.0/assets/scss/main.scss ADDED
@@ -0,0 +1,624 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** This file is major component of this plugin so please don't try to edit here. */
2
+
3
+ @if( $page_wrapper != '' ) {
4
+ #{$page_wrapper} {
5
+ transition: transform $animation_speed;
6
+ }
7
+ }
8
+
9
+ @if( $menu_to_hide != '' ) {
10
+ #{$menu_to_hide} {
11
+ display: none !important;
12
+ }
13
+ }
14
+
15
+ /* Hamburger menu styling */
16
+ @media screen and (max-width: $tablet_breakpoint ) {
17
+
18
+ #{$menu_trigger_id} {
19
+
20
+ width : $menu_trigger_width;
21
+ height : $menu_trigger_height;
22
+ position: $menu_trigger_position_type;
23
+ top : $menu_trigger_distance_from_top;
24
+ display: inline-block;
25
+
26
+ @if ( $menu_trigger_side == right ) {
27
+ right: $menu_trigger_distance_from_side;
28
+ } @else {
29
+ left: $menu_trigger_distance_from_side;
30
+ }
31
+
32
+ @if ( $menu_trigger_transparent_background == 'on' ) {
33
+ background: transparent;
34
+ } @else {
35
+
36
+ background: $menu_trigger_background_color;
37
+
38
+ &:hover,
39
+ &:focus,
40
+ &.is-active:hover {
41
+ background: $menu_trigger_background_color_hover;
42
+ text-decoration: unset;
43
+ }
44
+
45
+ &.is-active {
46
+ background: $menu_trigger_active_color;
47
+ }
48
+ }
49
+
50
+ transition: transform $animation_speed, background-color $color_transition_speed;
51
+
52
+ .rmp-trigger-box {
53
+ width: $menu_trigger_line_width + $menu_trigger_line_width_unit;
54
+ color: $menu_trigger_title_color;
55
+ }
56
+
57
+ .rmp-trigger-icon-active,
58
+ .rmp-trigger-text-open {
59
+ display: none;
60
+ }
61
+
62
+ &.is-active .rmp-trigger-icon-active,
63
+ &.is-active .rmp-trigger-text-open {
64
+ display:inline;
65
+ }
66
+
67
+ &.is-active .rmp-trigger-icon-inactive,
68
+ &.is-active .rmp-trigger-text {
69
+ display: none;
70
+ }
71
+
72
+ .rmp-trigger-label {
73
+ color:$menu_trigger_title_color;
74
+ pointer-events: none;
75
+ line-height: $menu_trigger_title_line_height;
76
+
77
+ @if( $menu_trigger_title_font != '' ) {
78
+ font-family: $menu_trigger_title_font;
79
+ } @else {
80
+ font-family: inherit
81
+ }
82
+
83
+ font-size: $menu_trigger_title_font_size;
84
+ display: inline;
85
+ text-transform: inherit;
86
+ }
87
+
88
+ .responsive-menu-pro-inner {
89
+ display: block;
90
+ }
91
+
92
+ .responsive-menu-pro-inner,
93
+ .responsive-menu-pro-inner::before,
94
+ .responsive-menu-pro-inner::after {
95
+ width: $menu_trigger_line_width + $menu_trigger_line_width_unit;
96
+ height: $menu_trigger_line_height + $menu_trigger_line_height_unit;
97
+ background-color: $menu_trigger_line_color;
98
+ border-radius: 4px;
99
+ position: absolute;
100
+ }
101
+
102
+ &.is-active .responsive-menu-pro-inner,
103
+ &.is-active .responsive-menu-pro-inner::before,
104
+ &.is-active .responsive-menu-pro-inner::after {
105
+ background-color: $menu_trigger_line_active_color;
106
+ }
107
+
108
+ &:hover .responsive-menu-pro-inner,
109
+ &:hover .responsive-menu-pro-inner::before,
110
+ &:hover .responsive-menu-pro-inner::after {
111
+ background-color: $menu_trigger_line_color_hover;
112
+ }
113
+
114
+ }
115
+
116
+ #{$menu_container} {
117
+ position: fixed;
118
+ top: 0;
119
+ margin: 0;
120
+ transition: transform $animation_speed;
121
+ overflow: auto;
122
+ display:block;
123
+
124
+ @if ( $menu_width ) {
125
+ width: $menu_width + $menu_width_unit;
126
+ }
127
+
128
+ @if ( $menu_maximum_width != '' ) {
129
+ max-width: $menu_maximum_width+$menu_maximum_width_unit;
130
+ }
131
+
132
+ @if ( $menu_minimum_width != '' ) {
133
+ min-width: $menu_minimum_width + $menu_minimum_width_unit;
134
+ }
135
+
136
+ background-color: $menu_container_background_colour;
137
+
138
+ @if ( $menu_container_background_image ) {
139
+ background-image: url($menu_container_background_image);
140
+ }
141
+
142
+ height: 100%;
143
+
144
+ @if ( $menu_container_appear_from == "right" ) {
145
+ right:0;
146
+ } @else {
147
+ left:0;
148
+ }
149
+
150
+ @if( $menu_container_padding_top != '' ) {
151
+ padding-top : $menu_container_padding_top;
152
+ }
153
+
154
+ @if( $menu_container_padding_left != '' ) {
155
+ padding-left : $menu_container_padding_left;
156
+ }
157
+
158
+ @if( $menu_container_padding_bottom != '' ) {
159
+ padding-bottom : $menu_container_padding_bottom;
160
+ }
161
+
162
+ @if( $menu_container_padding_right != '' ) {
163
+ padding-right : $menu_container_padding_right;
164
+ }
165
+
166
+ }
167
+
168
+ #{$menu_wrap} {
169
+
170
+ @if( $menu_section_padding_top != '' ) {
171
+ padding-top : $menu_section_padding_top;
172
+ }
173
+
174
+ @if( $menu_section_padding_left != '' ) {
175
+ padding-left : $menu_section_padding_left;
176
+ }
177
+
178
+ @if( $menu_section_padding_bottom != '' ) {
179
+ padding-bottom : $menu_section_padding_bottom;
180
+ }
181
+
182
+ @if( $menu_section_padding_right != '' ) {
183
+ padding-right : $menu_section_padding_right;
184
+ }
185
+
186
+ @if( $menu_background_color != '' ) {
187
+ background-color: $menu_background_color;
188
+ }
189
+
190
+ .rmp-menu,
191
+ .rmp-submenu {
192
+ width: 100%;
193
+ box-sizing: border-box;
194
+ margin: 0;
195
+ padding: 0;
196
+ }
197
+
198
+ .rmp-submenu-depth-1 .rmp-menu-item-link {
199
+ padding-#{$menu_depth_side} : ( $menu_item_padding_depth_1 + $menu_item_padding_depth_1_unit);
200
+ }
201
+
202
+ .rmp-submenu-depth-2 .rmp-menu-item-link {
203
+ padding-#{$menu_depth_side} : ( $menu_item_padding_depth_2 + $menu_item_padding_depth_2_unit);
204
+ }
205
+
206
+ .rmp-submenu-depth-3 .rmp-menu-item-link {
207
+ padding-#{$menu_depth_side} : ( $menu_item_padding_depth_3 + $menu_item_padding_depth_3_unit);
208
+ }
209
+
210
+ .rmp-submenu-depth-4 .rmp-menu-item-link {
211
+ padding-#{$menu_depth_side} : ( $menu_item_padding_depth_4 + $menu_item_padding_depth_4_unit);
212
+ }
213
+
214
+ .rmp-submenu.rmp-submenu-open {
215
+ display: block;
216
+ }
217
+
218
+ .rmp-menu-item {
219
+ width: 100%;
220
+ list-style: none;
221
+ margin:0;
222
+ }
223
+
224
+ .rmp-menu-item-link {
225
+
226
+ @if( $menu_item_height != '' ) {
227
+ height: ( $menu_item_height + $menu_item_height_unit);
228
+ }
229
+
230
+ @if( $menu_item_line_height != '' ) {
231
+ line-height: ( $menu_item_line_height + $menu_item_line_height_unit );
232
+ }
233
+
234
+ @if( $menu_item_font_size != '' ) {
235
+ font-size: ( $menu_item_font_size + $menu_item_font_size_unit );
236
+ }
237
+
238
+
239
+ @if( $menu_item_border_width != '' ) {
240
+ border-bottom: ( $menu_item_border_width + $menu_item_border_width_unit ) solid $menu_item_border_color;
241
+ } @else {
242
+ border-bottom: ( 0 + $menu_item_border_width_unit ) solid $menu_item_border_color;
243
+ }
244
+
245
+ @if( $menu_item_font_family != '' ) {
246
+ font-family: $menu_item_font_family;
247
+ } @else {
248
+ font-family: inherit;
249
+ }
250
+
251
+ color: $menu_item_text_color;
252
+ text-align: $menu_item_text_alignment;
253
+ background-color: $menu_item_background_color;
254
+ font-weight: $menu_item_font_weight;
255
+ letter-spacing: ($menu_item_letter_spacing + 'px');
256
+ display: block;
257
+ width: 100%;
258
+ text-decoration: none;
259
+ position: relative;
260
+ transition: background-color $color_transition_speed, border-color $color_transition_speed, $color_transition_speed;
261
+
262
+ @if ( $menu_word_wrap == 'on' ) {
263
+ word-wrap: break-word;
264
+ height: auto;
265
+ }
266
+
267
+ padding: 0 ( $menu_item_padding + $menu_item_padding_unit);
268
+
269
+ @if ( $menu_item_toggle_position == 'left' ) {
270
+ padding-left: ( $menu_item_toggle_width + $menu_item_toggle_width_unit );
271
+ } @else if( $menu_item_toggle_position == 'right' ) {
272
+ padding-right: ( $menu_item_toggle_width + $menu_item_toggle_width_unit );
273
+ }
274
+
275
+ &:after,
276
+ &:before{
277
+ display: none;
278
+ }
279
+
280
+ &:hover {
281
+ color: $menu_item_text_color_hover;
282
+ border-color: $menu_item_border_color_hover;
283
+ background-color: $menu_item_background_color_hover;
284
+ }
285
+
286
+ &:focus {
287
+ outline: none;
288
+ border-color:unset;
289
+ box-shadow:unset;
290
+ }
291
+
292
+ .rmp-font-icon {
293
+ height: ( $menu_item_height + $menu_item_height_unit);
294
+ line-height: ( $menu_item_line_height + $menu_item_line_height_unit );
295
+ margin-right: 10px;
296
+ font-size: ( $menu_item_font_size + $menu_item_font_size_unit );
297
+ }
298
+ }
299
+
300
+
301
+ .rmp-menu-current-item {
302
+ .rmp-menu-item-link {
303
+ color: $menu_current_item_text_color;
304
+ border-color: $menu_current_item_border_color;
305
+ background-color: $menu_current_item_background_color;
306
+
307
+ &:hover {
308
+ color: $menu_current_item_text_color_hover;
309
+ border-color: $menu_current_item_border_color_hover;
310
+ background-color: $menu_current_item_background_color_hover;
311
+ }
312
+ }
313
+ }
314
+
315
+ .rmp-menu-subarrow {
316
+ position: absolute;
317
+ top: 0;
318
+ bottom: 0;
319
+ text-align: center;
320
+ overflow: hidden;
321
+ background-size: cover;
322
+ overflow: hidden;
323
+ @if ( $menu_item_toggle_position == 'left' ) {
324
+ left: 0;
325
+ @if( $menu_item_toggle_border_width != 0 ) {
326
+ border-right-style:solid;
327
+ border-right-color:$menu_item_toggle_border_color;
328
+ border-right-width: ( $menu_item_toggle_border_width + $menu_item_toggle_border_width_unit );
329
+ }
330
+ } @else {
331
+ right: 0;
332
+ @if( $menu_item_toggle_border_width != 0 ) {
333
+ border-left-style:solid;
334
+ border-left-color:$menu_item_toggle_border_color;
335
+ border-left-width: ( $menu_item_toggle_border_width + $menu_item_toggle_border_width_unit );
336
+ }
337
+ }
338
+
339
+ height: ($menu_item_toggle_height + $menu_item_toggle_height_unit);
340
+
341
+ width: ( $menu_item_toggle_width + $menu_item_toggle_width_unit );
342
+ color: $menu_item_toggle_text_color;
343
+ background-color: $menu_item_toggle_background_color;
344
+
345
+ &:hover {
346
+ color: $menu_item_toggle_text_color_hover;
347
+ border-color: $menu_item_toggle_border_color_hover;
348
+ background-color: $menu_item_toggle_background_color_hover;
349
+ }
350
+
351
+ .rmp-font-icon {
352
+ margin-right: unset;
353
+ }
354
+
355
+ * {
356
+ vertical-align: middle;
357
+ line-height: ($menu_item_toggle_height + $menu_item_toggle_height_unit);
358
+ }
359
+ }
360
+
361
+ .rmp-menu-subarrow-active {
362
+ display: block;
363
+ background-size: cover;
364
+ color: $menu_current_item_toggle_text_color;
365
+ border-color: $menu_current_item_toggle_border_color;
366
+ background-color: $menu_current_item_toggle_background_color;
367
+ &:hover {
368
+ color: $menu_current_item_toggle_text_color_hover;
369
+ border-color: $menu_current_item_toggle_border_color_hover;
370
+ background-color: $menu_current_item_toggle_background_color_hover;
371
+ }
372
+ }
373
+
374
+ .rmp-submenu {
375
+ display: none;
376
+ .rmp-menu-item-link {
377
+ height: ( $submenu_item_height + $submenu_item_height_unit);
378
+ line-height: ( $submenu_item_line_height + $submenu_item_line_height_unit );
379
+ font-size: ( $submenu_item_font_size + $submenu_item_font_size_unit );
380
+
381
+ @if( $submenu_item_border_width != '' ) {
382
+ border-bottom: ( $submenu_item_border_width + $submenu_item_border_width_unit ) solid $submenu_item_border_color;
383
+ } @else {
384
+ border-bottom: ( 0 + $submenu_item_border_width_unit ) solid $submenu_item_border_color;
385
+ }
386
+
387
+ @if( $submenu_item_font_family != '' ) {
388
+ font-family: $submenu_item_font_family;
389
+ } @else {
390
+ font-family: inherit;
391
+ }
392
+
393
+ color: $submenu_item_text_color;
394
+ text-align: $submenu_item_text_alignment;
395
+ background-color: $submenu_item_background_color;
396
+ &:hover {
397
+ color: $submenu_item_text_color_hover;
398
+ border-color: $submenu_item_border_color_hover;
399
+ background-color: $submenu_item_background_color_hover;
400
+
401
+ }
402
+ }
403
+
404
+ .rmp-menu-current-item {
405
+ .rmp-menu-item-link {
406
+ color: $submenu_current_item_text_color;
407
+ border-color: $submenu_current_item_border_color;
408
+ background-color: $submenu_current_item_background_color;
409
+
410
+ &:hover {
411
+ color: $submenu_current_item_text_color_hover;
412
+ border-color: $submenu_current_item_border_color_hover;
413
+ background-color: $submenu_current_item_background_color_hover;
414
+ }
415
+ }
416
+ }
417
+
418
+ // If legacy setting is on then add these settings.
419
+ @if( $is_legacy == 'on' ) {
420
+
421
+ .rmp-menu-subarrow {
422
+
423
+ @if ( $submenu_item_toggle_position == 'left' ) {
424
+ left: 0;
425
+ border-left: unset;
426
+ @if( $submenu_item_toggle_border_width != 0 ) {
427
+ border-right-style:solid;
428
+ border-right-color:$submenu_item_toggle_border_color;
429
+ border-right-width: ( $submenu_item_toggle_border_width + $submenu_item_toggle_border_width_unit );
430
+ }
431
+ } @else {
432
+ right: 0;
433
+ border-right: unset;
434
+ @if( $submenu_item_toggle_border_width != 0 ) {
435
+ border-left-style:solid;
436
+ border-left-color:$submenu_item_toggle_border_color;
437
+ border-left-width: ( $submenu_item_toggle_border_width + $submenu_item_toggle_border_width_unit );
438
+ }
439
+ }
440
+
441
+ height: ($submenu_item_toggle_height + $submenu_item_toggle_height_unit);
442
+ line-height: ($submenu_item_toggle_height + $submenu_item_toggle_height_unit);
443
+ width: ( $submenu_item_toggle_width + $submenu_item_toggle_width_unit );
444
+ color: $submenu_item_toggle_text_color;
445
+ background-color: $submenu_item_toggle_background_color;
446
+
447
+ &:hover {
448
+ color: $submenu_item_toggle_text_color_hover;
449
+ border-color: $submenu_item_toggle_border_color_hover;
450
+ background-color: $submenu_item_toggle_background_color_hover;
451
+ }
452
+ }
453
+
454
+ .rmp-menu-subarrow-active {
455
+ color: $submenu_current_item_toggle_text_color;
456
+ border-color: $submenu_current_item_toggle_border_color;
457
+ background-color: $submenu_current_item_toggle_background_color;
458
+ &:hover {
459
+ color: $submenu_current_item_toggle_text_color_hover;
460
+ border-color: $submenu_current_item_toggle_border_color_hover;
461
+ background-color: $submenu_current_item_toggle_background_color_hover;
462
+ }
463
+ }
464
+ }
465
+ }
466
+
467
+ .rmp-menu-item-description {
468
+ margin: 0;
469
+ padding: 5px ( $menu_item_padding + $menu_item_padding_unit);
470
+ opacity: 0.8;
471
+ color: $menu_item_text_color;
472
+ }
473
+
474
+ }
475
+
476
+ #{$menu_search_box_wrap} {
477
+
478
+ display: block;
479
+
480
+ @if( $menu_search_section_padding_top != '' ) {
481
+ padding-top : $menu_search_section_padding_top;
482
+ }
483
+
484
+ @if( $menu_search_section_padding_left != '' ) {
485
+ padding-left : $menu_search_section_padding_left;
486
+ }
487
+
488
+ @if( $menu_search_section_padding_bottom != '' ) {
489
+ padding-bottom : $menu_search_section_padding_bottom;
490
+ }
491
+
492
+ @if( $menu_search_section_padding_right != '' ) {
493
+ padding-right : $menu_search_section_padding_right;
494
+ }
495
+
496
+ .rmp-search-form {
497
+ margin: 0;
498
+ }
499
+
500
+ .rmp-search-box {
501
+ background: $menu_search_box_background_color;
502
+ border: 1px solid $menu_search_box_border_color;
503
+ color: $menu_search_box_text_color;
504
+ width: 100%;
505
+ padding: 0 5%;
506
+
507
+ @if( $menu_search_box_border_radius != '' ) {
508
+ border-radius: $menu_search_box_border_radius;
509
+ }
510
+
511
+ height: ( $menu_search_box_height + $menu_search_box_height_unit );
512
+ -webkit-appearance: none;
513
+ &::placeholder {
514
+ color : black;
515
+ }
516
+ &:focus {
517
+ background-color: $menu_search_box_background_color;
518
+ outline:2px solid $menu_search_box_border_color;
519
+ color: $menu_search_box_text_color;
520
+ }
521
+ }
522
+ }
523
+
524
+ /** Menu Title Style */
525
+ #{$menu_title_wrap} {
526
+
527
+ @if( $menu_title_background != '' ) {
528
+ background-color: $menu_title_background;
529
+ }
530
+
531
+ @if( $menu_title_font_color != '' ) {
532
+ color: $menu_title_font_color;
533
+ }
534
+
535
+ @if( $menu_title_text_alignment != '' ) {
536
+ text-align: $menu_title_text_alignment;
537
+ }
538
+
539
+ @if( $menu_title_font_size != '' ) {
540
+ font-size: $menu_title_font_size;
541
+ }
542
+
543
+ @if( $menu_title_section_padding_top != '' ) {
544
+ padding-top : $menu_title_section_padding_top;
545
+ }
546
+
547
+ @if( $menu_title_section_padding_left != '' ) {
548
+ padding-left : $menu_title_section_padding_left;
549
+ }
550
+
551
+ @if( $menu_title_section_padding_bottom != '' ) {
552
+ padding-bottom : $menu_title_section_padding_bottom;
553
+ }
554
+
555
+ @if( $menu_title_section_padding_right != '' ) {
556
+ padding-right : $menu_title_section_padding_right;
557
+ }
558
+
559
+ transition: background-color $color_transition_speed, border-color $color_transition_speed, color $color_transition_speed;
560
+
561
+ &:hover {
562
+ background-color: $menu_title_background_hover;
563
+ color:$menu_title_font_color_hover;
564
+ }
565
+
566
+ & > a {
567
+ color: $menu_title_font_color;
568
+ width: 100%;
569
+ background-color: unset;
570
+ text-decoration: none;
571
+ &:hover {
572
+ color:$menu_title_font_color_hover;
573
+ }
574
+ }
575
+
576
+ .rmp-font-icon {
577
+ font-size: $menu_title_font_size;
578
+ }
579
+
580
+ .rmp-menu-title-image {
581
+
582
+ @if( $menu_title_image_width != '' ) {
583
+ width: $menu_title_image_width;
584
+ }
585
+
586
+ @if( $menu_title_image_height != '' ) {
587
+ height: $menu_title_image_height;
588
+ }
589
+ }
590
+ }
591
+
592
+ /** Menu Additional Content Style */
593
+ #{$menu_additional_content_wrap} {
594
+
595
+ @if( $menu_additional_section_padding_top != '' ) {
596
+ padding-top : $menu_additional_section_padding_top;
597
+ }
598
+
599
+ @if( $menu_additional_section_padding_left != '' ) {
600
+ padding-left : $menu_additional_section_padding_left;
601
+ }
602
+
603
+ @if( $menu_additional_section_padding_bottom != '' ) {
604
+ padding-bottom : $menu_additional_section_padding_bottom;
605
+ }
606
+
607
+ @if( $menu_additional_section_padding_right != '' ) {
608
+ padding-right : $menu_additional_section_padding_right;
609
+ }
610
+
611
+ @if( $menu_additional_content_color != '' ) {
612
+ color: $menu_additional_content_color;
613
+ }
614
+
615
+ @if( $menu_additional_content_alignment != '' ) {
616
+ text-align: $menu_additional_content_alignment;
617
+ }
618
+
619
+ @if( $menu_additional_content_font_size != '' ) {
620
+ font-size: ($menu_additional_content_font_size + $menu_additional_content_font_size_unit) ;
621
+ }
622
+
623
+ }
624
+ }
v4.0.0/inc/classes/class-admin.php ADDED
@@ -0,0 +1,576 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Admin class.
4
+ * This is core class which is responsible for admin functionality.
5
+ *
6
+ * @version 4.0.0
7
+ * @author Expresstech System
8
+ *
9
+ * @package responsive-menu-pro
10
+ */
11
+
12
+ namespace RMP\Features\Inc;
13
+ use RMP\Features\Inc\Traits\Singleton;
14
+ use RMP\Features\Inc\RMP_Menu;
15
+ use RMP\Features\Inc\Theme_Manager;
16
+ use RMP\Features\Inc\Option_Manager;
17
+
18
+ // Disable the direct access to this class.
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit;
21
+ }
22
+
23
+ /**
24
+ * Class Admin
25
+ *
26
+ */
27
+ class Admin {
28
+
29
+ use Singleton;
30
+
31
+ /**
32
+ * Instance of Option Manager class.
33
+ *
34
+ * @since 4.0.0
35
+ * @access protected
36
+ * @var object.
37
+ */
38
+ protected static $option_manager;
39
+
40
+ /**
41
+ * Construct method.
42
+ */
43
+ protected function __construct() {
44
+ $this->setup_hooks();
45
+ }
46
+
47
+ /**
48
+ * To setup action/filter.
49
+ *
50
+ * @return void
51
+ */
52
+ protected function setup_hooks() {
53
+
54
+ add_action( 'wp_ajax_rmp_save_global_settings', [ $this, 'save_menu_global_settings' ] );
55
+ add_action( 'wp_ajax_rmp_rollback_version', [ $this, 'rollback_version' ] );
56
+ add_action( 'wp_ajax_rmp_create_new_menu', [ $this, 'create_new_menu' ] );
57
+ add_action( 'wp_ajax_rmp_export_menu', [ $this, 'rmp_export_menu' ] );
58
+ add_action( 'wp_ajax_rmp_import_menu', [ $this, 'rmp_import_menu' ] );
59
+
60
+ add_shortcode( 'rmp_menu', [ $this, 'register_menu_shortcode' ] );
61
+ add_action( 'init', array($this,'rmp_menu_cpt'), 0 );
62
+
63
+ add_filter( 'post_row_actions', array($this,'rmp_menu_row_actions'), 10, 2 );
64
+ add_filter( 'get_edit_post_link', [ $this, 'my_edit_post_link' ], 10, 2 );
65
+
66
+ add_filter( 'manage_rmp_menu_posts_columns', array($this,'set_custom_edit_menu_columns') );
67
+ add_action( 'manage_rmp_menu_posts_custom_column' , array($this,'add_custom_columns'), 10, 2 );
68
+ add_action( 'admin_footer' , array($this,'add_new_menu_widget') );
69
+ add_action( 'admin_menu', array( $this, 'rmp_register_submenu_page' ) );
70
+ add_action( 'admin_menu', [$this, 'remove_default_add_cpt_page']);
71
+ add_action( 'rmp_create_new_menu', array( $this , 'set_global_options' ), 10 , 0 );
72
+ }
73
+
74
+ /**
75
+ * Function to save the global settings of setting page.
76
+ *
77
+ * @return json
78
+ */
79
+ public function save_menu_global_settings() {
80
+
81
+ check_ajax_referer( 'rmp_nonce', 'ajax_nonce' );
82
+
83
+ $options = array();
84
+ parse_str( $_POST['form'], $options );
85
+
86
+ foreach( $options as $key => $value ) {
87
+ $options[$key] = sanitize_text_field( $value );
88
+ }
89
+
90
+ update_option( 'rmp_global_setting_options', $options );
91
+
92
+ /**
93
+ * Fires after global settings is saved.
94
+ *
95
+ * @since 4.0.0
96
+ *
97
+ * @param array $option List of global settings.
98
+ */
99
+ do_action( 'rmp_save_global_settings', $options );
100
+
101
+ wp_send_json_success( 'Saved' );
102
+ }
103
+
104
+ /**
105
+ * Rollback to older version from setting page.
106
+ *
107
+ * @since 4.0.0
108
+ *
109
+ * @return void
110
+ */
111
+ public function rollback_version() {
112
+
113
+ if ( empty ( update_option( 'is_rmp_new_version', 0 ) ) ) {
114
+ add_option( 'is_rmp_new_version', 0 );
115
+ }
116
+
117
+ wp_send_json_success( ['redirect' => admin_url('admin.php?page=responsive-menu')] );
118
+ }
119
+
120
+ /**
121
+ * Function to create a new theme.
122
+ *
123
+ * @since 4.0.0
124
+ *
125
+ * @return json
126
+ */
127
+ public function create_new_menu() {
128
+
129
+ check_ajax_referer( 'rmp_nonce', 'ajax_nonce' );
130
+
131
+ $menu_name = sanitize_text_field( $_POST['menu_name'] );
132
+ if ( empty( $menu_name ) ) {
133
+ wp_send_json_error( [ 'message' => __('Enter the Menu name !', 'responsive-menu-pro') ] );
134
+ }
135
+
136
+ $menu_to_use = sanitize_text_field( $_POST['menu_to_use'] );
137
+ if ( empty( $menu_to_use ) ) {
138
+ wp_send_json_error( [ 'message' => __('Select menu to use !', 'responsive-menu-pro') ] );
139
+ }
140
+
141
+ $menu_theme = '';
142
+ if ( ! empty( $_POST['menu_theme'] ) ) {
143
+ $menu_theme = sanitize_text_field( $_POST['menu_theme'] );
144
+ }
145
+
146
+ $theme_type = '';
147
+ if ( ! empty( $_POST['theme_type'] ) ) {
148
+ $theme_type = sanitize_text_field( $_POST['theme_type'] );
149
+ }
150
+
151
+ $menu_show_on = sanitize_text_field( $_POST['menu_show_on'] );
152
+
153
+ $menu_show_on_pages = [];
154
+ if ( ! empty( $_POST['menu_show_on_pages'] ) && is_array( $_POST['menu_show_on_pages'] ) ) {
155
+ foreach ( $_POST['menu_show_on_pages'] as $key => $val ) {
156
+ $menu_show_on_pages[ $key ] = sanitize_text_field( $val );
157
+ }
158
+ }
159
+
160
+ $theme_options = [];
161
+
162
+ // Get appropriate theme as per theme type and theme name.
163
+ if ( ! empty( $theme_type ) && 'downloaded' == $theme_type ) {
164
+ $theme_manager = Theme_Manager::get_instance();
165
+ $theme_options = $theme_manager->get_downloaded_theme_settings( $menu_theme );
166
+ } else if ( ! empty( $theme_type ) && 'template' == $theme_type ) {
167
+ $theme_manager = Theme_Manager::get_instance();
168
+ $theme_options = $theme_manager->get_saved_theme_options( $menu_theme );
169
+ } else {
170
+ $theme_options = rmp_get_default_options();
171
+ }
172
+
173
+ // Create menu as post with rmp_menu cpt.
174
+ $new_menu = array(
175
+ 'post_title' => wp_strip_all_tags( $menu_name ),
176
+ 'post_author' => get_current_user_id(),
177
+ 'post_status' => 'publish',
178
+ 'post_type' => 'rmp_menu',
179
+ );
180
+
181
+ $menu_id = wp_insert_post( $new_menu );
182
+
183
+ $new_options = array(
184
+ 'menu_name' => $menu_name,
185
+ 'menu_to_use' => $menu_to_use,
186
+ 'menu_theme' => $menu_theme,
187
+ 'theme_type' => $theme_type,
188
+ 'menu_display_on' => $menu_show_on,
189
+ 'menu_show_on_pages' => $menu_show_on_pages,
190
+ 'menu_id' => $menu_id
191
+ );
192
+
193
+ $new_options = array_merge( $theme_options , $new_options );
194
+
195
+ if ( ! empty( $menu_id ) ) {
196
+
197
+ update_post_meta( $menu_id, 'rmp_menu_meta', $new_options);
198
+
199
+ /**
200
+ * Fires when menu is created and options is saved.
201
+ *
202
+ * @param int $menu_id Menu ID.
203
+ */
204
+ do_action( 'rmp_create_new_menu', $menu_id );
205
+
206
+ $status = __('Menu is created successfully', 'responsive-menu-pro');
207
+
208
+ } else {
209
+ $status = __('Unable to create new Menu', 'responsive-menu-pro');
210
+ }
211
+
212
+ wp_send_json_success( ['message' => $status ] );
213
+ }
214
+
215
+ /**
216
+ * This function register the shortcode for menu.
217
+ *
218
+ * @since 4.0.0
219
+ *
220
+ * @param Array $atts Attributes List.
221
+ * @param string $content It contain text from shortcode.
222
+ *
223
+ * @return HTML $output Menu contents.
224
+ */
225
+ public function register_menu_shortcode( $attrs = [] ) {
226
+
227
+ $attrs = shortcode_atts( [ 'id' => '' ], $attrs );
228
+
229
+ $attrs = array_change_key_case( (array) $attrs, CASE_LOWER );
230
+
231
+ // Check given id is valid.
232
+ if ( empty( $attrs['id'] ) ) {
233
+ return __( 'Please pass menu id as attribute.', 'responsive-menu-pro' );
234
+ }
235
+
236
+ $menu_id = $attrs['id'];
237
+ if ( 'publish' !== get_post_status( $menu_id ) ) {
238
+ return __( "Shortcode with menu id $menu_id is not published.", 'responsive-menu-pro' );
239
+ }
240
+
241
+ // Check shortcode option is activated or not.
242
+ $option_manager = Option_Manager::get_instance();
243
+ $option = $option_manager->get_option( $menu_id, 'menu_display_on' );
244
+
245
+ if ( 'shortcode' !== $option ) {
246
+ return __( 'Shortcode deactivated', 'responsive-menu-pro' );
247
+ }
248
+
249
+ ob_start();
250
+
251
+ $menu = new RMP_Menu( $menu_id );
252
+ $menu->build_menu();
253
+
254
+ return ob_get_clean();
255
+ }
256
+
257
+ /**
258
+ * Function to update the global options.
259
+ *
260
+ * @since 4.0.0
261
+ *
262
+ * @return void
263
+ */
264
+ public function set_global_options() {
265
+
266
+ $global_settings = get_option( 'rmp_global_setting_options' );
267
+ if( empty( $global_settings ) ) {
268
+ $default_options = rmp_global_default_setting_options();
269
+ update_option( 'rmp_global_setting_options', $default_options );
270
+ }
271
+ }
272
+
273
+ /**
274
+ * Add sub menu pages in responsive menu admin.
275
+ *
276
+ * @since 4.0.0
277
+ */
278
+ public function rmp_register_submenu_page() {
279
+
280
+ add_submenu_page(
281
+ 'edit.php?post_type=rmp_menu',
282
+ __( 'Settings', 'responsive-menu-pro' ),
283
+ __( 'Settings', 'responsive-menu-pro' ),
284
+ 'manage_options',
285
+ 'settings',
286
+ array( $this, 'rmp_global_settings_page' )
287
+ );
288
+
289
+ add_submenu_page (
290
+ 'edit.php?post_type=rmp_menu',
291
+ __( 'Themes', 'responsive-menu-pro' ),
292
+ __( 'Themes', 'responsive-menu-pro' ),
293
+ 'manage_options',
294
+ 'themes',
295
+ array( $this, 'rmp_theme_admin_page' )
296
+ );
297
+
298
+ }
299
+
300
+ /**
301
+ * Add template to the themes page.
302
+ *
303
+ * @since 4.0.0
304
+ */
305
+ public function rmp_theme_admin_page() {
306
+
307
+ // Check user capabilities.
308
+ if ( ! current_user_can( 'manage_options' ) ) {
309
+ return;
310
+ }
311
+
312
+ include_once RMP_PLUGIN_PATH_V4 . '/templates/rmp-themes.php';
313
+ }
314
+
315
+ /**
316
+ * Add template to the setting page.
317
+ *
318
+ * @since 4.0.0
319
+ *
320
+ * @return void
321
+ */
322
+ public function rmp_global_settings_page() {
323
+
324
+ // Check user capabilities.
325
+ if ( ! current_user_can( 'manage_options' ) ) {
326
+ return;
327
+ }
328
+
329
+ include_once RMP_PLUGIN_PATH_V4 . '/templates/rmp-settings.php';
330
+ }
331
+
332
+ /**
333
+ * Remove create new menu default link of rmp_menu post type.
334
+ *
335
+ * @since 4.0.0
336
+ *
337
+ * @return void
338
+ */
339
+ function remove_default_add_cpt_page() {
340
+ remove_submenu_page( 'edit.php?post_type=rmp_menu', 'post-new.php?post_type=rmp_menu' );
341
+ }
342
+
343
+ /**
344
+ * Function to add the new menu wizard template.
345
+ *
346
+ * @since 4.0.0
347
+ *
348
+ * @return void
349
+ */
350
+ public function add_new_menu_widget() {
351
+ include_once RMP_PLUGIN_PATH_V4 . '/templates/new-menu-wizard.php';
352
+ }
353
+
354
+ /**
355
+ * Function to change the edit label and url.
356
+ * @since 4.0.0
357
+ *
358
+ * @param array $actions List of post row actions.
359
+ * @param Object $post Post object
360
+ *
361
+ * @return array $actions
362
+ */
363
+ public function rmp_menu_row_actions( $actions, $post ) {
364
+
365
+ if ( 'rmp_menu' == $post->post_type ) {
366
+ $actions['edit'] = sprintf(
367
+ '<a href="%s" aria-label="Edit"> %s </a>',
368
+ esc_url( get_edit_post_link( $post->ID ) ),
369
+ __( 'Customize', 'responsive-menu-pro' )
370
+ );
371
+ }
372
+
373
+ return $actions;
374
+ }
375
+
376
+ /**
377
+ * Function to add the custom column.
378
+ *
379
+ * @since 4.0.0
380
+ *
381
+ * @param array $columns List of columns.
382
+ *
383
+ * @return array $columns Edited columns list.
384
+ */
385
+ public function set_custom_edit_menu_columns($columns) {
386
+
387
+ unset( $columns['date'] );
388
+ $columns['shortcode_place'] = __( 'Shortcode', 'responsive-menu-pro' );
389
+ $columns['actions'] = __( 'Actions', 'responsive-menu-pro' );
390
+ $columns['date'] = __( 'Date', 'responsive-menu-pro' );
391
+
392
+ return $columns;
393
+ }
394
+
395
+ /**
396
+ * Function to change the edit url of post type rmp_menu
397
+ *
398
+ * @since 4.0.0
399
+ *
400
+ * @param string $url Post edit URL.
401
+ * @param int $post_id Post ID
402
+ *
403
+ * @return string $url Edited post url URL
404
+ */
405
+ public function my_edit_post_link( $url, $post_id ) {
406
+
407
+ if ( 'rmp_menu' == get_post_type() ) {
408
+ $url = get_admin_url() .'post.php?post='. $post_id .'&action=edit&editor=true';
409
+ }
410
+
411
+ return $url;
412
+ }
413
+
414
+ /**
415
+ * Function to add the data to the custom columns for the rmp_menu post type.
416
+ *
417
+ * @since 4.0.0
418
+ *
419
+ * @param string $column Column Name
420
+ * @param int $post_id Post ID
421
+ *
422
+ * @return void
423
+ */
424
+ function add_custom_columns( $column, $post_id ) {
425
+ $option_manager = Option_Manager::get_instance();
426
+
427
+ switch ( $column ) {
428
+
429
+ case 'actions' :
430
+ echo sprintf(
431
+ '<a href="%s" class="button" aria-label="Customize"> %s </a>',
432
+ esc_url( get_edit_post_link( $post_id) ),
433
+ __( 'Customize', 'responsive-menu-pro' )
434
+ );
435
+ break;
436
+ case 'shortcode_place' :
437
+
438
+ $option = $option_manager->get_option( $post_id, 'menu_display_on' );
439
+ if( 'shortcode' === $option ) {
440
+ echo sprintf('<code>[rmp_menu id="%s"]</code>', $post_id );
441
+ } else {
442
+ esc_html_e( 'Shortcode deactivated', 'responsive-menu-pro' );
443
+ }
444
+
445
+ break;
446
+
447
+ }
448
+ }
449
+
450
+ /**
451
+ * Register rmp_menu custom post type.
452
+ *
453
+ * @since 4.0.0
454
+ */
455
+ public function rmp_menu_cpt() {
456
+
457
+ $labels = array(
458
+ 'name' => __( 'Responsive Menu', 'responsive-menu-pro' ),
459
+ 'singular_name' => 'Rmp_Menu',
460
+ 'menu_name' => __( 'Responsive Menu', 'responsive-menu-pro' ),
461
+ 'parent_item_colon' => __( 'Parent Menu', 'responsive-menu-pro' ),
462
+ 'all_items' => __( 'Menus', 'responsive-menu-pro' ),
463
+ 'view_item' => __( 'View Menu', 'responsive-menu-pro' ),
464
+ 'add_new_item' => __( 'Add New Menu', 'responsive-menu-pro' ),
465
+ 'add_new' => __( 'Create New Menu', 'responsive-menu-pro' ),
466
+ 'edit_item' => __( 'Edit Menu', 'responsive-menu-pro' ),
467
+ 'update_item' => __( 'Update Menu', 'responsive-menu-pro' ),
468
+ 'search_items' => __( 'Search Menu', 'responsive-menu-pro' ),
469
+ 'not_found' => __( 'Not Found', 'responsive-menu-pro' ),
470
+ 'not_found_in_trash' => __( 'Not found in Trash', 'responsive-menu-pro' )
471
+ );
472
+
473
+ $args = array(
474
+ 'label' => __( 'Responsive Menu', 'responsive-menu-pro' ),
475
+ 'description' => __( 'Responsive Menu' , 'responsive-menu-pro' ),
476
+ 'labels' => $labels,
477
+ 'supports' => array( 'title', 'author'),
478
+ 'public' => false,
479
+ 'hierarchical' => false,
480
+ 'show_ui' => true,
481
+ 'show_in_menu' => true,
482
+ 'show_in_nav_menus' => false,
483
+ 'show_in_admin_bar' => false,
484
+ 'has_archive' => false,
485
+ 'can_export' => false,
486
+ 'exclude_from_search' => true,
487
+ 'taxonomies' => array(),
488
+ 'publicly_queryable' => false,
489
+ 'capability_type' => 'post',
490
+ 'menu_icon' => RMP_PLUGIN_URL_V4 .'/assets/images/rmp-logo.png'
491
+ );
492
+
493
+ register_post_type( 'rmp_menu', $args );
494
+
495
+ /**
496
+ * This action will be useful when need hooks after cpt register.
497
+ * @param CPT rmp_menu
498
+ */
499
+ do_action( 'rmp_after_cpt_registered', 'rmp_menu' );
500
+ }
501
+
502
+ /**
503
+ * Function to export the menu
504
+ *
505
+ * @since 4.0.0
506
+ *
507
+ * @return json
508
+ */
509
+ public function rmp_export_menu() {
510
+
511
+ check_ajax_referer( 'rmp_nonce', 'ajax_nonce' );
512
+
513
+ $menu_id = sanitize_text_field( $_POST['menu_id'] );
514
+ if ( empty( $menu_id ) ) {
515
+ wp_send_json_error( [ 'message' => __('Select menu !', 'responsive-menu-pro') ] );
516
+ }
517
+
518
+ $option_manager = Option_Manager::get_instance();
519
+ $option = $option_manager->get_options( $menu_id );
520
+
521
+ wp_send_json_success( json_encode( $option ) );
522
+ }
523
+
524
+ /**
525
+ * Function to import the menu settings.
526
+ *
527
+ * @since 4.0.0
528
+ *
529
+ * @return json
530
+ */
531
+ public function rmp_import_menu() {
532
+
533
+ check_ajax_referer( 'rmp_nonce', 'ajax_nonce' );
534
+
535
+ if( empty( $_FILES['file']['name'] ) ) {
536
+ wp_send_json_error( [ 'message' => __('Please add file !', 'responsive-menu-pro') ] );
537
+ }
538
+
539
+ $file_type = pathinfo( basename( $_FILES["file"]["name"] ), PATHINFO_EXTENSION );
540
+
541
+ if( empty( $_FILES['file']['tmp_name'] ) || 'json' != $file_type ) {
542
+ wp_send_json_error( [ 'message' => __('Please add json file !', 'responsive-menu-pro') ] );
543
+ }
544
+
545
+ $menu_id = sanitize_text_field( $_POST['menu_id'] );
546
+ if ( empty( $menu_id ) ) {
547
+ wp_send_json_error( [ 'message' => __('Select menu !', 'responsive-menu-pro') ] );
548
+ }
549
+
550
+ $file_contents = file_get_contents( $_FILES['file']['tmp_name'] );
551
+ $import_options = json_decode( $file_contents, true );
552
+
553
+ $option_manager = Option_Manager::get_instance();
554
+ $exist_option = $option_manager->get_options( $menu_id );
555
+
556
+ // Some required options replced in imported settings with existing menu settings.
557
+ $import_options['menu_name'] = $exist_option['menu_name'];
558
+ $import_options['theme_type'] = 'default';
559
+ $import_options['menu_theme'] = null;
560
+ $import_options['menu_to_use'] = $exist_option['menu_to_use'];
561
+ $import_options['menu_to_use_in_mobile'] = $exist_option['menu_to_use_in_mobile'];
562
+
563
+ update_post_meta( $menu_id, 'rmp_menu_meta' , $import_options );
564
+ /**
565
+ * Fires when menu is imported.
566
+ *
567
+ * @since 4.0.0
568
+ *
569
+ * @param int $menu_id
570
+ */
571
+ do_action( 'rmp_import_menu', $menu_id );
572
+
573
+ wp_send_json_success( [ 'message' => __( 'Menu settings imported successfully!', 'responsive-menu-pro') ] );
574
+ }
575
+
576
+ }
v4.0.0/inc/classes/class-assets.php ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Assets class.
4
+ *
5
+ * This class is responsible to load the resources as per page call.
6
+ *
7
+ * @since 4.0.0
8
+ * @author Expresstech System
9
+ * @package responsive_menu_pro
10
+ */
11
+
12
+ namespace RMP\Features\Inc;
13
+
14
+ use RMP\Features\Inc\Traits\Singleton;
15
+
16
+ // Disable the direct access to this class.
17
+ if ( ! defined( 'ABSPATH' ) ) {
18
+ exit;
19
+ }
20
+
21
+ /**
22
+ * Class Assets
23
+ *
24
+ */
25
+ class Assets {
26
+
27
+ use Singleton;
28
+
29
+ /**
30
+ * Construct method.
31
+ */
32
+ protected function __construct() {
33
+ $this->setup_hooks();
34
+ }
35
+
36
+ /**
37
+ * To setup action/filter.
38
+ *
39
+ * @return void
40
+ */
41
+ protected function setup_hooks() {
42
+
43
+ add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
44
+ add_action('admin_head', [ $this, 'admin_custom_style_inline'] );
45
+ }
46
+
47
+ /**
48
+ * Add custom css to manage size of admin menu logo.
49
+ *
50
+ * @since 4.0.0
51
+ */
52
+ function admin_custom_style_inline() {
53
+ echo '<style>
54
+ #adminmenu .menu-icon-rmp_menu .wp-menu-image img{
55
+ height: 18px;
56
+ }
57
+
58
+ .responsive-menu-license-upgrade-link {
59
+ color: #f80668;
60
+ font-weight: 600;
61
+ }
62
+
63
+ </style>';
64
+ }
65
+
66
+ /**
67
+ * To enqueue scripts and styles in admin.
68
+ *
69
+ * @param string $hook_suffix Admin page name.
70
+ *
71
+ * @return void
72
+ */
73
+ public function admin_enqueue_scripts( $hook_suffix ) {
74
+
75
+
76
+
77
+ $post_type = get_post_type();
78
+
79
+ if ( empty( $post_type ) && ! empty( $_GET['post_type'] ) ) {
80
+ $post_type = $_GET['post_type'];
81
+ }
82
+
83
+ if ( 'rmp_menu' !== $post_type ) {
84
+ return;
85
+ }
86
+
87
+ if ( wp_is_mobile() ) {
88
+ wp_enqueue_script( 'jquery-touch-punch' );
89
+ }
90
+
91
+ /**
92
+ * Fires before enqueue the scripts.
93
+ */
94
+ do_action( 'before_rmp_enqueue_scripts' );
95
+
96
+ wp_enqueue_script( 'jquery-ui-tabs' );
97
+ wp_enqueue_script( 'jquery-ui-accordion' );
98
+ wp_enqueue_script( 'jquery-ui-draggable' );
99
+ wp_enqueue_script( 'jquery-ui-sortable' );
100
+ wp_enqueue_style( 'wp-color-picker' );
101
+
102
+ if ( ! did_action( 'wp_enqueue_media' ) ) {
103
+ wp_enqueue_media();
104
+ }
105
+
106
+ wp_enqueue_script(
107
+ 'rmp_editor_scripts',
108
+ RMP_PLUGIN_URL_V4 . '/assets/admin/js/rmp-editor.js',
109
+ array('jquery'),
110
+ RMP_PLUGIN_VERSION,
111
+ true
112
+ );
113
+
114
+ wp_enqueue_script(
115
+ 'rmp_admin_icon_scripts',
116
+ RMP_PLUGIN_URL_V4 . '/assets/admin/js/rmp-icon.js',
117
+ array('jquery'),
118
+ RMP_PLUGIN_VERSION,
119
+ true
120
+ );
121
+
122
+ wp_enqueue_script(
123
+ 'rmp_admin_selectize_scripts',
124
+ RMP_PLUGIN_URL_V4 . '/assets/admin/js/selectize.js',
125
+ null,
126
+ RMP_PLUGIN_VERSION
127
+ );
128
+
129
+ wp_enqueue_style(
130
+ 'rmp_admin_selectize_styles',
131
+ RMP_PLUGIN_URL_V4 . '/assets/admin/scss/selectize.css',
132
+ null,
133
+ RMP_PLUGIN_VERSION
134
+ );
135
+
136
+ wp_enqueue_script(
137
+ 'rmp_custom_color_alpha_scripts',
138
+ RMP_PLUGIN_URL_V4 . '/assets/admin/js/wp-color-alpha.js',
139
+ array('wp-color-picker'),
140
+ RMP_PLUGIN_VERSION
141
+ );
142
+
143
+ wp_enqueue_script(
144
+ 'rmp_admin_dropzone_scripts',
145
+ 'https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.7.0/min/dropzone.min.js',
146
+ array('jquery'),
147
+ RMP_PLUGIN_VERSION
148
+ );
149
+
150
+ wp_enqueue_style(
151
+ 'rmp_admin_styles',
152
+ RMP_PLUGIN_URL_V4 . '/assets/admin/scss/admin.css',
153
+ null,
154
+ RMP_PLUGIN_VERSION
155
+ );
156
+
157
+ wp_register_script(
158
+ 'rmp_admin_scripts',
159
+ RMP_PLUGIN_URL_V4 . '/assets/admin/js/rmp-admin.js',
160
+ array( 'wp-color-picker', 'jquery' ),
161
+ RMP_PLUGIN_VERSION,
162
+ true
163
+ );
164
+
165
+ wp_localize_script(
166
+ 'rmp_admin_scripts',
167
+ 'rmpObject',
168
+ array (
169
+ 'ajaxURL' => admin_url( 'admin-ajax.php' ),
170
+ 'ajax_nonce' => wp_create_nonce('rmp_nonce'),
171
+ 'THEMES_FOLDER_URL' => wp_upload_dir()['baseurl'] . '/rmp-themes/',
172
+ )
173
+ );
174
+
175
+ wp_enqueue_script( 'rmp_admin_scripts' );
176
+
177
+ wp_enqueue_script(
178
+ 'rmp_preview_scripts',
179
+ RMP_PLUGIN_URL_V4 . '/assets/admin/js/rmp-preview.js',
180
+ array('jquery'),
181
+ RMP_PLUGIN_VERSION,
182
+ true
183
+ );
184
+
185
+ /** Enqueue the icons resources */
186
+
187
+ wp_enqueue_style( 'dashicons' );
188
+
189
+ wp_enqueue_style(
190
+ 'rmp-admin-fontawesome-icons',
191
+ 'https://use.fontawesome.com/releases/v5.13.0/css/all.css',
192
+ null,
193
+ RMP_PLUGIN_VERSION
194
+ );
195
+
196
+ wp_enqueue_style(
197
+ 'rmp-admin-glyph-icons',
198
+ RMP_PLUGIN_URL_V4 . '/assets/admin/scss/glyphicons.css',
199
+ null,
200
+ RMP_PLUGIN_VERSION
201
+ );
202
+
203
+ /**
204
+ * Fires after enqueue the scripts.
205
+ */
206
+ do_action( 'after_rmp_enqueue_scripts' );
207
+ }
208
+
209
+ }
v4.0.0/inc/classes/class-control-manager.php ADDED
@@ -0,0 +1,1271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Control_Manager class.
4
+ * This class prepare the input control and it's markup.
5
+ *
6
+ * @version 4.0.0
7
+ * @author Expresstech System
8
+ *
9
+ * @package responsive-menu-pro
10
+ */
11
+
12
+ namespace RMP\Features\Inc;
13
+
14
+ use RMP\Features\Inc\Traits\Singleton;
15
+
16
+ // Disable the direct access to this class.
17
+ if ( ! defined( 'ABSPATH' ) ) {
18
+ exit;
19
+ }
20
+
21
+ /**
22
+ * Class Control_Manager
23
+ */
24
+ class Control_Manager {
25
+
26
+ use Singleton;
27
+
28
+ /**
29
+ * Construct method.
30
+ */
31
+ protected function __construct() {
32
+ $this->setup_hooks();
33
+ }
34
+
35
+ /**
36
+ * To setup action/filter.
37
+ *
38
+ * @version 4.0.0
39
+ *
40
+ * @return void
41
+ */
42
+ protected function setup_hooks() {
43
+
44
+ }
45
+
46
+ /**
47
+ * Add hidden field input control.
48
+ *
49
+ * @version 4.0.0
50
+ *
51
+ * @param array List of attribute
52
+ *
53
+ * @return HTML|string
54
+ */
55
+ public function add_hidden_control( $param ) {
56
+ return sprintf( '<input type="hidden" name="%s" value="%s" >',
57
+ esc_attr( $param['name'] ),
58
+ esc_attr( $param['value'] ) );
59
+ }
60
+
61
+ /**
62
+ * This function prepare the single text input control.
63
+ *
64
+ * @version 4.0.0
65
+ * @param array $param List of attributes for a input control
66
+ *
67
+ * @return HTML
68
+ */
69
+ public function add_text_input_control( $param ) {
70
+
71
+ if ( empty( $param ) ) {
72
+ return;
73
+ }
74
+
75
+ /**
76
+ * Filters the text input control attributes before create.
77
+ *
78
+ * @version 4.0.0
79
+ * @param array $param List of attribute.
80
+ */
81
+ $param = apply_filters( 'rmp_before_add_text_input_control', $param );
82
+
83
+ $group_classes = '';
84
+ if ( ! empty( $param['group_classes'] ) ) {
85
+ $group_classes = $param['group_classes'];
86
+ }
87
+
88
+ $html = sprintf('<div class="rmp-input-control-wrapper %s">', $group_classes );
89
+
90
+ //Check tooltip text is added or not.
91
+ $tool_tip = '';
92
+ if ( ! empty( $param['tool_tip'] ) ) {
93
+ $tool_tip = $this->get_tool_tip( $param['tool_tip'] );
94
+ }
95
+
96
+ $is_disabled = '';
97
+ $feature_label = '';
98
+ // Check feature type.
99
+ if( ! empty( $param['feature_type'] ) ) {
100
+ $is_disabled = 'disabled';
101
+ $feature_label = sprintf(
102
+ '<a target="_blank" class="upgrade-tooltip" href="https://responsive.menu/pricing?utm_source=free-plugin&utm_medium=option&utm_campaign=hide_on_mobile" > %s </a>',
103
+ $param['feature_type']
104
+ );
105
+ }
106
+
107
+ // Check label is exist.
108
+ if ( ! empty( $param['label'] ) ) {
109
+ $html .= sprintf(
110
+ '<div class="rmp-input-control-label">
111
+ <span> %s </span>
112
+ <span> %s </span>
113
+ %s
114
+ </div>',
115
+ esc_html( $param['label'] ),
116
+ $tool_tip,
117
+ $feature_label
118
+ );
119
+ }
120
+
121
+ $html .= '<div class="rmp-input-control">';
122
+
123
+ // Check this input has multi device options.
124
+ $has_multi_device = '';
125
+ if ( ! empty( $param['multi_device']) ) {
126
+ $has_multi_device = 'multi-device=true';
127
+
128
+ $html .= $this->get_device_options();
129
+ }
130
+
131
+ //Place holder text.
132
+ $placeholder = '';
133
+ if ( ! empty( $param['placeholder'] ) ) {
134
+ $placeholder = $param['placeholder'];
135
+ }
136
+
137
+ // Check the input control type that maybe text,number or any other.
138
+ if ( ! empty( $param['type']) ) {
139
+
140
+ $class = '';
141
+ if ( ! empty( $param['class'] ) ) {
142
+ $class = $param['class'];
143
+ }
144
+
145
+ $html .= sprintf( '<input type="%s" id="%s" name="%s" %s class="%s" value="%s" placeholder="%s" %s>',
146
+ esc_attr( $param['type'] ),
147
+ esc_attr( $param['id'] ),
148
+ esc_attr( $param['name'] ),
149
+ esc_attr( $has_multi_device ),
150
+ esc_attr( $class ),
151
+ esc_attr( $param['value'] ),
152
+ esc_attr( $placeholder ),
153
+ esc_attr( $is_disabled )
154
+ );
155
+ }
156
+
157
+ // Check the unit of the this control.
158
+ if ( ! empty( $param['has_unit']) ) {
159
+ $unit_type = $param['has_unit']['unit_type'];
160
+ if ( 'all' === $unit_type ) {
161
+ $html .= $this->get_input_control_unit( $param['has_unit'] );
162
+ } else {
163
+ $html .= sprintf('<span class="unit-%1$s"> %1$s </span>', esc_html( $unit_type ) );
164
+ }
165
+ }
166
+
167
+ $html .= '</div></div>';
168
+
169
+ /**
170
+ * Filters the text input attributes/contents after prepared.
171
+ *
172
+ * @version 4.0.0
173
+ *
174
+ * @param HTML|string Input control contents.
175
+ * @param array $param List of attribute.
176
+ */
177
+ $html = apply_filters( 'rmp_text_control_html', $html, $param );
178
+
179
+ // Check if echo parameter is empty or false.
180
+ if ( empty( $param['echo'] ) ) {
181
+ return $html;
182
+ }
183
+
184
+ echo $html;
185
+ }
186
+
187
+ /**
188
+ * This function prepare the group text input control.
189
+ *
190
+ * @version 4.0.0
191
+ * @param array $param List of attributes for a input control
192
+ *
193
+ * @return HTML
194
+ */
195
+ public function add_group_text_control( $param ) {
196
+
197
+ if ( empty( $param) ) {
198
+ return;
199
+ }
200
+
201
+ /**
202
+ * Filters the text group input control attributes before create.
203
+ *
204
+ * @version 4.0.0
205
+ * @param array $param List of attribute.
206
+ */
207
+ $param = apply_filters('rmp_before_add_group_text_control', $param );
208
+
209
+ $group_classes = '';
210
+
211
+ if ( ! empty( $param['group_classes'] ) ) {
212
+ $group_classes = $param['group_classes'];
213
+ }
214
+
215
+ $html = sprintf('<div class="rmp-input-control-wrapper full-size %s">', $group_classes );
216
+
217
+ //Check tooltip text is added or not.
218
+ $tool_tip = '';
219
+ if ( ! empty( $param['tool_tip'] ) ) {
220
+ $tool_tip = $this->get_tool_tip( $param['tool_tip'] );
221
+ }
222
+
223
+ // Check label is exist.
224
+ if ( ! empty( $param['label'] ) ) {
225
+ $html .= sprintf('<div class="rmp-input-control-label"> <span> %s </span> %s </div>', esc_html( $param['label'] ), $tool_tip );
226
+ }
227
+
228
+ $html .= '<div class="rmp-input-control rmp-input-group-control">';
229
+
230
+ // Check this input has multi device options.
231
+ $has_multi_device = '';
232
+ if ( ! empty( $param['multi_device']) ) {
233
+ $has_multi_device = 'multi-device=true';
234
+
235
+ $html .= $this->get_device_options();
236
+ }
237
+
238
+ // Check the input control type that maybe text,number or any other.
239
+ if ( ! empty( $param['type']) ) {
240
+ $class = '';
241
+ if ( ! empty( $param['class'] ) ) {
242
+ $class = $param['class'];
243
+ }
244
+
245
+ if ( ! empty( $param['input_options'] ) ) {
246
+
247
+ foreach( $param['input_options'] as $input ) {
248
+ $value = ! empty( $param['value_options'][$input] ) ? $param['value_options'][$input] : '0px';
249
+
250
+ $html .= sprintf(
251
+ '<div class="rmp-group-input-wrapper">
252
+ <label> %s </label>
253
+ <input type="%s" placeholder="0px" data-input="%s" id="%s" name="%s" %s class="no-updates rmp-group-input %s" value="%s">
254
+ </div>',
255
+ esc_html__( $input, 'responsive-menu-pro' ),
256
+ esc_attr( $param['type'] ),
257
+ esc_attr( $input ),
258
+ esc_attr( $class.'-'.$input ),
259
+ esc_attr( $param['name'].'['. $input .']' ),
260
+ esc_attr( $has_multi_device ),
261
+ esc_attr( $class ),
262
+ esc_attr( $value )
263
+ );
264
+ }
265
+
266
+ $html .= sprintf(
267
+ '<div class="rmp-group-input-wrapper">
268
+ <button type="button" class="is-linked rmp-group-input rmp-group-input-linked">
269
+ <span class="dashicons dashicons-admin-links "></span>
270
+ </button></div>');
271
+ }
272
+ }
273
+
274
+ // Check the unit of the this control.
275
+ if ( ! empty( $param['has_unit']) ) {
276
+ $unit_type = $param['has_unit']['unit_type'];
277
+ if ( 'all' === $unit_type ) {
278
+ $html .= $this->get_input_control_unit( $param['has_unit'] );
279
+ } else {
280
+ $html .= sprintf('<span class="unit-%1$s"> %1$s </span>', esc_html( $unit_type ) );
281
+ }
282
+ }
283
+
284
+ $html .= '</div></div>';
285
+
286
+ /**
287
+ * Filters the text input attributes/contents after prepared.
288
+ *
289
+ * @version 4.0.0
290
+ *
291
+ * @param HTML|string Input control contents.
292
+ * @param array $param List of attribute.
293
+ */
294
+ $html = apply_filters( 'rmp_text_control_html', $html, $param );
295
+
296
+
297
+ // Check if echo parameter is empty or false.
298
+ if ( empty( $param['echo'] ) ) {
299
+ return $html;
300
+ }
301
+
302
+ echo $html;
303
+
304
+ }
305
+
306
+ /**
307
+ * This function prepare input unit options.
308
+ *
309
+ * @version 4.0.0
310
+ * @param array $param List of attributes for a input control
311
+ *
312
+ * @return HTML
313
+ */
314
+ protected function get_input_control_unit( $param ) {
315
+
316
+ if ( empty( $param['name'] ) ) {
317
+ return;
318
+ }
319
+
320
+ $value = '';
321
+
322
+ if ( ! empty( $param['value'] ) ) {
323
+ $value = $param['value'];
324
+ }
325
+
326
+ $has_multi_device = '';
327
+ if ( ! empty( $param['multi_device']) ) {
328
+ $has_multi_device = 'multi-device="true"';
329
+ }
330
+
331
+ $unit_options = [ 'px', '%','em','rem','vw','vh' ];
332
+
333
+ /**
334
+ * Filters the input units.
335
+ *
336
+ * @param array $unit_options List of units.
337
+ */
338
+ $unit_options = apply_filters( 'rmp_input_units', $unit_options );
339
+
340
+ $options = '';
341
+ foreach( $unit_options as $unit ) {
342
+
343
+ $is_selected = '';
344
+ if ( $value === $unit ) {
345
+ $is_selected = 'selected';
346
+ }
347
+
348
+ $feature_label = '';
349
+ $is_disabled = '';
350
+ if ( ! empty( $param['default'] ) && $param['default'] !== $unit ) {
351
+ $is_disabled = 'disabled';
352
+ $feature_label = __( ' (PRO)', 'responsive-menu-pro' );
353
+ }
354
+
355
+ $options .= sprintf(
356
+ '<option %s value="%s" %s >%s</option>',
357
+ esc_attr( $is_disabled ),
358
+ esc_attr($unit),
359
+ esc_attr( $is_selected ),
360
+ esc_attr( $unit . $feature_label )
361
+ );
362
+ }
363
+
364
+ return sprintf(
365
+ '<select id="%1$s" name="%2$s" class="%3$s" %4$s > %5$s </select>',
366
+ esc_attr( $param['id'] ),
367
+ esc_attr( $param['name'] ),
368
+ esc_attr( $param['classes'] ),
369
+ $has_multi_device,
370
+ $options
371
+ );
372
+
373
+ }
374
+
375
+ /**
376
+ * This function prepare the color control.
377
+ *
378
+ * @version 4.0.0
379
+ * @param array $param List of attributes for a input control
380
+ *
381
+ * @return HTML
382
+ */
383
+ public function add_color_control( $param ) {
384
+
385
+ if ( empty( $param) ) {
386
+ return;
387
+ }
388
+
389
+ /**
390
+ * Filters the color input control attribute.
391
+ *
392
+ * @version 4.0.0
393
+ * @param array $param List of attribute.
394
+ */
395
+ $param = apply_filters( 'rmp_before_add_color_control', $param );
396
+
397
+ $group_classes = '';
398
+
399
+ if ( ! empty( $param['group_classes'] ) ) {
400
+ $group_classes = $param['group_classes'];
401
+ }
402
+
403
+ $html = sprintf('<div class="rmp-input-control-wrapper %s">', $group_classes );
404
+
405
+ //Check tooltip text is added or not.
406
+ $tool_tip = '';
407
+ if ( ! empty( $param['tool_tip'] ) ) {
408
+ $tool_tip = $this->get_tool_tip( $param['tool_tip'] );
409
+ }
410
+
411
+ // Check label is exist.
412
+ if ( ! empty( $param['label'] ) ) {
413
+ $html .= sprintf('<div class="rmp-input-control-label"> <span> %s </span> %s </div>', esc_html( $param['label'] ), $tool_tip );
414
+ }
415
+
416
+ $html .= '<div class="rmp-input-control">';
417
+
418
+ // Check this input has multi device options.
419
+ $has_multi_device = '';
420
+ if ( ! empty( $param['multi_device']) ) {
421
+ $has_multi_device = 'multi-device=true';
422
+ $html .= $this->get_device_options();
423
+ }
424
+
425
+ $class = '';
426
+ if ( ! empty( $param['class'] ) ) {
427
+ $class = $param['class'];
428
+ }
429
+
430
+ $html .= sprintf( '<input type="text" id="%s" name="%s" %s class="no-updates rmp-color-input %s" value="%s">',
431
+ esc_attr( $param['id'] ),
432
+ esc_attr( $param['name'] ),
433
+ esc_attr( $has_multi_device ),
434
+ esc_attr( $class ),
435
+ esc_attr( $param['value'] )
436
+ );
437
+
438
+ $html .= '</div></div>';
439
+
440
+
441
+ /**
442
+ * Filters the color input control html.
443
+ *
444
+ * @version 4.0.0
445
+ * @param HTML|string Input control contents.
446
+ * @param array $param List of attribute.
447
+ */
448
+ $html = apply_filters( 'rmp_color_control_html', $html, $param );
449
+
450
+ // Check if echo parameter is empty or false.
451
+ if ( empty( $param['echo'] ) ) {
452
+ return $html;
453
+ }
454
+
455
+ echo $html;
456
+ }
457
+
458
+ /**
459
+ * This function prepare the button input control.
460
+ *
461
+ * @version 4.0.0
462
+ * @param array $param List of attributes for a input control
463
+ *
464
+ * @return HTML
465
+ */
466
+ public function add_button_control( $param ) {
467
+ if ( empty( $param) ) {
468
+ return;
469
+ }
470
+
471
+ /**
472
+ * Filters the button input control attribute.
473
+ *
474
+ * @version 4.0.0
475
+ * @param array $param List of attribute.
476
+ */
477
+ $param = apply_filters('rmp_before_add_button_control', $param );
478
+
479
+ $group_classes = '';
480
+ if ( ! empty( $param['group_classes'] ) ) {
481
+ $group_classes = $param['group_classes'];
482
+ }
483
+
484
+ $html = sprintf( '<div class="rmp-input-control-wrapper %s">', $group_classes );
485
+
486
+ $html .= '<div class="rmp-input-control">';
487
+
488
+ $class = '';
489
+ if ( ! empty( $param['class'] ) ) {
490
+ $class = $param['class'];
491
+ }
492
+
493
+
494
+ $html .= sprintf( '<button type="button" id="%s" class="button button-primary button-large %s" >%s</button>',
495
+ esc_attr( $param['id'] ),
496
+ esc_attr( $class ),
497
+ esc_html( $param['label'] )
498
+ );
499
+
500
+ $html .= '</div></div>';
501
+
502
+ /**
503
+ * Filters the button input control html.
504
+ * @version 4.0.0
505
+ *
506
+ * @param HTML|string Input control contents.
507
+ * @param array $param List of attribute.
508
+ */
509
+ $html = apply_filters( 'rmp_button_control_html', $html, $param );
510
+
511
+ // Check if echo parameter is empty or false.
512
+ if ( empty( $param['echo'] ) ) {
513
+ return $html;
514
+ }
515
+
516
+ echo $html;
517
+
518
+ }
519
+
520
+ /**
521
+ * This function prepare the checkbox as switcher input control.
522
+ *
523
+ * @version 4.0.0
524
+ * @param array $param List of attributes for a input control
525
+ *
526
+ * @return HTML
527
+ */
528
+ public function add_switcher_control( $param ) {
529
+
530
+ if ( empty( $param ) ) {
531
+ return;
532
+ }
533
+
534
+ /**
535
+ * Filters the switcher input control attributes.
536
+ *
537
+ * @version 4.0.0
538
+ * @param array $param List of attribute.
539
+ */
540
+ $param = apply_filters('rmp_before_add_switcher_control', $param );
541
+
542
+ $group_classes = '';
543
+
544
+ if ( ! empty( $param['group_classes'] ) ) {
545
+ $group_classes = $param['group_classes'];
546
+ }
547
+
548
+ $html = sprintf('<div class="rmp-input-control-wrapper rmp-input-control-switcher %s">', $group_classes );
549
+
550
+ //Check tooltip text is added or not.
551
+ $tool_tip = '';
552
+ if ( ! empty( $param['tool_tip'] ) ) {
553
+ $tool_tip = $this->get_tool_tip( $param['tool_tip'] );
554
+ }
555
+
556
+ $is_disabled = '';
557
+ $feature_label = '';
558
+ // Check feature type.
559
+ if( ! empty( $param['feature_type'] ) ) {
560
+ $is_disabled = 'disabled';
561
+ $feature_label = sprintf(
562
+ '<a target="_blank" class="upgrade-tooltip" href="https://responsive.menu/pricing?utm_source=free-plugin&utm_medium=option&utm_campaign=hide_on_mobile" > %s </a>',
563
+ $param['feature_type']
564
+ );
565
+ }
566
+
567
+ // Check label is exist.
568
+ if ( ! empty( $param['label'] ) ) {
569
+ $html .= sprintf(
570
+ '<div class="rmp-input-control-label">
571
+ <span> %s </span>
572
+ %s
573
+ </div>',
574
+ esc_html( $param['label'] ),
575
+ $tool_tip
576
+ );
577
+ }
578
+
579
+ if ( ! empty( $param['name'] ) ) {
580
+
581
+ $html .= '<div class="rmp-input-control">';
582
+ $html .= $feature_label;
583
+
584
+ // Check multi device options is enabled.
585
+ $has_multi_device = '';
586
+ if ( ! empty( $param['multi_device']) ) {
587
+ $has_multi_device = 'multi-device=true';
588
+ $html .= $this->get_device_options();
589
+ }
590
+
591
+ $class = '';
592
+ if ( ! empty( $param['class'] ) ) {
593
+ $class = $param['class'];
594
+ }
595
+
596
+ $html .= sprintf( '<input %s type="hidden" value="off" name="%s"/>', esc_attr( $is_disabled ), esc_attr( $param['name'] ) );
597
+ $html .= sprintf( '<input %s type="checkbox" id="%s" name="%s" %s class="toggle %s" value="on" %s>',
598
+ esc_attr( $is_disabled ),
599
+ esc_attr( $param['id'] ),
600
+ esc_attr( $param['name'] ),
601
+ esc_attr( $has_multi_device ),
602
+ esc_attr( $class ),
603
+ esc_attr( $param['is_checked'] )
604
+ );
605
+
606
+ $html .= '</div>';
607
+ }
608
+
609
+ $html .= '</div>';
610
+
611
+ /**
612
+ * Filters the switcher input control html.
613
+ *
614
+ * @version 4.0.0
615
+ *
616
+ * @param HTML|string Input control contents.
617
+ * @param array $param List of attribute.
618
+ */
619
+ $html = apply_filters( 'rmp_switcher_control_html', $html, $param );
620
+
621
+ // Check if echo parameter is empty or false.
622
+ if ( empty( $param['echo'] ) ) {
623
+ return $html;
624
+ }
625
+
626
+ echo $html;
627
+ }
628
+
629
+ /**
630
+ * This function prepare the select/dropdown input control.
631
+ *
632
+ * @version 4.0.0
633
+ * @param array $param List of attributes for a input control
634
+ *
635
+ * @return HTML
636
+ */
637
+ public function add_select_control( $param ) {
638
+
639
+ if ( empty( $param) ) {
640
+ return;
641
+ }
642
+
643
+ /**
644
+ * Filters the select input control attributes.
645
+ *
646
+ * @version 4.0.0
647
+ * @param array $param List of attribute.
648
+ */
649
+ $param = apply_filters('rmp_before_add_select_control', $param );
650
+
651
+ $group_classes = '';
652
+
653
+ if ( ! empty( $param['group_classes'] ) ) {
654
+ $group_classes = $param['group_classes'];
655
+ }
656
+
657
+ $html = sprintf('<div class="rmp-input-control-wrapper %s">', $group_classes );
658
+
659
+ //Check tooltip text is added or not.
660
+ $tool_tip = '';
661
+ if ( ! empty( $param['tool_tip'] ) ) {
662
+ $tool_tip = $this->get_tool_tip( $param['tool_tip'] );
663
+ }
664
+
665
+ $is_disabled = '';
666
+ $feature_label = '';
667
+ // Check feature type.
668
+ if( ! empty( $param['feature_type'] ) ) {
669
+ $is_disabled = 'disabled';
670
+ $feature_label = sprintf(
671
+ '<a target="_blank" class="upgrade-tooltip" href="https://responsive.menu/pricing?utm_source=free-plugin&utm_medium=option&utm_campaign=hide_on_mobile" > %s </a>',
672
+ $param['feature_type']
673
+ );
674
+ }
675
+
676
+ // Check label is exist.
677
+ if ( ! empty( $param['label'] ) ) {
678
+ $html .= sprintf(
679
+ '<div class="rmp-input-control-label">
680
+ <span> %s </span>
681
+ <span> %s </span>
682
+ %s
683
+ </div>',
684
+ esc_html( $param['label'] ),
685
+ $tool_tip,
686
+ $feature_label
687
+ );
688
+ }
689
+
690
+ $html .= '<div class="rmp-input-control">';
691
+
692
+ // Check multi device options is enabled.
693
+ $has_multi_device = '';
694
+ if ( ! empty( $param['multi_device']) ) {
695
+ $has_multi_device = 'multi-device=true';
696
+
697
+ $html .= $this->get_device_options();
698
+ }
699
+
700
+ $class = '';
701
+ if ( ! empty( $param['class'] ) ) {
702
+ $class = $param['class'];
703
+ }
704
+
705
+ $options = '';
706
+
707
+ if ( ! empty( $param['options'] ) ) {
708
+ foreach( $param['options'] as $key => $value ) {
709
+ $is_select = '';
710
+ if ( ! empty( $param['value'] ) ) {
711
+ if( ! empty( $param['multiple'] ) && is_array( $param['value'] ) && in_array( $key, $param['value'] ) ) {
712
+ $is_select = 'selected';
713
+ } elseif( $key == $param['value'] ) {
714
+ $is_select = 'selected';
715
+ }
716
+ }
717
+
718
+ // Check options is pro.
719
+ $disabled = '';
720
+ if ( strpos( strtolower($value) , 'pro' ) ) {
721
+ $disabled = 'disabled';
722
+ }
723
+
724
+ $options .= sprintf('<option %s value="%s" %s> %s </option>',
725
+ esc_attr( $disabled ),
726
+ esc_attr( $key ),
727
+ esc_attr( $is_select ),
728
+ esc_html( $value )
729
+ );
730
+ }
731
+ }
732
+
733
+ // Check multiple value is allowed.
734
+ $is_multiple_value_allow = '';
735
+ if ( ! empty( $param['multiple'] ) ) {
736
+ $is_multiple_value_allow = 'multiple';
737
+ }
738
+
739
+ $html .= sprintf( '<select id="%s" name="%s" %s class="%s" %s>%s</select>',
740
+ esc_attr( $param['id'] ),
741
+ esc_attr( $param['name'] ),
742
+ esc_attr( $has_multi_device ),
743
+ esc_attr( $class ),
744
+ esc_attr( $is_multiple_value_allow ),
745
+ $options
746
+ );
747
+
748
+ $html .= '</div></div>';
749
+
750
+ /**
751
+ * Filters the select input control html.
752
+ *
753
+ * @version 4.0.0
754
+ *
755
+ * @param HTML|string Input control contents.
756
+ * @param array $param List of attribute.
757
+ */
758
+ $html = apply_filters( 'rmp_select_control_html', $html, $param );
759
+
760
+ // Check if echo parameter is empty or false.
761
+ if ( empty( $param['echo'] ) ) {
762
+ return $html;
763
+ }
764
+
765
+ echo $html;
766
+ }
767
+
768
+ /**
769
+ * This function prepare the tooltip.
770
+ *
771
+ * @version 4.0.0
772
+ * @param array $param List of attributes for a input control
773
+ *
774
+ * @return HTML
775
+ */
776
+ public function get_tool_tip( $param ) {
777
+
778
+ if ( empty( $param['text'] ) ) {
779
+ return;
780
+ }
781
+
782
+ return sprintf(
783
+ '<div class="rmp-tooltip-icon dashicons dashicons-editor-help">
784
+ <span class="rmp-tooltip-content"> %s </span>
785
+ </div>',
786
+ wp_kses(
787
+ $param['text'],
788
+ array(
789
+ 'a' => array(
790
+ 'href' => array(),
791
+ 'title' => array()
792
+ )
793
+ )
794
+ )
795
+ );
796
+ }
797
+
798
+ /**
799
+ * This function prepare the icon picker control.
800
+ *
801
+ * @version 4.0.0
802
+ * @param array $param List of attributes for a input control
803
+ *
804
+ * @return HTML
805
+ */
806
+ public function add_icon_picker_control( $param ) {
807
+
808
+ if ( empty( $param) ) {
809
+ return;
810
+ }
811
+
812
+ $group_classes = '';
813
+
814
+ if ( ! empty( $param['group_classes'] ) ) {
815
+ $group_classes = $param['group_classes'];
816
+ }
817
+
818
+ $html = sprintf('<div class="rmp-input-control-wrapper %s">', $group_classes );
819
+
820
+ //Check tooltip text is added or not.
821
+ $tool_tip = '';
822
+ if ( ! empty( $param['tool_tip'] ) ) {
823
+ $tool_tip = $this->get_tool_tip( $param['tool_tip'] );
824
+ }
825
+
826
+ $is_disabled = '';
827
+ $feature_label = '';
828
+ // Check feature type.
829
+ if( ! empty( $param['feature_type'] ) ) {
830
+ $is_disabled = 'disabled';
831
+ $feature_label = sprintf(
832
+ '<a target="_blank" class="upgrade-tooltip" href="https://responsive.menu/pricing?utm_source=free-plugin&utm_medium=option&utm_campaign=hide_on_mobile" > %s </a>',
833
+ $param['feature_type']
834
+ );
835
+ }
836
+
837
+ // Check label is exist.
838
+ if ( ! empty( $param['label'] ) ) {
839
+ $html .= sprintf(
840
+ '<div class="rmp-input-control-label">
841
+ <span> %s </span>
842
+ <span> %s </span>
843
+ %s
844
+ </div>',
845
+ esc_html( $param['label'] ),
846
+ $tool_tip,
847
+ $feature_label
848
+ );
849
+ }
850
+
851
+ $html .= sprintf('<div class="rmp-input-control rmp-icon-picker-container">');
852
+
853
+ // Check multiple device option enabled.
854
+ $has_multi_device = '';
855
+ if ( ! empty( $param['multi_device']) ) {
856
+ $has_multi_device = 'multi-device=true';
857
+
858
+ $html .= $this->get_device_options();
859
+ }
860
+
861
+ $class = '';
862
+ if ( ! empty( $param['class'] ) ) {
863
+ $class = $param['class'];
864
+ }
865
+
866
+ $icon_value = '';
867
+ $trash_icon = '';
868
+ $is_icon_set = "false";
869
+ if( ! empty( $param['value'] ) ) {
870
+ $icon_value = $param['value'];
871
+ $trash_icon = '<i class="rmp-icon-picker-trash dashicons dashicons-trash" aria-hidden="true"></i>';
872
+ $is_icon_set = "true";
873
+ }
874
+
875
+ $html .= sprintf( '<input type="hidden" placeholder="fa fa-icon" id="%s" name="%s" %s class="rmp-icon-hidden-input %s" value="%s">',
876
+ esc_attr( $param['id'] ),
877
+ esc_attr( $param['name'] ),
878
+ esc_attr( $has_multi_device ),
879
+ esc_attr( $class ),
880
+ esc_attr( $icon_value )
881
+ );
882
+
883
+ $html .= sprintf(
884
+ '<div class="rmp-icon-picker %s" for="%s" id="%s" data-icon="%s">
885
+ <div class="rmp-icon-picker-placeholder">
886
+ <span> %s </span>
887
+ <label> Choose Icon</label>
888
+ </div>
889
+ %s
890
+ %s
891
+ </div>',
892
+ esc_attr( $param['picker_class'] . $is_disabled ),
893
+ esc_attr( $param['id'] ),
894
+ esc_attr( $param['picker_id'] ),
895
+ esc_attr( $is_icon_set ),
896
+ file_get_contents( RMP_PLUGIN_PATH_V4 .'/assets/admin/icons/svg/image-placeholder.svg' ),
897
+ $icon_value,
898
+ $trash_icon
899
+ );
900
+
901
+ $html .= '</div></div>';
902
+
903
+ /**
904
+ * Filters the icon picker control html.
905
+ *
906
+ * @version 4.0.0
907
+ *
908
+ * @param HTML|string Input control contents.
909
+ * @param array $param List of attribute.
910
+ */
911
+ $html = apply_filters( 'rmp_icon_picker_control_html', $html, $param);
912
+
913
+ // Check if echo parameter is empty or false.
914
+ if ( empty( $param['echo'] ) ) {
915
+ return $html;
916
+ }
917
+
918
+ echo $html;
919
+ }
920
+
921
+ /**
922
+ * This function prepare the image input control.
923
+ *
924
+ * @version 4.0.0
925
+ * @param array $param List of attributes for a input control
926
+ *
927
+ * @return HTML
928
+ */
929
+ public function add_image_control( $param ) {
930
+
931
+ if ( empty( $param) ) {
932
+ return;
933
+ }
934
+
935
+ $group_classes = '';
936
+
937
+ if ( ! empty( $param['group_classes'] ) ) {
938
+ $group_classes = $param['group_classes'];
939
+ }
940
+
941
+ $html = sprintf('<div class="rmp-input-control-wrapper %s">', $group_classes );
942
+
943
+ //Check tooltip text is added or not.
944
+ $tool_tip = '';
945
+ if ( ! empty( $param['tool_tip'] ) ) {
946
+ $tool_tip = $this->get_tool_tip( $param['tool_tip'] );
947
+ }
948
+
949
+ // Check label is exist.
950
+ if ( ! empty( $param['label'] ) ) {
951
+ $html .= sprintf('<div class="rmp-input-control-label"> <span> %s </span> %s </div>', esc_html( $param['label'] ), $tool_tip );
952
+ }
953
+
954
+ $html .= '<div class="rmp-input-control rmp-image-picker-container">';
955
+
956
+ // Check multi device option is enabled.
957
+ $has_multi_device = '';
958
+ if ( ! empty( $param['multi_device']) ) {
959
+ $has_multi_device = 'multi-device=true';
960
+ $html .= $this->get_device_options();
961
+ }
962
+
963
+ $class = '';
964
+ if ( ! empty( $param['class'] ) ) {
965
+ $class = $param['class'];
966
+ }
967
+
968
+ $image_url = '';
969
+ $trash_icon = '';
970
+ $image_style = '';
971
+ if ( ! empty( $param['value'] ) ) {
972
+ $image_url = $param['value'];
973
+ $trash_icon = '<i class="rmp-image-picker-trash dashicons dashicons-trash" aria-hidden="true"></i>';
974
+ $image_style = sprintf('style="background-image: url(%s);"', $image_url );
975
+ }
976
+
977
+ $html .= sprintf( '<input type="hidden" id="%s" name="%s" %s class="rmp-image-url-input %s" value="%s">',
978
+ esc_attr( $param['id'] ),
979
+ esc_attr( $param['name'] ),
980
+ esc_attr( $has_multi_device ),
981
+ esc_attr( $class ),
982
+ esc_url( $image_url )
983
+ );
984
+
985
+ $html .= sprintf(
986
+ '<div class="rmp-image-picker %s" for="%s" id="%s" %s>
987
+ <div class="rmp-image-picker-placeholder">
988
+ <span> %s </span>
989
+ <label> Choose Image</label>
990
+ </div>
991
+ %s
992
+ </div>',
993
+ esc_attr( $param['picker_class'] ),
994
+ esc_attr( $param['id'] ),
995
+ esc_attr( $param['picker_id'] ),
996
+ $image_style,
997
+ file_get_contents( RMP_PLUGIN_PATH_V4 .'/assets/admin/icons/svg/image-placeholder.svg' ),
998
+ $trash_icon
999
+ );
1000
+
1001
+ $html .= '</div></div>';
1002
+
1003
+ /**
1004
+ * Filters the icon picker control html.
1005
+ *
1006
+ * @version 4.0.0
1007
+ *
1008
+ * @param HTML|string Input control contents.
1009
+ * @param array $param List of attribute.
1010
+ */
1011
+ $html = apply_filters( 'rmp_add_image_control_html', $html, $param );
1012
+
1013
+ // Check if echo parameter is empty or false.
1014
+ if ( empty( $param['echo'] ) ) {
1015
+ return $html;
1016
+ }
1017
+
1018
+ echo $html;
1019
+ }
1020
+
1021
+ /**
1022
+ * This function prepare the alignment control.
1023
+ *
1024
+ * @version 4.0.0
1025
+ * @param array $param List of attributes for a input control
1026
+ *
1027
+ * @return HTML
1028
+ */
1029
+ public function add_text_alignment_control( $param ) {
1030
+
1031
+ if ( empty( $param) ) {
1032
+ return;
1033
+ }
1034
+
1035
+ $group_classes = '';
1036
+
1037
+ if ( ! empty( $param['group_classes'] ) ) {
1038
+ $group_classes = $param['group_classes'];
1039
+ }
1040
+
1041
+ $html = sprintf('<div class="rmp-input-control-wrapper %s">', $group_classes );
1042
+
1043
+ //Check tooltip text is added or not.
1044
+ $tool_tip = '';
1045
+ if ( ! empty( $param['tool_tip'] ) ) {
1046
+ $tool_tip = $this->get_tool_tip( $param['tool_tip'] );
1047
+ }
1048
+
1049
+ // Check label is exist.
1050
+ if ( ! empty( $param['label'] ) ) {
1051
+ $html .= sprintf('<div class="rmp-input-control-label"> <span> %s </span> %s </div>', esc_html( $param['label'] ), $tool_tip );
1052
+ }
1053
+
1054
+ $html .= '<div class="rmp-input-control">';
1055
+
1056
+ // Check multiple device options is enabled.
1057
+ $has_multi_device = '';
1058
+ if ( ! empty( $param['multi_device']) ) {
1059
+ $has_multi_device = 'multi-device=true';
1060
+
1061
+ $html .= $this->get_device_options();
1062
+ }
1063
+
1064
+ $class = '';
1065
+ if ( ! empty( $param['class'] ) ) {
1066
+ $class = $param['class'];
1067
+ }
1068
+
1069
+ $options = '';
1070
+ foreach( $param['options'] as $value ) {
1071
+ $is_checked = '';
1072
+ if ( $param['value'] == $value ) {
1073
+ $is_checked = 'checked';
1074
+ }
1075
+
1076
+ $id = esc_attr( $class ) . '-' . $value;
1077
+ $icon = '';
1078
+ if ( 'left' == $value ) {
1079
+ $icon = '<span class="dashicons dashicons-editor-alignleft"></span>';
1080
+ } else if( 'justify' == $value ) {
1081
+ $icon = '<span class="dashicons dashicons-editor-justify"></span>';
1082
+ } else if( 'right' == $value ) {
1083
+ $icon = '<span class="dashicons dashicons-editor-alignright "></span>';
1084
+ } else if( 'center' == $value ) {
1085
+ $icon = '<span class="dashicons dashicons-editor-aligncenter "></span>';
1086
+ }
1087
+
1088
+ $options .= sprintf(
1089
+ '<input id="%s" type="radio" name="%s" %s class="no-updates %s" value="%s" %s>
1090
+ <label for="%s"> %s </label>',
1091
+ esc_attr( $id ),
1092
+ esc_attr( $param['name'] ),
1093
+ esc_attr( $has_multi_device ),
1094
+ esc_attr( $class ),
1095
+ esc_attr( $value ),
1096
+ esc_attr( $is_checked ),
1097
+ esc_attr( $id ),
1098
+ $icon
1099
+ );
1100
+ }
1101
+
1102
+ $html .= sprintf( '<div class="align-icons-group"> %s </div>', $options );
1103
+
1104
+ $html .= '</div></div>';
1105
+
1106
+ /**
1107
+ * Filters the icon picker control html.
1108
+ *
1109
+ * @version 4.0.0
1110
+ *
1111
+ * @param HTML|string Input control contents.
1112
+ * @param array $param List of attribute.
1113
+ */
1114
+ $html = apply_filters( 'rmp_add_text_alignment_control_html', $html, $param );
1115
+
1116
+ // Check if echo parameter is empty or false.
1117
+ if ( empty( $param['echo'] ) ) {
1118
+ return $html;
1119
+ }
1120
+
1121
+ echo $html;
1122
+ }
1123
+
1124
+ /**
1125
+ * Function to prepare the device visibility control,
1126
+ * those are mobile, tablet and desktop as options.
1127
+ *
1128
+ * @version 4.0.0
1129
+ *
1130
+ * @param array $options list of values.
1131
+ *
1132
+ * @return HTML
1133
+ */
1134
+ public function add_device_visibility_control( $options ) {
1135
+
1136
+ $mobile = sprintf(
1137
+ '<div class="device-icon">
1138
+ <input type="hidden" name="menu[use_mobile_menu]" value="on"/>
1139
+ <input disabled class="rmp-menu-display-device checkbox mobile" type="checkbox"/>
1140
+ <label for="rmp-menu-display-device-mobile" title="mobile" >
1141
+ <span class="corner-icon">
1142
+ <i class="fas fa-check-circle" aria-hidden="true"></i>
1143
+ </span>
1144
+ <span class="device">
1145
+ <svg width="15" height="20" viewBox="0 0 15 20" fill="none" xmlns="http://www.w3.org/2000/svg">
1146
+ <path d="M7.5 5.625C7.5 5.625 7.49251 5.625 7.47754 5.625C7.28288 5.625 7.10319 5.57259 6.93848 5.46777C6.78874 5.34798 6.68392 5.20573 6.62402 5.04102C6.59408 4.98112 6.57161 4.92122 6.55664 4.86133C6.54167 4.80143 6.53418 4.74154 6.53418 4.68164C6.53418 4.68164 6.53418 4.67415 6.53418 4.65918C6.53418 4.62923 6.53418 4.59928 6.53418 4.56934C6.54915 4.53939 6.55664 4.50195 6.55664 4.45703V4.47949C6.57161 4.44954 6.5791 4.4196 6.5791 4.38965C6.59408 4.3597 6.60905 4.32975 6.62402 4.2998C6.639 4.26986 6.64648 4.23991 6.64648 4.20996C6.66146 4.18001 6.68392 4.15007 6.71387 4.12012C6.72884 4.10514 6.74382 4.08268 6.75879 4.05273C6.77376 4.02279 6.79622 4.00033 6.82617 3.98535C6.90104 3.89551 6.99837 3.82812 7.11816 3.7832C7.23796 3.73828 7.36523 3.71582 7.5 3.71582C7.52995 3.71582 7.5599 3.71582 7.58984 3.71582C7.61979 3.71582 7.64974 3.72331 7.67969 3.73828C7.70964 3.73828 7.73958 3.74577 7.76953 3.76074C7.81445 3.76074 7.8444 3.76823 7.85938 3.7832C7.88932 3.79818 7.91927 3.81315 7.94922 3.82812C7.97917 3.8431 8.00911 3.85807 8.03906 3.87305C8.06901 3.88802 8.09147 3.91048 8.10645 3.94043C8.13639 3.9554 8.15885 3.97038 8.17383 3.98535C8.20378 4.00033 8.22624 4.02279 8.24121 4.05273C8.25618 4.08268 8.27116 4.10514 8.28613 4.12012C8.31608 4.15007 8.33105 4.18001 8.33105 4.20996C8.34603 4.23991 8.361 4.26986 8.37598 4.2998C8.39095 4.32975 8.39844 4.3597 8.39844 4.38965C8.41341 4.4196 8.42839 4.44954 8.44336 4.47949C8.44336 4.50944 8.44336 4.53939 8.44336 4.56934C8.45833 4.59928 8.46582 4.62923 8.46582 4.65918C8.46582 4.73405 8.45833 4.80143 8.44336 4.86133C8.42839 4.92122 8.40592 4.98112 8.37598 5.04102C8.361 5.10091 8.33105 5.16081 8.28613 5.2207C8.25618 5.26562 8.21875 5.31055 8.17383 5.35547C8.08398 5.43034 7.97917 5.49772 7.85938 5.55762C7.75456 5.60254 7.63477 5.625 7.5 5.625ZM9.40918 16.1592C9.40918 15.9046 9.31185 15.6875 9.11719 15.5078C8.9375 15.3132 8.72038 15.2158 8.46582 15.2158H6.53418C6.27962 15.2158 6.05501 15.3132 5.86035 15.5078C5.68066 15.6875 5.59082 15.9046 5.59082 16.1592C5.59082 16.4287 5.68066 16.6608 5.86035 16.8555C6.05501 17.0352 6.27962 17.125 6.53418 17.125H8.46582C8.72038 17.125 8.9375 17.0352 9.11719 16.8555C9.31185 16.6608 9.40918 16.4287 9.40918 16.1592ZM14.2158 16.6533V4.1875C14.2158 3.25911 13.8864 2.47298 13.2275 1.8291C12.5687 1.17025 11.7751 0.84082 10.8467 0.84082H4.15332C3.22493 0.84082 2.43132 1.17025 1.77246 1.8291C1.11361 2.47298 0.78418 3.25911 0.78418 4.1875V16.6533C0.78418 17.5667 1.11361 18.3529 1.77246 19.0117C2.43132 19.6706 3.22493 20 4.15332 20H10.8467C11.7751 20 12.5687 19.6706 13.2275 19.0117C13.8864 18.3529 14.2158 17.5667 14.2158 16.6533ZM10.8467 2.75C11.251 2.75 11.5879 2.89225 11.8574 3.17676C12.1419 3.46126 12.2842 3.79818 12.2842 4.1875V16.6533C12.2842 17.0426 12.1419 17.3796 11.8574 17.6641C11.5879 17.9486 11.251 18.0908 10.8467 18.0908H4.15332C3.74902 18.0908 3.40462 17.9486 3.12012 17.6641C2.85059 17.3796 2.71582 17.0426 2.71582 16.6533V4.1875C2.71582 3.79818 2.85059 3.46126 3.12012 3.17676C3.40462 2.89225 3.74902 2.75 4.15332 2.75H10.8467Z" fill="#56606D"/>
1147
+ </svg>
1148
+ </span>
1149
+ </label>
1150
+ <span class="rmp-input-control-label device-title"> %s </span>
1151
+ </div>',
1152
+ __( 'Mobile', 'responsive-menu-pro' )
1153
+ );
1154
+
1155
+ $tablet = sprintf(
1156
+ '<div class="device-icon">
1157
+ <input type="hidden" name="menu[use_tablet_menu]" value="on"/>
1158
+ <input type="hidden" name="menu[use_tablet_menu]" value="on"/>
1159
+ <input disabled class="rmp-menu-display-device checkbox tablet" type="checkbox"/>
1160
+ <label for="rmp-menu-display-device-tablet" title="tablet" >
1161
+ <span class="corner-icon">
1162
+ <i class="fas fa-check-circle" aria-hidden="true"></i>
1163
+ </span>
1164
+ <span class="device">
1165
+ <svg width="16" height="19" viewBox="0 0 16 19" fill="none" xmlns="http://www.w3.org/2000/svg">
1166
+ <path d="M12.125 19H3.875C2.98698 19 2.22786 18.6849 1.59766 18.0547C0.981771 17.4245 0.673828 16.6725 0.673828 15.7988V3.875C0.673828 2.98698 0.981771 2.23503 1.59766 1.61914C2.22786 0.988932 2.98698 0.673828 3.875 0.673828H12.125C13.013 0.673828 13.765 0.988932 14.3809 1.61914C15.0111 2.23503 15.3262 2.98698 15.3262 3.875V15.7988C15.3262 16.6725 15.0111 17.4245 14.3809 18.0547C13.765 18.6849 13.013 19 12.125 19ZM3.875 2.5C3.5026 2.5 3.18034 2.63607 2.9082 2.9082C2.63607 3.18034 2.5 3.5026 2.5 3.875V15.7988C2.5 16.1712 2.63607 16.4935 2.9082 16.7656C3.18034 17.0378 3.5026 17.1738 3.875 17.1738H12.125C12.4974 17.1738 12.8197 17.0378 13.0918 16.7656C13.3639 16.4935 13.5 16.1712 13.5 15.7988V3.875C13.5 3.5026 13.3639 3.18034 13.0918 2.9082C12.8197 2.63607 12.4974 2.5 12.125 2.5H3.875ZM8.64453 15.9922C8.73047 15.9062 8.79492 15.806 8.83789 15.6914C8.89518 15.5768 8.92383 15.4622 8.92383 15.3477C8.92383 15.3333 8.92383 15.3262 8.92383 15.3262C8.92383 15.0827 8.83073 14.875 8.64453 14.7031C8.47266 14.5169 8.25781 14.4238 8 14.4238C7.74219 14.4238 7.52018 14.5169 7.33398 14.7031C7.16211 14.875 7.07617 15.0827 7.07617 15.3262C7.07617 15.584 7.16211 15.806 7.33398 15.9922C7.52018 16.1641 7.74219 16.25 8 16.25C8.12891 16.25 8.24349 16.2285 8.34375 16.1855C8.45833 16.1283 8.55859 16.0638 8.64453 15.9922Z" fill="#56606D"/>
1167
+ </svg>
1168
+ </span>
1169
+ </label>
1170
+ <span class="rmp-input-control-label device-title"> %s </span>
1171
+ </div>',
1172
+ __( 'Tablet', 'responsive-menu-pro' )
1173
+ );
1174
+
1175
+ $desktop = sprintf(
1176
+ '<div class="device-icon">
1177
+ <input type="hidden" name="menu[use_desktop_menu]" value="off"/>
1178
+ <input disabled class="rmp-menu-display-device checkbox desktop" type="checkbox" />
1179
+ <label for="rmp-menu-display-device-desktop" title="desktop" >
1180
+ <span class="corner-icon">
1181
+ <i class="fas fa-check-circle" aria-hidden="true"></i>
1182
+ </span>
1183
+ <span class="device">
1184
+ <svg width="20" height="19" viewBox="0 0 20 19" fill="none" xmlns="http://www.w3.org/2000/svg">
1185
+ <path d="M15.9512 0.673828H4.04883C3.16081 0.673828 2.40169 0.988932 1.77148 1.61914C1.14128 2.23503 0.826172 2.98698 0.826172 3.875V12.125C0.826172 13.013 1.14128 13.7721 1.77148 14.4023C2.40169 15.0182 3.16081 15.3262 4.04883 15.3262H9.07617V17.1738H6.32617C6.08268 17.1738 5.86784 17.2669 5.68164 17.4531C5.50977 17.625 5.42383 17.8327 5.42383 18.0762C5.42383 18.334 5.50977 18.556 5.68164 18.7422C5.86784 18.9141 6.08268 19 6.32617 19H13.6738C13.9173 19 14.125 18.9141 14.2969 18.7422C14.4831 18.556 14.5762 18.334 14.5762 18.0762C14.5762 17.8327 14.4831 17.625 14.2969 17.4531C14.125 17.2669 13.9173 17.1738 13.6738 17.1738H10.9238V15.3262H15.9512C16.8392 15.3262 17.5983 15.0182 18.2285 14.4023C18.8587 13.7721 19.1738 13.013 19.1738 12.125V3.875C19.1738 2.98698 18.8587 2.23503 18.2285 1.61914C17.5983 0.988932 16.8392 0.673828 15.9512 0.673828ZM17.3262 12.125C17.3262 12.4974 17.1901 12.8197 16.918 13.0918C16.6602 13.3639 16.3379 13.5 15.9512 13.5H4.04883C3.66211 13.5 3.33268 13.3639 3.06055 13.0918C2.80273 12.8197 2.67383 12.4974 2.67383 12.125V3.875C2.67383 3.5026 2.80273 3.18034 3.06055 2.9082C3.33268 2.63607 3.66211 2.5 4.04883 2.5H15.9512C16.3379 2.5 16.6602 2.63607 16.918 2.9082C17.1901 3.18034 17.3262 3.5026 17.3262 3.875V12.125ZM7.76562 3.83203C7.83724 3.90365 7.88737 3.98242 7.91602 4.06836C7.95898 4.13997 7.98047 4.22591 7.98047 4.32617C7.98047 4.42643 7.95898 4.51953 7.91602 4.60547C7.88737 4.67708 7.83724 4.7487 7.76562 4.82031L5.01562 7.57031C4.95833 7.6276 4.88672 7.67057 4.80078 7.69922C4.72917 7.72786 4.64323 7.74219 4.54297 7.74219C4.35677 7.74219 4.19206 7.67773 4.04883 7.54883C3.91992 7.41992 3.85547 7.25521 3.85547 7.05469C3.85547 6.96875 3.86979 6.88997 3.89844 6.81836C3.94141 6.73242 3.99154 6.65365 4.04883 6.58203L6.79883 3.83203C6.85612 3.77474 6.92773 3.73177 7.01367 3.70312C7.09961 3.66016 7.19271 3.63867 7.29297 3.63867C7.37891 3.63867 7.46484 3.66016 7.55078 3.70312C7.63672 3.73177 7.70833 3.77474 7.76562 3.83203Z" fill="white"/>
1186
+ </svg>
1187
+ </span>
1188
+ </label>
1189
+ <span class="rmp-input-control-label device-title"> %s </span>
1190
+ </div>',
1191
+ __( 'Desktop', 'responsive-menu-pro' )
1192
+ );
1193
+
1194
+ $device_options = sprintf( '<div class="device-icons-group">%s %s %s</div>', $mobile, $tablet, $desktop );
1195
+
1196
+ return sprintf(
1197
+ '<div class="rmp-input-control-wrapper full-size">
1198
+ <label class="rmp-input-control-label">
1199
+ %s
1200
+ <a target="_blank" class="upgrade-tooltip" href="https://responsive.menu/pricing?utm_source=free-plugin&utm_medium=option&utm_campaign=hide_on_mobile" > PRO </a>
1201
+ </label>
1202
+ <div class="rmp-input-control">
1203
+ %s
1204
+ </div>
1205
+ </div>',
1206
+ __('Device Visibility', 'responsive-menu-pro'),
1207
+ $device_options
1208
+ );
1209
+ }
1210
+
1211
+ /**
1212
+ * Function to return the device options markup.
1213
+ *
1214
+ * @version 4.0.0
1215
+ *
1216
+ * @return HTML
1217
+ */
1218
+ protected function get_device_options() {
1219
+ return sprintf(
1220
+ '<div class="rmp-device-switcher-holder">
1221
+ <a target="_blank" class="upgrade-tooltip" href="https://responsive.menu/pricing?utm_source=free-plugin&utm_medium=option&utm_campaign=hide_on_mobile" > PRO </a>
1222
+ <ul class="select rmp-device-switcher" >
1223
+ <li data-device="mobile">
1224
+ %s
1225
+ </li>
1226
+ <li data-device="tablet">
1227
+ %s
1228
+ </li>
1229
+ <li data-device="desktop">
1230
+ %s
1231
+ </li>
1232
+ </ul>
1233
+ </div>',
1234
+ file_get_contents( RMP_PLUGIN_PATH_V4 .'/assets/admin/icons/svg/mobile.svg' ),
1235
+ file_get_contents( RMP_PLUGIN_PATH_V4 .'/assets/admin/icons/svg/tablet.svg' ),
1236
+ file_get_contents( RMP_PLUGIN_PATH_V4 .'/assets/admin/icons/svg/desktop.svg' )
1237
+ );
1238
+ }
1239
+
1240
+ public function add_sub_heading( $param ) {
1241
+ if ( empty( $param['text'] ) ) {
1242
+ return;
1243
+ }
1244
+
1245
+ //Check tooltip text is added or not.
1246
+ $tool_tip = '';
1247
+ if ( ! empty( $param['tool_tip'] ) ) {
1248
+ $tool_tip = $this->get_tool_tip( $param['tool_tip'] );
1249
+ }
1250
+
1251
+ return sprintf (
1252
+ '<div class="rmp-accordion-sub-heading"> %s %s</div>',
1253
+ esc_html( $param['text'] ),
1254
+ $tool_tip
1255
+ );
1256
+ }
1257
+
1258
+ public function upgrade_notice() {
1259
+ return sprintf(
1260
+ '<div class="upgrade-options">
1261
+ <div class="upgrade-notes">
1262
+ <p> %s </p>
1263
+ <a target="_blank" href="https://responsive.menu/pricing?utm_source=free-plugin&utm_medium=option&utm_campaign=hide_on_mobile" class="button"> %s </a>
1264
+ </div>
1265
+ </div>',
1266
+ __('This feature is not available in free version. <br/> Upgrade now to use', 'responsive-menu-pro'),
1267
+ esc_html__('Upgrade to Pro', 'responsive-menu-pro')
1268
+ );
1269
+ }
1270
+
1271
+ }
v4.0.0/inc/classes/class-editor-manager.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Editor_Manager class.
4
+ * This class is responsible for editing the menu functionality.
5
+ *
6
+ * @version 4.0.0
7
+ * @author Expresstech System
8
+ *
9
+ * @package responsive-menu-pro
10
+ */
11
+
12
+ namespace RMP\Features\Inc;
13
+
14
+ use RMP\Features\Inc\Traits\Singleton;
15
+ use RMP\Features\Inc\Option_Manager;
16
+
17
+ // Disable the direct access to this class.
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit;
20
+ }
21
+
22
+ /**
23
+ * Class Editor_Manager
24
+ */
25
+ class Editor_Manager {
26
+
27
+ use Singleton;
28
+
29
+ /**
30
+ * Construct method.
31
+ */
32
+ protected function __construct() {
33
+ $this->setup_hooks();
34
+ }
35
+
36
+ /**
37
+ * To setup action/filter.
38
+ *
39
+ * @version 4.0.0
40
+ *
41
+ * @return void
42
+ */
43
+ protected function setup_hooks() {
44
+ add_action('wp_ajax_rmp_save_menu_action', array( $this, 'rmp_save_options' ) );
45
+ add_action('wp_ajax_rmp_mega_menu_item_enable', array( $this, 'enable_mega_menu_item' ) );
46
+ add_action('wp_ajax_rmp_save_mega_menu_item', array( $this, 'rmp_save_mega_menu_item' ) );
47
+ }
48
+
49
+ /**
50
+ * This function save the settings and meta of mega menu item.
51
+ *
52
+ * @version 4.0.0
53
+ *
54
+ * @return json
55
+ */
56
+ public function rmp_save_mega_menu_item() {
57
+
58
+ check_ajax_referer( 'rmp_nonce', 'ajax_nonce' );
59
+
60
+ $item_id = sanitize_text_field( $_POST['item_id'] );
61
+ if ( empty( $item_id ) ) {
62
+ wp_send_json_error( [ 'message' => __( 'Menu Item ID missing', 'responsive-menu-pro' ) ] );
63
+ }
64
+
65
+ $menu_id = sanitize_text_field( $_POST['menu_id'] );
66
+ if ( empty( $menu_id ) ) {
67
+ wp_send_json_error(
68
+ [ 'message' => __( 'Menu ID missing !', 'responsive-menu-pro' )]);
69
+ }
70
+
71
+ if ( empty( $_POST['item_meta'] ) ) {
72
+ wp_send_json_error( [ 'message' => __( 'Unable to get mega menu settings', 'responsive-menu-pro' )] );
73
+ }
74
+
75
+ $item_meta = [];
76
+
77
+ // Don't forget to sanitize the data using recursive.
78
+ if ( is_array( $_POST['item_meta'] ) ) {
79
+
80
+ $item_meta = $_POST['item_meta'];
81
+ }
82
+
83
+ update_post_meta( $menu_id, '_rmp_mega_menu_'. $item_id, $item_meta );
84
+
85
+ /**
86
+ * Fires when mega menu item settings update.
87
+ *
88
+ * @version 4.0.0
89
+ *
90
+ * @param int $menu_id Menu Id.
91
+ * @param int $item_id Item ID for which mega menu settings are updated
92
+ * @param array $item_meta List of mega menu settings of an item.
93
+ */
94
+ do_action( 'rmp_update_mega_menu_item', $menu_id, $item_id, $item_meta );
95
+
96
+ wp_send_json_success( ['message' => 'success'] );
97
+
98
+ }
99
+
100
+ /**
101
+ * Function to update the enable option of mega menu item.
102
+ *
103
+ * @version 4.0.0
104
+ *
105
+ * @return json
106
+ */
107
+ public function enable_mega_menu_item() {
108
+
109
+ check_ajax_referer( 'rmp_nonce', 'ajax_nonce' );
110
+
111
+ $menu_id = sanitize_text_field( $_POST['menu_id'] );
112
+ $item_id = sanitize_text_field( $_POST['item_id'] );
113
+ $value = sanitize_text_field( $_POST['value'] );
114
+
115
+ $options = get_post_meta( $menu_id, 'rmp_menu_meta' );
116
+
117
+ if ( ! empty( $options ) ) {
118
+ $options = $options[0];
119
+ $options['mega_menu'][$item_id] = $value ;
120
+ $options = update_post_meta( $menu_id, 'rmp_menu_meta', $options );
121
+
122
+ wp_send_json_success( [ 'message' => __( 'Success', 'responsive-menu-pro' ) ] );
123
+ }
124
+
125
+ wp_send_json_error(
126
+ [ 'message' => __( 'Menu not found', 'responsive-menu-pro' ) ]
127
+ );
128
+
129
+ }
130
+
131
+ /**
132
+ * This function saved the menu options when click update in the menu editor.
133
+ *
134
+ * @since 4.0.0
135
+ *
136
+ * @return json
137
+ */
138
+ public function rmp_save_options() {
139
+
140
+ check_ajax_referer( 'rmp_nonce', 'ajax_nonce' );
141
+
142
+ $options = [];
143
+ parse_str( $_POST['form'], $options );
144
+
145
+ $menu_id = sanitize_text_field( $options['menu_id'] );
146
+ if ( empty( $menu_id ) ) {
147
+ wp_send_json_error( [ 'message' => __( 'Menu ID missing !', 'responsive-menu-pro' ) ] );
148
+ }
149
+
150
+ $options = $options['menu'];
151
+
152
+ // Merge the default and update options.
153
+ $options = array_merge( rmp_get_default_options() , $options );
154
+
155
+ update_post_meta( $menu_id, 'rmp_menu_meta', $options );
156
+
157
+ /**
158
+ * Fires when saved the options.
159
+ *
160
+ * @version 4.0.0
161
+ * @param int $menu_id Menu ID.
162
+ */
163
+ do_action( 'rmp_save_menu', $menu_id );
164
+
165
+ // Return the response after success.
166
+ wp_send_json_success();
167
+ }
168
+
169
+ }
v4.0.0/inc/classes/class-editor.php ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Editor class.
4
+ * This class is responsible for editor UI.
5
+ *
6
+ * @version 4.0.0
7
+ * @author Expresstech System
8
+ *
9
+ * @package responsive-menu-pro
10
+ */
11
+
12
+ namespace RMP\Features\Inc;
13
+
14
+ use RMP\Features\Inc\Traits\Singleton;
15
+
16
+ // Disable the direct access to this class.
17
+ if ( ! defined( 'ABSPATH' ) ) {
18
+ exit;
19
+ }
20
+
21
+ /**
22
+ * Class Editor
23
+ */
24
+ class Editor {
25
+
26
+ use Singleton;
27
+
28
+ /**
29
+ * Construct method.
30
+ */
31
+ protected function __construct() {
32
+ $this->setup_hooks();
33
+ }
34
+
35
+ /**
36
+ * To setup action/filter.
37
+ *
38
+ * @version 4.0.0
39
+ *
40
+ * @return void
41
+ */
42
+ protected function setup_hooks() {
43
+ add_action( 'admin_head', [ $this,'render_menu_editor_page'] );
44
+ }
45
+
46
+ /**
47
+ * Function to load the menu editor page when click on particular menu
48
+ * customize option from menu list.
49
+ *
50
+ * @version 4.0.0
51
+ *
52
+ * @return void
53
+ */
54
+ public function render_menu_editor_page() {
55
+
56
+ $editor = filter_input( INPUT_GET, 'editor', FILTER_SANITIZE_STRING );
57
+ if ( ! empty( $editor ) && get_post_type() == 'rmp_menu' && is_admin() ) {
58
+ set_current_screen();
59
+ include RMP_PLUGIN_PATH_V4 . '/templates/rmp-editor.php';
60
+ exit;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Add hooter section in editor.
66
+ *
67
+ * @version 4.0.0
68
+ *
69
+ * @param HTML.
70
+ */
71
+ public function header_section( $menu_name ) {
72
+
73
+ ob_start();
74
+ ?>
75
+ <div id="rmp-editor-header" class="rmp-editor-header">
76
+
77
+ <!-- Plugin logo on editor header-->
78
+ <div class="rmp-editor-header-logo">
79
+ <span class="dashicons dashicons-arrow-left-alt rmp-editor-header-back"></span>
80
+ <img alt="logo" src="<?php echo esc_url( RMP_PLUGIN_URL_V4 .'/assets/images/rmp-logo.png' ); ?>" />
81
+ </div>
82
+
83
+ <!-- Menu title on editor header-->
84
+ <div class="rmp-editor-header-title"><?php echo esc_html( $menu_name ); ?></div>
85
+
86
+ <!-- Exit from editor button in header-->
87
+ <a class="rmp-editor-header-close" href="<?php echo esc_url( admin_url().'/edit.php?post_type=rmp_menu' ); ?>">
88
+ <span class="fas fa-times"></span>
89
+ <span class="screen-reader-text">
90
+ <?php echo esc_html__('Close the editor and go back to the previous page', 'responsive-menu-pro' ); ?>
91
+ </span>
92
+ </a>
93
+
94
+ </div>
95
+ <?php
96
+
97
+ $html = ob_get_clean();
98
+
99
+ /**
100
+ * Filters the editor header.
101
+ *
102
+ * @param string|HTML $html
103
+ */
104
+ $html = apply_filters( 'rmp_editor_header_html', $html );
105
+
106
+ return $html;
107
+ }
108
+
109
+ /**
110
+ * Add Footer section in editor.
111
+ *
112
+ * @param HTML.
113
+ */
114
+ public function footer_section() {
115
+ ob_start();
116
+ ?>
117
+ <div id="rmp-editor-footer" class="rmp-editor-footer">
118
+
119
+ <!-- Update the settings button in footer-->
120
+ <button type="button" class="menu-save" id="rmp-save-menu-options">
121
+ <?php esc_html_e( 'Update', 'responsive-menu-pro' ); ?>
122
+ </button>
123
+
124
+ <!-- Themes options when click on up arrow button in footer-->
125
+ <button type="button" class="rmp-theme-settings" id="rmp-theme-action" >
126
+ <span class="dashicons dashicons-arrow-up "></span>
127
+ </button>
128
+
129
+ <div class="rmp-footer-sub-menu-wrapper" id="rmp-footer-theme-options">
130
+ <ul class="rmp-footer-sub-menu">
131
+ <li>
132
+ <a id="rmp-theme-save-button" class="rmp-theme-save-button">
133
+ <span class="fas fa-save"></span>
134
+ <span> <?php esc_html_e( 'Save as theme', 'responsive-menu-pro' ); ?></span>
135
+ </a>
136
+ </li>
137
+
138
+ <li>
139
+ <a id="rmp-theme-change-button" class="rmp-theme-change-button" >
140
+ <span class="fas fa-folder-open "></span>
141
+ <span><?php esc_html_e( 'Change theme', 'responsive-menu-pro' ); ?></span>
142
+ </a>
143
+ </li>
144
+ </ul>
145
+ </div>
146
+
147
+ <!-- Device options in footer-->
148
+ <div class="rmp-preview-device-wrapper">
149
+
150
+ <button type="button" id="rmp-preview-mobile" class=" rmp-device-preview rmp-preview-mobile active" aria-pressed="1" data-device="mobile">
151
+ <?php echo file_get_contents( RMP_PLUGIN_PATH_V4 .'/assets/admin/icons/svg/mobile.svg' ); ?>
152
+ <span class="screen-reader-text">
153
+ <?php echo esc_html__('Enter mobile preview mode', 'responsive-menu-pro' ); ?>
154
+ </span>
155
+ </button>
156
+
157
+ <button type="button" id="rmp-preview-tablet" class="rmp-preview-tablet rmp-device-preview" aria-pressed="" data-device="tablet">
158
+ <?php echo file_get_contents( RMP_PLUGIN_PATH_V4 .'/assets/admin/icons/svg/tablet.svg' ); ?>
159
+ <span class="screen-reader-text">
160
+ <?php echo esc_html__('Enter tablet preview mode', 'responsive-menu-pro' ); ?>
161
+ </span>
162
+ </button>
163
+
164
+ <button type="button" id="rmp-preview-desktop" class="rmp-preview-desktop rmp-device-preview" aria-pressed="" data-device="desktop">
165
+ <?php echo file_get_contents( RMP_PLUGIN_PATH_V4 .'/assets/admin/icons/svg/desktop.svg' ); ?>
166
+ <span class="screen-reader-text">
167
+ <?php echo esc_html__('Enter desktop preview mode', 'responsive-menu-pro' ); ?>
168
+ </span>
169
+ </button>
170
+
171
+ </div>
172
+
173
+ </div>
174
+ <?php
175
+
176
+ $html = ob_get_clean();
177
+
178
+ /**
179
+ * Filters the editor footer html.
180
+ *
181
+ * @param string|HTML $html
182
+ */
183
+ $html = apply_filters( 'rmp_editor_footer_html', $html );
184
+
185
+ return $html;
186
+ }
187
+
188
+ /**
189
+ * Function to return the markups for sidebar drawers.
190
+ *
191
+ * @return HTML|string
192
+ */
193
+ public function sidebar_drawer() {
194
+ return (
195
+ '<button type="button" class="collapse-sidebar" aria-expanded="true" aria-label="Hide Controls">
196
+ <span class="collapse-sidebar-arrow"></span>
197
+ </button>'
198
+ );
199
+ }
200
+
201
+ }
v4.0.0/inc/classes/class-option-manager.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file contain the Option_Manager class and it's functionalities.
4
+ *
5
+ * @version 4.0.0
6
+ * @author Expresstech System
7
+ *
8
+ * @package responsive-menu-pro
9
+ */
10
+
11
+ namespace RMP\Features\Inc;
12
+
13
+ use RMP\Features\Inc\Traits\Singleton;
14
+ use responsive_menu_pro\frontend\RMP_Menu;
15
+
16
+ // Disable the direct access to this class.
17
+ if ( ! defined( 'ABSPATH' ) ) {
18
+ exit;
19
+ }
20
+
21
+ /**
22
+ * Class Option_Manager
23
+ * This class is responsible for provide the options for menu that
24
+ * maybe global or specific menu options.
25
+ *
26
+ * @version 4.0.0
27
+ */
28
+ class Option_Manager {
29
+
30
+ use Singleton;
31
+
32
+ /**
33
+ * Construct method.
34
+ */
35
+ protected function __construct() {
36
+ $this->setup_hooks();
37
+ }
38
+
39
+ /**
40
+ * To setup action/filter.
41
+ *
42
+ * @version 4.0.0
43
+ *
44
+ * @return void
45
+ */
46
+ protected function setup_hooks() {
47
+ }
48
+
49
+ /**
50
+ * This function get all options stored in rmp_menu post meta for menu.
51
+ *
52
+ * @access public
53
+ * @param int $menu_id Menu id
54
+ *
55
+ * @return array $options Array of backend setting options.
56
+ */
57
+ public function get_options( $menu_id ) {
58
+
59
+ $options = get_post_meta( $menu_id, 'rmp_menu_meta' );
60
+
61
+ if ( empty( $options[0] ) ) {
62
+ return [];
63
+ }
64
+
65
+ $options = $options[0];
66
+ $options['menu_id'] = $menu_id;
67
+
68
+ return $options;
69
+ }
70
+
71
+ /**
72
+ * This function get all options stored in table for responsive menu.
73
+ *
74
+ * @access public
75
+ * @param int $menu_id Menu id
76
+ *
77
+ * @return array $options Array of backend setting options.
78
+ */
79
+ public function get_option( $menu_id, $key ) {
80
+
81
+ $options = $this->get_options( $menu_id );
82
+
83
+ if ( ! empty( $options[$key] ) ) {
84
+ return $options[$key];
85
+ }
86
+
87
+ return;
88
+ }
89
+
90
+ /**
91
+ * Return the global setting options.
92
+ *
93
+ * @version 4.0.0
94
+ * @access public
95
+ *
96
+ * @return array
97
+ */
98
+ public function get_global_options() {
99
+
100
+ $global_settings = get_option( 'rmp_global_setting_options' );
101
+
102
+ if ( ! empty( $global_settings ) ) {
103
+ return $global_settings;
104
+ }
105
+
106
+ return [];
107
+ }
108
+
109
+ /**
110
+ * Return global option
111
+ *
112
+ * @version 4.0.0
113
+ *
114
+ * @access public
115
+ * @param string $key Option name.
116
+ *
117
+ * @return string|null
118
+ */
119
+ public function get_global_option( $key ) {
120
+
121
+ $global_options = $this->get_global_options();
122
+
123
+ if ( ! empty( $global_options[$key] ) ) {
124
+ return $global_options[$key];
125
+ }
126
+
127
+ return;
128
+ }
129
+
130
+ }
v4.0.0/inc/classes/class-plugin.php ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin manifest class.
4
+ *
5
+ * @package responsive-menu-pro
6
+ */
7
+
8
+ namespace RMP\Features\Inc;
9
+
10
+ use RMP\Features\Inc\Traits\Singleton;
11
+
12
+ /**
13
+ * Class Plugin
14
+ */
15
+ class Plugin {
16
+
17
+ use Singleton;
18
+
19
+ /**
20
+ * Construct method.
21
+ */
22
+ protected function __construct() {
23
+ // Load plugin classes.
24
+ Admin::get_instance();
25
+ Assets::get_instance();
26
+ Editor::get_instance();
27
+ Editor_Manager::get_instance();
28
+ Preview::get_instance();
29
+ Control_Manager::get_instance();
30
+ Theme_Manager::get_instance();
31
+ Option_Manager::get_instance();
32
+ Style_Manager::get_instance();
33
+ UI_Manager::get_instance();
34
+ RMP_Migration::get_instance();
35
+
36
+ $this->setup_hooks();
37
+ }
38
+
39
+ /**
40
+ * To setup action/filter.
41
+ *
42
+ * @return void
43
+ */
44
+ protected function setup_hooks() {
45
+
46
+ add_action( 'plugins_loaded', [ $this, 'rmp_load_plugin_text_domain' ] );
47
+ add_action( 'admin_notices', [ $this, 'rmp_deactivate_paid_version_notice' ] );
48
+
49
+ // Check current config and environment support wp_body_open or not.
50
+
51
+ if( $this->has_support( 'wp_body_open' ) ) {
52
+ add_action( 'wp_body_open' , [ $this, 'menu_render_on_frontend'] );
53
+ } else {
54
+ add_action( 'wp_footer' , [ $this, 'menu_render_on_frontend'] );
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Function to show the admin notice if plugin deactivate.
60
+ *
61
+ * @return void
62
+ */
63
+ public function rmp_deactivate_paid_version_notice() {
64
+ if( get_transient('og-admin-notice-activation') ) {
65
+ printf(
66
+ '<div class="notice notice-error is-dismissible">
67
+ <p>%s</p>
68
+ </div>',
69
+ __('Responsive Menu has been deactivated','responsive-menu-pro' )
70
+ );
71
+ delete_transient( 'og-admin-notice-activation-pro' );
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Load plugin text domain.
77
+ *
78
+ * @version 4.0.0
79
+ *
80
+ * @return void
81
+ */
82
+ public function rmp_load_plugin_text_domain() {
83
+ load_plugin_textdomain( 'responsive-menu-pro', false, RMP_PLUGIN_DIR_NAME . '/v4.0.0/languages' );
84
+ }
85
+
86
+ /**
87
+ * Function to render the nenu on frontend.
88
+ *
89
+ * @version 4.0.0
90
+ */
91
+ function menu_render_on_frontend() {
92
+
93
+ $option_manager = Option_Manager::get_instance();
94
+ $menu_ids = get_all_rmp_menu_ids();
95
+
96
+ if ( empty( $menu_ids ) ) {
97
+ return;
98
+ }
99
+
100
+ foreach ( $menu_ids as $menu_id ) {
101
+
102
+ $menu_show_on = $option_manager->get_option( $menu_id, 'menu_display_on' );
103
+
104
+ if ( ! empty( $menu_show_on ) && 'shortcode' === $menu_show_on ) {
105
+ continue;
106
+ }
107
+
108
+ $menu = new \RMP\Features\Inc\RMP_Menu( $menu_id );
109
+ $menu->build_menu();
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Check support of wp_body_open for plugins and themes.
115
+ *
116
+ * @since 4.0.0
117
+ *
118
+ * @param string $hook Name of hook.
119
+ * @return boolean
120
+ */
121
+ public function has_support( $hook ) {
122
+
123
+ // Check wp core support wp_body_open hook or not.
124
+ if( ! has_action( $hook ) ) {
125
+ return false;
126
+ }
127
+
128
+ // If is_plugin_active function not exist then add plugin.php file from core.
129
+ if( ! function_exists( 'is_plugin_active' ) ) {
130
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
131
+ }
132
+
133
+ // List of unsupported themes and plugins.
134
+ $unsupported_extensions = [
135
+ 'oxygen/functions.php'
136
+ ];
137
+
138
+ foreach( $unsupported_extensions as $extension ) {
139
+ if( is_plugin_active( $extension ) ) {
140
+ return false;
141
+ }
142
+ }
143
+
144
+ return true;
145
+ }
146
+
147
+ }
v4.0.0/inc/classes/class-preview.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Preview class.
4
+ * This class is responsible for preview related functionality.
5
+ *
6
+ * @version 4.0.0
7
+ * @author Expresstech System
8
+ *
9
+ * @package responsive-menu-pro
10
+ */
11
+
12
+ namespace RMP\Features\Inc;
13
+
14
+ use RMP\Features\Inc\Traits\Singleton;
15
+ use RMP\Features\Inc\RMP_Menu;
16
+
17
+ // Disable the direct access to this class.
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit;
20
+ }
21
+
22
+ /**
23
+ * Class Preview
24
+ */
25
+ class Preview {
26
+
27
+ use Singleton;
28
+
29
+ /**
30
+ * Construct method.
31
+ */
32
+ protected function __construct() {
33
+ $this->setup_hooks();
34
+ }
35
+
36
+ /**
37
+ * To setup action/filter.
38
+ *
39
+ * @version 4.0.0
40
+ *
41
+ * @return void
42
+ */
43
+ protected function setup_hooks() {
44
+ add_action('wp_ajax_rmp_enable_menu_item', array( $this, 'enable_menu_item' ) );
45
+ }
46
+
47
+ /**
48
+ * This function get the content of menu item for live preview element.
49
+ *
50
+ * @return HTML
51
+ */
52
+ public function enable_menu_item() {
53
+
54
+ check_ajax_referer( 'rmp_nonce', 'ajax_nonce' );
55
+
56
+ $menu_id = $_POST['menu_id'];
57
+ $menu_element = $_POST['menu_element'];
58
+ $menu = new RMP_Menu($menu_id);
59
+
60
+ if ( $menu_element === 'menu' ) {
61
+ $html = $menu->menu();
62
+ } elseif ( 'search' === $menu_element ) {
63
+ $html = $menu->menu_search_box();
64
+ } elseif( 'title' === $menu_element ) {
65
+ $html = $menu->menu_title();
66
+ } else {
67
+ $html = $menu->menu_additional_content();
68
+ }
69
+
70
+ wp_send_json_success( [ 'markup' => $html ] );
71
+
72
+ }
73
+
74
+ }
v4.0.0/inc/classes/class-rmp-menu.php ADDED
@@ -0,0 +1,442 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * This is core class file for responsive menu pro.
5
+ *
6
+ * @since 4.0.0
7
+ *
8
+ * @package responsive_menu_pro
9
+ */
10
+
11
+ namespace RMP\Features\Inc;
12
+ use RMP\Features\Inc\Option_Manager;
13
+ use RMP\Features\Inc\Walker;
14
+
15
+ /** Disbale the direct access to this class */
16
+ if ( ! defined( 'ABSPATH' ) ) {
17
+ exit;
18
+ }
19
+
20
+ if ( ! class_exists( 'RMP_Menu' ) ) :
21
+
22
+ /**
23
+ * Class RMP_Menu prepare the menu as per loction and menu id.
24
+ *
25
+ * @package responsive_menu_pro
26
+ *
27
+ * @author Expresstech System
28
+ */
29
+ class RMP_Menu {
30
+
31
+ /**
32
+ * Hold the menu id.
33
+ *
34
+ * @since 4.0.0
35
+ * @access protected
36
+ * @var string $menu_id
37
+ */
38
+ protected $menu_id;
39
+
40
+ /**
41
+ * Hold the menu id.
42
+ *
43
+ * @since 4.0.0
44
+ * @access protected
45
+ * @var array $options
46
+ */
47
+ public $options;
48
+
49
+ /**
50
+ * This is menu class constructor function.
51
+ *
52
+ * @access public
53
+ *
54
+ */
55
+ public function __construct( $menu_id ) {
56
+
57
+ $option_manager = Option_Manager::get_instance();
58
+ $this->options = $option_manager->get_options( $menu_id );
59
+
60
+ $this->menu_id = $menu_id;
61
+ }
62
+
63
+ /**
64
+ * Prepare mobile menu markup.
65
+ *
66
+ * @version 4.0.0
67
+ *
68
+ * @return HTML|string
69
+ */
70
+ public function mobile_menu() {
71
+
72
+ $menu_switcher = $this->menu_trigger();
73
+
74
+ $menu_items = '';
75
+ if ( ! empty( $this->options['items_order'] ) ) {
76
+ $menu_items = $this->options['items_order'];
77
+ }
78
+
79
+ $html = '';
80
+
81
+ if ( empty( $menu_items ) ) {
82
+ return;
83
+ }
84
+
85
+ foreach( $menu_items as $key => $value ) {
86
+ if ( ! empty( $value ) && $value === 'on' ) {
87
+ if ( 'menu' === $key ) {
88
+ $html .= $this->menu();
89
+ } elseif ( 'title' === $key ) {
90
+ $html .= $this->menu_title();
91
+ } elseif ( 'search' === $key ) {
92
+ $html .= $this->menu_search_box();
93
+ } else {
94
+ $html .= $this->menu_additional_content();
95
+ }
96
+ }
97
+ }
98
+
99
+ $side_animation = 'rmp-' . $this->options['animation_type'] . '-' . $this->options['menu_appear_from'];
100
+ $html = sprintf( '%s<div id="rmp-container-%s" class="rmp-container %s">%s</div>',
101
+ $menu_switcher,
102
+ $this->menu_id,
103
+ esc_attr( $side_animation ),
104
+ $html
105
+ );
106
+
107
+ return $html;
108
+ }
109
+
110
+ /**
111
+ * Function to print the menu markups in webpage.
112
+ */
113
+ public function build_menu() {
114
+ echo $this->mobile_menu();
115
+ return;
116
+ }
117
+
118
+ public function menu() {
119
+ $param = $this->rmp_nav_menu_args();
120
+ $param['echo'] = false;
121
+ return wp_nav_menu( $param );
122
+ }
123
+
124
+ public function menu_trigger() {
125
+
126
+ $menu_trigger_type = '<span class="rmp-trigger-box">';
127
+
128
+ //Normal state menu trigger type.
129
+ if ( ! empty( $this->options['button_font_icon'] ) ) {
130
+ $menu_trigger_type .= sprintf(
131
+ '<span class="rmp-trigger-icon rmp-trigger-icon-inactive">%s</span>',
132
+ $this->options['button_font_icon']
133
+ );
134
+ } else if ( ! empty ( $this->options['button_image'] ) ) {
135
+ $menu_trigger_type .= sprintf(
136
+ '<img src="%s" alt="%s" class="rmp-trigger-icon rmp-trigger-icon-inactive" width="100" height="100">',
137
+ esc_url( $this->options['button_image'] ),
138
+ rmp_image_alt_by_url( $this->options['button_image'] )
139
+ );
140
+ } else {
141
+ $menu_trigger_type .= sprintf('<span class="responsive-menu-pro-inner"></span>');
142
+ }
143
+
144
+ //Active state menu trigger type.
145
+ if ( ! empty( $this->options['button_font_icon_when_clicked'] ) ) {
146
+ $menu_trigger_type .= sprintf(
147
+ '<span class="rmp-trigger-icon rmp-trigger-icon-active">%s</span>',
148
+ $this->options['button_font_icon_when_clicked']
149
+ );
150
+ } else if ( ! empty ( $this->options['button_image_when_clicked'] ) ) {
151
+ $menu_trigger_type .= sprintf(
152
+ '<img src="%s" alt="%s" class="rmp-trigger-icon rmp-trigger-icon-active" width="100" height="100">',
153
+ esc_url( $this->options['button_image_when_clicked'] ),
154
+ rmp_image_alt_by_url( $this->options['button_image_when_clicked'] )
155
+ );
156
+ }
157
+
158
+ $menu_trigger_type .= '</span>';
159
+
160
+ $menu_trigger_text = '';
161
+ $trigger_text_position = '';
162
+
163
+ if ( !empty( $this->options['button_title_position'] ) ) {
164
+ $trigger_text_position = $this->options['button_title_position'];
165
+ }
166
+
167
+ //Menu trigger text.
168
+ if ( ! empty( $this->options['button_title'] ) ) {
169
+ $menu_trigger_text .= sprintf(
170
+ '<span class="rmp-trigger-text">%s</span>',
171
+ esc_html( $this->options['button_title'] )
172
+ );
173
+
174
+ if ( ! empty( $this->options['button_title_open'] ) ) {
175
+ $menu_trigger_text .= sprintf(
176
+ '<span class="rmp-trigger-text-open">%s</span>',
177
+ esc_html( $this->options['button_title_open'] )
178
+ );
179
+ }
180
+
181
+ $menu_trigger_text = sprintf(
182
+ '<div class="rmp-trigger-label rmp-trigger-label-%s">
183
+ %s
184
+ </div>',
185
+ esc_attr($trigger_text_position),
186
+ $menu_trigger_text
187
+ );
188
+ }
189
+
190
+ $menu_trigger_content = '';
191
+
192
+ if ( 'left' === $trigger_text_position || 'top' === $trigger_text_position ) {
193
+ $menu_trigger_content .= $menu_trigger_text;
194
+
195
+ }
196
+
197
+ $menu_trigger_content .= $menu_trigger_type;
198
+
199
+ if ( 'bottom' === $trigger_text_position || 'right' === $trigger_text_position ) {
200
+ $menu_trigger_content .= $menu_trigger_text;
201
+ }
202
+
203
+
204
+ $trigger_click_animation = '';
205
+ if ( ! empty( $this->options['button_click_animation'] ) ) {
206
+ $trigger_click_animation = $this->options['button_click_animation'];
207
+ }
208
+
209
+ $rmp_menu_trigger = sprintf(
210
+ '<button type="button" aria-controls="rmp-container-%s" aria-label="Menu Trigger" id="rmp_menu_trigger-%s" class="rmp_menu_trigger rmp-menu-trigger-%s">
211
+ %s
212
+ </button>',
213
+ $this->menu_id,
214
+ $this->menu_id,
215
+ $trigger_click_animation,
216
+ $menu_trigger_content
217
+ );
218
+
219
+ return $rmp_menu_trigger;
220
+ }
221
+
222
+ /**
223
+ * Returns menu title.
224
+ *
225
+ * @return HTML|string
226
+ */
227
+ public function menu_title() {
228
+
229
+ $menu_title_wrap = null;
230
+ $menu_title = '';
231
+ if ( ! empty( $this->options['menu_title'] ) ) {
232
+ $menu_title = $this->options['menu_title'];
233
+ }
234
+
235
+ $menu_image = '';
236
+ if ( ! empty( $this->options['menu_title_image'] ) ) {
237
+ $image_alt = rmp_image_alt_by_url( $this->options['menu_title_image'] );
238
+ $menu_image = sprintf('<img class="rmp-menu-title-image" src="%1$s" alt="%2$s" title="%2$s" width="100" height="100"/>',
239
+ esc_url( $this->options['menu_title_image'] ),
240
+ esc_attr( $image_alt )
241
+ );
242
+ }
243
+
244
+ if( ! empty( $this->options['menu_title_font_icon'] ) ) {
245
+ $menu_image = sprintf( "%s", $this->options['menu_title_font_icon'] );
246
+ }
247
+
248
+ $link_target = '_self';
249
+ if ( ! empty( $this->options['menu_title_link_location'] ) ) {
250
+ $link_target = $this->options['menu_title_link_location'];
251
+ }
252
+
253
+ $link_href = '';
254
+ if ( ! empty( $this->options['menu_title_link'] ) ) {
255
+ $link_href = sprintf('href="%s"',
256
+ esc_url( $this->options['menu_title_link'] )
257
+ );
258
+ }
259
+
260
+ $menu_title_wrap = sprintf('
261
+ <div id="rmp-menu-title-%s" class="rmp-menu-title">
262
+ <a %s target="%s" id="rmp-menu-title-link">
263
+ %s
264
+ <span>%s</span>
265
+ </a>
266
+ </div>',
267
+ esc_attr( $this->menu_id),
268
+ $link_href,
269
+ esc_attr( $link_target ),
270
+ $menu_image,
271
+ esc_html( $menu_title )
272
+ );
273
+
274
+ return $menu_title_wrap;
275
+ }
276
+
277
+ /**
278
+ * Return menu search box.
279
+ *
280
+ * @return HTML|string
281
+ */
282
+ public function menu_search_box() {
283
+
284
+ $menu_search_wrap = sprintf('
285
+ <div id="rmp-search-box-%s" class="rmp-search-box">
286
+ <form action="%s" class="rmp-search-form" role="search">
287
+ <input type="search" name="s" title="Search" placeholder="%s" class="rmp-search-box">
288
+ </form>
289
+ </div>',
290
+ esc_attr( $this->menu_id),
291
+ esc_url( home_url( '/' ) ),
292
+ __( 'Search', 'responsive-menu-pro' )
293
+ );
294
+
295
+ return $menu_search_wrap;
296
+ }
297
+
298
+ public function menu_additional_content() {
299
+
300
+ $content = '';
301
+
302
+ if ( ! empty( $this->options['menu_additional_content'] ) ) {
303
+ $content = $this->options['menu_additional_content'];
304
+ }
305
+
306
+ $menu_content_wrap = sprintf(
307
+ '<div id="rmp-menu-additional-content-%s" class="rmp-menu-additional-content">
308
+ %s
309
+ </div>',
310
+ esc_attr( $this->menu_id),
311
+ $content
312
+ );
313
+
314
+ return $menu_content_wrap;
315
+ }
316
+
317
+ public function rmp_nav_menu_args( $args = null ) {
318
+
319
+ $menu = $this->get_wp_menu_to_use();
320
+
321
+ // Check menu exist or not.
322
+ $is_exist = false;
323
+ foreach( get_terms('nav_menu') as $nav_menu ) {
324
+ if ( $nav_menu->slug === $menu ) {
325
+ $is_exist = true;
326
+ break;
327
+ }
328
+ }
329
+
330
+ if ( ! $is_exist ) {
331
+ return $args;
332
+ }
333
+
334
+ $menu_location = $this->get_wp_menu_location();
335
+ $menu_depth = $this->options['menu_depth'];
336
+ $wp_menu_obj = wp_get_nav_menu_object( $menu );
337
+
338
+ if ( empty( $menu_depth ) ) {
339
+ $menu_depth = 0;
340
+ }
341
+
342
+ $menu_label = ! empty( $this->options['menu_name'] ) ? $this->options['menu_name'] : 'Default';
343
+
344
+ if ( empty( $menu_label ) ) {
345
+ $menu_label = $menu;
346
+ }
347
+
348
+ $item_wrap_attrs = array(
349
+ "id" => '%1$s',
350
+ "class" => '%2$s',
351
+ "role" => "menubar",
352
+ "aria-label" => $menu_label,
353
+ );
354
+
355
+ $wrap_attributes = apply_filters( "rmp_wrap_attributes", $item_wrap_attrs , $this->menu_id, $menu_location );
356
+
357
+ $attributes = "";
358
+ foreach ( $wrap_attributes as $attribute => $value ) {
359
+ if ( ! empty( $value ) ) {
360
+ $attributes .= sprintf(' %s="%s"', $attribute, esc_attr( $value ) );
361
+ }
362
+ }
363
+
364
+ $walker = new Walker( $this->options );
365
+ if ( ! empty( $this->options['custom_walker'] ) ) {
366
+ $walker = new $this->options['custom_walker']( $this->options );
367
+ }
368
+
369
+ $param = array(
370
+ 'container' => 'div',
371
+ 'container_id' => 'rmp-menu-wrap-' . $this->menu_id,
372
+ 'container_class' => 'rmp-menu-wrap',
373
+ 'menu_id' => 'rmp-menu-'.$this->menu_id,
374
+ 'menu_class' => 'rmp-menu',
375
+ 'menu' => $wp_menu_obj,
376
+ 'depth' => $menu_depth,
377
+ 'fallback_cb' => 'wp_page_menu',
378
+ 'before' => '',
379
+ 'after' => '',
380
+ 'link_before' => '',
381
+ 'link_after' => '',
382
+ 'theme_location' => '',
383
+ 'walker' => $walker,
384
+ 'items_wrap' => '<ul' . $attributes . '>%3$s</ul>',
385
+ );
386
+
387
+ $param = apply_filters( "rmp_nav_menu_args", $param, $wp_menu_obj->term_id , $menu_location );
388
+ return $param;
389
+ }
390
+
391
+
392
+ /**
393
+ * Function to return the correct wp menu name.
394
+ *
395
+ * @version 4.0.0
396
+ *
397
+ * @return string Name of wp menu.
398
+ */
399
+ public function get_wp_menu_to_use() {
400
+
401
+ $menu = '';
402
+
403
+ // Set menu as per settings priority.
404
+ if ( ! empty( $this->options['different_menu_for_mobile'] ) && 'on' === $this->options['different_menu_for_mobile'] && wp_is_mobile() ) {
405
+ $menu = $this->options['menu_to_use_in_mobile'];
406
+ } elseif( ! empty( $this->options['theme_location_menu'] ) && has_nav_menu( $this->options['theme_location_menu'] ) ) {
407
+ $menu = get_term(get_nav_menu_locations()[ $this->options['theme_location_menu'] ], 'nav_menu')->slug;
408
+ } elseif( ! empty($this->options['menu_to_use'] ) ) {
409
+ $menu = $this->options['menu_to_use'];
410
+ } elseif( ! empty( get_terms('nav_menu')[0]->slug ) ) {
411
+ $menu = get_terms('nav_menu')[0]->slug;
412
+ }
413
+
414
+ return $menu;
415
+ }
416
+
417
+ /**
418
+ * Function to get the location of menu.
419
+ *
420
+ * @return string Returns the menu location.
421
+ */
422
+ public function get_wp_menu_location() {
423
+
424
+ $menu = $this->get_wp_menu_to_use();
425
+ if ( empty( $menu ) ) {
426
+ return;
427
+ }
428
+
429
+ $theme_location = null;
430
+ $menu_object = wp_get_nav_menu_object( $menu );
431
+ $theme_locations = get_nav_menu_locations();
432
+ foreach ( $theme_locations as $location => $value ) {
433
+ if ( $value === $menu_object->term_id ) {
434
+ $theme_location = $location;
435
+ break;
436
+ }
437
+ }
438
+ return $theme_location;
439
+ }
440
+
441
+ }
442
+ endif;
v4.0.0/inc/classes/class-rmp-migration.php ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * This is migration class which is responsible for migration.
5
+ *
6
+ * @since 4.0.0
7
+ *
8
+ * @package responsive_menu_pro
9
+ */
10
+
11
+ namespace RMP\Features\Inc;
12
+
13
+ /** Disable the direct access to this class */
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit;
16
+ }
17
+
18
+ if ( ! class_exists( 'RMP_Migration' ) ) :
19
+
20
+ /**
21
+ * Class RMP_Migration handle the migration.
22
+ *
23
+ * @package responsive_menu_pro
24
+ *
25
+ * @author Expresstech System
26
+ */
27
+ class RMP_Migration {
28
+
29
+ /**
30
+ * Instance of this class.
31
+ *
32
+ * @since 4.0.0
33
+ * @access protected
34
+ * @var object $instance Instance of this class.
35
+ */
36
+ protected static $instance;
37
+
38
+ /**
39
+ * Returns new or existing instance.
40
+ *
41
+ * @since 4.0.0
42
+ *
43
+ * @return RMP_Admin instance.
44
+ */
45
+ final public static function get_instance() {
46
+
47
+ if ( ! isset( static::$instance ) ) {
48
+ static::$instance = new RMP_Migration();
49
+ static::$instance->setup();
50
+ }
51
+
52
+ return self::$instance;
53
+ }
54
+
55
+ /**
56
+ * Setup hooks.
57
+ *
58
+ * @since 4.0.0
59
+ */
60
+ protected function setup() {
61
+
62
+ if ( ! empty( get_option('responsive_menu_version') ) ) {
63
+ add_action( 'rmp_after_cpt_registered', array( $this, 'migrate' ) );
64
+ }
65
+
66
+ }
67
+
68
+ /**
69
+ * Function to migrate the options and convert it to new menu.
70
+ */
71
+ public function migrate() {
72
+
73
+ if ( ! empty( get_option( 'rmp_migrate10111') ) ) {
74
+ return;
75
+ }
76
+
77
+ $older_options = $this->get_table_options();
78
+
79
+ //Separate the global options and migrate it into new format.
80
+ $this->migrate_global_settings( $older_options );
81
+
82
+ $converted_options = $this->convert_older_menu_option_to_new_format();
83
+
84
+ $new_menu = array(
85
+ 'post_title' => 'Default Menu',
86
+ 'post_author' => get_current_user_id(),
87
+ 'post_status' => 'publish',
88
+ 'post_type' => 'rmp_menu',
89
+ );
90
+
91
+ $post_id = wp_insert_post( $new_menu );
92
+
93
+ if ( ! empty( $post_id ) ) {
94
+
95
+ $converted_options['menu_name'] = 'Default Menu';
96
+ update_post_meta( $post_id, 'rmp_menu_meta', $converted_options );
97
+
98
+ /**
99
+ * Fires when menu is migrated.
100
+ *
101
+ * @param int $post_id
102
+ */
103
+ do_action( 'rmp_migrate_menu_style', $post_id );
104
+ }
105
+
106
+ update_option( 'rmp_migrate10111', true );
107
+ }
108
+
109
+ /**
110
+ * Convert all required the options to new responsive menu.
111
+ */
112
+ public function convert_older_menu_option_to_new_format() {
113
+
114
+ $older_options = $this->get_table_options();
115
+ $new_options = $older_options;
116
+
117
+ //Menu elements order.
118
+ $new_options['items_order'] = json_decode( $older_options['items_order'], true );
119
+
120
+ //Migrate all font icon options.
121
+ $page_icons = json_decode( $older_options['menu_font_icons'], true );
122
+ $menu_item_icons = [];
123
+
124
+ //Migrate toggle button events.
125
+ $new_options['button_trigger_type_click'] = 'on';
126
+ $new_options['button_trigger_type_hover'] = 'off';
127
+
128
+ if( ! empty( $page_icons['id'] ) ) {
129
+ foreach( $page_icons['id'] as $key => $item_id ) {
130
+ if( empty( $item_id ) ) {
131
+ continue;
132
+ }
133
+ $icon = $page_icons['icon'][$key];
134
+ $type = $page_icons['type'][$key];
135
+ $menu_item_icons['id'][] = $item_id;
136
+ $menu_item_icons['icon'][] = $this->get_icon_element( $type, $icon );
137
+ }
138
+ }
139
+
140
+ $new_options['menu_font_icons'] = $menu_item_icons;
141
+
142
+ if ( ! empty( $new_options['active_arrow_font_icon'] ) ) {
143
+ $new_options['active_arrow_font_icon'] = $this->get_icon_element( $older_options['active_arrow_font_icon_type'], $older_options['active_arrow_font_icon'] );
144
+ }
145
+
146
+ if ( ! empty( $new_options['button_font_icon'] ) ) {
147
+ $new_options['button_font_icon'] = $this->get_icon_element( $older_options['button_font_icon_type'], $older_options['button_font_icon'] );
148
+ }
149
+
150
+ if ( ! empty( $new_options['button_font_icon_when_clicked'] ) ) {
151
+ $new_options['button_font_icon_when_clicked'] = $this->get_icon_element( $older_options['button_font_icon_when_clicked_type'], $older_options['button_font_icon_when_clicked'] );
152
+
153
+ }
154
+
155
+ if ( ! empty( $new_options['inactive_arrow_font_icon'] ) ) {
156
+ $new_options['inactive_arrow_font_icon'] = $this->get_icon_element( $older_options['inactive_arrow_font_icon_type'], $older_options['inactive_arrow_font_icon'] );
157
+ }
158
+
159
+ if ( ! empty( $new_options['menu_title_font_icon'] ) ) {
160
+ $new_options['menu_title_font_icon'] = $this->get_icon_element( $older_options['menu_title_font_icon_type'], $older_options['menu_title_font_icon'] );
161
+ }
162
+
163
+ $default_options = rmp_get_default_options();
164
+ $new_options = array_merge( $default_options, $new_options );
165
+
166
+ //Padding on menu elements.
167
+ $new_options['menu_title_padding'] = [
168
+ 'left' => '5%',
169
+ 'top' => '0px',
170
+ 'right' => '5%',
171
+ 'bottom' => '0px'
172
+ ];
173
+
174
+ $new_options['menu_search_section_padding'] = [
175
+ 'left' => '5%',
176
+ 'top' => '0px',
177
+ 'right' => '5%',
178
+ 'bottom' => '0px'
179
+ ];
180
+
181
+ $new_options['menu_additional_section_padding'] = [
182
+ 'left' => '5%',
183
+ 'top' => '0px',
184
+ 'right' => '5%',
185
+ 'bottom' => '0px'
186
+ ];
187
+
188
+ $new_options['tablet_breakpoint'] = $older_options['breakpoint'];
189
+
190
+ $new_options['menu_sub_arrow_border_width'] = 1;
191
+ if( ! empty( $older_options['menu_border_width'] ) ) {
192
+ $new_options['menu_sub_arrow_border_width'] = $older_options['menu_border_width'];
193
+ }
194
+
195
+ $new_options['menu_sub_arrow_border_width_unit'] = 'px';
196
+ if( ! empty( $older_options['menu_border_width_unit'] ) ) {
197
+ $new_options['menu_sub_arrow_border_width_unit'] = $older_options['menu_border_width_unit'];
198
+ }
199
+
200
+ $new_options['submenu_sub_arrow_border_width'] = 1;
201
+ if( ! empty( $older_options['submenu_border_width'] ) ) {
202
+ $new_options['submenu_sub_arrow_border_width'] = $older_options['submenu_border_width'];
203
+ }
204
+
205
+ $new_options['submenu_sub_arrow_border_width_unit'] = 'px';
206
+ if( ! empty( $older_options['menu_border_width_unit'] ) ) {
207
+ $new_options['submenu_sub_arrow_border_width_unit'] = $older_options['submenu_border_width_unit'];
208
+ }
209
+
210
+ return $new_options;
211
+ }
212
+
213
+ public function get_icon_element( $type, $icon ) {
214
+
215
+ switch($type) {
216
+ case 'glyphicon':
217
+ return '<span class="rmp-font-icon glyphicon glyphicon-' . $icon . '" aria-hidden="true"></span>';
218
+ case 'font-awesome':
219
+ return '<span class="rmp-font-icon fas fa-' . $icon .'"></span>';
220
+ case 'font-awesome-brand':
221
+ return '<span class="rmp-font-icon fab fa-' . $icon .'"></span>';
222
+ default:
223
+ return $icon;
224
+ }
225
+ }
226
+
227
+ /**
228
+ * Function to separate the global setting options.
229
+ *
230
+ * @param array $older_options List of options.
231
+ */
232
+ public function migrate_global_settings( $older_options ) {
233
+
234
+ if ( empty( $older_options ) ) {
235
+ return;
236
+ }
237
+
238
+ $global_options = [];
239
+ $global_options['rmp_custom_css'] = $older_options['custom_css'];
240
+ $global_options['rmp_license_key'] = get_option('responsive_menu_pro_license_key');
241
+ $global_options['rmp_external_files'] = $older_options['external_files'];
242
+ $global_options['rmp_minify_scripts'] = $older_options['minify_scripts'];
243
+ $global_options['rmp_remove_glyphicon'] = $older_options['remove_bootstrap'];
244
+ $global_options['rmp_scripts_in_footer'] = $older_options['scripts_in_footer'];
245
+ $global_options['rmp_remove_fontawesome'] = $older_options['remove_fontawesome'];
246
+ $global_options['menu_adjust_for_wp_admin_bar'] = 'hide';
247
+
248
+ $global_options = array_merge( rmp_global_default_setting_options(), $global_options );
249
+ update_option( 'rmp_global_setting_options', $global_options );
250
+
251
+ }
252
+
253
+ public function get_table_options() {
254
+
255
+ if ( ! $this->is_rmp_table_exist() ) {
256
+ return;
257
+ }
258
+
259
+ global $wpdb;
260
+ $table_name = $wpdb->prefix . 'responsive_menu';
261
+
262
+ $query = sprintf( 'SELECT * FROM %s', $table_name );
263
+ $results = $wpdb->get_results( $query , ARRAY_A);
264
+
265
+ $options = [];
266
+ foreach( $results as $result ) {
267
+ $options[$result['name']] = $result['value'];
268
+ }
269
+
270
+ return $options;
271
+ }
272
+
273
+ /**
274
+ * Function to check the table is exist or not.
275
+ *
276
+ * @access public
277
+ *
278
+ * @return bool
279
+ */
280
+ public function is_rmp_table_exist() {
281
+
282
+ global $wpdb;
283
+ $table_name = $wpdb->prefix . 'responsive_menu';
284
+
285
+ $sql_query = $wpdb->prepare(
286
+ "SHOW TABLES LIKE %s",
287
+ $table_name
288
+ );
289
+
290
+ if ( $wpdb->get_var( $sql_query ) === $table_name ) {
291
+ return true;
292
+ }
293
+
294
+ return false;
295
+ }
296
+
297
+ }
298
+
299
+ RMP_Migration::get_instance();
300
+
301
+ endif;
v4.0.0/inc/classes/class-style-manager.php ADDED
@@ -0,0 +1,1497 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file contain the Style_Manager class and it's functions.
4
+ *
5
+ * @version 4.0.0
6
+ * @author Expresstech System
7
+ *
8
+ * @package responsive-menu-pro
9
+ */
10
+
11
+ namespace RMP\Features\Inc;
12
+ use RMP\Features\Inc\Option_Manager;
13
+ use RMP\Features\Inc\Traits\Singleton;
14
+ use ScssPhp\ScssPhp\Compiler;
15
+
16
+ // Disable the direct access to this class.
17
+ if ( ! defined( 'ABSPATH' ) ) {
18
+ exit;
19
+ }
20
+
21
+ /**
22
+ * Class Style_Manager
23
+ *
24
+ * This class is responsible for handle the styling from frontend.
25
+ *
26
+ * @version 4.0.0
27
+ */
28
+ class Style_Manager {
29
+
30
+ use Singleton;
31
+
32
+ /**
33
+ * Instance of option manager class.
34
+ *
35
+ * @version 4.0.0
36
+ *
37
+ * @var array $option_manager.
38
+ */
39
+ protected $option_manager;
40
+
41
+ /**
42
+ * Construct method.
43
+ */
44
+ protected function __construct() {
45
+ $this->option_manager = Option_Manager::get_instance();
46
+ $this->setup_hooks();
47
+ }
48
+
49
+ /**
50
+ * To setup action/filter.
51
+ *
52
+ * @version 4.0.0
53
+ *
54
+ * @return void
55
+ */
56
+ protected function setup_hooks() {
57
+
58
+ add_action( 'wp_head', array( $this , 'enqueue_styles_as_inline' ) );
59
+ add_action( 'wp_enqueue_scripts', array( $this , 'add_rmp_menu_frontend_scripts' ) );
60
+ add_action( 'rmp_create_new_menu', array( $this , 'save_style_css_on_file' ), 10 , 0 );
61
+ add_action( 'rmp_save_menu', array( $this , 'save_style_css_on_file' ), 10, 0 );
62
+ add_action( 'rmp_update_mega_menu_item', array( $this , 'save_style_css_on_file' ), 10, 0 );
63
+ add_action( 'rmp_save_global_settings', array( $this , 'save_style_css_on_file' ), 10, 0 );
64
+ add_action( 'rmp_theme_apply', array( $this , 'save_style_css_on_file' ), 10, 0 );
65
+ add_action( 'rmp_migrate_menu_style', [ $this , 'save_style_css_on_file' ], 10, 0 );
66
+ add_action( 'rmp_import_menu', [ $this , 'save_style_css_on_file' ], 10, 0 );
67
+
68
+ // Hide adminbar.
69
+ if ( 'hide' == $this->option_manager->get_global_option( 'menu_adjust_for_wp_admin_bar' ) ) {
70
+ add_filter( 'show_admin_bar', '__return_false' );
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Function to call the css generate for all menu one by one.
76
+ *
77
+ * @return string $css
78
+ */
79
+ public function get_menus_scss_to_css() {
80
+
81
+ $menu_ids = get_all_rmp_menu_ids();
82
+
83
+ if ( empty( $menu_ids ) ) {
84
+ return;
85
+ }
86
+
87
+ $css = '';
88
+ foreach ( $menu_ids as $menu_id ) {
89
+ $css .= $this->get_css_for_menu( $menu_id );
90
+ }
91
+
92
+ $css .= $this->get_common_scss_to_css();
93
+
94
+ //Add custom css from setting page.
95
+ $css .= $this->option_manager->get_global_option( 'rmp_custom_css' );
96
+
97
+ //If minify is enable from settings then minify the style css.
98
+ if ( 'on' === $this->option_manager->get_global_option( 'rmp_minify_scripts' ) ) {
99
+ $css = $this->minify( $css );
100
+ }
101
+
102
+ return $css;
103
+ }
104
+
105
+ /**
106
+ * Function to save the css in files.
107
+ */
108
+ public function save_style_css_on_file() {
109
+ global $wp_filesystem;
110
+
111
+ if ( empty( $wp_filesystem ) ) {
112
+ require_once( ABSPATH . 'wp-admin/includes/file.php' );
113
+ }
114
+
115
+ WP_Filesystem();
116
+
117
+ $upload_dir = wp_upload_dir();
118
+
119
+ $dir = trailingslashit( $upload_dir['basedir'] ) . 'rmp-menu/css/';
120
+
121
+ if ( ! $wp_filesystem->is_dir( $dir ) ) {
122
+ wp_mkdir_p( $dir );
123
+ }
124
+
125
+ $css = $this->get_menus_scss_to_css();
126
+
127
+ if ( ! $wp_filesystem->put_contents( $dir . 'rmp-menu.css' , $css, 0644 ) ) {
128
+ return new \WP_Error( "Notice: Unable to write css in file." );
129
+ }
130
+
131
+ }
132
+
133
+ /**
134
+ * Enqueue the stylesheet held on the filesystem.
135
+ */
136
+ public function enqueue_styles_as_file() {
137
+
138
+ $upload_dir = wp_upload_dir();
139
+
140
+ $filename = 'rmp-menu.css';
141
+
142
+ $file_path = trailingslashit( $upload_dir['basedir'] ) . 'rmp-menu/css/' . $filename;
143
+
144
+ // If file is not exist then create it.
145
+ if ( ! file_exists( $file_path ) ) {
146
+ $this->save_style_css_on_file();
147
+ }
148
+
149
+ if ( file_exists( $file_path ) ) {
150
+
151
+ $file_url = trailingslashit( $upload_dir['baseurl'] ) . 'rmp-menu/css/' . $filename;
152
+
153
+ $protocol = is_ssl() ? 'https://' : 'http://';
154
+
155
+ // Ensure we're using the correct protocol.
156
+ $file_url = str_replace( array( "http://", "https://" ), $protocol, $file_url );
157
+
158
+ wp_enqueue_style( 'rmp-menu-styles', $file_url, false, substr( md5( filemtime( $file_path ) ), 0, 6 ) );
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Function to minify the css to reduce the file size.
164
+ *
165
+ * @param string $row_css
166
+ *
167
+ * @return string $minified
168
+ */
169
+ public function minify( $row_css ) {
170
+
171
+ // Remove comments.
172
+ $minified = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $row_css );
173
+
174
+ // Remove tabs, spaces, newlines, etc.
175
+ $minified = str_replace(array("\r\n","\r","\n","\t",' ',' ',' '), '', $minified);
176
+
177
+ // Remove other spaces before/after.
178
+ $minified = preg_replace(array('(( )+{)','({( )+)'), '{', $minified);
179
+ $minified = preg_replace(array('(( )+})','(}( )+)','(;( )*})'), '}', $minified);
180
+ $minified = preg_replace(array('(;( )+)','(( )+;)'), ';', $minified);
181
+
182
+ return $minified;
183
+ }
184
+
185
+ /**
186
+ * Function to combine the options of all the menus.
187
+ *
188
+ * @version 4.0.0
189
+ *
190
+ * @return array $options;
191
+ */
192
+ public function get_all_menu_options() {
193
+ $menu_ids = get_all_rmp_menu_ids();
194
+ $menu_options = [];
195
+
196
+ foreach ( $menu_ids as $menu_id ) {
197
+ $options = $this->option_manager->get_options( $menu_id );
198
+ $options['active_toggle_contents'] = $this->get_active_toggle_contents( $options );
199
+ $options['inactive_toggle_contents'] = $this->get_inactive_toggle_contents( $options );
200
+
201
+ $menu_options[] = $options;
202
+ }
203
+
204
+ return $menu_options;
205
+ }
206
+
207
+ /**
208
+ * Function get the active item toggle icon.
209
+ *
210
+ * @version 4.0.0
211
+ *
212
+ * @param array options
213
+ * @return HTML
214
+ */
215
+ public function get_active_toggle_contents( $options ) {
216
+
217
+ if ( ! empty( $options['active_arrow_font_icon'] ) ) {
218
+ return $options['active_arrow_font_icon'];
219
+ } elseif( ! empty( $options['active_arrow_image'] ) ) {
220
+ return sprintf( '<img alt="%s" src="%s" />',
221
+ rmp_image_alt_by_url( $options['active_arrow_image']),
222
+ esc_url( $options['active_arrow_image'])
223
+ );
224
+ } else {
225
+ return $options['active_arrow_shape'];
226
+ }
227
+ }
228
+
229
+ /**
230
+ * Function get the inactive item toggle icon.
231
+ *
232
+ * @version 4.0.0
233
+ *
234
+ * @param array options
235
+ * @return HTML
236
+ */
237
+ public function get_inactive_toggle_contents( $options ) {
238
+
239
+ if ( ! empty( $options['inactive_arrow_font_icon'] ) ) {
240
+ return $options['inactive_arrow_font_icon'];
241
+ } elseif( ! empty( $options['inactive_arrow_image'] ) ) {
242
+ return sprintf( '<img alt="%s" src="%s" />',
243
+ rmp_image_alt_by_url( $options['inactive_arrow_image']),
244
+ esc_url($options['inactive_arrow_image'])
245
+ );
246
+ } else {
247
+ return $options['inactive_arrow_shape'];
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Add menu scripts for frontend.
253
+ */
254
+ public function add_rmp_menu_frontend_scripts() {
255
+
256
+ $in_footer = false;
257
+ if ( 'on' === $this->option_manager->get_global_option( 'rmp_scripts_in_footer' ) ) {
258
+ $in_footer = true;
259
+ }
260
+
261
+ wp_enqueue_script('jquery');
262
+
263
+ wp_register_script(
264
+ 'rmp_menu_scripts',
265
+ RMP_PLUGIN_URL_V4 . '/assets/js/rmp-menu.js',
266
+ array( 'jquery' ),
267
+ RMP_PLUGIN_VERSION,
268
+ $in_footer
269
+ );
270
+
271
+ wp_localize_script(
272
+ 'rmp_menu_scripts',
273
+ 'rmp_menu',
274
+ array (
275
+ 'ajaxURL' => admin_url( 'admin-ajax.php' ),
276
+ 'wp_nonce' => wp_create_nonce('ajax-nonce'),
277
+ 'menu' => $this->get_all_menu_options(),
278
+ )
279
+ );
280
+
281
+ wp_enqueue_script( 'rmp_menu_scripts' );
282
+
283
+ if ( 'on' != $this->option_manager->get_global_option( 'rmp_remove_dashicons' ) ) {
284
+ wp_enqueue_style( 'dashicons' );
285
+ }
286
+
287
+ if ( 'on' === $this->option_manager->get_global_option( 'rmp_external_files' ) ) {
288
+ $this->enqueue_styles_as_file();
289
+ }
290
+
291
+ }
292
+
293
+ /**
294
+ * This function enqueue inline the menu style css.
295
+ *
296
+ * @version 4.0.0
297
+ */
298
+ public function enqueue_styles_as_inline() {
299
+
300
+ if ( 'on' == $this->option_manager->get_global_option( 'rmp_external_files' ) ) {
301
+ return;
302
+ }
303
+
304
+ $css = $this->get_menus_scss_to_css();
305
+ echo '<style id="rmp-inline-menu-styles">'. $css . '</style>';
306
+ }
307
+
308
+ /**
309
+ * This function convert the scss to css for menu.
310
+ *
311
+ * @param int $menu_id This is menu id for which converting the scss to css.
312
+ *
313
+ * @return string|WP_Error
314
+ */
315
+ public function get_css_for_menu( $menu_id ) {
316
+
317
+ try {
318
+ $options = $this->option_manager->get_options( $menu_id );
319
+
320
+ $is_legacy = 'off';
321
+ if ( ! empty( get_option('responsive_menu_version') ) ) {
322
+ $is_legacy = 'on';
323
+ }
324
+
325
+ $tablet_breakpoint = '';
326
+ if ( ! empty( $options['tablet_breakpoint'] ) ) {
327
+ $tablet_breakpoint = $options['tablet_breakpoint'].'px';
328
+ }
329
+
330
+ $menu_trigger_id = '';
331
+ if ( ! empty( $options['menu_id'] ) ) {
332
+ $menu_trigger_id = '#rmp_menu_trigger-' . $options['menu_id'];
333
+ }
334
+
335
+ $button_position_type = '';
336
+ if ( ! empty( $options['button_position_type'] ) ) {
337
+ $button_position_type = $options['button_position_type'];
338
+ }
339
+
340
+ $menu_trigger_side = '';
341
+ if ( ! empty( $options['button_left_or_right'] ) ) {
342
+ $menu_trigger_side = $options['button_left_or_right'];
343
+ }
344
+
345
+ $button_distance_from_side = '0';
346
+ if ( ! empty( $options['button_distance_from_side'] ) ) {
347
+ $button_distance_from_side = $options['button_distance_from_side'] . $options['button_distance_from_side_unit'];
348
+ }
349
+
350
+ $menu_trigger_distance_from_top = '0';
351
+ if ( ! empty( $options['button_top'] ) ) {
352
+ $menu_trigger_distance_from_top = $options['button_top'] . $options['button_top_unit'];
353
+ }
354
+
355
+ $menu_trigger_width = '';
356
+ if ( ! empty( $options['button_width'] ) ) {
357
+ $menu_trigger_width = $options['button_width'] . $options['button_width_unit'];
358
+ }
359
+
360
+ $menu_trigger_height = '';
361
+ if ( ! empty( $options['button_height'] ) ) {
362
+ $menu_trigger_height = $options['button_height'] . $options['button_height_unit'];
363
+ }
364
+
365
+ $menu_trigger_background_color = '';
366
+ if ( ! empty( $options['button_background_colour'] ) ) {
367
+ $menu_trigger_background_color = $options['button_background_colour'];
368
+ }
369
+
370
+ $menu_trigger_background_color_hover = '';
371
+ if ( ! empty( $options['button_background_colour_hover'] ) ) {
372
+ $menu_trigger_background_color_hover = $options['button_background_colour_hover'];
373
+ }
374
+
375
+ $menu_trigger_active_color = '';
376
+ if ( ! empty( $options['button_background_colour_active'] ) ) {
377
+ $menu_trigger_active_color = $options['button_background_colour_active'];
378
+ }
379
+
380
+ $menu_trigger_transparent_background = '';
381
+ if ( ! empty( $options['button_transparent_background'] ) ) {
382
+ $menu_trigger_transparent_background = $options['button_transparent_background'];
383
+ }
384
+
385
+ $menu_trigger_line_color = '';
386
+ if ( ! empty( $options['button_line_colour'] ) ) {
387
+ $menu_trigger_line_color = $options['button_line_colour'];
388
+ }
389
+
390
+ $menu_trigger_line_color_hover = '';
391
+ if ( ! empty( $options['button_line_colour_hover'] ) ) {
392
+ $menu_trigger_line_color_hover = $options['button_line_colour_hover'];
393
+ }
394
+
395
+ $menu_trigger_line_active_color = '';
396
+ if ( ! empty( $options['button_line_colour_active'] ) ) {
397
+ $menu_trigger_line_active_color = $options['button_line_colour_active'];
398
+ }
399
+
400
+ $menu_trigger_title_color = '';
401
+ if ( ! empty( $options['button_text_colour'] ) ) {
402
+ $menu_trigger_title_color = $options['button_text_colour'];
403
+ }
404
+
405
+ $menu_trigger_title_line_height = '';
406
+ if ( ! empty( $options['button_title_line_height'] ) ) {
407
+ $menu_trigger_title_line_height = $options['button_title_line_height'] . $options['button_title_line_height_unit'];
408
+ }
409
+
410
+ $menu_trigger_title_font_size = '';
411
+ if ( ! empty( $options['button_font_size'] ) ) {
412
+ $menu_trigger_title_font_size = $options['button_font_size'] . $options['button_font_size_unit'];
413
+ }
414
+
415
+ $menu_trigger_title_font = '';
416
+ if ( ! empty( $options['button_font'] ) ) {
417
+ $menu_trigger_title_font = $options['button_font'];
418
+ }
419
+
420
+ $menu_trigger_line_height = '';
421
+ if ( ! empty( $options['button_line_height'] ) ) {
422
+ $menu_trigger_line_height = $options['button_line_height'];
423
+ }
424
+
425
+ $menu_trigger_line_height_unit = '';
426
+ if ( ! empty( $options['button_line_height_unit'] ) ) {
427
+ $menu_trigger_line_height_unit = $options['button_line_height_unit'];
428
+ }
429
+
430
+ $menu_trigger_line_width = '';
431
+ if ( ! empty( $options['button_line_width'] ) ) {
432
+ $menu_trigger_line_width = $options['button_line_width'];
433
+ }
434
+
435
+ $menu_trigger_line_width_unit = '';
436
+ if ( ! empty( $options['button_line_width_unit'] ) ) {
437
+ $menu_trigger_line_width_unit = $options['button_line_width_unit'];
438
+ }
439
+
440
+ $menu_trigger_line_margin = '';
441
+ if ( ! empty( $options['button_line_margin'] ) ) {
442
+ $menu_trigger_line_margin = $options['button_line_margin'];
443
+ }
444
+
445
+ $menu_trigger_line_margin_unit = '';
446
+ if ( ! empty( $options['button_line_margin_unit'] ) ) {
447
+ $menu_trigger_line_margin_unit = $options['button_line_margin_unit'];
448
+ }
449
+
450
+ $menu_search_box_wrap = '';
451
+ if ( ! empty( $options['menu_id'] ) ) {
452
+ $menu_search_box_wrap = '#rmp-search-box-' . $options['menu_id'];
453
+ }
454
+
455
+ $menu_search_section_padding_left = '';
456
+ if ( ! empty( $options['menu_search_section_padding']['left'] ) ) {
457
+ $menu_search_section_padding_left = $options['menu_search_section_padding']['left'];
458
+ }
459
+
460
+ $menu_search_section_padding_top = '';
461
+ if ( ! empty( $options['menu_search_section_padding']['top'] ) ) {
462
+ $menu_search_section_padding_top = $options['menu_search_section_padding']['top'];
463
+ }
464
+
465
+ $menu_search_section_padding_right = '';
466
+ if ( ! empty( $options['menu_search_section_padding']['right'] ) ) {
467
+ $menu_search_section_padding_right = $options['menu_search_section_padding']['right'];
468
+ }
469
+
470
+ $menu_search_section_padding_bottom = '';
471
+ if ( ! empty( $options['menu_search_section_padding']['bottom'] ) ) {
472
+ $menu_search_section_padding_bottom = $options['menu_search_section_padding']['bottom'];
473
+ }
474
+
475
+ $menu_search_box_text_color = '';
476
+ if ( ! empty( $options['menu_search_box_text_colour'] ) ) {
477
+ $menu_search_box_text_color = $options['menu_search_box_text_colour'];
478
+ }
479
+
480
+ $menu_search_box_background_color = '';
481
+ if ( ! empty( $options['menu_search_box_background_colour'] ) ) {
482
+ $menu_search_box_background_color = $options['menu_search_box_background_colour'];
483
+ }
484
+
485
+ $menu_search_box_border_color = '';
486
+ if ( ! empty( $options['menu_search_box_border_colour'] ) ) {
487
+ $menu_search_box_border_color = $options['menu_search_box_border_colour'];
488
+ }
489
+
490
+ $menu_search_box_placeholder_color = '';
491
+ if ( ! empty( $options['menu_search_box_placeholder_colour'] ) ) {
492
+ $menu_search_box_placeholder_color = $options['menu_search_box_placeholder_colour'];
493
+ }
494
+
495
+ $menu_search_box_border_radius = '0';
496
+ if ( ! empty( $options['menu_search_box_border_radius'] ) ) {
497
+ $menu_search_box_border_radius = $options['menu_search_box_border_radius'] . 'px';
498
+ }
499
+
500
+ $menu_search_box_height = '';
501
+ if ( ! empty( $options['menu_search_box_height'] ) ) {
502
+ $menu_search_box_height = $options['menu_search_box_height'];
503
+ }
504
+
505
+ $menu_search_box_height_unit = '';
506
+ if ( ! empty( $options['menu_search_box_height_unit'] ) ) {
507
+ $menu_search_box_height_unit = $options['menu_search_box_height_unit'];
508
+ }
509
+
510
+ $menu_additional_content_wrap = '';
511
+ if ( ! empty( $options['menu_id'] ) ) {
512
+ $menu_additional_content_wrap = '#rmp-menu-additional-content-' . $options['menu_id'];
513
+ }
514
+
515
+ $menu_additional_section_padding_left = '';
516
+ if ( ! empty( $options['menu_additional_section_padding']['left'] ) ) {
517
+ $menu_additional_section_padding_left = $options['menu_additional_section_padding']['left'];
518
+ }
519
+
520
+ $menu_additional_section_padding_top = '';
521
+ if ( ! empty( $options['menu_additional_section_padding']['top'] ) ) {
522
+ $menu_additional_section_padding_top = $options['menu_additional_section_padding']['top'];
523
+ }
524
+
525
+ $menu_additional_section_padding_right = '';
526
+ if ( ! empty( $options['menu_additional_section_padding']['right'] ) ) {
527
+ $menu_additional_section_padding_right = $options['menu_additional_section_padding']['right'];
528
+ }
529
+
530
+ $menu_additional_section_padding_bottom = '';
531
+ if ( ! empty( $options['menu_additional_section_padding']['bottom'] ) ) {
532
+ $menu_additional_section_padding_bottom = $options['menu_additional_section_padding']['bottom'];
533
+ }
534
+
535
+ $menu_additional_content_color = '';
536
+ if ( ! empty( $options['menu_additional_content_colour'] ) ) {
537
+ $menu_additional_content_color = $options['menu_additional_content_colour'];
538
+ }
539
+
540
+ $menu_additional_content_alignment = '';
541
+ if ( ! empty( $options['menu_additional_content_alignment'] ) ) {
542
+ $menu_additional_content_alignment = $options['menu_additional_content_alignment'];
543
+ }
544
+
545
+ $menu_additional_content_font_size = '';
546
+ if ( ! empty( $options['menu_additional_content_font_size'] ) ) {
547
+ $menu_additional_content_font_size = $options['menu_additional_content_font_size'];
548
+ }
549
+
550
+ $menu_additional_content_font_size_unit = '';
551
+ if ( ! empty( $options['menu_additional_content_font_size_unit'] ) ) {
552
+ $menu_additional_content_font_size_unit = $options['menu_additional_content_font_size_unit'];
553
+ }
554
+
555
+ $menu_title_wrap = '';
556
+ if ( ! empty( $options['menu_id'] ) ) {
557
+ $menu_title_wrap = '#rmp-menu-title-' . $options['menu_id'];
558
+ }
559
+
560
+ $menu_title_section_padding_left = '';
561
+ if ( ! empty( $options['menu_title_section_padding']['left'] ) ) {
562
+ $menu_title_section_padding_left = $options['menu_title_section_padding']['left'];
563
+ }
564
+
565
+ $menu_title_section_padding_top = '';
566
+ if ( ! empty( $options['menu_title_section_padding']['top'] ) ) {
567
+ $menu_title_section_padding_top = $options['menu_title_section_padding']['top'];
568
+ }
569
+
570
+ $menu_title_section_padding_right = '';
571
+ if ( ! empty( $options['menu_title_section_padding']['right'] ) ) {
572
+ $menu_title_section_padding_right = $options['menu_title_section_padding']['right'];
573
+ }
574
+
575
+ $menu_title_section_padding_bottom = '';
576
+ if ( ! empty( $options['menu_title_section_padding']['bottom'] ) ) {
577
+ $menu_title_section_padding_bottom = $options['menu_title_section_padding']['bottom'];
578
+ }
579
+
580
+
581
+ $menu_title_background = '';
582
+ if ( ! empty( $options['menu_title_background_colour'] ) ) {
583
+ $menu_title_background = $options['menu_title_background_colour'];
584
+ }
585
+
586
+ $menu_title_background_hover = '';
587
+ if ( ! empty( $options['menu_title_background_hover_colour'] ) ) {
588
+ $menu_title_background_hover = $options['menu_title_background_hover_colour'];
589
+ }
590
+
591
+ $menu_title_font_color = '';
592
+ if ( ! empty( $options['menu_title_colour'] ) ) {
593
+ $menu_title_font_color = $options['menu_title_colour'];
594
+ }
595
+
596
+ $menu_title_font_color_hover = '';
597
+ if ( ! empty( $options['menu_title_hover_colour'] ) ) {
598
+ $menu_title_font_color_hover = $options['menu_title_hover_colour'];
599
+ }
600
+
601
+ $menu_title_text_alignment = '';
602
+ if ( ! empty( $options['menu_title_alignment'] ) ) {
603
+ $menu_title_text_alignment = $options['menu_title_alignment'];
604
+ }
605
+
606
+ $menu_title_font_size = '';
607
+ if ( ! empty( $options['menu_title_font_size'] ) ) {
608
+ $menu_title_font_size = $options['menu_title_font_size'] . 'px';
609
+ }
610
+
611
+ $menu_title_image_width = '';
612
+ if ( ! empty( $options['menu_title_image_width'] ) ) {
613
+ $menu_title_image_width = $options['menu_title_image_width'] . $options['menu_title_image_width_unit'];
614
+ }
615
+
616
+ $menu_title_image_height = '';
617
+ if ( ! empty( $options['menu_title_image_height'] ) ) {
618
+ $menu_title_image_height = $options['menu_title_image_height'] . $options['menu_title_image_height_unit'];
619
+ }
620
+
621
+ $menu_container = '';
622
+ if ( ! empty( $options['menu_id'] ) ) {
623
+ $menu_container = '#rmp-container-' . $options['menu_id'];
624
+ }
625
+
626
+ $menu_container_padding_left = '';
627
+ if ( ! empty( $options['menu_container_padding']['left'] ) ) {
628
+ $menu_container_padding_left = $options['menu_container_padding']['left'];
629
+ }
630
+
631
+ $menu_container_padding_top = '';
632
+ if ( ! empty( $options['menu_container_padding']['top'] ) ) {
633
+ $menu_container_padding_top = $options['menu_container_padding']['top'];
634
+ }
635
+
636
+ $menu_container_padding_right = '';
637
+ if ( ! empty( $options['menu_container_padding']['right'] ) ) {
638
+ $menu_container_padding_right = $options['menu_container_padding']['right'];
639
+ }
640
+
641
+ $menu_container_padding_bottom = '';
642
+ if ( ! empty( $options['menu_container_padding']['bottom'] ) ) {
643
+ $menu_container_padding_bottom = $options['menu_container_padding']['bottom'];
644
+ }
645
+
646
+ $menu_width = '';
647
+ if ( ! empty( $options['menu_width'] ) ) {
648
+ $menu_width = $options['menu_width'];
649
+ }
650
+
651
+ $menu_width_unit = '';
652
+ if ( ! empty( $options['menu_width_unit'] ) ) {
653
+ $menu_width_unit = $options['menu_width_unit'];
654
+ }
655
+
656
+ $menu_maximum_width = '';
657
+ if ( ! empty( $options['menu_maximum_width'] ) ) {
658
+ $menu_maximum_width = $options['menu_maximum_width'];
659
+ }
660
+
661
+ $menu_maximum_width_unit = '';
662
+ if ( ! empty( $options['menu_maximum_width_unit'] ) ) {
663
+ $menu_maximum_width_unit = $options['menu_maximum_width_unit'];
664
+ }
665
+
666
+ $menu_minimum_width = '';
667
+ if ( ! empty( $options['menu_minimum_width'] ) ) {
668
+ $menu_minimum_width = $options['menu_minimum_width'];
669
+ }
670
+
671
+ $menu_minimum_width_unit = '';
672
+ if ( ! empty( $options['menu_minimum_width_unit'] ) ) {
673
+ $menu_minimum_width_unit = $options['menu_minimum_width_unit'];
674
+ }
675
+
676
+ $menu_container_background_colour = '';
677
+ if ( ! empty( $options['menu_container_background_colour'] ) ) {
678
+ $menu_container_background_colour = $options['menu_container_background_colour'];
679
+ }
680
+
681
+
682
+ $menu_container_background_image = '';
683
+ if ( ! empty( $options['menu_background_image'] ) ) {
684
+ $menu_container_background_image = $options['menu_background_image'];
685
+ }
686
+
687
+
688
+ $menu_container_appear_from = '';
689
+ if ( ! empty( $options['menu_appear_from'] ) ) {
690
+ $menu_container_appear_from = $options['menu_appear_from'];
691
+ }
692
+
693
+ $page_wrapper = '';
694
+ if ( ! empty( $options['page_wrapper'] ) ) {
695
+ $page_wrapper = $options['page_wrapper'];
696
+ }
697
+
698
+
699
+ $menu_wrap = '';
700
+ if ( ! empty( $options['menu_id'] ) ) {
701
+ $menu_wrap = '#rmp-menu-wrap-' .$options['menu_id'];
702
+ }
703
+
704
+ $menu_section_padding_left = '';
705
+ if ( ! empty( $options['menu_section_padding']['left'] ) ) {
706
+ $menu_section_padding_left = $options['menu_section_padding']['left'];
707
+ }
708
+
709
+ $menu_section_padding_top = '';
710
+ if ( ! empty( $options['menu_section_padding']['top'] ) ) {
711
+ $menu_section_padding_top = $options['menu_section_padding']['top'];
712
+ }
713
+
714
+ $menu_section_padding_right = '';
715
+ if ( ! empty( $options['menu_section_padding']['right'] ) ) {
716
+ $menu_section_padding_right = $options['menu_section_padding']['right'];
717
+ }
718
+
719
+ $menu_section_padding_bottom = '';
720
+ if ( ! empty( $options['menu_section_padding']['bottom'] ) ) {
721
+ $menu_section_padding_bottom = $options['menu_section_padding']['bottom'];
722
+ }
723
+
724
+ $menu_background_color = '';
725
+ if ( ! empty( $options['menu_background_colour'] ) ) {
726
+ $menu_background_color = $options['menu_background_colour'];
727
+ }
728
+
729
+ $menu_item_height = '';
730
+ if ( ! empty( $options['menu_links_height'] ) ) {
731
+ $menu_item_height = $options['menu_links_height'];
732
+ }
733
+
734
+ $menu_item_height_unit = '';
735
+ if ( ! empty( $options['menu_links_height_unit'] ) ) {
736
+ $menu_item_height_unit = $options['menu_links_height_unit'];
737
+ }
738
+
739
+ $menu_item_line_height = '';
740
+ if ( ! empty( $options['menu_links_line_height'] ) ) {
741
+ $menu_item_line_height = $options['menu_links_line_height'];
742
+ }
743
+
744
+ $menu_item_line_height_unit = '';
745
+ if ( ! empty( $options['menu_links_line_height_unit'] ) ) {
746
+ $menu_item_line_height_unit = $options['menu_links_line_height_unit'];
747
+ }
748
+
749
+
750
+ $menu_item_font_weight = 'intial';
751
+ if ( ! empty( $options['menu_font_weight'] ) ) {
752
+ $menu_item_font_weight = $options['menu_font_weight'];
753
+ }
754
+
755
+
756
+ $menu_item_letter_spacing = '0';
757
+ if ( ! empty( $options['menu_text_letter_spacing'] ) ) {
758
+ $menu_item_letter_spacing = $options['menu_text_letter_spacing'];
759
+ }
760
+
761
+ $menu_item_border_width = '0';
762
+ if ( ! empty( $options['menu_border_width'] ) ) {
763
+ $menu_item_border_width = $options['menu_border_width'];
764
+ }
765
+
766
+ $menu_item_border_width_unit = '';
767
+ if ( ! empty( $options['menu_border_width_unit'] ) ) {
768
+ $menu_item_border_width_unit = $options['menu_border_width_unit'];
769
+ }
770
+
771
+ $menu_item_border_color = '';
772
+ if ( ! empty( $options['menu_item_border_colour'] ) ) {
773
+ $menu_item_border_color = $options['menu_item_border_colour'];
774
+ }
775
+
776
+ $menu_item_border_color_hover = '';
777
+ if ( ! empty( $options['menu_item_border_colour_hover'] ) ) {
778
+ $menu_item_border_color_hover = $options['menu_item_border_colour_hover'];
779
+ }
780
+
781
+ $menu_current_item_border_color = '';
782
+ if ( ! empty( $options['menu_current_item_border_colour'] ) ) {
783
+ $menu_current_item_border_color = $options['menu_current_item_border_colour'];
784
+ }
785
+
786
+ $menu_current_item_border_color_hover = '';
787
+ if ( ! empty( $options['menu_current_item_border_hover_colour'] ) ) {
788
+ $menu_current_item_border_color_hover = $options['menu_current_item_border_hover_colour'];
789
+ }
790
+
791
+ $menu_item_font_size = '';
792
+ if ( ! empty( $options['menu_font_size'] ) ) {
793
+ $menu_item_font_size = $options['menu_font_size'];
794
+ }
795
+
796
+ $menu_item_font_size_unit = '';
797
+ if ( ! empty( $options['menu_font_size_unit'] ) ) {
798
+ $menu_item_font_size_unit = $options['menu_font_size_unit'];
799
+ }
800
+
801
+ $menu_item_font_family = '';
802
+ if ( ! empty( $options['menu_font'] ) ) {
803
+ $menu_item_font_family = $options['menu_font'];
804
+ }
805
+
806
+ $menu_item_text_alignment = '';
807
+ if ( ! empty( $options['menu_text_alignment'] ) ) {
808
+ $menu_item_text_alignment = $options['menu_text_alignment'];
809
+ }
810
+
811
+ $menu_item_text_color = '';
812
+ if ( ! empty( $options['menu_link_colour'] ) ) {
813
+ $menu_item_text_color = $options['menu_link_colour'];
814
+ }
815
+
816
+ $menu_item_text_color_hover = '';
817
+ if ( ! empty( $options['menu_link_hover_colour'] ) ) {
818
+ $menu_item_text_color_hover = $options['menu_link_hover_colour'];
819
+ }
820
+
821
+ $menu_current_item_text_color = '';
822
+ if ( ! empty( $options['menu_current_link_colour'] ) ) {
823
+ $menu_current_item_text_color = $options['menu_current_link_colour'];
824
+ }
825
+
826
+ $menu_current_item_text_color_hover = '';
827
+ if ( ! empty( $options['menu_current_link_hover_colour'] ) ) {
828
+ $menu_current_item_text_color_hover = $options['menu_current_link_hover_colour'];
829
+ }
830
+
831
+ $menu_item_background_color = '';
832
+ if ( ! empty( $options['menu_item_background_colour'] ) ) {
833
+ $menu_item_background_color = $options['menu_item_background_colour'];
834
+ }
835
+
836
+
837
+ $menu_item_background_color_hover = '';
838
+ if ( ! empty( $options['menu_item_background_hover_colour'] ) ) {
839
+ $menu_item_background_color_hover = $options['menu_item_background_hover_colour'];
840
+ }
841
+
842
+ $menu_current_item_background_color = '';
843
+ if ( ! empty( $options['menu_current_item_background_colour'] ) ) {
844
+ $menu_current_item_background_color = $options['menu_current_item_background_colour'];
845
+ }
846
+
847
+ $menu_current_item_background_color_hover = '';
848
+ if ( ! empty( $options['menu_current_item_background_hover_colour'] ) ) {
849
+ $menu_current_item_background_color_hover = $options['menu_current_item_background_hover_colour'];
850
+ }
851
+
852
+ $menu_item_padding = '';
853
+ if ( ! empty( $options['menu_depth_0'] ) ) {
854
+ $menu_item_padding = $options['menu_depth_0'];
855
+ }
856
+
857
+ $menu_item_padding_unit = '';
858
+ if ( ! empty( $options['menu_depth_0_unit'] ) ) {
859
+ $menu_item_padding_unit = $options['menu_depth_0_unit'];
860
+ }
861
+
862
+
863
+
864
+ $menu_depth_side = '';
865
+ if ( ! empty( $options['menu_depth_side'] ) ) {
866
+ $menu_depth_side = $options['menu_depth_side'];
867
+ }
868
+
869
+ $menu_item_padding_depth_1 = '';
870
+ if ( ! empty( $options['menu_depth_1'] ) ) {
871
+ $menu_item_padding_depth_1 = $options['menu_depth_1'];
872
+ }
873
+
874
+ $menu_item_padding_depth_1_unit = '';
875
+ if ( ! empty( $options['menu_depth_1_unit'] ) ) {
876
+ $menu_item_padding_depth_1_unit = $options['menu_depth_1_unit'];
877
+ }
878
+
879
+ $menu_item_padding_depth_2 = '';
880
+ if ( ! empty( $options['menu_depth_2'] ) ) {
881
+ $menu_item_padding_depth_2 = $options['menu_depth_2'];
882
+ }
883
+
884
+ $menu_item_padding_depth_2_unit = '';
885
+ if ( ! empty( $options['menu_depth_2_unit'] ) ) {
886
+ $menu_item_padding_depth_2_unit = $options['menu_depth_2_unit'];
887
+ }
888
+
889
+ $menu_item_padding_depth_3 = '';
890
+ if ( ! empty( $options['menu_depth_3'] ) ) {
891
+ $menu_item_padding_depth_3 = $options['menu_depth_3'];
892
+ }
893
+
894
+ $menu_item_padding_depth_3_unit = '';
895
+ if ( ! empty( $options['menu_depth_3_unit'] ) ) {
896
+ $menu_item_padding_depth_3_unit = $options['menu_depth_3_unit'];
897
+ }
898
+
899
+ $menu_item_padding_depth_4 = '';
900
+ if ( ! empty( $options['menu_depth_4'] ) ) {
901
+ $menu_item_padding_depth_4 = $options['menu_depth_4'];
902
+ }
903
+
904
+ $menu_item_padding_depth_4_unit = '';
905
+ if ( ! empty( $options['menu_depth_4_unit'] ) ) {
906
+ $menu_item_padding_depth_4_unit = $options['menu_depth_4_unit'];
907
+ }
908
+
909
+ $menu_word_wrap = '';
910
+ if ( ! empty( $options['menu_word_wrap'] ) ) {
911
+ $menu_word_wrap = $options['menu_word_wrap'];
912
+ }
913
+
914
+ $menu_item_toggle_position = '';
915
+ if ( ! empty( $options['arrow_position'] ) ) {
916
+ $menu_item_toggle_position = $options['arrow_position'];
917
+ }
918
+
919
+ $menu_item_toggle_height = '';
920
+ if ( ! empty( $options['submenu_arrow_height'] ) ) {
921
+ $menu_item_toggle_height = $options['submenu_arrow_height'];
922
+ }
923
+
924
+ $menu_item_toggle_height_unit = '';
925
+ if ( ! empty( $options['submenu_arrow_height_unit'] ) ) {
926
+ $menu_item_toggle_height_unit = $options['submenu_arrow_height_unit'];
927
+ }
928
+
929
+ $menu_item_toggle_width = '';
930
+ if ( ! empty( $options['submenu_arrow_width'] ) ) {
931
+ $menu_item_toggle_width = $options['submenu_arrow_width'];
932
+ }
933
+
934
+ $menu_item_toggle_width_unit = '';
935
+ if ( ! empty( $options['submenu_arrow_width_unit'] ) ) {
936
+ $menu_item_toggle_width_unit = $options['submenu_arrow_width_unit'];
937
+ }
938
+
939
+ $menu_item_toggle_text_color = '';
940
+ if ( ! empty( $options['menu_sub_arrow_shape_colour'] ) ) {
941
+ $menu_item_toggle_text_color = $options['menu_sub_arrow_shape_colour'];
942
+ }
943
+
944
+
945
+ $menu_item_toggle_text_color_hover = '';
946
+ if ( ! empty( $options['menu_sub_arrow_shape_hover_colour'] ) ) {
947
+ $menu_item_toggle_text_color_hover = $options['menu_sub_arrow_shape_hover_colour'];
948
+ }
949
+
950
+
951
+ $menu_current_item_toggle_text_color = '';
952
+ if ( ! empty( $options['menu_sub_arrow_shape_colour_active'] ) ) {
953
+ $menu_current_item_toggle_text_color = $options['menu_sub_arrow_shape_colour_active'];
954
+ }
955
+
956
+
957
+ $menu_current_item_toggle_text_color_hover = '';
958
+ if ( ! empty( $options['menu_sub_arrow_shape_hover_colour_active'] ) ) {
959
+ $menu_current_item_toggle_text_color_hover = $options['menu_sub_arrow_shape_hover_colour_active'];
960
+ }
961
+
962
+ $menu_item_toggle_background_color = '';
963
+ if ( ! empty( $options['menu_sub_arrow_background_colour'] ) ) {
964
+ $menu_item_toggle_background_color = $options['menu_sub_arrow_background_colour'];
965
+ }
966
+
967
+ $menu_item_toggle_background_color_hover = '';
968
+ if ( ! empty( $options['menu_sub_arrow_background_hover_colour'] ) ) {
969
+ $menu_item_toggle_background_color_hover = $options['menu_sub_arrow_background_hover_colour'];
970
+ }
971
+
972
+ $menu_current_item_toggle_background_color = '';
973
+ if ( ! empty( $options['menu_sub_arrow_background_colour_active'] ) ) {
974
+ $menu_current_item_toggle_background_color = $options['menu_sub_arrow_background_colour_active'];
975
+ }
976
+
977
+ $menu_current_item_toggle_background_color_hover = '';
978
+ if ( ! empty( $options['menu_sub_arrow_background_hover_colour_active'] ) ) {
979
+ $menu_current_item_toggle_background_color_hover = $options['menu_sub_arrow_background_hover_colour_active'];
980
+ }
981
+
982
+
983
+ $menu_item_toggle_border_color = '';
984
+ if ( ! empty( $options['menu_sub_arrow_border_colour'] ) ) {
985
+ $menu_item_toggle_border_color = $options['menu_sub_arrow_border_colour'];
986
+ }
987
+
988
+ $menu_item_toggle_border_color_hover = '';
989
+ if ( ! empty( $options['menu_sub_arrow_border_hover_colour'] ) ) {
990
+ $menu_item_toggle_border_color_hover = $options['menu_sub_arrow_border_hover_colour'];
991
+ }
992
+
993
+ $menu_current_item_toggle_border_color = '';
994
+ if ( ! empty( $options['menu_sub_arrow_border_colour_active'] ) ) {
995
+ $menu_current_item_toggle_border_color = $options['menu_sub_arrow_border_colour_active'];
996
+ }
997
+
998
+
999
+ $menu_current_item_toggle_border_color_hover = '';
1000
+ if ( ! empty( $options['menu_sub_arrow_border_hover_colour_active'] ) ) {
1001
+ $menu_current_item_toggle_border_color_hover = $options['menu_sub_arrow_border_hover_colour_active'];
1002
+ }
1003
+
1004
+ $submenu_item_height = '';
1005
+ if ( ! empty( $options['submenu_links_height'] ) ) {
1006
+ $submenu_item_height = $options['submenu_links_height'];
1007
+ }
1008
+
1009
+ $submenu_item_height_unit = '';
1010
+ if ( ! empty( $options['submenu_links_height_unit'] ) ) {
1011
+ $submenu_item_height = $options['submenu_links_height_unit'];
1012
+ }
1013
+
1014
+ $submenu_item_line_height = '';
1015
+ if ( ! empty( $options['submenu_links_line_height'] ) ) {
1016
+ $submenu_item_line_height = $options['submenu_links_line_height'];
1017
+ }
1018
+
1019
+ $submenu_item_line_height_unit = '';
1020
+ if ( ! empty( $options['submenu_links_line_height_unit'] ) ) {
1021
+ $submenu_item_line_height_unit = $options['submenu_links_line_height_unit'];
1022
+ }
1023
+
1024
+ $submenu_item_border_width = '0';
1025
+ if ( ! empty( $options['submenu_border_width'] ) ) {
1026
+ $submenu_item_border_width = $options['submenu_border_width'];
1027
+ }
1028
+
1029
+ $submenu_item_border_width_unit = '';
1030
+ if ( ! empty( $options['submenu_border_width_unit'] ) ) {
1031
+ $submenu_item_border_width_unit = $options['submenu_border_width_unit'];
1032
+ }
1033
+
1034
+ $submenu_item_border_color = '';
1035
+ if ( ! empty( $options['submenu_item_border_colour'] ) ) {
1036
+ $submenu_item_border_color = $options['submenu_item_border_colour'];
1037
+ }
1038
+
1039
+ $submenu_item_border_color_hover = '';
1040
+ if ( ! empty( $options['submenu_item_border_colour_hover'] ) ) {
1041
+ $submenu_item_border_color_hover = $options['submenu_item_border_colour_hover'];
1042
+ }
1043
+
1044
+ $submenu_current_item_border_color = '';
1045
+ if ( ! empty( $options['submenu_current_item_border_colour'] ) ) {
1046
+ $submenu_current_item_border_color = $options['submenu_current_item_border_colour'];
1047
+ }
1048
+
1049
+ $submenu_current_item_border_color_hover = '';
1050
+ if ( ! empty( $options['submenu_current_item_border_hover_colour'] ) ) {
1051
+ $submenu_current_item_border_color_hover = $options['submenu_current_item_border_hover_colour'];
1052
+ }
1053
+
1054
+ $submenu_item_font_size = '0';
1055
+ if ( ! empty( $options['submenu_font_size'] ) ) {
1056
+ $submenu_item_font_size = $options['submenu_font_size'];
1057
+ }
1058
+
1059
+ $submenu_item_font_size_unit = '';
1060
+ if ( ! empty( $options['submenu_font_size_unit'] ) ) {
1061
+ $submenu_item_font_size_unit = $options['submenu_font_size_unit'];
1062
+ }
1063
+
1064
+ $submenu_item_font_family = '';
1065
+ if ( ! empty( $options['submenu_font'] ) ) {
1066
+ $submenu_item_font_family = $options['submenu_font'];
1067
+ }
1068
+
1069
+ $submenu_item_text_alignment = '';
1070
+ if ( ! empty( $options['submenu_text_alignment'] ) ) {
1071
+ $submenu_item_text_alignment = $options['submenu_text_alignment'];
1072
+ }
1073
+
1074
+ $submenu_item_text_color = '';
1075
+ if ( ! empty( $options['submenu_link_colour'] ) ) {
1076
+ $submenu_item_text_color = $options['submenu_link_colour'];
1077
+ }
1078
+
1079
+ $submenu_item_text_color_hover = '';
1080
+ if ( ! empty( $options['submenu_link_hover_colour'] ) ) {
1081
+ $submenu_item_text_color_hover = $options['submenu_link_hover_colour'];
1082
+ }
1083
+
1084
+ $submenu_current_item_text_color = '';
1085
+ if ( ! empty( $options['submenu_current_link_colour'] ) ) {
1086
+ $submenu_current_item_text_color = $options['submenu_current_link_colour'];
1087
+ }
1088
+
1089
+ $submenu_current_item_text_color_hover = '';
1090
+ if ( ! empty( $options['submenu_current_link_hover_colour'] ) ) {
1091
+ $submenu_current_item_text_color_hover = $options['submenu_current_link_hover_colour'];
1092
+ }
1093
+
1094
+ $submenu_item_background_color = '';
1095
+ if ( ! empty( $options['submenu_item_background_colour'] ) ) {
1096
+ $submenu_item_background_color = $options['submenu_item_background_colour'];
1097
+ }
1098
+
1099
+ $submenu_item_background_color_hover = '';
1100
+ if ( ! empty( $options['submenu_item_background_hover_colour'] ) ) {
1101
+ $submenu_item_background_color_hover = $options['submenu_item_background_hover_colour'];
1102
+ }
1103
+
1104
+ $submenu_current_item_background_color = '';
1105
+ if ( ! empty( $options['submenu_current_item_background_colour'] ) ) {
1106
+ $submenu_current_item_background_color = $options['submenu_current_item_background_colour'];
1107
+ }
1108
+
1109
+ $submenu_current_item_background_color_hover = '';
1110
+ if ( ! empty( $options['submenu_current_item_background_hover_colour'] ) ) {
1111
+ $submenu_current_item_background_color_hover = $options['submenu_current_item_background_hover_colour'];
1112
+ }
1113
+
1114
+ $submenu_item_toggle_position = '';
1115
+ if ( ! empty( $options['submenu_arrow_position'] ) ) {
1116
+ $submenu_item_toggle_position = $options['submenu_arrow_position'];
1117
+ }
1118
+
1119
+ $submenu_item_toggle_height = '';
1120
+ if ( ! empty( $options['submenu_submenu_arrow_height'] ) ) {
1121
+ $submenu_item_toggle_height = $options['submenu_submenu_arrow_height'];
1122
+ }
1123
+
1124
+ $submenu_item_toggle_height_unit = '';
1125
+ if ( ! empty( $options['submenu_submenu_arrow_height_unit'] ) ) {
1126
+ $submenu_item_toggle_height_unit = $options['submenu_submenu_arrow_height_unit'];
1127
+ }
1128
+
1129
+
1130
+ $submenu_item_toggle_width = '';
1131
+ if ( ! empty( $options['submenu_submenu_arrow_width'] ) ) {
1132
+ $submenu_item_toggle_width = $options['submenu_submenu_arrow_width'];
1133
+ }
1134
+
1135
+ $submenu_item_toggle_width_unit = '';
1136
+ if ( ! empty( $options['submenu_submenu_arrow_width_unit'] ) ) {
1137
+ $submenu_item_toggle_width_unit = $options['submenu_submenu_arrow_width_unit'];
1138
+ }
1139
+
1140
+ $menu_sub_arrow_border_width = '0';
1141
+ if ( ! empty( $options['menu_sub_arrow_border_width'] ) ) {
1142
+ $menu_sub_arrow_border_width = $options['menu_sub_arrow_border_width'];
1143
+ }
1144
+
1145
+ $menu_sub_arrow_border_width_unit = 'px';
1146
+ if ( ! empty( $options['menu_sub_arrow_border_width_unit'] ) ) {
1147
+ $menu_sub_arrow_border_width_unit = $options['menu_sub_arrow_border_width_unit'];
1148
+ }
1149
+
1150
+ $submenu_sub_arrow_border_width = '0';
1151
+ if ( ! empty( $options['submenu_sub_arrow_border_width'] ) ) {
1152
+ $submenu_sub_arrow_border_width = $options['submenu_sub_arrow_border_width'];
1153
+ }
1154
+
1155
+ $submenu_sub_arrow_border_width_unit = 'px';
1156
+ if ( ! empty( $options['submenu_sub_arrow_border_width_unit'] ) ) {
1157
+ $submenu_sub_arrow_border_width_unit = $options['submenu_sub_arrow_border_width_unit'];
1158
+ }
1159
+
1160
+ $submenu_item_toggle_text_color = '';
1161
+ if ( ! empty( $options['submenu_sub_arrow_shape_colour'] ) ) {
1162
+ $submenu_item_toggle_text_color = $options['submenu_sub_arrow_shape_colour'];
1163
+ }
1164
+
1165
+ $submenu_item_toggle_text_color_hover = '';
1166
+ if ( ! empty( $options['submenu_sub_arrow_shape_hover_colour'] ) ) {
1167
+ $submenu_item_toggle_text_color_hover = $options['submenu_sub_arrow_shape_hover_colour'];
1168
+ }
1169
+
1170
+ $submenu_current_item_toggle_text_color = '';
1171
+ if ( ! empty( $options['submenu_sub_arrow_shape_colour_active'] ) ) {
1172
+ $submenu_current_item_toggle_text_color = $options['submenu_sub_arrow_shape_colour_active'];
1173
+ }
1174
+
1175
+ $submenu_current_item_toggle_text_color_hover = '';
1176
+ if ( ! empty( $options['submenu_sub_arrow_shape_hover_colour_active'] ) ) {
1177
+ $submenu_current_item_toggle_text_color_hover = $options['submenu_sub_arrow_shape_hover_colour_active'];
1178
+ }
1179
+
1180
+ $submenu_item_toggle_background_color = '';
1181
+ if ( ! empty( $options['submenu_sub_arrow_background_colour'] ) ) {
1182
+ $submenu_item_toggle_background_color = $options['submenu_sub_arrow_background_colour'];
1183
+ }
1184
+
1185
+ $submenu_item_toggle_background_color_hover = '';
1186
+ if ( ! empty( $options['submenu_sub_arrow_background_hover_colour'] ) ) {
1187
+ $submenu_item_toggle_background_color_hover = $options['submenu_sub_arrow_background_hover_colour'];
1188
+ }
1189
+
1190
+ $submenu_current_item_toggle_background_color = '';
1191
+ if ( ! empty( $options['submenu_sub_arrow_background_colour_active'] ) ) {
1192
+ $submenu_current_item_toggle_background_color = $options['submenu_sub_arrow_background_colour_active'];
1193
+ }
1194
+
1195
+ $submenu_current_item_toggle_background_color_hover = '';
1196
+ if ( ! empty( $options['submenu_sub_arrow_background_hover_colour_active'] ) ) {
1197
+ $submenu_current_item_toggle_background_color_hover = $options['submenu_sub_arrow_background_hover_colour_active'];
1198
+ }
1199
+
1200
+ $submenu_item_toggle_border_color = '';
1201
+ if ( ! empty( $options['submenu_sub_arrow_border_colour'] ) ) {
1202
+ $submenu_item_toggle_border_color = $options['submenu_sub_arrow_border_colour'];
1203
+ }
1204
+
1205
+ $submenu_item_toggle_border_color_hover = '';
1206
+ if ( ! empty( $options['submenu_sub_arrow_border_hover_colour'] ) ) {
1207
+ $submenu_item_toggle_border_color_hover = $options['submenu_sub_arrow_border_hover_colour'];
1208
+ }
1209
+
1210
+ $submenu_current_item_toggle_border_color = '';
1211
+ if ( ! empty( $options['submenu_sub_arrow_border_colour_active'] ) ) {
1212
+ $submenu_current_item_toggle_border_color = $options['submenu_sub_arrow_border_colour_active'];
1213
+ }
1214
+
1215
+ $submenu_current_item_toggle_border_color_hover = '';
1216
+ if ( ! empty( $options['submenu_sub_arrow_border_hover_colour_active'] ) ) {
1217
+ $submenu_current_item_toggle_border_color_hover = $options['submenu_sub_arrow_border_hover_colour_active'];
1218
+ }
1219
+
1220
+ //Animation delay and times.
1221
+
1222
+ $animation_speed = '';
1223
+ if ( ! empty( $options['animation_speed'] ) ) {
1224
+ $animation_speed = $options['animation_speed'] . 's';
1225
+ }
1226
+
1227
+ $color_transition_speed = '';
1228
+ if ( ! empty( $options['transition_speed'] ) ) {
1229
+ $color_transition_speed = $options['transition_speed'] . 's';
1230
+ }
1231
+
1232
+ $sub_menu_transition_speed = '';
1233
+ if ( ! empty( $options['sub_menu_speed'] ) ) {
1234
+ $sub_menu_transition_speed = $options['sub_menu_speed'] . 's';
1235
+ }
1236
+
1237
+ $menu_to_hide = '';
1238
+ if ( ! empty( $options['menu_to_hide'] ) ) {
1239
+ $menu_to_hide = $options['menu_to_hide'];
1240
+ }
1241
+
1242
+ $parse_options = array (
1243
+ // Menu breakpoints
1244
+ 'tablet_breakpoint' => $tablet_breakpoint,
1245
+
1246
+ // Menu hamburger toggle options.
1247
+ 'menu_trigger_id' => $menu_trigger_id,
1248
+ 'menu_trigger_position_type' => $button_position_type,
1249
+ 'menu_trigger_side' => $menu_trigger_side,
1250
+ 'menu_trigger_distance_from_side' => $button_distance_from_side,
1251
+ 'menu_trigger_distance_from_top' => $menu_trigger_distance_from_top,
1252
+ 'menu_trigger_width' => $menu_trigger_width,
1253
+ 'menu_trigger_height' => $menu_trigger_height,
1254
+ 'menu_trigger_background_color' => $menu_trigger_background_color,
1255
+ 'menu_trigger_background_color_hover' => $menu_trigger_background_color_hover,
1256
+ 'menu_trigger_active_color' => $menu_trigger_active_color,
1257
+ 'menu_trigger_transparent_background' => $menu_trigger_transparent_background,
1258
+ 'menu_trigger_line_color' => $menu_trigger_line_color,
1259
+ 'menu_trigger_line_color_hover' => $menu_trigger_line_color_hover,
1260
+ 'menu_trigger_line_active_color' => $menu_trigger_line_active_color,
1261
+ 'menu_trigger_title_color' => $menu_trigger_title_color,
1262
+ 'menu_trigger_title_line_height' => $menu_trigger_title_line_height,
1263
+ 'menu_trigger_title_font_size' => $menu_trigger_title_font_size,
1264
+ 'menu_trigger_title_font' => $menu_trigger_title_font,
1265
+ 'menu_trigger_line_height' => $menu_trigger_line_height,
1266
+ 'menu_trigger_line_height_unit' => $menu_trigger_line_height_unit,
1267
+ 'menu_trigger_line_width' => $menu_trigger_line_width,
1268
+ 'menu_trigger_line_width_unit' => $menu_trigger_line_width_unit,
1269
+ 'menu_trigger_line_margin' => $menu_trigger_line_margin,
1270
+ 'menu_trigger_line_margin_unit' => $menu_trigger_line_margin_unit,
1271
+
1272
+ // Menu searchbox options.
1273
+ 'menu_search_box_wrap' => $menu_search_box_wrap,
1274
+ 'menu_search_box_text_color' => $menu_search_box_text_color,
1275
+ 'menu_search_box_background_color' => $menu_search_box_background_color,
1276
+ 'menu_search_box_border_color' => $menu_search_box_border_color,
1277
+ 'menu_search_box_placeholder_color' => $menu_search_box_placeholder_color,
1278
+ 'menu_search_box_border_radius' => $menu_search_box_border_radius,
1279
+ 'menu_search_box_height_unit' => $menu_search_box_height_unit,
1280
+ 'menu_search_box_height' => $menu_search_box_height,
1281
+ 'menu_search_section_padding_bottom' => $menu_search_section_padding_bottom,
1282
+ 'menu_search_section_padding_right' => $menu_search_section_padding_right,
1283
+ 'menu_search_section_padding_top' => $menu_search_section_padding_top,
1284
+ 'menu_search_section_padding_left' => $menu_search_section_padding_left,
1285
+
1286
+ // Menu additional contents options.
1287
+ 'menu_additional_content_wrap' => $menu_additional_content_wrap,
1288
+ 'menu_additional_content_color' => $menu_additional_content_color,
1289
+ 'menu_additional_content_alignment' => $menu_additional_content_alignment,
1290
+ 'menu_additional_content_font_size' => $menu_additional_content_font_size,
1291
+ 'menu_additional_content_font_size_unit' => $menu_additional_content_font_size_unit,
1292
+ 'menu_additional_section_padding_left' => $menu_additional_section_padding_left,
1293
+ 'menu_additional_section_padding_top' => $menu_additional_section_padding_top,
1294
+ 'menu_additional_section_padding_bottom' => $menu_additional_section_padding_bottom,
1295
+ 'menu_additional_section_padding_right' => $menu_additional_section_padding_right,
1296
+
1297
+ // Menu title options.
1298
+ 'menu_title_wrap' => $menu_title_wrap,
1299
+ 'menu_title_background' => $menu_title_background,
1300
+ 'menu_title_background_hover' => $menu_title_background_hover,
1301
+ 'menu_title_font_color' => $menu_title_font_color,
1302
+ 'menu_title_font_color_hover' => $menu_title_font_color_hover,
1303
+ 'menu_title_font_size' => $menu_title_font_size,
1304
+ 'menu_title_image_width' => $menu_title_image_width,
1305
+ 'menu_title_image_height' => $menu_title_image_height,
1306
+ 'menu_title_text_alignment' => $menu_title_text_alignment,
1307
+ 'menu_title_section_padding_left' => $menu_title_section_padding_left,
1308
+ 'menu_title_section_padding_top' => $menu_title_section_padding_top,
1309
+ 'menu_title_section_padding_right' => $menu_title_section_padding_right,
1310
+ 'menu_title_section_padding_bottom' => $menu_title_section_padding_bottom,
1311
+
1312
+ // Menu items and it's settings options.
1313
+ 'menu_container' => $menu_container,
1314
+ 'menu_width' => $menu_width,
1315
+ 'menu_width_unit' => $menu_width_unit,
1316
+ 'menu_maximum_width' => $menu_maximum_width,
1317
+ 'menu_maximum_width_unit' => $menu_maximum_width_unit,
1318
+ 'menu_minimum_width' => $menu_minimum_width,
1319
+ 'menu_minimum_width_unit' => $menu_minimum_width_unit,
1320
+ 'menu_container_background_colour' => $menu_container_background_colour,
1321
+ 'menu_container_background_image' => "'" . $menu_container_background_image . "'",
1322
+ 'menu_container_appear_from' => $menu_container_appear_from,
1323
+ 'page_wrapper' => $page_wrapper,
1324
+ 'menu_to_hide' => $menu_to_hide,
1325
+ 'menu_container_padding_left' => $menu_container_padding_left,
1326
+ 'menu_container_padding_top' => $menu_container_padding_top,
1327
+ 'menu_container_padding_bottom' => $menu_container_padding_bottom,
1328
+ 'menu_container_padding_right' => $menu_container_padding_right,
1329
+ 'menu_wrap' => $menu_wrap,
1330
+ 'menu_section_padding_bottom' => $menu_section_padding_bottom,
1331
+ 'menu_section_padding_right' => $menu_section_padding_right,
1332
+ 'menu_section_padding_top' => $menu_section_padding_top,
1333
+ 'menu_section_padding_left' => $menu_section_padding_left,
1334
+
1335
+ 'menu_background_color' => $menu_background_color,
1336
+ 'menu_item_height' => $menu_item_height,
1337
+ 'menu_item_height_unit' => $menu_item_height_unit,
1338
+ 'menu_item_line_height' => $menu_item_line_height,
1339
+ 'menu_item_line_height_unit' => $menu_item_line_height_unit,
1340
+ 'menu_item_font_weight' => $menu_item_font_weight,
1341
+ 'menu_item_letter_spacing' => $menu_item_letter_spacing,
1342
+
1343
+ 'menu_item_border_width' => $menu_item_border_width,
1344
+ 'menu_item_border_width_unit' => $menu_item_border_width_unit,
1345
+ 'menu_item_border_color' => $menu_item_border_color,
1346
+ 'menu_item_border_color_hover' => $menu_item_border_color_hover,
1347
+ 'menu_current_item_border_color' => $menu_current_item_border_color,
1348
+ 'menu_current_item_border_color_hover' => $menu_current_item_border_color_hover,
1349
+
1350
+ 'menu_item_font_size' => $menu_item_font_size,
1351
+ 'menu_item_font_size_unit' => $menu_item_font_size_unit,
1352
+ 'menu_item_font_family' => $menu_item_font_family,
1353
+ 'menu_item_text_alignment' => $menu_item_text_alignment,
1354
+ 'menu_item_text_color' => $menu_item_text_color,
1355
+ 'menu_item_text_color_hover' => $menu_item_text_color_hover,
1356
+ 'menu_current_item_text_color' => $menu_current_item_text_color,
1357
+ 'menu_current_item_text_color_hover' => $menu_current_item_text_color_hover,
1358
+
1359
+ 'menu_item_padding' => $menu_item_padding,
1360
+ 'menu_item_padding_unit' => $menu_item_padding_unit,
1361
+ 'menu_item_background_color' => $menu_item_background_color,
1362
+ 'menu_item_background_color_hover' => $menu_item_background_color_hover,
1363
+ 'menu_current_item_background_color' => $menu_current_item_background_color,
1364
+ 'menu_current_item_background_color_hover' => $menu_current_item_background_color_hover,
1365
+
1366
+ 'menu_item_toggle_position' => $menu_item_toggle_position,
1367
+ 'menu_item_toggle_height' => $menu_item_toggle_height,
1368
+ 'menu_item_toggle_height_unit' => $menu_item_toggle_height_unit,
1369
+ 'menu_item_toggle_width' => $menu_item_toggle_width,
1370
+ 'menu_item_toggle_width_unit' => $menu_item_toggle_width_unit,
1371
+ 'menu_item_toggle_text_color' => $menu_item_toggle_text_color,
1372
+ 'menu_item_toggle_text_color_hover' => $menu_item_toggle_text_color_hover,
1373
+ 'menu_current_item_toggle_text_color' => $menu_current_item_toggle_text_color,
1374
+ 'menu_current_item_toggle_text_color_hover' => $menu_current_item_toggle_text_color_hover,
1375
+ 'menu_item_toggle_background_color' => $menu_item_toggle_background_color,
1376
+ 'menu_item_toggle_background_color_hover' => $menu_item_toggle_background_color_hover,
1377
+ 'menu_current_item_toggle_background_color' => $menu_current_item_toggle_background_color,
1378
+ 'menu_current_item_toggle_background_color_hover' => $menu_current_item_toggle_background_color_hover,
1379
+ 'menu_item_toggle_border_color' => $menu_item_toggle_border_color,
1380
+ 'menu_item_toggle_border_color_hover' => $menu_item_toggle_border_color_hover,
1381
+ 'menu_current_item_toggle_border_color' => $menu_item_toggle_border_color_hover,
1382
+ 'menu_current_item_toggle_border_color_hover' => $menu_current_item_toggle_border_color_hover,
1383
+
1384
+ 'menu_item_toggle_border_width' => $menu_sub_arrow_border_width,
1385
+ 'menu_item_toggle_border_width_unit' => $menu_sub_arrow_border_width_unit,
1386
+
1387
+ // Sub-level menu items options.
1388
+ 'submenu_item_height' => $submenu_item_height,
1389
+ 'submenu_item_height_unit' => $submenu_item_height_unit,
1390
+ 'submenu_item_line_height' => $submenu_item_line_height,
1391
+ 'submenu_item_line_height_unit' => $submenu_item_line_height_unit,
1392
+
1393
+ 'submenu_item_border_width' => $submenu_item_border_width,
1394
+ 'submenu_item_border_width_unit' => $submenu_item_border_width_unit,
1395
+ 'submenu_item_border_color' => $submenu_item_border_color,
1396
+ 'submenu_item_border_color_hover' => $submenu_item_border_color_hover,
1397
+ 'submenu_current_item_border_color' => $submenu_current_item_border_color,
1398
+ 'submenu_current_item_border_color_hover' => $submenu_current_item_border_color_hover,
1399
+
1400
+ 'submenu_item_font_size' => $submenu_item_font_size,
1401
+ 'submenu_item_font_size_unit' => $submenu_item_font_size_unit,
1402
+ 'submenu_item_font_family' => $submenu_item_font_family,
1403
+ 'submenu_item_text_alignment' => $submenu_item_text_alignment,
1404
+
1405
+ 'submenu_item_text_color' => $submenu_item_text_color,
1406
+ 'submenu_item_text_color_hover' => $submenu_item_text_color_hover,
1407
+ 'submenu_current_item_text_color' => $submenu_current_item_text_color,
1408
+ 'submenu_current_item_text_color_hover' => $submenu_current_item_text_color_hover,
1409
+ 'submenu_item_background_color' => $submenu_item_background_color,
1410
+ 'submenu_item_background_color_hover' => $submenu_item_background_color_hover,
1411
+ 'submenu_current_item_background_color' => $submenu_current_item_background_color,
1412
+ 'submenu_current_item_background_color_hover' => $submenu_current_item_background_color_hover,
1413
+
1414
+ 'submenu_item_toggle_position' => $submenu_item_toggle_position,
1415
+ 'submenu_item_toggle_height' => $submenu_item_toggle_height,
1416
+ 'submenu_item_toggle_height_unit' => $submenu_item_toggle_height_unit,
1417
+ 'submenu_item_toggle_width' => $submenu_item_toggle_width,
1418
+ 'submenu_item_toggle_width_unit' => $submenu_item_toggle_width_unit,
1419
+ 'is_legacy' => $is_legacy,
1420
+
1421
+ 'submenu_item_toggle_text_color' => $submenu_item_toggle_text_color,
1422
+ 'submenu_item_toggle_text_color_hover' => $submenu_item_toggle_text_color_hover,
1423
+ 'submenu_current_item_toggle_text_color' => $submenu_current_item_toggle_text_color,
1424
+ 'submenu_current_item_toggle_text_color_hover' => $submenu_current_item_toggle_text_color_hover,
1425
+ 'submenu_item_toggle_background_color' => $submenu_item_toggle_background_color,
1426
+ 'submenu_item_toggle_background_color_hover' => $submenu_item_toggle_background_color_hover,
1427
+ 'submenu_current_item_toggle_background_color' => $submenu_current_item_toggle_background_color,
1428
+ 'submenu_current_item_toggle_background_color_hover' => $submenu_current_item_toggle_background_color_hover,
1429
+ 'submenu_item_toggle_border_color' => $submenu_item_toggle_border_color,
1430
+ 'submenu_item_toggle_border_color_hover' => $submenu_item_toggle_border_color_hover,
1431
+ 'submenu_current_item_toggle_border_color' => $submenu_current_item_toggle_border_color,
1432
+ 'submenu_current_item_toggle_border_color_hover' => $submenu_current_item_toggle_border_color_hover,
1433
+
1434
+ 'submenu_item_toggle_border_width' => $submenu_sub_arrow_border_width,
1435
+ 'submenu_item_toggle_border_width_unit' => $submenu_sub_arrow_border_width_unit,
1436
+
1437
+ 'menu_depth_side' => $menu_depth_side,
1438
+ 'menu_item_padding_depth_1' => $menu_item_padding_depth_1,
1439
+ 'menu_item_padding_depth_1_unit' => $menu_item_padding_depth_1_unit,
1440
+ 'menu_item_padding_depth_2' => $menu_item_padding_depth_2,
1441
+ 'menu_item_padding_depth_2_unit' => $menu_item_padding_depth_2_unit,
1442
+ 'menu_item_padding_depth_3' => $menu_item_padding_depth_3,
1443
+ 'menu_item_padding_depth_3_unit' => $menu_item_padding_depth_3_unit,
1444
+ 'menu_item_padding_depth_4' => $menu_item_padding_depth_4,
1445
+ 'menu_item_padding_depth_4_unit' => $menu_item_padding_depth_4_unit,
1446
+ 'menu_word_wrap' => $menu_word_wrap,
1447
+
1448
+ //Animation and transition.
1449
+ 'animation_speed' => $animation_speed,
1450
+ 'color_transition_speed' => $color_transition_speed,
1451
+ 'sub_menu_transition_speed' => $sub_menu_transition_speed
1452
+ );
1453
+
1454
+ $scss = new Compiler();
1455
+ $scss->setImportPaths( RMP_PLUGIN_PATH_V4 . '/assets/scss/' );
1456
+ $scss->setVariables( $parse_options );
1457
+ $css = $scss->compile( '@import "main.scss";' );
1458
+
1459
+ return $css;
1460
+ }
1461
+
1462
+
1463
+ catch ( Exception $e ) {
1464
+ return new \WP_Error( "Warning: Menu style scss compile failed <br/> <br />" . $e->getMessage() );
1465
+ }
1466
+ }
1467
+
1468
+ /**
1469
+ * This function convert the common scss style to css.
1470
+ *
1471
+ * @return string/WP_Error
1472
+ */
1473
+ public function get_common_scss_to_css() {
1474
+ try {
1475
+
1476
+
1477
+ $menu_adjust_for_wp_admin_bar = $this->option_manager->get_global_option( 'menu_adjust_for_wp_admin_bar' );
1478
+
1479
+ $options = [
1480
+ 'menu_adjust_for_wp_admin_bar' => $menu_adjust_for_wp_admin_bar
1481
+ ];
1482
+
1483
+ $scss = new Compiler();
1484
+ $scss->setImportPaths( RMP_PLUGIN_PATH_V4 . '/assets/scss/' );
1485
+ $scss->setVariables( $options );
1486
+ $css = $scss->compile( '@import "common.scss";' );
1487
+
1488
+ return $css;
1489
+ }
1490
+
1491
+ catch ( Exception $e ) {
1492
+ return new \WP_Error( "Warning: Common style scss compile failed <br/> <br />" . $e->getMessage() );
1493
+ }
1494
+
1495
+ }
1496
+
1497
+ }
v4.0.0/inc/classes/class-theme-manager.php ADDED
@@ -0,0 +1,572 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file contain the Theme_Manager class and it's functionalities for menu.
4
+ *
5
+ * @version 4.0.0
6
+ * @author Expresstech System
7
+ *
8
+ * @package responsive-menu-pro
9
+ */
10
+
11
+ namespace RMP\Features\Inc;
12
+
13
+ use RMP\Features\Inc\Traits\Singleton;
14
+ use responsive_menu_pro\frontend\RMP_Menu;
15
+
16
+ // Disable the direct access to this class.
17
+ if ( ! defined( 'ABSPATH' ) ) {
18
+ exit;
19
+ }
20
+
21
+ /**
22
+ * Class Theme_Manager
23
+ * This class is handling the menu themes and its functionalities.
24
+ *
25
+ * @version 4.0.0
26
+ */
27
+ class Theme_Manager {
28
+
29
+ use Singleton;
30
+
31
+ /**
32
+ * This is option key where saved themes are stored.
33
+ * @var string $theme_option
34
+ */
35
+ protected static $theme_option = 'rmp_themes';
36
+
37
+ /**
38
+ * Construct method.
39
+ */
40
+ protected function __construct() {
41
+ $this->setup_hooks();
42
+ }
43
+
44
+ /**
45
+ * To setup action/filter.
46
+ *
47
+ * @version 4.0.0
48
+ *
49
+ * @return void
50
+ */
51
+ protected function setup_hooks() {
52
+ add_action('wp_ajax_rmp_save_theme', array( $this, 'rmp_save_theme' ) );
53
+ add_action('admin_post_rmp_upload_theme_file', array( $this, 'rmp_upload_theme' ) );
54
+ add_action('wp_ajax_rmp_theme_delete', array( $this, 'rmp_theme_delete' ) );
55
+ add_action('wp_ajax_rmp_theme_apply', array( $this, 'rmp_theme_apply' ) );
56
+ add_action('wp_ajax_rmp_theme_download', array( $this, 'rmp_theme_download' ) );
57
+ }
58
+
59
+
60
+ /**
61
+ * Function to get the list of pro theme from store.
62
+ *
63
+ * @since 4.0.0
64
+ *
65
+ * @return array $pro_themes
66
+ */
67
+ public function get_themes_by_api() {
68
+ $pro_themes = [];
69
+
70
+ //These are older version theme which are not compatible with new version.
71
+ $exclude_theme_ids = ['47704','47698','45318'];
72
+
73
+ $endpoint_url = 'https://responsive.menu/edd-api/v2/products/?category=theme';
74
+ $rmp_response = wp_remote_get( $endpoint_url, array( 'sslverify' => false ) );
75
+ $rmp_response_body = wp_remote_retrieve_body( $rmp_response );
76
+ $rmp_response_body = json_decode( $rmp_response_body, true );
77
+ if ( ! empty( $rmp_response_body ) && is_array( $rmp_response_body ) ) {
78
+ foreach ( $rmp_response_body['products'] as $key => $product ) {
79
+ if ( ! in_array( $product['info']['id'], $exclude_theme_ids ) ) {
80
+ $pro_themes[] = array(
81
+ 'name' => $product['info']['title'],
82
+ 'preview_url' => $product['info']['thumbnail'],
83
+ 'buy_link' => $product['info']['link'],
84
+ 'price' => $product['pricing']['amount']
85
+ );
86
+ }
87
+ }
88
+ }
89
+
90
+ return $pro_themes;
91
+ }
92
+
93
+ /**
94
+ * Function to apply the theme in the menu.
95
+ *
96
+ * @since 4.0.0
97
+ *
98
+ * @return json
99
+ */
100
+ public function rmp_theme_apply() {
101
+
102
+ check_ajax_referer( 'rmp_nonce', 'ajax_nonce' );
103
+
104
+ $theme_name = sanitize_text_field( $_POST['theme_name'] );
105
+ if ( empty( $theme_name ) ) {
106
+ wp_send_json_error( [ 'message' => __( 'Theme Name Missing', 'responsive-menu-pro' ) ] );
107
+ }
108
+
109
+ $theme_type = sanitize_text_field( $_POST['theme_type'] );
110
+ $menu_id = sanitize_text_field( $_POST['menu_id'] );
111
+ $menu_to_use = sanitize_text_field( $_POST['menu_to_use'] );
112
+
113
+ if ( 'template' === $theme_type ) {
114
+ $theme_option = $this->get_saved_theme_options( $theme_name );
115
+ } else {
116
+ $theme_option = $this->get_downloaded_theme_settings( $theme_name );
117
+ }
118
+
119
+ $theme_option['menu_id'] = $menu_id;
120
+ $theme_option['menu_theme'] = $theme_name;
121
+ $theme_option['theme_type'] = $theme_type;
122
+ $theme_option['menu_to_use'] = $menu_to_use;
123
+
124
+ update_post_meta( $menu_id, 'rmp_menu_meta' ,$theme_option );
125
+
126
+ /**
127
+ * Fires when menu theme applied and options are saved.
128
+ *
129
+ * @since 4.0.0
130
+ * @param int $menu_id
131
+ */
132
+ do_action('rmp_theme_apply', $menu_id );
133
+
134
+ wp_send_json_error( [ 'message' => __( 'Theme applied', 'responsive-menu-pro' ) ] );
135
+
136
+ }
137
+
138
+ public function get_downloaded_theme_settings( $theme_name ) {
139
+ $theme_dir_path = wp_upload_dir()['basedir'] . '/rmp-menu/themes';
140
+ $theme_dirs = glob( $theme_dir_path . '/*' , GLOB_ONLYDIR );
141
+
142
+ foreach( $theme_dirs as $theme_dir ) {
143
+ $config_file = $theme_dir . '/config.json';
144
+ if ( file_exists( $config_file ) ) {
145
+ $config = json_decode( file_get_contents( $config_file ), true);
146
+ if ( $config['name'] == $theme_name ) {
147
+ $options = json_decode( file_get_contents( $theme_dir . '/options.json' ), true);
148
+ return $options;
149
+ }
150
+ }
151
+ }
152
+
153
+ return [];
154
+ }
155
+
156
+ public function rmp_theme_delete() {
157
+
158
+ check_ajax_referer( 'rmp_nonce', 'ajax_nonce' );
159
+
160
+ $theme_name = sanitize_text_field( $_POST['theme_name'] );
161
+ if ( empty( $theme_name ) ) {
162
+ wp_send_json_error( [ 'message' => __( 'Theme Name Missing', 'responsive-menu-pro' ) ] );
163
+ }
164
+
165
+ $theme_type = sanitize_text_field( $_POST['theme_type'] );
166
+
167
+ if ( 'template' === $theme_type ) {
168
+ $this->delete_template( $theme_name );
169
+ } else {
170
+ $this->delete_theme_folder( $theme_name );
171
+ }
172
+
173
+ wp_send_json_success( [ 'message' => __( 'Theme deleted', 'responsive-menu-pro' ) ] );
174
+
175
+ }
176
+
177
+ public function rmp_theme_download() {
178
+
179
+ check_ajax_referer( 'rmp_nonce', 'ajax_nonce' );
180
+
181
+ $theme_name = sanitize_text_field( $_POST['theme_name'] );
182
+ if ( empty( $theme_name ) ) {
183
+ wp_send_json_error( [ 'message' => __( 'Theme Name Missing', 'responsive-menu-pro' ) ] );
184
+ }
185
+
186
+ $theme_type = sanitize_text_field( $_POST['theme_type'] );
187
+
188
+ $theme_option = [];
189
+ if ( 'template' === $theme_type ) {
190
+ $theme_option = $this->get_saved_theme_options( $theme_name );
191
+ } else {
192
+ $theme = $this->download_zip( $theme_name );
193
+ }
194
+
195
+ $theme_options_json = json_encode( $theme_option );
196
+
197
+ wp_send_json_success( $theme_options_json );
198
+ }
199
+
200
+ public function prepare_theme_zip_file( $theme_name, $options ) {
201
+ $zip_file_name = $theme_name . '.zip';
202
+
203
+ $zip = new ZipArchive();
204
+
205
+ if ( $zip->open( $zip_file_name ) === TRUE ) {
206
+ $zip->addFile( '/path/to/index.txt', 'newname.txt' );
207
+ $zip->close();
208
+ } else {
209
+ echo 'failed';
210
+ }
211
+ }
212
+
213
+ public function download_zip( $theme_name ) {
214
+
215
+ $theme_dir = $this->get_theme_dir( $theme_name );
216
+
217
+ if ( empty( $theme_dir ) ) {
218
+ return;
219
+ }
220
+
221
+ $theme_root = wp_upload_dir()['basedir'] . '/rmp-menu/themes';
222
+
223
+ // Filename for a zip package
224
+ $file_name = strtolower ( preg_replace('/\s+/', '-', $theme_name ) ) . '.zip';
225
+ $zip_file = $theme_root.'/'.$file_name;
226
+
227
+ $zip = new \ZipArchive();
228
+ if ( $zip->open( $zip_file , \ZipArchive::CREATE | \ZipArchive::OVERWRITE ) ) {
229
+
230
+ foreach ( glob( $theme_dir . "/*" ) as $file) {
231
+ $zip->addFile($file);
232
+ }
233
+
234
+ $zip->close();
235
+ }
236
+
237
+ if ( file_exists( $zip_file ) ) {
238
+ header('Content-Type: application/zip');
239
+ header('Content-Disposition: attachment; filename="'.basename( $zip_file ).'"');
240
+ header('Content-Length: ' . filesize($zip_file));
241
+ }
242
+ }
243
+
244
+ public function get_theme_dir( $theme_name ) {
245
+
246
+ $theme_dir_path = wp_upload_dir()['basedir'] . '/rmp-menu/themes';
247
+ $theme_dirs = glob( $theme_dir_path . '/*' , GLOB_ONLYDIR );
248
+
249
+ foreach( $theme_dirs as $theme_dir ) {
250
+ $config_file = $theme_dir . '/config.json';
251
+ if ( file_exists( $config_file ) ) {
252
+ $config = json_decode( file_get_contents( $config_file ), true);
253
+ if ( $config['name'] == $theme_name ) {
254
+ return $theme_dir;
255
+ }
256
+ }
257
+ }
258
+ return false;
259
+ }
260
+
261
+ public function delete_theme_folder( $theme_name ) {
262
+
263
+ if ( empty( $theme_name ) ) {
264
+ return;
265
+ }
266
+
267
+ $theme_dir = $this->get_theme_dir( $theme_name );
268
+ if ( empty( $theme_dir ) ) {
269
+ return;
270
+ }
271
+
272
+ $this->delete_files( $theme_dir );
273
+ }
274
+
275
+ public function delete_files( $dir ) {
276
+ foreach( glob($dir . '/*') as $file) {
277
+ if( is_dir($file)) delete_files($file); else unlink($file);
278
+ }
279
+ rmdir($dir);
280
+ }
281
+
282
+ public function delete_template( $theme_name ) {
283
+ $rmp_themes = get_option( self::$theme_option );
284
+
285
+ if ( empty( $rmp_themes ) ) {
286
+ return false;
287
+ }
288
+
289
+ foreach( $rmp_themes as $theme_key => $options ) {
290
+ if ( $theme_name == $theme_key ) {
291
+ unset( $rmp_themes[$theme_key] );
292
+ update_option( self::$theme_option , $rmp_themes );
293
+ return true;
294
+ }
295
+ }
296
+
297
+ return false;
298
+ }
299
+
300
+ public function rmp_upload_theme() {
301
+
302
+ status_header(200);
303
+
304
+ $theme = $_FILES['file']['tmp_name'];
305
+
306
+ WP_Filesystem();
307
+ $upload_dir = wp_upload_dir()['basedir'] . '/rmp-menu/themes/';
308
+
309
+ $unzip_file = unzip_file( $theme , $upload_dir );
310
+
311
+ if ( is_wp_error( $unzip_file ) ) {
312
+ $status = ['danger' => $unzip_file->get_error_message() ];
313
+ } else {
314
+ $status = [ 'success' => 'Theme Imported Successfully.'];
315
+ }
316
+
317
+ return $status;
318
+ }
319
+
320
+
321
+ public function get_themes_from_uploads() {
322
+
323
+ $theme_url = wp_upload_dir()['baseurl'] . '/rmp-menu/themes';
324
+ $theme_dir_path = wp_upload_dir()['basedir'] . '/rmp-menu/themes';
325
+ $theme_dirs = glob( $theme_dir_path . '/*' , GLOB_ONLYDIR );
326
+
327
+ $themes = [];
328
+
329
+ foreach( $theme_dirs as $theme_dir ) {
330
+ $config_file = $theme_dir . '/config.json';
331
+ if ( file_exists( $config_file ) ) {
332
+ $config = json_decode( file_get_contents( $config_file ), true);
333
+ $themes[basename($theme_dir)]['theme_name'] = $config['name'];
334
+ $themes[basename($theme_dir)]['theme_version'] = $config['version'];
335
+ $themes[basename($theme_dir)]['status'] = ! empty( $config['is_paid'] ) ? 'Pro' : 'Free';
336
+ $themes[basename($theme_dir)]['theme_preview_url'] = $theme_url .'/'. basename($theme_dir) . '/preview.png';
337
+ }
338
+ }
339
+
340
+ return $themes;
341
+ }
342
+
343
+ public function rmp_save_theme() {
344
+
345
+ check_ajax_referer( 'rmp_nonce', 'ajax_nonce' );
346
+
347
+ $theme_name = sanitize_text_field( $_POST['theme_name'] );
348
+ if ( empty( $theme_name ) ) {
349
+ wp_send_json_error( [ 'message' => __( 'Theme Name Missing', 'responsive-menu-pro' ) ] );
350
+ }
351
+
352
+ $menu_id = sanitize_text_field( $_POST['menu_id'] );
353
+ if ( empty( $menu_id ) ) {
354
+ wp_send_json_error(
355
+ [ 'message' => __( 'Menu ID missing !', 'responsive-menu-pro' )]);
356
+ }
357
+
358
+ $options = array();
359
+ parse_str( $_POST['form'], $options );
360
+ $options = $options['menu'];
361
+
362
+ foreach( $options['mega_menu'] as $key ) {
363
+ $options['mega_menu_item'][$key] = get_post_meta( $menu_id, '_rmp_mega_menu_' . $key );
364
+ }
365
+
366
+ unset( $options['mega_menu'] );
367
+
368
+ $rmp_themes = get_option( self::$theme_option );
369
+ if ( empty( $rmp_themes ) || ! is_array( $rmp_themes ) ) {
370
+ $rmp_theme = [];
371
+ }
372
+
373
+ $rmp_themes[$theme_name] = $options;
374
+
375
+ update_option( self::$theme_option , $rmp_themes );
376
+
377
+ $data = $this->saved_theme_list();
378
+
379
+
380
+ wp_send_json_success( ['themes' => $data , 'message' => $theme_name . ' is saved' ] );
381
+
382
+ exit();
383
+
384
+
385
+ }
386
+
387
+
388
+ public function saved_theme_list() {
389
+
390
+ $rmp_themes = get_option( self::$theme_option );
391
+
392
+ if ( empty( $rmp_themes ) ) {
393
+ return;
394
+ }
395
+
396
+ $theme_list = [];
397
+ foreach( $rmp_themes as $theme_name => $options ) {
398
+ $theme_list[] = $theme_name;
399
+ }
400
+
401
+ return $theme_list;
402
+ }
403
+
404
+ public function get_saved_theme_options( $theme_name ) {
405
+
406
+
407
+ $rmp_themes = get_option( self::$theme_option );
408
+
409
+ if ( empty( $rmp_themes ) ) {
410
+ return;
411
+ }
412
+
413
+ foreach( $rmp_themes as $theme_key => $options ) {
414
+ if( $theme_name == $theme_key ) {
415
+ return $options;
416
+ }
417
+ }
418
+
419
+ return [];
420
+ }
421
+
422
+ public function rmp_saves_theme_list_html() {
423
+
424
+ $rmp_themes = $this->saved_theme_list();
425
+
426
+ if ( empty( $rmp_themes ) ) {
427
+ return;
428
+ }
429
+
430
+ $html = '';
431
+ foreach( $rmp_themes as $theme_name ) {
432
+ $html .= sprintf(
433
+ '<div class="rmp-theme-title ">
434
+ <span class="item-title"> %1$s </span>
435
+ <span class="item-controls">
436
+ <a theme-name="%1$s" class="rmp-theme-apply" theme-type="template">Apply</a>
437
+ </span>
438
+ </div>',
439
+ esc_attr( $theme_name )
440
+ );
441
+ }
442
+
443
+ return $html;
444
+ }
445
+
446
+ public function rmp_saved_theme_list_for_new_menu() {
447
+
448
+ $rmp_themes = $this->saved_theme_list();
449
+
450
+ if ( empty( $rmp_themes ) ) {
451
+ return;
452
+ }
453
+
454
+ $html = '';
455
+ foreach( $rmp_themes as $theme_name ) {
456
+ $html .= sprintf('
457
+ <div class="rmp-theme-item">
458
+ <input type="radio" class="rmp-theme-option" name="menu_theme" id="%1$s" value="%1$s" theme-type="template"/>
459
+ <label class="rmp-theme-title" for="%1$s"> %1$s </label>
460
+ </div>',
461
+ esc_attr( $theme_name )
462
+ );
463
+ }
464
+
465
+ return $html;
466
+ }
467
+
468
+ public function get_themes_from_theme_store( $in_wizard = false ) {
469
+ $themes = $this->get_themes_by_api();
470
+
471
+ if ( empty( $themes ) && $in_wizard ) {
472
+ return __( '<h2>Coming soon..</h2>', 'responsive-menu-pro' );
473
+ }
474
+
475
+ $html = '';
476
+ foreach( $themes as $theme ) {
477
+
478
+ $action_label = __( 'BUY NOW','responsive-menu-pro' );
479
+ $status = __( 'Pro','responsive-menu-pro' );
480
+ if ( 0 == $theme['price'] ) {
481
+ $status = __( 'Free','responsive-menu-pro' );
482
+ $action_label = __( 'DOWNLOAD','responsive-menu-pro' );
483
+ }
484
+
485
+ $html .= sprintf(
486
+ '<li class="rmp_theme_grid_item">
487
+ <div class="rmp-item-card">
488
+ <figure class="rmp-item-card_image">
489
+ <img src="%1$s" alt="%2$s" loading="lazy"/>
490
+ <figcaption class="rmp-item-card_label %3$s">
491
+ <span class="dashicons dashicons-star-filled "></span> %3$s
492
+ </figcaption>
493
+ </figure>
494
+ <div class="rmp-item-card_contents">
495
+ <h4> %2$s </h4>
496
+ </div>
497
+ <div class="rmp-item-card_action">
498
+ <a href="%4$s" target="_blank" class="button %5$s"> %5$s </a>
499
+ </div>
500
+ </div>
501
+ </li>',
502
+ esc_url( $theme['preview_url']),
503
+ esc_attr( $theme['name'] ),
504
+ $status,
505
+ esc_url( $theme['buy_link'] ),
506
+ $action_label
507
+ );
508
+ }
509
+
510
+ return $html;
511
+ }
512
+
513
+ public function all_theme_combine_list() {
514
+
515
+ $all_themes = [];
516
+
517
+ //Local saved themes.
518
+ $themes = $this->saved_theme_list();
519
+
520
+ if ( ! empty( $themes ) && is_array( $themes ) ) {
521
+ foreach( $themes as $theme ) {
522
+ $all_themes[] = [ 'name' => $theme , 'type' => 'Template' ];
523
+ }
524
+ }
525
+
526
+ //Uploaded themes.
527
+ $themes = $this->get_themes_from_uploads();
528
+ if ( ! empty( $themes ) && is_array( $themes ) ) {
529
+ foreach( $themes as $theme ) {
530
+ $all_themes[] = [ 'name' => $theme['theme_name'] , 'type' => 'Downloaded', 'preview_url' => $theme['theme_preview_url'] ];
531
+ }
532
+ }
533
+
534
+ return $all_themes;
535
+ }
536
+
537
+ public function get_theme_preview_url( $theme_name ) {
538
+
539
+ $theme_url = wp_upload_dir()['baseurl'] . '/rmp-menu/themes';
540
+ $theme_dir_path = wp_upload_dir()['basedir'] . '/rmp-menu/themes';
541
+ $theme_dirs = glob( $theme_dir_path . '/*' , GLOB_ONLYDIR );
542
+
543
+ foreach( $theme_dirs as $theme_dir ) {
544
+ $config_file = $theme_dir . '/config.json';
545
+ if ( file_exists( $config_file ) ) {
546
+ $config = json_decode( file_get_contents( $config_file ), true);
547
+ if ( $config['name'] == $theme_name ) {
548
+ return $theme_url .'/'. basename($theme_dir) . '/preview.png';
549
+ }
550
+ }
551
+ }
552
+ return '';
553
+ }
554
+
555
+ public function get_theme_thumbnail( $theme_name, $theme_type ) {
556
+ if( 'Default' == $theme_name || $theme_type != 'downloaded' ) {
557
+ return sprintf( '<img src="%s" class="theme-thumbnail">',
558
+ esc_url( RMP_PLUGIN_URL_V4 .'/assets/images/no-preview.jpeg' )
559
+ );
560
+ } else {
561
+ $theme_url = $this->get_theme_preview_url( $theme_name );
562
+ return sprintf( '<img src="%s" class="theme-thumbnail">',
563
+ esc_url( $theme_url )
564
+ );
565
+ }
566
+ }
567
+
568
+ }
569
+
570
+
571
+
572
+
v4.0.0/inc/classes/class-ui-manager.php ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file contain thh UI_Manager class and it's functionalities.
4
+ *
5
+ * @version 4.0.0
6
+ *
7
+ * @author Expresstech System
8
+ *
9
+ * @package responsive-menu-pro
10
+ */
11
+
12
+ namespace RMP\Features\Inc;
13
+ use RMP\Features\Inc\Control_Manager;
14
+ use RMP\Features\Inc\Traits\Singleton;
15
+
16
+ // Disable the direct access to this class.
17
+ if ( ! defined( 'ABSPATH' ) ) {
18
+ exit;
19
+ }
20
+
21
+ /**
22
+ * Class UI_Manager
23
+ * This class is responsible for provide the UI.
24
+ *
25
+ * @version 4.0.0
26
+ */
27
+ class UI_Manager {
28
+
29
+ use Singleton;
30
+
31
+ /**
32
+ * Instance of this control manager class.
33
+ *
34
+ * @since 4.0.0
35
+ * @access protected
36
+ * @var object.
37
+ */
38
+
39
+ protected $control_manager;
40
+
41
+ /**
42
+ * Construct method.
43
+ */
44
+ protected function __construct() {
45
+ $this->setup_hooks();
46
+ }
47
+
48
+ /**
49
+ * To setup action/filter.
50
+ *
51
+ * @version 4.0.0
52
+ *
53
+ * @return void
54
+ */
55
+ protected function setup_hooks() {
56
+ $this->control_manager = Control_Manager::get_instance();
57
+ }
58
+
59
+ public function accordion_divider() {
60
+ return '<div class="rmp-h-separator clearfix"></div>';
61
+ }
62
+
63
+
64
+ public function start_accordion_item( $accordion_attr ) {
65
+
66
+ if ( empty( $accordion_attr ) ) {
67
+ return;
68
+ }
69
+
70
+ $item_class = '';
71
+ if ( ! empty( $accordion_attr['item_class'] ) ) {
72
+ $item_class = $accordion_attr['item_class'];
73
+ }
74
+
75
+ $html = sprintf('<li class="rmp-accordion-item %s">', esc_attr( $item_class ) );
76
+
77
+ //According header.
78
+ if ( ! empty( $accordion_attr['item_header'] ) ) {
79
+
80
+ $title_class = '';
81
+ if ( ! empty( $accordion_attr['item_header']['title_class'] ) ) {
82
+ $title_class = $accordion_attr['item_header']['title_class'];
83
+ }
84
+
85
+ $title_span_class = '';
86
+ if ( ! empty( $accordion_attr['item_header']['title_span_class'] ) ) {
87
+ $title_span_class = $accordion_attr['item_header']['title_span_class'];
88
+ }
89
+
90
+ //Check tooltip text is added or not.
91
+ $tool_tip = '';
92
+ if ( ! empty( $accordion_attr['tool_tip'] ) ) {
93
+ $tool_tip = $this->control_manager->get_tool_tip( $accordion_attr['tool_tip'] );
94
+ }
95
+
96
+ $feature_label = '';
97
+ // Check feature type.
98
+ if( ! empty( $accordion_attr['feature_type'] ) ) {
99
+ $feature_label = sprintf(
100
+ '<a target="_blank" class="upgrade-tooltip" href="https://responsive.menu/pricing?utm_source=free-plugin&utm_medium=option&utm_campaign=hide_on_mobile" > %s </a>',
101
+ $accordion_attr['feature_type']
102
+ );
103
+ }
104
+
105
+ $title_contents = '';
106
+ if ( ! empty( $accordion_attr['item_header']['item_title'] ) ) {
107
+ $title_contents .= sprintf('<span class="%s"> %s %s %s</span>',
108
+ esc_attr( $title_span_class ),
109
+ esc_html( $accordion_attr['item_header']['item_title'] ),
110
+ $tool_tip,
111
+ $feature_label
112
+ );
113
+ }
114
+
115
+ $switcher = '';
116
+ if ( ! empty( $accordion_attr['item_header']['item_control']['switcher'] ) ) {
117
+
118
+ $switcher .= '<span class="item-controls">';
119
+ $switcher .= sprintf( '<input type="hidden" value="off" name="%s"/>', esc_attr( $accordion_attr['item_header']['item_control']['name'] ) );
120
+ $switcher .= sprintf( '<input type="checkbox" id="%s" name="%s" class="toggle %s" value="on" %s>',
121
+ esc_attr( $accordion_attr['item_header']['item_control']['id'] ),
122
+ esc_attr( $accordion_attr['item_header']['item_control']['name'] ),
123
+ esc_attr( $accordion_attr['item_header']['item_control']['class'] ),
124
+ esc_attr( $accordion_attr['item_header']['item_control']['is_checked'] )
125
+ );
126
+ $switcher .= '</span>';
127
+ }
128
+
129
+ $title_contents .= $switcher;
130
+
131
+ $html .= sprintf('<div class="rmp-accordion-title %s">%s</div>',
132
+ esc_attr( $title_class ),
133
+ $title_contents
134
+ );
135
+ }
136
+
137
+ // If self_close_item is true then avoid contents for this accordion item and close it.
138
+ if ( ! empty( $accordion_attr['self_close_item'] ) ) {
139
+ $html .= '</li>';
140
+ return $html;
141
+ }
142
+
143
+ //Accordion contents start.
144
+ $content_class = '';
145
+ if ( ! empty( $accordion_attr['item_content']['content_class'] ) ) {
146
+ $content_class = $accordion_attr['item_content']['content_class'];
147
+ }
148
+
149
+ $html .= sprintf('<div class="rmp-accordion-content rmp-menu-controls %s">', esc_attr( $content_class ) );
150
+
151
+ return $html;
152
+
153
+ }
154
+
155
+ public function end_accordion_item() {
156
+ //Accordion contents end.
157
+ return '</div></li>';
158
+ }
159
+
160
+
161
+ public function add_editor_menu_item( $tab_attr ) {
162
+
163
+ if ( empty( $tab_attr ) ) {
164
+ return;
165
+ }
166
+
167
+ $item_class = '';
168
+ if ( ! empty( $tab_attr['item_class'] ) ) {
169
+ $item_class = $tab_attr['item_class'];
170
+ }
171
+
172
+ $aria_owns = '';
173
+ if ( ! empty( $tab_attr['aria_owns'] ) ) {
174
+ $aria_owns = $tab_attr['aria_owns'];
175
+ }
176
+
177
+ $html = sprintf('<li class="rmp-tab-item %s" aria-owns="%s">', esc_attr( $item_class ), esc_attr( $aria_owns ) );
178
+
179
+
180
+ //Item header.
181
+ if ( ! empty( $tab_attr['item_header'] ) ) {
182
+
183
+ $title_class = '';
184
+ if ( ! empty( $tab_attr['item_header']['title_class'] ) ) {
185
+ $title_class = $tab_attr['item_header']['title_class'];
186
+ }
187
+
188
+ $title_contents = '';
189
+
190
+ if ( ! empty( $tab_attr['item_header']['item_title'] ) ) {
191
+ $title_contents .= sprintf('<span class="%s"> %s </span>',
192
+ esc_attr( $title_class ),
193
+ esc_html( $tab_attr['item_header']['item_title'] )
194
+ );
195
+ }
196
+
197
+ //Item icon.
198
+ if ( ! empty( $tab_attr['item_header']['item_svg_icon'] ) ) {
199
+ $html .= sprintf(
200
+ '<span class="rmp-tab-item-icon">%s</span>',
201
+ file_get_contents( $tab_attr['item_header']['item_svg_icon'] )
202
+ );
203
+ }
204
+
205
+ $html .= sprintf('<h3 class="rmp-tab-item-title %s">%s</h3>',
206
+ esc_attr( $title_class ),
207
+ $title_contents
208
+ );
209
+ }
210
+
211
+ $html .= '</li>';
212
+
213
+ return $html;
214
+
215
+ }
216
+
217
+ public function start_tabs_controls_panel( $param ) {
218
+
219
+ $items_count = 2;
220
+ if( ! empty( $param['tab_items'] ) ) {
221
+ $items_count = count( $param['tab_items'] );
222
+ }
223
+
224
+ $html = sprintf( '<div class="tabs %s">
225
+ <ul class="nav-tab-wrapper rmp-tab-items rmp-tab-items-%s" >',
226
+ esc_attr( $param['tab_classes'] ),
227
+ esc_attr( $items_count )
228
+ );
229
+
230
+ foreach( $param['tab_items'] as $tab_item ) {
231
+ $html .= sprintf(
232
+ '<li><a class="nav-tab %s" href="#%s">%s</a></li>',
233
+ esc_attr( $tab_item['item_class'] ),
234
+ esc_attr( $tab_item['item_target'] ),
235
+ esc_html( $tab_item['item_text'] )
236
+ );
237
+ }
238
+
239
+ $html .= '</ul>';
240
+
241
+ return $html;
242
+ }
243
+
244
+ public function end_tabs_controls_panel() {
245
+ return '</div>';
246
+ }
247
+
248
+
249
+ public function start_tab_item( $param ) {
250
+ $html = sprintf('<div id="%s" class="%s">',esc_attr( $param['item_id'] ), esc_attr( $param['item_class'] ) );
251
+
252
+ return $html;
253
+ }
254
+
255
+ public function end_tab_item() {
256
+ return '</div>';
257
+ }
258
+
259
+ public function start_group_controls() {
260
+ return '<div class="rmp-input-control-group">';
261
+ }
262
+
263
+ public function end_group_controls() {
264
+ return '</div>';
265
+ }
266
+
267
+
268
+
269
+ public function start_sub_accordion() {
270
+ return '<ul class="rmp-sub-accordion-container">';
271
+ }
272
+
273
+ public function end_sub_accordion() {
274
+ return '</ul>';
275
+ }
276
+
277
+
278
+ }
v4.0.0/inc/classes/class-walker.php ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This is core class file for responsive menu pro to design the menu
4
+ * with custom walker with saved settings.
5
+ *
6
+ * @since 4.0.0
7
+ *
8
+ * @package responsive_menu_pro
9
+ */
10
+
11
+ namespace RMP\Features\Inc;
12
+
13
+ /** Disable the direct access to this class */
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit;
16
+ }
17
+
18
+ /**
19
+ * Class Walker prepare the menu as per loction and menu id.
20
+ *
21
+ * @since 4.0.0
22
+ * @package responsive_menu_pro
23
+ *
24
+ * @author Expresstech System
25
+ */
26
+ class Walker extends \Walker_Nav_Menu {
27
+
28
+ /**
29
+ * Hold the current menu item.
30
+ *
31
+ * @since 4.0.0
32
+ * @access protected
33
+ * @var string $current_item
34
+ */
35
+ private $current_item;
36
+
37
+ /**
38
+ * Hold the top most item id
39
+ *
40
+ * @since 4.0.0
41
+ * @access protected
42
+ * @var object
43
+ */
44
+ protected $root_item_id;
45
+
46
+ /**
47
+ * This is Walker class constructor function.
48
+ *
49
+ * @access public
50
+ * @param array $option
51
+ */
52
+ public function __construct( $options ) {
53
+ $this->options = $options;
54
+ }
55
+
56
+ /**
57
+ * Function to create element for menu items.
58
+ *
59
+ * @access public
60
+ * @version 4.0.0
61
+ *
62
+ * @param string/HTML $output
63
+ * @param object $item
64
+ * @param int $depth
65
+ * @param array $args
66
+ * @param int $id
67
+ */
68
+ public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0) {
69
+
70
+ $this->set_current_item($item);
71
+
72
+ $classes = array();
73
+ if ( ! empty( $item->classes ) ) {
74
+ $classes = (array) $item->classes;
75
+ }
76
+
77
+ $rmp_menu_classes = $classes;
78
+
79
+ /** Add rmp menu classes as per item */
80
+ foreach( $classes as $class ) {
81
+ switch($class) {
82
+ case 'menu-item' :
83
+ $rmp_menu_classes[] = 'rmp-menu-item';
84
+ break;
85
+ case 'current-menu-item':
86
+ $rmp_menu_classes[] = 'rmp-menu-current-item';
87
+ break;
88
+ case 'menu-item-has-children':
89
+ $rmp_menu_classes[] = 'rmp-menu-item-has-children';
90
+ break;
91
+ case 'current-menu-parent':
92
+ $rmp_menu_classes[] = 'rmp-menu-item-current-parent';
93
+ break;
94
+ case 'current-menu-ancestor':
95
+ $rmp_menu_classes[] = 'rmp-menu-item-current-ancestor';
96
+ break;
97
+ }
98
+ }
99
+
100
+ // Add top/sub level class as per item.
101
+ if ( $item->menu_item_parent == 0 ) {
102
+ $rmp_menu_classes[] = 'rmp-menu-top-level-item';
103
+ $this->root_item_id = $item->ID;
104
+ } else {
105
+ $rmp_menu_classes[] = 'rmp-menu-sub-level-item';
106
+ }
107
+
108
+ /* Clear child class if we are at the final depth level */
109
+ if ( isset( $rmp_menu_classes ) ) {
110
+ $has_child = array_search( 'rmp-menu-item-has-children', $rmp_menu_classes );
111
+ if ( ( $depth + 1 ) == $this->options['menu_depth'] && ( $has_child ) !== false) {
112
+ unset( $rmp_menu_classes[$has_child] );
113
+ }
114
+ }
115
+
116
+ $class_names = join( ' ', array_unique( $rmp_menu_classes ) );
117
+
118
+ /** Prepare classes for menu item. */
119
+ if ( ! empty( $class_names ) ) {
120
+ $class_names = sprintf( 'class="%s"', esc_attr( $class_names ) );
121
+ } else {
122
+ $class_names = '';
123
+ }
124
+
125
+ // Start menu item and set classes & ID.
126
+ $output .= sprintf(
127
+ '<li id="rmp-menu-item-%s" %s role="none">',
128
+ esc_attr( $item->ID ) ,
129
+ $class_names
130
+ );
131
+
132
+ // Set attributes on menu item link.
133
+ $atts = array();
134
+ $atts['title'] = ! empty( $item->attr_title ) ? $item->attr_title : '';
135
+ $atts['target'] = ! empty( $item->target ) ? $item->target : '';
136
+ $atts['rel'] = ! empty( $item->xfn ) ? $item->xfn : '';
137
+ $atts['href'] = ! empty( $item->url ) ? $item->url : '';
138
+ $atts['class'] = 'rmp-menu-item-link';
139
+ $atts['role'] = 'menuitem';
140
+ $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );
141
+
142
+ $attributes = '';
143
+ foreach( $atts as $key => $value ) {
144
+ if ( ! empty( $value ) ) {
145
+ $value = ('href' === $key ) ? esc_url( $value ) : esc_attr( $value );
146
+ $attributes .= sprintf( ' %s = "%s" ' , $key , $value );
147
+ }
148
+ }
149
+
150
+ $title = apply_filters( 'the_title', $item->title, $item->ID );
151
+ $title = apply_filters( 'rmp_menu_item_title', $title, $item, $args, $depth );
152
+
153
+ // Activate the required menu item by default.
154
+ $sub_menu_arrow = '';
155
+ if ( in_array( 'rmp-menu-item-has-children', $rmp_menu_classes ) ) {
156
+
157
+ $inactive_arrow = sprintf(
158
+ '<div class="rmp-menu-subarrow">%s</div>',
159
+ $this->get_inactive_arrow()
160
+ );
161
+
162
+ $active_arrow = sprintf(
163
+ '<div class="rmp-menu-subarrow rmp-menu-subarrow-active">%s</div>',
164
+ $this->get_active_arrow()
165
+ );
166
+
167
+ if( 'on' == $this->options['auto_expand_all_submenus'] ) {
168
+ $sub_menu_arrow = $active_arrow;
169
+ } elseif (
170
+ $this->options['auto_expand_current_submenus'] == 'on' &&
171
+ ( in_array( 'rmp-menu-item-current-parent', $rmp_menu_classes ) ||
172
+ in_array('rmp-menu-item-current-ancestor', $rmp_menu_classes ) ) ) {
173
+ $sub_menu_arrow = $active_arrow;
174
+ } else {
175
+ $sub_menu_arrow = $inactive_arrow;
176
+ }
177
+ }
178
+
179
+ /* Clear Arrow if we are at the final depth level */
180
+ if ( $depth + 1 == $this->options['menu_depth'] ) {
181
+ $sub_menu_arrow = '';
182
+ }
183
+
184
+ $item_output = '';
185
+ $item_output .= sprintf( '<a %s >', $attributes );
186
+ $item_output .= $title;
187
+ $item_output .= $sub_menu_arrow;
188
+ $item_output .= '</a>';
189
+
190
+ // If description is enable then add it below of menu item.
191
+ if ( ! empty( $item->description ) && $this->options['submenu_descriptions_on'] == 'on' ) {
192
+ $item_output .= sprintf( '<p class="rmp-menu-item-description"> %s </p>', esc_html( $item->description ) );
193
+ }
194
+
195
+ // Theme support for twenty twenty one.
196
+ if ( function_exists( 'twenty_twenty_one_add_sub_menu_toggle' ) ) {
197
+ remove_filter( 'walker_nav_menu_start_el', 'twenty_twenty_one_add_sub_menu_toggle', 10 );
198
+ remove_filter( 'walker_nav_menu_start_el', 'twenty_twenty_one_nav_menu_social_icons', 10 );
199
+ }
200
+
201
+ /* End Add Desktop Menu Widgets to Sub Items */
202
+ $output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args );
203
+
204
+ }
205
+
206
+ /**
207
+ * Function to build the sub-menu items.
208
+ *
209
+ * @since 4.0.0
210
+ * @access public
211
+ *
212
+ * @param string|HTML $output
213
+ * @param int $depth
214
+ * @param array $args
215
+ */
216
+ public function start_lvl( &$output, $depth = 0, $args = array() ) {
217
+
218
+ // Add sub-menu item wrap.
219
+ $output .= sprintf( '<ul aria-label="%s"
220
+ role="menu" data-depth="%s"
221
+ class="rmp-submenu rmp-submenu-depth-%s">',
222
+ esc_attr( $this->current_item->title),
223
+ ( $depth + 2 ),
224
+ ($depth + 1) . $this->get_submenu_class_open_or_not()
225
+ );
226
+ }
227
+
228
+ /**
229
+ * Function to close the menu item.
230
+ *
231
+ * @access public
232
+ * @version 4.0.0
233
+ *
234
+ * @param string/HTML $output
235
+ * @param object $item
236
+ * @param int $depth
237
+ * @param array $args
238
+ */
239
+ public function end_el( &$output, $item, $depth = 0, $args = array() ) {
240
+ $output .= "</li>";
241
+ }
242
+
243
+ /**
244
+ * Function to close the sub-menu items.
245
+ *
246
+ * @since 4.0.0
247
+ * @access public
248
+ *
249
+ * @param string|HTML $output
250
+ * @param int $depth
251
+ * @param array $args
252
+ */
253
+ public function end_lvl( &$output, $depth = 0, $args = array() ) {
254
+ $output .= "</ul>";
255
+ }
256
+
257
+ /**
258
+ * Function get the active item toggle icon.
259
+ *
260
+ * @return HTML
261
+ */
262
+ public function get_active_arrow() {
263
+ if ( ! empty( $this->options['active_arrow_font_icon'] ) ) {
264
+ return $this->options['active_arrow_font_icon'];
265
+ } elseif( ! empty( $this->options['active_arrow_image'] ) ) {
266
+ return sprintf( '<img alt="%s" src="%s" />',
267
+ rmp_image_alt_by_url( $this->options['active_arrow_image']),
268
+ esc_url($this->options['active_arrow_image'])
269
+ );
270
+ } else {
271
+ return $this->options['active_arrow_shape'];
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Function get the inactive item toggle icon.
277
+ *
278
+ * @return HTML
279
+ */
280
+ public function get_inactive_arrow() {
281
+
282
+ if ( ! empty( $this->options['inactive_arrow_font_icon'] ) ) {
283
+ return $this->options['inactive_arrow_font_icon'];
284
+ } elseif( ! empty( $this->options['inactive_arrow_image'] ) ) {
285
+ return sprintf( '<img alt="%s" src="%s" />',
286
+ rmp_image_alt_by_url( $this->options['inactive_arrow_image']),
287
+ esc_url($this->options['inactive_arrow_image'])
288
+ );
289
+ } else {
290
+ return $this->options['inactive_arrow_shape'];
291
+ }
292
+ }
293
+
294
+ /**
295
+ * Function to set the current item object.
296
+ *
297
+ * @param object $item Menu item object.
298
+ */
299
+ public function set_current_item( $item ) {
300
+ $this->current_item = $item;
301
+ }
302
+
303
+ /**
304
+ * Function to return the current item object.
305
+ *
306
+ * @return object $item Menu item object.
307
+ */
308
+ public function get_current_item() {
309
+ return $this->current_item;
310
+ }
311
+
312
+ /**
313
+ * Check submenu need to open or not.
314
+ *
315
+ * @return boolean
316
+ */
317
+ public function get_submenu_class_open_or_not() {
318
+ return $this->expand_all_submenu_options_is_on() || $this->expand_current_submenu_on_and_item_is_parent() ? ' rmp-submenu-open' : '';
319
+ }
320
+
321
+ /**
322
+ * Check all submenu need to open or not.
323
+ *
324
+ * @return boolean
325
+ */
326
+ public function expand_all_submenu_options_is_on() {
327
+ return $this->options['auto_expand_all_submenus'] == 'on';
328
+ }
329
+
330
+ /**
331
+ * Check current submenu need to open or not.
332
+ *
333
+ * @return boolean
334
+ */
335
+ public function expand_current_submenu_on_and_item_is_parent() {
336
+ return ($this->options['auto_expand_current_submenus'] == 'on')
337
+ && ($this->get_current_item()->current_item_ancestor || $this->get_current_item()->current_item_parent);
338
+ }
339
+ }
v4.0.0/inc/helpers/autoloader.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Autoloader file for plugin.
4
+ *
5
+ * @package responsive-menu-pro
6
+ */
7
+
8
+ namespace RMP\Features\Inc\Helpers;
9
+
10
+ /**
11
+ * Auto loader function.
12
+ *
13
+ * @param string $resource Source namespace.
14
+ *
15
+ * @return void
16
+ */
17
+ function autoloader( $resource = '' ) {
18
+
19
+ $resource_path = false;
20
+ $namespace_root = 'RMP\Features\\';
21
+ $resource = trim( $resource, '\\' );
22
+
23
+ if ( empty( $resource ) || strpos( $resource, '\\' ) === false || strpos( $resource, $namespace_root ) !== 0 ) {
24
+ // Not our namespace, bail out.
25
+ return;
26
+ }
27
+
28
+ // Remove our root namespace.
29
+ $resource = str_replace( $namespace_root, '', $resource );
30
+
31
+ $path = explode(
32
+ '\\',
33
+ str_replace( '_', '-', strtolower( $resource ) )
34
+ );
35
+
36
+ /**
37
+ * Time to determine which type of resource path it is,
38
+ * so that we can deduce the correct file path for it.
39
+ */
40
+ if ( empty( $path[0] ) || empty( $path[1] ) ) {
41
+ return;
42
+ }
43
+
44
+ $directory = '';
45
+ $file_name = '';
46
+
47
+ if ( 'inc' === $path[0] ) {
48
+
49
+ switch ( $path[1] ) {
50
+ case 'traits':
51
+ $directory = 'traits';
52
+ $file_name = sprintf( 'trait-%s', trim( strtolower( $path[2] ) ) );
53
+ break;
54
+
55
+ case 'post-types':
56
+ case 'taxonomies':
57
+ case 'blocks':
58
+ case 'meta-boxes':
59
+ case 'widgets':
60
+ case 'plugin-configs':
61
+ /**
62
+ * If there is class name provided for specific directory then load that.
63
+ * otherwise find in inc/ directory.
64
+ */
65
+ if ( ! empty( $path[2] ) ) {
66
+ $directory = sprintf( 'classes/%s', $path[1] );
67
+ $file_name = sprintf( 'class-%s', trim( strtolower( $path[2] ) ) );
68
+ break;
69
+ }
70
+ default:
71
+ $directory = 'classes';
72
+ $file_name = sprintf( 'class-%s', trim( strtolower( $path[1] ) ) );
73
+ break;
74
+ }
75
+
76
+ $resource_path = sprintf( '%s/inc/%s/%s.php', untrailingslashit( RMP_PLUGIN_PATH_V4 ), $directory, $file_name );
77
+ }
78
+
79
+ /**
80
+ * If $is_valid_file has 0 means valid path or 2 means the file path contains a Windows drive path.
81
+ */
82
+ $is_valid_file = validate_file( $resource_path );
83
+
84
+ if ( ! empty( $resource_path ) && file_exists( $resource_path ) && ( 0 === $is_valid_file || 2 === $is_valid_file ) ) {
85
+ // We already making sure that file is exists and valid.
86
+ require_once( $resource_path );
87
+ }
88
+
89
+ }
90
+
91
+ spl_autoload_register( '\RMP\Features\Inc\Helpers\autoloader' );
v4.0.0/inc/helpers/custom-functions.php ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * RMP features custom functions.
4
+ *
5
+ * @version 4.0.0
6
+ *
7
+ * @package responsive-menu-pro
8
+ */
9
+
10
+ //namespace RMP\Features\Inc\Helpers;
11
+
12
+ /**
13
+ * Function to check the input is checked or not.
14
+ *
15
+ * @version 4.0.0
16
+ *
17
+ * @param string $actual_value
18
+ *
19
+ * @return string|null
20
+ */
21
+ function is_rmp_option_checked( $actual_value, $options, $key ) {
22
+
23
+ if ( empty( $options[$key] ) ) {
24
+ return;
25
+ }
26
+
27
+ $checked_value = $options[$key];
28
+ if ( $actual_value == $checked_value ) {
29
+ return "checked";
30
+ }
31
+
32
+ return;
33
+ }
34
+
35
+ /**
36
+ * Function to return the value from option
37
+ *
38
+ * @version 4.0.0
39
+ *
40
+ * @param string $key
41
+ * @param array $options
42
+ *
43
+ * @return string|array
44
+ */
45
+ function rmp_get_value( $options , $key ) {
46
+
47
+ if ( empty( $options[$key] ) ) {
48
+ return;
49
+ }
50
+
51
+ return $options[$key];
52
+ }
53
+
54
+ function rmp_get_list_of_pages() {
55
+
56
+ $posts = get_posts( [
57
+ 'numberposts' => -1,
58
+ 'post_type' => 'any'
59
+ ] );
60
+
61
+ $all_pages = [];
62
+
63
+ foreach( $posts as $post ) {
64
+ $all_pages[$post->ID] = $post->post_title;
65
+ }
66
+
67
+ return $all_pages;
68
+ }
69
+
70
+ /**
71
+ * Return the form to select a dashicon
72
+ *
73
+ * @since 1.5.2
74
+ * @return string
75
+ */
76
+ function rmp_dashicon_selector() {
77
+
78
+ $return = '';
79
+ foreach ( rmp_all_dash_icons() as $code => $class ) {
80
+
81
+ $bits = explode( "-", $code );
82
+ $code = "&#x" . $bits[1] . "";
83
+ $type = $bits[0];
84
+
85
+ $return .= sprintf( '<div class="%s font-icon">', esc_attr($type) );
86
+ $return .= sprintf('<input class="radio" id="%1$s" type="radio" rel="%2$s" name="icon" value="dashicons %1$s" />', esc_attr($class), esc_attr($code) );
87
+ $return .= sprintf('<label rel="%1$s" for="%2$s" title="%2$s" ></label>', $code, esc_attr($class) );
88
+ $return .= "</div>";
89
+
90
+ }
91
+
92
+ return $return;
93
+ }
94
+
95
+
96
+ /**
97
+ * Function to return the all menu ids of published menu.
98
+ *
99
+ * @since 4.0.0
100
+ * @return array $menu_ids;
101
+ */
102
+ function get_all_rmp_menu_ids() {
103
+
104
+ $args = array(
105
+ 'post_type' => 'rmp_menu',
106
+ 'posts_per_page' => -1,
107
+ 'post_status' => 'publish',
108
+ );
109
+
110
+ $query = new \WP_Query($args);
111
+ $menu_ids = [];
112
+
113
+ if ( $query->have_posts() ) {
114
+ while ( $query->have_posts() ) {
115
+ $query->the_post();
116
+ $menu_ids[] = get_the_ID();
117
+ }
118
+
119
+ wp_reset_postdata();
120
+ }
121
+
122
+ return $menu_ids;
123
+ }
124
+
125
+ /**
126
+ * Function to return the all published menu list.
127
+ *
128
+ * @since 4.0.0
129
+ * @return array;
130
+ */
131
+ function rmp_get_all_menus() {
132
+
133
+ $args = array(
134
+ 'post_type' => 'rmp_menu',
135
+ 'posts_per_page' => -1,
136
+ 'post_status' => 'publish',
137
+ );
138
+
139
+ $query = new \WP_Query($args);
140
+ $menus = [];
141
+
142
+ if ( $query->have_posts() ) {
143
+ while ( $query->have_posts() ) {
144
+ $query->the_post();
145
+ $menus[ get_the_ID() ] = get_the_title();
146
+ }
147
+
148
+ wp_reset_postdata();
149
+ }
150
+
151
+ return $menus;
152
+ }
153
+
154
+
155
+
156
+ /**
157
+ * Get image alt text by image URL
158
+ *
159
+ * @param String $image_url
160
+ *
161
+ * @return Bool | String
162
+ */
163
+ function rmp_image_alt_by_url( $image_url ) {
164
+ global $wpdb;
165
+
166
+ if( empty( $image_url ) ) {
167
+ return '';
168
+ }
169
+
170
+ $query_arr = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE guid='%s';", strtolower( $image_url ) ) );
171
+ $image_id = ( ! empty( $query_arr ) ) ? $query_arr[0] : 0;
172
+
173
+ return get_post_meta( $image_id, '_wp_attachment_image_alt', true );
174
+ }
175
+
176
+ /**
177
+ * Return the menu items.
178
+ */
179
+ function rmp_get_wp_nav_menu_items( $options ) {
180
+
181
+ $menu = '';
182
+
183
+ if( ! empty( $options['theme_location_menu'] ) && has_nav_menu( $options['theme_location_menu'] ) ) {
184
+ $menu = get_term(get_nav_menu_locations()[ $options['theme_location_menu'] ], 'nav_menu')->slug;
185
+ } elseif( ! empty($options['menu_to_use'] ) ) {
186
+ $menu = $options['menu_to_use'];
187
+ } elseif( !empty( get_terms('nav_menu')[0]->slug ) ) {
188
+ $menu = get_terms('nav_menu')[0]->slug;
189
+ }
190
+
191
+ return wp_get_nav_menu_items($menu);
192
+ }
v4.0.0/inc/helpers/default-options.php ADDED
@@ -0,0 +1,1130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file contain the list of functions which have default options.
4
+ *
5
+ * @version 4.0.0
6
+ *
7
+ * @package responsive-menu-pro
8
+ */
9
+
10
+ /**
11
+ * Function return the global settings default values.
12
+ *
13
+ * @version 4.0.0
14
+ *
15
+ * @return array List of options.
16
+ */
17
+ function rmp_global_default_setting_options() {
18
+
19
+ return [
20
+ 'rmp_custom_css' => '',
21
+ 'rmp_license_key' => '',
22
+ 'menu_adjust_for_wp_admin_bar' => 'hide',
23
+ 'rmp_external_files' => 'on',
24
+ 'rmp_minify_scripts' => 'on',
25
+ 'rmp_scripts_in_footer' => 'on',
26
+ 'rmp_remove_fontawesome' => 'off',
27
+ 'rmp_remove_glyphicon' => 'off',
28
+ 'rmp_remove_dashicons' => 'off',
29
+ 'rmp_remove_material_icons' => 'off',
30
+ ];
31
+ }
32
+
33
+ /**
34
+ * Function return the multi device options.
35
+ * Here, Add the option which you want to make the multi device.
36
+ *
37
+ * @version 4.0.0
38
+ *
39
+ * @return array List of options.
40
+ */
41
+ function rmp_get_multi_device_options() {
42
+
43
+ return [
44
+ 'menu_font' => '',
45
+ 'menu_font_size' => '',
46
+ 'menu_font_size_unit' => 'px',
47
+ 'menu_item_background_colour' => '',
48
+ 'menu_item_background_hover_colour' => '#212121',
49
+ 'menu_link_colour' => '',
50
+ 'menu_link_hover_colour' => '',
51
+ 'menu_links_height' => '',
52
+ 'menu_links_height_unit' => 'px',
53
+ 'menu_links_line_height' => '40',
54
+ 'menu_links_line_height_unit' => 'px',
55
+ 'submenu_font' => '',
56
+ 'submenu_font_size' => '',
57
+ 'submenu_font_size_unit' => '',
58
+ 'submenu_item_background_colour' => '',
59
+ 'submenu_item_background_hover_colour' => '#212121',
60
+ 'submenu_link_colour' => '',
61
+ 'submenu_link_hover_colour' => '',
62
+ 'submenu_links_height' => '',
63
+ 'submenu_links_height_unit' => 'px',
64
+ 'submenu_links_line_height' => '',
65
+ 'submenu_links_line_height_unit' => 'px'
66
+ ];
67
+ }
68
+
69
+ function rmp_animation_delay_options() {
70
+ $time_options = [
71
+ '100ms' => '100ms',
72
+ '200ms' => '200ms',
73
+ '300ms' => '300ms',
74
+ '400ms' => '400ms',
75
+ '500ms' => '500ms',
76
+ '600ms' => '600ms',
77
+ '700ms' => '700ms',
78
+ '800ms' => '800ms',
79
+ '900ms' => '900ms',
80
+ '1000ms' => '1000ms',
81
+ ];
82
+
83
+ return $time_options;
84
+ }
85
+
86
+ /**
87
+ * Function to return the list of shortcut keys for menu open and close.
88
+ *
89
+ * @version 4.0.0
90
+ *
91
+ * @return array
92
+ */
93
+ function rmp_get_menu_open_close_keys() {
94
+ return [
95
+ 27 => 'Esc',
96
+ 13 => 'Enter',
97
+ 32 => 'Space',
98
+ 37 => 'Left',
99
+ 38 => 'Up',
100
+ 39 => 'Right',
101
+ 40 => 'Down'
102
+ ];
103
+ }
104
+
105
+ function rmp_font_weight_options() {
106
+
107
+ $unit_options = array(
108
+ '100' => '100',
109
+ '200' => '200',
110
+ '300' => '300',
111
+ '400' => '400',
112
+ '500' => '500',
113
+ '600' => '600',
114
+ '700' => '700',
115
+ '800' => '800',
116
+ '900' => '900',
117
+ 'normal'=>'Normal',
118
+ 'bold' => 'Bold',
119
+ 'bolder' => 'Bolder',
120
+ 'lighter' => 'Lighter',
121
+ 'initial' => 'Initial',
122
+ 'inherit' => 'Inherit',
123
+ );
124
+
125
+ $unit_options = apply_filters('rmp_font_weight_options', $unit_options );
126
+
127
+ return $unit_options;
128
+ }
129
+
130
+ function rmp_hamburger_type_animation_options() {
131
+
132
+ $type = array (
133
+ 'off' => __( 'Off', 'responsive-menu-pro' ),
134
+ 'boring' => __( 'Boring','responsive-menu-pro' ),
135
+ '3dx' => __( '3DX (PRO)','responsive-menu-pro' ),
136
+ '3dx-r' => __( '3DX Reverse (PRO)','responsive-menu-pro' ),
137
+ '3dy' => __( '3DY (PRO)','responsive-menu-pro' ),
138
+ '3dy-r' => __( '3DY Reverse (PRO)','responsive-menu-pro' ),
139
+ 'arrow' => __( 'Arrow (PRO)','responsive-menu-pro' ),
140
+ 'arrow-r' => __( 'Arrow Reverse (PRO)','responsive-menu-pro' ),
141
+ 'arrowalt' => __( 'Arrow Alt (PRO)','responsive-menu-pro'),
142
+ 'arrowalt-r' => __( 'Arrow Alt Reverse (PRO)','responsive-menu-pro' ),
143
+ 'collapse' => __('Collapse (PRO)','responsive-menu-pro' ),
144
+ 'collapse-r' => __('Collapse Reverse (PRO)','responsive-menu-pro' ),
145
+ 'elastic' => __('Elastic (PRO)','responsive-menu-pro' ),
146
+ 'elastic-r' => __('Elastic Reverse (PRO)','responsive-menu-pro' ),
147
+ 'emphatic' => __( 'Emphatic (PRO)','responsive-menu-pro' ),
148
+ 'emphatic-r' => __('Emphatic Reverse (PRO)','responsive-menu-pro' ),
149
+ 'minus' => __('Minus (PRO)','responsive-menu-pro' ),
150
+ 'slider' => __('Slider (PRO)','responsive-menu-pro' ),
151
+ 'slider-r' => __('Slider Reverse (PRO)','responsive-menu-pro' ),
152
+ 'spin' => __('Spin (PRO)','responsive-menu-pro' ),
153
+ 'spin-r' => __('Spin Reverse (PRO)','responsive-menu-pro' ),
154
+ 'spring' => __('Spring (PRO)','responsive-menu-pro' ),
155
+ 'spring-r' => __('Spring Reverse (PRO)','responsive-menu-pro' ),
156
+ 'stand' => __('Stand (PRO)','responsive-menu-pro' ),
157
+ 'stand-r' => __('Stand Reverse (PRO)','responsive-menu-pro' ),
158
+ 'squeeze' => __('Squeeze (PRO)','responsive-menu-pro' ),
159
+ 'vortex' => __('Vortex (PRO)','responsive-menu-pro' ),
160
+ 'vortex-r' => __('Vortex Reverse (PRO)','responsive-menu-pro' )
161
+ );
162
+
163
+ $type = apply_filters('rmp_button_animation_type', $type );
164
+
165
+ return $type;
166
+ }
167
+
168
+
169
+ /**
170
+ * List of all available DashIcon classes.
171
+ *
172
+ * @since 1.0
173
+ * @return array - Sorted list of icon classes
174
+ */
175
+ function rmp_all_dash_icons() {
176
+
177
+ $icons = array(
178
+ 'dash-f333' => 'dashicons-menu',
179
+ 'dash-f319' => 'dashicons-admin-site',
180
+ 'dash-f226' => 'dashicons-dashboard',
181
+ 'dash-f109' => 'dashicons-admin-post',
182
+ 'dash-f104' => 'dashicons-admin-media',
183
+ 'dash-f103' => 'dashicons-admin-links',
184
+ 'dash-f105' => 'dashicons-admin-page',
185
+ 'dash-f101' => 'dashicons-admin-comments',
186
+ 'dash-f100' => 'dashicons-admin-appearance',
187
+ 'dash-f106' => 'dashicons-admin-plugins',
188
+ 'dash-f110' => 'dashicons-admin-users',
189
+ 'dash-f107' => 'dashicons-admin-tools',
190
+ 'dash-f108' => 'dashicons-admin-settings',
191
+ 'dash-f112' => 'dashicons-admin-network',
192
+ 'dash-f102' => 'dashicons-admin-home',
193
+ 'dash-f111' => 'dashicons-admin-generic',
194
+ 'dash-f148' => 'dashicons-admin-collapse',
195
+ 'dash-f536' => 'dashicons-filter',
196
+ 'dash-f540' => 'dashicons-admin-editor',
197
+ 'dash-f541' => 'dashicons-admin-multisite',
198
+ 'dash-f119' => 'dashicons-welcome-write-blog',
199
+ 'dash-f133' => 'dashicons-welcome-add-page',
200
+ 'dash-f115' => 'dashicons-welcome-view-site',
201
+ 'dash-f116' => 'dashicons-welcome-widgets-menus',
202
+ 'dash-f117' => 'dashicons-welcome-comments',
203
+ 'dash-f118' => 'dashicons-welcome-learn-more',
204
+ 'dash-f123' => 'dashicons-format-aside',
205
+ 'dash-f128' => 'dashicons-format-image',
206
+ 'dash-f161' => 'dashicons-format-gallery',
207
+ 'dash-f126' => 'dashicons-format-video',
208
+ 'dash-f130' => 'dashicons-format-status',
209
+ 'dash-f122' => 'dashicons-format-quote',
210
+ 'dash-f125' => 'dashicons-format-chat',
211
+ 'dash-f127' => 'dashicons-format-audio',
212
+ 'dash-f306' => 'dashicons-camera',
213
+ 'dash-f232' => 'dashicons-images-alt',
214
+ 'dash-f233' => 'dashicons-images-alt2',
215
+ 'dash-f234' => 'dashicons-video-alt',
216
+ 'dash-f235' => 'dashicons-video-alt2',
217
+ 'dash-f236' => 'dashicons-video-alt3',
218
+ 'dash-f501' => 'dashicons-media-archive',
219
+ 'dash-f500' => 'dashicons-media-audio',
220
+ 'dash-f499' => 'dashicons-media-code',
221
+ 'dash-f498' => 'dashicons-media-default',
222
+ 'dash-f497' => 'dashicons-media-document',
223
+ 'dash-f496' => 'dashicons-media-interactive',
224
+ 'dash-f495' => 'dashicons-media-spreadsheet',
225
+ 'dash-f491' => 'dashicons-media-text',
226
+ 'dash-f490' => 'dashicons-media-video',
227
+ 'dash-f492' => 'dashicons-playlist-audio',
228
+ 'dash-f493' => 'dashicons-playlist-video',
229
+ 'dash-f522' => 'dashicons-controls-play',
230
+ 'dash-f523' => 'dashicons-controls-pause',
231
+ 'dash-f519' => 'dashicons-controls-forward',
232
+ 'dash-f517' => 'dashicons-controls-skipforward',
233
+ 'dash-f518' => 'dashicons-controls-back',
234
+ 'dash-f516' => 'dashicons-controls-skipback',
235
+ 'dash-f515' => 'dashicons-controls-repeat',
236
+ 'dash-f521' => 'dashicons-controls-volumeon',
237
+ 'dash-f520' => 'dashicons-controls-volumeoff',
238
+ 'dash-f165' => 'dashicons-image-crop',
239
+ 'dash-f531' => 'dashicons-image-rotate',
240
+ 'dash-f166' => 'dashicons-image-rotate-left',
241
+ 'dash-f167' => 'dashicons-image-rotate-right',
242
+ 'dash-f168' => 'dashicons-image-flip-vertical',
243
+ 'dash-f169' => 'dashicons-image-flip-horizontal',
244
+ 'dash-f533' => 'dashicons-image-filter',
245
+ 'dash-f171' => 'dashicons-undo',
246
+ 'dash-f172' => 'dashicons-redo',
247
+ 'dash-f200' => 'dashicons-editor-bold',
248
+ 'dash-f201' => 'dashicons-editor-italic',
249
+ 'dash-f203' => 'dashicons-editor-ul',
250
+ 'dash-f204' => 'dashicons-editor-ol',
251
+ 'dash-f205' => 'dashicons-editor-quote',
252
+ 'dash-f206' => 'dashicons-editor-alignleft',
253
+ 'dash-f207' => 'dashicons-editor-aligncenter',
254
+ 'dash-f208' => 'dashicons-editor-alignright',
255
+ 'dash-f209' => 'dashicons-editor-insertmore',
256
+ 'dash-f210' => 'dashicons-editor-spellcheck',
257
+ 'dash-f211' => 'dashicons-editor-expand',
258
+ 'dash-f506' => 'dashicons-editor-contract',
259
+ 'dash-f212' => 'dashicons-editor-kitchensink',
260
+ 'dash-f213' => 'dashicons-editor-underline',
261
+ 'dash-f214' => 'dashicons-editor-justify',
262
+ 'dash-f215' => 'dashicons-editor-textcolor',
263
+ 'dash-f216' => 'dashicons-editor-paste-word',
264
+ 'dash-f217' => 'dashicons-editor-paste-text',
265
+ 'dash-f218' => 'dashicons-editor-removeformatting',
266
+ 'dash-f219' => 'dashicons-editor-video',
267
+ 'dash-f220' => 'dashicons-editor-customchar',
268
+ 'dash-f221' => 'dashicons-editor-outdent',
269
+ 'dash-f222' => 'dashicons-editor-indent',
270
+ 'dash-f223' => 'dashicons-editor-help',
271
+ 'dash-f224' => 'dashicons-editor-strikethrough',
272
+ 'dash-f225' => 'dashicons-editor-unlink',
273
+ 'dash-f320' => 'dashicons-editor-rtl',
274
+ 'dash-f474' => 'dashicons-editor-break',
275
+ 'dash-f475' => 'dashicons-editor-code',
276
+ 'dash-f476' => 'dashicons-editor-paragraph',
277
+ 'dash-f535' => 'dashicons-editor-table',
278
+ 'dash-f135' => 'dashicons-align-left',
279
+ 'dash-f136' => 'dashicons-align-right',
280
+ 'dash-f134' => 'dashicons-align-center',
281
+ 'dash-f138' => 'dashicons-align-none',
282
+ 'dash-f160' => 'dashicons-lock',
283
+ 'dash-f528' => 'dashicons-unlock',
284
+ 'dash-f145' => 'dashicons-calendar',
285
+ 'dash-f508' => 'dashicons-calendar-alt',
286
+ 'dash-f177' => 'dashicons-visibility',
287
+ 'dash-f530' => 'dashicons-hidden',
288
+ 'dash-f173' => 'dashicons-post-status',
289
+ 'dash-f464' => 'dashicons-edit',
290
+ 'dash-f182' => 'dashicons-trash',
291
+ 'dash-f537' => 'dashicons-sticky',
292
+ 'dash-f504' => 'dashicons-external',
293
+ 'dash-f142' => 'dashicons-arrow-up',
294
+ 'dash-f140' => 'dashicons-arrow-down',
295
+ 'dash-f139' => 'dashicons-arrow-right',
296
+ 'dash-f141' => 'dashicons-arrow-left',
297
+ 'dash-f342' => 'dashicons-arrow-up-alt',
298
+ 'dash-f346' => 'dashicons-arrow-down-alt',
299
+ 'dash-f344' => 'dashicons-arrow-right-alt',
300
+ 'dash-f340' => 'dashicons-arrow-left-alt',
301
+ 'dash-f343' => 'dashicons-arrow-up-alt2',
302
+ 'dash-f347' => 'dashicons-arrow-down-alt2',
303
+ 'dash-f345' => 'dashicons-arrow-right-alt2',
304
+ 'dash-f341' => 'dashicons-arrow-left-alt2',
305
+ 'dash-f156' => 'dashicons-sort',
306
+ 'dash-f229' => 'dashicons-leftright',
307
+ 'dash-f503' => 'dashicons-randomize',
308
+ 'dash-f163' => 'dashicons-list-view',
309
+ 'dash-f164' => 'dashicons-exerpt-view',
310
+ 'dash-f509' => 'dashicons-grid-view',
311
+ 'dash-f237' => 'dashicons-share',
312
+ 'dash-f240' => 'dashicons-share-alt',
313
+ 'dash-f242' => 'dashicons-share-alt2',
314
+ 'dash-f301' => 'dashicons-twitter',
315
+ 'dash-f303' => 'dashicons-rss',
316
+ 'dash-f465' => 'dashicons-email',
317
+ 'dash-f466' => 'dashicons-email-alt',
318
+ 'dash-f304' => 'dashicons-facebook',
319
+ 'dash-f305' => 'dashicons-facebook-alt',
320
+ 'dash-f462' => 'dashicons-googleplus',
321
+ 'dash-f325' => 'dashicons-networking',
322
+ 'dash-f308' => 'dashicons-hammer',
323
+ 'dash-f309' => 'dashicons-art',
324
+ 'dash-f310' => 'dashicons-migrate',
325
+ 'dash-f311' => 'dashicons-performance',
326
+ 'dash-f483' => 'dashicons-universal-access',
327
+ 'dash-f507' => 'dashicons-universal-access-alt',
328
+ 'dash-f486' => 'dashicons-tickets',
329
+ 'dash-f484' => 'dashicons-nametag',
330
+ 'dash-f481' => 'dashicons-clipboard',
331
+ 'dash-f487' => 'dashicons-heart',
332
+ 'dash-f488' => 'dashicons-megaphone',
333
+ 'dash-f489' => 'dashicons-schedule',
334
+ 'dash-f120' => 'dashicons-wordpress',
335
+ 'dash-f324' => 'dashicons-wordpress-alt',
336
+ 'dash-f157' => 'dashicons-pressthis',
337
+ 'dash-f463' => 'dashicons-update',
338
+ 'dash-f180' => 'dashicons-screenoptions',
339
+ 'dash-f348' => 'dashicons-info',
340
+ 'dash-f174' => 'dashicons-cart',
341
+ 'dash-f175' => 'dashicons-feedback',
342
+ 'dash-f176' => 'dashicons-cloud',
343
+ 'dash-f326' => 'dashicons-translation',
344
+ 'dash-f323' => 'dashicons-tag',
345
+ 'dash-f318' => 'dashicons-category',
346
+ 'dash-f480' => 'dashicons-archive',
347
+ 'dash-f479' => 'dashicons-tagcloud',
348
+ 'dash-f478' => 'dashicons-text',
349
+ 'dash-f147' => 'dashicons-yes',
350
+ 'dash-f158' => 'dashicons-no',
351
+ 'dash-f335' => 'dashicons-no-alt',
352
+ 'dash-f132' => 'dashicons-plus',
353
+ 'dash-f502' => 'dashicons-plus-alt',
354
+ 'dash-f460' => 'dashicons-minus',
355
+ 'dash-f153' => 'dashicons-dismiss',
356
+ 'dash-f159' => 'dashicons-marker',
357
+ 'dash-f155' => 'dashicons-star-filled',
358
+ 'dash-f459' => 'dashicons-star-half',
359
+ 'dash-f154' => 'dashicons-star-empty',
360
+ 'dash-f227' => 'dashicons-flag',
361
+ 'dash-f534' => 'dashicons-warning',
362
+ 'dash-f230' => 'dashicons-location',
363
+ 'dash-f231' => 'dashicons-location-alt',
364
+ 'dash-f178' => 'dashicons-vault',
365
+ 'dash-f332' => 'dashicons-shield',
366
+ 'dash-f334' => 'dashicons-shield-alt',
367
+ 'dash-f468' => 'dashicons-sos',
368
+ 'dash-f179' => 'dashicons-search',
369
+ 'dash-f181' => 'dashicons-slides',
370
+ 'dash-f183' => 'dashicons-analytics',
371
+ 'dash-f184' => 'dashicons-chart-pie',
372
+ 'dash-f185' => 'dashicons-chart-bar',
373
+ 'dash-f238' => 'dashicons-chart-line',
374
+ 'dash-f239' => 'dashicons-chart-area',
375
+ 'dash-f307' => 'dashicons-groups',
376
+ 'dash-f338' => 'dashicons-businessman',
377
+ 'dash-f336' => 'dashicons-id',
378
+ 'dash-f337' => 'dashicons-id-alt',
379
+ 'dash-f312' => 'dashicons-products',
380
+ 'dash-f313' => 'dashicons-awards',
381
+ 'dash-f314' => 'dashicons-forms',
382
+ 'dash-f473' => 'dashicons-testimonial',
383
+ 'dash-f322' => 'dashicons-portfolio',
384
+ 'dash-f330' => 'dashicons-book',
385
+ 'dash-f331' => 'dashicons-book-alt',
386
+ 'dash-f316' => 'dashicons-download',
387
+ 'dash-f317' => 'dashicons-upload',
388
+ 'dash-f321' => 'dashicons-backup',
389
+ 'dash-f469' => 'dashicons-clock',
390
+ 'dash-f339' => 'dashicons-lightbulb',
391
+ 'dash-f482' => 'dashicons-microphone',
392
+ 'dash-f472' => 'dashicons-desktop',
393
+ 'dash-f471' => 'dashicons-tablet',
394
+ 'dash-f470' => 'dashicons-smartphone',
395
+ 'dash-f525' => 'dashicons-phone',
396
+ 'dash-f510' => 'dashicons-index-card',
397
+ 'dash-f511' => 'dashicons-carrot',
398
+ 'dash-f512' => 'dashicons-building',
399
+ 'dash-f513' => 'dashicons-store',
400
+ 'dash-f514' => 'dashicons-album',
401
+ 'dash-f527' => 'dashicons-palmtree',
402
+ 'dash-f524' => 'dashicons-tickets-alt',
403
+ 'dash-f526' => 'dashicons-money',
404
+ 'dash-f328' => 'dashicons-smiley',
405
+ 'dash-f529' => 'dashicons-thumbs-up',
406
+ 'dash-f542' => 'dashicons-thumbs-down',
407
+ 'dash-f538' => 'dashicons-layout',
408
+ 'dash-f452' => 'dashicons-buddicons-activity',
409
+ 'dash-f477' => 'dashicons-buddicons-bbpress-logo',
410
+ 'dash-f448' => 'dashicons-buddicons-buddypress-logo',
411
+ 'dash-f453' => 'dashicons-buddicons-community',
412
+ 'dash-f449' => 'dashicons-buddicons-forums',
413
+ 'dash-f454' => 'dashicons-buddicons-friends',
414
+ 'dash-f456' => 'dashicons-buddicons-groups',
415
+ 'dash-f457' => 'dashicons-buddicons-pm',
416
+ 'dash-f451' => 'dashicons-buddicons-replies',
417
+ 'dash-f450' => 'dashicons-buddicons-topics',
418
+ 'dash-f455' => 'dashicons-buddicons-tracking',
419
+ 'dash-f12c' => 'dashicons-editor-ol-rtl',
420
+ 'dash-f10c' => 'dashicons-editor-ltr',
421
+ 'dash-f10d' => 'dashicons-tide',
422
+ 'dash-f124' => 'dashicons-rest-api',
423
+ 'dash-f13a' => 'dashicons-code-standards',
424
+ 'dash-f11d' => 'dashicons-admin-site-alt',
425
+ 'dash-f11e' => 'dashicons-admin-site-alt2',
426
+ 'dash-f11f' => 'dashicons-admin-site-alt3',
427
+ 'dash-f228' => 'dashicons-menu-alt',
428
+ 'dash-f329' => 'dashicons-menu-alt2',
429
+ 'dash-f349' => 'dashicons-menu-alt3',
430
+ 'dash-f12d' => 'dashicons-instagram',
431
+ 'dash-f12f' => 'dashicons-businesswoman',
432
+ 'dash-f12e' => 'dashicons-businessperson',
433
+ 'dash-f467' => 'dashicons-email-alt2',
434
+ 'dash-f12a' => 'dashicons-yes-alt',
435
+ 'dash-f129' => 'dashicons-camera-alt',
436
+ 'dash-f485' => 'dashicons-plugins-checked',
437
+ 'dash-f113' => 'dashicons-update-alt',
438
+ 'dash-f121' => 'dashicons-text-page',
439
+ );
440
+
441
+ $icons = apply_filters( "rmp_dashicons", $icons );
442
+
443
+ krsort( $icons );
444
+
445
+ return $icons;
446
+ }
447
+
448
+
449
+ /**
450
+ * List of all available glyphicon classes.
451
+ *
452
+ * @since 1.0
453
+ * @return array - Sorted list of icon classes
454
+ */
455
+ function rmp_all_glyph_icons() {
456
+
457
+
458
+ $glyph = array(
459
+ 'glyph-2a' => 'glyphicon-asterisk',
460
+ 'glyph-2b' => 'glyphicon-plus',
461
+ 'glyph-20ac' => 'glyphicon-eur',
462
+ 'glyph-2212' => 'glyphicon-minus',
463
+ 'glyph-2601' => 'glyphicon-cloud',
464
+ 'glyph-2709' => 'glyphicon-envelope',
465
+ 'glyph-270f' => 'glyphicon-pencil',
466
+ 'glyph-e001' => 'glyphicon-glass',
467
+ 'glyph-e002' => 'glyphicon-music',
468
+ 'glyph-e003' => 'glyphicon-search',
469
+ 'glyph-e005' => 'glyphicon-heart',
470
+ 'glyph-e006' => 'glyphicon-star',
471
+ 'glyph-e007' => 'glyphicon-star-empty',
472
+ 'glyph-e008' => 'glyphicon-user',
473
+ 'glyph-e009' => 'glyphicon-film',
474
+ 'glyph-e010' => 'glyphicon-th-large',
475
+ 'glyph-e011' => 'glyphicon-th',
476
+ 'glyph-e012' => 'glyphicon-th-list',
477
+ 'glyph-e013' => 'glyphicon-ok',
478
+ 'glyph-e014' => 'glyphicon-remove',
479
+ 'glyph-e015' => 'glyphicon-zoom-in',
480
+ 'glyph-e016' => 'glyphicon-zoom-out',
481
+ 'glyph-e017' => 'glyphicon-off',
482
+ 'glyph-e018' => 'glyphicon-signal',
483
+ 'glyph-e019' => 'glyphicon-cog',
484
+ 'glyph-e020' => 'glyphicon-trash',
485
+ 'glyph-e021' => 'glyphicon-home',
486
+ 'glyph-e022' => 'glyphicon-file',
487
+ 'glyph-e023' => 'glyphicon-time',
488
+ 'glyph-e024' => 'glyphicon-road',
489
+ 'glyph-e025' => 'glyphicon-download-alt',
490
+ 'glyph-e026' => 'glyphicon-download',
491
+ 'glyph-e027' => 'glyphicon-upload',
492
+ 'glyph-e028' => 'glyphicon-inbox',
493
+ 'glyph-e029' => 'glyphicon-play-circle',
494
+ 'glyph-e030' => 'glyphicon-repeat',
495
+ 'glyph-e031' => 'glyphicon-refresh',
496
+ 'glyph-e032' => 'glyphicon-list-alt',
497
+ 'glyph-e033' => 'glyphicon-lock',
498
+ 'glyph-e034' => 'glyphicon-flag',
499
+ 'glyph-e035' => 'glyphicon-headphones',
500
+ 'glyph-e036' => 'glyphicon-volume-off',
501
+ 'glyph-e037' => 'glyphicon-volume-down',
502
+ 'glyph-e038' => 'glyphicon-volume-up',
503
+ 'glyph-e039' => 'glyphicon-qrcode',
504
+ 'glyph-e040' => 'glyphicon-barcode',
505
+ 'glyph-e041' => 'glyphicon-tag',
506
+ 'glyph-e042' => 'glyphicon-tags',
507
+ 'glyph-e043' => 'glyphicon-book',
508
+ 'glyph-e044' => 'glyphicon-bookmark',
509
+ 'glyph-e045' => 'glyphicon-print',
510
+ 'glyph-e046' => 'glyphicon-camera',
511
+ 'glyph-e047' => 'glyphicon-font',
512
+ 'glyph-e048' => 'glyphicon-bold',
513
+ 'glyph-e049' => 'glyphicon-italic',
514
+ 'glyph-e050' => 'glyphicon-text-height',
515
+ 'glyph-e051' => 'glyphicon-text-width',
516
+ 'glyph-e052' => 'glyphicon-align-left',
517
+ 'glyph-e053' => 'glyphicon-align-center',
518
+ 'glyph-e054' => 'glyphicon-align-right',
519
+ 'glyph-e055' => 'glyphicon-align-justify',
520
+ 'glyph-e056' => 'glyphicon-list',
521
+ 'glyph-e057' => 'glyphicon-indent-left',
522
+ 'glyph-e058' => 'glyphicon-indent-right',
523
+ 'glyph-e059' => 'glyphicon-facetime-video',
524
+ 'glyph-e060' => 'glyphicon-picture',
525
+ 'glyph-e062' => 'glyphicon-map-marker',
526
+ 'glyph-e063' => 'glyphicon-adjust',
527
+ 'glyph-e064' => 'glyphicon-tint',
528
+ 'glyph-e065' => 'glyphicon-edit',
529
+ 'glyph-e066' => 'glyphicon-share',
530
+ 'glyph-e067' => 'glyphicon-check',
531
+ 'glyph-e068' => 'glyphicon-move',
532
+ 'glyph-e069' => 'glyphicon-step-backward',
533
+ 'glyph-e070' => 'glyphicon-fast-backward',
534
+ 'glyph-e071' => 'glyphicon-backward',
535
+ 'glyph-e072' => 'glyphicon-play',
536
+ 'glyph-e073' => 'glyphicon-pause',
537
+ 'glyph-e074' => 'glyphicon-stop',
538
+ 'glyph-e075' => 'glyphicon-forward',
539
+ 'glyph-e076' => 'glyphicon-fast-forward',
540
+ 'glyph-e077' => 'glyphicon-step-forward',
541
+ 'glyph-e078' => 'glyphicon-eject',
542
+ 'glyph-e079' => 'glyphicon-chevron-left',
543
+ 'glyph-e080' => 'glyphicon-chevron-right',
544
+ 'glyph-e081' => 'glyphicon-plus-sign',
545
+ 'glyph-e082' => 'glyphicon-minus-sign',
546
+ 'glyph-e083' => 'glyphicon-remove-sign',
547
+ 'glyph-e084' => 'glyphicon-ok-sign',
548
+ 'glyph-e085' => 'glyphicon-question-sign',
549
+ 'glyph-e086' => 'glyphicon-info-sign',
550
+ 'glyph-e087' => 'glyphicon-screenshot',
551
+ 'glyph-e088' => 'glyphicon-remove-circle',
552
+ 'glyph-e089' => 'glyphicon-ok-circle',
553
+ 'glyph-e090' => 'glyphicon-ban-circle',
554
+ 'glyph-e091' => 'glyphicon-arrow-left',
555
+ 'glyph-e092' => 'glyphicon-arrow-right',
556
+ 'glyph-e093' => 'glyphicon-arrow-up',
557
+ 'glyph-e094' => 'glyphicon-arrow-down',
558
+ 'glyph-e095' => 'glyphicon-share-alt',
559
+ 'glyph-e096' => 'glyphicon-resize-full',
560
+ 'glyph-e097' => 'glyphicon-resize-small',
561
+ 'glyph-e101' => 'glyphicon-exclamation-sign',
562
+ 'glyph-e102' => 'glyphicon-gift',
563
+ 'glyph-e103' => 'glyphicon-leaf',
564
+ 'glyph-e104' => 'glyphicon-fire',
565
+ 'glyph-e105' => 'glyphicon-eye-open',
566
+ 'glyph-e106' => 'glyphicon-eye-close',
567
+ 'glyph-e107' => 'glyphicon-warning-sign',
568
+ 'glyph-e108' => 'glyphicon-plane',
569
+ 'glyph-e109' => 'glyphicon-calendar',
570
+ 'glyph-e110' => 'glyphicon-random',
571
+ 'glyph-e111' => 'glyphicon-comment',
572
+ 'glyph-e112' => 'glyphicon-magnet',
573
+ 'glyph-e113' => 'glyphicon-chevron-up',
574
+ 'glyph-e114' => 'glyphicon-chevron-down',
575
+ 'glyph-e115' => 'glyphicon-retweet',
576
+ 'glyph-e116' => 'glyphicon-shopping-cart',
577
+ 'glyph-e117' => 'glyphicon-folder-close',
578
+ 'glyph-e118' => 'glyphicon-folder-open',
579
+ 'glyph-e119' => 'glyphicon-resize-vertical',
580
+ 'glyph-e120' => 'glyphicon-resize-horizontal',
581
+ 'glyph-e121' => 'glyphicon-hdd',
582
+ 'glyph-e122' => 'glyphicon-bullhorn',
583
+ 'glyph-e123' => 'glyphicon-bell',
584
+ 'glyph-e124' => 'glyphicon-certificate',
585
+ 'glyph-e125' => 'glyphicon-thumbs-up',
586
+ 'glyph-e126' => 'glyphicon-thumbs-down',
587
+ 'glyph-e127' => 'glyphicon-hand-right',
588
+ 'glyph-e128' => 'glyphicon-hand-left',
589
+ 'glyph-e129' => 'glyphicon-hand-up',
590
+ 'glyph-e130' => 'glyphicon-hand-down',
591
+ 'glyph-e131' => 'glyphicon-circle-arrow-right',
592
+ 'glyph-e132' => 'glyphicon-circle-arrow-left',
593
+ 'glyph-e133' => 'glyphicon-circle-arrow-up',
594
+ 'glyph-e134' => 'glyphicon-circle-arrow-down',
595
+ 'glyph-e135' => 'glyphicon-globe',
596
+ 'glyph-e136' => 'glyphicon-wrench',
597
+ 'glyph-e137' => 'glyphicon-tasks',
598
+ 'glyph-e138' => 'glyphicon-filter',
599
+ 'glyph-e139' => 'glyphicon-briefcase',
600
+ 'glyph-e140' => 'glyphicon-fullscreen',
601
+ 'glyph-e141' => 'glyphicon-dashboard',
602
+ 'glyph-e142' => 'glyphicon-paperclip',
603
+ 'glyph-e143' => 'glyphicon-heart-empty',
604
+ 'glyph-e144' => 'glyphicon-link',
605
+ 'glyph-e145' => 'glyphicon-phone',
606
+ 'glyph-e146' => 'glyphicon-pushpin',
607
+ 'glyph-e148' => 'glyphicon-usd',
608
+ 'glyph-e149' => 'glyphicon-gbp',
609
+ 'glyph-e150' => 'glyphicon-sort',
610
+ 'glyph-e151' => 'glyphicon-sort-by-alphabet',
611
+ 'glyph-e152' => 'glyphicon-sort-by-alphabet-alt',
612
+ 'glyph-e153' => 'glyphicon-sort-by-order',
613
+ 'glyph-e154' => 'glyphicon-sort-by-order-alt',
614
+ 'glyph-e155' => 'glyphicon-sort-by-attributes',
615
+ 'glyph-e156' => 'glyphicon-sort-by-attributes-alt',
616
+ 'glyph-e157' => 'glyphicon-unchecked',
617
+ 'glyph-e158' => 'glyphicon-expand',
618
+ 'glyph-e159' => 'glyphicon-collapse-down',
619
+ 'glyph-e160' => 'glyphicon-collapse-up',
620
+ 'glyph-e161' => 'glyphicon-log-in',
621
+ 'glyph-e162' => 'glyphicon-flash',
622
+ 'glyph-e163' => 'glyphicon-log-out',
623
+ 'glyph-e164' => 'glyphicon-new-window',
624
+ 'glyph-e165' => 'glyphicon-record',
625
+ 'glyph-e166' => 'glyphicon-save',
626
+ 'glyph-e167' => 'glyphicon-open',
627
+ 'glyph-e168' => 'glyphicon-saved',
628
+ 'glyph-e169' => 'glyphicon-import',
629
+ 'glyph-e170' => 'glyphicon-export',
630
+ 'glyph-e171' => 'glyphicon-send',
631
+ 'glyph-e172' => 'glyphicon-floppy-disk',
632
+ 'glyph-e173' => 'glyphicon-floppy-saved',
633
+ 'glyph-e174' => 'glyphicon-floppy-remove',
634
+ 'glyph-e175' => 'glyphicon-floppy-save',
635
+ 'glyph-e176' => 'glyphicon-floppy-open',
636
+ 'glyph-e177' => 'glyphicon-credit-card',
637
+ 'glyph-e178' => 'glyphicon-transfer',
638
+ 'glyph-e179' => 'glyphicon-cutlery',
639
+ 'glyph-e180' => 'glyphicon-header',
640
+ 'glyph-e181' => 'glyphicon-compressed',
641
+ 'glyph-e182' => 'glyphicon-earphone',
642
+ 'glyph-e183' => 'glyphicon-phone-alt',
643
+ 'glyph-e184' => 'glyphicon-tower',
644
+ 'glyph-e185' => 'glyphicon-stats',
645
+ 'glyph-e186' => 'glyphicon-sd-video',
646
+ 'glyph-e187' => 'glyphicon-hd-video',
647
+ 'glyph-e188' => 'glyphicon-subtitles',
648
+ 'glyph-e189' => 'glyphicon-sound-stereo',
649
+ 'glyph-e190' => 'glyphicon-sound-dolby',
650
+ 'glyph-e191' => 'glyphicon-sound-5-1',
651
+ 'glyph-e192' => 'glyphicon-sound-6-1',
652
+ 'glyph-e193' => 'glyphicon-sound-7-1',
653
+ 'glyph-e194' => 'glyphicon-copyright-mark',
654
+ 'glyph-e195' => 'glyphicon-registration-mark',
655
+ 'glyph-e197' => 'glyphicon-cloud-download',
656
+ 'glyph-e198' => 'glyphicon-cloud-upload',
657
+ 'glyph-e199' => 'glyphicon-tree-conifer',
658
+ 'glyph-e200' => 'glyphicon-tree-deciduous',
659
+ 'glyph-e201' => 'glyphicon-cd',
660
+ 'glyph-e202' => 'glyphicon-save-file',
661
+ 'glyph-e203' => 'glyphicon-open-file',
662
+ 'glyph-e204' => 'glyphicon-level-up',
663
+ 'glyph-e205' => 'glyphicon-copy',
664
+ 'glyph-e206' => 'glyphicon-paste',
665
+ 'glyph-e209' => 'glyphicon-alert',
666
+ 'glyph-e210' => 'glyphicon-equalizer',
667
+ 'glyph-e211' => 'glyphicon-king',
668
+ 'glyph-e212' => 'glyphicon-queen',
669
+ 'glyph-e213' => 'glyphicon-pawn',
670
+ 'glyph-e214' => 'glyphicon-bishop',
671
+ 'glyph-e215' => 'glyphicon-knight',
672
+ 'glyph-e216' => 'glyphicon-baby-formula',
673
+ 'glyph-26fa' => 'glyphicon-tent',
674
+ 'glyph-e218' => 'glyphicon-blackboard',
675
+ 'glyph-e219' => 'glyphicon-bed',
676
+ 'glyph-f8ff' => 'glyphicon-apple',
677
+ 'glyph-e221' => 'glyphicon-erase',
678
+ 'glyph-231b' => 'glyphicon-hourglass',
679
+ 'glyph-e223' => 'glyphicon-lamp',
680
+ 'glyph-e224' => 'glyphicon-duplicate',
681
+ 'glyph-e225' => 'glyphicon-piggy-bank',
682
+ 'glyph-e226' => 'glyphicon-scissors',
683
+ 'glyph-e227' => 'glyphicon-bitcoin',
684
+ 'glyph-0a5' => 'glyphicon-yen',
685
+ 'glyph-20bd' => 'glyphicon-ruble',
686
+ 'glyph-e230' => 'glyphicon-scale',
687
+ 'glyph-e231' => 'glyphicon-ice-lolly',
688
+ 'glyph-e232' => 'glyphicon-ice-lolly-tasted',
689
+ 'glyph-e233' => 'glyphicon-education',
690
+ 'glyph-e234' => 'glyphicon-option-horizontal',
691
+ 'glyph-e235' => 'glyphicon-option-vertical',
692
+ 'glyph-e236' => 'glyphicon-menu-hamburger',
693
+ 'glyph-e237' => 'glyphicon-modal-window',
694
+ 'glyph-e238' => 'glyphicon-oil',
695
+ 'glyph-e239' => 'glyphicon-grain',
696
+ 'glyph-e240' => 'glyphicon-sunglasses',
697
+ 'glyph-e241' => 'glyphicon-text-size',
698
+ 'glyph-e242' => 'glyphicon-text-color',
699
+ 'glyph-e243' => 'glyphicon-text-background',
700
+ 'glyph-e244' => 'glyphicon-object-align-top',
701
+ 'glyph-e245' => 'glyphicon-object-align-bottom',
702
+ 'glyph-e246' => 'glyphicon-object-align-horizontal',
703
+ 'glyph-e247' => 'glyphicon-object-align-left',
704
+ 'glyph-e248' => 'glyphicon-object-align-vertical',
705
+ 'glyph-e249' => 'glyphicon-object-align-right',
706
+ 'glyph-e250' => 'glyphicon-triangle-right',
707
+ 'glyph-e251' => 'glyphicon-triangle-left',
708
+ 'glyph-e252' => 'glyphicon-triangle-bottom',
709
+ 'glyph-e253' => 'glyphicon-triangle-top',
710
+ 'glyph-e254' => 'glyphicon-console',
711
+ 'glyph-e255' => 'glyphicon-superscript',
712
+ 'glyph-e256' => 'glyphicon-subscript',
713
+ 'glyph-e257' => 'glyphicon-menu-left',
714
+ 'glyph-e258' => 'glyphicon-menu-right',
715
+ 'glyph-e259' => 'glyphicon-menu-down',
716
+ 'glyph-e260' => 'glyphicon-menu-up',
717
+ );
718
+
719
+ $glyph = apply_filters( "rmp_glyphicon", $glyph );
720
+ krsort( $glyph );
721
+
722
+ return $glyph;
723
+ }
724
+
725
+
726
+ /**
727
+ * Get default options.
728
+ * @since 4.0.0
729
+ *
730
+ * @return array default_options list of option with default value.
731
+ */
732
+ function rmp_get_default_options() {
733
+
734
+ $default_options = array (
735
+ //Initial Setup -> Device breakpoints
736
+ 'mobile_breakpoint' => 600,
737
+ 'tablet_breakpoint' => 8000,
738
+
739
+ //Initial Setup -> Menu settings
740
+ 'menu_name' => '',
741
+ 'menu_to_use' => '',
742
+ //'current_theme_location' => 'off',
743
+ 'use_desktop_menu' => 'on',
744
+ 'use_mobile_menu' => 'on',
745
+ 'use_tablet_menu' => 'on',
746
+ 'menu_display_on' => 'all-pages',
747
+ 'menu_show_on_pages' => '',
748
+ 'different_menu_for_mobile' => 'off',
749
+ 'menu_to_use_in_mobile' => '',
750
+ 'menu_to_hide' => '',
751
+
752
+ //Container -> Title, Image
753
+ 'menu_title' => '',
754
+ 'menu_title_alignment' => 'left',
755
+ 'menu_title_font_size' => 14,
756
+ 'menu_title_font_size_unit' => 'px',
757
+ 'menu_title_colour' => '#fff',
758
+ 'menu_title_hover_colour' => '#fff',
759
+ 'menu_title_background_colour' => '',
760
+ 'menu_title_background_hover_colour' => '#212121',
761
+ 'menu_title_link' => '#',
762
+ 'menu_title_link_location' => '_self',
763
+ 'menu_title_image_icon' => 'off',
764
+ 'menu_title_font_icon' => null,
765
+ 'menu_title_image' => '',
766
+ 'menu_title_image_alt' => '',
767
+ 'menu_title_image_height' => null,
768
+ 'menu_title_image_height_unit' => 'px',
769
+ 'menu_title_image_width' => null,
770
+ 'menu_title_image_width_unit' => '%',
771
+ 'menu_title_padding' => [
772
+ 'left' => '0px',
773
+ 'top' => '0px',
774
+ 'right' => '0px',
775
+ 'bottom' => '0px'
776
+ ],
777
+ //Container -> Search box
778
+ 'menu_search_box_text' => 'Search',
779
+ 'menu_search_box_text_colour' => '#333',
780
+ 'menu_search_box_border_colour' => '#dadada',
781
+ 'menu_search_box_background_colour' => '#fff',
782
+ 'menu_search_box_placeholder_colour' => '#c7c7cd',
783
+ 'menu_search_box_height' => '50',
784
+ 'menu_search_box_height_unit' => 'px',
785
+ 'menu_search_box_border_radius' => '0',
786
+ 'menu_search_section_padding' => [
787
+ 'left' => '0px',
788
+ 'top' => '0px',
789
+ 'right' => '0px',
790
+ 'bottom' => '0px'
791
+ ],
792
+
793
+ //Container -> Additional
794
+ 'menu_additional_content' => '',
795
+ 'menu_additional_content_colour' => '#fff',
796
+ 'menu_additional_content_font_size' => 16 ,
797
+ 'menu_additional_content_font_size_unit' => 'px',
798
+ 'menu_additional_content_alignment' => 'left',
799
+ 'menu_additional_section_padding' => [
800
+ 'left' => '0px',
801
+ 'top' => '0px',
802
+ 'right' => '0px',
803
+ 'bottom' => '0px'
804
+ ],
805
+ //Container -> Menu
806
+ 'menu_background_colour' => '',
807
+ 'menu_section_padding' => [
808
+ 'left' => '0px',
809
+ 'top' => '0px',
810
+ 'right' => '0px',
811
+ 'bottom' => '0px'
812
+ ],
813
+
814
+ 'menu_depth' => 5,
815
+ 'submenu_descriptions_on' => 'off',
816
+ 'menu_depth_side' => 'left',
817
+ 'menu_depth_0' => 5,
818
+ 'menu_depth_1' => 10,
819
+ 'menu_depth_2' => 15,
820
+ 'menu_depth_3' => 20,
821
+ 'menu_depth_4' => 25,
822
+ 'menu_depth_5' => 30,
823
+ 'menu_depth_0_unit' => '%',
824
+ 'menu_depth_1_unit' => '%',
825
+ 'menu_depth_2_unit' => '%',
826
+ 'menu_depth_3_unit' => '%',
827
+ 'menu_depth_4_unit' => '%',
828
+ 'menu_depth_5_unit' => '%',
829
+ 'theme_location_menu' => '',
830
+ 'custom_walker' => '',
831
+
832
+ // Container > Appearance
833
+ 'menu_width' => 75,
834
+ 'menu_width_unit' => '%',
835
+ 'menu_maximum_width' => '',
836
+ 'menu_maximum_width_unit' => 'px',
837
+ 'menu_minimum_width' => '',
838
+ 'menu_minimum_width_unit' => 'px',
839
+ 'menu_auto_height' => 'off',
840
+ 'menu_container_background_colour' => '#212121',
841
+ 'menu_background_image' => '',
842
+ 'menu_appear_from' => 'left',
843
+ 'animation_type' => 'slide',
844
+ 'page_wrapper' => '',
845
+ 'menu_container_padding' => [
846
+ 'left' => '0px',
847
+ 'top' => '0px',
848
+ 'right' => '0px',
849
+ 'bottom' => '0px'
850
+ ],
851
+
852
+ // Container > Behaviour
853
+ 'menu_close_on_link_click' => 'off',
854
+ 'menu_close_on_body_click' => 'off',
855
+ 'menu_close_on_scroll' => 'off',
856
+ 'enable_touch_gestures' => 'off',
857
+ 'keyboard_shortcut_open_menu' => '',
858
+ 'keyboard_shortcut_close_menu' => '',
859
+
860
+ // Toggle Button > Hamburger Element
861
+ 'button_width' => 55,
862
+ 'button_width_unit' => 'px',
863
+ 'button_height' => 55,
864
+ 'button_height_unit' => 'px',
865
+ 'button_background_colour' => '#000',
866
+ 'button_background_colour_hover' => '#000',
867
+ 'button_background_colour_active' => '#000',
868
+ 'button_transparent_background' => 'off',
869
+
870
+ // Toggle Button > Positioning
871
+ 'button_left_or_right' => 'right',
872
+ 'button_position_type' => 'fixed',
873
+ 'button_top' => 15,
874
+ 'button_top_unit' => 'px',
875
+ 'button_distance_from_side' => 5,
876
+ 'button_distance_from_side_unit' => '%',
877
+ 'button_push_with_animation' => 'off',
878
+
879
+
880
+ // Toggle BUtton > Hamburger Type
881
+ 'button_click_animation' => 'boring',
882
+ 'button_line_colour' => '#fff',
883
+ 'button_line_colour_hover' => '#fff',
884
+ 'button_line_colour_active' => '#fff',
885
+ 'button_line_margin' => 5,
886
+ 'button_line_margin_unit' => 'px',
887
+ 'button_line_height' => 3,
888
+ 'button_line_height_unit' => 'px',
889
+ 'button_line_width' => 25,
890
+ 'button_line_width_unit' => 'px',
891
+
892
+
893
+ // Toggle BUtton > Title
894
+ 'button_title' => '',
895
+ 'button_title_open' => '',
896
+ 'button_text_colour' => '#fff',
897
+ 'button_font_size' => 14,
898
+ 'button_font_size_unit' => 'px',
899
+ 'button_title_position' => 'left',
900
+ 'button_title_line_height' => '13',
901
+ 'button_title_line_height_unit' => 'px',
902
+ 'button_font' => null,
903
+
904
+ // Toggle BUtton > Image
905
+ 'button_image' => null,
906
+ 'button_image_alt' => null,
907
+ 'button_image_when_clicked' => null,
908
+ 'button_image_alt_when_clicked' => null,
909
+
910
+ // Toggle BUtton > Font-icons
911
+ 'button_font_icon' => null,
912
+ 'button_font_icon_when_clicked' => null,
913
+
914
+ // Toggle Button > Others
915
+ 'button_trigger_type_click' => 'on',
916
+ 'button_trigger_type_hover' => 'off',
917
+ 'button_click_trigger' => '#responsive-menu-pro-button',
918
+
919
+
920
+
921
+ // Dropdown -> Top level Menu -> Item Styling
922
+
923
+ // Animation Settings
924
+
925
+ 'animation_speed' => 0.5,
926
+ 'transition_speed' => 0.5,
927
+ 'sub_menu_speed' => 0.2,
928
+
929
+ // Menu Settings
930
+ 'active_arrow_shape' => '▲',
931
+ 'inactive_arrow_shape' => '▼',
932
+ 'active_arrow_image' => '',
933
+ 'active_arrow_image_alt' => '',
934
+ 'inactive_arrow_image' => '',
935
+ 'inactive_arrow_image_alt' => '',
936
+ 'active_arrow_font_icon' => '',
937
+ 'inactive_arrow_font_icon' => '',
938
+ 'arrow_position' => 'right',
939
+ 'submenu_arrow_width' => '40',
940
+ 'submenu_arrow_width_unit' => 'px',
941
+ 'submenu_arrow_height' => '39',
942
+ 'submenu_arrow_height_unit' => 'px',
943
+
944
+ 'accordion_animation' => 'off',
945
+ 'auto_expand_all_submenus' => 'off',
946
+ 'auto_expand_current_submenus' => 'off',
947
+
948
+
949
+ 'menu_item_background_colour' => '#212121',
950
+ 'menu_item_background_hover_colour' => '#3f3f3f',
951
+ 'menu_item_border_colour' => '#212121',
952
+ 'menu_item_border_colour_hover' => '#212121',
953
+
954
+ 'menu_current_item_background_colour' => '#212121',
955
+ 'menu_current_item_background_hover_colour' => '#3f3f3f',
956
+ 'menu_current_item_border_colour' => '#212121',
957
+ 'menu_current_item_border_hover_colour' => '#3f3f3f',
958
+
959
+ 'menu_link_colour' => '#fff',
960
+ 'menu_link_hover_colour' => '#fff',
961
+ 'menu_current_link_colour' => '#fff',
962
+ 'menu_current_link_hover_colour' => '#fff',
963
+ 'menu_sub_arrow_border_width' => '0',
964
+ 'menu_sub_arrow_border_width_unit' => 'px',
965
+ 'menu_sub_arrow_border_colour' => '#212121',
966
+ 'menu_sub_arrow_border_hover_colour' => '#3f3f3f',
967
+ 'menu_sub_arrow_border_colour_active' => '#212121',
968
+ 'menu_sub_arrow_border_hover_colour_active' => '#3f3f3f',
969
+ 'menu_sub_arrow_background_colour' => '#212121',
970
+ 'menu_sub_arrow_background_hover_colour' => '#3f3f3f',
971
+ 'menu_sub_arrow_background_colour_active' => '#212121',
972
+ 'menu_sub_arrow_background_hover_colour_active' => '#3f3f3f',
973
+ 'menu_sub_arrow_shape_colour' => '#fff',
974
+ 'menu_sub_arrow_shape_hover_colour' => '#fff',
975
+ 'menu_sub_arrow_shape_colour_active' => '#fff',
976
+ 'menu_sub_arrow_shape_hover_colour_active' => '#fff',
977
+
978
+ // Sub Menus > Styling
979
+ 'submenu_font' => null,
980
+ 'submenu_font_size' => 13,
981
+ 'submenu_font_size_unit' => 'px',
982
+ 'submenu_links_height' => 40,
983
+ 'submenu_links_height_unit' => 'px',
984
+ 'submenu_links_line_height' => 40,
985
+ 'submenu_links_line_height_unit' => 'px',
986
+ 'submenu_text_alignment' => 'left',
987
+
988
+ // Sub Menus > Item Borders
989
+ 'submenu_border_width' => 0,
990
+ 'submenu_border_width_unit' => 'px',
991
+ 'submenu_item_border_colour' => '#212121',
992
+ 'submenu_item_border_colour_hover' => '#212121',
993
+ 'submenu_current_item_border_colour' => '#212121',
994
+ 'submenu_current_item_border_hover_colour' => '#3f3f3f',
995
+
996
+ // Sub Menus > Item Text
997
+ 'submenu_link_colour' => '#fff',
998
+ 'submenu_link_hover_colour' => '#fff',
999
+ 'submenu_current_link_colour' => '#fff',
1000
+ 'submenu_current_link_hover_colour' => '#fff',
1001
+
1002
+ // Sub Menus > Item Background
1003
+ 'submenu_item_background_colour' => '#212121',
1004
+ 'submenu_item_background_hover_colour' => '#3f3f3f',
1005
+ 'submenu_current_item_background_colour' => '#212121',
1006
+ 'submenu_current_item_background_hover_colour' => '#3f3f3f',
1007
+
1008
+ // Sub Menus > Trigger Icon
1009
+ 'submenu_arrow_position' => 'right',
1010
+
1011
+ // Sub Menus > Trigger Sizing
1012
+ 'submenu_submenu_arrow_height' => '39',
1013
+ 'submenu_submenu_arrow_height_unit' => 'px',
1014
+ 'submenu_submenu_arrow_width' => '40',
1015
+ 'submenu_submenu_arrow_width_unit' => 'px',
1016
+
1017
+ // Sub Menus > Trigger Colours
1018
+ 'submenu_sub_arrow_shape_colour' => '#fff',
1019
+ 'submenu_sub_arrow_shape_hover_colour' => '#fff',
1020
+ 'submenu_sub_arrow_shape_colour_active' => '#fff',
1021
+ 'submenu_sub_arrow_shape_hover_colour_active' => '#fff',
1022
+
1023
+ // Sub Menus > Trigger Background
1024
+ 'submenu_sub_arrow_background_colour' => '#212121',
1025
+ 'submenu_sub_arrow_background_hover_colour' => '#3f3f3f',
1026
+ 'submenu_sub_arrow_background_colour_active' => '#212121',
1027
+ 'submenu_sub_arrow_background_hover_colour_active' => '#3f3f3f',
1028
+
1029
+ // Sub Menus > Trigger Border
1030
+ 'submenu_sub_arrow_border_width' => '0',
1031
+ 'submenu_sub_arrow_border_width_unit' => 'px',
1032
+ 'submenu_sub_arrow_border_colour' => '#212121',
1033
+ 'submenu_sub_arrow_border_hover_colour' => '#3f3f3f',
1034
+ 'submenu_sub_arrow_border_colour_active' => '#212121',
1035
+ 'submenu_sub_arrow_border_hover_colour_active' => '#3f3f3f',
1036
+
1037
+ 'menu_font' => null,
1038
+ 'menu_font_size' => 13,
1039
+ 'menu_font_size_unit' => 'px',
1040
+
1041
+ 'menu_text_alignment' => 'left',
1042
+ 'menu_links_height' => 40,
1043
+ 'menu_links_height_unit' => 'px',
1044
+ 'menu_links_line_height' => 40,
1045
+ 'menu_links_line_height_unit' => 'px',
1046
+ 'menu_border_width' => 0,
1047
+ 'menu_border_width_unit' => 'px',
1048
+
1049
+
1050
+ // Container > Technical
1051
+
1052
+
1053
+ 'menu_item_click_to_trigger_submenu' => 'off',
1054
+ 'menu_disable_scrolling' => 'off',
1055
+ 'menu_overlay' => 'off',
1056
+ 'menu_overlay_colour' => 'rgba(0,0,0,0.7)',
1057
+ 'menu_font_icons' => '',
1058
+
1059
+ 'menu_word_wrap' => 'off',
1060
+
1061
+ 'desktop_menu_positioning' => 'absolute',
1062
+ 'desktop_menu_hide_and_show' => false,
1063
+ 'desktop_submenu_open_on_click' => false,
1064
+ 'desktop_submenu_open_animation' => '',
1065
+ 'desktop_submenu_open_animation_speed' => '0ms',
1066
+ 'desktop_menu_width' => '',
1067
+ 'desktop_menu_width_unit' => '%',
1068
+ 'desktop_menu_side' => 'left',
1069
+
1070
+ 'use_header_bar' => 'off',
1071
+ 'header_bar_adjust_page' => null,
1072
+ 'header_bar_breakpoint' => '8000',
1073
+ 'header_bar_logo' => null,
1074
+ 'header_bar_logo_height' => null,
1075
+ 'header_bar_logo_height_unit' => 'px',
1076
+ 'header_bar_logo_width' => null,
1077
+ 'header_bar_logo_width_unit' => '%',
1078
+ 'header_bar_logo_alt' => '',
1079
+ 'header_bar_logo_link' => null,
1080
+ 'header_bar_title' => null,
1081
+ 'header_bar_html_content' => null,
1082
+ 'header_bar_height' => '80',
1083
+ 'header_bar_height_unit' => 'px',
1084
+ 'header_bar_font_size' => '14',
1085
+ 'header_bar_font_size_unit' => 'px',
1086
+ 'header_bar_font' => null,
1087
+ 'header_bar_background_color' => '#212121',
1088
+ 'header_bar_text_color' => '#ffffff',
1089
+ 'header_bar_position_type' => 'fixed',
1090
+
1091
+ 'header_bar_items_order' => [
1092
+ 'title' => 'off',
1093
+ 'search' => 'off',
1094
+ 'additional content' => 'off',
1095
+ 'logo' => 'on',
1096
+ 'menu' => 'on'
1097
+ ],
1098
+
1099
+ 'items_order' => [
1100
+ 'title' => 'off',
1101
+ 'menu' => 'on',
1102
+ 'search' => 'on',
1103
+ 'additional content' => 'off'
1104
+ ],
1105
+ // Menu > Animations
1106
+ 'smooth_scroll_on' => 'off',
1107
+ 'smooth_scroll_speed' => 500,
1108
+
1109
+ // Menu > Fade Items In
1110
+ 'fade_submenus' => 'off',
1111
+ 'fade_submenus_side' => 'left',
1112
+ 'fade_submenus_delay' => 100,
1113
+ 'fade_submenus_speed' => 500,
1114
+
1115
+ 'use_slide_effect' => 'off',
1116
+ 'slide_effect_back_to_text' => 'Back',
1117
+
1118
+ 'theme_type' => 'default',
1119
+ 'menu_theme' => null,
1120
+
1121
+ 'menu_display_device' => '',
1122
+ 'menu_display_condition' => '',
1123
+ 'menu_font_weight' => 'normal',
1124
+ 'submenu_font_weight' => 'normal',
1125
+ 'menu_text_letter_spacing' => '0',
1126
+ 'submenu_text_letter_spacing' => '0',
1127
+ );
1128
+
1129
+ return $default_options;
1130
+ }
v4.0.0/inc/traits/trait-singleton.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Singleton trait which implements Singleton pattern in any class in which this trait is used.
4
+ *
5
+ * Using the singleton pattern in WordPress is an easy way to protect against
6
+ * mistakes caused by creating multiple objects or multiple initialization
7
+ * of classes which need to be initialized only once.
8
+ *
9
+ * With complex plugins, there are many cases where multiple copies of
10
+ * the plugin would load, and action hooks would load (and trigger) multiple
11
+ * times.
12
+ *
13
+ * If you're planning on using a global variable, then you should implement
14
+ * this trait. Singletons are a way to safely use globals; they let you
15
+ * access and set the global from anywhere, without risk of collision.
16
+ *
17
+ * If any method in a class needs to be aware of "state", then you should
18
+ * implement this trait in that class.
19
+ *
20
+ * If any method in the class need to "talk" to another or be aware of what
21
+ * another method has done, then you should implement this trait in that class.
22
+ *
23
+ * If you specifically need multiple objects, then use a normal class.
24
+ *
25
+ * @package responsive-menu-pro
26
+ */
27
+
28
+ namespace RMP\Features\Inc\Traits;
29
+
30
+ trait Singleton {
31
+
32
+ /**
33
+ * Protected class constructor to prevent direct object creation
34
+ *
35
+ * This is meant to be overridden in the classes which implement
36
+ * this trait. This is ideal for doing stuff that you only want to
37
+ * do once, such as hooking into actions and filters, etc.
38
+ */
39
+ protected function __construct() {
40
+ }
41
+
42
+ /**
43
+ * Prevent object cloning
44
+ */
45
+ final protected function __clone() {
46
+ }
47
+
48
+ /**
49
+ * This method returns new or existing Singleton instance
50
+ * of the class for which it is called. This method is set
51
+ * as final intentionally, it is not meant to be overridden.
52
+ *
53
+ * @return object Singleton instance of the class.
54
+ */
55
+ final public static function get_instance() {
56
+
57
+ /**
58
+ * Collection of instance.
59
+ *
60
+ * @var array
61
+ */
62
+ static $instance = [];
63
+
64
+ /**
65
+ * If this trait is implemented in a class which has multiple
66
+ * sub-classes then static::$_instance will be overwritten with the most recent
67
+ * sub-class instance. Thanks to late static binding
68
+ * we use get_called_class() to grab the called class name, and store
69
+ * a key=>value pair for each `classname => instance` in self::$_instance
70
+ * for each sub-class.
71
+ */
72
+ $called_class = get_called_class();
73
+
74
+ if ( ! isset( $instance[ $called_class ] ) ) {
75
+
76
+ $instance[ $called_class ] = new $called_class();
77
+
78
+ /**
79
+ * Dependent items can use the RMP_features_singleton_init_{$called_class} hook to execute code
80
+ */
81
+ do_action( sprintf( 'rmp_features_singleton_init_%s', $called_class ) );
82
+
83
+ }
84
+
85
+ return $instance[ $called_class ];
86
+
87
+ }
88
+
89
+ }
v4.0.0/languages/responsive-menu.pot ADDED
@@ -0,0 +1,1546 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2020 responsive-menu
2
+ # This file is distributed under the same license as the responsive-menu package.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: responsive-menu\n"
6
+ "MIME-Version: 1.0\n"
7
+ "Content-Type: text/plain; charset=UTF-8\n"
8
+ "Content-Transfer-Encoding: 8bit\n"
9
+ "X-Poedit-Basepath: ..\n"
10
+ "X-Poedit-KeywordsList: __;_e;_ex:1,2c;_n:1,2;_n_noop:1,2;_nx:1,2,4c;_nx_noop:1,2,3c;_x:1,2c;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c\n"
11
+ "X-Poedit-SearchPath-0: .\n"
12
+ "X-Poedit-SearchPathExcluded-0: *.js\n"
13
+ "X-Poedit-SourceCharset: UTF-8\n"
14
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
15
+
16
+
17
+ #: inc/classes/class-admin.php:279
18
+ msgid "Enter the Menu name !"
19
+ msgstr ""
20
+
21
+ #: inc/classes/class-admin.php:284
22
+ msgid "Select menu to use !"
23
+ msgstr ""
24
+
25
+ #: inc/classes/class-admin.php:358
26
+ msgid "Menu is created successfully"
27
+ msgstr ""
28
+
29
+ #: inc/classes/class-admin.php:361
30
+ msgid "Unable to create new Menu"
31
+ msgstr ""
32
+
33
+ #: inc/classes/class-admin.php:385
34
+ msgid "Please pass menu id as attribute."
35
+ msgstr ""
36
+
37
+ #: inc/classes/class-admin.php:398 inc/classes/class-admin.php:594
38
+ msgid "Shortcode deactivated"
39
+ msgstr ""
40
+
41
+ #: inc/classes/class-admin.php:434 inc/classes/class-admin.php:435
42
+ #: templates/rmp-editor.php:105
43
+ msgid "Settings"
44
+ msgstr ""
45
+
46
+ #: inc/classes/class-admin.php:443 inc/classes/class-admin.php:444
47
+ #: templates/rmp-editor.php:98 templates/rmp-themes.php:17
48
+ msgid "Themes"
49
+ msgstr ""
50
+
51
+ #: inc/classes/class-admin.php:521 inc/classes/class-admin.php:585
52
+ msgid "Customize"
53
+ msgstr ""
54
+
55
+ #: inc/classes/class-admin.php:540
56
+ msgid "Shortcode"
57
+ msgstr ""
58
+
59
+ #: inc/classes/class-admin.php:541
60
+ msgid "Actions"
61
+ msgstr ""
62
+
63
+ #: inc/classes/class-admin.php:542
64
+ msgid "Date"
65
+ msgstr ""
66
+
67
+ #: inc/classes/class-admin.php:610 inc/classes/class-admin.php:612
68
+ #: inc/classes/class-admin.php:626 inc/classes/class-admin.php:627
69
+ #: templates/rmp-settings.php:39
70
+ msgid "Responsive Menu"
71
+ msgstr ""
72
+
73
+ #: inc/classes/class-admin.php:613
74
+ msgid "Parent Menu"
75
+ msgstr ""
76
+
77
+ #: inc/classes/class-admin.php:614
78
+ msgid "Menus"
79
+ msgstr ""
80
+
81
+ #: inc/classes/class-admin.php:615
82
+ msgid "View Menu"
83
+ msgstr ""
84
+
85
+ #: inc/classes/class-admin.php:616
86
+ msgid "Add New Menu"
87
+ msgstr ""
88
+
89
+ #: inc/classes/class-admin.php:617 templates/new-menu-wizard.php:20
90
+ msgid "Create New Menu"
91
+ msgstr ""
92
+
93
+ #: inc/classes/class-admin.php:618
94
+ msgid "Edit Menu"
95
+ msgstr ""
96
+
97
+ #: inc/classes/class-admin.php:619
98
+ msgid "Update Menu"
99
+ msgstr ""
100
+
101
+ #: inc/classes/class-admin.php:620
102
+ msgid "Search Menu"
103
+ msgstr ""
104
+
105
+ #: inc/classes/class-admin.php:621
106
+ msgid "Not Found"
107
+ msgstr ""
108
+
109
+ #: inc/classes/class-admin.php:622
110
+ msgid "Not found in Trash"
111
+ msgstr ""
112
+
113
+ #: inc/classes/class-control-manager.php:1055 templates/rmp-editor.php:528
114
+ msgid "Mobile"
115
+ msgstr ""
116
+
117
+ #: inc/classes/class-control-manager.php:1075 templates/rmp-editor.php:542
118
+ msgid "Tablet"
119
+ msgstr ""
120
+
121
+ #: inc/classes/class-control-manager.php:1095
122
+ msgid "Desktop"
123
+ msgstr ""
124
+
125
+ #: inc/classes/class-control-manager.php:1107
126
+ msgid "Device Visibility"
127
+ msgstr ""
128
+
129
+ #: inc/classes/class-editor-manager.php:63 inc/classes/class-ui-manager.php:71
130
+ msgid "Menu Item ID missing"
131
+ msgstr ""
132
+
133
+ #: inc/classes/class-editor-manager.php:69
134
+ #: inc/classes/class-editor-manager.php:154
135
+ #: inc/classes/class-editor-manager.php:239
136
+ #: inc/classes/class-theme-manager.php:350
137
+ msgid "Menu ID missing !"
138
+ msgstr ""
139
+
140
+ #: inc/classes/class-editor-manager.php:73
141
+ msgid "Unable to get mega menu settings"
142
+ msgstr ""
143
+
144
+ #: inc/classes/class-editor-manager.php:129
145
+ #: inc/classes/class-ui-manager.php:105 inc/classes/class-ui-manager.php:378
146
+ msgid "Success"
147
+ msgstr ""
148
+
149
+ #: inc/classes/class-editor-manager.php:133
150
+ msgid "Menu not found"
151
+ msgstr ""
152
+
153
+ #: inc/classes/class-editor.php:90
154
+ msgid "Close the editor and go back to the previous page"
155
+ msgstr ""
156
+
157
+ #: inc/classes/class-editor.php:121
158
+ msgid "Update"
159
+ msgstr ""
160
+
161
+ #: inc/classes/class-editor.php:134
162
+ msgid "Save as theme"
163
+ msgstr ""
164
+
165
+ #: inc/classes/class-editor.php:141
166
+ msgid "Change theme"
167
+ msgstr ""
168
+
169
+ #: inc/classes/class-editor.php:153
170
+ msgid "Enter mobile preview mode"
171
+ msgstr ""
172
+
173
+ #: inc/classes/class-editor.php:160
174
+ msgid "Enter tablet preview mode"
175
+ msgstr ""
176
+
177
+ #: inc/classes/class-editor.php:167
178
+ msgid "Enter desktop preview mode"
179
+ msgstr ""
180
+
181
+ #: inc/classes/class-theme-manager.php:106
182
+ #: inc/classes/class-theme-manager.php:158
183
+ #: inc/classes/class-theme-manager.php:179
184
+ #: inc/classes/class-theme-manager.php:344
185
+ msgid "Theme Name Missing"
186
+ msgstr ""
187
+
188
+ #: inc/classes/class-theme-manager.php:130
189
+ msgid "Theme applied"
190
+ msgstr ""
191
+
192
+ #: inc/classes/class-theme-manager.php:169
193
+ msgid "Theme deleted"
194
+ msgstr ""
195
+
196
+ #: inc/classes/class-theme-manager.php:474
197
+ msgid "<h2>Coming soon..</h2>"
198
+ msgstr ""
199
+
200
+ #: inc/classes/class-theme-manager.php:480
201
+ msgid "BUY NOW"
202
+ msgstr ""
203
+
204
+ #: inc/classes/class-theme-manager.php:481
205
+ msgid "PRO"
206
+ msgstr ""
207
+
208
+ #: inc/classes/class-theme-manager.php:483
209
+ msgid "FREE"
210
+ msgstr ""
211
+
212
+ #: inc/classes/class-theme-manager.php:484
213
+ msgid "INSTALL"
214
+ msgstr ""
215
+
216
+ #: inc/classes/class-ui-manager.php:78
217
+ msgid "Column Sizes Missing !"
218
+ msgstr ""
219
+
220
+ #: inc/classes/class-ui-manager.php:99
221
+ msgid "Column Size Missing !"
222
+ msgstr ""
223
+
224
+ #: inc/classes/class-ui-manager.php:364
225
+ msgid "Menu ID is missing !"
226
+ msgstr ""
227
+
228
+ #: inc/classes/class-ui-manager.php:372
229
+ msgid "Menu item ID is missing !"
230
+ msgstr ""
231
+
232
+ #: inc/classes/class-ui-manager.php:397
233
+ msgid "Select Structure"
234
+ msgstr ""
235
+
236
+ #: inc/classes/class-ui-manager.php:484
237
+ msgid "Column Padding"
238
+ msgstr ""
239
+
240
+ #: inc/classes/class-ui-manager.php:495 inc/classes/class-ui-manager.php:730
241
+ #: templates/rmp-editor.php:242 templates/rmp-editor.php:457
242
+ #: templates/rmp-editor.php:1212 templates/rmp-editor.php:1447
243
+ #: templates/rmp-editor.php:1911 templates/rmp-editor.php:2191
244
+ #: templates/menu-elements/search.php:40
245
+ msgid "Background Color"
246
+ msgstr ""
247
+
248
+ #: inc/classes/class-ui-manager.php:503 templates/rmp-editor.php:1227
249
+ #: templates/rmp-editor.php:2202
250
+ msgid "Background Hover"
251
+ msgstr ""
252
+
253
+ #: inc/classes/class-ui-manager.php:715
254
+ msgid "Panel Width"
255
+ msgstr ""
256
+
257
+ #: inc/classes/class-ui-manager.php:738 templates/rmp-editor.php:2782
258
+ msgid "Background Image"
259
+ msgstr ""
260
+
261
+ #: inc/classes/class-ui-manager.php:748
262
+ msgid "Panel Padding"
263
+ msgstr ""
264
+
265
+ #: inc/classes/class-ui-manager.php:759
266
+ msgid "Sync live preview.."
267
+ msgstr ""
268
+
269
+ #: inc/classes/class-widget-manager.php:114
270
+ #: inc/classes/class-widget-manager.php:177
271
+ msgid "Widget Id is missing"
272
+ msgstr ""
273
+
274
+ #: inc/classes/class-widget-manager.php:121
275
+ msgid "Base Id is missing"
276
+ msgstr ""
277
+
278
+ #: inc/classes/class-widget-manager.php:128
279
+ #, php-format
280
+ msgid "Saved %s"
281
+ msgstr ""
282
+
283
+ #: inc/classes/class-widget-manager.php:130
284
+ #, php-format
285
+ msgid "Failed to save %s"
286
+ msgstr ""
287
+
288
+ #: inc/classes/class-widget-manager.php:186
289
+ #, php-format
290
+ msgid "Failed to edit %s"
291
+ msgstr ""
292
+
293
+ #: inc/classes/class-widget-manager.php:207
294
+ #, php-format
295
+ msgid "Deleted %s"
296
+ msgstr ""
297
+
298
+ #: inc/classes/class-widget-manager.php:314
299
+ msgid "Delete"
300
+ msgstr ""
301
+
302
+ #: inc/classes/class-widget-manager.php:315
303
+ msgid "Done"
304
+ msgstr ""
305
+
306
+ #: inc/classes/class-widget-manager.php:318
307
+ msgid "Save"
308
+ msgstr ""
309
+
310
+ #: inc/classes/class-widget-manager.php:343
311
+ msgid "Widget parameter is missing"
312
+ msgstr ""
313
+
314
+ #: inc/classes/class-widget-manager.php:352
315
+ #, php-format
316
+ msgid "Failed to add %s to %d"
317
+ msgstr ""
318
+
319
+ #: inc/classes/class-widget-manager.php:505
320
+ msgid "Responsive Mega Menu Widgets"
321
+ msgstr ""
322
+
323
+ #: inc/classes/class-widget-manager.php:506
324
+ msgid ""
325
+ "Here it stored all the widgets of responsive mega menu so please add the "
326
+ "widgets from menu"
327
+ msgstr ""
328
+
329
+ #: inc/helpers/default-options.php:133
330
+ msgid "Off"
331
+ msgstr ""
332
+
333
+ #: inc/helpers/default-options.php:134
334
+ msgid "Boring"
335
+ msgstr ""
336
+
337
+ #: inc/helpers/default-options.php:135
338
+ msgid "3DX"
339
+ msgstr ""
340
+
341
+ #: inc/helpers/default-options.php:136
342
+ msgid "3DX Reverse"
343
+ msgstr ""
344
+
345
+ #: inc/helpers/default-options.php:137
346
+ msgid "3DY"
347
+ msgstr ""
348
+
349
+ #: inc/helpers/default-options.php:138
350
+ msgid "3DY Reverse"
351
+ msgstr ""
352
+
353
+ #: inc/helpers/default-options.php:139
354
+ msgid "Arrow"
355
+ msgstr ""
356
+
357
+ #: inc/helpers/default-options.php:140
358
+ msgid "Arrow Reverse"
359
+ msgstr ""
360
+
361
+ #: inc/helpers/default-options.php:141
362
+ msgid "Arrow Alt"
363
+ msgstr ""
364
+
365
+ #: inc/helpers/default-options.php:142
366
+ msgid "Arrow Alt Reverse"
367
+ msgstr ""
368
+
369
+ #: inc/license/Check.php:232
370
+ #, php-format
371
+ msgid ""
372
+ "There is a new version of %1$s available. %2$sView version %3$s details%4$s."
373
+ msgstr ""
374
+
375
+ #: inc/license/Check.php:240
376
+ #, php-format
377
+ msgid ""
378
+ "There is a new version of %1$s available. %2$sView version %3$s details%4$s "
379
+ "or %5$supdate now%6$s."
380
+ msgstr ""
381
+
382
+ #: inc/license/Check.php:473
383
+ msgid "You do not have permission to install plugin updates"
384
+ msgstr ""
385
+
386
+ #: inc/license/Check.php:473
387
+ msgid "Error"
388
+ msgstr ""
389
+
390
+ #: templates/icon-dialog.php:18
391
+ msgid "Select icon"
392
+ msgstr ""
393
+
394
+ #: templates/icon-dialog.php:24
395
+ msgid "Dashicons"
396
+ msgstr ""
397
+
398
+ #: templates/icon-dialog.php:25
399
+ msgid "Material Icons (mdi)"
400
+ msgstr ""
401
+
402
+ #: templates/icon-dialog.php:26
403
+ msgid "FontAwesome Solid (fas)"
404
+ msgstr ""
405
+
406
+ #: templates/icon-dialog.php:27
407
+ msgid "FontAwesome Brand (fab)"
408
+ msgstr ""
409
+
410
+ #: templates/icon-dialog.php:28
411
+ msgid "FontAwesome Regular (far)"
412
+ msgstr ""
413
+
414
+ #: templates/icon-dialog.php:29
415
+ msgid "GlyphIcon"
416
+ msgstr ""
417
+
418
+ #: templates/icon-dialog.php:30
419
+ msgid "Custom"
420
+ msgstr ""
421
+
422
+ #: templates/icon-dialog.php:86
423
+ msgid "Use theme"
424
+ msgstr ""
425
+
426
+ #: templates/icon-dialog.php:93 templates/new-menu-wizard.php:158
427
+ msgid "Premium"
428
+ msgstr ""
429
+
430
+ #: templates/icon-dialog.php:94 templates/new-menu-wizard.php:157
431
+ msgid "My Downloads"
432
+ msgstr ""
433
+
434
+ #: templates/icon-dialog.php:95 templates/new-menu-wizard.php:159
435
+ msgid "Templates"
436
+ msgstr ""
437
+
438
+ #: templates/new-menu-wizard.php:30
439
+ msgid "Menu Setting"
440
+ msgstr ""
441
+
442
+ #: templates/new-menu-wizard.php:31
443
+ msgid "Fill menu settings and show/hide as per preferences"
444
+ msgstr ""
445
+
446
+ #: templates/new-menu-wizard.php:42
447
+ msgid "Select Themes"
448
+ msgstr ""
449
+
450
+ #: templates/new-menu-wizard.php:43
451
+ msgid "Use pre-made theme to speed up the things."
452
+ msgstr ""
453
+
454
+ #: templates/new-menu-wizard.php:52
455
+ msgid "Enter Menu Name"
456
+ msgstr ""
457
+
458
+ #: templates/new-menu-wizard.php:56
459
+ msgid "Menu to Use"
460
+ msgstr ""
461
+
462
+ #: templates/new-menu-wizard.php:126
463
+ msgid "Display Condition"
464
+ msgstr ""
465
+
466
+ #: templates/new-menu-wizard.php:130 templates/rmp-editor.php:950
467
+ msgid "Show on all pages "
468
+ msgstr ""
469
+
470
+ #: templates/new-menu-wizard.php:131 templates/rmp-editor.php:951
471
+ msgid "Exclude some pages "
472
+ msgstr ""
473
+
474
+ #: templates/new-menu-wizard.php:132 templates/rmp-editor.php:952
475
+ msgid "Include only pages "
476
+ msgstr ""
477
+
478
+ #: templates/new-menu-wizard.php:133 templates/rmp-editor.php:953
479
+ msgid "Use as shortcode"
480
+ msgstr ""
481
+
482
+ #: templates/new-menu-wizard.php:215
483
+ msgid "Next"
484
+ msgstr ""
485
+
486
+ #: templates/new-menu-wizard.php:218
487
+ msgid "Create Menu"
488
+ msgstr ""
489
+
490
+ #: templates/rmp-editor.php:51
491
+ msgid "rmp-menu-editor"
492
+ msgstr ""
493
+
494
+ #: templates/rmp-editor.php:69
495
+ msgid "Mobile Menu"
496
+ msgstr ""
497
+
498
+ #: templates/rmp-editor.php:76
499
+ msgid "Desktop Menu"
500
+ msgstr ""
501
+
502
+ #: templates/rmp-editor.php:83
503
+ msgid "Menu Items"
504
+ msgstr ""
505
+
506
+ #: templates/rmp-editor.php:90
507
+ msgid "Header Bar"
508
+ msgstr ""
509
+
510
+ #: templates/rmp-editor.php:115
511
+ msgid "Theme options"
512
+ msgstr ""
513
+
514
+ #: templates/rmp-editor.php:131
515
+ msgid "Save As Theme"
516
+ msgstr ""
517
+
518
+ #: templates/rmp-editor.php:140
519
+ msgid "Change Theme"
520
+ msgstr ""
521
+
522
+ #: templates/rmp-editor.php:158 templates/rmp-editor.php:885
523
+ msgid "Theme Location"
524
+ msgstr ""
525
+
526
+ #: templates/rmp-editor.php:166
527
+ msgid "Menu from location"
528
+ msgstr ""
529
+
530
+ #: templates/rmp-editor.php:169
531
+ msgid ""
532
+ "If you want to use a theme location menu rather than a specific menu then "
533
+ "you can select that here."
534
+ msgstr ""
535
+
536
+ #: templates/rmp-editor.php:180
537
+ msgid "Sub Level Menu Trigger"
538
+ msgstr ""
539
+
540
+ #: templates/rmp-editor.php:187 templates/rmp-editor.php:675
541
+ #: templates/rmp-editor.php:1775 templates/rmp-editor.php:2707
542
+ msgid "Width"
543
+ msgstr ""
544
+
545
+ #: templates/rmp-editor.php:208 templates/rmp-editor.php:408
546
+ #: templates/rmp-editor.php:1796
547
+ msgid "Height"
548
+ msgstr ""
549
+
550
+ #: templates/rmp-editor.php:229 templates/rmp-editor.php:692
551
+ #: templates/rmp-editor.php:1818 templates/rmp-editor.php:2257
552
+ msgid "Position"
553
+ msgstr ""
554
+
555
+ #: templates/rmp-editor.php:247 templates/rmp-editor.php:287
556
+ #: templates/rmp-editor.php:326 templates/rmp-editor.php:1176
557
+ #: templates/rmp-editor.php:1279 templates/rmp-editor.php:1451
558
+ #: templates/rmp-editor.php:1510 templates/rmp-editor.php:1836
559
+ #: templates/rmp-editor.php:1876 templates/rmp-editor.php:1916
560
+ msgid "Normal"
561
+ msgstr ""
562
+
563
+ #: templates/rmp-editor.php:255 templates/rmp-editor.php:295
564
+ #: templates/rmp-editor.php:334 templates/rmp-editor.php:1184
565
+ #: templates/rmp-editor.php:1287 templates/rmp-editor.php:1460
566
+ #: templates/rmp-editor.php:1518 templates/rmp-editor.php:1844
567
+ #: templates/rmp-editor.php:1884 templates/rmp-editor.php:1924
568
+ msgid "Hover"
569
+ msgstr ""
570
+
571
+ #: templates/rmp-editor.php:263 templates/rmp-editor.php:303
572
+ #: templates/rmp-editor.php:342 templates/rmp-editor.php:1193
573
+ #: templates/rmp-editor.php:1295 templates/rmp-editor.php:1469
574
+ #: templates/rmp-editor.php:1526 templates/rmp-editor.php:1852
575
+ #: templates/rmp-editor.php:1892 templates/rmp-editor.php:1932
576
+ msgid "Active Item"
577
+ msgstr ""
578
+
579
+ #: templates/rmp-editor.php:271 templates/rmp-editor.php:311
580
+ #: templates/rmp-editor.php:350 templates/rmp-editor.php:1201
581
+ #: templates/rmp-editor.php:1303 templates/rmp-editor.php:1477
582
+ #: templates/rmp-editor.php:1534 templates/rmp-editor.php:1634
583
+ #: templates/rmp-editor.php:1860 templates/rmp-editor.php:1900
584
+ #: templates/rmp-editor.php:1940
585
+ msgid "Active Item Hover"
586
+ msgstr ""
587
+
588
+ #: templates/rmp-editor.php:282 templates/rmp-editor.php:1871
589
+ #: templates/menu-elements/search.php:49
590
+ msgid "Border Color"
591
+ msgstr ""
592
+
593
+ #: templates/rmp-editor.php:321
594
+ msgid "Arrow Text Color"
595
+ msgstr ""
596
+
597
+ #: templates/rmp-editor.php:386
598
+ msgid "Enable Header Bar"
599
+ msgstr ""
600
+
601
+ #: templates/rmp-editor.php:390 templates/rmp-editor.php:1985
602
+ msgid "Enabled"
603
+ msgstr ""
604
+
605
+ #: templates/rmp-editor.php:394
606
+ msgid ""
607
+ "Turning this on will make the Header Bar show on your site automatically."
608
+ msgstr ""
609
+
610
+ #: templates/rmp-editor.php:403 templates/rmp-editor.php:2702
611
+ msgid "Appearance"
612
+ msgstr ""
613
+
614
+ #: templates/rmp-editor.php:424 templates/rmp-editor.php:1116
615
+ #: templates/rmp-editor.php:1568 templates/rmp-editor.php:2582
616
+ msgid "Font Family"
617
+ msgstr ""
618
+
619
+ #: templates/rmp-editor.php:426 templates/rmp-editor.php:2585
620
+ msgid "Enter font"
621
+ msgstr ""
622
+
623
+ #: templates/rmp-editor.php:433 templates/rmp-editor.php:1096
624
+ #: templates/rmp-editor.php:1551 templates/rmp-editor.php:2593
625
+ #: templates/menu-elements/additional-content.php:32
626
+ #: templates/menu-elements/title.php:79
627
+ msgid "Font Size"
628
+ msgstr ""
629
+
630
+ #: templates/rmp-editor.php:450 templates/rmp-editor.php:1170
631
+ #: templates/rmp-editor.php:1606 templates/rmp-editor.php:1831
632
+ #: templates/rmp-editor.php:2629
633
+ #: templates/menu-elements/additional-content.php:56
634
+ #: templates/menu-elements/search.php:33
635
+ msgid "Text Color"
636
+ msgstr ""
637
+
638
+ #: templates/rmp-editor.php:468
639
+ msgid "Advance Settings"
640
+ msgstr ""
641
+
642
+ #: templates/rmp-editor.php:474 templates/rmp-editor.php:2127
643
+ msgid "Breakpoint"
644
+ msgstr ""
645
+
646
+ #: templates/rmp-editor.php:480
647
+ msgid "Show the header bar below this screen resolution"
648
+ msgstr ""
649
+
650
+ #: templates/rmp-editor.php:488
651
+ msgid "Positioning"
652
+ msgstr ""
653
+
654
+ #: templates/rmp-editor.php:498
655
+ msgid "Adjust Page"
656
+ msgstr ""
657
+
658
+ #: templates/rmp-editor.php:502
659
+ msgid ""
660
+ "Turning this on will automatically adjust your page to bring the content "
661
+ "down inline with the header bar."
662
+ msgstr ""
663
+
664
+ #: templates/rmp-editor.php:522
665
+ msgid "Device Breakpoints"
666
+ msgstr ""
667
+
668
+ #: templates/rmp-editor.php:534
669
+ msgid "Set the breakpoint below which you want mobile menu"
670
+ msgstr ""
671
+
672
+ #: templates/rmp-editor.php:548
673
+ msgid "Set the breakpoint below which you want tablet menu"
674
+ msgstr ""
675
+
676
+ #: templates/rmp-editor.php:559
677
+ msgid "Animation Speeds"
678
+ msgstr ""
679
+
680
+ #: templates/rmp-editor.php:566
681
+ msgid "Colours"
682
+ msgstr ""
683
+
684
+ #: templates/rmp-editor.php:573
685
+ msgid ""
686
+ "Specify the speed at which colours transition from standard to active or "
687
+ "hover states."
688
+ msgstr ""
689
+
690
+ #: templates/rmp-editor.php:581
691
+ msgid "Sub Menus"
692
+ msgstr ""
693
+
694
+ #: templates/rmp-editor.php:588
695
+ msgid "Specify the speed at which the sub menus transition."
696
+ msgstr ""
697
+
698
+ #: templates/rmp-editor.php:602
699
+ msgid "Technical"
700
+ msgstr ""
701
+
702
+ #: templates/rmp-editor.php:607
703
+ msgid "Trigger Menu on page load"
704
+ msgstr ""
705
+
706
+ #: templates/rmp-editor.php:611
707
+ msgid "The menu will appear in expanded state when the page loads."
708
+ msgstr ""
709
+
710
+ #: templates/rmp-editor.php:620
711
+ msgid "Disable Background Scrolling"
712
+ msgstr ""
713
+
714
+ #: templates/rmp-editor.php:624
715
+ msgid "This will disable the background page scrolling."
716
+ msgstr ""
717
+
718
+ #: templates/rmp-editor.php:635
719
+ msgid "Page Overlay"
720
+ msgstr ""
721
+
722
+ #: templates/rmp-editor.php:638
723
+ msgid "Put a backdrop when menu is active."
724
+ msgstr ""
725
+
726
+ #: templates/rmp-editor.php:643
727
+ msgid "Enable"
728
+ msgstr ""
729
+
730
+ #: templates/rmp-editor.php:652 templates/rmp-editor.php:1610
731
+ msgid "Color"
732
+ msgstr ""
733
+
734
+ #: templates/rmp-editor.php:670
735
+ msgid "General Setup"
736
+ msgstr ""
737
+
738
+ #: templates/rmp-editor.php:700
739
+ msgid "Alignment"
740
+ msgstr ""
741
+
742
+ #: templates/rmp-editor.php:711
743
+ msgid "Dropdown Effect"
744
+ msgstr ""
745
+
746
+ #: templates/rmp-editor.php:725
747
+ msgid "Transition Delay"
748
+ msgstr ""
749
+
750
+ #: templates/rmp-editor.php:736
751
+ msgid "Hide original menu"
752
+ msgstr ""
753
+
754
+ #: templates/rmp-editor.php:739 templates/rmp-editor.php:2844
755
+ msgid "CSS Selector"
756
+ msgstr ""
757
+
758
+ #: templates/rmp-editor.php:745
759
+ msgid "Add a valid CSS selector that contains original theme menu."
760
+ msgstr ""
761
+
762
+ #: templates/rmp-editor.php:753
763
+ msgid "Mega Menu Setup"
764
+ msgstr ""
765
+
766
+ #: templates/rmp-editor.php:765 templates/rmp-editor.php:2069
767
+ #: templates/rmp-editor.php:2856 templates/menu-elements/menu.php:13
768
+ msgid "Behaviour"
769
+ msgstr ""
770
+
771
+ #: templates/rmp-editor.php:770
772
+ msgid "Click to open dropdown"
773
+ msgstr ""
774
+
775
+ #: templates/rmp-editor.php:774
776
+ msgid "Use click event instead of hover event to show dropdowns"
777
+ msgstr ""
778
+
779
+ #: templates/rmp-editor.php:782
780
+ msgid "Hide menu on scroll"
781
+ msgstr ""
782
+
783
+ #: templates/rmp-editor.php:807
784
+ msgid "Container"
785
+ msgstr ""
786
+
787
+ #: templates/rmp-editor.php:816
788
+ msgid "Toggle button"
789
+ msgstr ""
790
+
791
+ #: templates/rmp-editor.php:831
792
+ msgid "General Settings"
793
+ msgstr ""
794
+
795
+ #: templates/rmp-editor.php:840
796
+ msgid "Advanced Settings"
797
+ msgstr ""
798
+
799
+ #: templates/rmp-editor.php:849
800
+ msgid "Legacy Settings"
801
+ msgstr ""
802
+
803
+ #: templates/rmp-editor.php:862
804
+ msgid "Menu Settings"
805
+ msgstr ""
806
+
807
+ #: templates/rmp-editor.php:869
808
+ msgid "Name"
809
+ msgstr ""
810
+
811
+ #: templates/rmp-editor.php:879
812
+ msgid "If no options appear here, make sure you have set them up under"
813
+ msgstr ""
814
+
815
+ #: templates/rmp-editor.php:880
816
+ msgid "Appearance > Menus or"
817
+ msgstr ""
818
+
819
+ #: templates/rmp-editor.php:882
820
+ msgid "here"
821
+ msgstr ""
822
+
823
+ #: templates/rmp-editor.php:883
824
+ msgid "Please note that the"
825
+ msgstr ""
826
+
827
+ #: templates/rmp-editor.php:886
828
+ msgid "option will take precedence over this."
829
+ msgstr ""
830
+
831
+ #: templates/rmp-editor.php:895
832
+ msgid "Choose WP Menu"
833
+ msgstr ""
834
+
835
+ #: templates/rmp-editor.php:924
836
+ msgid " Use different menu for mobile & tablet "
837
+ msgstr ""
838
+
839
+ #: templates/rmp-editor.php:933
840
+ msgid "Mobile & Tablet Menu"
841
+ msgstr ""
842
+
843
+ #: templates/rmp-editor.php:946
844
+ msgid "Display condition"
845
+ msgstr ""
846
+
847
+ #: templates/rmp-editor.php:965
848
+ msgid "Select Pages"
849
+ msgstr ""
850
+
851
+ #: templates/rmp-editor.php:977
852
+ msgid "Hide Theme Menu"
853
+ msgstr ""
854
+
855
+ #: templates/rmp-editor.php:983
856
+ msgid ""
857
+ "To hide your current theme menu you need to put the CSS selector here. Any "
858
+ "legal CSS selection criteria is valid."
859
+ msgstr ""
860
+
861
+ #: templates/rmp-editor.php:998
862
+ msgid "Item Icon"
863
+ msgstr ""
864
+
865
+ #: templates/rmp-editor.php:1006
866
+ msgid "Item Stytling"
867
+ msgstr ""
868
+
869
+ #: templates/rmp-editor.php:1035 templates/rmp-editor.php:1325
870
+ msgid "Item Height"
871
+ msgstr ""
872
+
873
+ #: templates/rmp-editor.php:1053 templates/rmp-editor.php:1343
874
+ #: templates/rmp-editor.php:2418 templates/rmp-editor.php:2610
875
+ msgid "Line Height"
876
+ msgstr ""
877
+
878
+ #: templates/rmp-editor.php:1071
879
+ msgid "Padding"
880
+ msgstr ""
881
+
882
+ #: templates/rmp-editor.php:1091 templates/rmp-editor.php:1547
883
+ msgid "Typography"
884
+ msgstr ""
885
+
886
+ #: templates/rmp-editor.php:1125 templates/rmp-editor.php:1577
887
+ msgid "Font Weight"
888
+ msgstr ""
889
+
890
+ #: templates/rmp-editor.php:1134 templates/rmp-editor.php:1585
891
+ #: templates/menu-elements/additional-content.php:47
892
+ #: templates/menu-elements/title.php:94
893
+ msgid "Text Alignment"
894
+ msgstr ""
895
+
896
+ #: templates/rmp-editor.php:1143 templates/rmp-editor.php:1593
897
+ msgid "Letter Spacing"
898
+ msgstr ""
899
+
900
+ #: templates/rmp-editor.php:1155
901
+ msgid "Word Wrap"
902
+ msgstr ""
903
+
904
+ #: templates/rmp-editor.php:1217
905
+ msgid "Background"
906
+ msgstr ""
907
+
908
+ #: templates/rmp-editor.php:1236
909
+ msgid "Active Item Background"
910
+ msgstr ""
911
+
912
+ #: templates/rmp-editor.php:1244
913
+ msgid "Active Item Background Hover"
914
+ msgstr ""
915
+
916
+ #: templates/rmp-editor.php:1254 templates/rmp-editor.php:1486
917
+ msgid "Border"
918
+ msgstr ""
919
+
920
+ #: templates/rmp-editor.php:1259 templates/rmp-editor.php:1490
921
+ msgid "Border Width"
922
+ msgstr ""
923
+
924
+ #: templates/rmp-editor.php:1363
925
+ msgid "Paddings"
926
+ msgstr ""
927
+
928
+ #: templates/rmp-editor.php:1367 templates/rmp-editor.php:2243
929
+ msgid "Side"
930
+ msgstr ""
931
+
932
+ #: templates/rmp-editor.php:1378
933
+ msgid "Child Level 1"
934
+ msgstr ""
935
+
936
+ #: templates/rmp-editor.php:1395
937
+ msgid "Child Level 2"
938
+ msgstr ""
939
+
940
+ #: templates/rmp-editor.php:1412
941
+ msgid "Child Level 3"
942
+ msgstr ""
943
+
944
+ #: templates/rmp-editor.php:1429
945
+ msgid "Child Level 4"
946
+ msgstr ""
947
+
948
+ #: templates/rmp-editor.php:1619
949
+ msgid "Hover Color"
950
+ msgstr ""
951
+
952
+ #: templates/rmp-editor.php:1627
953
+ msgid "Active Item Color"
954
+ msgstr ""
955
+
956
+ #: templates/rmp-editor.php:1651
957
+ msgid "Trigger Icon"
958
+ msgstr ""
959
+
960
+ #: templates/rmp-editor.php:1686
961
+ msgid "Text Shape"
962
+ msgstr ""
963
+
964
+ #: templates/rmp-editor.php:1695
965
+ msgid "Active Text Shape"
966
+ msgstr ""
967
+
968
+ #: templates/rmp-editor.php:1714 templates/rmp-editor.php:2477
969
+ msgid "Font Icon"
970
+ msgstr ""
971
+
972
+ #: templates/rmp-editor.php:1725 templates/rmp-editor.php:2491
973
+ msgid "Active Font Icon"
974
+ msgstr ""
975
+
976
+ #: templates/rmp-editor.php:1746 templates/rmp-editor.php:2512
977
+ #: templates/header-elements/logo.php:20 templates/menu-elements/title.php:52
978
+ msgid "Image"
979
+ msgstr ""
980
+
981
+ #: templates/rmp-editor.php:1757 templates/rmp-editor.php:2525
982
+ msgid "Active Image"
983
+ msgstr ""
984
+
985
+ #: templates/rmp-editor.php:1955 templates/rmp-editor.php:2366
986
+ #: templates/rmp-editor.php:2795
987
+ msgid "Animation"
988
+ msgstr ""
989
+
990
+ #: templates/rmp-editor.php:1997
991
+ msgid "Appearing Side"
992
+ msgstr ""
993
+
994
+ #: templates/rmp-editor.php:2007
995
+ msgid "Delay"
996
+ msgstr ""
997
+
998
+ #: templates/rmp-editor.php:2019
999
+ msgid "Speed"
1000
+ msgstr ""
1001
+
1002
+ #: templates/rmp-editor.php:2039
1003
+ msgid "Enabled Sliding"
1004
+ msgstr ""
1005
+
1006
+ #: templates/rmp-editor.php:2051
1007
+ msgid "Back Text"
1008
+ msgstr ""
1009
+
1010
+ #: templates/rmp-editor.php:2058
1011
+ msgid ""
1012
+ "You can specify the text used for clicking to get back to the previous level "
1013
+ "when using the slide effect.."
1014
+ msgstr ""
1015
+
1016
+ #: templates/rmp-editor.php:2074
1017
+ msgid "Use Accordion"
1018
+ msgstr ""
1019
+
1020
+ #: templates/rmp-editor.php:2083
1021
+ msgid "Auto Expand All Sub Menus"
1022
+ msgstr ""
1023
+
1024
+ #: templates/rmp-editor.php:2092
1025
+ msgid "Auto Expand Current Sub Menus"
1026
+ msgstr ""
1027
+
1028
+ #: templates/rmp-editor.php:2101
1029
+ msgid "Expand Sub items on Parent Item Click"
1030
+ msgstr ""
1031
+
1032
+ #: templates/rmp-editor.php:2122
1033
+ msgid "Hamburger Breakpoint"
1034
+ msgstr ""
1035
+
1036
+ #: templates/rmp-editor.php:2133
1037
+ msgid "Show the toggle button below this screen resolution."
1038
+ msgstr ""
1039
+
1040
+ #: templates/rmp-editor.php:2144
1041
+ msgid "Button Style"
1042
+ msgstr ""
1043
+
1044
+ #: templates/rmp-editor.php:2151
1045
+ msgid "Container Width"
1046
+ msgstr ""
1047
+
1048
+ #: templates/rmp-editor.php:2168
1049
+ msgid "Container Height"
1050
+ msgstr ""
1051
+
1052
+ #: templates/rmp-editor.php:2212
1053
+ msgid "Active Color"
1054
+ msgstr ""
1055
+
1056
+ #: templates/rmp-editor.php:2220
1057
+ msgid "Transparent Background"
1058
+ msgstr ""
1059
+
1060
+ #: templates/rmp-editor.php:2236
1061
+ msgid "Button Position"
1062
+ msgstr ""
1063
+
1064
+ #: templates/rmp-editor.php:2271
1065
+ msgid "Distance from Side"
1066
+ msgstr ""
1067
+
1068
+ #: templates/rmp-editor.php:2292
1069
+ msgid "Distance from Top"
1070
+ msgstr ""
1071
+
1072
+ #: templates/rmp-editor.php:2314
1073
+ msgid "Push Button with Menu"
1074
+ msgstr ""
1075
+
1076
+ #: templates/rmp-editor.php:2317
1077
+ msgid "The toggle button will slide along with menu container."
1078
+ msgstr ""
1079
+
1080
+ #: templates/rmp-editor.php:2330
1081
+ msgid "Button Type"
1082
+ msgstr ""
1083
+
1084
+ #: templates/rmp-editor.php:2376
1085
+ msgid "Line Spacing"
1086
+ msgstr ""
1087
+
1088
+ #: templates/rmp-editor.php:2398
1089
+ msgid "Line Width"
1090
+ msgstr ""
1091
+
1092
+ #: templates/rmp-editor.php:2441
1093
+ msgid "Line Color"
1094
+ msgstr ""
1095
+
1096
+ #: templates/rmp-editor.php:2449
1097
+ msgid "Line Hover"
1098
+ msgstr ""
1099
+
1100
+ #: templates/rmp-editor.php:2459
1101
+ msgid "Line Active"
1102
+ msgstr ""
1103
+
1104
+ #: templates/rmp-editor.php:2484
1105
+ msgid "Use a custom font icon instead of standard hamburger lines"
1106
+ msgstr ""
1107
+
1108
+ #: templates/rmp-editor.php:2519
1109
+ msgid "Use a custom image instead of standard hamburger lines."
1110
+ msgstr ""
1111
+
1112
+ #: templates/rmp-editor.php:2541
1113
+ msgid "Button Text"
1114
+ msgstr ""
1115
+
1116
+ #: templates/rmp-editor.php:2548
1117
+ msgid "Text"
1118
+ msgstr ""
1119
+
1120
+ #: templates/rmp-editor.php:2551 templates/rmp-editor.php:2563
1121
+ msgid "Enter text"
1122
+ msgstr ""
1123
+
1124
+ #: templates/rmp-editor.php:2555
1125
+ msgid ""
1126
+ "Add text along with hamburger icon/image when button is in active state."
1127
+ msgstr ""
1128
+
1129
+ #: templates/rmp-editor.php:2560
1130
+ msgid "Active Text"
1131
+ msgstr ""
1132
+
1133
+ #: templates/rmp-editor.php:2573
1134
+ msgid "Text Position"
1135
+ msgstr ""
1136
+
1137
+ #: templates/rmp-editor.php:2642
1138
+ msgid "Button Behaviour"
1139
+ msgstr ""
1140
+
1141
+ #: templates/rmp-editor.php:2647
1142
+ msgid "Toggle menu on click"
1143
+ msgstr ""
1144
+
1145
+ #: templates/rmp-editor.php:2655
1146
+ msgid "Toggle menu on hover"
1147
+ msgstr ""
1148
+
1149
+ #: templates/rmp-editor.php:2663
1150
+ msgid "Custom Toggle Selector"
1151
+ msgstr ""
1152
+
1153
+ #: templates/rmp-editor.php:2670
1154
+ msgid ""
1155
+ "If you don't want to use the button that comes with the menu, you can "
1156
+ "specify your own container trigger here. Any CSS selector is accepted."
1157
+ msgstr ""
1158
+
1159
+ #: templates/rmp-editor.php:2713 templates/rmp-editor.php:2731
1160
+ #: templates/rmp-editor.php:2747 templates/header-elements/logo.php:47
1161
+ #: templates/header-elements/logo.php:63
1162
+ msgid "Enter value"
1163
+ msgstr ""
1164
+
1165
+ #: templates/rmp-editor.php:2726
1166
+ msgid "Maximum Width"
1167
+ msgstr ""
1168
+
1169
+ #: templates/rmp-editor.php:2742
1170
+ msgid "Minimum Width"
1171
+ msgstr ""
1172
+
1173
+ #: templates/rmp-editor.php:2760
1174
+ msgid "Auto Height"
1175
+ msgstr ""
1176
+
1177
+ #: templates/rmp-editor.php:2764
1178
+ msgid "Limit container height upto last container element"
1179
+ msgstr ""
1180
+
1181
+ #: templates/rmp-editor.php:2774
1182
+ msgid "Container Background"
1183
+ msgstr ""
1184
+
1185
+ #: templates/rmp-editor.php:2800
1186
+ msgid "Direction"
1187
+ msgstr ""
1188
+
1189
+ #: templates/rmp-editor.php:2803
1190
+ msgid "Set the viewport side for container entry."
1191
+ msgstr ""
1192
+
1193
+ #: templates/rmp-editor.php:2812
1194
+ msgid "Type"
1195
+ msgstr ""
1196
+
1197
+ #: templates/rmp-editor.php:2824
1198
+ msgid "Transition delay"
1199
+ msgstr ""
1200
+
1201
+ #: templates/rmp-editor.php:2830
1202
+ msgid "Control the speed of animation for container entry and exit."
1203
+ msgstr ""
1204
+
1205
+ #: templates/rmp-editor.php:2838
1206
+ msgid "Push Wrapper"
1207
+ msgstr ""
1208
+
1209
+ #: templates/rmp-editor.php:2842
1210
+ msgid ""
1211
+ "Mention the CSS selector of the main element which should be pushed when "
1212
+ "using push animations."
1213
+ msgstr ""
1214
+
1215
+ #: templates/rmp-editor.php:2861
1216
+ msgid "Hide Menu On"
1217
+ msgstr ""
1218
+
1219
+ #: templates/rmp-editor.php:2865
1220
+ msgid "Page Clicks"
1221
+ msgstr ""
1222
+
1223
+ #: templates/rmp-editor.php:2872
1224
+ msgid "Page Scroll"
1225
+ msgstr ""
1226
+
1227
+ #: templates/rmp-editor.php:2879
1228
+ msgid "Link Clicks"
1229
+ msgstr ""
1230
+
1231
+ #: templates/rmp-editor.php:2888
1232
+ msgid "Enable Touch Gestures"
1233
+ msgstr ""
1234
+
1235
+ #: templates/rmp-editor.php:2891
1236
+ msgid ""
1237
+ "This will enable you to drag or swipe to close the container on touch "
1238
+ "devices."
1239
+ msgstr ""
1240
+
1241
+ #: templates/rmp-editor.php:2901
1242
+ msgid "Keyboard Controls"
1243
+ msgstr ""
1244
+
1245
+ #: templates/rmp-editor.php:2903
1246
+ msgid "Select keystrokes to control the menu via keyboard."
1247
+ msgstr ""
1248
+
1249
+ #: templates/rmp-editor.php:2911
1250
+ msgid "Hide Menu"
1251
+ msgstr ""
1252
+
1253
+ #: templates/rmp-editor.php:2922
1254
+ msgid "Show Menu "
1255
+ msgstr ""
1256
+
1257
+ #: templates/rmp-settings.php:44
1258
+ msgid "General"
1259
+ msgstr ""
1260
+
1261
+ #: templates/rmp-settings.php:45
1262
+ msgid "Advance"
1263
+ msgstr ""
1264
+
1265
+ #: templates/rmp-settings.php:46
1266
+ msgid "Style"
1267
+ msgstr ""
1268
+
1269
+ #: templates/rmp-settings.php:52
1270
+ msgid "License Key"
1271
+ msgstr ""
1272
+
1273
+ #: templates/rmp-settings.php:57
1274
+ msgid "Validate"
1275
+ msgstr ""
1276
+
1277
+ #: templates/rmp-settings.php:63
1278
+ msgid ""
1279
+ "Don't panic. The plugin will still function 100%, it is only automatic "
1280
+ "updates that will be affected."
1281
+ msgstr ""
1282
+
1283
+ #: templates/rmp-settings.php:64
1284
+ msgid "You can read about troubleshooting license issues."
1285
+ msgstr ""
1286
+
1287
+ #: templates/rmp-settings.php:76
1288
+ msgid "Rollback Version"
1289
+ msgstr ""
1290
+
1291
+ #: templates/rmp-settings.php:84
1292
+ msgid "Rollback"
1293
+ msgstr ""
1294
+
1295
+ #: templates/rmp-settings.php:86
1296
+ msgid ""
1297
+ "Experiencing an issue with latest version 4.0.0? Rollback to a previous "
1298
+ "version before the issue appeared."
1299
+ msgstr ""
1300
+
1301
+ #: templates/rmp-settings.php:99
1302
+ msgid "Adjust for WP Admin Bar"
1303
+ msgstr ""
1304
+
1305
+ #: templates/rmp-settings.php:104
1306
+ msgid "None"
1307
+ msgstr ""
1308
+
1309
+ #: templates/rmp-settings.php:105
1310
+ msgid "Adjust"
1311
+ msgstr ""
1312
+
1313
+ #: templates/rmp-settings.php:106
1314
+ msgid "Hide"
1315
+ msgstr ""
1316
+
1317
+ #: templates/rmp-settings.php:109
1318
+ msgid ""
1319
+ "If you use the WP Admin bar when logged in, this will help you to adjust the "
1320
+ "admin bar."
1321
+ msgstr ""
1322
+
1323
+ #: templates/rmp-settings.php:117
1324
+ msgid "Use external files"
1325
+ msgstr ""
1326
+
1327
+ #: templates/rmp-settings.php:123
1328
+ msgid ""
1329
+ "Create external files for the CSS and JavaScrips created by this plugin."
1330
+ msgstr ""
1331
+
1332
+ #: templates/rmp-settings.php:131
1333
+ msgid "Minify scripts"
1334
+ msgstr ""
1335
+
1336
+ #: templates/rmp-settings.php:137
1337
+ msgid "Minify the CSS and JavaScrips created by this plugin."
1338
+ msgstr ""
1339
+
1340
+ #: templates/rmp-settings.php:145
1341
+ msgid "Place scripts in footer"
1342
+ msgstr ""
1343
+
1344
+ #: templates/rmp-settings.php:151
1345
+ msgid "Place the JavaScrips created by this plugin in the footer."
1346
+ msgstr ""
1347
+
1348
+ #: templates/rmp-settings.php:159
1349
+ msgid "Remove Dashicons"
1350
+ msgstr ""
1351
+
1352
+ #: templates/rmp-settings.php:165
1353
+ msgid "Stop this plugins dashicons scripts from being load at frontend."
1354
+ msgstr ""
1355
+
1356
+ #: templates/rmp-settings.php:172
1357
+ msgid "Remove FontAwesome Scripts"
1358
+ msgstr ""
1359
+
1360
+ #: templates/rmp-settings.php:178
1361
+ msgid ""
1362
+ "Stop this plugins FontAwesome scripts from being load. Useful if you want to "
1363
+ "run your own FontAwesome version or already have it installed."
1364
+ msgstr ""
1365
+
1366
+ #: templates/rmp-settings.php:185
1367
+ msgid "Remove GlyphIcon Scripts"
1368
+ msgstr ""
1369
+
1370
+ #: templates/rmp-settings.php:191
1371
+ msgid "Stop this plugins GlyphIcon resource from being load at frontend."
1372
+ msgstr ""
1373
+
1374
+ #: templates/rmp-settings.php:198
1375
+ msgid "Remove Material Icons Scripts"
1376
+ msgstr ""
1377
+
1378
+ #: templates/rmp-settings.php:204
1379
+ msgid ""
1380
+ "Stop this plugins Material icons resource from being loaded at frontend."
1381
+ msgstr ""
1382
+
1383
+ #: templates/rmp-settings.php:218
1384
+ msgid "Custom CSS"
1385
+ msgstr ""
1386
+
1387
+ #: templates/rmp-settings.php:221
1388
+ msgid ""
1389
+ "You can place any Custom CSS you want here. Very useful if you want to make "
1390
+ "minor tweaks to some margins, paddings or colours or even for whole new "
1391
+ "layouts or designs."
1392
+ msgstr ""
1393
+
1394
+ #: templates/rmp-settings.php:232
1395
+ msgid "Save Settings"
1396
+ msgstr ""
1397
+
1398
+ #: templates/rmp-themes.php:21
1399
+ msgid "Upload theme"
1400
+ msgstr ""
1401
+
1402
+ #: templates/rmp-themes.php:33
1403
+ msgid "Import Menu Theme To Your Library"
1404
+ msgstr ""
1405
+
1406
+ #: templates/rmp-themes.php:35
1407
+ msgid "Drop zip files here or click to upload."
1408
+ msgstr ""
1409
+
1410
+ #: templates/rmp-themes.php:39
1411
+ msgid "Select Files"
1412
+ msgstr ""
1413
+
1414
+ #: templates/header-elements/additional-content.php:4
1415
+ msgid "HTML Content"
1416
+ msgstr ""
1417
+
1418
+ #: templates/header-elements/additional-content.php:20
1419
+ msgid "Additional Contents"
1420
+ msgstr ""
1421
+
1422
+ #: templates/header-elements/logo.php:4
1423
+ msgid "Logo"
1424
+ msgstr ""
1425
+
1426
+ #: templates/header-elements/logo.php:31
1427
+ msgid "Target Link"
1428
+ msgstr ""
1429
+
1430
+ #: templates/header-elements/logo.php:37
1431
+ msgid "Enter link"
1432
+ msgstr ""
1433
+
1434
+ #: templates/header-elements/logo.php:42 templates/menu-elements/title.php:144
1435
+ msgid "Image Width"
1436
+ msgstr ""
1437
+
1438
+ #: templates/header-elements/logo.php:58 templates/menu-elements/title.php:160
1439
+ msgid "Image Height"
1440
+ msgstr ""
1441
+
1442
+ #: templates/header-elements/menu.php:4 templates/menu-elements/menu.php:3
1443
+ msgid "Menu"
1444
+ msgstr ""
1445
+
1446
+ #: templates/header-elements/search.php:5 templates/menu-elements/search.php:4
1447
+ msgid "Search"
1448
+ msgstr ""
1449
+
1450
+ #: templates/header-elements/title.php:4 templates/menu-elements/title.php:3
1451
+ msgid "Title"
1452
+ msgstr ""
1453
+
1454
+ #: templates/header-elements/title.php:19 templates/menu-elements/title.php:22
1455
+ msgid "Title Text "
1456
+ msgstr ""
1457
+
1458
+ #: templates/menu-elements/additional-content.php:3
1459
+ msgid "Additional Content"
1460
+ msgstr ""
1461
+
1462
+ #: templates/menu-elements/additional-content.php:14
1463
+ #: templates/menu-elements/menu.php:12 templates/menu-elements/search.php:15
1464
+ #: templates/menu-elements/title.php:15
1465
+ msgid "Contents"
1466
+ msgstr ""
1467
+
1468
+ #: templates/menu-elements/additional-content.php:15
1469
+ #: templates/menu-elements/search.php:16 templates/menu-elements/title.php:16
1470
+ msgid "Styles"
1471
+ msgstr ""
1472
+
1473
+ #: templates/menu-elements/menu-item-icons.php:15
1474
+ #: templates/menu-elements/menu-item-icons.php:44
1475
+ msgid "Select Item"
1476
+ msgstr ""
1477
+
1478
+ #: templates/menu-elements/menu-item-icons.php:75
1479
+ msgid "Add Icon"
1480
+ msgstr ""
1481
+
1482
+ #: templates/menu-elements/menu.php:20
1483
+ msgid "Menu Background"
1484
+ msgstr ""
1485
+
1486
+ #: templates/menu-elements/menu.php:28
1487
+ msgid "Depth Level"
1488
+ msgstr ""
1489
+
1490
+ #: templates/menu-elements/menu.php:31
1491
+ msgid "Set the level of nesting for sub menus."
1492
+ msgstr ""
1493
+
1494
+ #: templates/menu-elements/menu.php:44
1495
+ msgid "Item Descriptions"
1496
+ msgstr ""
1497
+
1498
+ #: templates/menu-elements/menu.php:47
1499
+ msgid ""
1500
+ "Show the description text of menu items. Description text should be set "
1501
+ "while creating WordPress menus."
1502
+ msgstr ""
1503
+
1504
+ #: templates/menu-elements/menu.php:59
1505
+ msgid "Custom Walker"
1506
+ msgstr ""
1507
+
1508
+ #: templates/menu-elements/menu.php:64
1509
+ msgid "Modify the HTML output by using a custom Walker class."
1510
+ msgstr ""
1511
+
1512
+ #: templates/menu-elements/menu.php:76
1513
+ msgid "Smooth Scroll Enabled"
1514
+ msgstr ""
1515
+
1516
+ #: templates/menu-elements/menu.php:80
1517
+ msgid "The webpage will scroll smoothly to their target sections on same page."
1518
+ msgstr ""
1519
+
1520
+ #: templates/menu-elements/menu.php:88
1521
+ msgid "Scroll Speed"
1522
+ msgstr ""
1523
+
1524
+ #: templates/menu-elements/search.php:56
1525
+ msgid "Placeholder Color"
1526
+ msgstr ""
1527
+
1528
+ #: templates/menu-elements/title.php:32
1529
+ msgid "Link "
1530
+ msgstr ""
1531
+
1532
+ #: templates/menu-elements/title.php:42
1533
+ msgid "Link Target"
1534
+ msgstr ""
1535
+
1536
+ #: templates/menu-elements/title.php:62
1537
+ msgid "Set Font"
1538
+ msgstr ""
1539
+
1540
+ #: templates/menu-elements/title.php:149
1541
+ msgid "Enter width"
1542
+ msgstr ""
1543
+
1544
+ #: templates/menu-elements/title.php:165
1545
+ msgid "Enter height"
1546
+ msgstr ""
v4.0.0/libs/scssphp/composer.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ {
2
+ "require": {
3
+ "scssphp/scssphp": "^1.1"
4
+ }
5
+ }
v4.0.0/libs/scssphp/composer.lock ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_readme": [
3
+ "This file locks the dependencies of your project to a known state",
4
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5
+ "This file is @generated automatically"
6
+ ],
7
+ "content-hash": "639d6b1231e90f706ba0d28d5e0a622f",
8
+ "packages": [
9
+ {
10
+ "name": "scssphp/scssphp",
11
+ "version": "1.1.0",
12
+ "source": {
13
+ "type": "git",
14
+ "url": "https://github.com/scssphp/scssphp.git",
15
+ "reference": "4363ddce8d750f055c436833dd77d83517946532"
16
+ },
17
+ "dist": {
18
+ "type": "zip",
19
+ "url": "https://api.github.com/repos/scssphp/scssphp/zipball/4363ddce8d750f055c436833dd77d83517946532",
20
+ "reference": "4363ddce8d750f055c436833dd77d83517946532",
21
+ "shasum": ""
22
+ },
23
+ "require": {
24
+ "ext-ctype": "*",
25
+ "ext-json": "*",
26
+ "php": ">=5.6.0"
27
+ },
28
+ "require-dev": {
29
+ "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3",
30
+ "squizlabs/php_codesniffer": "~3.5",
31
+ "twbs/bootstrap": "~4.3",
32
+ "zurb/foundation": "~6.5"
33
+ },
34
+ "bin": [
35
+ "bin/pscss"
36
+ ],
37
+ "type": "library",
38
+ "autoload": {
39
+ "psr-4": {
40
+ "ScssPhp\\ScssPhp\\": "src/"
41
+ }
42
+ },
43
+ "notification-url": "https://packagist.org/downloads/",
44
+ "license": [
45
+ "MIT"
46
+ ],
47
+ "authors": [
48
+ {
49
+ "name": "Anthon Pang",
50
+ "email": "apang@softwaredevelopment.ca",
51
+ "homepage": "https://github.com/robocoder"
52
+ },
53
+ {
54
+ "name": "Cédric Morin",
55
+ "email": "cedric@yterium.com",
56
+ "homepage": "https://github.com/Cerdic"
57
+ }
58
+ ],
59
+ "description": "scssphp is a compiler for SCSS written in PHP.",
60
+ "homepage": "http://scssphp.github.io/scssphp/",
61
+ "keywords": [
62
+ "css",
63
+ "less",
64
+ "sass",
65
+ "scss",
66
+ "stylesheet"
67
+ ],
68
+ "time": "2020-04-21T15:53:32+00:00"
69
+ }
70
+ ],
71
+ "packages-dev": [],
72
+ "aliases": [],
73
+ "minimum-stability": "stable",
74
+ "stability-flags": [],
75
+ "prefer-stable": false,
76
+ "prefer-lowest": false,
77
+ "platform": [],
78
+ "platform-dev": []
79
+ }
v4.0.0/libs/scssphp/vendor/autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload.php @generated by Composer
4
+
5
+ require_once __DIR__ . '/composer/autoload_real.php';
6
+
7
+ return ComposerAutoloaderInit63d42ceb3ded2b5ffe0e0f4c4066ef1c::getLoader();
v4.0.0/libs/scssphp/vendor/bin/pscss ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env sh
2
+
3
+ dir=$(cd "${0%[/\\]*}" > /dev/null; cd "../scssphp/scssphp/bin" && pwd)
4
+
5
+ if [ -d /proc/cygdrive ]; then
6
+ case $(which php) in
7
+ $(readlink -n /proc/cygdrive)/*)
8
+ # We are in Cygwin using Windows php, so the path must be translated
9
+ dir=$(cygpath -m "$dir");
10
+ ;;
11
+ esac
12
+ fi
13
+
14
+ "${dir}/pscss" "$@"
v4.0.0/libs/scssphp/vendor/bin/pscss.bat ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ @ECHO OFF
2
+ setlocal DISABLEDELAYEDEXPANSION
3
+ SET BIN_TARGET=%~dp0/../scssphp/scssphp/bin/pscss
4
+ php "%BIN_TARGET%" %*
v4.0.0/libs/scssphp/vendor/composer/ClassLoader.php ADDED
@@ -0,0 +1,445 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer\Autoload;
14
+
15
+ /**
16
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17
+ *
18
+ * $loader = new \Composer\Autoload\ClassLoader();
19
+ *
20
+ * // register classes with namespaces
21
+ * $loader->add('Symfony\Component', __DIR__.'/component');
22
+ * $loader->add('Symfony', __DIR__.'/framework');
23
+ *
24
+ * // activate the autoloader
25
+ * $loader->register();
26
+ *
27
+ * // to enable searching the include path (eg. for PEAR packages)
28
+ * $loader->setUseIncludePath(true);
29
+ *
30
+ * In this example, if you try to use a class in the Symfony\Component
31
+ * namespace or one of its children (Symfony\Component\Console for instance),
32
+ * the autoloader will first look for the class under the component/
33
+ * directory, and it will then fallback to the framework/ directory if not
34
+ * found before giving up.
35
+ *
36
+ * This class is loosely based on the Symfony UniversalClassLoader.
37
+ *
38
+ * @author Fabien Potencier <fabien@symfony.com>
39
+ * @author Jordi Boggiano <j.boggiano@seld.be>
40
+ * @see http://www.php-fig.org/psr/psr-0/
41
+ * @see http://www.php-fig.org/psr/psr-4/
42
+ */
43
+ class ClassLoader
44
+ {
45
+ // PSR-4
46
+ private $prefixLengthsPsr4 = array();
47
+ private $prefixDirsPsr4 = array();
48
+ private $fallbackDirsPsr4 = array();
49
+
50
+ // PSR-0
51
+ private $prefixesPsr0 = array();
52
+ private $fallbackDirsPsr0 = array();
53
+
54
+ private $useIncludePath = false;
55
+ private $classMap = array();
56
+ private $classMapAuthoritative = false;
57
+ private $missingClasses = array();
58
+ private $apcuPrefix;
59
+
60
+ public function getPrefixes()
61
+ {
62
+ if (!empty($this->prefixesPsr0)) {
63
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
64
+ }
65
+
66
+ return array();
67
+ }
68
+
69
+ public function getPrefixesPsr4()
70
+ {
71
+ return $this->prefixDirsPsr4;
72
+ }
73
+
74
+ public function getFallbackDirs()
75
+ {
76
+ return $this->fallbackDirsPsr0;
77
+ }
78
+
79
+ public function getFallbackDirsPsr4()
80
+ {
81
+ return $this->fallbackDirsPsr4;
82
+ }
83
+
84
+ public function getClassMap()
85
+ {
86
+ return $this->classMap;
87
+ }
88
+
89
+ /**
90
+ * @param array $classMap Class to filename map
91
+ */
92
+ public function addClassMap(array $classMap)
93
+ {
94
+ if ($this->classMap) {
95
+ $this->classMap = array_merge($this->classMap, $classMap);
96
+ } else {
97
+ $this->classMap = $classMap;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Registers a set of PSR-0 directories for a given prefix, either
103
+ * appending or prepending to the ones previously set for this prefix.
104
+ *
105
+ * @param string $prefix The prefix
106
+ * @param array|string $paths The PSR-0 root directories
107
+ * @param bool $prepend Whether to prepend the directories
108
+ */
109
+ public function add($prefix, $paths, $prepend = false)
110
+ {
111
+ if (!$prefix) {
112
+ if ($prepend) {
113
+ $this->fallbackDirsPsr0 = array_merge(
114
+ (array) $paths,
115
+ $this->fallbackDirsPsr0
116
+ );
117
+ } else {
118
+ $this->fallbackDirsPsr0 = array_merge(
119
+ $this->fallbackDirsPsr0,
120
+ (array) $paths
121
+ );
122
+ }
123
+
124
+ return;
125
+ }
126
+
127
+ $first = $prefix[0];
128
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
129
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130
+
131
+ return;
132
+ }
133
+ if ($prepend) {
134
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
135
+ (array) $paths,
136
+ $this->prefixesPsr0[$first][$prefix]
137
+ );
138
+ } else {
139
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
140
+ $this->prefixesPsr0[$first][$prefix],
141
+ (array) $paths
142
+ );
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Registers a set of PSR-4 directories for a given namespace, either
148
+ * appending or prepending to the ones previously set for this namespace.
149
+ *
150
+ * @param string $prefix The prefix/namespace, with trailing '\\'
151
+ * @param array|string $paths The PSR-4 base directories
152
+ * @param bool $prepend Whether to prepend the directories
153
+ *
154
+ * @throws \InvalidArgumentException
155
+ */
156
+ public function addPsr4($prefix, $paths, $prepend = false)
157
+ {
158
+ if (!$prefix) {
159
+ // Register directories for the root namespace.
160
+ if ($prepend) {
161
+ $this->fallbackDirsPsr4 = array_merge(
162
+ (array) $paths,
163
+ $this->fallbackDirsPsr4
164
+ );
165
+ } else {
166
+ $this->fallbackDirsPsr4 = array_merge(
167
+ $this->fallbackDirsPsr4,
168
+ (array) $paths
169
+ );
170
+ }
171
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172
+ // Register directories for a new namespace.
173
+ $length = strlen($prefix);
174
+ if ('\\' !== $prefix[$length - 1]) {
175
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176
+ }
177
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
179
+ } elseif ($prepend) {
180
+ // Prepend directories for an already registered namespace.
181
+ $this->prefixDirsPsr4[$prefix] = array_merge(
182
+ (array) $paths,
183
+ $this->prefixDirsPsr4[$prefix]
184
+ );
185
+ } else {
186
+ // Append directories for an already registered namespace.
187
+ $this->prefixDirsPsr4[$prefix] = array_merge(
188
+ $this->prefixDirsPsr4[$prefix],
189
+ (array) $paths
190
+ );
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Registers a set of PSR-0 directories for a given prefix,
196
+ * replacing any others previously set for this prefix.
197
+ *
198
+ * @param string $prefix The prefix
199
+ * @param array|string $paths The PSR-0 base directories
200
+ */
201
+ public function set($prefix, $paths)
202
+ {
203
+ if (!$prefix) {
204
+ $this->fallbackDirsPsr0 = (array) $paths;
205
+ } else {
206
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Registers a set of PSR-4 directories for a given namespace,
212
+ * replacing any others previously set for this namespace.
213
+ *
214
+ * @param string $prefix The prefix/namespace, with trailing '\\'
215
+ * @param array|string $paths The PSR-4 base directories
216
+ *
217
+ * @throws \InvalidArgumentException
218
+ */
219
+ public function setPsr4($prefix, $paths)
220
+ {
221
+ if (!$prefix) {
222
+ $this->fallbackDirsPsr4 = (array) $paths;
223
+ } else {
224
+ $length = strlen($prefix);
225
+ if ('\\' !== $prefix[$length - 1]) {
226
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227
+ }
228
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Turns on searching the include path for class files.
235
+ *
236
+ * @param bool $useIncludePath
237
+ */
238
+ public function setUseIncludePath($useIncludePath)
239
+ {
240
+ $this->useIncludePath = $useIncludePath;
241
+ }
242
+
243
+ /**
244
+ * Can be used to check if the autoloader uses the include path to check
245
+ * for classes.
246
+ *
247
+ * @return bool
248
+ */
249
+ public function getUseIncludePath()
250
+ {
251
+ return $this->useIncludePath;
252
+ }
253
+
254
+ /**
255
+ * Turns off searching the prefix and fallback directories for classes
256
+ * that have not been registered with the class map.
257
+ *
258
+ * @param bool $classMapAuthoritative
259
+ */
260
+ public function setClassMapAuthoritative($classMapAuthoritative)
261
+ {
262
+ $this->classMapAuthoritative = $classMapAuthoritative;
263
+ }
264
+
265
+ /**
266
+ * Should class lookup fail if not found in the current class map?
267
+ *
268
+ * @return bool
269
+ */
270
+ public function isClassMapAuthoritative()
271
+ {
272
+ return $this->classMapAuthoritative;
273
+ }
274
+
275
+ /**
276
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277
+ *
278
+ * @param string|null $apcuPrefix
279
+ */
280
+ public function setApcuPrefix($apcuPrefix)
281
+ {
282
+ $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
283
+ }
284
+
285
+ /**
286
+ * The APCu prefix in use, or null if APCu caching is not enabled.
287
+ *
288
+ * @return string|null
289
+ */
290
+ public function getApcuPrefix()
291
+ {
292
+ return $this->apcuPrefix;
293
+ }
294
+
295
+ /**
296
+ * Registers this instance as an autoloader.
297
+ *
298
+ * @param bool $prepend Whether to prepend the autoloader or not
299
+ */
300
+ public function register($prepend = false)
301
+ {
302
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303
+ }
304
+
305
+ /**
306
+ * Unregisters this instance as an autoloader.
307
+ */
308
+ public function unregister()
309
+ {
310
+ spl_autoload_unregister(array($this, 'loadClass'));
311
+ }
312
+
313
+ /**
314
+ * Loads the given class or interface.
315
+ *
316
+ * @param string $class The name of the class
317
+ * @return bool|null True if loaded, null otherwise
318
+ */
319
+ public function loadClass($class)
320
+ {
321
+ if ($file = $this->findFile($class)) {
322
+ includeFile($file);
323
+
324
+ return true;
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Finds the path to the file where the class is defined.
330
+ *
331
+ * @param string $class The name of the class
332
+ *
333
+ * @return string|false The path if found, false otherwise
334
+ */
335
+ public function findFile($class)
336
+ {
337
+ // class map lookup
338
+ if (isset($this->classMap[$class])) {
339
+ return $this->classMap[$class];
340
+ }
341
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342
+ return false;
343
+ }
344
+ if (null !== $this->apcuPrefix) {
345
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346
+ if ($hit) {
347
+ return $file;
348
+ }
349
+ }
350
+
351
+ $file = $this->findFileWithExtension($class, '.php');
352
+
353
+ // Search for Hack files if we are running on HHVM
354
+ if (false === $file && defined('HHVM_VERSION')) {
355
+ $file = $this->findFileWithExtension($class, '.hh');
356
+ }
357
+
358
+ if (null !== $this->apcuPrefix) {
359
+ apcu_add($this->apcuPrefix.$class, $file);
360
+ }
361
+
362
+ if (false === $file) {
363
+ // Remember that this class does not exist.
364
+ $this->missingClasses[$class] = true;
365
+ }
366
+
367
+ return $file;
368
+ }
369
+
370
+ private function findFileWithExtension($class, $ext)
371
+ {
372
+ // PSR-4 lookup
373
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374
+
375
+ $first = $class[0];
376
+ if (isset($this->prefixLengthsPsr4[$first])) {
377
+ $subPath = $class;
378
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
379
+ $subPath = substr($subPath, 0, $lastPos);
380
+ $search = $subPath . '\\';
381
+ if (isset($this->prefixDirsPsr4[$search])) {
382
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
384
+ if (file_exists($file = $dir . $pathEnd)) {
385
+ return $file;
386
+ }
387
+ }
388
+ }
389
+ }
390
+ }
391
+
392
+ // PSR-4 fallback dirs
393
+ foreach ($this->fallbackDirsPsr4 as $dir) {
394
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395
+ return $file;
396
+ }
397
+ }
398
+
399
+ // PSR-0 lookup
400
+ if (false !== $pos = strrpos($class, '\\')) {
401
+ // namespaced class name
402
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404
+ } else {
405
+ // PEAR-like class name
406
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407
+ }
408
+
409
+ if (isset($this->prefixesPsr0[$first])) {
410
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411
+ if (0 === strpos($class, $prefix)) {
412
+ foreach ($dirs as $dir) {
413
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414
+ return $file;
415
+ }
416
+ }
417
+ }
418
+ }
419
+ }
420
+
421
+ // PSR-0 fallback dirs
422
+ foreach ($this->fallbackDirsPsr0 as $dir) {
423
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424
+ return $file;
425
+ }
426
+ }
427
+
428
+ // PSR-0 include paths.
429
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430
+ return $file;
431
+ }
432
+
433
+ return false;
434
+ }
435
+ }
436
+
437
+ /**
438
+ * Scope isolated include.
439
+ *
440
+ * Prevents access to $this/self from included files.
441
+ */
442
+ function includeFile($file)
443
+ {
444
+ include $file;
445
+ }
v4.0.0/libs/scssphp/vendor/composer/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Copyright (c) Nils Adermann, Jordi Boggiano
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished
9
+ to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
v4.0.0/libs/scssphp/vendor/composer/autoload_classmap.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_classmap.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
v4.0.0/libs/scssphp/vendor/composer/autoload_namespaces.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_namespaces.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
v4.0.0/libs/scssphp/vendor/composer/autoload_psr4.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_psr4.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'ScssPhp\\ScssPhp\\' => array($vendorDir . '/scssphp/scssphp/src'),
10
+ );
v4.0.0/libs/scssphp/vendor/composer/autoload_real.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit63d42ceb3ded2b5ffe0e0f4c4066ef1c
6
+ {
7
+ private static $loader;
8
+
9
+ public static function loadClassLoader($class)
10
+ {
11
+ if ('Composer\Autoload\ClassLoader' === $class) {
12
+ require __DIR__ . '/ClassLoader.php';
13
+ }
14
+ }
15
+
16
+ public static function getLoader()
17
+ {
18
+ if (null !== self::$loader) {
19
+ return self::$loader;
20
+ }
21
+
22
+ spl_autoload_register(array('ComposerAutoloaderInit63d42ceb3ded2b5ffe0e0f4c4066ef1c', 'loadClassLoader'), true, true);
23
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit63d42ceb3ded2b5ffe0e0f4c4066ef1c', 'loadClassLoader'));
25
+
26
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
+ if ($useStaticLoader) {
28
+ require_once __DIR__ . '/autoload_static.php';
29
+
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit63d42ceb3ded2b5ffe0e0f4c4066ef1c::getInitializer($loader));
31
+ } else {
32
+ $map = require __DIR__ . '/autoload_namespaces.php';
33
+ foreach ($map as $namespace => $path) {
34
+ $loader->set($namespace, $path);
35
+ }
36
+
37
+ $map = require __DIR__ . '/autoload_psr4.php';
38
+ foreach ($map as $namespace => $path) {
39
+ $loader->setPsr4($namespace, $path);
40
+ }
41
+
42
+ $classMap = require __DIR__ . '/autoload_classmap.php';
43
+ if ($classMap) {
44
+ $loader->addClassMap($classMap);
45
+ }
46
+ }
47
+
48
+ $loader->register(true);
49
+
50
+ return $loader;
51
+ }
52
+ }
v4.0.0/libs/scssphp/vendor/composer/autoload_static.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_static.php @generated by Composer
4
+
5
+ namespace Composer\Autoload;
6
+
7
+ class ComposerStaticInit63d42ceb3ded2b5ffe0e0f4c4066ef1c
8
+ {
9
+ public static $prefixLengthsPsr4 = array (
10
+ 'S' =>
11
+ array (
12
+ 'ScssPhp\\ScssPhp\\' => 16,
13
+ ),
14
+ );
15
+
16
+ public static $prefixDirsPsr4 = array (
17
+ 'ScssPhp\\ScssPhp\\' =>
18
+ array (
19
+ 0 => __DIR__ . '/..' . '/scssphp/scssphp/src',
20
+ ),
21
+ );
22
+
23
+ public static function getInitializer(ClassLoader $loader)
24
+ {
25
+ return \Closure::bind(function () use ($loader) {
26
+ $loader->prefixLengthsPsr4 = ComposerStaticInit63d42ceb3ded2b5ffe0e0f4c4066ef1c::$prefixLengthsPsr4;
27
+ $loader->prefixDirsPsr4 = ComposerStaticInit63d42ceb3ded2b5ffe0e0f4c4066ef1c::$prefixDirsPsr4;
28
+
29
+ }, null, ClassLoader::class);
30
+ }
31
+ }
v4.0.0/libs/scssphp/vendor/composer/installed.json ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "name": "scssphp/scssphp",
4
+ "version": "1.1.0",
5
+ "version_normalized": "1.1.0.0",
6
+ "source": {
7
+ "type": "git",
8
+ "url": "https://github.com/scssphp/scssphp.git",
9
+ "reference": "4363ddce8d750f055c436833dd77d83517946532"
10
+ },
11
+ "dist": {
12
+ "type": "zip",
13
+ "url": "https://api.github.com/repos/scssphp/scssphp/zipball/4363ddce8d750f055c436833dd77d83517946532",
14
+ "reference": "4363ddce8d750f055c436833dd77d83517946532",
15
+ "shasum": ""
16
+ },
17
+ "require": {
18
+ "ext-ctype": "*",
19
+ "ext-json": "*",
20
+ "php": ">=5.6.0"
21
+ },
22
+ "require-dev": {
23
+ "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3",
24
+ "squizlabs/php_codesniffer": "~3.5",
25
+ "twbs/bootstrap": "~4.3",
26
+ "zurb/foundation": "~6.5"
27
+ },
28
+ "time": "2020-04-21T15:53:32+00:00",
29
+ "bin": [
30
+ "bin/pscss"
31
+ ],
32
+ "type": "library",
33
+ "installation-source": "dist",
34
+ "autoload": {
35
+ "psr-4": {
36
+ "ScssPhp\\ScssPhp\\": "src/"
37
+ }
38
+ },
39
+ "notification-url": "https://packagist.org/downloads/",
40
+ "license": [
41
+ "MIT"
42
+ ],
43
+ "authors": [
44
+ {
45
+ "name": "Anthon Pang",
46
+ "email": "apang@softwaredevelopment.ca",
47
+ "homepage": "https://github.com/robocoder"
48
+ },
49
+ {
50
+ "name": "Cédric Morin",
51
+ "email": "cedric@yterium.com",
52
+ "homepage": "https://github.com/Cerdic"
53
+ }
54
+ ],
55
+ "description": "scssphp is a compiler for SCSS written in PHP.",
56
+ "homepage": "http://scssphp.github.io/scssphp/",
57
+ "keywords": [
58
+ "css",
59
+ "less",
60
+ "sass",
61
+ "scss",
62
+ "stylesheet"
63
+ ]
64
+ }
65
+ ]
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/LICENSE.md ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2015 Leaf Corcoran, http://scssphp.github.io/scssphp
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/README.md ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # scssphp
2
+ ### <http://scssphp.github.io/scssphp>
3
+
4
+ [![Build](https://travis-ci.org/scssphp/scssphp.svg?branch=master)](http://travis-ci.org/scssphp/scssphp)
5
+ [![License](https://poser.pugx.org/scssphp/scssphp/license)](https://packagist.org/packages/scssphp/scssphp)
6
+
7
+ `scssphp` is a compiler for SCSS written in PHP.
8
+
9
+ Checkout the homepage, <http://scssphp.github.io/scssphp>, for directions on how to use.
10
+
11
+ ## Running Tests
12
+
13
+ `scssphp` uses [PHPUnit](https://github.com/sebastianbergmann/phpunit) for testing.
14
+
15
+ Run the following command from the root directory to run every test:
16
+
17
+ vendor/bin/phpunit tests
18
+
19
+ There are several tests in the `tests/` directory:
20
+
21
+ * `ApiTest.php` contains various unit tests that test the PHP interface.
22
+ * `ExceptionTest.php` contains unit tests that test for exceptions thrown by the parser and compiler.
23
+ * `FailingTest.php` contains tests reported in Github issues that demonstrate compatibility bugs.
24
+ * `InputTest.php` compiles every `.scss` file in the `tests/inputs` directory
25
+ then compares to the respective `.css` file in the `tests/outputs` directory.
26
+ * `ScssTest.php` extracts (ruby) `scss` tests from the `tests/scss_test.rb` file.
27
+
28
+ When changing any of the tests in `tests/inputs`, the tests will most likely
29
+ fail because the output has changed. Once you verify that the output is correct
30
+ you can run the following command to rebuild all the tests:
31
+
32
+ BUILD=1 vendor/bin/phpunit tests
33
+
34
+ This will compile all the tests, and save results into `tests/outputs`.
35
+
36
+ To enable the `scss` compatibility tests:
37
+
38
+ TEST_SCSS_COMPAT=1 vendor/bin/phpunit tests
39
+
40
+ ## Coding Standard
41
+
42
+ `scssphp` source conforms to [PSR2](http://www.php-fig.org/psr/psr-2/).
43
+
44
+ Run the following command from the root directory to check the code for "sniffs".
45
+
46
+ vendor/bin/phpcs --standard=PSR2 bin src tests
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/bin/pscss ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env php
2
+ <?php
3
+ /**
4
+ * SCSSPHP
5
+ *
6
+ * @copyright 2012-2020 Leaf Corcoran
7
+ *
8
+ * @license http://opensource.org/licenses/MIT MIT
9
+ *
10
+ * @link http://scssphp.github.io/scssphp
11
+ */
12
+
13
+ error_reporting(E_ALL);
14
+
15
+ if (version_compare(PHP_VERSION, '5.6') < 0) {
16
+ die('Requires PHP 5.6 or above');
17
+ }
18
+
19
+ include __DIR__ . '/../scss.inc.php';
20
+
21
+ use ScssPhp\ScssPhp\Compiler;
22
+ use ScssPhp\ScssPhp\Parser;
23
+ use ScssPhp\ScssPhp\Version;
24
+
25
+ $style = null;
26
+ $loadPaths = null;
27
+ $precision = null;
28
+ $dumpTree = false;
29
+ $inputFile = null;
30
+ $changeDir = false;
31
+ $debugInfo = false;
32
+ $lineNumbers = false;
33
+ $ignoreErrors = false;
34
+ $encoding = false;
35
+ $sourceMap = false;
36
+
37
+ /**
38
+ * Parse argument
39
+ *
40
+ * @param integer $i
41
+ * @param array $options
42
+ *
43
+ * @return string|null
44
+ */
45
+ function parseArgument(&$i, $options) {
46
+ global $argc;
47
+ global $argv;
48
+
49
+ if (! preg_match('/^(?:' . implode('|', (array) $options) . ')=?(.*)/', $argv[$i], $matches)) {
50
+ return;
51
+ }
52
+
53
+ if (strlen($matches[1])) {
54
+ return $matches[1];
55
+ }
56
+
57
+ if ($i + 1 < $argc) {
58
+ $i++;
59
+
60
+ return $argv[$i];
61
+ }
62
+ }
63
+
64
+ for ($i = 1; $i < $argc; $i++) {
65
+ if ($argv[$i] === '-?' || $argv[$i] === '-h' || $argv[$i] === '--help') {
66
+ $exe = $argv[0];
67
+
68
+ $HELP = <<<EOT
69
+ Usage: $exe [options] [input-file]
70
+
71
+ Options include:
72
+
73
+ --help Show this message [-h, -?]
74
+ --continue-on-error Continue compilation (as best as possible) when error encountered
75
+ --debug-info Annotate selectors with CSS referring to the source file and line number [-g]
76
+ --dump-tree Dump formatted parse tree [-T]
77
+ --iso8859-1 Use iso8859-1 encoding instead of default utf-8
78
+ --line-numbers Annotate selectors with comments referring to the source file and line number [--line-comments]
79
+ --load-path=PATH Set import path [-I]
80
+ --precision=N Set decimal number precision (default 10) [-p]
81
+ --sourcemap Create source map file
82
+ --style=FORMAT Set the output format (compact, compressed, crunched, expanded, or nested) [-s, -t]
83
+ --version Print the version [-v]
84
+
85
+ EOT;
86
+ exit($HELP);
87
+ }
88
+
89
+ if ($argv[$i] === '-v' || $argv[$i] === '--version') {
90
+ exit(Version::VERSION . "\n");
91
+ }
92
+
93
+ if ($argv[$i] === '--continue-on-error') {
94
+ $ignoreErrors = true;
95
+ continue;
96
+ }
97
+
98
+ if ($argv[$i] === '-g' || $argv[$i] === '--debug-info') {
99
+ $debugInfo = true;
100
+ continue;
101
+ }
102
+
103
+ if ($argv[$i] === '--iso8859-1') {
104
+ $encoding = 'iso8859-1';
105
+ continue;
106
+ }
107
+
108
+ if ($argv[$i] === '--line-numbers' || $argv[$i] === '--line-comments') {
109
+ $lineNumbers = true;
110
+ continue;
111
+ }
112
+
113
+ if ($argv[$i] === '--sourcemap') {
114
+ $sourceMap = true;
115
+ continue;
116
+ }
117
+
118
+ if ($argv[$i] === '-T' || $argv[$i] === '--dump-tree') {
119
+ $dumpTree = true;
120
+ continue;
121
+ }
122
+
123
+ $value = parseArgument($i, array('-t', '-s', '--style'));
124
+
125
+ if (isset($value)) {
126
+ $style = $value;
127
+ continue;
128
+ }
129
+
130
+ $value = parseArgument($i, array('-I', '--load-path'));
131
+
132
+ if (isset($value)) {
133
+ $loadPaths = $value;
134
+ continue;
135
+ }
136
+
137
+ $value = parseArgument($i, array('-p', '--precision'));
138
+
139
+ if (isset($value)) {
140
+ $precision = $value;
141
+ continue;
142
+ }
143
+
144
+ if (file_exists($argv[$i])) {
145
+ $inputFile = $argv[$i];
146
+ continue;
147
+ }
148
+ }
149
+
150
+
151
+ if ($inputFile) {
152
+ $data = file_get_contents($inputFile);
153
+
154
+ $newWorkingDir = dirname(realpath($inputFile));
155
+ $oldWorkingDir = getcwd();
156
+
157
+ if ($oldWorkingDir !== $newWorkingDir) {
158
+ $changeDir = chdir($newWorkingDir);
159
+ $inputFile = basename($inputFile);
160
+ }
161
+ } else {
162
+ $data = '';
163
+
164
+ while (! feof(STDIN)) {
165
+ $data .= fread(STDIN, 8192);
166
+ }
167
+ }
168
+
169
+ if ($dumpTree) {
170
+ $parser = new Parser($inputFile);
171
+
172
+ print_r(json_decode(json_encode($parser->parse($data)), true));
173
+
174
+ exit();
175
+ }
176
+
177
+ $scss = new Compiler();
178
+
179
+ if ($debugInfo) {
180
+ $scss->setLineNumberStyle(Compiler::DEBUG_INFO);
181
+ }
182
+
183
+ if ($lineNumbers) {
184
+ $scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
185
+ }
186
+
187
+ if ($ignoreErrors) {
188
+ $scss->setIgnoreErrors($ignoreErrors);
189
+ }
190
+
191
+ if ($loadPaths) {
192
+ $scss->setImportPaths(explode(PATH_SEPARATOR, $loadPaths));
193
+ }
194
+
195
+ if ($precision) {
196
+ $scss->setNumberPrecision($precision);
197
+ }
198
+
199
+ if ($style) {
200
+ $scss->setFormatter('ScssPhp\\ScssPhp\\Formatter\\' . ucfirst($style));
201
+ }
202
+
203
+ if ($sourceMap) {
204
+ $scss->setSourceMap(Compiler::SOURCE_MAP_INLINE);
205
+ }
206
+
207
+ if ($encoding) {
208
+ $scss->setEncoding($encoding);
209
+ }
210
+
211
+ echo $scss->compile($data, $inputFile);
212
+
213
+ if ($changeDir) {
214
+ chdir($oldWorkingDir);
215
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/composer.json ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "scssphp/scssphp",
3
+ "type": "library",
4
+ "description": "scssphp is a compiler for SCSS written in PHP.",
5
+ "keywords": ["css", "stylesheet", "scss", "sass", "less"],
6
+ "homepage": "http://scssphp.github.io/scssphp/",
7
+ "license": [
8
+ "MIT"
9
+ ],
10
+ "authors": [
11
+ {
12
+ "name": "Anthon Pang",
13
+ "email": "apang@softwaredevelopment.ca",
14
+ "homepage": "https://github.com/robocoder"
15
+ },
16
+ {
17
+ "name": "Cédric Morin",
18
+ "email": "cedric@yterium.com",
19
+ "homepage": "https://github.com/Cerdic"
20
+ }
21
+ ],
22
+ "autoload": {
23
+ "psr-4": { "ScssPhp\\ScssPhp\\": "src/" }
24
+ },
25
+ "autoload-dev": {
26
+ "psr-4": { "ScssPhp\\ScssPhp\\Tests\\": "tests/" }
27
+ },
28
+ "require": {
29
+ "php": ">=5.6.0",
30
+ "ext-json": "*",
31
+ "ext-ctype": "*"
32
+ },
33
+ "require-dev": {
34
+ "squizlabs/php_codesniffer": "~3.5",
35
+ "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3",
36
+ "twbs/bootstrap": "~4.3",
37
+ "zurb/foundation": "~6.5"
38
+ },
39
+ "minimum-stability": "dev",
40
+ "bin": ["bin/pscss"],
41
+ "archive": {
42
+ "exclude": [
43
+ "/Makefile",
44
+ "/.gitattributes",
45
+ "/.gitignore",
46
+ "/.travis.yml",
47
+ "/phpunit.xml.dist",
48
+ "/tests"
49
+ ]
50
+ }
51
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/scss.inc.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (version_compare(PHP_VERSION, '5.6') < 0) {
3
+ throw new \Exception('scssphp requires PHP 5.6 or above');
4
+ }
5
+
6
+ if (! class_exists('ScssPhp\ScssPhp\Version', false)) {
7
+ include_once __DIR__ . '/src/Base/Range.php';
8
+ include_once __DIR__ . '/src/Block.php';
9
+ include_once __DIR__ . '/src/Cache.php';
10
+ include_once __DIR__ . '/src/Colors.php';
11
+ include_once __DIR__ . '/src/Compiler.php';
12
+ include_once __DIR__ . '/src/Compiler/Environment.php';
13
+ include_once __DIR__ . '/src/Exception/CompilerException.php';
14
+ include_once __DIR__ . '/src/Exception/ParserException.php';
15
+ include_once __DIR__ . '/src/Exception/RangeException.php';
16
+ include_once __DIR__ . '/src/Exception/ServerException.php';
17
+ include_once __DIR__ . '/src/Formatter.php';
18
+ include_once __DIR__ . '/src/Formatter/Compact.php';
19
+ include_once __DIR__ . '/src/Formatter/Compressed.php';
20
+ include_once __DIR__ . '/src/Formatter/Crunched.php';
21
+ include_once __DIR__ . '/src/Formatter/Debug.php';
22
+ include_once __DIR__ . '/src/Formatter/Expanded.php';
23
+ include_once __DIR__ . '/src/Formatter/Nested.php';
24
+ include_once __DIR__ . '/src/Formatter/OutputBlock.php';
25
+ include_once __DIR__ . '/src/Node.php';
26
+ include_once __DIR__ . '/src/Node/Number.php';
27
+ include_once __DIR__ . '/src/Parser.php';
28
+ include_once __DIR__ . '/src/SourceMap/Base64.php';
29
+ include_once __DIR__ . '/src/SourceMap/Base64VLQ.php';
30
+ include_once __DIR__ . '/src/SourceMap/SourceMapGenerator.php';
31
+ include_once __DIR__ . '/src/Type.php';
32
+ include_once __DIR__ . '/src/Util.php';
33
+ include_once __DIR__ . '/src/Version.php';
34
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Base/Range.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2015-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Base;
13
+
14
+ /**
15
+ * Range
16
+ *
17
+ * @author Anthon Pang <anthon.pang@gmail.com>
18
+ */
19
+ class Range
20
+ {
21
+ public $first;
22
+ public $last;
23
+
24
+ /**
25
+ * Initialize range
26
+ *
27
+ * @param integer|float $first
28
+ * @param integer|float $last
29
+ */
30
+ public function __construct($first, $last)
31
+ {
32
+ $this->first = $first;
33
+ $this->last = $last;
34
+ }
35
+
36
+ /**
37
+ * Test for inclusion in range
38
+ *
39
+ * @param integer|float $value
40
+ *
41
+ * @return boolean
42
+ */
43
+ public function includes($value)
44
+ {
45
+ return $value >= $this->first && $value <= $this->last;
46
+ }
47
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Block.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp;
13
+
14
+ /**
15
+ * Block
16
+ *
17
+ * @author Anthon Pang <anthon.pang@gmail.com>
18
+ */
19
+ class Block
20
+ {
21
+ /**
22
+ * @var string
23
+ */
24
+ public $type;
25
+
26
+ /**
27
+ * @var \ScssPhp\ScssPhp\Block
28
+ */
29
+ public $parent;
30
+
31
+ /**
32
+ * @var string
33
+ */
34
+ public $sourceName;
35
+
36
+ /**
37
+ * @var integer
38
+ */
39
+ public $sourceIndex;
40
+
41
+ /**
42
+ * @var integer
43
+ */
44
+ public $sourceLine;
45
+
46
+ /**
47
+ * @var integer
48
+ */
49
+ public $sourceColumn;
50
+
51
+ /**
52
+ * @var array
53
+ */
54
+ public $selectors;
55
+
56
+ /**
57
+ * @var array
58
+ */
59
+ public $comments;
60
+
61
+ /**
62
+ * @var array
63
+ */
64
+ public $children;
65
+
66
+ /**
67
+ * @var \ScssPhp\ScssPhp\Block
68
+ */
69
+ public $selfParent;
70
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Cache.php ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp;
13
+
14
+ use Exception;
15
+
16
+ /**
17
+ * The scss cache manager.
18
+ *
19
+ * In short:
20
+ *
21
+ * allow to put in cache/get from cache a generic result from a known operation on a generic dataset,
22
+ * taking in account options that affects the result
23
+ *
24
+ * The cache manager is agnostic about data format and only the operation is expected to be described by string
25
+ */
26
+
27
+ /**
28
+ * SCSS cache
29
+ *
30
+ * @author Cedric Morin <cedric@yterium.com>
31
+ */
32
+ class Cache
33
+ {
34
+ const CACHE_VERSION = 1;
35
+
36
+ // directory used for storing data
37
+ public static $cacheDir = false;
38
+
39
+ // prefix for the storing data
40
+ public static $prefix = 'scssphp_';
41
+
42
+ // force a refresh : 'once' for refreshing the first hit on a cache only, true to never use the cache in this hit
43
+ public static $forceRefresh = false;
44
+
45
+ // specifies the number of seconds after which data cached will be seen as 'garbage' and potentially cleaned up
46
+ public static $gcLifetime = 604800;
47
+
48
+ // array of already refreshed cache if $forceRefresh==='once'
49
+ protected static $refreshed = [];
50
+
51
+ /**
52
+ * Constructor
53
+ *
54
+ * @param array $options
55
+ */
56
+ public function __construct($options)
57
+ {
58
+ // check $cacheDir
59
+ if (isset($options['cacheDir'])) {
60
+ self::$cacheDir = $options['cacheDir'];
61
+ }
62
+
63
+ if (empty(self::$cacheDir)) {
64
+ throw new Exception('cacheDir not set');
65
+ }
66
+
67
+ if (isset($options['prefix'])) {
68
+ self::$prefix = $options['prefix'];
69
+ }
70
+
71
+ if (empty(self::$prefix)) {
72
+ throw new Exception('prefix not set');
73
+ }
74
+
75
+ if (isset($options['forceRefresh'])) {
76
+ self::$forceRefresh = $options['forceRefresh'];
77
+ }
78
+
79
+ self::checkCacheDir();
80
+ }
81
+
82
+ /**
83
+ * Get the cached result of $operation on $what,
84
+ * which is known as dependant from the content of $options
85
+ *
86
+ * @param string $operation parse, compile...
87
+ * @param mixed $what content key (e.g., filename to be treated)
88
+ * @param array $options any option that affect the operation result on the content
89
+ * @param integer $lastModified last modified timestamp
90
+ *
91
+ * @return mixed
92
+ *
93
+ * @throws \Exception
94
+ */
95
+ public function getCache($operation, $what, $options = [], $lastModified = null)
96
+ {
97
+ $fileCache = self::$cacheDir . self::cacheName($operation, $what, $options);
98
+
99
+ if (((self::$forceRefresh === false) || (self::$forceRefresh === 'once' &&
100
+ isset(self::$refreshed[$fileCache]))) && file_exists($fileCache)
101
+ ) {
102
+ $cacheTime = filemtime($fileCache);
103
+
104
+ if ((\is_null($lastModified) || $cacheTime > $lastModified) &&
105
+ $cacheTime + self::$gcLifetime > time()
106
+ ) {
107
+ $c = file_get_contents($fileCache);
108
+ $c = unserialize($c);
109
+
110
+ if (\is_array($c) && isset($c['value'])) {
111
+ return $c['value'];
112
+ }
113
+ }
114
+ }
115
+
116
+ return null;
117
+ }
118
+
119
+ /**
120
+ * Put in cache the result of $operation on $what,
121
+ * which is known as dependant from the content of $options
122
+ *
123
+ * @param string $operation
124
+ * @param mixed $what
125
+ * @param mixed $value
126
+ * @param array $options
127
+ */
128
+ public function setCache($operation, $what, $value, $options = [])
129
+ {
130
+ $fileCache = self::$cacheDir . self::cacheName($operation, $what, $options);
131
+
132
+ $c = ['value' => $value];
133
+ $c = serialize($c);
134
+
135
+ file_put_contents($fileCache, $c);
136
+
137
+ if (self::$forceRefresh === 'once') {
138
+ self::$refreshed[$fileCache] = true;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Get the cache name for the caching of $operation on $what,
144
+ * which is known as dependant from the content of $options
145
+ *
146
+ * @param string $operation
147
+ * @param mixed $what
148
+ * @param array $options
149
+ *
150
+ * @return string
151
+ */
152
+ private static function cacheName($operation, $what, $options = [])
153
+ {
154
+ $t = [
155
+ 'version' => self::CACHE_VERSION,
156
+ 'operation' => $operation,
157
+ 'what' => $what,
158
+ 'options' => $options
159
+ ];
160
+
161
+ $t = self::$prefix
162
+ . sha1(json_encode($t))
163
+ . ".$operation"
164
+ . ".scsscache";
165
+
166
+ return $t;
167
+ }
168
+
169
+ /**
170
+ * Check that the cache dir exists and is writeable
171
+ *
172
+ * @throws \Exception
173
+ */
174
+ public static function checkCacheDir()
175
+ {
176
+ self::$cacheDir = str_replace('\\', '/', self::$cacheDir);
177
+ self::$cacheDir = rtrim(self::$cacheDir, '/') . '/';
178
+
179
+ if (! is_dir(self::$cacheDir)) {
180
+ if (! mkdir(self::$cacheDir)) {
181
+ throw new Exception('Cache directory couldn\'t be created: ' . self::$cacheDir);
182
+ }
183
+ }
184
+
185
+ if (! is_writable(self::$cacheDir)) {
186
+ throw new Exception('Cache directory isn\'t writable: ' . self::$cacheDir);
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Delete unused cached files
192
+ */
193
+ public static function cleanCache()
194
+ {
195
+ static $clean = false;
196
+
197
+ if ($clean || empty(self::$cacheDir)) {
198
+ return;
199
+ }
200
+
201
+ $clean = true;
202
+
203
+ // only remove files with extensions created by SCSSPHP Cache
204
+ // css files removed based on the list files
205
+ $removeTypes = ['scsscache' => 1];
206
+
207
+ $files = scandir(self::$cacheDir);
208
+
209
+ if (! $files) {
210
+ return;
211
+ }
212
+
213
+ $checkTime = time() - self::$gcLifetime;
214
+
215
+ foreach ($files as $file) {
216
+ // don't delete if the file wasn't created with SCSSPHP Cache
217
+ if (strpos($file, self::$prefix) !== 0) {
218
+ continue;
219
+ }
220
+
221
+ $parts = explode('.', $file);
222
+ $type = array_pop($parts);
223
+
224
+ if (! isset($removeTypes[$type])) {
225
+ continue;
226
+ }
227
+
228
+ $fullPath = self::$cacheDir . $file;
229
+ $mtime = filemtime($fullPath);
230
+
231
+ // don't delete if it's a relatively new file
232
+ if ($mtime > $checkTime) {
233
+ continue;
234
+ }
235
+
236
+ unlink($fullPath);
237
+ }
238
+ }
239
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Colors.php ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp;
13
+
14
+ /**
15
+ * CSS Colors
16
+ *
17
+ * @author Leaf Corcoran <leafot@gmail.com>
18
+ */
19
+ class Colors
20
+ {
21
+ /**
22
+ * CSS Colors
23
+ *
24
+ * @see http://www.w3.org/TR/css3-color
25
+ *
26
+ * @var array
27
+ */
28
+ protected static $cssColors = [
29
+ 'aliceblue' => '240,248,255',
30
+ 'antiquewhite' => '250,235,215',
31
+ 'aqua' => '0,255,255',
32
+ 'aquamarine' => '127,255,212',
33
+ 'azure' => '240,255,255',
34
+ 'beige' => '245,245,220',
35
+ 'bisque' => '255,228,196',
36
+ 'black' => '0,0,0',
37
+ 'blanchedalmond' => '255,235,205',
38
+ 'blue' => '0,0,255',
39
+ 'blueviolet' => '138,43,226',
40
+ 'brown' => '165,42,42',
41
+ 'burlywood' => '222,184,135',
42
+ 'cadetblue' => '95,158,160',
43
+ 'chartreuse' => '127,255,0',
44
+ 'chocolate' => '210,105,30',
45
+ 'coral' => '255,127,80',
46
+ 'cornflowerblue' => '100,149,237',
47
+ 'cornsilk' => '255,248,220',
48
+ 'crimson' => '220,20,60',
49
+ 'cyan' => '0,255,255',
50
+ 'darkblue' => '0,0,139',
51
+ 'darkcyan' => '0,139,139',
52
+ 'darkgoldenrod' => '184,134,11',
53
+ 'darkgray' => '169,169,169',
54
+ 'darkgreen' => '0,100,0',
55
+ 'darkgrey' => '169,169,169',
56
+ 'darkkhaki' => '189,183,107',
57
+ 'darkmagenta' => '139,0,139',
58
+ 'darkolivegreen' => '85,107,47',
59
+ 'darkorange' => '255,140,0',
60
+ 'darkorchid' => '153,50,204',
61
+ 'darkred' => '139,0,0',
62
+ 'darksalmon' => '233,150,122',
63
+ 'darkseagreen' => '143,188,143',
64
+ 'darkslateblue' => '72,61,139',
65
+ 'darkslategray' => '47,79,79',
66
+ 'darkslategrey' => '47,79,79',
67
+ 'darkturquoise' => '0,206,209',
68
+ 'darkviolet' => '148,0,211',
69
+ 'deeppink' => '255,20,147',
70
+ 'deepskyblue' => '0,191,255',
71
+ 'dimgray' => '105,105,105',
72
+ 'dimgrey' => '105,105,105',
73
+ 'dodgerblue' => '30,144,255',
74
+ 'firebrick' => '178,34,34',
75
+ 'floralwhite' => '255,250,240',
76
+ 'forestgreen' => '34,139,34',
77
+ 'fuchsia' => '255,0,255',
78
+ 'gainsboro' => '220,220,220',
79
+ 'ghostwhite' => '248,248,255',
80
+ 'gold' => '255,215,0',
81
+ 'goldenrod' => '218,165,32',
82
+ 'gray' => '128,128,128',
83
+ 'green' => '0,128,0',
84
+ 'greenyellow' => '173,255,47',
85
+ 'grey' => '128,128,128',
86
+ 'honeydew' => '240,255,240',
87
+ 'hotpink' => '255,105,180',
88
+ 'indianred' => '205,92,92',
89
+ 'indigo' => '75,0,130',
90
+ 'ivory' => '255,255,240',
91
+ 'khaki' => '240,230,140',
92
+ 'lavender' => '230,230,250',
93
+ 'lavenderblush' => '255,240,245',
94
+ 'lawngreen' => '124,252,0',
95
+ 'lemonchiffon' => '255,250,205',
96
+ 'lightblue' => '173,216,230',
97
+ 'lightcoral' => '240,128,128',
98
+ 'lightcyan' => '224,255,255',
99
+ 'lightgoldenrodyellow' => '250,250,210',
100
+ 'lightgray' => '211,211,211',
101
+ 'lightgreen' => '144,238,144',
102
+ 'lightgrey' => '211,211,211',
103
+ 'lightpink' => '255,182,193',
104
+ 'lightsalmon' => '255,160,122',
105
+ 'lightseagreen' => '32,178,170',
106
+ 'lightskyblue' => '135,206,250',
107
+ 'lightslategray' => '119,136,153',
108
+ 'lightslategrey' => '119,136,153',
109
+ 'lightsteelblue' => '176,196,222',
110
+ 'lightyellow' => '255,255,224',
111
+ 'lime' => '0,255,0',
112
+ 'limegreen' => '50,205,50',
113
+ 'linen' => '250,240,230',
114
+ 'magenta' => '255,0,255',
115
+ 'maroon' => '128,0,0',
116
+ 'mediumaquamarine' => '102,205,170',
117
+ 'mediumblue' => '0,0,205',
118
+ 'mediumorchid' => '186,85,211',
119
+ 'mediumpurple' => '147,112,219',
120
+ 'mediumseagreen' => '60,179,113',
121
+ 'mediumslateblue' => '123,104,238',
122
+ 'mediumspringgreen' => '0,250,154',
123
+ 'mediumturquoise' => '72,209,204',
124
+ 'mediumvioletred' => '199,21,133',
125
+ 'midnightblue' => '25,25,112',
126
+ 'mintcream' => '245,255,250',
127
+ 'mistyrose' => '255,228,225',
128
+ 'moccasin' => '255,228,181',
129
+ 'navajowhite' => '255,222,173',
130
+ 'navy' => '0,0,128',
131
+ 'oldlace' => '253,245,230',
132
+ 'olive' => '128,128,0',
133
+ 'olivedrab' => '107,142,35',
134
+ 'orange' => '255,165,0',
135
+ 'orangered' => '255,69,0',
136
+ 'orchid' => '218,112,214',
137
+ 'palegoldenrod' => '238,232,170',
138
+ 'palegreen' => '152,251,152',
139
+ 'paleturquoise' => '175,238,238',
140
+ 'palevioletred' => '219,112,147',
141
+ 'papayawhip' => '255,239,213',
142
+ 'peachpuff' => '255,218,185',
143
+ 'peru' => '205,133,63',
144
+ 'pink' => '255,192,203',
145
+ 'plum' => '221,160,221',
146
+ 'powderblue' => '176,224,230',
147
+ 'purple' => '128,0,128',
148
+ 'rebeccapurple' => '102,51,153',
149
+ 'red' => '255,0,0',
150
+ 'rosybrown' => '188,143,143',
151
+ 'royalblue' => '65,105,225',
152
+ 'saddlebrown' => '139,69,19',
153
+ 'salmon' => '250,128,114',
154
+ 'sandybrown' => '244,164,96',
155
+ 'seagreen' => '46,139,87',
156
+ 'seashell' => '255,245,238',
157
+ 'sienna' => '160,82,45',
158
+ 'silver' => '192,192,192',
159
+ 'skyblue' => '135,206,235',
160
+ 'slateblue' => '106,90,205',
161
+ 'slategray' => '112,128,144',
162
+ 'slategrey' => '112,128,144',
163
+ 'snow' => '255,250,250',
164
+ 'springgreen' => '0,255,127',
165
+ 'steelblue' => '70,130,180',
166
+ 'tan' => '210,180,140',
167
+ 'teal' => '0,128,128',
168
+ 'thistle' => '216,191,216',
169
+ 'tomato' => '255,99,71',
170
+ 'transparent' => '0,0,0,0',
171
+ 'turquoise' => '64,224,208',
172
+ 'violet' => '238,130,238',
173
+ 'wheat' => '245,222,179',
174
+ 'white' => '255,255,255',
175
+ 'whitesmoke' => '245,245,245',
176
+ 'yellow' => '255,255,0',
177
+ 'yellowgreen' => '154,205,50',
178
+ ];
179
+
180
+ /**
181
+ * Convert named color in a [r,g,b[,a]] array
182
+ *
183
+ * @param string $colorName
184
+ *
185
+ * @return array|null
186
+ */
187
+ public static function colorNameToRGBa($colorName)
188
+ {
189
+ if (\is_string($colorName) && isset(static::$cssColors[$colorName])) {
190
+ $rgba = explode(',', static::$cssColors[$colorName]);
191
+
192
+ // only case with opacity is transparent, with opacity=0, so we can intval on opacity also
193
+ $rgba = array_map('intval', $rgba);
194
+
195
+ return $rgba;
196
+ }
197
+
198
+ return null;
199
+ }
200
+
201
+ /**
202
+ * Reverse conversion : from RGBA to a color name if possible
203
+ *
204
+ * @param integer $r
205
+ * @param integer $g
206
+ * @param integer $b
207
+ * @param integer $a
208
+ *
209
+ * @return string|null
210
+ */
211
+ public static function RGBaToColorName($r, $g, $b, $a = 1)
212
+ {
213
+ static $reverseColorTable = null;
214
+
215
+ if (! is_numeric($r) || ! is_numeric($g) || ! is_numeric($b) || ! is_numeric($a)) {
216
+ return null;
217
+ }
218
+
219
+ if ($a < 1) {
220
+ return null;
221
+ }
222
+
223
+ if (\is_null($reverseColorTable)) {
224
+ $reverseColorTable = [];
225
+
226
+ foreach (static::$cssColors as $name => $rgb_str) {
227
+ $rgb_str = explode(',', $rgb_str);
228
+
229
+ if (\count($rgb_str) == 3) {
230
+ $reverseColorTable[\intval($rgb_str[0])][\intval($rgb_str[1])][\intval($rgb_str[2])] = $name;
231
+ }
232
+ }
233
+ }
234
+
235
+ if (isset($reverseColorTable[\intval($r)][\intval($g)][\intval($b)])) {
236
+ return $reverseColorTable[\intval($r)][\intval($g)][\intval($b)];
237
+ }
238
+
239
+ return null;
240
+ }
241
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Compiler.php ADDED
@@ -0,0 +1,7838 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp;
13
+
14
+ use ScssPhp\ScssPhp\Base\Range;
15
+ use ScssPhp\ScssPhp\Block;
16
+ use ScssPhp\ScssPhp\Cache;
17
+ use ScssPhp\ScssPhp\Colors;
18
+ use ScssPhp\ScssPhp\Compiler\Environment;
19
+ use ScssPhp\ScssPhp\Exception\CompilerException;
20
+ use ScssPhp\ScssPhp\Formatter\OutputBlock;
21
+ use ScssPhp\ScssPhp\Node;
22
+ use ScssPhp\ScssPhp\SourceMap\SourceMapGenerator;
23
+ use ScssPhp\ScssPhp\Type;
24
+ use ScssPhp\ScssPhp\Parser;
25
+ use ScssPhp\ScssPhp\Util;
26
+
27
+ /**
28
+ * The scss compiler and parser.
29
+ *
30
+ * Converting SCSS to CSS is a three stage process. The incoming file is parsed
31
+ * by `Parser` into a syntax tree, then it is compiled into another tree
32
+ * representing the CSS structure by `Compiler`. The CSS tree is fed into a
33
+ * formatter, like `Formatter` which then outputs CSS as a string.
34
+ *
35
+ * During the first compile, all values are *reduced*, which means that their
36
+ * types are brought to the lowest form before being dump as strings. This
37
+ * handles math equations, variable dereferences, and the like.
38
+ *
39
+ * The `compile` function of `Compiler` is the entry point.
40
+ *
41
+ * In summary:
42
+ *
43
+ * The `Compiler` class creates an instance of the parser, feeds it SCSS code,
44
+ * then transforms the resulting tree to a CSS tree. This class also holds the
45
+ * evaluation context, such as all available mixins and variables at any given
46
+ * time.
47
+ *
48
+ * The `Parser` class is only concerned with parsing its input.
49
+ *
50
+ * The `Formatter` takes a CSS tree, and dumps it to a formatted string,
51
+ * handling things like indentation.
52
+ */
53
+
54
+ /**
55
+ * SCSS compiler
56
+ *
57
+ * @author Leaf Corcoran <leafot@gmail.com>
58
+ */
59
+ class Compiler
60
+ {
61
+ const LINE_COMMENTS = 1;
62
+ const DEBUG_INFO = 2;
63
+
64
+ const WITH_RULE = 1;
65
+ const WITH_MEDIA = 2;
66
+ const WITH_SUPPORTS = 4;
67
+ const WITH_ALL = 7;
68
+
69
+ const SOURCE_MAP_NONE = 0;
70
+ const SOURCE_MAP_INLINE = 1;
71
+ const SOURCE_MAP_FILE = 2;
72
+
73
+ /**
74
+ * @var array
75
+ */
76
+ protected static $operatorNames = [
77
+ '+' => 'add',
78
+ '-' => 'sub',
79
+ '*' => 'mul',
80
+ '/' => 'div',
81
+ '%' => 'mod',
82
+
83
+ '==' => 'eq',
84
+ '!=' => 'neq',
85
+ '<' => 'lt',
86
+ '>' => 'gt',
87
+
88
+ '<=' => 'lte',
89
+ '>=' => 'gte',
90
+ '<=>' => 'cmp',
91
+ ];
92
+
93
+ /**
94
+ * @var array
95
+ */
96
+ protected static $namespaces = [
97
+ 'special' => '%',
98
+ 'mixin' => '@',
99
+ 'function' => '^',
100
+ ];
101
+
102
+ public static $true = [Type::T_KEYWORD, 'true'];
103
+ public static $false = [Type::T_KEYWORD, 'false'];
104
+ public static $NaN = [Type::T_KEYWORD, 'NaN'];
105
+ public static $Infinity = [Type::T_KEYWORD, 'Infinity'];
106
+ public static $null = [Type::T_NULL];
107
+ public static $nullString = [Type::T_STRING, '', []];
108
+ public static $defaultValue = [Type::T_KEYWORD, ''];
109
+ public static $selfSelector = [Type::T_SELF];
110
+ public static $emptyList = [Type::T_LIST, '', []];
111
+ public static $emptyMap = [Type::T_MAP, [], []];
112
+ public static $emptyString = [Type::T_STRING, '"', []];
113
+ public static $with = [Type::T_KEYWORD, 'with'];
114
+ public static $without = [Type::T_KEYWORD, 'without'];
115
+
116
+ protected $importPaths = [''];
117
+ protected $importCache = [];
118
+ protected $importedFiles = [];
119
+ protected $userFunctions = [];
120
+ protected $registeredVars = [];
121
+ protected $registeredFeatures = [
122
+ 'extend-selector-pseudoclass' => false,
123
+ 'at-error' => true,
124
+ 'units-level-3' => false,
125
+ 'global-variable-shadowing' => false,
126
+ ];
127
+
128
+ protected $encoding = null;
129
+ protected $lineNumberStyle = null;
130
+
131
+ protected $sourceMap = self::SOURCE_MAP_NONE;
132
+ protected $sourceMapOptions = [];
133
+
134
+ /**
135
+ * @var string|\ScssPhp\ScssPhp\Formatter
136
+ */
137
+ protected $formatter = 'ScssPhp\ScssPhp\Formatter\Nested';
138
+
139
+ protected $rootEnv;
140
+ protected $rootBlock;
141
+
142
+ /**
143
+ * @var \ScssPhp\ScssPhp\Compiler\Environment
144
+ */
145
+ protected $env;
146
+ protected $scope;
147
+ protected $storeEnv;
148
+ protected $charsetSeen;
149
+ protected $sourceNames;
150
+
151
+ protected $cache;
152
+
153
+ protected $indentLevel;
154
+ protected $extends;
155
+ protected $extendsMap;
156
+ protected $parsedFiles;
157
+ protected $parser;
158
+ protected $sourceIndex;
159
+ protected $sourceLine;
160
+ protected $sourceColumn;
161
+ protected $stderr;
162
+ protected $shouldEvaluate;
163
+ protected $ignoreErrors;
164
+ protected $ignoreCallStackMessage = false;
165
+
166
+ protected $callStack = [];
167
+
168
+ /**
169
+ * Constructor
170
+ *
171
+ * @param array|null $cacheOptions
172
+ */
173
+ public function __construct($cacheOptions = null)
174
+ {
175
+ $this->parsedFiles = [];
176
+ $this->sourceNames = [];
177
+
178
+ if ($cacheOptions) {
179
+ $this->cache = new Cache($cacheOptions);
180
+ }
181
+
182
+ $this->stderr = fopen('php://stderr', 'w');
183
+ }
184
+
185
+ /**
186
+ * Get compiler options
187
+ *
188
+ * @return array
189
+ */
190
+ public function getCompileOptions()
191
+ {
192
+ $options = [
193
+ 'importPaths' => $this->importPaths,
194
+ 'registeredVars' => $this->registeredVars,
195
+ 'registeredFeatures' => $this->registeredFeatures,
196
+ 'encoding' => $this->encoding,
197
+ 'sourceMap' => serialize($this->sourceMap),
198
+ 'sourceMapOptions' => $this->sourceMapOptions,
199
+ 'formatter' => $this->formatter,
200
+ ];
201
+
202
+ return $options;
203
+ }
204
+
205
+ /**
206
+ * Set an alternative error output stream, for testing purpose only
207
+ *
208
+ * @param resource $handle
209
+ */
210
+ public function setErrorOuput($handle)
211
+ {
212
+ $this->stderr = $handle;
213
+ }
214
+
215
+ /**
216
+ * Compile scss
217
+ *
218
+ * @api
219
+ *
220
+ * @param string $code
221
+ * @param string $path
222
+ *
223
+ * @return string
224
+ */
225
+ public function compile($code, $path = null)
226
+ {
227
+ if ($this->cache) {
228
+ $cacheKey = ($path ? $path : "(stdin)") . ":" . md5($code);
229
+ $compileOptions = $this->getCompileOptions();
230
+ $cache = $this->cache->getCache("compile", $cacheKey, $compileOptions);
231
+
232
+ if (\is_array($cache) && isset($cache['dependencies']) && isset($cache['out'])) {
233
+ // check if any dependency file changed before accepting the cache
234
+ foreach ($cache['dependencies'] as $file => $mtime) {
235
+ if (! is_file($file) || filemtime($file) !== $mtime) {
236
+ unset($cache);
237
+ break;
238
+ }
239
+ }
240
+
241
+ if (isset($cache)) {
242
+ return $cache['out'];
243
+ }
244
+ }
245
+ }
246
+
247
+
248
+ $this->indentLevel = -1;
249
+ $this->extends = [];
250
+ $this->extendsMap = [];
251
+ $this->sourceIndex = null;
252
+ $this->sourceLine = null;
253
+ $this->sourceColumn = null;
254
+ $this->env = null;
255
+ $this->scope = null;
256
+ $this->storeEnv = null;
257
+ $this->charsetSeen = null;
258
+ $this->shouldEvaluate = null;
259
+ $this->ignoreCallStackMessage = false;
260
+
261
+ $this->parser = $this->parserFactory($path);
262
+ $tree = $this->parser->parse($code);
263
+ $this->parser = null;
264
+
265
+ $this->formatter = new $this->formatter();
266
+ $this->rootBlock = null;
267
+ $this->rootEnv = $this->pushEnv($tree);
268
+
269
+ $this->injectVariables($this->registeredVars);
270
+ $this->compileRoot($tree);
271
+ $this->popEnv();
272
+
273
+ $sourceMapGenerator = null;
274
+
275
+ if ($this->sourceMap) {
276
+ if (\is_object($this->sourceMap) && $this->sourceMap instanceof SourceMapGenerator) {
277
+ $sourceMapGenerator = $this->sourceMap;
278
+ $this->sourceMap = self::SOURCE_MAP_FILE;
279
+ } elseif ($this->sourceMap !== self::SOURCE_MAP_NONE) {
280
+ $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions);
281
+ }
282
+ }
283
+
284
+ $out = $this->formatter->format($this->scope, $sourceMapGenerator);
285
+
286
+ if (! empty($out) && $this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) {
287
+ $sourceMap = $sourceMapGenerator->generateJson();
288
+ $sourceMapUrl = null;
289
+
290
+ switch ($this->sourceMap) {
291
+ case self::SOURCE_MAP_INLINE:
292
+ $sourceMapUrl = sprintf('data:application/json,%s', Util::encodeURIComponent($sourceMap));
293
+ break;
294
+
295
+ case self::SOURCE_MAP_FILE:
296
+ $sourceMapUrl = $sourceMapGenerator->saveMap($sourceMap);
297
+ break;
298
+ }
299
+
300
+ $out .= sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl);
301
+ }
302
+
303
+ if ($this->cache && isset($cacheKey) && isset($compileOptions)) {
304
+ $v = [
305
+ 'dependencies' => $this->getParsedFiles(),
306
+ 'out' => &$out,
307
+ ];
308
+
309
+ $this->cache->setCache("compile", $cacheKey, $v, $compileOptions);
310
+ }
311
+
312
+ return $out;
313
+ }
314
+
315
+ /**
316
+ * Instantiate parser
317
+ *
318
+ * @param string $path
319
+ *
320
+ * @return \ScssPhp\ScssPhp\Parser
321
+ */
322
+ protected function parserFactory($path)
323
+ {
324
+ // https://sass-lang.com/documentation/at-rules/import
325
+ // CSS files imported by Sass don’t allow any special Sass features.
326
+ // In order to make sure authors don’t accidentally write Sass in their CSS,
327
+ // all Sass features that aren’t also valid CSS will produce errors.
328
+ // Otherwise, the CSS will be rendered as-is. It can even be extended!
329
+ $cssOnly = false;
330
+
331
+ if (substr($path, '-4') === '.css') {
332
+ $cssOnly = true;
333
+ }
334
+
335
+ $parser = new Parser($path, \count($this->sourceNames), $this->encoding, $this->cache, $cssOnly);
336
+
337
+ $this->sourceNames[] = $path;
338
+ $this->addParsedFile($path);
339
+
340
+ return $parser;
341
+ }
342
+
343
+ /**
344
+ * Is self extend?
345
+ *
346
+ * @param array $target
347
+ * @param array $origin
348
+ *
349
+ * @return boolean
350
+ */
351
+ protected function isSelfExtend($target, $origin)
352
+ {
353
+ foreach ($origin as $sel) {
354
+ if (\in_array($target, $sel)) {
355
+ return true;
356
+ }
357
+ }
358
+
359
+ return false;
360
+ }
361
+
362
+ /**
363
+ * Push extends
364
+ *
365
+ * @param array $target
366
+ * @param array $origin
367
+ * @param array|null $block
368
+ */
369
+ protected function pushExtends($target, $origin, $block)
370
+ {
371
+ if ($this->isSelfExtend($target, $origin)) {
372
+ return;
373
+ }
374
+
375
+ $i = \count($this->extends);
376
+ $this->extends[] = [$target, $origin, $block];
377
+
378
+ foreach ($target as $part) {
379
+ if (isset($this->extendsMap[$part])) {
380
+ $this->extendsMap[$part][] = $i;
381
+ } else {
382
+ $this->extendsMap[$part] = [$i];
383
+ }
384
+ }
385
+ }
386
+
387
+ /**
388
+ * Make output block
389
+ *
390
+ * @param string $type
391
+ * @param array $selectors
392
+ *
393
+ * @return \ScssPhp\ScssPhp\Formatter\OutputBlock
394
+ */
395
+ protected function makeOutputBlock($type, $selectors = null)
396
+ {
397
+ $out = new OutputBlock;
398
+ $out->type = $type;
399
+ $out->lines = [];
400
+ $out->children = [];
401
+ $out->parent = $this->scope;
402
+ $out->selectors = $selectors;
403
+ $out->depth = $this->env->depth;
404
+
405
+ if ($this->env->block instanceof Block) {
406
+ $out->sourceName = $this->env->block->sourceName;
407
+ $out->sourceLine = $this->env->block->sourceLine;
408
+ $out->sourceColumn = $this->env->block->sourceColumn;
409
+ } else {
410
+ $out->sourceName = null;
411
+ $out->sourceLine = null;
412
+ $out->sourceColumn = null;
413
+ }
414
+
415
+ return $out;
416
+ }
417
+
418
+ /**
419
+ * Compile root
420
+ *
421
+ * @param \ScssPhp\ScssPhp\Block $rootBlock
422
+ */
423
+ protected function compileRoot(Block $rootBlock)
424
+ {
425
+ $this->rootBlock = $this->scope = $this->makeOutputBlock(Type::T_ROOT);
426
+
427
+ $this->compileChildrenNoReturn($rootBlock->children, $this->scope);
428
+ $this->flattenSelectors($this->scope);
429
+ $this->missingSelectors();
430
+ }
431
+
432
+ /**
433
+ * Report missing selectors
434
+ */
435
+ protected function missingSelectors()
436
+ {
437
+ foreach ($this->extends as $extend) {
438
+ if (isset($extend[3])) {
439
+ continue;
440
+ }
441
+
442
+ list($target, $origin, $block) = $extend;
443
+
444
+ // ignore if !optional
445
+ if ($block[2]) {
446
+ continue;
447
+ }
448
+
449
+ $target = implode(' ', $target);
450
+ $origin = $this->collapseSelectors($origin);
451
+
452
+ $this->sourceLine = $block[Parser::SOURCE_LINE];
453
+ $this->throwError("\"$origin\" failed to @extend \"$target\". The selector \"$target\" was not found.");
454
+ }
455
+ }
456
+
457
+ /**
458
+ * Flatten selectors
459
+ *
460
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
461
+ * @param string $parentKey
462
+ */
463
+ protected function flattenSelectors(OutputBlock $block, $parentKey = null)
464
+ {
465
+ if ($block->selectors) {
466
+ $selectors = [];
467
+
468
+ foreach ($block->selectors as $s) {
469
+ $selectors[] = $s;
470
+
471
+ if (! \is_array($s)) {
472
+ continue;
473
+ }
474
+
475
+ // check extends
476
+ if (! empty($this->extendsMap)) {
477
+ $this->matchExtends($s, $selectors);
478
+
479
+ // remove duplicates
480
+ array_walk($selectors, function (&$value) {
481
+ $value = serialize($value);
482
+ });
483
+
484
+ $selectors = array_unique($selectors);
485
+
486
+ array_walk($selectors, function (&$value) {
487
+ $value = unserialize($value);
488
+ });
489
+ }
490
+ }
491
+
492
+ $block->selectors = [];
493
+ $placeholderSelector = false;
494
+
495
+ foreach ($selectors as $selector) {
496
+ if ($this->hasSelectorPlaceholder($selector)) {
497
+ $placeholderSelector = true;
498
+ continue;
499
+ }
500
+
501
+ $block->selectors[] = $this->compileSelector($selector);
502
+ }
503
+
504
+ if ($placeholderSelector && 0 === \count($block->selectors) && null !== $parentKey) {
505
+ unset($block->parent->children[$parentKey]);
506
+
507
+ return;
508
+ }
509
+ }
510
+
511
+ foreach ($block->children as $key => $child) {
512
+ $this->flattenSelectors($child, $key);
513
+ }
514
+ }
515
+
516
+ /**
517
+ * Glue parts of :not( or :nth-child( ... that are in general splitted in selectors parts
518
+ *
519
+ * @param array $parts
520
+ *
521
+ * @return array
522
+ */
523
+ protected function glueFunctionSelectors($parts)
524
+ {
525
+ $new = [];
526
+
527
+ foreach ($parts as $part) {
528
+ if (\is_array($part)) {
529
+ $part = $this->glueFunctionSelectors($part);
530
+ $new[] = $part;
531
+ } else {
532
+ // a selector part finishing with a ) is the last part of a :not( or :nth-child(
533
+ // and need to be joined to this
534
+ if (\count($new) && \is_string($new[\count($new) - 1]) &&
535
+ \strlen($part) && substr($part, -1) === ')' && strpos($part, '(') === false
536
+ ) {
537
+ while (\count($new)>1 && substr($new[\count($new) - 1], -1) !== '(') {
538
+ $part = array_pop($new) . $part;
539
+ }
540
+ $new[\count($new) - 1] .= $part;
541
+ } else {
542
+ $new[] = $part;
543
+ }
544
+ }
545
+ }
546
+
547
+ return $new;
548
+ }
549
+
550
+ /**
551
+ * Match extends
552
+ *
553
+ * @param array $selector
554
+ * @param array $out
555
+ * @param integer $from
556
+ * @param boolean $initial
557
+ */
558
+ protected function matchExtends($selector, &$out, $from = 0, $initial = true)
559
+ {
560
+ static $partsPile = [];
561
+ $selector = $this->glueFunctionSelectors($selector);
562
+
563
+ if (\count($selector) == 1 && \in_array(reset($selector), $partsPile)) {
564
+ return;
565
+ }
566
+
567
+ $outRecurs = [];
568
+
569
+ foreach ($selector as $i => $part) {
570
+ if ($i < $from) {
571
+ continue;
572
+ }
573
+
574
+ // check that we are not building an infinite loop of extensions
575
+ // if the new part is just including a previous part don't try to extend anymore
576
+ if (\count($part) > 1) {
577
+ foreach ($partsPile as $previousPart) {
578
+ if (! \count(array_diff($previousPart, $part))) {
579
+ continue 2;
580
+ }
581
+ }
582
+ }
583
+
584
+ $partsPile[] = $part;
585
+
586
+ if ($this->matchExtendsSingle($part, $origin, $initial)) {
587
+ $after = \array_slice($selector, $i + 1);
588
+ $before = \array_slice($selector, 0, $i);
589
+ list($before, $nonBreakableBefore) = $this->extractRelationshipFromFragment($before);
590
+
591
+ foreach ($origin as $new) {
592
+ $k = 0;
593
+
594
+ // remove shared parts
595
+ if (\count($new) > 1) {
596
+ while ($k < $i && isset($new[$k]) && $selector[$k] === $new[$k]) {
597
+ $k++;
598
+ }
599
+ }
600
+
601
+ if (\count($nonBreakableBefore) and $k == \count($new)) {
602
+ $k--;
603
+ }
604
+
605
+ $replacement = [];
606
+ $tempReplacement = $k > 0 ? \array_slice($new, $k) : $new;
607
+
608
+ for ($l = \count($tempReplacement) - 1; $l >= 0; $l--) {
609
+ $slice = [];
610
+
611
+ foreach ($tempReplacement[$l] as $chunk) {
612
+ if (! \in_array($chunk, $slice)) {
613
+ $slice[] = $chunk;
614
+ }
615
+ }
616
+
617
+ array_unshift($replacement, $slice);
618
+
619
+ if (! $this->isImmediateRelationshipCombinator(end($slice))) {
620
+ break;
621
+ }
622
+ }
623
+
624
+ $afterBefore = $l != 0 ? \array_slice($tempReplacement, 0, $l) : [];
625
+
626
+ // Merge shared direct relationships.
627
+ $mergedBefore = $this->mergeDirectRelationships($afterBefore, $nonBreakableBefore);
628
+
629
+ $result = array_merge(
630
+ $before,
631
+ $mergedBefore,
632
+ $replacement,
633
+ $after
634
+ );
635
+
636
+ if ($result === $selector) {
637
+ continue;
638
+ }
639
+
640
+ $this->pushOrMergeExtentedSelector($out, $result);
641
+
642
+ // recursively check for more matches
643
+ $startRecurseFrom = \count($before) + min(\count($nonBreakableBefore), \count($mergedBefore));
644
+
645
+ if (\count($origin) > 1) {
646
+ $this->matchExtends($result, $out, $startRecurseFrom, false);
647
+ } else {
648
+ $this->matchExtends($result, $outRecurs, $startRecurseFrom, false);
649
+ }
650
+
651
+ // selector sequence merging
652
+ if (! empty($before) && \count($new) > 1) {
653
+ $preSharedParts = $k > 0 ? \array_slice($before, 0, $k) : [];
654
+ $postSharedParts = $k > 0 ? \array_slice($before, $k) : $before;
655
+
656
+ list($betweenSharedParts, $nonBreakabl2) = $this->extractRelationshipFromFragment($afterBefore);
657
+
658
+ $result2 = array_merge(
659
+ $preSharedParts,
660
+ $betweenSharedParts,
661
+ $postSharedParts,
662
+ $nonBreakabl2,
663
+ $nonBreakableBefore,
664
+ $replacement,
665
+ $after
666
+ );
667
+
668
+ $this->pushOrMergeExtentedSelector($out, $result2);
669
+ }
670
+ }
671
+ }
672
+ array_pop($partsPile);
673
+ }
674
+
675
+ while (\count($outRecurs)) {
676
+ $result = array_shift($outRecurs);
677
+ $this->pushOrMergeExtentedSelector($out, $result);
678
+ }
679
+ }
680
+
681
+ /**
682
+ * Test a part for being a pseudo selector
683
+ *
684
+ * @param string $part
685
+ * @param array $matches
686
+ *
687
+ * @return boolean
688
+ */
689
+ protected function isPseudoSelector($part, &$matches)
690
+ {
691
+ if (strpos($part, ":") === 0
692
+ && preg_match(",^::?([\w-]+)\((.+)\)$,", $part, $matches)
693
+ ) {
694
+ return true;
695
+ }
696
+
697
+ return false;
698
+ }
699
+
700
+ /**
701
+ * Push extended selector except if
702
+ * - this is a pseudo selector
703
+ * - same as previous
704
+ * - in a white list
705
+ * in this case we merge the pseudo selector content
706
+ *
707
+ * @param array $out
708
+ * @param array $extended
709
+ */
710
+ protected function pushOrMergeExtentedSelector(&$out, $extended)
711
+ {
712
+ if (\count($out) && \count($extended) === 1 && \count(reset($extended)) === 1) {
713
+ $single = reset($extended);
714
+ $part = reset($single);
715
+
716
+ if ($this->isPseudoSelector($part, $matchesExtended) &&
717
+ \in_array($matchesExtended[1], [ 'slotted' ])
718
+ ) {
719
+ $prev = end($out);
720
+ $prev = $this->glueFunctionSelectors($prev);
721
+
722
+ if (\count($prev) === 1 && \count(reset($prev)) === 1) {
723
+ $single = reset($prev);
724
+ $part = reset($single);
725
+
726
+ if ($this->isPseudoSelector($part, $matchesPrev) &&
727
+ $matchesPrev[1] === $matchesExtended[1]
728
+ ) {
729
+ $extended = explode($matchesExtended[1] . '(', $matchesExtended[0], 2);
730
+ $extended[1] = $matchesPrev[2] . ", " . $extended[1];
731
+ $extended = implode($matchesExtended[1] . '(', $extended);
732
+ $extended = [ [ $extended ]];
733
+ array_pop($out);
734
+ }
735
+ }
736
+ }
737
+ }
738
+ $out[] = $extended;
739
+ }
740
+
741
+ /**
742
+ * Match extends single
743
+ *
744
+ * @param array $rawSingle
745
+ * @param array $outOrigin
746
+ * @param boolean $initial
747
+ *
748
+ * @return boolean
749
+ */
750
+ protected function matchExtendsSingle($rawSingle, &$outOrigin, $initial = true)
751
+ {
752
+ $counts = [];
753
+ $single = [];
754
+
755
+ // simple usual cases, no need to do the whole trick
756
+ if (\in_array($rawSingle, [['>'],['+'],['~']])) {
757
+ return false;
758
+ }
759
+
760
+ foreach ($rawSingle as $part) {
761
+ // matches Number
762
+ if (! \is_string($part)) {
763
+ return false;
764
+ }
765
+
766
+ if (! preg_match('/^[\[.:#%]/', $part) && \count($single)) {
767
+ $single[\count($single) - 1] .= $part;
768
+ } else {
769
+ $single[] = $part;
770
+ }
771
+ }
772
+
773
+ $extendingDecoratedTag = false;
774
+
775
+ if (\count($single) > 1) {
776
+ $matches = null;
777
+ $extendingDecoratedTag = preg_match('/^[a-z0-9]+$/i', $single[0], $matches) ? $matches[0] : false;
778
+ }
779
+
780
+ $outOrigin = [];
781
+ $found = false;
782
+
783
+ foreach ($single as $k => $part) {
784
+ if (isset($this->extendsMap[$part])) {
785
+ foreach ($this->extendsMap[$part] as $idx) {
786
+ $counts[$idx] = isset($counts[$idx]) ? $counts[$idx] + 1 : 1;
787
+ }
788
+ }
789
+
790
+ if ($initial &&
791
+ $this->isPseudoSelector($part, $matches) &&
792
+ ! \in_array($matches[1], [ 'not' ])
793
+ ) {
794
+ $buffer = $matches[2];
795
+ $parser = $this->parserFactory(__METHOD__);
796
+
797
+ if ($parser->parseSelector($buffer, $subSelectors)) {
798
+ foreach ($subSelectors as $ksub => $subSelector) {
799
+ $subExtended = [];
800
+ $this->matchExtends($subSelector, $subExtended, 0, false);
801
+
802
+ if ($subExtended) {
803
+ $subSelectorsExtended = $subSelectors;
804
+ $subSelectorsExtended[$ksub] = $subExtended;
805
+
806
+ foreach ($subSelectorsExtended as $ksse => $sse) {
807
+ $subSelectorsExtended[$ksse] = $this->collapseSelectors($sse);
808
+ }
809
+
810
+ $subSelectorsExtended = implode(', ', $subSelectorsExtended);
811
+ $singleExtended = $single;
812
+ $singleExtended[$k] = str_replace("(".$buffer.")", "($subSelectorsExtended)", $part);
813
+ $outOrigin[] = [ $singleExtended ];
814
+ $found = true;
815
+ }
816
+ }
817
+ }
818
+ }
819
+ }
820
+
821
+ foreach ($counts as $idx => $count) {
822
+ list($target, $origin, /* $block */) = $this->extends[$idx];
823
+
824
+ $origin = $this->glueFunctionSelectors($origin);
825
+
826
+ // check count
827
+ if ($count !== \count($target)) {
828
+ continue;
829
+ }
830
+
831
+ $this->extends[$idx][3] = true;
832
+
833
+ $rem = array_diff($single, $target);
834
+
835
+ foreach ($origin as $j => $new) {
836
+ // prevent infinite loop when target extends itself
837
+ if ($this->isSelfExtend($single, $origin)) {
838
+ return false;
839
+ }
840
+
841
+ $replacement = end($new);
842
+
843
+ // Extending a decorated tag with another tag is not possible.
844
+ if ($extendingDecoratedTag && $replacement[0] != $extendingDecoratedTag &&
845
+ preg_match('/^[a-z0-9]+$/i', $replacement[0])
846
+ ) {
847
+ unset($origin[$j]);
848
+ continue;
849
+ }
850
+
851
+ $combined = $this->combineSelectorSingle($replacement, $rem);
852
+
853
+ if (\count(array_diff($combined, $origin[$j][\count($origin[$j]) - 1]))) {
854
+ $origin[$j][\count($origin[$j]) - 1] = $combined;
855
+ }
856
+ }
857
+
858
+ $outOrigin = array_merge($outOrigin, $origin);
859
+
860
+ $found = true;
861
+ }
862
+
863
+ return $found;
864
+ }
865
+
866
+ /**
867
+ * Extract a relationship from the fragment.
868
+ *
869
+ * When extracting the last portion of a selector we will be left with a
870
+ * fragment which may end with a direction relationship combinator. This
871
+ * method will extract the relationship fragment and return it along side
872
+ * the rest.
873
+ *
874
+ * @param array $fragment The selector fragment maybe ending with a direction relationship combinator.
875
+ *
876
+ * @return array The selector without the relationship fragment if any, the relationship fragment.
877
+ */
878
+ protected function extractRelationshipFromFragment(array $fragment)
879
+ {
880
+ $parents = [];
881
+ $children = [];
882
+
883
+ $j = $i = \count($fragment);
884
+
885
+ for (;;) {
886
+ $children = $j != $i ? \array_slice($fragment, $j, $i - $j) : [];
887
+ $parents = \array_slice($fragment, 0, $j);
888
+ $slice = end($parents);
889
+
890
+ if (empty($slice) || ! $this->isImmediateRelationshipCombinator($slice[0])) {
891
+ break;
892
+ }
893
+
894
+ $j -= 2;
895
+ }
896
+
897
+ return [$parents, $children];
898
+ }
899
+
900
+ /**
901
+ * Combine selector single
902
+ *
903
+ * @param array $base
904
+ * @param array $other
905
+ *
906
+ * @return array
907
+ */
908
+ protected function combineSelectorSingle($base, $other)
909
+ {
910
+ $tag = [];
911
+ $out = [];
912
+ $wasTag = false;
913
+ $pseudo = [];
914
+
915
+ while (\count($other) && strpos(end($other), ':')===0) {
916
+ array_unshift($pseudo, array_pop($other));
917
+ }
918
+
919
+ foreach ([array_reverse($base), array_reverse($other)] as $single) {
920
+ foreach ($single as $part) {
921
+ if (preg_match('/^[\[:]/', $part)) {
922
+ $out[] = $part;
923
+ $wasTag = false;
924
+ } elseif (preg_match('/^[\.#]/', $part)) {
925
+ array_unshift($out, $part);
926
+ $wasTag = false;
927
+ } elseif (preg_match('/^[^_-]/', $part)) {
928
+ $tag[] = $part;
929
+ $wasTag = true;
930
+ } elseif ($wasTag) {
931
+ $tag[\count($tag) - 1] .= $part;
932
+ } else {
933
+ $out[] = $part;
934
+ }
935
+ }
936
+ }
937
+
938
+ if (\count($tag)) {
939
+ array_unshift($out, $tag[0]);
940
+ }
941
+
942
+ while (\count($pseudo)) {
943
+ $out[] = array_shift($pseudo);
944
+ }
945
+
946
+ return $out;
947
+ }
948
+
949
+ /**
950
+ * Compile media
951
+ *
952
+ * @param \ScssPhp\ScssPhp\Block $media
953
+ */
954
+ protected function compileMedia(Block $media)
955
+ {
956
+ $this->pushEnv($media);
957
+
958
+ $mediaQueries = $this->compileMediaQuery($this->multiplyMedia($this->env));
959
+
960
+ if (! empty($mediaQueries) && $mediaQueries) {
961
+ $previousScope = $this->scope;
962
+ $parentScope = $this->mediaParent($this->scope);
963
+
964
+ foreach ($mediaQueries as $mediaQuery) {
965
+ $this->scope = $this->makeOutputBlock(Type::T_MEDIA, [$mediaQuery]);
966
+
967
+ $parentScope->children[] = $this->scope;
968
+ $parentScope = $this->scope;
969
+ }
970
+
971
+ // top level properties in a media cause it to be wrapped
972
+ $needsWrap = false;
973
+
974
+ foreach ($media->children as $child) {
975
+ $type = $child[0];
976
+
977
+ if ($type !== Type::T_BLOCK &&
978
+ $type !== Type::T_MEDIA &&
979
+ $type !== Type::T_DIRECTIVE &&
980
+ $type !== Type::T_IMPORT
981
+ ) {
982
+ $needsWrap = true;
983
+ break;
984
+ }
985
+ }
986
+
987
+ if ($needsWrap) {
988
+ $wrapped = new Block;
989
+ $wrapped->sourceName = $media->sourceName;
990
+ $wrapped->sourceIndex = $media->sourceIndex;
991
+ $wrapped->sourceLine = $media->sourceLine;
992
+ $wrapped->sourceColumn = $media->sourceColumn;
993
+ $wrapped->selectors = [];
994
+ $wrapped->comments = [];
995
+ $wrapped->parent = $media;
996
+ $wrapped->children = $media->children;
997
+
998
+ $media->children = [[Type::T_BLOCK, $wrapped]];
999
+
1000
+ if (isset($this->lineNumberStyle)) {
1001
+ $annotation = $this->makeOutputBlock(Type::T_COMMENT);
1002
+ $annotation->depth = 0;
1003
+
1004
+ $file = $this->sourceNames[$media->sourceIndex];
1005
+ $line = $media->sourceLine;
1006
+
1007
+ switch ($this->lineNumberStyle) {
1008
+ case static::LINE_COMMENTS:
1009
+ $annotation->lines[] = '/* line ' . $line
1010
+ . ($file ? ', ' . $file : '')
1011
+ . ' */';
1012
+ break;
1013
+
1014
+ case static::DEBUG_INFO:
1015
+ $annotation->lines[] = '@media -sass-debug-info{'
1016
+ . ($file ? 'filename{font-family:"' . $file . '"}' : '')
1017
+ . 'line{font-family:' . $line . '}}';
1018
+ break;
1019
+ }
1020
+
1021
+ $this->scope->children[] = $annotation;
1022
+ }
1023
+ }
1024
+
1025
+ $this->compileChildrenNoReturn($media->children, $this->scope);
1026
+
1027
+ $this->scope = $previousScope;
1028
+ }
1029
+
1030
+ $this->popEnv();
1031
+ }
1032
+
1033
+ /**
1034
+ * Media parent
1035
+ *
1036
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope
1037
+ *
1038
+ * @return \ScssPhp\ScssPhp\Formatter\OutputBlock
1039
+ */
1040
+ protected function mediaParent(OutputBlock $scope)
1041
+ {
1042
+ while (! empty($scope->parent)) {
1043
+ if (! empty($scope->type) && $scope->type !== Type::T_MEDIA) {
1044
+ break;
1045
+ }
1046
+
1047
+ $scope = $scope->parent;
1048
+ }
1049
+
1050
+ return $scope;
1051
+ }
1052
+
1053
+ /**
1054
+ * Compile directive
1055
+ *
1056
+ * @param \ScssPhp\ScssPhp\Block|array $block
1057
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
1058
+ */
1059
+ protected function compileDirective($directive, OutputBlock $out)
1060
+ {
1061
+ if (\is_array($directive)) {
1062
+ $s = '@' . $directive[0];
1063
+
1064
+ if (! empty($directive[1])) {
1065
+ $s .= ' ' . $this->compileValue($directive[1]);
1066
+ }
1067
+
1068
+ $this->appendRootDirective($s . ';', $out);
1069
+ } else {
1070
+ $s = '@' . $directive->name;
1071
+
1072
+ if (! empty($directive->value)) {
1073
+ $s .= ' ' . $this->compileValue($directive->value);
1074
+ }
1075
+
1076
+ if ($directive->name === 'keyframes' || substr($directive->name, -10) === '-keyframes') {
1077
+ $this->compileKeyframeBlock($directive, [$s]);
1078
+ } else {
1079
+ $this->compileNestedBlock($directive, [$s]);
1080
+ }
1081
+ }
1082
+ }
1083
+
1084
+ /**
1085
+ * Compile at-root
1086
+ *
1087
+ * @param \ScssPhp\ScssPhp\Block $block
1088
+ */
1089
+ protected function compileAtRoot(Block $block)
1090
+ {
1091
+ $env = $this->pushEnv($block);
1092
+ $envs = $this->compactEnv($env);
1093
+ list($with, $without) = $this->compileWith(isset($block->with) ? $block->with : null);
1094
+
1095
+ // wrap inline selector
1096
+ if ($block->selector) {
1097
+ $wrapped = new Block;
1098
+ $wrapped->sourceName = $block->sourceName;
1099
+ $wrapped->sourceIndex = $block->sourceIndex;
1100
+ $wrapped->sourceLine = $block->sourceLine;
1101
+ $wrapped->sourceColumn = $block->sourceColumn;
1102
+ $wrapped->selectors = $block->selector;
1103
+ $wrapped->comments = [];
1104
+ $wrapped->parent = $block;
1105
+ $wrapped->children = $block->children;
1106
+ $wrapped->selfParent = $block->selfParent;
1107
+
1108
+ $block->children = [[Type::T_BLOCK, $wrapped]];
1109
+ $block->selector = null;
1110
+ }
1111
+
1112
+ $selfParent = $block->selfParent;
1113
+
1114
+ if (! $block->selfParent->selectors && isset($block->parent) && $block->parent &&
1115
+ isset($block->parent->selectors) && $block->parent->selectors
1116
+ ) {
1117
+ $selfParent = $block->parent;
1118
+ }
1119
+
1120
+ $this->env = $this->filterWithWithout($envs, $with, $without);
1121
+
1122
+ $saveScope = $this->scope;
1123
+ $this->scope = $this->filterScopeWithWithout($saveScope, $with, $without);
1124
+
1125
+ // propagate selfParent to the children where they still can be useful
1126
+ $this->compileChildrenNoReturn($block->children, $this->scope, $selfParent);
1127
+
1128
+ $this->scope = $this->completeScope($this->scope, $saveScope);
1129
+ $this->scope = $saveScope;
1130
+ $this->env = $this->extractEnv($envs);
1131
+
1132
+ $this->popEnv();
1133
+ }
1134
+
1135
+ /**
1136
+ * Filter at-root scope depending of with/without option
1137
+ *
1138
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope
1139
+ * @param array $with
1140
+ * @param array $without
1141
+ *
1142
+ * @return mixed
1143
+ */
1144
+ protected function filterScopeWithWithout($scope, $with, $without)
1145
+ {
1146
+ $filteredScopes = [];
1147
+ $childStash = [];
1148
+
1149
+ if ($scope->type === TYPE::T_ROOT) {
1150
+ return $scope;
1151
+ }
1152
+
1153
+ // start from the root
1154
+ while ($scope->parent && $scope->parent->type !== TYPE::T_ROOT) {
1155
+ array_unshift($childStash, $scope);
1156
+ $scope = $scope->parent;
1157
+ }
1158
+
1159
+ for (;;) {
1160
+ if (! $scope) {
1161
+ break;
1162
+ }
1163
+
1164
+ if ($this->isWith($scope, $with, $without)) {
1165
+ $s = clone $scope;
1166
+ $s->children = [];
1167
+ $s->lines = [];
1168
+ $s->parent = null;
1169
+
1170
+ if ($s->type !== Type::T_MEDIA && $s->type !== Type::T_DIRECTIVE) {
1171
+ $s->selectors = [];
1172
+ }
1173
+
1174
+ $filteredScopes[] = $s;
1175
+ }
1176
+
1177
+ if (\count($childStash)) {
1178
+ $scope = array_shift($childStash);
1179
+ } elseif ($scope->children) {
1180
+ $scope = end($scope->children);
1181
+ } else {
1182
+ $scope = null;
1183
+ }
1184
+ }
1185
+
1186
+ if (! \count($filteredScopes)) {
1187
+ return $this->rootBlock;
1188
+ }
1189
+
1190
+ $newScope = array_shift($filteredScopes);
1191
+ $newScope->parent = $this->rootBlock;
1192
+
1193
+ $this->rootBlock->children[] = $newScope;
1194
+
1195
+ $p = &$newScope;
1196
+
1197
+ while (\count($filteredScopes)) {
1198
+ $s = array_shift($filteredScopes);
1199
+ $s->parent = $p;
1200
+ $p->children[] = $s;
1201
+ $newScope = &$p->children[0];
1202
+ $p = &$p->children[0];
1203
+ }
1204
+
1205
+ return $newScope;
1206
+ }
1207
+
1208
+ /**
1209
+ * found missing selector from a at-root compilation in the previous scope
1210
+ * (if at-root is just enclosing a property, the selector is in the parent tree)
1211
+ *
1212
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope
1213
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $previousScope
1214
+ *
1215
+ * @return mixed
1216
+ */
1217
+ protected function completeScope($scope, $previousScope)
1218
+ {
1219
+ if (! $scope->type && (! $scope->selectors || ! \count($scope->selectors)) && \count($scope->lines)) {
1220
+ $scope->selectors = $this->findScopeSelectors($previousScope, $scope->depth);
1221
+ }
1222
+
1223
+ if ($scope->children) {
1224
+ foreach ($scope->children as $k => $c) {
1225
+ $scope->children[$k] = $this->completeScope($c, $previousScope);
1226
+ }
1227
+ }
1228
+
1229
+ return $scope;
1230
+ }
1231
+
1232
+ /**
1233
+ * Find a selector by the depth node in the scope
1234
+ *
1235
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $scope
1236
+ * @param integer $depth
1237
+ *
1238
+ * @return array
1239
+ */
1240
+ protected function findScopeSelectors($scope, $depth)
1241
+ {
1242
+ if ($scope->depth === $depth && $scope->selectors) {
1243
+ return $scope->selectors;
1244
+ }
1245
+
1246
+ if ($scope->children) {
1247
+ foreach (array_reverse($scope->children) as $c) {
1248
+ if ($s = $this->findScopeSelectors($c, $depth)) {
1249
+ return $s;
1250
+ }
1251
+ }
1252
+ }
1253
+
1254
+ return [];
1255
+ }
1256
+
1257
+ /**
1258
+ * Compile @at-root's with: inclusion / without: exclusion into 2 lists uses to filter scope/env later
1259
+ *
1260
+ * @param array $withCondition
1261
+ *
1262
+ * @return array
1263
+ */
1264
+ protected function compileWith($withCondition)
1265
+ {
1266
+ // just compile what we have in 2 lists
1267
+ $with = [];
1268
+ $without = ['rule' => true];
1269
+
1270
+ if ($withCondition) {
1271
+ if ($this->libMapHasKey([$withCondition, static::$with])) {
1272
+ $without = []; // cancel the default
1273
+ $list = $this->coerceList($this->libMapGet([$withCondition, static::$with]));
1274
+
1275
+ foreach ($list[2] as $item) {
1276
+ $keyword = $this->compileStringContent($this->coerceString($item));
1277
+
1278
+ $with[$keyword] = true;
1279
+ }
1280
+ }
1281
+
1282
+ if ($this->libMapHasKey([$withCondition, static::$without])) {
1283
+ $without = []; // cancel the default
1284
+ $list = $this->coerceList($this->libMapGet([$withCondition, static::$without]));
1285
+
1286
+ foreach ($list[2] as $item) {
1287
+ $keyword = $this->compileStringContent($this->coerceString($item));
1288
+
1289
+ $without[$keyword] = true;
1290
+ }
1291
+ }
1292
+ }
1293
+
1294
+ return [$with, $without];
1295
+ }
1296
+
1297
+ /**
1298
+ * Filter env stack
1299
+ *
1300
+ * @param array $envs
1301
+ * @param array $with
1302
+ * @param array $without
1303
+ *
1304
+ * @return \ScssPhp\ScssPhp\Compiler\Environment
1305
+ */
1306
+ protected function filterWithWithout($envs, $with, $without)
1307
+ {
1308
+ $filtered = [];
1309
+
1310
+ foreach ($envs as $e) {
1311
+ if ($e->block && ! $this->isWith($e->block, $with, $without)) {
1312
+ $ec = clone $e;
1313
+ $ec->block = null;
1314
+ $ec->selectors = [];
1315
+
1316
+ $filtered[] = $ec;
1317
+ } else {
1318
+ $filtered[] = $e;
1319
+ }
1320
+ }
1321
+
1322
+ return $this->extractEnv($filtered);
1323
+ }
1324
+
1325
+ /**
1326
+ * Filter WITH rules
1327
+ *
1328
+ * @param \ScssPhp\ScssPhp\Block|\ScssPhp\ScssPhp\Formatter\OutputBlock $block
1329
+ * @param array $with
1330
+ * @param array $without
1331
+ *
1332
+ * @return boolean
1333
+ */
1334
+ protected function isWith($block, $with, $without)
1335
+ {
1336
+ if (isset($block->type)) {
1337
+ if ($block->type === Type::T_MEDIA) {
1338
+ return $this->testWithWithout('media', $with, $without);
1339
+ }
1340
+
1341
+ if ($block->type === Type::T_DIRECTIVE) {
1342
+ if (isset($block->name)) {
1343
+ return $this->testWithWithout($block->name, $with, $without);
1344
+ } elseif (isset($block->selectors) && preg_match(',@(\w+),ims', json_encode($block->selectors), $m)) {
1345
+ return $this->testWithWithout($m[1], $with, $without);
1346
+ } else {
1347
+ return $this->testWithWithout('???', $with, $without);
1348
+ }
1349
+ }
1350
+ } elseif (isset($block->selectors)) {
1351
+ // a selector starting with number is a keyframe rule
1352
+ if (\count($block->selectors)) {
1353
+ $s = reset($block->selectors);
1354
+
1355
+ while (\is_array($s)) {
1356
+ $s = reset($s);
1357
+ }
1358
+
1359
+ if (\is_object($s) && $s instanceof Node\Number) {
1360
+ return $this->testWithWithout('keyframes', $with, $without);
1361
+ }
1362
+ }
1363
+
1364
+ return $this->testWithWithout('rule', $with, $without);
1365
+ }
1366
+
1367
+ return true;
1368
+ }
1369
+
1370
+ /**
1371
+ * Test a single type of block against with/without lists
1372
+ *
1373
+ * @param string $what
1374
+ * @param array $with
1375
+ * @param array $without
1376
+ *
1377
+ * @return boolean
1378
+ * true if the block should be kept, false to reject
1379
+ */
1380
+ protected function testWithWithout($what, $with, $without)
1381
+ {
1382
+
1383
+ // if without, reject only if in the list (or 'all' is in the list)
1384
+ if (\count($without)) {
1385
+ return (isset($without[$what]) || isset($without['all'])) ? false : true;
1386
+ }
1387
+
1388
+ // otherwise reject all what is not in the with list
1389
+ return (isset($with[$what]) || isset($with['all'])) ? true : false;
1390
+ }
1391
+
1392
+
1393
+ /**
1394
+ * Compile keyframe block
1395
+ *
1396
+ * @param \ScssPhp\ScssPhp\Block $block
1397
+ * @param array $selectors
1398
+ */
1399
+ protected function compileKeyframeBlock(Block $block, $selectors)
1400
+ {
1401
+ $env = $this->pushEnv($block);
1402
+
1403
+ $envs = $this->compactEnv($env);
1404
+
1405
+ $this->env = $this->extractEnv(array_filter($envs, function (Environment $e) {
1406
+ return ! isset($e->block->selectors);
1407
+ }));
1408
+
1409
+ $this->scope = $this->makeOutputBlock($block->type, $selectors);
1410
+ $this->scope->depth = 1;
1411
+ $this->scope->parent->children[] = $this->scope;
1412
+
1413
+ $this->compileChildrenNoReturn($block->children, $this->scope);
1414
+
1415
+ $this->scope = $this->scope->parent;
1416
+ $this->env = $this->extractEnv($envs);
1417
+
1418
+ $this->popEnv();
1419
+ }
1420
+
1421
+ /**
1422
+ * Compile nested properties lines
1423
+ *
1424
+ * @param \ScssPhp\ScssPhp\Block $block
1425
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
1426
+ */
1427
+ protected function compileNestedPropertiesBlock(Block $block, OutputBlock $out)
1428
+ {
1429
+ $prefix = $this->compileValue($block->prefix) . '-';
1430
+
1431
+ $nested = $this->makeOutputBlock($block->type);
1432
+ $nested->parent = $out;
1433
+
1434
+ if ($block->hasValue) {
1435
+ $nested->depth = $out->depth + 1;
1436
+ }
1437
+
1438
+ $out->children[] = $nested;
1439
+
1440
+ foreach ($block->children as $child) {
1441
+ switch ($child[0]) {
1442
+ case Type::T_ASSIGN:
1443
+ array_unshift($child[1][2], $prefix);
1444
+ break;
1445
+
1446
+ case Type::T_NESTED_PROPERTY:
1447
+ array_unshift($child[1]->prefix[2], $prefix);
1448
+ break;
1449
+ }
1450
+
1451
+ $this->compileChild($child, $nested);
1452
+ }
1453
+ }
1454
+
1455
+ /**
1456
+ * Compile nested block
1457
+ *
1458
+ * @param \ScssPhp\ScssPhp\Block $block
1459
+ * @param array $selectors
1460
+ */
1461
+ protected function compileNestedBlock(Block $block, $selectors)
1462
+ {
1463
+ $this->pushEnv($block);
1464
+
1465
+ $this->scope = $this->makeOutputBlock($block->type, $selectors);
1466
+ $this->scope->parent->children[] = $this->scope;
1467
+
1468
+ // wrap assign children in a block
1469
+ // except for @font-face
1470
+ if ($block->type !== Type::T_DIRECTIVE || $block->name !== "font-face") {
1471
+ // need wrapping?
1472
+ $needWrapping = false;
1473
+
1474
+ foreach ($block->children as $child) {
1475
+ if ($child[0] === Type::T_ASSIGN) {
1476
+ $needWrapping = true;
1477
+ break;
1478
+ }
1479
+ }
1480
+
1481
+ if ($needWrapping) {
1482
+ $wrapped = new Block;
1483
+ $wrapped->sourceName = $block->sourceName;
1484
+ $wrapped->sourceIndex = $block->sourceIndex;
1485
+ $wrapped->sourceLine = $block->sourceLine;
1486
+ $wrapped->sourceColumn = $block->sourceColumn;
1487
+ $wrapped->selectors = [];
1488
+ $wrapped->comments = [];
1489
+ $wrapped->parent = $block;
1490
+ $wrapped->children = $block->children;
1491
+ $wrapped->selfParent = $block->selfParent;
1492
+
1493
+ $block->children = [[Type::T_BLOCK, $wrapped]];
1494
+ }
1495
+ }
1496
+
1497
+ $this->compileChildrenNoReturn($block->children, $this->scope);
1498
+
1499
+ $this->scope = $this->scope->parent;
1500
+
1501
+ $this->popEnv();
1502
+ }
1503
+
1504
+ /**
1505
+ * Recursively compiles a block.
1506
+ *
1507
+ * A block is analogous to a CSS block in most cases. A single SCSS document
1508
+ * is encapsulated in a block when parsed, but it does not have parent tags
1509
+ * so all of its children appear on the root level when compiled.
1510
+ *
1511
+ * Blocks are made up of selectors and children.
1512
+ *
1513
+ * The children of a block are just all the blocks that are defined within.
1514
+ *
1515
+ * Compiling the block involves pushing a fresh environment on the stack,
1516
+ * and iterating through the props, compiling each one.
1517
+ *
1518
+ * @see Compiler::compileChild()
1519
+ *
1520
+ * @param \ScssPhp\ScssPhp\Block $block
1521
+ */
1522
+ protected function compileBlock(Block $block)
1523
+ {
1524
+ $env = $this->pushEnv($block);
1525
+ $env->selectors = $this->evalSelectors($block->selectors);
1526
+
1527
+ $out = $this->makeOutputBlock(null);
1528
+
1529
+ if (isset($this->lineNumberStyle) && \count($env->selectors) && \count($block->children)) {
1530
+ $annotation = $this->makeOutputBlock(Type::T_COMMENT);
1531
+ $annotation->depth = 0;
1532
+
1533
+ $file = $this->sourceNames[$block->sourceIndex];
1534
+ $line = $block->sourceLine;
1535
+
1536
+ switch ($this->lineNumberStyle) {
1537
+ case static::LINE_COMMENTS:
1538
+ $annotation->lines[] = '/* line ' . $line
1539
+ . ($file ? ', ' . $file : '')
1540
+ . ' */';
1541
+ break;
1542
+
1543
+ case static::DEBUG_INFO:
1544
+ $annotation->lines[] = '@media -sass-debug-info{'
1545
+ . ($file ? 'filename{font-family:"' . $file . '"}' : '')
1546
+ . 'line{font-family:' . $line . '}}';
1547
+ break;
1548
+ }
1549
+
1550
+ $this->scope->children[] = $annotation;
1551
+ }
1552
+
1553
+ $this->scope->children[] = $out;
1554
+
1555
+ if (\count($block->children)) {
1556
+ $out->selectors = $this->multiplySelectors($env, $block->selfParent);
1557
+
1558
+ // propagate selfParent to the children where they still can be useful
1559
+ $selfParentSelectors = null;
1560
+
1561
+ if (isset($block->selfParent->selectors)) {
1562
+ $selfParentSelectors = $block->selfParent->selectors;
1563
+ $block->selfParent->selectors = $out->selectors;
1564
+ }
1565
+
1566
+ $this->compileChildrenNoReturn($block->children, $out, $block->selfParent);
1567
+
1568
+ // and revert for the following children of the same block
1569
+ if ($selfParentSelectors) {
1570
+ $block->selfParent->selectors = $selfParentSelectors;
1571
+ }
1572
+ }
1573
+
1574
+ $this->popEnv();
1575
+ }
1576
+
1577
+
1578
+ /**
1579
+ * Compile the value of a comment that can have interpolation
1580
+ *
1581
+ * @param array $value
1582
+ * @param boolean $pushEnv
1583
+ *
1584
+ * @return array|mixed|string
1585
+ */
1586
+ protected function compileCommentValue($value, $pushEnv = false)
1587
+ {
1588
+ $c = $value[1];
1589
+
1590
+ if (isset($value[2])) {
1591
+ if ($pushEnv) {
1592
+ $this->pushEnv();
1593
+ }
1594
+
1595
+ $ignoreCallStackMessage = $this->ignoreCallStackMessage;
1596
+ $this->ignoreCallStackMessage = true;
1597
+
1598
+ try {
1599
+ $c = $this->compileValue($value[2]);
1600
+ } catch (\Exception $e) {
1601
+ // ignore error in comment compilation which are only interpolation
1602
+ }
1603
+
1604
+ $this->ignoreCallStackMessage = $ignoreCallStackMessage;
1605
+
1606
+ if ($pushEnv) {
1607
+ $this->popEnv();
1608
+ }
1609
+ }
1610
+
1611
+ return $c;
1612
+ }
1613
+
1614
+ /**
1615
+ * Compile root level comment
1616
+ *
1617
+ * @param array $block
1618
+ */
1619
+ protected function compileComment($block)
1620
+ {
1621
+ $out = $this->makeOutputBlock(Type::T_COMMENT);
1622
+ $out->lines[] = $this->compileCommentValue($block, true);
1623
+
1624
+ $this->scope->children[] = $out;
1625
+ }
1626
+
1627
+ /**
1628
+ * Evaluate selectors
1629
+ *
1630
+ * @param array $selectors
1631
+ *
1632
+ * @return array
1633
+ */
1634
+ protected function evalSelectors($selectors)
1635
+ {
1636
+ $this->shouldEvaluate = false;
1637
+
1638
+ $selectors = array_map([$this, 'evalSelector'], $selectors);
1639
+
1640
+ // after evaluating interpolates, we might need a second pass
1641
+ if ($this->shouldEvaluate) {
1642
+ $selectors = $this->revertSelfSelector($selectors);
1643
+ $buffer = $this->collapseSelectors($selectors);
1644
+ $parser = $this->parserFactory(__METHOD__);
1645
+
1646
+ if ($parser->parseSelector($buffer, $newSelectors)) {
1647
+ $selectors = array_map([$this, 'evalSelector'], $newSelectors);
1648
+ }
1649
+ }
1650
+
1651
+ return $selectors;
1652
+ }
1653
+
1654
+ /**
1655
+ * Evaluate selector
1656
+ *
1657
+ * @param array $selector
1658
+ *
1659
+ * @return array
1660
+ */
1661
+ protected function evalSelector($selector)
1662
+ {
1663
+ return array_map([$this, 'evalSelectorPart'], $selector);
1664
+ }
1665
+
1666
+ /**
1667
+ * Evaluate selector part; replaces all the interpolates, stripping quotes
1668
+ *
1669
+ * @param array $part
1670
+ *
1671
+ * @return array
1672
+ */
1673
+ protected function evalSelectorPart($part)
1674
+ {
1675
+ foreach ($part as &$p) {
1676
+ if (\is_array($p) && ($p[0] === Type::T_INTERPOLATE || $p[0] === Type::T_STRING)) {
1677
+ $p = $this->compileValue($p);
1678
+
1679
+ // force re-evaluation
1680
+ if (strpos($p, '&') !== false || strpos($p, ',') !== false) {
1681
+ $this->shouldEvaluate = true;
1682
+ }
1683
+ } elseif (\is_string($p) && \strlen($p) >= 2 &&
1684
+ ($first = $p[0]) && ($first === '"' || $first === "'") &&
1685
+ substr($p, -1) === $first
1686
+ ) {
1687
+ $p = substr($p, 1, -1);
1688
+ }
1689
+ }
1690
+
1691
+ return $this->flattenSelectorSingle($part);
1692
+ }
1693
+
1694
+ /**
1695
+ * Collapse selectors
1696
+ *
1697
+ * @param array $selectors
1698
+ * @param boolean $selectorFormat
1699
+ * if false return a collapsed string
1700
+ * if true return an array description of a structured selector
1701
+ *
1702
+ * @return string
1703
+ */
1704
+ protected function collapseSelectors($selectors, $selectorFormat = false)
1705
+ {
1706
+ $parts = [];
1707
+
1708
+ foreach ($selectors as $selector) {
1709
+ $output = [];
1710
+ $glueNext = false;
1711
+
1712
+ foreach ($selector as $node) {
1713
+ $compound = '';
1714
+
1715
+ array_walk_recursive(
1716
+ $node,
1717
+ function ($value, $key) use (&$compound) {
1718
+ $compound .= $value;
1719
+ }
1720
+ );
1721
+
1722
+ if ($selectorFormat && $this->isImmediateRelationshipCombinator($compound)) {
1723
+ if (\count($output)) {
1724
+ $output[\count($output) - 1] .= ' ' . $compound;
1725
+ } else {
1726
+ $output[] = $compound;
1727
+ }
1728
+
1729
+ $glueNext = true;
1730
+ } elseif ($glueNext) {
1731
+ $output[\count($output) - 1] .= ' ' . $compound;
1732
+ $glueNext = false;
1733
+ } else {
1734
+ $output[] = $compound;
1735
+ }
1736
+ }
1737
+
1738
+ if ($selectorFormat) {
1739
+ foreach ($output as &$o) {
1740
+ $o = [Type::T_STRING, '', [$o]];
1741
+ }
1742
+
1743
+ $output = [Type::T_LIST, ' ', $output];
1744
+ } else {
1745
+ $output = implode(' ', $output);
1746
+ }
1747
+
1748
+ $parts[] = $output;
1749
+ }
1750
+
1751
+ if ($selectorFormat) {
1752
+ $parts = [Type::T_LIST, ',', $parts];
1753
+ } else {
1754
+ $parts = implode(', ', $parts);
1755
+ }
1756
+
1757
+ return $parts;
1758
+ }
1759
+
1760
+ /**
1761
+ * Parse down the selector and revert [self] to "&" before a reparsing
1762
+ *
1763
+ * @param array $selectors
1764
+ *
1765
+ * @return array
1766
+ */
1767
+ protected function revertSelfSelector($selectors)
1768
+ {
1769
+ foreach ($selectors as &$part) {
1770
+ if (\is_array($part)) {
1771
+ if ($part === [Type::T_SELF]) {
1772
+ $part = '&';
1773
+ } else {
1774
+ $part = $this->revertSelfSelector($part);
1775
+ }
1776
+ }
1777
+ }
1778
+
1779
+ return $selectors;
1780
+ }
1781
+
1782
+ /**
1783
+ * Flatten selector single; joins together .classes and #ids
1784
+ *
1785
+ * @param array $single
1786
+ *
1787
+ * @return array
1788
+ */
1789
+ protected function flattenSelectorSingle($single)
1790
+ {
1791
+ $joined = [];
1792
+
1793
+ foreach ($single as $part) {
1794
+ if (empty($joined) ||
1795
+ ! \is_string($part) ||
1796
+ preg_match('/[\[.:#%]/', $part)
1797
+ ) {
1798
+ $joined[] = $part;
1799
+ continue;
1800
+ }
1801
+
1802
+ if (\is_array(end($joined))) {
1803
+ $joined[] = $part;
1804
+ } else {
1805
+ $joined[\count($joined) - 1] .= $part;
1806
+ }
1807
+ }
1808
+
1809
+ return $joined;
1810
+ }
1811
+
1812
+ /**
1813
+ * Compile selector to string; self(&) should have been replaced by now
1814
+ *
1815
+ * @param string|array $selector
1816
+ *
1817
+ * @return string
1818
+ */
1819
+ protected function compileSelector($selector)
1820
+ {
1821
+ if (! \is_array($selector)) {
1822
+ return $selector; // media and the like
1823
+ }
1824
+
1825
+ return implode(
1826
+ ' ',
1827
+ array_map(
1828
+ [$this, 'compileSelectorPart'],
1829
+ $selector
1830
+ )
1831
+ );
1832
+ }
1833
+
1834
+ /**
1835
+ * Compile selector part
1836
+ *
1837
+ * @param array $piece
1838
+ *
1839
+ * @return string
1840
+ */
1841
+ protected function compileSelectorPart($piece)
1842
+ {
1843
+ foreach ($piece as &$p) {
1844
+ if (! \is_array($p)) {
1845
+ continue;
1846
+ }
1847
+
1848
+ switch ($p[0]) {
1849
+ case Type::T_SELF:
1850
+ $p = '&';
1851
+ break;
1852
+
1853
+ default:
1854
+ $p = $this->compileValue($p);
1855
+ break;
1856
+ }
1857
+ }
1858
+
1859
+ return implode($piece);
1860
+ }
1861
+
1862
+ /**
1863
+ * Has selector placeholder?
1864
+ *
1865
+ * @param array $selector
1866
+ *
1867
+ * @return boolean
1868
+ */
1869
+ protected function hasSelectorPlaceholder($selector)
1870
+ {
1871
+ if (! \is_array($selector)) {
1872
+ return false;
1873
+ }
1874
+
1875
+ foreach ($selector as $parts) {
1876
+ foreach ($parts as $part) {
1877
+ if (\strlen($part) && '%' === $part[0]) {
1878
+ return true;
1879
+ }
1880
+ }
1881
+ }
1882
+
1883
+ return false;
1884
+ }
1885
+
1886
+ protected function pushCallStack($name = '')
1887
+ {
1888
+ $this->callStack[] = [
1889
+ 'n' => $name,
1890
+ Parser::SOURCE_INDEX => $this->sourceIndex,
1891
+ Parser::SOURCE_LINE => $this->sourceLine,
1892
+ Parser::SOURCE_COLUMN => $this->sourceColumn
1893
+ ];
1894
+
1895
+ // infinite calling loop
1896
+ if (\count($this->callStack) > 25000) {
1897
+ // not displayed but you can var_dump it to deep debug
1898
+ $msg = $this->callStackMessage(true, 100);
1899
+ $msg = "Infinite calling loop";
1900
+
1901
+ $this->throwError($msg);
1902
+ }
1903
+ }
1904
+
1905
+ protected function popCallStack()
1906
+ {
1907
+ array_pop($this->callStack);
1908
+ }
1909
+
1910
+ /**
1911
+ * Compile children and return result
1912
+ *
1913
+ * @param array $stms
1914
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
1915
+ * @param string $traceName
1916
+ *
1917
+ * @return array|null
1918
+ */
1919
+ protected function compileChildren($stms, OutputBlock $out, $traceName = '')
1920
+ {
1921
+ $this->pushCallStack($traceName);
1922
+
1923
+ foreach ($stms as $stm) {
1924
+ $ret = $this->compileChild($stm, $out);
1925
+
1926
+ if (isset($ret)) {
1927
+ $this->popCallStack();
1928
+
1929
+ return $ret;
1930
+ }
1931
+ }
1932
+
1933
+ $this->popCallStack();
1934
+
1935
+ return null;
1936
+ }
1937
+
1938
+ /**
1939
+ * Compile children and throw exception if unexpected @return
1940
+ *
1941
+ * @param array $stms
1942
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
1943
+ * @param \ScssPhp\ScssPhp\Block $selfParent
1944
+ * @param string $traceName
1945
+ *
1946
+ * @throws \Exception
1947
+ */
1948
+ protected function compileChildrenNoReturn($stms, OutputBlock $out, $selfParent = null, $traceName = '')
1949
+ {
1950
+ $this->pushCallStack($traceName);
1951
+
1952
+ foreach ($stms as $stm) {
1953
+ if ($selfParent && isset($stm[1]) && \is_object($stm[1]) && $stm[1] instanceof Block) {
1954
+ $stm[1]->selfParent = $selfParent;
1955
+ $ret = $this->compileChild($stm, $out);
1956
+ $stm[1]->selfParent = null;
1957
+ } elseif ($selfParent && \in_array($stm[0], [TYPE::T_INCLUDE, TYPE::T_EXTEND])) {
1958
+ $stm['selfParent'] = $selfParent;
1959
+ $ret = $this->compileChild($stm, $out);
1960
+ unset($stm['selfParent']);
1961
+ } else {
1962
+ $ret = $this->compileChild($stm, $out);
1963
+ }
1964
+
1965
+ if (isset($ret)) {
1966
+ $this->throwError('@return may only be used within a function');
1967
+ $this->popCallStack();
1968
+
1969
+ return;
1970
+ }
1971
+ }
1972
+
1973
+ $this->popCallStack();
1974
+ }
1975
+
1976
+
1977
+ /**
1978
+ * evaluate media query : compile internal value keeping the structure inchanged
1979
+ *
1980
+ * @param array $queryList
1981
+ *
1982
+ * @return array
1983
+ */
1984
+ protected function evaluateMediaQuery($queryList)
1985
+ {
1986
+ static $parser = null;
1987
+
1988
+ $outQueryList = [];
1989
+
1990
+ foreach ($queryList as $kql => $query) {
1991
+ $shouldReparse = false;
1992
+
1993
+ foreach ($query as $kq => $q) {
1994
+ for ($i = 1; $i < \count($q); $i++) {
1995
+ $value = $this->compileValue($q[$i]);
1996
+
1997
+ // the parser had no mean to know if media type or expression if it was an interpolation
1998
+ // so you need to reparse if the T_MEDIA_TYPE looks like anything else a media type
1999
+ if ($q[0] == Type::T_MEDIA_TYPE &&
2000
+ (strpos($value, '(') !== false ||
2001
+ strpos($value, ')') !== false ||
2002
+ strpos($value, ':') !== false ||
2003
+ strpos($value, ',') !== false)
2004
+ ) {
2005
+ $shouldReparse = true;
2006
+ }
2007
+
2008
+ $queryList[$kql][$kq][$i] = [Type::T_KEYWORD, $value];
2009
+ }
2010
+ }
2011
+
2012
+ if ($shouldReparse) {
2013
+ if (\is_null($parser)) {
2014
+ $parser = $this->parserFactory(__METHOD__);
2015
+ }
2016
+
2017
+ $queryString = $this->compileMediaQuery([$queryList[$kql]]);
2018
+ $queryString = reset($queryString);
2019
+
2020
+ if (strpos($queryString, '@media ') === 0) {
2021
+ $queryString = substr($queryString, 7);
2022
+ $queries = [];
2023
+
2024
+ if ($parser->parseMediaQueryList($queryString, $queries)) {
2025
+ $queries = $this->evaluateMediaQuery($queries[2]);
2026
+
2027
+ while (\count($queries)) {
2028
+ $outQueryList[] = array_shift($queries);
2029
+ }
2030
+
2031
+ continue;
2032
+ }
2033
+ }
2034
+ }
2035
+
2036
+ $outQueryList[] = $queryList[$kql];
2037
+ }
2038
+
2039
+ return $outQueryList;
2040
+ }
2041
+
2042
+ /**
2043
+ * Compile media query
2044
+ *
2045
+ * @param array $queryList
2046
+ *
2047
+ * @return array
2048
+ */
2049
+ protected function compileMediaQuery($queryList)
2050
+ {
2051
+ $start = '@media ';
2052
+ $default = trim($start);
2053
+ $out = [];
2054
+ $current = "";
2055
+
2056
+ foreach ($queryList as $query) {
2057
+ $type = null;
2058
+ $parts = [];
2059
+
2060
+ $mediaTypeOnly = true;
2061
+
2062
+ foreach ($query as $q) {
2063
+ if ($q[0] !== Type::T_MEDIA_TYPE) {
2064
+ $mediaTypeOnly = false;
2065
+ break;
2066
+ }
2067
+ }
2068
+
2069
+ foreach ($query as $q) {
2070
+ switch ($q[0]) {
2071
+ case Type::T_MEDIA_TYPE:
2072
+ $newType = array_map([$this, 'compileValue'], \array_slice($q, 1));
2073
+
2074
+ // combining not and anything else than media type is too risky and should be avoided
2075
+ if (! $mediaTypeOnly) {
2076
+ if (\in_array(Type::T_NOT, $newType) || ($type && \in_array(Type::T_NOT, $type) )) {
2077
+ if ($type) {
2078
+ array_unshift($parts, implode(' ', array_filter($type)));
2079
+ }
2080
+
2081
+ if (! empty($parts)) {
2082
+ if (\strlen($current)) {
2083
+ $current .= $this->formatter->tagSeparator;
2084
+ }
2085
+
2086
+ $current .= implode(' and ', $parts);
2087
+ }
2088
+
2089
+ if ($current) {
2090
+ $out[] = $start . $current;
2091
+ }
2092
+
2093
+ $current = "";
2094
+ $type = null;
2095
+ $parts = [];
2096
+ }
2097
+ }
2098
+
2099
+ if ($newType === ['all'] && $default) {
2100
+ $default = $start . 'all';
2101
+ }
2102
+
2103
+ // all can be safely ignored and mixed with whatever else
2104
+ if ($newType !== ['all']) {
2105
+ if ($type) {
2106
+ $type = $this->mergeMediaTypes($type, $newType);
2107
+
2108
+ if (empty($type)) {
2109
+ // merge failed : ignore this query that is not valid, skip to the next one
2110
+ $parts = [];
2111
+ $default = ''; // if everything fail, no @media at all
2112
+ continue 3;
2113
+ }
2114
+ } else {
2115
+ $type = $newType;
2116
+ }
2117
+ }
2118
+ break;
2119
+
2120
+ case Type::T_MEDIA_EXPRESSION:
2121
+ if (isset($q[2])) {
2122
+ $parts[] = '('
2123
+ . $this->compileValue($q[1])
2124
+ . $this->formatter->assignSeparator
2125
+ . $this->compileValue($q[2])
2126
+ . ')';
2127
+ } else {
2128
+ $parts[] = '('
2129
+ . $this->compileValue($q[1])
2130
+ . ')';
2131
+ }
2132
+ break;
2133
+
2134
+ case Type::T_MEDIA_VALUE:
2135
+ $parts[] = $this->compileValue($q[1]);
2136
+ break;
2137
+ }
2138
+ }
2139
+
2140
+ if ($type) {
2141
+ array_unshift($parts, implode(' ', array_filter($type)));
2142
+ }
2143
+
2144
+ if (! empty($parts)) {
2145
+ if (\strlen($current)) {
2146
+ $current .= $this->formatter->tagSeparator;
2147
+ }
2148
+
2149
+ $current .= implode(' and ', $parts);
2150
+ }
2151
+ }
2152
+
2153
+ if ($current) {
2154
+ $out[] = $start . $current;
2155
+ }
2156
+
2157
+ // no @media type except all, and no conflict?
2158
+ if (! $out && $default) {
2159
+ $out[] = $default;
2160
+ }
2161
+
2162
+ return $out;
2163
+ }
2164
+
2165
+ /**
2166
+ * Merge direct relationships between selectors
2167
+ *
2168
+ * @param array $selectors1
2169
+ * @param array $selectors2
2170
+ *
2171
+ * @return array
2172
+ */
2173
+ protected function mergeDirectRelationships($selectors1, $selectors2)
2174
+ {
2175
+ if (empty($selectors1) || empty($selectors2)) {
2176
+ return array_merge($selectors1, $selectors2);
2177
+ }
2178
+
2179
+ $part1 = end($selectors1);
2180
+ $part2 = end($selectors2);
2181
+
2182
+ if (! $this->isImmediateRelationshipCombinator($part1[0]) && $part1 !== $part2) {
2183
+ return array_merge($selectors1, $selectors2);
2184
+ }
2185
+
2186
+ $merged = [];
2187
+
2188
+ do {
2189
+ $part1 = array_pop($selectors1);
2190
+ $part2 = array_pop($selectors2);
2191
+
2192
+ if (! $this->isImmediateRelationshipCombinator($part1[0]) && $part1 !== $part2) {
2193
+ if ($this->isImmediateRelationshipCombinator(reset($merged)[0])) {
2194
+ array_unshift($merged, [$part1[0] . $part2[0]]);
2195
+ $merged = array_merge($selectors1, $selectors2, $merged);
2196
+ } else {
2197
+ $merged = array_merge($selectors1, [$part1], $selectors2, [$part2], $merged);
2198
+ }
2199
+
2200
+ break;
2201
+ }
2202
+
2203
+ array_unshift($merged, $part1);
2204
+ } while (! empty($selectors1) && ! empty($selectors2));
2205
+
2206
+ return $merged;
2207
+ }
2208
+
2209
+ /**
2210
+ * Merge media types
2211
+ *
2212
+ * @param array $type1
2213
+ * @param array $type2
2214
+ *
2215
+ * @return array|null
2216
+ */
2217
+ protected function mergeMediaTypes($type1, $type2)
2218
+ {
2219
+ if (empty($type1)) {
2220
+ return $type2;
2221
+ }
2222
+
2223
+ if (empty($type2)) {
2224
+ return $type1;
2225
+ }
2226
+
2227
+ if (\count($type1) > 1) {
2228
+ $m1 = strtolower($type1[0]);
2229
+ $t1 = strtolower($type1[1]);
2230
+ } else {
2231
+ $m1 = '';
2232
+ $t1 = strtolower($type1[0]);
2233
+ }
2234
+
2235
+ if (\count($type2) > 1) {
2236
+ $m2 = strtolower($type2[0]);
2237
+ $t2 = strtolower($type2[1]);
2238
+ } else {
2239
+ $m2 = '';
2240
+ $t2 = strtolower($type2[0]);
2241
+ }
2242
+
2243
+ if (($m1 === Type::T_NOT) ^ ($m2 === Type::T_NOT)) {
2244
+ if ($t1 === $t2) {
2245
+ return null;
2246
+ }
2247
+
2248
+ return [
2249
+ $m1 === Type::T_NOT ? $m2 : $m1,
2250
+ $m1 === Type::T_NOT ? $t2 : $t1,
2251
+ ];
2252
+ }
2253
+
2254
+ if ($m1 === Type::T_NOT && $m2 === Type::T_NOT) {
2255
+ // CSS has no way of representing "neither screen nor print"
2256
+ if ($t1 !== $t2) {
2257
+ return null;
2258
+ }
2259
+
2260
+ return [Type::T_NOT, $t1];
2261
+ }
2262
+
2263
+ if ($t1 !== $t2) {
2264
+ return null;
2265
+ }
2266
+
2267
+ // t1 == t2, neither m1 nor m2 are "not"
2268
+ return [empty($m1)? $m2 : $m1, $t1];
2269
+ }
2270
+
2271
+ /**
2272
+ * Compile import; returns true if the value was something that could be imported
2273
+ *
2274
+ * @param array $rawPath
2275
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
2276
+ * @param boolean $once
2277
+ *
2278
+ * @return boolean
2279
+ */
2280
+ protected function compileImport($rawPath, OutputBlock $out, $once = false)
2281
+ {
2282
+ if ($rawPath[0] === Type::T_STRING) {
2283
+ $path = $this->compileStringContent($rawPath);
2284
+
2285
+ if ($path = $this->findImport($path)) {
2286
+ if (! $once || ! \in_array($path, $this->importedFiles)) {
2287
+ $this->importFile($path, $out);
2288
+ $this->importedFiles[] = $path;
2289
+ }
2290
+
2291
+ return true;
2292
+ }
2293
+
2294
+ $this->appendRootDirective('@import ' . $this->compileValue($rawPath). ';', $out);
2295
+
2296
+ return false;
2297
+ }
2298
+
2299
+ if ($rawPath[0] === Type::T_LIST) {
2300
+ // handle a list of strings
2301
+ if (\count($rawPath[2]) === 0) {
2302
+ return false;
2303
+ }
2304
+
2305
+ foreach ($rawPath[2] as $path) {
2306
+ if ($path[0] !== Type::T_STRING) {
2307
+ $this->appendRootDirective('@import ' . $this->compileValue($rawPath) . ';', $out);
2308
+
2309
+ return false;
2310
+ }
2311
+ }
2312
+
2313
+ foreach ($rawPath[2] as $path) {
2314
+ $this->compileImport($path, $out, $once);
2315
+ }
2316
+
2317
+ return true;
2318
+ }
2319
+
2320
+ $this->appendRootDirective('@import ' . $this->compileValue($rawPath) . ';', $out);
2321
+
2322
+ return false;
2323
+ }
2324
+
2325
+
2326
+ /**
2327
+ * Append a root directive like @import or @charset as near as the possible from the source code
2328
+ * (keeping before comments, @import and @charset coming before in the source code)
2329
+ *
2330
+ * @param string $line
2331
+ * @param @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
2332
+ * @param array $allowed
2333
+ */
2334
+ protected function appendRootDirective($line, $out, $allowed = [Type::T_COMMENT])
2335
+ {
2336
+ $root = $out;
2337
+
2338
+ while ($root->parent) {
2339
+ $root = $root->parent;
2340
+ }
2341
+
2342
+ $i = 0;
2343
+
2344
+ while ($i < \count($root->children)) {
2345
+ if (! isset($root->children[$i]->type) || ! \in_array($root->children[$i]->type, $allowed)) {
2346
+ break;
2347
+ }
2348
+
2349
+ $i++;
2350
+ }
2351
+
2352
+ // remove incompatible children from the bottom of the list
2353
+ $saveChildren = [];
2354
+
2355
+ while ($i < \count($root->children)) {
2356
+ $saveChildren[] = array_pop($root->children);
2357
+ }
2358
+
2359
+ // insert the directive as a comment
2360
+ $child = $this->makeOutputBlock(Type::T_COMMENT);
2361
+ $child->lines[] = $line;
2362
+ $child->sourceName = $this->sourceNames[$this->sourceIndex];
2363
+ $child->sourceLine = $this->sourceLine;
2364
+ $child->sourceColumn = $this->sourceColumn;
2365
+
2366
+ $root->children[] = $child;
2367
+
2368
+ // repush children
2369
+ while (\count($saveChildren)) {
2370
+ $root->children[] = array_pop($saveChildren);
2371
+ }
2372
+ }
2373
+
2374
+ /**
2375
+ * Append lines to the current output block:
2376
+ * directly to the block or through a child if necessary
2377
+ *
2378
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
2379
+ * @param string $type
2380
+ * @param string|mixed $line
2381
+ */
2382
+ protected function appendOutputLine(OutputBlock $out, $type, $line)
2383
+ {
2384
+ $outWrite = &$out;
2385
+
2386
+ if ($type === Type::T_COMMENT) {
2387
+ $parent = $out->parent;
2388
+
2389
+ if (end($parent->children) !== $out) {
2390
+ $outWrite = &$parent->children[\count($parent->children) - 1];
2391
+ }
2392
+ }
2393
+
2394
+ // check if it's a flat output or not
2395
+ if (\count($out->children)) {
2396
+ $lastChild = &$out->children[\count($out->children) - 1];
2397
+
2398
+ if ($lastChild->depth === $out->depth &&
2399
+ \is_null($lastChild->selectors) &&
2400
+ ! \count($lastChild->children)
2401
+ ) {
2402
+ $outWrite = $lastChild;
2403
+ } else {
2404
+ $nextLines = $this->makeOutputBlock($type);
2405
+ $nextLines->parent = $out;
2406
+ $nextLines->depth = $out->depth;
2407
+
2408
+ $out->children[] = $nextLines;
2409
+ $outWrite = &$nextLines;
2410
+ }
2411
+ }
2412
+
2413
+ $outWrite->lines[] = $line;
2414
+ }
2415
+
2416
+ /**
2417
+ * Compile child; returns a value to halt execution
2418
+ *
2419
+ * @param array $child
2420
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
2421
+ *
2422
+ * @return array
2423
+ */
2424
+ protected function compileChild($child, OutputBlock $out)
2425
+ {
2426
+ if (isset($child[Parser::SOURCE_LINE])) {
2427
+ $this->sourceIndex = isset($child[Parser::SOURCE_INDEX]) ? $child[Parser::SOURCE_INDEX] : null;
2428
+ $this->sourceLine = isset($child[Parser::SOURCE_LINE]) ? $child[Parser::SOURCE_LINE] : -1;
2429
+ $this->sourceColumn = isset($child[Parser::SOURCE_COLUMN]) ? $child[Parser::SOURCE_COLUMN] : -1;
2430
+ } elseif (\is_array($child) && isset($child[1]->sourceLine)) {
2431
+ $this->sourceIndex = $child[1]->sourceIndex;
2432
+ $this->sourceLine = $child[1]->sourceLine;
2433
+ $this->sourceColumn = $child[1]->sourceColumn;
2434
+ } elseif (! empty($out->sourceLine) && ! empty($out->sourceName)) {
2435
+ $this->sourceLine = $out->sourceLine;
2436
+ $this->sourceIndex = array_search($out->sourceName, $this->sourceNames);
2437
+ $this->sourceColumn = $out->sourceColumn;
2438
+
2439
+ if ($this->sourceIndex === false) {
2440
+ $this->sourceIndex = null;
2441
+ }
2442
+ }
2443
+
2444
+ switch ($child[0]) {
2445
+ case Type::T_SCSSPHP_IMPORT_ONCE:
2446
+ $rawPath = $this->reduce($child[1]);
2447
+
2448
+ $this->compileImport($rawPath, $out, true);
2449
+ break;
2450
+
2451
+ case Type::T_IMPORT:
2452
+ $rawPath = $this->reduce($child[1]);
2453
+
2454
+ $this->compileImport($rawPath, $out);
2455
+ break;
2456
+
2457
+ case Type::T_DIRECTIVE:
2458
+ $this->compileDirective($child[1], $out);
2459
+ break;
2460
+
2461
+ case Type::T_AT_ROOT:
2462
+ $this->compileAtRoot($child[1]);
2463
+ break;
2464
+
2465
+ case Type::T_MEDIA:
2466
+ $this->compileMedia($child[1]);
2467
+ break;
2468
+
2469
+ case Type::T_BLOCK:
2470
+ $this->compileBlock($child[1]);
2471
+ break;
2472
+
2473
+ case Type::T_CHARSET:
2474
+ if (! $this->charsetSeen) {
2475
+ $this->charsetSeen = true;
2476
+ $this->appendRootDirective('@charset ' . $this->compileValue($child[1]) . ';', $out);
2477
+ }
2478
+ break;
2479
+
2480
+ case Type::T_CUSTOM_PROPERTY:
2481
+ list(, $name, $value) = $child;
2482
+ $compiledName = $this->compileValue($name);
2483
+
2484
+ // if the value reduces to null from something else then
2485
+ // the property should be discarded
2486
+ if ($value[0] !== Type::T_NULL) {
2487
+ $value = $this->reduce($value);
2488
+
2489
+ if ($value[0] === Type::T_NULL || $value === static::$nullString) {
2490
+ break;
2491
+ }
2492
+ }
2493
+
2494
+ $compiledValue = $this->compileValue($value);
2495
+
2496
+ $line = $this->formatter->customProperty(
2497
+ $compiledName,
2498
+ $compiledValue
2499
+ );
2500
+
2501
+ $this->appendOutputLine($out, Type::T_ASSIGN, $line);
2502
+ break;
2503
+
2504
+ case Type::T_ASSIGN:
2505
+ list(, $name, $value) = $child;
2506
+
2507
+ if ($name[0] === Type::T_VARIABLE) {
2508
+ $flags = isset($child[3]) ? $child[3] : [];
2509
+ $isDefault = \in_array('!default', $flags);
2510
+ $isGlobal = \in_array('!global', $flags);
2511
+
2512
+ if ($isGlobal) {
2513
+ $this->set($name[1], $this->reduce($value), false, $this->rootEnv, $value);
2514
+ break;
2515
+ }
2516
+
2517
+ $shouldSet = $isDefault &&
2518
+ (\is_null($result = $this->get($name[1], false)) ||
2519
+ $result === static::$null);
2520
+
2521
+ if (! $isDefault || $shouldSet) {
2522
+ $this->set($name[1], $this->reduce($value), true, null, $value);
2523
+ }
2524
+ break;
2525
+ }
2526
+
2527
+ $compiledName = $this->compileValue($name);
2528
+
2529
+ // handle shorthand syntaxes : size / line-height...
2530
+ if (\in_array($compiledName, ['font', 'grid-row', 'grid-column', 'border-radius'])) {
2531
+ if ($value[0] === Type::T_VARIABLE) {
2532
+ // if the font value comes from variable, the content is already reduced
2533
+ // (i.e., formulas were already calculated), so we need the original unreduced value
2534
+ $value = $this->get($value[1], true, null, true);
2535
+ }
2536
+
2537
+ $shorthandValue=&$value;
2538
+
2539
+ $shorthandDividerNeedsUnit = false;
2540
+ $maxListElements = null;
2541
+ $maxShorthandDividers = 1;
2542
+
2543
+ switch ($compiledName) {
2544
+ case 'border-radius':
2545
+ $maxListElements = 4;
2546
+ $shorthandDividerNeedsUnit = true;
2547
+ break;
2548
+ }
2549
+
2550
+ if ($compiledName === 'font' and $value[0] === Type::T_LIST && $value[1]==',') {
2551
+ // this is the case if more than one font is given: example: "font: 400 1em/1.3 arial,helvetica"
2552
+ // we need to handle the first list element
2553
+ $shorthandValue=&$value[2][0];
2554
+ }
2555
+
2556
+ if ($shorthandValue[0] === Type::T_EXPRESSION && $shorthandValue[1] === '/') {
2557
+ $revert = true;
2558
+
2559
+ if ($shorthandDividerNeedsUnit) {
2560
+ $divider = $shorthandValue[3];
2561
+
2562
+ if (\is_array($divider)) {
2563
+ $divider = $this->reduce($divider, true);
2564
+ }
2565
+
2566
+ if (\intval($divider->dimension) and ! \count($divider->units)) {
2567
+ $revert = false;
2568
+ }
2569
+ }
2570
+
2571
+ if ($revert) {
2572
+ $shorthandValue = $this->expToString($shorthandValue);
2573
+ }
2574
+ } elseif ($shorthandValue[0] === Type::T_LIST) {
2575
+ foreach ($shorthandValue[2] as &$item) {
2576
+ if ($item[0] === Type::T_EXPRESSION && $item[1] === '/') {
2577
+ if ($maxShorthandDividers > 0) {
2578
+ $revert = true;
2579
+ // if the list of values is too long, this has to be a shorthand,
2580
+ // otherwise it could be a real division
2581
+ if (\is_null($maxListElements) or \count($shorthandValue[2]) <= $maxListElements) {
2582
+ if ($shorthandDividerNeedsUnit) {
2583
+ $divider = $item[3];
2584
+
2585
+ if (\is_array($divider)) {
2586
+ $divider = $this->reduce($divider, true);
2587
+ }
2588
+
2589
+ if (\intval($divider->dimension) and ! \count($divider->units)) {
2590
+ $revert = false;
2591
+ }
2592
+ }
2593
+ }
2594
+
2595
+ if ($revert) {
2596
+ $item = $this->expToString($item);
2597
+ $maxShorthandDividers--;
2598
+ }
2599
+ }
2600
+ }
2601
+ }
2602
+ }
2603
+ }
2604
+
2605
+ // if the value reduces to null from something else then
2606
+ // the property should be discarded
2607
+ if ($value[0] !== Type::T_NULL) {
2608
+ $value = $this->reduce($value);
2609
+
2610
+ if ($value[0] === Type::T_NULL || $value === static::$nullString) {
2611
+ break;
2612
+ }
2613
+ }
2614
+
2615
+ $compiledValue = $this->compileValue($value);
2616
+
2617
+ // ignore empty value
2618
+ if (\strlen($compiledValue)) {
2619
+ $line = $this->formatter->property(
2620
+ $compiledName,
2621
+ $compiledValue
2622
+ );
2623
+ $this->appendOutputLine($out, Type::T_ASSIGN, $line);
2624
+ }
2625
+ break;
2626
+
2627
+ case Type::T_COMMENT:
2628
+ if ($out->type === Type::T_ROOT) {
2629
+ $this->compileComment($child);
2630
+ break;
2631
+ }
2632
+
2633
+ $line = $this->compileCommentValue($child, true);
2634
+ $this->appendOutputLine($out, Type::T_COMMENT, $line);
2635
+ break;
2636
+
2637
+ case Type::T_MIXIN:
2638
+ case Type::T_FUNCTION:
2639
+ list(, $block) = $child;
2640
+ // the block need to be able to go up to it's parent env to resolve vars
2641
+ $block->parentEnv = $this->getStoreEnv();
2642
+ $this->set(static::$namespaces[$block->type] . $block->name, $block, true);
2643
+ break;
2644
+
2645
+ case Type::T_EXTEND:
2646
+ foreach ($child[1] as $sel) {
2647
+ $results = $this->evalSelectors([$sel]);
2648
+
2649
+ foreach ($results as $result) {
2650
+ // only use the first one
2651
+ $result = current($result);
2652
+ $selectors = $out->selectors;
2653
+
2654
+ if (! $selectors && isset($child['selfParent'])) {
2655
+ $selectors = $this->multiplySelectors($this->env, $child['selfParent']);
2656
+ }
2657
+
2658
+ $this->pushExtends($result, $selectors, $child);
2659
+ }
2660
+ }
2661
+ break;
2662
+
2663
+ case Type::T_IF:
2664
+ list(, $if) = $child;
2665
+
2666
+ if ($this->isTruthy($this->reduce($if->cond, true))) {
2667
+ return $this->compileChildren($if->children, $out);
2668
+ }
2669
+
2670
+ foreach ($if->cases as $case) {
2671
+ if ($case->type === Type::T_ELSE ||
2672
+ $case->type === Type::T_ELSEIF && $this->isTruthy($this->reduce($case->cond))
2673
+ ) {
2674
+ return $this->compileChildren($case->children, $out);
2675
+ }
2676
+ }
2677
+ break;
2678
+
2679
+ case Type::T_EACH:
2680
+ list(, $each) = $child;
2681
+
2682
+ $list = $this->coerceList($this->reduce($each->list), ',', true);
2683
+
2684
+ $this->pushEnv();
2685
+
2686
+ foreach ($list[2] as $item) {
2687
+ if (\count($each->vars) === 1) {
2688
+ $this->set($each->vars[0], $item, true);
2689
+ } else {
2690
+ list(,, $values) = $this->coerceList($item);
2691
+
2692
+ foreach ($each->vars as $i => $var) {
2693
+ $this->set($var, isset($values[$i]) ? $values[$i] : static::$null, true);
2694
+ }
2695
+ }
2696
+
2697
+ $ret = $this->compileChildren($each->children, $out);
2698
+
2699
+ if ($ret) {
2700
+ if ($ret[0] !== Type::T_CONTROL) {
2701
+ $store = $this->env->store;
2702
+ $this->popEnv();
2703
+ $this->backPropagateEnv($store, $each->vars);
2704
+
2705
+ return $ret;
2706
+ }
2707
+
2708
+ if ($ret[1]) {
2709
+ break;
2710
+ }
2711
+ }
2712
+ }
2713
+ $store = $this->env->store;
2714
+ $this->popEnv();
2715
+ $this->backPropagateEnv($store, $each->vars);
2716
+
2717
+ break;
2718
+
2719
+ case Type::T_WHILE:
2720
+ list(, $while) = $child;
2721
+
2722
+ while ($this->isTruthy($this->reduce($while->cond, true))) {
2723
+ $ret = $this->compileChildren($while->children, $out);
2724
+
2725
+ if ($ret) {
2726
+ if ($ret[0] !== Type::T_CONTROL) {
2727
+ return $ret;
2728
+ }
2729
+
2730
+ if ($ret[1]) {
2731
+ break;
2732
+ }
2733
+ }
2734
+ }
2735
+ break;
2736
+
2737
+ case Type::T_FOR:
2738
+ list(, $for) = $child;
2739
+
2740
+ $start = $this->reduce($for->start, true);
2741
+ $end = $this->reduce($for->end, true);
2742
+
2743
+ if (! ($start[2] == $end[2] || $end->unitless())) {
2744
+ $this->throwError('Incompatible units: "%s" and "%s".', $start->unitStr(), $end->unitStr());
2745
+
2746
+ break;
2747
+ }
2748
+
2749
+ $unit = $start[2];
2750
+ $start = $start[1];
2751
+ $end = $end[1];
2752
+
2753
+ $d = $start < $end ? 1 : -1;
2754
+
2755
+ $this->pushEnv();
2756
+
2757
+ for (;;) {
2758
+ if ((! $for->until && $start - $d == $end) ||
2759
+ ($for->until && $start == $end)
2760
+ ) {
2761
+ break;
2762
+ }
2763
+
2764
+ $this->set($for->var, new Node\Number($start, $unit));
2765
+ $start += $d;
2766
+
2767
+ $ret = $this->compileChildren($for->children, $out);
2768
+
2769
+ if ($ret) {
2770
+ if ($ret[0] !== Type::T_CONTROL) {
2771
+ $store = $this->env->store;
2772
+ $this->popEnv();
2773
+ $this->backPropagateEnv($store, [$for->var]);
2774
+ return $ret;
2775
+ }
2776
+
2777
+ if ($ret[1]) {
2778
+ break;
2779
+ }
2780
+ }
2781
+ }
2782
+
2783
+ $store = $this->env->store;
2784
+ $this->popEnv();
2785
+ $this->backPropagateEnv($store, [$for->var]);
2786
+
2787
+ break;
2788
+
2789
+ case Type::T_BREAK:
2790
+ return [Type::T_CONTROL, true];
2791
+
2792
+ case Type::T_CONTINUE:
2793
+ return [Type::T_CONTROL, false];
2794
+
2795
+ case Type::T_RETURN:
2796
+ return $this->reduce($child[1], true);
2797
+
2798
+ case Type::T_NESTED_PROPERTY:
2799
+ $this->compileNestedPropertiesBlock($child[1], $out);
2800
+ break;
2801
+
2802
+ case Type::T_INCLUDE:
2803
+ // including a mixin
2804
+ list(, $name, $argValues, $content, $argUsing) = $child;
2805
+
2806
+ $mixin = $this->get(static::$namespaces['mixin'] . $name, false);
2807
+
2808
+ if (! $mixin) {
2809
+ $this->throwError("Undefined mixin $name");
2810
+ break;
2811
+ }
2812
+
2813
+ $callingScope = $this->getStoreEnv();
2814
+
2815
+ // push scope, apply args
2816
+ $this->pushEnv();
2817
+ $this->env->depth--;
2818
+
2819
+ // Find the parent selectors in the env to be able to know what '&' refers to in the mixin
2820
+ // and assign this fake parent to childs
2821
+ $selfParent = null;
2822
+
2823
+ if (isset($child['selfParent']) && isset($child['selfParent']->selectors)) {
2824
+ $selfParent = $child['selfParent'];
2825
+ } else {
2826
+ $parentSelectors = $this->multiplySelectors($this->env);
2827
+
2828
+ if ($parentSelectors) {
2829
+ $parent = new Block();
2830
+ $parent->selectors = $parentSelectors;
2831
+
2832
+ foreach ($mixin->children as $k => $child) {
2833
+ if (isset($child[1]) && \is_object($child[1]) && $child[1] instanceof Block) {
2834
+ $mixin->children[$k][1]->parent = $parent;
2835
+ }
2836
+ }
2837
+ }
2838
+ }
2839
+
2840
+ // clone the stored content to not have its scope spoiled by a further call to the same mixin
2841
+ // i.e., recursive @include of the same mixin
2842
+ if (isset($content)) {
2843
+ $copyContent = clone $content;
2844
+ $copyContent->scope = clone $callingScope;
2845
+
2846
+ $this->setRaw(static::$namespaces['special'] . 'content', $copyContent, $this->env);
2847
+ } else {
2848
+ $this->setRaw(static::$namespaces['special'] . 'content', null, $this->env);
2849
+ }
2850
+
2851
+ // save the "using" argument list for applying it to when "@content" is invoked
2852
+ if (isset($argUsing)) {
2853
+ $this->setRaw(static::$namespaces['special'] . 'using', $argUsing, $this->env);
2854
+ } else {
2855
+ $this->setRaw(static::$namespaces['special'] . 'using', null, $this->env);
2856
+ }
2857
+
2858
+ if (isset($mixin->args)) {
2859
+ $this->applyArguments($mixin->args, $argValues);
2860
+ }
2861
+
2862
+ $this->env->marker = 'mixin';
2863
+
2864
+ if (! empty($mixin->parentEnv)) {
2865
+ $this->env->declarationScopeParent = $mixin->parentEnv;
2866
+ } else {
2867
+ $this->throwError("@mixin $name() without parentEnv");
2868
+ }
2869
+
2870
+ $this->compileChildrenNoReturn($mixin->children, $out, $selfParent, $this->env->marker . " " . $name);
2871
+
2872
+ $this->popEnv();
2873
+ break;
2874
+
2875
+ case Type::T_MIXIN_CONTENT:
2876
+ $env = isset($this->storeEnv) ? $this->storeEnv : $this->env;
2877
+ $content = $this->get(static::$namespaces['special'] . 'content', false, $env);
2878
+ $argUsing = $this->get(static::$namespaces['special'] . 'using', false, $env);
2879
+ $argContent = $child[1];
2880
+
2881
+ if (! $content) {
2882
+ break;
2883
+ }
2884
+
2885
+ $storeEnv = $this->storeEnv;
2886
+ $varsUsing = [];
2887
+
2888
+ if (isset($argUsing) && isset($argContent)) {
2889
+ // Get the arguments provided for the content with the names provided in the "using" argument list
2890
+ $this->storeEnv = null;
2891
+ $varsUsing = $this->applyArguments($argUsing, $argContent, false);
2892
+ }
2893
+
2894
+ // restore the scope from the @content
2895
+ $this->storeEnv = $content->scope;
2896
+
2897
+ // append the vars from using if any
2898
+ foreach ($varsUsing as $name => $val) {
2899
+ $this->set($name, $val, true, $this->storeEnv);
2900
+ }
2901
+
2902
+ $this->compileChildrenNoReturn($content->children, $out);
2903
+
2904
+ $this->storeEnv = $storeEnv;
2905
+ break;
2906
+
2907
+ case Type::T_DEBUG:
2908
+ list(, $value) = $child;
2909
+
2910
+ $fname = $this->sourceNames[$this->sourceIndex];
2911
+ $line = $this->sourceLine;
2912
+ $value = $this->compileValue($this->reduce($value, true));
2913
+
2914
+ fwrite($this->stderr, "File $fname on line $line DEBUG: $value\n");
2915
+ break;
2916
+
2917
+ case Type::T_WARN:
2918
+ list(, $value) = $child;
2919
+
2920
+ $fname = $this->sourceNames[$this->sourceIndex];
2921
+ $line = $this->sourceLine;
2922
+ $value = $this->compileValue($this->reduce($value, true));
2923
+
2924
+ fwrite($this->stderr, "File $fname on line $line WARN: $value\n");
2925
+ break;
2926
+
2927
+ case Type::T_ERROR:
2928
+ list(, $value) = $child;
2929
+
2930
+ $fname = $this->sourceNames[$this->sourceIndex];
2931
+ $line = $this->sourceLine;
2932
+ $value = $this->compileValue($this->reduce($value, true));
2933
+
2934
+ $this->throwError("File $fname on line $line ERROR: $value\n");
2935
+ break;
2936
+
2937
+ case Type::T_CONTROL:
2938
+ $this->throwError('@break/@continue not permitted in this scope');
2939
+ break;
2940
+
2941
+ default:
2942
+ $this->throwError("unknown child type: $child[0]");
2943
+ }
2944
+ }
2945
+
2946
+ /**
2947
+ * Reduce expression to string
2948
+ *
2949
+ * @param array $exp
2950
+ *
2951
+ * @return array
2952
+ */
2953
+ protected function expToString($exp)
2954
+ {
2955
+ list(, $op, $left, $right, /* $inParens */, $whiteLeft, $whiteRight) = $exp;
2956
+
2957
+ $content = [$this->reduce($left)];
2958
+
2959
+ if ($whiteLeft) {
2960
+ $content[] = ' ';
2961
+ }
2962
+
2963
+ $content[] = $op;
2964
+
2965
+ if ($whiteRight) {
2966
+ $content[] = ' ';
2967
+ }
2968
+
2969
+ $content[] = $this->reduce($right);
2970
+
2971
+ return [Type::T_STRING, '', $content];
2972
+ }
2973
+
2974
+ /**
2975
+ * Is truthy?
2976
+ *
2977
+ * @param array $value
2978
+ *
2979
+ * @return boolean
2980
+ */
2981
+ protected function isTruthy($value)
2982
+ {
2983
+ return $value !== static::$false && $value !== static::$null;
2984
+ }
2985
+
2986
+ /**
2987
+ * Is the value a direct relationship combinator?
2988
+ *
2989
+ * @param string $value
2990
+ *
2991
+ * @return boolean
2992
+ */
2993
+ protected function isImmediateRelationshipCombinator($value)
2994
+ {
2995
+ return $value === '>' || $value === '+' || $value === '~';
2996
+ }
2997
+
2998
+ /**
2999
+ * Should $value cause its operand to eval
3000
+ *
3001
+ * @param array $value
3002
+ *
3003
+ * @return boolean
3004
+ */
3005
+ protected function shouldEval($value)
3006
+ {
3007
+ switch ($value[0]) {
3008
+ case Type::T_EXPRESSION:
3009
+ if ($value[1] === '/') {
3010
+ return $this->shouldEval($value[2]) || $this->shouldEval($value[3]);
3011
+ }
3012
+
3013
+ // fall-thru
3014
+ case Type::T_VARIABLE:
3015
+ case Type::T_FUNCTION_CALL:
3016
+ return true;
3017
+ }
3018
+
3019
+ return false;
3020
+ }
3021
+
3022
+ /**
3023
+ * Reduce value
3024
+ *
3025
+ * @param array $value
3026
+ * @param boolean $inExp
3027
+ *
3028
+ * @return null|string|array|\ScssPhp\ScssPhp\Node\Number
3029
+ */
3030
+ protected function reduce($value, $inExp = false)
3031
+ {
3032
+ if (\is_null($value)) {
3033
+ return null;
3034
+ }
3035
+
3036
+ switch ($value[0]) {
3037
+ case Type::T_EXPRESSION:
3038
+ list(, $op, $left, $right, $inParens) = $value;
3039
+
3040
+ $opName = isset(static::$operatorNames[$op]) ? static::$operatorNames[$op] : $op;
3041
+ $inExp = $inExp || $this->shouldEval($left) || $this->shouldEval($right);
3042
+
3043
+ $left = $this->reduce($left, true);
3044
+
3045
+ if ($op !== 'and' && $op !== 'or') {
3046
+ $right = $this->reduce($right, true);
3047
+ }
3048
+
3049
+ // special case: looks like css shorthand
3050
+ if ($opName == 'div' && ! $inParens && ! $inExp && isset($right[2]) &&
3051
+ (($right[0] !== Type::T_NUMBER && $right[2] != '') ||
3052
+ ($right[0] === Type::T_NUMBER && ! $right->unitless()))
3053
+ ) {
3054
+ return $this->expToString($value);
3055
+ }
3056
+
3057
+ $left = $this->coerceForExpression($left);
3058
+ $right = $this->coerceForExpression($right);
3059
+ $ltype = $left[0];
3060
+ $rtype = $right[0];
3061
+
3062
+ $ucOpName = ucfirst($opName);
3063
+ $ucLType = ucfirst($ltype);
3064
+ $ucRType = ucfirst($rtype);
3065
+
3066
+ // this tries:
3067
+ // 1. op[op name][left type][right type]
3068
+ // 2. op[left type][right type] (passing the op as first arg
3069
+ // 3. op[op name]
3070
+ $fn = "op${ucOpName}${ucLType}${ucRType}";
3071
+
3072
+ if (\is_callable([$this, $fn]) ||
3073
+ (($fn = "op${ucLType}${ucRType}") &&
3074
+ \is_callable([$this, $fn]) &&
3075
+ $passOp = true) ||
3076
+ (($fn = "op${ucOpName}") &&
3077
+ \is_callable([$this, $fn]) &&
3078
+ $genOp = true)
3079
+ ) {
3080
+ $coerceUnit = false;
3081
+
3082
+ if (! isset($genOp) &&
3083
+ $left[0] === Type::T_NUMBER && $right[0] === Type::T_NUMBER
3084
+ ) {
3085
+ $coerceUnit = true;
3086
+
3087
+ switch ($opName) {
3088
+ case 'mul':
3089
+ $targetUnit = $left[2];
3090
+
3091
+ foreach ($right[2] as $unit => $exp) {
3092
+ $targetUnit[$unit] = (isset($targetUnit[$unit]) ? $targetUnit[$unit] : 0) + $exp;
3093
+ }
3094
+ break;
3095
+
3096
+ case 'div':
3097
+ $targetUnit = $left[2];
3098
+
3099
+ foreach ($right[2] as $unit => $exp) {
3100
+ $targetUnit[$unit] = (isset($targetUnit[$unit]) ? $targetUnit[$unit] : 0) - $exp;
3101
+ }
3102
+ break;
3103
+
3104
+ case 'mod':
3105
+ $targetUnit = $left[2];
3106
+ break;
3107
+
3108
+ default:
3109
+ $targetUnit = $left->unitless() ? $right[2] : $left[2];
3110
+ }
3111
+
3112
+ $baseUnitLeft = $left->isNormalizable();
3113
+ $baseUnitRight = $right->isNormalizable();
3114
+
3115
+ if ($baseUnitLeft && $baseUnitRight && $baseUnitLeft === $baseUnitRight) {
3116
+ $left = $left->normalize();
3117
+ $right = $right->normalize();
3118
+ }
3119
+ }
3120
+
3121
+ $shouldEval = $inParens || $inExp;
3122
+
3123
+ if (isset($passOp)) {
3124
+ $out = $this->$fn($op, $left, $right, $shouldEval);
3125
+ } else {
3126
+ $out = $this->$fn($left, $right, $shouldEval);
3127
+ }
3128
+
3129
+ if (isset($out)) {
3130
+ if ($coerceUnit && $out[0] === Type::T_NUMBER) {
3131
+ $out = $out->coerce($targetUnit);
3132
+ }
3133
+
3134
+ return $out;
3135
+ }
3136
+ }
3137
+
3138
+ return $this->expToString($value);
3139
+
3140
+ case Type::T_UNARY:
3141
+ list(, $op, $exp, $inParens) = $value;
3142
+
3143
+ $inExp = $inExp || $this->shouldEval($exp);
3144
+ $exp = $this->reduce($exp);
3145
+
3146
+ if ($exp[0] === Type::T_NUMBER) {
3147
+ switch ($op) {
3148
+ case '+':
3149
+ return new Node\Number($exp[1], $exp[2]);
3150
+
3151
+ case '-':
3152
+ return new Node\Number(-$exp[1], $exp[2]);
3153
+ }
3154
+ }
3155
+
3156
+ if ($op === 'not') {
3157
+ if ($inExp || $inParens) {
3158
+ if ($exp === static::$false || $exp === static::$null) {
3159
+ return static::$true;
3160
+ }
3161
+
3162
+ return static::$false;
3163
+ }
3164
+
3165
+ $op = $op . ' ';
3166
+ }
3167
+
3168
+ return [Type::T_STRING, '', [$op, $exp]];
3169
+
3170
+ case Type::T_VARIABLE:
3171
+ return $this->reduce($this->get($value[1]));
3172
+
3173
+ case Type::T_LIST:
3174
+ foreach ($value[2] as &$item) {
3175
+ $item = $this->reduce($item);
3176
+ }
3177
+
3178
+ return $value;
3179
+
3180
+ case Type::T_MAP:
3181
+ foreach ($value[1] as &$item) {
3182
+ $item = $this->reduce($item);
3183
+ }
3184
+
3185
+ foreach ($value[2] as &$item) {
3186
+ $item = $this->reduce($item);
3187
+ }
3188
+
3189
+ return $value;
3190
+
3191
+ case Type::T_STRING:
3192
+ foreach ($value[2] as &$item) {
3193
+ if (\is_array($item) || $item instanceof \ArrayAccess) {
3194
+ $item = $this->reduce($item);
3195
+ }
3196
+ }
3197
+
3198
+ return $value;
3199
+
3200
+ case Type::T_INTERPOLATE:
3201
+ $value[1] = $this->reduce($value[1]);
3202
+
3203
+ if ($inExp) {
3204
+ return $value[1];
3205
+ }
3206
+
3207
+ return $value;
3208
+
3209
+ case Type::T_FUNCTION_CALL:
3210
+ return $this->fncall($value[1], $value[2]);
3211
+
3212
+ case Type::T_SELF:
3213
+ $selfSelector = $this->multiplySelectors($this->env);
3214
+ $selfSelector = $this->collapseSelectors($selfSelector, true);
3215
+
3216
+ return $selfSelector;
3217
+
3218
+ default:
3219
+ return $value;
3220
+ }
3221
+ }
3222
+
3223
+ /**
3224
+ * Function caller
3225
+ *
3226
+ * @param string $name
3227
+ * @param array $argValues
3228
+ *
3229
+ * @return array|null
3230
+ */
3231
+ protected function fncall($name, $argValues)
3232
+ {
3233
+ // SCSS @function
3234
+ if ($this->callScssFunction($name, $argValues, $returnValue)) {
3235
+ return $returnValue;
3236
+ }
3237
+
3238
+ // native PHP functions
3239
+ if ($this->callNativeFunction($name, $argValues, $returnValue)) {
3240
+ return $returnValue;
3241
+ }
3242
+
3243
+ // for CSS functions, simply flatten the arguments into a list
3244
+ $listArgs = [];
3245
+
3246
+ foreach ((array) $argValues as $arg) {
3247
+ if (empty($arg[0])) {
3248
+ $listArgs[] = $this->reduce($arg[1]);
3249
+ }
3250
+ }
3251
+
3252
+ return [Type::T_FUNCTION, $name, [Type::T_LIST, ',', $listArgs]];
3253
+ }
3254
+
3255
+ /**
3256
+ * Normalize name
3257
+ *
3258
+ * @param string $name
3259
+ *
3260
+ * @return string
3261
+ */
3262
+ protected function normalizeName($name)
3263
+ {
3264
+ return str_replace('-', '_', $name);
3265
+ }
3266
+
3267
+ /**
3268
+ * Normalize value
3269
+ *
3270
+ * @param array $value
3271
+ *
3272
+ * @return array
3273
+ */
3274
+ public function normalizeValue($value)
3275
+ {
3276
+ $value = $this->coerceForExpression($this->reduce($value));
3277
+
3278
+ switch ($value[0]) {
3279
+ case Type::T_LIST:
3280
+ $value = $this->extractInterpolation($value);
3281
+
3282
+ if ($value[0] !== Type::T_LIST) {
3283
+ return [Type::T_KEYWORD, $this->compileValue($value)];
3284
+ }
3285
+
3286
+ foreach ($value[2] as $key => $item) {
3287
+ $value[2][$key] = $this->normalizeValue($item);
3288
+ }
3289
+
3290
+ if (! empty($value['enclosing'])) {
3291
+ unset($value['enclosing']);
3292
+ }
3293
+
3294
+ return $value;
3295
+
3296
+ case Type::T_STRING:
3297
+ return [$value[0], '"', [$this->compileStringContent($value)]];
3298
+
3299
+ case Type::T_NUMBER:
3300
+ return $value->normalize();
3301
+
3302
+ case Type::T_INTERPOLATE:
3303
+ return [Type::T_KEYWORD, $this->compileValue($value)];
3304
+
3305
+ default:
3306
+ return $value;
3307
+ }
3308
+ }
3309
+
3310
+ /**
3311
+ * Add numbers
3312
+ *
3313
+ * @param array $left
3314
+ * @param array $right
3315
+ *
3316
+ * @return \ScssPhp\ScssPhp\Node\Number
3317
+ */
3318
+ protected function opAddNumberNumber($left, $right)
3319
+ {
3320
+ return new Node\Number($left[1] + $right[1], $left[2]);
3321
+ }
3322
+
3323
+ /**
3324
+ * Multiply numbers
3325
+ *
3326
+ * @param array $left
3327
+ * @param array $right
3328
+ *
3329
+ * @return \ScssPhp\ScssPhp\Node\Number
3330
+ */
3331
+ protected function opMulNumberNumber($left, $right)
3332
+ {
3333
+ return new Node\Number($left[1] * $right[1], $left[2]);
3334
+ }
3335
+
3336
+ /**
3337
+ * Subtract numbers
3338
+ *
3339
+ * @param array $left
3340
+ * @param array $right
3341
+ *
3342
+ * @return \ScssPhp\ScssPhp\Node\Number
3343
+ */
3344
+ protected function opSubNumberNumber($left, $right)
3345
+ {
3346
+ return new Node\Number($left[1] - $right[1], $left[2]);
3347
+ }
3348
+
3349
+ /**
3350
+ * Divide numbers
3351
+ *
3352
+ * @param array $left
3353
+ * @param array $right
3354
+ *
3355
+ * @return array|\ScssPhp\ScssPhp\Node\Number
3356
+ */
3357
+ protected function opDivNumberNumber($left, $right)
3358
+ {
3359
+ if ($right[1] == 0) {
3360
+ return ($left[1] == 0) ? static::$NaN : static::$Infinity;
3361
+ }
3362
+
3363
+ return new Node\Number($left[1] / $right[1], $left[2]);
3364
+ }
3365
+
3366
+ /**
3367
+ * Mod numbers
3368
+ *
3369
+ * @param array $left
3370
+ * @param array $right
3371
+ *
3372
+ * @return \ScssPhp\ScssPhp\Node\Number
3373
+ */
3374
+ protected function opModNumberNumber($left, $right)
3375
+ {
3376
+ if ($right[1] == 0) {
3377
+ return static::$NaN;
3378
+ }
3379
+
3380
+ return new Node\Number($left[1] % $right[1], $left[2]);
3381
+ }
3382
+
3383
+ /**
3384
+ * Add strings
3385
+ *
3386
+ * @param array $left
3387
+ * @param array $right
3388
+ *
3389
+ * @return array|null
3390
+ */
3391
+ protected function opAdd($left, $right)
3392
+ {
3393
+ if ($strLeft = $this->coerceString($left)) {
3394
+ if ($right[0] === Type::T_STRING) {
3395
+ $right[1] = '';
3396
+ }
3397
+
3398
+ $strLeft[2][] = $right;
3399
+
3400
+ return $strLeft;
3401
+ }
3402
+
3403
+ if ($strRight = $this->coerceString($right)) {
3404
+ if ($left[0] === Type::T_STRING) {
3405
+ $left[1] = '';
3406
+ }
3407
+
3408
+ array_unshift($strRight[2], $left);
3409
+
3410
+ return $strRight;
3411
+ }
3412
+
3413
+ return null;
3414
+ }
3415
+
3416
+ /**
3417
+ * Boolean and
3418
+ *
3419
+ * @param array $left
3420
+ * @param array $right
3421
+ * @param boolean $shouldEval
3422
+ *
3423
+ * @return array|null
3424
+ */
3425
+ protected function opAnd($left, $right, $shouldEval)
3426
+ {
3427
+ $truthy = ($left === static::$null || $right === static::$null) ||
3428
+ ($left === static::$false || $left === static::$true) &&
3429
+ ($right === static::$false || $right === static::$true);
3430
+
3431
+ if (! $shouldEval) {
3432
+ if (! $truthy) {
3433
+ return null;
3434
+ }
3435
+ }
3436
+
3437
+ if ($left !== static::$false && $left !== static::$null) {
3438
+ return $this->reduce($right, true);
3439
+ }
3440
+
3441
+ return $left;
3442
+ }
3443
+
3444
+ /**
3445
+ * Boolean or
3446
+ *
3447
+ * @param array $left
3448
+ * @param array $right
3449
+ * @param boolean $shouldEval
3450
+ *
3451
+ * @return array|null
3452
+ */
3453
+ protected function opOr($left, $right, $shouldEval)
3454
+ {
3455
+ $truthy = ($left === static::$null || $right === static::$null) ||
3456
+ ($left === static::$false || $left === static::$true) &&
3457
+ ($right === static::$false || $right === static::$true);
3458
+
3459
+ if (! $shouldEval) {
3460
+ if (! $truthy) {
3461
+ return null;
3462
+ }
3463
+ }
3464
+
3465
+ if ($left !== static::$false && $left !== static::$null) {
3466
+ return $left;
3467
+ }
3468
+
3469
+ return $this->reduce($right, true);
3470
+ }
3471
+
3472
+ /**
3473
+ * Compare colors
3474
+ *
3475
+ * @param string $op
3476
+ * @param array $left
3477
+ * @param array $right
3478
+ *
3479
+ * @return array
3480
+ */
3481
+ protected function opColorColor($op, $left, $right)
3482
+ {
3483
+ $out = [Type::T_COLOR];
3484
+
3485
+ foreach ([1, 2, 3] as $i) {
3486
+ $lval = isset($left[$i]) ? $left[$i] : 0;
3487
+ $rval = isset($right[$i]) ? $right[$i] : 0;
3488
+
3489
+ switch ($op) {
3490
+ case '+':
3491
+ $out[] = $lval + $rval;
3492
+ break;
3493
+
3494
+ case '-':
3495
+ $out[] = $lval - $rval;
3496
+ break;
3497
+
3498
+ case '*':
3499
+ $out[] = $lval * $rval;
3500
+ break;
3501
+
3502
+ case '%':
3503
+ $out[] = $lval % $rval;
3504
+ break;
3505
+
3506
+ case '/':
3507
+ if ($rval == 0) {
3508
+ $this->throwError("color: Can't divide by zero");
3509
+ break 2;
3510
+ }
3511
+
3512
+ $out[] = (int) ($lval / $rval);
3513
+ break;
3514
+
3515
+ case '==':
3516
+ return $this->opEq($left, $right);
3517
+
3518
+ case '!=':
3519
+ return $this->opNeq($left, $right);
3520
+
3521
+ default:
3522
+ $this->throwError("color: unknown op $op");
3523
+ break 2;
3524
+ }
3525
+ }
3526
+
3527
+ if (isset($left[4])) {
3528
+ $out[4] = $left[4];
3529
+ } elseif (isset($right[4])) {
3530
+ $out[4] = $right[4];
3531
+ }
3532
+
3533
+ return $this->fixColor($out);
3534
+ }
3535
+
3536
+ /**
3537
+ * Compare color and number
3538
+ *
3539
+ * @param string $op
3540
+ * @param array $left
3541
+ * @param array $right
3542
+ *
3543
+ * @return array
3544
+ */
3545
+ protected function opColorNumber($op, $left, $right)
3546
+ {
3547
+ $value = $right[1];
3548
+
3549
+ return $this->opColorColor(
3550
+ $op,
3551
+ $left,
3552
+ [Type::T_COLOR, $value, $value, $value]
3553
+ );
3554
+ }
3555
+
3556
+ /**
3557
+ * Compare number and color
3558
+ *
3559
+ * @param string $op
3560
+ * @param array $left
3561
+ * @param array $right
3562
+ *
3563
+ * @return array
3564
+ */
3565
+ protected function opNumberColor($op, $left, $right)
3566
+ {
3567
+ $value = $left[1];
3568
+
3569
+ return $this->opColorColor(
3570
+ $op,
3571
+ [Type::T_COLOR, $value, $value, $value],
3572
+ $right
3573
+ );
3574
+ }
3575
+
3576
+ /**
3577
+ * Compare number1 == number2
3578
+ *
3579
+ * @param array $left
3580
+ * @param array $right
3581
+ *
3582
+ * @return array
3583
+ */
3584
+ protected function opEq($left, $right)
3585
+ {
3586
+ if (($lStr = $this->coerceString($left)) && ($rStr = $this->coerceString($right))) {
3587
+ $lStr[1] = '';
3588
+ $rStr[1] = '';
3589
+
3590
+ $left = $this->compileValue($lStr);
3591
+ $right = $this->compileValue($rStr);
3592
+ }
3593
+
3594
+ return $this->toBool($left === $right);
3595
+ }
3596
+
3597
+ /**
3598
+ * Compare number1 != number2
3599
+ *
3600
+ * @param array $left
3601
+ * @param array $right
3602
+ *
3603
+ * @return array
3604
+ */
3605
+ protected function opNeq($left, $right)
3606
+ {
3607
+ if (($lStr = $this->coerceString($left)) && ($rStr = $this->coerceString($right))) {
3608
+ $lStr[1] = '';
3609
+ $rStr[1] = '';
3610
+
3611
+ $left = $this->compileValue($lStr);
3612
+ $right = $this->compileValue($rStr);
3613
+ }
3614
+
3615
+ return $this->toBool($left !== $right);
3616
+ }
3617
+
3618
+ /**
3619
+ * Compare number1 >= number2
3620
+ *
3621
+ * @param array $left
3622
+ * @param array $right
3623
+ *
3624
+ * @return array
3625
+ */
3626
+ protected function opGteNumberNumber($left, $right)
3627
+ {
3628
+ return $this->toBool($left[1] >= $right[1]);
3629
+ }
3630
+
3631
+ /**
3632
+ * Compare number1 > number2
3633
+ *
3634
+ * @param array $left
3635
+ * @param array $right
3636
+ *
3637
+ * @return array
3638
+ */
3639
+ protected function opGtNumberNumber($left, $right)
3640
+ {
3641
+ return $this->toBool($left[1] > $right[1]);
3642
+ }
3643
+
3644
+ /**
3645
+ * Compare number1 <= number2
3646
+ *
3647
+ * @param array $left
3648
+ * @param array $right
3649
+ *
3650
+ * @return array
3651
+ */
3652
+ protected function opLteNumberNumber($left, $right)
3653
+ {
3654
+ return $this->toBool($left[1] <= $right[1]);
3655
+ }
3656
+
3657
+ /**
3658
+ * Compare number1 < number2
3659
+ *
3660
+ * @param array $left
3661
+ * @param array $right
3662
+ *
3663
+ * @return array
3664
+ */
3665
+ protected function opLtNumberNumber($left, $right)
3666
+ {
3667
+ return $this->toBool($left[1] < $right[1]);
3668
+ }
3669
+
3670
+ /**
3671
+ * Three-way comparison, aka spaceship operator
3672
+ *
3673
+ * @param array $left
3674
+ * @param array $right
3675
+ *
3676
+ * @return \ScssPhp\ScssPhp\Node\Number
3677
+ */
3678
+ protected function opCmpNumberNumber($left, $right)
3679
+ {
3680
+ $n = $left[1] - $right[1];
3681
+
3682
+ return new Node\Number($n ? $n / abs($n) : 0, '');
3683
+ }
3684
+
3685
+ /**
3686
+ * Cast to boolean
3687
+ *
3688
+ * @api
3689
+ *
3690
+ * @param mixed $thing
3691
+ *
3692
+ * @return array
3693
+ */
3694
+ public function toBool($thing)
3695
+ {
3696
+ return $thing ? static::$true : static::$false;
3697
+ }
3698
+
3699
+ /**
3700
+ * Compiles a primitive value into a CSS property value.
3701
+ *
3702
+ * Values in scssphp are typed by being wrapped in arrays, their format is
3703
+ * typically:
3704
+ *
3705
+ * array(type, contents [, additional_contents]*)
3706
+ *
3707
+ * The input is expected to be reduced. This function will not work on
3708
+ * things like expressions and variables.
3709
+ *
3710
+ * @api
3711
+ *
3712
+ * @param array $value
3713
+ *
3714
+ * @return string|array
3715
+ */
3716
+ public function compileValue($value)
3717
+ {
3718
+ $value = $this->reduce($value);
3719
+
3720
+ switch ($value[0]) {
3721
+ case Type::T_KEYWORD:
3722
+ return $value[1];
3723
+
3724
+ case Type::T_COLOR:
3725
+ // [1] - red component (either number for a %)
3726
+ // [2] - green component
3727
+ // [3] - blue component
3728
+ // [4] - optional alpha component
3729
+ list(, $r, $g, $b) = $value;
3730
+
3731
+ $r = $this->compileRGBAValue($r);
3732
+ $g = $this->compileRGBAValue($g);
3733
+ $b = $this->compileRGBAValue($b);
3734
+
3735
+ if (\count($value) === 5) {
3736
+ $alpha = $this->compileRGBAValue($value[4], true);
3737
+
3738
+ if (! is_numeric($alpha) || $alpha < 1) {
3739
+ $colorName = Colors::RGBaToColorName($r, $g, $b, $alpha);
3740
+
3741
+ if (! \is_null($colorName)) {
3742
+ return $colorName;
3743
+ }
3744
+
3745
+ if (is_numeric($alpha)) {
3746
+ $a = new Node\Number($alpha, '');
3747
+ } else {
3748
+ $a = $alpha;
3749
+ }
3750
+
3751
+ return 'rgba(' . $r . ', ' . $g . ', ' . $b . ', ' . $a . ')';
3752
+ }
3753
+ }
3754
+
3755
+ if (! is_numeric($r) || ! is_numeric($g) || ! is_numeric($b)) {
3756
+ return 'rgb(' . $r . ', ' . $g . ', ' . $b . ')';
3757
+ }
3758
+
3759
+ $colorName = Colors::RGBaToColorName($r, $g, $b);
3760
+
3761
+ if (! \is_null($colorName)) {
3762
+ return $colorName;
3763
+ }
3764
+
3765
+ $h = sprintf('#%02x%02x%02x', $r, $g, $b);
3766
+
3767
+ // Converting hex color to short notation (e.g. #003399 to #039)
3768
+ if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) {
3769
+ $h = '#' . $h[1] . $h[3] . $h[5];
3770
+ }
3771
+
3772
+ return $h;
3773
+
3774
+ case Type::T_NUMBER:
3775
+ return $value->output($this);
3776
+
3777
+ case Type::T_STRING:
3778
+ return $value[1] . $this->compileStringContent($value) . $value[1];
3779
+
3780
+ case Type::T_FUNCTION:
3781
+ $args = ! empty($value[2]) ? $this->compileValue($value[2]) : '';
3782
+
3783
+ return "$value[1]($args)";
3784
+
3785
+ case Type::T_LIST:
3786
+ $value = $this->extractInterpolation($value);
3787
+
3788
+ if ($value[0] !== Type::T_LIST) {
3789
+ return $this->compileValue($value);
3790
+ }
3791
+
3792
+ list(, $delim, $items) = $value;
3793
+ $pre = $post = "";
3794
+
3795
+ if (! empty($value['enclosing'])) {
3796
+ switch ($value['enclosing']) {
3797
+ case 'parent':
3798
+ //$pre = "(";
3799
+ //$post = ")";
3800
+ break;
3801
+ case 'forced_parent':
3802
+ $pre = "(";
3803
+ $post = ")";
3804
+ break;
3805
+ case 'bracket':
3806
+ case 'forced_bracket':
3807
+ $pre = "[";
3808
+ $post = "]";
3809
+ break;
3810
+ }
3811
+ }
3812
+
3813
+ $prefix_value = '';
3814
+ if ($delim !== ' ') {
3815
+ $prefix_value = ' ';
3816
+ }
3817
+
3818
+ $filtered = [];
3819
+
3820
+ foreach ($items as $item) {
3821
+ if ($item[0] === Type::T_NULL) {
3822
+ continue;
3823
+ }
3824
+
3825
+ $compiled = $this->compileValue($item);
3826
+ if ($prefix_value && \strlen($compiled)) {
3827
+ $compiled = $prefix_value . $compiled;
3828
+ }
3829
+ $filtered[] = $compiled;
3830
+ }
3831
+
3832
+ return $pre . substr(implode("$delim", $filtered), \strlen($prefix_value)) . $post;
3833
+
3834
+ case Type::T_MAP:
3835
+ $keys = $value[1];
3836
+ $values = $value[2];
3837
+ $filtered = [];
3838
+
3839
+ for ($i = 0, $s = \count($keys); $i < $s; $i++) {
3840
+ $filtered[$this->compileValue($keys[$i])] = $this->compileValue($values[$i]);
3841
+ }
3842
+
3843
+ array_walk($filtered, function (&$value, $key) {
3844
+ $value = $key . ': ' . $value;
3845
+ });
3846
+
3847
+ return '(' . implode(', ', $filtered) . ')';
3848
+
3849
+ case Type::T_INTERPOLATED:
3850
+ // node created by extractInterpolation
3851
+ list(, $interpolate, $left, $right) = $value;
3852
+ list(,, $whiteLeft, $whiteRight) = $interpolate;
3853
+
3854
+ $delim = $left[1];
3855
+
3856
+ if ($delim && $delim !== ' ' && ! $whiteLeft) {
3857
+ $delim .= ' ';
3858
+ }
3859
+
3860
+ $left = \count($left[2]) > 0 ?
3861
+ $this->compileValue($left) . $delim . $whiteLeft: '';
3862
+
3863
+ $delim = $right[1];
3864
+
3865
+ if ($delim && $delim !== ' ') {
3866
+ $delim .= ' ';
3867
+ }
3868
+
3869
+ $right = \count($right[2]) > 0 ?
3870
+ $whiteRight . $delim . $this->compileValue($right) : '';
3871
+
3872
+ return $left . $this->compileValue($interpolate) . $right;
3873
+
3874
+ case Type::T_INTERPOLATE:
3875
+ // strip quotes if it's a string
3876
+ $reduced = $this->reduce($value[1]);
3877
+
3878
+ switch ($reduced[0]) {
3879
+ case Type::T_LIST:
3880
+ $reduced = $this->extractInterpolation($reduced);
3881
+
3882
+ if ($reduced[0] !== Type::T_LIST) {
3883
+ break;
3884
+ }
3885
+
3886
+ list(, $delim, $items) = $reduced;
3887
+
3888
+ if ($delim !== ' ') {
3889
+ $delim .= ' ';
3890
+ }
3891
+
3892
+ $filtered = [];
3893
+
3894
+ foreach ($items as $item) {
3895
+ if ($item[0] === Type::T_NULL) {
3896
+ continue;
3897
+ }
3898
+
3899
+ $temp = $this->compileValue([Type::T_KEYWORD, $item]);
3900
+
3901
+ if ($temp[0] === Type::T_STRING) {
3902
+ $filtered[] = $this->compileStringContent($temp);
3903
+ } elseif ($temp[0] === Type::T_KEYWORD) {
3904
+ $filtered[] = $temp[1];
3905
+ } else {
3906
+ $filtered[] = $this->compileValue($temp);
3907
+ }
3908
+ }
3909
+
3910
+ $reduced = [Type::T_KEYWORD, implode("$delim", $filtered)];
3911
+ break;
3912
+
3913
+ case Type::T_STRING:
3914
+ $reduced = [Type::T_KEYWORD, $this->compileStringContent($reduced)];
3915
+ break;
3916
+
3917
+ case Type::T_NULL:
3918
+ $reduced = [Type::T_KEYWORD, ''];
3919
+ }
3920
+
3921
+ return $this->compileValue($reduced);
3922
+
3923
+ case Type::T_NULL:
3924
+ return 'null';
3925
+
3926
+ case Type::T_COMMENT:
3927
+ return $this->compileCommentValue($value);
3928
+
3929
+ default:
3930
+ $this->throwError("unknown value type: ".json_encode($value));
3931
+ }
3932
+ }
3933
+
3934
+ /**
3935
+ * Flatten list
3936
+ *
3937
+ * @param array $list
3938
+ *
3939
+ * @return string
3940
+ */
3941
+ protected function flattenList($list)
3942
+ {
3943
+ return $this->compileValue($list);
3944
+ }
3945
+
3946
+ /**
3947
+ * Compile string content
3948
+ *
3949
+ * @param array $string
3950
+ *
3951
+ * @return string
3952
+ */
3953
+ protected function compileStringContent($string)
3954
+ {
3955
+ $parts = [];
3956
+
3957
+ foreach ($string[2] as $part) {
3958
+ if (\is_array($part) || $part instanceof \ArrayAccess) {
3959
+ $parts[] = $this->compileValue($part);
3960
+ } else {
3961
+ $parts[] = $part;
3962
+ }
3963
+ }
3964
+
3965
+ return implode($parts);
3966
+ }
3967
+
3968
+ /**
3969
+ * Extract interpolation; it doesn't need to be recursive, compileValue will handle that
3970
+ *
3971
+ * @param array $list
3972
+ *
3973
+ * @return array
3974
+ */
3975
+ protected function extractInterpolation($list)
3976
+ {
3977
+ $items = $list[2];
3978
+
3979
+ foreach ($items as $i => $item) {
3980
+ if ($item[0] === Type::T_INTERPOLATE) {
3981
+ $before = [Type::T_LIST, $list[1], \array_slice($items, 0, $i)];
3982
+ $after = [Type::T_LIST, $list[1], \array_slice($items, $i + 1)];
3983
+
3984
+ return [Type::T_INTERPOLATED, $item, $before, $after];
3985
+ }
3986
+ }
3987
+
3988
+ return $list;
3989
+ }
3990
+
3991
+ /**
3992
+ * Find the final set of selectors
3993
+ *
3994
+ * @param \ScssPhp\ScssPhp\Compiler\Environment $env
3995
+ * @param \ScssPhp\ScssPhp\Block $selfParent
3996
+ *
3997
+ * @return array
3998
+ */
3999
+ protected function multiplySelectors(Environment $env, $selfParent = null)
4000
+ {
4001
+ $envs = $this->compactEnv($env);
4002
+ $selectors = [];
4003
+ $parentSelectors = [[]];
4004
+
4005
+ $selfParentSelectors = null;
4006
+
4007
+ if (! \is_null($selfParent) && $selfParent->selectors) {
4008
+ $selfParentSelectors = $this->evalSelectors($selfParent->selectors);
4009
+ }
4010
+
4011
+ while ($env = array_pop($envs)) {
4012
+ if (empty($env->selectors)) {
4013
+ continue;
4014
+ }
4015
+
4016
+ $selectors = $env->selectors;
4017
+
4018
+ do {
4019
+ $stillHasSelf = false;
4020
+ $prevSelectors = $selectors;
4021
+ $selectors = [];
4022
+
4023
+ foreach ($prevSelectors as $selector) {
4024
+ foreach ($parentSelectors as $parent) {
4025
+ if ($selfParentSelectors) {
4026
+ foreach ($selfParentSelectors as $selfParent) {
4027
+ // if no '&' in the selector, each call will give same result, only add once
4028
+ $s = $this->joinSelectors($parent, $selector, $stillHasSelf, $selfParent);
4029
+ $selectors[serialize($s)] = $s;
4030
+ }
4031
+ } else {
4032
+ $s = $this->joinSelectors($parent, $selector, $stillHasSelf);
4033
+ $selectors[serialize($s)] = $s;
4034
+ }
4035
+ }
4036
+ }
4037
+ } while ($stillHasSelf);
4038
+
4039
+ $parentSelectors = $selectors;
4040
+ }
4041
+
4042
+ $selectors = array_values($selectors);
4043
+
4044
+ return $selectors;
4045
+ }
4046
+
4047
+ /**
4048
+ * Join selectors; looks for & to replace, or append parent before child
4049
+ *
4050
+ * @param array $parent
4051
+ * @param array $child
4052
+ * @param boolean $stillHasSelf
4053
+ * @param array $selfParentSelectors
4054
+
4055
+ * @return array
4056
+ */
4057
+ protected function joinSelectors($parent, $child, &$stillHasSelf, $selfParentSelectors = null)
4058
+ {
4059
+ $setSelf = false;
4060
+ $out = [];
4061
+
4062
+ foreach ($child as $part) {
4063
+ $newPart = [];
4064
+
4065
+ foreach ($part as $p) {
4066
+ // only replace & once and should be recalled to be able to make combinations
4067
+ if ($p === static::$selfSelector && $setSelf) {
4068
+ $stillHasSelf = true;
4069
+ }
4070
+
4071
+ if ($p === static::$selfSelector && ! $setSelf) {
4072
+ $setSelf = true;
4073
+
4074
+ if (\is_null($selfParentSelectors)) {
4075
+ $selfParentSelectors = $parent;
4076
+ }
4077
+
4078
+ foreach ($selfParentSelectors as $i => $parentPart) {
4079
+ if ($i > 0) {
4080
+ $out[] = $newPart;
4081
+ $newPart = [];
4082
+ }
4083
+
4084
+ foreach ($parentPart as $pp) {
4085
+ if (\is_array($pp)) {
4086
+ $flatten = [];
4087
+
4088
+ array_walk_recursive($pp, function ($a) use (&$flatten) {
4089
+ $flatten[] = $a;
4090
+ });
4091
+
4092
+ $pp = implode($flatten);
4093
+ }
4094
+
4095
+ $newPart[] = $pp;
4096
+ }
4097
+ }
4098
+ } else {
4099
+ $newPart[] = $p;
4100
+ }
4101
+ }
4102
+
4103
+ $out[] = $newPart;
4104
+ }
4105
+
4106
+ return $setSelf ? $out : array_merge($parent, $child);
4107
+ }
4108
+
4109
+ /**
4110
+ * Multiply media
4111
+ *
4112
+ * @param \ScssPhp\ScssPhp\Compiler\Environment $env
4113
+ * @param array $childQueries
4114
+ *
4115
+ * @return array
4116
+ */
4117
+ protected function multiplyMedia(Environment $env = null, $childQueries = null)
4118
+ {
4119
+ if (! isset($env) ||
4120
+ ! empty($env->block->type) && $env->block->type !== Type::T_MEDIA
4121
+ ) {
4122
+ return $childQueries;
4123
+ }
4124
+
4125
+ // plain old block, skip
4126
+ if (empty($env->block->type)) {
4127
+ return $this->multiplyMedia($env->parent, $childQueries);
4128
+ }
4129
+
4130
+ $parentQueries = isset($env->block->queryList)
4131
+ ? $env->block->queryList
4132
+ : [[[Type::T_MEDIA_VALUE, $env->block->value]]];
4133
+
4134
+ $store = [$this->env, $this->storeEnv];
4135
+
4136
+ $this->env = $env;
4137
+ $this->storeEnv = null;
4138
+ $parentQueries = $this->evaluateMediaQuery($parentQueries);
4139
+
4140
+ list($this->env, $this->storeEnv) = $store;
4141
+
4142
+ if (\is_null($childQueries)) {
4143
+ $childQueries = $parentQueries;
4144
+ } else {
4145
+ $originalQueries = $childQueries;
4146
+ $childQueries = [];
4147
+
4148
+ foreach ($parentQueries as $parentQuery) {
4149
+ foreach ($originalQueries as $childQuery) {
4150
+ $childQueries[] = array_merge(
4151
+ $parentQuery,
4152
+ [[Type::T_MEDIA_TYPE, [Type::T_KEYWORD, 'all']]],
4153
+ $childQuery
4154
+ );
4155
+ }
4156
+ }
4157
+ }
4158
+
4159
+ return $this->multiplyMedia($env->parent, $childQueries);
4160
+ }
4161
+
4162
+ /**
4163
+ * Convert env linked list to stack
4164
+ *
4165
+ * @param \ScssPhp\ScssPhp\Compiler\Environment $env
4166
+ *
4167
+ * @return array
4168
+ */
4169
+ protected function compactEnv(Environment $env)
4170
+ {
4171
+ for ($envs = []; $env; $env = $env->parent) {
4172
+ $envs[] = $env;
4173
+ }
4174
+
4175
+ return $envs;
4176
+ }
4177
+
4178
+ /**
4179
+ * Convert env stack to singly linked list
4180
+ *
4181
+ * @param array $envs
4182
+ *
4183
+ * @return \ScssPhp\ScssPhp\Compiler\Environment
4184
+ */
4185
+ protected function extractEnv($envs)
4186
+ {
4187
+ for ($env = null; $e = array_pop($envs);) {
4188
+ $e->parent = $env;
4189
+ $env = $e;
4190
+ }
4191
+
4192
+ return $env;
4193
+ }
4194
+
4195
+ /**
4196
+ * Push environment
4197
+ *
4198
+ * @param \ScssPhp\ScssPhp\Block $block
4199
+ *
4200
+ * @return \ScssPhp\ScssPhp\Compiler\Environment
4201
+ */
4202
+ protected function pushEnv(Block $block = null)
4203
+ {
4204
+ $env = new Environment;
4205
+ $env->parent = $this->env;
4206
+ $env->parentStore = $this->storeEnv;
4207
+ $env->store = [];
4208
+ $env->block = $block;
4209
+ $env->depth = isset($this->env->depth) ? $this->env->depth + 1 : 0;
4210
+
4211
+ $this->env = $env;
4212
+ $this->storeEnv = null;
4213
+
4214
+ return $env;
4215
+ }
4216
+
4217
+ /**
4218
+ * Pop environment
4219
+ */
4220
+ protected function popEnv()
4221
+ {
4222
+ $this->storeEnv = $this->env->parentStore;
4223
+ $this->env = $this->env->parent;
4224
+ }
4225
+
4226
+ /**
4227
+ * Propagate vars from a just poped Env (used in @each and @for)
4228
+ *
4229
+ * @param array $store
4230
+ * @param null|array $excludedVars
4231
+ */
4232
+ protected function backPropagateEnv($store, $excludedVars = null)
4233
+ {
4234
+ foreach ($store as $key => $value) {
4235
+ if (empty($excludedVars) || ! \in_array($key, $excludedVars)) {
4236
+ $this->set($key, $value, true);
4237
+ }
4238
+ }
4239
+ }
4240
+
4241
+ /**
4242
+ * Get store environment
4243
+ *
4244
+ * @return \ScssPhp\ScssPhp\Compiler\Environment
4245
+ */
4246
+ protected function getStoreEnv()
4247
+ {
4248
+ return isset($this->storeEnv) ? $this->storeEnv : $this->env;
4249
+ }
4250
+
4251
+ /**
4252
+ * Set variable
4253
+ *
4254
+ * @param string $name
4255
+ * @param mixed $value
4256
+ * @param boolean $shadow
4257
+ * @param \ScssPhp\ScssPhp\Compiler\Environment $env
4258
+ * @param mixed $valueUnreduced
4259
+ */
4260
+ protected function set($name, $value, $shadow = false, Environment $env = null, $valueUnreduced = null)
4261
+ {
4262
+ $name = $this->normalizeName($name);
4263
+
4264
+ if (! isset($env)) {
4265
+ $env = $this->getStoreEnv();
4266
+ }
4267
+
4268
+ if ($shadow) {
4269
+ $this->setRaw($name, $value, $env, $valueUnreduced);
4270
+ } else {
4271
+ $this->setExisting($name, $value, $env, $valueUnreduced);
4272
+ }
4273
+ }
4274
+
4275
+ /**
4276
+ * Set existing variable
4277
+ *
4278
+ * @param string $name
4279
+ * @param mixed $value
4280
+ * @param \ScssPhp\ScssPhp\Compiler\Environment $env
4281
+ * @param mixed $valueUnreduced
4282
+ */
4283
+ protected function setExisting($name, $value, Environment $env, $valueUnreduced = null)
4284
+ {
4285
+ $storeEnv = $env;
4286
+ $specialContentKey = static::$namespaces['special'] . 'content';
4287
+
4288
+ $hasNamespace = $name[0] === '^' || $name[0] === '@' || $name[0] === '%';
4289
+
4290
+ $maxDepth = 10000;
4291
+
4292
+ for (;;) {
4293
+ if ($maxDepth-- <= 0) {
4294
+ break;
4295
+ }
4296
+
4297
+ if (\array_key_exists($name, $env->store)) {
4298
+ break;
4299
+ }
4300
+
4301
+ if (! $hasNamespace && isset($env->marker)) {
4302
+ if (! empty($env->store[$specialContentKey])) {
4303
+ $env = $env->store[$specialContentKey]->scope;
4304
+ continue;
4305
+ }
4306
+
4307
+ if (! empty($env->declarationScopeParent)) {
4308
+ $env = $env->declarationScopeParent;
4309
+ continue;
4310
+ } else {
4311
+ $env = $storeEnv;
4312
+ break;
4313
+ }
4314
+ }
4315
+
4316
+ if (isset($env->parentStore)) {
4317
+ $env = $env->parentStore;
4318
+ } elseif (isset($env->parent)) {
4319
+ $env = $env->parent;
4320
+ } else {
4321
+ $env = $storeEnv;
4322
+ break;
4323
+ }
4324
+ }
4325
+
4326
+ $env->store[$name] = $value;
4327
+
4328
+ if ($valueUnreduced) {
4329
+ $env->storeUnreduced[$name] = $valueUnreduced;
4330
+ }
4331
+ }
4332
+
4333
+ /**
4334
+ * Set raw variable
4335
+ *
4336
+ * @param string $name
4337
+ * @param mixed $value
4338
+ * @param \ScssPhp\ScssPhp\Compiler\Environment $env
4339
+ * @param mixed $valueUnreduced
4340
+ */
4341
+ protected function setRaw($name, $value, Environment $env, $valueUnreduced = null)
4342
+ {
4343
+ $env->store[$name] = $value;
4344
+
4345
+ if ($valueUnreduced) {
4346
+ $env->storeUnreduced[$name] = $valueUnreduced;
4347
+ }
4348
+ }
4349
+
4350
+ /**
4351
+ * Get variable
4352
+ *
4353
+ * @api
4354
+ *
4355
+ * @param string $name
4356
+ * @param boolean $shouldThrow
4357
+ * @param \ScssPhp\ScssPhp\Compiler\Environment $env
4358
+ * @param boolean $unreduced
4359
+ *
4360
+ * @return mixed|null
4361
+ */
4362
+ public function get($name, $shouldThrow = true, Environment $env = null, $unreduced = false)
4363
+ {
4364
+ $normalizedName = $this->normalizeName($name);
4365
+ $specialContentKey = static::$namespaces['special'] . 'content';
4366
+
4367
+ if (! isset($env)) {
4368
+ $env = $this->getStoreEnv();
4369
+ }
4370
+
4371
+ $hasNamespace = $normalizedName[0] === '^' || $normalizedName[0] === '@' || $normalizedName[0] === '%';
4372
+
4373
+ $maxDepth = 10000;
4374
+
4375
+ for (;;) {
4376
+ if ($maxDepth-- <= 0) {
4377
+ break;
4378
+ }
4379
+
4380
+ if (\array_key_exists($normalizedName, $env->store)) {
4381
+ if ($unreduced && isset($env->storeUnreduced[$normalizedName])) {
4382
+ return $env->storeUnreduced[$normalizedName];
4383
+ }
4384
+
4385
+ return $env->store[$normalizedName];
4386
+ }
4387
+
4388
+ if (! $hasNamespace && isset($env->marker)) {
4389
+ if (! empty($env->store[$specialContentKey])) {
4390
+ $env = $env->store[$specialContentKey]->scope;
4391
+ continue;
4392
+ }
4393
+
4394
+ if (! empty($env->declarationScopeParent)) {
4395
+ $env = $env->declarationScopeParent;
4396
+ } else {
4397
+ $env = $this->rootEnv;
4398
+ }
4399
+ continue;
4400
+ }
4401
+
4402
+ if (isset($env->parentStore)) {
4403
+ $env = $env->parentStore;
4404
+ } elseif (isset($env->parent)) {
4405
+ $env = $env->parent;
4406
+ } else {
4407
+ break;
4408
+ }
4409
+ }
4410
+
4411
+ if ($shouldThrow) {
4412
+ $this->throwError("Undefined variable \$$name" . ($maxDepth <= 0 ? " (infinite recursion)" : ""));
4413
+ }
4414
+
4415
+ // found nothing
4416
+ return null;
4417
+ }
4418
+
4419
+ /**
4420
+ * Has variable?
4421
+ *
4422
+ * @param string $name
4423
+ * @param \ScssPhp\ScssPhp\Compiler\Environment $env
4424
+ *
4425
+ * @return boolean
4426
+ */
4427
+ protected function has($name, Environment $env = null)
4428
+ {
4429
+ return ! \is_null($this->get($name, false, $env));
4430
+ }
4431
+
4432
+ /**
4433
+ * Inject variables
4434
+ *
4435
+ * @param array $args
4436
+ */
4437
+ protected function injectVariables(array $args)
4438
+ {
4439
+ if (empty($args)) {
4440
+ return;
4441
+ }
4442
+
4443
+ $parser = $this->parserFactory(__METHOD__);
4444
+
4445
+ foreach ($args as $name => $strValue) {
4446
+ if ($name[0] === '$') {
4447
+ $name = substr($name, 1);
4448
+ }
4449
+
4450
+ if (! $parser->parseValue($strValue, $value)) {
4451
+ $value = $this->coerceValue($strValue);
4452
+ }
4453
+
4454
+ $this->set($name, $value);
4455
+ }
4456
+ }
4457
+
4458
+ /**
4459
+ * Set variables
4460
+ *
4461
+ * @api
4462
+ *
4463
+ * @param array $variables
4464
+ */
4465
+ public function setVariables(array $variables)
4466
+ {
4467
+ $this->registeredVars = array_merge($this->registeredVars, $variables);
4468
+ }
4469
+
4470
+ /**
4471
+ * Unset variable
4472
+ *
4473
+ * @api
4474
+ *
4475
+ * @param string $name
4476
+ */
4477
+ public function unsetVariable($name)
4478
+ {
4479
+ unset($this->registeredVars[$name]);
4480
+ }
4481
+
4482
+ /**
4483
+ * Returns list of variables
4484
+ *
4485
+ * @api
4486
+ *
4487
+ * @return array
4488
+ */
4489
+ public function getVariables()
4490
+ {
4491
+ return $this->registeredVars;
4492
+ }
4493
+
4494
+ /**
4495
+ * Adds to list of parsed files
4496
+ *
4497
+ * @api
4498
+ *
4499
+ * @param string $path
4500
+ */
4501
+ public function addParsedFile($path)
4502
+ {
4503
+ if (isset($path) && is_file($path)) {
4504
+ $this->parsedFiles[realpath($path)] = filemtime($path);
4505
+ }
4506
+ }
4507
+
4508
+ /**
4509
+ * Returns list of parsed files
4510
+ *
4511
+ * @api
4512
+ *
4513
+ * @return array
4514
+ */
4515
+ public function getParsedFiles()
4516
+ {
4517
+ return $this->parsedFiles;
4518
+ }
4519
+
4520
+ /**
4521
+ * Add import path
4522
+ *
4523
+ * @api
4524
+ *
4525
+ * @param string|callable $path
4526
+ */
4527
+ public function addImportPath($path)
4528
+ {
4529
+ if (! \in_array($path, $this->importPaths)) {
4530
+ $this->importPaths[] = $path;
4531
+ }
4532
+ }
4533
+
4534
+ /**
4535
+ * Set import paths
4536
+ *
4537
+ * @api
4538
+ *
4539
+ * @param string|array $path
4540
+ */
4541
+ public function setImportPaths($path)
4542
+ {
4543
+ $this->importPaths = (array) $path;
4544
+ }
4545
+
4546
+ /**
4547
+ * Set number precision
4548
+ *
4549
+ * @api
4550
+ *
4551
+ * @param integer $numberPrecision
4552
+ */
4553
+ public function setNumberPrecision($numberPrecision)
4554
+ {
4555
+ Node\Number::$precision = $numberPrecision;
4556
+ }
4557
+
4558
+ /**
4559
+ * Set formatter
4560
+ *
4561
+ * @api
4562
+ *
4563
+ * @param string $formatterName
4564
+ */
4565
+ public function setFormatter($formatterName)
4566
+ {
4567
+ $this->formatter = $formatterName;
4568
+ }
4569
+
4570
+ /**
4571
+ * Set line number style
4572
+ *
4573
+ * @api
4574
+ *
4575
+ * @param string $lineNumberStyle
4576
+ */
4577
+ public function setLineNumberStyle($lineNumberStyle)
4578
+ {
4579
+ $this->lineNumberStyle = $lineNumberStyle;
4580
+ }
4581
+
4582
+ /**
4583
+ * Enable/disable source maps
4584
+ *
4585
+ * @api
4586
+ *
4587
+ * @param integer $sourceMap
4588
+ */
4589
+ public function setSourceMap($sourceMap)
4590
+ {
4591
+ $this->sourceMap = $sourceMap;
4592
+ }
4593
+
4594
+ /**
4595
+ * Set source map options
4596
+ *
4597
+ * @api
4598
+ *
4599
+ * @param array $sourceMapOptions
4600
+ */
4601
+ public function setSourceMapOptions($sourceMapOptions)
4602
+ {
4603
+ $this->sourceMapOptions = $sourceMapOptions;
4604
+ }
4605
+
4606
+ /**
4607
+ * Register function
4608
+ *
4609
+ * @api
4610
+ *
4611
+ * @param string $name
4612
+ * @param callable $func
4613
+ * @param array $prototype
4614
+ */
4615
+ public function registerFunction($name, $func, $prototype = null)
4616
+ {
4617
+ $this->userFunctions[$this->normalizeName($name)] = [$func, $prototype];
4618
+ }
4619
+
4620
+ /**
4621
+ * Unregister function
4622
+ *
4623
+ * @api
4624
+ *
4625
+ * @param string $name
4626
+ */
4627
+ public function unregisterFunction($name)
4628
+ {
4629
+ unset($this->userFunctions[$this->normalizeName($name)]);
4630
+ }
4631
+
4632
+ /**
4633
+ * Add feature
4634
+ *
4635
+ * @api
4636
+ *
4637
+ * @param string $name
4638
+ */
4639
+ public function addFeature($name)
4640
+ {
4641
+ $this->registeredFeatures[$name] = true;
4642
+ }
4643
+
4644
+ /**
4645
+ * Import file
4646
+ *
4647
+ * @param string $path
4648
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $out
4649
+ */
4650
+ protected function importFile($path, OutputBlock $out)
4651
+ {
4652
+ $this->pushCallStack('import '.$path);
4653
+ // see if tree is cached
4654
+ $realPath = realpath($path);
4655
+
4656
+ if (isset($this->importCache[$realPath])) {
4657
+ $this->handleImportLoop($realPath);
4658
+
4659
+ $tree = $this->importCache[$realPath];
4660
+ } else {
4661
+ $code = file_get_contents($path);
4662
+ $parser = $this->parserFactory($path);
4663
+ $tree = $parser->parse($code);
4664
+
4665
+ $this->importCache[$realPath] = $tree;
4666
+ }
4667
+
4668
+ $pi = pathinfo($path);
4669
+
4670
+ array_unshift($this->importPaths, $pi['dirname']);
4671
+ $this->compileChildrenNoReturn($tree->children, $out);
4672
+ array_shift($this->importPaths);
4673
+ $this->popCallStack();
4674
+ }
4675
+
4676
+ /**
4677
+ * Return the file path for an import url if it exists
4678
+ *
4679
+ * @api
4680
+ *
4681
+ * @param string $url
4682
+ *
4683
+ * @return string|null
4684
+ */
4685
+ public function findImport($url)
4686
+ {
4687
+ $urls = [];
4688
+
4689
+ $hasExtension = preg_match('/[.]s?css$/', $url);
4690
+
4691
+ // for "normal" scss imports (ignore vanilla css and external requests)
4692
+ if (! preg_match('~\.css$|^https?://|^//~', $url)) {
4693
+ $isPartial = (strpos(basename($url), '_') === 0);
4694
+
4695
+ // try both normal and the _partial filename
4696
+ $urls = [$url . ($hasExtension ? '' : '.scss')];
4697
+
4698
+ if (! $isPartial) {
4699
+ $urls[] = preg_replace('~[^/]+$~', '_\0', $url) . ($hasExtension ? '' : '.scss');
4700
+ }
4701
+
4702
+ if (! $hasExtension) {
4703
+ $urls[] = "$url/index.scss";
4704
+ $urls[] = "$url/_index.scss";
4705
+ // allow to find a plain css file, *if* no scss or partial scss is found
4706
+ $urls[] .= $url . ".css";
4707
+ }
4708
+ }
4709
+
4710
+ foreach ($this->importPaths as $dir) {
4711
+ if (\is_string($dir)) {
4712
+ // check urls for normal import paths
4713
+ foreach ($urls as $full) {
4714
+ $separator = (
4715
+ ! empty($dir) &&
4716
+ substr($dir, -1) !== '/' &&
4717
+ substr($full, 0, 1) !== '/'
4718
+ ) ? '/' : '';
4719
+ $full = $dir . $separator . $full;
4720
+
4721
+ if (is_file($file = $full)) {
4722
+ return $file;
4723
+ }
4724
+ }
4725
+ } elseif (\is_callable($dir)) {
4726
+ // check custom callback for import path
4727
+ $file = \call_user_func($dir, $url);
4728
+
4729
+ if (! \is_null($file)) {
4730
+ return $file;
4731
+ }
4732
+ }
4733
+ }
4734
+
4735
+ if ($urls) {
4736
+ if (! $hasExtension or preg_match('/[.]scss$/', $url)) {
4737
+ $this->throwError("`$url` file not found for @import");
4738
+ }
4739
+ }
4740
+
4741
+ return null;
4742
+ }
4743
+
4744
+ /**
4745
+ * Set encoding
4746
+ *
4747
+ * @api
4748
+ *
4749
+ * @param string $encoding
4750
+ */
4751
+ public function setEncoding($encoding)
4752
+ {
4753
+ $this->encoding = $encoding;
4754
+ }
4755
+
4756
+ /**
4757
+ * Ignore errors?
4758
+ *
4759
+ * @api
4760
+ *
4761
+ * @param boolean $ignoreErrors
4762
+ *
4763
+ * @return \ScssPhp\ScssPhp\Compiler
4764
+ */
4765
+ public function setIgnoreErrors($ignoreErrors)
4766
+ {
4767
+ $this->ignoreErrors = $ignoreErrors;
4768
+
4769
+ return $this;
4770
+ }
4771
+
4772
+ /**
4773
+ * Throw error (exception)
4774
+ *
4775
+ * @api
4776
+ *
4777
+ * @param string $msg Message with optional sprintf()-style vararg parameters
4778
+ *
4779
+ * @throws \ScssPhp\ScssPhp\Exception\CompilerException
4780
+ */
4781
+ public function throwError($msg)
4782
+ {
4783
+ if ($this->ignoreErrors) {
4784
+ return;
4785
+ }
4786
+
4787
+ if (\func_num_args() > 1) {
4788
+ $msg = \call_user_func_array('sprintf', \func_get_args());
4789
+ }
4790
+
4791
+ if (! $this->ignoreCallStackMessage) {
4792
+ $line = $this->sourceLine;
4793
+ $column = $this->sourceColumn;
4794
+
4795
+ $loc = isset($this->sourceNames[$this->sourceIndex])
4796
+ ? $this->sourceNames[$this->sourceIndex] . " on line $line, at column $column"
4797
+ : "line: $line, column: $column";
4798
+
4799
+ $msg = "$msg: $loc";
4800
+
4801
+ $callStackMsg = $this->callStackMessage();
4802
+
4803
+ if ($callStackMsg) {
4804
+ $msg .= "\nCall Stack:\n" . $callStackMsg;
4805
+ }
4806
+ }
4807
+
4808
+ throw new CompilerException($msg);
4809
+ }
4810
+
4811
+ /**
4812
+ * Beautify call stack for output
4813
+ *
4814
+ * @param boolean $all
4815
+ * @param null $limit
4816
+ *
4817
+ * @return string
4818
+ */
4819
+ protected function callStackMessage($all = false, $limit = null)
4820
+ {
4821
+ $callStackMsg = [];
4822
+ $ncall = 0;
4823
+
4824
+ if ($this->callStack) {
4825
+ foreach (array_reverse($this->callStack) as $call) {
4826
+ if ($all || (isset($call['n']) && $call['n'])) {
4827
+ $msg = "#" . $ncall++ . " " . $call['n'] . " ";
4828
+ $msg .= (isset($this->sourceNames[$call[Parser::SOURCE_INDEX]])
4829
+ ? $this->sourceNames[$call[Parser::SOURCE_INDEX]]
4830
+ : '(unknown file)');
4831
+ $msg .= " on line " . $call[Parser::SOURCE_LINE];
4832
+
4833
+ $callStackMsg[] = $msg;
4834
+
4835
+ if (! \is_null($limit) && $ncall > $limit) {
4836
+ break;
4837
+ }
4838
+ }
4839
+ }
4840
+ }
4841
+
4842
+ return implode("\n", $callStackMsg);
4843
+ }
4844
+
4845
+ /**
4846
+ * Handle import loop
4847
+ *
4848
+ * @param string $name
4849
+ *
4850
+ * @throws \Exception
4851
+ */
4852
+ protected function handleImportLoop($name)
4853
+ {
4854
+ for ($env = $this->env; $env; $env = $env->parent) {
4855
+ if (! $env->block) {
4856
+ continue;
4857
+ }
4858
+
4859
+ $file = $this->sourceNames[$env->block->sourceIndex];
4860
+
4861
+ if (realpath($file) === $name) {
4862
+ $this->throwError('An @import loop has been found: %s imports %s', $file, basename($file));
4863
+ break;
4864
+ }
4865
+ }
4866
+ }
4867
+
4868
+ /**
4869
+ * Call SCSS @function
4870
+ *
4871
+ * @param string $name
4872
+ * @param array $argValues
4873
+ * @param array $returnValue
4874
+ *
4875
+ * @return boolean Returns true if returnValue is set; otherwise, false
4876
+ */
4877
+ protected function callScssFunction($name, $argValues, &$returnValue)
4878
+ {
4879
+ $func = $this->get(static::$namespaces['function'] . $name, false);
4880
+
4881
+ if (! $func) {
4882
+ return false;
4883
+ }
4884
+
4885
+ $this->pushEnv();
4886
+
4887
+ // set the args
4888
+ if (isset($func->args)) {
4889
+ $this->applyArguments($func->args, $argValues);
4890
+ }
4891
+
4892
+ // throw away lines and children
4893
+ $tmp = new OutputBlock;
4894
+ $tmp->lines = [];
4895
+ $tmp->children = [];
4896
+
4897
+ $this->env->marker = 'function';
4898
+
4899
+ if (! empty($func->parentEnv)) {
4900
+ $this->env->declarationScopeParent = $func->parentEnv;
4901
+ } else {
4902
+ $this->throwError("@function $name() without parentEnv");
4903
+ }
4904
+
4905
+ $ret = $this->compileChildren($func->children, $tmp, $this->env->marker . " " . $name);
4906
+
4907
+ $this->popEnv();
4908
+
4909
+ $returnValue = ! isset($ret) ? static::$defaultValue : $ret;
4910
+
4911
+ return true;
4912
+ }
4913
+
4914
+ /**
4915
+ * Call built-in and registered (PHP) functions
4916
+ *
4917
+ * @param string $name
4918
+ * @param array $args
4919
+ * @param array $returnValue
4920
+ *
4921
+ * @return boolean Returns true if returnValue is set; otherwise, false
4922
+ */
4923
+ protected function callNativeFunction($name, $args, &$returnValue)
4924
+ {
4925
+ // try a lib function
4926
+ $name = $this->normalizeName($name);
4927
+ $libName = null;
4928
+
4929
+ if (isset($this->userFunctions[$name])) {
4930
+ // see if we can find a user function
4931
+ list($f, $prototype) = $this->userFunctions[$name];
4932
+ } elseif (($f = $this->getBuiltinFunction($name)) && \is_callable($f)) {
4933
+ $libName = $f[1];
4934
+ $prototype = isset(static::$$libName) ? static::$$libName : null;
4935
+ } else {
4936
+ return false;
4937
+ }
4938
+
4939
+ @list($sorted, $kwargs) = $this->sortNativeFunctionArgs($libName, $prototype, $args);
4940
+
4941
+ if ($name !== 'if' && $name !== 'call') {
4942
+ $inExp = true;
4943
+
4944
+ if ($name === 'join') {
4945
+ $inExp = false;
4946
+ }
4947
+
4948
+ foreach ($sorted as &$val) {
4949
+ $val = $this->reduce($val, $inExp);
4950
+ }
4951
+ }
4952
+
4953
+ $returnValue = \call_user_func($f, $sorted, $kwargs);
4954
+
4955
+ if (! isset($returnValue)) {
4956
+ return false;
4957
+ }
4958
+
4959
+ $returnValue = $this->coerceValue($returnValue);
4960
+
4961
+ return true;
4962
+ }
4963
+
4964
+ /**
4965
+ * Get built-in function
4966
+ *
4967
+ * @param string $name Normalized name
4968
+ *
4969
+ * @return array
4970
+ */
4971
+ protected function getBuiltinFunction($name)
4972
+ {
4973
+ $libName = 'lib' . preg_replace_callback(
4974
+ '/_(.)/',
4975
+ function ($m) {
4976
+ return ucfirst($m[1]);
4977
+ },
4978
+ ucfirst($name)
4979
+ );
4980
+
4981
+ return [$this, $libName];
4982
+ }
4983
+
4984
+ /**
4985
+ * Sorts keyword arguments
4986
+ *
4987
+ * @param string $functionName
4988
+ * @param array $prototypes
4989
+ * @param array $args
4990
+ *
4991
+ * @return array
4992
+ */
4993
+ protected function sortNativeFunctionArgs($functionName, $prototypes, $args)
4994
+ {
4995
+ static $parser = null;
4996
+
4997
+ if (! isset($prototypes)) {
4998
+ $keyArgs = [];
4999
+ $posArgs = [];
5000
+
5001
+ // separate positional and keyword arguments
5002
+ foreach ($args as $arg) {
5003
+ list($key, $value) = $arg;
5004
+
5005
+ $key = $key[1];
5006
+
5007
+ if (empty($key)) {
5008
+ $posArgs[] = empty($arg[2]) ? $value : $arg;
5009
+ } else {
5010
+ $keyArgs[$key] = $value;
5011
+ }
5012
+ }
5013
+
5014
+ return [$posArgs, $keyArgs];
5015
+ }
5016
+
5017
+ // specific cases ?
5018
+ if (\in_array($functionName, ['libRgb', 'libRgba', 'libHsl', 'libHsla'])) {
5019
+ // notation 100 127 255 / 0 is in fact a simple list of 4 values
5020
+ foreach ($args as $k => $arg) {
5021
+ if ($arg[1][0] === Type::T_LIST && \count($arg[1][2]) === 3) {
5022
+ $last = end($arg[1][2]);
5023
+
5024
+ if ($last[0] === Type::T_EXPRESSION && $last[1] === '/') {
5025
+ array_pop($arg[1][2]);
5026
+ $arg[1][2][] = $last[2];
5027
+ $arg[1][2][] = $last[3];
5028
+ $args[$k] = $arg;
5029
+ }
5030
+ }
5031
+ }
5032
+ }
5033
+
5034
+ $finalArgs = [];
5035
+
5036
+ if (! \is_array(reset($prototypes))) {
5037
+ $prototypes = [$prototypes];
5038
+ }
5039
+
5040
+ $keyArgs = [];
5041
+
5042
+ // trying each prototypes
5043
+ $prototypeHasMatch = false;
5044
+ $exceptionMessage = '';
5045
+
5046
+ foreach ($prototypes as $prototype) {
5047
+ $argDef = [];
5048
+
5049
+ foreach ($prototype as $i => $p) {
5050
+ $default = null;
5051
+ $p = explode(':', $p, 2);
5052
+ $name = array_shift($p);
5053
+
5054
+ if (\count($p)) {
5055
+ $p = trim(reset($p));
5056
+
5057
+ if ($p === 'null') {
5058
+ // differentiate this null from the static::$null
5059
+ $default = [Type::T_KEYWORD, 'null'];
5060
+ } else {
5061
+ if (\is_null($parser)) {
5062
+ $parser = $this->parserFactory(__METHOD__);
5063
+ }
5064
+
5065
+ $parser->parseValue($p, $default);
5066
+ }
5067
+ }
5068
+
5069
+ $isVariable = false;
5070
+
5071
+ if (substr($name, -3) === '...') {
5072
+ $isVariable = true;
5073
+ $name = substr($name, 0, -3);
5074
+ }
5075
+
5076
+ $argDef[] = [$name, $default, $isVariable];
5077
+ }
5078
+
5079
+ $ignoreCallStackMessage = $this->ignoreCallStackMessage;
5080
+ $this->ignoreCallStackMessage = true;
5081
+
5082
+ try {
5083
+ $vars = $this->applyArguments($argDef, $args, false, false);
5084
+
5085
+ // ensure all args are populated
5086
+ foreach ($prototype as $i => $p) {
5087
+ $name = explode(':', $p)[0];
5088
+
5089
+ if (! isset($finalArgs[$i])) {
5090
+ $finalArgs[$i] = null;
5091
+ }
5092
+ }
5093
+
5094
+ // apply positional args
5095
+ foreach (array_values($vars) as $i => $val) {
5096
+ $finalArgs[$i] = $val;
5097
+ }
5098
+
5099
+ $keyArgs = array_merge($keyArgs, $vars);
5100
+ $prototypeHasMatch = true;
5101
+
5102
+ // overwrite positional args with keyword args
5103
+ foreach ($prototype as $i => $p) {
5104
+ $name = explode(':', $p)[0];
5105
+
5106
+ if (isset($keyArgs[$name])) {
5107
+ $finalArgs[$i] = $keyArgs[$name];
5108
+ }
5109
+
5110
+ // special null value as default: translate to real null here
5111
+ if ($finalArgs[$i] === [Type::T_KEYWORD, 'null']) {
5112
+ $finalArgs[$i] = null;
5113
+ }
5114
+ }
5115
+ // should we break if this prototype seems fulfilled?
5116
+ } catch (CompilerException $e) {
5117
+ $exceptionMessage = $e->getMessage();
5118
+ }
5119
+ $this->ignoreCallStackMessage = $ignoreCallStackMessage;
5120
+ }
5121
+
5122
+ if ($exceptionMessage && ! $prototypeHasMatch) {
5123
+ $this->throwError($exceptionMessage);
5124
+ }
5125
+
5126
+ return [$finalArgs, $keyArgs];
5127
+ }
5128
+
5129
+ /**
5130
+ * Apply argument values per definition
5131
+ *
5132
+ * @param array $argDef
5133
+ * @param array $argValues
5134
+ * @param boolean $storeInEnv
5135
+ * @param boolean $reduce
5136
+ * only used if $storeInEnv = false
5137
+ *
5138
+ * @return array
5139
+ *
5140
+ * @throws \Exception
5141
+ */
5142
+ protected function applyArguments($argDef, $argValues, $storeInEnv = true, $reduce = true)
5143
+ {
5144
+ $output = [];
5145
+
5146
+ if (\is_array($argValues) && \count($argValues) && end($argValues) === static::$null) {
5147
+ array_pop($argValues);
5148
+ }
5149
+
5150
+ if ($storeInEnv) {
5151
+ $storeEnv = $this->getStoreEnv();
5152
+
5153
+ $env = new Environment;
5154
+ $env->store = $storeEnv->store;
5155
+ }
5156
+
5157
+ $hasVariable = false;
5158
+ $args = [];
5159
+
5160
+ foreach ($argDef as $i => $arg) {
5161
+ list($name, $default, $isVariable) = $argDef[$i];
5162
+
5163
+ $args[$name] = [$i, $name, $default, $isVariable];
5164
+ $hasVariable |= $isVariable;
5165
+ }
5166
+
5167
+ $splatSeparator = null;
5168
+ $keywordArgs = [];
5169
+ $deferredKeywordArgs = [];
5170
+ $remaining = [];
5171
+ $hasKeywordArgument = false;
5172
+
5173
+ // assign the keyword args
5174
+ foreach ((array) $argValues as $arg) {
5175
+ if (! empty($arg[0])) {
5176
+ $hasKeywordArgument = true;
5177
+
5178
+ $name = $arg[0][1];
5179
+ if (! isset($args[$name])) {
5180
+ foreach (array_keys($args) as $an) {
5181
+ if (str_replace("_", "-", $an) === str_replace("_", "-", $name)) {
5182
+ $name = $an;
5183
+ break;
5184
+ }
5185
+ }
5186
+ }
5187
+
5188
+ if (! isset($args[$name]) || $args[$name][3]) {
5189
+ if ($hasVariable) {
5190
+ $deferredKeywordArgs[$name] = $arg[1];
5191
+ } else {
5192
+ $this->throwError("Mixin or function doesn't have an argument named $%s.", $arg[0][1]);
5193
+ break;
5194
+ }
5195
+ } elseif ($args[$name][0] < \count($remaining)) {
5196
+ $this->throwError("The argument $%s was passed both by position and by name.", $arg[0][1]);
5197
+ break;
5198
+ } else {
5199
+ $keywordArgs[$name] = $arg[1];
5200
+ }
5201
+ } elseif ($arg[2] === true) {
5202
+ $val = $this->reduce($arg[1], true);
5203
+
5204
+ if ($val[0] === Type::T_LIST) {
5205
+ foreach ($val[2] as $name => $item) {
5206
+ if (! is_numeric($name)) {
5207
+ if (! isset($args[$name])) {
5208
+ foreach (array_keys($args) as $an) {
5209
+ if (str_replace("_", "-", $an) === str_replace("_", "-", $name)) {
5210
+ $name = $an;
5211
+ break;
5212
+ }
5213
+ }
5214
+ }
5215
+
5216
+ if ($hasVariable) {
5217
+ $deferredKeywordArgs[$name] = $item;
5218
+ } else {
5219
+ $keywordArgs[$name] = $item;
5220
+ }
5221
+ } else {
5222
+ if (\is_null($splatSeparator)) {
5223
+ $splatSeparator = $val[1];
5224
+ }
5225
+
5226
+ $remaining[] = $item;
5227
+ }
5228
+ }
5229
+ } elseif ($val[0] === Type::T_MAP) {
5230
+ foreach ($val[1] as $i => $name) {
5231
+ $name = $this->compileStringContent($this->coerceString($name));
5232
+ $item = $val[2][$i];
5233
+
5234
+ if (! is_numeric($name)) {
5235
+ if (! isset($args[$name])) {
5236
+ foreach (array_keys($args) as $an) {
5237
+ if (str_replace("_", "-", $an) === str_replace("_", "-", $name)) {
5238
+ $name = $an;
5239
+ break;
5240
+ }
5241
+ }
5242
+ }
5243
+
5244
+ if ($hasVariable) {
5245
+ $deferredKeywordArgs[$name] = $item;
5246
+ } else {
5247
+ $keywordArgs[$name] = $item;
5248
+ }
5249
+ } else {
5250
+ if (\is_null($splatSeparator)) {
5251
+ $splatSeparator = $val[1];
5252
+ }
5253
+
5254
+ $remaining[] = $item;
5255
+ }
5256
+ }
5257
+ } else {
5258
+ $remaining[] = $val;
5259
+ }
5260
+ } elseif ($hasKeywordArgument) {
5261
+ $this->throwError('Positional arguments must come before keyword arguments.');
5262
+ break;
5263
+ } else {
5264
+ $remaining[] = $arg[1];
5265
+ }
5266
+ }
5267
+
5268
+ foreach ($args as $arg) {
5269
+ list($i, $name, $default, $isVariable) = $arg;
5270
+
5271
+ if ($isVariable) {
5272
+ $val = [Type::T_LIST, \is_null($splatSeparator) ? ',' : $splatSeparator , [], $isVariable];
5273
+
5274
+ for ($count = \count($remaining); $i < $count; $i++) {
5275
+ $val[2][] = $remaining[$i];
5276
+ }
5277
+
5278
+ foreach ($deferredKeywordArgs as $itemName => $item) {
5279
+ $val[2][$itemName] = $item;
5280
+ }
5281
+ } elseif (isset($remaining[$i])) {
5282
+ $val = $remaining[$i];
5283
+ } elseif (isset($keywordArgs[$name])) {
5284
+ $val = $keywordArgs[$name];
5285
+ } elseif (! empty($default)) {
5286
+ continue;
5287
+ } else {
5288
+ $this->throwError("Missing argument $name");
5289
+ break;
5290
+ }
5291
+
5292
+ if ($storeInEnv) {
5293
+ $this->set($name, $this->reduce($val, true), true, $env);
5294
+ } else {
5295
+ $output[$name] = ($reduce ? $this->reduce($val, true) : $val);
5296
+ }
5297
+ }
5298
+
5299
+ if ($storeInEnv) {
5300
+ $storeEnv->store = $env->store;
5301
+ }
5302
+
5303
+ foreach ($args as $arg) {
5304
+ list($i, $name, $default, $isVariable) = $arg;
5305
+
5306
+ if ($isVariable || isset($remaining[$i]) || isset($keywordArgs[$name]) || empty($default)) {
5307
+ continue;
5308
+ }
5309
+
5310
+ if ($storeInEnv) {
5311
+ $this->set($name, $this->reduce($default, true), true);
5312
+ } else {
5313
+ $output[$name] = ($reduce ? $this->reduce($default, true) : $default);
5314
+ }
5315
+ }
5316
+
5317
+ return $output;
5318
+ }
5319
+
5320
+ /**
5321
+ * Coerce a php value into a scss one
5322
+ *
5323
+ * @param mixed $value
5324
+ *
5325
+ * @return array|\ScssPhp\ScssPhp\Node\Number
5326
+ */
5327
+ protected function coerceValue($value)
5328
+ {
5329
+ if (\is_array($value) || $value instanceof \ArrayAccess) {
5330
+ return $value;
5331
+ }
5332
+
5333
+ if (\is_bool($value)) {
5334
+ return $this->toBool($value);
5335
+ }
5336
+
5337
+ if (\is_null($value)) {
5338
+ return static::$null;
5339
+ }
5340
+
5341
+ if (is_numeric($value)) {
5342
+ return new Node\Number($value, '');
5343
+ }
5344
+
5345
+ if ($value === '') {
5346
+ return static::$emptyString;
5347
+ }
5348
+
5349
+ $value = [Type::T_KEYWORD, $value];
5350
+ $color = $this->coerceColor($value);
5351
+
5352
+ if ($color) {
5353
+ return $color;
5354
+ }
5355
+
5356
+ return $value;
5357
+ }
5358
+
5359
+ /**
5360
+ * Coerce something to map
5361
+ *
5362
+ * @param array $item
5363
+ *
5364
+ * @return array
5365
+ */
5366
+ protected function coerceMap($item)
5367
+ {
5368
+ if ($item[0] === Type::T_MAP) {
5369
+ return $item;
5370
+ }
5371
+
5372
+ if ($item[0] === static::$emptyList[0] &&
5373
+ $item[1] === static::$emptyList[1] &&
5374
+ $item[2] === static::$emptyList[2]
5375
+ ) {
5376
+ return static::$emptyMap;
5377
+ }
5378
+
5379
+ return [Type::T_MAP, [$item], [static::$null]];
5380
+ }
5381
+
5382
+ /**
5383
+ * Coerce something to list
5384
+ *
5385
+ * @param array $item
5386
+ * @param string $delim
5387
+ * @param boolean $removeTrailingNull
5388
+ *
5389
+ * @return array
5390
+ */
5391
+ protected function coerceList($item, $delim = ',', $removeTrailingNull = false)
5392
+ {
5393
+ if (isset($item) && $item[0] === Type::T_LIST) {
5394
+ // remove trailing null from the list
5395
+ if ($removeTrailingNull && end($item[2]) === static::$null) {
5396
+ array_pop($item[2]);
5397
+ }
5398
+
5399
+ return $item;
5400
+ }
5401
+
5402
+ if (isset($item) && $item[0] === Type::T_MAP) {
5403
+ $keys = $item[1];
5404
+ $values = $item[2];
5405
+ $list = [];
5406
+
5407
+ for ($i = 0, $s = \count($keys); $i < $s; $i++) {
5408
+ $key = $keys[$i];
5409
+ $value = $values[$i];
5410
+
5411
+ switch ($key[0]) {
5412
+ case Type::T_LIST:
5413
+ case Type::T_MAP:
5414
+ case Type::T_STRING:
5415
+ case Type::T_NULL:
5416
+ break;
5417
+
5418
+ default:
5419
+ $key = [Type::T_KEYWORD, $this->compileStringContent($this->coerceString($key))];
5420
+ break;
5421
+ }
5422
+
5423
+ $list[] = [
5424
+ Type::T_LIST,
5425
+ '',
5426
+ [$key, $value]
5427
+ ];
5428
+ }
5429
+
5430
+ return [Type::T_LIST, ',', $list];
5431
+ }
5432
+
5433
+ return [Type::T_LIST, $delim, ! isset($item) ? []: [$item]];
5434
+ }
5435
+
5436
+ /**
5437
+ * Coerce color for expression
5438
+ *
5439
+ * @param array $value
5440
+ *
5441
+ * @return array|null
5442
+ */
5443
+ protected function coerceForExpression($value)
5444
+ {
5445
+ if ($color = $this->coerceColor($value)) {
5446
+ return $color;
5447
+ }
5448
+
5449
+ return $value;
5450
+ }
5451
+
5452
+ /**
5453
+ * Coerce value to color
5454
+ *
5455
+ * @param array $value
5456
+ *
5457
+ * @return array|null
5458
+ */
5459
+ protected function coerceColor($value, $inRGBFunction = false)
5460
+ {
5461
+ switch ($value[0]) {
5462
+ case Type::T_COLOR:
5463
+ for ($i = 1; $i <= 3; $i++) {
5464
+ if (! is_numeric($value[$i])) {
5465
+ $cv = $this->compileRGBAValue($value[$i]);
5466
+
5467
+ if (! is_numeric($cv)) {
5468
+ return null;
5469
+ }
5470
+
5471
+ $value[$i] = $cv;
5472
+ }
5473
+
5474
+ if (isset($value[4])) {
5475
+ if (! is_numeric($value[4])) {
5476
+ $cv = $this->compileRGBAValue($value[4], true);
5477
+
5478
+ if (! is_numeric($cv)) {
5479
+ return null;
5480
+ }
5481
+
5482
+ $value[4] = $cv;
5483
+ }
5484
+ }
5485
+ }
5486
+
5487
+ return $value;
5488
+
5489
+ case Type::T_LIST:
5490
+ if ($inRGBFunction) {
5491
+ if (\count($value[2]) == 3 || \count($value[2]) == 4) {
5492
+ $color = $value[2];
5493
+ array_unshift($color, Type::T_COLOR);
5494
+
5495
+ return $this->coerceColor($color);
5496
+ }
5497
+ }
5498
+
5499
+ return null;
5500
+
5501
+ case Type::T_KEYWORD:
5502
+ if (! \is_string($value[1])) {
5503
+ return null;
5504
+ }
5505
+
5506
+ $name = strtolower($value[1]);
5507
+
5508
+ // hexa color?
5509
+ if (preg_match('/^#([0-9a-f]+)$/i', $name, $m)) {
5510
+ $nofValues = \strlen($m[1]);
5511
+
5512
+ if (\in_array($nofValues, [3, 4, 6, 8])) {
5513
+ $nbChannels = 3;
5514
+ $color = [];
5515
+ $num = hexdec($m[1]);
5516
+
5517
+ switch ($nofValues) {
5518
+ case 4:
5519
+ $nbChannels = 4;
5520
+ // then continuing with the case 3:
5521
+ case 3:
5522
+ for ($i = 0; $i < $nbChannels; $i++) {
5523
+ $t = $num & 0xf;
5524
+ array_unshift($color, $t << 4 | $t);
5525
+ $num >>= 4;
5526
+ }
5527
+
5528
+ break;
5529
+
5530
+ case 8:
5531
+ $nbChannels = 4;
5532
+ // then continuing with the case 6:
5533
+ case 6:
5534
+ for ($i = 0; $i < $nbChannels; $i++) {
5535
+ array_unshift($color, $num & 0xff);
5536
+ $num >>= 8;
5537
+ }
5538
+
5539
+ break;
5540
+ }
5541
+
5542
+ if ($nbChannels === 4) {
5543
+ if ($color[3] === 255) {
5544
+ $color[3] = 1; // fully opaque
5545
+ } else {
5546
+ $color[3] = round($color[3] / 255, 3);
5547
+ }
5548
+ }
5549
+
5550
+ array_unshift($color, Type::T_COLOR);
5551
+
5552
+ return $color;
5553
+ }
5554
+ }
5555
+
5556
+ if ($rgba = Colors::colorNameToRGBa($name)) {
5557
+ return isset($rgba[3])
5558
+ ? [Type::T_COLOR, $rgba[0], $rgba[1], $rgba[2], $rgba[3]]
5559
+ : [Type::T_COLOR, $rgba[0], $rgba[1], $rgba[2]];
5560
+ }
5561
+
5562
+ return null;
5563
+ }
5564
+
5565
+ return null;
5566
+ }
5567
+
5568
+ /**
5569
+ * @param integer|\ScssPhp\ScssPhp\Node\Number $value
5570
+ * @param boolean $isAlpha
5571
+ *
5572
+ * @return integer|mixed
5573
+ */
5574
+ protected function compileRGBAValue($value, $isAlpha = false)
5575
+ {
5576
+ if ($isAlpha) {
5577
+ return $this->compileColorPartValue($value, 0, 1, false);
5578
+ }
5579
+
5580
+ return $this->compileColorPartValue($value, 0, 255, true);
5581
+ }
5582
+
5583
+ /**
5584
+ * @param mixed $value
5585
+ * @param integer|float $min
5586
+ * @param integer|float $max
5587
+ * @param boolean $isInt
5588
+ * @param boolean $clamp
5589
+ * @param boolean $modulo
5590
+ *
5591
+ * @return integer|mixed
5592
+ */
5593
+ protected function compileColorPartValue($value, $min, $max, $isInt = true, $clamp = true, $modulo = false)
5594
+ {
5595
+ if (! is_numeric($value)) {
5596
+ if (\is_array($value)) {
5597
+ $reduced = $this->reduce($value);
5598
+
5599
+ if (\is_object($reduced) && $value->type === Type::T_NUMBER) {
5600
+ $value = $reduced;
5601
+ }
5602
+ }
5603
+
5604
+ if (\is_object($value) && $value->type === Type::T_NUMBER) {
5605
+ $num = $value->dimension;
5606
+
5607
+ if (\count($value->units)) {
5608
+ $unit = array_keys($value->units);
5609
+ $unit = reset($unit);
5610
+
5611
+ switch ($unit) {
5612
+ case '%':
5613
+ $num *= $max / 100;
5614
+ break;
5615
+ default:
5616
+ break;
5617
+ }
5618
+ }
5619
+
5620
+ $value = $num;
5621
+ } elseif (\is_array($value)) {
5622
+ $value = $this->compileValue($value);
5623
+ }
5624
+ }
5625
+
5626
+ if (is_numeric($value)) {
5627
+ if ($isInt) {
5628
+ $value = round($value);
5629
+ }
5630
+
5631
+ if ($clamp) {
5632
+ $value = min($max, max($min, $value));
5633
+ }
5634
+
5635
+ if ($modulo) {
5636
+ $value = $value % $max;
5637
+
5638
+ // still negative?
5639
+ while ($value < $min) {
5640
+ $value += $max;
5641
+ }
5642
+ }
5643
+
5644
+ return $value;
5645
+ }
5646
+
5647
+ return $value;
5648
+ }
5649
+
5650
+ /**
5651
+ * Coerce value to string
5652
+ *
5653
+ * @param array $value
5654
+ *
5655
+ * @return array|null
5656
+ */
5657
+ protected function coerceString($value)
5658
+ {
5659
+ if ($value[0] === Type::T_STRING) {
5660
+ return $value;
5661
+ }
5662
+
5663
+ return [Type::T_STRING, '', [$this->compileValue($value)]];
5664
+ }
5665
+
5666
+ /**
5667
+ * Coerce value to a percentage
5668
+ *
5669
+ * @param array $value
5670
+ *
5671
+ * @return integer|float
5672
+ */
5673
+ protected function coercePercent($value)
5674
+ {
5675
+ if ($value[0] === Type::T_NUMBER) {
5676
+ if (! empty($value[2]['%'])) {
5677
+ return $value[1] / 100;
5678
+ }
5679
+
5680
+ return $value[1];
5681
+ }
5682
+
5683
+ return 0;
5684
+ }
5685
+
5686
+ /**
5687
+ * Assert value is a map
5688
+ *
5689
+ * @api
5690
+ *
5691
+ * @param array $value
5692
+ *
5693
+ * @return array
5694
+ *
5695
+ * @throws \Exception
5696
+ */
5697
+ public function assertMap($value)
5698
+ {
5699
+ $value = $this->coerceMap($value);
5700
+
5701
+ if ($value[0] !== Type::T_MAP) {
5702
+ $this->throwError('expecting map, %s received', $value[0]);
5703
+ }
5704
+
5705
+ return $value;
5706
+ }
5707
+
5708
+ /**
5709
+ * Assert value is a list
5710
+ *
5711
+ * @api
5712
+ *
5713
+ * @param array $value
5714
+ *
5715
+ * @return array
5716
+ *
5717
+ * @throws \Exception
5718
+ */
5719
+ public function assertList($value)
5720
+ {
5721
+ if ($value[0] !== Type::T_LIST) {
5722
+ $this->throwError('expecting list, %s received', $value[0]);
5723
+ }
5724
+
5725
+ return $value;
5726
+ }
5727
+
5728
+ /**
5729
+ * Assert value is a color
5730
+ *
5731
+ * @api
5732
+ *
5733
+ * @param array $value
5734
+ *
5735
+ * @return array
5736
+ *
5737
+ * @throws \Exception
5738
+ */
5739
+ public function assertColor($value)
5740
+ {
5741
+ if ($color = $this->coerceColor($value)) {
5742
+ return $color;
5743
+ }
5744
+
5745
+ $this->throwError('expecting color, %s received', $value[0]);
5746
+ }
5747
+
5748
+ /**
5749
+ * Assert value is a number
5750
+ *
5751
+ * @api
5752
+ *
5753
+ * @param array $value
5754
+ *
5755
+ * @return integer|float
5756
+ *
5757
+ * @throws \Exception
5758
+ */
5759
+ public function assertNumber($value)
5760
+ {
5761
+ if ($value[0] !== Type::T_NUMBER) {
5762
+ $this->throwError('expecting number, %s received', $value[0]);
5763
+ }
5764
+
5765
+ return $value[1];
5766
+ }
5767
+
5768
+ /**
5769
+ * Make sure a color's components don't go out of bounds
5770
+ *
5771
+ * @param array $c
5772
+ *
5773
+ * @return array
5774
+ */
5775
+ protected function fixColor($c)
5776
+ {
5777
+ foreach ([1, 2, 3] as $i) {
5778
+ if ($c[$i] < 0) {
5779
+ $c[$i] = 0;
5780
+ }
5781
+
5782
+ if ($c[$i] > 255) {
5783
+ $c[$i] = 255;
5784
+ }
5785
+ }
5786
+
5787
+ return $c;
5788
+ }
5789
+
5790
+ /**
5791
+ * Convert RGB to HSL
5792
+ *
5793
+ * @api
5794
+ *
5795
+ * @param integer $red
5796
+ * @param integer $green
5797
+ * @param integer $blue
5798
+ *
5799
+ * @return array
5800
+ */
5801
+ public function toHSL($red, $green, $blue)
5802
+ {
5803
+ $min = min($red, $green, $blue);
5804
+ $max = max($red, $green, $blue);
5805
+
5806
+ $l = $min + $max;
5807
+ $d = $max - $min;
5808
+
5809
+ if ((int) $d === 0) {
5810
+ $h = $s = 0;
5811
+ } else {
5812
+ if ($l < 255) {
5813
+ $s = $d / $l;
5814
+ } else {
5815
+ $s = $d / (510 - $l);
5816
+ }
5817
+
5818
+ if ($red == $max) {
5819
+ $h = 60 * ($green - $blue) / $d;
5820
+ } elseif ($green == $max) {
5821
+ $h = 60 * ($blue - $red) / $d + 120;
5822
+ } elseif ($blue == $max) {
5823
+ $h = 60 * ($red - $green) / $d + 240;
5824
+ }
5825
+ }
5826
+
5827
+ return [Type::T_HSL, fmod($h, 360), $s * 100, $l / 5.1];
5828
+ }
5829
+
5830
+ /**
5831
+ * Hue to RGB helper
5832
+ *
5833
+ * @param float $m1
5834
+ * @param float $m2
5835
+ * @param float $h
5836
+ *
5837
+ * @return float
5838
+ */
5839
+ protected function hueToRGB($m1, $m2, $h)
5840
+ {
5841
+ if ($h < 0) {
5842
+ $h += 1;
5843
+ } elseif ($h > 1) {
5844
+ $h -= 1;
5845
+ }
5846
+
5847
+ if ($h * 6 < 1) {
5848
+ return $m1 + ($m2 - $m1) * $h * 6;
5849
+ }
5850
+
5851
+ if ($h * 2 < 1) {
5852
+ return $m2;
5853
+ }
5854
+
5855
+ if ($h * 3 < 2) {
5856
+ return $m1 + ($m2 - $m1) * (2/3 - $h) * 6;
5857
+ }
5858
+
5859
+ return $m1;
5860
+ }
5861
+
5862
+ /**
5863
+ * Convert HSL to RGB
5864
+ *
5865
+ * @api
5866
+ *
5867
+ * @param integer $hue H from 0 to 360
5868
+ * @param integer $saturation S from 0 to 100
5869
+ * @param integer $lightness L from 0 to 100
5870
+ *
5871
+ * @return array
5872
+ */
5873
+ public function toRGB($hue, $saturation, $lightness)
5874
+ {
5875
+ if ($hue < 0) {
5876
+ $hue += 360;
5877
+ }
5878
+
5879
+ $h = $hue / 360;
5880
+ $s = min(100, max(0, $saturation)) / 100;
5881
+ $l = min(100, max(0, $lightness)) / 100;
5882
+
5883
+ $m2 = $l <= 0.5 ? $l * ($s + 1) : $l + $s - $l * $s;
5884
+ $m1 = $l * 2 - $m2;
5885
+
5886
+ $r = $this->hueToRGB($m1, $m2, $h + 1/3) * 255;
5887
+ $g = $this->hueToRGB($m1, $m2, $h) * 255;
5888
+ $b = $this->hueToRGB($m1, $m2, $h - 1/3) * 255;
5889
+
5890
+ $out = [Type::T_COLOR, $r, $g, $b];
5891
+
5892
+ return $out;
5893
+ }
5894
+
5895
+ // Built in functions
5896
+
5897
+ protected static $libCall = ['name', 'args...'];
5898
+ protected function libCall($args, $kwargs)
5899
+ {
5900
+ $name = $this->compileStringContent($this->coerceString($this->reduce(array_shift($args), true)));
5901
+ $callArgs = [];
5902
+
5903
+ // $kwargs['args'] is [Type::T_LIST, ',', [..]]
5904
+ foreach ($kwargs['args'][2] as $varname => $arg) {
5905
+ if (is_numeric($varname)) {
5906
+ $varname = null;
5907
+ } else {
5908
+ $varname = [ 'var', $varname];
5909
+ }
5910
+
5911
+ $callArgs[] = [$varname, $arg, false];
5912
+ }
5913
+
5914
+ return $this->reduce([Type::T_FUNCTION_CALL, $name, $callArgs]);
5915
+ }
5916
+
5917
+ protected static $libIf = ['condition', 'if-true', 'if-false:'];
5918
+ protected function libIf($args)
5919
+ {
5920
+ list($cond, $t, $f) = $args;
5921
+
5922
+ if (! $this->isTruthy($this->reduce($cond, true))) {
5923
+ return $this->reduce($f, true);
5924
+ }
5925
+
5926
+ return $this->reduce($t, true);
5927
+ }
5928
+
5929
+ protected static $libIndex = ['list', 'value'];
5930
+ protected function libIndex($args)
5931
+ {
5932
+ list($list, $value) = $args;
5933
+
5934
+ if ($value[0] === Type::T_MAP) {
5935
+ return static::$null;
5936
+ }
5937
+
5938
+ if ($list[0] === Type::T_MAP ||
5939
+ $list[0] === Type::T_STRING ||
5940
+ $list[0] === Type::T_KEYWORD ||
5941
+ $list[0] === Type::T_INTERPOLATE
5942
+ ) {
5943
+ $list = $this->coerceList($list, ' ');
5944
+ }
5945
+
5946
+ if ($list[0] !== Type::T_LIST) {
5947
+ return static::$null;
5948
+ }
5949
+
5950
+ $values = [];
5951
+
5952
+ foreach ($list[2] as $item) {
5953
+ $values[] = $this->normalizeValue($item);
5954
+ }
5955
+
5956
+ $key = array_search($this->normalizeValue($value), $values);
5957
+
5958
+ return false === $key ? static::$null : $key + 1;
5959
+ }
5960
+
5961
+ protected static $libRgb = [
5962
+ ['color'],
5963
+ ['color', 'alpha'],
5964
+ ['channels'],
5965
+ ['red', 'green', 'blue'],
5966
+ ['red', 'green', 'blue', 'alpha'] ];
5967
+ protected function libRgb($args, $kwargs, $funcName = 'rgb')
5968
+ {
5969
+ switch (\count($args)) {
5970
+ case 1:
5971
+ if (! $color = $this->coerceColor($args[0], true)) {
5972
+ $color = [Type::T_STRING, '', [$funcName . '(', $args[0], ')']];
5973
+ }
5974
+ break;
5975
+
5976
+ case 3:
5977
+ $color = [Type::T_COLOR, $args[0], $args[1], $args[2]];
5978
+
5979
+ if (! $color = $this->coerceColor($color)) {
5980
+ $color = [Type::T_STRING, '', [$funcName .'(', $args[0], ', ', $args[1], ', ', $args[2], ')']];
5981
+ }
5982
+
5983
+ return $color;
5984
+
5985
+ case 2:
5986
+ if ($color = $this->coerceColor($args[0], true)) {
5987
+ $alpha = $this->compileRGBAValue($args[1], true);
5988
+
5989
+ if (is_numeric($alpha)) {
5990
+ $color[4] = $alpha;
5991
+ } else {
5992
+ $color = [Type::T_STRING, '',
5993
+ [$funcName . '(', $color[1], ', ', $color[2], ', ', $color[3], ', ', $alpha, ')']];
5994
+ }
5995
+ } else {
5996
+ $color = [Type::T_STRING, '', [$funcName . '(', $args[0], ')']];
5997
+ }
5998
+ break;
5999
+
6000
+ case 4:
6001
+ default:
6002
+ $color = [Type::T_COLOR, $args[0], $args[1], $args[2], $args[3]];
6003
+
6004
+ if (! $color = $this->coerceColor($color)) {
6005
+ $color = [Type::T_STRING, '',
6006
+ [$funcName . '(', $args[0], ', ', $args[1], ', ', $args[2], ', ', $args[3], ')']];
6007
+ }
6008
+ break;
6009
+ }
6010
+
6011
+ return $color;
6012
+ }
6013
+
6014
+ protected static $libRgba = [
6015
+ ['color'],
6016
+ ['color', 'alpha'],
6017
+ ['channels'],
6018
+ ['red', 'green', 'blue'],
6019
+ ['red', 'green', 'blue', 'alpha'] ];
6020
+ protected function libRgba($args, $kwargs)
6021
+ {
6022
+ return $this->libRgb($args, $kwargs, 'rgba');
6023
+ }
6024
+
6025
+ // helper function for adjust_color, change_color, and scale_color
6026
+ protected function alterColor($args, $fn)
6027
+ {
6028
+ $color = $this->assertColor($args[0]);
6029
+
6030
+ foreach ([1 => 1, 2 => 2, 3 => 3, 7 => 4] as $iarg => $irgba) {
6031
+ if (isset($args[$iarg])) {
6032
+ $val = $this->assertNumber($args[$iarg]);
6033
+
6034
+ if (! isset($color[$irgba])) {
6035
+ $color[$irgba] = (($irgba < 4) ? 0 : 1);
6036
+ }
6037
+
6038
+ $color[$irgba] = \call_user_func($fn, $color[$irgba], $val, $iarg);
6039
+ }
6040
+ }
6041
+
6042
+ if (! empty($args[4]) || ! empty($args[5]) || ! empty($args[6])) {
6043
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
6044
+
6045
+ foreach ([4 => 1, 5 => 2, 6 => 3] as $iarg => $ihsl) {
6046
+ if (! empty($args[$iarg])) {
6047
+ $val = $this->assertNumber($args[$iarg]);
6048
+ $hsl[$ihsl] = \call_user_func($fn, $hsl[$ihsl], $val, $iarg);
6049
+ }
6050
+ }
6051
+
6052
+ $rgb = $this->toRGB($hsl[1], $hsl[2], $hsl[3]);
6053
+
6054
+ if (isset($color[4])) {
6055
+ $rgb[4] = $color[4];
6056
+ }
6057
+
6058
+ $color = $rgb;
6059
+ }
6060
+
6061
+ return $color;
6062
+ }
6063
+
6064
+ protected static $libAdjustColor = [
6065
+ 'color', 'red:null', 'green:null', 'blue:null',
6066
+ 'hue:null', 'saturation:null', 'lightness:null', 'alpha:null'
6067
+ ];
6068
+ protected function libAdjustColor($args)
6069
+ {
6070
+ return $this->alterColor($args, function ($base, $alter, $i) {
6071
+ return $base + $alter;
6072
+ });
6073
+ }
6074
+
6075
+ protected static $libChangeColor = [
6076
+ 'color', 'red:null', 'green:null', 'blue:null',
6077
+ 'hue:null', 'saturation:null', 'lightness:null', 'alpha:null'
6078
+ ];
6079
+ protected function libChangeColor($args)
6080
+ {
6081
+ return $this->alterColor($args, function ($base, $alter, $i) {
6082
+ return $alter;
6083
+ });
6084
+ }
6085
+
6086
+ protected static $libScaleColor = [
6087
+ 'color', 'red:null', 'green:null', 'blue:null',
6088
+ 'hue:null', 'saturation:null', 'lightness:null', 'alpha:null'
6089
+ ];
6090
+ protected function libScaleColor($args)
6091
+ {
6092
+ return $this->alterColor($args, function ($base, $scale, $i) {
6093
+ // 1, 2, 3 - rgb
6094
+ // 4, 5, 6 - hsl
6095
+ // 7 - a
6096
+ switch ($i) {
6097
+ case 1:
6098
+ case 2:
6099
+ case 3:
6100
+ $max = 255;
6101
+ break;
6102
+
6103
+ case 4:
6104
+ $max = 360;
6105
+ break;
6106
+
6107
+ case 7:
6108
+ $max = 1;
6109
+ break;
6110
+
6111
+ default:
6112
+ $max = 100;
6113
+ }
6114
+
6115
+ $scale = $scale / 100;
6116
+
6117
+ if ($scale < 0) {
6118
+ return $base * $scale + $base;
6119
+ }
6120
+
6121
+ return ($max - $base) * $scale + $base;
6122
+ });
6123
+ }
6124
+
6125
+ protected static $libIeHexStr = ['color'];
6126
+ protected function libIeHexStr($args)
6127
+ {
6128
+ $color = $this->coerceColor($args[0]);
6129
+ $color[4] = isset($color[4]) ? round(255 * $color[4]) : 255;
6130
+
6131
+ return [Type::T_STRING, '', [sprintf('#%02X%02X%02X%02X', $color[4], $color[1], $color[2], $color[3])]];
6132
+ }
6133
+
6134
+ protected static $libRed = ['color'];
6135
+ protected function libRed($args)
6136
+ {
6137
+ $color = $this->coerceColor($args[0]);
6138
+
6139
+ return $color[1];
6140
+ }
6141
+
6142
+ protected static $libGreen = ['color'];
6143
+ protected function libGreen($args)
6144
+ {
6145
+ $color = $this->coerceColor($args[0]);
6146
+
6147
+ return $color[2];
6148
+ }
6149
+
6150
+ protected static $libBlue = ['color'];
6151
+ protected function libBlue($args)
6152
+ {
6153
+ $color = $this->coerceColor($args[0]);
6154
+
6155
+ return $color[3];
6156
+ }
6157
+
6158
+ protected static $libAlpha = ['color'];
6159
+ protected function libAlpha($args)
6160
+ {
6161
+ if ($color = $this->coerceColor($args[0])) {
6162
+ return isset($color[4]) ? $color[4] : 1;
6163
+ }
6164
+
6165
+ // this might be the IE function, so return value unchanged
6166
+ return null;
6167
+ }
6168
+
6169
+ protected static $libOpacity = ['color'];
6170
+ protected function libOpacity($args)
6171
+ {
6172
+ $value = $args[0];
6173
+
6174
+ if ($value[0] === Type::T_NUMBER) {
6175
+ return null;
6176
+ }
6177
+
6178
+ return $this->libAlpha($args);
6179
+ }
6180
+
6181
+ // mix two colors
6182
+ protected static $libMix = ['color-1', 'color-2', 'weight:0.5'];
6183
+ protected function libMix($args)
6184
+ {
6185
+ list($first, $second, $weight) = $args;
6186
+
6187
+ $first = $this->assertColor($first);
6188
+ $second = $this->assertColor($second);
6189
+
6190
+ if (! isset($weight)) {
6191
+ $weight = 0.5;
6192
+ } else {
6193
+ $weight = $this->coercePercent($weight);
6194
+ }
6195
+
6196
+ $firstAlpha = isset($first[4]) ? $first[4] : 1;
6197
+ $secondAlpha = isset($second[4]) ? $second[4] : 1;
6198
+
6199
+ $w = $weight * 2 - 1;
6200
+ $a = $firstAlpha - $secondAlpha;
6201
+
6202
+ $w1 = (($w * $a === -1 ? $w : ($w + $a) / (1 + $w * $a)) + 1) / 2.0;
6203
+ $w2 = 1.0 - $w1;
6204
+
6205
+ $new = [Type::T_COLOR,
6206
+ $w1 * $first[1] + $w2 * $second[1],
6207
+ $w1 * $first[2] + $w2 * $second[2],
6208
+ $w1 * $first[3] + $w2 * $second[3],
6209
+ ];
6210
+
6211
+ if ($firstAlpha != 1.0 || $secondAlpha != 1.0) {
6212
+ $new[] = $firstAlpha * $weight + $secondAlpha * (1 - $weight);
6213
+ }
6214
+
6215
+ return $this->fixColor($new);
6216
+ }
6217
+
6218
+ protected static $libHsl =[
6219
+ ['channels'],
6220
+ ['hue', 'saturation', 'lightness'],
6221
+ ['hue', 'saturation', 'lightness', 'alpha'] ];
6222
+ protected function libHsl($args, $kwargs, $funcName = 'hsl')
6223
+ {
6224
+ if (\count($args) == 1) {
6225
+ if ($args[0][0] !== Type::T_LIST || \count($args[0][2]) < 3 || \count($args[0][2]) > 4) {
6226
+ return [Type::T_STRING, '', [$funcName . '(', $args[0], ')']];
6227
+ }
6228
+
6229
+ $args = $args[0][2];
6230
+ }
6231
+
6232
+ $hue = $this->compileColorPartValue($args[0], 0, 360, false, false, true);
6233
+ $saturation = $this->compileColorPartValue($args[1], 0, 100, false);
6234
+ $lightness = $this->compileColorPartValue($args[2], 0, 100, false);
6235
+
6236
+ $alpha = null;
6237
+
6238
+ if (\count($args) === 4) {
6239
+ $alpha = $this->compileColorPartValue($args[3], 0, 100, false);
6240
+
6241
+ if (! is_numeric($hue) || ! is_numeric($saturation) || ! is_numeric($lightness) || ! is_numeric($alpha)) {
6242
+ return [Type::T_STRING, '',
6243
+ [$funcName . '(', $args[0], ', ', $args[1], ', ', $args[2], ', ', $args[3], ')']];
6244
+ }
6245
+ } else {
6246
+ if (! is_numeric($hue) || ! is_numeric($saturation) || ! is_numeric($lightness)) {
6247
+ return [Type::T_STRING, '', [$funcName . '(', $args[0], ', ', $args[1], ', ', $args[2], ')']];
6248
+ }
6249
+ }
6250
+
6251
+ $color = $this->toRGB($hue, $saturation, $lightness);
6252
+
6253
+ if (! \is_null($alpha)) {
6254
+ $color[4] = $alpha;
6255
+ }
6256
+
6257
+ return $color;
6258
+ }
6259
+
6260
+ protected static $libHsla = [
6261
+ ['channels'],
6262
+ ['hue', 'saturation', 'lightness', 'alpha:1'] ];
6263
+ protected function libHsla($args, $kwargs)
6264
+ {
6265
+ return $this->libHsl($args, $kwargs, 'hsla');
6266
+ }
6267
+
6268
+ protected static $libHue = ['color'];
6269
+ protected function libHue($args)
6270
+ {
6271
+ $color = $this->assertColor($args[0]);
6272
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
6273
+
6274
+ return new Node\Number($hsl[1], 'deg');
6275
+ }
6276
+
6277
+ protected static $libSaturation = ['color'];
6278
+ protected function libSaturation($args)
6279
+ {
6280
+ $color = $this->assertColor($args[0]);
6281
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
6282
+
6283
+ return new Node\Number($hsl[2], '%');
6284
+ }
6285
+
6286
+ protected static $libLightness = ['color'];
6287
+ protected function libLightness($args)
6288
+ {
6289
+ $color = $this->assertColor($args[0]);
6290
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
6291
+
6292
+ return new Node\Number($hsl[3], '%');
6293
+ }
6294
+
6295
+ protected function adjustHsl($color, $idx, $amount)
6296
+ {
6297
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
6298
+ $hsl[$idx] += $amount;
6299
+ $out = $this->toRGB($hsl[1], $hsl[2], $hsl[3]);
6300
+
6301
+ if (isset($color[4])) {
6302
+ $out[4] = $color[4];
6303
+ }
6304
+
6305
+ return $out;
6306
+ }
6307
+
6308
+ protected static $libAdjustHue = ['color', 'degrees'];
6309
+ protected function libAdjustHue($args)
6310
+ {
6311
+ $color = $this->assertColor($args[0]);
6312
+ $degrees = $this->assertNumber($args[1]);
6313
+
6314
+ return $this->adjustHsl($color, 1, $degrees);
6315
+ }
6316
+
6317
+ protected static $libLighten = ['color', 'amount'];
6318
+ protected function libLighten($args)
6319
+ {
6320
+ $color = $this->assertColor($args[0]);
6321
+ $amount = Util::checkRange('amount', new Range(0, 100), $args[1], '%');
6322
+
6323
+ return $this->adjustHsl($color, 3, $amount);
6324
+ }
6325
+
6326
+ protected static $libDarken = ['color', 'amount'];
6327
+ protected function libDarken($args)
6328
+ {
6329
+ $color = $this->assertColor($args[0]);
6330
+ $amount = Util::checkRange('amount', new Range(0, 100), $args[1], '%');
6331
+
6332
+ return $this->adjustHsl($color, 3, -$amount);
6333
+ }
6334
+
6335
+ protected static $libSaturate = [['color', 'amount'], ['number']];
6336
+ protected function libSaturate($args)
6337
+ {
6338
+ $value = $args[0];
6339
+
6340
+ if ($value[0] === Type::T_NUMBER) {
6341
+ return null;
6342
+ }
6343
+
6344
+ $color = $this->assertColor($value);
6345
+ $amount = 100 * $this->coercePercent($args[1]);
6346
+
6347
+ return $this->adjustHsl($color, 2, $amount);
6348
+ }
6349
+
6350
+ protected static $libDesaturate = ['color', 'amount'];
6351
+ protected function libDesaturate($args)
6352
+ {
6353
+ $color = $this->assertColor($args[0]);
6354
+ $amount = 100 * $this->coercePercent($args[1]);
6355
+
6356
+ return $this->adjustHsl($color, 2, -$amount);
6357
+ }
6358
+
6359
+ protected static $libGrayscale = ['color'];
6360
+ protected function libGrayscale($args)
6361
+ {
6362
+ $value = $args[0];
6363
+
6364
+ if ($value[0] === Type::T_NUMBER) {
6365
+ return null;
6366
+ }
6367
+
6368
+ return $this->adjustHsl($this->assertColor($value), 2, -100);
6369
+ }
6370
+
6371
+ protected static $libComplement = ['color'];
6372
+ protected function libComplement($args)
6373
+ {
6374
+ return $this->adjustHsl($this->assertColor($args[0]), 1, 180);
6375
+ }
6376
+
6377
+ protected static $libInvert = ['color', 'weight:1'];
6378
+ protected function libInvert($args)
6379
+ {
6380
+ list($value, $weight) = $args;
6381
+
6382
+ if (! isset($weight)) {
6383
+ $weight = 1;
6384
+ } else {
6385
+ $weight = $this->coercePercent($weight);
6386
+ }
6387
+
6388
+ if ($value[0] === Type::T_NUMBER) {
6389
+ return null;
6390
+ }
6391
+
6392
+ $color = $this->assertColor($value);
6393
+ $inverted = $color;
6394
+ $inverted[1] = 255 - $inverted[1];
6395
+ $inverted[2] = 255 - $inverted[2];
6396
+ $inverted[3] = 255 - $inverted[3];
6397
+
6398
+ if ($weight < 1) {
6399
+ return $this->libMix([$inverted, $color, [Type::T_NUMBER, $weight]]);
6400
+ }
6401
+
6402
+ return $inverted;
6403
+ }
6404
+
6405
+ // increases opacity by amount
6406
+ protected static $libOpacify = ['color', 'amount'];
6407
+ protected function libOpacify($args)
6408
+ {
6409
+ $color = $this->assertColor($args[0]);
6410
+ $amount = $this->coercePercent($args[1]);
6411
+
6412
+ $color[4] = (isset($color[4]) ? $color[4] : 1) + $amount;
6413
+ $color[4] = min(1, max(0, $color[4]));
6414
+
6415
+ return $color;
6416
+ }
6417
+
6418
+ protected static $libFadeIn = ['color', 'amount'];
6419
+ protected function libFadeIn($args)
6420
+ {
6421
+ return $this->libOpacify($args);
6422
+ }
6423
+
6424
+ // decreases opacity by amount
6425
+ protected static $libTransparentize = ['color', 'amount'];
6426
+ protected function libTransparentize($args)
6427
+ {
6428
+ $color = $this->assertColor($args[0]);
6429
+ $amount = $this->coercePercent($args[1]);
6430
+
6431
+ $color[4] = (isset($color[4]) ? $color[4] : 1) - $amount;
6432
+ $color[4] = min(1, max(0, $color[4]));
6433
+
6434
+ return $color;
6435
+ }
6436
+
6437
+ protected static $libFadeOut = ['color', 'amount'];
6438
+ protected function libFadeOut($args)
6439
+ {
6440
+ return $this->libTransparentize($args);
6441
+ }
6442
+
6443
+ protected static $libUnquote = ['string'];
6444
+ protected function libUnquote($args)
6445
+ {
6446
+ $str = $args[0];
6447
+
6448
+ if ($str[0] === Type::T_STRING) {
6449
+ $str[1] = '';
6450
+ }
6451
+
6452
+ return $str;
6453
+ }
6454
+
6455
+ protected static $libQuote = ['string'];
6456
+ protected function libQuote($args)
6457
+ {
6458
+ $value = $args[0];
6459
+
6460
+ if ($value[0] === Type::T_STRING && ! empty($value[1])) {
6461
+ return $value;
6462
+ }
6463
+
6464
+ return [Type::T_STRING, '"', [$value]];
6465
+ }
6466
+
6467
+ protected static $libPercentage = ['number'];
6468
+ protected function libPercentage($args)
6469
+ {
6470
+ return new Node\Number($this->coercePercent($args[0]) * 100, '%');
6471
+ }
6472
+
6473
+ protected static $libRound = ['number'];
6474
+ protected function libRound($args)
6475
+ {
6476
+ $num = $args[0];
6477
+
6478
+ return new Node\Number(round($num[1]), $num[2]);
6479
+ }
6480
+
6481
+ protected static $libFloor = ['number'];
6482
+ protected function libFloor($args)
6483
+ {
6484
+ $num = $args[0];
6485
+
6486
+ return new Node\Number(floor($num[1]), $num[2]);
6487
+ }
6488
+
6489
+ protected static $libCeil = ['number'];
6490
+ protected function libCeil($args)
6491
+ {
6492
+ $num = $args[0];
6493
+
6494
+ return new Node\Number(ceil($num[1]), $num[2]);
6495
+ }
6496
+
6497
+ protected static $libAbs = ['number'];
6498
+ protected function libAbs($args)
6499
+ {
6500
+ $num = $args[0];
6501
+
6502
+ return new Node\Number(abs($num[1]), $num[2]);
6503
+ }
6504
+
6505
+ protected function libMin($args)
6506
+ {
6507
+ $numbers = $this->getNormalizedNumbers($args);
6508
+ $minOriginal = null;
6509
+ $minNormalized = null;
6510
+
6511
+ foreach ($numbers as $key => $pair) {
6512
+ list($original, $normalized) = $pair;
6513
+
6514
+ if (\is_null($normalized) or \is_null($minNormalized)) {
6515
+ if (\is_null($minOriginal) || $original[1] <= $minOriginal[1]) {
6516
+ $minOriginal = $original;
6517
+ $minNormalized = $normalized;
6518
+ }
6519
+ } elseif ($normalized[1] <= $minNormalized[1]) {
6520
+ $minOriginal = $original;
6521
+ $minNormalized = $normalized;
6522
+ }
6523
+ }
6524
+
6525
+ return $minOriginal;
6526
+ }
6527
+
6528
+ protected function libMax($args)
6529
+ {
6530
+ $numbers = $this->getNormalizedNumbers($args);
6531
+ $maxOriginal = null;
6532
+ $maxNormalized = null;
6533
+
6534
+ foreach ($numbers as $key => $pair) {
6535
+ list($original, $normalized) = $pair;
6536
+
6537
+ if (\is_null($normalized) or \is_null($maxNormalized)) {
6538
+ if (\is_null($maxOriginal) || $original[1] >= $maxOriginal[1]) {
6539
+ $maxOriginal = $original;
6540
+ $maxNormalized = $normalized;
6541
+ }
6542
+ } elseif ($normalized[1] >= $maxNormalized[1]) {
6543
+ $maxOriginal = $original;
6544
+ $maxNormalized = $normalized;
6545
+ }
6546
+ }
6547
+
6548
+ return $maxOriginal;
6549
+ }
6550
+
6551
+ /**
6552
+ * Helper to normalize args containing numbers
6553
+ *
6554
+ * @param array $args
6555
+ *
6556
+ * @return array
6557
+ */
6558
+ protected function getNormalizedNumbers($args)
6559
+ {
6560
+ $unit = null;
6561
+ $originalUnit = null;
6562
+ $numbers = [];
6563
+
6564
+ foreach ($args as $key => $item) {
6565
+ if ($item[0] !== Type::T_NUMBER) {
6566
+ $this->throwError('%s is not a number', $item[0]);
6567
+ break;
6568
+ }
6569
+
6570
+ $number = $item->normalize();
6571
+
6572
+ if (empty($unit)) {
6573
+ $unit = $number[2];
6574
+ $originalUnit = $item->unitStr();
6575
+ } elseif ($number[1] && $unit !== $number[2] && ! empty($number[2])) {
6576
+ $this->throwError('Incompatible units: "%s" and "%s".', $originalUnit, $item->unitStr());
6577
+ break;
6578
+ }
6579
+
6580
+ $numbers[$key] = [$args[$key], empty($number[2]) ? null : $number];
6581
+ }
6582
+
6583
+ return $numbers;
6584
+ }
6585
+
6586
+ protected static $libLength = ['list'];
6587
+ protected function libLength($args)
6588
+ {
6589
+ $list = $this->coerceList($args[0], ',', true);
6590
+
6591
+ return \count($list[2]);
6592
+ }
6593
+
6594
+ //protected static $libListSeparator = ['list...'];
6595
+ protected function libListSeparator($args)
6596
+ {
6597
+ if (\count($args) > 1) {
6598
+ return 'comma';
6599
+ }
6600
+
6601
+ $list = $this->coerceList($args[0]);
6602
+
6603
+ if (\count($list[2]) <= 1) {
6604
+ return 'space';
6605
+ }
6606
+
6607
+ if ($list[1] === ',') {
6608
+ return 'comma';
6609
+ }
6610
+
6611
+ return 'space';
6612
+ }
6613
+
6614
+ protected static $libNth = ['list', 'n'];
6615
+ protected function libNth($args)
6616
+ {
6617
+ $list = $this->coerceList($args[0], ',', false);
6618
+ $n = $this->assertNumber($args[1]);
6619
+
6620
+ if ($n > 0) {
6621
+ $n--;
6622
+ } elseif ($n < 0) {
6623
+ $n += \count($list[2]);
6624
+ }
6625
+
6626
+ return isset($list[2][$n]) ? $list[2][$n] : static::$defaultValue;
6627
+ }
6628
+
6629
+ protected static $libSetNth = ['list', 'n', 'value'];
6630
+ protected function libSetNth($args)
6631
+ {
6632
+ $list = $this->coerceList($args[0]);
6633
+ $n = $this->assertNumber($args[1]);
6634
+
6635
+ if ($n > 0) {
6636
+ $n--;
6637
+ } elseif ($n < 0) {
6638
+ $n += \count($list[2]);
6639
+ }
6640
+
6641
+ if (! isset($list[2][$n])) {
6642
+ $this->throwError('Invalid argument for "n"');
6643
+
6644
+ return null;
6645
+ }
6646
+
6647
+ $list[2][$n] = $args[2];
6648
+
6649
+ return $list;
6650
+ }
6651
+
6652
+ protected static $libMapGet = ['map', 'key'];
6653
+ protected function libMapGet($args)
6654
+ {
6655
+ $map = $this->assertMap($args[0]);
6656
+ $key = $args[1];
6657
+
6658
+ if (! \is_null($key)) {
6659
+ $key = $this->compileStringContent($this->coerceString($key));
6660
+
6661
+ for ($i = \count($map[1]) - 1; $i >= 0; $i--) {
6662
+ if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) {
6663
+ return $map[2][$i];
6664
+ }
6665
+ }
6666
+ }
6667
+
6668
+ return static::$null;
6669
+ }
6670
+
6671
+ protected static $libMapKeys = ['map'];
6672
+ protected function libMapKeys($args)
6673
+ {
6674
+ $map = $this->assertMap($args[0]);
6675
+ $keys = $map[1];
6676
+
6677
+ return [Type::T_LIST, ',', $keys];
6678
+ }
6679
+
6680
+ protected static $libMapValues = ['map'];
6681
+ protected function libMapValues($args)
6682
+ {
6683
+ $map = $this->assertMap($args[0]);
6684
+ $values = $map[2];
6685
+
6686
+ return [Type::T_LIST, ',', $values];
6687
+ }
6688
+
6689
+ protected static $libMapRemove = ['map', 'key'];
6690
+ protected function libMapRemove($args)
6691
+ {
6692
+ $map = $this->assertMap($args[0]);
6693
+ $key = $this->compileStringContent($this->coerceString($args[1]));
6694
+
6695
+ for ($i = \count($map[1]) - 1; $i >= 0; $i--) {
6696
+ if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) {
6697
+ array_splice($map[1], $i, 1);
6698
+ array_splice($map[2], $i, 1);
6699
+ }
6700
+ }
6701
+
6702
+ return $map;
6703
+ }
6704
+
6705
+ protected static $libMapHasKey = ['map', 'key'];
6706
+ protected function libMapHasKey($args)
6707
+ {
6708
+ $map = $this->assertMap($args[0]);
6709
+ $key = $this->compileStringContent($this->coerceString($args[1]));
6710
+
6711
+ for ($i = \count($map[1]) - 1; $i >= 0; $i--) {
6712
+ if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) {
6713
+ return true;
6714
+ }
6715
+ }
6716
+
6717
+ return false;
6718
+ }
6719
+
6720
+ protected static $libMapMerge = ['map-1', 'map-2'];
6721
+ protected function libMapMerge($args)
6722
+ {
6723
+ $map1 = $this->assertMap($args[0]);
6724
+ $map2 = $this->assertMap($args[1]);
6725
+
6726
+ foreach ($map2[1] as $i2 => $key2) {
6727
+ $key = $this->compileStringContent($this->coerceString($key2));
6728
+
6729
+ foreach ($map1[1] as $i1 => $key1) {
6730
+ if ($key === $this->compileStringContent($this->coerceString($key1))) {
6731
+ $map1[2][$i1] = $map2[2][$i2];
6732
+ continue 2;
6733
+ }
6734
+ }
6735
+
6736
+ $map1[1][] = $map2[1][$i2];
6737
+ $map1[2][] = $map2[2][$i2];
6738
+ }
6739
+
6740
+ return $map1;
6741
+ }
6742
+
6743
+ protected static $libKeywords = ['args'];
6744
+ protected function libKeywords($args)
6745
+ {
6746
+ $this->assertList($args[0]);
6747
+
6748
+ $keys = [];
6749
+ $values = [];
6750
+
6751
+ foreach ($args[0][2] as $name => $arg) {
6752
+ $keys[] = [Type::T_KEYWORD, $name];
6753
+ $values[] = $arg;
6754
+ }
6755
+
6756
+ return [Type::T_MAP, $keys, $values];
6757
+ }
6758
+
6759
+ protected static $libIsBracketed = ['list'];
6760
+ protected function libIsBracketed($args)
6761
+ {
6762
+ $list = $args[0];
6763
+ $this->coerceList($list, ' ');
6764
+
6765
+ if (! empty($list['enclosing']) && $list['enclosing'] === 'bracket') {
6766
+ return true;
6767
+ }
6768
+
6769
+ return false;
6770
+ }
6771
+
6772
+ protected function listSeparatorForJoin($list1, $sep)
6773
+ {
6774
+ if (! isset($sep)) {
6775
+ return $list1[1];
6776
+ }
6777
+
6778
+ switch ($this->compileValue($sep)) {
6779
+ case 'comma':
6780
+ return ',';
6781
+
6782
+ case 'space':
6783
+ return ' ';
6784
+
6785
+ default:
6786
+ return $list1[1];
6787
+ }
6788
+ }
6789
+
6790
+ protected static $libJoin = ['list1', 'list2', 'separator:null', 'bracketed:auto'];
6791
+ protected function libJoin($args)
6792
+ {
6793
+ list($list1, $list2, $sep, $bracketed) = $args;
6794
+
6795
+ $list1 = $this->coerceList($list1, ' ', true);
6796
+ $list2 = $this->coerceList($list2, ' ', true);
6797
+ $sep = $this->listSeparatorForJoin($list1, $sep);
6798
+
6799
+ if ($bracketed === static::$true) {
6800
+ $bracketed = true;
6801
+ } elseif ($bracketed === static::$false) {
6802
+ $bracketed = false;
6803
+ } elseif ($bracketed === [Type::T_KEYWORD, 'auto']) {
6804
+ $bracketed = 'auto';
6805
+ } elseif ($bracketed === static::$null) {
6806
+ $bracketed = false;
6807
+ } else {
6808
+ $bracketed = $this->compileValue($bracketed);
6809
+ $bracketed = ! ! $bracketed;
6810
+
6811
+ if ($bracketed === true) {
6812
+ $bracketed = true;
6813
+ }
6814
+ }
6815
+
6816
+ if ($bracketed === 'auto') {
6817
+ $bracketed = false;
6818
+
6819
+ if (! empty($list1['enclosing']) && $list1['enclosing'] === 'bracket') {
6820
+ $bracketed = true;
6821
+ }
6822
+ }
6823
+
6824
+ $res = [Type::T_LIST, $sep, array_merge($list1[2], $list2[2])];
6825
+
6826
+ if (isset($list1['enclosing'])) {
6827
+ $res['enlcosing'] = $list1['enclosing'];
6828
+ }
6829
+
6830
+ if ($bracketed) {
6831
+ $res['enclosing'] = 'bracket';
6832
+ }
6833
+
6834
+ return $res;
6835
+ }
6836
+
6837
+ protected static $libAppend = ['list', 'val', 'separator:null'];
6838
+ protected function libAppend($args)
6839
+ {
6840
+ list($list1, $value, $sep) = $args;
6841
+
6842
+ $list1 = $this->coerceList($list1, ' ', true);
6843
+ $sep = $this->listSeparatorForJoin($list1, $sep);
6844
+ $res = [Type::T_LIST, $sep, array_merge($list1[2], [$value])];
6845
+
6846
+ if (isset($list1['enclosing'])) {
6847
+ $res['enclosing'] = $list1['enclosing'];
6848
+ }
6849
+
6850
+ return $res;
6851
+ }
6852
+
6853
+ protected function libZip($args)
6854
+ {
6855
+ foreach ($args as $key => $arg) {
6856
+ $args[$key] = $this->coerceList($arg);
6857
+ }
6858
+
6859
+ $lists = [];
6860
+ $firstList = array_shift($args);
6861
+
6862
+ foreach ($firstList[2] as $key => $item) {
6863
+ $list = [Type::T_LIST, '', [$item]];
6864
+
6865
+ foreach ($args as $arg) {
6866
+ if (isset($arg[2][$key])) {
6867
+ $list[2][] = $arg[2][$key];
6868
+ } else {
6869
+ break 2;
6870
+ }
6871
+ }
6872
+
6873
+ $lists[] = $list;
6874
+ }
6875
+
6876
+ return [Type::T_LIST, ',', $lists];
6877
+ }
6878
+
6879
+ protected static $libTypeOf = ['value'];
6880
+ protected function libTypeOf($args)
6881
+ {
6882
+ $value = $args[0];
6883
+
6884
+ switch ($value[0]) {
6885
+ case Type::T_KEYWORD:
6886
+ if ($value === static::$true || $value === static::$false) {
6887
+ return 'bool';
6888
+ }
6889
+
6890
+ if ($this->coerceColor($value)) {
6891
+ return 'color';
6892
+ }
6893
+
6894
+ // fall-thru
6895
+ case Type::T_FUNCTION:
6896
+ return 'string';
6897
+
6898
+ case Type::T_LIST:
6899
+ if (isset($value[3]) && $value[3]) {
6900
+ return 'arglist';
6901
+ }
6902
+
6903
+ // fall-thru
6904
+ default:
6905
+ return $value[0];
6906
+ }
6907
+ }
6908
+
6909
+ protected static $libUnit = ['number'];
6910
+ protected function libUnit($args)
6911
+ {
6912
+ $num = $args[0];
6913
+
6914
+ if ($num[0] === Type::T_NUMBER) {
6915
+ return [Type::T_STRING, '"', [$num->unitStr()]];
6916
+ }
6917
+
6918
+ return '';
6919
+ }
6920
+
6921
+ protected static $libUnitless = ['number'];
6922
+ protected function libUnitless($args)
6923
+ {
6924
+ $value = $args[0];
6925
+
6926
+ return $value[0] === Type::T_NUMBER && $value->unitless();
6927
+ }
6928
+
6929
+ protected static $libComparable = ['number-1', 'number-2'];
6930
+ protected function libComparable($args)
6931
+ {
6932
+ list($number1, $number2) = $args;
6933
+
6934
+ if (! isset($number1[0]) || $number1[0] !== Type::T_NUMBER ||
6935
+ ! isset($number2[0]) || $number2[0] !== Type::T_NUMBER
6936
+ ) {
6937
+ $this->throwError('Invalid argument(s) for "comparable"');
6938
+
6939
+ return null;
6940
+ }
6941
+
6942
+ $number1 = $number1->normalize();
6943
+ $number2 = $number2->normalize();
6944
+
6945
+ return $number1[2] === $number2[2] || $number1->unitless() || $number2->unitless();
6946
+ }
6947
+
6948
+ protected static $libStrIndex = ['string', 'substring'];
6949
+ protected function libStrIndex($args)
6950
+ {
6951
+ $string = $this->coerceString($args[0]);
6952
+ $stringContent = $this->compileStringContent($string);
6953
+
6954
+ $substring = $this->coerceString($args[1]);
6955
+ $substringContent = $this->compileStringContent($substring);
6956
+
6957
+ $result = strpos($stringContent, $substringContent);
6958
+
6959
+ return $result === false ? static::$null : new Node\Number($result + 1, '');
6960
+ }
6961
+
6962
+ protected static $libStrInsert = ['string', 'insert', 'index'];
6963
+ protected function libStrInsert($args)
6964
+ {
6965
+ $string = $this->coerceString($args[0]);
6966
+ $stringContent = $this->compileStringContent($string);
6967
+
6968
+ $insert = $this->coerceString($args[1]);
6969
+ $insertContent = $this->compileStringContent($insert);
6970
+
6971
+ list(, $index) = $args[2];
6972
+
6973
+ $string[2] = [substr_replace($stringContent, $insertContent, $index - 1, 0)];
6974
+
6975
+ return $string;
6976
+ }
6977
+
6978
+ protected static $libStrLength = ['string'];
6979
+ protected function libStrLength($args)
6980
+ {
6981
+ $string = $this->coerceString($args[0]);
6982
+ $stringContent = $this->compileStringContent($string);
6983
+
6984
+ return new Node\Number(\strlen($stringContent), '');
6985
+ }
6986
+
6987
+ protected static $libStrSlice = ['string', 'start-at', 'end-at:-1'];
6988
+ protected function libStrSlice($args)
6989
+ {
6990
+ if (isset($args[2]) && ! $args[2][1]) {
6991
+ return static::$nullString;
6992
+ }
6993
+
6994
+ $string = $this->coerceString($args[0]);
6995
+ $stringContent = $this->compileStringContent($string);
6996
+
6997
+ $start = (int) $args[1][1];
6998
+
6999
+ if ($start > 0) {
7000
+ $start--;
7001
+ }
7002
+
7003
+ $end = isset($args[2]) ? (int) $args[2][1] : -1;
7004
+ $length = $end < 0 ? $end + 1 : ($end > 0 ? $end - $start : $end);
7005
+
7006
+ $string[2] = $length
7007
+ ? [substr($stringContent, $start, $length)]
7008
+ : [substr($stringContent, $start)];
7009
+
7010
+ return $string;
7011
+ }
7012
+
7013
+ protected static $libToLowerCase = ['string'];
7014
+ protected function libToLowerCase($args)
7015
+ {
7016
+ $string = $this->coerceString($args[0]);
7017
+ $stringContent = $this->compileStringContent($string);
7018
+
7019
+ $string[2] = [\function_exists('mb_strtolower') ? mb_strtolower($stringContent) : strtolower($stringContent)];
7020
+
7021
+ return $string;
7022
+ }
7023
+
7024
+ protected static $libToUpperCase = ['string'];
7025
+ protected function libToUpperCase($args)
7026
+ {
7027
+ $string = $this->coerceString($args[0]);
7028
+ $stringContent = $this->compileStringContent($string);
7029
+
7030
+ $string[2] = [\function_exists('mb_strtoupper') ? mb_strtoupper($stringContent) : strtoupper($stringContent)];
7031
+
7032
+ return $string;
7033
+ }
7034
+
7035
+ protected static $libFeatureExists = ['feature'];
7036
+ protected function libFeatureExists($args)
7037
+ {
7038
+ $string = $this->coerceString($args[0]);
7039
+ $name = $this->compileStringContent($string);
7040
+
7041
+ return $this->toBool(
7042
+ \array_key_exists($name, $this->registeredFeatures) ? $this->registeredFeatures[$name] : false
7043
+ );
7044
+ }
7045
+
7046
+ protected static $libFunctionExists = ['name'];
7047
+ protected function libFunctionExists($args)
7048
+ {
7049
+ $string = $this->coerceString($args[0]);
7050
+ $name = $this->compileStringContent($string);
7051
+
7052
+ // user defined functions
7053
+ if ($this->has(static::$namespaces['function'] . $name)) {
7054
+ return true;
7055
+ }
7056
+
7057
+ $name = $this->normalizeName($name);
7058
+
7059
+ if (isset($this->userFunctions[$name])) {
7060
+ return true;
7061
+ }
7062
+
7063
+ // built-in functions
7064
+ $f = $this->getBuiltinFunction($name);
7065
+
7066
+ return $this->toBool(\is_callable($f));
7067
+ }
7068
+
7069
+ protected static $libGlobalVariableExists = ['name'];
7070
+ protected function libGlobalVariableExists($args)
7071
+ {
7072
+ $string = $this->coerceString($args[0]);
7073
+ $name = $this->compileStringContent($string);
7074
+
7075
+ return $this->has($name, $this->rootEnv);
7076
+ }
7077
+
7078
+ protected static $libMixinExists = ['name'];
7079
+ protected function libMixinExists($args)
7080
+ {
7081
+ $string = $this->coerceString($args[0]);
7082
+ $name = $this->compileStringContent($string);
7083
+
7084
+ return $this->has(static::$namespaces['mixin'] . $name);
7085
+ }
7086
+
7087
+ protected static $libVariableExists = ['name'];
7088
+ protected function libVariableExists($args)
7089
+ {
7090
+ $string = $this->coerceString($args[0]);
7091
+ $name = $this->compileStringContent($string);
7092
+
7093
+ return $this->has($name);
7094
+ }
7095
+
7096
+ /**
7097
+ * Workaround IE7's content counter bug.
7098
+ *
7099
+ * @param array $args
7100
+ *
7101
+ * @return array
7102
+ */
7103
+ protected function libCounter($args)
7104
+ {
7105
+ $list = array_map([$this, 'compileValue'], $args);
7106
+
7107
+ return [Type::T_STRING, '', ['counter(' . implode(',', $list) . ')']];
7108
+ }
7109
+
7110
+ protected static $libRandom = ['limit:1'];
7111
+ protected function libRandom($args)
7112
+ {
7113
+ if (isset($args[0])) {
7114
+ $n = $this->assertNumber($args[0]);
7115
+
7116
+ if ($n < 1) {
7117
+ $this->throwError("\$limit must be greater than or equal to 1");
7118
+
7119
+ return null;
7120
+ }
7121
+
7122
+ if ($n - \intval($n) > 0) {
7123
+ $this->throwError("Expected \$limit to be an integer but got $n for `random`");
7124
+
7125
+ return null;
7126
+ }
7127
+
7128
+ return new Node\Number(mt_rand(1, \intval($n)), '');
7129
+ }
7130
+
7131
+ return new Node\Number(mt_rand(1, mt_getrandmax()), '');
7132
+ }
7133
+
7134
+ protected function libUniqueId()
7135
+ {
7136
+ static $id;
7137
+
7138
+ if (! isset($id)) {
7139
+ $id = mt_rand(0, pow(36, 8));
7140
+ }
7141
+
7142
+ $id += mt_rand(0, 10) + 1;
7143
+
7144
+ return [Type::T_STRING, '', ['u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)]];
7145
+ }
7146
+
7147
+ protected function inspectFormatValue($value, $force_enclosing_display = false)
7148
+ {
7149
+ if ($value === static::$null) {
7150
+ $value = [Type::T_KEYWORD, 'null'];
7151
+ }
7152
+
7153
+ $stringValue = [$value];
7154
+
7155
+ if ($value[0] === Type::T_LIST) {
7156
+ if (end($value[2]) === static::$null) {
7157
+ array_pop($value[2]);
7158
+ $value[2][] = [Type::T_STRING, '', ['']];
7159
+ $force_enclosing_display = true;
7160
+ }
7161
+
7162
+ if (! empty($value['enclosing']) &&
7163
+ ($force_enclosing_display ||
7164
+ ($value['enclosing'] === 'bracket') ||
7165
+ ! \count($value[2]))
7166
+ ) {
7167
+ $value['enclosing'] = 'forced_'.$value['enclosing'];
7168
+ $force_enclosing_display = true;
7169
+ }
7170
+
7171
+ foreach ($value[2] as $k => $listelement) {
7172
+ $value[2][$k] = $this->inspectFormatValue($listelement, $force_enclosing_display);
7173
+ }
7174
+
7175
+ $stringValue = [$value];
7176
+ }
7177
+
7178
+ return [Type::T_STRING, '', $stringValue];
7179
+ }
7180
+
7181
+ protected static $libInspect = ['value'];
7182
+ protected function libInspect($args)
7183
+ {
7184
+ $value = $args[0];
7185
+
7186
+ return $this->inspectFormatValue($value);
7187
+ }
7188
+
7189
+ /**
7190
+ * Preprocess selector args
7191
+ *
7192
+ * @param array $arg
7193
+ *
7194
+ * @return array|boolean
7195
+ */
7196
+ protected function getSelectorArg($arg)
7197
+ {
7198
+ static $parser = null;
7199
+
7200
+ if (\is_null($parser)) {
7201
+ $parser = $this->parserFactory(__METHOD__);
7202
+ }
7203
+
7204
+ $arg = $this->libUnquote([$arg]);
7205
+ $arg = $this->compileValue($arg);
7206
+
7207
+ $parsedSelector = [];
7208
+
7209
+ if ($parser->parseSelector($arg, $parsedSelector)) {
7210
+ $selector = $this->evalSelectors($parsedSelector);
7211
+ $gluedSelector = $this->glueFunctionSelectors($selector);
7212
+
7213
+ return $gluedSelector;
7214
+ }
7215
+
7216
+ return false;
7217
+ }
7218
+
7219
+ /**
7220
+ * Postprocess selector to output in right format
7221
+ *
7222
+ * @param array $selectors
7223
+ *
7224
+ * @return string
7225
+ */
7226
+ protected function formatOutputSelector($selectors)
7227
+ {
7228
+ $selectors = $this->collapseSelectors($selectors, true);
7229
+
7230
+ return $selectors;
7231
+ }
7232
+
7233
+ protected static $libIsSuperselector = ['super', 'sub'];
7234
+ protected function libIsSuperselector($args)
7235
+ {
7236
+ list($super, $sub) = $args;
7237
+
7238
+ $super = $this->getSelectorArg($super);
7239
+ $sub = $this->getSelectorArg($sub);
7240
+
7241
+ return $this->isSuperSelector($super, $sub);
7242
+ }
7243
+
7244
+ /**
7245
+ * Test a $super selector again $sub
7246
+ *
7247
+ * @param array $super
7248
+ * @param array $sub
7249
+ *
7250
+ * @return boolean
7251
+ */
7252
+ protected function isSuperSelector($super, $sub)
7253
+ {
7254
+ // one and only one selector for each arg
7255
+ if (! $super || \count($super) !== 1) {
7256
+ $this->throwError("Invalid super selector for isSuperSelector()");
7257
+ }
7258
+
7259
+ if (! $sub || \count($sub) !== 1) {
7260
+ $this->throwError("Invalid sub selector for isSuperSelector()");
7261
+ }
7262
+
7263
+ $super = reset($super);
7264
+ $sub = reset($sub);
7265
+
7266
+ $i = 0;
7267
+ $nextMustMatch = false;
7268
+
7269
+ foreach ($super as $node) {
7270
+ $compound = '';
7271
+
7272
+ array_walk_recursive(
7273
+ $node,
7274
+ function ($value, $key) use (&$compound) {
7275
+ $compound .= $value;
7276
+ }
7277
+ );
7278
+
7279
+ if ($this->isImmediateRelationshipCombinator($compound)) {
7280
+ if ($node !== $sub[$i]) {
7281
+ return false;
7282
+ }
7283
+
7284
+ $nextMustMatch = true;
7285
+ $i++;
7286
+ } else {
7287
+ while ($i < \count($sub) && ! $this->isSuperPart($node, $sub[$i])) {
7288
+ if ($nextMustMatch) {
7289
+ return false;
7290
+ }
7291
+
7292
+ $i++;
7293
+ }
7294
+
7295
+ if ($i >= \count($sub)) {
7296
+ return false;
7297
+ }
7298
+
7299
+ $nextMustMatch = false;
7300
+ $i++;
7301
+ }
7302
+ }
7303
+
7304
+ return true;
7305
+ }
7306
+
7307
+ /**
7308
+ * Test a part of super selector again a part of sub selector
7309
+ *
7310
+ * @param array $superParts
7311
+ * @param array $subParts
7312
+ *
7313
+ * @return boolean
7314
+ */
7315
+ protected function isSuperPart($superParts, $subParts)
7316
+ {
7317
+ $i = 0;
7318
+
7319
+ foreach ($superParts as $superPart) {
7320
+ while ($i < \count($subParts) && $subParts[$i] !== $superPart) {
7321
+ $i++;
7322
+ }
7323
+
7324
+ if ($i >= \count($subParts)) {
7325
+ return false;
7326
+ }
7327
+
7328
+ $i++;
7329
+ }
7330
+
7331
+ return true;
7332
+ }
7333
+
7334
+ protected static $libSelectorAppend = ['selector...'];
7335
+ protected function libSelectorAppend($args)
7336
+ {
7337
+ // get the selector... list
7338
+ $args = reset($args);
7339
+ $args = $args[2];
7340
+
7341
+ if (\count($args) < 1) {
7342
+ $this->throwError("selector-append() needs at least 1 argument");
7343
+ }
7344
+
7345
+ $selectors = array_map([$this, 'getSelectorArg'], $args);
7346
+
7347
+ return $this->formatOutputSelector($this->selectorAppend($selectors));
7348
+ }
7349
+
7350
+ /**
7351
+ * Append parts of the last selector in the list to the previous, recursively
7352
+ *
7353
+ * @param array $selectors
7354
+ *
7355
+ * @return array
7356
+ *
7357
+ * @throws \ScssPhp\ScssPhp\Exception\CompilerException
7358
+ */
7359
+ protected function selectorAppend($selectors)
7360
+ {
7361
+ $lastSelectors = array_pop($selectors);
7362
+
7363
+ if (! $lastSelectors) {
7364
+ $this->throwError("Invalid selector list in selector-append()");
7365
+ }
7366
+
7367
+ while (\count($selectors)) {
7368
+ $previousSelectors = array_pop($selectors);
7369
+
7370
+ if (! $previousSelectors) {
7371
+ $this->throwError("Invalid selector list in selector-append()");
7372
+ }
7373
+
7374
+ // do the trick, happening $lastSelector to $previousSelector
7375
+ $appended = [];
7376
+
7377
+ foreach ($lastSelectors as $lastSelector) {
7378
+ $previous = $previousSelectors;
7379
+
7380
+ foreach ($lastSelector as $lastSelectorParts) {
7381
+ foreach ($lastSelectorParts as $lastSelectorPart) {
7382
+ foreach ($previous as $i => $previousSelector) {
7383
+ foreach ($previousSelector as $j => $previousSelectorParts) {
7384
+ $previous[$i][$j][] = $lastSelectorPart;
7385
+ }
7386
+ }
7387
+ }
7388
+ }
7389
+
7390
+ foreach ($previous as $ps) {
7391
+ $appended[] = $ps;
7392
+ }
7393
+ }
7394
+
7395
+ $lastSelectors = $appended;
7396
+ }
7397
+
7398
+ return $lastSelectors;
7399
+ }
7400
+
7401
+ protected static $libSelectorExtend = ['selectors', 'extendee', 'extender'];
7402
+ protected function libSelectorExtend($args)
7403
+ {
7404
+ list($selectors, $extendee, $extender) = $args;
7405
+
7406
+ $selectors = $this->getSelectorArg($selectors);
7407
+ $extendee = $this->getSelectorArg($extendee);
7408
+ $extender = $this->getSelectorArg($extender);
7409
+
7410
+ if (! $selectors || ! $extendee || ! $extender) {
7411
+ $this->throwError("selector-extend() invalid arguments");
7412
+ }
7413
+
7414
+ $extended = $this->extendOrReplaceSelectors($selectors, $extendee, $extender);
7415
+
7416
+ return $this->formatOutputSelector($extended);
7417
+ }
7418
+
7419
+ protected static $libSelectorReplace = ['selectors', 'original', 'replacement'];
7420
+ protected function libSelectorReplace($args)
7421
+ {
7422
+ list($selectors, $original, $replacement) = $args;
7423
+
7424
+ $selectors = $this->getSelectorArg($selectors);
7425
+ $original = $this->getSelectorArg($original);
7426
+ $replacement = $this->getSelectorArg($replacement);
7427
+
7428
+ if (! $selectors || ! $original || ! $replacement) {
7429
+ $this->throwError("selector-replace() invalid arguments");
7430
+ }
7431
+
7432
+ $replaced = $this->extendOrReplaceSelectors($selectors, $original, $replacement, true);
7433
+
7434
+ return $this->formatOutputSelector($replaced);
7435
+ }
7436
+
7437
+ /**
7438
+ * Extend/replace in selectors
7439
+ * used by selector-extend and selector-replace that use the same logic
7440
+ *
7441
+ * @param array $selectors
7442
+ * @param array $extendee
7443
+ * @param array $extender
7444
+ * @param boolean $replace
7445
+ *
7446
+ * @return array
7447
+ */
7448
+ protected function extendOrReplaceSelectors($selectors, $extendee, $extender, $replace = false)
7449
+ {
7450
+ $saveExtends = $this->extends;
7451
+ $saveExtendsMap = $this->extendsMap;
7452
+
7453
+ $this->extends = [];
7454
+ $this->extendsMap = [];
7455
+
7456
+ foreach ($extendee as $es) {
7457
+ // only use the first one
7458
+ $this->pushExtends(reset($es), $extender, null);
7459
+ }
7460
+
7461
+ $extended = [];
7462
+
7463
+ foreach ($selectors as $selector) {
7464
+ if (! $replace) {
7465
+ $extended[] = $selector;
7466
+ }
7467
+
7468
+ $n = \count($extended);
7469
+
7470
+ $this->matchExtends($selector, $extended);
7471
+
7472
+ // if didnt match, keep the original selector if we are in a replace operation
7473
+ if ($replace and \count($extended) === $n) {
7474
+ $extended[] = $selector;
7475
+ }
7476
+ }
7477
+
7478
+ $this->extends = $saveExtends;
7479
+ $this->extendsMap = $saveExtendsMap;
7480
+
7481
+ return $extended;
7482
+ }
7483
+
7484
+ protected static $libSelectorNest = ['selector...'];
7485
+ protected function libSelectorNest($args)
7486
+ {
7487
+ // get the selector... list
7488
+ $args = reset($args);
7489
+ $args = $args[2];
7490
+
7491
+ if (\count($args) < 1) {
7492
+ $this->throwError("selector-nest() needs at least 1 argument");
7493
+ }
7494
+
7495
+ $selectorsMap = array_map([$this, 'getSelectorArg'], $args);
7496
+ $envs = [];
7497
+
7498
+ foreach ($selectorsMap as $selectors) {
7499
+ $env = new Environment();
7500
+ $env->selectors = $selectors;
7501
+
7502
+ $envs[] = $env;
7503
+ }
7504
+
7505
+ $envs = array_reverse($envs);
7506
+ $env = $this->extractEnv($envs);
7507
+ $outputSelectors = $this->multiplySelectors($env);
7508
+
7509
+ return $this->formatOutputSelector($outputSelectors);
7510
+ }
7511
+
7512
+ protected static $libSelectorParse = ['selectors'];
7513
+ protected function libSelectorParse($args)
7514
+ {
7515
+ $selectors = reset($args);
7516
+ $selectors = $this->getSelectorArg($selectors);
7517
+
7518
+ return $this->formatOutputSelector($selectors);
7519
+ }
7520
+
7521
+ protected static $libSelectorUnify = ['selectors1', 'selectors2'];
7522
+ protected function libSelectorUnify($args)
7523
+ {
7524
+ list($selectors1, $selectors2) = $args;
7525
+
7526
+ $selectors1 = $this->getSelectorArg($selectors1);
7527
+ $selectors2 = $this->getSelectorArg($selectors2);
7528
+
7529
+ if (! $selectors1 || ! $selectors2) {
7530
+ $this->throwError("selector-unify() invalid arguments");
7531
+ }
7532
+
7533
+ // only consider the first compound of each
7534
+ $compound1 = reset($selectors1);
7535
+ $compound2 = reset($selectors2);
7536
+
7537
+ // unify them and that's it
7538
+ $unified = $this->unifyCompoundSelectors($compound1, $compound2);
7539
+
7540
+ return $this->formatOutputSelector($unified);
7541
+ }
7542
+
7543
+ /**
7544
+ * The selector-unify magic as its best
7545
+ * (at least works as expected on test cases)
7546
+ *
7547
+ * @param array $compound1
7548
+ * @param array $compound2
7549
+ *
7550
+ * @return array|mixed
7551
+ */
7552
+ protected function unifyCompoundSelectors($compound1, $compound2)
7553
+ {
7554
+ if (! \count($compound1)) {
7555
+ return $compound2;
7556
+ }
7557
+
7558
+ if (! \count($compound2)) {
7559
+ return $compound1;
7560
+ }
7561
+
7562
+ // check that last part are compatible
7563
+ $lastPart1 = array_pop($compound1);
7564
+ $lastPart2 = array_pop($compound2);
7565
+ $last = $this->mergeParts($lastPart1, $lastPart2);
7566
+
7567
+ if (! $last) {
7568
+ return [[]];
7569
+ }
7570
+
7571
+ $unifiedCompound = [$last];
7572
+ $unifiedSelectors = [$unifiedCompound];
7573
+
7574
+ // do the rest
7575
+ while (\count($compound1) || \count($compound2)) {
7576
+ $part1 = end($compound1);
7577
+ $part2 = end($compound2);
7578
+
7579
+ if ($part1 && ($match2 = $this->matchPartInCompound($part1, $compound2))) {
7580
+ list($compound2, $part2, $after2) = $match2;
7581
+
7582
+ if ($after2) {
7583
+ $unifiedSelectors = $this->prependSelectors($unifiedSelectors, $after2);
7584
+ }
7585
+
7586
+ $c = $this->mergeParts($part1, $part2);
7587
+ $unifiedSelectors = $this->prependSelectors($unifiedSelectors, [$c]);
7588
+
7589
+ $part1 = $part2 = null;
7590
+
7591
+ array_pop($compound1);
7592
+ }
7593
+
7594
+ if ($part2 && ($match1 = $this->matchPartInCompound($part2, $compound1))) {
7595
+ list($compound1, $part1, $after1) = $match1;
7596
+
7597
+ if ($after1) {
7598
+ $unifiedSelectors = $this->prependSelectors($unifiedSelectors, $after1);
7599
+ }
7600
+
7601
+ $c = $this->mergeParts($part2, $part1);
7602
+ $unifiedSelectors = $this->prependSelectors($unifiedSelectors, [$c]);
7603
+
7604
+ $part1 = $part2 = null;
7605
+
7606
+ array_pop($compound2);
7607
+ }
7608
+
7609
+ $new = [];
7610
+
7611
+ if ($part1 && $part2) {
7612
+ array_pop($compound1);
7613
+ array_pop($compound2);
7614
+
7615
+ $s = $this->prependSelectors($unifiedSelectors, [$part2]);
7616
+ $new = array_merge($new, $this->prependSelectors($s, [$part1]));
7617
+ $s = $this->prependSelectors($unifiedSelectors, [$part1]);
7618
+ $new = array_merge($new, $this->prependSelectors($s, [$part2]));
7619
+ } elseif ($part1) {
7620
+ array_pop($compound1);
7621
+
7622
+ $new = array_merge($new, $this->prependSelectors($unifiedSelectors, [$part1]));
7623
+ } elseif ($part2) {
7624
+ array_pop($compound2);
7625
+
7626
+ $new = array_merge($new, $this->prependSelectors($unifiedSelectors, [$part2]));
7627
+ }
7628
+
7629
+ if ($new) {
7630
+ $unifiedSelectors = $new;
7631
+ }
7632
+ }
7633
+
7634
+ return $unifiedSelectors;
7635
+ }
7636
+
7637
+ /**
7638
+ * Prepend each selector from $selectors with $parts
7639
+ *
7640
+ * @param array $selectors
7641
+ * @param array $parts
7642
+ *
7643
+ * @return array
7644
+ */
7645
+ protected function prependSelectors($selectors, $parts)
7646
+ {
7647
+ $new = [];
7648
+
7649
+ foreach ($selectors as $compoundSelector) {
7650
+ array_unshift($compoundSelector, $parts);
7651
+
7652
+ $new[] = $compoundSelector;
7653
+ }
7654
+
7655
+ return $new;
7656
+ }
7657
+
7658
+ /**
7659
+ * Try to find a matching part in a compound:
7660
+ * - with same html tag name
7661
+ * - with some class or id or something in common
7662
+ *
7663
+ * @param array $part
7664
+ * @param array $compound
7665
+ *
7666
+ * @return array|boolean
7667
+ */
7668
+ protected function matchPartInCompound($part, $compound)
7669
+ {
7670
+ $partTag = $this->findTagName($part);
7671
+ $before = $compound;
7672
+ $after = [];
7673
+
7674
+ // try to find a match by tag name first
7675
+ while (\count($before)) {
7676
+ $p = array_pop($before);
7677
+
7678
+ if ($partTag && $partTag !== '*' && $partTag == $this->findTagName($p)) {
7679
+ return [$before, $p, $after];
7680
+ }
7681
+
7682
+ $after[] = $p;
7683
+ }
7684
+
7685
+ // try again matching a non empty intersection and a compatible tagname
7686
+ $before = $compound;
7687
+ $after = [];
7688
+
7689
+ while (\count($before)) {
7690
+ $p = array_pop($before);
7691
+
7692
+ if ($this->checkCompatibleTags($partTag, $this->findTagName($p))) {
7693
+ if (\count(array_intersect($part, $p))) {
7694
+ return [$before, $p, $after];
7695
+ }
7696
+ }
7697
+
7698
+ $after[] = $p;
7699
+ }
7700
+
7701
+ return false;
7702
+ }
7703
+
7704
+ /**
7705
+ * Merge two part list taking care that
7706
+ * - the html tag is coming first - if any
7707
+ * - the :something are coming last
7708
+ *
7709
+ * @param array $parts1
7710
+ * @param array $parts2
7711
+ *
7712
+ * @return array
7713
+ */
7714
+ protected function mergeParts($parts1, $parts2)
7715
+ {
7716
+ $tag1 = $this->findTagName($parts1);
7717
+ $tag2 = $this->findTagName($parts2);
7718
+ $tag = $this->checkCompatibleTags($tag1, $tag2);
7719
+
7720
+ // not compatible tags
7721
+ if ($tag === false) {
7722
+ return [];
7723
+ }
7724
+
7725
+ if ($tag) {
7726
+ if ($tag1) {
7727
+ $parts1 = array_diff($parts1, [$tag1]);
7728
+ }
7729
+
7730
+ if ($tag2) {
7731
+ $parts2 = array_diff($parts2, [$tag2]);
7732
+ }
7733
+ }
7734
+
7735
+ $mergedParts = array_merge($parts1, $parts2);
7736
+ $mergedOrderedParts = [];
7737
+
7738
+ foreach ($mergedParts as $part) {
7739
+ if (strpos($part, ':') === 0) {
7740
+ $mergedOrderedParts[] = $part;
7741
+ }
7742
+ }
7743
+
7744
+ $mergedParts = array_diff($mergedParts, $mergedOrderedParts);
7745
+ $mergedParts = array_merge($mergedParts, $mergedOrderedParts);
7746
+
7747
+ if ($tag) {
7748
+ array_unshift($mergedParts, $tag);
7749
+ }
7750
+
7751
+ return $mergedParts;
7752
+ }
7753
+
7754
+ /**
7755
+ * Check the compatibility between two tag names:
7756
+ * if both are defined they should be identical or one has to be '*'
7757
+ *
7758
+ * @param string $tag1
7759
+ * @param string $tag2
7760
+ *
7761
+ * @return array|boolean
7762
+ */
7763
+ protected function checkCompatibleTags($tag1, $tag2)
7764
+ {
7765
+ $tags = [$tag1, $tag2];
7766
+ $tags = array_unique($tags);
7767
+ $tags = array_filter($tags);
7768
+
7769
+ if (\count($tags) > 1) {
7770
+ $tags = array_diff($tags, ['*']);
7771
+ }
7772
+
7773
+ // not compatible nodes
7774
+ if (\count($tags) > 1) {
7775
+ return false;
7776
+ }
7777
+
7778
+ return $tags;
7779
+ }
7780
+
7781
+ /**
7782
+ * Find the html tag name in a selector parts list
7783
+ *
7784
+ * @param array $parts
7785
+ *
7786
+ * @return mixed|string
7787
+ */
7788
+ protected function findTagName($parts)
7789
+ {
7790
+ foreach ($parts as $part) {
7791
+ if (! preg_match('/^[\[.:#%_-]/', $part)) {
7792
+ return $part;
7793
+ }
7794
+ }
7795
+
7796
+ return '';
7797
+ }
7798
+
7799
+ protected static $libSimpleSelectors = ['selector'];
7800
+ protected function libSimpleSelectors($args)
7801
+ {
7802
+ $selector = reset($args);
7803
+ $selector = $this->getSelectorArg($selector);
7804
+
7805
+ // remove selectors list layer, keeping the first one
7806
+ $selector = reset($selector);
7807
+
7808
+ // remove parts list layer, keeping the first part
7809
+ $part = reset($selector);
7810
+
7811
+ $listParts = [];
7812
+
7813
+ foreach ($part as $p) {
7814
+ $listParts[] = [Type::T_STRING, '', [$p]];
7815
+ }
7816
+
7817
+ return [Type::T_LIST, ',', $listParts];
7818
+ }
7819
+
7820
+ protected static $libScssphpGlob = ['pattern'];
7821
+ protected function libScssphpGlob($args)
7822
+ {
7823
+ $string = $this->coerceString($args[0]);
7824
+ $pattern = $this->compileStringContent($string);
7825
+ $matches = glob($pattern);
7826
+ $listParts = [];
7827
+
7828
+ foreach ($matches as $match) {
7829
+ if (! is_file($match)) {
7830
+ continue;
7831
+ }
7832
+
7833
+ $listParts[] = [Type::T_STRING, '"', [$match]];
7834
+ }
7835
+
7836
+ return [Type::T_LIST, ',', $listParts];
7837
+ }
7838
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Compiler/Environment.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Compiler;
13
+
14
+ /**
15
+ * Compiler environment
16
+ *
17
+ * @author Anthon Pang <anthon.pang@gmail.com>
18
+ */
19
+ class Environment
20
+ {
21
+ /**
22
+ * @var \ScssPhp\ScssPhp\Block
23
+ */
24
+ public $block;
25
+
26
+ /**
27
+ * @var \ScssPhp\ScssPhp\Compiler\Environment
28
+ */
29
+ public $parent;
30
+
31
+ /**
32
+ * @var array
33
+ */
34
+ public $store;
35
+
36
+ /**
37
+ * @var array
38
+ */
39
+ public $storeUnreduced;
40
+
41
+ /**
42
+ * @var integer
43
+ */
44
+ public $depth;
45
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Exception/CompilerException.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Exception;
13
+
14
+ /**
15
+ * Compiler exception
16
+ *
17
+ * @author Oleksandr Savchenko <traveltino@gmail.com>
18
+ */
19
+ class CompilerException extends \Exception
20
+ {
21
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Exception/ParserException.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Exception;
13
+
14
+ /**
15
+ * Parser Exception
16
+ *
17
+ * @author Oleksandr Savchenko <traveltino@gmail.com>
18
+ */
19
+ class ParserException extends \Exception
20
+ {
21
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Exception/RangeException.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Exception;
13
+
14
+ /**
15
+ * Range exception
16
+ *
17
+ * @author Anthon Pang <anthon.pang@gmail.com>
18
+ */
19
+ class RangeException extends \Exception
20
+ {
21
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Exception/ServerException.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Exception;
13
+
14
+ /**
15
+ * Server Exception
16
+ *
17
+ * @author Anthon Pang <anthon.pang@gmail.com>
18
+ */
19
+ class ServerException extends \Exception
20
+ {
21
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter.php ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp;
13
+
14
+ use ScssPhp\ScssPhp\Formatter\OutputBlock;
15
+ use ScssPhp\ScssPhp\SourceMap\SourceMapGenerator;
16
+
17
+ /**
18
+ * Base formatter
19
+ *
20
+ * @author Leaf Corcoran <leafot@gmail.com>
21
+ */
22
+ abstract class Formatter
23
+ {
24
+ /**
25
+ * @var integer
26
+ */
27
+ public $indentLevel;
28
+
29
+ /**
30
+ * @var string
31
+ */
32
+ public $indentChar;
33
+
34
+ /**
35
+ * @var string
36
+ */
37
+ public $break;
38
+
39
+ /**
40
+ * @var string
41
+ */
42
+ public $open;
43
+
44
+ /**
45
+ * @var string
46
+ */
47
+ public $close;
48
+
49
+ /**
50
+ * @var string
51
+ */
52
+ public $tagSeparator;
53
+
54
+ /**
55
+ * @var string
56
+ */
57
+ public $assignSeparator;
58
+
59
+ /**
60
+ * @var boolean
61
+ */
62
+ public $keepSemicolons;
63
+
64
+ /**
65
+ * @var \ScssPhp\ScssPhp\Formatter\OutputBlock
66
+ */
67
+ protected $currentBlock;
68
+
69
+ /**
70
+ * @var integer
71
+ */
72
+ protected $currentLine;
73
+
74
+ /**
75
+ * @var integer
76
+ */
77
+ protected $currentColumn;
78
+
79
+ /**
80
+ * @var \ScssPhp\ScssPhp\SourceMap\SourceMapGenerator
81
+ */
82
+ protected $sourceMapGenerator;
83
+
84
+ /**
85
+ * @var string
86
+ */
87
+ protected $strippedSemicolon;
88
+
89
+ /**
90
+ * Initialize formatter
91
+ *
92
+ * @api
93
+ */
94
+ abstract public function __construct();
95
+
96
+ /**
97
+ * Return indentation (whitespace)
98
+ *
99
+ * @return string
100
+ */
101
+ protected function indentStr()
102
+ {
103
+ return '';
104
+ }
105
+
106
+ /**
107
+ * Return property assignment
108
+ *
109
+ * @api
110
+ *
111
+ * @param string $name
112
+ * @param mixed $value
113
+ *
114
+ * @return string
115
+ */
116
+ public function property($name, $value)
117
+ {
118
+ return rtrim($name) . $this->assignSeparator . $value . ';';
119
+ }
120
+
121
+ /**
122
+ * Return custom property assignment
123
+ * differs in that you have to keep spaces in the value as is
124
+ *
125
+ * @api
126
+ *
127
+ * @param string $name
128
+ * @param mixed $value
129
+ *
130
+ * @return string
131
+ */
132
+ public function customProperty($name, $value)
133
+ {
134
+ return rtrim($name) . trim($this->assignSeparator) . $value . ';';
135
+ }
136
+
137
+ /**
138
+ * Output lines inside a block
139
+ *
140
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
141
+ */
142
+ protected function blockLines(OutputBlock $block)
143
+ {
144
+ $inner = $this->indentStr();
145
+ $glue = $this->break . $inner;
146
+
147
+ $this->write($inner . implode($glue, $block->lines));
148
+
149
+ if (! empty($block->children)) {
150
+ $this->write($this->break);
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Output block selectors
156
+ *
157
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
158
+ */
159
+ protected function blockSelectors(OutputBlock $block)
160
+ {
161
+ $inner = $this->indentStr();
162
+
163
+ $this->write($inner
164
+ . implode($this->tagSeparator, $block->selectors)
165
+ . $this->open . $this->break);
166
+ }
167
+
168
+ /**
169
+ * Output block children
170
+ *
171
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
172
+ */
173
+ protected function blockChildren(OutputBlock $block)
174
+ {
175
+ foreach ($block->children as $child) {
176
+ $this->block($child);
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Output non-empty block
182
+ *
183
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
184
+ */
185
+ protected function block(OutputBlock $block)
186
+ {
187
+ if (empty($block->lines) && empty($block->children)) {
188
+ return;
189
+ }
190
+
191
+ $this->currentBlock = $block;
192
+
193
+ $pre = $this->indentStr();
194
+
195
+ if (! empty($block->selectors)) {
196
+ $this->blockSelectors($block);
197
+
198
+ $this->indentLevel++;
199
+ }
200
+
201
+ if (! empty($block->lines)) {
202
+ $this->blockLines($block);
203
+ }
204
+
205
+ if (! empty($block->children)) {
206
+ $this->blockChildren($block);
207
+ }
208
+
209
+ if (! empty($block->selectors)) {
210
+ $this->indentLevel--;
211
+
212
+ if (! $this->keepSemicolons) {
213
+ $this->strippedSemicolon = '';
214
+ }
215
+
216
+ if (empty($block->children)) {
217
+ $this->write($this->break);
218
+ }
219
+
220
+ $this->write($pre . $this->close . $this->break);
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Test and clean safely empty children
226
+ *
227
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
228
+ *
229
+ * @return boolean
230
+ */
231
+ protected function testEmptyChildren($block)
232
+ {
233
+ $isEmpty = empty($block->lines);
234
+
235
+ if ($block->children) {
236
+ foreach ($block->children as $k => &$child) {
237
+ if (! $this->testEmptyChildren($child)) {
238
+ $isEmpty = false;
239
+ continue;
240
+ }
241
+
242
+ if ($child->type === Type::T_MEDIA || $child->type === Type::T_DIRECTIVE) {
243
+ $child->children = [];
244
+ $child->selectors = null;
245
+ }
246
+ }
247
+ }
248
+
249
+ return $isEmpty;
250
+ }
251
+
252
+ /**
253
+ * Entry point to formatting a block
254
+ *
255
+ * @api
256
+ *
257
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block An abstract syntax tree
258
+ * @param \ScssPhp\ScssPhp\SourceMap\SourceMapGenerator|null $sourceMapGenerator Optional source map generator
259
+ *
260
+ * @return string
261
+ */
262
+ public function format(OutputBlock $block, SourceMapGenerator $sourceMapGenerator = null)
263
+ {
264
+ $this->sourceMapGenerator = null;
265
+
266
+ if ($sourceMapGenerator) {
267
+ $this->currentLine = 1;
268
+ $this->currentColumn = 0;
269
+ $this->sourceMapGenerator = $sourceMapGenerator;
270
+ }
271
+
272
+ $this->testEmptyChildren($block);
273
+
274
+ ob_start();
275
+
276
+ $this->block($block);
277
+
278
+ $out = ob_get_clean();
279
+
280
+ return $out;
281
+ }
282
+
283
+ /**
284
+ * Output content
285
+ *
286
+ * @param string $str
287
+ */
288
+ protected function write($str)
289
+ {
290
+ if (! empty($this->strippedSemicolon)) {
291
+ echo $this->strippedSemicolon;
292
+
293
+ $this->strippedSemicolon = '';
294
+ }
295
+
296
+ /*
297
+ * Maybe Strip semi-colon appended by property(); it's a separator, not a terminator
298
+ * will be striped for real before a closing, otherwise displayed unchanged starting the next write
299
+ */
300
+ if (! $this->keepSemicolons &&
301
+ $str &&
302
+ (strpos($str, ';') !== false) &&
303
+ (substr($str, -1) === ';')
304
+ ) {
305
+ $str = substr($str, 0, -1);
306
+
307
+ $this->strippedSemicolon = ';';
308
+ }
309
+
310
+ if ($this->sourceMapGenerator) {
311
+ $this->sourceMapGenerator->addMapping(
312
+ $this->currentLine,
313
+ $this->currentColumn,
314
+ $this->currentBlock->sourceLine,
315
+ //columns from parser are off by one
316
+ $this->currentBlock->sourceColumn > 0 ? $this->currentBlock->sourceColumn - 1 : 0,
317
+ $this->currentBlock->sourceName
318
+ );
319
+
320
+ $lines = explode("\n", $str);
321
+ $lineCount = \count($lines);
322
+ $this->currentLine += $lineCount-1;
323
+
324
+ $lastLine = array_pop($lines);
325
+
326
+ $this->currentColumn = ($lineCount === 1 ? $this->currentColumn : 0) + \strlen($lastLine);
327
+ }
328
+
329
+ echo $str;
330
+ }
331
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/Compact.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Formatter;
13
+
14
+ use ScssPhp\ScssPhp\Formatter;
15
+
16
+ /**
17
+ * Compact formatter
18
+ *
19
+ * @author Leaf Corcoran <leafot@gmail.com>
20
+ */
21
+ class Compact extends Formatter
22
+ {
23
+ /**
24
+ * {@inheritdoc}
25
+ */
26
+ public function __construct()
27
+ {
28
+ $this->indentLevel = 0;
29
+ $this->indentChar = '';
30
+ $this->break = '';
31
+ $this->open = ' {';
32
+ $this->close = "}\n\n";
33
+ $this->tagSeparator = ',';
34
+ $this->assignSeparator = ':';
35
+ $this->keepSemicolons = true;
36
+ }
37
+
38
+ /**
39
+ * {@inheritdoc}
40
+ */
41
+ public function indentStr()
42
+ {
43
+ return ' ';
44
+ }
45
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/Compressed.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Formatter;
13
+
14
+ use ScssPhp\ScssPhp\Formatter;
15
+ use ScssPhp\ScssPhp\Formatter\OutputBlock;
16
+
17
+ /**
18
+ * Compressed formatter
19
+ *
20
+ * @author Leaf Corcoran <leafot@gmail.com>
21
+ */
22
+ class Compressed extends Formatter
23
+ {
24
+ /**
25
+ * {@inheritdoc}
26
+ */
27
+ public function __construct()
28
+ {
29
+ $this->indentLevel = 0;
30
+ $this->indentChar = ' ';
31
+ $this->break = '';
32
+ $this->open = '{';
33
+ $this->close = '}';
34
+ $this->tagSeparator = ',';
35
+ $this->assignSeparator = ':';
36
+ $this->keepSemicolons = false;
37
+ }
38
+
39
+ /**
40
+ * {@inheritdoc}
41
+ */
42
+ public function blockLines(OutputBlock $block)
43
+ {
44
+ $inner = $this->indentStr();
45
+
46
+ $glue = $this->break . $inner;
47
+
48
+ foreach ($block->lines as $index => $line) {
49
+ if (substr($line, 0, 2) === '/*' && substr($line, 2, 1) !== '!') {
50
+ unset($block->lines[$index]);
51
+ } elseif (substr($line, 0, 3) === '/*!') {
52
+ $block->lines[$index] = '/*' . substr($line, 3);
53
+ }
54
+ }
55
+
56
+ $this->write($inner . implode($glue, $block->lines));
57
+
58
+ if (! empty($block->children)) {
59
+ $this->write($this->break);
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Output block selectors
65
+ *
66
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
67
+ */
68
+ protected function blockSelectors(OutputBlock $block)
69
+ {
70
+ $inner = $this->indentStr();
71
+
72
+ $this->write(
73
+ $inner
74
+ . implode(
75
+ $this->tagSeparator,
76
+ str_replace([' > ', ' + ', ' ~ '], ['>', '+', '~'], $block->selectors)
77
+ )
78
+ . $this->open . $this->break
79
+ );
80
+ }
81
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/Crunched.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Formatter;
13
+
14
+ use ScssPhp\ScssPhp\Formatter;
15
+ use ScssPhp\ScssPhp\Formatter\OutputBlock;
16
+
17
+ /**
18
+ * Crunched formatter
19
+ *
20
+ * @author Anthon Pang <anthon.pang@gmail.com>
21
+ */
22
+ class Crunched extends Formatter
23
+ {
24
+ /**
25
+ * {@inheritdoc}
26
+ */
27
+ public function __construct()
28
+ {
29
+ $this->indentLevel = 0;
30
+ $this->indentChar = ' ';
31
+ $this->break = '';
32
+ $this->open = '{';
33
+ $this->close = '}';
34
+ $this->tagSeparator = ',';
35
+ $this->assignSeparator = ':';
36
+ $this->keepSemicolons = false;
37
+ }
38
+
39
+ /**
40
+ * {@inheritdoc}
41
+ */
42
+ public function blockLines(OutputBlock $block)
43
+ {
44
+ $inner = $this->indentStr();
45
+
46
+ $glue = $this->break . $inner;
47
+
48
+ foreach ($block->lines as $index => $line) {
49
+ if (substr($line, 0, 2) === '/*') {
50
+ unset($block->lines[$index]);
51
+ }
52
+ }
53
+
54
+ $this->write($inner . implode($glue, $block->lines));
55
+
56
+ if (! empty($block->children)) {
57
+ $this->write($this->break);
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Output block selectors
63
+ *
64
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
65
+ */
66
+ protected function blockSelectors(OutputBlock $block)
67
+ {
68
+ $inner = $this->indentStr();
69
+
70
+ $this->write(
71
+ $inner
72
+ . implode(
73
+ $this->tagSeparator,
74
+ str_replace([' > ', ' + ', ' ~ '], ['>', '+', '~'], $block->selectors)
75
+ )
76
+ . $this->open . $this->break
77
+ );
78
+ }
79
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/Debug.php ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Formatter;
13
+
14
+ use ScssPhp\ScssPhp\Formatter;
15
+ use ScssPhp\ScssPhp\Formatter\OutputBlock;
16
+
17
+ /**
18
+ * Debug formatter
19
+ *
20
+ * @author Anthon Pang <anthon.pang@gmail.com>
21
+ */
22
+ class Debug extends Formatter
23
+ {
24
+ /**
25
+ * {@inheritdoc}
26
+ */
27
+ public function __construct()
28
+ {
29
+ $this->indentLevel = 0;
30
+ $this->indentChar = '';
31
+ $this->break = "\n";
32
+ $this->open = ' {';
33
+ $this->close = ' }';
34
+ $this->tagSeparator = ', ';
35
+ $this->assignSeparator = ': ';
36
+ $this->keepSemicolons = true;
37
+ }
38
+
39
+ /**
40
+ * {@inheritdoc}
41
+ */
42
+ protected function indentStr()
43
+ {
44
+ return str_repeat(' ', $this->indentLevel);
45
+ }
46
+
47
+ /**
48
+ * {@inheritdoc}
49
+ */
50
+ protected function blockLines(OutputBlock $block)
51
+ {
52
+ $indent = $this->indentStr();
53
+
54
+ if (empty($block->lines)) {
55
+ $this->write("{$indent}block->lines: []\n");
56
+
57
+ return;
58
+ }
59
+
60
+ foreach ($block->lines as $index => $line) {
61
+ $this->write("{$indent}block->lines[{$index}]: $line\n");
62
+ }
63
+ }
64
+
65
+ /**
66
+ * {@inheritdoc}
67
+ */
68
+ protected function blockSelectors(OutputBlock $block)
69
+ {
70
+ $indent = $this->indentStr();
71
+
72
+ if (empty($block->selectors)) {
73
+ $this->write("{$indent}block->selectors: []\n");
74
+
75
+ return;
76
+ }
77
+
78
+ foreach ($block->selectors as $index => $selector) {
79
+ $this->write("{$indent}block->selectors[{$index}]: $selector\n");
80
+ }
81
+ }
82
+
83
+ /**
84
+ * {@inheritdoc}
85
+ */
86
+ protected function blockChildren(OutputBlock $block)
87
+ {
88
+ $indent = $this->indentStr();
89
+
90
+ if (empty($block->children)) {
91
+ $this->write("{$indent}block->children: []\n");
92
+
93
+ return;
94
+ }
95
+
96
+ $this->indentLevel++;
97
+
98
+ foreach ($block->children as $i => $child) {
99
+ $this->block($child);
100
+ }
101
+
102
+ $this->indentLevel--;
103
+ }
104
+
105
+ /**
106
+ * {@inheritdoc}
107
+ */
108
+ protected function block(OutputBlock $block)
109
+ {
110
+ $indent = $this->indentStr();
111
+
112
+ $this->write("{$indent}block->type: {$block->type}\n" .
113
+ "{$indent}block->depth: {$block->depth}\n");
114
+
115
+ $this->currentBlock = $block;
116
+
117
+ $this->blockSelectors($block);
118
+ $this->blockLines($block);
119
+ $this->blockChildren($block);
120
+ }
121
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/Expanded.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Formatter;
13
+
14
+ use ScssPhp\ScssPhp\Formatter;
15
+ use ScssPhp\ScssPhp\Formatter\OutputBlock;
16
+
17
+ /**
18
+ * Expanded formatter
19
+ *
20
+ * @author Leaf Corcoran <leafot@gmail.com>
21
+ */
22
+ class Expanded extends Formatter
23
+ {
24
+ /**
25
+ * {@inheritdoc}
26
+ */
27
+ public function __construct()
28
+ {
29
+ $this->indentLevel = 0;
30
+ $this->indentChar = ' ';
31
+ $this->break = "\n";
32
+ $this->open = ' {';
33
+ $this->close = '}';
34
+ $this->tagSeparator = ', ';
35
+ $this->assignSeparator = ': ';
36
+ $this->keepSemicolons = true;
37
+ }
38
+
39
+ /**
40
+ * {@inheritdoc}
41
+ */
42
+ protected function indentStr()
43
+ {
44
+ return str_repeat($this->indentChar, $this->indentLevel);
45
+ }
46
+
47
+ /**
48
+ * {@inheritdoc}
49
+ */
50
+ protected function blockLines(OutputBlock $block)
51
+ {
52
+ $inner = $this->indentStr();
53
+
54
+ $glue = $this->break . $inner;
55
+
56
+ foreach ($block->lines as $index => $line) {
57
+ if (substr($line, 0, 2) === '/*') {
58
+ $block->lines[$index] = preg_replace('/[\r\n]+/', $glue, $line);
59
+ }
60
+ }
61
+
62
+ $this->write($inner . implode($glue, $block->lines));
63
+
64
+ if (empty($block->selectors) || ! empty($block->children)) {
65
+ $this->write($this->break);
66
+ }
67
+ }
68
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/Nested.php ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Formatter;
13
+
14
+ use ScssPhp\ScssPhp\Formatter;
15
+ use ScssPhp\ScssPhp\Formatter\OutputBlock;
16
+ use ScssPhp\ScssPhp\Type;
17
+
18
+ /**
19
+ * Nested formatter
20
+ *
21
+ * @author Leaf Corcoran <leafot@gmail.com>
22
+ */
23
+ class Nested extends Formatter
24
+ {
25
+ /**
26
+ * @var integer
27
+ */
28
+ private $depth;
29
+
30
+ /**
31
+ * {@inheritdoc}
32
+ */
33
+ public function __construct()
34
+ {
35
+ $this->indentLevel = 0;
36
+ $this->indentChar = ' ';
37
+ $this->break = "\n";
38
+ $this->open = ' {';
39
+ $this->close = ' }';
40
+ $this->tagSeparator = ', ';
41
+ $this->assignSeparator = ': ';
42
+ $this->keepSemicolons = true;
43
+ }
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ protected function indentStr()
49
+ {
50
+ $n = $this->depth - 1;
51
+
52
+ return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
53
+ }
54
+
55
+ /**
56
+ * {@inheritdoc}
57
+ */
58
+ protected function blockLines(OutputBlock $block)
59
+ {
60
+ $inner = $this->indentStr();
61
+ $glue = $this->break . $inner;
62
+
63
+ foreach ($block->lines as $index => $line) {
64
+ if (substr($line, 0, 2) === '/*') {
65
+ $block->lines[$index] = preg_replace('/[\r\n]+/', $glue, $line);
66
+ }
67
+ }
68
+
69
+ $this->write($inner . implode($glue, $block->lines));
70
+ }
71
+
72
+ /**
73
+ * {@inheritdoc}
74
+ */
75
+ protected function block(OutputBlock $block)
76
+ {
77
+ static $depths;
78
+ static $downLevel;
79
+ static $closeBlock;
80
+ static $previousEmpty;
81
+ static $previousHasSelector;
82
+
83
+ if ($block->type === 'root') {
84
+ $depths = [ 0 ];
85
+ $downLevel = '';
86
+ $closeBlock = '';
87
+ $this->depth = 0;
88
+ $previousEmpty = false;
89
+ $previousHasSelector = false;
90
+ }
91
+
92
+ $isMediaOrDirective = \in_array($block->type, [Type::T_DIRECTIVE, Type::T_MEDIA]);
93
+ $isSupport = ($block->type === Type::T_DIRECTIVE
94
+ && $block->selectors && strpos(implode('', $block->selectors), '@supports') !== false);
95
+
96
+ while ($block->depth < end($depths) || ($block->depth == 1 && end($depths) == 1)) {
97
+ array_pop($depths);
98
+ $this->depth--;
99
+
100
+ if (! $this->depth && ($block->depth <= 1 || (! $this->indentLevel && $block->type === Type::T_COMMENT)) &&
101
+ (($block->selectors && ! $isMediaOrDirective) || $previousHasSelector)
102
+ ) {
103
+ $downLevel = $this->break;
104
+ }
105
+
106
+ if (empty($block->lines) && empty($block->children)) {
107
+ $previousEmpty = true;
108
+ }
109
+ }
110
+
111
+ if (empty($block->lines) && empty($block->children)) {
112
+ return;
113
+ }
114
+
115
+ $this->currentBlock = $block;
116
+
117
+ if (! empty($block->lines) || (! empty($block->children) && ($this->depth < 1 || $isSupport))) {
118
+ if ($block->depth > end($depths)) {
119
+ if (! $previousEmpty || $this->depth < 1) {
120
+ $this->depth++;
121
+
122
+ $depths[] = $block->depth;
123
+ } else {
124
+ // keep the current depth unchanged but take the block depth as a new reference for following blocks
125
+ array_pop($depths);
126
+
127
+ $depths[] = $block->depth;
128
+ }
129
+ }
130
+ }
131
+
132
+ $previousEmpty = ($block->type === Type::T_COMMENT);
133
+ $previousHasSelector = false;
134
+
135
+ if (! empty($block->selectors)) {
136
+ if ($closeBlock) {
137
+ $this->write($closeBlock);
138
+ $closeBlock = '';
139
+ }
140
+
141
+ if ($downLevel) {
142
+ $this->write($downLevel);
143
+ $downLevel = '';
144
+ }
145
+
146
+ $this->blockSelectors($block);
147
+
148
+ $this->indentLevel++;
149
+ }
150
+
151
+ if (! empty($block->lines)) {
152
+ if ($closeBlock) {
153
+ $this->write($closeBlock);
154
+ $closeBlock = '';
155
+ }
156
+
157
+ if ($downLevel) {
158
+ $this->write($downLevel);
159
+ $downLevel = '';
160
+ }
161
+
162
+ $this->blockLines($block);
163
+
164
+ $closeBlock = $this->break;
165
+ }
166
+
167
+ if (! empty($block->children)) {
168
+ if ($this->depth > 0 && ($isMediaOrDirective || ! $this->hasFlatChild($block))) {
169
+ array_pop($depths);
170
+
171
+ $this->depth--;
172
+ $this->blockChildren($block);
173
+ $this->depth++;
174
+
175
+ $depths[] = $block->depth;
176
+ } else {
177
+ $this->blockChildren($block);
178
+ }
179
+ }
180
+
181
+ // reclear to not be spoiled by children if T_DIRECTIVE
182
+ if ($block->type === Type::T_DIRECTIVE) {
183
+ $previousHasSelector = false;
184
+ }
185
+
186
+ if (! empty($block->selectors)) {
187
+ $this->indentLevel--;
188
+
189
+ if (! $this->keepSemicolons) {
190
+ $this->strippedSemicolon = '';
191
+ }
192
+
193
+ $this->write($this->close);
194
+
195
+ $closeBlock = $this->break;
196
+
197
+ if ($this->depth > 1 && ! empty($block->children)) {
198
+ array_pop($depths);
199
+ $this->depth--;
200
+ }
201
+
202
+ if (! $isMediaOrDirective) {
203
+ $previousHasSelector = true;
204
+ }
205
+ }
206
+
207
+ if ($block->type === 'root') {
208
+ $this->write($this->break);
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Block has flat child
214
+ *
215
+ * @param \ScssPhp\ScssPhp\Formatter\OutputBlock $block
216
+ *
217
+ * @return boolean
218
+ */
219
+ private function hasFlatChild($block)
220
+ {
221
+ foreach ($block->children as $child) {
222
+ if (empty($child->selectors)) {
223
+ return true;
224
+ }
225
+ }
226
+
227
+ return false;
228
+ }
229
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Formatter/OutputBlock.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Formatter;
13
+
14
+ /**
15
+ * Output block
16
+ *
17
+ * @author Anthon Pang <anthon.pang@gmail.com>
18
+ */
19
+ class OutputBlock
20
+ {
21
+ /**
22
+ * @var string
23
+ */
24
+ public $type;
25
+
26
+ /**
27
+ * @var integer
28
+ */
29
+ public $depth;
30
+
31
+ /**
32
+ * @var array
33
+ */
34
+ public $selectors;
35
+
36
+ /**
37
+ * @var array
38
+ */
39
+ public $lines;
40
+
41
+ /**
42
+ * @var array
43
+ */
44
+ public $children;
45
+
46
+ /**
47
+ * @var \ScssPhp\ScssPhp\Formatter\OutputBlock
48
+ */
49
+ public $parent;
50
+
51
+ /**
52
+ * @var string
53
+ */
54
+ public $sourceName;
55
+
56
+ /**
57
+ * @var integer
58
+ */
59
+ public $sourceLine;
60
+
61
+ /**
62
+ * @var integer
63
+ */
64
+ public $sourceColumn;
65
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Node.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp;
13
+
14
+ /**
15
+ * Base node
16
+ *
17
+ * @author Anthon Pang <anthon.pang@gmail.com>
18
+ */
19
+ abstract class Node
20
+ {
21
+ /**
22
+ * @var string
23
+ */
24
+ public $type;
25
+
26
+ /**
27
+ * @var integer
28
+ */
29
+ public $sourceIndex;
30
+
31
+ /**
32
+ * @var integer
33
+ */
34
+ public $sourceLine;
35
+
36
+ /**
37
+ * @var integer
38
+ */
39
+ public $sourceColumn;
40
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Node/Number.php ADDED
@@ -0,0 +1,390 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\Node;
13
+
14
+ use ScssPhp\ScssPhp\Compiler;
15
+ use ScssPhp\ScssPhp\Node;
16
+ use ScssPhp\ScssPhp\Type;
17
+
18
+ /**
19
+ * Dimension + optional units
20
+ *
21
+ * {@internal
22
+ * This is a work-in-progress.
23
+ *
24
+ * The \ArrayAccess interface is temporary until the migration is complete.
25
+ * }}
26
+ *
27
+ * @author Anthon Pang <anthon.pang@gmail.com>
28
+ */
29
+ class Number extends Node implements \ArrayAccess
30
+ {
31
+ /**
32
+ * @var integer
33
+ */
34
+ public static $precision = 10;
35
+
36
+ /**
37
+ * @see http://www.w3.org/TR/2012/WD-css3-values-20120308/
38
+ *
39
+ * @var array
40
+ */
41
+ protected static $unitTable = [
42
+ 'in' => [
43
+ 'in' => 1,
44
+ 'pc' => 6,
45
+ 'pt' => 72,
46
+ 'px' => 96,
47
+ 'cm' => 2.54,
48
+ 'mm' => 25.4,
49
+ 'q' => 101.6,
50
+ ],
51
+ 'turn' => [
52
+ 'deg' => 360,
53
+ 'grad' => 400,
54
+ 'rad' => 6.28318530717958647692528676, // 2 * M_PI
55
+ 'turn' => 1,
56
+ ],
57
+ 's' => [
58
+ 's' => 1,
59
+ 'ms' => 1000,
60
+ ],
61
+ 'Hz' => [
62
+ 'Hz' => 1,
63
+ 'kHz' => 0.001,
64
+ ],
65
+ 'dpi' => [
66
+ 'dpi' => 1,
67
+ 'dpcm' => 1/2.54,
68
+ 'dppx' => 1/96,
69
+ ],
70
+ ];
71
+
72
+ /**
73
+ * @var integer|float
74
+ */
75
+ public $dimension;
76
+
77
+ /**
78
+ * @var array
79
+ */
80
+ public $units;
81
+
82
+ /**
83
+ * Initialize number
84
+ *
85
+ * @param mixed $dimension
86
+ * @param mixed $initialUnit
87
+ */
88
+ public function __construct($dimension, $initialUnit)
89
+ {
90
+ $this->type = Type::T_NUMBER;
91
+ $this->dimension = $dimension;
92
+ $this->units = \is_array($initialUnit)
93
+ ? $initialUnit
94
+ : ($initialUnit ? [$initialUnit => 1]
95
+ : []);
96
+ }
97
+
98
+ /**
99
+ * Coerce number to target units
100
+ *
101
+ * @param array $units
102
+ *
103
+ * @return \ScssPhp\ScssPhp\Node\Number
104
+ */
105
+ public function coerce($units)
106
+ {
107
+ if ($this->unitless()) {
108
+ return new Number($this->dimension, $units);
109
+ }
110
+
111
+ $dimension = $this->dimension;
112
+
113
+ if (\count($units)) {
114
+ $baseUnit = array_keys($units);
115
+ $baseUnit = reset($baseUnit);
116
+ $baseUnit = $this->findBaseUnit($baseUnit);
117
+ if ($baseUnit && isset(static::$unitTable[$baseUnit])) {
118
+ foreach (static::$unitTable[$baseUnit] as $unit => $conv) {
119
+ $from = isset($this->units[$unit]) ? $this->units[$unit] : 0;
120
+ $to = isset($units[$unit]) ? $units[$unit] : 0;
121
+ $factor = pow($conv, $from - $to);
122
+ $dimension /= $factor;
123
+ }
124
+ }
125
+ }
126
+
127
+ return new Number($dimension, $units);
128
+ }
129
+
130
+ /**
131
+ * Normalize number
132
+ *
133
+ * @return \ScssPhp\ScssPhp\Node\Number
134
+ */
135
+ public function normalize()
136
+ {
137
+ $dimension = $this->dimension;
138
+ $units = [];
139
+
140
+ $this->normalizeUnits($dimension, $units);
141
+
142
+ return new Number($dimension, $units);
143
+ }
144
+
145
+ /**
146
+ * {@inheritdoc}
147
+ */
148
+ public function offsetExists($offset)
149
+ {
150
+ if ($offset === -3) {
151
+ return ! \is_null($this->sourceColumn);
152
+ }
153
+
154
+ if ($offset === -2) {
155
+ return ! \is_null($this->sourceLine);
156
+ }
157
+
158
+ if ($offset === -1 ||
159
+ $offset === 0 ||
160
+ $offset === 1 ||
161
+ $offset === 2
162
+ ) {
163
+ return true;
164
+ }
165
+
166
+ return false;
167
+ }
168
+
169
+ /**
170
+ * {@inheritdoc}
171
+ */
172
+ public function offsetGet($offset)
173
+ {
174
+ switch ($offset) {
175
+ case -3:
176
+ return $this->sourceColumn;
177
+
178
+ case -2:
179
+ return $this->sourceLine;
180
+
181
+ case -1:
182
+ return $this->sourceIndex;
183
+
184
+ case 0:
185
+ return $this->type;
186
+
187
+ case 1:
188
+ return $this->dimension;
189
+
190
+ case 2:
191
+ return $this->units;
192
+ }
193
+ }
194
+
195
+ /**
196
+ * {@inheritdoc}
197
+ */
198
+ public function offsetSet($offset, $value)
199
+ {
200
+ if ($offset === 1) {
201
+ $this->dimension = $value;
202
+ } elseif ($offset === 2) {
203
+ $this->units = $value;
204
+ } elseif ($offset == -1) {
205
+ $this->sourceIndex = $value;
206
+ } elseif ($offset == -2) {
207
+ $this->sourceLine = $value;
208
+ } elseif ($offset == -3) {
209
+ $this->sourceColumn = $value;
210
+ }
211
+ }
212
+
213
+ /**
214
+ * {@inheritdoc}
215
+ */
216
+ public function offsetUnset($offset)
217
+ {
218
+ if ($offset === 1) {
219
+ $this->dimension = null;
220
+ } elseif ($offset === 2) {
221
+ $this->units = null;
222
+ } elseif ($offset === -1) {
223
+ $this->sourceIndex = null;
224
+ } elseif ($offset === -2) {
225
+ $this->sourceLine = null;
226
+ } elseif ($offset === -3) {
227
+ $this->sourceColumn = null;
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Returns true if the number is unitless
233
+ *
234
+ * @return boolean
235
+ */
236
+ public function unitless()
237
+ {
238
+ return ! array_sum($this->units);
239
+ }
240
+
241
+ /**
242
+ * Test if a number can be normalized in a base unit
243
+ * ie if its units are homogeneous
244
+ *
245
+ * @return boolean
246
+ */
247
+ public function isNormalizable()
248
+ {
249
+ if ($this->unitless()) {
250
+ return false;
251
+ }
252
+
253
+ $baseUnit = null;
254
+
255
+ foreach ($this->units as $unit => $exp) {
256
+ $b = $this->findBaseUnit($unit);
257
+
258
+ if (\is_null($baseUnit)) {
259
+ $baseUnit = $b;
260
+ }
261
+
262
+ if (\is_null($b) or $b !== $baseUnit) {
263
+ return false;
264
+ }
265
+ }
266
+
267
+ return $baseUnit;
268
+ }
269
+
270
+ /**
271
+ * Returns unit(s) as the product of numerator units divided by the product of denominator units
272
+ *
273
+ * @return string
274
+ */
275
+ public function unitStr()
276
+ {
277
+ $numerators = [];
278
+ $denominators = [];
279
+
280
+ foreach ($this->units as $unit => $unitSize) {
281
+ if ($unitSize > 0) {
282
+ $numerators = array_pad($numerators, \count($numerators) + $unitSize, $unit);
283
+ continue;
284
+ }
285
+
286
+ if ($unitSize < 0) {
287
+ $denominators = array_pad($denominators, \count($denominators) - $unitSize, $unit);
288
+ continue;
289
+ }
290
+ }
291
+
292
+ return implode('*', $numerators) . (\count($denominators) ? '/' . implode('*', $denominators) : '');
293
+ }
294
+
295
+ /**
296
+ * Output number
297
+ *
298
+ * @param \ScssPhp\ScssPhp\Compiler $compiler
299
+ *
300
+ * @return string
301
+ */
302
+ public function output(Compiler $compiler = null)
303
+ {
304
+ $dimension = round($this->dimension, static::$precision);
305
+
306
+ $units = array_filter($this->units, function ($unitSize) {
307
+ return $unitSize;
308
+ });
309
+
310
+ if (\count($units) > 1 && array_sum($units) === 0) {
311
+ $dimension = $this->dimension;
312
+ $units = [];
313
+
314
+ $this->normalizeUnits($dimension, $units);
315
+
316
+ $dimension = round($dimension, static::$precision);
317
+ $units = array_filter($units, function ($unitSize) {
318
+ return $unitSize;
319
+ });
320
+ }
321
+
322
+ $unitSize = array_sum($units);
323
+
324
+ if ($compiler && ($unitSize > 1 || $unitSize < 0 || \count($units) > 1)) {
325
+ $this->units = $units;
326
+ $unit = $this->unitStr();
327
+ } else {
328
+ reset($units);
329
+ $unit = key($units);
330
+ }
331
+
332
+ $dimension = number_format($dimension, static::$precision, '.', '');
333
+
334
+ return (static::$precision ? rtrim(rtrim($dimension, '0'), '.') : $dimension) . $unit;
335
+ }
336
+
337
+ /**
338
+ * {@inheritdoc}
339
+ */
340
+ public function __toString()
341
+ {
342
+ return $this->output();
343
+ }
344
+
345
+ /**
346
+ * Normalize units
347
+ *
348
+ * @param integer|float $dimension
349
+ * @param array $units
350
+ * @param string $baseUnit
351
+ */
352
+ private function normalizeUnits(&$dimension, &$units, $baseUnit = null)
353
+ {
354
+ $dimension = $this->dimension;
355
+ $units = [];
356
+
357
+ foreach ($this->units as $unit => $exp) {
358
+ if (! $baseUnit) {
359
+ $baseUnit = $this->findBaseUnit($unit);
360
+ }
361
+
362
+ if ($baseUnit && isset(static::$unitTable[$baseUnit][$unit])) {
363
+ $factor = pow(static::$unitTable[$baseUnit][$unit], $exp);
364
+
365
+ $unit = $baseUnit;
366
+ $dimension /= $factor;
367
+ }
368
+
369
+ $units[$unit] = $exp + (isset($units[$unit]) ? $units[$unit] : 0);
370
+ }
371
+ }
372
+
373
+ /**
374
+ * Find the base unit family for a given unit
375
+ *
376
+ * @param string $unit
377
+ *
378
+ * @return string|null
379
+ */
380
+ private function findBaseUnit($unit)
381
+ {
382
+ foreach (static::$unitTable as $baseUnit => $unitVariants) {
383
+ if (isset($unitVariants[$unit])) {
384
+ return $baseUnit;
385
+ }
386
+ }
387
+
388
+ return null;
389
+ }
390
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Parser.php ADDED
@@ -0,0 +1,3404 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp;
13
+
14
+ use ScssPhp\ScssPhp\Block;
15
+ use ScssPhp\ScssPhp\Cache;
16
+ use ScssPhp\ScssPhp\Compiler;
17
+ use ScssPhp\ScssPhp\Exception\ParserException;
18
+ use ScssPhp\ScssPhp\Node;
19
+ use ScssPhp\ScssPhp\Type;
20
+
21
+ /**
22
+ * Parser
23
+ *
24
+ * @author Leaf Corcoran <leafot@gmail.com>
25
+ */
26
+ class Parser
27
+ {
28
+ const SOURCE_INDEX = -1;
29
+ const SOURCE_LINE = -2;
30
+ const SOURCE_COLUMN = -3;
31
+
32
+ /**
33
+ * @var array
34
+ */
35
+ protected static $precedence = [
36
+ '=' => 0,
37
+ 'or' => 1,
38
+ 'and' => 2,
39
+ '==' => 3,
40
+ '!=' => 3,
41
+ '<=>' => 3,
42
+ '<=' => 4,
43
+ '>=' => 4,
44
+ '<' => 4,
45
+ '>' => 4,
46
+ '+' => 5,
47
+ '-' => 5,
48
+ '*' => 6,
49
+ '/' => 6,
50
+ '%' => 6,
51
+ ];
52
+
53
+ protected static $commentPattern;
54
+ protected static $operatorPattern;
55
+ protected static $whitePattern;
56
+
57
+ protected $cache;
58
+
59
+ private $sourceName;
60
+ private $sourceIndex;
61
+ private $sourcePositions;
62
+ private $charset;
63
+ private $count;
64
+ private $env;
65
+ private $inParens;
66
+ private $eatWhiteDefault;
67
+ private $discardComments;
68
+ private $allowVars;
69
+ private $buffer;
70
+ private $utf8;
71
+ private $encoding;
72
+ private $patternModifiers;
73
+ private $commentsSeen;
74
+
75
+ private $cssOnly;
76
+
77
+ /**
78
+ * Constructor
79
+ *
80
+ * @api
81
+ *
82
+ * @param string $sourceName
83
+ * @param integer $sourceIndex
84
+ * @param string $encoding
85
+ * @param \ScssPhp\ScssPhp\Cache $cache
86
+ */
87
+ public function __construct($sourceName, $sourceIndex = 0, $encoding = 'utf-8', $cache = null, $cssOnly = false)
88
+ {
89
+ $this->sourceName = $sourceName ?: '(stdin)';
90
+ $this->sourceIndex = $sourceIndex;
91
+ $this->charset = null;
92
+ $this->utf8 = ! $encoding || strtolower($encoding) === 'utf-8';
93
+ $this->patternModifiers = $this->utf8 ? 'Aisu' : 'Ais';
94
+ $this->commentsSeen = [];
95
+ $this->commentsSeen = [];
96
+ $this->allowVars = true;
97
+ $this->cssOnly = $cssOnly;
98
+
99
+ if (empty(static::$operatorPattern)) {
100
+ static::$operatorPattern = '([*\/%+-]|[!=]\=|\>\=?|\<\=\>|\<\=?|and|or)';
101
+
102
+ $commentSingle = '\/\/';
103
+ $commentMultiLeft = '\/\*';
104
+ $commentMultiRight = '\*\/';
105
+
106
+ static::$commentPattern = $commentMultiLeft . '.*?' . $commentMultiRight;
107
+ static::$whitePattern = $this->utf8
108
+ ? '/' . $commentSingle . '[^\n]*\s*|(' . static::$commentPattern . ')\s*|\s+/AisuS'
109
+ : '/' . $commentSingle . '[^\n]*\s*|(' . static::$commentPattern . ')\s*|\s+/AisS';
110
+ }
111
+
112
+ if ($cache) {
113
+ $this->cache = $cache;
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Get source file name
119
+ *
120
+ * @api
121
+ *
122
+ * @return string
123
+ */
124
+ public function getSourceName()
125
+ {
126
+ return $this->sourceName;
127
+ }
128
+
129
+ /**
130
+ * Throw parser error
131
+ *
132
+ * @api
133
+ *
134
+ * @param string $msg
135
+ *
136
+ * @throws \ScssPhp\ScssPhp\Exception\ParserException
137
+ */
138
+ public function throwParseError($msg = 'parse error')
139
+ {
140
+ list($line, $column) = $this->getSourcePosition($this->count);
141
+
142
+ $loc = empty($this->sourceName)
143
+ ? "line: $line, column: $column"
144
+ : "$this->sourceName on line $line, at column $column";
145
+
146
+ if ($this->peek("(.*?)(\n|$)", $m, $this->count)) {
147
+ $this->restoreEncoding();
148
+
149
+ throw new ParserException("$msg: failed at `$m[1]` $loc");
150
+ }
151
+
152
+ $this->restoreEncoding();
153
+
154
+ throw new ParserException("$msg: $loc");
155
+ }
156
+
157
+ /**
158
+ * Parser buffer
159
+ *
160
+ * @api
161
+ *
162
+ * @param string $buffer
163
+ *
164
+ * @return \ScssPhp\ScssPhp\Block
165
+ */
166
+ public function parse($buffer)
167
+ {
168
+ if ($this->cache) {
169
+ $cacheKey = $this->sourceName . ":" . md5($buffer);
170
+ $parseOptions = [
171
+ 'charset' => $this->charset,
172
+ 'utf8' => $this->utf8,
173
+ ];
174
+ $v = $this->cache->getCache("parse", $cacheKey, $parseOptions);
175
+
176
+ if (! \is_null($v)) {
177
+ return $v;
178
+ }
179
+ }
180
+
181
+ // strip BOM (byte order marker)
182
+ if (substr($buffer, 0, 3) === "\xef\xbb\xbf") {
183
+ $buffer = substr($buffer, 3);
184
+ }
185
+
186
+ $this->buffer = rtrim($buffer, "\x00..\x1f");
187
+ $this->count = 0;
188
+ $this->env = null;
189
+ $this->inParens = false;
190
+ $this->eatWhiteDefault = true;
191
+
192
+ $this->saveEncoding();
193
+ $this->extractLineNumbers($buffer);
194
+
195
+ $this->pushBlock(null); // root block
196
+ $this->whitespace();
197
+ $this->pushBlock(null);
198
+ $this->popBlock();
199
+
200
+ while ($this->parseChunk()) {
201
+ ;
202
+ }
203
+
204
+ if ($this->count !== \strlen($this->buffer)) {
205
+ $this->throwParseError();
206
+ }
207
+
208
+ if (! empty($this->env->parent)) {
209
+ $this->throwParseError('unclosed block');
210
+ }
211
+
212
+ if ($this->charset) {
213
+ array_unshift($this->env->children, $this->charset);
214
+ }
215
+
216
+ $this->restoreEncoding();
217
+
218
+ if ($this->cache) {
219
+ $this->cache->setCache("parse", $cacheKey, $this->env, $parseOptions);
220
+ }
221
+
222
+ return $this->env;
223
+ }
224
+
225
+ /**
226
+ * Parse a value or value list
227
+ *
228
+ * @api
229
+ *
230
+ * @param string $buffer
231
+ * @param string|array $out
232
+ *
233
+ * @return boolean
234
+ */
235
+ public function parseValue($buffer, &$out)
236
+ {
237
+ $this->count = 0;
238
+ $this->env = null;
239
+ $this->inParens = false;
240
+ $this->eatWhiteDefault = true;
241
+ $this->buffer = (string) $buffer;
242
+
243
+ $this->saveEncoding();
244
+
245
+ $list = $this->valueList($out);
246
+
247
+ $this->restoreEncoding();
248
+
249
+ return $list;
250
+ }
251
+
252
+ /**
253
+ * Parse a selector or selector list
254
+ *
255
+ * @api
256
+ *
257
+ * @param string $buffer
258
+ * @param string|array $out
259
+ *
260
+ * @return boolean
261
+ */
262
+ public function parseSelector($buffer, &$out)
263
+ {
264
+ $this->count = 0;
265
+ $this->env = null;
266
+ $this->inParens = false;
267
+ $this->eatWhiteDefault = true;
268
+ $this->buffer = (string) $buffer;
269
+
270
+ $this->saveEncoding();
271
+
272
+ $selector = $this->selectors($out);
273
+
274
+ $this->restoreEncoding();
275
+
276
+ return $selector;
277
+ }
278
+
279
+ /**
280
+ * Parse a media Query
281
+ *
282
+ * @api
283
+ *
284
+ * @param string $buffer
285
+ * @param string|array $out
286
+ *
287
+ * @return boolean
288
+ */
289
+ public function parseMediaQueryList($buffer, &$out)
290
+ {
291
+ $this->count = 0;
292
+ $this->env = null;
293
+ $this->inParens = false;
294
+ $this->eatWhiteDefault = true;
295
+ $this->buffer = (string) $buffer;
296
+
297
+ $this->saveEncoding();
298
+
299
+ $isMediaQuery = $this->mediaQueryList($out);
300
+
301
+ $this->restoreEncoding();
302
+
303
+ return $isMediaQuery;
304
+ }
305
+
306
+ /**
307
+ * Parse a single chunk off the head of the buffer and append it to the
308
+ * current parse environment.
309
+ *
310
+ * Returns false when the buffer is empty, or when there is an error.
311
+ *
312
+ * This function is called repeatedly until the entire document is
313
+ * parsed.
314
+ *
315
+ * This parser is most similar to a recursive descent parser. Single
316
+ * functions represent discrete grammatical rules for the language, and
317
+ * they are able to capture the text that represents those rules.
318
+ *
319
+ * Consider the function Compiler::keyword(). (All parse functions are
320
+ * structured the same.)
321
+ *
322
+ * The function takes a single reference argument. When calling the
323
+ * function it will attempt to match a keyword on the head of the buffer.
324
+ * If it is successful, it will place the keyword in the referenced
325
+ * argument, advance the position in the buffer, and return true. If it
326
+ * fails then it won't advance the buffer and it will return false.
327
+ *
328
+ * All of these parse functions are powered by Compiler::match(), which behaves
329
+ * the same way, but takes a literal regular expression. Sometimes it is
330
+ * more convenient to use match instead of creating a new function.
331
+ *
332
+ * Because of the format of the functions, to parse an entire string of
333
+ * grammatical rules, you can chain them together using &&.
334
+ *
335
+ * But, if some of the rules in the chain succeed before one fails, then
336
+ * the buffer position will be left at an invalid state. In order to
337
+ * avoid this, Compiler::seek() is used to remember and set buffer positions.
338
+ *
339
+ * Before parsing a chain, use $s = $this->count to remember the current
340
+ * position into $s. Then if a chain fails, use $this->seek($s) to
341
+ * go back where we started.
342
+ *
343
+ * @return boolean
344
+ */
345
+ protected function parseChunk()
346
+ {
347
+ $s = $this->count;
348
+
349
+ // the directives
350
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] === '@') {
351
+ if ($this->literal('@at-root', 8) &&
352
+ ($this->selectors($selector) || true) &&
353
+ ($this->map($with) || true) &&
354
+ (($this->matchChar('(')
355
+ && $this->interpolation($with)
356
+ && $this->matchChar(')')) || true) &&
357
+ $this->matchChar('{', false)
358
+ ) {
359
+ if ($this->cssOnly) {
360
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
361
+ }
362
+
363
+ $atRoot = $this->pushSpecialBlock(Type::T_AT_ROOT, $s);
364
+ $atRoot->selector = $selector;
365
+ $atRoot->with = $with;
366
+
367
+ return true;
368
+ }
369
+
370
+ $this->seek($s);
371
+
372
+ if ($this->literal('@media', 6) && $this->mediaQueryList($mediaQueryList) && $this->matchChar('{', false)) {
373
+ $media = $this->pushSpecialBlock(Type::T_MEDIA, $s);
374
+ $media->queryList = $mediaQueryList[2];
375
+
376
+ return true;
377
+ }
378
+
379
+ $this->seek($s);
380
+
381
+ if ($this->literal('@mixin', 6) &&
382
+ $this->keyword($mixinName) &&
383
+ ($this->argumentDef($args) || true) &&
384
+ $this->matchChar('{', false)
385
+ ) {
386
+ if ($this->cssOnly) {
387
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
388
+ }
389
+
390
+ $mixin = $this->pushSpecialBlock(Type::T_MIXIN, $s);
391
+ $mixin->name = $mixinName;
392
+ $mixin->args = $args;
393
+
394
+ return true;
395
+ }
396
+
397
+ $this->seek($s);
398
+
399
+ if ($this->literal('@include', 8) &&
400
+ $this->keyword($mixinName) &&
401
+ ($this->matchChar('(') &&
402
+ ($this->argValues($argValues) || true) &&
403
+ $this->matchChar(')') || true) &&
404
+ ($this->end() ||
405
+ ($this->literal('using', 5) &&
406
+ $this->argumentDef($argUsing) &&
407
+ ($this->end() || $this->matchChar('{') && $hasBlock = true)) ||
408
+ $this->matchChar('{') && $hasBlock = true)
409
+ ) {
410
+ if ($this->cssOnly) {
411
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
412
+ }
413
+
414
+ $child = [
415
+ Type::T_INCLUDE,
416
+ $mixinName,
417
+ isset($argValues) ? $argValues : null,
418
+ null,
419
+ isset($argUsing) ? $argUsing : null
420
+ ];
421
+
422
+ if (! empty($hasBlock)) {
423
+ $include = $this->pushSpecialBlock(Type::T_INCLUDE, $s);
424
+ $include->child = $child;
425
+ } else {
426
+ $this->append($child, $s);
427
+ }
428
+
429
+ return true;
430
+ }
431
+
432
+ $this->seek($s);
433
+
434
+ if ($this->literal('@scssphp-import-once', 20) &&
435
+ $this->valueList($importPath) &&
436
+ $this->end()
437
+ ) {
438
+ if ($this->cssOnly) {
439
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
440
+ }
441
+
442
+ $this->append([Type::T_SCSSPHP_IMPORT_ONCE, $importPath], $s);
443
+
444
+ return true;
445
+ }
446
+
447
+ $this->seek($s);
448
+
449
+ if ($this->literal('@import', 7) &&
450
+ $this->valueList($importPath) &&
451
+ $this->end()
452
+ ) {
453
+ $this->append([Type::T_IMPORT, $importPath], $s);
454
+
455
+ return true;
456
+ }
457
+
458
+ $this->seek($s);
459
+
460
+ if ($this->literal('@import', 7) &&
461
+ $this->url($importPath) &&
462
+ $this->end()
463
+ ) {
464
+ if ($this->cssOnly) {
465
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
466
+ }
467
+
468
+ $this->append([Type::T_IMPORT, $importPath], $s);
469
+
470
+ return true;
471
+ }
472
+
473
+ $this->seek($s);
474
+
475
+ if ($this->literal('@extend', 7) &&
476
+ $this->selectors($selectors) &&
477
+ $this->end()
478
+ ) {
479
+ if ($this->cssOnly) {
480
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
481
+ }
482
+
483
+ // check for '!flag'
484
+ $optional = $this->stripOptionalFlag($selectors);
485
+ $this->append([Type::T_EXTEND, $selectors, $optional], $s);
486
+
487
+ return true;
488
+ }
489
+
490
+ $this->seek($s);
491
+
492
+ if ($this->literal('@function', 9) &&
493
+ $this->keyword($fnName) &&
494
+ $this->argumentDef($args) &&
495
+ $this->matchChar('{', false)
496
+ ) {
497
+ if ($this->cssOnly) {
498
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
499
+ }
500
+
501
+ $func = $this->pushSpecialBlock(Type::T_FUNCTION, $s);
502
+ $func->name = $fnName;
503
+ $func->args = $args;
504
+
505
+ return true;
506
+ }
507
+
508
+ $this->seek($s);
509
+
510
+ if ($this->literal('@break', 6) && $this->end()) {
511
+ if ($this->cssOnly) {
512
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
513
+ }
514
+
515
+ $this->append([Type::T_BREAK], $s);
516
+
517
+ return true;
518
+ }
519
+
520
+ $this->seek($s);
521
+
522
+ if ($this->literal('@continue', 9) && $this->end()) {
523
+ if ($this->cssOnly) {
524
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
525
+ }
526
+
527
+ $this->append([Type::T_CONTINUE], $s);
528
+
529
+ return true;
530
+ }
531
+
532
+ $this->seek($s);
533
+
534
+ if ($this->literal('@return', 7) && ($this->valueList($retVal) || true) && $this->end()) {
535
+ if ($this->cssOnly) {
536
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
537
+ }
538
+
539
+ $this->append([Type::T_RETURN, isset($retVal) ? $retVal : [Type::T_NULL]], $s);
540
+
541
+ return true;
542
+ }
543
+
544
+ $this->seek($s);
545
+
546
+ if ($this->literal('@each', 5) &&
547
+ $this->genericList($varNames, 'variable', ',', false) &&
548
+ $this->literal('in', 2) &&
549
+ $this->valueList($list) &&
550
+ $this->matchChar('{', false)
551
+ ) {
552
+ if ($this->cssOnly) {
553
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
554
+ }
555
+
556
+ $each = $this->pushSpecialBlock(Type::T_EACH, $s);
557
+
558
+ foreach ($varNames[2] as $varName) {
559
+ $each->vars[] = $varName[1];
560
+ }
561
+
562
+ $each->list = $list;
563
+
564
+ return true;
565
+ }
566
+
567
+ $this->seek($s);
568
+
569
+ if ($this->literal('@while', 6) &&
570
+ $this->expression($cond) &&
571
+ $this->matchChar('{', false)
572
+ ) {
573
+ if ($this->cssOnly) {
574
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
575
+ }
576
+
577
+ $while = $this->pushSpecialBlock(Type::T_WHILE, $s);
578
+ $while->cond = $cond;
579
+
580
+ return true;
581
+ }
582
+
583
+ $this->seek($s);
584
+
585
+ if ($this->literal('@for', 4) &&
586
+ $this->variable($varName) &&
587
+ $this->literal('from', 4) &&
588
+ $this->expression($start) &&
589
+ ($this->literal('through', 7) ||
590
+ ($forUntil = true && $this->literal('to', 2))) &&
591
+ $this->expression($end) &&
592
+ $this->matchChar('{', false)
593
+ ) {
594
+ if ($this->cssOnly) {
595
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
596
+ }
597
+
598
+ $for = $this->pushSpecialBlock(Type::T_FOR, $s);
599
+ $for->var = $varName[1];
600
+ $for->start = $start;
601
+ $for->end = $end;
602
+ $for->until = isset($forUntil);
603
+
604
+ return true;
605
+ }
606
+
607
+ $this->seek($s);
608
+
609
+ if ($this->literal('@if', 3) && $this->valueList($cond) && $this->matchChar('{', false)) {
610
+ if ($this->cssOnly) {
611
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
612
+ }
613
+
614
+ $if = $this->pushSpecialBlock(Type::T_IF, $s);
615
+
616
+ while ($cond[0] === Type::T_LIST
617
+ && ! empty($cond['enclosing'])
618
+ && $cond['enclosing'] === 'parent'
619
+ && \count($cond[2]) == 1) {
620
+ $cond = reset($cond[2]);
621
+ }
622
+
623
+ $if->cond = $cond;
624
+ $if->cases = [];
625
+
626
+ return true;
627
+ }
628
+
629
+ $this->seek($s);
630
+
631
+ if ($this->literal('@debug', 6) &&
632
+ $this->valueList($value) &&
633
+ $this->end()
634
+ ) {
635
+ if ($this->cssOnly) {
636
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
637
+ }
638
+
639
+ $this->append([Type::T_DEBUG, $value], $s);
640
+
641
+ return true;
642
+ }
643
+
644
+ $this->seek($s);
645
+
646
+ if ($this->literal('@warn', 5) &&
647
+ $this->valueList($value) &&
648
+ $this->end()
649
+ ) {
650
+ if ($this->cssOnly) {
651
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
652
+ }
653
+
654
+ $this->append([Type::T_WARN, $value], $s);
655
+
656
+ return true;
657
+ }
658
+
659
+ $this->seek($s);
660
+
661
+ if ($this->literal('@error', 6) &&
662
+ $this->valueList($value) &&
663
+ $this->end()
664
+ ) {
665
+ if ($this->cssOnly) {
666
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
667
+ }
668
+
669
+ $this->append([Type::T_ERROR, $value], $s);
670
+
671
+ return true;
672
+ }
673
+
674
+ $this->seek($s);
675
+
676
+ if ($this->literal('@content', 8) &&
677
+ ($this->end() ||
678
+ $this->matchChar('(') &&
679
+ $this->argValues($argContent) &&
680
+ $this->matchChar(')') &&
681
+ $this->end())
682
+ ) {
683
+ if ($this->cssOnly) {
684
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
685
+ }
686
+
687
+ $this->append([Type::T_MIXIN_CONTENT, isset($argContent) ? $argContent : null], $s);
688
+
689
+ return true;
690
+ }
691
+
692
+ $this->seek($s);
693
+
694
+ $last = $this->last();
695
+
696
+ if (isset($last) && $last[0] === Type::T_IF) {
697
+ list(, $if) = $last;
698
+
699
+ if ($this->literal('@else', 5)) {
700
+ if ($this->matchChar('{', false)) {
701
+ $else = $this->pushSpecialBlock(Type::T_ELSE, $s);
702
+ } elseif ($this->literal('if', 2) && $this->valueList($cond) && $this->matchChar('{', false)) {
703
+ $else = $this->pushSpecialBlock(Type::T_ELSEIF, $s);
704
+ $else->cond = $cond;
705
+ }
706
+
707
+ if (isset($else)) {
708
+ $else->dontAppend = true;
709
+ $if->cases[] = $else;
710
+
711
+ return true;
712
+ }
713
+ }
714
+
715
+ $this->seek($s);
716
+ }
717
+
718
+ // only retain the first @charset directive encountered
719
+ if ($this->literal('@charset', 8) &&
720
+ $this->valueList($charset) &&
721
+ $this->end()
722
+ ) {
723
+ if (! isset($this->charset)) {
724
+ $statement = [Type::T_CHARSET, $charset];
725
+
726
+ list($line, $column) = $this->getSourcePosition($s);
727
+
728
+ $statement[static::SOURCE_LINE] = $line;
729
+ $statement[static::SOURCE_COLUMN] = $column;
730
+ $statement[static::SOURCE_INDEX] = $this->sourceIndex;
731
+
732
+ $this->charset = $statement;
733
+ }
734
+
735
+ return true;
736
+ }
737
+
738
+ $this->seek($s);
739
+
740
+ if ($this->literal('@supports', 9) &&
741
+ ($t1=$this->supportsQuery($supportQuery)) &&
742
+ ($t2=$this->matchChar('{', false))
743
+ ) {
744
+ $directive = $this->pushSpecialBlock(Type::T_DIRECTIVE, $s);
745
+ $directive->name = 'supports';
746
+ $directive->value = $supportQuery;
747
+
748
+ return true;
749
+ }
750
+
751
+ $this->seek($s);
752
+
753
+ // doesn't match built in directive, do generic one
754
+ if ($this->matchChar('@', false) &&
755
+ $this->keyword($dirName) &&
756
+ $this->directiveValue($dirValue, '{')
757
+ ) {
758
+ if ($dirName === 'media') {
759
+ $directive = $this->pushSpecialBlock(Type::T_MEDIA, $s);
760
+ } else {
761
+ $directive = $this->pushSpecialBlock(Type::T_DIRECTIVE, $s);
762
+ $directive->name = $dirName;
763
+ }
764
+
765
+ if (isset($dirValue)) {
766
+ $directive->value = $dirValue;
767
+ }
768
+
769
+ return true;
770
+ }
771
+
772
+ $this->seek($s);
773
+
774
+ // maybe it's a generic blockless directive
775
+ if ($this->matchChar('@', false) &&
776
+ $this->keyword($dirName) &&
777
+ $this->directiveValue($dirValue) &&
778
+ $this->end()
779
+ ) {
780
+ $this->append([Type::T_DIRECTIVE, [$dirName, $dirValue]], $s);
781
+
782
+ return true;
783
+ }
784
+
785
+ $this->seek($s);
786
+
787
+ return false;
788
+ }
789
+
790
+ // custom properties : right part is static
791
+ if (($this->customProperty($name) || ($this->cssOnly && $this->propertyName($name))) &&
792
+ $this->matchChar(':', false)
793
+ ) {
794
+ $start = $this->count;
795
+
796
+ // but can be complex and finish with ; or }
797
+ foreach ([';','}'] as $ending) {
798
+ if ($this->openString($ending, $stringValue, '(', ')', false) &&
799
+ $this->end()
800
+ ) {
801
+ $end = $this->count;
802
+ $value = $stringValue;
803
+
804
+ // check if we have only a partial value due to nested [] or { } to take in account
805
+ $nestingPairs = [['[', ']'], ['{', '}']];
806
+
807
+ foreach ($nestingPairs as $nestingPair) {
808
+ $p = strpos($this->buffer, $nestingPair[0], $start);
809
+
810
+ if ($p && $p < $end) {
811
+ $this->seek($start);
812
+
813
+ if ($this->openString($ending, $stringValue, $nestingPair[0], $nestingPair[1], false) &&
814
+ $this->end() &&
815
+ $this->count > $end
816
+ ) {
817
+ $end = $this->count;
818
+ $value = $stringValue;
819
+ }
820
+ }
821
+ }
822
+
823
+ $this->seek($end);
824
+ $this->append([Type::T_CUSTOM_PROPERTY, $name, $value], $s);
825
+
826
+ return true;
827
+ }
828
+ }
829
+
830
+ // TODO: output an error here if nothing found according to sass spec
831
+ }
832
+
833
+ $this->seek($s);
834
+
835
+ // property shortcut
836
+ // captures most properties before having to parse a selector
837
+ if ($this->keyword($name, false) &&
838
+ $this->literal(': ', 2) &&
839
+ $this->valueList($value) &&
840
+ $this->end()
841
+ ) {
842
+ $name = [Type::T_STRING, '', [$name]];
843
+ $this->append([Type::T_ASSIGN, $name, $value], $s);
844
+
845
+ return true;
846
+ }
847
+
848
+ $this->seek($s);
849
+
850
+ // variable assigns
851
+ if ($this->variable($name) &&
852
+ $this->matchChar(':') &&
853
+ $this->valueList($value) &&
854
+ $this->end()
855
+ ) {
856
+ if ($this->cssOnly) {
857
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
858
+ }
859
+
860
+ // check for '!flag'
861
+ $assignmentFlags = $this->stripAssignmentFlags($value);
862
+ $this->append([Type::T_ASSIGN, $name, $value, $assignmentFlags], $s);
863
+
864
+ return true;
865
+ }
866
+
867
+ $this->seek($s);
868
+
869
+ // misc
870
+ if ($this->literal('-->', 3)) {
871
+ return true;
872
+ }
873
+
874
+ // opening css block
875
+ if ($this->selectors($selectors) && $this->matchChar('{', false)) {
876
+ if ($this->cssOnly) {
877
+ if (! empty($this->env->parent)) {
878
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
879
+ }
880
+ }
881
+
882
+ $this->pushBlock($selectors, $s);
883
+
884
+ if ($this->eatWhiteDefault) {
885
+ $this->whitespace();
886
+ $this->append(null); // collect comments at the beginning if needed
887
+ }
888
+
889
+ return true;
890
+ }
891
+
892
+ $this->seek($s);
893
+
894
+ // property assign, or nested assign
895
+ if ($this->propertyName($name) && $this->matchChar(':')) {
896
+ $foundSomething = false;
897
+
898
+ if ($this->valueList($value)) {
899
+ if (empty($this->env->parent)) {
900
+ $this->throwParseError('expected "{"');
901
+ }
902
+
903
+ $this->append([Type::T_ASSIGN, $name, $value], $s);
904
+ $foundSomething = true;
905
+ }
906
+
907
+ if ($this->matchChar('{', false)) {
908
+ if ($this->cssOnly) {
909
+ $this->throwParseError("SCSS syntax not allowed in CSS file");
910
+ }
911
+
912
+ $propBlock = $this->pushSpecialBlock(Type::T_NESTED_PROPERTY, $s);
913
+ $propBlock->prefix = $name;
914
+ $propBlock->hasValue = $foundSomething;
915
+
916
+ $foundSomething = true;
917
+ } elseif ($foundSomething) {
918
+ $foundSomething = $this->end();
919
+ }
920
+
921
+ if ($foundSomething) {
922
+ return true;
923
+ }
924
+ }
925
+
926
+ $this->seek($s);
927
+
928
+ // closing a block
929
+ if ($this->matchChar('}', false)) {
930
+ $block = $this->popBlock();
931
+
932
+ if (! isset($block->type) || $block->type !== Type::T_IF) {
933
+ if ($this->env->parent) {
934
+ $this->append(null); // collect comments before next statement if needed
935
+ }
936
+ }
937
+
938
+ if (isset($block->type) && $block->type === Type::T_INCLUDE) {
939
+ $include = $block->child;
940
+ unset($block->child);
941
+ $include[3] = $block;
942
+ $this->append($include, $s);
943
+ } elseif (empty($block->dontAppend)) {
944
+ $type = isset($block->type) ? $block->type : Type::T_BLOCK;
945
+ $this->append([$type, $block], $s);
946
+ }
947
+
948
+ // collect comments just after the block closing if needed
949
+ if ($this->eatWhiteDefault) {
950
+ $this->whitespace();
951
+
952
+ if ($this->env->comments) {
953
+ $this->append(null);
954
+ }
955
+ }
956
+
957
+ return true;
958
+ }
959
+
960
+ // extra stuff
961
+ if ($this->matchChar(';') ||
962
+ $this->literal('<!--', 4)
963
+ ) {
964
+ return true;
965
+ }
966
+
967
+ return false;
968
+ }
969
+
970
+ /**
971
+ * Push block onto parse tree
972
+ *
973
+ * @param array $selectors
974
+ * @param integer $pos
975
+ *
976
+ * @return \ScssPhp\ScssPhp\Block
977
+ */
978
+ protected function pushBlock($selectors, $pos = 0)
979
+ {
980
+ list($line, $column) = $this->getSourcePosition($pos);
981
+
982
+ $b = new Block;
983
+ $b->sourceName = $this->sourceName;
984
+ $b->sourceLine = $line;
985
+ $b->sourceColumn = $column;
986
+ $b->sourceIndex = $this->sourceIndex;
987
+ $b->selectors = $selectors;
988
+ $b->comments = [];
989
+ $b->parent = $this->env;
990
+
991
+ if (! $this->env) {
992
+ $b->children = [];
993
+ } elseif (empty($this->env->children)) {
994
+ $this->env->children = $this->env->comments;
995
+ $b->children = [];
996
+ $this->env->comments = [];
997
+ } else {
998
+ $b->children = $this->env->comments;
999
+ $this->env->comments = [];
1000
+ }
1001
+
1002
+ $this->env = $b;
1003
+
1004
+ // collect comments at the beginning of a block if needed
1005
+ if ($this->eatWhiteDefault) {
1006
+ $this->whitespace();
1007
+
1008
+ if ($this->env->comments) {
1009
+ $this->append(null);
1010
+ }
1011
+ }
1012
+
1013
+ return $b;
1014
+ }
1015
+
1016
+ /**
1017
+ * Push special (named) block onto parse tree
1018
+ *
1019
+ * @param string $type
1020
+ * @param integer $pos
1021
+ *
1022
+ * @return \ScssPhp\ScssPhp\Block
1023
+ */
1024
+ protected function pushSpecialBlock($type, $pos)
1025
+ {
1026
+ $block = $this->pushBlock(null, $pos);
1027
+ $block->type = $type;
1028
+
1029
+ return $block;
1030
+ }
1031
+
1032
+ /**
1033
+ * Pop scope and return last block
1034
+ *
1035
+ * @return \ScssPhp\ScssPhp\Block
1036
+ *
1037
+ * @throws \Exception
1038
+ */
1039
+ protected function popBlock()
1040
+ {
1041
+
1042
+ // collect comments ending just before of a block closing
1043
+ if ($this->env->comments) {
1044
+ $this->append(null);
1045
+ }
1046
+
1047
+ // pop the block
1048
+ $block = $this->env;
1049
+
1050
+ if (empty($block->parent)) {
1051
+ $this->throwParseError('unexpected }');
1052
+ }
1053
+
1054
+ if ($block->type == Type::T_AT_ROOT) {
1055
+ // keeps the parent in case of self selector &
1056
+ $block->selfParent = $block->parent;
1057
+ }
1058
+
1059
+ $this->env = $block->parent;
1060
+
1061
+ unset($block->parent);
1062
+
1063
+ return $block;
1064
+ }
1065
+
1066
+ /**
1067
+ * Peek input stream
1068
+ *
1069
+ * @param string $regex
1070
+ * @param array $out
1071
+ * @param integer $from
1072
+ *
1073
+ * @return integer
1074
+ */
1075
+ protected function peek($regex, &$out, $from = null)
1076
+ {
1077
+ if (! isset($from)) {
1078
+ $from = $this->count;
1079
+ }
1080
+
1081
+ $r = '/' . $regex . '/' . $this->patternModifiers;
1082
+ $result = preg_match($r, $this->buffer, $out, null, $from);
1083
+
1084
+ return $result;
1085
+ }
1086
+
1087
+ /**
1088
+ * Seek to position in input stream (or return current position in input stream)
1089
+ *
1090
+ * @param integer $where
1091
+ */
1092
+ protected function seek($where)
1093
+ {
1094
+ $this->count = $where;
1095
+ }
1096
+
1097
+ /**
1098
+ * Match string looking for either ending delim, escape, or string interpolation
1099
+ *
1100
+ * {@internal This is a workaround for preg_match's 250K string match limit. }}
1101
+ *
1102
+ * @param array $m Matches (passed by reference)
1103
+ * @param string $delim Delimeter
1104
+ *
1105
+ * @return boolean True if match; false otherwise
1106
+ */
1107
+ protected function matchString(&$m, $delim)
1108
+ {
1109
+ $token = null;
1110
+
1111
+ $end = \strlen($this->buffer);
1112
+
1113
+ // look for either ending delim, escape, or string interpolation
1114
+ foreach (['#{', '\\', $delim] as $lookahead) {
1115
+ $pos = strpos($this->buffer, $lookahead, $this->count);
1116
+
1117
+ if ($pos !== false && $pos < $end) {
1118
+ $end = $pos;
1119
+ $token = $lookahead;
1120
+ }
1121
+ }
1122
+
1123
+ if (! isset($token)) {
1124
+ return false;
1125
+ }
1126
+
1127
+ $match = substr($this->buffer, $this->count, $end - $this->count);
1128
+ $m = [
1129
+ $match . $token,
1130
+ $match,
1131
+ $token
1132
+ ];
1133
+ $this->count = $end + \strlen($token);
1134
+
1135
+ return true;
1136
+ }
1137
+
1138
+ /**
1139
+ * Try to match something on head of buffer
1140
+ *
1141
+ * @param string $regex
1142
+ * @param array $out
1143
+ * @param boolean $eatWhitespace
1144
+ *
1145
+ * @return boolean
1146
+ */
1147
+ protected function match($regex, &$out, $eatWhitespace = null)
1148
+ {
1149
+ $r = '/' . $regex . '/' . $this->patternModifiers;
1150
+
1151
+ if (! preg_match($r, $this->buffer, $out, null, $this->count)) {
1152
+ return false;
1153
+ }
1154
+
1155
+ $this->count += \strlen($out[0]);
1156
+
1157
+ if (! isset($eatWhitespace)) {
1158
+ $eatWhitespace = $this->eatWhiteDefault;
1159
+ }
1160
+
1161
+ if ($eatWhitespace) {
1162
+ $this->whitespace();
1163
+ }
1164
+
1165
+ return true;
1166
+ }
1167
+
1168
+ /**
1169
+ * Match a single string
1170
+ *
1171
+ * @param string $char
1172
+ * @param boolean $eatWhitespace
1173
+ *
1174
+ * @return boolean
1175
+ */
1176
+ protected function matchChar($char, $eatWhitespace = null)
1177
+ {
1178
+ if (! isset($this->buffer[$this->count]) || $this->buffer[$this->count] !== $char) {
1179
+ return false;
1180
+ }
1181
+
1182
+ $this->count++;
1183
+
1184
+ if (! isset($eatWhitespace)) {
1185
+ $eatWhitespace = $this->eatWhiteDefault;
1186
+ }
1187
+
1188
+ if ($eatWhitespace) {
1189
+ $this->whitespace();
1190
+ }
1191
+
1192
+ return true;
1193
+ }
1194
+
1195
+ /**
1196
+ * Match literal string
1197
+ *
1198
+ * @param string $what
1199
+ * @param integer $len
1200
+ * @param boolean $eatWhitespace
1201
+ *
1202
+ * @return boolean
1203
+ */
1204
+ protected function literal($what, $len, $eatWhitespace = null)
1205
+ {
1206
+ if (strcasecmp(substr($this->buffer, $this->count, $len), $what) !== 0) {
1207
+ return false;
1208
+ }
1209
+
1210
+ $this->count += $len;
1211
+
1212
+ if (! isset($eatWhitespace)) {
1213
+ $eatWhitespace = $this->eatWhiteDefault;
1214
+ }
1215
+
1216
+ if ($eatWhitespace) {
1217
+ $this->whitespace();
1218
+ }
1219
+
1220
+ return true;
1221
+ }
1222
+
1223
+ /**
1224
+ * Match some whitespace
1225
+ *
1226
+ * @return boolean
1227
+ */
1228
+ protected function whitespace()
1229
+ {
1230
+ $gotWhite = false;
1231
+
1232
+ while (preg_match(static::$whitePattern, $this->buffer, $m, null, $this->count)) {
1233
+ if (isset($m[1]) && empty($this->commentsSeen[$this->count])) {
1234
+ // comment that are kept in the output CSS
1235
+ $comment = [];
1236
+ $startCommentCount = $this->count;
1237
+ $endCommentCount = $this->count + \strlen($m[1]);
1238
+
1239
+ // find interpolations in comment
1240
+ $p = strpos($this->buffer, '#{', $this->count);
1241
+
1242
+ while ($p !== false && $p < $endCommentCount) {
1243
+ $c = substr($this->buffer, $this->count, $p - $this->count);
1244
+ $comment[] = $c;
1245
+ $this->count = $p;
1246
+ $out = null;
1247
+
1248
+ if ($this->interpolation($out)) {
1249
+ // keep right spaces in the following string part
1250
+ if ($out[3]) {
1251
+ while ($this->buffer[$this->count-1] !== '}') {
1252
+ $this->count--;
1253
+ }
1254
+
1255
+ $out[3] = '';
1256
+ }
1257
+
1258
+ $comment[] = [Type::T_COMMENT, substr($this->buffer, $p, $this->count - $p), $out];
1259
+ } else {
1260
+ $comment[] = substr($this->buffer, $this->count, 2);
1261
+
1262
+ $this->count += 2;
1263
+ }
1264
+
1265
+ $p = strpos($this->buffer, '#{', $this->count);
1266
+ }
1267
+
1268
+ // remaining part
1269
+ $c = substr($this->buffer, $this->count, $endCommentCount - $this->count);
1270
+
1271
+ if (! $comment) {
1272
+ // single part static comment
1273
+ $this->appendComment([Type::T_COMMENT, $c]);
1274
+ } else {
1275
+ $comment[] = $c;
1276
+ $staticComment = substr($this->buffer, $startCommentCount, $endCommentCount - $startCommentCount);
1277
+ $this->appendComment([Type::T_COMMENT, $staticComment, [Type::T_STRING, '', $comment]]);
1278
+ }
1279
+
1280
+ $this->commentsSeen[$startCommentCount] = true;
1281
+ $this->count = $endCommentCount;
1282
+ } else {
1283
+ // comment that are ignored and not kept in the output css
1284
+ $this->count += \strlen($m[0]);
1285
+ }
1286
+
1287
+ $gotWhite = true;
1288
+ }
1289
+
1290
+ return $gotWhite;
1291
+ }
1292
+
1293
+ /**
1294
+ * Append comment to current block
1295
+ *
1296
+ * @param array $comment
1297
+ */
1298
+ protected function appendComment($comment)
1299
+ {
1300
+ if (! $this->discardComments) {
1301
+ if ($comment[0] === Type::T_COMMENT) {
1302
+ if (\is_string($comment[1])) {
1303
+ $comment[1] = substr(preg_replace(['/^\s+/m', '/^(.)/m'], ['', ' \1'], $comment[1]), 1);
1304
+ }
1305
+
1306
+ if (isset($comment[2]) and \is_array($comment[2]) and $comment[2][0] === Type::T_STRING) {
1307
+ foreach ($comment[2][2] as $k => $v) {
1308
+ if (\is_string($v)) {
1309
+ $p = strpos($v, "\n");
1310
+
1311
+ if ($p !== false) {
1312
+ $comment[2][2][$k] = substr($v, 0, $p + 1)
1313
+ . preg_replace(['/^\s+/m', '/^(.)/m'], ['', ' \1'], substr($v, $p+1));
1314
+ }
1315
+ }
1316
+ }
1317
+ }
1318
+ }
1319
+
1320
+ $this->env->comments[] = $comment;
1321
+ }
1322
+ }
1323
+
1324
+ /**
1325
+ * Append statement to current block
1326
+ *
1327
+ * @param array $statement
1328
+ * @param integer $pos
1329
+ */
1330
+ protected function append($statement, $pos = null)
1331
+ {
1332
+ if (! \is_null($statement)) {
1333
+ if (! \is_null($pos)) {
1334
+ list($line, $column) = $this->getSourcePosition($pos);
1335
+
1336
+ $statement[static::SOURCE_LINE] = $line;
1337
+ $statement[static::SOURCE_COLUMN] = $column;
1338
+ $statement[static::SOURCE_INDEX] = $this->sourceIndex;
1339
+ }
1340
+
1341
+ $this->env->children[] = $statement;
1342
+ }
1343
+
1344
+ $comments = $this->env->comments;
1345
+
1346
+ if ($comments) {
1347
+ $this->env->children = array_merge($this->env->children, $comments);
1348
+ $this->env->comments = [];
1349
+ }
1350
+ }
1351
+
1352
+ /**
1353
+ * Returns last child was appended
1354
+ *
1355
+ * @return array|null
1356
+ */
1357
+ protected function last()
1358
+ {
1359
+ $i = \count($this->env->children) - 1;
1360
+
1361
+ if (isset($this->env->children[$i])) {
1362
+ return $this->env->children[$i];
1363
+ }
1364
+ }
1365
+
1366
+ /**
1367
+ * Parse media query list
1368
+ *
1369
+ * @param array $out
1370
+ *
1371
+ * @return boolean
1372
+ */
1373
+ protected function mediaQueryList(&$out)
1374
+ {
1375
+ return $this->genericList($out, 'mediaQuery', ',', false);
1376
+ }
1377
+
1378
+ /**
1379
+ * Parse media query
1380
+ *
1381
+ * @param array $out
1382
+ *
1383
+ * @return boolean
1384
+ */
1385
+ protected function mediaQuery(&$out)
1386
+ {
1387
+ $expressions = null;
1388
+ $parts = [];
1389
+
1390
+ if (($this->literal('only', 4) && ($only = true) || $this->literal('not', 3) && ($not = true) || true) &&
1391
+ $this->mixedKeyword($mediaType)
1392
+ ) {
1393
+ $prop = [Type::T_MEDIA_TYPE];
1394
+
1395
+ if (isset($only)) {
1396
+ $prop[] = [Type::T_KEYWORD, 'only'];
1397
+ }
1398
+
1399
+ if (isset($not)) {
1400
+ $prop[] = [Type::T_KEYWORD, 'not'];
1401
+ }
1402
+
1403
+ $media = [Type::T_LIST, '', []];
1404
+
1405
+ foreach ((array) $mediaType as $type) {
1406
+ if (\is_array($type)) {
1407
+ $media[2][] = $type;
1408
+ } else {
1409
+ $media[2][] = [Type::T_KEYWORD, $type];
1410
+ }
1411
+ }
1412
+
1413
+ $prop[] = $media;
1414
+ $parts[] = $prop;
1415
+ }
1416
+
1417
+ if (empty($parts) || $this->literal('and', 3)) {
1418
+ $this->genericList($expressions, 'mediaExpression', 'and', false);
1419
+
1420
+ if (\is_array($expressions)) {
1421
+ $parts = array_merge($parts, $expressions[2]);
1422
+ }
1423
+ }
1424
+
1425
+ $out = $parts;
1426
+
1427
+ return true;
1428
+ }
1429
+
1430
+ /**
1431
+ * Parse supports query
1432
+ *
1433
+ * @param array $out
1434
+ *
1435
+ * @return boolean
1436
+ */
1437
+ protected function supportsQuery(&$out)
1438
+ {
1439
+ $expressions = null;
1440
+ $parts = [];
1441
+
1442
+ $s = $this->count;
1443
+
1444
+ $not = false;
1445
+
1446
+ if (($this->literal('not', 3) && ($not = true) || true) &&
1447
+ $this->matchChar('(') &&
1448
+ ($this->expression($property)) &&
1449
+ $this->literal(': ', 2) &&
1450
+ $this->valueList($value) &&
1451
+ $this->matchChar(')')
1452
+ ) {
1453
+ $support = [Type::T_STRING, '', [[Type::T_KEYWORD, ($not ? 'not ' : '') . '(']]];
1454
+ $support[2][] = $property;
1455
+ $support[2][] = [Type::T_KEYWORD, ': '];
1456
+ $support[2][] = $value;
1457
+ $support[2][] = [Type::T_KEYWORD, ')'];
1458
+
1459
+ $parts[] = $support;
1460
+ $s = $this->count;
1461
+ } else {
1462
+ $this->seek($s);
1463
+ }
1464
+
1465
+ if ($this->matchChar('(') &&
1466
+ $this->supportsQuery($subQuery) &&
1467
+ $this->matchChar(')')
1468
+ ) {
1469
+ $parts[] = [Type::T_STRING, '', [[Type::T_KEYWORD, '('], $subQuery, [Type::T_KEYWORD, ')']]];
1470
+ $s = $this->count;
1471
+ } else {
1472
+ $this->seek($s);
1473
+ }
1474
+
1475
+ if ($this->literal('not', 3) &&
1476
+ $this->supportsQuery($subQuery)
1477
+ ) {
1478
+ $parts[] = [Type::T_STRING, '', [[Type::T_KEYWORD, 'not '], $subQuery]];
1479
+ $s = $this->count;
1480
+ } else {
1481
+ $this->seek($s);
1482
+ }
1483
+
1484
+ if ($this->literal('selector(', 9) &&
1485
+ $this->selector($selector) &&
1486
+ $this->matchChar(')')
1487
+ ) {
1488
+ $support = [Type::T_STRING, '', [[Type::T_KEYWORD, 'selector(']]];
1489
+
1490
+ $selectorList = [Type::T_LIST, '', []];
1491
+
1492
+ foreach ($selector as $sc) {
1493
+ $compound = [Type::T_STRING, '', []];
1494
+
1495
+ foreach ($sc as $scp) {
1496
+ if (\is_array($scp)) {
1497
+ $compound[2][] = $scp;
1498
+ } else {
1499
+ $compound[2][] = [Type::T_KEYWORD, $scp];
1500
+ }
1501
+ }
1502
+
1503
+ $selectorList[2][] = $compound;
1504
+ }
1505
+
1506
+ $support[2][] = $selectorList;
1507
+ $support[2][] = [Type::T_KEYWORD, ')'];
1508
+ $parts[] = $support;
1509
+ $s = $this->count;
1510
+ } else {
1511
+ $this->seek($s);
1512
+ }
1513
+
1514
+ if ($this->variable($var) or $this->interpolation($var)) {
1515
+ $parts[] = $var;
1516
+ $s = $this->count;
1517
+ } else {
1518
+ $this->seek($s);
1519
+ }
1520
+
1521
+ if ($this->literal('and', 3) &&
1522
+ $this->genericList($expressions, 'supportsQuery', ' and', false)) {
1523
+ array_unshift($expressions[2], [Type::T_STRING, '', $parts]);
1524
+
1525
+ $parts = [$expressions];
1526
+ $s = $this->count;
1527
+ } else {
1528
+ $this->seek($s);
1529
+ }
1530
+
1531
+ if ($this->literal('or', 2) &&
1532
+ $this->genericList($expressions, 'supportsQuery', ' or', false)) {
1533
+ array_unshift($expressions[2], [Type::T_STRING, '', $parts]);
1534
+
1535
+ $parts = [$expressions];
1536
+ $s = $this->count;
1537
+ } else {
1538
+ $this->seek($s);
1539
+ }
1540
+
1541
+ if (\count($parts)) {
1542
+ if ($this->eatWhiteDefault) {
1543
+ $this->whitespace();
1544
+ }
1545
+
1546
+ $out = [Type::T_STRING, '', $parts];
1547
+
1548
+ return true;
1549
+ }
1550
+
1551
+ return false;
1552
+ }
1553
+
1554
+
1555
+ /**
1556
+ * Parse media expression
1557
+ *
1558
+ * @param array $out
1559
+ *
1560
+ * @return boolean
1561
+ */
1562
+ protected function mediaExpression(&$out)
1563
+ {
1564
+ $s = $this->count;
1565
+ $value = null;
1566
+
1567
+ if ($this->matchChar('(') &&
1568
+ $this->expression($feature) &&
1569
+ ($this->matchChar(':') && $this->expression($value) || true) &&
1570
+ $this->matchChar(')')
1571
+ ) {
1572
+ $out = [Type::T_MEDIA_EXPRESSION, $feature];
1573
+
1574
+ if ($value) {
1575
+ $out[] = $value;
1576
+ }
1577
+
1578
+ return true;
1579
+ }
1580
+
1581
+ $this->seek($s);
1582
+
1583
+ return false;
1584
+ }
1585
+
1586
+ /**
1587
+ * Parse argument values
1588
+ *
1589
+ * @param array $out
1590
+ *
1591
+ * @return boolean
1592
+ */
1593
+ protected function argValues(&$out)
1594
+ {
1595
+ if ($this->genericList($list, 'argValue', ',', false)) {
1596
+ $out = $list[2];
1597
+
1598
+ return true;
1599
+ }
1600
+
1601
+ return false;
1602
+ }
1603
+
1604
+ /**
1605
+ * Parse argument value
1606
+ *
1607
+ * @param array $out
1608
+ *
1609
+ * @return boolean
1610
+ */
1611
+ protected function argValue(&$out)
1612
+ {
1613
+ $s = $this->count;
1614
+
1615
+ $keyword = null;
1616
+
1617
+ if (! $this->variable($keyword) || ! $this->matchChar(':')) {
1618
+ $this->seek($s);
1619
+
1620
+ $keyword = null;
1621
+ }
1622
+
1623
+ if ($this->genericList($value, 'expression')) {
1624
+ $out = [$keyword, $value, false];
1625
+ $s = $this->count;
1626
+
1627
+ if ($this->literal('...', 3)) {
1628
+ $out[2] = true;
1629
+ } else {
1630
+ $this->seek($s);
1631
+ }
1632
+
1633
+ return true;
1634
+ }
1635
+
1636
+ return false;
1637
+ }
1638
+
1639
+ /**
1640
+ * Parse directive value list that considers $vars as keyword
1641
+ *
1642
+ * @param array $out
1643
+ * @param boolean|string $endChar
1644
+ *
1645
+ * @return boolean
1646
+ */
1647
+ protected function directiveValue(&$out, $endChar = false)
1648
+ {
1649
+ $s = $this->count;
1650
+
1651
+ if ($this->variable($out)) {
1652
+ if ($endChar && $this->matchChar($endChar, false)) {
1653
+ return true;
1654
+ }
1655
+
1656
+ if (! $endChar && $this->end()) {
1657
+ return true;
1658
+ }
1659
+ }
1660
+
1661
+ $this->seek($s);
1662
+
1663
+ if ($endChar and $this->openString($endChar, $out)) {
1664
+ if ($this->matchChar($endChar, false)) {
1665
+ return true;
1666
+ }
1667
+ }
1668
+
1669
+ $this->seek($s);
1670
+
1671
+ $allowVars = $this->allowVars;
1672
+ $this->allowVars = false;
1673
+
1674
+ $res = $this->genericList($out, 'spaceList', ',');
1675
+ $this->allowVars = $allowVars;
1676
+
1677
+ if ($res) {
1678
+ if ($endChar && $this->matchChar($endChar, false)) {
1679
+ return true;
1680
+ }
1681
+
1682
+ if (! $endChar && $this->end()) {
1683
+ return true;
1684
+ }
1685
+ }
1686
+
1687
+ $this->seek($s);
1688
+
1689
+ if ($endChar && $this->matchChar($endChar, false)) {
1690
+ return true;
1691
+ }
1692
+
1693
+ return false;
1694
+ }
1695
+
1696
+ /**
1697
+ * Parse comma separated value list
1698
+ *
1699
+ * @param array $out
1700
+ *
1701
+ * @return boolean
1702
+ */
1703
+ protected function valueList(&$out)
1704
+ {
1705
+ $discardComments = $this->discardComments;
1706
+ $this->discardComments = true;
1707
+ $res = $this->genericList($out, 'spaceList', ',');
1708
+ $this->discardComments = $discardComments;
1709
+
1710
+ return $res;
1711
+ }
1712
+
1713
+ /**
1714
+ * Parse space separated value list
1715
+ *
1716
+ * @param array $out
1717
+ *
1718
+ * @return boolean
1719
+ */
1720
+ protected function spaceList(&$out)
1721
+ {
1722
+ return $this->genericList($out, 'expression');
1723
+ }
1724
+
1725
+ /**
1726
+ * Parse generic list
1727
+ *
1728
+ * @param array $out
1729
+ * @param callable $parseItem
1730
+ * @param string $delim
1731
+ * @param boolean $flatten
1732
+ *
1733
+ * @return boolean
1734
+ */
1735
+ protected function genericList(&$out, $parseItem, $delim = '', $flatten = true)
1736
+ {
1737
+ $s = $this->count;
1738
+ $items = [];
1739
+ $value = null;
1740
+
1741
+ while ($this->$parseItem($value)) {
1742
+ $trailing_delim = false;
1743
+ $items[] = $value;
1744
+
1745
+ if ($delim) {
1746
+ if (! $this->literal($delim, \strlen($delim))) {
1747
+ break;
1748
+ }
1749
+
1750
+ $trailing_delim = true;
1751
+ }
1752
+ }
1753
+
1754
+ if (! $items) {
1755
+ $this->seek($s);
1756
+
1757
+ return false;
1758
+ }
1759
+
1760
+ if ($trailing_delim) {
1761
+ $items[] = [Type::T_NULL];
1762
+ }
1763
+
1764
+ if ($flatten && \count($items) === 1) {
1765
+ $out = $items[0];
1766
+ } else {
1767
+ $out = [Type::T_LIST, $delim, $items];
1768
+ }
1769
+
1770
+ return true;
1771
+ }
1772
+
1773
+ /**
1774
+ * Parse expression
1775
+ *
1776
+ * @param array $out
1777
+ * @param boolean $listOnly
1778
+ * @param boolean $lookForExp
1779
+ *
1780
+ * @return boolean
1781
+ */
1782
+ protected function expression(&$out, $listOnly = false, $lookForExp = true)
1783
+ {
1784
+ $s = $this->count;
1785
+ $discard = $this->discardComments;
1786
+ $this->discardComments = true;
1787
+ $allowedTypes = ($listOnly ? [Type::T_LIST] : [Type::T_LIST, Type::T_MAP]);
1788
+
1789
+ if ($this->matchChar('(')) {
1790
+ if ($this->enclosedExpression($lhs, $s, ")", $allowedTypes)) {
1791
+ if ($lookForExp) {
1792
+ $out = $this->expHelper($lhs, 0);
1793
+ } else {
1794
+ $out = $lhs;
1795
+ }
1796
+
1797
+ $this->discardComments = $discard;
1798
+
1799
+ return true;
1800
+ }
1801
+
1802
+ $this->seek($s);
1803
+ }
1804
+
1805
+ if (\in_array(Type::T_LIST, $allowedTypes) && $this->matchChar('[')) {
1806
+ if ($this->enclosedExpression($lhs, $s, "]", [Type::T_LIST])) {
1807
+ if ($lookForExp) {
1808
+ $out = $this->expHelper($lhs, 0);
1809
+ } else {
1810
+ $out = $lhs;
1811
+ }
1812
+
1813
+ $this->discardComments = $discard;
1814
+
1815
+ return true;
1816
+ }
1817
+
1818
+ $this->seek($s);
1819
+ }
1820
+
1821
+ if (! $listOnly && $this->value($lhs)) {
1822
+ if ($lookForExp) {
1823
+ $out = $this->expHelper($lhs, 0);
1824
+ } else {
1825
+ $out = $lhs;
1826
+ }
1827
+
1828
+ $this->discardComments = $discard;
1829
+
1830
+ return true;
1831
+ }
1832
+
1833
+ $this->discardComments = $discard;
1834
+
1835
+ return false;
1836
+ }
1837
+
1838
+ /**
1839
+ * Parse expression specifically checking for lists in parenthesis or brackets
1840
+ *
1841
+ * @param array $out
1842
+ * @param integer $s
1843
+ * @param string $closingParen
1844
+ * @param array $allowedTypes
1845
+ *
1846
+ * @return boolean
1847
+ */
1848
+ protected function enclosedExpression(&$out, $s, $closingParen = ")", $allowedTypes = [Type::T_LIST, Type::T_MAP])
1849
+ {
1850
+ if ($this->matchChar($closingParen) && \in_array(Type::T_LIST, $allowedTypes)) {
1851
+ $out = [Type::T_LIST, '', []];
1852
+
1853
+ switch ($closingParen) {
1854
+ case ")":
1855
+ $out['enclosing'] = 'parent'; // parenthesis list
1856
+ break;
1857
+
1858
+ case "]":
1859
+ $out['enclosing'] = 'bracket'; // bracketed list
1860
+ break;
1861
+ }
1862
+
1863
+ return true;
1864
+ }
1865
+
1866
+ if ($this->valueList($out) && $this->matchChar($closingParen) &&
1867
+ \in_array($out[0], [Type::T_LIST, Type::T_KEYWORD]) &&
1868
+ \in_array(Type::T_LIST, $allowedTypes)
1869
+ ) {
1870
+ if ($out[0] !== Type::T_LIST || ! empty($out['enclosing'])) {
1871
+ $out = [Type::T_LIST, '', [$out]];
1872
+ }
1873
+
1874
+ switch ($closingParen) {
1875
+ case ")":
1876
+ $out['enclosing'] = 'parent'; // parenthesis list
1877
+ break;
1878
+
1879
+ case "]":
1880
+ $out['enclosing'] = 'bracket'; // bracketed list
1881
+ break;
1882
+ }
1883
+
1884
+ return true;
1885
+ }
1886
+
1887
+ $this->seek($s);
1888
+
1889
+ if (\in_array(Type::T_MAP, $allowedTypes) && $this->map($out)) {
1890
+ return true;
1891
+ }
1892
+
1893
+ return false;
1894
+ }
1895
+
1896
+ /**
1897
+ * Parse left-hand side of subexpression
1898
+ *
1899
+ * @param array $lhs
1900
+ * @param integer $minP
1901
+ *
1902
+ * @return array
1903
+ */
1904
+ protected function expHelper($lhs, $minP)
1905
+ {
1906
+ $operators = static::$operatorPattern;
1907
+
1908
+ $ss = $this->count;
1909
+ $whiteBefore = isset($this->buffer[$this->count - 1]) &&
1910
+ ctype_space($this->buffer[$this->count - 1]);
1911
+
1912
+ while ($this->match($operators, $m, false) && static::$precedence[$m[1]] >= $minP) {
1913
+ $whiteAfter = isset($this->buffer[$this->count]) &&
1914
+ ctype_space($this->buffer[$this->count]);
1915
+ $varAfter = isset($this->buffer[$this->count]) &&
1916
+ $this->buffer[$this->count] === '$';
1917
+
1918
+ $this->whitespace();
1919
+
1920
+ $op = $m[1];
1921
+
1922
+ // don't turn negative numbers into expressions
1923
+ if ($op === '-' && $whiteBefore && ! $whiteAfter && ! $varAfter) {
1924
+ break;
1925
+ }
1926
+
1927
+ if (! $this->value($rhs) && ! $this->expression($rhs, true, false)) {
1928
+ break;
1929
+ }
1930
+
1931
+ // peek and see if rhs belongs to next operator
1932
+ if ($this->peek($operators, $next) && static::$precedence[$next[1]] > static::$precedence[$op]) {
1933
+ $rhs = $this->expHelper($rhs, static::$precedence[$next[1]]);
1934
+ }
1935
+
1936
+ $lhs = [Type::T_EXPRESSION, $op, $lhs, $rhs, $this->inParens, $whiteBefore, $whiteAfter];
1937
+ $ss = $this->count;
1938
+ $whiteBefore = isset($this->buffer[$this->count - 1]) &&
1939
+ ctype_space($this->buffer[$this->count - 1]);
1940
+ }
1941
+
1942
+ $this->seek($ss);
1943
+
1944
+ return $lhs;
1945
+ }
1946
+
1947
+ /**
1948
+ * Parse value
1949
+ *
1950
+ * @param array $out
1951
+ *
1952
+ * @return boolean
1953
+ */
1954
+ protected function value(&$out)
1955
+ {
1956
+ if (! isset($this->buffer[$this->count])) {
1957
+ return false;
1958
+ }
1959
+
1960
+ $s = $this->count;
1961
+ $char = $this->buffer[$this->count];
1962
+
1963
+ if ($this->literal('url(', 4) && $this->match('data:([a-z]+)\/([a-z0-9.+-]+);base64,', $m, false)) {
1964
+ $len = strspn(
1965
+ $this->buffer,
1966
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwyxz0123456789+/=',
1967
+ $this->count
1968
+ );
1969
+
1970
+ $this->count += $len;
1971
+
1972
+ if ($this->matchChar(')')) {
1973
+ $content = substr($this->buffer, $s, $this->count - $s);
1974
+ $out = [Type::T_KEYWORD, $content];
1975
+
1976
+ return true;
1977
+ }
1978
+ }
1979
+
1980
+ $this->seek($s);
1981
+
1982
+ if ($this->literal('url(', 4, false) && $this->match('\s*(\/\/[^\s\)]+)\s*', $m)) {
1983
+ $content = 'url(' . $m[1];
1984
+
1985
+ if ($this->matchChar(')')) {
1986
+ $content .= ')';
1987
+ $out = [Type::T_KEYWORD, $content];
1988
+
1989
+ return true;
1990
+ }
1991
+ }
1992
+
1993
+ $this->seek($s);
1994
+
1995
+ // not
1996
+ if ($char === 'n' && $this->literal('not', 3, false)) {
1997
+ if ($this->whitespace() && $this->value($inner)) {
1998
+ $out = [Type::T_UNARY, 'not', $inner, $this->inParens];
1999
+
2000
+ return true;
2001
+ }
2002
+
2003
+ $this->seek($s);
2004
+
2005
+ if ($this->parenValue($inner)) {
2006
+ $out = [Type::T_UNARY, 'not', $inner, $this->inParens];
2007
+
2008
+ return true;
2009
+ }
2010
+
2011
+ $this->seek($s);
2012
+ }
2013
+
2014
+ // addition
2015
+ if ($char === '+') {
2016
+ $this->count++;
2017
+
2018
+ $follow_white = $this->whitespace();
2019
+
2020
+ if ($this->value($inner)) {
2021
+ $out = [Type::T_UNARY, '+', $inner, $this->inParens];
2022
+
2023
+ return true;
2024
+ }
2025
+
2026
+ if ($follow_white) {
2027
+ $out = [Type::T_KEYWORD, $char];
2028
+ return true;
2029
+ }
2030
+
2031
+ $this->seek($s);
2032
+
2033
+ return false;
2034
+ }
2035
+
2036
+ // negation
2037
+ if ($char === '-') {
2038
+ if ($this->customProperty($out)) {
2039
+ return true;
2040
+ }
2041
+
2042
+ $this->count++;
2043
+
2044
+ $follow_white = $this->whitespace();
2045
+
2046
+ if ($this->variable($inner) || $this->unit($inner) || $this->parenValue($inner)) {
2047
+ $out = [Type::T_UNARY, '-', $inner, $this->inParens];
2048
+
2049
+ return true;
2050
+ }
2051
+
2052
+ if ($this->keyword($inner) && ! $this->func($inner, $out)) {
2053
+ $out = [Type::T_UNARY, '-', $inner, $this->inParens];
2054
+
2055
+ return true;
2056
+ }
2057
+
2058
+ if ($follow_white) {
2059
+ $out = [Type::T_KEYWORD, $char];
2060
+
2061
+ return true;
2062
+ }
2063
+
2064
+ $this->seek($s);
2065
+ }
2066
+
2067
+ // paren
2068
+ if ($char === '(' && $this->parenValue($out)) {
2069
+ return true;
2070
+ }
2071
+
2072
+ if ($char === '#') {
2073
+ if ($this->interpolation($out) || $this->color($out)) {
2074
+ return true;
2075
+ }
2076
+
2077
+ $this->count++;
2078
+
2079
+ if ($this->keyword($keyword)) {
2080
+ $out = [Type::T_KEYWORD, "#" . $keyword];
2081
+
2082
+ return true;
2083
+ }
2084
+
2085
+ $this->count--;
2086
+ }
2087
+
2088
+ if ($this->matchChar('&', true)) {
2089
+ $out = [Type::T_SELF];
2090
+
2091
+ return true;
2092
+ }
2093
+
2094
+ if ($char === '$' && $this->variable($out)) {
2095
+ return true;
2096
+ }
2097
+
2098
+ if ($char === 'p' && $this->progid($out)) {
2099
+ return true;
2100
+ }
2101
+
2102
+ if (($char === '"' || $char === "'") && $this->string($out)) {
2103
+ return true;
2104
+ }
2105
+
2106
+ if ($this->unit($out)) {
2107
+ return true;
2108
+ }
2109
+
2110
+ // unicode range with wildcards
2111
+ if ($this->literal('U+', 2) && $this->match('([0-9A-F]+\?*)(-([0-9A-F]+))?', $m, false)) {
2112
+ $out = [Type::T_KEYWORD, 'U+' . $m[0]];
2113
+
2114
+ return true;
2115
+ }
2116
+
2117
+ if ($this->keyword($keyword, false)) {
2118
+ if ($this->func($keyword, $out)) {
2119
+ return true;
2120
+ }
2121
+
2122
+ $this->whitespace();
2123
+
2124
+ if ($keyword === 'null') {
2125
+ $out = [Type::T_NULL];
2126
+ } else {
2127
+ $out = [Type::T_KEYWORD, $keyword];
2128
+ }
2129
+
2130
+ return true;
2131
+ }
2132
+
2133
+ return false;
2134
+ }
2135
+
2136
+ /**
2137
+ * Parse parenthesized value
2138
+ *
2139
+ * @param array $out
2140
+ *
2141
+ * @return boolean
2142
+ */
2143
+ protected function parenValue(&$out)
2144
+ {
2145
+ $s = $this->count;
2146
+
2147
+ $inParens = $this->inParens;
2148
+
2149
+ if ($this->matchChar('(')) {
2150
+ if ($this->matchChar(')')) {
2151
+ $out = [Type::T_LIST, '', []];
2152
+
2153
+ return true;
2154
+ }
2155
+
2156
+ $this->inParens = true;
2157
+
2158
+ if ($this->expression($exp) && $this->matchChar(')')) {
2159
+ $out = $exp;
2160
+ $this->inParens = $inParens;
2161
+
2162
+ return true;
2163
+ }
2164
+ }
2165
+
2166
+ $this->inParens = $inParens;
2167
+ $this->seek($s);
2168
+
2169
+ return false;
2170
+ }
2171
+
2172
+ /**
2173
+ * Parse "progid:"
2174
+ *
2175
+ * @param array $out
2176
+ *
2177
+ * @return boolean
2178
+ */
2179
+ protected function progid(&$out)
2180
+ {
2181
+ $s = $this->count;
2182
+
2183
+ if ($this->literal('progid:', 7, false) &&
2184
+ $this->openString('(', $fn) &&
2185
+ $this->matchChar('(')
2186
+ ) {
2187
+ $this->openString(')', $args, '(');
2188
+
2189
+ if ($this->matchChar(')')) {
2190
+ $out = [Type::T_STRING, '', [
2191
+ 'progid:', $fn, '(', $args, ')'
2192
+ ]];
2193
+
2194
+ return true;
2195
+ }
2196
+ }
2197
+
2198
+ $this->seek($s);
2199
+
2200
+ return false;
2201
+ }
2202
+
2203
+ /**
2204
+ * Parse function call
2205
+ *
2206
+ * @param string $name
2207
+ * @param array $func
2208
+ *
2209
+ * @return boolean
2210
+ */
2211
+ protected function func($name, &$func)
2212
+ {
2213
+ $s = $this->count;
2214
+
2215
+ if ($this->matchChar('(')) {
2216
+ if ($name === 'alpha' && $this->argumentList($args)) {
2217
+ $func = [Type::T_FUNCTION, $name, [Type::T_STRING, '', $args]];
2218
+
2219
+ return true;
2220
+ }
2221
+
2222
+ if ($name !== 'expression' && ! preg_match('/^(-[a-z]+-)?calc$/', $name)) {
2223
+ $ss = $this->count;
2224
+
2225
+ if ($this->argValues($args) && $this->matchChar(')')) {
2226
+ $func = [Type::T_FUNCTION_CALL, $name, $args];
2227
+
2228
+ return true;
2229
+ }
2230
+
2231
+ $this->seek($ss);
2232
+ }
2233
+
2234
+ if (($this->openString(')', $str, '(') || true) &&
2235
+ $this->matchChar(')')
2236
+ ) {
2237
+ $args = [];
2238
+
2239
+ if (! empty($str)) {
2240
+ $args[] = [null, [Type::T_STRING, '', [$str]]];
2241
+ }
2242
+
2243
+ $func = [Type::T_FUNCTION_CALL, $name, $args];
2244
+
2245
+ return true;
2246
+ }
2247
+ }
2248
+
2249
+ $this->seek($s);
2250
+
2251
+ return false;
2252
+ }
2253
+
2254
+ /**
2255
+ * Parse function call argument list
2256
+ *
2257
+ * @param array $out
2258
+ *
2259
+ * @return boolean
2260
+ */
2261
+ protected function argumentList(&$out)
2262
+ {
2263
+ $s = $this->count;
2264
+ $this->matchChar('(');
2265
+
2266
+ $args = [];
2267
+
2268
+ while ($this->keyword($var)) {
2269
+ if ($this->matchChar('=') && $this->expression($exp)) {
2270
+ $args[] = [Type::T_STRING, '', [$var . '=']];
2271
+ $arg = $exp;
2272
+ } else {
2273
+ break;
2274
+ }
2275
+
2276
+ $args[] = $arg;
2277
+
2278
+ if (! $this->matchChar(',')) {
2279
+ break;
2280
+ }
2281
+
2282
+ $args[] = [Type::T_STRING, '', [', ']];
2283
+ }
2284
+
2285
+ if (! $this->matchChar(')') || ! $args) {
2286
+ $this->seek($s);
2287
+
2288
+ return false;
2289
+ }
2290
+
2291
+ $out = $args;
2292
+
2293
+ return true;
2294
+ }
2295
+
2296
+ /**
2297
+ * Parse mixin/function definition argument list
2298
+ *
2299
+ * @param array $out
2300
+ *
2301
+ * @return boolean
2302
+ */
2303
+ protected function argumentDef(&$out)
2304
+ {
2305
+ $s = $this->count;
2306
+ $this->matchChar('(');
2307
+
2308
+ $args = [];
2309
+
2310
+ while ($this->variable($var)) {
2311
+ $arg = [$var[1], null, false];
2312
+
2313
+ $ss = $this->count;
2314
+
2315
+ if ($this->matchChar(':') && $this->genericList($defaultVal, 'expression')) {
2316
+ $arg[1] = $defaultVal;
2317
+ } else {
2318
+ $this->seek($ss);
2319
+ }
2320
+
2321
+ $ss = $this->count;
2322
+
2323
+ if ($this->literal('...', 3)) {
2324
+ $sss = $this->count;
2325
+
2326
+ if (! $this->matchChar(')')) {
2327
+ $this->throwParseError('... has to be after the final argument');
2328
+ }
2329
+
2330
+ $arg[2] = true;
2331
+
2332
+ $this->seek($sss);
2333
+ } else {
2334
+ $this->seek($ss);
2335
+ }
2336
+
2337
+ $args[] = $arg;
2338
+
2339
+ if (! $this->matchChar(',')) {
2340
+ break;
2341
+ }
2342
+ }
2343
+
2344
+ if (! $this->matchChar(')')) {
2345
+ $this->seek($s);
2346
+
2347
+ return false;
2348
+ }
2349
+
2350
+ $out = $args;
2351
+
2352
+ return true;
2353
+ }
2354
+
2355
+ /**
2356
+ * Parse map
2357
+ *
2358
+ * @param array $out
2359
+ *
2360
+ * @return boolean
2361
+ */
2362
+ protected function map(&$out)
2363
+ {
2364
+ $s = $this->count;
2365
+
2366
+ if (! $this->matchChar('(')) {
2367
+ return false;
2368
+ }
2369
+
2370
+ $keys = [];
2371
+ $values = [];
2372
+
2373
+ while ($this->genericList($key, 'expression') && $this->matchChar(':') &&
2374
+ $this->genericList($value, 'expression')
2375
+ ) {
2376
+ $keys[] = $key;
2377
+ $values[] = $value;
2378
+
2379
+ if (! $this->matchChar(',')) {
2380
+ break;
2381
+ }
2382
+ }
2383
+
2384
+ if (! $keys || ! $this->matchChar(')')) {
2385
+ $this->seek($s);
2386
+
2387
+ return false;
2388
+ }
2389
+
2390
+ $out = [Type::T_MAP, $keys, $values];
2391
+
2392
+ return true;
2393
+ }
2394
+
2395
+ /**
2396
+ * Parse color
2397
+ *
2398
+ * @param array $out
2399
+ *
2400
+ * @return boolean
2401
+ */
2402
+ protected function color(&$out)
2403
+ {
2404
+ $s = $this->count;
2405
+
2406
+ if ($this->match('(#([0-9a-f]+))', $m)) {
2407
+ if (\in_array(\strlen($m[2]), [3,4,6,8])) {
2408
+ $out = [Type::T_KEYWORD, $m[0]];
2409
+
2410
+ return true;
2411
+ }
2412
+
2413
+ $this->seek($s);
2414
+
2415
+ return false;
2416
+ }
2417
+
2418
+ return false;
2419
+ }
2420
+
2421
+ /**
2422
+ * Parse number with unit
2423
+ *
2424
+ * @param array $unit
2425
+ *
2426
+ * @return boolean
2427
+ */
2428
+ protected function unit(&$unit)
2429
+ {
2430
+ $s = $this->count;
2431
+
2432
+ if ($this->match('([0-9]*(\.)?[0-9]+)([%a-zA-Z]+)?', $m, false)) {
2433
+ if (\strlen($this->buffer) === $this->count || ! ctype_digit($this->buffer[$this->count])) {
2434
+ $this->whitespace();
2435
+
2436
+ $unit = new Node\Number($m[1], empty($m[3]) ? '' : $m[3]);
2437
+
2438
+ return true;
2439
+ }
2440
+
2441
+ $this->seek($s);
2442
+ }
2443
+
2444
+ return false;
2445
+ }
2446
+
2447
+ /**
2448
+ * Parse string
2449
+ *
2450
+ * @param array $out
2451
+ *
2452
+ * @return boolean
2453
+ */
2454
+ protected function string(&$out)
2455
+ {
2456
+ $s = $this->count;
2457
+
2458
+ if ($this->matchChar('"', false)) {
2459
+ $delim = '"';
2460
+ } elseif ($this->matchChar("'", false)) {
2461
+ $delim = "'";
2462
+ } else {
2463
+ return false;
2464
+ }
2465
+
2466
+ $content = [];
2467
+ $oldWhite = $this->eatWhiteDefault;
2468
+ $this->eatWhiteDefault = false;
2469
+ $hasInterpolation = false;
2470
+
2471
+ while ($this->matchString($m, $delim)) {
2472
+ if ($m[1] !== '') {
2473
+ $content[] = $m[1];
2474
+ }
2475
+
2476
+ if ($m[2] === '#{') {
2477
+ $this->count -= \strlen($m[2]);
2478
+
2479
+ if ($this->interpolation($inter, false)) {
2480
+ $content[] = $inter;
2481
+ $hasInterpolation = true;
2482
+ } else {
2483
+ $this->count += \strlen($m[2]);
2484
+ $content[] = '#{'; // ignore it
2485
+ }
2486
+ } elseif ($m[2] === '\\') {
2487
+ if ($this->matchChar('"', false)) {
2488
+ $content[] = $m[2] . '"';
2489
+ } elseif ($this->matchChar("'", false)) {
2490
+ $content[] = $m[2] . "'";
2491
+ } elseif ($this->literal("\\", 1, false)) {
2492
+ $content[] = $m[2] . "\\";
2493
+ } elseif ($this->literal("\r\n", 2, false) ||
2494
+ $this->matchChar("\r", false) ||
2495
+ $this->matchChar("\n", false) ||
2496
+ $this->matchChar("\f", false)
2497
+ ) {
2498
+ // this is a continuation escaping, to be ignored
2499
+ } else {
2500
+ $content[] = $m[2];
2501
+ }
2502
+ } else {
2503
+ $this->count -= \strlen($delim);
2504
+ break; // delim
2505
+ }
2506
+ }
2507
+
2508
+ $this->eatWhiteDefault = $oldWhite;
2509
+
2510
+ if ($this->literal($delim, \strlen($delim))) {
2511
+ if ($hasInterpolation) {
2512
+ $delim = '"';
2513
+
2514
+ foreach ($content as &$string) {
2515
+ if ($string === "\\\\") {
2516
+ $string = "\\";
2517
+ } elseif ($string === "\\'") {
2518
+ $string = "'";
2519
+ } elseif ($string === '\\"') {
2520
+ $string = '"';
2521
+ }
2522
+ }
2523
+ }
2524
+
2525
+ $out = [Type::T_STRING, $delim, $content];
2526
+
2527
+ return true;
2528
+ }
2529
+
2530
+ $this->seek($s);
2531
+
2532
+ return false;
2533
+ }
2534
+
2535
+ /**
2536
+ * Parse keyword or interpolation
2537
+ *
2538
+ * @param array $out
2539
+ * @param boolean $restricted
2540
+ *
2541
+ * @return boolean
2542
+ */
2543
+ protected function mixedKeyword(&$out, $restricted = false)
2544
+ {
2545
+ $parts = [];
2546
+
2547
+ $oldWhite = $this->eatWhiteDefault;
2548
+ $this->eatWhiteDefault = false;
2549
+
2550
+ for (;;) {
2551
+ if ($restricted ? $this->restrictedKeyword($key) : $this->keyword($key)) {
2552
+ $parts[] = $key;
2553
+ continue;
2554
+ }
2555
+
2556
+ if ($this->interpolation($inter)) {
2557
+ $parts[] = $inter;
2558
+ continue;
2559
+ }
2560
+
2561
+ break;
2562
+ }
2563
+
2564
+ $this->eatWhiteDefault = $oldWhite;
2565
+
2566
+ if (! $parts) {
2567
+ return false;
2568
+ }
2569
+
2570
+ if ($this->eatWhiteDefault) {
2571
+ $this->whitespace();
2572
+ }
2573
+
2574
+ $out = $parts;
2575
+
2576
+ return true;
2577
+ }
2578
+
2579
+ /**
2580
+ * Parse an unbounded string stopped by $end
2581
+ *
2582
+ * @param string $end
2583
+ * @param array $out
2584
+ * @param string $nestingOpen
2585
+ * @param string $nestingClose
2586
+ * @param boolean $trimEnd
2587
+ *
2588
+ * @return boolean
2589
+ */
2590
+ protected function openString($end, &$out, $nestingOpen = null, $nestingClose = null, $trimEnd = true)
2591
+ {
2592
+ $oldWhite = $this->eatWhiteDefault;
2593
+ $this->eatWhiteDefault = false;
2594
+
2595
+ if ($nestingOpen && ! $nestingClose) {
2596
+ $nestingClose = $end;
2597
+ }
2598
+
2599
+ $patt = '(.*?)([\'"]|#\{|'
2600
+ . $this->pregQuote($end) . '|'
2601
+ . (($nestingClose && $nestingClose !== $end) ? $this->pregQuote($nestingClose) . '|' : '')
2602
+ . static::$commentPattern . ')';
2603
+
2604
+ $nestingLevel = 0;
2605
+
2606
+ $content = [];
2607
+
2608
+ while ($this->match($patt, $m, false)) {
2609
+ if (isset($m[1]) && $m[1] !== '') {
2610
+ $content[] = $m[1];
2611
+
2612
+ if ($nestingOpen) {
2613
+ $nestingLevel += substr_count($m[1], $nestingOpen);
2614
+ }
2615
+ }
2616
+
2617
+ $tok = $m[2];
2618
+
2619
+ $this->count-= \strlen($tok);
2620
+
2621
+ if ($tok === $end && ! $nestingLevel) {
2622
+ break;
2623
+ }
2624
+
2625
+ if ($tok === $nestingClose) {
2626
+ $nestingLevel--;
2627
+ }
2628
+
2629
+ if (($tok === "'" || $tok === '"') && $this->string($str)) {
2630
+ $content[] = $str;
2631
+ continue;
2632
+ }
2633
+
2634
+ if ($tok === '#{' && $this->interpolation($inter)) {
2635
+ $content[] = $inter;
2636
+ continue;
2637
+ }
2638
+
2639
+ $content[] = $tok;
2640
+ $this->count+= \strlen($tok);
2641
+ }
2642
+
2643
+ $this->eatWhiteDefault = $oldWhite;
2644
+
2645
+ if (! $content || $tok !== $end) {
2646
+ return false;
2647
+ }
2648
+
2649
+ // trim the end
2650
+ if ($trimEnd && \is_string(end($content))) {
2651
+ $content[\count($content) - 1] = rtrim(end($content));
2652
+ }
2653
+
2654
+ $out = [Type::T_STRING, '', $content];
2655
+
2656
+ return true;
2657
+ }
2658
+
2659
+ /**
2660
+ * Parser interpolation
2661
+ *
2662
+ * @param string|array $out
2663
+ * @param boolean $lookWhite save information about whitespace before and after
2664
+ *
2665
+ * @return boolean
2666
+ */
2667
+ protected function interpolation(&$out, $lookWhite = true)
2668
+ {
2669
+ $oldWhite = $this->eatWhiteDefault;
2670
+ $allowVars = $this->allowVars;
2671
+ $this->allowVars = true;
2672
+ $this->eatWhiteDefault = true;
2673
+
2674
+ $s = $this->count;
2675
+
2676
+ if ($this->literal('#{', 2) && $this->valueList($value) && $this->matchChar('}', false)) {
2677
+ if ($value === [Type::T_SELF]) {
2678
+ $out = $value;
2679
+ } else {
2680
+ if ($lookWhite) {
2681
+ $left = ($s > 0 && preg_match('/\s/', $this->buffer[$s - 1])) ? ' ' : '';
2682
+ $right = preg_match('/\s/', $this->buffer[$this->count]) ? ' ': '';
2683
+ } else {
2684
+ $left = $right = false;
2685
+ }
2686
+
2687
+ $out = [Type::T_INTERPOLATE, $value, $left, $right];
2688
+ }
2689
+
2690
+ $this->eatWhiteDefault = $oldWhite;
2691
+ $this->allowVars = $allowVars;
2692
+
2693
+ if ($this->eatWhiteDefault) {
2694
+ $this->whitespace();
2695
+ }
2696
+
2697
+ return true;
2698
+ }
2699
+
2700
+ $this->seek($s);
2701
+
2702
+ $this->eatWhiteDefault = $oldWhite;
2703
+ $this->allowVars = $allowVars;
2704
+
2705
+ return false;
2706
+ }
2707
+
2708
+ /**
2709
+ * Parse property name (as an array of parts or a string)
2710
+ *
2711
+ * @param array $out
2712
+ *
2713
+ * @return boolean
2714
+ */
2715
+ protected function propertyName(&$out)
2716
+ {
2717
+ $parts = [];
2718
+
2719
+ $oldWhite = $this->eatWhiteDefault;
2720
+ $this->eatWhiteDefault = false;
2721
+
2722
+ for (;;) {
2723
+ if ($this->interpolation($inter)) {
2724
+ $parts[] = $inter;
2725
+ continue;
2726
+ }
2727
+
2728
+ if ($this->keyword($text)) {
2729
+ $parts[] = $text;
2730
+ continue;
2731
+ }
2732
+
2733
+ if (! $parts && $this->match('[:.#]', $m, false)) {
2734
+ // css hacks
2735
+ $parts[] = $m[0];
2736
+ continue;
2737
+ }
2738
+
2739
+ break;
2740
+ }
2741
+
2742
+ $this->eatWhiteDefault = $oldWhite;
2743
+
2744
+ if (! $parts) {
2745
+ return false;
2746
+ }
2747
+
2748
+ // match comment hack
2749
+ if (preg_match(static::$whitePattern, $this->buffer, $m, null, $this->count)) {
2750
+ if (! empty($m[0])) {
2751
+ $parts[] = $m[0];
2752
+ $this->count += \strlen($m[0]);
2753
+ }
2754
+ }
2755
+
2756
+ $this->whitespace(); // get any extra whitespace
2757
+
2758
+ $out = [Type::T_STRING, '', $parts];
2759
+
2760
+ return true;
2761
+ }
2762
+
2763
+ /**
2764
+ * Parse custom property name (as an array of parts or a string)
2765
+ *
2766
+ * @param array $out
2767
+ *
2768
+ * @return boolean
2769
+ */
2770
+ protected function customProperty(&$out)
2771
+ {
2772
+ $s = $this->count;
2773
+
2774
+ if (! $this->literal('--', 2, false)) {
2775
+ return false;
2776
+ }
2777
+
2778
+ $parts = ['--'];
2779
+
2780
+ $oldWhite = $this->eatWhiteDefault;
2781
+ $this->eatWhiteDefault = false;
2782
+
2783
+ for (;;) {
2784
+ if ($this->interpolation($inter)) {
2785
+ $parts[] = $inter;
2786
+ continue;
2787
+ }
2788
+
2789
+ if ($this->variable($var)) {
2790
+ $parts[] = $var;
2791
+ continue;
2792
+ }
2793
+
2794
+ if ($this->keyword($text)) {
2795
+ $parts[] = $text;
2796
+ continue;
2797
+ }
2798
+
2799
+ break;
2800
+ }
2801
+
2802
+ $this->eatWhiteDefault = $oldWhite;
2803
+
2804
+ if (\count($parts) == 1) {
2805
+ $this->seek($s);
2806
+
2807
+ return false;
2808
+ }
2809
+
2810
+ $this->whitespace(); // get any extra whitespace
2811
+
2812
+ $out = [Type::T_STRING, '', $parts];
2813
+
2814
+ return true;
2815
+ }
2816
+
2817
+ /**
2818
+ * Parse comma separated selector list
2819
+ *
2820
+ * @param array $out
2821
+ * @param boolean $subSelector
2822
+ *
2823
+ * @return boolean
2824
+ */
2825
+ protected function selectors(&$out, $subSelector = false)
2826
+ {
2827
+ $s = $this->count;
2828
+ $selectors = [];
2829
+
2830
+ while ($this->selector($sel, $subSelector)) {
2831
+ $selectors[] = $sel;
2832
+
2833
+ if (! $this->matchChar(',', true)) {
2834
+ break;
2835
+ }
2836
+
2837
+ while ($this->matchChar(',', true)) {
2838
+ ; // ignore extra
2839
+ }
2840
+ }
2841
+
2842
+ if (! $selectors) {
2843
+ $this->seek($s);
2844
+
2845
+ return false;
2846
+ }
2847
+
2848
+ $out = $selectors;
2849
+
2850
+ return true;
2851
+ }
2852
+
2853
+ /**
2854
+ * Parse whitespace separated selector list
2855
+ *
2856
+ * @param array $out
2857
+ * @param boolean $subSelector
2858
+ *
2859
+ * @return boolean
2860
+ */
2861
+ protected function selector(&$out, $subSelector = false)
2862
+ {
2863
+ $selector = [];
2864
+
2865
+ for (;;) {
2866
+ $s = $this->count;
2867
+
2868
+ if ($this->match('[>+~]+', $m, true)) {
2869
+ if ($subSelector && \is_string($subSelector) && strpos($subSelector, 'nth-') === 0 &&
2870
+ $m[0] === '+' && $this->match("(\d+|n\b)", $counter)
2871
+ ) {
2872
+ $this->seek($s);
2873
+ } else {
2874
+ $selector[] = [$m[0]];
2875
+ continue;
2876
+ }
2877
+ }
2878
+
2879
+ if ($this->selectorSingle($part, $subSelector)) {
2880
+ $selector[] = $part;
2881
+ $this->match('\s+', $m);
2882
+ continue;
2883
+ }
2884
+
2885
+ if ($this->match('\/[^\/]+\/', $m, true)) {
2886
+ $selector[] = [$m[0]];
2887
+ continue;
2888
+ }
2889
+
2890
+ break;
2891
+ }
2892
+
2893
+ if (! $selector) {
2894
+ return false;
2895
+ }
2896
+
2897
+ $out = $selector;
2898
+
2899
+ return true;
2900
+ }
2901
+
2902
+ /**
2903
+ * Parse the parts that make up a selector
2904
+ *
2905
+ * {@internal
2906
+ * div[yes=no]#something.hello.world:nth-child(-2n+1)%placeholder
2907
+ * }}
2908
+ *
2909
+ * @param array $out
2910
+ * @param boolean $subSelector
2911
+ *
2912
+ * @return boolean
2913
+ */
2914
+ protected function selectorSingle(&$out, $subSelector = false)
2915
+ {
2916
+ $oldWhite = $this->eatWhiteDefault;
2917
+ $this->eatWhiteDefault = false;
2918
+
2919
+ $parts = [];
2920
+
2921
+ if ($this->matchChar('*', false)) {
2922
+ $parts[] = '*';
2923
+ }
2924
+
2925
+ for (;;) {
2926
+ if (! isset($this->buffer[$this->count])) {
2927
+ break;
2928
+ }
2929
+
2930
+ $s = $this->count;
2931
+ $char = $this->buffer[$this->count];
2932
+
2933
+ // see if we can stop early
2934
+ if ($char === '{' || $char === ',' || $char === ';' || $char === '}' || $char === '@') {
2935
+ break;
2936
+ }
2937
+
2938
+ // parsing a sub selector in () stop with the closing )
2939
+ if ($subSelector && $char === ')') {
2940
+ break;
2941
+ }
2942
+
2943
+ //self
2944
+ switch ($char) {
2945
+ case '&':
2946
+ $parts[] = Compiler::$selfSelector;
2947
+ $this->count++;
2948
+ continue 2;
2949
+
2950
+ case '.':
2951
+ $parts[] = '.';
2952
+ $this->count++;
2953
+ continue 2;
2954
+
2955
+ case '|':
2956
+ $parts[] = '|';
2957
+ $this->count++;
2958
+ continue 2;
2959
+ }
2960
+
2961
+ if ($char === '\\' && $this->match('\\\\\S', $m)) {
2962
+ $parts[] = $m[0];
2963
+ continue;
2964
+ }
2965
+
2966
+ if ($char === '%') {
2967
+ $this->count++;
2968
+
2969
+ if ($this->placeholder($placeholder)) {
2970
+ $parts[] = '%';
2971
+ $parts[] = $placeholder;
2972
+ continue;
2973
+ }
2974
+
2975
+ break;
2976
+ }
2977
+
2978
+ if ($char === '#') {
2979
+ if ($this->interpolation($inter)) {
2980
+ $parts[] = $inter;
2981
+ continue;
2982
+ }
2983
+
2984
+ $parts[] = '#';
2985
+ $this->count++;
2986
+ continue;
2987
+ }
2988
+
2989
+ // a pseudo selector
2990
+ if ($char === ':') {
2991
+ if ($this->buffer[$this->count + 1] === ':') {
2992
+ $this->count += 2;
2993
+ $part = '::';
2994
+ } else {
2995
+ $this->count++;
2996
+ $part = ':';
2997
+ }
2998
+
2999
+ if ($this->mixedKeyword($nameParts, true)) {
3000
+ $parts[] = $part;
3001
+
3002
+ foreach ($nameParts as $sub) {
3003
+ $parts[] = $sub;
3004
+ }
3005
+
3006
+ $ss = $this->count;
3007
+
3008
+ if ($nameParts === ['not'] || $nameParts === ['is'] ||
3009
+ $nameParts === ['has'] || $nameParts === ['where'] ||
3010
+ $nameParts === ['slotted'] ||
3011
+ $nameParts === ['nth-child'] || $nameParts == ['nth-last-child'] ||
3012
+ $nameParts === ['nth-of-type'] || $nameParts == ['nth-last-of-type']
3013
+ ) {
3014
+ if ($this->matchChar('(', true) &&
3015
+ ($this->selectors($subs, reset($nameParts)) || true) &&
3016
+ $this->matchChar(')')
3017
+ ) {
3018
+ $parts[] = '(';
3019
+
3020
+ while ($sub = array_shift($subs)) {
3021
+ while ($ps = array_shift($sub)) {
3022
+ foreach ($ps as &$p) {
3023
+ $parts[] = $p;
3024
+ }
3025
+
3026
+ if (\count($sub) && reset($sub)) {
3027
+ $parts[] = ' ';
3028
+ }
3029
+ }
3030
+
3031
+ if (\count($subs) && reset($subs)) {
3032
+ $parts[] = ', ';
3033
+ }
3034
+ }
3035
+
3036
+ $parts[] = ')';
3037
+ } else {
3038
+ $this->seek($ss);
3039
+ }
3040
+ } else {
3041
+ if ($this->matchChar('(') &&
3042
+ ($this->openString(')', $str, '(') || true) &&
3043
+ $this->matchChar(')')
3044
+ ) {
3045
+ $parts[] = '(';
3046
+
3047
+ if (! empty($str)) {
3048
+ $parts[] = $str;
3049
+ }
3050
+
3051
+ $parts[] = ')';
3052
+ } else {
3053
+ $this->seek($ss);
3054
+ }
3055
+ }
3056
+
3057
+ continue;
3058
+ }
3059
+ }
3060
+
3061
+ $this->seek($s);
3062
+
3063
+ // 2n+1
3064
+ if ($subSelector && \is_string($subSelector) && strpos($subSelector, 'nth-') === 0) {
3065
+ if ($this->match("(\s*(\+\s*|\-\s*)?(\d+|n|\d+n))+", $counter)) {
3066
+ $parts[] = $counter[0];
3067
+ //$parts[] = str_replace(' ', '', $counter[0]);
3068
+ continue;
3069
+ }
3070
+ }
3071
+
3072
+ $this->seek($s);
3073
+
3074
+ // attribute selector
3075
+ if ($char === '[' &&
3076
+ $this->matchChar('[') &&
3077
+ ($this->openString(']', $str, '[') || true) &&
3078
+ $this->matchChar(']')
3079
+ ) {
3080
+ $parts[] = '[';
3081
+
3082
+ if (! empty($str)) {
3083
+ $parts[] = $str;
3084
+ }
3085
+
3086
+ $parts[] = ']';
3087
+ continue;
3088
+ }
3089
+
3090
+ $this->seek($s);
3091
+
3092
+ // for keyframes
3093
+ if ($this->unit($unit)) {
3094
+ $parts[] = $unit;
3095
+ continue;
3096
+ }
3097
+
3098
+ if ($this->restrictedKeyword($name)) {
3099
+ $parts[] = $name;
3100
+ continue;
3101
+ }
3102
+
3103
+ break;
3104
+ }
3105
+
3106
+ $this->eatWhiteDefault = $oldWhite;
3107
+
3108
+ if (! $parts) {
3109
+ return false;
3110
+ }
3111
+
3112
+ $out = $parts;
3113
+
3114
+ return true;
3115
+ }
3116
+
3117
+ /**
3118
+ * Parse a variable
3119
+ *
3120
+ * @param array $out
3121
+ *
3122
+ * @return boolean
3123
+ */
3124
+ protected function variable(&$out)
3125
+ {
3126
+ $s = $this->count;
3127
+
3128
+ if ($this->matchChar('$', false) && $this->keyword($name)) {
3129
+ if ($this->allowVars) {
3130
+ $out = [Type::T_VARIABLE, $name];
3131
+ } else {
3132
+ $out = [Type::T_KEYWORD, '$' . $name];
3133
+ }
3134
+
3135
+ return true;
3136
+ }
3137
+
3138
+ $this->seek($s);
3139
+
3140
+ return false;
3141
+ }
3142
+
3143
+ /**
3144
+ * Parse a keyword
3145
+ *
3146
+ * @param string $word
3147
+ * @param boolean $eatWhitespace
3148
+ *
3149
+ * @return boolean
3150
+ */
3151
+ protected function keyword(&$word, $eatWhitespace = null)
3152
+ {
3153
+ if ($this->match(
3154
+ $this->utf8
3155
+ ? '(([\pL\w\x{00A0}-\x{10FFFF}_\-\*!"\']|[\\\\].)([\pL\w\x{00A0}-\x{10FFFF}\-_"\']|[\\\\].)*)'
3156
+ : '(([\w_\-\*!"\']|[\\\\].)([\w\-_"\']|[\\\\].)*)',
3157
+ $m,
3158
+ $eatWhitespace
3159
+ )) {
3160
+ $word = $m[1];
3161
+
3162
+ return true;
3163
+ }
3164
+
3165
+ return false;
3166
+ }
3167
+
3168
+ /**
3169
+ * Parse a keyword that should not start with a number
3170
+ *
3171
+ * @param string $word
3172
+ * @param boolean $eatWhitespace
3173
+ *
3174
+ * @return boolean
3175
+ */
3176
+ protected function restrictedKeyword(&$word, $eatWhitespace = null)
3177
+ {
3178
+ $s = $this->count;
3179
+
3180
+ if ($this->keyword($word, $eatWhitespace) && (\ord($word[0]) > 57 || \ord($word[0]) < 48)) {
3181
+ return true;
3182
+ }
3183
+
3184
+ $this->seek($s);
3185
+
3186
+ return false;
3187
+ }
3188
+
3189
+ /**
3190
+ * Parse a placeholder
3191
+ *
3192
+ * @param string|array $placeholder
3193
+ *
3194
+ * @return boolean
3195
+ */
3196
+ protected function placeholder(&$placeholder)
3197
+ {
3198
+ if ($this->match(
3199
+ $this->utf8
3200
+ ? '([\pL\w\-_]+)'
3201
+ : '([\w\-_]+)',
3202
+ $m
3203
+ )) {
3204
+ $placeholder = $m[1];
3205
+
3206
+ return true;
3207
+ }
3208
+
3209
+ if ($this->interpolation($placeholder)) {
3210
+ return true;
3211
+ }
3212
+
3213
+ return false;
3214
+ }
3215
+
3216
+ /**
3217
+ * Parse a url
3218
+ *
3219
+ * @param array $out
3220
+ *
3221
+ * @return boolean
3222
+ */
3223
+ protected function url(&$out)
3224
+ {
3225
+ if ($this->match('(url\(\s*(["\']?)([^)]+)\2\s*\))', $m)) {
3226
+ $out = [Type::T_STRING, '', ['url(' . $m[2] . $m[3] . $m[2] . ')']];
3227
+
3228
+ return true;
3229
+ }
3230
+
3231
+ return false;
3232
+ }
3233
+
3234
+ /**
3235
+ * Consume an end of statement delimiter
3236
+ *
3237
+ * @return boolean
3238
+ */
3239
+ protected function end()
3240
+ {
3241
+ if ($this->matchChar(';')) {
3242
+ return true;
3243
+ }
3244
+
3245
+ if ($this->count === \strlen($this->buffer) || $this->buffer[$this->count] === '}') {
3246
+ // if there is end of file or a closing block next then we don't need a ;
3247
+ return true;
3248
+ }
3249
+
3250
+ return false;
3251
+ }
3252
+
3253
+ /**
3254
+ * Strip assignment flag from the list
3255
+ *
3256
+ * @param array $value
3257
+ *
3258
+ * @return array
3259
+ */
3260
+ protected function stripAssignmentFlags(&$value)
3261
+ {
3262
+ $flags = [];
3263
+
3264
+ for ($token = &$value; $token[0] === Type::T_LIST && ($s = \count($token[2])); $token = &$lastNode) {
3265
+ $lastNode = &$token[2][$s - 1];
3266
+
3267
+ while ($lastNode[0] === Type::T_KEYWORD && \in_array($lastNode[1], ['!default', '!global'])) {
3268
+ array_pop($token[2]);
3269
+
3270
+ $node = end($token[2]);
3271
+ $token = $this->flattenList($token);
3272
+ $flags[] = $lastNode[1];
3273
+ $lastNode = $node;
3274
+ }
3275
+ }
3276
+
3277
+ return $flags;
3278
+ }
3279
+
3280
+ /**
3281
+ * Strip optional flag from selector list
3282
+ *
3283
+ * @param array $selectors
3284
+ *
3285
+ * @return string
3286
+ */
3287
+ protected function stripOptionalFlag(&$selectors)
3288
+ {
3289
+ $optional = false;
3290
+ $selector = end($selectors);
3291
+ $part = end($selector);
3292
+
3293
+ if ($part === ['!optional']) {
3294
+ array_pop($selectors[\count($selectors) - 1]);
3295
+
3296
+ $optional = true;
3297
+ }
3298
+
3299
+ return $optional;
3300
+ }
3301
+
3302
+ /**
3303
+ * Turn list of length 1 into value type
3304
+ *
3305
+ * @param array $value
3306
+ *
3307
+ * @return array
3308
+ */
3309
+ protected function flattenList($value)
3310
+ {
3311
+ if ($value[0] === Type::T_LIST && \count($value[2]) === 1) {
3312
+ return $this->flattenList($value[2][0]);
3313
+ }
3314
+
3315
+ return $value;
3316
+ }
3317
+
3318
+ /**
3319
+ * Quote regular expression
3320
+ *
3321
+ * @param string $what
3322
+ *
3323
+ * @return string
3324
+ */
3325
+ private function pregQuote($what)
3326
+ {
3327
+ return preg_quote($what, '/');
3328
+ }
3329
+
3330
+ /**
3331
+ * Extract line numbers from buffer
3332
+ *
3333
+ * @param string $buffer
3334
+ */
3335
+ private function extractLineNumbers($buffer)
3336
+ {
3337
+ $this->sourcePositions = [0 => 0];
3338
+ $prev = 0;
3339
+
3340
+ while (($pos = strpos($buffer, "\n", $prev)) !== false) {
3341
+ $this->sourcePositions[] = $pos;
3342
+ $prev = $pos + 1;
3343
+ }
3344
+
3345
+ $this->sourcePositions[] = \strlen($buffer);
3346
+
3347
+ if (substr($buffer, -1) !== "\n") {
3348
+ $this->sourcePositions[] = \strlen($buffer) + 1;
3349
+ }
3350
+ }
3351
+
3352
+ /**
3353
+ * Get source line number and column (given character position in the buffer)
3354
+ *
3355
+ * @param integer $pos
3356
+ *
3357
+ * @return array
3358
+ */
3359
+ private function getSourcePosition($pos)
3360
+ {
3361
+ $low = 0;
3362
+ $high = \count($this->sourcePositions);
3363
+
3364
+ while ($low < $high) {
3365
+ $mid = (int) (($high + $low) / 2);
3366
+
3367
+ if ($pos < $this->sourcePositions[$mid]) {
3368
+ $high = $mid - 1;
3369
+ continue;
3370
+ }
3371
+
3372
+ if ($pos >= $this->sourcePositions[$mid + 1]) {
3373
+ $low = $mid + 1;
3374
+ continue;
3375
+ }
3376
+
3377
+ return [$mid + 1, $pos - $this->sourcePositions[$mid]];
3378
+ }
3379
+
3380
+ return [$low + 1, $pos - $this->sourcePositions[$low]];
3381
+ }
3382
+
3383
+ /**
3384
+ * Save internal encoding
3385
+ */
3386
+ private function saveEncoding()
3387
+ {
3388
+ if (\extension_loaded('mbstring')) {
3389
+ $this->encoding = mb_internal_encoding();
3390
+
3391
+ mb_internal_encoding('iso-8859-1');
3392
+ }
3393
+ }
3394
+
3395
+ /**
3396
+ * Restore internal encoding
3397
+ */
3398
+ private function restoreEncoding()
3399
+ {
3400
+ if (\extension_loaded('mbstring') && $this->encoding) {
3401
+ mb_internal_encoding($this->encoding);
3402
+ }
3403
+ }
3404
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/SourceMap/Base64.php ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\SourceMap;
13
+
14
+ /**
15
+ * Base 64 Encode/Decode
16
+ *
17
+ * @author Anthon Pang <anthon.pang@gmail.com>
18
+ */
19
+ class Base64
20
+ {
21
+ /**
22
+ * @var array
23
+ */
24
+ private static $encodingMap = [
25
+ 0 => 'A',
26
+ 1 => 'B',
27
+ 2 => 'C',
28
+ 3 => 'D',
29
+ 4 => 'E',
30
+ 5 => 'F',
31
+ 6 => 'G',
32
+ 7 => 'H',
33
+ 8 => 'I',
34
+ 9 => 'J',
35
+ 10 => 'K',
36
+ 11 => 'L',
37
+ 12 => 'M',
38
+ 13 => 'N',
39
+ 14 => 'O',
40
+ 15 => 'P',
41
+ 16 => 'Q',
42
+ 17 => 'R',
43
+ 18 => 'S',
44
+ 19 => 'T',
45
+ 20 => 'U',
46
+ 21 => 'V',
47
+ 22 => 'W',
48
+ 23 => 'X',
49
+ 24 => 'Y',
50
+ 25 => 'Z',
51
+ 26 => 'a',
52
+ 27 => 'b',
53
+ 28 => 'c',
54
+ 29 => 'd',
55
+ 30 => 'e',
56
+ 31 => 'f',
57
+ 32 => 'g',
58
+ 33 => 'h',
59
+ 34 => 'i',
60
+ 35 => 'j',
61
+ 36 => 'k',
62
+ 37 => 'l',
63
+ 38 => 'm',
64
+ 39 => 'n',
65
+ 40 => 'o',
66
+ 41 => 'p',
67
+ 42 => 'q',
68
+ 43 => 'r',
69
+ 44 => 's',
70
+ 45 => 't',
71
+ 46 => 'u',
72
+ 47 => 'v',
73
+ 48 => 'w',
74
+ 49 => 'x',
75
+ 50 => 'y',
76
+ 51 => 'z',
77
+ 52 => '0',
78
+ 53 => '1',
79
+ 54 => '2',
80
+ 55 => '3',
81
+ 56 => '4',
82
+ 57 => '5',
83
+ 58 => '6',
84
+ 59 => '7',
85
+ 60 => '8',
86
+ 61 => '9',
87
+ 62 => '+',
88
+ 63 => '/',
89
+ ];
90
+
91
+ /**
92
+ * @var array
93
+ */
94
+ private static $decodingMap = [
95
+ 'A' => 0,
96
+ 'B' => 1,
97
+ 'C' => 2,
98
+ 'D' => 3,
99
+ 'E' => 4,
100
+ 'F' => 5,
101
+ 'G' => 6,
102
+ 'H' => 7,
103
+ 'I' => 8,
104
+ 'J' => 9,
105
+ 'K' => 10,
106
+ 'L' => 11,
107
+ 'M' => 12,
108
+ 'N' => 13,
109
+ 'O' => 14,
110
+ 'P' => 15,
111
+ 'Q' => 16,
112
+ 'R' => 17,
113
+ 'S' => 18,
114
+ 'T' => 19,
115
+ 'U' => 20,
116
+ 'V' => 21,
117
+ 'W' => 22,
118
+ 'X' => 23,
119
+ 'Y' => 24,
120
+ 'Z' => 25,
121
+ 'a' => 26,
122
+ 'b' => 27,
123
+ 'c' => 28,
124
+ 'd' => 29,
125
+ 'e' => 30,
126
+ 'f' => 31,
127
+ 'g' => 32,
128
+ 'h' => 33,
129
+ 'i' => 34,
130
+ 'j' => 35,
131
+ 'k' => 36,
132
+ 'l' => 37,
133
+ 'm' => 38,
134
+ 'n' => 39,
135
+ 'o' => 40,
136
+ 'p' => 41,
137
+ 'q' => 42,
138
+ 'r' => 43,
139
+ 's' => 44,
140
+ 't' => 45,
141
+ 'u' => 46,
142
+ 'v' => 47,
143
+ 'w' => 48,
144
+ 'x' => 49,
145
+ 'y' => 50,
146
+ 'z' => 51,
147
+ 0 => 52,
148
+ 1 => 53,
149
+ 2 => 54,
150
+ 3 => 55,
151
+ 4 => 56,
152
+ 5 => 57,
153
+ 6 => 58,
154
+ 7 => 59,
155
+ 8 => 60,
156
+ 9 => 61,
157
+ '+' => 62,
158
+ '/' => 63,
159
+ ];
160
+
161
+ /**
162
+ * Convert to base64
163
+ *
164
+ * @param integer $value
165
+ *
166
+ * @return string
167
+ */
168
+ public static function encode($value)
169
+ {
170
+ return self::$encodingMap[$value];
171
+ }
172
+
173
+ /**
174
+ * Convert from base64
175
+ *
176
+ * @param string $value
177
+ *
178
+ * @return integer
179
+ */
180
+ public static function decode($value)
181
+ {
182
+ return self::$decodingMap[$value];
183
+ }
184
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/SourceMap/Base64VLQ.php ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\SourceMap;
13
+
14
+ use ScssPhp\ScssPhp\SourceMap\Base64;
15
+
16
+ /**
17
+ * Base 64 VLQ
18
+ *
19
+ * Based on the Base 64 VLQ implementation in Closure Compiler:
20
+ * https://github.com/google/closure-compiler/blob/master/src/com/google/debugging/sourcemap/Base64VLQ.java
21
+ *
22
+ * Copyright 2011 The Closure Compiler Authors.
23
+ *
24
+ * Licensed under the Apache License, Version 2.0 (the "License");
25
+ * you may not use this file except in compliance with the License.
26
+ * You may obtain a copy of the License at
27
+ *
28
+ * http://www.apache.org/licenses/LICENSE-2.0
29
+ *
30
+ * Unless required by applicable law or agreed to in writing, software
31
+ * distributed under the License is distributed on an "AS IS" BASIS,
32
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33
+ * See the License for the specific language governing permissions and
34
+ * limitations under the License.
35
+ *
36
+ * @author John Lenz <johnlenz@google.com>
37
+ * @author Anthon Pang <anthon.pang@gmail.com>
38
+ */
39
+ class Base64VLQ
40
+ {
41
+ // A Base64 VLQ digit can represent 5 bits, so it is base-32.
42
+ const VLQ_BASE_SHIFT = 5;
43
+
44
+ // A mask of bits for a VLQ digit (11111), 31 decimal.
45
+ const VLQ_BASE_MASK = 31;
46
+
47
+ // The continuation bit is the 6th bit.
48
+ const VLQ_CONTINUATION_BIT = 32;
49
+
50
+ /**
51
+ * Returns the VLQ encoded value.
52
+ *
53
+ * @param integer $value
54
+ *
55
+ * @return string
56
+ */
57
+ public static function encode($value)
58
+ {
59
+ $encoded = '';
60
+ $vlq = self::toVLQSigned($value);
61
+
62
+ do {
63
+ $digit = $vlq & self::VLQ_BASE_MASK;
64
+ $vlq >>= self::VLQ_BASE_SHIFT;
65
+
66
+ if ($vlq > 0) {
67
+ $digit |= self::VLQ_CONTINUATION_BIT;
68
+ }
69
+
70
+ $encoded .= Base64::encode($digit);
71
+ } while ($vlq > 0);
72
+
73
+ return $encoded;
74
+ }
75
+
76
+ /**
77
+ * Decodes VLQValue.
78
+ *
79
+ * @param string $str
80
+ * @param integer $index
81
+ *
82
+ * @return integer
83
+ */
84
+ public static function decode($str, &$index)
85
+ {
86
+ $result = 0;
87
+ $shift = 0;
88
+
89
+ do {
90
+ $c = $str[$index++];
91
+ $digit = Base64::decode($c);
92
+ $continuation = ($digit & self::VLQ_CONTINUATION_BIT) != 0;
93
+ $digit &= self::VLQ_BASE_MASK;
94
+ $result = $result + ($digit << $shift);
95
+ $shift = $shift + self::VLQ_BASE_SHIFT;
96
+ } while ($continuation);
97
+
98
+ return self::fromVLQSigned($result);
99
+ }
100
+
101
+ /**
102
+ * Converts from a two-complement value to a value where the sign bit is
103
+ * is placed in the least significant bit. For example, as decimals:
104
+ * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
105
+ * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
106
+ *
107
+ * @param integer $value
108
+ *
109
+ * @return integer
110
+ */
111
+ private static function toVLQSigned($value)
112
+ {
113
+ if ($value < 0) {
114
+ return ((-$value) << 1) + 1;
115
+ }
116
+
117
+ return ($value << 1) + 0;
118
+ }
119
+
120
+ /**
121
+ * Converts to a two-complement value from a value where the sign bit is
122
+ * is placed in the least significant bit. For example, as decimals:
123
+ * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
124
+ * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
125
+ *
126
+ * @param integer $value
127
+ *
128
+ * @return integer
129
+ */
130
+ private static function fromVLQSigned($value)
131
+ {
132
+ $negate = ($value & 1) === 1;
133
+ $value = ($value >> 1) & ~(1<<(8 * PHP_INT_SIZE - 1)); // unsigned right shift
134
+
135
+ if (! $negate) {
136
+ return $value;
137
+ }
138
+
139
+ // We need to OR 0x80000000 here to ensure the 32nd bit (the sign bit) is
140
+ // always set for negative numbers. If `value` were 1, (meaning `negate` is
141
+ // true and all other bits were zeros), `value` would now be 0. -0 is just
142
+ // 0, and doesn't flip the 32nd bit as intended. All positive numbers will
143
+ // successfully flip the 32nd bit without issue, so it's a noop for them.
144
+ return -$value | 0x80000000;
145
+ }
146
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/SourceMap/SourceMapGenerator.php ADDED
@@ -0,0 +1,348 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp\SourceMap;
13
+
14
+ use ScssPhp\ScssPhp\Exception\CompilerException;
15
+
16
+ /**
17
+ * Source Map Generator
18
+ *
19
+ * {@internal Derivative of oyejorge/less.php's lib/SourceMap/Generator.php, relicensed with permission. }}
20
+ *
21
+ * @author Josh Schmidt <oyejorge@gmail.com>
22
+ * @author Nicolas FRANÇOIS <nicolas.francois@frog-labs.com>
23
+ */
24
+ class SourceMapGenerator
25
+ {
26
+ /**
27
+ * What version of source map does the generator generate?
28
+ */
29
+ const VERSION = 3;
30
+
31
+ /**
32
+ * Array of default options
33
+ *
34
+ * @var array
35
+ */
36
+ protected $defaultOptions = [
37
+ // an optional source root, useful for relocating source files
38
+ // on a server or removing repeated values in the 'sources' entry.
39
+ // This value is prepended to the individual entries in the 'source' field.
40
+ 'sourceRoot' => '',
41
+
42
+ // an optional name of the generated code that this source map is associated with.
43
+ 'sourceMapFilename' => null,
44
+
45
+ // url of the map
46
+ 'sourceMapURL' => null,
47
+
48
+ // absolute path to a file to write the map to
49
+ 'sourceMapWriteTo' => null,
50
+
51
+ // output source contents?
52
+ 'outputSourceFiles' => false,
53
+
54
+ // base path for filename normalization
55
+ 'sourceMapRootpath' => '',
56
+
57
+ // base path for filename normalization
58
+ 'sourceMapBasepath' => ''
59
+ ];
60
+
61
+ /**
62
+ * The base64 VLQ encoder
63
+ *
64
+ * @var \ScssPhp\ScssPhp\SourceMap\Base64VLQ
65
+ */
66
+ protected $encoder;
67
+
68
+ /**
69
+ * Array of mappings
70
+ *
71
+ * @var array
72
+ */
73
+ protected $mappings = [];
74
+
75
+ /**
76
+ * Array of contents map
77
+ *
78
+ * @var array
79
+ */
80
+ protected $contentsMap = [];
81
+
82
+ /**
83
+ * File to content map
84
+ *
85
+ * @var array
86
+ */
87
+ protected $sources = [];
88
+ protected $sourceKeys = [];
89
+
90
+ /**
91
+ * @var array
92
+ */
93
+ private $options;
94
+
95
+ public function __construct(array $options = [])
96
+ {
97
+ $this->options = array_merge($this->defaultOptions, $options);
98
+ $this->encoder = new Base64VLQ();
99
+ }
100
+
101
+ /**
102
+ * Adds a mapping
103
+ *
104
+ * @param integer $generatedLine The line number in generated file
105
+ * @param integer $generatedColumn The column number in generated file
106
+ * @param integer $originalLine The line number in original file
107
+ * @param integer $originalColumn The column number in original file
108
+ * @param string $sourceFile The original source file
109
+ */
110
+ public function addMapping($generatedLine, $generatedColumn, $originalLine, $originalColumn, $sourceFile)
111
+ {
112
+ $this->mappings[] = [
113
+ 'generated_line' => $generatedLine,
114
+ 'generated_column' => $generatedColumn,
115
+ 'original_line' => $originalLine,
116
+ 'original_column' => $originalColumn,
117
+ 'source_file' => $sourceFile
118
+ ];
119
+
120
+ $this->sources[$sourceFile] = $sourceFile;
121
+ }
122
+
123
+ /**
124
+ * Saves the source map to a file
125
+ *
126
+ * @param string $content The content to write
127
+ *
128
+ * @return string
129
+ *
130
+ * @throws \ScssPhp\ScssPhp\Exception\CompilerException If the file could not be saved
131
+ */
132
+ public function saveMap($content)
133
+ {
134
+ $file = $this->options['sourceMapWriteTo'];
135
+ $dir = \dirname($file);
136
+
137
+ // directory does not exist
138
+ if (! is_dir($dir)) {
139
+ // FIXME: create the dir automatically?
140
+ throw new CompilerException(
141
+ sprintf('The directory "%s" does not exist. Cannot save the source map.', $dir)
142
+ );
143
+ }
144
+
145
+ // FIXME: proper saving, with dir write check!
146
+ if (file_put_contents($file, $content) === false) {
147
+ throw new CompilerException(sprintf('Cannot save the source map to "%s"', $file));
148
+ }
149
+
150
+ return $this->options['sourceMapURL'];
151
+ }
152
+
153
+ /**
154
+ * Generates the JSON source map
155
+ *
156
+ * @return string
157
+ *
158
+ * @see https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#
159
+ */
160
+ public function generateJson()
161
+ {
162
+ $sourceMap = [];
163
+ $mappings = $this->generateMappings();
164
+
165
+ // File version (always the first entry in the object) and must be a positive integer.
166
+ $sourceMap['version'] = self::VERSION;
167
+
168
+ // An optional name of the generated code that this source map is associated with.
169
+ $file = $this->options['sourceMapFilename'];
170
+
171
+ if ($file) {
172
+ $sourceMap['file'] = $file;
173
+ }
174
+
175
+ // An optional source root, useful for relocating source files on a server or removing repeated values in the
176
+ // 'sources' entry. This value is prepended to the individual entries in the 'source' field.
177
+ $root = $this->options['sourceRoot'];
178
+
179
+ if ($root) {
180
+ $sourceMap['sourceRoot'] = $root;
181
+ }
182
+
183
+ // A list of original sources used by the 'mappings' entry.
184
+ $sourceMap['sources'] = [];
185
+
186
+ foreach ($this->sources as $sourceUri => $sourceFilename) {
187
+ $sourceMap['sources'][] = $this->normalizeFilename($sourceFilename);
188
+ }
189
+
190
+ // A list of symbol names used by the 'mappings' entry.
191
+ $sourceMap['names'] = [];
192
+
193
+ // A string with the encoded mapping data.
194
+ $sourceMap['mappings'] = $mappings;
195
+
196
+ if ($this->options['outputSourceFiles']) {
197
+ // An optional list of source content, useful when the 'source' can't be hosted.
198
+ // The contents are listed in the same order as the sources above.
199
+ // 'null' may be used if some original sources should be retrieved by name.
200
+ $sourceMap['sourcesContent'] = $this->getSourcesContent();
201
+ }
202
+
203
+ // less.js compat fixes
204
+ if (\count($sourceMap['sources']) && empty($sourceMap['sourceRoot'])) {
205
+ unset($sourceMap['sourceRoot']);
206
+ }
207
+
208
+ return json_encode($sourceMap, JSON_UNESCAPED_SLASHES);
209
+ }
210
+
211
+ /**
212
+ * Returns the sources contents
213
+ *
214
+ * @return array|null
215
+ */
216
+ protected function getSourcesContent()
217
+ {
218
+ if (empty($this->sources)) {
219
+ return null;
220
+ }
221
+
222
+ $content = [];
223
+
224
+ foreach ($this->sources as $sourceFile) {
225
+ $content[] = file_get_contents($sourceFile);
226
+ }
227
+
228
+ return $content;
229
+ }
230
+
231
+ /**
232
+ * Generates the mappings string
233
+ *
234
+ * @return string
235
+ */
236
+ public function generateMappings()
237
+ {
238
+ if (! \count($this->mappings)) {
239
+ return '';
240
+ }
241
+
242
+ $this->sourceKeys = array_flip(array_keys($this->sources));
243
+
244
+ // group mappings by generated line number.
245
+ $groupedMap = $groupedMapEncoded = [];
246
+
247
+ foreach ($this->mappings as $m) {
248
+ $groupedMap[$m['generated_line']][] = $m;
249
+ }
250
+
251
+ ksort($groupedMap);
252
+
253
+ $lastGeneratedLine = $lastOriginalIndex = $lastOriginalLine = $lastOriginalColumn = 0;
254
+
255
+ foreach ($groupedMap as $lineNumber => $lineMap) {
256
+ while (++$lastGeneratedLine < $lineNumber) {
257
+ $groupedMapEncoded[] = ';';
258
+ }
259
+
260
+ $lineMapEncoded = [];
261
+ $lastGeneratedColumn = 0;
262
+
263
+ foreach ($lineMap as $m) {
264
+ $mapEncoded = $this->encoder->encode($m['generated_column'] - $lastGeneratedColumn);
265
+ $lastGeneratedColumn = $m['generated_column'];
266
+
267
+ // find the index
268
+ if ($m['source_file']) {
269
+ $index = $this->findFileIndex($m['source_file']);
270
+
271
+ if ($index !== false) {
272
+ $mapEncoded .= $this->encoder->encode($index - $lastOriginalIndex);
273
+ $lastOriginalIndex = $index;
274
+ // lines are stored 0-based in SourceMap spec version 3
275
+ $mapEncoded .= $this->encoder->encode($m['original_line'] - 1 - $lastOriginalLine);
276
+ $lastOriginalLine = $m['original_line'] - 1;
277
+ $mapEncoded .= $this->encoder->encode($m['original_column'] - $lastOriginalColumn);
278
+ $lastOriginalColumn = $m['original_column'];
279
+ }
280
+ }
281
+
282
+ $lineMapEncoded[] = $mapEncoded;
283
+ }
284
+
285
+ $groupedMapEncoded[] = implode(',', $lineMapEncoded) . ';';
286
+ }
287
+
288
+ return rtrim(implode($groupedMapEncoded), ';');
289
+ }
290
+
291
+ /**
292
+ * Finds the index for the filename
293
+ *
294
+ * @param string $filename
295
+ *
296
+ * @return integer|false
297
+ */
298
+ protected function findFileIndex($filename)
299
+ {
300
+ return $this->sourceKeys[$filename];
301
+ }
302
+
303
+ /**
304
+ * Normalize filename
305
+ *
306
+ * @param string $filename
307
+ *
308
+ * @return string
309
+ */
310
+ protected function normalizeFilename($filename)
311
+ {
312
+ $filename = $this->fixWindowsPath($filename);
313
+ $rootpath = $this->options['sourceMapRootpath'];
314
+ $basePath = $this->options['sourceMapBasepath'];
315
+
316
+ // "Trim" the 'sourceMapBasepath' from the output filename.
317
+ if (\strlen($basePath) && strpos($filename, $basePath) === 0) {
318
+ $filename = substr($filename, \strlen($basePath));
319
+ }
320
+
321
+ // Remove extra leading path separators.
322
+ if (strpos($filename, '\\') === 0 || strpos($filename, '/') === 0) {
323
+ $filename = substr($filename, 1);
324
+ }
325
+
326
+ return $rootpath . $filename;
327
+ }
328
+
329
+ /**
330
+ * Fix windows paths
331
+ *
332
+ * @param string $path
333
+ * @param boolean $addEndSlash
334
+ *
335
+ * @return string
336
+ */
337
+ public function fixWindowsPath($path, $addEndSlash = false)
338
+ {
339
+ $slash = ($addEndSlash) ? '/' : '';
340
+
341
+ if (! empty($path)) {
342
+ $path = str_replace('\\', '/', $path);
343
+ $path = rtrim($path, '/') . $slash;
344
+ }
345
+
346
+ return $path;
347
+ }
348
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Type.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp;
13
+
14
+ /**
15
+ * Block/node types
16
+ *
17
+ * @author Anthon Pang <anthon.pang@gmail.com>
18
+ */
19
+ class Type
20
+ {
21
+ const T_ASSIGN = 'assign';
22
+ const T_AT_ROOT = 'at-root';
23
+ const T_BLOCK = 'block';
24
+ const T_BREAK = 'break';
25
+ const T_CHARSET = 'charset';
26
+ const T_COLOR = 'color';
27
+ const T_COMMENT = 'comment';
28
+ const T_CONTINUE = 'continue';
29
+ const T_CONTROL = 'control';
30
+ const T_CUSTOM_PROPERTY = 'custom';
31
+ const T_DEBUG = 'debug';
32
+ const T_DIRECTIVE = 'directive';
33
+ const T_EACH = 'each';
34
+ const T_ELSE = 'else';
35
+ const T_ELSEIF = 'elseif';
36
+ const T_ERROR = 'error';
37
+ const T_EXPRESSION = 'exp';
38
+ const T_EXTEND = 'extend';
39
+ const T_FOR = 'for';
40
+ const T_FUNCTION = 'function';
41
+ const T_FUNCTION_CALL = 'fncall';
42
+ const T_HSL = 'hsl';
43
+ const T_IF = 'if';
44
+ const T_IMPORT = 'import';
45
+ const T_INCLUDE = 'include';
46
+ const T_INTERPOLATE = 'interpolate';
47
+ const T_INTERPOLATED = 'interpolated';
48
+ const T_KEYWORD = 'keyword';
49
+ const T_LIST = 'list';
50
+ const T_MAP = 'map';
51
+ const T_MEDIA = 'media';
52
+ const T_MEDIA_EXPRESSION = 'mediaExp';
53
+ const T_MEDIA_TYPE = 'mediaType';
54
+ const T_MEDIA_VALUE = 'mediaValue';
55
+ const T_MIXIN = 'mixin';
56
+ const T_MIXIN_CONTENT = 'mixin_content';
57
+ const T_NESTED_PROPERTY = 'nestedprop';
58
+ const T_NOT = 'not';
59
+ const T_NULL = 'null';
60
+ const T_NUMBER = 'number';
61
+ const T_RETURN = 'return';
62
+ const T_ROOT = 'root';
63
+ const T_SCSSPHP_IMPORT_ONCE = 'scssphp-import-once';
64
+ const T_SELF = 'self';
65
+ const T_STRING = 'string';
66
+ const T_UNARY = 'unary';
67
+ const T_VARIABLE = 'var';
68
+ const T_WARN = 'warn';
69
+ const T_WHILE = 'while';
70
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Util.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp;
13
+
14
+ use ScssPhp\ScssPhp\Base\Range;
15
+ use ScssPhp\ScssPhp\Exception\RangeException;
16
+
17
+ /**
18
+ * Utilty functions
19
+ *
20
+ * @author Anthon Pang <anthon.pang@gmail.com>
21
+ */
22
+ class Util
23
+ {
24
+ /**
25
+ * Asserts that `value` falls within `range` (inclusive), leaving
26
+ * room for slight floating-point errors.
27
+ *
28
+ * @param string $name The name of the value. Used in the error message.
29
+ * @param \ScssPhp\ScssPhp\Base\Range $range Range of values.
30
+ * @param array $value The value to check.
31
+ * @param string $unit The unit of the value. Used in error reporting.
32
+ *
33
+ * @return mixed `value` adjusted to fall within range, if it was outside by a floating-point margin.
34
+ *
35
+ * @throws \ScssPhp\ScssPhp\Exception\RangeException
36
+ */
37
+ public static function checkRange($name, Range $range, $value, $unit = '')
38
+ {
39
+ $val = $value[1];
40
+ $grace = new Range(-0.00001, 0.00001);
41
+
42
+ if ($range->includes($val)) {
43
+ return $val;
44
+ }
45
+
46
+ if ($grace->includes($val - $range->first)) {
47
+ return $range->first;
48
+ }
49
+
50
+ if ($grace->includes($val - $range->last)) {
51
+ return $range->last;
52
+ }
53
+
54
+ throw new RangeException("$name {$val} must be between {$range->first} and {$range->last}$unit");
55
+ }
56
+
57
+ /**
58
+ * Encode URI component
59
+ *
60
+ * @param string $string
61
+ *
62
+ * @return string
63
+ */
64
+ public static function encodeURIComponent($string)
65
+ {
66
+ $revert = ['%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')'];
67
+
68
+ return strtr(rawurlencode($string), $revert);
69
+ }
70
+ }
v4.0.0/libs/scssphp/vendor/scssphp/scssphp/src/Version.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2020 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://scssphp.github.io/scssphp
10
+ */
11
+
12
+ namespace ScssPhp\ScssPhp;
13
+
14
+ /**
15
+ * SCSSPHP version
16
+ *
17
+ * @author Leaf Corcoran <leafot@gmail.com>
18
+ */
19
+ class Version
20
+ {
21
+ const VERSION = '1.1.0';
22
+ }
v4.0.0/package-lock.json ADDED
@@ -0,0 +1,11775 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "rmp-menu",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 1,
5
+ "requires": true,
6
+ "dependencies": {
7
+ "@babel/code-frame": {
8
+ "version": "7.10.4",
9
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
10
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
11
+ "dev": true,
12
+ "requires": {
13
+ "@babel/highlight": "^7.10.4"
14
+ }
15
+ },
16
+ "@babel/compat-data": {
17
+ "version": "7.11.0",
18
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz",
19
+ "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==",
20
+ "dev": true,
21
+ "requires": {
22
+ "browserslist": "^4.12.0",
23
+ "invariant": "^2.2.4",
24
+ "semver": "^5.5.0"
25
+ }
26
+ },
27
+ "@babel/core": {
28
+ "version": "7.11.6",
29
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz",
30
+ "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==",
31
+ "dev": true,
32
+ "requires": {
33
+ "@babel/code-frame": "^7.10.4",
34
+ "@babel/generator": "^7.11.6",
35
+ "@babel/helper-module-transforms": "^7.11.0",
36
+ "@babel/helpers": "^7.10.4",
37
+ "@babel/parser": "^7.11.5",
38
+ "@babel/template": "^7.10.4",
39
+ "@babel/traverse": "^7.11.5",
40
+ "@babel/types": "^7.11.5",
41
+ "convert-source-map": "^1.7.0",
42
+ "debug": "^4.1.0",
43
+ "gensync": "^1.0.0-beta.1",
44
+ "json5": "^2.1.2",
45
+ "lodash": "^4.17.19",
46
+ "resolve": "^1.3.2",
47
+ "semver": "^5.4.1",
48
+ "source-map": "^0.5.0"
49
+ }
50
+ },
51
+ "@babel/generator": {
52
+ "version": "7.11.6",
53
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
54
+ "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
55
+ "dev": true,
56
+ "requires": {
57
+ "@babel/types": "^7.11.5",
58
+ "jsesc": "^2.5.1",
59
+ "source-map": "^0.5.0"
60
+ }
61
+ },
62
+ "@babel/helper-annotate-as-pure": {
63
+ "version": "7.10.4",
64
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz",
65
+ "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==",
66
+ "dev": true,
67
+ "requires": {
68
+ "@babel/types": "^7.10.4"
69
+ }
70
+ },
71
+ "@babel/helper-builder-binary-assignment-operator-visitor": {
72
+ "version": "7.10.4",
73
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz",
74
+ "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==",
75
+ "dev": true,
76
+ "requires": {
77
+ "@babel/helper-explode-assignable-expression": "^7.10.4",
78
+ "@babel/types": "^7.10.4"
79
+ }
80
+ },
81
+ "@babel/helper-compilation-targets": {
82
+ "version": "7.10.4",
83
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz",
84
+ "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==",
85
+ "dev": true,
86
+ "requires": {
87
+ "@babel/compat-data": "^7.10.4",
88
+ "browserslist": "^4.12.0",
89
+ "invariant": "^2.2.4",
90
+ "levenary": "^1.1.1",
91
+ "semver": "^5.5.0"
92
+ }
93
+ },
94
+ "@babel/helper-create-class-features-plugin": {
95
+ "version": "7.10.5",
96
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz",
97
+ "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==",
98
+ "dev": true,
99
+ "requires": {
100
+ "@babel/helper-function-name": "^7.10.4",
101
+ "@babel/helper-member-expression-to-functions": "^7.10.5",
102
+ "@babel/helper-optimise-call-expression": "^7.10.4",
103
+ "@babel/helper-plugin-utils": "^7.10.4",
104
+ "@babel/helper-replace-supers": "^7.10.4",
105
+ "@babel/helper-split-export-declaration": "^7.10.4"
106
+ }
107
+ },
108
+ "@babel/helper-create-regexp-features-plugin": {
109
+ "version": "7.10.4",
110
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz",
111
+ "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==",
112
+ "dev": true,
113
+ "requires": {
114
+ "@babel/helper-annotate-as-pure": "^7.10.4",
115
+ "@babel/helper-regex": "^7.10.4",
116
+ "regexpu-core": "^4.7.0"
117
+ }
118
+ },
119
+ "@babel/helper-define-map": {
120
+ "version": "7.10.5",
121
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz",
122
+ "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==",
123
+ "dev": true,
124
+ "requires": {
125
+ "@babel/helper-function-name": "^7.10.4",
126
+ "@babel/types": "^7.10.5",
127
+ "lodash": "^4.17.19"
128
+ }
129
+ },
130
+ "@babel/helper-explode-assignable-expression": {
131
+ "version": "7.11.4",
132
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz",
133
+ "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==",
134
+ "dev": true,
135
+ "requires": {
136
+ "@babel/types": "^7.10.4"
137
+ }
138
+ },
139
+ "@babel/helper-function-name": {
140
+ "version": "7.10.4",
141
+ "resolved": "https://registry.npmjs.org/@babel/helpe