PluginProbe
MaxButtons – Create buttons / 7.13.2
MaxButtons – Create buttons v7.13.2
6.23 6.24 6.25 6.26 6.26.1 6.27 6.28 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.1.1 7.1.2 7.1.3 7.10 7.11 7.13 7.13.1 7.13.2 7.13.3 All 100 releases
maxbuttons / assets / libraries / scssphp / src / SourceMap / SourceMapGenerator.php

SourceMapGenerator.php in MaxButtons – Create buttons 7.13.2, at assets/libraries/scssphp/src/SourceMap/SourceMapGenerator.php

338 lines 9.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 *
34 * @var array
35 */
36 protected $defaultOptions = array(
37 // an optional source root, useful for relocating source files
38 // on a server or removing repeated values in the 'sources' entry.
39 // This value is prepended to the individual entries in the 'source' field.
40 'sourceRoot' => '',
41
42 // an optional name of the generated code that this source map is associated with.
43 'sourceMapFilename' => null,
44
45 // url of the map
46 'sourceMapURL' => null,
47
48 // absolute path to a file to write the map to
49 'sourceMapWriteTo' => null,
50
51 // output source contents?
52 'outputSourceFiles' => false,
53
54 // base path for filename normalization
55 'sourceMapRootpath' => '',
56
57 // base path for filename normalization
58 'sourceMapBasepath' => ''
59 );
60
61 /**
62 * The base64 VLQ encoder
63 *
64 * @var \Leafo\ScssPhp\SourceMap\Base64VLQEncoder
65 */
66 protected $encoder;
67
68 /**
69 * Array of mappings
70 *
71 * @var array
72 */
73 protected $mappings = array();
74
75 /**
76 * Array of contents map
77 *
78 * @var array
79 */
80 protected $contentsMap = array();
81
82 /**
83 * File to content map
84 *
85 * @var array
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 }
100
101 /**
102 * Adds a mapping
103 *
104 * @param integer $generatedLine The line number in generated file
105 * @param integer $generatedColumn The column number in generated file
106 * @param integer $originalLine The line number in original file
107 * @param integer $originalColumn The column number in original file
108 * @param string $sourceFile The original source file
109 */
110 public function addMapping($generatedLine, $generatedColumn, $originalLine, $originalColumn, $sourceFile)
111 {
112 $this->mappings[] = array(
113 'generated_line' => $generatedLine,
114 'generated_column' => $generatedColumn,
115 'original_line' => $originalLine,
116 'original_column' => $originalColumn,
117 'source_file' => $sourceFile
118 );
119
120 $this->sources[$sourceFile] = $sourceFile;
121 }
122
123 /**
124 * Saves the source map to a file
125 *
126 * @param string $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
208 /**
209 * Returns the sources contents
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
228 /**
229 * Generates the mappings string
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
271 $mapEncoded .= $this->encoder->encode($m['original_line'] - 1 - $lastOriginalLine);
272 $lastOriginalLine = $m['original_line'] - 1;
273 $mapEncoded .= $this->encoder->encode($m['original_column'] - $lastOriginalColumn);
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
287 /**
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 }
338