Use Celerity to version all static resources
Summary:
We don't use versioned URIs for images, so when they change users may get old versions.
This was a particular issue with the recent logo change, which several users reported cache-related issues from.
Instead, use Celerity to manage image URI versions in addition to CSS/JS.
This is complicated, because we need to rewrite image URIs inside of CSS, which means the hash of a CSS file has to be derived from the current image data. Otherwise, when we updated an image the CSS wouldn't update, so we wouldn't be any better off.
So basically we:
- Find all the "raw" files, and put them into the map.
- Find all the CSS/JS, perform content-altering transformations on it (i.e., not minification) based on the partial map, and then put it into the map based on transformed hashes.
(If we wanted, we could now do CSS variables or whatever for "free", more or less.)
Test Plan:
- Regenerated celerity map, browsed site, verified images generated with versioned URIs.
- Moved "blue" flag image over "green" flag image, regenerated map, verified "green" flag image and the associated CSS changed hashes.
- Added transformation unit tests; ran unit tests.
Reviewers: btrahan, vrana, jungejason
Reviewed By: vrana
CC: aran
Maniphest Tasks: T1073
Differential Revision: https://secure.phabricator.com/D2146
2012-04-08 19:07:51 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @group celerity
|
|
|
|
*/
|
|
|
|
final class CelerityResourceTransformer {
|
|
|
|
|
|
|
|
private $minify;
|
2014-01-01 03:02:49 +01:00
|
|
|
private $rawURIMap;
|
Use Celerity to version all static resources
Summary:
We don't use versioned URIs for images, so when they change users may get old versions.
This was a particular issue with the recent logo change, which several users reported cache-related issues from.
Instead, use Celerity to manage image URI versions in addition to CSS/JS.
This is complicated, because we need to rewrite image URIs inside of CSS, which means the hash of a CSS file has to be derived from the current image data. Otherwise, when we updated an image the CSS wouldn't update, so we wouldn't be any better off.
So basically we:
- Find all the "raw" files, and put them into the map.
- Find all the CSS/JS, perform content-altering transformations on it (i.e., not minification) based on the partial map, and then put it into the map based on transformed hashes.
(If we wanted, we could now do CSS variables or whatever for "free", more or less.)
Test Plan:
- Regenerated celerity map, browsed site, verified images generated with versioned URIs.
- Moved "blue" flag image over "green" flag image, regenerated map, verified "green" flag image and the associated CSS changed hashes.
- Added transformation unit tests; ran unit tests.
Reviewers: btrahan, vrana, jungejason
Reviewed By: vrana
CC: aran
Maniphest Tasks: T1073
Differential Revision: https://secure.phabricator.com/D2146
2012-04-08 19:07:51 +02:00
|
|
|
private $celerityMap;
|
2012-10-17 17:37:05 +02:00
|
|
|
private $translateURICallback;
|
2013-06-20 00:42:17 +02:00
|
|
|
private $currentPath;
|
2012-10-17 17:37:05 +02:00
|
|
|
|
|
|
|
public function setTranslateURICallback($translate_uricallback) {
|
|
|
|
$this->translateURICallback = $translate_uricallback;
|
|
|
|
return $this;
|
|
|
|
}
|
Use Celerity to version all static resources
Summary:
We don't use versioned URIs for images, so when they change users may get old versions.
This was a particular issue with the recent logo change, which several users reported cache-related issues from.
Instead, use Celerity to manage image URI versions in addition to CSS/JS.
This is complicated, because we need to rewrite image URIs inside of CSS, which means the hash of a CSS file has to be derived from the current image data. Otherwise, when we updated an image the CSS wouldn't update, so we wouldn't be any better off.
So basically we:
- Find all the "raw" files, and put them into the map.
- Find all the CSS/JS, perform content-altering transformations on it (i.e., not minification) based on the partial map, and then put it into the map based on transformed hashes.
(If we wanted, we could now do CSS variables or whatever for "free", more or less.)
Test Plan:
- Regenerated celerity map, browsed site, verified images generated with versioned URIs.
- Moved "blue" flag image over "green" flag image, regenerated map, verified "green" flag image and the associated CSS changed hashes.
- Added transformation unit tests; ran unit tests.
Reviewers: btrahan, vrana, jungejason
Reviewed By: vrana
CC: aran
Maniphest Tasks: T1073
Differential Revision: https://secure.phabricator.com/D2146
2012-04-08 19:07:51 +02:00
|
|
|
|
|
|
|
public function setMinify($minify) {
|
|
|
|
$this->minify = $minify;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setCelerityMap(CelerityResourceMap $celerity_map) {
|
|
|
|
$this->celerityMap = $celerity_map;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2014-01-01 03:02:49 +01:00
|
|
|
public function setRawURIMap(array $raw_urimap) {
|
|
|
|
$this->rawURIMap = $raw_urimap;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getRawURIMap() {
|
|
|
|
return $this->rawURIMap;
|
|
|
|
}
|
|
|
|
|
2013-05-19 02:04:22 +02:00
|
|
|
/**
|
|
|
|
* @phutil-external-symbol function jsShrink
|
|
|
|
*/
|
Use Celerity to version all static resources
Summary:
We don't use versioned URIs for images, so when they change users may get old versions.
This was a particular issue with the recent logo change, which several users reported cache-related issues from.
Instead, use Celerity to manage image URI versions in addition to CSS/JS.
This is complicated, because we need to rewrite image URIs inside of CSS, which means the hash of a CSS file has to be derived from the current image data. Otherwise, when we updated an image the CSS wouldn't update, so we wouldn't be any better off.
So basically we:
- Find all the "raw" files, and put them into the map.
- Find all the CSS/JS, perform content-altering transformations on it (i.e., not minification) based on the partial map, and then put it into the map based on transformed hashes.
(If we wanted, we could now do CSS variables or whatever for "free", more or less.)
Test Plan:
- Regenerated celerity map, browsed site, verified images generated with versioned URIs.
- Moved "blue" flag image over "green" flag image, regenerated map, verified "green" flag image and the associated CSS changed hashes.
- Added transformation unit tests; ran unit tests.
Reviewers: btrahan, vrana, jungejason
Reviewed By: vrana
CC: aran
Maniphest Tasks: T1073
Differential Revision: https://secure.phabricator.com/D2146
2012-04-08 19:07:51 +02:00
|
|
|
public function transformResource($path, $data) {
|
|
|
|
$type = self::getResourceType($path);
|
|
|
|
|
|
|
|
switch ($type) {
|
|
|
|
case 'css':
|
2013-10-19 23:23:19 +02:00
|
|
|
$data = $this->replaceCSSPrintRules($path, $data);
|
2013-06-20 00:42:17 +02:00
|
|
|
$data = $this->replaceCSSVariables($path, $data);
|
Use Celerity to version all static resources
Summary:
We don't use versioned URIs for images, so when they change users may get old versions.
This was a particular issue with the recent logo change, which several users reported cache-related issues from.
Instead, use Celerity to manage image URI versions in addition to CSS/JS.
This is complicated, because we need to rewrite image URIs inside of CSS, which means the hash of a CSS file has to be derived from the current image data. Otherwise, when we updated an image the CSS wouldn't update, so we wouldn't be any better off.
So basically we:
- Find all the "raw" files, and put them into the map.
- Find all the CSS/JS, perform content-altering transformations on it (i.e., not minification) based on the partial map, and then put it into the map based on transformed hashes.
(If we wanted, we could now do CSS variables or whatever for "free", more or less.)
Test Plan:
- Regenerated celerity map, browsed site, verified images generated with versioned URIs.
- Moved "blue" flag image over "green" flag image, regenerated map, verified "green" flag image and the associated CSS changed hashes.
- Added transformation unit tests; ran unit tests.
Reviewers: btrahan, vrana, jungejason
Reviewed By: vrana
CC: aran
Maniphest Tasks: T1073
Differential Revision: https://secure.phabricator.com/D2146
2012-04-08 19:07:51 +02:00
|
|
|
$data = preg_replace_callback(
|
2012-10-17 17:37:05 +02:00
|
|
|
'@url\s*\((\s*[\'"]?.*?)\)@s',
|
|
|
|
nonempty(
|
|
|
|
$this->translateURICallback,
|
|
|
|
array($this, 'translateResourceURI')),
|
Use Celerity to version all static resources
Summary:
We don't use versioned URIs for images, so when they change users may get old versions.
This was a particular issue with the recent logo change, which several users reported cache-related issues from.
Instead, use Celerity to manage image URI versions in addition to CSS/JS.
This is complicated, because we need to rewrite image URIs inside of CSS, which means the hash of a CSS file has to be derived from the current image data. Otherwise, when we updated an image the CSS wouldn't update, so we wouldn't be any better off.
So basically we:
- Find all the "raw" files, and put them into the map.
- Find all the CSS/JS, perform content-altering transformations on it (i.e., not minification) based on the partial map, and then put it into the map based on transformed hashes.
(If we wanted, we could now do CSS variables or whatever for "free", more or less.)
Test Plan:
- Regenerated celerity map, browsed site, verified images generated with versioned URIs.
- Moved "blue" flag image over "green" flag image, regenerated map, verified "green" flag image and the associated CSS changed hashes.
- Added transformation unit tests; ran unit tests.
Reviewers: btrahan, vrana, jungejason
Reviewed By: vrana
CC: aran
Maniphest Tasks: T1073
Differential Revision: https://secure.phabricator.com/D2146
2012-04-08 19:07:51 +02:00
|
|
|
$data);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$this->minify) {
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Some resources won't survive minification (like Raphael.js), and are
|
|
|
|
// marked so as not to be minified.
|
|
|
|
if (strpos($data, '@'.'do-not-minify') !== false) {
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ($type) {
|
|
|
|
case 'css':
|
|
|
|
// Remove comments.
|
|
|
|
$data = preg_replace('@/\*.*?\*/@s', '', $data);
|
|
|
|
// Remove whitespace around symbols.
|
|
|
|
$data = preg_replace('@\s*([{}:;,])\s*@', '\1', $data);
|
|
|
|
// Remove unnecessary semicolons.
|
|
|
|
$data = preg_replace('@;}@', '}', $data);
|
|
|
|
// Replace #rrggbb with #rgb when possible.
|
|
|
|
$data = preg_replace(
|
|
|
|
'@#([a-f0-9])\1([a-f0-9])\2([a-f0-9])\3@i',
|
|
|
|
'#\1\2\3',
|
|
|
|
$data);
|
|
|
|
$data = trim($data);
|
|
|
|
break;
|
|
|
|
case 'js':
|
|
|
|
|
2013-05-19 02:04:22 +02:00
|
|
|
// If `jsxmin` is available, use it. jsxmin is the Javelin minifier and
|
|
|
|
// produces the smallest output, but is complicated to build.
|
|
|
|
if (Filesystem::binaryExists('jsxmin')) {
|
|
|
|
$future = new ExecFuture('jsxmin __DEV__:0');
|
Use Celerity to version all static resources
Summary:
We don't use versioned URIs for images, so when they change users may get old versions.
This was a particular issue with the recent logo change, which several users reported cache-related issues from.
Instead, use Celerity to manage image URI versions in addition to CSS/JS.
This is complicated, because we need to rewrite image URIs inside of CSS, which means the hash of a CSS file has to be derived from the current image data. Otherwise, when we updated an image the CSS wouldn't update, so we wouldn't be any better off.
So basically we:
- Find all the "raw" files, and put them into the map.
- Find all the CSS/JS, perform content-altering transformations on it (i.e., not minification) based on the partial map, and then put it into the map based on transformed hashes.
(If we wanted, we could now do CSS variables or whatever for "free", more or less.)
Test Plan:
- Regenerated celerity map, browsed site, verified images generated with versioned URIs.
- Moved "blue" flag image over "green" flag image, regenerated map, verified "green" flag image and the associated CSS changed hashes.
- Added transformation unit tests; ran unit tests.
Reviewers: btrahan, vrana, jungejason
Reviewed By: vrana
CC: aran
Maniphest Tasks: T1073
Differential Revision: https://secure.phabricator.com/D2146
2012-04-08 19:07:51 +02:00
|
|
|
$future->write($data);
|
|
|
|
list($err, $result) = $future->resolve();
|
|
|
|
if (!$err) {
|
|
|
|
$data = $result;
|
2013-05-19 02:04:22 +02:00
|
|
|
break;
|
Use Celerity to version all static resources
Summary:
We don't use versioned URIs for images, so when they change users may get old versions.
This was a particular issue with the recent logo change, which several users reported cache-related issues from.
Instead, use Celerity to manage image URI versions in addition to CSS/JS.
This is complicated, because we need to rewrite image URIs inside of CSS, which means the hash of a CSS file has to be derived from the current image data. Otherwise, when we updated an image the CSS wouldn't update, so we wouldn't be any better off.
So basically we:
- Find all the "raw" files, and put them into the map.
- Find all the CSS/JS, perform content-altering transformations on it (i.e., not minification) based on the partial map, and then put it into the map based on transformed hashes.
(If we wanted, we could now do CSS variables or whatever for "free", more or less.)
Test Plan:
- Regenerated celerity map, browsed site, verified images generated with versioned URIs.
- Moved "blue" flag image over "green" flag image, regenerated map, verified "green" flag image and the associated CSS changed hashes.
- Added transformation unit tests; ran unit tests.
Reviewers: btrahan, vrana, jungejason
Reviewed By: vrana
CC: aran
Maniphest Tasks: T1073
Differential Revision: https://secure.phabricator.com/D2146
2012-04-08 19:07:51 +02:00
|
|
|
}
|
|
|
|
}
|
2013-05-19 02:04:22 +02:00
|
|
|
|
|
|
|
// If `jsxmin` is not available, use `JsShrink`, which doesn't compress
|
|
|
|
// quite as well but is always available.
|
|
|
|
$root = dirname(phutil_get_library_root('phabricator'));
|
|
|
|
require_once $root.'/externals/JsShrink/jsShrink.php';
|
|
|
|
$data = jsShrink($data);
|
|
|
|
|
Use Celerity to version all static resources
Summary:
We don't use versioned URIs for images, so when they change users may get old versions.
This was a particular issue with the recent logo change, which several users reported cache-related issues from.
Instead, use Celerity to manage image URI versions in addition to CSS/JS.
This is complicated, because we need to rewrite image URIs inside of CSS, which means the hash of a CSS file has to be derived from the current image data. Otherwise, when we updated an image the CSS wouldn't update, so we wouldn't be any better off.
So basically we:
- Find all the "raw" files, and put them into the map.
- Find all the CSS/JS, perform content-altering transformations on it (i.e., not minification) based on the partial map, and then put it into the map based on transformed hashes.
(If we wanted, we could now do CSS variables or whatever for "free", more or less.)
Test Plan:
- Regenerated celerity map, browsed site, verified images generated with versioned URIs.
- Moved "blue" flag image over "green" flag image, regenerated map, verified "green" flag image and the associated CSS changed hashes.
- Added transformation unit tests; ran unit tests.
Reviewers: btrahan, vrana, jungejason
Reviewed By: vrana
CC: aran
Maniphest Tasks: T1073
Differential Revision: https://secure.phabricator.com/D2146
2012-04-08 19:07:51 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function getResourceType($path) {
|
|
|
|
return last(explode('.', $path));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function translateResourceURI(array $matches) {
|
|
|
|
$uri = trim($matches[1], "'\" \r\t\n");
|
|
|
|
|
2014-01-01 16:46:25 +01:00
|
|
|
$alternatives = array_unique(
|
|
|
|
array(
|
|
|
|
$uri,
|
|
|
|
ltrim($uri, '/'),
|
|
|
|
));
|
|
|
|
|
|
|
|
foreach ($alternatives as $alternative) {
|
|
|
|
if ($this->rawURIMap !== null) {
|
|
|
|
if (isset($this->rawURIMap[$alternative])) {
|
|
|
|
$uri = $this->rawURIMap[$alternative];
|
|
|
|
break;
|
|
|
|
}
|
2014-01-01 03:02:49 +01:00
|
|
|
}
|
2014-01-01 16:46:25 +01:00
|
|
|
|
|
|
|
if ($this->celerityMap) {
|
|
|
|
$resource_uri = $this->celerityMap->getURIForName($alternative);
|
|
|
|
if ($resource_uri) {
|
|
|
|
$uri = $resource_uri;
|
|
|
|
break;
|
|
|
|
}
|
Use Celerity to version all static resources
Summary:
We don't use versioned URIs for images, so when they change users may get old versions.
This was a particular issue with the recent logo change, which several users reported cache-related issues from.
Instead, use Celerity to manage image URI versions in addition to CSS/JS.
This is complicated, because we need to rewrite image URIs inside of CSS, which means the hash of a CSS file has to be derived from the current image data. Otherwise, when we updated an image the CSS wouldn't update, so we wouldn't be any better off.
So basically we:
- Find all the "raw" files, and put them into the map.
- Find all the CSS/JS, perform content-altering transformations on it (i.e., not minification) based on the partial map, and then put it into the map based on transformed hashes.
(If we wanted, we could now do CSS variables or whatever for "free", more or less.)
Test Plan:
- Regenerated celerity map, browsed site, verified images generated with versioned URIs.
- Moved "blue" flag image over "green" flag image, regenerated map, verified "green" flag image and the associated CSS changed hashes.
- Added transformation unit tests; ran unit tests.
Reviewers: btrahan, vrana, jungejason
Reviewed By: vrana
CC: aran
Maniphest Tasks: T1073
Differential Revision: https://secure.phabricator.com/D2146
2012-04-08 19:07:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 'url('.$uri.')';
|
|
|
|
}
|
|
|
|
|
2013-06-20 00:42:17 +02:00
|
|
|
private function replaceCSSVariables($path, $data) {
|
|
|
|
$this->currentPath = $path;
|
|
|
|
return preg_replace_callback(
|
|
|
|
'/{\$([^}]+)}/',
|
|
|
|
array($this, 'replaceCSSVariable'),
|
|
|
|
$data);
|
|
|
|
}
|
|
|
|
|
2013-10-19 23:23:19 +02:00
|
|
|
private function replaceCSSPrintRules($path, $data) {
|
|
|
|
$this->currentPath = $path;
|
|
|
|
return preg_replace_callback(
|
|
|
|
'/!print\s+(.+?{.+?})/s',
|
|
|
|
array($this, 'replaceCSSPrintRule'),
|
|
|
|
$data);
|
|
|
|
}
|
|
|
|
|
2013-10-17 18:32:34 +02:00
|
|
|
public static function getCSSVariableMap() {
|
|
|
|
return array(
|
2013-08-30 23:40:46 +02:00
|
|
|
// Base Colors
|
2013-06-20 05:25:41 +02:00
|
|
|
'red' => '#c0392b',
|
|
|
|
'lightred' => '#f4dddb',
|
|
|
|
'orange' => '#e67e22',
|
|
|
|
'lightorange' => '#f7e2d4',
|
|
|
|
'yellow' => '#f1c40f',
|
|
|
|
'lightyellow' => '#fdf5d4',
|
|
|
|
'green' => '#139543',
|
|
|
|
'lightgreen' => '#d7eddf',
|
|
|
|
'blue' => '#2980b9',
|
|
|
|
'lightblue' => '#daeaf3',
|
|
|
|
'sky' => '#3498db',
|
|
|
|
'lightsky' => '#ddeef9',
|
|
|
|
'indigo' => '#c6539d',
|
|
|
|
'lightindigo' => '#f5e2ef',
|
|
|
|
'violet' => '#8e44ad',
|
|
|
|
'lightviolet' => '#ecdff1',
|
2013-10-17 18:32:34 +02:00
|
|
|
'charcoal' => '#4b4d51',
|
|
|
|
'backdrop' => '#c4cde0',
|
2013-08-30 23:40:46 +02:00
|
|
|
|
|
|
|
// Base Greys
|
2013-09-03 16:00:06 +02:00
|
|
|
'lightgreyborder' => '#C7CCD9',
|
|
|
|
'greyborder' => '#A1A6B0',
|
2013-08-30 23:40:46 +02:00
|
|
|
'darkgreyborder' => '#676A70',
|
|
|
|
'lightgreytext' => '#92969D',
|
2013-09-02 17:10:47 +02:00
|
|
|
'greytext' => '#74777D',
|
2013-08-30 23:40:46 +02:00
|
|
|
'darkgreytext' => '#4B4D51',
|
|
|
|
'lightgreybackground' => '#F7F7F7',
|
|
|
|
'greybackground' => '#EBECEE',
|
2014-02-09 19:21:47 +01:00
|
|
|
'darkgreybackground' => '#DFE0E2',
|
2013-09-02 17:10:47 +02:00
|
|
|
|
|
|
|
// Base Blues
|
2013-09-05 21:29:07 +02:00
|
|
|
'thinblueborder' => '#DDE8EF',
|
2013-09-02 17:10:47 +02:00
|
|
|
'lightblueborder' => '#BFCFDA',
|
|
|
|
'blueborder' => '#8C98B8',
|
|
|
|
'darkblueborder' => '#626E82',
|
|
|
|
'lightbluebackground' => '#F8F9FC',
|
|
|
|
'bluebackground' => '#DAE7FF',
|
2013-09-03 16:00:06 +02:00
|
|
|
'lightbluetext' => '#8C98B8',
|
|
|
|
'bluetext' => '#6B748C',
|
|
|
|
'darkbluetext' => '#464C5C',
|
2013-06-20 00:42:17 +02:00
|
|
|
);
|
2013-10-17 18:32:34 +02:00
|
|
|
}
|
|
|
|
|
2013-10-19 23:23:19 +02:00
|
|
|
|
2013-10-17 18:32:34 +02:00
|
|
|
public function replaceCSSVariable($matches) {
|
|
|
|
static $map;
|
|
|
|
if (!$map) {
|
|
|
|
$map = self::getCSSVariableMap();
|
|
|
|
}
|
2013-06-20 00:42:17 +02:00
|
|
|
|
|
|
|
$var_name = $matches[1];
|
|
|
|
if (empty($map[$var_name])) {
|
|
|
|
$path = $this->currentPath;
|
|
|
|
throw new Exception(
|
|
|
|
"CSS file '{$path}' has unknown variable '{$var_name}'.");
|
|
|
|
}
|
|
|
|
|
|
|
|
return $map[$var_name];
|
|
|
|
}
|
|
|
|
|
2013-10-19 23:23:19 +02:00
|
|
|
public function replaceCSSPrintRule($matches) {
|
|
|
|
$rule = $matches[1];
|
|
|
|
|
|
|
|
$rules = array();
|
|
|
|
$rules[] = '.printable '.$rule;
|
|
|
|
$rules[] = "@media print {\n ".str_replace("\n", "\n ", $rule)."\n}\n";
|
|
|
|
|
|
|
|
return implode("\n\n", $rules);
|
|
|
|
}
|
Use Celerity to version all static resources
Summary:
We don't use versioned URIs for images, so when they change users may get old versions.
This was a particular issue with the recent logo change, which several users reported cache-related issues from.
Instead, use Celerity to manage image URI versions in addition to CSS/JS.
This is complicated, because we need to rewrite image URIs inside of CSS, which means the hash of a CSS file has to be derived from the current image data. Otherwise, when we updated an image the CSS wouldn't update, so we wouldn't be any better off.
So basically we:
- Find all the "raw" files, and put them into the map.
- Find all the CSS/JS, perform content-altering transformations on it (i.e., not minification) based on the partial map, and then put it into the map based on transformed hashes.
(If we wanted, we could now do CSS variables or whatever for "free", more or less.)
Test Plan:
- Regenerated celerity map, browsed site, verified images generated with versioned URIs.
- Moved "blue" flag image over "green" flag image, regenerated map, verified "green" flag image and the associated CSS changed hashes.
- Added transformation unit tests; ran unit tests.
Reviewers: btrahan, vrana, jungejason
Reviewed By: vrana
CC: aran
Maniphest Tasks: T1073
Differential Revision: https://secure.phabricator.com/D2146
2012-04-08 19:07:51 +02:00
|
|
|
}
|