Как пересчитать пути URL-адреса css при перемещении его в другую папку

#php #css #relative-path

#php #css #относительный путь

Вопрос:

Каков наилучший способ перевести css, чтобы он работал по другому пути. Я просмотрел несколько разных библиотек (CrushCSS, minify), и, похоже, они работают только над этой службой вместе со сжатием файлов (чего я не хочу делать).

Мое лучшее регулярное выражение? Если да, то каковы все возможные случаи, которые мне нужно будет обработать?

Например, введите: /base/my.css

 @import url "../another/file.css"
#container {
    background: url('example/relative/path.png');
}
#container2 {
    background: url('/example/absolute/path.png');
}
 

Ожидаемый результат: /base/example/path/my.css

 @import url "../../../another/file.css"
#container {
    background: url('../relative/path.png');
}
#container2 {
    background: url('/example/absolute/path.png');
}
 

Редактировать:

Меня не интересует «лучшая практика» или способы избежать проблем такого типа. Меня интересует только то, как выполнить преобразование, чтобы css оставался правильным в новом пути.

Ответ №1:

Я бы сказал, что лучшим способом было бы всегда использовать URL-адреса относительно корня вашего сайта. /example/absolute/path.png всегда будет работать, независимо от того, где вы разместите файл CSS.

Комментарии:

1. Это не вариант, поскольку файлы css уже существуют. Я ищу способ их программного перемещения, сохраняя при этом их действительность.

2. Также в моем случае я не могу использовать абсолютные пути, поскольку база сайта не гарантируется / .

3. Они всегда будут /something . В вашем собственном домене или поддомене они будут относиться к /, а если вы находитесь в подкаталоге, то они будут /подкаталог.

4. В моем случае сайт доступен для просмотра из двух разных каталогов одновременно (не мое дело). Так что, если я буду использовать url('/path') для одного, это приведет к разрыву другой ссылки. Я должен использовать относительный css, чтобы он работал.

5. В этом случае, я думаю, у вас есть только два реалистичных варианта. 1) Создайте символические ссылки в местоположении b, которые указывают на файлы в местоположении a, чтобы оба пути к рассматриваемому ресурсу были действительными, или б) замените файл CSS скриптом PHP, который выводит файл CSS с путями, пересчитанными по мере необходимости. Я бы рекомендовал первое, так как последнее вызовет проблемы с кэшированием таблицы стилей.

Ответ №2:

Я решил, что я бы реорганизовал некоторый код из Minify, чтобы обеспечить необходимое мне абстрактное преобразование css.

 <?php

//This class is heavy borrowed from Minify_ImportProcessor

class CSSImporter
{

    static function changePaths( $content, $current_path, $target_path )
    {
        $current_path = rtrim( $current_path, "/" );
        $target_path = rtrim( $target_path, "/" );
        $current_path_slugs = explode( "/", $current_path );
        $target_path_slugs = explode( "/", $target_path );
        $smallest_count = min( count( $current_path_slugs ), count( $target_path_slugs ) );
        for( $i = 0; $i < $smallest_count amp;amp; $current_path_slugs[$i] === $target_path_slugs[$i]; $i   );
        $change_prefix = implode( "/", array_merge( array_fill( 0, count( $target_path_slugs ) - $i, ".." ), array_slice( $current_path_slugs, $i ) ) );
        if( strlen( $change_prefix ) > 0 ) $change_prefix .= "/";

        $content = preg_replace_callback(
            '/
            @import\s 
            (?:url\(\s*)?     # maybe url(
            ['"]?              # maybe quote
            (.*?)               # 1 = URI
            ['"]?              # maybe end quote
            (?:\s*\))?        # maybe )
            ([a-zA-Z,\s]*)?    # 2 = media list
            ;                   # end token
            /x',
            function( $m ) use ( $change_prefix ) {
                $url = $change_prefix.$m[1];
                $url = str_replace('/./', '/', $url);
                do {
                    $url = preg_replace('@/(?!\.\.?)[^/] /\.\.@', '/', $url, 1, $changed);
                } while( $changed );
                return "@import url('$url'){$m[2]};";
            },
            $content
        );
        $content = preg_replace_callback(
            '/url\(\s*([^\)\s] )\s*\)/',
            function( $m ) use ( $change_prefix ) {
                // $m[1] is either quoted or not
                $quote = ($m[1][0] === "'" || $m[1][0] === '"')
                    ? $m[1][0]
                    : '';
                $url = ($quote === '')
                    ? $m[1]
                    : substr($m[1], 1, strlen($m[1]) - 2);

                if( '/' !== $url[0] amp;amp; strpos( $url, '//') === FALSE ) {
                    $url = $change_prefix.$url;
                    $url = str_replace('/./', '/', $url);
                    do {
                        $url = preg_replace('@/(?!\.\.?)[^/] /\.\.@', '/', $url, 1, $changed);
                    } while( $changed );
                }
                return "url({$quote}{$url}{$quote})";
            },
            $content
        );
        return $content;
    }

}

?>