Responsive Menu - Version 3.0.12

Version Description

(22nd September 2016) = ** Requires PHP 5.4** * Fixed close menu on link click bug with single header (Pro only) * Fixed conflict bug with "close on link clicks" and "disable parent click" options * Added header bar title link to WPML/Polylang * Added alt tag option for every image * Link target now taken into account with "Close Menu on Link Clicks"

Download this release

Release Info

Developer ResponsiveMenu
Plugin Icon 128x128 Responsive Menu
Version 3.0.12
Comparing to
See all releases

Code changes from version 3.0.11 to 3.0.12

Files changed (121) hide show
  1. readme.txt +60 -90
  2. responsive-menu.php +1 -1
  3. src/app/Collections/OptionsCollection.php +5 -5
  4. src/app/Mappers/JsMapper.php +6 -1
  5. src/app/Mappers/scss.inc.php +4 -4
  6. src/app/Walkers/WpWalker.php +7 -1
  7. src/config/admin_ordering.php +38 -0
  8. src/config/default_options.php +9 -2
  9. src/config/option_helpers.php +3 -0
  10. src/config/services.php +1 -1
  11. tests/app/Collections/OptionsCollectionTest.php +138 -0
  12. tests/app/Controllers/AdminTest.php +51 -0
  13. tests/app/Controllers/FrontTest.php +37 -0
  14. tests/app/Database/MigrationTest.php +114 -0
  15. tests/app/Database/WpDatabaseTest.php +61 -0
  16. tests/app/Factories/CssFactoryTest.php +35 -0
  17. tests/app/Factories/JsFactoryTest.php +30 -0
  18. tests/app/Factories/OptionFactoryTest.php +61 -0
  19. tests/app/Filesystem/FileCreatorTest.php +25 -0
  20. tests/app/Filesystem/FolderCreatorTest.php +21 -0
  21. tests/app/Filesystem/ScriptsBuilderTest.php +23 -0
  22. tests/app/Filters/HtmlFilterTest.php +15 -0
  23. tests/app/Filters/JsonFilterTest.php +19 -0
  24. tests/app/Filters/TextFilterTest.php +19 -0
  25. tests/app/Form/CheckboxTest.php +33 -0
  26. tests/app/Form/ColourTest.php +16 -0
  27. tests/app/Form/ExportTest.php +16 -0
  28. tests/app/Form/FontIconPageListTest.php +0 -0
  29. tests/app/Form/FontIconTest.php +23 -0
  30. tests/app/Form/HeaderBarOrderingTest.php +18 -0
  31. tests/app/Form/ImageTest.php +17 -0
  32. tests/app/Form/ImportTest.php +16 -0
  33. tests/app/Form/MenuOrderingTest.php +17 -0
  34. tests/app/Form/ResetTest.php +16 -0
  35. tests/app/Form/SelectTest.php +47 -0
  36. tests/app/Form/TextAreaTest.php +16 -0
  37. tests/app/Form/TextTest.php +16 -0
  38. tests/app/Formatters/MinifyTest.php +27 -0
  39. tests/app/Mappers/JsMapperTest.php +59 -0
  40. tests/app/Mappers/ScssBaseMapperTest.php +32 -0
  41. tests/app/Mappers/ScssButtonMapperTest.php +42 -0
  42. tests/app/Mappers/ScssMenuMapperTest.php +67 -0
  43. tests/app/Models/OptionTest.php +57 -0
  44. tests/app/Repositories/OptionRepositoryTest.php +87 -0
  45. tests/app/Routing/ContainerTest.php +66 -0
  46. tests/app/Services/OptionsServiceTest.php +59 -0
  47. tests/app/Translation/TranslatorTest.php +50 -0
  48. tests/app/View/AdminViewTest.php +19 -0
  49. tests/app/View/FrontViewTest.php +18 -0
  50. tests/app/ViewModels/ButtonTest.php +18 -0
  51. tests/app/ViewModels/Components/Admin/BoxesTest.php +50 -0
  52. tests/app/ViewModels/Components/Admin/TabsTest.php +25 -0
  53. tests/app/ViewModels/Components/Button/ButtonTest.php +36 -0
  54. tests/app/ViewModels/Components/ComponentFactoryTest.php +27 -0
  55. tests/app/ViewModels/Components/Menu/AdditionalContentTest.php +28 -0
  56. tests/app/ViewModels/Components/Menu/MenuTest.php +36 -0
  57. tests/app/ViewModels/Components/Menu/SearchTest.php +21 -0
  58. tests/app/ViewModels/Components/Menu/TitleTest.php +32 -0
  59. tests/app/ViewModels/MenuTest.php +32 -0
  60. tests/app/Walkers/WpWalkerTest.php +93 -0
  61. tests/scssc/ApiTest.php +80 -0
  62. tests/scssc/InputTest.php +80 -0
  63. tests/scssc/compare-scss.sh +25 -0
  64. tests/scssc/inputs/builtins.scss +171 -0
  65. tests/scssc/inputs/comments.scss +28 -0
  66. tests/scssc/inputs/compass_extract.scss +248 -0
  67. tests/scssc/inputs/content.scss +61 -0
  68. tests/scssc/inputs/content_with_function.scss +17 -0
  69. tests/scssc/inputs/default_args.scss +15 -0
  70. tests/scssc/inputs/directives.scss +108 -0
  71. tests/scssc/inputs/extends.scss +184 -0
  72. tests/scssc/inputs/filter_effects.scss +48 -0
  73. tests/scssc/inputs/functions.scss +81 -0
  74. tests/scssc/inputs/ie7.scss +12 -0
  75. tests/scssc/inputs/if.scss +76 -0
  76. tests/scssc/inputs/if_on_null.scss +8 -0
  77. tests/scssc/inputs/import.scss +23 -0
  78. tests/scssc/inputs/imports/_partial.scss +10 -0
  79. tests/scssc/inputs/imports/simple.scss +4 -0
  80. tests/scssc/inputs/interpolation.scss +86 -0
  81. tests/scssc/inputs/keyword_args.scss +24 -0
  82. tests/scssc/inputs/list.scss +15 -0
  83. tests/scssc/inputs/looping.scss +51 -0
  84. tests/scssc/inputs/media.scss +208 -0
  85. tests/scssc/inputs/mixins.scss +158 -0
  86. tests/scssc/inputs/nesting.scss +45 -0
  87. tests/scssc/inputs/null.scss +41 -0
  88. tests/scssc/inputs/operators.scss +143 -0
  89. tests/scssc/inputs/placeholder_selector.scss +18 -0
  90. tests/scssc/inputs/scss_css.scss +986 -0
  91. tests/scssc/inputs/selectors.scss +187 -0
  92. tests/scssc/inputs/values.scss +43 -0
  93. tests/scssc/inputs/variables.scss +56 -0
  94. tests/scssc/outputs/builtins.css +126 -0
  95. tests/scssc/outputs/comments.css +19 -0
  96. tests/scssc/outputs/compass_extract.css +28 -0
  97. tests/scssc/outputs/content.css +29 -0
  98. tests/scssc/outputs/content_with_function.css +2 -0
  99. tests/scssc/outputs/default_args.css +3 -0
  100. tests/scssc/outputs/directives.css +77 -0
  101. tests/scssc/outputs/extends.css +87 -0
  102. tests/scssc/outputs/filter_effects.css +20 -0
  103. tests/scssc/outputs/functions.css +22 -0
  104. tests/scssc/outputs/ie7.css +8 -0
  105. tests/scssc/outputs/if.css +21 -0
  106. tests/scssc/outputs/if_on_null.css +2 -0
  107. tests/scssc/outputs/import.css +27 -0
  108. tests/scssc/outputs/interpolation.css +54 -0
  109. tests/scssc/outputs/keyword_args.css +6 -0
  110. tests/scssc/outputs/list.css +7 -0
  111. tests/scssc/outputs/looping.css +45 -0
  112. tests/scssc/outputs/media.css +103 -0
  113. tests/scssc/outputs/mixins.css +83 -0
  114. tests/scssc/outputs/nesting.css +22 -0
  115. tests/scssc/outputs/null.css +21 -0
  116. tests/scssc/outputs/operators.css +105 -0
  117. tests/scssc/outputs/placeholder_selector.css +7 -0
  118. tests/scssc/outputs/scss_css.css +741 -0
  119. tests/scssc/outputs/selectors.css +335 -0
  120. tests/scssc/outputs/values.css +34 -0
  121. tests/scssc/outputs/variables.css +24 -0
readme.txt CHANGED
@@ -4,111 +4,67 @@ Donate link: https://responsive.menu/donate
4
  Tags: responsive, menu, responsive menu, mobile menu, wordpress responsive menu, wp responsive menu, tablet menu, mobile, tablet, 3 lines, 3 line, three line, three lines
5
  Requires at least: 3.5.0
6
  Tested up to: 4.6
7
- Stable tag: 3.0.11
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
- This is a Highly Customisable Responsive Menu Plugin for WordPress
12
 
13
  == Description ==
14
-
15
- This is a Highly Customisable Responsive Menu Plugin for WordPress, with over 120 customisable options giving you a combination of 14,000 options!
16
  <br /><br />
17
- **Requires PHP 5.4+**, please ensure you have this installed before upgrading.
18
  <br /><br />
19
- With this plugin, you can edit the following and more:
20
- <ul>
21
- <li>Menu Title</li>
22
- <li>Menu Title Image</li>
23
- <li>Button Title</li>
24
- <li>Button Title Image</li>
25
- <li>Menu To Responsify</li>
26
- <li>Media Query Breakpoint Width</li>
27
- <li>CSS Options For Hiding Specific Elements</li>
28
- <li>Menu Depth To Display</li>
29
- <li>Top Location</li>
30
- <li>Right Percentage Location</li>
31
- <li>Line & Text Colour</li>
32
- <li>Menu Button Background Colour</li>
33
- <li>Absolute and Fixed Positioning</li>
34
- <li>Menu Font</li>
35
- <li>Menu Title Colour</li>
36
- <li>Menu Title Hover Colour</li>
37
- <li>Menu Title Background Colour</li>
38
- <li>Menu Text Colour</li>
39
- <li>Menu Text Hover Colour</li>
40
- <li>Menu Background Colour</li>
41
- <li>Menu Link Background Hover Colour</li>
42
- <li>Menu Text Size</li>
43
- <li>Menu Button Text Size</li>
44
- <li>Menu Links Text Size</li>
45
- <li>Choose Overlay or Push Animations</li>
46
- <li>Slide Animation Speed</li>
47
- <li>Ability to auto expand/hide sub-menus</li>
48
- <li>Inclusion/Exclusion of Search Box</li>
49
- <li>Choice of Positioning of Search Box</li>
50
- <li>Transition speed</li>
51
- <li>Slide Animation Speed</li>
52
- <li>Menu Link Heights</li>
53
- <li>Text Alignment</li>
54
- <li>Choice of side to slide in from (left, right, top, bottom)</li>
55
- <li>Choice to use inline/external stylesheets and scripts</li>
56
- <li>Option to include JavaScript in footer</li>
57
- <li>Option to remove CSS !important tags</li>
58
- <li>Choice to Minify created CSS and JS files (saves up to 50% file space)</li>
59
- <li>Choice to auto-close menu items on click (for single page sites)</li>
60
- <li>Choice to replace 3 lines with an x on click</li>
61
- <li>Minimum width of menu</li>
62
- <li>Maximum width of menu</li>
63
- <li>Choice to Auto Expand Parent Links</li>
64
- <li>Choice to Ignore Clicks on Ancestor Links</li>
65
- <li>Choice to Close Menu Automatically on Page Clicks</li>
66
- <li>Choice to Specify Title Menu Link</li>
67
- <li>Choice to Specify Title Menu Link Location</li>
68
- <li>Ability to add custom HTML snippet inside the menu</li>
69
- <li>Choice of location for custom HTML snippet inside the menu</li>
70
- <li>Choice of using shortode or not</li>
71
- <li>Ability to change the 3 lines height</li>
72
- <li>Ability to change the 3 lines width</li>
73
- <li>Ability to Export Options</li>
74
- <li>Ability to Import Options</li>
75
- <li>Ability to set sub menu arrow shape/image Options</li>
76
- <li>Ability to set custom click trigger</li>
77
- <li>Ability to push menu button with animation</li>
78
- <li>Ability to change Current Page background hover colour</li>
79
- <li>Ability to change Current Page Link hover colour</li>
80
- <li>Ability to provide a custom walker option</li>
81
- <li>Ability to choose to use transient caching or not</li>
82
- <li>Ability to choose if menu is shown on left or right of screen</li>
83
- <li>Ability to set theme location menu</li>
84
- <li>Ability to reset to default</li>
85
- <li>Ability to set menu text location</li>
86
- <li>Ability to set menu text line height</li>
87
- <li>Plus more...</li>
88
- </ul>
89
- The plugin creates a nice three-lined mobile menu button (or custom image if you choose) that users can click on to bring a slide out menu (from the left, right, top or bottom - again your choice), which is easily navigated.
90
  <br /><br />
91
- It is fully responsive if you have the viewport meta tag on your site, using media queries with the widths defined by you. It can be used as a responsive menu, mobile menu, tablet menu or full dedicated menu for your main site.
92
  <br /><br />
93
- It requires no shortcodes (although you can use them) or fancy php code to be inserted by yourself making it very easy to install and you can design it to look exactly as you want to or leave it with its default values to have it looking amazing in just a matter of seconds.
94
  <br /><br />
95
- You have the choice to include the stylesheets and scripts inline to avoid adding any extra HTTP requests to your site or through external stylesheets created by the plug-in. Either way, the code added is extremely small (only a little jQuery and CSS) and there is even an option to minify the output if you wish saving a further 50% on file space.
96
  <br /><br />
97
- It also includes the following functionality:
 
 
 
 
98
  <ul>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  <li>WPML/Polylang Support</li>
 
 
100
  </ul>
101
- If you decide to go Pro then you will also get the following functionality:
 
102
  <ul>
 
 
103
  <li>FontIcon Support for individual menu items</li>
104
- <li>Button Animation Effects</li>
105
- <li>Colour Opacity option</li>
106
- <li>Header Bar</li>
107
- <li>Single Menu Option</li>
 
108
  </ul>
 
109
  For more reasons to go Pro, please visit <a target="_blank" href="https://responsive.menu/why-go-pro/">this page</a>.
110
- If you would like to see any other options added to the plugin or would like to help with translating the plugin into various languages then please email me or place them in a support ticket.
111
- <br />
112
 
113
  == Installation ==
114
 
@@ -138,14 +94,28 @@ To view our whole FAQ, please go to https://responsive.menu/faq/
138
 
139
  == Screenshots ==
140
 
141
- 1. Fully customisable Admin Screen
 
 
 
 
142
 
143
- 2. Example Front End Menu Button
144
 
145
- 3. Example Front End Expanded Menu
 
 
146
 
147
  == Changelog ==
148
 
 
 
 
 
 
 
 
 
149
  = 3.0.11 (29th August 2016) =
150
  ** Requires PHP 5.4**
151
  * Fixed export options bug (Pro only)
4
  Tags: responsive, menu, responsive menu, mobile menu, wordpress responsive menu, wp responsive menu, tablet menu, mobile, tablet, 3 lines, 3 line, three line, three lines
5
  Requires at least: 3.5.0
6
  Tested up to: 4.6
7
+ Stable tag: 3.0.12
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
+ Highly customisable Responsive Menu plugin with 150+ options. No coding knowledge needed to design it exactly as you want.
12
 
13
  == Description ==
14
+ **Description:**
 
15
  <br /><br />
16
+ Highly customisable Responsive Menu Plugin for WordPress. With over 150 customisable options you get a combination of 22,500 options! No coding experience or knowledge is needed with an easy to use interface you can get it looking exactly as you want with minimal fuss.
17
  <br /><br />
18
+ **See it in action:**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  <br /><br />
20
+ <a href="https://responsive.menu">https://responsive.menu</a>
21
  <br /><br />
22
+ **Requirements:**
23
  <br /><br />
24
+ PHP 5.4+
25
  <br /><br />
26
+ **Fully documented:**
27
+ <br /><br />
28
+ <a href="https://responsive.menu/docs/">https://responsive.menu/docs/</a>
29
+ <br /><br />
30
+ **Basic Functionality:**
31
  <ul>
32
+ <li>Change every colour</li>
33
+ <li>Set the fonts, font sizes and text alignment you want to use</li>
34
+ <li>Set which side and where you want the button to show</li>
35
+ <li>Set which side the menu appears from (left, right, top or bottom)</li>
36
+ <li>Choice of menu animations (slide over the top or push the content)</li>
37
+ <li>Choice of which Menu to use</li>
38
+ <li>Choice of screen size at which the menu will be shown</li>
39
+ <li>Choice of CSS elements to hide when menu is showing</li>
40
+ <li>Choice of Sub-menu depth to display down to</li>
41
+ <li>Choice of Animation Types & Speeds for the Menu & Button</li>
42
+ <li>Integrated search (fully customisable)</li>
43
+ <li>Ability to disable and re-order the different components</li>
44
+ <li>Ability to fix the button to the top or to let it scroll with the page</li>
45
+ <li>Ability to upload logos, sub-arrow images etc.</li>
46
+ <li>Ability to include Scripts externally, minified and in footer</li>
47
+ <li>Ability to import and export options in a click of a button</li>
48
+ <li>Ability to add custom HTML components</li>
49
+ <li>Ability to choose custom menu triggers</li>
50
  <li>WPML/Polylang Support</li>
51
+ <li>RTL Support</li>
52
+ <li>Plus much, much more!</li>
53
  </ul>
54
+
55
+ **Advanced & Pro Functionality:**
56
  <ul>
57
+ <li>Use background image for the menu</li>
58
+ <li>Preview your changes before implementing</li>
59
  <li>FontIcon Support for individual menu items</li>
60
+ <li>15 button animation effects</li>
61
+ <li>Colour opacity for all colours</li>
62
+ <li>Custom overlay colour and opacity</li>
63
+ <li>Integrated header bar</li>
64
+ <li>Let the plugin provide and style your main menu as well as hamburger menu</li>
65
  </ul>
66
+
67
  For more reasons to go Pro, please visit <a target="_blank" href="https://responsive.menu/why-go-pro/">this page</a>.
 
 
68
 
69
  == Installation ==
70
 
94
 
95
  == Screenshots ==
96
 
97
+ 1. Example Front End Menu Button
98
+
99
+ 2. Front End Expanded Menu with Background Image (requires Pro)
100
+
101
+ 3. Alternative Example Front End Expanded Menu with Background Image (requires Pro)
102
 
103
+ 4. Alternative Example Front End Expanded Menu with Background Image (requires Pro)
104
 
105
+ 5. Alternative Example Front End Expanded Menu with Background Image (requires Pro)
106
+
107
+ 6. Fully customisable Admin Screen
108
 
109
  == Changelog ==
110
 
111
+ = 3.0.12 (22nd September 2016) =
112
+ ** Requires PHP 5.4**
113
+ * Fixed close menu on link click bug with single header (Pro only)
114
+ * Fixed conflict bug with "close on link clicks" and "disable parent click" options
115
+ * Added header bar title link to WPML/Polylang
116
+ * Added alt tag option for every image
117
+ * Link target now taken into account with "Close Menu on Link Clicks"
118
+
119
  = 3.0.11 (29th August 2016) =
120
  ** Requires PHP 5.4**
121
  * Fixed export options bug (Pro only)
responsive-menu.php CHANGED
@@ -4,7 +4,7 @@
4
  Plugin Name: Responsive Menu
5
  Plugin URI: https://responsive.menu
6
  Description: Highly Customisable Responsive Menu Plugin for WordPress
7
- Version: 3.0.11
8
  Author: Responsive Menu
9
  Text Domain: responsive-menu
10
  Author URI: https://responsive.menu
4
  Plugin Name: Responsive Menu
5
  Plugin URI: https://responsive.menu
6
  Description: Highly Customisable Responsive Menu Plugin for WordPress
7
+ Version: 3.0.12
8
  Author: Responsive Menu
9
  Text Domain: responsive-menu
10
  Author URI: https://responsive.menu
src/app/Collections/OptionsCollection.php CHANGED
@@ -25,7 +25,7 @@ class OptionsCollection implements \ArrayAccess {
25
 
26
  public function getActiveArrow() {
27
  if($this->options['active_arrow_image'] && $this->options['active_arrow_image']->getValue())
28
- return '<img src="' . $this->options['active_arrow_image'] .'" />';
29
  else
30
  return $this->options['active_arrow_shape'];
31
 
@@ -33,7 +33,7 @@ class OptionsCollection implements \ArrayAccess {
33
 
34
  public function getInActiveArrow() {
35
  if($this->options['inactive_arrow_image'] && $this->options['inactive_arrow_image']->getValue())
36
- return '<img src="' . $this->options['inactive_arrow_image'] .'" />';
37
  else
38
  return $this->options['inactive_arrow_shape'];
39
 
@@ -41,7 +41,7 @@ class OptionsCollection implements \ArrayAccess {
41
 
42
  public function getTitleImage() {
43
  if($this->options['menu_title_image'] && $this->options['menu_title_image']->getValue())
44
- return '<img src="' . $this->options['menu_title_image'] .'" />';
45
  else
46
  return null;
47
 
@@ -49,14 +49,14 @@ class OptionsCollection implements \ArrayAccess {
49
 
50
  public function getButtonIcon() {
51
  if($this->options['button_image'] && $this->options['button_image']->getValue())
52
- return '<img src="' . $this->options['button_image'] .'" class="responsive-menu-button-icon responsive-menu-button-icon-active" />';
53
  else
54
  return '<span class="responsive-menu-inner"></span>';
55
  }
56
 
57
  public function getButtonIconActive() {
58
  if($this->options['button_image'] && $this->options['button_image']->getValue())
59
- return '<img src="' . $this->options['button_image_when_clicked'] .'" class="responsive-menu-button-icon responsive-menu-button-icon-inactive" />';
60
  }
61
 
62
  public function offsetExists($offset) {
25
 
26
  public function getActiveArrow() {
27
  if($this->options['active_arrow_image'] && $this->options['active_arrow_image']->getValue())
28
+ return '<img alt="' . $this->options['active_arrow_image_alt'] .'" src="' . $this->options['active_arrow_image'] .'" />';
29
  else
30
  return $this->options['active_arrow_shape'];
31
 
33
 
34
  public function getInActiveArrow() {
35
  if($this->options['inactive_arrow_image'] && $this->options['inactive_arrow_image']->getValue())
36
+ return '<img alt="' . $this->options['inactive_arrow_image_alt'] .'" src="' . $this->options['inactive_arrow_image'] .'" />';
37
  else
38
  return $this->options['inactive_arrow_shape'];
39
 
41
 
42
  public function getTitleImage() {
43
  if($this->options['menu_title_image'] && $this->options['menu_title_image']->getValue())
44
+ return '<img alt="' . $this->options['menu_title_image_alt'] .'" src="' . $this->options['menu_title_image'] .'" />';
45
  else
46
  return null;
47
 
49
 
50
  public function getButtonIcon() {
51
  if($this->options['button_image'] && $this->options['button_image']->getValue())
52
+ return '<img alt="' . $this->options['button_image_alt'] .'" src="' . $this->options['button_image'] .'" class="responsive-menu-button-icon responsive-menu-button-icon-active" />';
53
  else
54
  return '<span class="responsive-menu-inner"></span>';
55
  }
56
 
57
  public function getButtonIconActive() {
58
  if($this->options['button_image'] && $this->options['button_image']->getValue())
59
+ return '<img alt="' . $this->options['button_image_alt_when_clicked'] .'" src="' . $this->options['button_image_when_clicked'] .'" class="responsive-menu-button-icon responsive-menu-button-icon-inactive" />';
60
  }
61
 
62
  public function offsetExists($offset) {
src/app/Mappers/JsMapper.php CHANGED
@@ -145,14 +145,19 @@ class JsMapper {
145
  if(this.closeOnLinkClick == 'on') {
146
  $(this.linkElement).on('click', function(e) {
147
  e.preventDefault();
 
 
 
 
148
  old_href = $(this).attr('href');
 
149
  if(self.isOpen) {
150
  if($(e.target).closest('.responsive-menu-subarrow').length) {
151
  return;
152
  }
153
  self.closeMenu();
154
  setTimeout(function() {
155
- window.location = old_href;
156
  }, self.animationSpeed);
157
  }
158
  });
145
  if(this.closeOnLinkClick == 'on') {
146
  $(this.linkElement).on('click', function(e) {
147
  e.preventDefault();
148
+ /* Fix for when close menu on parent clicks is on */
149
+ if(self.itemTriggerSubMenu == 'on' && $(this).is('.responsive-menu-item-has-children > ' + self.linkElement)) {
150
+ return;
151
+ }
152
  old_href = $(this).attr('href');
153
+ old_target = typeof $(this).attr('target') == 'undefined' ? '_self' : $(this).attr('target');
154
  if(self.isOpen) {
155
  if($(e.target).closest('.responsive-menu-subarrow').length) {
156
  return;
157
  }
158
  self.closeMenu();
159
  setTimeout(function() {
160
+ window.open(old_href, old_target);
161
  }, self.animationSpeed);
162
  }
163
  });
src/app/Mappers/scss.inc.php CHANGED
@@ -3384,7 +3384,7 @@ class scss_parser_free {
3384
  if ($this->variable($out)) return true;
3385
  if ($this->color($out)) return true;
3386
  if ($this->unit($out)) return true;
3387
- if ($this->string($out)) return true;
3388
  if ($this->func($out)) return true;
3389
  if ($this->progid($out)) return true;
3390
 
@@ -3582,7 +3582,7 @@ class scss_parser_free {
3582
  return false;
3583
  }
3584
 
3585
- protected function string(&$out) {
3586
  $s = $this->seek();
3587
  if ($this->literal('"', false)) {
3588
  $delim = '"';
@@ -3695,7 +3695,7 @@ class scss_parser_free {
3695
  }
3696
  }
3697
 
3698
- if (($tok == "'" || $tok == '"') && $this->string($str)) {
3699
  $content[] = $str;
3700
  continue;
3701
  }
@@ -3939,7 +3939,7 @@ class scss_parser_free {
3939
  $attrParts[] = " ";
3940
  continue;
3941
  }
3942
- if ($this->string($str)) {
3943
  $attrParts[] = $str;
3944
  continue;
3945
  }
3384
  if ($this->variable($out)) return true;
3385
  if ($this->color($out)) return true;
3386
  if ($this->unit($out)) return true;
3387
+ if ($this->text($out)) return true;
3388
  if ($this->func($out)) return true;
3389
  if ($this->progid($out)) return true;
3390
 
3582
  return false;
3583
  }
3584
 
3585
+ protected function text(&$out) {
3586
  $s = $this->seek();
3587
  if ($this->literal('"', false)) {
3588
  $delim = '"';
3695
  }
3696
  }
3697
 
3698
+ if (($tok == "'" || $tok == '"') && $this->text($str)) {
3699
  $content[] = $str;
3700
  continue;
3701
  }
3939
  $attrParts[] = " ";
3940
  continue;
3941
  }
3942
+ if ($this->text($str)) {
3943
  $attrParts[] = $str;
3944
  continue;
3945
  }
src/app/Walkers/WpWalker.php CHANGED
@@ -29,6 +29,13 @@ class WpWalker extends \Walker_Nav_Menu {
29
  endswitch;
30
  endforeach;
31
 
 
 
 
 
 
 
 
32
  $class_names = join(' ', array_unique($responsive_menu_classes));
33
  $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
34
 
@@ -43,7 +50,6 @@ class WpWalker extends \Walker_Nav_Menu {
43
  $atts['href'] = ! empty( $item->url ) ? $item->url : '';
44
  $atts['class'] = 'responsive-menu-item-link';
45
 
46
-
47
  $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );
48
 
49
  $attributes = '';
29
  endswitch;
30
  endforeach;
31
 
32
+ /* Clear child class if we are at the final depth level */
33
+ if(isset($responsive_menu_classes)):
34
+ if($depth + 1 == $this->options['menu_depth']->getValue() && ($key = array_search('responsive-menu-item-has-children', $responsive_menu_classes)) !== false) {
35
+ unset($responsive_menu_classes[$key]);
36
+ }
37
+ endif;
38
+
39
  $class_names = join(' ', array_unique($responsive_menu_classes));
40
  $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
41
 
50
  $atts['href'] = ! empty( $item->url ) ? $item->url : '';
51
  $atts['class'] = 'responsive-menu-item-link';
52
 
 
53
  $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );
54
 
55
  $attributes = '';
src/config/admin_ordering.php CHANGED
@@ -139,6 +139,11 @@ $order_mapping = [
139
  'label' => __('', 'responsive-menu'),
140
  'type' => 'image'
141
  ],
 
 
 
 
 
142
  [
143
  'option' => 'menu_title_background_colour',
144
  'title' => __('Title Background Colour', 'responsive-menu'),
@@ -263,6 +268,13 @@ $order_mapping = [
263
  ],
264
  __('Background Colours', 'responsive-menu') =>
265
  [
 
 
 
 
 
 
 
266
  [
267
  'option' => 'menu_background_colour',
268
  'title' => __('Background Colour', 'responsive-menu'),
@@ -664,11 +676,21 @@ $order_mapping = [
664
  'label' => __('', 'responsive-menu'),
665
  'type' => 'image'
666
  ],
 
 
 
 
 
667
  [
668
  'option' => 'button_image_when_clicked',
669
  'title' => __('Image When Clicked', 'responsive-menu'),
670
  'label' => __('', 'responsive-menu'),
671
  'type' => 'image'
 
 
 
 
 
672
  ]
673
  ],
674
  __('Advanced', 'responsive-menu') =>
@@ -855,12 +877,22 @@ __('Sub-Menus', 'responsive-menu') => [
855
  'label' => __('', 'responsive-menu'),
856
  'type' => 'image'
857
  ],
 
 
 
 
 
858
  [
859
  'option' => 'inactive_arrow_image',
860
  'title' => __('Image Inactive', 'responsive-menu'),
861
  'label' => __('', 'responsive-menu'),
862
  'type' => 'image'
863
  ],
 
 
 
 
 
864
  [
865
  'option' => 'arrow_position',
866
  'title' => __('Icon Position', 'responsive-menu'),
@@ -1004,6 +1036,12 @@ __('Sub-Menus', 'responsive-menu') => [
1004
  'type' => 'image',
1005
  'pro' => true
1006
  ],
 
 
 
 
 
 
1007
  [
1008
  'option' => 'header_bar_logo_link',
1009
  'title' => __('Link', 'responsive-menu'),
139
  'label' => __('', 'responsive-menu'),
140
  'type' => 'image'
141
  ],
142
+ [
143
+ 'option' => 'menu_title_image_alt',
144
+ 'title' => __('Alt Text', 'responsive-menu'),
145
+ 'label' => __('', 'responsive-menu'),
146
+ ],
147
  [
148
  'option' => 'menu_title_background_colour',
149
  'title' => __('Title Background Colour', 'responsive-menu'),
268
  ],
269
  __('Background Colours', 'responsive-menu') =>
270
  [
271
+ [
272
+ 'option' => 'menu_background_image',
273
+ 'title' => __('Background Image', 'responsive-menu'),
274
+ 'label' => __('', 'responsive-menu'),
275
+ 'type' => 'image',
276
+ 'pro' => true
277
+ ],
278
  [
279
  'option' => 'menu_background_colour',
280
  'title' => __('Background Colour', 'responsive-menu'),
676
  'label' => __('', 'responsive-menu'),
677
  'type' => 'image'
678
  ],
679
+ [
680
+ 'option' => 'button_image_alt',
681
+ 'title' => __('Alt Text', 'responsive-menu'),
682
+ 'label' => __('', 'responsive-menu')
683
+ ],
684
  [
685
  'option' => 'button_image_when_clicked',
686
  'title' => __('Image When Clicked', 'responsive-menu'),
687
  'label' => __('', 'responsive-menu'),
688
  'type' => 'image'
689
+ ],
690
+ [
691
+ 'option' => 'button_image_alt_when_clicked',
692
+ 'title' => __('Alt Text', 'responsive-menu'),
693
+ 'label' => __('', 'responsive-menu')
694
  ]
695
  ],
696
  __('Advanced', 'responsive-menu') =>
877
  'label' => __('', 'responsive-menu'),
878
  'type' => 'image'
879
  ],
880
+ [
881
+ 'option' => 'active_arrow_image_alt',
882
+ 'title' => __('Alt Text', 'responsive-menu'),
883
+ 'label' => __('', 'responsive-menu')
884
+ ],
885
  [
886
  'option' => 'inactive_arrow_image',
887
  'title' => __('Image Inactive', 'responsive-menu'),
888
  'label' => __('', 'responsive-menu'),
889
  'type' => 'image'
890
  ],
891
+ [
892
+ 'option' => 'inactive_arrow_image_alt',
893
+ 'title' => __('Alt Text', 'responsive-menu'),
894
+ 'label' => __('', 'responsive-menu')
895
+ ],
896
  [
897
  'option' => 'arrow_position',
898
  'title' => __('Icon Position', 'responsive-menu'),
1036
  'type' => 'image',
1037
  'pro' => true
1038
  ],
1039
+ [
1040
+ 'option' => 'header_bar_logo_alt',
1041
+ 'title' => __('Alt Text', 'responsive-menu'),
1042
+ 'label' => __('', 'responsive-menu'),
1043
+ 'pro' => true
1044
+ ],
1045
  [
1046
  'option' => 'header_bar_logo_link',
1047
  'title' => __('Link', 'responsive-menu'),
src/config/default_options.php CHANGED
@@ -11,7 +11,9 @@ $default_options = [
11
  // Button Settings
12
  'button_title' => null,
13
  'button_image' => null,
 
14
  'button_image_when_clicked' => null,
 
15
  'button_font' => null,
16
  'button_font_icon' => null,
17
  'button_font_icon_when_clicked' => null,
@@ -46,7 +48,9 @@ $default_options = [
46
  'active_arrow_shape' => '▲',
47
  'inactive_arrow_shape' => '▼',
48
  'active_arrow_image' => '',
 
49
  'inactive_arrow_image' => '',
 
50
  'active_arrow_font_icon' => '',
51
  'inactive_arrow_font_icon' => '',
52
  'arrow_position' => 'right',
@@ -57,6 +61,7 @@ $default_options = [
57
  'auto_expand_current_submenus' => 'off',
58
 
59
  'menu_background_colour' => '#212121',
 
60
  'menu_item_background_colour' => '#212121',
61
  'menu_item_background_hover_colour' => '#3f3f3f',
62
  'menu_item_border_colour' => '#212121',
@@ -97,6 +102,7 @@ $default_options = [
97
  'menu_additional_content_colour' => '#fff',
98
  'menu_title' => null,
99
  'menu_title_image' => null,
 
100
  'menu_title_font_icon' => null,
101
  'menu_appear_from' => 'left',
102
  'menu_title_link' => null,
@@ -148,6 +154,7 @@ $default_options = [
148
  'use_header_bar' => 'off',
149
  'header_bar_breakpoint' => '800',
150
  'header_bar_logo' => null,
 
151
  'header_bar_logo_link' => null,
152
  'header_bar_title' => null,
153
  'header_bar_html_content' => null,
@@ -158,7 +165,7 @@ $default_options = [
158
  'header_bar_text_color' => '#ffffff',
159
  'header_bar_position_type' => 'fixed',
160
 
161
- 'items_order' => '{"title": "on","menu":"on","search":"on","additional content":"on"}',
162
- 'header_bar_items_order' => '{"logo": "on","title":"on","search":"on","html content":"on","button":"on"}',
163
 
164
  ];
11
  // Button Settings
12
  'button_title' => null,
13
  'button_image' => null,
14
+ 'button_image_alt' => null,
15
  'button_image_when_clicked' => null,
16
+ 'button_image_alt_when_clicked' => null,
17
  'button_font' => null,
18
  'button_font_icon' => null,
19
  'button_font_icon_when_clicked' => null,
48
  'active_arrow_shape' => '▲',
49
  'inactive_arrow_shape' => '▼',
50
  'active_arrow_image' => '',
51
+ 'active_arrow_image_alt' => '',
52
  'inactive_arrow_image' => '',
53
+ 'inactive_arrow_image_alt' => '',
54
  'active_arrow_font_icon' => '',
55
  'inactive_arrow_font_icon' => '',
56
  'arrow_position' => 'right',
61
  'auto_expand_current_submenus' => 'off',
62
 
63
  'menu_background_colour' => '#212121',
64
+ 'menu_background_image' => '',
65
  'menu_item_background_colour' => '#212121',
66
  'menu_item_background_hover_colour' => '#3f3f3f',
67
  'menu_item_border_colour' => '#212121',
102
  'menu_additional_content_colour' => '#fff',
103
  'menu_title' => null,
104
  'menu_title_image' => null,
105
+ 'menu_title_image_alt' => null,
106
  'menu_title_font_icon' => null,
107
  'menu_appear_from' => 'left',
108
  'menu_title_link' => null,
154
  'use_header_bar' => 'off',
155
  'header_bar_breakpoint' => '800',
156
  'header_bar_logo' => null,
157
+ 'header_bar_logo_alt' => '',
158
  'header_bar_logo_link' => null,
159
  'header_bar_title' => null,
160
  'header_bar_html_content' => null,
165
  'header_bar_text_color' => '#ffffff',
166
  'header_bar_position_type' => 'fixed',
167
 
168
+ 'items_order' => '{"title":"on","menu":"on","search":"on","additional content":"on"}',
169
+ 'header_bar_items_order' => '{"logo":"on","title":"on","search":"on","html content":"on","button":"on"}',
170
 
171
  ];
src/config/option_helpers.php CHANGED
@@ -4,6 +4,9 @@ $option_helpers = [
4
  'menu_font_icons' => [
5
  'filter' => 'ResponsiveMenu\Filters\JsonFilter'
6
  ],
 
 
 
7
  'menu_additional_content' => [
8
  'filter' => 'ResponsiveMenu\Filters\HtmlFilter'
9
  ],
4
  'menu_font_icons' => [
5
  'filter' => 'ResponsiveMenu\Filters\JsonFilter'
6
  ],
7
+ 'menu_title' => [
8
+ 'filter' => 'ResponsiveMenu\Filters\HtmlFilter'
9
+ ],
10
  'menu_additional_content' => [
11
  'filter' => 'ResponsiveMenu\Filters\HtmlFilter'
12
  ],
src/config/services.php CHANGED
@@ -3,7 +3,7 @@
3
  $container = new ResponsiveMenu\Routing\Container();
4
 
5
  $container['current_version'] = function($c) {
6
- return '3.0.11';
7
  };
8
 
9
  $container['option_helpers'] = function($c) {
3
  $container = new ResponsiveMenu\Routing\Container();
4
 
5
  $container['current_version'] = function($c) {
6
+ return '3.0.12';
7
  };
8
 
9
  $container['option_helpers'] = function($c) {
tests/app/Collections/OptionsCollectionTest.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class OptionsCollectionTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->collection = new ResponsiveMenu\Collections\OptionsCollection;
9
+ }
10
+
11
+ public function testAddingOptionReturnTypes() {
12
+ $this->collection->add(new ResponsiveMenu\Models\Option('a', 'a'));
13
+ $all_options = $this->collection->all();
14
+ $this->assertInternalType('array', $all_options);
15
+ $this->assertInstanceOf('ResponsiveMenu\Models\Option', $all_options['a']);
16
+ }
17
+
18
+ public function testAddingMultipleOptionReturnTypes() {
19
+ $this->collection->add(new ResponsiveMenu\Models\Option('a', 'a'));
20
+ $this->collection->add(new ResponsiveMenu\Models\Option('b', 'b'));
21
+ $all_options = $this->collection->all();
22
+ $this->assertInternalType('array', $all_options);
23
+ $this->assertInstanceOf('ResponsiveMenu\Models\Option', $all_options['a']);
24
+ $this->assertInstanceOf('ResponsiveMenu\Models\Option', $all_options['b']);
25
+ }
26
+
27
+ public function testAddingOptionGetOptionReturnTypes() {
28
+ $this->collection->add(new ResponsiveMenu\Models\Option('a', 'a'));
29
+ $this->assertInstanceOf('ResponsiveMenu\Models\Option', $this->collection->get('a'));
30
+ }
31
+
32
+ public function testAddingMultipleOptionGetOptionReturnTypes() {
33
+ $this->collection->add(new ResponsiveMenu\Models\Option('a', 'a'));
34
+ $this->collection->add(new ResponsiveMenu\Models\Option('b', 'b'));
35
+
36
+ $this->assertInstanceOf('ResponsiveMenu\Models\Option', $this->collection->get('a'));
37
+ $this->assertInstanceOf('ResponsiveMenu\Models\Option', $this->collection->get('b'));
38
+ }
39
+
40
+ public function testUsesFontAwesomeIcons() {
41
+ $this->assertFalse($this->collection->usesFontIcons());
42
+ }
43
+
44
+ public function testGetActiveArrow() {
45
+ $this->collection->add(new ResponsiveMenu\Models\Option('active_arrow_image', 'test.jpg'));
46
+ $this->collection->add(new ResponsiveMenu\Models\Option('active_arrow_image_alt', 'test-alt'));
47
+ $this->assertEquals('<img alt="test-alt" src="test.jpg" />', $this->collection->getActiveArrow());
48
+ }
49
+
50
+ public function testGetActiveArrowDoesntExist() {
51
+ $this->collection->add(new ResponsiveMenu\Models\Option('active_arrow_image', ''));
52
+ $this->collection->add(new ResponsiveMenu\Models\Option('active_arrow_shape', 'arrow'));
53
+ $this->assertEquals('arrow', $this->collection->getActiveArrow());
54
+ }
55
+
56
+ public function testGetInactiveArrow() {
57
+ $this->collection->add(new ResponsiveMenu\Models\Option('inactive_arrow_image', 'test.jpg'));
58
+ $this->collection->add(new ResponsiveMenu\Models\Option('inactive_arrow_image_alt', 'test-alt'));
59
+ $this->assertEquals('<img alt="test-alt" src="test.jpg" />', $this->collection->getInActiveArrow());
60
+ }
61
+
62
+ public function testGetInactiveArrowDoesntExist() {
63
+ $this->collection->add(new ResponsiveMenu\Models\Option('inactive_arrow_image', ''));
64
+ $this->collection->add(new ResponsiveMenu\Models\Option('inactive_arrow_shape', 'arrow'));
65
+ $this->assertEquals('arrow', $this->collection->getInActiveArrow());
66
+ }
67
+
68
+ public function testGetInactiveTitleImage() {
69
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_title_image', 'test.jpg'));
70
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_title_image_alt', 'test-alt'));
71
+ $this->assertEquals('<img alt="test-alt" src="test.jpg" />', $this->collection->getTitleImage());
72
+ }
73
+
74
+ public function testGetInactiveTitleImageDoesntExist() {
75
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_title_image', ''));
76
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_title_image_alt', ''));
77
+ $this->assertEquals(null, $this->collection->getTitleImage());
78
+ }
79
+
80
+ public function testGetButtonIcon() {
81
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_image', 'test.jpg'));
82
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_image_alt', 'test-alt'));
83
+ $this->assertEquals('<img alt="test-alt" src="test.jpg" class="responsive-menu-button-icon responsive-menu-button-icon-active" />', $this->collection->getButtonIcon());
84
+ }
85
+
86
+ public function testGetButtonIconDoesntExist() {
87
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_image', ''));
88
+ $this->assertEquals('<span class="responsive-menu-inner"></span>', $this->collection->getButtonIcon());
89
+ }
90
+
91
+ public function testGetButtonIconActive() {
92
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_image', 'test2.jpg'));
93
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_image_alt', 'alt-a'));
94
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_image_when_clicked', 'test.jpg'));
95
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_image_alt_when_clicked', 'alt-b'));
96
+ $this->assertEquals('<img alt="alt-b" src="test.jpg" class="responsive-menu-button-icon responsive-menu-button-icon-inactive" />', $this->collection->getButtonIconActive());
97
+ }
98
+
99
+ public function testGetButtonIconActiveDoesntExist() {
100
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_image', ''));
101
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_image_alt', ''));
102
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_image_when_clicked', 'test.jpg'));
103
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_image_alt_when_clicked', 'test.jpg'));
104
+ $this->assertEquals(null, $this->collection->getButtonIconActive());
105
+ }
106
+
107
+ public function testIsCollectionEmpty() {
108
+ $this->assertTrue($this->collection->isEmpty());
109
+ }
110
+
111
+ public function testIsCollectionEmptyNotEmpty() {
112
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_image', 'test.jpg'));
113
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_image_alt', 'test.jpg'));
114
+ $this->assertFalse($this->collection->isEmpty());
115
+ }
116
+
117
+ public function testArrayAccessGetFunctions() {
118
+ $this->collection->add(new ResponsiveMenu\Models\Option('a', 'a'));
119
+ $this->collection->add(new ResponsiveMenu\Models\Option('b', 'b'));
120
+ $this->assertInstanceOf('ResponsiveMenu\Models\Option', $this->collection['a']);
121
+ $this->assertInstanceOf('ResponsiveMenu\Models\Option', $this->collection['b']);
122
+ }
123
+
124
+ public function testArrayAccessSetFunctions() {
125
+ $this->collection['a'] = new ResponsiveMenu\Models\Option('a', 'a');
126
+ $this->collection['b'] = new ResponsiveMenu\Models\Option('b', 'b');
127
+ $this->assertInstanceOf('ResponsiveMenu\Models\Option', $this->collection->get('a'));
128
+ $this->assertInstanceOf('ResponsiveMenu\Models\Option', $this->collection->get('b'));
129
+ }
130
+
131
+ public function testArrayAccessUnSetFunctions() {
132
+ $this->collection['a'] = new ResponsiveMenu\Models\Option('a', 'a');
133
+ $this->collection['b'] = new ResponsiveMenu\Models\Option('b', 'b');
134
+ unset($this->collection['b']);
135
+ $this->assertArrayNotHasKey('b', $this->collection);
136
+ }
137
+
138
+ }
tests/app/Controllers/AdminTest.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+ use ResponsiveMenu\Collections\OptionsCollection;
5
+ use ResponsiveMenu\Models\Option;
6
+
7
+ class AdminTest extends TestCase {
8
+
9
+ static public function setUpBeforeClass() {
10
+ function __($a, $b) {
11
+ return $a;
12
+ }
13
+ }
14
+ public function setUp() {
15
+ $this->view = $this->createMock('ResponsiveMenu\View\AdminView');
16
+ $this->service = $this->createMock('ResponsiveMenu\Services\OptionService');
17
+ $this->view->method('render')->willReturn(true);
18
+ $this->view->method('display')->will($this->returnArgument(0));
19
+ $this->service->method('combineOptions')->willReturn([]);
20
+ $collection = new OptionsCollection;
21
+ $collection->add(new Option('a', 1));
22
+ $this->service->method('all')->willReturn($collection);
23
+ $this->controller = new ResponsiveMenu\Controllers\Admin($this->service, $this->view);
24
+
25
+ }
26
+
27
+ public function testUpdate() {
28
+ $this->assertTrue($this->controller->update([],[]));
29
+ }
30
+
31
+ public function testReset() {
32
+ $this->assertTrue($this->controller->reset([]));
33
+ }
34
+
35
+ public function testIndex() {
36
+ $this->assertTrue($this->controller->index([]));
37
+ }
38
+
39
+ public function testExport() {
40
+ $this->assertNull($this->controller->export());
41
+ }
42
+
43
+ public function testImportNoFile() {
44
+ $this->assertTrue($this->controller->import(['a' => 1], null));
45
+ }
46
+
47
+ public function testImport() {
48
+ $this->assertTrue($this->controller->import(['a' => 1], ['b' => 2]));
49
+ }
50
+
51
+ }
tests/app/Controllers/FrontTest.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+ use ResponsiveMenu\Collections\OptionsCollection;
5
+ use ResponsiveMenu\Models\Option;
6
+
7
+ class FrontTest extends TestCase {
8
+
9
+ public function setUp() {
10
+ $this->view = $this->createMock('ResponsiveMenu\View\FrontView');
11
+ $this->service = $this->createMock('ResponsiveMenu\Services\OptionService');
12
+ $this->menu = $this->createMock('ResponsiveMenu\ViewModels\Menu');
13
+ $this->button = $this->createMock('ResponsiveMenu\ViewModels\Button');
14
+ $this->collection = new OptionsCollection;
15
+
16
+ $this->view->method('render')->willReturn('rendered');
17
+ $this->controller = new ResponsiveMenu\Controllers\Front($this->service, $this->view, $this->menu, $this->button);
18
+
19
+ }
20
+
21
+ public function testPreview() {
22
+ $this->assertEquals('rendered', $this->controller->preview());
23
+ }
24
+
25
+ public function testIndexShortcodeIsNotCalled() {
26
+ $this->collection->add(new Option('shortcode', 'off'));
27
+ $this->service->method('all')->willReturn($this->collection);
28
+ $this->assertEquals('rendered', $this->controller->index());
29
+ }
30
+
31
+ public function testIndexShortcodeIsCalled() {
32
+ $this->service->method('all')->willReturn($this->collection);
33
+ $this->view->method('addShortcode')->willReturn('shortcode added');
34
+ $this->assertEquals('shortcode added', $this->controller->index());
35
+ }
36
+
37
+ }
tests/app/Database/MigrationTest.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+ use ResponsiveMenu\Collections\OptionsCollection;
5
+ use ResponsiveMenu\Database\Migration;
6
+ use ResponsiveMenu\Models\Option;
7
+
8
+ class MigrationTest extends TestCase {
9
+
10
+ public function setUp() {
11
+ $this->database = $this->createMock('ResponsiveMenu\Database\WpDatabase');
12
+ $this->service = $this->createMock('ResponsiveMenu\Services\OptionService');
13
+ $this->defaults = ['default_one' => 1, 'default_two' => 'string', 'default_three' => 4.5, 'default_four' => 'new'];
14
+ $this->current_version = '3.0.8';
15
+ $this->old_version = '3.0.7';
16
+ $this->old_options = ['default_one' => 4, 'default_two' => 'old string', 'default_three' => 4.5, 'RM' => 'old RM value', 'RMDepth' => 'old RMDepth value'];
17
+
18
+ $this->base_migration = new Migration($this->database, $this->service, $this->defaults, $this->current_version, $this->old_version, $this->old_options);
19
+
20
+ $this->options_collection = new OptionsCollection;
21
+ $this->options_collection->add(new Option('default_one', 5));
22
+ $this->options_collection->add(new Option('default_two', 'string'));
23
+ $this->options_collection->add(new Option('default_three', 7.5));
24
+
25
+ /*
26
+ * Mock the repository all() function to return controlled options collection
27
+ */
28
+ $service_options = new OptionsCollection;
29
+ $service_options->add(new Option('default_one', 5));
30
+ $service_options->add(new Option('default_two', 'new option'));
31
+ $service_options->add(new Option('to_delete', 'delete me!'));
32
+ $service_options->add(new Option('to_delete_also', 'delete me too!'));
33
+ $this->service->method('all')->willReturn($service_options);
34
+
35
+ }
36
+
37
+ public function testVersionCompareNeedsUpdate() {
38
+ $this->assertTrue($this->base_migration->needsUpdate());
39
+ }
40
+
41
+ public function testVersionCompareDoesntNeedUpdate() {
42
+ $migration = new Migration($this->database, $this->service, $this->defaults, $this->current_version, '3.0.9', $this->old_options);
43
+ $this->assertFalse($migration->needsUpdate());
44
+ }
45
+
46
+ public function testVersionCompareNeedUpdateWithDoubleEndPoint() {
47
+ $migration = new Migration($this->database, $this->service, $this->defaults, '3.0.10', $this->old_version, $this->old_options);
48
+ $this->assertTrue($migration->needsUpdate());
49
+ }
50
+
51
+ public function testVersionCompareDoesntNeedUpdateWithDoubleEndPoint() {
52
+ $migration = new Migration($this->database, $this->service, $this->defaults, '3.0.10', '3.1.0', $this->old_options);
53
+ $this->assertFalse($migration->needsUpdate());
54
+ }
55
+
56
+ public function testVersionCompareDoesNeedUpdateWithTenComparedToOne() {
57
+ $migration = new Migration($this->database, $this->service, $this->defaults, '3.0.10', '3.0.1', $this->old_options);
58
+ $this->assertTrue($migration->needsUpdate());
59
+ }
60
+
61
+ public function testVersionCompareDoesntNeedUpdateWithOneComparedToTen() {
62
+ $migration = new Migration($this->database, $this->service, $this->defaults, '3.0.1', '3.0.10', $this->old_options);
63
+ $this->assertFalse($migration->needsUpdate());
64
+ }
65
+
66
+ public function testVersionCompareDoesntNeedUpdateWithDoubleEndPointWithVersionHigher() {
67
+ $migration = new Migration($this->database, $this->service, $this->defaults, '3.0.10', '3.2.0', $this->old_options);
68
+ $this->assertFalse($migration->needsUpdate());
69
+ }
70
+
71
+ public function testVersionCompareDoesNeedUpdateWithDoubleEndPointWithVersionHigher() {
72
+ $migration = new Migration($this->database, $this->service, $this->defaults, '3.2.0', '3.0.10', $this->old_options);
73
+ $this->assertTrue($migration->needsUpdate());
74
+ }
75
+
76
+ public function testNewOptionsReturnedAreCorrect() {
77
+ $this->assertSame(['default_four' => 'new'], $this->base_migration->getNewOptions($this->options_collection));
78
+ }
79
+
80
+ public function testIsVersion3CheckReturnsFalse() {
81
+ $migration = new Migration($this->database, $this->service, $this->defaults, $this->current_version, '2.8.0', $this->old_options);
82
+ $this->assertFalse($migration->isVersion3());
83
+ }
84
+
85
+ public function testIsVersion3CheckReturnsTrue() {
86
+ $this->assertTrue($this->base_migration->isVersion3());
87
+ }
88
+
89
+ public function testDeletableOptions() {
90
+ $this->assertSame(['to_delete' => 'to_delete', 'to_delete_also' => 'to_delete_also'], $this->base_migration->getOptionsToDelete());
91
+ }
92
+
93
+ public function testOptionsToMigrate() {
94
+ $this->assertSame(['menu_to_use' => 'old RM value', 'menu_depth' => 'old RMDepth value'], $this->base_migration->getMigratedOptions());
95
+ }
96
+
97
+ public function testSetup() {
98
+ $this->database->method('createTable')->willReturn(true);
99
+ $migration = new Migration($this->database, $this->service, $this->defaults, '3.0.10', '2.8.9', $this->old_options);
100
+ $this->assertEquals(null, $migration->setUp());
101
+ }
102
+
103
+ public function testSynchronise() {
104
+ $this->assertEquals(null, $this->base_migration->synchronise());
105
+ }
106
+
107
+ public function testAddNewOptionsEmpty() {
108
+ $service = $this->createMock('ResponsiveMenu\Services\OptionService');
109
+ $service->method('all')->willReturn(new ResponsiveMenu\Collections\OptionsCollection);
110
+ $migration = new Migration($this->database, $service, $this->defaults, $this->current_version, $this->old_version, $this->old_options);
111
+ $this->assertEquals(null, $migration->addNewOptions());
112
+ }
113
+
114
+ }
tests/app/Database/WpDatabaseTest.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+ use ResponsiveMenu\Database\WpDatabase;
5
+
6
+ class WpDatabaseTest extends TestCase {
7
+
8
+ public function setUp() {
9
+ $this->wpdb = $this->getMockBuilder('wpdb')
10
+ ->setMethods(['update', 'delete', 'get_results', 'insert', 'select'])
11
+ ->getMock();
12
+ $this->wpdb->prefix = 'prefix';
13
+ $this->db = new WpDatabase($this->wpdb);
14
+
15
+ if(!function_exists('current_time')):
16
+ function current_time($type) {
17
+ return '0000';
18
+ }
19
+ endif;
20
+
21
+ if(!function_exists('update_option')):
22
+ function update_option($a, $b) {
23
+ return $a . ' ' . $b;
24
+ }
25
+ endif;
26
+ }
27
+
28
+ public function testUpdate() {
29
+ $this->wpdb->method('update')->will($this->returnArgument(0));
30
+ $this->assertEquals('prefixupdate_arg', $this->db->update('update_arg', [], []));
31
+ }
32
+
33
+ public function testDelete() {
34
+ $this->wpdb->method('delete')->will($this->returnArgument(0));
35
+ $this->assertEquals('prefixdelete_arg', $this->db->delete('delete_arg', 'b'));
36
+ }
37
+
38
+ public function testGetResults() {
39
+ $this->wpdb->method('get_results')->will($this->returnArgument(0));
40
+ $this->assertEquals('SELECT * FROM prefixget_results_arg', $this->db->all('get_results_arg'));
41
+ }
42
+
43
+ public function testInsertResults() {
44
+ $this->wpdb->method('insert')->will($this->returnArgument(0));
45
+ $this->assertEquals('prefixinsert_arg', $this->db->insert('insert_arg', []));
46
+ }
47
+
48
+ public function testSelectResults() {
49
+ $this->wpdb->method('get_results')->will($this->returnArgument(0));
50
+ $this->assertEquals('SELECT * FROM prefixselect_arg WHERE a = \'b\';', $this->db->select('select_arg', 'a', 'b'));
51
+ }
52
+
53
+ public function testMySqlTime() {
54
+ $this->assertEquals('0000', $this->db->mySqlTime());
55
+ }
56
+
57
+ public function testUpdateOption() {
58
+ $this->assertEquals('a b', $this->db->updateOption('a', 'b'));
59
+ }
60
+
61
+ }
tests/app/Factories/CssFactoryTest.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+ use ResponsiveMenu\Factories\CssFactory;
5
+ use ResponsiveMenu\Collections\OptionsCollection;
6
+ use ResponsiveMenu\Models\Option;
7
+
8
+ class CssFactoryTest extends TestCase {
9
+
10
+ public function setUp() {
11
+ $this->base_mapper = $this->createMock('ResponsiveMenu\Mappers\ScssBaseMapper');
12
+ $this->button_mapper = $this->createMock('ResponsiveMenu\Mappers\ScssButtonMapper');
13
+ $this->menu_mapper = $this->createMock('ResponsiveMenu\Mappers\ScssMenuMapper');
14
+ $this->minifier = $this->createMock('ResponsiveMenu\Formatters\Minify');
15
+
16
+ $this->base_mapper->method('map')->willReturn('a');
17
+ $this->button_mapper->method('map')->willReturn('b');
18
+ $this->menu_mapper->method('map')->willReturn('c');
19
+ $this->minifier->method('minify')->willReturn('d');
20
+ $this->factory = new CssFactory($this->minifier, $this->base_mapper, $this->button_mapper, $this->menu_mapper);
21
+ }
22
+
23
+ public function testMinified() {
24
+ $collection = new OptionsCollection;
25
+ $collection->add(new Option('minify_scripts', 'on'));
26
+ $this->assertequals('d', $this->factory->build($collection));
27
+ }
28
+
29
+ public function testNotMinified() {
30
+ $collection = new OptionsCollection;
31
+ $collection->add(new Option('minify_scripts', 'off'));
32
+ $this->assertequals('abc', $this->factory->build($collection));
33
+ }
34
+
35
+ }
tests/app/Factories/JsFactoryTest.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+ use ResponsiveMenu\Factories\JsFactory;
5
+ use ResponsiveMenu\Collections\OptionsCollection;
6
+ use ResponsiveMenu\Models\Option;
7
+
8
+ class JsFactoryTest extends TestCase {
9
+
10
+ public function setUp() {
11
+ $this->mapper = $this->createMock('ResponsiveMenu\Mappers\JsMapper');
12
+ $this->minifier = $this->createMock('ResponsiveMenu\Formatters\Minify');
13
+ $this->mapper->method('map')->willReturn('a');
14
+ $this->minifier->method('minify')->willReturn('b');
15
+ $this->factory = new JsFactory($this->mapper, $this->minifier);
16
+ }
17
+
18
+ public function testMinified() {
19
+ $collection = new OptionsCollection;
20
+ $collection->add(new Option('minify_scripts', 'on'));
21
+ $this->assertequals('b', $this->factory->build($collection));
22
+ }
23
+
24
+ public function testNotMinified() {
25
+ $collection = new OptionsCollection;
26
+ $collection->add(new Option('minify_scripts', 'off'));
27
+ $this->assertequals('a', $this->factory->build($collection));
28
+ }
29
+
30
+ }
tests/app/Factories/OptionFactoryTest.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class OptionFactoryTest extends TestCase {
6
+
7
+ public static function setUpBeforeClass() {
8
+ if(!function_exists('stripslashes_deep')):
9
+ function stripslashes_deep($a) {
10
+ return $a;
11
+ }
12
+ endif;
13
+ }
14
+
15
+ public function setUp() {
16
+ $defaults = ['a' => 1, 'b' => 2, 'c' => 3];
17
+ $helpers = ['a' => ['filter' => 'ResponsiveMenu\Filters\HtmlFilter'], 'c' => ['filter' => 'ResponsiveMenu\Filters\JsonFilter']];
18
+ $this->factory = new ResponsiveMenu\Factories\OptionFactory($defaults, $helpers);
19
+ }
20
+
21
+ public function testSetFilterIsReturned() {
22
+ $option = $this->factory->build('a', 4);
23
+ $this->assertInstanceOf('ResponsiveMenu\Filters\HtmlFilter', $option->getFilter());
24
+ }
25
+
26
+ public function testDefaultFilterIsReturned() {
27
+ $option = $this->factory->build('b', 4);
28
+ $this->assertInstanceOf('ResponsiveMenu\Filters\TextFilter', $option->getFilter());
29
+ }
30
+
31
+ public function testOptionIsReturned() {
32
+ $option = $this->factory->build('b', 4);
33
+ $this->assertInstanceOf('ResponsiveMenu\Models\Option', $option);
34
+ }
35
+
36
+ public function testDefaultIsReturnedIfValueIsNull() {
37
+ $option = $this->factory->build('b', null);
38
+ $this->assertEquals(2, $option->getValue());
39
+ }
40
+
41
+ public function testZeroIsReturnedAndNotDefault() {
42
+ $option = $this->factory->build('b', 0);
43
+ $this->assertEquals(0, $option->getValue());
44
+ }
45
+
46
+ public function testUpdatedValueIsReturned() {
47
+ $option = $this->factory->build('a', 'updated');
48
+ $this->assertEquals('updated', $option->getValue());
49
+ }
50
+
51
+ public function testDecodingArrayData() {
52
+ $option = $this->factory->build('a', ['a' => 1, 'b' => ['a' => 1, 'b' => 2]]);
53
+ $this->assertEquals(['a' => 1, 'b' => ['a' => 1, 'b' => 2]], $option->getValue());
54
+ }
55
+
56
+ public function testDecodedOfJsonDataToArray() {
57
+ $option = $this->factory->build('c', '{"a":"1","b":"2"}');
58
+ $this->assertEquals('{"a":"1","b":"2"}', $option->getValue());
59
+ }
60
+
61
+ }
tests/app/Filesystem/FileCreatorTest.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class FileCreatorTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->creator = new ResponsiveMenu\Filesystem\FileCreator;
9
+ }
10
+
11
+ public function testCreate() {
12
+ $this->assertTrue($this->creator->create(dirname(__FILE__), 'test.txt','a'));
13
+ $this->assertEquals('a', file_get_contents(dirname(__FILE__) . '/test.txt'));
14
+ }
15
+
16
+ public function testFailToCreate() {
17
+ $this->assertFalse($this->creator->create('', 'test.txt','a'));
18
+ }
19
+
20
+ public function tearDown() {
21
+ if(file_exists(dirname(__FILE__). '/test.txt'))
22
+ unlink(dirname(__FILE__). '/test.txt');
23
+ }
24
+
25
+ }
tests/app/Filesystem/FolderCreatorTest.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class FolderCreatorTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->creator = new ResponsiveMenu\Filesystem\FolderCreator;
9
+ $this->dir = dirname(__FILE__) . '/tmp';
10
+ }
11
+
12
+ public function testCreate() {
13
+ $this->creator->create($this->dir);
14
+ $this->assertTrue($this->creator->exists($this->dir));
15
+ }
16
+
17
+ public function tearDown() {
18
+ rmdir($this->dir);
19
+ }
20
+
21
+ }
tests/app/Filesystem/ScriptsBuilderTest.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class ScriptsBuilderTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->files = $this->createMock('ResponsiveMenu\Filesystem\FileCreator');
9
+ $this->folders = $this->createMock('ResponsiveMenu\Filesystem\FolderCreator');
10
+ $this->css = $this->createMock('ResponsiveMenu\Factories\CssFactory');
11
+ $this->js = $this->createMock('ResponsiveMenu\Factories\JsFactory');
12
+ $this->collection = $this->createMock('ResponsiveMenu\Collections\OptionsCollection');
13
+ $this->id = 2;
14
+
15
+ $this->builder = new ResponsiveMenu\Filesystem\ScriptsBuilder($this->css, $this->js, $this->files, $this->folders, $this->id);
16
+
17
+ }
18
+
19
+ public function testBuild() {
20
+ $this->assertEquals(null, $this->builder->build($this->collection));
21
+ }
22
+
23
+ }
tests/app/Filters/HtmlFilterTest.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class HtmlFilterTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->filter = new ResponsiveMenu\Filters\HtmlFilter;
9
+ }
10
+
11
+ public function testFiltered() {
12
+ $this->assertEquals('a', $this->filter->filter('a'));
13
+ }
14
+
15
+ }
tests/app/Filters/JsonFilterTest.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class JsonFilterTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->filter = new ResponsiveMenu\Filters\JsonFilter;
9
+ }
10
+
11
+ public function testFilteredWithString() {
12
+ $this->assertEquals('{"a":1,"b":2}', $this->filter->filter('{"a":1,"b":2}'));
13
+ }
14
+
15
+ public function testFilteredWithArray() {
16
+ $this->assertEquals('{"a":1,"b":2}', $this->filter->filter(['a' => 1, 'b' => 2]));
17
+ }
18
+
19
+ }
tests/app/Filters/TextFilterTest.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class TextFilterTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->filter = new ResponsiveMenu\Filters\TextFilter;
9
+ }
10
+
11
+ public function testFilteredWithString() {
12
+ $this->assertEquals('a', $this->filter->filter('a'));
13
+ }
14
+
15
+ public function testFilteredWithHtml() {
16
+ $this->assertEquals('a', $this->filter->filter('<span class="test">a</span>'));
17
+ }
18
+
19
+ }
tests/app/Form/CheckboxTest.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class CheckboxTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->form_component = new ResponsiveMenu\Form\Checkbox;
9
+ }
10
+
11
+ public function testRendering() {
12
+ $output = $this->form_component->render(new ResponsiveMenu\Models\Option('a', 1));
13
+ $this->assertEquals("<div class='onoffswitch'>
14
+ <input type='checkbox' class='checkbox onoffswitch-checkbox' id='a' name='menu[a]' value='on' />
15
+ <label class='onoffswitch-label' for='a'>
16
+ <span class='onoffswitch-inner'></span>
17
+ <span class='onoffswitch-switch'></span>
18
+ </label>
19
+ </div>", $output);
20
+ }
21
+
22
+ public function testRenderingTurnedOn() {
23
+ $output = $this->form_component->render(new ResponsiveMenu\Models\Option('a', 'on'));
24
+ $this->assertEquals("<div class='onoffswitch'>
25
+ <input type='checkbox' class='checkbox onoffswitch-checkbox' id='a' checked='checked' name='menu[a]' value='on' />
26
+ <label class='onoffswitch-label' for='a'>
27
+ <span class='onoffswitch-inner'></span>
28
+ <span class='onoffswitch-switch'></span>
29
+ </label>
30
+ </div>", $output);
31
+ }
32
+
33
+ }
tests/app/Form/ColourTest.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class ColourTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->form_component = new ResponsiveMenu\Form\Colour;
9
+ }
10
+
11
+ public function testRendering() {
12
+ $output = $this->form_component->render(new ResponsiveMenu\Models\Option('a', 1));
13
+ $this->assertEquals("<input type='text' class='colour wp-color-picker' id='a' name='menu[a]' value='1' />", $output);
14
+ }
15
+
16
+ }
tests/app/Form/ExportTest.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class ExportTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->form_component = new ResponsiveMenu\Form\Export;
9
+ }
10
+
11
+ public function testRendering() {
12
+ $output = $this->form_component->render();
13
+ $this->assertEquals('<input type="submit" class="button submit" name="responsive_menu_export" value="Export Options" />', $output);
14
+ }
15
+
16
+ }
tests/app/Form/FontIconPageListTest.php ADDED
File without changes
tests/app/Form/FontIconTest.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class FontIconPageListTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->form_component = new ResponsiveMenu\Form\FontIconPageList;
9
+ }
10
+
11
+ public function testRendering() {
12
+ $output = $this->form_component->render(new ResponsiveMenu\Models\Option('a', '{"id":["1", "2"],"icon":["a", "b"]}'));
13
+ $this->assertContains("class='a_icon'", $output);
14
+ $this->assertContains("value='2'", $output);
15
+ $this->assertContains("value='b'", $output);
16
+ }
17
+
18
+ public function testRenderingWhenEmpty() {
19
+ $output = $this->form_component->render(new ResponsiveMenu\Models\Option('a', 'b'));
20
+ $this->assertContains("class='a_icon'", $output);
21
+ }
22
+
23
+ }
tests/app/Form/HeaderBarOrderingTest.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class HeaderBarOrderingTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->form_component = new ResponsiveMenu\Form\HeaderBarOrdering;
9
+ }
10
+
11
+ public function testRendering() {
12
+ $output = $this->form_component->render(new ResponsiveMenu\Models\Option('a', '{"search": "on", "button": "off"}'));
13
+ $this->assertContains('order-option-switch order-option-switch-on', $output);
14
+ $this->assertContains('value="off" name="menu[a][button]"', $output);
15
+ $this->assertContains('value="on" name="menu[a][search]"', $output);
16
+ }
17
+
18
+ }
tests/app/Form/ImageTest.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class ImageTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->form_component = new ResponsiveMenu\Form\Image;
9
+ }
10
+
11
+ public function testRendering() {
12
+ $output = $this->form_component->render(new ResponsiveMenu\Models\Option('a', 1));
13
+ $this->assertEquals("<input type='text' class='image' id='a' name='menu[a]' value='1' />"
14
+ . "<button type='button' class='button image_button' for='a' /><i class='fa fa-upload'></i></button>", $output);
15
+ }
16
+
17
+ }
tests/app/Form/ImportTest.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class ImportTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->form_component = new ResponsiveMenu\Form\Import;
9
+ }
10
+
11
+ public function testRendering() {
12
+ $output = $this->form_component->render();
13
+ $this->assertEquals('<input type="file" name="responsive_menu_import_file" /><input type="submit" class="button submit" name="responsive_menu_import" value="Import Options" />', $output);
14
+ }
15
+
16
+ }
tests/app/Form/MenuOrderingTest.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class MenuOrderingTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->form_component = new ResponsiveMenu\Form\MenuOrdering;
9
+ }
10
+
11
+ public function testRendering() {
12
+ $output = $this->form_component->render(new ResponsiveMenu\Models\Option('a', '{"search": "on", "title": "off"}'));
13
+ $this->assertContains('menu-order-option-switch menu-order-option-switch-on', $output);
14
+ $this->assertContains('value="off" name="menu[a][title]"', $output);
15
+ $this->assertContains('value="on" name="menu[a][search]"', $output);
16
+ }
17
+ }
tests/app/Form/ResetTest.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class ResetTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->form_component = new ResponsiveMenu\Form\Reset;
9
+ }
10
+
11
+ public function testRendering() {
12
+ $output = $this->form_component->render();
13
+ $this->assertEquals('<input type="submit" class="button submit" name="responsive_menu_reset" value="Reset Options" />', $output);
14
+ }
15
+
16
+ }
tests/app/Form/SelectTest.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class SelectTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->form_component = new ResponsiveMenu\Form\Select;
9
+ }
10
+
11
+ public function testRendering() {
12
+ $options = [['value' => 1, 'display' => 'a'],['value' => 2, 'display' => 'b']];
13
+ $output = $this->form_component->render(new ResponsiveMenu\Models\Option('a', 4), $options);
14
+
15
+ $expected = "<div class='select-style'><select class='select' name='menu[a]' id='a'>";
16
+ $expected .= "<option value='1'>a</option>";
17
+ $expected .= "<option value='2'>b</option>";
18
+ $expected .= "</select></div>";
19
+
20
+ $this->assertEquals($expected, $output);
21
+ }
22
+
23
+ public function testRenderingWithSelected() {
24
+ $options = [['value' => 1, 'display' => 'a'],['value' => 2, 'display' => 'b']];
25
+ $output = $this->form_component->render(new ResponsiveMenu\Models\Option('a', 2), $options);
26
+
27
+ $expected = "<div class='select-style'><select class='select' name='menu[a]' id='a'>";
28
+ $expected .= "<option value='1'>a</option>";
29
+ $expected .= "<option value='2' selected='selected'>b</option>";
30
+ $expected .= "</select></div>";
31
+
32
+ $this->assertEquals($expected, $output);
33
+ }
34
+
35
+ public function testRenderingWithDisabled() {
36
+ $options = [['value' => 1, 'display' => 'a', 'disabled' => true],['value' => 2, 'display' => 'b']];
37
+ $output = $this->form_component->render(new ResponsiveMenu\Models\Option('a', 2), $options);
38
+
39
+ $expected = "<div class='select-style'><select class='select' name='menu[a]' id='a'>";
40
+ $expected .= "<option value='1' disabled='disabled'>a [PRO]</option>";
41
+ $expected .= "<option value='2' selected='selected'>b</option>";
42
+ $expected .= "</select></div>";
43
+
44
+ $this->assertEquals($expected, $output);
45
+ }
46
+
47
+ }
tests/app/Form/TextAreaTest.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class TextAreaTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->form_component = new ResponsiveMenu\Form\TextArea;
9
+ }
10
+
11
+ public function testRendering() {
12
+ $output = $this->form_component->render(new ResponsiveMenu\Models\Option('a', 1));
13
+ $this->assertEquals("<textarea class='textarea' id='a' name='menu[a]'>1</textarea>", $output);
14
+ }
15
+
16
+ }
tests/app/Form/TextTest.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class TextTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->form_component = new ResponsiveMenu\Form\Text;
9
+ }
10
+
11
+ public function testRendering() {
12
+ $output = $this->form_component->render(new ResponsiveMenu\Models\Option('a', 1));
13
+ $this->assertEquals("<input type='text' class='text' id='a' name='menu[a]' value='1' />", $output);
14
+ }
15
+
16
+ }
tests/app/Formatters/MinifyTest.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class MinifyTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->minify = new ResponsiveMenu\Formatters\Minify;
9
+ }
10
+
11
+ public function testSimpleCSSWhitespaceRemovalTest() {
12
+ $this->assertEquals('.class{}', $this->minify->minify('.class { }'));
13
+ }
14
+
15
+ public function testSimpleCSSCommentRemovalTest() {
16
+ $this->assertEquals('.class{}', $this->minify->minify('.class{} /*comment */'));
17
+ }
18
+
19
+ public function testSimpleCSSTabRemovalTest() {
20
+ $this->assertEquals('.class{}', $this->minify->minify('.class{ }'));
21
+ }
22
+
23
+ public function testSimpleCSSWhitespaceAfterRemovalTest() {
24
+ $this->assertEquals('.class{}', $this->minify->minify('.class{} '));
25
+ }
26
+
27
+ }
tests/app/Mappers/JsMapperTest.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class JsMapperTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->collection = new ResponsiveMenu\Collections\OptionsCollection;
9
+ $this->collection->add(new ResponsiveMenu\Models\Option('animation_speed', 5));
10
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_click_trigger', 'a'));
11
+ $this->collection->add(new ResponsiveMenu\Models\Option('active_arrow_image', 'a'));
12
+ $this->collection->add(new ResponsiveMenu\Models\Option('active_arrow_image_alt', 'n'));
13
+ $this->collection->add(new ResponsiveMenu\Models\Option('inactive_arrow_image', 'b'));
14
+ $this->collection->add(new ResponsiveMenu\Models\Option('inactive_arrow_image_alt', 'm'));
15
+ $this->collection->add(new ResponsiveMenu\Models\Option('breakpoint', 'c'));
16
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_click_trigger', 'd'));
17
+ $this->collection->add(new ResponsiveMenu\Models\Option('animation_type', 'e'));
18
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_appear_from', 'f'));
19
+ $this->collection->add(new ResponsiveMenu\Models\Option('page_wrapper', 'g'));
20
+ $this->collection->add(new ResponsiveMenu\Models\Option('accordion_animation', 'h'));
21
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_close_on_body_click', 'i'));
22
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_close_on_link_click', 'j'));
23
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_item_click_to_trigger_submenu', 'k'));
24
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_push_with_animation', 'l'));
25
+
26
+ $this->mapper = new ResponsiveMenu\Mappers\JsMapper;
27
+ }
28
+
29
+ public function testOutput() {
30
+ $mapped = $this->mapper->map($this->collection);
31
+ $this->assertContains('animationSpeed: 5000', $mapped);
32
+ $this->assertContains("trigger: 'd'", $mapped);
33
+ $this->assertContains('breakpoint: c', $mapped);
34
+ $this->assertContains("pushButton: 'l'", $mapped);
35
+ $this->assertContains("animationType: 'e'", $mapped);
36
+ $this->assertContains("animationSide: 'f'", $mapped);
37
+ $this->assertContains("pageWrapper: 'g'", $mapped);
38
+ $this->assertContains("accordion: 'h'", $mapped);
39
+ $this->assertContains("closeOnBodyClick: 'i'", $mapped);
40
+ $this->assertContains("closeOnLinkClick: 'j'", $mapped);
41
+ $this->assertContains("itemTriggerSubMenu: 'k'", $mapped);
42
+ $this->assertContains('alt="m"', $mapped);
43
+ $this->assertContains('alt="n"', $mapped);
44
+ }
45
+
46
+ public function testDefaultAnimationSpeed() {
47
+ $collection = new ResponsiveMenu\Collections\OptionsCollection;
48
+ $collection->add(new ResponsiveMenu\Models\Option('active_arrow_image', 'a'));
49
+ $collection->add(new ResponsiveMenu\Models\Option('active_arrow_image_alt', 'c'));
50
+ $collection->add(new ResponsiveMenu\Models\Option('inactive_arrow_image', 'b'));
51
+ $collection->add(new ResponsiveMenu\Models\Option('inactive_arrow_image_alt', 'd'));
52
+ $mapper = new ResponsiveMenu\Mappers\JsMapper;
53
+ $mapped = $this->mapper->map($collection);
54
+ $this->assertContains('animationSpeed: 500', $mapped);
55
+ $this->assertContains('alt="c"', $mapped);
56
+ $this->assertContains('alt="d"', $mapped);
57
+ }
58
+
59
+ }
tests/app/Mappers/ScssBaseMapperTest.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class ScssBaseMapperTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->collection = new ResponsiveMenu\Collections\OptionsCollection;
9
+ $this->scss = new scssc_free;
10
+ $this->mapper = new ResponsiveMenu\Mappers\ScssBaseMapper($this->scss);
11
+ }
12
+
13
+ public function testThis() {
14
+ $this->collection->add(new ResponsiveMenu\Models\Option('breakpoint', 6000));
15
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_text_alignment', 'right'));
16
+ $mapped = $this->mapper->map($this->collection);
17
+ $mapped = $this->mapper->map($this->collection);
18
+ $this->assertContains('max-width: 6000px)', $mapped);
19
+ $this->assertContains('padding-right: 10%', $mapped);
20
+ $this->assertContains('padding-right: 15%', $mapped);
21
+ }
22
+
23
+ public function testThat() {
24
+ $this->collection->add(new ResponsiveMenu\Models\Option('breakpoint', 3000));
25
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_text_alignment', 'left'));
26
+ $mapped = $this->mapper->map($this->collection);
27
+ $this->assertContains('max-width: 3000px)', $mapped);
28
+ $this->assertContains('padding-left: 10%', $mapped);
29
+ $this->assertContains('padding-left: 15%', $mapped);
30
+ }
31
+
32
+ }
tests/app/Mappers/ScssButtonMapperTest.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class ScssButtonMapperTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->collection = new ResponsiveMenu\Collections\OptionsCollection;
9
+ $this->collection->add(new ResponsiveMenu\Models\Option('breakpoint', 444));
10
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_line_height', 555));
11
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_line_margin', 50));
12
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_line_colour', '#fff'));
13
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_line_width', 50));
14
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_width', 777));
15
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_height', 888));
16
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_click_animation', 50));
17
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_transparent_background', 'on'));
18
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_background_colour', '#fff'));
19
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_background_colour_hover', '#fff'));
20
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_position_type', 'left'));
21
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_top', 50));
22
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_left_or_right', 'left'));
23
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_distance_from_side', 5));
24
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_line_colour', '#fff'));
25
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_text_colour', '#fff'));
26
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_font_size', 5));
27
+ $this->collection->add(new ResponsiveMenu\Models\Option('button_title_line_height', 5));
28
+ $this->collection->add(new ResponsiveMenu\Models\Option('animation_speed', 5));
29
+ $this->collection->add(new ResponsiveMenu\Models\Option('transition_speed', 5));
30
+ $this->scss = new scssc_free;
31
+ $this->mapper = new ResponsiveMenu\Mappers\ScssButtonMapper($this->scss);
32
+ }
33
+
34
+ public function testOutput() {
35
+ $mapped = $this->mapper->map($this->collection);
36
+ $this->assertContains('height: 555px;', $mapped);
37
+ $this->assertContains('height: 888px;', $mapped);
38
+ $this->assertContains('width: 777px;', $mapped);
39
+ $this->assertContains('max-width: 444px', $mapped);
40
+ }
41
+
42
+ }
tests/app/Mappers/ScssMenuMapperTest.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class ScssMenuMapperTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->collection = new ResponsiveMenu\Collections\OptionsCollection;
9
+ $this->collection->add(new ResponsiveMenu\Models\Option('breakpoint', 111));
10
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_close_on_body_click', 'on'));
11
+ $this->collection->add(new ResponsiveMenu\Models\Option('page_wrapper', '#wrapper'));
12
+ $this->collection->add(new ResponsiveMenu\Models\Option('animation_speed', 222));
13
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_width', 333));
14
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_appear_from', 'left'));
15
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_background_colour', '#ffffff'));
16
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_text_alignment', 'right'));
17
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_additional_content_colour', '#ffffff'));
18
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_search_box_background_colour', '#ffffff'));
19
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_search_box_border_colour', '#ffffff'));
20
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_search_box_text_colour', '#ffffff'));
21
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_search_box_placholder_colour', '#ffffff'));
22
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_maximum_width', 444));
23
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_minimum_width', 555));
24
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_font', 'Arial'));
25
+ $this->collection->add(new ResponsiveMenu\Models\Option('transition_speed', 777));
26
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_title_background_colour', '#ffffff'));
27
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_title_colour', '#ffffff'));
28
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_title_font_size', 888));
29
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_title_hover_colour', '#ffffff'));
30
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_title_background_hover_colour', '#ffffff'));
31
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_font_size', 999));
32
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_links_height', 1000));
33
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_item_border_colour', '#ffffff'));
34
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_link_colour', '#ffffff'));
35
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_item_background_colour', '#ffffff'));
36
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_link_hover_colour', '#ffffff'));
37
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_item_background_hover_colour', '#ffffff'));
38
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_item_border_colour_hover', '#ffffff'));
39
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_sub_arrow_shape_hover_colour', '#ffffff'));
40
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_sub_arrow_border_hover_colour', '#ffffff'));
41
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_sub_arrow_background_hover_colour', '#ffffff'));
42
+ $this->collection->add(new ResponsiveMenu\Models\Option('arrow_position', 'left'));
43
+ $this->collection->add(new ResponsiveMenu\Models\Option('submenu_arrow_height', 2000));
44
+ $this->collection->add(new ResponsiveMenu\Models\Option('submenu_arrow_width', 3000));
45
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_sub_arrow_shape_colour', '#ffffff'));
46
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_sub_arrow_border_colour', '#ffffff'));
47
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_sub_arrow_background_colour', '#ffffff'));
48
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_current_item_background_colour', '#ffffff'));
49
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_current_link_colour', '#ffffff'));
50
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_current_item_border_colour', '#ffffff'));
51
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_current_item_background_hover_colour', '#ffffff'));
52
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_current_link_hover_colour', '#ffffff'));
53
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_current_item_border_hover_colour', '#ffffff'));
54
+ $this->collection->add(new ResponsiveMenu\Models\Option('menu_to_hide', '#tohide'));
55
+ $this->scss = new scssc_free;
56
+ $this->mapper = new ResponsiveMenu\Mappers\ScssMenuMapper($this->scss);
57
+ }
58
+
59
+ public function testThis() {
60
+ $mapped = $this->mapper->map($this->collection);
61
+ $this->assertContains('width: 333%;', $mapped);
62
+ $this->assertContains('max-width: 444px;', $mapped);
63
+ $this->assertContains('min-width: 555px;', $mapped);
64
+
65
+ }
66
+
67
+ }
tests/app/Models/OptionTest.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class OptionTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->option = new ResponsiveMenu\Models\Option('a', 'b');
9
+ }
10
+
11
+ public function testGetName() {
12
+ $this->assertEquals('a', $this->option->getName());
13
+ }
14
+
15
+ public function testGetValue() {
16
+ $this->assertEquals('b', $this->option->getValue());
17
+ }
18
+
19
+ public function testSetValue() {
20
+ $this->option->setValue('c');
21
+ $this->assertEquals('c', $this->option->getValue());
22
+ }
23
+
24
+ public function testToString() {
25
+ $this->assertEquals('b', $this->option);
26
+ }
27
+
28
+ public function testAddFilter() {
29
+ $filter = $this->createMock('ResponsiveMenu\Filters\TextFilter');
30
+ $filter->method('filter')->willReturn('d');
31
+ $this->option->setFilter($filter);
32
+ $this->assertEquals('b', $this->option->getValue());
33
+ $this->assertEquals('d', $this->option->getFiltered());
34
+ }
35
+
36
+ public function testAddAndGetFilter() {
37
+ $filter = $this->createMock('ResponsiveMenu\Filters\TextFilter');
38
+ $filter->method('filter')->willReturn('d');
39
+ $this->option->setFilter($filter);
40
+ $this->assertInstanceOf('ResponsiveMenu\Filters\TextFilter', $this->option->getFilter());
41
+ }
42
+
43
+ public function testFilteredJsonAsString() {
44
+ $option = new ResponsiveMenu\Models\Option('a', '{"a":"1","b":"2"}');
45
+ $filter = new ResponsiveMenu\Filters\JsonFilter;
46
+ $option->setFilter($filter);
47
+ $this->assertEquals('{"a":"1","b":"2"}', $option->getFiltered());
48
+ }
49
+
50
+ public function testFilteredJsonAsArray() {
51
+ $option = new ResponsiveMenu\Models\Option('a', ['a' => 1,'b' => 2]);
52
+ $filter = new ResponsiveMenu\Filters\JsonFilter;
53
+ $option->setFilter($filter);
54
+ $this->assertEquals('{"a":1,"b":2}', $option->getFiltered());
55
+ }
56
+
57
+ }
tests/app/Repositories/OptionRepositoryTest.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class OptionRepositoryTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->db = $this->createMock('ResponsiveMenu\Database\WpDatabase');
9
+ $this->factory = $this->createMock('ResponsiveMenu\Factories\OptionFactory');
10
+ $this->defaults = ['a' => 1, 'b' => 2, 'c' => 3];
11
+
12
+ $this->repo = new ResponsiveMenu\Repositories\OptionRepository($this->db, $this->factory, $this->defaults);
13
+ }
14
+
15
+ public function testCollectionReturned() {
16
+ $obj_1 = new \StdClass;
17
+ $obj_1->name = 'a';
18
+ $obj_1->value = 1;
19
+
20
+ $obj_2 = new \StdClass;
21
+ $obj_2->name = 'b';
22
+ $obj_2->value = 2;
23
+
24
+ $this->db->method('all')->willReturn([$obj_1, $obj_2]);
25
+
26
+ $this->factory->method('build')->will($this->onConsecutiveCalls(
27
+ new ResponsiveMenu\Models\Option('a', 1),
28
+ new ResponsiveMenu\Models\Option('b', 2)
29
+ ));
30
+
31
+ $this->assertInstanceOf('ResponsiveMenu\Collections\OptionsCollection', $this->repo->all());
32
+ }
33
+
34
+ public function testCollectionCountIsReturned() {
35
+ $obj_1 = new \StdClass;
36
+ $obj_1->name = 'a';
37
+ $obj_1->value = 1;
38
+
39
+ $obj_2 = new \StdClass;
40
+ $obj_2->name = 'b';
41
+ $obj_2->value = 2;
42
+
43
+ $this->db->method('all')->willReturn([$obj_1, $obj_2]);
44
+
45
+ $this->factory->method('build')->will($this->onConsecutiveCalls(
46
+ new ResponsiveMenu\Models\Option('a', 1),
47
+ new ResponsiveMenu\Models\Option('b', 2)
48
+ ));
49
+
50
+ $this->assertEquals(2, count($this->repo->all()->all()));
51
+ }
52
+
53
+ public function testDbUpdateIsCalled() {
54
+ $option = $this->createMock('ResponsiveMenu\Models\Option');
55
+ $option->method('getFiltered')->willReturn(1);
56
+ $option->method('getName')->willReturn('a');
57
+ $this->db->method('update')->willReturn(true);
58
+ $this->assertTrue($this->repo->update($option));
59
+ }
60
+
61
+ public function testDbCreateIsCalled() {
62
+ $option = $this->createMock('ResponsiveMenu\Models\Option');
63
+ $option->method('getFiltered')->willReturn(1);
64
+ $option->method('getName')->willReturn('a');
65
+ $this->db->method('insert')->willReturn(true);
66
+ $this->db->method('mySqlTime')->willReturn('123');
67
+ $this->assertTrue($this->repo->create($option));
68
+ }
69
+
70
+ public function testDbRemoveIsCalled() {
71
+ $this->db->method('delete')->willReturn(true);
72
+ $this->assertTrue($this->repo->remove('a'));
73
+ }
74
+
75
+ public function testBuildFromArray() {
76
+ $opt_1 = new ResponsiveMenu\Models\Option('a', 4);
77
+ $opt_1->setFilter($this->createMock('ResponsiveMenu\Filters\TextFilter'));
78
+
79
+ $opt_2 = new ResponsiveMenu\Models\Option('d', 6);
80
+ $opt_2->setFilter($this->createMock('ResponsiveMenu\Filters\TextFilter'));
81
+
82
+ $this->factory->method('build')->will($this->onConsecutiveCalls($opt_1, $opt_2, $opt_1, $opt_2));
83
+
84
+ $this->assertInstanceOf('ResponsiveMenu\Collections\OptionsCollection', $this->repo->buildFromArray(['a' => 4, 'd' => 6]));
85
+ }
86
+
87
+ }
tests/app/Routing/ContainerTest.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+ use ResponsiveMenu\Routing\Container;
5
+
6
+ class ContainerTest extends TestCase {
7
+
8
+ public function testCreatedObjectIsReturn() {
9
+ $container = new Container;
10
+ $container['std'] = function($c) {
11
+ return new \StdClass;
12
+ };
13
+ $this->assertInstanceOf('StdClass', $container['std']);
14
+ }
15
+
16
+ public function testCreatedObjectIsReturnedWithDependencies() {
17
+ $container = new Container;
18
+ $container['std'] = function($c) {
19
+ return new \StdClass;
20
+ };
21
+ $container['std_two'] = function($c) {
22
+ return new \StdClass($c['std']);
23
+ };
24
+ $this->assertInstanceOf('StdClass', $container['std']);
25
+ $this->assertInstanceOf('StdClass', $container['std_two']);
26
+ }
27
+
28
+ public function testVariableIsReturned() {
29
+ $container = new Container;
30
+ $container['var'] = 5;
31
+ $this->assertEquals(5, $container['var']);
32
+ }
33
+
34
+ public function testVariableIsset() {
35
+ $container = new Container;
36
+ $container['var'] = 5;
37
+ $this->assertTrue(isset($container['var']));
38
+ $this->assertFalse(isset($container['not_set']));
39
+ }
40
+
41
+ public function testVariableKeys() {
42
+ $container = new Container;
43
+ $container['var'] = 5;
44
+ $container['var_two'] = 6;
45
+ $this->assertEquals(['var', 'var_two'], $container->keys());
46
+ }
47
+
48
+ /**
49
+ * @expectedException \InvalidArgumentException
50
+ */
51
+ public function testExceptionThrownIfDoesntExist() {
52
+ $container = new Container;
53
+ $container['doesnt_exist'];
54
+ }
55
+
56
+ /**
57
+ * @expectedException \InvalidArgumentException
58
+ */
59
+ public function testExceptionThrownIfDoesntExistAfterUnsetting() {
60
+ $container = new Container;
61
+ $container['to_delete'] = 5;
62
+ unset($container['to_delete']);
63
+ $container['to_delete'];
64
+ }
65
+
66
+ }
tests/app/Services/OptionsServiceTest.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+ use ResponsiveMenu\Services\OptionService;
5
+
6
+ class OptionsServiceTest extends TestCase {
7
+
8
+ public function setUp() {
9
+ $this->repository = $this->createMock('ResponsiveMenu\Repositories\OptionRepository');
10
+ $this->factory = $this->createMock('ResponsiveMenu\Factories\OptionFactory');
11
+ $this->translator = $this->createMock('ResponsiveMenu\Translation\Translator');
12
+ $this->scripts_builder = $this->createMock('ResponsiveMenu\Filesystem\ScriptsBuilder');
13
+
14
+ $this->service = new OptionService($this->repository, $this->factory, $this->translator, $this->scripts_builder);
15
+ }
16
+
17
+ public function testCombiningBasicOptions() {
18
+ $this->assertSame(['one' => 1, 'two' => 'two'], $this->service->combineOptions(['one' => 1],['two' => 'two']));
19
+ }
20
+
21
+ public function testCombiningStringZeroOptions() {
22
+ $this->assertSame(['one' => '0'], $this->service->combineOptions(['one' => 'default'],['one' => '0']));
23
+ }
24
+
25
+ public function testCombiningIntegerZeroOptions() {
26
+ $this->assertSame(['one' => 0], $this->service->combineOptions(['one' => 'default'],['one' => 0]));
27
+ }
28
+
29
+ public function testOverwritingDefaultOptionValue() {
30
+ $this->assertSame(['one' => 'updated'], $this->service->combineOptions(['one' => 'default'],['one' => 'updated']));
31
+ }
32
+
33
+ public function testRepositoryReturn() {
34
+ $this->repository->method('all')->willReturn('a');
35
+ $this->assertEquals('a', $this->service->all());
36
+ }
37
+
38
+ public function testBuildPostArray() {
39
+ $this->repository->method('buildFromArray')->willReturn('a');
40
+ $this->assertEquals('a', $this->service->buildFromPostArray([]));
41
+ }
42
+
43
+ public function testUpdateOptions() {
44
+ $this->repository->method('all')->willReturn(new ResponsiveMenu\Collections\OptionsCollection);
45
+ $this->repository->method('update')->willReturn('a');
46
+ $this->factory->method('build')->willReturn(new ResponsiveMenu\Models\Option('a', 1));
47
+ $this->assertInstanceOf('ResponsiveMenu\Collections\OptionsCollection', $this->service->updateOptions(['a' => 1]));
48
+ }
49
+
50
+ public function testCreateOptions() {
51
+ $collection = new ResponsiveMenu\Collections\OptionsCollection;
52
+ $collection->add(new ResponsiveMenu\Models\Option('external_files', 'on'));
53
+ $this->repository->method('all')->willReturn($collection);
54
+ $this->repository->method('create')->willReturn('a');
55
+ $this->factory->method('build')->willReturn(new ResponsiveMenu\Models\Option('a', 1));
56
+ $this->assertInstanceOf('ResponsiveMenu\Collections\OptionsCollection', $this->service->createOptions(['a' => 1]));
57
+ }
58
+
59
+ }
tests/app/Translation/TranslatorTest.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace ResponsiveMenu\Translation;
4
+
5
+ use PHPUnit\Framework\TestCase;
6
+ use ResponsiveMenu\Collections\OptionsCollection;
7
+ use ResponsiveMenu\Models\Option;
8
+
9
+ class TranslatorTest extends TestCase {
10
+
11
+ public static function setUpBeforeClass() {
12
+ function apply_filters($a, $b, $c, $d) {
13
+ return $b;
14
+ }
15
+ function get_home_url() {
16
+ return 'home';
17
+ }
18
+ function do_action($a, $b, $c, $d) {
19
+ return $d;
20
+ }
21
+ function pll__($a) {
22
+ return $a;
23
+ }
24
+ function do_shortcode($a) {
25
+ return $a;
26
+ }
27
+ }
28
+ public function setUp() {
29
+ $this->translator = new Translator;
30
+ }
31
+
32
+ public function testSearchUrl() {
33
+ $this->assertEquals('home', $this->translator->searchUrl());
34
+ }
35
+
36
+ public function testSaveTranslations() {
37
+ $collection = new OptionsCollection;
38
+ $collection->add(new Option('menu_additional_content', 'a'));
39
+ $this->assertNull($this->translator->saveTranslations($collection));
40
+ }
41
+
42
+ public function testTranslate() {
43
+ $this->assertEquals('a', $this->translator->translate(new Option('menu_additional_content', 'a')));
44
+ }
45
+
46
+ public function testAllowShortcode() {
47
+ $this->assertEquals('a', $this->translator->allowShortcode('a'));
48
+ }
49
+
50
+ }
tests/app/View/AdminViewTest.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace ResponsiveMenu\View;
4
+ use PHPUnit\Framework\Testcase;
5
+
6
+ class AdminViewTest extends TestCase {
7
+
8
+ public function setUp() {
9
+ function is_admin() {
10
+ return false;
11
+ }
12
+ }
13
+
14
+ public function testSetup() {
15
+ $admin_view = new AdminView;
16
+ $this->assertInstanceOf('ResponsiveMenu\View\AdminView', $admin_view);
17
+ }
18
+
19
+ }
tests/app/View/FrontViewTest.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace ResponsiveMenu\View;
4
+ use PHPUnit\Framework\Testcase;
5
+
6
+ class FrontViewTest extends TestCase {
7
+
8
+ public function setUp() {
9
+ $this->js_factory = $this->createMock('ResponsiveMenu\Factories\JsFactory');
10
+ $this->css_factory = $this->createMock('ResponsiveMenu\Factories\CssFactory');
11
+ }
12
+
13
+ public function testSetup() {
14
+ $front_view = new FrontView($this->js_factory, $this->css_factory);
15
+ $this->assertInstanceOf('ResponsiveMenu\View\FrontView', $front_view);
16
+ }
17
+
18
+ }
tests/app/ViewModels/ButtonTest.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class ButtonTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->collection = $this->createMock('ResponsiveMenu\Collections\OptionsCollection');
9
+ $this->component = $this->createMock('ResponsiveMenu\ViewModels\Components\Button\Button');
10
+ $this->component->method('render')->willReturn('a');
11
+ $this->button = new ResponsiveMenu\ViewModels\Button($this->component);
12
+ }
13
+
14
+ public function testOutput() {
15
+ $this->assertEquals('a', $this->button->getHtml($this->collection));
16
+ }
17
+
18
+ }
tests/app/ViewModels/Components/Admin/BoxesTest.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace ResponsiveMenu\ViewModels\Components\Admin;
4
+
5
+ use PHPUnit\Framework\TestCase;
6
+ use ResponsiveMenu\Models\Option;
7
+ use ResponsiveMenu\Collections\OptionsCollection;
8
+
9
+ class BoxesTest extends TestCase {
10
+
11
+ public function setUp() {
12
+ $this->collection = new OptionsCollection;
13
+ $this->collection->add(new Option('a_three', 'a value'));
14
+ $this->collection->add(new Option('b_three', 'b value'));
15
+
16
+ $this->component = new Boxes(
17
+ [
18
+ 'a one' => [
19
+ 'a two' => [
20
+ [
21
+ 'type' => 'text',
22
+ 'option' => 'a_three',
23
+ 'title' => 'a three title',
24
+ 'label' => 'a three label',
25
+ ]
26
+ ]
27
+ ],
28
+ 'b one' => [
29
+ 'b two' => [
30
+ [
31
+ 'type' => 'colour',
32
+ 'option' => 'b_three',
33
+ 'title' => 'b three title',
34
+ 'label' => 'b three label',
35
+ ]
36
+ ]
37
+ ]
38
+ ], $this->collection);
39
+ }
40
+
41
+ public function testRender() {
42
+
43
+ $rendered = $this->component->render();
44
+ $this->assertContains('tab_container_a_one"', $rendered);
45
+ $this->assertContains('id="b_three_container"', $rendered);
46
+ $this->assertContains('<div class="label">a three title</div>', $rendered);
47
+ $this->assertContains('<div class="label">b three title</div>', $rendered);
48
+ }
49
+
50
+ }
tests/app/ViewModels/Components/Admin/TabsTest.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace ResponsiveMenu\ViewModels\Components\Admin;
4
+
5
+ use PHPUnit\Framework\TestCase;
6
+ use ResponsiveMenu\Models\Option;
7
+ use ResponsiveMenu\Collections\OptionsCollection;
8
+
9
+ class TabsTest extends TestCase {
10
+
11
+ public function setUp() {
12
+ $this->component = new Tabs(['a one' => '1', 'b two' => '2']);
13
+ }
14
+
15
+ public function testRender() {
16
+
17
+ $rendered = $this->component->render();
18
+ $this->assertContains('id="tab_a_one"', $rendered);
19
+ $this->assertContains('id="tab_b_two"', $rendered);
20
+ $this->assertContains('>a one<', $rendered);
21
+ $this->assertContains('>b two<', $rendered);
22
+ $this->assertContains('active_tab', $rendered);
23
+ }
24
+
25
+ }
tests/app/ViewModels/Components/Button/ButtonTest.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace ResponsiveMenu\ViewModels\Components\Button;
4
+
5
+ use PHPUnit\Framework\TestCase;
6
+ use ResponsiveMenu\Models\Option;
7
+ use ResponsiveMenu\Collections\OptionsCollection;
8
+
9
+ class ButtonTest extends TestCase {
10
+
11
+ public function setUp() {
12
+ $this->translator = $this->createMock('ResponsiveMenu\Translation\Translator');
13
+ $this->component = new Button($this->translator);
14
+ }
15
+
16
+ public function testRender() {
17
+ $collection = new OptionsCollection;
18
+ $collection->add(new Option('button_title', 'b'));
19
+ $collection->add(new Option('button_title_position', 'left'));
20
+ $collection->add(new Option('button_click_animation', 'd'));
21
+ $collection->add(new Option('button_image', 'e'));
22
+ $collection->add(new Option('button_image_alt', 'g'));
23
+ $collection->add(new Option('button_image_when_clicked', 'f'));
24
+ $collection->add(new Option('button_image_alt_when_clicked', 'h'));
25
+
26
+ $this->translator->method('translate')->willReturn('a');
27
+
28
+ $rendered = $this->component->render($collection);
29
+ $this->assertContains('responsive-menu-label-left', $rendered);
30
+ $this->assertContains('responsive-menu-accessible', $rendered);
31
+ $this->assertContains('responsive-menu-d', $rendered);
32
+ $this->assertContains('alt="g"', $rendered);
33
+ $this->assertContains('alt="h"', $rendered);
34
+ }
35
+
36
+ }
tests/app/ViewModels/Components/ComponentFactoryTest.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class ComponentFactoryTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->factory = new ResponsiveMenu\ViewModels\Components\ComponentFactory;
9
+ }
10
+
11
+ public function testMapTitle() {
12
+ $this->assertInstanceOf('ResponsiveMenu\ViewModels\Components\Menu\Title', $this->factory->build('title'));
13
+ }
14
+
15
+ public function testMapMenu() {
16
+ $this->assertInstanceOf('ResponsiveMenu\ViewModels\Components\Menu\Menu', $this->factory->build('menu'));
17
+ }
18
+
19
+ public function testMapSearch() {
20
+ $this->assertInstanceOf('ResponsiveMenu\ViewModels\Components\Menu\Search', $this->factory->build('search'));
21
+ }
22
+
23
+ public function testMapAdditionalContent() {
24
+ $this->assertInstanceOf('ResponsiveMenu\ViewModels\Components\Menu\AdditionalContent', $this->factory->build('additional content'));
25
+ }
26
+
27
+ }
tests/app/ViewModels/Components/Menu/AdditionalContentTest.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class AdditionalContentTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->translator = $this->createMock('ResponsiveMenu\Translation\Translator');
9
+ $this->component = new ResponsiveMenu\ViewModels\Components\Menu\AdditionalContent($this->translator);
10
+ }
11
+
12
+ public function testRender() {
13
+ $collection = new ResponsiveMenu\Collections\OptionsCollection;
14
+ $collection->add(new ResponsiveMenu\Models\Option('menu_additional_content', 'b'));
15
+ $this->translator->method('translate')->willReturn('b');
16
+ $this->translator->method('allowShortcode')->willReturn('b');
17
+ $this->assertEquals('<div id="responsive-menu-additional-content">b</div>', $this->component->render($collection));
18
+ }
19
+
20
+ public function testRenderEmpty() {
21
+ $collection = new ResponsiveMenu\Collections\OptionsCollection;
22
+ $collection->add(new ResponsiveMenu\Models\Option('menu_additional_content', ''));
23
+ $this->translator->method('translate')->willReturn('');
24
+ $this->translator->method('allowShortcode')->willReturn('');
25
+ $this->assertNull($this->component->render($collection));
26
+ }
27
+
28
+ }
tests/app/ViewModels/Components/Menu/MenuTest.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace ResponsiveMenu\ViewModels\Components\Menu;
4
+ use PHPUnit\Framework\TestCase;
5
+ use ResponsiveMenu\Models\Option;
6
+
7
+ class MenuTest extends TestCase {
8
+
9
+ public function setUp() {
10
+
11
+ function wp_nav_menu($args) {
12
+ return $args;
13
+ }
14
+
15
+ $this->translator = $this->createMock('ResponsiveMenu\Translation\Translator');
16
+ $this->component = new Menu($this->translator);
17
+ }
18
+
19
+ public function testRender() {
20
+ $collection = new \ResponsiveMenu\Collections\OptionsCollection;
21
+ $collection->add(new Option('menu_to_use', 'b'));
22
+ $collection->add(new Option('theme_location_menu', 'b'));
23
+ $collection->add(new Option('menu_depth', 'b'));
24
+ $collection->add(new Option('custom_walker', '\StdClass'));
25
+ $this->translator->method('translate')->willReturn('b');
26
+ $args = $this->component->render($collection);
27
+ $this->assertEquals('', $args['container']);
28
+ $this->assertEquals('responsive-menu', $args['menu_id']);
29
+ $this->assertNull($args['menu_class']);
30
+ $this->assertNull($args['menu']);
31
+ $this->assertEquals('b', $args['depth']);
32
+ $this->assertEquals('b', $args['theme_location']);
33
+ $this->assertFalse($args['echo']);
34
+ }
35
+
36
+ }
tests/app/ViewModels/Components/Menu/SearchTest.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace ResponsiveMenu\ViewModels\Components\Menu;
4
+
5
+ use PHPUnit\Framework\TestCase;
6
+ use ResponsiveMenu\Collections\OptionsCollection;
7
+
8
+ class SearchTest extends TestCase {
9
+
10
+ public function setUp() {
11
+ $this->translator = $this->createMock('ResponsiveMenu\Translation\Translator');
12
+ $this->component = new Search($this->translator);
13
+ }
14
+
15
+ public function testRender() {
16
+ $collection = new OptionsCollection;
17
+ $this->translator->method('searchUrl')->willReturn('a');
18
+ $this->assertContains('action="a" ', $this->component->render($collection));
19
+ }
20
+
21
+ }
tests/app/ViewModels/Components/Menu/TitleTest.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace ResponsiveMenu\ViewModels\Components\Menu;
4
+
5
+ use PHPUnit\Framework\TestCase;
6
+ use ResponsiveMenu\Models\Option;
7
+ use ResponsiveMenu\Collections\OptionsCollection;
8
+
9
+ class TitleTest extends TestCase {
10
+
11
+ public function setUp() {
12
+ $this->translator = $this->createMock('ResponsiveMenu\Translation\Translator');
13
+ $this->component = new Title($this->translator);
14
+ }
15
+
16
+ public function testRender() {
17
+ $collection = new OptionsCollection;
18
+ $collection->add(new Option('menu_title', 'a'));
19
+ $collection->add(new Option('menu_title_link', 'b'));
20
+ $collection->add(new Option('menu_title_link_location', 'c'));
21
+ $collection->add(new Option('menu_title_image', 'd'));
22
+ $collection->add(new Option('menu_title_image_alt', 'e'));
23
+ $this->translator->method('translate')->will($this->onConsecutiveCalls('a', 'b'));
24
+ $rendered = $this->component->render($collection);
25
+ $this->assertContains('target="c"', $rendered);
26
+ $this->assertContains('href="b"', $rendered);
27
+ $this->assertContains('alt="e"', $rendered);
28
+ $this->assertContains('src="d"', $rendered);
29
+ $this->assertContains('>a<', $rendered);
30
+ }
31
+
32
+ }
tests/app/ViewModels/MenuTest.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class MenuTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->collection = new ResponsiveMenu\Collections\OptionsCollection;
9
+ $this->factory = $this->createMock('ResponsiveMenu\ViewModels\Components\ComponentFactory');
10
+ $this->component = $this->createMock('ResponsiveMenu\ViewModels\Components\Menu\Title');
11
+ $this->component->method('render')->willReturn('a');
12
+ $this->factory->method('build')->willReturn($this->component);
13
+
14
+ $this->menu = new ResponsiveMenu\ViewModels\Menu($this->factory);
15
+ }
16
+
17
+ public function testOutput() {
18
+ $this->collection->add(new ResponsiveMenu\Models\Option('items_order', '{"title" : "on", "search" : "off"}'));
19
+ $this->assertEquals('a', $this->menu->getHtml($this->collection));
20
+ }
21
+
22
+ public function testOutputWithTwoOptionsOn() {
23
+ $this->collection->add(new ResponsiveMenu\Models\Option('items_order', '{"title" : "on", "search" : "on"}'));
24
+ $this->assertEquals('aa', $this->menu->getHtml($this->collection));
25
+ }
26
+
27
+ public function testOutputWithOptionsOff() {
28
+ $this->collection->add(new ResponsiveMenu\Models\Option('items_order', '{"title" : "off", "search" : "off"}'));
29
+ $this->assertEquals('', $this->menu->getHtml($this->collection));
30
+ }
31
+
32
+ }
tests/app/Walkers/WpWalkerTest.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PHPUnit\Framework\TestCase;
4
+
5
+ class WpWalkerTest extends TestCase {
6
+
7
+ public function setUp() {
8
+ $this->getMockBuilder('\Walker_Nav_Menu')->getMock();
9
+ $this->collection = new ResponsiveMenu\Collections\OptionsCollection;
10
+ $this->walker = new ResponsiveMenu\Walkers\WpWalker($this->collection);
11
+ }
12
+
13
+ public function testEndEl() {
14
+ $output = 'output';
15
+ $this->walker->end_el($output, null);
16
+ $this->assertEquals('output</li>', $output);
17
+ }
18
+
19
+ public function testEndLvl() {
20
+ $output = 'output';
21
+ $this->walker->end_lvl($output, null);
22
+ $this->assertEquals('output</ul>', $output);
23
+ }
24
+
25
+ public function testStartLvlNoOptions() {
26
+ $output = 'output';
27
+ $this->walker->start_lvl($output, 1);
28
+ $this->assertEquals("output<ul class='responsive-menu-submenu responsive-menu-submenu-depth-2'>", $output);
29
+ }
30
+
31
+ public function testStartLvlWithExpandSubMenusOff() {
32
+ $this->collection['auto_expand_all_submenus'] = 'off';
33
+ $output = 'output';
34
+ $this->walker->start_lvl($output, 1);
35
+ $this->assertEquals("output<ul class='responsive-menu-submenu responsive-menu-submenu-depth-2'>", $output);
36
+ }
37
+
38
+ public function testStartLvlWithExpandSubMenusOn() {
39
+ $this->collection['auto_expand_all_submenus'] = 'on';
40
+ $output = 'output';
41
+ $this->walker->start_lvl($output, 2);
42
+ $this->assertEquals("output<ul class='responsive-menu-submenu responsive-menu-submenu-depth-3 responsive-menu-submenu-open'>", $output);
43
+ }
44
+
45
+ public function testStartLvlWithExpandCurrentSubMenusOff() {
46
+ $current_item = new \StdClass;
47
+ $current_item->current_item_ancestor = true;
48
+ $current_item->current_item_parent = true;
49
+ $this->walker->setCurrentItem($current_item);
50
+
51
+ $this->collection['auto_expand_current_submenus'] = 'off';
52
+ $output = 'output';
53
+ $this->walker->start_lvl($output, 4);
54
+ $this->assertEquals("output<ul class='responsive-menu-submenu responsive-menu-submenu-depth-5'>", $output);
55
+ }
56
+
57
+ public function testStartLvlWithExpandCurrentSubMenusOn() {
58
+ $current_item = new \StdClass;
59
+ $current_item->current_item_ancestor = true;
60
+ $current_item->current_item_parent = true;
61
+ $this->walker->setCurrentItem($current_item);
62
+
63
+ $this->collection['auto_expand_current_submenus'] = 'on';
64
+ $output = 'output';
65
+ $this->walker->start_lvl($output, 3);
66
+ $this->assertEquals("output<ul class='responsive-menu-submenu responsive-menu-submenu-depth-4 responsive-menu-submenu-open'>", $output);
67
+ }
68
+
69
+ public function testStartLvlWithExpandCurrentSubMenusOnCurrentItemFalse() {
70
+ $current_item = new \StdClass;
71
+ $current_item->current_item_ancestor = false;
72
+ $current_item->current_item_parent = false;
73
+ $this->walker->setCurrentItem($current_item);
74
+
75
+ $this->collection['auto_expand_current_submenus'] = 'on';
76
+ $output = 'output';
77
+ $this->walker->start_lvl($output, 3);
78
+ $this->assertEquals("output<ul class='responsive-menu-submenu responsive-menu-submenu-depth-4'>", $output);
79
+ }
80
+
81
+ public function testStartLvlWithExpandCurrentSubMenusOnCurrentItemFalseAndTrue() {
82
+ $current_item = new \StdClass;
83
+ $current_item->current_item_ancestor = false;
84
+ $current_item->current_item_parent = true;
85
+ $this->walker->setCurrentItem($current_item);
86
+
87
+ $this->collection['auto_expand_current_submenus'] = 'on';
88
+ $output = 'output';
89
+ $this->walker->start_lvl($output, 3);
90
+ $this->assertEquals("output<ul class='responsive-menu-submenu responsive-menu-submenu-depth-4 responsive-menu-submenu-open'>", $output);
91
+ }
92
+
93
+ }
tests/scssc/ApiTest.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once dirname(dirname(dirname(__FILE__))) . '/src/app/Mappers/scss.inc.php';
4
+
5
+ class ApiTest extends PHPUnit_Framework_TestCase
6
+ {
7
+ public function setUp()
8
+ {
9
+ $this->scss = new scssc_free();
10
+ }
11
+
12
+ public function testUserFunction()
13
+ {
14
+ $this->scss->registerFunction("add-two", function ($args) {
15
+ list($a, $b) = $args;
16
+ return $a[1] + $b[1];
17
+ });
18
+
19
+ $this->assertEquals(
20
+ "result: 30;",
21
+ $this->compile("result: add-two(10, 20);")
22
+ );
23
+ }
24
+
25
+ public function testImportMissing()
26
+ {
27
+ $this->assertEquals(
28
+ '@import "missing";',
29
+ $this->compile('@import "missing";')
30
+ );
31
+ }
32
+
33
+ public function testImportCustomCallback()
34
+ {
35
+ $this->scss->addImportPath(function ($path) {
36
+ return __DIR__ . '/inputs/' . str_replace('.css', '.scss', $path);
37
+ });
38
+
39
+ $this->assertEquals(
40
+ trim(file_get_contents(__DIR__ . '/outputs/variables.css')),
41
+ $this->compile('@import "variables.css";')
42
+ );
43
+ }
44
+
45
+ /**
46
+ * @dataProvider provideSetVariables
47
+ */
48
+ public function testSetVariables($expected, $scss, $variables)
49
+ {
50
+ $this->scss->setVariables($variables);
51
+
52
+ $this->assertEquals($expected, $this->compile($scss));
53
+ }
54
+
55
+ public function provideSetVariables()
56
+ {
57
+ return array(
58
+ array(
59
+ ".magic {\n color: red;\n width: 760px; }",
60
+ '.magic { color: $color; width: $base - 200; }',
61
+ array(
62
+ 'color' => 'red',
63
+ 'base' => '960px',
64
+ ),
65
+ ),
66
+ array(
67
+ ".logo {\n color: #808080; }",
68
+ '.logo { color: desaturate($primary, 100%); }',
69
+ array(
70
+ 'primary' => '#ff0000',
71
+ ),
72
+ ),
73
+ );
74
+ }
75
+
76
+ public function compile($str)
77
+ {
78
+ return trim($this->scss->compile($str));
79
+ }
80
+ }
tests/scssc/InputTest.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once dirname(dirname(dirname(__FILE__))) . '/src/app/Mappers/scss.inc.php';
4
+
5
+ function _dump($value) {
6
+ fwrite(STDOUT, print_r($value, true));
7
+ }
8
+
9
+ function _quote($str) {
10
+ return preg_quote($str, "/");
11
+ }
12
+
13
+ class InputTest extends PHPUnit_Framework_TestCase {
14
+ protected static $inputDir = "inputs";
15
+ protected static $outputDir = "outputs";
16
+
17
+ public function setUp() {
18
+ $this->scss = new scssc_free();
19
+ $this->scss->addImportPath(__DIR__ . "/" . self::$inputDir);
20
+ }
21
+
22
+ /**
23
+ * @dataProvider fileNameProvider
24
+ */
25
+ public function testInputFile($inFname, $outFname) {
26
+ if (getenv("BUILD")) {
27
+ return $this->buildInput($inFname,$outFname);
28
+ }
29
+
30
+ if (!is_readable($outFname)) {
31
+ $this->fail("$outFname is missing, ".
32
+ "consider building tests with BUILD=true");
33
+ }
34
+
35
+ $input = file_get_contents($inFname);
36
+ $output = file_get_contents($outFname);
37
+
38
+ $this->assertEquals($output, $this->scss->compile($input));
39
+ }
40
+
41
+ public function fileNameProvider() {
42
+ return array_map(function($a) { return array($a, InputTest::outputNameFor($a)); },
43
+ self::findInputNames());
44
+ }
45
+
46
+ // only run when env is set
47
+ public function buildInput($inFname, $outFname) {
48
+ $css = $this->scss->compile(file_get_contents($inFname));
49
+ file_put_contents($outFname, $css);
50
+ }
51
+
52
+ static public function findInputNames($pattern="*") {
53
+ $files = glob(__DIR__ . "/" . self::$inputDir . "/" . $pattern);
54
+ $files = array_filter($files, "is_file");
55
+ if ($pattern = getenv("MATCH")) {
56
+ $files = array_filter($files, function($fname) use ($pattern) {
57
+ return preg_match("/$pattern/", $fname);
58
+ });
59
+ }
60
+
61
+ return $files;
62
+ }
63
+
64
+ static public function outputNameFor($input) {
65
+ $front = _quote(__DIR__ . "/");
66
+ $out = preg_replace("/^$front/", "", $input);
67
+
68
+ $in = _quote(self::$inputDir . "/");
69
+ $out = preg_replace("/$in/", self::$outputDir . "/", $out);
70
+ $out = preg_replace("/.scss$/", ".css", $out);
71
+
72
+ return __DIR__ . "/" . $out;
73
+ }
74
+
75
+ static public function buildTests($pattern) {
76
+ $files = self::findInputNames($pattern);
77
+ foreach ($files as $file) {
78
+ }
79
+ }
80
+ }
tests/scssc/compare-scss.sh ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ diff_tool="$1"
4
+
5
+ for file in $(ls inputs/*.scss); do
6
+ out_file=$(echo $file | sed -e 's/inputs/outputs/' -e 's/\.scss$/\.css/')
7
+ sass=$(scss < $file 2> /dev/null)
8
+ if [ $? = "0" ]; then
9
+ # echo $file
10
+ # echo "$sass"
11
+ # echo
12
+
13
+ if [ "$(cat $out_file)" != "$sass" ]; then
14
+ echo "* [FAIL] $file"
15
+ if [ -n "$diff_tool" ]; then
16
+ $diff_tool $out_file <(echo "$sass") 2> /dev/null
17
+ fi
18
+ else
19
+ echo " [PASS] $file"
20
+ fi
21
+ else
22
+ echo " $file"
23
+ fi
24
+ done
25
+
tests/scssc/inputs/builtins.scss ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #color {
3
+ color: rgb(34,234,24);
4
+
5
+ red: red(rgb(34,234,24));
6
+ green: green(rgb(34,234,24));
7
+ blue: blue(rgb(34,234,24));
8
+
9
+ color: rgba(1,2,4, 0.5);
10
+ a1: alpha(rgb(1,2,4));
11
+ a2: alpha(rgba(1,2,4, 0.5));
12
+
13
+ mix: mix(rgb(1,2,3), rgb(3,4,5));
14
+
15
+ rgba: rgba($color: #a7c, $alpha: 0.4);
16
+ rgba: rgba(#a7c, 0.4);
17
+ }
18
+
19
+ #hsl {
20
+ color: hsl(100, 50, 55);
21
+ color: hsla(100, 50, 55, 0.5);
22
+
23
+ hue: hue(hsl(100, 50, 55));
24
+ sat: saturation(hsl(100, 50, 55));
25
+ lig: lightness(hsl(100, 50, 55));
26
+ }
27
+
28
+ #more-color {
29
+ $color: hsl(-80,44,33);
30
+
31
+ light: lighten($color, 10%);
32
+ dark: darken($color, 10%);
33
+
34
+ sat: saturate($color, 10%);
35
+ desat: desaturate($color, 10%);
36
+
37
+ gray: grayscale($color);
38
+ comp: complement($color);
39
+ inv: invert($color);
40
+ }
41
+
42
+ #more-more-color {
43
+ $color: rgba(1,2,3,0.5);
44
+ op: opacity($color);
45
+
46
+ opacify: opacify($color, 0.1);
47
+ opacify: fade-in($color, 0.1);
48
+
49
+ transparentize: transparentize($color, 0.1);
50
+ transparentize: fade-out($color, 0.1);
51
+ transparentize: transparentize(#348203, 0.1);
52
+ }
53
+
54
+ #more-more-more-color {
55
+ $color: rgba(10,10,10,0);
56
+ color: adjust-color($color, $blue: 69, $red: 55, $green: 100, $alpha: 0.4);
57
+ color: adjust-color($color, $hue: 170, $saturation: 100, $lightness: 50);
58
+
59
+ color: change-color($color, $blue: 69, $red: 55, $green: 100, $alpha: 0.4);
60
+ color: change-color($color, $hue: 170, $saturation: 100, $lightness: 50);
61
+
62
+ color: scale-color($color, $red: 55%);
63
+ color: scale-color($color, $red: -55%);
64
+
65
+ color: scale-color($color, $lightness: 55%);
66
+ color: scale-color($color, $lightness: -55%);
67
+
68
+ color: ie-hex-str($color);
69
+ color: ie-hex-str(#abc);
70
+ }
71
+
72
+ #string {
73
+ color: unquote("hello what is going on");
74
+ // color: quote(yeah you know it); // **
75
+ color: quote(yeah);
76
+ color: quote("I do?");
77
+ }
78
+
79
+ #number {
80
+ color: percentage(100/40);
81
+ color: round(3.4);
82
+ color: floor(3.4);
83
+ color: ceil(3.4);
84
+
85
+ top: floor(10.4px);
86
+ top: ceil(.4ex);
87
+ width: percentage(100px / 50px);
88
+ bottom: abs(-10px);
89
+ padding: min(5em, 3em, 4em) max(2px, 1in) min(1in, 96px) max(1in, 72pt);
90
+ }
91
+
92
+ #list {
93
+ len: length(hello world what);
94
+ len: length(thing);
95
+
96
+ n: nth(hello world what, 1);
97
+ // n: nth(hello world what, 100); // **
98
+
99
+ hello: join(one two three, hello, comma);
100
+ hello: join(one two three, hello world what is going, comma);
101
+ hello: append(one two three, hello, comma);
102
+
103
+ index: index(1px solid red, solid);
104
+ index: index(1px solid red, dashed);
105
+ index: index(1px solid red, #f00);
106
+ index: index(96px solid red, 1in);
107
+ index: index((1in 2) a b, 1in);
108
+ index: index((1in 2) a b, (96px 2));
109
+ index: index((1in 2) a b, (1in, 2));
110
+ index: index((1px solid red), solid);
111
+ index: index(1px 3px + 3px, 4+2px);
112
+ $var: oo;
113
+ index: index(foo bar, f#{$var});
114
+
115
+ $yes: one, two, three;
116
+ $no: great job;
117
+ world: join($yes, $no);
118
+ world: append($yes, $no);
119
+
120
+ cool: join($yes, $no, space);
121
+ cool: join($no, $yes);
122
+
123
+ zip: zip((1px, 2px), (solid dashed));
124
+ zip: zip(1px 2px 3px, solid dashed, red green blue);
125
+ }
126
+
127
+ #introspection {
128
+ t: type-of(100px);
129
+ t: type-of(asdf);
130
+ t: type-of("asdf");
131
+ t: type-of(true);
132
+ t: type-of(#fff);
133
+ t: type-of(blue);
134
+ t: type-of(one two three);
135
+
136
+ u: unit(12);
137
+ u: unit(12px);
138
+ u: unit(12em);
139
+
140
+ l: unitless(23);
141
+ l: unitless(23deg);
142
+
143
+ c: comparable(2px, 1px);
144
+ c: comparable(100px, 3em);
145
+ c: comparable(10cm, 3mm);
146
+ c: comparable(1, 4);
147
+ c: comparable(1ex, 4em);
148
+ c: comparable(2em, 5em);
149
+ }
150
+
151
+ #if {
152
+ color: if(true, yes, no);
153
+ color: if(false, yes, no);
154
+ color: if(false or true, yes, no);
155
+ color: if(10px, yes, no);
156
+ }
157
+
158
+ .transparent {
159
+ r: red(transparent);
160
+ g: green(transparent);
161
+ b: blue(transparent);
162
+ a: alpha(transparent);
163
+ }
164
+
165
+ .alpha {
166
+ a: alpha(black);
167
+ a: alpha(#fff);
168
+ a: alpha(rgb(0, 0, 0));
169
+ a: alpha(rgba(0, 0, 0, 0.5));
170
+ a: alpha(currentColor);
171
+ }
tests/scssc/inputs/comments.scss ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ // what is going on?
3
+
4
+ /** what the heck **/
5
+
6
+ /**
7
+
8
+ Here is a block comment
9
+
10
+ **/
11
+
12
+
13
+ // this is a comment
14
+
15
+ // trailing backslash \
16
+ /*hello*/div /*yeah*/ { //surew
17
+ border: 1px solid red; // world
18
+ /* another property */
19
+ color: url('http://mage-page.com');
20
+ string: "hello /* this is not a comment */";
21
+ world: "// neither is this";
22
+ string: 'hello /* this is not a comment */' /*what if this is a comment */;
23
+ world: '// neither is this' // hell world;
24
+ ;
25
+ what-ever: 100px;
26
+ background: url(/*this is not a comment?*/); // uhh what happens here
27
+ }
28
+
tests/scssc/inputs/compass_extract.scss ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Extracted from compass/typography/vertical_rhythm.scss
2
+
3
+
4
+ // The base font size.
5
+ $base-font-size: 16px !default;
6
+
7
+ // The base line height determines the basic unit of vertical rhythm.
8
+ $base-line-height: 24px !default;
9
+
10
+ // Set the default border style for rhythm borders.
11
+ $default-rhythm-border-style: solid !default;
12
+
13
+ // The default font size in all browsers.
14
+ $browser-default-font-size: 16px;
15
+
16
+ // Set to false if you want to use absolute pixels in sizing your typography.
17
+ $relative-font-sizing: true !default;
18
+
19
+ // Allows the `adjust-font-size-to` mixin and the `lines-for-font-size` function
20
+ // to round the line height to the nearest half line height instead of the
21
+ // nearest integral line height to avoid large spacing between lines.
22
+ $round-to-nearest-half-line: false !default;
23
+
24
+ // Ensure there is at least this many pixels
25
+ // of vertical padding above and below the text.
26
+ $min-line-padding: 2px !default;
27
+
28
+ // $base-font-size but in your output unit of choice.
29
+ // Defaults to 1em when `$relative-font-sizing` is true.
30
+ $font-unit: if($relative-font-sizing, 1em, $base-font-size) !default;
31
+
32
+ // The basic unit of font rhythm.
33
+ $base-rhythm-unit: $base-line-height / $base-font-size * $font-unit;
34
+
35
+ // The leader is the amount of whitespace in a line.
36
+ // It might be useful in your calculations.
37
+ $base-leader: ($base-line-height - $base-font-size) * $font-unit / $base-font-size;
38
+
39
+ // The half-leader is the amount of whitespace above and below a line.
40
+ // It might be useful in your calculations.
41
+ $base-half-leader: $base-leader / 2;
42
+
43
+ // True if a number has a relative unit.
44
+ @function relative-unit($number) {
45
+ @return unit($number) == "%" or unit($number) == "em" or unit($number) == "rem"
46
+ }
47
+
48
+ // True if a number has an absolute unit.
49
+ @function absolute-unit($number) {
50
+ @return not (relative-unit($number) or unitless($number));
51
+ }
52
+
53
+ @if $relative-font-sizing and not relative-unit($font-unit) {
54
+ @warn "$relative-font-sizing is true but $font-unit is set to #{$font-unit} which is not a relative unit.";
55
+ }
56
+
57
+ // Establishes a font baseline for the given font-size.
58
+ @mixin establish-baseline($font-size: $base-font-size) {
59
+ // IE 6 refuses to resize fonts set in pixels and it weirdly resizes fonts
60
+ // whose root is set in ems. So we set the root font size in percentages of
61
+ // the default font size.
62
+ * html {
63
+ font-size: 100% * ($font-size / $browser-default-font-size);
64
+ }
65
+ html {
66
+ font-size: $font-size;
67
+ @include adjust-leading-to(1, if($relative-font-sizing, $font-size, $base-font-size));
68
+ }
69
+ }
70
+
71
+ // Resets the line-height to 1 vertical rhythm unit.
72
+ // Does not work on elements whose font-size is different from $base-font-size.
73
+ //
74
+ // @deprecated This mixin will be removed in the next release.
75
+ // Please use the `adjust-leading-to` mixin instead.
76
+ @mixin reset-baseline {
77
+ @include adjust-leading-to(1, if($relative-font-sizing, $base-font-size, $base-font-size));
78
+ }
79
+
80
+ // Show a background image that can be used to debug your alignments.
81
+ // Include the $img argument if you would rather use your own image than the
82
+ // Compass default gradient image.
83
+ @mixin debug-vertical-alignment($img: false) {
84
+ @if $img {
85
+ background: image-url($img);
86
+ } @else {
87
+ @include baseline-grid-background($base-rhythm-unit);
88
+ }
89
+ }
90
+
91
+ // Adjust a block to have a different font size and line height to maintain the
92
+ // rhythm. $lines specifies how many multiples of the baseline rhythm each line
93
+ // of this font should use up. It does not have to be an integer, but it
94
+ // defaults to the smallest integer that is large enough to fit the font.
95
+ // Use $from-size to adjust from a font-size other than the base font-size.
96
+ @mixin adjust-font-size-to($to-size, $lines: lines-for-font-size($to-size), $from-size: $base-font-size) {
97
+ @if not $relative-font-sizing and $from-size != $base-font-size {
98
+ @warn "$relative-font-sizing is false but a relative font size was passed to adjust-font-size-to";
99
+ }
100
+ font-size: $font-unit * $to-size / $from-size;
101
+ @include adjust-leading-to($lines, if($relative-font-sizing, $to-size, $base-font-size));
102
+ }
103
+
104
+ // Adjust a block to have different line height to maintain the rhythm.
105
+ // $lines specifies how many multiples of the baseline rhythm each line of this
106
+ // font should use up. It does not have to be an integer, but it defaults to the
107
+ // smallest integer that is large enough to fit the font.
108
+ @mixin adjust-leading-to($lines, $font-size: $base-font-size) {
109
+ line-height: rhythm($lines, $font-size);
110
+ }
111
+
112
+ // Calculate rhythm units.
113
+ @function rhythm(
114
+ $lines: 1,
115
+ $font-size: $base-font-size,
116
+ $offset: 0
117
+ ) {
118
+ @if not $relative-font-sizing and $font-size != $base-font-size {
119
+ @warn "$relative-font-sizing is false but a relative font size was passed to the rhythm function";
120
+ }
121
+ $rhythm: $font-unit * ($lines * $base-line-height - $offset) / $font-size;
122
+ // Round the pixels down to nearest integer.
123
+ @if unit($rhythm) == px {
124
+ $rhythm: floor($rhythm);
125
+ }
126
+ @return $rhythm;
127
+ }
128
+
129
+ // Calculate the minimum multiple of rhythm units needed to contain the font-size.
130
+ @function lines-for-font-size($font-size) {
131
+ $lines: if($round-to-nearest-half-line,
132
+ ceil(2 * $font-size / $base-line-height) / 2,
133
+ ceil($font-size / $base-line-height));
134
+ @if $lines * $base-line-height - $font-size < $min-line-padding * 2 {
135
+ $lines: $lines + if($round-to-nearest-half-line, 0.5, 1);
136
+ }
137
+ @return $lines;
138
+ }
139
+
140
+ // Apply leading whitespace. The $property can be margin or padding.
141
+ @mixin leader($lines: 1, $font-size: $base-font-size, $property: margin) {
142
+ #{$property}-top: rhythm($lines, $font-size);
143
+ }
144
+
145
+ // Apply leading whitespace as padding.
146
+ @mixin padding-leader($lines: 1, $font-size: $base-font-size) {
147
+ padding-top: rhythm($lines, $font-size);
148
+ }
149
+
150
+ // Apply leading whitespace as margin.
151
+ @mixin margin-leader($lines: 1, $font-size: $base-font-size) {
152
+ margin-top: rhythm($lines, $font-size);
153
+ }
154
+
155
+ // Apply trailing whitespace. The $property can be margin or padding.
156
+ @mixin trailer($lines: 1, $font-size: $base-font-size, $property: margin) {
157
+ #{$property}-bottom: rhythm($lines, $font-size);
158
+ }
159
+
160
+ // Apply trailing whitespace as padding.
161
+ @mixin padding-trailer($lines: 1, $font-size: $base-font-size) {
162
+ padding-bottom: rhythm($lines, $font-size);
163
+ }
164
+
165
+ // Apply trailing whitespace as margin.
166
+ @mixin margin-trailer($lines: 1, $font-size: $base-font-size) {
167
+ margin-bottom: rhythm($lines, $font-size);
168
+ }
169
+
170
+ // Shorthand mixin to apply whitespace for top and bottom margins and padding.
171
+ @mixin rhythm($leader: 0, $padding-leader: 0, $padding-trailer: 0, $trailer: 0, $font-size: $base-font-size) {
172
+ @include leader($leader, $font-size);
173
+ @include padding-leader($padding-leader, $font-size);
174
+ @include padding-trailer($padding-trailer, $font-size);
175
+ @include trailer($trailer, $font-size);
176
+ }
177
+
178
+ // Apply a border and whitespace to any side without destroying the vertical
179
+ // rhythm. The whitespace must be greater than the width of the border.
180
+ @mixin apply-side-rhythm-border($side, $width: 1px, $lines: 1, $font-size: $base-font-size, $border-style: $default-rhythm-border-style) {
181
+ @if not $relative-font-sizing and $font-size != $base-font-size {
182
+ @warn "$relative-font-sizing is false but a relative font size was passed to apply-side-rhythm-border";
183
+ }
184
+ border-#{$side}: {
185
+ style: $border-style;
186
+ width: $font-unit * $width / $font-size;
187
+ };
188
+ padding-#{$side}: rhythm($lines, $font-size, $offset: $width);
189
+ }
190
+
191
+ // Apply borders and whitespace equally to all sides.
192
+ @mixin rhythm-borders($width: 1px, $lines: 1, $font-size: $base-font-size, $border-style: $default-rhythm-border-style) {
193
+ @if not $relative-font-sizing and $font-size != $base-font-size {
194
+ @warn "$relative-font-sizing is false but a relative font size was passed to rhythm-borders";
195
+ }
196
+ border: {
197
+ style: $border-style;
198
+ width: $font-unit * $width / $font-size;
199
+ };
200
+ padding: rhythm($lines, $font-size, $offset: $width);
201
+ }
202
+
203
+ // Apply a leading border.
204
+ @mixin leading-border($width: 1px, $lines: 1, $font-size: $base-font-size, $border-style: $default-rhythm-border-style) {
205
+ @include apply-side-rhythm-border(top, $width, $lines, $font-size, $border-style);
206
+ }
207
+
208
+ // Apply a trailing border.
209
+ @mixin trailing-border($width: 1px, $lines: 1, $font-size: $base-font-size, $border-style: $default-rhythm-border-style) {
210
+ @include apply-side-rhythm-border(bottom, $width, $lines, $font-size, $border-style);
211
+ }
212
+
213
+ // Apply both leading and trailing borders.
214
+ @mixin horizontal-borders($width: 1px, $lines: 1, $font-size: $base-font-size, $border-style: $default-rhythm-border-style) {
215
+ @include leading-border($width, $lines, $font-size, $border-style);
216
+ @include trailing-border($width, $lines, $font-size, $border-style);
217
+ }
218
+
219
+ // Alias for `horizontal-borders` mixin.
220
+ @mixin h-borders($width: 1px, $lines: 1, $font-size: $base-font-size, $border-style: $default-rhythm-border-style) {
221
+ @include horizontal-borders($width, $lines, $font-size, $border-style);
222
+ }
223
+
224
+ #test-0 {
225
+ unit: relative-unit(10px);
226
+ unit: relative-unit(50%);
227
+ rhythm: rhythm();
228
+ size: lines-for-font-size(15px);
229
+ size: lines-for-font-size(16px);
230
+ size: lines-for-font-size(17px);
231
+ size: lines-for-font-size(27px);
232
+ size: lines-for-font-size(37px);
233
+ }
234
+
235
+
236
+ #test-1 {
237
+ @include rhythm(5, 6, 7);
238
+ }
239
+
240
+ #test-2 {
241
+ @include rhythm-borders;
242
+ }
243
+
244
+ #test-3 {
245
+ @include horizontal-borders;
246
+ }
247
+
248
+
tests/scssc/inputs/content.scss ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ @mixin apply-to-ie6-only {
3
+ * html {
4
+ @content;
5
+ }
6
+ }
7
+ @include apply-to-ie6-only {
8
+ #logo {
9
+ background-image: url(/logo.gif);
10
+ }
11
+ }
12
+
13
+
14
+ $color: white;
15
+ @mixin colors($color: blue) {
16
+ background-color: $color;
17
+ @content;
18
+ border-color: $color;
19
+ }
20
+ .colors {
21
+ @include colors { color: $color; }
22
+ }
23
+
24
+
25
+ @mixin iphone {
26
+ @media only screen and (max-width: 480px) {
27
+ @content;
28
+ }
29
+ }
30
+
31
+ @include iphone {
32
+ body { color: red }
33
+ }
34
+
35
+
36
+ #sidebar {
37
+ $sidebar-width: 300px;
38
+ width: $sidebar-width;
39
+ @include iphone {
40
+ width: $sidebar-width / 3;
41
+ }
42
+ }
43
+
44
+
45
+ @mixin respond-to($width) {
46
+ @media only screen and (min-width: $width) { @content; }
47
+ }
48
+
49
+ @include respond-to(40em) {
50
+ @for $i from 1 through 2 {
51
+ .grid-#{$i} { width: 100%; }
52
+ }
53
+ }
54
+
55
+ @include respond-to(40em) {
56
+ $i: 1;
57
+ @while $i <= 2 {
58
+ .grid-#{$i} { width: 100%; }
59
+ $i: $i + 1;
60
+ }
61
+ }
tests/scssc/inputs/content_with_function.scss ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ $test-var: true;
2
+
3
+ @mixin mixin-using-content() {
4
+ @content;
5
+ }
6
+
7
+ @function test-function($value) {
8
+ @return $value;
9
+ }
10
+
11
+ @include mixin-using-content {
12
+ @if $test-var {
13
+ body {
14
+ padding: test-function(1 px);
15
+ }
16
+ }
17
+ }
tests/scssc/inputs/default_args.scss ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ @mixin cool($color: blue) {
4
+ margin: 100px;
5
+ }
6
+
7
+ @function what($height: red) {
8
+ @return $height;
9
+ }
10
+
11
+ div {
12
+ height: what();
13
+ @include cool;
14
+ }
15
+
tests/scssc/inputs/directives.scss ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ @charset "hello-world";
3
+
4
+ @page :left {
5
+ div {
6
+ color: red;
7
+ }
8
+ }
9
+
10
+ @page test {
11
+ @media yes {
12
+ div {
13
+ color: red;
14
+ }
15
+
16
+ @media no {
17
+ pre {
18
+ color: blue;
19
+ }
20
+ }
21
+ }
22
+ }
23
+
24
+ @media something {
25
+ @page {
26
+ @media else {
27
+ div {
28
+ height: 200px;
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+
35
+ div {
36
+ color: red;
37
+ @page yeah {
38
+ pre {
39
+ height: 20px;
40
+ }
41
+ }
42
+ }
43
+
44
+ @font-face {
45
+ color: red;
46
+ height: 20px;
47
+ }
48
+
49
+
50
+ @keyframes 'bounce' {
51
+ from {
52
+ top: 100px;
53
+ animation-timing-function: ease-out;
54
+ }
55
+
56
+ 25% {
57
+ top: 50px;
58
+ animation-timing-function: ease-in;
59
+ }
60
+
61
+ 50% {
62
+ top: 100px;
63
+ animation-timing-function: ease-out;
64
+ }
65
+
66
+ 75% {
67
+ top: 75px;
68
+ animation-timing-function: ease-in;
69
+ }
70
+
71
+ to {
72
+ top: 100px;
73
+ }
74
+ }
75
+
76
+ @-webkit-keyframes flowouttoleft {
77
+ 0% { -webkit-transform: translateX(0) scale(1); }
78
+ 60%, 70% { -webkit-transform: translateX(0) scale(.7); }
79
+ 100% { -webkit-transform: translateX(-100%) scale(.7); }
80
+ }
81
+
82
+ div {
83
+ animation-name: 'diagonal-slide';
84
+ animation-duration: 5s;
85
+ animation-iteration-count: 10;
86
+ }
87
+
88
+ @keyframes 'diagonal-slide' {
89
+
90
+ from {
91
+ left: 0;
92
+ top: 0;
93
+ }
94
+
95
+ to {
96
+ left: 100px;
97
+ top: 100px;
98
+ }
99
+
100
+ }
101
+
102
+ @document url(http://www.w3.org/),
103
+ url-prefix(http://www.w3.org/Style/),
104
+ domain(mozilla.org),
105
+ regexp("https:.*")
106
+ {
107
+ body { color: purple; background: yellow; }
108
+ }
tests/scssc/inputs/extends.scss ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ error, other {
3
+ border: 1px #f00;
4
+ background-color: #fdd;
5
+ }
6
+
7
+ pre, span {
8
+ seriousError {
9
+ @extend error;
10
+ font-size: 20px;
11
+ }
12
+ }
13
+
14
+ hello {
15
+ @extend other;
16
+ color: green;
17
+ div {
18
+ margin: 10px;
19
+ }
20
+ }
21
+
22
+ .cool {
23
+ color: red;
24
+ }
25
+
26
+ .blue {
27
+ color: purple;
28
+ }
29
+
30
+ .me {
31
+ @extend .cool, .blue;
32
+ }
33
+
34
+ .hoverlink { @extend a:hover }
35
+ a:hover { text-decoration: underline }
36
+
37
+
38
+ // partial matching and selector merging:
39
+
40
+ div.hello.world.hmm {
41
+ color: blue;
42
+ }
43
+
44
+ pre, code {
45
+ .okay.span {
46
+ @extend .hello;
47
+ }
48
+ }
49
+
50
+ // multiple matches per selector
51
+ .xxxxx .xxxxx .xxxxx {
52
+ color: green;
53
+ }
54
+
55
+ code {
56
+ @extend .xxxxx;
57
+ color: red;
58
+ }
59
+
60
+
61
+ // chained
62
+
63
+ .alpha {
64
+ color: red;
65
+ }
66
+
67
+ .beta {
68
+ @extend .alpha;
69
+ color: white;
70
+ }
71
+
72
+ .gama {
73
+ @extend .beta;
74
+ color: blue;
75
+ }
76
+
77
+ // merging selector sequences
78
+
79
+ #admin .tabbar a {font-weight: bold}
80
+ #demo .overview .fakelink {@extend a}
81
+
82
+ a1 b1 c1 d1 { color: red; }
83
+ x1 y1 z1 w1 { @extend a1; }
84
+
85
+ a2 b2 c2 d2 { color: red; }
86
+ x2 y2 z2 w2 { @extend b2; }
87
+
88
+
89
+ a3 b3 c3 d3 { color: red; }
90
+ x3 y3 z3 w3 { @extend c3; }
91
+
92
+
93
+ a4 b4 c4 d4 { color: red; }
94
+ x4 y4 z4 w4 { @extend d4; }
95
+
96
+ // removing common prefix
97
+
98
+ #butt .yeah .okay { font-weight: bold }
99
+ #butt .umm .sure { @extend .okay }
100
+
101
+ a9 b9 s9 t9 v9 { color: red; }
102
+
103
+ a9 b9 x9 y9 z9 {
104
+ @extend v9;
105
+ }
106
+
107
+ // extends & media
108
+
109
+ @media print {
110
+ horse {
111
+ color: blue;
112
+ }
113
+ }
114
+
115
+ man {
116
+ color: red;
117
+ @extend horse;
118
+ }
119
+
120
+
121
+ // result == match
122
+
123
+ wassup {
124
+ color: blue;
125
+ @extend wassup;
126
+ }
127
+
128
+ .foo {
129
+ .wassup {
130
+ @extend .wassup;
131
+ color: blue;
132
+ }
133
+ }
134
+
135
+ // multi-extend
136
+
137
+ #something {
138
+ color: red;
139
+ }
140
+
141
+ .x {
142
+ @extend #something;
143
+ }
144
+
145
+ .y {
146
+ @extend #something;
147
+ }
148
+
149
+ // twitter-sass-bootstrap infinite loop
150
+
151
+ .nav-tabs {
152
+ &.nav-justified {
153
+ @extend .nav-justified;
154
+ }
155
+ }
156
+ .nav-justified {
157
+ text-align: justify;
158
+ }
159
+
160
+ // multi-extend with nesting
161
+
162
+ .btn:hover,
163
+ .btn:active,
164
+ .btn.active,
165
+ .btn.disabled,
166
+ .btn[disabled] {
167
+ color: red;
168
+ }
169
+ .edit .actions {
170
+ button {
171
+ float: right;
172
+ @extend .btn;
173
+ }
174
+ }
175
+ .edit {
176
+ .new {
177
+ .actions {
178
+ padding: 0;
179
+ }
180
+ .actions button {
181
+ @extend .btn;
182
+ }
183
+ }
184
+ }
tests/scssc/inputs/filter_effects.scss ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #number {
2
+ -webkit-filter: grayscale(1)
3
+ sepia(0.5)
4
+ saturate(0.1)
5
+ invert(1)
6
+ opacity(0.5)
7
+ brightness(0.5)
8
+ contrast(0.5);
9
+ }
10
+
11
+ #percentage {
12
+ -webkit-filter: grayscale(100%)
13
+ sepia(50%)
14
+ saturate(10%)
15
+ invert(100%)
16
+ opacity(50%)
17
+ brightness(50%)
18
+ contrast(50%);
19
+ }
20
+
21
+ #misc {
22
+ -webkit-filter: hue-rotate(90deg)
23
+ blur(10px)
24
+ drop-shadow(10px -16px 30px purple);
25
+ }
26
+
27
+ @mixin opacity($opacity, $style: 0) {
28
+ @if ($opacity < 1) {
29
+ opacity: $opacity;
30
+ filter: alpha(opacity=$opacity * 100, style=$style);
31
+ } @else {
32
+ opacity: $opacity / 100;
33
+ filter: alpha(opacity=$opacity);
34
+ }
35
+ }
36
+
37
+ #decimal {
38
+ @include opacity(.5, 1);
39
+ }
40
+
41
+ #percent {
42
+ @include opacity(50);
43
+ }
44
+
45
+ .row {
46
+ background-color: darken(#2ba6cb, 40%);
47
+ color: darken(#2ba6cb, 10%);
48
+ }
tests/scssc/inputs/functions.scss ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ @function hello($x) {
3
+ @return $x + 4;
4
+ }
5
+
6
+ @function add($a, $b) {
7
+ @return $a + $b;
8
+ }
9
+
10
+ div {
11
+ color: hello(10px);
12
+ sum: add(11, 12);
13
+ }
14
+
15
+ // make sure values are being reduced before being passed up to previous scope
16
+
17
+ @function one($a, $b) {
18
+ @return $a $b;
19
+ }
20
+
21
+ @function two($a, $b) {
22
+ @return $a#{$a} $b;
23
+ }
24
+
25
+ @function three($a, $b: default) {
26
+ @return "hello #{$a} and #{$b}"
27
+ }
28
+
29
+ @function all($a...) {
30
+ @return "hello #{$a}"
31
+ }
32
+
33
+ div {
34
+ hello: one(10, 55);
35
+ hello: two(10, 55);
36
+ hello: three(10, 55);
37
+ }
38
+
39
+
40
+ @function hello_world() {
41
+ @return 1000;
42
+ }
43
+
44
+ del {
45
+ color: hello-world();
46
+ }
47
+
48
+ div {
49
+ $args: foo bar;
50
+ hello: three($args...);
51
+ hello: three(bar...);
52
+ hello: all(Alice, Bob, Tom);
53
+ }
54
+
55
+ @function stringConcatCompassStyle($start,$last)
56
+ {
57
+ // Compass still uses it like this
58
+ @return #{$start}-#{$last};
59
+ }
60
+
61
+ .foo
62
+ {
63
+ test2: stringConcatCompassStyle(-moz,art);
64
+ }
65
+
66
+ @mixin content_test {
67
+ span {
68
+ $color: green;
69
+ @content;
70
+ }
71
+ }
72
+
73
+ @function func_test($c) {
74
+ @return $c + 1;
75
+ }
76
+
77
+ div {
78
+ @include content_test {
79
+ height: func_test(2px);
80
+ }
81
+ }
tests/scssc/inputs/ie7.scss ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // http://jes.st/2013/ie7s-css-breaking-content-counter-bug/
2
+ #foo:before {
3
+ content: counter(item, ".") ": ";
4
+ }
5
+
6
+ #bar:before {
7
+ content: counter(item,".");
8
+ }
9
+
10
+ #fu:before {
11
+ content: counter(item);
12
+ }
tests/scssc/inputs/if.scss ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ @function conds($val) {
3
+ @if $val {
4
+ @return "red";
5
+ }
6
+
7
+ @return "blue";
8
+ }
9
+
10
+ div {
11
+ @if something {
12
+ color: blue;
13
+ }
14
+ }
15
+
16
+ pre {
17
+ val-1: conds(true);
18
+ val-2: conds(false);
19
+ val-3: conds(null);
20
+ val-4: conds(1);
21
+ val-5: conds(0);
22
+ }
23
+
24
+
25
+ span {
26
+ @if false {
27
+ color: red;
28
+ } @else {
29
+ color: blue;
30
+ }
31
+
32
+ @if true {
33
+ height: 10px;
34
+ } @else {
35
+ color: 20px;
36
+ }
37
+
38
+ @if false {
39
+ height: 10px;
40
+ } @elseif false {
41
+ color: 20px;
42
+ } @else {
43
+ width: 20px;
44
+ }
45
+ }
46
+
47
+ div {
48
+ @if false {
49
+ color: red;
50
+ } @else if false {
51
+ color: green;
52
+ } @else {
53
+ color: blue;
54
+ }
55
+
56
+ @if false {
57
+ border-color: red;
58
+ } @else if true {
59
+ border-color: green;
60
+ } @else {
61
+ border-color: blue;
62
+ }
63
+
64
+ }
65
+
66
+ // doesn't work in scss, thing loses scope
67
+ del {
68
+ @if false {
69
+ $thing: yes;
70
+ } @else {
71
+ $thing: no;
72
+ }
73
+
74
+ thing: $thing;
75
+ }
76
+
tests/scssc/inputs/if_on_null.scss ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ @function testfunc($pseudo: null) {
2
+ $output: if($pseudo, "green", "red");
3
+ @return $output;
4
+ }
5
+
6
+ body {
7
+ background-color: testfunc();
8
+ }
tests/scssc/inputs/import.scss ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ @import "foo.css";
3
+ @import "foo" screen;
4
+ @import "http://foo.com/bar";
5
+ @import url(foo);
6
+
7
+ @import "imports/simple";
8
+
9
+ pre {
10
+ color: red;
11
+ @import "imports/simple.scss";
12
+ }
13
+
14
+ code {
15
+ @import "imports/simple", "imports/simple";
16
+ }
17
+
18
+ @import "imports/partial";
19
+
20
+ body {
21
+ color: $variable;
22
+ @include partial-mixin();
23
+ }
tests/scssc/inputs/imports/_partial.scss ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #partial {
3
+ color: blue;
4
+ }
5
+
6
+ $variable: #7C2;
7
+
8
+ @mixin partial-mixin() {
9
+ background: gray;
10
+ }
tests/scssc/inputs/imports/simple.scss ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ div {
2
+ height: 200px;
3
+ color: red;
4
+ }
tests/scssc/inputs/interpolation.scss ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ div {
3
+ color: red#{white} blue;
4
+ color: red #{white} blue;
5
+ color: red #{white}blue;
6
+ color: red#{white}blue;
7
+ color: #{umm}#{yeah}#{what};
8
+ color: #{stacked};
9
+
10
+ font-size: 10px/#{something};
11
+ font-size: 10px / #{something};
12
+
13
+ test: "what#{"world"}wrong";
14
+ test: "what#{'world'}wrong";
15
+ test: "what#{world}wrong";
16
+ test: "what"#{world}"wrong";
17
+
18
+ hi: "what is #{4 + 12} end"
19
+ }
20
+
21
+
22
+ // interpolation in selectors
23
+
24
+ pre {
25
+ $var: cool;
26
+
27
+ #{var} {
28
+ color: red;
29
+ }
30
+
31
+ #{var} dad {
32
+ color: red;
33
+ }
34
+
35
+ bed#{var}dad {
36
+ color: red;
37
+ }
38
+ }
39
+
40
+ cool {
41
+ @for $x from 1 through 5 {
42
+ .thing-#{$x} {
43
+ color: red;
44
+ }
45
+ }
46
+ }
47
+
48
+ a#{b}c#{d}e {
49
+ color: red;
50
+ }
51
+
52
+ ##{hello}, .#{world}{
53
+ color: red;
54
+ }
55
+
56
+ #abc#{hello}yeah, .cool#{world}yes{
57
+ color: red;
58
+ }
59
+
60
+ $scope: 2;
61
+
62
+ div.element:nth-child(#{$scope}n)
63
+ {
64
+ display: none;
65
+ }
66
+
67
+ // property interpolation
68
+
69
+ div {
70
+ $var: hello;
71
+ #{$var}: world;
72
+ cool#{$var}:world;
73
+ #{$var}one:world;
74
+ two#{$var}one:world;
75
+
76
+ one#{a + b}two: cool;
77
+
78
+ #{hello}: {
79
+ #{world}: red;
80
+ #{mold}: white;
81
+ #{$var}: blue;
82
+ }
83
+
84
+ }
85
+
86
+
tests/scssc/inputs/keyword_args.scss ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ // mixins
3
+
4
+ @mixin hello($a: one, $b:two, $c:three, $d: four) {
5
+ out: $a $b $c $d;
6
+ }
7
+
8
+ pre {
9
+ @include hello(alpha, $d: palace, $b: fort);
10
+ }
11
+
12
+
13
+ // functions
14
+
15
+ @function cool($a, $b) {
16
+ @return $a - $b;
17
+ }
18
+
19
+ div {
20
+ hello: cool($b: 5, $a: 10);
21
+ world: cool(5, 10);
22
+ }
23
+
24
+
tests/scssc/inputs/list.scss ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ $list: (black);
2
+ $list: join($list, white, comma);
3
+
4
+ div {
5
+ padding: join(10px 20px, 30px 40px);
6
+ margin: join((0, 10px), (10px, 10px), space);
7
+ background: linear-gradient($list);
8
+ }
9
+
10
+ $list: ();
11
+ $list: join($list, (red, blue), comma);
12
+
13
+ p {
14
+ background: linear-gradient($list);
15
+ }
tests/scssc/inputs/looping.scss ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ div {
3
+ @each $var in what is this {
4
+ color: $var;
5
+ }
6
+
7
+ @each $var in what, is, this {
8
+ font: $var;
9
+ }
10
+
11
+ $list: what is this;
12
+ @each $var in $list {
13
+ background: $var;
14
+ }
15
+
16
+ $list: what, is, this;
17
+ @each $var in $list {
18
+ border: $var;
19
+ }
20
+ }
21
+
22
+
23
+ span {
24
+ $i: 0;
25
+ @while $i <= 10 {
26
+ color: $i;
27
+ $i: $i + 1;
28
+ }
29
+ }
30
+
31
+ pre {
32
+ @for $x from 1 to 5 {
33
+ color: $x;
34
+ }
35
+
36
+ @for $x from 1 through 5 {
37
+ height: $x;
38
+ }
39
+
40
+ $y: 10;
41
+ @for $x from $y through 3 {
42
+ cool: $x;
43
+ }
44
+
45
+ }
46
+
47
+ $j: null;
48
+ @while $j {
49
+ .item { width: 2em; }
50
+ $j: false;
51
+ }
tests/scssc/inputs/media.scss ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ // media syntax
3
+ @media {
4
+ div { color: blue; }
5
+ }
6
+ @media what {
7
+ div { color: blue; }
8
+ }
9
+
10
+ @media (cool) {
11
+ div { color: blue; }
12
+ }
13
+ @media (cool: blue) {
14
+ div { color: blue; }
15
+ }
16
+
17
+ @media hello and (world) and (butt: man) {
18
+ div { color: blue; }
19
+ }
20
+
21
+ $navbarCollapseWidth: 940px;
22
+
23
+ @media (max-width: $navbarCollapseWidth) {
24
+ color: red;
25
+ }
26
+
27
+ // media bubbling
28
+ @media not hello and (world) {
29
+ color: blue;
30
+ pre {
31
+ color: blue;
32
+ }
33
+
34
+ @media butt {
35
+ color: red;
36
+ div {
37
+ color: red;
38
+ }
39
+ }
40
+ }
41
+
42
+ @media a, b {
43
+ @media c {
44
+ color: blue;
45
+ }
46
+ }
47
+
48
+ @media a{
49
+ @media b, c {
50
+ color: blue;
51
+ }
52
+ }
53
+
54
+ @media a, b{
55
+ @media c, d {
56
+ color: blue;
57
+ }
58
+ }
59
+
60
+ $media: cree;
61
+ $feature: -webkit-min-device-pixel-ratio;
62
+ $value: 1.5;
63
+
64
+ div {
65
+ color: blue;
66
+ @media s#{$media}n and ($feature: $value) {
67
+ .sidebar {
68
+ width: 500px;
69
+ }
70
+ }
71
+ }
72
+
73
+ // @media + @mixin
74
+ @mixin color {
75
+ color: red;
76
+ .success {
77
+ color: green;
78
+ }
79
+ }
80
+
81
+ div {
82
+ position: absolute;
83
+ $y: 2em;
84
+ @media screen {
85
+ top: 0;
86
+ $x: 5px;
87
+ p {
88
+ margin: $x;
89
+ }
90
+ bottom: 6em + $y;
91
+ @include color;
92
+ }
93
+ }
94
+
95
+ .button {
96
+ width: 300px;
97
+ height: 100px;
98
+ background: #eee;
99
+
100
+ :hover {
101
+ background: #aaa;
102
+ }
103
+
104
+ @media only screen and (max-width : 300px){
105
+ width: 100px;
106
+ height: 100px;
107
+ }
108
+ }
109
+
110
+ code {
111
+ position: absolute;
112
+ @media screen {
113
+ pre {
114
+ height: 20px;
115
+ }
116
+ height: 10px;
117
+ }
118
+ }
119
+
120
+ dt {
121
+ @media screen {
122
+ @media (color: blue) {
123
+ height: 10px;
124
+ }
125
+ }
126
+ }
127
+
128
+ // nesting media queries
129
+ @media screen {
130
+ .screen {
131
+ width: 12px;
132
+ }
133
+ @media only screen {
134
+ .only-screen {
135
+ height: 11px;
136
+ }
137
+ }
138
+ }
139
+
140
+ @media only screen {
141
+ .only-screen {
142
+ width: 14px;
143
+ }
144
+ @media only screen {
145
+ .only-screen {
146
+ height: 16px;
147
+ }
148
+ }
149
+ }
150
+
151
+ @media not screen {
152
+ @media screen {
153
+ .invalid {
154
+ height: 12px;
155
+ }
156
+ }
157
+ }
158
+
159
+ @media not screen {
160
+ @media print {
161
+ .only-print {
162
+ height: 12px;
163
+ }
164
+ }
165
+ }
166
+
167
+ @media screen {
168
+ @media not print {
169
+ .only-print {
170
+ height: 12px;
171
+ }
172
+ }
173
+ }
174
+
175
+ @media not screen {
176
+ @media not print {
177
+ .invalid {
178
+ height: 12px;
179
+ }
180
+ }
181
+ }
182
+
183
+ @media not screen {
184
+ @media not screen {
185
+ .not-screen {
186
+ height: 15px;
187
+ }
188
+ }
189
+ }
190
+
191
+ @media only screen {
192
+ @media print {
193
+ .invalid {
194
+ height: 15px;
195
+ }
196
+ }
197
+ }
198
+
199
+ @media only screen {
200
+ @media screen and (color: blue) {
201
+ @media screen and (width: 13) {
202
+ .only-screen {
203
+ height: 15px;
204
+ }
205
+ }
206
+ }
207
+ }
208
+
tests/scssc/inputs/mixins.scss ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ @mixin something {
3
+ color: red;
4
+ pre {
5
+ height: 200px;
6
+ }
7
+ }
8
+
9
+ div {
10
+ color: blue;
11
+ @include something;
12
+ }
13
+
14
+ @mixin something($color) {
15
+ color: $color;
16
+
17
+ div {
18
+ height: 20px;
19
+ }
20
+ }
21
+
22
+ @mixin cool($a, $b, $c) {
23
+ height: $a + $b + $c;
24
+ }
25
+
26
+ span {
27
+ @include something(blue);
28
+ }
29
+
30
+ html {
31
+ @include cool(10px, 12px, 21px);
32
+ }
33
+
34
+
35
+ @mixin hello_world {
36
+ height: 20px;
37
+ }
38
+
39
+ del {
40
+ @include hello-world;
41
+ }
42
+
43
+
44
+ // variable shadowing
45
+
46
+
47
+ $color: white;
48
+ @mixin colors($color: blue) {
49
+ color: $color;
50
+ }
51
+
52
+ div {
53
+ color: $color;
54
+ @include colors();
55
+ color: $color;
56
+ }
57
+
58
+ @mixin linear-gradient($from, $to, $pos: left top) {
59
+ background-image: linear-gradient($pos, $from, $to);
60
+ }
61
+
62
+ div {
63
+ @include linear-gradient(red, green);
64
+ }
65
+
66
+ @mixin box-shadow($shadows...) {
67
+ -moz-box-shadow: $shadows;
68
+ -webkit-box-shadow: $shadows;
69
+ box-shadow: $shadows;
70
+ }
71
+
72
+ div {
73
+ @include box-shadow(10px 10px 5px #888);
74
+ @include box-shadow(inset 10px 10px #888, -10px -10px #f4f4f4);
75
+ }
76
+
77
+ @mixin nested {
78
+ @include something(red);
79
+ }
80
+
81
+ div {
82
+ p {
83
+ .class {
84
+ @include nested;
85
+ }
86
+
87
+ @include nested;
88
+
89
+ .top {
90
+ top: 0;
91
+
92
+ div {
93
+ color: red;
94
+ }
95
+ }
96
+
97
+ color: blue;
98
+ }
99
+ }
100
+
101
+ // mixin content (http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#mixin-content)
102
+ @mixin content-simple {
103
+ div.mixin-content-simple {
104
+ @content;
105
+ }
106
+ }
107
+
108
+ @mixin content-with-arg ( $background ) {
109
+ div.mixin-content-with-arg {
110
+ background: $background;
111
+ @content;
112
+ }
113
+ }
114
+
115
+ @include content-simple {
116
+ color: red;
117
+ }
118
+
119
+ @include content-with-arg($background: blue) {
120
+ color: red;
121
+ }
122
+
123
+ @include content-with-arg($background: purple) {
124
+ @include hello_world;
125
+ }
126
+
127
+ @include content-simple {
128
+ @include cool(10px, 12px, 21px);
129
+ }
130
+
131
+ @include content-simple {
132
+ @include something(orange);
133
+ }
134
+
135
+ @include content-with-arg($background: purple) {
136
+ @include cool(10px, 12px, 21px);
137
+ }
138
+
139
+ @include content-with-arg($background: purple) {
140
+ @include something(orange);
141
+ }
142
+
143
+ @mixin wallpaper($image, $top: 0, $right: 0, $bottom: 0, $left: 0) {
144
+ background: $image;
145
+ position: absolute;
146
+ top: $top;
147
+ right: $right;
148
+ bottom: $bottom;
149
+ left: $left;
150
+ }
151
+
152
+ @mixin logo($offsets...) {
153
+ @include wallpaper(url(/images/logo.png), $offsets...);
154
+ }
155
+
156
+ #please-wait {
157
+ @include logo(1em, $left: 4em, $bottom: 3em);
158
+ }
tests/scssc/inputs/nesting.scss ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ body {
4
+ color: red;
5
+ }
6
+
7
+
8
+ div {
9
+ color: red;
10
+ height: yes;
11
+
12
+ pre {
13
+ color: blue;
14
+ }
15
+ }
16
+
17
+
18
+ div: blue;
19
+
20
+
21
+ div {
22
+ font: 10px hello world {
23
+ size: 10px;
24
+ color: blue;
25
+ }
26
+
27
+ border: {
28
+ left: 1px solid blue;
29
+ right: 2px dashed green;
30
+ }
31
+ }
32
+
33
+
34
+ #nested-nesting {
35
+ bar: baz;
36
+ bang: {
37
+ bop: bar;
38
+ bip: 1px;
39
+ blat: {
40
+ baf: bort
41
+ }
42
+ }
43
+ }
44
+
45
+
tests/scssc/inputs/null.scss ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ $list: null;
2
+ .div {
3
+ one: null;
4
+ one: null world;
5
+ one: NULL world;
6
+ one: a null, b;
7
+ two: a $list $list, $list, b;
8
+ three: $list;
9
+ }
10
+
11
+ $value: null;
12
+ p:before {
13
+ content: "I ate #{$value} pies!";
14
+ }
15
+
16
+ @mixin Rounded($radius1, $direction: null, $radius2: false) {
17
+ $corner: null;
18
+ @if $direction == TL { $corner: top-left-; }
19
+ @if $direction == TR { $corner: top-right-; }
20
+ @if $direction == BL { $corner: bottom-left-; }
21
+ @if $direction == BR { $corner: bottom-right-; }
22
+ @if $radius2 {
23
+ -webkit-border-#{$corner}radius: $radius1 $radius2;
24
+ border-#{$corner}radius: $radius1 $radius2;
25
+ } @else {
26
+ -webkit-border-#{$corner}radius: $radius1;
27
+ border-#{$corner}radius: $radius1;
28
+ }
29
+ }
30
+
31
+ .foo {
32
+ @include Rounded(10);
33
+ }
34
+
35
+ .fu {
36
+ @include Rounded(20, null);
37
+ }
38
+
39
+ .bar {
40
+ @include Rounded(30, TL);
41
+ }
tests/scssc/inputs/operators.scss ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ body {
4
+ color: 1 + 2 + 5;
5
+ color: 1 + 2 * 5 + 5;
6
+ height: 10px/10px;
7
+ color: 10px/2 + 1;
8
+ color: (10px/2);
9
+ bottom: (4/2px);
10
+ top: 1em * (1 * 24px - 0) / 16px;
11
+ left: 1 - 2cm;
12
+ top: (2cm/12px);
13
+ }
14
+
15
+ div {
16
+ color: 4 == 3;
17
+ color: hello == hello;
18
+
19
+ color: 4 > 3;
20
+ color: 4 < 3;
21
+ color: what > 3;
22
+ }
23
+
24
+
25
+ #units {
26
+ test: 1in + 4cm;
27
+ test: 12mm + 1;
28
+ test: 1 + 3em;
29
+ test: 1mm + 1cm;
30
+ test: 1cm + 1mm;
31
+ }
32
+
33
+ #modulo {
34
+ test: 3 % 2;
35
+ test: 4cm % 3;
36
+ }
37
+
38
+ #colors {
39
+ color: red + rgb(1,2,3);
40
+ color: red - rgb(1,2,3);
41
+ color: rgba(1,2,3, 0.5) * rgba(3,4,5, 0.5);
42
+ color: rgba(10,15,20, 0.5) / rgba(2,2,2, 0.5);
43
+
44
+ color: rgba(1,2,3, 0.5) * 2;
45
+ color: rgba(1,2,3, 0.5) / 2;
46
+ color: rgba(1,2,3, 0.5) + 2;
47
+ color: rgba(1,2,3, 0.5) - 2;
48
+
49
+ color: blue + 34;
50
+
51
+ color: #fff == #000;
52
+ color: #fff == #fff;
53
+
54
+ color: #fff != #000;
55
+ color: #fff != #fff;
56
+ }
57
+
58
+
59
+ #preserve {
60
+ hello: what -going;
61
+ hello: what - going;
62
+ }
63
+
64
+ #strings {
65
+ hello: what -going;
66
+
67
+ hello: what +going;
68
+ hello: what+going;
69
+ hello: what+ going;
70
+ hello: what + going;
71
+
72
+ hello: "what" + going;
73
+ hello: going + "what";
74
+ hello: "what" + "what";
75
+ }
76
+
77
+ #negation {
78
+ $num: 100;
79
+ a: -$num + 40;
80
+ b: 10 -$num;
81
+ b: 10 - $num;
82
+ }
83
+
84
+ #bools-fail {
85
+ and: false and two;
86
+ and: one and two;
87
+ and: one and false;
88
+
89
+ or: false or two;
90
+ or: one or two;
91
+ or: one or false;
92
+ }
93
+
94
+ #bools {
95
+ and: (false and two);
96
+ and: (one and two);
97
+ and: (one and false);
98
+
99
+ or: (false or two);
100
+ or: (one or two);
101
+ or: (one or false);
102
+ }
103
+
104
+
105
+ #nots-fail {
106
+ not: not true + 2;
107
+ not: not false;
108
+ not: not 0;
109
+ not: not 1;
110
+ not: not "";
111
+ not: not hello;
112
+ }
113
+
114
+ #nots {
115
+ not: (not true) + 2;
116
+ not: (not false);
117
+ not: (not 0);
118
+ not: (not 1);
119
+ not: (not "");
120
+ not: (not hello);
121
+ }
122
+
123
+ #string-test {
124
+ str: hi == "hi";
125
+ str: hi == "no";
126
+ str: 'yes' == 'yes';
127
+
128
+ $var1: "hello";
129
+ $var2: hello;
130
+
131
+ str: "#{$var1}" == '#{$var2}';
132
+
133
+ str: xhello#{$var1}x == "x#{$var2}hellox"; // xhellohellofalse
134
+
135
+ str: unit(10px) == px;
136
+ }
137
+
138
+
139
+ #special {
140
+ cancel-unit: (10px / 10px);
141
+ }
142
+
143
+
tests/scssc/inputs/placeholder_selector.scss ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #context a%extreme span {
2
+ color: blue;
3
+ font-weight: bold;
4
+ font-size: 2em;
5
+ }
6
+
7
+ .notice, .error { @extend %extreme; }
8
+
9
+ .hidden %placeholder {
10
+ margin: 0;
11
+ }
12
+
13
+ p {
14
+ @extend #context;
15
+ padding: 2em;
16
+ }
17
+
18
+ div { @extend .hidden; }
tests/scssc/inputs/scss_css.scss ADDED
@@ -0,0 +1,986 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [foo~=bar] {
2
+ a: b; }
3
+
4
+
5
+ [foo^=bar] {
6
+ a: b; }
7
+
8
+
9
+ [foo$=bar] {
10
+ a: b; }
11
+
12
+
13
+ [foo*=bar] {
14
+ a: b; }
15
+
16
+
17
+ [foo|=en] {
18
+ a: b; }
19
+
20
+
21
+ foo {
22
+ a: 2;
23
+ b: 2.3em;
24
+ c: 50%;
25
+ d: "fraz bran";
26
+ e: flanny-blanny-blan;
27
+ f: url(http://sass-lang.com);
28
+ // g: U+ffa?;
29
+ h: #aabbcc; }
30
+
31
+
32
+ selector {
33
+ property: value;
34
+ property2: value; }
35
+
36
+
37
+ sel{p:v}
38
+
39
+ .foo {
40
+ /* Foo
41
+ Bar
42
+ Baz */
43
+ a: b; }
44
+
45
+
46
+ .foo {
47
+ /* Foo
48
+ Bar
49
+ Baz */
50
+ a: b; }
51
+
52
+
53
+ .foo {/* Foo
54
+ Bar */
55
+ a: b; }
56
+
57
+
58
+ .foo {/* Foo
59
+ Bar
60
+ Baz */
61
+ a: b; }
62
+
63
+
64
+ @foo {
65
+ rule {
66
+ a: b; }
67
+
68
+ a: b; }
69
+
70
+
71
+ @foo {a:b};
72
+ @bar {a:b};
73
+
74
+
75
+ @foo "bar"
76
+
77
+ foo {
78
+ a: 12px calc(100%/3 - 2*1em - 2*1px);
79
+ b: 12px -moz-calc(100%/3 - 2*1em - 2*1px);
80
+ b: 12px -webkit-calc(100%/3 - 2*1em - 2*1px);
81
+ b: 12px -foobar-calc(100%/3 - 2*1em - 2*1px); }
82
+
83
+
84
+ foo {bar: baz}
85
+ <!--
86
+ bar {bar: baz}
87
+ -->
88
+ baz {bar: baz}
89
+
90
+
91
+ /*
92
+ * foo
93
+ */
94
+ bar {baz: bang}
95
+
96
+
97
+ E, F {
98
+ a: b; }
99
+
100
+
101
+ E F, G H {
102
+ a: b; }
103
+
104
+
105
+ E > F, G > H {
106
+ a: b; }
107
+
108
+
109
+ /* This is a CSS comment. */
110
+ .one {color: green;} /* Another comment */
111
+ /* The following should not be used:
112
+ .two {color: red;} */
113
+ .three {color: green; /* color: red; */}
114
+ /**
115
+ .four {color: red;} */
116
+ .five {color: green;}
117
+ /**/
118
+ .six {color: green;}
119
+ /*********/
120
+ .seven {color: green;}
121
+ /* a comment **/
122
+ .eight {color: green;}
123
+
124
+
125
+ foo {
126
+ a: \foo bar;
127
+ b: foo\ bar;
128
+ c: \2022 \0020;
129
+ d: foo\\bar;
130
+ e: foo\"\'bar; }
131
+
132
+
133
+ foo {
134
+ a: "\foo bar";
135
+ b: "foo\ bar";
136
+ c: "\2022 \0020";
137
+ d: "foo\\bar";
138
+ e: "foo\"'bar"; }
139
+
140
+
141
+ foo {
142
+ _name: val;
143
+ *name: val;
144
+ :name: val;
145
+ .name: val;
146
+ #name: val;
147
+ name/**/: val;
148
+ name/*\**/: val;
149
+ name: val; }
150
+
151
+
152
+ @foo "bar" ;
153
+
154
+ foo {
155
+ a: -moz-element(#foo);
156
+ b: -webkit-element(#foo);
157
+ b: -foobar-element(#foo); }
158
+
159
+
160
+ @foo {}
161
+
162
+ @foo {
163
+ }
164
+
165
+
166
+ @foo;
167
+
168
+ foo {;;;;
169
+ bar: baz;;;;
170
+ ;;}
171
+
172
+
173
+ #foo .bar {}
174
+
175
+ #foo .bar {
176
+ }
177
+
178
+
179
+ 0% {
180
+ a: b; }
181
+
182
+
183
+ 60% {
184
+ a: b; }
185
+
186
+
187
+ 100% {
188
+ a: b; }
189
+
190
+
191
+ 12px {
192
+ a: b; }
193
+
194
+
195
+ "foo" {
196
+ a: b; }
197
+
198
+
199
+ foo {
200
+ a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); }
201
+
202
+
203
+ :foo("bar") {
204
+ a: b; }
205
+
206
+
207
+ :foo(bar) {
208
+ a: b; }
209
+
210
+
211
+ :foo(12px) {
212
+ a: b; }
213
+
214
+
215
+ :foo(+) {
216
+ a: b; }
217
+
218
+
219
+ :foo(-) {
220
+ a: b; }
221
+
222
+
223
+ :foo(+"bar") {
224
+ a: b; }
225
+
226
+
227
+ :foo(-++--baz-"bar"12px) {
228
+ a: b; }
229
+
230
+
231
+ foo {
232
+ a: foo-bar(12);
233
+ b: -foo-bar-baz(13, 14 15); }
234
+
235
+
236
+ @import "foo.css";
237
+
238
+ @import 'foo.css';
239
+
240
+ @import url("foo.css");
241
+
242
+ @import url('foo.css');
243
+
244
+ @import url(foo.css);
245
+
246
+ @import "foo.css" screen;
247
+
248
+ @import "foo.css" screen, print;
249
+
250
+ @import "foo.css" screen, print and (foo: 0);
251
+
252
+ @import "foo.css" screen, only print, screen and (foo: 0);
253
+
254
+ foo {
255
+ a: foo !important;
256
+ b: foo bar !important;
257
+ b: foo, bar !important; }
258
+
259
+
260
+ foo {
261
+ a: -moz-bar-baz;
262
+ b: foo -o-bar-baz; }
263
+
264
+
265
+ foo {a: /* b; c: */ d}
266
+
267
+
268
+ foo {a /*: b; c */: d}
269
+
270
+
271
+ /* Foo
272
+ * Bar */
273
+
274
+
275
+ .foo {
276
+ /* Foo
277
+ * Bar */ }
278
+
279
+
280
+ [foo] {
281
+ a: b; }
282
+
283
+
284
+ [foo="bar"] {
285
+ a: b; }
286
+
287
+
288
+ [foo~="bar"] {
289
+ a: b; }
290
+
291
+
292
+ [foo^="bar"] {
293
+ a: b; }
294
+
295
+
296
+ [foo$="bar"] {
297
+ a: b; }
298
+
299
+
300
+ [foo*="bar"] {
301
+ a: b; }
302
+
303
+
304
+ [foo|="en"] {
305
+ a: b; }
306
+
307
+
308
+ :root {
309
+ a: b; }
310
+
311
+
312
+ :nth-child(n) {
313
+ a: b; }
314
+
315
+
316
+ :nth-last-child(n) {
317
+ a: b; }
318
+
319
+
320
+ :nth-of-type(n) {
321
+ a: b; }
322
+
323
+
324
+ :nth-last-of-type(n) {
325
+ a: b; }
326
+
327
+
328
+ :first-child {
329
+ a: b; }
330
+
331
+
332
+ :last-child {
333
+ a: b; }
334
+
335
+
336
+ :first-of-type {
337
+ a: b; }
338
+
339
+
340
+ :last-of-type {
341
+ a: b; }
342
+
343
+
344
+ :only-child {
345
+ a: b; }
346
+
347
+
348
+ :only-of-type {
349
+ a: b; }
350
+
351
+
352
+ :empty {
353
+ a: b; }
354
+
355
+
356
+ :link {
357
+ a: b; }
358
+
359
+
360
+ :visited {
361
+ a: b; }
362
+
363
+
364
+ :active {
365
+ a: b; }
366
+
367
+
368
+ :hover {
369
+ a: b; }
370
+
371
+
372
+ :focus {
373
+ a: b; }
374
+
375
+
376
+ :target {
377
+ a: b; }
378
+
379
+
380
+ :lang(fr) {
381
+ a: b; }
382
+
383
+
384
+ :enabled {
385
+ a: b; }
386
+
387
+
388
+ :disabled {
389
+ a: b; }
390
+
391
+
392
+ :checked {
393
+ a: b; }
394
+
395
+
396
+ ::first-line {
397
+ a: b; }
398
+
399
+
400
+ ::first-letter {
401
+ a: b; }
402
+
403
+
404
+ ::before {
405
+ a: b; }
406
+
407
+
408
+ ::after {
409
+ a: b; }
410
+
411
+
412
+ .warning {
413
+ a: b; }
414
+
415
+
416
+ #myid {
417
+ a: b; }
418
+
419
+
420
+ :not(s) {
421
+ a: b; }
422
+
423
+
424
+ @media all {
425
+ rule1 {
426
+ prop: val; }
427
+
428
+ rule2 {
429
+ prop: val; } }
430
+
431
+
432
+ @media screen, print {
433
+ rule1 {
434
+ prop: val; }
435
+
436
+ rule2 {
437
+ prop: val; } }
438
+
439
+
440
+ @media screen and (-webkit-min-device-pixel-ratio:0) {
441
+ a: b; }
442
+
443
+
444
+ @media only screen, print and (foo: 0px) and (bar: flam(12px solid)) {
445
+ a: b; }
446
+
447
+
448
+ :-moz-any(h1, h2, h3) {
449
+ a: b; }
450
+
451
+
452
+ :-moz-any(.foo) {
453
+ a: b; }
454
+
455
+
456
+ :-moz-any(foo bar, .baz > .bang) {
457
+ a: b; }
458
+
459
+
460
+ @-moz-document url(http://www.w3.org/),
461
+ url-prefix(http://www.w3.org/Style/),
462
+ domain(mozilla.org),
463
+ regexp("^https:.*") {
464
+ .foo {a: b}
465
+ }
466
+
467
+
468
+ foo {
469
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000);
470
+ filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); }
471
+
472
+
473
+ foo {
474
+ filter: alpha(opacity=20);
475
+ filter: alpha(opacity=20, enabled=true);
476
+ filter: blaznicate(foo=bar, baz=bang bip, bart=#fa4600); }
477
+
478
+
479
+ @foo bar {
480
+ a: b; }
481
+
482
+ @bar baz {
483
+ c: d; }
484
+
485
+
486
+ @foo bar;
487
+ @bar baz;
488
+
489
+
490
+ /* Foo
491
+ * Bar */
492
+ /* Baz
493
+ * Bang */
494
+
495
+
496
+ .foo {
497
+ /* Foo
498
+ * Bar */
499
+ /* Baz
500
+ * Bang */ }
501
+
502
+
503
+ .foo {
504
+ /* Foo Bar *//* Baz Bang */ }
505
+
506
+
507
+ @namespace "http://www.w3.org/Profiles/xhtml1-strict";
508
+
509
+ @namespace url(http://www.w3.org/Profiles/xhtml1-strict);
510
+
511
+ @namespace html url("http://www.w3.org/Profiles/xhtml1-strict");
512
+
513
+ [foo|bar=baz] {
514
+ a: b; }
515
+
516
+
517
+ [*|bar=baz] {
518
+ a: b; }
519
+
520
+
521
+ [foo|bar|=baz] {
522
+ a: b; }
523
+
524
+
525
+ foo|E {
526
+ a: b; }
527
+
528
+
529
+ *|E {
530
+ a: b; }
531
+
532
+
533
+ foo|* {
534
+ a: b; }
535
+
536
+
537
+ *|* {
538
+ a: b; }
539
+
540
+
541
+ :not(foo|bar) {
542
+ a: b; }
543
+
544
+
545
+ :not(*|bar) {
546
+ a: b; }
547
+
548
+
549
+ :not(foo|*) {
550
+ a: b; }
551
+
552
+
553
+ :not(*|*) {
554
+ a: b; }
555
+
556
+
557
+ :not(#blah) {
558
+ a: b; }
559
+
560
+
561
+ :not(.blah) {
562
+ a: b; }
563
+
564
+
565
+ :not([foo]) {
566
+ a: b; }
567
+
568
+
569
+ :not([foo^="bar"]) {
570
+ a: b; }
571
+
572
+
573
+ :not([baz|foo~="bar"]) {
574
+ a: b; }
575
+
576
+
577
+ :not(:hover) {
578
+ a: b; }
579
+
580
+
581
+ :not(:nth-child(2n + 3)) {
582
+ a: b; }
583
+
584
+
585
+ :not(:not(#foo)) {
586
+ a: b; }
587
+
588
+
589
+ :not(a#foo.bar) {
590
+ a: b; }
591
+
592
+
593
+ :not(#foo .bar > baz) {
594
+ a: b; }
595
+
596
+
597
+ :not(h1, h2, h3) {
598
+ a: b; }
599
+
600
+
601
+ @mixin foo {
602
+ a: b; }
603
+
604
+
605
+ foo {
606
+ a: "bang #{1 + " bar "} bip"; }
607
+
608
+
609
+ :nth-child(-n) {
610
+ a: b; }
611
+
612
+
613
+ :nth-child(+n) {
614
+ a: b; }
615
+
616
+
617
+ :nth-child(even) {
618
+ a: b; }
619
+
620
+
621
+ :nth-child(odd) {
622
+ a: b; }
623
+
624
+
625
+ :nth-child(50) {
626
+ a: b; }
627
+
628
+
629
+ :nth-child(-50) {
630
+ a: b; }
631
+
632
+
633
+ :nth-child(+50) {
634
+ a: b; }
635
+
636
+
637
+ :nth-child(2n+3) {
638
+ a: b; }
639
+
640
+
641
+ :nth-child(2n-3) {
642
+ a: b; }
643
+
644
+
645
+ :nth-child(+2n-3) {
646
+ a: b; }
647
+
648
+
649
+ :nth-child(-2n+3) {
650
+ a: b; }
651
+
652
+
653
+ :nth-child(-2n+ 3) {
654
+ a: b; }
655
+
656
+
657
+ :nth-child( 2n + 3 ) {
658
+ a: b; }
659
+
660
+
661
+ foo {
662
+ a: foo bar baz;
663
+ b: foo, #aabbcc, -12;
664
+ c: 1px/2px/-3px;
665
+ d: foo bar, baz/bang; }
666
+
667
+
668
+ @page {
669
+ prop1: val;
670
+ prop2: val; }
671
+
672
+
673
+ @page flap {
674
+ prop1: val;
675
+ prop2: val; }
676
+
677
+
678
+ @page :first {
679
+ prop1: val;
680
+ prop2: val; }
681
+
682
+
683
+ @page flap:first {
684
+ prop1: val;
685
+ prop2: val; }
686
+
687
+
688
+ .foo {
689
+ /* Foo */
690
+ a: b; }
691
+
692
+
693
+ .foo {
694
+ /* Foo
695
+ * Bar */a: b; }
696
+
697
+
698
+ /* Foo */
699
+ .foo {
700
+ a: b; }
701
+
702
+
703
+ /* Foo
704
+ * Bar */.foo {
705
+ a: b; }
706
+
707
+
708
+ .foo /* .a #foo */ #bar:baz(/* bang )*/ bip) {
709
+ a: b; }
710
+
711
+
712
+ > E {
713
+ a: b; }
714
+
715
+
716
+ + E {
717
+ a: b; }
718
+
719
+
720
+ ~ E {
721
+ a: b; }
722
+
723
+
724
+ > > E {
725
+ a: b; }
726
+
727
+
728
+ >> E {
729
+ a: b; }
730
+
731
+
732
+ E* {
733
+ a: b; }
734
+
735
+
736
+ E*.foo {
737
+ a: b; }
738
+
739
+
740
+ E*:hover {
741
+ a: b; }
742
+
743
+
744
+ E,
745
+ F {
746
+ a: b; }
747
+
748
+
749
+ E
750
+ F {
751
+ a: b; }
752
+
753
+
754
+ E, F
755
+ G, H {
756
+ a: b; }
757
+
758
+
759
+ body {
760
+ /*
761
+ //comment here
762
+ */
763
+ }
764
+
765
+
766
+ E>F { a: b;}
767
+
768
+ E~F { a: b;}
769
+
770
+ E+F { a: b;}
771
+
772
+ * {
773
+ a: b; }
774
+
775
+
776
+ E {
777
+ a: b; }
778
+
779
+
780
+ E[foo] {
781
+ a: b; }
782
+
783
+
784
+ E[foo="bar"] {
785
+ a: b; }
786
+
787
+
788
+ E[foo~="bar"] {
789
+ a: b; }
790
+
791
+
792
+ E[foo^="bar"] {
793
+ a: b; }
794
+
795
+
796
+ E[foo$="bar"] {
797
+ a: b; }
798
+
799
+
800
+ E[foo*="bar"] {
801
+ a: b; }
802
+
803
+
804
+ E[foo|="en"] {
805
+ a: b; }
806
+
807
+
808
+ E:root {
809
+ a: b; }
810
+
811
+
812
+ E:nth-child(n) {
813
+ a: b; }
814
+
815
+
816
+ E:nth-last-child(n) {
817
+ a: b; }
818
+
819
+
820
+ E:nth-of-type(n) {
821
+ a: b; }
822
+
823
+
824
+ E:nth-last-of-type(n) {
825
+ a: b; }
826
+
827
+
828
+ E:first-child {
829
+ a: b; }
830
+
831
+
832
+ E:last-child {
833
+ a: b; }
834
+
835
+
836
+ E:first-of-type {
837
+ a: b; }
838
+
839
+
840
+ E:last-of-type {
841
+ a: b; }
842
+
843
+
844
+ E:only-child {
845
+ a: b; }
846
+
847
+
848
+ E:only-of-type {
849
+ a: b; }
850
+
851
+
852
+ E:empty {
853
+ a: b; }
854
+
855
+
856
+ E:link {
857
+ a: b; }
858
+
859
+
860
+ E:visited {
861
+ a: b; }
862
+
863
+
864
+ E:active {
865
+ a: b; }
866
+
867
+
868
+ E:hover {
869
+ a: b; }
870
+
871
+
872
+ E:focus {
873
+ a: b; }
874
+
875
+
876
+ E:target {
877
+ a: b; }
878
+
879
+
880
+ E:lang(fr) {
881
+ a: b; }
882
+
883
+
884
+ E:enabled {
885
+ a: b; }
886
+
887
+
888
+ E:disabled {
889
+ a: b; }
890
+
891
+
892
+ E:checked {
893
+ a: b; }
894
+
895
+
896
+ E::first-line {
897
+ a: b; }
898
+
899
+
900
+ E::first-letter {
901
+ a: b; }
902
+
903
+
904
+ E::before {
905
+ a: b; }
906
+
907
+
908
+ E::after {
909
+ a: b; }
910
+
911
+
912
+ E.warning {
913
+ a: b; }
914
+
915
+
916
+ E#myid {
917
+ a: b; }
918
+
919
+
920
+ E:not(s) {
921
+ a: b; }
922
+
923
+
924
+ E F {
925
+ a: b; }
926
+
927
+
928
+ E > F {
929
+ a: b; }
930
+
931
+
932
+ E + F {
933
+ a: b; }
934
+
935
+
936
+ E ~ F {
937
+ a: b; }
938
+
939
+
940
+ @supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
941
+ .foo {
942
+ a: b;
943
+ }
944
+ }
945
+
946
+
947
+ @-prefix-supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
948
+ .foo {
949
+ a: b;
950
+ }
951
+ }
952
+
953
+
954
+ foo {
955
+ foo: bar;
956
+ #baz: bang;
957
+ #bip: bop; }
958
+
959
+
960
+ foo {
961
+ a: -2;
962
+ b: -2.3em;
963
+ c: -50%;
964
+ d: -foo(bar baz); }
965
+
966
+
967
+ foo {
968
+ a: -0.5em;
969
+ b: +0.5em;
970
+ c: -foo(12px);
971
+ d: +foo(12px);
972
+ }
973
+
974
+
975
+ @charset "UTF-8";
976
+
977
+ foo {
978
+ -moz-foo-bar: blat;
979
+ -o-flat-blang: wibble; }
980
+
981
+
982
+ foo {
983
+ a: foo();
984
+ b: bar baz-bang() bip; }
985
+
986
+
tests/scssc/inputs/selectors.scss ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ * { color: blue; }
2
+ E { color: blue; }
3
+
4
+ E:not(:link) { color: blue; }
5
+ E:not(:link):not(:visited) { color: blue; }
6
+ E:not(:link, :visited) { color: blue; }
7
+ E:matches(:hover, :focus) { color: blue; }
8
+
9
+ E.warning { color: blue; }
10
+ E#id { color: blue; }
11
+ E[foo] { color: blue; }
12
+ E[foo="barbar"] { color: blue; }
13
+ E[foo="barbar" i] { color: blue; }
14
+ E[foo~="hello#$@%@$#^"] { color: blue; }
15
+ E[foo^="color: green;"] { color: blue; }
16
+ E[foo$="239023"] { color: blue; }
17
+ E[foo*="29302"] { color: blue; }
18
+ E[foo|="239032"] { color: blue; }
19
+
20
+ [foo] { color: blue; }
21
+ [foo] .helloWorld { color: blue; }
22
+ [foo].helloWorld { color: blue; }
23
+ [foo="barbar"] { color: blue; }
24
+ [foo~="hello#$@%@$#^"] { color: blue; }
25
+ [foo^="color: green;"] { color: blue; }
26
+ [foo$="239023"] { color: blue; }
27
+ [foo*="29302"] { color: blue; }
28
+ [foo|="239032"] { color: blue; }
29
+
30
+ E:dir(ltr) { color: blue; }
31
+ E:lang(en) { color: blue; }
32
+ E:lang(en, fr) { color: blue; }
33
+
34
+ E:any-link { color: blue; }
35
+ E:link { color: blue; }
36
+ E:visited { color: blue; }
37
+ E:local-link { color: blue; }
38
+ E:local-link(0) { color: red; }
39
+ E:local-link(1) { color: white; }
40
+ E:local-link(2) { color: red; }
41
+ E:target { color: blue; }
42
+ E:scope { color: blue; }
43
+
44
+ E:current { color: blue; }
45
+ E:current(:link) { color: blue; }
46
+ E:past { color: blue; }
47
+ E:future { color: blue; }
48
+
49
+ E:active { color: blue; }
50
+ E:hover { color: blue; }
51
+ E:focus { color: blue; }
52
+ E:enabled { color: blue; }
53
+ E:disabled { color: blue; }
54
+ E:indeterminate { color: blue; }
55
+ E:default { color: blue; }
56
+ E:in-range { color: blue; }
57
+ E:out-of-range { color: blue; }
58
+ E:required { color: blue; }
59
+ E:optional { color: blue; }
60
+ E:read-only { color: blue; }
61
+ E:read-write { color: blue; }
62
+
63
+ E:root { color: blue; }
64
+ E:empty { color: blue; }
65
+ E:first-child { color: blue; }
66
+ E:nth-child(odd) { color: blue; }
67
+ E:nth-child(2n+1) { color: blue; }
68
+ E:nth-child(5) { color: blue; }
69
+ E:last-child { color: blue; }
70
+ E:nth-last-child(-n+2) { color: blue; }
71
+ E:only-child { color: blue; }
72
+ E:first-of-type { color: blue; }
73
+ E:nth-of-type(2n) { color: blue; }
74
+ E:last-of-type { color: blue; }
75
+ E:nth-last-of-type(n) { color: blue; }
76
+ E:only-of-type { color: blue; }
77
+ E:nth-match(odd) { color: blue; }
78
+ E:nth-last-match(odd) { color: blue; }
79
+
80
+ E:column(n) { color: blue; }
81
+ E:nth-column(n) { color: blue; }
82
+ E:nth-last-column(n) { color: blue; }
83
+
84
+ E F { color: blue; }
85
+ E > F { color: blue; }
86
+ E + F { color: blue; }
87
+ E ~ F { color: blue; }
88
+ E /foo/ F { color: blue; }
89
+ E! > F { color: blue; }
90
+
91
+ // namespaces
92
+ [foo|att=val] { color: blue }
93
+ [*|att] { color: yellow }
94
+ [|att] { color: green }
95
+ [att] { color: green }
96
+
97
+ // CSS2.1
98
+ E::first-line { color: blue; }
99
+ E::first-letter { color: blue; }
100
+ E::before { color: blue; }
101
+ E::after { color: blue; }
102
+
103
+ // CSS3 UI (at risk)
104
+ E::choices { color: blue; }
105
+ E::value { color: blue; }
106
+ E::repeat-index { color: blue; }
107
+ E::repeat-item { color: blue; }
108
+
109
+ E:first { color: blue; }
110
+ E:first-line { color: blue; }
111
+ E:first-letter { color: blue; }
112
+ E:before{ color: blue; }
113
+ E:after { color: blue; }
114
+ E:checked { color: blue; }
115
+ E:invalid { color: blue; }
116
+ E:valid { color: blue; }
117
+ E:left { color: blue; }
118
+ E:right { color: blue; }
119
+
120
+ // -moz experimental
121
+ E:any(ol) { color: blue; }
122
+ E::selection { color: blue; }
123
+
124
+ // one of these is nested property,
125
+ // the other is a css block.
126
+ div {
127
+ font:something {
128
+ size: 30em;
129
+ }
130
+
131
+ font: something {
132
+ size: 30em;
133
+ }
134
+
135
+ }
136
+
137
+ // self selector
138
+
139
+ .something {
140
+ &.world {
141
+ color: blue;
142
+ }
143
+
144
+ & .mold {
145
+ height: 200px;
146
+ }
147
+
148
+ .dog & {
149
+ color: blue;
150
+ }
151
+ }
152
+
153
+ .simple {
154
+ .dad & .wolf {
155
+ color: blue;
156
+ }
157
+
158
+ .rad&.bad {
159
+ color: blue;
160
+ }
161
+
162
+ }
163
+
164
+ div {
165
+ .something & .what {
166
+ &.world {
167
+ color: blue;
168
+ }
169
+ }
170
+ }
171
+
172
+ div {
173
+ &.foo & {
174
+ color: blue;
175
+ }
176
+ }
177
+
178
+ .main, div {
179
+ .message div {
180
+ .title {
181
+ .nice-fonts & {
182
+ font-size: 24px;
183
+ }
184
+ }
185
+ }
186
+ }
187
+
tests/scssc/inputs/values.scss ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #values {
3
+ color: #eee;
4
+ color: #eeeeee;
5
+ height: 20px;
6
+ width: 80%;
7
+ color: "hello world";
8
+ height: url("http://google.com");
9
+ dads: url(http://leafo.net);
10
+ padding: 10px 10px 10px 10px, 3px 3px 3px;
11
+ textblock: "This is a \
12
+ multiline block \
13
+ #not { color: #eee;}";
14
+ margin: 4,3,1;
15
+ content: "This is a \
16
+ multiline string.";
17
+ border-radius: -1px -1px -1px black;
18
+ }
19
+
20
+ #subtraction {
21
+ lit: 10 -11;
22
+ lit: 10 - 11;
23
+ lit: 10- 11;
24
+ lit: 10-11;
25
+
26
+ $num: 100;
27
+ var: 10 -$num;
28
+ var: 10 - $num;
29
+ var: 10- $num;
30
+ var: 10-$num;
31
+ }
32
+
33
+
34
+ #special {
35
+ a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12);
36
+ }
37
+
38
+ #unary {
39
+ b: +0.5em;
40
+ c: -foo(12px);
41
+ d: +foo(12px);
42
+ }
43
+
tests/scssc/inputs/variables.scss ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ $color: red, two, three;
3
+
4
+ div {
5
+ height: $color;
6
+ }
7
+
8
+ $a: 1000;
9
+
10
+ div {
11
+ $a: 2000 !default;
12
+ num: $a;
13
+ }
14
+
15
+ div {
16
+ $b: 2000 !default;
17
+ num: $b;
18
+ }
19
+
20
+ $cool_color: null;
21
+ $cool_color: blue !default;
22
+
23
+ pre {
24
+ color: $cool_color;
25
+ }
26
+
27
+ $something_man: 100px;
28
+ cool: $something_man;
29
+
30
+
31
+ del {
32
+ $something: blue;
33
+
34
+ div {
35
+ $something: red;
36
+ pre {
37
+ color: $something;
38
+ }
39
+ }
40
+
41
+ color: $something;
42
+ }
43
+
44
+ $font-family-simple: Arial !default;
45
+ $font-family-spaces: Helvetica Neue !default;
46
+ $font-family-quotes: "Helvetica Neue" !default;
47
+ $font-family-commas: Helvetica, Arial, sans-serif !default;
48
+ $font-family-sans: "Helvetica Neue", Helvetica, Arial, sans-serif !default;
49
+
50
+ body {
51
+ font-family: $font-family-simple;
52
+ font-family: $font-family-spaces;
53
+ font-family: $font-family-quotes;
54
+ font-family: $font-family-commas;
55
+ font-family: $font-family-sans;
56
+ }
tests/scssc/outputs/builtins.css ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #color {
2
+ color: #22ea18;
3
+ red: 34;
4
+ green: 234;
5
+ blue: 24;
6
+ color: rgba(1, 2, 4, 0.5);
7
+ a1: 1;
8
+ a2: 0.5;
9
+ mix: #020304;
10
+ rgba: rgba(170, 119, 204, 0.4);
11
+ rgba: rgba(170, 119, 204, 0.4); }
12
+
13
+ #hsl {
14
+ color: #79c653;
15
+ color: rgba(121, 198, 83, 0.5);
16
+ hue: 100deg;
17
+ sat: 50%;
18
+ lig: 55%; }
19
+
20
+ #more-color {
21
+ light: #7e3d9e;
22
+ dark: #432154;
23
+ sat: #632782;
24
+ desat: #5e3871;
25
+ gray: #545454;
26
+ comp: #48792f;
27
+ inv: #9fd086; }
28
+
29
+ #more-more-color {
30
+ op: 0.5;
31
+ opacify: rgba(1, 2, 3, 0.6);
32
+ opacify: rgba(1, 2, 3, 0.6);
33
+ transparentize: rgba(1, 2, 3, 0.4);
34
+ transparentize: rgba(1, 2, 3, 0.4);
35
+ transparentize: rgba(52, 130, 3, 0.9); }
36
+
37
+ #more-more-more-color {
38
+ color: rgba(65, 110, 79, 0.4);
39
+ color: rgba(20, 255, 216, 0);
40
+ color: rgba(55, 100, 69, 0.4);
41
+ color: rgba(0, 255, 213, 0);
42
+ color: rgba(145, 10, 10, 0);
43
+ color: rgba(5, 10, 10, 0);
44
+ color: rgba(145, 145, 145, 0);
45
+ color: rgba(5, 5, 5, 0);
46
+ color: #000A0A0A;
47
+ color: #FFAABBCC; }
48
+
49
+ #string {
50
+ color: hello what is going on;
51
+ color: "yeah";
52
+ color: "I do?"; }
53
+
54
+ #number {
55
+ color: 250%;
56
+ color: 3;
57
+ color: 3;
58
+ color: 4;
59
+ top: 10px;
60
+ top: 1ex;
61
+ width: 200%;
62
+ bottom: 10px;
63
+ padding: 3em 1in 96px 72pt; }
64
+
65
+ #list {
66
+ len: 3;
67
+ len: 1;
68
+ n: hello;
69
+ hello: one, two, three, hello;
70
+ hello: one, two, three, hello, world, what, is, going;
71
+ hello: one, two, three, hello;
72
+ index: 2;
73
+ index: false;
74
+ index: 3;
75
+ index: 1;
76
+ index: false;
77
+ index: 1;
78
+ index: false;
79
+ index: 2;
80
+ index: 2;
81
+ index: 1;
82
+ world: one, two, three, great, job;
83
+ world: one, two, three, great job;
84
+ cool: one two three great job;
85
+ cool: great job one two three;
86
+ zip: 1px solid, 2px dashed;
87
+ zip: 1px solid red, 2px dashed green; }
88
+
89
+ #introspection {
90
+ t: number;
91
+ t: string;
92
+ t: string;
93
+ t: bool;
94
+ t: color;
95
+ t: color;
96
+ t: list;
97
+ u: "";
98
+ u: "px";
99
+ u: "em";
100
+ l: true;
101
+ l: false;
102
+ c: true;
103
+ c: false;
104
+ c: true;
105
+ c: true;
106
+ c: false;
107
+ c: true; }
108
+
109
+ #if {
110
+ color: yes;
111
+ color: no;
112
+ color: yes;
113
+ color: yes; }
114
+
115
+ .transparent {
116
+ r: 0;
117
+ g: 0;
118
+ b: 0;
119
+ a: 0; }
120
+
121
+ .alpha {
122
+ a: 1;
123
+ a: 1;
124
+ a: 1;
125
+ a: 0.5;
126
+ a: alpha(currentColor); }
tests/scssc/outputs/comments.css ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** what the heck **/
2
+ /**
3
+
4
+ Here is a block comment
5
+
6
+ **/
7
+ /*hello*/
8
+ div {
9
+ /* another property */
10
+ border: 1px solid red;
11
+ color: url('http://mage-page.com');
12
+ string: "hello /* this is not a comment */";
13
+ world: "// neither is this";
14
+ /*what if this is a comment */
15
+ string: 'hello /* this is not a comment */';
16
+ world: '// neither is this';
17
+ what-ever: 100px;
18
+ /*this is not a comment?*/
19
+ background: url(); }
tests/scssc/outputs/compass_extract.css ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #test-0 {
2
+ unit: false;
3
+ unit: true;
4
+ rhythm: 1.5em;
5
+ size: 1;
6
+ size: 1;
7
+ size: 1;
8
+ size: 2;
9
+ size: 2; }
10
+
11
+ #test-1 {
12
+ margin-top: 7.5em;
13
+ padding-top: 9em;
14
+ padding-bottom: 10.5em;
15
+ margin-bottom: 0em; }
16
+
17
+ #test-2 {
18
+ border-style: solid;
19
+ border-width: 0.0625em;
20
+ padding: 1.4375em; }
21
+
22
+ #test-3 {
23
+ border-top-style: solid;
24
+ border-top-width: 0.0625em;
25
+ padding-top: 1.4375em;
26
+ border-bottom-style: solid;
27
+ border-bottom-width: 0.0625em;
28
+ padding-bottom: 1.4375em; }
tests/scssc/outputs/content.css ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ * html #logo {
2
+ background-image: url(/logo.gif); }
3
+
4
+ .colors {
5
+ background-color: blue;
6
+ color: white;
7
+ border-color: blue; }
8
+
9
+ @media only screen and (max-width: 480px) {
10
+ body {
11
+ color: red; } }
12
+
13
+ #sidebar {
14
+ width: 300px; }
15
+ @media only screen and (max-width: 480px) {
16
+ #sidebar {
17
+ width: 100px; } }
18
+
19
+ @media only screen and (min-width: 40em) {
20
+ .grid-1 {
21
+ width: 100%; }
22
+ .grid-2 {
23
+ width: 100%; } }
24
+
25
+ @media only screen and (min-width: 40em) {
26
+ .grid-1 {
27
+ width: 100%; }
28
+ .grid-2 {
29
+ width: 100%; } }
tests/scssc/outputs/content_with_function.css ADDED
@@ -0,0 +1,2 @@
 
 
1
+ body {
2
+ padding: 1 px; }
tests/scssc/outputs/default_args.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ div {
2
+ height: red;
3
+ margin: 100px; }
tests/scssc/outputs/directives.css ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @charset "hello-world";
2
+ @page :left {
3
+ div {
4
+ color: red; } }
5
+
6
+ @page test {
7
+ @media yes {
8
+ div {
9
+ color: red; } } }
10
+
11
+ @media something {
12
+ @page {
13
+ @media else {
14
+ div {
15
+ height: 200px; } } } }
16
+
17
+ div {
18
+ color: red; }
19
+ @page yeah {
20
+ div pre {
21
+ height: 20px; } }
22
+
23
+ @font-face {
24
+ color: red;
25
+ height: 20px; }
26
+
27
+ @keyframes 'bounce' {
28
+ from {
29
+ top: 100px;
30
+ animation-timing-function: ease-out; }
31
+
32
+ 25% {
33
+ top: 50px;
34
+ animation-timing-function: ease-in; }
35
+
36
+ 50% {
37
+ top: 100px;
38
+ animation-timing-function: ease-out; }
39
+
40
+ 75% {
41
+ top: 75px;
42
+ animation-timing-function: ease-in; }
43
+
44
+ to {
45
+ top: 100px; } }
46
+
47
+ @-webkit-keyframes flowouttoleft {
48
+ 0% {
49
+ -webkit-transform: translateX(0) scale(1); }
50
+
51
+ 60%, 70% {
52
+ -webkit-transform: translateX(0) scale(0.7); }
53
+
54
+ 100% {
55
+ -webkit-transform: translateX(-100%) scale(0.7); } }
56
+
57
+ div {
58
+ animation-name: 'diagonal-slide';
59
+ animation-duration: 5s;
60
+ animation-iteration-count: 10; }
61
+
62
+ @keyframes 'diagonal-slide' {
63
+ from {
64
+ left: 0;
65
+ top: 0; }
66
+
67
+ to {
68
+ left: 100px;
69
+ top: 100px; } }
70
+
71
+ @document url(http://www.w3.org/),
72
+ url-prefix(http://www.w3.org/Style/),
73
+ domain(mozilla.org),
74
+ regexp("https:.*") {
75
+ body {
76
+ color: purple;
77
+ background: yellow; } }
tests/scssc/outputs/extends.css ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ error, pre seriousError, span seriousError, other, hello {
2
+ border: 1px #f00;
3
+ background-color: #fdd; }
4
+
5
+ pre seriousError, span seriousError {
6
+ font-size: 20px; }
7
+
8
+ hello {
9
+ color: green; }
10
+ hello div {
11
+ margin: 10px; }
12
+
13
+ .cool, .me {
14
+ color: red; }
15
+
16
+ .blue, .me {
17
+ color: purple; }
18
+
19
+ a:hover, .hoverlink, #demo .overview .fakelink:hover {
20
+ text-decoration: underline; }
21
+
22
+ div.hello.world.hmm, pre div.okay.span.world.hmm, pre #butt .umm div.sure.span.world.hmm, #butt .umm pre div.sure.span.world.hmm, code div.okay.span.world.hmm, code #butt .umm div.sure.span.world.hmm, #butt .umm code div.sure.span.world.hmm {
23
+ color: blue; }
24
+
25
+ .xxxxx .xxxxx .xxxxx, code .xxxxx .xxxxx, code code .xxxxx, code code code, code .xxxxx code, .xxxxx code .xxxxx, .xxxxx code code, .xxxxx .xxxxx code {
26
+ color: green; }
27
+
28
+ code {
29
+ color: red; }
30
+
31
+ .alpha, .beta, .gama {
32
+ color: red; }
33
+
34
+ .beta, .gama {
35
+ color: white; }
36
+
37
+ .gama {
38
+ color: blue; }
39
+
40
+ #admin .tabbar a, #admin .tabbar #demo .overview .fakelink, #demo .overview #admin .tabbar .fakelink {
41
+ font-weight: bold; }
42
+
43
+ a1 b1 c1 d1, x1 y1 z1 w1 b1 c1 d1 {
44
+ color: red; }
45
+
46
+ a2 b2 c2 d2, a2 x2 y2 z2 w2 c2 d2, x2 y2 z2 a2 w2 c2 d2 {
47
+ color: red; }
48
+
49
+ a3 b3 c3 d3, a3 b3 x3 y3 z3 w3 d3, x3 y3 z3 a3 b3 w3 d3 {
50
+ color: red; }
51
+
52
+ a4 b4 c4 d4, a4 b4 c4 x4 y4 z4 w4, x4 y4 z4 a4 b4 c4 w4 {
53
+ color: red; }
54
+
55
+ #butt .yeah .okay, #butt .yeah .umm .sure, #butt .umm .yeah .sure {
56
+ font-weight: bold; }
57
+
58
+ a9 b9 s9 t9 v9, a9 b9 s9 t9 x9 y9 z9, a9 b9 x9 y9 s9 t9 z9 {
59
+ color: red; }
60
+
61
+ @media print {
62
+ horse, man {
63
+ color: blue; } }
64
+
65
+ man {
66
+ color: red; }
67
+
68
+ wassup {
69
+ color: blue; }
70
+
71
+ .foo .wassup {
72
+ color: blue; }
73
+
74
+ #something, .x, .y {
75
+ color: red; }
76
+
77
+ .nav-justified, .nav-tabs.nav-justified {
78
+ text-align: justify; }
79
+
80
+ .btn:hover, .edit .actions button:hover, .edit .new .actions button:hover, .btn:active, .edit .actions button:active, .edit .new .actions button:active, .btn.active, .edit .actions button.active, .edit .new .actions button.active, .btn.disabled, .edit .actions button.disabled, .edit .new .actions button.disabled, .btn[disabled], .edit .actions button[disabled], .edit .new .actions button[disabled] {
81
+ color: red; }
82
+
83
+ .edit .actions button {
84
+ float: right; }
85
+
86
+ .edit .new .actions {
87
+ padding: 0; }
tests/scssc/outputs/filter_effects.css ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #number {
2
+ -webkit-filter: grayscale(1) sepia(0.5) saturate(0.1) invert(1) opacity(0.5) brightness(0.5) contrast(0.5); }
3
+
4
+ #percentage {
5
+ -webkit-filter: grayscale(100%) sepia(50%) saturate(10%) invert(100%) opacity(50%) brightness(50%) contrast(50%); }
6
+
7
+ #misc {
8
+ -webkit-filter: hue-rotate(90deg) blur(10px) drop-shadow(10px -16px 30px purple); }
9
+
10
+ #decimal {
11
+ opacity: 0.5;
12
+ filter: alpha(opacity=50, style=1); }
13
+
14
+ #percent {
15
+ opacity: 0.5;
16
+ filter: alpha(opacity=50); }
17
+
18
+ .row {
19
+ background-color: #071c23;
20
+ color: #2284a1; }
tests/scssc/outputs/functions.css ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ div {
2
+ color: 14px;
3
+ sum: 23; }
4
+
5
+ div {
6
+ hello: 10 55;
7
+ hello: 1010 55;
8
+ hello: "hello 10 and 55"; }
9
+
10
+ del {
11
+ color: 1000; }
12
+
13
+ div {
14
+ hello: "hello foo and bar";
15
+ hello: "hello bar and default";
16
+ hello: "hello Alice, Bob, Tom"; }
17
+
18
+ .foo {
19
+ test2: -moz-art; }
20
+
21
+ div span {
22
+ height: 3px; }
tests/scssc/outputs/ie7.css ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ #foo:before {
2
+ content: counter(item,".") ": "; }
3
+
4
+ #bar:before {
5
+ content: counter(item,"."); }
6
+
7
+ #fu:before {
8
+ content: counter(item); }
tests/scssc/outputs/if.css ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ div {
2
+ color: blue; }
3
+
4
+ pre {
5
+ val-1: "red";
6
+ val-2: "blue";
7
+ val-3: "blue";
8
+ val-4: "red";
9
+ val-5: "red"; }
10
+
11
+ span {
12
+ color: blue;
13
+ height: 10px;
14
+ width: 20px; }
15
+
16
+ div {
17
+ color: blue;
18
+ border-color: green; }
19
+
20
+ del {
21
+ thing: no; }
tests/scssc/outputs/if_on_null.css ADDED
@@ -0,0 +1,2 @@
 
 
1
+ body {
2
+ background-color: "red"; }
tests/scssc/outputs/import.css ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import "foo.css";
2
+ @import "foo" screen;
3
+ @import "http://foo.com/bar";
4
+ @import url(foo);
5
+ div {
6
+ height: 200px;
7
+ color: red; }
8
+
9
+ pre {
10
+ color: red; }
11
+ pre div {
12
+ height: 200px;
13
+ color: red; }
14
+
15
+ code div {
16
+ height: 200px;
17
+ color: red; }
18
+ code div {
19
+ height: 200px;
20
+ color: red; }
21
+
22
+ #partial {
23
+ color: blue; }
24
+
25
+ body {
26
+ color: #7c2;
27
+ background: gray; }
tests/scssc/outputs/interpolation.css ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ div {
2
+ color: redwhite blue;
3
+ color: red white blue;
4
+ color: red whiteblue;
5
+ color: redwhiteblue;
6
+ color: ummyeahwhat;
7
+ color: stacked;
8
+ font-size: 10px/something;
9
+ font-size: 10px / something;
10
+ test: "whatworldwrong";
11
+ test: "whatworldwrong";
12
+ test: "whatworldwrong";
13
+ test: "what"world"wrong";
14
+ hi: "what is 16 end"; }
15
+
16
+ pre var {
17
+ color: red; }
18
+ pre var dad {
19
+ color: red; }
20
+ pre bedvardad {
21
+ color: red; }
22
+
23
+ cool .thing-1 {
24
+ color: red; }
25
+ cool .thing-2 {
26
+ color: red; }
27
+ cool .thing-3 {
28
+ color: red; }
29
+ cool .thing-4 {
30
+ color: red; }
31
+ cool .thing-5 {
32
+ color: red; }
33
+
34
+ abcde {
35
+ color: red; }
36
+
37
+ #hello, .world {
38
+ color: red; }
39
+
40
+ #abchelloyeah, .coolworldyes {
41
+ color: red; }
42
+
43
+ div.element:nth-child(2n) {
44
+ display: none; }
45
+
46
+ div {
47
+ hello: world;
48
+ coolhello: world;
49
+ helloone: world;
50
+ twohelloone: world;
51
+ oneabtwo: cool;
52
+ hello-world: red;
53
+ hello-mold: white;
54
+ hello-hello: blue; }
tests/scssc/outputs/keyword_args.css ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ pre {
2
+ out: alpha fort three palace; }
3
+
4
+ div {
5
+ hello: 5;
6
+ world: -5; }
tests/scssc/outputs/list.css ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ div {
2
+ padding: 10px 20px 30px 40px;
3
+ margin: 0 10px 10px 10px;
4
+ background: linear-gradient(black, white); }
5
+
6
+ p {
7
+ background: linear-gradient(red, blue); }
tests/scssc/outputs/looping.css ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ div {
2
+ color: what;
3
+ color: is;
4
+ color: this;
5
+ font: what;
6
+ font: is;
7
+ font: this;
8
+ background: what;
9
+ background: is;
10
+ background: this;
11
+ border: what;
12
+ border: is;
13
+ border: this; }
14
+
15
+ span {
16
+ color: 0;
17
+ color: 1;
18
+ color: 2;
19
+ color: 3;
20
+ color: 4;
21
+ color: 5;
22
+ color: 6;
23
+ color: 7;
24
+ color: 8;
25
+ color: 9;
26
+ color: 10; }
27
+
28
+ pre {
29
+ color: 1;
30
+ color: 2;
31
+ color: 3;
32
+ color: 4;
33
+ height: 1;
34
+ height: 2;
35
+ height: 3;
36
+ height: 4;
37
+ height: 5;
38
+ cool: 10;
39
+ cool: 9;
40
+ cool: 8;
41
+ cool: 7;
42
+ cool: 6;
43
+ cool: 5;
44
+ cool: 4;
45
+ cool: 3; }
tests/scssc/outputs/media.css ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @media {
2
+ div {
3
+ color: blue; } }
4
+
5
+ @media what {
6
+ div {
7
+ color: blue; } }
8
+
9
+ @media (cool) {
10
+ div {
11
+ color: blue; } }
12
+
13
+ @media (cool: blue) {
14
+ div {
15
+ color: blue; } }
16
+
17
+ @media hello and (world) and (butt: man) {
18
+ div {
19
+ color: blue; } }
20
+
21
+ @media (max-width: 940px) {
22
+ color: red; }
23
+
24
+ @media not hello and (world) {
25
+ color: blue;
26
+ pre {
27
+ color: blue; } }
28
+ @media butt and (world) {
29
+ color: red;
30
+ div {
31
+ color: red; } }
32
+
33
+ div {
34
+ color: blue; }
35
+ @media screen and (-webkit-min-device-pixel-ratio: 1.5) {
36
+ div .sidebar {
37
+ width: 500px; } }
38
+
39
+ div {
40
+ position: absolute; }
41
+ @media screen {
42
+ div {
43
+ top: 0;
44
+ bottom: 8em;
45
+ color: red; }
46
+ div p {
47
+ margin: 5px; }
48
+
49
+ div .success {
50
+ color: green; } }
51
+
52
+ .button {
53
+ width: 300px;
54
+ height: 100px;
55
+ background: #eee; }
56
+ .button :hover {
57
+ background: #aaa; }
58
+ @media only screen and (max-width: 300px) {
59
+ .button {
60
+ width: 100px;
61
+ height: 100px; } }
62
+
63
+ code {
64
+ position: absolute; }
65
+ @media screen {
66
+ code {
67
+ height: 10px; }
68
+ code pre {
69
+ height: 20px; } }
70
+
71
+ @media screen and (color: blue) {
72
+ dt {
73
+ height: 10px; } }
74
+
75
+ @media screen {
76
+ .screen {
77
+ width: 12px; } }
78
+ @media only screen {
79
+ .only-screen {
80
+ height: 11px; } }
81
+
82
+ @media only screen {
83
+ .only-screen {
84
+ width: 14px; } }
85
+ @media only screen {
86
+ .only-screen {
87
+ height: 16px; } }
88
+
89
+ @media print {
90
+ .only-print {
91
+ height: 12px; } }
92
+
93
+ @media screen {
94
+ .only-print {
95
+ height: 12px; } }
96
+
97
+ @media not screen {
98
+ .not-screen {
99
+ height: 15px; } }
100
+
101
+ @media only screen and (color: blue) and (width: 13) {
102
+ .only-screen {
103
+ height: 15px; } }
tests/scssc/outputs/mixins.css ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ div {
2
+ color: blue;
3
+ color: red; }
4
+ div pre {
5
+ height: 200px; }
6
+
7
+ span {
8
+ color: blue; }
9
+ span div {
10
+ height: 20px; }
11
+
12
+ html {
13
+ height: 43px; }
14
+
15
+ del {
16
+ height: 20px; }
17
+
18
+ div {
19
+ color: white;
20
+ color: blue;
21
+ color: white; }
22
+
23
+ div {
24
+ background-image: linear-gradient(left top, red, green); }
25
+
26
+ div {
27
+ -moz-box-shadow: 10px 10px 5px #888;
28
+ -webkit-box-shadow: 10px 10px 5px #888;
29
+ box-shadow: 10px 10px 5px #888;
30
+ -moz-box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4;
31
+ -webkit-box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4;
32
+ box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4; }
33
+
34
+ div p {
35
+ color: red;
36
+ color: blue; }
37
+ div p .class {
38
+ color: red; }
39
+ div p .class div {
40
+ height: 20px; }
41
+ div p div {
42
+ height: 20px; }
43
+ div p .top {
44
+ top: 0; }
45
+ div p .top div {
46
+ color: red; }
47
+
48
+ div.mixin-content-simple {
49
+ color: red; }
50
+
51
+ div.mixin-content-with-arg {
52
+ background: blue;
53
+ color: red; }
54
+
55
+ div.mixin-content-with-arg {
56
+ background: purple;
57
+ height: 20px; }
58
+
59
+ div.mixin-content-simple {
60
+ height: 43px; }
61
+
62
+ div.mixin-content-simple {
63
+ color: orange; }
64
+ div.mixin-content-simple div {
65
+ height: 20px; }
66
+
67
+ div.mixin-content-with-arg {
68
+ background: purple;
69
+ height: 43px; }
70
+
71
+ div.mixin-content-with-arg {
72
+ background: purple;
73
+ color: orange; }
74
+ div.mixin-content-with-arg div {
75
+ height: 20px; }
76
+
77
+ #please-wait {
78
+ background: url(/images/logo.png);
79
+ position: absolute;
80
+ top: 1em;
81
+ right: 0;
82
+ bottom: 3em;
83
+ left: 4em; }
tests/scssc/outputs/nesting.css ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ div: blue;
2
+ body {
3
+ color: red; }
4
+
5
+ div {
6
+ color: red;
7
+ height: yes; }
8
+ div pre {
9
+ color: blue; }
10
+
11
+ div {
12
+ font: 10px hello world;
13
+ font-size: 10px;
14
+ font-color: blue;
15
+ border-left: 1px solid blue;
16
+ border-right: 2px dashed green; }
17
+
18
+ #nested-nesting {
19
+ bar: baz;
20
+ bang-bop: bar;
21
+ bang-bip: 1px;
22
+ bang-blat-baf: bort; }
tests/scssc/outputs/null.css ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .div {
2
+ one: null;
3
+ one: world;
4
+ one: NULL world;
5
+ one: a, b;
6
+ two: a, b; }
7
+
8
+ p:before {
9
+ content: "I ate pies!"; }
10
+
11
+ .foo {
12
+ -webkit-border-radius: 10;
13
+ border-radius: 10; }
14
+
15
+ .fu {
16
+ -webkit-border-radius: 20;
17
+ border-radius: 20; }
18
+
19
+ .bar {
20
+ -webkit-border-top-left-radius: 30;
21
+ border-top-left-radius: 30; }
tests/scssc/outputs/operators.css ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ color: 8;
3
+ color: 16;
4
+ height: 10px/10px;
5
+ color: 6px;
6
+ color: 5px;
7
+ bottom: 2px;
8
+ top: 1.5em;
9
+ left: -1cm;
10
+ top: 6.29921; }
11
+
12
+ div {
13
+ color: false;
14
+ color: true;
15
+ color: true;
16
+ color: false;
17
+ color: what > 3; }
18
+
19
+ #units {
20
+ test: 2.5748in;
21
+ test: 13mm;
22
+ test: 4em;
23
+ test: 11mm;
24
+ test: 1.1cm; }
25
+
26
+ #modulo {
27
+ test: 1;
28
+ test: 1cm; }
29
+
30
+ #colors {
31
+ color: #ff0203;
32
+ color: #fe0000;
33
+ color: rgba(3, 8, 15, 0.5);
34
+ color: rgba(5, 8, 10, 0.5);
35
+ color: rgba(2, 4, 6, 0.5);
36
+ color: rgba(1, 1, 2, 0.5);
37
+ color: rgba(3, 4, 5, 0.5);
38
+ color: rgba(0, 0, 1, 0.5);
39
+ color: #22f;
40
+ color: false;
41
+ color: true;
42
+ color: true;
43
+ color: false; }
44
+
45
+ #preserve {
46
+ hello: what -going;
47
+ hello: what - going; }
48
+
49
+ #strings {
50
+ hello: what -going;
51
+ hello: whatgoing;
52
+ hello: whatgoing;
53
+ hello: whatgoing;
54
+ hello: whatgoing;
55
+ hello: "whatgoing";
56
+ hello: goingwhat;
57
+ hello: "whatwhat"; }
58
+
59
+ #negation {
60
+ a: -60;
61
+ b: 10 -100;
62
+ b: -90; }
63
+
64
+ #bools-fail {
65
+ and: false and two;
66
+ and: one and two;
67
+ and: one and false;
68
+ or: false or two;
69
+ or: one or two;
70
+ or: one or false; }
71
+
72
+ #bools {
73
+ and: false;
74
+ and: two;
75
+ and: false;
76
+ or: two;
77
+ or: one;
78
+ or: one; }
79
+
80
+ #nots-fail {
81
+ not: false2;
82
+ not: not false;
83
+ not: not 0;
84
+ not: not 1;
85
+ not: not "";
86
+ not: not hello; }
87
+
88
+ #nots {
89
+ not: false2;
90
+ not: true;
91
+ not: false;
92
+ not: false;
93
+ not: false;
94
+ not: false; }
95
+
96
+ #string-test {
97
+ str: true;
98
+ str: false;
99
+ str: true;
100
+ str: true;
101
+ str: xhellohellofalse;
102
+ str: true; }
103
+
104
+ #special {
105
+ cancel-unit: 1; }
tests/scssc/outputs/placeholder_selector.css ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ p a.notice span, p a.error span, #context a.notice span, #context a.error span {
2
+ color: blue;
3
+ font-weight: bold;
4
+ font-size: 2em; }
5
+
6
+ p {
7
+ padding: 2em; }
tests/scssc/outputs/scss_css.css ADDED
@@ -0,0 +1,741 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import "foo.css";
2
+ @import 'foo.css';
3
+ @import url("foo.css");
4
+ @import url('foo.css');
5
+ @import url(foo.css);
6
+ @import "foo.css" screen;
7
+ @import "foo.css" screen, print;
8
+ /* Foo
9
+ * Bar */
10
+ /* Baz
11
+ * Bang */
12
+ @charset "UTF-8";
13
+ [foo~=bar] {
14
+ a: b; }
15
+
16
+ [foo^=bar] {
17
+ a: b; }
18
+
19
+ [foo$=bar] {
20
+ a: b; }
21
+
22
+ [foo*=bar] {
23
+ a: b; }
24
+
25
+ [foo|=en] {
26
+ a: b; }
27
+
28
+ foo {
29
+ a: 2;
30
+ b: 2.3em;
31
+ c: 50%;
32
+ d: "fraz bran";
33
+ e: flanny-blanny-blan;
34
+ f: url(http://sass-lang.com);
35
+ h: #abc; }
36
+
37
+ selector {
38
+ property: value;
39
+ property2: value; }
40
+
41
+ sel {
42
+ p: v; }
43
+
44
+ .foo {
45
+ a: b; }
46
+
47
+ .foo {
48
+ a: b; }
49
+
50
+ .foo {
51
+ a: b; }
52
+
53
+ .foo {
54
+ a: b; }
55
+
56
+ @foo {
57
+ a: b;
58
+ rule {
59
+ a: b; } }
60
+
61
+ @foo {
62
+ a: b; }
63
+
64
+ @bar {
65
+ a: b; }
66
+
67
+ @foo "bar"
68
+
69
+ foo {
70
+ a: 12px calc(100%/3 - 2*1em - 2*1px);
71
+ b: 12px -moz-calc(100%/3 - 2*1em - 2*1px);
72
+ b: 12px -webkit-calc(100%/3 - 2*1em - 2*1px);
73
+ b: 12px -foobar-calc(100%/3 - 2*1em - 2*1px); }
74
+
75
+ foo {
76
+ bar: baz; }
77
+
78
+ bar {
79
+ bar: baz; }
80
+
81
+ baz {
82
+ bar: baz;
83
+ /*
84
+ * foo
85
+ */ }
86
+
87
+ bar {
88
+ baz: bang; }
89
+
90
+ E, F {
91
+ a: b; }
92
+
93
+ E F, G H {
94
+ a: b; }
95
+
96
+ E > F, G > H {
97
+ a: b;
98
+ /* This is a CSS comment. */ }
99
+
100
+ .one {
101
+ color: green;
102
+ /* Another comment */
103
+ /* The following should not be used:
104
+ .two {color: red;} */ }
105
+
106
+ .three {
107
+ /* color: red; */
108
+ color: green;
109
+ /**
110
+ .four {color: red;} */ }
111
+
112
+ .five {
113
+ color: green;
114
+ /**/ }
115
+
116
+ .six {
117
+ color: green;
118
+ /*********/ }
119
+
120
+ .seven {
121
+ color: green;
122
+ /* a comment **/ }
123
+
124
+ .eight {
125
+ color: green; }
126
+
127
+ foo {
128
+ a: \foo bar;
129
+ b: foo\ bar;
130
+ c: \2022 \0020;
131
+ d: foo\\bar;
132
+ e: foo\"\'bar; }
133
+
134
+ foo {
135
+ a: "\foo bar";
136
+ b: "foo\ bar";
137
+ c: "\2022 \0020";
138
+ d: "foo\\bar";
139
+ e: "foo\"'bar"; }
140
+
141
+ foo {
142
+ _name: val;
143
+ *name: val;
144
+ :name: val;
145
+ .name: val;
146
+ #name: val;
147
+ name/**/: val;
148
+ name/*\**/: val;
149
+ name: val; }
150
+
151
+ @foo "bar" ;
152
+
153
+ foo {
154
+ a: -moz-element(#foo);
155
+ b: -webkit-element(#foo);
156
+ b: -foobar-element(#foo); }
157
+
158
+ @foo ;
159
+
160
+ foo {
161
+ bar: baz; }
162
+
163
+ 0% {
164
+ a: b; }
165
+
166
+ 60% {
167
+ a: b; }
168
+
169
+ 100% {
170
+ a: b; }
171
+
172
+ 12px {
173
+ a: b; }
174
+
175
+ "foo" {
176
+ a: b; }
177
+
178
+ foo {
179
+ a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); }
180
+
181
+ :foo("bar") {
182
+ a: b; }
183
+
184
+ :foo(bar) {
185
+ a: b; }
186
+
187
+ :foo(12px) {
188
+ a: b; }
189
+
190
+ :foo(+) {
191
+ a: b; }
192
+
193
+ :foo(-) {
194
+ a: b; }
195
+
196
+ :foo(+"bar") {
197
+ a: b; }
198
+
199
+ :foo(-++--baz-"bar"12px) {
200
+ a: b; }
201
+
202
+ foo {
203
+ a: foo-bar(12);
204
+ b: -foo-bar-baz(13, 14 15); }
205
+
206
+ @import "foo.css" screen, print and (foo: 0);
207
+
208
+ @import "foo.css" screen, only print, screen and (foo: 0);
209
+
210
+ foo {
211
+ a: foo !important;
212
+ b: foo bar !important;
213
+ b: foo, bar !important; }
214
+
215
+ foo {
216
+ a: -moz-bar-baz;
217
+ b: foo -o-bar-baz; }
218
+
219
+ foo {
220
+ /* b; c: */
221
+ a: d; }
222
+
223
+ foo {
224
+ /*: b; c */
225
+ a : d;
226
+ /* Foo
227
+ * Bar */ }
228
+
229
+ [foo] {
230
+ a: b; }
231
+
232
+ [foo="bar"] {
233
+ a: b; }
234
+
235
+ [foo~="bar"] {
236
+ a: b; }
237
+
238
+ [foo^="bar"] {
239
+ a: b; }
240
+
241
+ [foo$="bar"] {
242
+ a: b; }
243
+
244
+ [foo*="bar"] {
245
+ a: b; }
246
+
247
+ [foo|="en"] {
248
+ a: b; }
249
+
250
+ :root {
251
+ a: b; }
252
+
253
+ :nth-child(n) {
254
+ a: b; }
255
+
256
+ :nth-last-child(n) {
257
+ a: b; }
258
+
259
+ :nth-of-type(n) {
260
+ a: b; }
261
+
262
+ :nth-last-of-type(n) {
263
+ a: b; }
264
+
265
+ :first-child {
266
+ a: b; }
267
+
268
+ :last-child {
269
+ a: b; }
270
+
271
+ :first-of-type {
272
+ a: b; }
273
+
274
+ :last-of-type {
275
+ a: b; }
276
+
277
+ :only-child {
278
+ a: b; }
279
+
280
+ :only-of-type {
281
+ a: b; }
282
+
283
+ :empty {
284
+ a: b; }
285
+
286
+ :link {
287
+ a: b; }
288
+
289
+ :visited {
290
+ a: b; }
291
+
292
+ :active {
293
+ a: b; }
294
+
295
+ :hover {
296
+ a: b; }
297
+
298
+ :focus {
299
+ a: b; }
300
+
301
+ :target {
302
+ a: b; }
303
+
304
+ :lang(fr) {
305
+ a: b; }
306
+
307
+ :enabled {
308
+ a: b; }
309
+
310
+ :disabled {
311
+ a: b; }
312
+
313
+ :checked {
314
+ a: b; }
315
+
316
+ ::first-line {
317
+ a: b; }
318
+
319
+ ::first-letter {
320
+ a: b; }
321
+
322
+ ::before {
323
+ a: b; }
324
+
325
+ ::after {
326
+ a: b; }
327
+
328
+ .warning {
329
+ a: b; }
330
+
331
+ #myid {
332
+ a: b; }
333
+
334
+ :not(s) {
335
+ a: b; }
336
+
337
+ @media all {
338
+ rule1 {
339
+ prop: val; }
340
+
341
+ rule2 {
342
+ prop: val; } }
343
+
344
+ @media screen, print {
345
+ rule1 {
346
+ prop: val; }
347
+
348
+ rule2 {
349
+ prop: val; } }
350
+
351
+ @media screen and (-webkit-min-device-pixel-ratio: 0) {
352
+ a: b; }
353
+
354
+ @media only screen, print and (foo: 0px) and (bar: flam(12px solid)) {
355
+ a: b; }
356
+
357
+ :-moz-any(h1, h2, h3) {
358
+ a: b; }
359
+
360
+ :-moz-any(.foo) {
361
+ a: b; }
362
+
363
+ :-moz-any(foo bar, .baz > .bang) {
364
+ a: b; }
365
+
366
+ @-moz-document url(http://www.w3.org/),
367
+ url-prefix(http://www.w3.org/Style/),
368
+ domain(mozilla.org),
369
+ regexp("^https:.*") {
370
+ .foo {
371
+ a: b; } }
372
+
373
+ foo {
374
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000);
375
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); }
376
+
377
+ foo {
378
+ filter: alpha(opacity=20);
379
+ filter: alpha(opacity=20, enabled=true);
380
+ filter: blaznicate(foo=bar, baz=bang bip, bart=#fa4600); }
381
+
382
+ @foo bar {
383
+ a: b; }
384
+
385
+ @bar baz {
386
+ c: d; }
387
+
388
+ @namespace "http://www.w3.org/Profiles/xhtml1-strict";
389
+
390
+ @namespace url(http://www.w3.org/Profiles/xhtml1-strict);
391
+
392
+ @namespace html url("http://www.w3.org/Profiles/xhtml1-strict");
393
+
394
+ [foo|bar=baz] {
395
+ a: b; }
396
+
397
+ [*|bar=baz] {
398
+ a: b; }
399
+
400
+ [foo|bar|=baz] {
401
+ a: b; }
402
+
403
+ foo|E {
404
+ a: b; }
405
+
406
+ *|E {
407
+ a: b; }
408
+
409
+ foo|* {
410
+ a: b; }
411
+
412
+ *|* {
413
+ a: b; }
414
+
415
+ :not(foo|bar) {
416
+ a: b; }
417
+
418
+ :not(*|bar) {
419
+ a: b; }
420
+
421
+ :not(foo|*) {
422
+ a: b; }
423
+
424
+ :not(*|*) {
425
+ a: b; }
426
+
427
+ :not(#blah) {
428
+ a: b; }
429
+
430
+ :not(.blah) {
431
+ a: b; }
432
+
433
+ :not([foo]) {
434
+ a: b; }
435
+
436
+ :not([foo^="bar"]) {
437
+ a: b; }
438
+
439
+ :not([baz|foo~="bar"]) {
440
+ a: b; }
441
+
442
+ :not(:hover) {
443
+ a: b; }
444
+
445
+ :not(:nth-child(2n + 3)) {
446
+ a: b; }
447
+
448
+ :not(:not(#foo)) {
449
+ a: b; }
450
+
451
+ :not(a#foo.bar) {
452
+ a: b; }
453
+
454
+ :not(#foo .bar > baz) {
455
+ a: b; }
456
+
457
+ :not(h1, h2, h3) {
458
+ a: b; }
459
+
460
+ foo {
461
+ a: "bang 1 bar bip"; }
462
+
463
+ :nth-child(-n) {
464
+ a: b; }
465
+
466
+ :nth-child(+n) {
467
+ a: b; }
468
+
469
+ :nth-child(even) {
470
+ a: b; }
471
+
472
+ :nth-child(odd) {
473
+ a: b; }
474
+
475
+ :nth-child(50) {
476
+ a: b; }
477
+
478
+ :nth-child(-50) {
479
+ a: b; }
480
+
481
+ :nth-child(+50) {
482
+ a: b; }
483
+
484
+ :nth-child(2n+3) {
485
+ a: b; }
486
+
487
+ :nth-child(2n-3) {
488
+ a: b; }
489
+
490
+ :nth-child(+2n-3) {
491
+ a: b; }
492
+
493
+ :nth-child(-2n+3) {
494
+ a: b; }
495
+
496
+ :nth-child(-2n+ 3) {
497
+ a: b; }
498
+
499
+ :nth-child( 2n + 3) {
500
+ a: b; }
501
+
502
+ foo {
503
+ a: foo bar baz;
504
+ b: foo, #abc, -12;
505
+ c: 1px/2px/-3px;
506
+ d: foo bar, baz/bang; }
507
+
508
+ @page {
509
+ prop1: val;
510
+ prop2: val; }
511
+
512
+ @page flap {
513
+ prop1: val;
514
+ prop2: val; }
515
+
516
+ @page :first {
517
+ prop1: val;
518
+ prop2: val; }
519
+
520
+ @page flap:first {
521
+ prop1: val;
522
+ prop2: val; }
523
+
524
+ .foo {
525
+ a: b; }
526
+
527
+ .foo {
528
+ a: b;
529
+ /* Foo */ }
530
+
531
+ .foo {
532
+ a: b;
533
+ /* Foo
534
+ * Bar */ }
535
+
536
+ .foo {
537
+ a: b; }
538
+
539
+ .foo #bar:baz(/* bang )*/ bip) {
540
+ a: b; }
541
+
542
+ > E {
543
+ a: b; }
544
+
545
+ + E {
546
+ a: b; }
547
+
548
+ ~ E {
549
+ a: b; }
550
+
551
+ > > E {
552
+ a: b; }
553
+
554
+ >> E {
555
+ a: b; }
556
+
557
+ E* {
558
+ a: b; }
559
+
560
+ E*.foo {
561
+ a: b; }
562
+
563
+ E*:hover {
564
+ a: b; }
565
+
566
+ E, F {
567
+ a: b; }
568
+
569
+ E F {
570
+ a: b; }
571
+
572
+ E, F G, H {
573
+ a: b; }
574
+
575
+ E > F {
576
+ a: b; }
577
+
578
+ E ~ F {
579
+ a: b; }
580
+
581
+ E + F {
582
+ a: b; }
583
+
584
+ * {
585
+ a: b; }
586
+
587
+ E {
588
+ a: b; }
589
+
590
+ E[foo] {
591
+ a: b; }
592
+
593
+ E[foo="bar"] {
594
+ a: b; }
595
+
596
+ E[foo~="bar"] {
597
+ a: b; }
598
+
599
+ E[foo^="bar"] {
600
+ a: b; }
601
+
602
+ E[foo$="bar"] {
603
+ a: b; }
604
+
605
+ E[foo*="bar"] {
606
+ a: b; }
607
+
608
+ E[foo|="en"] {
609
+ a: b; }
610
+
611
+ E:root {
612
+ a: b; }
613
+
614
+ E:nth-child(n) {
615
+ a: b; }
616
+
617
+ E:nth-last-child(n) {
618
+ a: b; }
619
+
620
+ E:nth-of-type(n) {
621
+ a: b; }
622
+
623
+ E:nth-last-of-type(n) {
624
+ a: b; }
625
+
626
+ E:first-child {
627
+ a: b; }
628
+
629
+ E:last-child {
630
+ a: b; }
631
+
632
+ E:first-of-type {
633
+ a: b; }
634
+
635
+ E:last-of-type {
636
+ a: b; }
637
+
638
+ E:only-child {
639
+ a: b; }
640
+
641
+ E:only-of-type {
642
+ a: b; }
643
+
644
+ E:empty {
645
+ a: b; }
646
+
647
+ E:link {
648
+ a: b; }
649
+
650
+ E:visited {
651
+ a: b; }
652
+
653
+ E:active {
654
+ a: b; }
655
+
656
+ E:hover {
657
+ a: b; }
658
+
659
+ E:focus {
660
+ a: b; }
661
+
662
+ E:target {
663
+ a: b; }
664
+
665
+ E:lang(fr) {
666
+ a: b; }
667
+
668
+ E:enabled {
669
+ a: b; }
670
+
671
+ E:disabled {
672
+ a: b; }
673
+
674
+ E:checked {
675
+ a: b; }
676
+
677
+ E::first-line {
678
+ a: b; }
679
+
680
+ E::first-letter {
681
+ a: b; }
682
+
683
+ E::before {
684
+ a: b; }
685
+
686
+ E::after {
687
+ a: b; }
688
+
689
+ E.warning {
690
+ a: b; }
691
+
692
+ E#myid {
693
+ a: b; }
694
+
695
+ E:not(s) {
696
+ a: b; }
697
+
698
+ E F {
699
+ a: b; }
700
+
701
+ E > F {
702
+ a: b; }
703
+
704
+ E + F {
705
+ a: b; }
706
+
707
+ E ~ F {
708
+ a: b; }
709
+
710
+ @supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
711
+ .foo {
712
+ a: b; } }
713
+
714
+ @-prefix-supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) {
715
+ .foo {
716
+ a: b; } }
717
+
718
+ foo {
719
+ foo: bar;
720
+ #baz: bang;
721
+ #bip: bop; }
722
+
723
+ foo {
724
+ a: -2;
725
+ b: -2.3em;
726
+ c: -50%;
727
+ d: -foo(bar baz); }
728
+
729
+ foo {
730
+ a: -0.5em;
731
+ b: 0.5em;
732
+ c: -foo(12px);
733
+ d: +foo(12px); }
734
+
735
+ foo {
736
+ -moz-foo-bar: blat;
737
+ -o-flat-blang: wibble; }
738
+
739
+ foo {
740
+ a: foo();
741
+ b: bar baz-bang() bip; }
tests/scssc/outputs/selectors.css ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ * {
2
+ color: blue; }
3
+
4
+ E {
5
+ color: blue; }
6
+
7
+ E:not(:link) {
8
+ color: blue; }
9
+
10
+ E:not(:link):not(:visited) {
11
+ color: blue; }
12
+
13
+ E:not(:link, :visited) {
14
+ color: blue; }
15
+
16
+ E:matches(:hover, :focus) {
17
+ color: blue; }
18
+
19
+ E.warning {
20
+ color: blue; }
21
+
22
+ E#id {
23
+ color: blue; }
24
+
25
+ E[foo] {
26
+ color: blue; }
27
+
28
+ E[foo="barbar"] {
29
+ color: blue; }
30
+
31
+ E[foo="barbar" i] {
32
+ color: blue; }
33
+
34
+ E[foo~="hello#$@%@$#^"] {
35
+ color: blue; }
36
+
37
+ E[foo^="color: green;"] {
38
+ color: blue; }
39
+
40
+ E[foo$="239023"] {
41
+ color: blue; }
42
+
43
+ E[foo*="29302"] {
44
+ color: blue; }
45
+
46
+ E[foo|="239032"] {
47
+ color: blue; }
48
+
49
+ [foo] {
50
+ color: blue; }
51
+
52
+ [foo] .helloWorld {
53
+ color: blue; }
54
+
55
+ [foo].helloWorld {
56
+ color: blue; }
57
+
58
+ [foo="barbar"] {
59
+ color: blue; }
60
+
61
+ [foo~="hello#$@%@$#^"] {
62
+ color: blue; }
63
+
64
+ [foo^="color: green;"] {
65
+ color: blue; }
66
+
67
+ [foo$="239023"] {
68
+ color: blue; }
69
+
70
+ [foo*="29302"] {
71
+ color: blue; }
72
+
73
+ [foo|="239032"] {
74
+ color: blue; }
75
+
76
+ E:dir(ltr) {
77
+ color: blue; }
78
+
79
+ E:lang(en) {
80
+ color: blue; }
81
+
82
+ E:lang(en, fr) {
83
+ color: blue; }
84
+
85
+ E:any-link {
86
+ color: blue; }
87
+
88
+ E:link {
89
+ color: blue; }
90
+
91
+ E:visited {
92
+ color: blue; }
93
+
94
+ E:local-link {
95
+ color: blue; }
96
+
97
+ E:local-link(0) {
98
+ color: red; }
99
+
100
+ E:local-link(1) {
101
+ color: white; }
102
+
103
+ E:local-link(2) {
104
+ color: red; }
105
+
106
+ E:target {
107
+ color: blue; }
108
+
109
+ E:scope {
110
+ color: blue; }
111
+
112
+ E:current {
113
+ color: blue; }
114
+
115
+ E:current(:link) {
116
+ color: blue; }
117
+
118
+ E:past {
119
+ color: blue; }
120
+
121
+ E:future {
122
+ color: blue; }
123
+
124
+ E:active {
125
+ color: blue; }
126
+
127
+ E:hover {
128
+ color: blue; }
129
+
130
+ E:focus {
131
+ color: blue; }
132
+
133
+ E:enabled {
134
+ color: blue; }
135
+
136
+ E:disabled {
137
+ color: blue; }
138
+
139
+ E:indeterminate {
140
+ color: blue; }
141
+
142
+ E:default {
143
+ color: blue; }
144
+
145
+ E:in-range {
146
+ color: blue; }
147
+
148
+ E:out-of-range {
149
+ color: blue; }
150
+
151
+ E:required {
152
+ color: blue; }
153
+
154
+ E:optional {
155
+ color: blue; }
156
+
157
+ E:read-only {
158
+ color: blue; }
159
+
160
+ E:read-write {
161
+ color: blue; }
162
+
163
+ E:root {
164
+ color: blue; }
165
+
166
+ E:empty {
167
+ color: blue; }
168
+
169
+ E:first-child {
170
+ color: blue; }
171
+
172
+ E:nth-child(odd) {
173
+ color: blue; }
174
+
175
+ E:nth-child(2n+1) {
176
+ color: blue; }
177
+
178
+ E:nth-child(5) {
179
+ color: blue; }
180
+
181
+ E:last-child {
182
+ color: blue; }
183
+
184
+ E:nth-last-child(-n+2) {
185
+ color: blue; }
186
+
187
+ E:only-child {
188
+ color: blue; }
189
+
190
+ E:first-of-type {
191
+ color: blue; }
192
+
193
+ E:nth-of-type(2n) {
194
+ color: blue; }
195
+
196
+ E:last-of-type {
197
+ color: blue; }
198
+
199
+ E:nth-last-of-type(n) {
200
+ color: blue; }
201
+
202
+ E:only-of-type {
203
+ color: blue; }
204
+
205
+ E:nth-match(odd) {
206
+ color: blue; }
207
+
208
+ E:nth-last-match(odd) {
209
+ color: blue; }
210
+
211
+ E:column(n) {
212
+ color: blue; }
213
+
214
+ E:nth-column(n) {
215
+ color: blue; }
216
+
217
+ E:nth-last-column(n) {
218
+ color: blue; }
219
+
220
+ E F {
221
+ color: blue; }
222
+
223
+ E > F {
224
+ color: blue; }
225
+
226
+ E + F {
227
+ color: blue; }
228
+
229
+ E ~ F {
230
+ color: blue; }
231
+
232
+ E /foo/ F {
233
+ color: blue; }
234
+
235
+ E! > F {
236
+ color: blue; }
237
+
238
+ [foo|att=val] {
239
+ color: blue; }
240
+
241
+ [*|att] {
242
+ color: yellow; }
243
+
244
+ [|att] {
245
+ color: green; }
246
+
247
+ [att] {
248
+ color: green; }
249
+
250
+ E::first-line {
251
+ color: blue; }
252
+
253
+ E::first-letter {
254
+ color: blue; }
255
+
256
+ E::before {
257
+ color: blue; }
258
+
259
+ E::after {
260
+ color: blue; }
261
+
262
+ E::choices {
263
+ color: blue; }
264
+
265
+ E::value {
266
+ color: blue; }
267
+
268
+ E::repeat-index {
269
+ color: blue; }
270
+
271
+ E::repeat-item {
272
+ color: blue; }
273
+
274
+ E:first {
275
+ color: blue; }
276
+
277
+ E:first-line {
278
+ color: blue; }
279
+
280
+ E:first-letter {
281
+ color: blue; }
282
+
283
+ E:before {
284
+ color: blue; }
285
+
286
+ E:after {
287
+ color: blue; }
288
+
289
+ E:checked {
290
+ color: blue; }
291
+
292
+ E:invalid {
293
+ color: blue; }
294
+
295
+ E:valid {
296
+ color: blue; }
297
+
298
+ E:left {
299
+ color: blue; }
300
+
301
+ E:right {
302
+ color: blue; }
303
+
304
+ E:any(ol) {
305
+ color: blue; }
306
+
307
+ E::selection {
308
+ color: blue; }
309
+
310
+ div {
311
+ font: something;
312
+ font-size: 30em; }
313
+ div font:something {
314
+ size: 30em; }
315
+
316
+ .something.world {
317
+ color: blue; }
318
+ .something .mold {
319
+ height: 200px; }
320
+ .dog .something {
321
+ color: blue; }
322
+
323
+ .dad .simple .wolf {
324
+ color: blue; }
325
+ .rad.simple.bad {
326
+ color: blue; }
327
+
328
+ .something div .what.world {
329
+ color: blue; }
330
+
331
+ div.foo div {
332
+ color: blue; }
333
+
334
+ .nice-fonts .main .message div .title, .nice-fonts div .message div .title {
335
+ font-size: 24px; }
tests/scssc/outputs/values.css ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #values {
2
+ color: #eee;
3
+ color: #eee;
4
+ height: 20px;
5
+ width: 80%;
6
+ color: "hello world";
7
+ height: url("http://google.com");
8
+ dads: url(http://leafo.net);
9
+ padding: 10px 10px 10px 10px, 3px 3px 3px;
10
+ textblock: "This is a \
11
+ multiline block \
12
+ #not { color: #eee;}";
13
+ margin: 4, 3, 1;
14
+ content: "This is a \
15
+ multiline string.";
16
+ border-radius: -1px -1px -1px black; }
17
+
18
+ #subtraction {
19
+ lit: 10 -11;
20
+ lit: -1;
21
+ lit: -1;
22
+ lit: -1;
23
+ var: 10 -100;
24
+ var: -90;
25
+ var: -90;
26
+ var: -90; }
27
+
28
+ #special {
29
+ a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); }
30
+
31
+ #unary {
32
+ b: 0.5em;
33
+ c: -foo(12px);
34
+ d: +foo(12px); }
tests/scssc/outputs/variables.css ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cool: 100px;
2
+ div {
3
+ height: red, two, three; }
4
+
5
+ div {
6
+ num: 1000; }
7
+
8
+ div {
9
+ num: 2000; }
10
+
11
+ pre {
12
+ color: blue; }
13
+
14
+ del {
15
+ color: red; }
16
+ del div pre {
17
+ color: red; }
18
+
19
+ body {
20
+ font-family: Arial;
21
+ font-family: Helvetica Neue;
22
+ font-family: "Helvetica Neue";
23
+ font-family: Helvetica, Arial, sans-serif;
24
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; }