/
CssUrlsFilter.php
122 lines (101 loc) · 2.97 KB
/
CssUrlsFilter.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<?php
namespace WebLoader\Filter;
/**
* Absolutize urls in CSS
*
* @author Jan Marek
* @license MIT
*/
class CssUrlsFilter
{
private $docRoot;
private $basePath;
/**
* @param string $docRoot web document root
* @param string $basePath base path
*/
public function __construct($docRoot, $basePath = '/')
{
$this->docRoot = \WebLoader\Path::normalize($docRoot);
if (!is_dir($this->docRoot)) {
throw new \WebLoader\InvalidArgumentException('Given document root is not directory.');
}
$this->basePath = $basePath;
}
/**
* Make relative url absolute
* @param string $url image url
* @param string $quote single or double quote
* @param string $cssFile absolute css file path
* @return string
*/
public function absolutizeUrl($url, $quote, $cssFile)
{
// is already absolute
if (preg_match('/^([a-z]+:\/)?\//', $url)) {
return $url;
}
$cssFile = \WebLoader\Path::normalize($cssFile);
// inside document root
if (strncmp($cssFile, $this->docRoot, strlen($this->docRoot)) === 0) {
$path = $this->basePath . substr(dirname($cssFile), strlen($this->docRoot)) . DIRECTORY_SEPARATOR . $url;
} else {
// outside document root we don't know
return $url;
}
$path = $this->cannonicalizePath($path);
return $quote === '"' ? addslashes($path) : $path;
}
/**
* Cannonicalize path
* @param string $path
* @return string path
*/
public function cannonicalizePath($path)
{
$path = strtr($path, DIRECTORY_SEPARATOR, '/');
$pathArr = array();
foreach (explode('/', $path) as $i => $name) {
if ($name === '.' || ($name === '' && $i > 0)) continue;
if ($name === '..') {
array_pop($pathArr);
continue;
}
$pathArr[] = $name;
}
return implode('/', $pathArr);
}
/**
* Invoke filter
* @param string $code
* @param \WebLoader\Compiler $loader
* @param string $file
* @return string
*/
public function __invoke($code, \WebLoader\Compiler $loader, $file = null)
{
// thanks to kravco
$regexp = '~
(?<![a-z])
url\( ## url(
\s* ## optional whitespace
([\'"])? ## optional single/double quote
(?!data:) ## keep data URIs
( (?: (?:\\\\.)+ ## escape sequences
| [^\'"\\\\,()\s]+ ## safe characters
| (?(1) (?!\1)[\'"\\\\,() \t] ## allowed special characters
| ^ ## (none, if not quoted)
)
)* ## (greedy match)
)
(?(1)\1) ## optional single/double quote
\s* ## optional whitespace
\) ## )
~xs';
$self = $this;
return preg_replace_callback($regexp, function ($matches) use ($self, $file)
{
return "url('" . $self->absolutizeUrl($matches[2], $matches[1], $file) . "')";
}, $code);
}
}