Lines.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. <?php
  2. /**
  3. * Class Minify_Lines
  4. * @package Minify
  5. */
  6. /**
  7. * Add line numbers in C-style comments for easier debugging of combined content
  8. *
  9. * @package Minify
  10. * @author Stephen Clay <steve@mrclay.org>
  11. * @author Adam Pedersen (Issue 55 fix)
  12. */
  13. class Minify_Lines {
  14. /**
  15. * Add line numbers in C-style comments
  16. *
  17. * This uses a very basic parser easily fooled by comment tokens inside
  18. * strings or regexes, but, otherwise, generally clean code will not be
  19. * mangled. URI rewriting can also be performed.
  20. *
  21. * @param string $content
  22. *
  23. * @param array $options available options:
  24. *
  25. * 'id': (optional) string to identify file. E.g. file name/path
  26. *
  27. * 'currentDir': (default null) if given, this is assumed to be the
  28. * directory of the current CSS file. Using this, minify will rewrite
  29. * all relative URIs in import/url declarations to correctly point to
  30. * the desired files, and prepend a comment with debugging information about
  31. * this process.
  32. *
  33. * @return string
  34. */
  35. public static function minify($content, $options = array())
  36. {
  37. $id = (isset($options['id']) && $options['id'])
  38. ? $options['id']
  39. : '';
  40. $content = str_replace("\r\n", "\n", $content);
  41. // Hackily rewrite strings with XPath expressions that are
  42. // likely to throw off our dumb parser (for Prototype 1.6.1).
  43. $content = str_replace('"/*"', '"/"+"*"', $content);
  44. $content = preg_replace('@([\'"])(\\.?//?)\\*@', '$1$2$1+$1*', $content);
  45. $lines = explode("\n", $content);
  46. $numLines = count($lines);
  47. // determine left padding
  48. $padTo = strlen((string) $numLines); // e.g. 103 lines = 3 digits
  49. $inComment = false;
  50. $i = 0;
  51. $newLines = array();
  52. while (null !== ($line = array_shift($lines))) {
  53. if (('' !== $id) && (0 == $i % 50)) {
  54. if ($inComment) {
  55. array_push($newLines, '', "/* {$id} *|", '');
  56. } else {
  57. array_push($newLines, '', "/* {$id} */", '');
  58. }
  59. }
  60. ++$i;
  61. $newLines[] = self::_addNote($line, $i, $inComment, $padTo);
  62. $inComment = self::_eolInComment($line, $inComment);
  63. }
  64. $content = implode("\n", $newLines) . "\n";
  65. // check for desired URI rewriting
  66. if (isset($options['currentDir'])) {
  67. Minify_CSS_UriRewriter::$debugText = '';
  68. $content = Minify_CSS_UriRewriter::rewrite(
  69. $content
  70. ,$options['currentDir']
  71. ,isset($options['docRoot']) ? $options['docRoot'] : $_SERVER['DOCUMENT_ROOT']
  72. ,isset($options['symlinks']) ? $options['symlinks'] : array()
  73. );
  74. $content = "/* Minify_CSS_UriRewriter::\$debugText\n\n"
  75. . Minify_CSS_UriRewriter::$debugText . "*/\n"
  76. . $content;
  77. }
  78. return $content;
  79. }
  80. /**
  81. * Is the parser within a C-style comment at the end of this line?
  82. *
  83. * @param string $line current line of code
  84. *
  85. * @param bool $inComment was the parser in a comment at the
  86. * beginning of the line?
  87. *
  88. * @return bool
  89. */
  90. private static function _eolInComment($line, $inComment)
  91. {
  92. // crude way to avoid things like // */
  93. $line = preg_replace('~//.*?(\\*/|/\\*).*~', '', $line);
  94. while (strlen($line)) {
  95. $search = $inComment
  96. ? '*/'
  97. : '/*';
  98. $pos = strpos($line, $search);
  99. if (false === $pos) {
  100. return $inComment;
  101. } else {
  102. if ($pos == 0
  103. || ($inComment
  104. ? substr($line, $pos, 3)
  105. : substr($line, $pos-1, 3)) != '*/*')
  106. {
  107. $inComment = ! $inComment;
  108. }
  109. $line = substr($line, $pos + 2);
  110. }
  111. }
  112. return $inComment;
  113. }
  114. /**
  115. * Prepend a comment (or note) to the given line
  116. *
  117. * @param string $line current line of code
  118. *
  119. * @param string $note content of note/comment
  120. *
  121. * @param bool $inComment was the parser in a comment at the
  122. * beginning of the line?
  123. *
  124. * @param int $padTo minimum width of comment
  125. *
  126. * @return string
  127. */
  128. private static function _addNote($line, $note, $inComment, $padTo)
  129. {
  130. return $inComment
  131. ? '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' *| ' . $line
  132. : '/* ' . str_pad($note, $padTo, ' ', STR_PAD_RIGHT) . ' */ ' . $line;
  133. }
  134. }