WP-SCSS - Version 1.2.4

Version Description

  • Updated scssphp to version 0.7.5
  • Added source map @iannacone
  • Always define $wpscss_compiler in the global scope @jazbek
Download this release

Release Info

Developer connectthink
Plugin Icon wp plugin WP-SCSS
Version 1.2.4
Comparing to
See all releases

Code changes from version 1.2.3 to 1.2.4

class/class-wp-scss.php CHANGED
@@ -1,5 +1,6 @@
1
  <?php
2
 
 
3
  use Leafo\ScssPhp\Compiler;
4
 
5
  class Wp_Scss {
@@ -9,7 +10,7 @@ class Wp_Scss {
9
  * @var string
10
  * @access public
11
  */
12
- public $scss_dir, $css_dir, $compile_method, $scssc, $compile_errors;
13
 
14
  /**
15
  * Set values for Wp_Scss::properties
@@ -22,7 +23,7 @@ class Wp_Scss {
22
  *
23
  * @var array compile_errors - catches errors from compile
24
  */
25
- public function __construct ($scss_dir, $css_dir, $compile_method) {
26
  global $scssc;
27
  $this->scss_dir = $scss_dir;
28
  $this->css_dir = $css_dir;
@@ -31,7 +32,9 @@ class Wp_Scss {
31
  $scssc = new Compiler();
32
 
33
  $scssc->setFormatter( $compile_method );
34
- $scssc->setImportPaths( $scss_dir );
 
 
35
  }
36
 
37
  /**
@@ -60,7 +63,17 @@ class Wp_Scss {
60
 
61
  if (is_writable($cache)) {
62
  try {
63
- $css = $scssc->compile(file_get_contents($in));
 
 
 
 
 
 
 
 
 
 
64
  file_put_contents($cache.basename($out), $css);
65
  } catch (Exception $e) {
66
  $errors = array (
@@ -85,7 +98,7 @@ class Wp_Scss {
85
  array_push($input_files, $file->getFilename());
86
  }
87
  }
88
-
89
  // For each input file, find matching css file and compile
90
  foreach ($input_files as $scss_file) {
91
  $input = $this->scss_dir.$scss_file;
1
  <?php
2
 
3
+ include_once( WPSCSS_PLUGIN_DIR . '/scssphp/scss.inc.php' );
4
  use Leafo\ScssPhp\Compiler;
5
 
6
  class Wp_Scss {
10
  * @var string
11
  * @access public
12
  */
13
+ public $scss_dir, $css_dir, $compile_method, $scssc, $compile_errors, $sourcemaps;
14
 
15
  /**
16
  * Set values for Wp_Scss::properties
23
  *
24
  * @var array compile_errors - catches errors from compile
25
  */
26
+ public function __construct ($scss_dir, $css_dir, $compile_method, $sourcemaps) {
27
  global $scssc;
28
  $this->scss_dir = $scss_dir;
29
  $this->css_dir = $css_dir;
32
  $scssc = new Compiler();
33
 
34
  $scssc->setFormatter( $compile_method );
35
+ $scssc->setImportPaths( $this->scss_dir );
36
+
37
+ $this->sourcemaps = $sourcemaps;
38
  }
39
 
40
  /**
63
 
64
  if (is_writable($cache)) {
65
  try {
66
+ $map = basename($out) . '.map';
67
+ $scssc->setSourceMap(constant('Leafo\ScssPhp\Compiler::' . $instance->sourcemaps));
68
+ $scssc->setSourceMapOptions(array(
69
+ 'sourceMapWriteTo' => $instance->css_dir . $map, // absolute path to a file to write the map to
70
+ 'sourceMapURL' => $map, // url of the map
71
+ 'sourceMapBasepath' => rtrim(ABSPATH, '/'), // base path for filename normalization
72
+ 'sourceRoot' => '/', // This value is prepended to the individual entries in the 'source' field.
73
+ ));
74
+
75
+ $css = $scssc->compile(file_get_contents($in), $in);
76
+
77
  file_put_contents($cache.basename($out), $css);
78
  } catch (Exception $e) {
79
  $errors = array (
98
  array_push($input_files, $file->getFilename());
99
  }
100
  }
101
+
102
  // For each input file, find matching css file and compile
103
  foreach ($input_files as $scss_file) {
104
  $input = $this->scss_dir.$scss_file;
options.php CHANGED
@@ -127,7 +127,25 @@ class Wp_Scss_Settings
127
  )
128
  )
129
  )
130
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
  add_settings_field(
133
  'Error Display', // ID
@@ -145,7 +163,7 @@ class Wp_Scss_Settings
145
  )
146
  )
147
  )
148
- );
149
 
150
  // Enqueuing Options
151
  add_settings_section(
@@ -195,7 +213,7 @@ class Wp_Scss_Settings
195
  print 'Add the paths to your directories below. Paths should start with the root of your theme. example: "/library/scss/"';
196
  }
197
  public function print_compile_info() {
198
- print 'Choose how you would like SCSS to be compiled and how you would like the plugin to handle errors';
199
  }
200
  public function print_enqueue_info() {
201
  print 'WP-SCSS can enqueue your css stylesheets in the header automatically.';
@@ -207,7 +225,7 @@ class Wp_Scss_Settings
207
  public function input_text_callback( $args ) {
208
  printf(
209
  '<input type="text" id="%s" name="wpscss_options[%s]" value="%s" />',
210
- esc_attr( $args['name'] ), esc_attr( $args['name'] ), esc_attr( $this->options[$args['name']])
211
  );
212
  }
213
 
@@ -219,7 +237,7 @@ class Wp_Scss_Settings
219
 
220
  $html = sprintf( '<select id="%s" name="wpscss_options[%s]">', esc_attr( $args['name'] ), esc_attr( $args['name'] ) );
221
  foreach( $args['type'] as $value => $title ) {
222
- $html .= '<option value="' . esc_attr( $value ) . '"' . selected( $this->options[esc_attr( $args['name'] )], esc_attr( $value ), false) . '>' . esc_attr( $title ) . '</option>';
223
  }
224
  $html .= '</select>';
225
 
127
  )
128
  )
129
  )
130
+ );
131
+
132
+ add_settings_field(
133
+ 'Source Map Mode', // ID
134
+ 'Source Map Mode', // Title
135
+ array( $this, 'input_select_callback' ), // Callback
136
+ 'wpscss_options', // Page
137
+ 'wpscss_compile_section', // Section
138
+ array( // args
139
+ 'name' => 'sourcemap_options',
140
+ 'type' => apply_filters( 'wp_scss_sourcemap_modes' ,
141
+ array(
142
+ 'SOURCE_MAP_NONE' => 'None',
143
+ 'SOURCE_MAP_INLINE' => 'Inline',
144
+ 'SOURCE_MAP_FILE' => 'File'
145
+ )
146
+ )
147
+ )
148
+ );
149
 
150
  add_settings_field(
151
  'Error Display', // ID
163
  )
164
  )
165
  )
166
+ );
167
 
168
  // Enqueuing Options
169
  add_settings_section(
213
  print 'Add the paths to your directories below. Paths should start with the root of your theme. example: "/library/scss/"';
214
  }
215
  public function print_compile_info() {
216
+ print 'Choose how you would like SCSS and source maps to be compiled and how you would like the plugin to handle errors';
217
  }
218
  public function print_enqueue_info() {
219
  print 'WP-SCSS can enqueue your css stylesheets in the header automatically.';
225
  public function input_text_callback( $args ) {
226
  printf(
227
  '<input type="text" id="%s" name="wpscss_options[%s]" value="%s" />',
228
+ esc_attr( $args['name'] ), esc_attr( $args['name'] ), esc_attr( isset($this->options[$args['name']]) ? $this->options[$args['name']] : '' )
229
  );
230
  }
231
 
237
 
238
  $html = sprintf( '<select id="%s" name="wpscss_options[%s]">', esc_attr( $args['name'] ), esc_attr( $args['name'] ) );
239
  foreach( $args['type'] as $value => $title ) {
240
+ $html .= '<option value="' . esc_attr( $value ) . '"' . selected( isset($this->options[esc_attr( $args['name'] )]) ? $this->options[esc_attr( $args['name'] )] : '', esc_attr( $value ), false) . '>' . esc_attr( $title ) . '</option>';
241
  }
242
  $html .= '</select>';
243
 
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: connectthink
3
  Tags: sass, scss, css
4
  Plugin URI: https://github.com/ConnectThink/WP-SCSS
5
  Requires at least: 3.0.1
6
- Tested up to: 4.9.2
7
- Stable tag: 1.2.3
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/copyleft/gpl.html
10
 
@@ -62,6 +62,11 @@ Make sure your directories are properly defined in the settings. Paths are defin
62
  If you are having issues with the plugin, create an issue on [github](https://github.com/ConnectThink/WP-SCSS), and we'll do our best to help.
63
 
64
  == Changelog ==
 
 
 
 
 
65
  = 1.2.3 =
66
  * Updated scssphp to version 0.7.2 [@hellerbenjamin](https://github.com/ConnectThink/WP-SCSS/pull/86)
67
  * Removed depricated screen_icon()
3
  Tags: sass, scss, css
4
  Plugin URI: https://github.com/ConnectThink/WP-SCSS
5
  Requires at least: 3.0.1
6
+ Tested up to: 4.9.5
7
+ Stable tag: 1.2.4
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/copyleft/gpl.html
10
 
62
  If you are having issues with the plugin, create an issue on [github](https://github.com/ConnectThink/WP-SCSS), and we'll do our best to help.
63
 
64
  == Changelog ==
65
+ = 1.2.4 =
66
+ * Updated scssphp to version 0.7.5
67
+ * Added source map [@iannacone](https://github.com/ConnectThink/WP-SCSS/issues/49)
68
+ * Always define $wpscss_compiler in the global scope [@jazbek](https://github.com/ConnectThink/WP-SCSS/pull/98)
69
+
70
  = 1.2.3 =
71
  * Updated scssphp to version 0.7.2 [@hellerbenjamin](https://github.com/ConnectThink/WP-SCSS/pull/86)
72
  * Removed depricated screen_icon()
scssphp/bin/pscss CHANGED
@@ -32,6 +32,7 @@ $debugInfo = false;
32
  $lineNumbers = false;
33
  $ignoreErrors = false;
34
  $encoding = false;
 
35
 
36
  /**
37
  * Parse argument
@@ -77,6 +78,7 @@ Options include:
77
  --iso8859-1 Use iso8859-1 encoding instead of utf-8 (default utf-8)
78
  --line-numbers Annotate selectors with comments referring to the source file and line number
79
  -p=precision Set decimal number precision (default 10)
 
80
  -T Dump formatted parse tree
81
  -v, --version Print the version
82
 
@@ -108,6 +110,11 @@ EOT;
108
  continue;
109
  }
110
 
 
 
 
 
 
111
  if ($argv[$i] === '-T') {
112
  $dumpTree = true;
113
  continue;
@@ -193,6 +200,10 @@ if ($style) {
193
  $scss->setFormatter('Leafo\\ScssPhp\\Formatter\\' . ucfirst($style));
194
  }
195
 
 
 
 
 
196
  if ($encoding) {
197
  $scss->setEncoding($encoding);
198
  }
32
  $lineNumbers = false;
33
  $ignoreErrors = false;
34
  $encoding = false;
35
+ $sourceMap = false;
36
 
37
  /**
38
  * Parse argument
78
  --iso8859-1 Use iso8859-1 encoding instead of utf-8 (default utf-8)
79
  --line-numbers Annotate selectors with comments referring to the source file and line number
80
  -p=precision Set decimal number precision (default 10)
81
+ --sourcemap Create source map file
82
  -T Dump formatted parse tree
83
  -v, --version Print the version
84
 
110
  continue;
111
  }
112
 
113
+ if ($argv[$i] === '--sourcemap') {
114
+ $sourceMap = true;
115
+ continue;
116
+ }
117
+
118
  if ($argv[$i] === '-T') {
119
  $dumpTree = true;
120
  continue;
200
  $scss->setFormatter('Leafo\\ScssPhp\\Formatter\\' . ucfirst($style));
201
  }
202
 
203
+ if ($sourceMap) {
204
+ $scss->setSourceMap(Compiler::SOURCE_MAP_FILE);
205
+ }
206
+
207
  if ($encoding) {
208
  $scss->setEncoding($encoding);
209
  }
scssphp/scss.inc.php CHANGED
@@ -11,7 +11,7 @@ if (! class_exists('Leafo\ScssPhp\Version', false)) {
11
  include_once __DIR__ . '/src/Compiler/Environment.php';
12
  include_once __DIR__ . '/src/Exception/CompilerException.php';
13
  include_once __DIR__ . '/src/Exception/ParserException.php';
14
- include_once __DIR__ . '/src/Exception/RangeException.php'; //exp
15
  include_once __DIR__ . '/src/Exception/ServerException.php';
16
  include_once __DIR__ . '/src/Formatter.php';
17
  include_once __DIR__ . '/src/Formatter/Compact.php';
@@ -24,7 +24,6 @@ if (! class_exists('Leafo\ScssPhp\Version', false)) {
24
  include_once __DIR__ . '/src/Node.php';
25
  include_once __DIR__ . '/src/Node/Number.php';
26
  include_once __DIR__ . '/src/Parser.php';
27
- // include_once __DIR__ . '/src/example/Server.php';
28
  include_once __DIR__ . '/src/SourceMap/Base64VLQEncoder.php';
29
  include_once __DIR__ . '/src/SourceMap/SourceMapGenerator.php';
30
  include_once __DIR__ . '/src/Type.php';
11
  include_once __DIR__ . '/src/Compiler/Environment.php';
12
  include_once __DIR__ . '/src/Exception/CompilerException.php';
13
  include_once __DIR__ . '/src/Exception/ParserException.php';
14
+ include_once __DIR__ . '/src/Exception/RangeException.php';
15
  include_once __DIR__ . '/src/Exception/ServerException.php';
16
  include_once __DIR__ . '/src/Formatter.php';
17
  include_once __DIR__ . '/src/Formatter/Compact.php';
24
  include_once __DIR__ . '/src/Node.php';
25
  include_once __DIR__ . '/src/Node/Number.php';
26
  include_once __DIR__ . '/src/Parser.php';
 
27
  include_once __DIR__ . '/src/SourceMap/Base64VLQEncoder.php';
28
  include_once __DIR__ . '/src/SourceMap/SourceMapGenerator.php';
29
  include_once __DIR__ . '/src/Type.php';
scssphp/src/Base/Range.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2015-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
scssphp/src/Block.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
@@ -29,7 +29,7 @@ class Block
29
  public $parent;
30
 
31
  /**
32
- * @var string;
33
  */
34
  public $sourceName;
35
 
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
29
  public $parent;
30
 
31
  /**
32
+ * @var string
33
  */
34
  public $sourceName;
35
 
scssphp/src/Colors.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
scssphp/src/Compiler.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
@@ -65,9 +65,9 @@ class Compiler
65
  const WITH_SUPPORTS = 4;
66
  const WITH_ALL = 7;
67
 
68
- const SOURCE_MAP_NONE = 0;
69
  const SOURCE_MAP_INLINE = 1;
70
- const SOURCE_MAP_FILE = 2;
71
 
72
  /**
73
  * @var array
@@ -128,13 +128,17 @@ class Compiler
128
  protected $sourceMap = self::SOURCE_MAP_NONE;
129
  protected $sourceMapOptions = [];
130
 
131
- /** @var string|Formatter */
 
 
132
  protected $formatter = 'Leafo\ScssPhp\Formatter\Nested';
133
 
134
  protected $rootEnv;
135
  protected $rootBlock;
136
 
137
- /** @var Environment */
 
 
138
  protected $env;
139
  protected $scope;
140
  protected $storeEnv;
@@ -202,22 +206,35 @@ class Compiler
202
  $this->popEnv();
203
 
204
  $sourceMapGenerator = null;
205
- if($this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) {
206
- $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions);
 
 
 
 
 
 
207
  }
 
208
  $out = $this->formatter->format($this->scope, $sourceMapGenerator);
209
- if(!empty($out) && $this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) {
210
- $sourceMap = $sourceMapGenerator->generateJson();
211
 
 
 
212
  $sourceMapUrl = null;
213
- if($this->sourceMap == self::SOURCE_MAP_INLINE) {
214
- $sourceMapUrl = sprintf('data:application/json,%s', self::encodeURIComponent($sourceMap));
215
- } elseif ($this->sourceMap == self::SOURCE_MAP_FILE) {
216
- $sourceMapUrl = $sourceMapGenerator->saveMap($sourceMap);
 
 
 
 
 
217
  }
218
 
219
  $out .= sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl);
220
  }
 
221
  return $out;
222
  }
223
 
@@ -293,14 +310,14 @@ class Compiler
293
  protected function makeOutputBlock($type, $selectors = null)
294
  {
295
  $out = new OutputBlock;
296
- $out->type = $type;
297
- $out->lines = [];
298
- $out->children = [];
299
- $out->parent = $this->scope;
300
- $out->selectors = $selectors;
301
- $out->depth = $this->env->depth;
302
- $out->sourceName = $this->env->block->sourceName;
303
- $out->sourceLine = $this->env->block->sourceLine;
304
  $out->sourceColumn = $this->env->block->sourceColumn;
305
 
306
  return $out;
@@ -684,7 +701,7 @@ class Compiler
684
 
685
  if ($needsWrap) {
686
  $wrapped = new Block;
687
- $wrapped->sourceName = $media->sourceName;
688
  $wrapped->sourceIndex = $media->sourceIndex;
689
  $wrapped->sourceLine = $media->sourceLine;
690
  $wrapped->sourceColumn = $media->sourceColumn;
@@ -1107,13 +1124,6 @@ class Compiler
1107
  return $selectors;
1108
  }
1109
 
1110
- /**
1111
- * @param array $sourceMapOptions
1112
- */
1113
- public function setSourceMapOptions($sourceMapOptions) {
1114
- $this->sourceMapOptions = $sourceMapOptions;
1115
- }
1116
-
1117
  /**
1118
  * Evaluate selector
1119
  *
@@ -1762,9 +1772,18 @@ class Compiler
1762
  list(, $for) = $child;
1763
 
1764
  $start = $this->reduce($for->start, true);
 
 
 
 
 
 
 
 
 
1765
  $start = $start[1];
1766
- $end = $this->reduce($for->end, true);
1767
- $end = $end[1];
1768
  $d = $start < $end ? 1 : -1;
1769
 
1770
  for (;;) {
@@ -1774,7 +1793,7 @@ class Compiler
1774
  break;
1775
  }
1776
 
1777
- $this->set($for->var, new Node\Number($start, ''));
1778
  $start += $d;
1779
 
1780
  $ret = $this->compileChildren($for->children, $out);
@@ -1959,7 +1978,7 @@ class Compiler
1959
  *
1960
  * @param string $value
1961
  *
1962
- * @return bool
1963
  */
1964
  protected function isImmediateRelationshipCombinator($value)
1965
  {
@@ -3338,12 +3357,29 @@ class Compiler
3338
  }
3339
 
3340
  /**
3341
- * @param int $sourceMap
 
 
 
 
3342
  */
3343
- public function setSourceMap($sourceMap) {
 
3344
  $this->sourceMap = $sourceMap;
3345
  }
3346
 
 
 
 
 
 
 
 
 
 
 
 
 
3347
  /**
3348
  * Register function
3349
  *
@@ -4490,7 +4526,7 @@ class Compiler
4490
  ];
4491
 
4492
  if ($firstAlpha != 1.0 || $secondAlpha != 1.0) {
4493
- $new[] = $firstAlpha * $weight + $secondAlpha * ($weight - 1);
4494
  }
4495
 
4496
  return $this->fixColor($new);
@@ -4713,36 +4749,32 @@ class Compiler
4713
  protected function libRound($args)
4714
  {
4715
  $num = $args[0];
4716
- $num[1] = round($num[1]);
4717
 
4718
- return $num;
4719
  }
4720
 
4721
  protected static $libFloor = ['value'];
4722
  protected function libFloor($args)
4723
  {
4724
  $num = $args[0];
4725
- $num[1] = floor($num[1]);
4726
 
4727
- return $num;
4728
  }
4729
 
4730
  protected static $libCeil = ['value'];
4731
  protected function libCeil($args)
4732
  {
4733
  $num = $args[0];
4734
- $num[1] = ceil($num[1]);
4735
 
4736
- return $num;
4737
  }
4738
 
4739
  protected static $libAbs = ['value'];
4740
  protected function libAbs($args)
4741
  {
4742
  $num = $args[0];
4743
- $num[1] = abs($num[1]);
4744
 
4745
- return $num;
4746
  }
4747
 
4748
  protected function libMin($args)
@@ -5170,7 +5202,7 @@ class Compiler
5170
  $string = $this->coerceString($args[0]);
5171
  $stringContent = $this->compileStringContent($string);
5172
 
5173
- $string[2] = [mb_strtolower($stringContent)];
5174
 
5175
  return $string;
5176
  }
@@ -5181,7 +5213,7 @@ class Compiler
5181
  $string = $this->coerceString($args[0]);
5182
  $stringContent = $this->compileStringContent($string);
5183
 
5184
- $string[2] = [mb_strtoupper($stringContent)];
5185
 
5186
  return $string;
5187
  }
@@ -5301,9 +5333,4 @@ class Compiler
5301
 
5302
  return $args[0];
5303
  }
5304
-
5305
- public static function encodeURIComponent($string){
5306
- $revert = array('%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')');
5307
- return strtr(rawurlencode($string), $revert);
5308
- }
5309
  }
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
65
  const WITH_SUPPORTS = 4;
66
  const WITH_ALL = 7;
67
 
68
+ const SOURCE_MAP_NONE = 0;
69
  const SOURCE_MAP_INLINE = 1;
70
+ const SOURCE_MAP_FILE = 2;
71
 
72
  /**
73
  * @var array
128
  protected $sourceMap = self::SOURCE_MAP_NONE;
129
  protected $sourceMapOptions = [];
130
 
131
+ /**
132
+ * @var string|\Leafo\ScssPhp\Formatter
133
+ */
134
  protected $formatter = 'Leafo\ScssPhp\Formatter\Nested';
135
 
136
  protected $rootEnv;
137
  protected $rootBlock;
138
 
139
+ /**
140
+ * @var \Leafo\ScssPhp\Compiler\Environment
141
+ */
142
  protected $env;
143
  protected $scope;
144
  protected $storeEnv;
206
  $this->popEnv();
207
 
208
  $sourceMapGenerator = null;
209
+
210
+ if ($this->sourceMap) {
211
+ if (is_object($this->sourceMap) && $this->sourceMap instanceof SourceMapGenerator) {
212
+ $sourceMapGenerator = $this->sourceMap;
213
+ $this->sourceMap = self::SOURCE_MAP_FILE;
214
+ } elseif ($this->sourceMap !== self::SOURCE_MAP_NONE) {
215
+ $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions);
216
+ }
217
  }
218
+
219
  $out = $this->formatter->format($this->scope, $sourceMapGenerator);
 
 
220
 
221
+ if (! empty($out) && $this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) {
222
+ $sourceMap = $sourceMapGenerator->generateJson();
223
  $sourceMapUrl = null;
224
+
225
+ switch ($this->sourceMap) {
226
+ case self::SOURCE_MAP_INLINE:
227
+ $sourceMapUrl = sprintf('data:application/json,%s', Util::encodeURIComponent($sourceMap));
228
+ break;
229
+
230
+ case self::SOURCE_MAP_FILE:
231
+ $sourceMapUrl = $sourceMapGenerator->saveMap($sourceMap);
232
+ break;
233
  }
234
 
235
  $out .= sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl);
236
  }
237
+
238
  return $out;
239
  }
240
 
310
  protected function makeOutputBlock($type, $selectors = null)
311
  {
312
  $out = new OutputBlock;
313
+ $out->type = $type;
314
+ $out->lines = [];
315
+ $out->children = [];
316
+ $out->parent = $this->scope;
317
+ $out->selectors = $selectors;
318
+ $out->depth = $this->env->depth;
319
+ $out->sourceName = $this->env->block->sourceName;
320
+ $out->sourceLine = $this->env->block->sourceLine;
321
  $out->sourceColumn = $this->env->block->sourceColumn;
322
 
323
  return $out;
701
 
702
  if ($needsWrap) {
703
  $wrapped = new Block;
704
+ $wrapped->sourceName = $media->sourceName;
705
  $wrapped->sourceIndex = $media->sourceIndex;
706
  $wrapped->sourceLine = $media->sourceLine;
707
  $wrapped->sourceColumn = $media->sourceColumn;
1124
  return $selectors;
1125
  }
1126
 
 
 
 
 
 
 
 
1127
  /**
1128
  * Evaluate selector
1129
  *
1772
  list(, $for) = $child;
1773
 
1774
  $start = $this->reduce($for->start, true);
1775
+ $end = $this->reduce($for->end, true);
1776
+
1777
+ if (! ($start[2] == $end[2] || $end->unitless())) {
1778
+ $this->throwError('Incompatible units: "%s" and "%s".', $start->unitStr(), $end->unitStr());
1779
+
1780
+ break;
1781
+ }
1782
+
1783
+ $unit = $start[2];
1784
  $start = $start[1];
1785
+ $end = $end[1];
1786
+
1787
  $d = $start < $end ? 1 : -1;
1788
 
1789
  for (;;) {
1793
  break;
1794
  }
1795
 
1796
+ $this->set($for->var, new Node\Number($start, $unit));
1797
  $start += $d;
1798
 
1799
  $ret = $this->compileChildren($for->children, $out);
1978
  *
1979
  * @param string $value
1980
  *
1981
+ * @return boolean
1982
  */
1983
  protected function isImmediateRelationshipCombinator($value)
1984
  {
3357
  }
3358
 
3359
  /**
3360
+ * Enable/disable source maps
3361
+ *
3362
+ * @api
3363
+ *
3364
+ * @param integer $sourceMap
3365
  */
3366
+ public function setSourceMap($sourceMap)
3367
+ {
3368
  $this->sourceMap = $sourceMap;
3369
  }
3370
 
3371
+ /**
3372
+ * Set source map options
3373
+ *
3374
+ * @api
3375
+ *
3376
+ * @param array $sourceMapOptions
3377
+ */
3378
+ public function setSourceMapOptions($sourceMapOptions)
3379
+ {
3380
+ $this->sourceMapOptions = $sourceMapOptions;
3381
+ }
3382
+
3383
  /**
3384
  * Register function
3385
  *
4526
  ];
4527
 
4528
  if ($firstAlpha != 1.0 || $secondAlpha != 1.0) {
4529
+ $new[] = $firstAlpha * $weight + $secondAlpha * (1 - $weight);
4530
  }
4531
 
4532
  return $this->fixColor($new);
4749
  protected function libRound($args)
4750
  {
4751
  $num = $args[0];
 
4752
 
4753
+ return new Node\Number(round($num[1]), $num[2]);
4754
  }
4755
 
4756
  protected static $libFloor = ['value'];
4757
  protected function libFloor($args)
4758
  {
4759
  $num = $args[0];
 
4760
 
4761
+ return new Node\Number(floor($num[1]), $num[2]);
4762
  }
4763
 
4764
  protected static $libCeil = ['value'];
4765
  protected function libCeil($args)
4766
  {
4767
  $num = $args[0];
 
4768
 
4769
+ return new Node\Number(ceil($num[1]), $num[2]);
4770
  }
4771
 
4772
  protected static $libAbs = ['value'];
4773
  protected function libAbs($args)
4774
  {
4775
  $num = $args[0];
 
4776
 
4777
+ return new Node\Number(abs($num[1]), $num[2]);
4778
  }
4779
 
4780
  protected function libMin($args)
5202
  $string = $this->coerceString($args[0]);
5203
  $stringContent = $this->compileStringContent($string);
5204
 
5205
+ $string[2] = [function_exists('mb_strtolower') ? mb_strtolower($stringContent) : strtolower($stringContent)];
5206
 
5207
  return $string;
5208
  }
5213
  $string = $this->coerceString($args[0]);
5214
  $stringContent = $this->compileStringContent($string);
5215
 
5216
+ $string[2] = [function_exists('mb_strtoupper') ? mb_strtoupper($stringContent) : strtoupper($stringContent)];
5217
 
5218
  return $string;
5219
  }
5333
 
5334
  return $args[0];
5335
  }
 
 
 
 
 
5336
  }
scssphp/src/Compiler/Environment.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
scssphp/src/Exception/CompilerException.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
scssphp/src/Exception/ParserException.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
scssphp/src/Exception/RangeException.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
scssphp/src/Exception/ServerException.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
scssphp/src/Formatter.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
@@ -62,23 +62,22 @@ abstract class Formatter
62
  public $keepSemicolons;
63
 
64
  /**
65
- * @var OutputBlock;
66
  */
67
  protected $currentBlock;
68
 
69
-
70
  /**
71
- * @var int
72
  */
73
  protected $currentLine;
74
 
75
  /**
76
- * @var int;
77
  */
78
  protected $currentColumn;
79
 
80
  /**
81
- * @var SourceMapGenerator
82
  */
83
  protected $sourceMapGenerator;
84
 
@@ -223,21 +222,21 @@ abstract class Formatter
223
  *
224
  * @api
225
  *
226
- * @param \Leafo\ScssPhp\Formatter\OutputBlock $block An abstract syntax tree
 
227
  *
228
- * @param SourceMapGenerator|null $sourceMapGenerator
229
  * @return string
230
- * @internal param bool $collectSourceMap
231
  */
232
  public function format(OutputBlock $block, SourceMapGenerator $sourceMapGenerator = null)
233
  {
234
- if($sourceMapGenerator) {
 
 
235
  $this->currentLine = 1;
236
  $this->currentColumn = 0;
237
  $this->sourceMapGenerator = $sourceMapGenerator;
238
- } else {
239
- $this->sourceMapGenerator = null;
240
  }
 
241
  ob_start();
242
 
243
  $this->block($block);
@@ -248,10 +247,11 @@ abstract class Formatter
248
  }
249
 
250
  /**
251
- * @param $str
252
  */
253
- protected function write($str) {
254
- if($this->sourceMapGenerator) {
 
255
  $this->sourceMapGenerator->addMapping(
256
  $this->currentLine,
257
  $this->currentColumn,
@@ -265,11 +265,8 @@ abstract class Formatter
265
  $this->currentLine += $lineCount-1;
266
 
267
  $lastLine = array_pop($lines);
268
- if($lineCount == 1) {
269
- $this->currentColumn += mb_strlen($lastLine);
270
- } else {
271
- $this->currentColumn = mb_strlen($lastLine);
272
- }
273
  }
274
 
275
  echo $str;
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
62
  public $keepSemicolons;
63
 
64
  /**
65
+ * @var \Leafo\ScssPhp\Formatter\OutputBlock
66
  */
67
  protected $currentBlock;
68
 
 
69
  /**
70
+ * @var integer
71
  */
72
  protected $currentLine;
73
 
74
  /**
75
+ * @var integer
76
  */
77
  protected $currentColumn;
78
 
79
  /**
80
+ * @var \Leafo\ScssPhp\SourceMap\SourceMapGenerator
81
  */
82
  protected $sourceMapGenerator;
83
 
222
  *
223
  * @api
224
  *
225
+ * @param \Leafo\ScssPhp\Formatter\OutputBlock $block An abstract syntax tree
226
+ * @param \Leafo\ScssPhp\SourceMap\SourceMapGenerator|null $sourceMapGenerator Optional source map generator
227
  *
 
228
  * @return string
 
229
  */
230
  public function format(OutputBlock $block, SourceMapGenerator $sourceMapGenerator = null)
231
  {
232
+ $this->sourceMapGenerator = null;
233
+
234
+ if ($sourceMapGenerator) {
235
  $this->currentLine = 1;
236
  $this->currentColumn = 0;
237
  $this->sourceMapGenerator = $sourceMapGenerator;
 
 
238
  }
239
+
240
  ob_start();
241
 
242
  $this->block($block);
247
  }
248
 
249
  /**
250
+ * @param string $str
251
  */
252
+ protected function write($str)
253
+ {
254
+ if ($this->sourceMapGenerator) {
255
  $this->sourceMapGenerator->addMapping(
256
  $this->currentLine,
257
  $this->currentColumn,
265
  $this->currentLine += $lineCount-1;
266
 
267
  $lastLine = array_pop($lines);
268
+
269
+ $this->currentColumn = ($lineCount === 1 ? $this->currentColumn : 0) + strlen($lastLine);
 
 
 
270
  }
271
 
272
  echo $str;
scssphp/src/Formatter/Compact.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
scssphp/src/Formatter/Compressed.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
@@ -53,10 +53,10 @@ class Compressed extends Formatter
53
  }
54
  }
55
 
56
- $this->write( $inner . implode($glue, $block->lines));
57
 
58
  if (! empty($block->children)) {
59
- $this->write( $this->break);
60
  }
61
  }
62
  }
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
53
  }
54
  }
55
 
56
+ $this->write($inner . implode($glue, $block->lines));
57
 
58
  if (! empty($block->children)) {
59
+ $this->write($this->break);
60
  }
61
  }
62
  }
scssphp/src/Formatter/Crunched.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
scssphp/src/Formatter/Debug.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
@@ -58,7 +58,7 @@ class Debug extends Formatter
58
  }
59
 
60
  foreach ($block->lines as $index => $line) {
61
- $this->write( "{$indent}block->lines[{$index}]: $line\n");
62
  }
63
  }
64
 
@@ -70,13 +70,13 @@ class Debug extends Formatter
70
  $indent = $this->indentStr();
71
 
72
  if (empty($block->selectors)) {
73
- $this->write( "{$indent}block->selectors: []\n");
74
 
75
  return;
76
  }
77
 
78
  foreach ($block->selectors as $index => $selector) {
79
- $this->write( "{$indent}block->selectors[{$index}]: $selector\n");
80
  }
81
  }
82
 
@@ -88,7 +88,7 @@ class Debug extends Formatter
88
  $indent = $this->indentStr();
89
 
90
  if (empty($block->children)) {
91
- $this->write( "{$indent}block->children: []\n");
92
 
93
  return;
94
  }
@@ -109,7 +109,7 @@ class Debug extends Formatter
109
  {
110
  $indent = $this->indentStr();
111
 
112
- $this->write( "{$indent}block->type: {$block->type}\n" .
113
  "{$indent}block->depth: {$block->depth}\n");
114
 
115
  $this->currentBlock = $block;
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
58
  }
59
 
60
  foreach ($block->lines as $index => $line) {
61
+ $this->write("{$indent}block->lines[{$index}]: $line\n");
62
  }
63
  }
64
 
70
  $indent = $this->indentStr();
71
 
72
  if (empty($block->selectors)) {
73
+ $this->write("{$indent}block->selectors: []\n");
74
 
75
  return;
76
  }
77
 
78
  foreach ($block->selectors as $index => $selector) {
79
+ $this->write("{$indent}block->selectors[{$index}]: $selector\n");
80
  }
81
  }
82
 
88
  $indent = $this->indentStr();
89
 
90
  if (empty($block->children)) {
91
+ $this->write("{$indent}block->children: []\n");
92
 
93
  return;
94
  }
109
  {
110
  $indent = $this->indentStr();
111
 
112
+ $this->write("{$indent}block->type: {$block->type}\n" .
113
  "{$indent}block->depth: {$block->depth}\n");
114
 
115
  $this->currentBlock = $block;
scssphp/src/Formatter/Expanded.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
scssphp/src/Formatter/Nested.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
@@ -12,6 +12,7 @@
12
  namespace Leafo\ScssPhp\Formatter;
13
 
14
  use Leafo\ScssPhp\Formatter;
 
15
 
16
  /**
17
  * Nested formatter
@@ -65,10 +66,10 @@ class Nested extends Formatter
65
  }
66
  }
67
 
68
- $this->write( $inner . implode($glue, $block->lines));
69
 
70
  if (! empty($block->children)) {
71
- $this->write( $this->break);
72
  }
73
  }
74
 
@@ -79,7 +80,7 @@ class Nested extends Formatter
79
  {
80
  $inner = $this->indentStr();
81
 
82
- $this->write( $inner
83
  . implode($this->tagSeparator, $block->selectors)
84
  . $this->open . $this->break);
85
  }
@@ -93,13 +94,13 @@ class Nested extends Formatter
93
  $this->block($child);
94
 
95
  if ($i < count($block->children) - 1) {
96
- $this->write( $this->break);
97
 
98
  if (isset($block->children[$i + 1])) {
99
  $next = $block->children[$i + 1];
100
 
101
  if ($next->depth === max($block->depth, 1) && $child->depth >= $next->depth) {
102
- $this->write( $this->break);
103
  }
104
  }
105
  }
@@ -141,11 +142,11 @@ class Nested extends Formatter
141
  if (! empty($block->selectors)) {
142
  $this->indentLevel--;
143
 
144
- $this->write( $this->close);
145
  }
146
 
147
  if ($block->type === 'root') {
148
- $this->write( $this->break);
149
  }
150
  }
151
 
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
12
  namespace Leafo\ScssPhp\Formatter;
13
 
14
  use Leafo\ScssPhp\Formatter;
15
+ use Leafo\ScssPhp\Formatter\OutputBlock;
16
 
17
  /**
18
  * Nested formatter
66
  }
67
  }
68
 
69
+ $this->write($inner . implode($glue, $block->lines));
70
 
71
  if (! empty($block->children)) {
72
+ $this->write($this->break);
73
  }
74
  }
75
 
80
  {
81
  $inner = $this->indentStr();
82
 
83
+ $this->write($inner
84
  . implode($this->tagSeparator, $block->selectors)
85
  . $this->open . $this->break);
86
  }
94
  $this->block($child);
95
 
96
  if ($i < count($block->children) - 1) {
97
+ $this->write($this->break);
98
 
99
  if (isset($block->children[$i + 1])) {
100
  $next = $block->children[$i + 1];
101
 
102
  if ($next->depth === max($block->depth, 1) && $child->depth >= $next->depth) {
103
+ $this->write($this->break);
104
  }
105
  }
106
  }
142
  if (! empty($block->selectors)) {
143
  $this->indentLevel--;
144
 
145
+ $this->write($this->close);
146
  }
147
 
148
  if ($block->type === 'root') {
149
+ $this->write($this->break);
150
  }
151
  }
152
 
scssphp/src/Formatter/OutputBlock.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
@@ -54,12 +54,12 @@ class OutputBlock
54
  public $sourceName;
55
 
56
  /**
57
- * @var int
58
  */
59
  public $sourceLine;
60
 
61
  /**
62
- * @var int
63
  */
64
  public $sourceColumn;
65
  }
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
54
  public $sourceName;
55
 
56
  /**
57
+ * @var integer
58
  */
59
  public $sourceLine;
60
 
61
  /**
62
+ * @var integer
63
  */
64
  public $sourceColumn;
65
  }
scssphp/src/Node.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
scssphp/src/Node/Number.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
scssphp/src/Parser.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
@@ -708,7 +708,7 @@ class Parser
708
  list($line, $column) = $this->getSourcePosition($pos);
709
 
710
  $b = new Block;
711
- $b->sourceName = $this->sourceName;
712
  $b->sourceLine = $line;
713
  $b->sourceColumn = $column;
714
  $b->sourceIndex = $this->sourceIndex;
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
708
  list($line, $column) = $this->getSourcePosition($pos);
709
 
710
  $b = new Block;
711
+ $b->sourceName = $this->sourceName;
712
  $b->sourceLine = $line;
713
  $b->sourceColumn = $column;
714
  $b->sourceIndex = $this->sourceIndex;
scssphp/src/SourceMap/Base64VLQEncoder.php CHANGED
@@ -1,174 +1,217 @@
1
  <?php
2
  /**
3
- * Created by PhpStorm.
4
- * User: nico
5
- * Date: 08/11/17
6
- * Time: 19:14
 
 
 
7
  */
8
 
9
  namespace Leafo\ScssPhp\SourceMap;
10
 
11
-
12
- class Base64VLQEncoder {
 
 
 
 
 
 
 
 
13
  /**
14
  * Shift
15
  *
16
  * @var integer
17
  */
18
  private $shift = 5;
 
19
  /**
20
  * Mask
21
  *
22
  * @var integer
23
  */
24
  private $mask = 0x1F; // == (1 << shift) == 0b00011111
 
25
  /**
26
  * Continuation bit
27
  *
28
  * @var integer
29
  */
30
  private $continuationBit = 0x20; // == (mask - 1 ) == 0b00100000
 
31
  /**
32
  * Char to integer map
33
  *
34
  * @var array
35
  */
36
  private $charToIntMap = array(
37
- 'A' => 0, 'B' => 1, 'C' => 2, 'D' => 3, 'E' => 4, 'F' => 5, 'G' => 6,
38
- 'H' => 7,'I' => 8, 'J' => 9, 'K' => 10, 'L' => 11, 'M' => 12, 'N' => 13,
39
- 'O' => 14, 'P' => 15, 'Q' => 16, 'R' => 17, 'S' => 18, 'T' => 19, 'U' => 20,
40
- 'V' => 21, 'W' => 22, 'X' => 23, 'Y' => 24, 'Z' => 25, 'a' => 26, 'b' => 27,
41
- 'c' => 28, 'd' => 29, 'e' => 30, 'f' => 31, 'g' => 32, 'h' => 33, 'i' => 34,
42
- 'j' => 35, 'k' => 36, 'l' => 37, 'm' => 38, 'n' => 39, 'o' => 40, 'p' => 41,
43
- 'q' => 42, 'r' => 43, 's' => 44, 't' => 45, 'u' => 46, 'v' => 47, 'w' => 48,
44
- 'x' => 49, 'y' => 50, 'z' => 51, 0 => 52, 1 => 53, 2 => 54, 3 => 55, 4 => 56,
45
- 5 => 57, 6 => 58, 7 => 59, 8 => 60, 9 => 61, '+' => 62, '/' => 63,
46
  );
 
47
  /**
48
  * Integer to char map
49
  *
50
  * @var array
51
  */
52
  private $intToCharMap = array(
53
- 0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D', 4 => 'E', 5 => 'F', 6 => 'G',
54
- 7 => 'H', 8 => 'I', 9 => 'J', 10 => 'K', 11 => 'L', 12 => 'M', 13 => 'N',
55
- 14 => 'O', 15 => 'P', 16 => 'Q', 17 => 'R', 18 => 'S', 19 => 'T', 20 => 'U',
56
- 21 => 'V', 22 => 'W', 23 => 'X', 24 => 'Y', 25 => 'Z', 26 => 'a', 27 => 'b',
57
- 28 => 'c', 29 => 'd', 30 => 'e', 31 => 'f', 32 => 'g', 33 => 'h', 34 => 'i',
58
- 35 => 'j', 36 => 'k', 37 => 'l', 38 => 'm', 39 => 'n', 40 => 'o', 41 => 'p',
59
- 42 => 'q', 43 => 'r', 44 => 's', 45 => 't', 46 => 'u', 47 => 'v', 48 => 'w',
60
- 49 => 'x', 50 => 'y', 51 => 'z', 52 => '0', 53 => '1', 54 => '2', 55 => '3',
61
- 56 => '4', 57 => '5', 58 => '6', 59 => '7', 60 => '8', 61 => '9', 62 => '+',
62
- 63 => '/',
63
  );
 
64
  /**
65
  * Constructor
66
  */
67
- public function __construct(){
 
68
  // I leave it here for future reference
69
- // foreach(str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/') as $i => $char)
70
  // {
71
- // $this->charToIntMap[$char] = $i;
72
- // $this->intToCharMap[$i] = $char;
73
  // }
74
  }
 
75
  /**
76
  * Convert from a two-complement value to a value where the sign bit is
77
- * is placed in the least significant bit. For example, as decimals:
78
- * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
79
- * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
80
  * We generate the value for 32 bit machines, hence -2147483648 becomes 1, not 4294967297,
81
  * even on a 64 bit machine.
 
82
  * @param string $aValue
83
  */
84
- public function toVLQSigned($aValue){
 
85
  return 0xffffffff & ($aValue < 0 ? ((-$aValue) << 1) + 1 : ($aValue << 1) + 0);
86
  }
 
87
  /**
88
  * Convert to a two-complement value from a value where the sign bit is
89
  * is placed in the least significant bit. For example, as decimals:
90
- * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
91
- * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
92
  * We assume that the value was generated with a 32 bit machine in mind.
93
  * Hence
94
- * 1 becomes -2147483648
95
  * even on a 64 bit machine.
 
96
  * @param integer $aValue
97
  */
98
- public function fromVLQSigned($aValue){
 
99
  return $aValue & 1 ? $this->zeroFill(~$aValue + 2, 1) | (-1 - 0x7fffffff) : $this->zeroFill($aValue, 1);
100
  }
 
101
  /**
102
  * Return the base 64 VLQ encoded value.
103
  *
104
  * @param string $aValue The value to encode
 
105
  * @return string The encoded value
106
  */
107
- public function encode($aValue){
 
108
  $encoded = '';
109
  $vlq = $this->toVLQSigned($aValue);
110
- do
111
- {
112
  $digit = $vlq & $this->mask;
113
  $vlq = $this->zeroFill($vlq, $this->shift);
114
- if($vlq > 0){
 
115
  $digit |= $this->continuationBit;
116
  }
 
117
  $encoded .= $this->base64Encode($digit);
118
- } while($vlq > 0);
 
119
  return $encoded;
120
  }
 
121
  /**
122
  * Return the value decoded from base 64 VLQ.
123
  *
124
  * @param string $encoded The encoded value to decode
 
125
  * @return integer The decoded value
126
  */
127
- public function decode($encoded){
 
128
  $vlq = 0;
129
  $i = 0;
130
- do
131
- {
132
  $digit = $this->base64Decode($encoded[$i]);
133
  $vlq |= ($digit & $this->mask) << ($i * $this->shift);
134
  $i++;
135
- } while($digit & $this->continuationBit);
 
136
  return $this->fromVLQSigned($vlq);
137
  }
 
138
  /**
139
  * Right shift with zero fill.
140
  *
141
  * @param integer $a number to shift
142
  * @param integer $b number of bits to shift
 
143
  * @return integer
144
  */
145
- public function zeroFill($a, $b){
 
146
  return ($a >= 0) ? ($a >> $b) : ($a >> $b) & (PHP_INT_MAX >> ($b - 1));
147
  }
 
148
  /**
149
  * Encode single 6-bit digit as base64.
150
  *
151
  * @param integer $number
 
152
  * @return string
153
- * @throws Exception If the number is invalid
 
154
  */
155
- public function base64Encode($number){
156
- if($number < 0 || $number > 63){
157
- throw new Exception(sprintf('Invalid number "%s" given. Must be between 0 and 63.', $number));
 
158
  }
 
159
  return $this->intToCharMap[$number];
160
  }
 
161
  /**
162
  * Decode single 6-bit digit from base64
163
  *
164
  * @param string $char
165
- * @return number
166
- * @throws Exception If the number is invalid
 
 
167
  */
168
- public function base64Decode($char){
169
- if(!array_key_exists($char, $this->charToIntMap)){
170
- throw new Exception(sprintf('Invalid base 64 digit "%s" given.', $char));
 
171
  }
 
172
  return $this->charToIntMap[$char];
173
  }
174
  }
1
  <?php
2
  /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://leafo.github.io/scssphp
10
  */
11
 
12
  namespace Leafo\ScssPhp\SourceMap;
13
 
14
+ /**
15
+ * Base64 VLQ Encoder
16
+ *
17
+ * {@internal Derivative of oyejorge/less.php's lib/SourceMap/Base64VLQ.php, relicensed with permission. }}
18
+ *
19
+ * @author Josh Schmidt <oyejorge@gmail.com>
20
+ * @author Nicolas FRANÇOIS <nicolas.francois@frog-labs.com>
21
+ */
22
+ class Base64VLQEncoder
23
+ {
24
  /**
25
  * Shift
26
  *
27
  * @var integer
28
  */
29
  private $shift = 5;
30
+
31
  /**
32
  * Mask
33
  *
34
  * @var integer
35
  */
36
  private $mask = 0x1F; // == (1 << shift) == 0b00011111
37
+
38
  /**
39
  * Continuation bit
40
  *
41
  * @var integer
42
  */
43
  private $continuationBit = 0x20; // == (mask - 1 ) == 0b00100000
44
+
45
  /**
46
  * Char to integer map
47
  *
48
  * @var array
49
  */
50
  private $charToIntMap = array(
51
+ 'A' => 0, 'B' => 1, 'C' => 2, 'D' => 3, 'E' => 4, 'F' => 5, 'G' => 6, 'H' => 7,
52
+ 'I' => 8, 'J' => 9, 'K' => 10, 'L' => 11, 'M' => 12, 'N' => 13, 'O' => 14, 'P' => 15,
53
+ 'Q' => 16, 'R' => 17, 'S' => 18, 'T' => 19, 'U' => 20, 'V' => 21, 'W' => 22, 'X' => 23,
54
+ 'Y' => 24, 'Z' => 25, 'a' => 26, 'b' => 27, 'c' => 28, 'd' => 29, 'e' => 30, 'f' => 31,
55
+ 'g' => 32, 'h' => 33, 'i' => 34, 'j' => 35, 'k' => 36, 'l' => 37, 'm' => 38, 'n' => 39,
56
+ 'o' => 40, 'p' => 41, 'q' => 42, 'r' => 43, 's' => 44, 't' => 45, 'u' => 46, 'v' => 47,
57
+ 'w' => 48, 'x' => 49, 'y' => 50, 'z' => 51, 0 => 52, 1 => 53, 2 => 54, 3 => 55,
58
+ 4 => 56, 5 => 57, 6 => 58, 7 => 59, 8 => 60, 9 => 61, '+' => 62, '/' => 63,
 
59
  );
60
+
61
  /**
62
  * Integer to char map
63
  *
64
  * @var array
65
  */
66
  private $intToCharMap = array(
67
+ 0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D', 4 => 'E', 5 => 'F', 6 => 'G', 7 => 'H',
68
+ 8 => 'I', 9 => 'J', 10 => 'K', 11 => 'L', 12 => 'M', 13 => 'N', 14 => 'O', 15 => 'P',
69
+ 16 => 'Q', 17 => 'R', 18 => 'S', 19 => 'T', 20 => 'U', 21 => 'V', 22 => 'W', 23 => 'X',
70
+ 24 => 'Y', 25 => 'Z', 26 => 'a', 27 => 'b', 28 => 'c', 29 => 'd', 30 => 'e', 31 => 'f',
71
+ 32 => 'g', 33 => 'h', 34 => 'i', 35 => 'j', 36 => 'k', 37 => 'l', 38 => 'm', 39 => 'n',
72
+ 40 => 'o', 41 => 'p', 42 => 'q', 43 => 'r', 44 => 's', 45 => 't', 46 => 'u', 47 => 'v',
73
+ 48 => 'w', 49 => 'x', 50 => 'y', 51 => 'z', 52 => '0', 53 => '1', 54 => '2', 55 => '3',
74
+ 56 => '4', 57 => '5', 58 => '6', 59 => '7', 60 => '8', 61 => '9', 62 => '+', 63 => '/',
 
 
75
  );
76
+
77
  /**
78
  * Constructor
79
  */
80
+ public function __construct()
81
+ {
82
  // I leave it here for future reference
83
+ // foreach (str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/') as $i => $char)
84
  // {
85
+ // $this->charToIntMap[$char] = $i;
86
+ // $this->intToCharMap[$i] = $char;
87
  // }
88
  }
89
+
90
  /**
91
  * Convert from a two-complement value to a value where the sign bit is
92
+ * is placed in the least significant bit. For example, as decimals:
93
+ * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
94
+ * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
95
  * We generate the value for 32 bit machines, hence -2147483648 becomes 1, not 4294967297,
96
  * even on a 64 bit machine.
97
+ *
98
  * @param string $aValue
99
  */
100
+ public function toVLQSigned($aValue)
101
+ {
102
  return 0xffffffff & ($aValue < 0 ? ((-$aValue) << 1) + 1 : ($aValue << 1) + 0);
103
  }
104
+
105
  /**
106
  * Convert to a two-complement value from a value where the sign bit is
107
  * is placed in the least significant bit. For example, as decimals:
108
+ * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
109
+ * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
110
  * We assume that the value was generated with a 32 bit machine in mind.
111
  * Hence
112
+ * 1 becomes -2147483648
113
  * even on a 64 bit machine.
114
+ *
115
  * @param integer $aValue
116
  */
117
+ public function fromVLQSigned($aValue)
118
+ {
119
  return $aValue & 1 ? $this->zeroFill(~$aValue + 2, 1) | (-1 - 0x7fffffff) : $this->zeroFill($aValue, 1);
120
  }
121
+
122
  /**
123
  * Return the base 64 VLQ encoded value.
124
  *
125
  * @param string $aValue The value to encode
126
+ *
127
  * @return string The encoded value
128
  */
129
+ public function encode($aValue)
130
+ {
131
  $encoded = '';
132
  $vlq = $this->toVLQSigned($aValue);
133
+
134
+ do {
135
  $digit = $vlq & $this->mask;
136
  $vlq = $this->zeroFill($vlq, $this->shift);
137
+
138
+ if ($vlq > 0) {
139
  $digit |= $this->continuationBit;
140
  }
141
+
142
  $encoded .= $this->base64Encode($digit);
143
+ } while ($vlq > 0);
144
+
145
  return $encoded;
146
  }
147
+
148
  /**
149
  * Return the value decoded from base 64 VLQ.
150
  *
151
  * @param string $encoded The encoded value to decode
152
+ *
153
  * @return integer The decoded value
154
  */
155
+ public function decode($encoded)
156
+ {
157
  $vlq = 0;
158
  $i = 0;
159
+
160
+ do {
161
  $digit = $this->base64Decode($encoded[$i]);
162
  $vlq |= ($digit & $this->mask) << ($i * $this->shift);
163
  $i++;
164
+ } while ($digit & $this->continuationBit);
165
+
166
  return $this->fromVLQSigned($vlq);
167
  }
168
+
169
  /**
170
  * Right shift with zero fill.
171
  *
172
  * @param integer $a number to shift
173
  * @param integer $b number of bits to shift
174
+ *
175
  * @return integer
176
  */
177
+ public function zeroFill($a, $b)
178
+ {
179
  return ($a >= 0) ? ($a >> $b) : ($a >> $b) & (PHP_INT_MAX >> ($b - 1));
180
  }
181
+
182
  /**
183
  * Encode single 6-bit digit as base64.
184
  *
185
  * @param integer $number
186
+ *
187
  * @return string
188
+ *
189
+ * @throws \Exception If the number is invalid
190
  */
191
+ public function base64Encode($number)
192
+ {
193
+ if ($number < 0 || $number > 63) {
194
+ throw new \Exception(sprintf('Invalid number "%s" given. Must be between 0 and 63.', $number));
195
  }
196
+
197
  return $this->intToCharMap[$number];
198
  }
199
+
200
  /**
201
  * Decode single 6-bit digit from base64
202
  *
203
  * @param string $char
204
+ *
205
+ * @return integer
206
+ *
207
+ * @throws \Exception If the number is invalid
208
  */
209
+ public function base64Decode($char)
210
+ {
211
+ if (! array_key_exists($char, $this->charToIntMap)) {
212
+ throw new \Exception(sprintf('Invalid base 64 digit "%s" given.', $char));
213
  }
214
+
215
  return $this->charToIntMap[$char];
216
  }
217
  }
scssphp/src/SourceMap/SourceMapGenerator.php CHANGED
@@ -1,20 +1,33 @@
1
  <?php
2
  /**
3
- * Created by PhpStorm.
4
- * User: nico
5
- * Date: 08/11/17
6
- * Time: 19:16
 
 
 
7
  */
8
 
9
  namespace Leafo\ScssPhp\SourceMap;
10
 
11
  use Leafo\ScssPhp\Exception\CompilerException;
12
 
13
- class SourceMapGenerator {
 
 
 
 
 
 
 
 
 
14
  /**
15
  * What version of source map does the generator generate?
16
  */
17
  const VERSION = 3;
 
18
  /**
19
  * Array of default options
20
  *
@@ -25,16 +38,22 @@ class SourceMapGenerator {
25
  // on a server or removing repeated values in the 'sources' entry.
26
  // This value is prepended to the individual entries in the 'source' field.
27
  'sourceRoot' => '',
 
28
  // an optional name of the generated code that this source map is associated with.
29
  'sourceMapFilename' => null,
 
30
  // url of the map
31
  'sourceMapURL' => null,
 
32
  // absolute path to a file to write the map to
33
  'sourceMapWriteTo' => null,
 
34
  // output source contents?
35
  'outputSourceFiles' => false,
 
36
  // base path for filename normalization
37
  'sourceMapRootpath' => '',
 
38
  // base path for filename normalization
39
  'sourceMapBasepath' => ''
40
  );
@@ -42,9 +61,10 @@ class SourceMapGenerator {
42
  /**
43
  * The base64 VLQ encoder
44
  *
45
- * @var Base64VLQEncoder
46
  */
47
  protected $encoder;
 
48
  /**
49
  * Array of mappings
50
  *
@@ -58,6 +78,7 @@ class SourceMapGenerator {
58
  * @var array
59
  */
60
  protected $contentsMap = array();
 
61
  /**
62
  * File to content map
63
  *
@@ -65,12 +86,14 @@ class SourceMapGenerator {
65
  */
66
  protected $sources = array();
67
  protected $source_keys = array();
 
68
  /**
69
  * @var array
70
  */
71
  private $options;
72
 
73
- public function __construct(array $options = []) {
 
74
  $this->options = array_merge($this->defaultOptions, $options);
75
  $this->encoder = new Base64VLQEncoder();
76
  }
@@ -78,13 +101,14 @@ class SourceMapGenerator {
78
  /**
79
  * Adds a mapping
80
  *
81
- * @param integer $generatedLine The line number in generated file
82
  * @param integer $generatedColumn The column number in generated file
83
- * @param integer $originalLine The line number in original file
84
- * @param integer $originalColumn The column number in original file
85
- * @param string $sourceFile The original source file
86
  */
87
- public function addMapping($generatedLine, $generatedColumn, $originalLine, $originalColumn, $sourceFile) {
 
88
  $this->mappings[] = array(
89
  'generated_line' => $generatedLine,
90
  'generated_column' => $generatedColumn,
@@ -97,67 +121,87 @@ class SourceMapGenerator {
97
  }
98
 
99
  /**
100
- * Saves the source map to a file
101
- *
102
- * @param string $file The absolute path to a file
103
- * @param string $content The content to write
104
- * @throws Exception If the file could not be saved
105
- */
106
- public function saveMap($content){
107
- $file = $this->options['sourceMapWriteTo'];
108
- $dir = dirname($file);
109
- // directory does not exist
110
- if( !is_dir($dir) ){
111
- // FIXME: create the dir automatically?
112
- throw new CompilerException(sprintf('The directory "%s" does not exist. Cannot save the source map.', $dir));
113
- }
114
- // FIXME: proper saving, with dir write check!
115
- if(file_put_contents($file, $content) === false){
116
- throw new CompilerException(sprintf('Cannot save the source map to "%s"', $file));
117
- }
118
- return $this->options['sourceMapURL'];
119
- }
 
 
 
 
 
120
 
121
  /**
122
  * Generates the JSON source map
123
  *
124
  * @return string
 
125
  * @see https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#
126
  */
127
- public function generateJson() {
 
128
  $sourceMap = array();
129
- $mappings = $this->generateMappings();
 
130
  // File version (always the first entry in the object) and must be a positive integer.
131
  $sourceMap['version'] = self::VERSION;
 
132
  // An optional name of the generated code that this source map is associated with.
133
  $file = $this->options['sourceMapFilename'];
134
- if($file) {
 
135
  $sourceMap['file'] = $file;
136
  }
137
- // An optional source root, useful for relocating source files on a server or removing repeated values in the 'sources' entry. This value is prepended to the individual entries in the 'source' field.
 
 
138
  $root = $this->options['sourceRoot'];
139
- if($root) {
 
140
  $sourceMap['sourceRoot'] = $root;
141
  }
 
142
  // A list of original sources used by the 'mappings' entry.
143
  $sourceMap['sources'] = array();
144
- foreach($this->sources as $source_uri => $source_filename) {
 
145
  $sourceMap['sources'][] = $this->normalizeFilename($source_filename);
146
  }
 
147
  // A list of symbol names used by the 'mappings' entry.
148
  $sourceMap['names'] = array();
 
149
  // A string with the encoded mapping data.
150
  $sourceMap['mappings'] = $mappings;
151
- if($this->options['outputSourceFiles']) {
 
152
  // An optional list of source content, useful when the 'source' can't be hosted.
153
  // The contents are listed in the same order as the sources above.
154
  // 'null' may be used if some original sources should be retrieved by name.
155
  $sourceMap['sourcesContent'] = $this->getSourcesContent();
156
  }
 
157
  // less.js compat fixes
158
- if(count($sourceMap['sources']) && empty($sourceMap['sourceRoot'])) {
159
  unset($sourceMap['sourceRoot']);
160
  }
 
161
  return json_encode($sourceMap);
162
  }
163
 
@@ -166,14 +210,18 @@ class SourceMapGenerator {
166
  *
167
  * @return array|null
168
  */
169
- protected function getSourcesContent() {
170
- if(empty($this->sources)) {
 
171
  return null;
172
  }
 
173
  $content = array();
174
- foreach($this->sources as $sourceFile) {
 
175
  $content[] = file_get_contents($sourceFile);
176
  }
 
177
  return $content;
178
  }
179
 
@@ -182,31 +230,41 @@ class SourceMapGenerator {
182
  *
183
  * @return string
184
  */
185
- public function generateMappings() {
186
- if(!count($this->mappings)) {
 
187
  return '';
188
  }
 
189
  $this->source_keys = array_flip(array_keys($this->sources));
 
190
  // group mappings by generated line number.
191
  $groupedMap = $groupedMapEncoded = array();
192
- foreach($this->mappings as $m) {
 
193
  $groupedMap[$m['generated_line']][] = $m;
194
  }
 
195
  ksort($groupedMap);
196
  $lastGeneratedLine = $lastOriginalIndex = $lastOriginalLine = $lastOriginalColumn = 0;
197
- foreach($groupedMap as $lineNumber => $line_map) {
198
- while(++$lastGeneratedLine < $lineNumber) {
 
199
  $groupedMapEncoded[] = ';';
200
  }
 
201
  $lineMapEncoded = array();
202
  $lastGeneratedColumn = 0;
203
- foreach($line_map as $m) {
 
204
  $mapEncoded = $this->encoder->encode($m['generated_column'] - $lastGeneratedColumn);
205
  $lastGeneratedColumn = $m['generated_column'];
 
206
  // find the index
207
- if($m['source_file']) {
208
  $index = $this->findFileIndex($m['source_file']);
209
- if($index !== false) {
 
210
  $mapEncoded .= $this->encoder->encode($index - $lastOriginalIndex);
211
  $lastOriginalIndex = $index;
212
  // lines are stored 0-based in SourceMap spec version 3
@@ -216,10 +274,13 @@ class SourceMapGenerator {
216
  $lastOriginalColumn = $m['original_column'];
217
  }
218
  }
 
219
  $lineMapEncoded[] = $mapEncoded;
220
  }
 
221
  $groupedMapEncoded[] = implode(',', $lineMapEncoded) . ';';
222
  }
 
223
  return rtrim(implode($groupedMapEncoded), ';');
224
  }
225
 
@@ -227,39 +288,50 @@ class SourceMapGenerator {
227
  * Finds the index for the filename
228
  *
229
  * @param string $filename
 
230
  * @return integer|false
231
  */
232
- protected function findFileIndex($filename) {
 
233
  return $this->source_keys[$filename];
234
  }
235
 
236
- protected function normalizeFilename($filename) {
 
237
  $filename = $this->fixWindowsPath($filename);
238
  $rootpath = $this->options['sourceMapRootpath'];
239
  $basePath = $this->options['sourceMapBasepath'];
 
240
  // "Trim" the 'sourceMapBasepath' from the output filename.
241
- if(strpos($filename, $basePath) === 0) {
242
  $filename = substr($filename, strlen($basePath));
243
  }
 
244
  // Remove extra leading path separators.
245
- if(strpos($filename, '\\') === 0 || strpos($filename, '/') === 0) {
246
  $filename = substr($filename, 1);
247
  }
 
248
  return $rootpath . $filename;
249
  }
250
 
251
  /**
252
- * fix windows paths
253
- * @param string $path
254
- * @param bool $addEndSlash
 
 
255
  * @return string
256
  */
257
- public function fixWindowsPath($path, $addEndSlash = false) {
 
258
  $slash = ($addEndSlash) ? '/' : '';
259
- if(!empty($path)) {
 
260
  $path = str_replace('\\', '/', $path);
261
  $path = rtrim($path, '/') . $slash;
262
  }
 
263
  return $path;
264
  }
265
  }
1
  <?php
2
  /**
3
+ * SCSSPHP
4
+ *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
+ *
7
+ * @license http://opensource.org/licenses/MIT MIT
8
+ *
9
+ * @link http://leafo.github.io/scssphp
10
  */
11
 
12
  namespace Leafo\ScssPhp\SourceMap;
13
 
14
  use Leafo\ScssPhp\Exception\CompilerException;
15
 
16
+ /**
17
+ * Source Map Generator
18
+ *
19
+ * {@internal Derivative of oyejorge/less.php's lib/SourceMap/Generator.php, relicensed with permission. }}
20
+ *
21
+ * @author Josh Schmidt <oyejorge@gmail.com>
22
+ * @author Nicolas FRANÇOIS <nicolas.francois@frog-labs.com>
23
+ */
24
+ class SourceMapGenerator
25
+ {
26
  /**
27
  * What version of source map does the generator generate?
28
  */
29
  const VERSION = 3;
30
+
31
  /**
32
  * Array of default options
33
  *
38
  // on a server or removing repeated values in the 'sources' entry.
39
  // This value is prepended to the individual entries in the 'source' field.
40
  'sourceRoot' => '',
41
+
42
  // an optional name of the generated code that this source map is associated with.
43
  'sourceMapFilename' => null,
44
+
45
  // url of the map
46
  'sourceMapURL' => null,
47
+
48
  // absolute path to a file to write the map to
49
  'sourceMapWriteTo' => null,
50
+
51
  // output source contents?
52
  'outputSourceFiles' => false,
53
+
54
  // base path for filename normalization
55
  'sourceMapRootpath' => '',
56
+
57
  // base path for filename normalization
58
  'sourceMapBasepath' => ''
59
  );
61
  /**
62
  * The base64 VLQ encoder
63
  *
64
+ * @var \Leafo\ScssPhp\SourceMap\Base64VLQEncoder
65
  */
66
  protected $encoder;
67
+
68
  /**
69
  * Array of mappings
70
  *
78
  * @var array
79
  */
80
  protected $contentsMap = array();
81
+
82
  /**
83
  * File to content map
84
  *
86
  */
87
  protected $sources = array();
88
  protected $source_keys = array();
89
+
90
  /**
91
  * @var array
92
  */
93
  private $options;
94
 
95
+ public function __construct(array $options = [])
96
+ {
97
  $this->options = array_merge($this->defaultOptions, $options);
98
  $this->encoder = new Base64VLQEncoder();
99
  }
101
  /**
102
  * Adds a mapping
103
  *
104
+ * @param integer $generatedLine The line number in generated file
105
  * @param integer $generatedColumn The column number in generated file
106
+ * @param integer $originalLine The line number in original file
107
+ * @param integer $originalColumn The column number in original file
108
+ * @param string $sourceFile The original source file
109
  */
110
+ public function addMapping($generatedLine, $generatedColumn, $originalLine, $originalColumn, $sourceFile)
111
+ {
112
  $this->mappings[] = array(
113
  'generated_line' => $generatedLine,
114
  'generated_column' => $generatedColumn,
121
  }
122
 
123
  /**
124
+ * Saves the source map to a file
125
+ *
126
+ * @param string $file The absolute path to a file
127
+ * @param string $content The content to write
128
+ *
129
+ * @throws \Leafo\ScssPhp\Exception\CompilerException If the file could not be saved
130
+ */
131
+ public function saveMap($content)
132
+ {
133
+ $file = $this->options['sourceMapWriteTo'];
134
+ $dir = dirname($file);
135
+
136
+ // directory does not exist
137
+ if (! is_dir($dir)) {
138
+ // FIXME: create the dir automatically?
139
+ throw new CompilerException(sprintf('The directory "%s" does not exist. Cannot save the source map.', $dir));
140
+ }
141
+
142
+ // FIXME: proper saving, with dir write check!
143
+ if (file_put_contents($file, $content) === false) {
144
+ throw new CompilerException(sprintf('Cannot save the source map to "%s"', $file));
145
+ }
146
+
147
+ return $this->options['sourceMapURL'];
148
+ }
149
 
150
  /**
151
  * Generates the JSON source map
152
  *
153
  * @return string
154
+ *
155
  * @see https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#
156
  */
157
+ public function generateJson()
158
+ {
159
  $sourceMap = array();
160
+ $mappings = $this->generateMappings();
161
+
162
  // File version (always the first entry in the object) and must be a positive integer.
163
  $sourceMap['version'] = self::VERSION;
164
+
165
  // An optional name of the generated code that this source map is associated with.
166
  $file = $this->options['sourceMapFilename'];
167
+
168
+ if ($file) {
169
  $sourceMap['file'] = $file;
170
  }
171
+
172
+ // An optional source root, useful for relocating source files on a server or removing repeated values in the
173
+ // 'sources' entry. This value is prepended to the individual entries in the 'source' field.
174
  $root = $this->options['sourceRoot'];
175
+
176
+ if ($root) {
177
  $sourceMap['sourceRoot'] = $root;
178
  }
179
+
180
  // A list of original sources used by the 'mappings' entry.
181
  $sourceMap['sources'] = array();
182
+
183
+ foreach ($this->sources as $source_uri => $source_filename) {
184
  $sourceMap['sources'][] = $this->normalizeFilename($source_filename);
185
  }
186
+
187
  // A list of symbol names used by the 'mappings' entry.
188
  $sourceMap['names'] = array();
189
+
190
  // A string with the encoded mapping data.
191
  $sourceMap['mappings'] = $mappings;
192
+
193
+ if ($this->options['outputSourceFiles']) {
194
  // An optional list of source content, useful when the 'source' can't be hosted.
195
  // The contents are listed in the same order as the sources above.
196
  // 'null' may be used if some original sources should be retrieved by name.
197
  $sourceMap['sourcesContent'] = $this->getSourcesContent();
198
  }
199
+
200
  // less.js compat fixes
201
+ if (count($sourceMap['sources']) && empty($sourceMap['sourceRoot'])) {
202
  unset($sourceMap['sourceRoot']);
203
  }
204
+
205
  return json_encode($sourceMap);
206
  }
207
 
210
  *
211
  * @return array|null
212
  */
213
+ protected function getSourcesContent()
214
+ {
215
+ if (empty($this->sources)) {
216
  return null;
217
  }
218
+
219
  $content = array();
220
+
221
+ foreach ($this->sources as $sourceFile) {
222
  $content[] = file_get_contents($sourceFile);
223
  }
224
+
225
  return $content;
226
  }
227
 
230
  *
231
  * @return string
232
  */
233
+ public function generateMappings()
234
+ {
235
+ if (! count($this->mappings)) {
236
  return '';
237
  }
238
+
239
  $this->source_keys = array_flip(array_keys($this->sources));
240
+
241
  // group mappings by generated line number.
242
  $groupedMap = $groupedMapEncoded = array();
243
+
244
+ foreach ($this->mappings as $m) {
245
  $groupedMap[$m['generated_line']][] = $m;
246
  }
247
+
248
  ksort($groupedMap);
249
  $lastGeneratedLine = $lastOriginalIndex = $lastOriginalLine = $lastOriginalColumn = 0;
250
+
251
+ foreach ($groupedMap as $lineNumber => $line_map) {
252
+ while (++$lastGeneratedLine < $lineNumber) {
253
  $groupedMapEncoded[] = ';';
254
  }
255
+
256
  $lineMapEncoded = array();
257
  $lastGeneratedColumn = 0;
258
+
259
+ foreach ($line_map as $m) {
260
  $mapEncoded = $this->encoder->encode($m['generated_column'] - $lastGeneratedColumn);
261
  $lastGeneratedColumn = $m['generated_column'];
262
+
263
  // find the index
264
+ if ($m['source_file']) {
265
  $index = $this->findFileIndex($m['source_file']);
266
+
267
+ if ($index !== false) {
268
  $mapEncoded .= $this->encoder->encode($index - $lastOriginalIndex);
269
  $lastOriginalIndex = $index;
270
  // lines are stored 0-based in SourceMap spec version 3
274
  $lastOriginalColumn = $m['original_column'];
275
  }
276
  }
277
+
278
  $lineMapEncoded[] = $mapEncoded;
279
  }
280
+
281
  $groupedMapEncoded[] = implode(',', $lineMapEncoded) . ';';
282
  }
283
+
284
  return rtrim(implode($groupedMapEncoded), ';');
285
  }
286
 
288
  * Finds the index for the filename
289
  *
290
  * @param string $filename
291
+ *
292
  * @return integer|false
293
  */
294
+ protected function findFileIndex($filename)
295
+ {
296
  return $this->source_keys[$filename];
297
  }
298
 
299
+ protected function normalizeFilename($filename)
300
+ {
301
  $filename = $this->fixWindowsPath($filename);
302
  $rootpath = $this->options['sourceMapRootpath'];
303
  $basePath = $this->options['sourceMapBasepath'];
304
+
305
  // "Trim" the 'sourceMapBasepath' from the output filename.
306
+ if (strpos($filename, $basePath) === 0) {
307
  $filename = substr($filename, strlen($basePath));
308
  }
309
+
310
  // Remove extra leading path separators.
311
+ if (strpos($filename, '\\') === 0 || strpos($filename, '/') === 0) {
312
  $filename = substr($filename, 1);
313
  }
314
+
315
  return $rootpath . $filename;
316
  }
317
 
318
  /**
319
+ * Fix windows paths
320
+ *
321
+ * @param string $path
322
+ * @param boolean $addEndSlash
323
+ *
324
  * @return string
325
  */
326
+ public function fixWindowsPath($path, $addEndSlash = false)
327
+ {
328
  $slash = ($addEndSlash) ? '/' : '';
329
+
330
+ if (! empty($path)) {
331
  $path = str_replace('\\', '/', $path);
332
  $path = rtrim($path, '/') . $slash;
333
  }
334
+
335
  return $path;
336
  }
337
  }
scssphp/src/Type.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
scssphp/src/Util.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
@@ -15,7 +15,7 @@ use Leafo\ScssPhp\Base\Range;
15
  use Leafo\ScssPhp\Exception\RangeException;
16
 
17
  /**
18
- * Utilties
19
  *
20
  * @author Anthon Pang <anthon.pang@gmail.com>
21
  */
@@ -25,10 +25,10 @@ class Util
25
  * Asserts that `value` falls within `range` (inclusive), leaving
26
  * room for slight floating-point errors.
27
  *
28
- * @param string $name The name of the value. Used in the error message.
29
- * @param Range $range Range of values.
30
- * @param array $value The value to check.
31
- * @param string $unit The unit of the value. Used in error reporting.
32
  *
33
  * @return mixed `value` adjusted to fall within range, if it was outside by a floating-point margin.
34
  *
@@ -53,4 +53,18 @@ class Util
53
 
54
  throw new RangeException("$name {$val} must be between {$range->first} and {$range->last}$unit");
55
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  }
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
15
  use Leafo\ScssPhp\Exception\RangeException;
16
 
17
  /**
18
+ * Utilty functions
19
  *
20
  * @author Anthon Pang <anthon.pang@gmail.com>
21
  */
25
  * Asserts that `value` falls within `range` (inclusive), leaving
26
  * room for slight floating-point errors.
27
  *
28
+ * @param string $name The name of the value. Used in the error message.
29
+ * @param \Leafo\ScssPhp\Base\Range $range Range of values.
30
+ * @param array $value The value to check.
31
+ * @param string $unit The unit of the value. Used in error reporting.
32
  *
33
  * @return mixed `value` adjusted to fall within range, if it was outside by a floating-point margin.
34
  *
53
 
54
  throw new RangeException("$name {$val} must be between {$range->first} and {$range->last}$unit");
55
  }
56
+
57
+ /**
58
+ * Encode URI component
59
+ *
60
+ * @param string $string
61
+ *
62
+ * @return string
63
+ */
64
+ public static function encodeURIComponent($string)
65
+ {
66
+ $revert = array('%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')');
67
+
68
+ return strtr(rawurlencode($string), $revert);
69
+ }
70
  }
scssphp/src/Version.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * SCSSPHP
4
  *
5
- * @copyright 2012-2017 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
@@ -18,5 +18,5 @@ namespace Leafo\ScssPhp;
18
  */
19
  class Version
20
  {
21
- const VERSION = 'v0.7.2';
22
  }
2
  /**
3
  * SCSSPHP
4
  *
5
+ * @copyright 2012-2018 Leaf Corcoran
6
  *
7
  * @license http://opensource.org/licenses/MIT MIT
8
  *
18
  */
19
  class Version
20
  {
21
+ const VERSION = 'v0.7.5';
22
  }
wp-scss.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: WP-SCSS
4
  * Plugin URI: https://github.com/ConnectThink/WP-SCSS
5
  * Description: Compiles scss files live on WordPress.
6
- * Version: 1.2.3
7
  * Author: Connect Think
8
  * Author URI: http://connectthink.com
9
  * License: GPLv3
@@ -46,7 +46,7 @@ if (!defined('WPSCSS_VERSION_KEY'))
46
  define('WPSCSS_VERSION_KEY', 'wpscss_version');
47
 
48
  if (!defined('WPSCSS_VERSION_NUM'))
49
- define('WPSCSS_VERSION_NUM', '1.2.3');
50
 
51
  // Add version to options table
52
  if ( get_option( WPSCSS_VERSION_KEY ) !== false ) {
@@ -113,8 +113,8 @@ function wpscss_plugin_action_links($links, $file) {
113
  */
114
 
115
  $wpscss_options = get_option( 'wpscss_options' );
116
- $scss_dir_setting = $wpscss_options['scss_dir'];
117
- $css_dir_setting = $wpscss_options['css_dir'];
118
 
119
  // Checks if directories are empty
120
  if( $scss_dir_setting == false || $css_dir_setting == false ) {
@@ -139,11 +139,12 @@ if( $scss_dir_setting == false || $css_dir_setting == false ) {
139
 
140
  // Plugin Settings
141
  $wpscss_settings = array(
142
- 'scss_dir' => WPSCSS_THEME_DIR . $scss_dir_setting,
143
- 'css_dir' => WPSCSS_THEME_DIR . $css_dir_setting,
144
- 'compiling' => $wpscss_options['compiling_options'],
145
- 'errors' => $wpscss_options['errors'],
146
- 'enqueue' => isset($wpscss_options['enqueue']) ? $wpscss_options['enqueue'] : 0
 
147
  );
148
 
149
 
@@ -154,10 +155,12 @@ $wpscss_settings = array(
154
  * If needs_compiling passes, runs compile method
155
  */
156
 
 
157
  $wpscss_compiler = new Wp_Scss(
158
  $wpscss_settings['scss_dir'],
159
  $wpscss_settings['css_dir'],
160
- $wpscss_settings['compiling']
 
161
  );
162
 
163
  //wp_scss_needs_compiling() needs to be run as wp_head-action to make it possible
3
  * Plugin Name: WP-SCSS
4
  * Plugin URI: https://github.com/ConnectThink/WP-SCSS
5
  * Description: Compiles scss files live on WordPress.
6
+ * Version: 1.2.4
7
  * Author: Connect Think
8
  * Author URI: http://connectthink.com
9
  * License: GPLv3
46
  define('WPSCSS_VERSION_KEY', 'wpscss_version');
47
 
48
  if (!defined('WPSCSS_VERSION_NUM'))
49
+ define('WPSCSS_VERSION_NUM', '1.2.4');
50
 
51
  // Add version to options table
52
  if ( get_option( WPSCSS_VERSION_KEY ) !== false ) {
113
  */
114
 
115
  $wpscss_options = get_option( 'wpscss_options' );
116
+ $scss_dir_setting = isset($wpscss_options['scss_dir']) ? $wpscss_options['scss_dir'] : '';
117
+ $css_dir_setting = isset($wpscss_options['css_dir']) ? $wpscss_options['css_dir'] : '';
118
 
119
  // Checks if directories are empty
120
  if( $scss_dir_setting == false || $css_dir_setting == false ) {
139
 
140
  // Plugin Settings
141
  $wpscss_settings = array(
142
+ 'scss_dir' => WPSCSS_THEME_DIR . $scss_dir_setting,
143
+ 'css_dir' => WPSCSS_THEME_DIR . $css_dir_setting,
144
+ 'compiling' => isset($wpscss_options['compiling_options']) ? $wpscss_options['compiling_options'] : 'Leafo\ScssPhp\Formatter\Expanded',
145
+ 'errors' => isset($wpscss_options['errors']) ? $wpscss_options['errors'] : 'show',
146
+ 'sourcemaps' => isset($wpscss_options['sourcemap_options']) ? $wpscss_options['sourcemap_options'] : 'SOURCE_MAP_NONE',
147
+ 'enqueue' => isset($wpscss_options['enqueue']) ? $wpscss_options['enqueue'] : 0
148
  );
149
 
150
 
155
  * If needs_compiling passes, runs compile method
156
  */
157
 
158
+ global $wpscss_compiler;
159
  $wpscss_compiler = new Wp_Scss(
160
  $wpscss_settings['scss_dir'],
161
  $wpscss_settings['css_dir'],
162
+ $wpscss_settings['compiling'],
163
+ $wpscss_settings['sourcemaps']
164
  );
165
 
166
  //wp_scss_needs_compiling() needs to be run as wp_head-action to make it possible