|
18 | 18 | use Leafo\ScssPhp\Exception\CompilerException; |
19 | 19 | use Leafo\ScssPhp\Formatter\OutputBlock; |
20 | 20 | use Leafo\ScssPhp\Node; |
| 21 | +use Leafo\ScssPhp\SourceMap\SourceMapGenerator; |
21 | 22 | use Leafo\ScssPhp\Type; |
22 | 23 | use Leafo\ScssPhp\Parser; |
23 | 24 | use Leafo\ScssPhp\Util; |
@@ -64,6 +65,9 @@ class Compiler |
64 | 65 | const WITH_SUPPORTS = 4; |
65 | 66 | const WITH_ALL = 7; |
66 | 67 |
|
| 68 | + const SOURCE_MAP_NONE = 0; |
| 69 | + const SOURCE_MAP_INLINE = 1; |
| 70 | + |
67 | 71 | /** |
68 | 72 | * @var array |
69 | 73 | */ |
@@ -120,11 +124,16 @@ class Compiler |
120 | 124 | protected $encoding = null; |
121 | 125 | protected $lineNumberStyle = null; |
122 | 126 |
|
| 127 | + protected $sourceMap = self::SOURCE_MAP_NONE; |
| 128 | + protected $sourceMapOptions = []; |
| 129 | + |
| 130 | + /** @var string|Formatter */ |
123 | 131 | protected $formatter = 'Leafo\ScssPhp\Formatter\Nested'; |
124 | 132 |
|
125 | 133 | protected $rootEnv; |
126 | 134 | protected $rootBlock; |
127 | 135 |
|
| 136 | + /** @var Environment */ |
128 | 137 | protected $env; |
129 | 138 | protected $scope; |
130 | 139 | protected $storeEnv; |
@@ -191,8 +200,21 @@ public function compile($code, $path = null) |
191 | 200 | $this->compileRoot($tree); |
192 | 201 | $this->popEnv(); |
193 | 202 |
|
194 | | - $out = $this->formatter->format($this->scope); |
| 203 | + $sourceMapGenerator = null; |
| 204 | + if($this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) { |
| 205 | + $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions); |
| 206 | + } |
| 207 | + $out = $this->formatter->format($this->scope, $sourceMapGenerator); |
| 208 | + if($this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) { |
| 209 | + $sourceMap = $sourceMapGenerator->generateJson(); |
| 210 | + |
| 211 | + $sourceMapUrl = null; |
| 212 | + if($this->sourceMap == self::SOURCE_MAP_INLINE) { |
| 213 | + $sourceMapUrl = sprintf('data:application/json,%s', self::encodeURIComponent($sourceMap)); |
| 214 | + } |
195 | 215 |
|
| 216 | + $out .= sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl); |
| 217 | + } |
196 | 218 | return $out; |
197 | 219 | } |
198 | 220 |
|
@@ -274,6 +296,9 @@ protected function makeOutputBlock($type, $selectors = null) |
274 | 296 | $out->parent = $this->scope; |
275 | 297 | $out->selectors = $selectors; |
276 | 298 | $out->depth = $this->env->depth; |
| 299 | + $out->sourceName = $this->env->block->sourceName; |
| 300 | + $out->sourceLine = $this->env->block->sourceLine; |
| 301 | + $out->sourceColumn = $this->env->block->sourceColumn; |
277 | 302 |
|
278 | 303 | return $out; |
279 | 304 | } |
@@ -656,6 +681,7 @@ protected function compileMedia(Block $media) |
656 | 681 |
|
657 | 682 | if ($needsWrap) { |
658 | 683 | $wrapped = new Block; |
| 684 | + $wrapped->sourceName = $media->sourceName; |
659 | 685 | $wrapped->sourceIndex = $media->sourceIndex; |
660 | 686 | $wrapped->sourceLine = $media->sourceLine; |
661 | 687 | $wrapped->sourceColumn = $media->sourceColumn; |
@@ -729,6 +755,7 @@ protected function compileAtRoot(Block $block) |
729 | 755 | // wrap inline selector |
730 | 756 | if ($block->selector) { |
731 | 757 | $wrapped = new Block; |
| 758 | + $wrapped->sourceName = $block->sourceName; |
732 | 759 | $wrapped->sourceIndex = $block->sourceIndex; |
733 | 760 | $wrapped->sourceLine = $block->sourceLine; |
734 | 761 | $wrapped->sourceColumn = $block->sourceColumn; |
@@ -785,6 +812,7 @@ private function spliceTree($envs, Block $block, $without) |
785 | 812 | } |
786 | 813 |
|
787 | 814 | $b = new Block; |
| 815 | + $b->sourceName = $e->block->sourceName; |
788 | 816 | $b->sourceIndex = $e->block->sourceIndex; |
789 | 817 | $b->sourceLine = $e->block->sourceLine; |
790 | 818 | $b->sourceColumn = $e->block->sourceColumn; |
@@ -1076,6 +1104,13 @@ protected function evalSelectors($selectors) |
1076 | 1104 | return $selectors; |
1077 | 1105 | } |
1078 | 1106 |
|
| 1107 | + /** |
| 1108 | + * @param array $sourceMapOptions |
| 1109 | + */ |
| 1110 | + public function setSourceMapOptions($sourceMapOptions) { |
| 1111 | + $this->sourceMapOptions = $sourceMapOptions; |
| 1112 | + } |
| 1113 | + |
1079 | 1114 | /** |
1080 | 1115 | * Evaluate selector |
1081 | 1116 | * |
@@ -3299,6 +3334,13 @@ public function setLineNumberStyle($lineNumberStyle) |
3299 | 3334 | $this->lineNumberStyle = $lineNumberStyle; |
3300 | 3335 | } |
3301 | 3336 |
|
| 3337 | + /** |
| 3338 | + * @param int $sourceMap |
| 3339 | + */ |
| 3340 | + public function setSourceMap($sourceMap) { |
| 3341 | + $this->sourceMap = $sourceMap; |
| 3342 | + } |
| 3343 | + |
3302 | 3344 | /** |
3303 | 3345 | * Register function |
3304 | 3346 | * |
@@ -5256,4 +5298,9 @@ protected function libInspect($args) |
5256 | 5298 |
|
5257 | 5299 | return $args[0]; |
5258 | 5300 | } |
| 5301 | + |
| 5302 | + public static function encodeURIComponent($string){ |
| 5303 | + $revert = array('%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')'); |
| 5304 | + return strtr(rawurlencode($string), $revert); |
| 5305 | + } |
5259 | 5306 | } |
0 commit comments