├── .gitignore ├── .travis.yml ├── COPYING ├── Kwf └── SourceMaps │ ├── Base64VLQ.php │ └── SourceMap.php ├── README.md ├── composer.json ├── composer.lock ├── phpunit.xml └── tests └── Kwf └── SourceMaps ├── ConcatTest.php ├── CreateTest.php ├── SourcesTest.php ├── StringReplaceTest.php ├── Test.php └── TestData.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | 6 | before_script: 7 | - composer self-update 8 | - composer install 9 | 10 | script: 11 | - ./vendor/bin/phpunit 12 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007-2014 by Vivid Planet Software GmbH 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /Kwf/SourceMaps/Base64VLQ.php: -------------------------------------------------------------------------------- 1 | 0) { 61 | $digit |= self::$CONTINUATION_BIT; 62 | } 63 | $encoded .= self::base64Encode($digit); 64 | } while ($vlq > 0); 65 | 66 | return $encoded; 67 | } 68 | 69 | /** 70 | * Return the value decoded from base 64 VLQ. 71 | */ 72 | public static function decode(&$encoded) 73 | { 74 | $vlq = 0; 75 | 76 | $i = 0; 77 | do { 78 | $digit = self::base64Decode($encoded[$i]); 79 | $vlq |= ($digit & self::$MASK) << ($i*self::$SHIFT); 80 | $i++; 81 | } while ($digit & self::$CONTINUATION_BIT); 82 | 83 | $encoded = substr($encoded, $i); 84 | return self::fromVLQSigned($vlq); 85 | } 86 | 87 | /** 88 | * Return the value decoded from base 64 VLQ. 89 | */ 90 | public static function decodePos($encoded, &$pos) 91 | { 92 | $vlq = 0; 93 | $i = 0; 94 | do { 95 | $digit = self::$CHAR_TO_INT[$encoded[$pos]]; 96 | $vlq += ($digit & 0x1F) << $i; 97 | $i += 5; $pos++; 98 | } while ($digit >= 0x20); 99 | 100 | return $vlq & 1 ? self::zeroFill(~$vlq + 2, 1) | (-1 - 0x7fffffff) : self::zeroFill($vlq, 1); 101 | } 102 | 103 | /** 104 | * Right shift with zero fill. 105 | * 106 | * @param number $a number to shift 107 | * @param integer $b number of bits to shift 108 | * @return integer 109 | */ 110 | public static function zeroFill($a, $b) 111 | { 112 | return ($a >= 0) ? ($a >> $b) : ($a >> $b) & (PHP_INT_MAX >> ($b - 1)); 113 | } 114 | 115 | /** 116 | * Encode single 6-bit digit as base64. 117 | * 118 | * @param integer $number 119 | * @return string 120 | */ 121 | public static function base64Encode($number) 122 | { 123 | if ($number < 0 || $number > 63) { 124 | throw new Exception("Must be between 0 and 63: ".$number); 125 | } 126 | return self::$INT_TO_CHAR[$number]; 127 | } 128 | 129 | /** 130 | * Decode single 6-bit digit from base64 131 | * 132 | * @param string $char 133 | * @return number 134 | */ 135 | public static function base64Decode($char) 136 | { 137 | if (!array_key_exists($char, self::$CHAR_TO_INT)) { 138 | throw new Exception("Not a valid base 64 digit: ".$char); 139 | } 140 | return self::$CHAR_TO_INT[$char]; 141 | } 142 | } 143 | 144 | // Initialize char conversion table. 145 | Kwf_SourceMaps_Base64VLQ::$CHAR_TO_INT = array(); 146 | Kwf_SourceMaps_Base64VLQ::$INT_TO_CHAR = array(); 147 | 148 | foreach (str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/') as $i => $char) { 149 | Kwf_SourceMaps_Base64VLQ::$CHAR_TO_INT[$char] = $i; 150 | Kwf_SourceMaps_Base64VLQ::$INT_TO_CHAR[$i] = $char; 151 | } 152 | 153 | -------------------------------------------------------------------------------- /Kwf/SourceMaps/SourceMap.php: -------------------------------------------------------------------------------- 1 | _map = json_decode($mapContents); 23 | if (!$this->_map) { 24 | throw new Exception("Failed parsing map: ".json_last_error()); 25 | } 26 | } else { 27 | $this->_map = $mapContents; 28 | } 29 | if (!isset($this->_map->version)) { 30 | throw new Exception("Invalid Source Map"); 31 | } 32 | if ($this->_map->version != 3) { 33 | throw new Exception("Unsupported Version"); 34 | } 35 | $this->_fileContents = $fileContents; 36 | } 37 | 38 | public function setFile($file) 39 | { 40 | $this->_map->file = $file; 41 | } 42 | 43 | public function getFile() 44 | { 45 | return $this->_map->file; 46 | } 47 | 48 | public function setSourceRoot($sourceRoot) 49 | { 50 | $this->_map->sourceRoot = $sourceRoot; 51 | } 52 | 53 | public function getSourceRoot() 54 | { 55 | return $this->_map->sourceRoot; 56 | } 57 | 58 | public function addSource($source) 59 | { 60 | $this->_map->sources[] = $source; 61 | } 62 | 63 | public function setSources(array $sources) 64 | { 65 | $this->_map->sources = $sources; 66 | } 67 | 68 | public function getSources() 69 | { 70 | return $this->_map->sources; 71 | } 72 | 73 | public function setMimeType($v) 74 | { 75 | $this->_mimeType = $v; 76 | } 77 | 78 | public function getMimeType() 79 | { 80 | return $this->_mimeType; 81 | } 82 | 83 | /** 84 | * Create a new, empty sourcemap 85 | * 86 | * @param string contents of the minified file 87 | */ 88 | public static function createEmptyMap($fileContents) 89 | { 90 | $map = (object) array( 91 | 'version' => 3, 92 | 'mappings' => '', 93 | 'sources' => array(), 94 | 'names' => array(), 95 | ); 96 | return new self($map, $fileContents); 97 | } 98 | 99 | /** 100 | * Create a new sourcemap based on sourceMappingURL with inline base64 encoded data 101 | * 102 | * Example: 103 | * //# sourceMappingURL=data:application/json;base64,.... 104 | * 105 | * @param string contents of the minified file including sourceMappingURL 106 | */ 107 | public static function createFromInline($fileContents) 108 | { 109 | // '//# sourceMappingURL=data:application/json;charset:utf-8;base64, 110 | // '//# sourceMappingURL=data:application/json;base64,' 111 | $pos = strrpos($fileContents, "\n//# sourceMappingURL="); 112 | $isCss = false; 113 | if ($pos === false) { 114 | $pos = strrpos($fileContents, "\n/*# sourceMappingURL="); 115 | if ($pos === false) { 116 | throw new Exception("No sourceMappingURL found"); 117 | } 118 | $isCss = true; 119 | } 120 | $url = substr($fileContents, $pos + 22); 121 | $url = rtrim($url); 122 | if ($isCss) { 123 | if (substr($url, -2) != '*/') { 124 | throw new Exception("sourceMappingURL isn't wrapped with closing */"); 125 | } 126 | $url = substr($url, 0, -2); //remove "*/" 127 | $url = rtrim($url); 128 | } 129 | 130 | if (substr($url, 0, 29) == 'data:application/json;base64,') { 131 | $map = substr($url, 29); 132 | } else if (substr($url, 0, 29 + 14) == 'data:application/json;charset:utf-8;base64,') { 133 | $map = substr($url, 29 + 14); 134 | } else if (substr($url, 0, 29 + 14) == 'data:application/json;charset=utf-8;base64,') { 135 | $map = substr($url, 29 + 14); 136 | } else { 137 | throw new Exception("Unsupported sourceMappingURL"); 138 | } 139 | $map = base64_decode($map); 140 | $map = json_decode($map); 141 | $fileContents = substr($fileContents, 0, $pos); 142 | $ret = new self($map, $fileContents); 143 | $ret->setMimeType($isCss ? 'text/css' : 'text/javascript'); 144 | return $ret; 145 | } 146 | 147 | public static function hasInline($fileContents) 148 | { 149 | $pos = strrpos($fileContents, "\n//# sourceMappingURL=data:"); 150 | if ($pos !== false) return true; 151 | $pos = strrpos($fileContents, "\n/*# sourceMappingURL=data:"); 152 | if ($pos !== false) return true; 153 | 154 | return false; 155 | } 156 | 157 | /** 158 | * Adds a mapping 159 | * 160 | * @param integer $generatedLine The line number in generated file 161 | * @param integer $generatedColumn The column number in generated file 162 | * @param integer $originalLine The line number in original file 163 | * @param integer $originalColumn The column number in original file 164 | * @param string $originalSource The original source file 165 | * @param string $originalName The original source name (optional) 166 | */ 167 | public function addMapping($generatedLine, $generatedColumn, $originalLine, $originalColumn, $originalSource, $originalName = null) 168 | { 169 | if (!isset($this->_mappings)) { 170 | $this->getMappings(); 171 | } 172 | $this->_mappings[] = array( 173 | 'generatedLine' => $generatedLine, 174 | 'generatedColumn' => $generatedColumn, 175 | 'originalLine' => $originalLine, 176 | 'originalColumn' => $originalColumn, 177 | 'originalSource' => $originalSource, 178 | 'originalName' => $originalName, 179 | ); 180 | $this->_mappingsChanged = true; 181 | } 182 | 183 | 184 | /** 185 | * Generates the mappings string 186 | * 187 | * Parts based on https://github.com/oyejorge/less.php/blob/master/lib/Less/SourceMap/Generator.php 188 | * Apache License Version 2.0 189 | * 190 | * @return string 191 | */ 192 | private function _generateMappings() 193 | { 194 | if (!isset($this->_mappings) && $this->_map->mappings) { 195 | //up to date, nothing to do 196 | return; 197 | } 198 | $this->_mappingsChanged = false; 199 | if (!count($this->_mappings)) { 200 | return ''; 201 | } 202 | 203 | foreach ($this->_mappings as $m) { 204 | if ($m['originalSource'] && !in_array($m['originalSource'], $this->_map->sources)) { 205 | $this->_map->sources[] = $m['originalSource']; 206 | } 207 | } 208 | 209 | $this->_map->names = array(); 210 | foreach ($this->_mappings as $m) { 211 | if ($m['originalName'] && !in_array($m['originalName'], $this->_map->names)) { 212 | $this->_map->names[] = $m['originalName']; 213 | } 214 | } 215 | 216 | // group mappings by generated line number. 217 | $groupedMap = $groupedMapEncoded = array(); 218 | foreach ($this->_mappings as $m) { 219 | $groupedMap[$m['generatedLine']][] = $m; 220 | } 221 | ksort($groupedMap); 222 | 223 | $lastGeneratedLine = $lastOriginalSourceIndex = $lastOriginalNameIndex = $lastOriginalLine = $lastOriginalColumn = 0; 224 | 225 | foreach ($groupedMap as $lineNumber => $lineMap) { 226 | while (++$lastGeneratedLine < $lineNumber) { 227 | $groupedMapEncoded[] = ';'; 228 | } 229 | 230 | $lineMapEncoded = array(); 231 | $lastGeneratedColumn = 0; 232 | 233 | foreach ($lineMap as $m) { 234 | $mapEncoded = Kwf_SourceMaps_Base64VLQ::encode($m['generatedColumn'] - $lastGeneratedColumn); 235 | $lastGeneratedColumn = $m['generatedColumn']; 236 | 237 | // find the index 238 | if ($m['originalSource']) { 239 | $index = array_search($m['originalSource'], $this->_map->sources); 240 | $mapEncoded .= Kwf_SourceMaps_Base64VLQ::encode($index - $lastOriginalSourceIndex); 241 | $lastOriginalSourceIndex = $index; 242 | 243 | // lines are stored 0-based in SourceMap spec version 3 244 | $mapEncoded .= Kwf_SourceMaps_Base64VLQ::encode($m['originalLine'] - 1 - $lastOriginalLine); 245 | $lastOriginalLine = $m['originalLine'] - 1; 246 | 247 | $mapEncoded .= Kwf_SourceMaps_Base64VLQ::encode($m['originalColumn'] - $lastOriginalColumn); 248 | $lastOriginalColumn = $m['originalColumn']; 249 | 250 | if ($m['originalName']) { 251 | $index = array_search($m['originalName'], $this->_map->names); 252 | $mapEncoded .= Kwf_SourceMaps_Base64VLQ::encode($index - $lastOriginalNameIndex); 253 | $lastOriginalNameIndex = $index; 254 | } 255 | } 256 | 257 | $lineMapEncoded[] = $mapEncoded; 258 | } 259 | 260 | $groupedMapEncoded[] = implode(',', $lineMapEncoded).';'; 261 | } 262 | 263 | $this->_map->mappings = rtrim(implode($groupedMapEncoded), ';'); 264 | } 265 | 266 | /** 267 | * Performant Source Map aware string replace 268 | * 269 | * @param string 270 | * @param string 271 | */ 272 | public function stringReplace($string, $replace) 273 | { 274 | if ($this->_mappingsChanged) { 275 | $this->_generateMappings(); 276 | } 277 | 278 | if (strpos("\n", $string)) { 279 | throw new Exception('string must not contain \n'); 280 | } 281 | if ($replace != "" && strpos("\n", $replace)) { 282 | throw new Exception('replace must not contain \n'); 283 | } 284 | 285 | $adjustOffsets = array(); 286 | $pos = 0; 287 | $str = $this->_fileContents; 288 | $offset = 0; 289 | $lineOffset = 0; 290 | while (($pos = strpos($str, $string, $pos)) !== false) { 291 | $line = substr_count(substr($str, 0, $pos), "\n") + 1; 292 | if (!isset($adjustOffsets[$line])) { 293 | //first in line 294 | $lineOffset = 0; 295 | } 296 | $this->_fileContents = substr($this->_fileContents, 0, $pos + $offset).$replace.substr($this->_fileContents, $pos + $offset + strlen($string)); 297 | $offset += strlen($replace) - strlen($string); 298 | $lineOffset += strlen($replace) - strlen($string); 299 | $column = $pos - strrpos(substr($str, 0, $pos), "\n") + 1; //strrpos can return false for first line which will subtract 0 (=false) 300 | $adjustOffsets[$line][] = array( 301 | 'column' => $column, 302 | 'absoluteOffset' => $offset, 303 | 'lineOffset' => $lineOffset, 304 | 'offset' => strlen($replace) - strlen($string), 305 | 'replacedLength' => strlen($string) 306 | ); 307 | $pos = $pos + strlen($string); 308 | } 309 | 310 | $mappings = $this->getMappings(); 311 | $this->_mappingsChanged = true; 312 | $this->_mappings = array(); 313 | foreach ($mappings as $mappingIndex=>$mapping) { 314 | if (isset($adjustOffsets[$mapping['generatedLine']])) { 315 | foreach (array_reverse($adjustOffsets[$mapping['generatedLine']], true) as $offsIndex=>$offs) { 316 | if ($mapping['generatedColumn'] > $offs['column']) { 317 | if ($mapping['generatedColumn'] < $offs['column']-1+$offs['replacedLength']) { 318 | //mapping inside replaced test, remove 319 | continue 2; 320 | } else { 321 | $mapping['generatedColumn'] += $offs['lineOffset']; 322 | break; 323 | } 324 | } 325 | } 326 | } 327 | $this->_mappings[] = $mapping; 328 | } 329 | } 330 | 331 | /** 332 | * set/overwrite all mappings 333 | * 334 | * @param array $mappings must be in the same form as returned by getMappings 335 | * 336 | */ 337 | public function setMappings(array $mappings) 338 | { 339 | $this->_mappings = $mappings; 340 | $this->_mappingsChanged = true; 341 | return $this; 342 | } 343 | 344 | /** 345 | * Return all mappings 346 | * 347 | * @return array with assoc array containing: generatedLine, generatedColumn, originalSource, originalLine, originalColumn, originalName 348 | */ 349 | public function getMappings() 350 | { 351 | if (isset($this->_mappings)) { 352 | return $this->_mappings; 353 | } 354 | 355 | $this->_mappings = array(); 356 | 357 | $generatedLine = 1; 358 | $previousGeneratedColumn = 0; 359 | $previousOriginalLine = 0; 360 | $previousOriginalColumn = 0; 361 | $previousSource = 0; 362 | $previousName = 0; 363 | 364 | $str = $this->_map->mappings; 365 | $end = strlen($str); 366 | $pos = 0; 367 | 368 | while ($pos < $end) { 369 | if ($str[$pos] === ';') { 370 | $generatedLine++; 371 | $pos++; 372 | $previousGeneratedColumn = 0; 373 | } else if ($str[$pos] === ',') { 374 | $pos++; 375 | } else { 376 | $mapping = array(); 377 | $mapping['generatedLine'] = $generatedLine; 378 | 379 | // Generated column. 380 | $value = Kwf_SourceMaps_Base64VLQ::decodePos($str, $pos); 381 | $mapping['generatedColumn'] = $previousGeneratedColumn + $value; 382 | $previousGeneratedColumn = $mapping['generatedColumn']; 383 | 384 | if ($pos < $end && !($str[$pos]==',' || $str[$pos]==';')) { 385 | // Original source. 386 | $value = Kwf_SourceMaps_Base64VLQ::decodePos($str, $pos); 387 | $mapping['originalSource'] = (isset($this->_map->sourceRoot) ? $this->_map->sourceRoot.'/' : '') 388 | . $this->_map->sources[$previousSource + $value]; 389 | $previousSource += $value; 390 | if ($pos >= $end || ($str[$pos]==',' || $str[$pos]==';')) { 391 | throw new Exception('Found a source, but no line and column'); 392 | } 393 | 394 | // Original line. 395 | $value = Kwf_SourceMaps_Base64VLQ::decodePos($str, $pos); 396 | $mapping['originalLine'] = $previousOriginalLine + $value; 397 | $previousOriginalLine = $mapping['originalLine']; 398 | // Lines are stored 0-based 399 | $mapping['originalLine'] += 1; 400 | if ($pos >= $end || ($str[$pos] == ',' || $str[$pos] == ';')) { 401 | throw new Exception('Found a source and line, but no column'); 402 | } 403 | 404 | // Original column. 405 | $value = Kwf_SourceMaps_Base64VLQ::decodePos($str, $pos); 406 | $mapping['originalColumn'] = $previousOriginalColumn + $value; 407 | $previousOriginalColumn = $mapping['originalColumn']; 408 | 409 | if ($pos < $end && !($str[$pos] == ',' || $str[$pos] == ';')) { 410 | // Original name. 411 | $value = Kwf_SourceMaps_Base64VLQ::decodePos($str, $pos); 412 | $mapping['originalName'] = $this->_map->names[$previousName + $value]; 413 | $previousName += $value; 414 | } else { 415 | $mapping['originalName'] = null; 416 | } 417 | } 418 | $this->_mappings[] = $mapping; 419 | } 420 | } 421 | return $this->_mappings; 422 | } 423 | 424 | protected function _addLastExtension() 425 | { 426 | $previousGeneratedColumn = 0; 427 | $previousOriginalLine = 0; 428 | $previousOriginalColumn = 0; 429 | $previousSource = 0; 430 | $previousName = 0; 431 | $lineCount = 0; 432 | 433 | $str = $this->_map->mappings; 434 | $end = strlen($str); 435 | $pos = 0; 436 | 437 | while ($pos < $end) { 438 | 439 | if ($str[$pos] === ';') { 440 | $pos++; 441 | $previousGeneratedColumn = 0; 442 | $lineCount++; 443 | } else if ($str[$pos] === ',') { 444 | $pos++; 445 | } else { 446 | // Generated column. 447 | $previousGeneratedColumn += Kwf_SourceMaps_Base64VLQ::decodePos($str, $pos); 448 | 449 | if ($pos < $end && !($str[$pos]==',' || $str[$pos]==';')) { 450 | // Original source. 451 | $previousSource += Kwf_SourceMaps_Base64VLQ::decodePos($str, $pos); 452 | if ($pos >= $end || ($str[$pos]==',' || $str[$pos]==';')) { 453 | throw new Exception('Found a source, but no line and column'); 454 | } 455 | 456 | // Original line. 457 | $previousOriginalLine += Kwf_SourceMaps_Base64VLQ::decodePos($str, $pos); 458 | if ($pos >= $end || ($str[$pos] == ',' || $str[$pos] == ';')) { 459 | throw new Exception('Found a source and line, but no column'); 460 | } 461 | 462 | // Original column. 463 | $previousOriginalColumn += Kwf_SourceMaps_Base64VLQ::decodePos($str, $pos); 464 | 465 | if ($pos < $end && !($str[$pos] == ',' || $str[$pos] == ';')) { 466 | // Original name. 467 | $previousName += Kwf_SourceMaps_Base64VLQ::decodePos($str, $pos); 468 | } 469 | } 470 | } 471 | } 472 | if ($this->_map->mappings) { //only add if mapping is not empty 473 | $this->_map->{'_x_org_koala-framework_last'} = (object) array( 474 | 'source' => $previousSource, 475 | 'originalLine' => $previousOriginalLine, 476 | 'originalColumn' => $previousOriginalColumn, 477 | 'name' => $previousName, 478 | ); 479 | /* 480 | commented out as it might lead to false positives if the last line doesn't contain a single mapping 481 | if (substr_count($this->_fileContents, "\n") != $lineCount) { 482 | throw new Exception("line count in mapping ($lineCount) doesn't match file (".substr_count($this->_fileContents, "\n").")"); 483 | } 484 | */ 485 | } 486 | } 487 | 488 | /** 489 | * Concat sourcemaps and keep mappings intact 490 | * 491 | * This is implemented very efficent by avoiding to parse the whole mappings string. 492 | */ 493 | public function concat(Kwf_SourceMaps_SourceMap $other) 494 | { 495 | if ($this->_mappingsChanged) { 496 | $this->_generateMappings(); 497 | } 498 | $missingLines = substr_count($this->_fileContents, "\n")-substr_count($this->_map->mappings, ";"); 499 | if ($missingLines > 0) { 500 | $this->_map->mappings .= str_repeat(';', $missingLines); 501 | } 502 | if (!isset($this->_map->{'_x_org_koala-framework_last'})) { 503 | $this->_addLastExtension(); 504 | } 505 | 506 | if (strlen($this->_fileContents) > 0) { 507 | if (substr($this->_fileContents, -1) != "\n") { 508 | $this->_fileContents .= "\n"; 509 | $this->_map->mappings .= ';'; 510 | } 511 | } 512 | 513 | $this->_fileContents .= $other->_fileContents; 514 | 515 | $data = $other->getMapContentsData(); 516 | 517 | if ($this->_map->mappings) { 518 | $previousFileLast = $this->_map->{'_x_org_koala-framework_last'}; 519 | } else { 520 | $previousFileLast = (object) array( 521 | 'source' => 0, 522 | 'originalLine' => 0, 523 | 'originalColumn' => 0, 524 | 'name' => 0, 525 | ); 526 | } 527 | if (!$data->mappings) { 528 | $data->mappings = str_repeat(';', substr_count($other->_fileContents, "\n")); 529 | $data->{'_x_org_koala-framework_last'} = (object) array( 530 | 'source' => -1, 531 | 'originalLine' => $previousFileLast->originalLine, 532 | 'originalColumn' => $previousFileLast->originalColumn, 533 | 'name' => -1, 534 | ); 535 | } 536 | $previousFileSourcesCount = count($this->_map->sources); 537 | $previousFileNamesCount = count($this->_map->names); 538 | if ($previousFileLast->source > $previousFileSourcesCount) { 539 | if ($previousFileSourcesCount != 0 && $previousFileLast->source != 0) { 540 | throw new Exception("Invalid last source, must not be higher than sources"); 541 | } 542 | } 543 | 544 | if ($previousFileLast->name > $previousFileNamesCount) { 545 | if ($previousFileNamesCount != 0 && $previousFileLast->name != 0) { 546 | throw new Exception("Invalid last name, must not be higher than names"); 547 | } 548 | } 549 | 550 | if ($data->sources) { 551 | foreach ($data->sources as $s) { 552 | $this->_map->sources[] = $s; 553 | } 554 | } 555 | if ($data->names) { 556 | foreach ($data->names as $n) { 557 | $this->_map->names[] = $n; 558 | } 559 | } 560 | 561 | $otherMappings = $data->mappings; 562 | 563 | $str = ''; 564 | 565 | $otherMappingsEnd = strlen($otherMappings); 566 | $otherMappingsPos = 0; 567 | 568 | while ($otherMappingsPos < $otherMappingsEnd && $otherMappings[$otherMappingsPos] === ';') { 569 | $str .= $otherMappings[$otherMappingsPos]; 570 | $otherMappingsPos++; 571 | } 572 | if ($otherMappingsPos < $otherMappingsEnd) { 573 | 574 | // Generated column. 575 | $str .= Kwf_SourceMaps_Base64VLQ::encode(Kwf_SourceMaps_Base64VLQ::decodePos($otherMappings, $otherMappingsPos)); 576 | if ($otherMappingsPos < $otherMappingsEnd && !($otherMappings[$otherMappingsPos] == ',' || $otherMappings[$otherMappingsPos] == ';')) { 577 | 578 | // Original source. 579 | $value = Kwf_SourceMaps_Base64VLQ::decodePos($otherMappings, $otherMappingsPos); 580 | if ($previousFileSourcesCount) { 581 | $absoluteValue = $value + $previousFileSourcesCount; 582 | $value = $absoluteValue - $previousFileLast->source; 583 | } 584 | $str .= Kwf_SourceMaps_Base64VLQ::encode($value); 585 | 586 | // Original line. 587 | $str .= Kwf_SourceMaps_Base64VLQ::encode(Kwf_SourceMaps_Base64VLQ::decodePos($otherMappings, $otherMappingsPos) - $previousFileLast->originalLine); 588 | 589 | // Original column. 590 | $str .= Kwf_SourceMaps_Base64VLQ::encode(Kwf_SourceMaps_Base64VLQ::decodePos($otherMappings, $otherMappingsPos) - $previousFileLast->originalColumn); 591 | 592 | // Original name. 593 | if ($otherMappingsPos < $otherMappingsEnd && !($otherMappings[$otherMappingsPos] == ',' || $otherMappings[$otherMappingsPos] == ';')) { 594 | $value = Kwf_SourceMaps_Base64VLQ::decodePos($otherMappings, $otherMappingsPos); 595 | if ($previousFileNamesCount) { 596 | $absoluteValue = $value + $previousFileNamesCount; 597 | $value = $absoluteValue - $previousFileLast->name; 598 | } 599 | $str .= Kwf_SourceMaps_Base64VLQ::encode($value); 600 | } else if (!count($data->names)) { 601 | //file doesn't have names at all, we don't have to adjust that offset 602 | } else { 603 | //loop thru mappings until we find a block with name 604 | while ($otherMappingsPos < $otherMappingsEnd) { 605 | if ($otherMappings[$otherMappingsPos] === ';') { 606 | $str .= $otherMappings[$otherMappingsPos]; 607 | $otherMappingsPos++; 608 | } else if ($otherMappings[$otherMappingsPos] === ',') { 609 | $str .= $otherMappings[$otherMappingsPos]; 610 | $otherMappingsPos++; 611 | } else { 612 | // Generated column. 613 | $str .= Kwf_SourceMaps_Base64VLQ::encode(Kwf_SourceMaps_Base64VLQ::decodePos($otherMappings, $otherMappingsPos)); 614 | 615 | if ($otherMappingsPos < $otherMappingsEnd && !($otherMappings[$otherMappingsPos] == ',' || $otherMappings[$otherMappingsPos] == ';')) { 616 | // Original source. 617 | $str .= Kwf_SourceMaps_Base64VLQ::encode(Kwf_SourceMaps_Base64VLQ::decodePos($otherMappings, $otherMappingsPos)); 618 | 619 | // Original line. 620 | $str .= Kwf_SourceMaps_Base64VLQ::encode(Kwf_SourceMaps_Base64VLQ::decodePos($otherMappings, $otherMappingsPos)); 621 | 622 | // Original column. 623 | $str .= Kwf_SourceMaps_Base64VLQ::encode(Kwf_SourceMaps_Base64VLQ::decodePos($otherMappings, $otherMappingsPos)); 624 | 625 | if ($otherMappingsPos < $otherMappingsEnd && !($otherMappings[$otherMappingsPos] == ',' || $otherMappings[$otherMappingsPos] == ';')) { 626 | // Original name. 627 | $value = Kwf_SourceMaps_Base64VLQ::decodePos($otherMappings, $otherMappingsPos); 628 | if ($previousFileNamesCount) { 629 | $absoluteValue = $value + $previousFileNamesCount; 630 | $value = $absoluteValue - $previousFileLast->name; 631 | } 632 | $str .= Kwf_SourceMaps_Base64VLQ::encode($value); 633 | break; 634 | } 635 | } 636 | } 637 | } 638 | } 639 | } 640 | 641 | } 642 | 643 | $this->_map->mappings .= $str.substr($otherMappings, $otherMappingsPos); 644 | 645 | $this->_map->{'_x_org_koala-framework_last'} = (object) array( 646 | 'source' => $previousFileSourcesCount + $data->{'_x_org_koala-framework_last'}->source, 647 | 'name' => $previousFileNamesCount + $data->{'_x_org_koala-framework_last'}->name, 648 | 'originalLine' => $data->{'_x_org_koala-framework_last'}->originalLine, 649 | 'originalColumn' => $data->{'_x_org_koala-framework_last'}->originalColumn 650 | ); 651 | } 652 | 653 | /** 654 | * Returns the contents of the minified file 655 | */ 656 | public function getFileContents() 657 | { 658 | return $this->_fileContents; 659 | } 660 | 661 | /** 662 | * Sets the contents of the minified file 663 | */ 664 | public function setFileContents($fileContents) 665 | { 666 | $this->_fileContents = $fileContents; 667 | return $this; 668 | } 669 | 670 | /** 671 | * Returns the contents of the source map as string 672 | * 673 | * @return string 674 | */ 675 | public function getMapContents($includeLastExtension = true) 676 | { 677 | if ($this->_mappingsChanged) { 678 | $this->_generateMappings(); 679 | } 680 | if ($includeLastExtension && !isset($this->_map->{'_x_org_koala-framework_last'})) { 681 | $this->_addLastExtension(); 682 | } 683 | return json_encode($this->_map); 684 | } 685 | 686 | /** 687 | * Returns the contents of the source map as object (that can be json_encoded) 688 | * 689 | * @return stdObject 690 | */ 691 | public function getMapContentsData($includeLastExtension = true) 692 | { 693 | if ($this->_mappingsChanged) { 694 | $this->_generateMappings(); 695 | } 696 | if ($includeLastExtension && !isset($this->_map->{'_x_org_koala-framework_last'})) { 697 | $this->_addLastExtension(); 698 | } 699 | return $this->_map; 700 | } 701 | 702 | /** 703 | * Save the source map to a file 704 | * 705 | * @param string file name the source map should be saved to 706 | * @param string optional file name the minified file should be saved to 707 | */ 708 | public function save($mapFileName, $fileFileName = null) 709 | { 710 | if ($fileFileName !== null) { 711 | file_put_contents($fileFileName, $this->_fileContents); 712 | } 713 | file_put_contents($mapFileName, $this->getMapContents()); 714 | } 715 | 716 | /** 717 | * Returns the contents of the minimied file with source map data appended inline as data url 718 | * 719 | * @return string 720 | */ 721 | public function getFileContentsInlineMap($includeLastExtension = true) 722 | { 723 | $ret = $this->_fileContents; 724 | if ($this->_mimeType == 'text/css') { 725 | $ret .= "\n/*# sourceMappingURL=data:application/json;base64,".base64_encode($this->getMapContents($includeLastExtension))." */\n"; 726 | } else { 727 | $ret .= "\n//# sourceMappingURL=data:application/json;base64,".base64_encode($this->getMapContents($includeLastExtension))."\n"; 728 | } 729 | return $ret; 730 | } 731 | } 732 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Source Maps Utilities Php Library[![Build Status](https://travis-ci.org/koala-framework/sourcemaps.svg?branch=master)](https://travis-ci.org/koala-framework/sourcemaps) 3 | 4 | ### Features 5 | 6 | * creating mappings 7 | * reading mappings 8 | * source map aware string replace for existing mapping 9 | * concat maps (optimized for best performance) 10 | 11 | ### Requirements 12 | 13 | * Php 5.2+ 14 | 15 | ### Installation 16 | Install using composer: 17 | 18 | composer require koala-framework/sourcemaps 19 | 20 | ### Example Usage 21 | 22 | //read 23 | $map = new Kwf_SourceMaps_SourceMap($mapContents, $minimiedFileContents); 24 | $map->getMappings() 25 | 26 | //create new map 27 | $map = Kwf_SourceMaps_SourceMap::createEmptyMap($minimiedFileContents); 28 | $map->addMapping(2, 3, 10, 12, 'foo.js'); //$generatedLine, $generatedColumn, $originalLine, $originalColumn, $originalSource, $originalName = null) 29 | $map->getMapContents(); 30 | 31 | //merge two maps 32 | $map1->concat($map2); 33 | 34 | //perform string replacement 35 | $map->stringReplace('foo', 'bar'); 36 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "koala-framework/sourcemaps", 3 | "description": "Sourcemaps Utities", 4 | "homepage": "http://www.koala-framework.org/", 5 | "license": "BSD-2-Clause", 6 | "require": { 7 | }, 8 | "require-dev": { 9 | "phpunit/phpunit": "3.7.*" 10 | }, 11 | "autoload": { 12 | "psr-0": { 13 | "Kwf_SourceMaps_": "" 14 | } 15 | }, 16 | "autoload-dev": { 17 | "psr-0": { 18 | "Kwf_SourceMaps_": "tests" 19 | } 20 | }, 21 | "extra": { 22 | "branch-alias": { 23 | "dev-master": "0.2-dev" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "0acaf28d41b926c0558d48d6601275df", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "phpunit/php-code-coverage", 12 | "version": "1.2.18", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 16 | "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", 21 | "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "php": ">=5.3.3", 26 | "phpunit/php-file-iterator": ">=1.3.0@stable", 27 | "phpunit/php-text-template": ">=1.2.0@stable", 28 | "phpunit/php-token-stream": ">=1.1.3,<1.3.0" 29 | }, 30 | "require-dev": { 31 | "phpunit/phpunit": "3.7.*@dev" 32 | }, 33 | "suggest": { 34 | "ext-dom": "*", 35 | "ext-xdebug": ">=2.0.5" 36 | }, 37 | "type": "library", 38 | "extra": { 39 | "branch-alias": { 40 | "dev-master": "1.2.x-dev" 41 | } 42 | }, 43 | "autoload": { 44 | "classmap": [ 45 | "PHP/" 46 | ] 47 | }, 48 | "notification-url": "https://packagist.org/downloads/", 49 | "include-path": [ 50 | "" 51 | ], 52 | "license": [ 53 | "BSD-3-Clause" 54 | ], 55 | "authors": [ 56 | { 57 | "name": "Sebastian Bergmann", 58 | "email": "sb@sebastian-bergmann.de", 59 | "role": "lead" 60 | } 61 | ], 62 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 63 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 64 | "keywords": [ 65 | "coverage", 66 | "testing", 67 | "xunit" 68 | ], 69 | "time": "2014-09-02 10:13:14" 70 | }, 71 | { 72 | "name": "phpunit/php-file-iterator", 73 | "version": "1.3.4", 74 | "source": { 75 | "type": "git", 76 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 77 | "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" 78 | }, 79 | "dist": { 80 | "type": "zip", 81 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", 82 | "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", 83 | "shasum": "" 84 | }, 85 | "require": { 86 | "php": ">=5.3.3" 87 | }, 88 | "type": "library", 89 | "autoload": { 90 | "classmap": [ 91 | "File/" 92 | ] 93 | }, 94 | "notification-url": "https://packagist.org/downloads/", 95 | "include-path": [ 96 | "" 97 | ], 98 | "license": [ 99 | "BSD-3-Clause" 100 | ], 101 | "authors": [ 102 | { 103 | "name": "Sebastian Bergmann", 104 | "email": "sb@sebastian-bergmann.de", 105 | "role": "lead" 106 | } 107 | ], 108 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 109 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 110 | "keywords": [ 111 | "filesystem", 112 | "iterator" 113 | ], 114 | "time": "2013-10-10 15:34:57" 115 | }, 116 | { 117 | "name": "phpunit/php-text-template", 118 | "version": "1.2.0", 119 | "source": { 120 | "type": "git", 121 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 122 | "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" 123 | }, 124 | "dist": { 125 | "type": "zip", 126 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", 127 | "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", 128 | "shasum": "" 129 | }, 130 | "require": { 131 | "php": ">=5.3.3" 132 | }, 133 | "type": "library", 134 | "autoload": { 135 | "classmap": [ 136 | "Text/" 137 | ] 138 | }, 139 | "notification-url": "https://packagist.org/downloads/", 140 | "include-path": [ 141 | "" 142 | ], 143 | "license": [ 144 | "BSD-3-Clause" 145 | ], 146 | "authors": [ 147 | { 148 | "name": "Sebastian Bergmann", 149 | "email": "sb@sebastian-bergmann.de", 150 | "role": "lead" 151 | } 152 | ], 153 | "description": "Simple template engine.", 154 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 155 | "keywords": [ 156 | "template" 157 | ], 158 | "time": "2014-01-30 17:20:04" 159 | }, 160 | { 161 | "name": "phpunit/php-timer", 162 | "version": "1.0.5", 163 | "source": { 164 | "type": "git", 165 | "url": "https://github.com/sebastianbergmann/php-timer.git", 166 | "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" 167 | }, 168 | "dist": { 169 | "type": "zip", 170 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", 171 | "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", 172 | "shasum": "" 173 | }, 174 | "require": { 175 | "php": ">=5.3.3" 176 | }, 177 | "type": "library", 178 | "autoload": { 179 | "classmap": [ 180 | "PHP/" 181 | ] 182 | }, 183 | "notification-url": "https://packagist.org/downloads/", 184 | "include-path": [ 185 | "" 186 | ], 187 | "license": [ 188 | "BSD-3-Clause" 189 | ], 190 | "authors": [ 191 | { 192 | "name": "Sebastian Bergmann", 193 | "email": "sb@sebastian-bergmann.de", 194 | "role": "lead" 195 | } 196 | ], 197 | "description": "Utility class for timing", 198 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 199 | "keywords": [ 200 | "timer" 201 | ], 202 | "time": "2013-08-02 07:42:54" 203 | }, 204 | { 205 | "name": "phpunit/php-token-stream", 206 | "version": "1.2.2", 207 | "source": { 208 | "type": "git", 209 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 210 | "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32" 211 | }, 212 | "dist": { 213 | "type": "zip", 214 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32", 215 | "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32", 216 | "shasum": "" 217 | }, 218 | "require": { 219 | "ext-tokenizer": "*", 220 | "php": ">=5.3.3" 221 | }, 222 | "type": "library", 223 | "extra": { 224 | "branch-alias": { 225 | "dev-master": "1.2-dev" 226 | } 227 | }, 228 | "autoload": { 229 | "classmap": [ 230 | "PHP/" 231 | ] 232 | }, 233 | "notification-url": "https://packagist.org/downloads/", 234 | "include-path": [ 235 | "" 236 | ], 237 | "license": [ 238 | "BSD-3-Clause" 239 | ], 240 | "authors": [ 241 | { 242 | "name": "Sebastian Bergmann", 243 | "email": "sb@sebastian-bergmann.de", 244 | "role": "lead" 245 | } 246 | ], 247 | "description": "Wrapper around PHP's tokenizer extension.", 248 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 249 | "keywords": [ 250 | "tokenizer" 251 | ], 252 | "time": "2014-03-03 05:10:30" 253 | }, 254 | { 255 | "name": "phpunit/phpunit", 256 | "version": "3.7.38", 257 | "source": { 258 | "type": "git", 259 | "url": "https://github.com/sebastianbergmann/phpunit.git", 260 | "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6" 261 | }, 262 | "dist": { 263 | "type": "zip", 264 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/38709dc22d519a3d1be46849868aa2ddf822bcf6", 265 | "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6", 266 | "shasum": "" 267 | }, 268 | "require": { 269 | "ext-ctype": "*", 270 | "ext-dom": "*", 271 | "ext-json": "*", 272 | "ext-pcre": "*", 273 | "ext-reflection": "*", 274 | "ext-spl": "*", 275 | "php": ">=5.3.3", 276 | "phpunit/php-code-coverage": "~1.2", 277 | "phpunit/php-file-iterator": "~1.3", 278 | "phpunit/php-text-template": "~1.1", 279 | "phpunit/php-timer": "~1.0", 280 | "phpunit/phpunit-mock-objects": "~1.2", 281 | "symfony/yaml": "~2.0" 282 | }, 283 | "require-dev": { 284 | "pear-pear.php.net/pear": "1.9.4" 285 | }, 286 | "suggest": { 287 | "phpunit/php-invoker": "~1.1" 288 | }, 289 | "bin": [ 290 | "composer/bin/phpunit" 291 | ], 292 | "type": "library", 293 | "extra": { 294 | "branch-alias": { 295 | "dev-master": "3.7.x-dev" 296 | } 297 | }, 298 | "autoload": { 299 | "classmap": [ 300 | "PHPUnit/" 301 | ] 302 | }, 303 | "notification-url": "https://packagist.org/downloads/", 304 | "include-path": [ 305 | "", 306 | "../../symfony/yaml/" 307 | ], 308 | "license": [ 309 | "BSD-3-Clause" 310 | ], 311 | "authors": [ 312 | { 313 | "name": "Sebastian Bergmann", 314 | "email": "sebastian@phpunit.de", 315 | "role": "lead" 316 | } 317 | ], 318 | "description": "The PHP Unit Testing framework.", 319 | "homepage": "http://www.phpunit.de/", 320 | "keywords": [ 321 | "phpunit", 322 | "testing", 323 | "xunit" 324 | ], 325 | "time": "2014-10-17 09:04:17" 326 | }, 327 | { 328 | "name": "phpunit/phpunit-mock-objects", 329 | "version": "1.2.3", 330 | "source": { 331 | "type": "git", 332 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 333 | "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875" 334 | }, 335 | "dist": { 336 | "type": "zip", 337 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875", 338 | "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875", 339 | "shasum": "" 340 | }, 341 | "require": { 342 | "php": ">=5.3.3", 343 | "phpunit/php-text-template": ">=1.1.1@stable" 344 | }, 345 | "suggest": { 346 | "ext-soap": "*" 347 | }, 348 | "type": "library", 349 | "autoload": { 350 | "classmap": [ 351 | "PHPUnit/" 352 | ] 353 | }, 354 | "notification-url": "https://packagist.org/downloads/", 355 | "include-path": [ 356 | "" 357 | ], 358 | "license": [ 359 | "BSD-3-Clause" 360 | ], 361 | "authors": [ 362 | { 363 | "name": "Sebastian Bergmann", 364 | "email": "sb@sebastian-bergmann.de", 365 | "role": "lead" 366 | } 367 | ], 368 | "description": "Mock Object library for PHPUnit", 369 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 370 | "keywords": [ 371 | "mock", 372 | "xunit" 373 | ], 374 | "time": "2013-01-13 10:24:48" 375 | }, 376 | { 377 | "name": "symfony/yaml", 378 | "version": "v2.5.5", 379 | "target-dir": "Symfony/Component/Yaml", 380 | "source": { 381 | "type": "git", 382 | "url": "https://github.com/symfony/Yaml.git", 383 | "reference": "b1dbc53593b98c2d694ebf383660ac9134d30b96" 384 | }, 385 | "dist": { 386 | "type": "zip", 387 | "url": "https://api.github.com/repos/symfony/Yaml/zipball/b1dbc53593b98c2d694ebf383660ac9134d30b96", 388 | "reference": "b1dbc53593b98c2d694ebf383660ac9134d30b96", 389 | "shasum": "" 390 | }, 391 | "require": { 392 | "php": ">=5.3.3" 393 | }, 394 | "type": "library", 395 | "extra": { 396 | "branch-alias": { 397 | "dev-master": "2.5-dev" 398 | } 399 | }, 400 | "autoload": { 401 | "psr-0": { 402 | "Symfony\\Component\\Yaml\\": "" 403 | } 404 | }, 405 | "notification-url": "https://packagist.org/downloads/", 406 | "license": [ 407 | "MIT" 408 | ], 409 | "authors": [ 410 | { 411 | "name": "Symfony Community", 412 | "homepage": "http://symfony.com/contributors" 413 | }, 414 | { 415 | "name": "Fabien Potencier", 416 | "email": "fabien@symfony.com" 417 | } 418 | ], 419 | "description": "Symfony Yaml Component", 420 | "homepage": "http://symfony.com", 421 | "time": "2014-09-22 09:14:18" 422 | } 423 | ], 424 | "aliases": [], 425 | "minimum-stability": "stable", 426 | "stability-flags": [], 427 | "prefer-stable": false, 428 | "platform": [], 429 | "platform-dev": [] 430 | } 431 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./tests/ 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /tests/Kwf/SourceMaps/ConcatTest.php: -------------------------------------------------------------------------------- 1 | concat($map2); 9 | 10 | $mappings = $map1->getMappings(); 11 | $this->assertEquals(13*2, count($mappings)); 12 | $this->assertEquals($mappings[0], array( 13 | 'generatedLine' => 1, 14 | 'generatedColumn' => 1, 15 | 'originalSource' => '/the/root/one.js', 16 | 'originalLine' => 1, 17 | 'originalColumn' => 1, 18 | 'originalName' => null 19 | )); 20 | $this->assertEquals($mappings[12], array( 21 | 'generatedLine' => 2, 22 | 'generatedColumn' => 28, 23 | 'originalSource' => '/the/root/two.js', 24 | 'originalLine' => 2, 25 | 'originalColumn' => 10, 26 | 'originalName' => 'n' 27 | )); 28 | 29 | $mappingsOffs = 13; 30 | $genLineOffs = 2; 31 | $this->assertEquals($mappings[$mappingsOffs+0], array( 32 | 'generatedLine' => $genLineOffs+1, 33 | 'generatedColumn' => 1, 34 | 'originalSource' => '/the/root/one.js', 35 | 'originalLine' => 1, 36 | 'originalColumn' => 1, 37 | 'originalName' => null 38 | )); 39 | $this->assertEquals($mappings[$mappingsOffs+12], array( 40 | 'generatedLine' => $genLineOffs+2, 41 | 'generatedColumn' => 28, 42 | 'originalSource' => '/the/root/two.js', 43 | 'originalLine' => 2, 44 | 'originalColumn' => 10, 45 | 'originalName' => 'n' 46 | )); 47 | 48 | $contents = $map1->getFileContents(); 49 | $contents = explode("\n", $contents); 50 | $this->assertEquals(2*2, count($contents)); 51 | } 52 | 53 | public function testConcatThree() 54 | { 55 | $map1 = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$testMap, Kwf_SourceMaps_TestData::$testGeneratedCode); 56 | $map2 = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$testMap, Kwf_SourceMaps_TestData::$testGeneratedCode); 57 | $map3 = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$testMap, Kwf_SourceMaps_TestData::$testGeneratedCode); 58 | $map1->concat($map2); 59 | $map1->concat($map3); 60 | 61 | $mappings = $map1->getMappings(); 62 | $this->assertEquals(13*3, count($mappings)); 63 | $this->assertEquals($mappings[0], array( 64 | 'generatedLine' => 1, 65 | 'generatedColumn' => 1, 66 | 'originalSource' => '/the/root/one.js', 67 | 'originalLine' => 1, 68 | 'originalColumn' => 1, 69 | 'originalName' => null 70 | )); 71 | $this->assertEquals($mappings[12], array( 72 | 'generatedLine' => 2, 73 | 'generatedColumn' => 28, 74 | 'originalSource' => '/the/root/two.js', 75 | 'originalLine' => 2, 76 | 'originalColumn' => 10, 77 | 'originalName' => 'n' 78 | )); 79 | 80 | $mappingsOffs = 13*2; 81 | $genLineOffs = 2*2; 82 | $this->assertEquals($mappings[$mappingsOffs+0], array( 83 | 'generatedLine' => $genLineOffs+1, 84 | 'generatedColumn' => 1, 85 | 'originalSource' => '/the/root/one.js', 86 | 'originalLine' => 1, 87 | 'originalColumn' => 1, 88 | 'originalName' => null 89 | )); 90 | $this->assertEquals($mappings[$mappingsOffs+12], array( 91 | 'generatedLine' => $genLineOffs+2, 92 | 'generatedColumn' => 28, 93 | 'originalSource' => '/the/root/two.js', 94 | 'originalLine' => 2, 95 | 'originalColumn' => 10, 96 | 'originalName' => 'n' 97 | )); 98 | 99 | $contents = $map1->getFileContents(); 100 | $contents = explode("\n", $contents); 101 | $this->assertEquals(2*3, count($contents)); 102 | } 103 | 104 | public function testWithEmpty() 105 | { 106 | $map = Kwf_SourceMaps_SourceMap::createEmptyMap(''); 107 | $map1 = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$testMap, Kwf_SourceMaps_TestData::$testGeneratedCode); 108 | $map->setSourceRoot($map1->getSourceRoot()); 109 | $map2 = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$testMap, Kwf_SourceMaps_TestData::$testGeneratedCode); 110 | $map->concat($map1); 111 | $map->concat($map2); 112 | 113 | $mappings = $map->getMappings(); 114 | $this->assertEquals(13*2, count($mappings)); 115 | $this->assertEquals($mappings[0], array( 116 | 'generatedLine' => 1, 117 | 'generatedColumn' => 1, 118 | 'originalSource' => '/the/root/one.js', 119 | 'originalLine' => 1, 120 | 'originalColumn' => 1, 121 | 'originalName' => null 122 | )); 123 | $this->assertEquals($mappings[12], array( 124 | 'generatedLine' => 2, 125 | 'generatedColumn' => 28, 126 | 'originalSource' => '/the/root/two.js', 127 | 'originalLine' => 2, 128 | 'originalColumn' => 10, 129 | 'originalName' => 'n' 130 | )); 131 | 132 | $mappingsOffs = 13; 133 | $genLineOffs = 2; 134 | $this->assertEquals($mappings[$mappingsOffs+0], array( 135 | 'generatedLine' => $genLineOffs+1, 136 | 'generatedColumn' => 1, 137 | 'originalSource' => '/the/root/one.js', 138 | 'originalLine' => 1, 139 | 'originalColumn' => 1, 140 | 'originalName' => null 141 | )); 142 | $this->assertEquals($mappings[$mappingsOffs+12], array( 143 | 'generatedLine' => $genLineOffs+2, 144 | 'generatedColumn' => 28, 145 | 'originalSource' => '/the/root/two.js', 146 | 'originalLine' => 2, 147 | 'originalColumn' => 10, 148 | 'originalName' => 'n' 149 | )); 150 | 151 | $contents = $map->getFileContents(); 152 | $contents = explode("\n", $contents); 153 | $this->assertEquals(2*2, count($contents)); 154 | } 155 | 156 | public function testWithNoMapping1() 157 | { 158 | $map = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$testSmallMap1, Kwf_SourceMaps_TestData::$testSmallGeneratedCode1); 159 | $map1 = Kwf_SourceMaps_SourceMap::createEmptyMap("aaa;\nbbb;\n"); 160 | $map2 = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$testSmallMap2, Kwf_SourceMaps_TestData::$testSmallGeneratedCode2); 161 | $map->concat($map1); 162 | $map->concat($map2); 163 | 164 | $mappings = $map->getMappings(); 165 | $mappingsOffs = 2; 166 | $genLineOffs = 1+2; 167 | $this->assertEquals($mappings[$mappingsOffs+0], array( 168 | 'generatedLine' => $genLineOffs+1, 169 | 'generatedColumn' => 1, 170 | 'originalSource' => '/the/root/one2.js', 171 | 'originalLine' => 1, 172 | 'originalColumn' => 1, 173 | 'originalName' => null 174 | )); 175 | $this->assertEquals($mappings[$mappingsOffs+1], array( 176 | 'generatedLine' => $genLineOffs+1, 177 | 'generatedColumn' => 5, 178 | 'originalSource' => '/the/root/one2.js', 179 | 'originalLine' => 1, 180 | 'originalColumn' => 5, 181 | 'originalName' => null 182 | )); 183 | } 184 | 185 | public function testWithNoMapping2() 186 | { 187 | $map = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$testSmallMap1, Kwf_SourceMaps_TestData::$testSmallGeneratedCode1); 188 | $map1 = Kwf_SourceMaps_SourceMap::createEmptyMap("aaa;\nbbb;"); 189 | $map2 = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$testSmallMap2, Kwf_SourceMaps_TestData::$testSmallGeneratedCode2); 190 | $map->concat($map1); 191 | $map->concat($map2); 192 | 193 | $mappings = $map->getMappings(); 194 | $mappingsOffs = 2; 195 | $genLineOffs = 1+2; 196 | $this->assertEquals($mappings[$mappingsOffs+0], array( 197 | 'generatedLine' => $genLineOffs+1, 198 | 'generatedColumn' => 1, 199 | 'originalSource' => '/the/root/one2.js', 200 | 'originalLine' => 1, 201 | 'originalColumn' => 1, 202 | 'originalName' => null 203 | )); 204 | $this->assertEquals($mappings[$mappingsOffs+1], array( 205 | 'generatedLine' => $genLineOffs+1, 206 | 'generatedColumn' => 5, 207 | 'originalSource' => '/the/root/one2.js', 208 | 'originalLine' => 1, 209 | 'originalColumn' => 5, 210 | 'originalName' => null 211 | )); 212 | } 213 | 214 | public function testWithoutMappingInLastLine() 215 | { 216 | $d1 = Kwf_SourceMaps_SourceMap::createEmptyMap(".kwcClass{a:red}\n"); 217 | $d1->addMapping(1, 0, 1, 0, 'aaa.scss'); 218 | 219 | $d2 = Kwf_SourceMaps_SourceMap::createEmptyMap('aaa'); 220 | $d2->addMapping(1, 0, 3, 0, 'bbb.scss'); 221 | 222 | $map = Kwf_SourceMaps_SourceMap::createEmptyMap(''); 223 | foreach (array($d1, $d2) as $c) { 224 | $map->concat($c); 225 | } 226 | $mappings = $map->getMappings(); 227 | $this->assertEquals($mappings[0], array( 228 | 'generatedLine' => 1, 229 | 'generatedColumn' => 0, 230 | 'originalSource' => 'aaa.scss', 231 | 'originalLine' => 1, 232 | 'originalColumn' => 0, 233 | 'originalName' => null 234 | )); 235 | $this->assertEquals($mappings[1], array( 236 | 'generatedLine' => 2, 237 | 'generatedColumn' => 0, 238 | 'originalSource' => 'bbb.scss', 239 | 'originalLine' => 3, 240 | 'originalColumn' => 0, 241 | 'originalName' => null 242 | )); 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /tests/Kwf/SourceMaps/CreateTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(!!$map->getMapContents()); 8 | $data = $map->getMapContentsData(); 9 | $this->assertTrue(!!$data); 10 | } 11 | 12 | public function testCreateSimple() 13 | { 14 | $map = Kwf_SourceMaps_SourceMap::createEmptyMap(Kwf_SourceMaps_TestData::$testGeneratedCode); 15 | $map->addMapping(1, 1, 1, 1, 'one.js'); 16 | $map->addMapping(1, 5, 1, 5, 'one.js'); 17 | $map->addMapping(1, 9, 1, 11, 'one.js'); 18 | $map->addMapping(1, 18, 1, 21, 'one.js', 'bar'); 19 | $map->addMapping(1, 21, 2, 3, 'one.js'); 20 | $map->addMapping(1, 28, 2, 10, 'one.js', 'baz'); 21 | $map->addMapping(1, 32, 2, 14, 'one.js', 'bar'); 22 | 23 | $map->addMapping(2, 1, 1, 1, 'two.js'); 24 | $map->addMapping(2, 5, 1, 5, 'two.js'); 25 | $map->addMapping(2, 9, 1, 11, 'two.js'); 26 | $map->addMapping(2, 18, 1, 21, 'two.js', 'n'); 27 | $map->addMapping(2, 21, 2, 3, 'two.js'); 28 | $map->addMapping(2, 28, 2, 10, 'two.js', 'n'); 29 | $this->assertEquals(13, count($map->getMappings())); 30 | $data = $map->getMapContentsData(); 31 | 32 | $testData = json_decode(Kwf_SourceMaps_TestData::$testMap); 33 | $this->assertEquals($data->mappings, $testData->mappings); 34 | $this->assertEquals($data->names, $testData->names); 35 | $this->assertEquals($data->sources, $testData->sources); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/Kwf/SourceMaps/SourcesTest.php: -------------------------------------------------------------------------------- 1 | getMappings(); 8 | $sources = $map->getSources(); 9 | $this->assertEquals(array('one.js', 'two.js'), $sources); 10 | } 11 | 12 | public function testAdd() 13 | { 14 | $map = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$testMap, Kwf_SourceMaps_TestData::$testGeneratedCode); 15 | $mappings = $map->getMappings(); 16 | $map->addSource('three.js'); 17 | $sources = $map->getSources(); 18 | $this->assertEquals(array('one.js', 'two.js', 'three.js'), $sources); 19 | 20 | $c = $map->getFileContentsInlineMap(false); 21 | $map = Kwf_SourceMaps_SourceMap::createFromInline($c); 22 | $this->assertEquals(array('one.js', 'two.js', 'three.js'), $sources); 23 | 24 | $map->addMapping(1, 1, 1, 1, 'one.js'); 25 | $c = $map->getFileContentsInlineMap(false); 26 | $this->assertEquals(array('one.js', 'two.js', 'three.js'), $sources); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/Kwf/SourceMaps/StringReplaceTest.php: -------------------------------------------------------------------------------- 1 | stringReplace('baz', 'asdfasdf'); 8 | 9 | //0 1 2 3 4 10 | //1234567890123456789012345678901234567890123 11 | $s = " ONE.foo=function(a){return asdfasdf(a);};\n". 12 | " TWO.inc=function(a){return a+1;};"; 13 | $this->assertEquals($map->getFileContents(), $s); 14 | 15 | $mappings = $map->getMappings(); 16 | $this->assertEquals($mappings[5], array( 17 | 'generatedLine' => 1, 18 | 'generatedColumn' => 28, //must not change 19 | 'originalSource' => '/the/root/one.js', 20 | 'originalLine' => 2, 21 | 'originalColumn' => 10, 22 | 'originalName' => 'baz' 23 | )); 24 | $this->assertEquals($mappings[6], array( 25 | 'generatedLine' => 1, 26 | 'generatedColumn' => 32+5, //this needs to be shifted 27 | 'originalSource' => '/the/root/one.js', 28 | 'originalLine' => 2, 29 | 'originalColumn' => 14, 30 | 'originalName' => 'bar' 31 | )); 32 | 33 | //first of line 2 34 | $this->assertEquals($mappings[7], array( 35 | 'generatedLine' => 2, 36 | 'generatedColumn' => 1, //must not change 37 | 'originalSource' => '/the/root/two.js', 38 | 'originalLine' => 1, 39 | 'originalColumn' => 1, 40 | 'originalName' => null 41 | )); 42 | } 43 | 44 | public function testStringReplaceSecondLine() 45 | { 46 | $map = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$testMap, Kwf_SourceMaps_TestData::$testGeneratedCode); 47 | $map->stringReplace('inc', 'increment'); 48 | 49 | //0 1 2 3 4 50 | //1234567890123456789012345678901234567890123 51 | // TWO.inc=function(a){return a+1;}; 52 | $s = " ONE.foo=function(a){return baz(a);};\n". 53 | " TWO.increment=function(a){return a+1;};"; 54 | $this->assertEquals($map->getFileContents(), $s); 55 | 56 | $mappings = $map->getMappings(); 57 | //last of line 1 58 | $this->assertEquals($mappings[6], array( 59 | 'generatedLine' => 1, 60 | 'generatedColumn' => 32, 61 | 'originalSource' => '/the/root/one.js', 62 | 'originalLine' => 2, 63 | 'originalColumn' => 14, 64 | 'originalName' => 'bar' 65 | )); 66 | 67 | 68 | $this->assertEquals($mappings[7], array( 69 | 'generatedLine' => 2, 70 | 'generatedColumn' => 1, //don't change 71 | 'originalSource' => '/the/root/two.js', 72 | 'originalLine' => 1, 73 | 'originalColumn' => 1, 74 | 'originalName' => null 75 | )); 76 | $this->assertEquals($mappings[8], array( 77 | 'generatedLine' => 2, 78 | 'generatedColumn' => 5, //don't change 79 | 'originalSource' => '/the/root/two.js', 80 | 'originalLine' => 1, 81 | 'originalColumn' => 5, 82 | 'originalName' => null 83 | )); 84 | $this->assertEquals($mappings[9], array( 85 | 'generatedLine' => 2, 86 | 'generatedColumn' => 9+6, 87 | 'originalSource' => '/the/root/two.js', 88 | 'originalLine' => 1, 89 | 'originalColumn' => 11, 90 | 'originalName' => null 91 | )); 92 | $this->assertEquals($mappings[10], array( 93 | 'generatedLine' => 2, 94 | 'generatedColumn' => 18+6, 95 | 'originalSource' => '/the/root/two.js', 96 | 'originalLine' => 1, 97 | 'originalColumn' => 21, 98 | 'originalName' => 'n' 99 | )); 100 | $this->assertEquals($mappings[12], array( 101 | 'generatedLine' => 2, 102 | 'generatedColumn' => 28+6, 103 | 'originalSource' => '/the/root/two.js', 104 | 'originalLine' => 2, 105 | 'originalColumn' => 10, 106 | 'originalName' => 'n' 107 | )); 108 | } 109 | 110 | public function testStringReplaceMultipleInOneLine() 111 | { 112 | $map = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$testMap, Kwf_SourceMaps_TestData::$testGeneratedCode); 113 | $map->stringReplace('a', 'xbbbbxxxxxxxx'); 114 | 115 | //0 1 2 3 4 116 | //1234567890123456789012345678901234567890123 117 | // ONE.foo=function(a){return baz(a);}; 118 | $s = " ONE.foo=function(xbbbbxxxxxxxx){return bxbbbbxxxxxxxxz(xbbbbxxxxxxxx);};\n". 119 | // TWO.inc=function(a){return a+1;}; 120 | " TWO.inc=function(xbbbbxxxxxxxx){return xbbbbxxxxxxxx+1;};"; 121 | $this->assertEquals($map->getFileContents(), $s); 122 | 123 | $mappings = $map->getMappings(); 124 | $this->assertEquals($mappings[3], array( 125 | 'generatedLine' => 1, 126 | 'generatedColumn' => 18, 127 | 'originalSource' => '/the/root/one.js', 128 | 'originalLine' => 1, 129 | 'originalColumn' => 21, 130 | 'originalName' => 'bar' 131 | )); 132 | $this->assertEquals($mappings[4], array( 133 | 'generatedLine' => 1, 134 | 'generatedColumn' => 21+12, 135 | 'originalSource' => '/the/root/one.js', 136 | 'originalLine' => 2, 137 | 'originalColumn' => 3, 138 | 'originalName' => null 139 | )); 140 | $this->assertEquals($mappings[5], array( 141 | 'generatedLine' => 1, 142 | 'generatedColumn' => 28+12, 143 | 'originalSource' => '/the/root/one.js', 144 | 'originalLine' => 2, 145 | 'originalColumn' => 10, 146 | 'originalName' => 'baz' 147 | )); 148 | $this->assertEquals($mappings[6], array( 149 | 'generatedLine' => 1, 150 | 'generatedColumn' => 32+12+12, 151 | 'originalSource' => '/the/root/one.js', 152 | 'originalLine' => 2, 153 | 'originalColumn' => 14, 154 | 'originalName' => 'bar' 155 | )); 156 | 157 | 158 | $this->assertEquals($mappings[10], array( 159 | 'generatedLine' => 2, 160 | 'generatedColumn' => 18, 161 | 'originalSource' => '/the/root/two.js', 162 | 'originalLine' => 1, 163 | 'originalColumn' => 21, 164 | 'originalName' => 'n' 165 | )); 166 | $this->assertEquals($mappings[11], array( 167 | 'generatedLine' => 2, 168 | 'generatedColumn' => 21+12, 169 | 'originalSource' => '/the/root/two.js', 170 | 'originalLine' => 2, 171 | 'originalColumn' => 3, 172 | 'originalName' => null 173 | )); 174 | $this->assertEquals($mappings[12], array( 175 | 'generatedLine' => 2, 176 | 'generatedColumn' => 28+12, 177 | 'originalSource' => '/the/root/two.js', 178 | 'originalLine' => 2, 179 | 'originalColumn' => 10, 180 | 'originalName' => 'n' 181 | )); 182 | } 183 | 184 | public function testLeaveFirstMappingUntouched() 185 | { 186 | $map = Kwf_SourceMaps_SourceMap::createEmptyMap('(function($,window,document,undefined){});'); 187 | $map->addMapping(1, 1, 1, 1, 'foo.js'); 188 | $map->addMapping(1, 10, 1, 11, 'foo.js', '$'); 189 | $map->addMapping(1, 12, 1, 14, 'foo.js', 'window'); 190 | $map->addMapping(1, 19, 1, 22, 'foo.js', 'document'); 191 | $map->addMapping(1, 28, 1, 32, 'foo.js', 'undefined'); 192 | 193 | $map->stringReplace('(function($,window,document,undefined){', "var $=jQuery=require('jQuery');"); 194 | $mappings = $map->getMappings(); 195 | $this->assertEquals($mappings[0], array( 196 | 'generatedLine' => 1, 197 | 'generatedColumn' => 1, 198 | 'originalSource' => 'foo.js', 199 | 'originalLine' => 1, 200 | 'originalColumn' => 1, 201 | 'originalName' => null 202 | )); 203 | } 204 | 205 | public function testRemoveReplacedMapping() 206 | { 207 | //0 1 2 3 4 208 | //01234567890123456789012345678901234567890123456789 209 | $map = Kwf_SourceMaps_SourceMap::createEmptyMap('(function($,window,document,undefined){var x=1;});'); 210 | $map->addMapping(1, 1, 1, 1, 'foo.js'); 211 | $map->addMapping(1, 10, 1, 11, 'foo.js', '$'); 212 | $map->addMapping(1, 12, 1, 14, 'foo.js', 'window'); 213 | $map->addMapping(1, 19, 1, 22, 'foo.js', 'document'); 214 | $map->addMapping(1, 28, 1, 32, 'foo.js', 'undefined'); 215 | $map->addMapping(1, 43, 2, 5, 'foo.js', 'x'); 216 | 217 | $map->stringReplace('(function($,window,document,undefined){', "var $=jQuery=require('jQuery');"); 218 | $mappings = $map->getMappings(); 219 | $this->assertEquals(2, count($mappings)); 220 | $this->assertEquals($mappings[0], array( 221 | 'generatedLine' => 1, 222 | 'generatedColumn' => 1, 223 | 'originalSource' => 'foo.js', 224 | 'originalLine' => 1, 225 | 'originalColumn' => 1, 226 | 'originalName' => null 227 | )); 228 | 229 | $this->assertEquals($mappings[1], array( 230 | 'generatedLine' => 1, 231 | 'generatedColumn' => 43+31-39, 232 | 'originalSource' => 'foo.js', 233 | 'originalLine' => 2, 234 | 'originalColumn' => 5, 235 | 'originalName' => 'x' 236 | )); 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /tests/Kwf/SourceMaps/Test.php: -------------------------------------------------------------------------------- 1 | assertEquals($result, $i); 10 | $this->assertEquals($v, ""); 11 | } 12 | } 13 | 14 | public function testEmptyMap() 15 | { 16 | $map = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$emptyMap, ''); 17 | $mappings = $map->getMappings(); 18 | $this->assertEquals(count($mappings), 0); 19 | } 20 | 21 | public function testGetMappings() 22 | { 23 | $map = new Kwf_SourceMaps_SourceMap(Kwf_SourceMaps_TestData::$testMap, Kwf_SourceMaps_TestData::$testGeneratedCode); 24 | $mappings = $map->getMappings(); 25 | $this->assertEquals(count($mappings), 13); 26 | $this->assertEquals($mappings[0], array( 27 | 'generatedLine' => 1, 28 | 'generatedColumn' => 1, 29 | 'originalSource' => '/the/root/one.js', 30 | 'originalLine' => 1, 31 | 'originalColumn' => 1, 32 | 'originalName' => null 33 | )); 34 | $this->assertEquals($mappings[1], array( 35 | 'generatedLine' => 1, 36 | 'generatedColumn' => 5, 37 | 'originalSource' => '/the/root/one.js', 38 | 'originalLine' => 1, 39 | 'originalColumn' => 5, 40 | 'originalName' => null 41 | )); 42 | $this->assertEquals($mappings[2], array( 43 | 'generatedLine' => 1, 44 | 'generatedColumn' => 9, 45 | 'originalSource' => '/the/root/one.js', 46 | 'originalLine' => 1, 47 | 'originalColumn' => 11, 48 | 'originalName' => null 49 | )); 50 | $this->assertEquals($mappings[3], array( 51 | 'generatedLine' => 1, 52 | 'generatedColumn' => 18, 53 | 'originalSource' => '/the/root/one.js', 54 | 'originalLine' => 1, 55 | 'originalColumn' => 21, 56 | 'originalName' => 'bar' 57 | )); 58 | $this->assertEquals($mappings[4], array( 59 | 'generatedLine' => 1, 60 | 'generatedColumn' => 21, 61 | 'originalSource' => '/the/root/one.js', 62 | 'originalLine' => 2, 63 | 'originalColumn' => 3, 64 | 'originalName' => null 65 | )); 66 | $this->assertEquals($mappings[5], array( 67 | 'generatedLine' => 1, 68 | 'generatedColumn' => 28, 69 | 'originalSource' => '/the/root/one.js', 70 | 'originalLine' => 2, 71 | 'originalColumn' => 10, 72 | 'originalName' => 'baz' 73 | )); 74 | $this->assertEquals($mappings[6], array( 75 | 'generatedLine' => 1, 76 | 'generatedColumn' => 32, 77 | 'originalSource' => '/the/root/one.js', 78 | 'originalLine' => 2, 79 | 'originalColumn' => 14, 80 | 'originalName' => 'bar' 81 | )); 82 | 83 | 84 | $this->assertEquals($mappings[7], array( 85 | 'generatedLine' => 2, 86 | 'generatedColumn' => 1, 87 | 'originalSource' => '/the/root/two.js', 88 | 'originalLine' => 1, 89 | 'originalColumn' => 1, 90 | 'originalName' => null 91 | )); 92 | $this->assertEquals($mappings[8], array( 93 | 'generatedLine' => 2, 94 | 'generatedColumn' => 5, 95 | 'originalSource' => '/the/root/two.js', 96 | 'originalLine' => 1, 97 | 'originalColumn' => 5, 98 | 'originalName' => null 99 | )); 100 | $this->assertEquals($mappings[9], array( 101 | 'generatedLine' => 2, 102 | 'generatedColumn' => 9, 103 | 'originalSource' => '/the/root/two.js', 104 | 'originalLine' => 1, 105 | 'originalColumn' => 11, 106 | 'originalName' => null 107 | )); 108 | $this->assertEquals($mappings[10], array( 109 | 'generatedLine' => 2, 110 | 'generatedColumn' => 18, 111 | 'originalSource' => '/the/root/two.js', 112 | 'originalLine' => 1, 113 | 'originalColumn' => 21, 114 | 'originalName' => 'n' 115 | )); 116 | $this->assertEquals($mappings[11], array( 117 | 'generatedLine' => 2, 118 | 'generatedColumn' => 21, 119 | 'originalSource' => '/the/root/two.js', 120 | 'originalLine' => 2, 121 | 'originalColumn' => 3, 122 | 'originalName' => null 123 | )); 124 | $this->assertEquals($mappings[12], array( 125 | 'generatedLine' => 2, 126 | 'generatedColumn' => 28, 127 | 'originalSource' => '/the/root/two.js', 128 | 'originalLine' => 2, 129 | 'originalColumn' => 10, 130 | 'originalName' => 'n' 131 | )); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /tests/Kwf/SourceMaps/TestData.php: -------------------------------------------------------------------------------- 1 |