function parse_css_media($css, &$pipeline, $baseindex = 0)
{
    // Remove comments
    $css = preg_replace("#/\\*.*?\\*/#is", "", $css);
    // Extract @page rules
    $css = parse_css_atpage_rules($css, $pipeline);
    // Extract @import rules
    if ($num = preg_match_all("/@import[^;]+;/", $css, $matches, PREG_PATTERN_ORDER)) {
        for ($i = 0; $i < $num; $i++) {
            $this->parse_css_import($matches[0][$i], $pipeline);
        }
    }
    // Remove @import rules so they will not break further processing
    $css = preg_replace("/@import[^;]+;/", "", $css);
    while (preg_match("/([^{}]*){(.*?)}(.*)/is", $css, $matches)) {
        // Drop extracted part
        $css = $matches[3];
        // Save extracted part
        $raw_selectors = $matches[1];
        $raw_properties = $matches[2];
        $selectors = parse_css_selectors($raw_selectors);
        $properties = parse_css_properties($raw_properties, $pipeline);
        foreach ($selectors as $selector) {
            $this->_lastId++;
            $rule = array($selector, $properties, $pipeline->get_base_url(), $this->_lastId + $baseindex);
            $this->add_rule($rule, $pipeline);
        }
    }
}
function parse_css_selectors($css, $media_queries = true)
{
    $result = $media_blocks = [];
    //---------------parse css media queries------------------
    if ($media_queries == true) {
        $media_blocks = parse_css_media_queries($css);
    }
    $b = 0;
    if (!empty($media_blocks)) {
        //---------------get css blocks-----------------
        $css_blocks = $css;
        foreach ($media_blocks as $media_block) {
            $css_blocks = str_ireplace($media_block, '~£&#' . $media_block . '~£&#', $css_blocks);
        }
        $css_blocks = explode('~£&#', $css_blocks);
        //---------------parse css blocks-----------------
        foreach ($css_blocks as $css_block) {
            preg_match('/(\\@media[^\\{]+)\\{(.*)\\}\\s+/ims', $css_block, $block);
            if (isset($block[2]) && !empty($block[2])) {
                $result[$block[1]] = parse_css_selectors($block[2], false);
            } else {
                $result[$b] = parse_css_selectors($css_block, false);
            }
            ++$b;
        }
    } else {
        //---------------escape base64 images------------------
        $css = preg_replace('/(data\\:[^;]+);/i', '$1~£&#', $css);
        //---------------parse css selectors------------------
        preg_match_all('/([^\\{\\}]+)\\{([^\\}]*)\\}/ims', $css, $arr);
        foreach ($arr[0] as $i => $x) {
            $selector = trim($arr[1][$i]);
            $rules = explode(';', trim($arr[2][$i]));
            $rules_arr = [];
            foreach ($rules as $strRule) {
                if (!empty($strRule)) {
                    $rule = explode(":", $strRule, 2);
                    if (isset($rule[1])) {
                        $rules_arr[trim($rule[0])] = str_replace('~£&#', ';', trim($rule[1]));
                    } else {
                        //debug
                    }
                }
            }
            $selectors = explode(',', trim($selector));
            foreach ($selectors as $strSel) {
                if ($media_queries === true) {
                    $result[$b][$strSel] = $rules_arr;
                } else {
                    $result[$strSel] = $rules_arr;
                }
            }
        }
    }
    return $result;
}
function parse_dom_contents($doc_contents = '', $doc_type = 'html')
{
    $dom_contents = [];
    if ($doc_type == 'html') {
        //-----------------parse html contents---------------
        $dom_contents['html:head'] = '';
        $dom_contents['html:links'] = '';
        $dom_contents['html:scripts'] = '';
        $dom_contents['html:styles'] = '';
        $dom_contents['html:body'] = '';
        //-----------------parse doc_contents---------------
        $dom = new DOMDocument();
        $dom->loadHTML($doc_contents);
        //----------parse head---------
        $head = $dom->getElementsByTagName('head');
        if ($head && 0 < $head->length) {
            $dom_contents['html:head'] = strip_single_tag($dom->savehtml($head->item(0)), 'head');
        }
        //----------parse link---------
        $links = $dom->getElementsByTagName('link');
        if ($links && 0 < $links->length) {
            foreach ($links as $i => $link) {
                if ($link->hasAttributes() && ($url = $link->getAttribute('href'))) {
                    foreach ($link->attributes as $attr) {
                        $name = $attr->nodeName;
                        $value = $attr->nodeValue;
                        $dom_contents['html:links'][$url][$name] = $value;
                    }
                    $dom_contents['html:links'][$url]['string'] = custom_trim($dom->savehtml($links->item($i)));
                }
            }
        }
        //----------parse script---------
        $scripts = $dom->getElementsByTagName('script');
        if ($scripts && 0 < $scripts->length) {
            foreach ($scripts as $i => $script) {
                if ($script->hasAttributes() && ($url = $script->getAttribute('src'))) {
                    foreach ($script->attributes as $attr) {
                        $name = $attr->nodeName;
                        $value = $attr->nodeValue;
                        $dom_contents['html:scripts'][$url][$name] = $value;
                    }
                    $dom_contents['html:scripts'][$url]['string'] = custom_trim($dom->savehtml($scripts->item($i)));
                }
            }
        }
        //----------parse style---------
        $styles = $dom->getElementsByTagName('style');
        if ($styles && 0 < $styles->length) {
            foreach ($styles as $i => $style) {
                if ($style->hasAttributes()) {
                    foreach ($style->attributes as $attr) {
                        $name = $attr->nodeName;
                        $value = $attr->nodeValue;
                        $dom_contents['html:styles'][$i][$name] = $value;
                    }
                }
                $dom_contents['html:styles'][$i]['string'] = strip_single_tag(custom_trim($dom->savehtml($styles->item($i))), 'style');
            }
        }
        //----------parse body---------
        $body = $dom->getElementsByTagName('body');
        if ($body && 0 < $body->length) {
            $dom_contents['html:body'] = strip_single_tag($dom->savehtml($body->item(0)), 'body');
        }
    } elseif ($doc_type == 'css') {
        $dom_contents['css'] = parse_css_selectors($doc_contents);
    }
    return $dom_contents;
}
function parse_css_media($css, &$pipeline, $baseindex = 0)
{
    // Remove comments
    $css = preg_replace("#/\\*.*?\\*/#is", "", $css);
    // Extract @import rules
    if ($num = preg_match_all("/@import[^;]+;/", $css, $matches, PREG_PATTERN_ORDER)) {
        for ($i = 0; $i < $num; $i++) {
            parse_css_import($matches[0][$i], $pipeline);
        }
    }
    while (preg_match("/([^{}]*){(.*?)}(.*)/is", $css, $matches)) {
        // Drop extracted part
        $css = $matches[3];
        // Save extracted part
        $raw_selectors = $matches[1];
        $raw_properties = $matches[2];
        $selectors = parse_css_selectors($raw_selectors);
        $properties = parse_css_properties($raw_properties, $pipeline);
        foreach ($selectors as $selector) {
            // FIXME: this stuff definitely should be incapsulated
            global $g_css;
            global $g_css_index;
            $g_css_index++;
            array_push($g_css, array($selector, $properties, $pipeline->get_base_url(), $g_css_index + $baseindex));
        }
    }
}