You are here

private function CSSmin::extract_data_urls in Advanced CSS/JS Aggregation 8.3

Same name and namespace in other branches
  1. 8.2 advagg_css_minify/yui/CSSMin.inc \CSSmin::extract_data_urls()
  2. 6 advagg_css_compress/yui/CSSMin.inc \CSSmin::extract_data_urls()

Utility method to replace all data urls with tokens before we start compressing, to avoid performance issues running some of the subsequent regexes against large strings chunks.

Parameters

string $css:

Return value

string

1 call to CSSmin::extract_data_urls()
CSSmin::run in advagg_css_minify/yui/CSSMin.inc
Minify a string of CSS

File

advagg_css_minify/yui/CSSMin.inc, line 440

Class

CSSmin

Code

private function extract_data_urls($css) {

  // Leave data urls alone to increase parse performance.
  $max_index = strlen($css) - 1;
  $append_index = $index = $last_index = $offset = 0;
  $sb = array();
  $pattern = '/url\\(\\s*(["\']?)data\\:/i';

  // Since we need to account for non-base64 data urls, we need to handle
  // ' and ) being part of the data string. Hence switching to indexOf,
  // to determine whether or not we have matching string terminators and
  // handling sb appends directly, instead of using matcher.append* methods.
  while (preg_match($pattern, $css, $m, 0, $offset)) {
    $index = $this
      ->index_of($css, $m[0], $offset);
    $last_index = $index + strlen($m[0]);
    $start_index = $index + 4;

    // "url(".length()
    $end_index = $last_index - 1;
    $terminator = $m[1];

    // ', " or empty (not quoted)
    $found_terminator = FALSE;
    if (strlen($terminator) === 0) {
      $terminator = ')';
    }
    while ($found_terminator === FALSE && $end_index + 1 <= $max_index) {
      $end_index = $this
        ->index_of($css, $terminator, $end_index + 1);

      // endIndex == 0 doesn't really apply here
      if ($end_index > 0 && substr($css, $end_index - 1, 1) !== '\\') {
        $found_terminator = TRUE;
        if (')' != $terminator) {
          $end_index = $this
            ->index_of($css, ')', $end_index);
        }
      }
    }

    // Enough searching, start moving stuff over to the buffer
    $sb[] = $this
      ->str_slice($css, $append_index, $index);
    if ($found_terminator) {
      $token = $this
        ->str_slice($css, $start_index, $end_index);
      $token = preg_replace('/\\s+/', '', $token);
      $this->preserved_tokens[] = $token;
      $preserver = 'url(' . self::TOKEN . (count($this->preserved_tokens) - 1) . '___)';
      $sb[] = $preserver;
      $append_index = $end_index + 1;
    }
    else {

      // No end terminator found, re-add the whole match. Should we throw/warn here?
      $sb[] = $this
        ->str_slice($css, $index, $last_index);
      $append_index = $last_index;
    }
    $offset = $last_index;
  }
  $sb[] = $this
    ->str_slice($css, $append_index);
  return implode('', $sb);
}