diff --git a/bin/pscss b/bin/pscss index ce80e6a9..70a2be3c 100755 --- a/bin/pscss +++ b/bin/pscss @@ -32,7 +32,6 @@ $debugInfo = false; $lineNumbers = false; $ignoreErrors = false; $encoding = false; -$sourceMap = false; /** * Parse argument @@ -78,7 +77,6 @@ Options include: --iso8859-1 Use iso8859-1 encoding instead of utf-8 (default utf-8) --line-numbers Annotate selectors with comments referring to the source file and line number -p=precision Set decimal number precision (default 10) - --sourcemap Create source map file -T Dump formatted parse tree -v, --version Print the version @@ -110,11 +108,6 @@ EOT; continue; } - if ($argv[$i] === '--sourcemap') { - $sourceMap = true; - continue; - } - if ($argv[$i] === '-T') { $dumpTree = true; continue; @@ -200,10 +193,6 @@ if ($style) { $scss->setFormatter('Leafo\\ScssPhp\\Formatter\\' . ucfirst($style)); } -if ($sourceMap) { - $scss->setSourceMap(Compiler::SOURCE_MAP_INLINE); -} - if ($encoding) { $scss->setEncoding($encoding); } diff --git a/scss.inc.php b/scss.inc.php index d75ecb55..c6d68d56 100644 --- a/scss.inc.php +++ b/scss.inc.php @@ -24,9 +24,6 @@ include_once __DIR__ . '/src/Node.php'; include_once __DIR__ . '/src/Node/Number.php'; include_once __DIR__ . '/src/Parser.php'; - include_once __DIR__ . '/src/SourceMap/Base64.php'; - include_once __DIR__ . '/src/SourceMap/Base64VLQ.php'; - include_once __DIR__ . '/src/SourceMap/SourceMapGenerator.php'; include_once __DIR__ . '/src/Type.php'; include_once __DIR__ . '/src/Util.php'; include_once __DIR__ . '/src/Version.php'; diff --git a/src/Compiler.php b/src/Compiler.php index 75accf8e..34c164ec 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -18,7 +18,6 @@ use Leafo\ScssPhp\Exception\CompilerException; use Leafo\ScssPhp\Formatter\OutputBlock; use Leafo\ScssPhp\Node; -use Leafo\ScssPhp\SourceMap\SourceMapGenerator; use Leafo\ScssPhp\Type; use Leafo\ScssPhp\Parser; use Leafo\ScssPhp\Util; @@ -125,9 +124,6 @@ class Compiler protected $encoding = null; protected $lineNumberStyle = null; - protected $sourceMap = self::SOURCE_MAP_NONE; - protected $sourceMapOptions = []; - /** * @var string|\Leafo\ScssPhp\Formatter */ @@ -153,7 +149,6 @@ class Compiler protected $sourceIndex; protected $sourceLine; protected $sourceColumn; - protected $stderr; protected $shouldEvaluate; protected $ignoreErrors; @@ -191,7 +186,6 @@ public function compile($code, $path = null) $this->storeEnv = null; $this->charsetSeen = null; $this->shouldEvaluate = null; - $this->stderr = fopen('php://stderr', 'w'); $this->parser = $this->parserFactory($path); $tree = $this->parser->parse($code); @@ -205,35 +199,7 @@ public function compile($code, $path = null) $this->compileRoot($tree); $this->popEnv(); - $sourceMapGenerator = null; - - if ($this->sourceMap) { - if (is_object($this->sourceMap) && $this->sourceMap instanceof SourceMapGenerator) { - $sourceMapGenerator = $this->sourceMap; - $this->sourceMap = self::SOURCE_MAP_FILE; - } elseif ($this->sourceMap !== self::SOURCE_MAP_NONE) { - $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions); - } - } - - $out = $this->formatter->format($this->scope, $sourceMapGenerator); - - if (! empty($out) && $this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) { - $sourceMap = $sourceMapGenerator->generateJson(); - $sourceMapUrl = null; - - switch ($this->sourceMap) { - case self::SOURCE_MAP_INLINE: - $sourceMapUrl = sprintf('data:application/json,%s', Util::encodeURIComponent($sourceMap)); - break; - - case self::SOURCE_MAP_FILE: - $sourceMapUrl = $sourceMapGenerator->saveMap($sourceMap); - break; - } - - $out .= sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl); - } + $out = $this->formatter->format($this->scope); return $out; } @@ -2193,7 +2159,7 @@ protected function compileChild($child, OutputBlock $out) $fname = $this->sourceNames[$this->sourceIndex]; $line = $this->sourceLine; $value = $this->compileValue($this->reduce($value, true)); - fwrite($this->stderr, "File $fname on line $line DEBUG: $value\n"); + $this->throwError("File $fname on line $line DEBUG: $value\n"); break; case Type::T_WARN: @@ -2202,7 +2168,7 @@ protected function compileChild($child, OutputBlock $out) $fname = $this->sourceNames[$this->sourceIndex]; $line = $this->sourceLine; $value = $this->compileValue($this->reduce($value, true)); - fwrite($this->stderr, "File $fname on line $line WARN: $value\n"); + $this->throwError("File $fname on line $line WARN: $value\n"); break; case Type::T_ERROR: @@ -3709,30 +3675,6 @@ public function setLineNumberStyle($lineNumberStyle) $this->lineNumberStyle = $lineNumberStyle; } - /** - * Enable/disable source maps - * - * @api - * - * @param integer $sourceMap - */ - public function setSourceMap($sourceMap) - { - $this->sourceMap = $sourceMap; - } - - /** - * Set source map options - * - * @api - * - * @param array $sourceMapOptions - */ - public function setSourceMapOptions($sourceMapOptions) - { - $this->sourceMapOptions = $sourceMapOptions; - } - /** * Register function * @@ -3787,7 +3729,8 @@ protected function importFile($path, OutputBlock $out) $tree = $this->importCache[$realPath]; } else { - $code = file_get_contents($path); + $wpfs = new \Boldgrid_Framework_Wp_Fs(); + $code = $wpfs->get_contents($path); $parser = $this->parserFactory($path); $tree = $parser->parse($code); @@ -4023,7 +3966,7 @@ protected function callNativeFunction($name, $args, &$returnValue) return false; } - @list($sorted, $kwargs) = $this->sortArgs($prototype, $args); + list($sorted, $kwargs) = array_pad($this->sortArgs($prototype, $args), 2, null); if ($name !== 'if' && $name !== 'call') { foreach ($sorted as &$val) { diff --git a/src/Formatter.php b/src/Formatter.php index 1403859d..f634ae94 100644 --- a/src/Formatter.php +++ b/src/Formatter.php @@ -12,7 +12,6 @@ namespace Leafo\ScssPhp; use Leafo\ScssPhp\Formatter\OutputBlock; -use Leafo\ScssPhp\SourceMap\SourceMapGenerator; /** * Base formatter @@ -76,11 +75,6 @@ abstract class Formatter */ protected $currentColumn; - /** - * @var \Leafo\ScssPhp\SourceMap\SourceMapGenerator - */ - protected $sourceMapGenerator; - /** * Initialize formatter * @@ -223,20 +217,11 @@ protected function block(OutputBlock $block) * @api * * @param \Leafo\ScssPhp\Formatter\OutputBlock $block An abstract syntax tree - * @param \Leafo\ScssPhp\SourceMap\SourceMapGenerator|null $sourceMapGenerator Optional source map generator * * @return string */ - public function format(OutputBlock $block, SourceMapGenerator $sourceMapGenerator = null) + public function format(OutputBlock $block) { - $this->sourceMapGenerator = null; - - if ($sourceMapGenerator) { - $this->currentLine = 1; - $this->currentColumn = 0; - $this->sourceMapGenerator = $sourceMapGenerator; - } - ob_start(); $this->block($block); @@ -251,25 +236,6 @@ public function format(OutputBlock $block, SourceMapGenerator $sourceMapGenerato */ protected function write($str) { - if ($this->sourceMapGenerator) { - $this->sourceMapGenerator->addMapping( - $this->currentLine, - $this->currentColumn, - $this->currentBlock->sourceLine, - //columns from parser are off by one - $this->currentBlock->sourceColumn > 0 ? $this->currentBlock->sourceColumn - 1 : 0, - $this->currentBlock->sourceName - ); - - $lines = explode("\n", $str); - $lineCount = count($lines); - $this->currentLine += $lineCount-1; - - $lastLine = array_pop($lines); - - $this->currentColumn = ($lineCount === 1 ? $this->currentColumn : 0) + strlen($lastLine); - } - echo $str; } } diff --git a/src/SourceMap/Base64.php b/src/SourceMap/Base64.php deleted file mode 100644 index 54015bb9..00000000 --- a/src/SourceMap/Base64.php +++ /dev/null @@ -1,184 +0,0 @@ - - */ -class Base64 -{ - /** - * @var array - */ - private static $encodingMap = [ - 0 => 'A', - 1 => 'B', - 2 => 'C', - 3 => 'D', - 4 => 'E', - 5 => 'F', - 6 => 'G', - 7 => 'H', - 8 => 'I', - 9 => 'J', - 10 => 'K', - 11 => 'L', - 12 => 'M', - 13 => 'N', - 14 => 'O', - 15 => 'P', - 16 => 'Q', - 17 => 'R', - 18 => 'S', - 19 => 'T', - 20 => 'U', - 21 => 'V', - 22 => 'W', - 23 => 'X', - 24 => 'Y', - 25 => 'Z', - 26 => 'a', - 27 => 'b', - 28 => 'c', - 29 => 'd', - 30 => 'e', - 31 => 'f', - 32 => 'g', - 33 => 'h', - 34 => 'i', - 35 => 'j', - 36 => 'k', - 37 => 'l', - 38 => 'm', - 39 => 'n', - 40 => 'o', - 41 => 'p', - 42 => 'q', - 43 => 'r', - 44 => 's', - 45 => 't', - 46 => 'u', - 47 => 'v', - 48 => 'w', - 49 => 'x', - 50 => 'y', - 51 => 'z', - 52 => '0', - 53 => '1', - 54 => '2', - 55 => '3', - 56 => '4', - 57 => '5', - 58 => '6', - 59 => '7', - 60 => '8', - 61 => '9', - 62 => '+', - 63 => '/', - ]; - - /** - * @var array - */ - private static $decodingMap = [ - 'A' => 0, - 'B' => 1, - 'C' => 2, - 'D' => 3, - 'E' => 4, - 'F' => 5, - 'G' => 6, - 'H' => 7, - 'I' => 8, - 'J' => 9, - 'K' => 10, - 'L' => 11, - 'M' => 12, - 'N' => 13, - 'O' => 14, - 'P' => 15, - 'Q' => 16, - 'R' => 17, - 'S' => 18, - 'T' => 19, - 'U' => 20, - 'V' => 21, - 'W' => 22, - 'X' => 23, - 'Y' => 24, - 'Z' => 25, - 'a' => 26, - 'b' => 27, - 'c' => 28, - 'd' => 29, - 'e' => 30, - 'f' => 31, - 'g' => 32, - 'h' => 33, - 'i' => 34, - 'j' => 35, - 'k' => 36, - 'l' => 37, - 'm' => 38, - 'n' => 39, - 'o' => 40, - 'p' => 41, - 'q' => 42, - 'r' => 43, - 's' => 44, - 't' => 45, - 'u' => 46, - 'v' => 47, - 'w' => 48, - 'x' => 49, - 'y' => 50, - 'z' => 51, - 0 => 52, - 1 => 53, - 2 => 54, - 3 => 55, - 4 => 56, - 5 => 57, - 6 => 58, - 7 => 59, - 8 => 60, - 9 => 61, - '+' => 62, - '/' => 63, - ]; - - /** - * Convert to base64 - * - * @param integer $value - * - * @return string - */ - public static function encode($value) - { - return self::$encodingMap[$value]; - } - - /** - * Convert from base64 - * - * @param string $value - * - * @return integer - */ - public static function decode($value) - { - return self::$decodingMap[$value]; - } -} diff --git a/src/SourceMap/Base64VLQ.php b/src/SourceMap/Base64VLQ.php deleted file mode 100644 index 6de3b5ee..00000000 --- a/src/SourceMap/Base64VLQ.php +++ /dev/null @@ -1,137 +0,0 @@ - - * @author Anthon Pang - */ -class Base64VLQ -{ - // A Base64 VLQ digit can represent 5 bits, so it is base-32. - const VLQ_BASE_SHIFT = 5; - - // A mask of bits for a VLQ digit (11111), 31 decimal. - const VLQ_BASE_MASK = 31; - - // The continuation bit is the 6th bit. - const VLQ_CONTINUATION_BIT = 32; - - /** - * Returns the VLQ encoded value. - * - * @param integer $value - * - * @return string - */ - public static function encode($value) - { - $encoded = ''; - $vlq = self::toVLQSigned($value); - - do { - $digit = $vlq & self::VLQ_BASE_MASK; - $vlq >>= self::VLQ_BASE_SHIFT; - - if ($vlq > 0) { - $digit |= self::VLQ_CONTINUATION_BIT; - } - - $encoded .= Base64::encode($digit); - } while ($vlq > 0); - - return $encoded; - } - - /** - * Decodes VLQValue. - * - * @param string $str - * @param integer $index - * - * @return integer - */ - public static function decode($str, &$index) - { - $result = 0; - $shift = 0; - - do { - $c = $str[$index++]; - $digit = Base64::decode($c); - $continuation = ($digit & self::VLQ_CONTINUATION_BIT) != 0; - $digit &= self::VLQ_BASE_MASK; - $result = $result + ($digit << $shift); - $shift = $shift + self::VLQ_BASE_SHIFT; - } while ($continuation); - - return self::fromVLQSigned($result); - } - - /** - * Converts from a two-complement value to a value where the sign bit is - * is placed in the least significant bit. For example, as decimals: - * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) - * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) - * - * @param integer $value - * - * @return integer - */ - private static function toVLQSigned($value) - { - if ($value < 0) { - return ((-$value) << 1) + 1; - } - - return ($value << 1) + 0; - } - - /** - * Converts to a two-complement value from a value where the sign bit is - * is placed in the least significant bit. For example, as decimals: - * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 - * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 - * - * @param integer $value - * - * @return integer - */ - private static function fromVLQSigned($value) - { - $negate = ($value & 1) === 1; - $value = $value >> 1; - - return $negate ? -$value : $value; - } -} diff --git a/src/SourceMap/Base64VLQEncoder.php b/src/SourceMap/Base64VLQEncoder.php deleted file mode 100644 index caf56c77..00000000 --- a/src/SourceMap/Base64VLQEncoder.php +++ /dev/null @@ -1,217 +0,0 @@ - - * @author Nicolas FRANÇOIS - */ -class Base64VLQEncoder -{ - /** - * Shift - * - * @var integer - */ - private $shift = 5; - - /** - * Mask - * - * @var integer - */ - private $mask = 0x1F; // == (1 << shift) == 0b00011111 - - /** - * Continuation bit - * - * @var integer - */ - private $continuationBit = 0x20; // == (mask - 1 ) == 0b00100000 - - /** - * Char to integer map - * - * @var array - */ - private $charToIntMap = [ - 'A' => 0, 'B' => 1, 'C' => 2, 'D' => 3, 'E' => 4, 'F' => 5, 'G' => 6, 'H' => 7, - 'I' => 8, 'J' => 9, 'K' => 10, 'L' => 11, 'M' => 12, 'N' => 13, 'O' => 14, 'P' => 15, - 'Q' => 16, 'R' => 17, 'S' => 18, 'T' => 19, 'U' => 20, 'V' => 21, 'W' => 22, 'X' => 23, - 'Y' => 24, 'Z' => 25, 'a' => 26, 'b' => 27, 'c' => 28, 'd' => 29, 'e' => 30, 'f' => 31, - 'g' => 32, 'h' => 33, 'i' => 34, 'j' => 35, 'k' => 36, 'l' => 37, 'm' => 38, 'n' => 39, - 'o' => 40, 'p' => 41, 'q' => 42, 'r' => 43, 's' => 44, 't' => 45, 'u' => 46, 'v' => 47, - 'w' => 48, 'x' => 49, 'y' => 50, 'z' => 51, 0 => 52, 1 => 53, 2 => 54, 3 => 55, - 4 => 56, 5 => 57, 6 => 58, 7 => 59, 8 => 60, 9 => 61, '+' => 62, '/' => 63, - ]; - - /** - * Integer to char map - * - * @var array - */ - private $intToCharMap = [ - 0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D', 4 => 'E', 5 => 'F', 6 => 'G', 7 => 'H', - 8 => 'I', 9 => 'J', 10 => 'K', 11 => 'L', 12 => 'M', 13 => 'N', 14 => 'O', 15 => 'P', - 16 => 'Q', 17 => 'R', 18 => 'S', 19 => 'T', 20 => 'U', 21 => 'V', 22 => 'W', 23 => 'X', - 24 => 'Y', 25 => 'Z', 26 => 'a', 27 => 'b', 28 => 'c', 29 => 'd', 30 => 'e', 31 => 'f', - 32 => 'g', 33 => 'h', 34 => 'i', 35 => 'j', 36 => 'k', 37 => 'l', 38 => 'm', 39 => 'n', - 40 => 'o', 41 => 'p', 42 => 'q', 43 => 'r', 44 => 's', 45 => 't', 46 => 'u', 47 => 'v', - 48 => 'w', 49 => 'x', 50 => 'y', 51 => 'z', 52 => '0', 53 => '1', 54 => '2', 55 => '3', - 56 => '4', 57 => '5', 58 => '6', 59 => '7', 60 => '8', 61 => '9', 62 => '+', 63 => '/', - ]; - - /** - * Constructor - */ - public function __construct() - { - // I leave it here for future reference - // foreach (str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/') as $i => $char) - // { - // $this->charToIntMap[$char] = $i; - // $this->intToCharMap[$i] = $char; - // } - } - - /** - * Convert from a two-complement value to a value where the sign bit is - * is placed in the least significant bit. For example, as decimals: - * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) - * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) - * We generate the value for 32 bit machines, hence -2147483648 becomes 1, not 4294967297, - * even on a 64 bit machine. - * - * @param string $aValue - */ - public function toVLQSigned($aValue) - { - return 0xffffffff & ($aValue < 0 ? ((-$aValue) << 1) + 1 : ($aValue << 1) + 0); - } - - /** - * Convert to a two-complement value from a value where the sign bit is - * is placed in the least significant bit. For example, as decimals: - * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 - * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 - * We assume that the value was generated with a 32 bit machine in mind. - * Hence - * 1 becomes -2147483648 - * even on a 64 bit machine. - * - * @param integer $aValue - */ - public function fromVLQSigned($aValue) - { - return $aValue & 1 ? $this->zeroFill(~$aValue + 2, 1) | (-1 - 0x7fffffff) : $this->zeroFill($aValue, 1); - } - - /** - * Return the base 64 VLQ encoded value. - * - * @param string $aValue The value to encode - * - * @return string The encoded value - */ - public function encode($aValue) - { - $encoded = ''; - $vlq = $this->toVLQSigned($aValue); - - do { - $digit = $vlq & $this->mask; - $vlq = $this->zeroFill($vlq, $this->shift); - - if ($vlq > 0) { - $digit |= $this->continuationBit; - } - - $encoded .= $this->base64Encode($digit); - } while ($vlq > 0); - - return $encoded; - } - - /** - * Return the value decoded from base 64 VLQ. - * - * @param string $encoded The encoded value to decode - * - * @return integer The decoded value - */ - public function decode($encoded) - { - $vlq = 0; - $i = 0; - - do { - $digit = $this->base64Decode($encoded[$i]); - $vlq |= ($digit & $this->mask) << ($i * $this->shift); - $i++; - } while ($digit & $this->continuationBit); - - return $this->fromVLQSigned($vlq); - } - - /** - * Right shift with zero fill. - * - * @param integer $a number to shift - * @param integer $b number of bits to shift - * - * @return integer - */ - public function zeroFill($a, $b) - { - return ($a >= 0) ? ($a >> $b) : ($a >> $b) & (PHP_INT_MAX >> ($b - 1)); - } - - /** - * Encode single 6-bit digit as base64. - * - * @param integer $number - * - * @return string - * - * @throws \Exception If the number is invalid - */ - public function base64Encode($number) - { - if ($number < 0 || $number > 63) { - throw new \Exception(sprintf('Invalid number "%s" given. Must be between 0 and 63.', $number)); - } - - return $this->intToCharMap[$number]; - } - - /** - * Decode single 6-bit digit from base64 - * - * @param string $char - * - * @return integer - * - * @throws \Exception If the number is invalid - */ - public function base64Decode($char) - { - if (! array_key_exists($char, $this->charToIntMap)) { - throw new \Exception(sprintf('Invalid base 64 digit "%s" given.', $char)); - } - - return $this->charToIntMap[$char]; - } -} diff --git a/src/SourceMap/SourceMapGenerator.php b/src/SourceMap/SourceMapGenerator.php deleted file mode 100644 index d2001462..00000000 --- a/src/SourceMap/SourceMapGenerator.php +++ /dev/null @@ -1,345 +0,0 @@ - - * @author Nicolas FRANÇOIS - */ -class SourceMapGenerator -{ - /** - * What version of source map does the generator generate? - */ - const VERSION = 3; - - /** - * Array of default options - * - * @var array - */ - protected $defaultOptions = [ - // 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. - 'sourceRoot' => '', - - // an optional name of the generated code that this source map is associated with. - 'sourceMapFilename' => null, - - // url of the map - 'sourceMapURL' => null, - - // absolute path to a file to write the map to - 'sourceMapWriteTo' => null, - - // output source contents? - 'outputSourceFiles' => false, - - // base path for filename normalization - 'sourceMapRootpath' => '', - - // base path for filename normalization - 'sourceMapBasepath' => '' - ]; - - /** - * The base64 VLQ encoder - * - * @var \Leafo\ScssPhp\SourceMap\Base64VLQ - */ - protected $encoder; - - /** - * Array of mappings - * - * @var array - */ - protected $mappings = []; - - /** - * Array of contents map - * - * @var array - */ - protected $contentsMap = []; - - /** - * File to content map - * - * @var array - */ - protected $sources = []; - protected $sourceKeys = []; - - /** - * @var array - */ - private $options; - - public function __construct(array $options = []) - { - $this->options = array_merge($this->defaultOptions, $options); - $this->encoder = new Base64VLQ(); - } - - /** - * Adds a mapping - * - * @param integer $generatedLine The line number in generated file - * @param integer $generatedColumn The column number in generated file - * @param integer $originalLine The line number in original file - * @param integer $originalColumn The column number in original file - * @param string $sourceFile The original source file - */ - public function addMapping($generatedLine, $generatedColumn, $originalLine, $originalColumn, $sourceFile) - { - $this->mappings[] = [ - 'generated_line' => $generatedLine, - 'generated_column' => $generatedColumn, - 'original_line' => $originalLine, - 'original_column' => $originalColumn, - 'source_file' => $sourceFile - ]; - - $this->sources[$sourceFile] = $sourceFile; - } - - /** - * Saves the source map to a file - * - * @param string $content The content to write - * - * @return string - * - * @throws \Leafo\ScssPhp\Exception\CompilerException If the file could not be saved - */ - public function saveMap($content) - { - $file = $this->options['sourceMapWriteTo']; - $dir = dirname($file); - - // directory does not exist - if (! is_dir($dir)) { - // FIXME: create the dir automatically? - throw new CompilerException(sprintf('The directory "%s" does not exist. Cannot save the source map.', $dir)); - } - - // FIXME: proper saving, with dir write check! - if (file_put_contents($file, $content) === false) { - throw new CompilerException(sprintf('Cannot save the source map to "%s"', $file)); - } - - return $this->options['sourceMapURL']; - } - - /** - * Generates the JSON source map - * - * @return string - * - * @see https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit# - */ - public function generateJson() - { - $sourceMap = []; - $mappings = $this->generateMappings(); - - // File version (always the first entry in the object) and must be a positive integer. - $sourceMap['version'] = self::VERSION; - - // An optional name of the generated code that this source map is associated with. - $file = $this->options['sourceMapFilename']; - - if ($file) { - $sourceMap['file'] = $file; - } - - // 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. - $root = $this->options['sourceRoot']; - - if ($root) { - $sourceMap['sourceRoot'] = $root; - } - - // A list of original sources used by the 'mappings' entry. - $sourceMap['sources'] = []; - - foreach ($this->sources as $sourceUri => $sourceFilename) { - $sourceMap['sources'][] = $this->normalizeFilename($sourceFilename); - } - - // A list of symbol names used by the 'mappings' entry. - $sourceMap['names'] = []; - - // A string with the encoded mapping data. - $sourceMap['mappings'] = $mappings; - - if ($this->options['outputSourceFiles']) { - // An optional list of source content, useful when the 'source' can't be hosted. - // The contents are listed in the same order as the sources above. - // 'null' may be used if some original sources should be retrieved by name. - $sourceMap['sourcesContent'] = $this->getSourcesContent(); - } - - // less.js compat fixes - if (count($sourceMap['sources']) && empty($sourceMap['sourceRoot'])) { - unset($sourceMap['sourceRoot']); - } - - return json_encode($sourceMap, JSON_UNESCAPED_SLASHES); - } - - /** - * Returns the sources contents - * - * @return array|null - */ - protected function getSourcesContent() - { - if (empty($this->sources)) { - return null; - } - - $content = []; - - foreach ($this->sources as $sourceFile) { - $content[] = file_get_contents($sourceFile); - } - - return $content; - } - - /** - * Generates the mappings string - * - * @return string - */ - public function generateMappings() - { - if (! count($this->mappings)) { - return ''; - } - - $this->sourceKeys = array_flip(array_keys($this->sources)); - - // group mappings by generated line number. - $groupedMap = $groupedMapEncoded = []; - - foreach ($this->mappings as $m) { - $groupedMap[$m['generated_line']][] = $m; - } - - ksort($groupedMap); - $lastGeneratedLine = $lastOriginalIndex = $lastOriginalLine = $lastOriginalColumn = 0; - - foreach ($groupedMap as $lineNumber => $lineMap) { - while (++$lastGeneratedLine < $lineNumber) { - $groupedMapEncoded[] = ';'; - } - - $lineMapEncoded = []; - $lastGeneratedColumn = 0; - - foreach ($lineMap as $m) { - $mapEncoded = $this->encoder->encode($m['generated_column'] - $lastGeneratedColumn); - $lastGeneratedColumn = $m['generated_column']; - - // find the index - if ($m['source_file']) { - $index = $this->findFileIndex($m['source_file']); - - if ($index !== false) { - $mapEncoded .= $this->encoder->encode($index - $lastOriginalIndex); - $lastOriginalIndex = $index; - // lines are stored 0-based in SourceMap spec version 3 - $mapEncoded .= $this->encoder->encode($m['original_line'] - 1 - $lastOriginalLine); - $lastOriginalLine = $m['original_line'] - 1; - $mapEncoded .= $this->encoder->encode($m['original_column'] - $lastOriginalColumn); - $lastOriginalColumn = $m['original_column']; - } - } - - $lineMapEncoded[] = $mapEncoded; - } - - $groupedMapEncoded[] = implode(',', $lineMapEncoded) . ';'; - } - - return rtrim(implode($groupedMapEncoded), ';'); - } - - /** - * Finds the index for the filename - * - * @param string $filename - * - * @return integer|false - */ - protected function findFileIndex($filename) - { - return $this->sourceKeys[$filename]; - } - - /** - * Normalize filename - * - * @param string $filename - * - * @return string - */ - protected function normalizeFilename($filename) - { - $filename = $this->fixWindowsPath($filename); - $rootpath = $this->options['sourceMapRootpath']; - $basePath = $this->options['sourceMapBasepath']; - - // "Trim" the 'sourceMapBasepath' from the output filename. - if (strlen($basePath) && strpos($filename, $basePath) === 0) { - $filename = substr($filename, strlen($basePath)); - } - - // Remove extra leading path separators. - if (strpos($filename, '\\') === 0 || strpos($filename, '/') === 0) { - $filename = substr($filename, 1); - } - - return $rootpath . $filename; - } - - /** - * Fix windows paths - * - * @param string $path - * @param boolean $addEndSlash - * - * @return string - */ - public function fixWindowsPath($path, $addEndSlash = false) - { - $slash = ($addEndSlash) ? '/' : ''; - - if (! empty($path)) { - $path = str_replace('\\', '/', $path); - $path = rtrim($path, '/') . $slash; - } - - return $path; - } -}