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
This commit is contained in:
@@ -144,7 +144,43 @@ phutil_require_module('phutil', 'parser/docblock');
|
|||||||
|
|
||||||
$root = Filesystem::resolvePath($argv[1]);
|
$root = Filesystem::resolvePath($argv[1]);
|
||||||
|
|
||||||
echo "Finding static resources...\n";
|
$resource_hash = PhabricatorEnv::getEnvConfig('celerity.resource-hash');
|
||||||
|
$runtime_map = array();
|
||||||
|
|
||||||
|
echo "Finding raw static resources...\n";
|
||||||
|
$raw_files = id(new FileFinder($root))
|
||||||
|
->withType('f')
|
||||||
|
->withSuffix('png')
|
||||||
|
->withSuffix('jpg')
|
||||||
|
->withSuffix('gif')
|
||||||
|
->withSuffix('swf')
|
||||||
|
->withFollowSymlinks(true)
|
||||||
|
->setGenerateChecksums(true)
|
||||||
|
->find();
|
||||||
|
|
||||||
|
echo "Processing ".count($raw_files)." files";
|
||||||
|
foreach ($raw_files as $path => $hash) {
|
||||||
|
echo ".";
|
||||||
|
$path = '/'.Filesystem::readablePath($path, $root);
|
||||||
|
$type = CelerityResourceTransformer::getResourceType($path);
|
||||||
|
|
||||||
|
$hash = md5($hash.$path.$resource_hash);
|
||||||
|
$uri = '/res/'.substr($hash, 0, 8).$path;
|
||||||
|
|
||||||
|
$runtime_map[$path] = array(
|
||||||
|
'hash' => $hash,
|
||||||
|
'uri' => $uri,
|
||||||
|
'disk' => $path,
|
||||||
|
'type' => $type,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
$xformer = id(new CelerityResourceTransformer())
|
||||||
|
->setMinify(false)
|
||||||
|
->setRawResourceMap($runtime_map);
|
||||||
|
|
||||||
|
echo "Finding transformable static resources...\n";
|
||||||
$files = id(new FileFinder($root))
|
$files = id(new FileFinder($root))
|
||||||
->withType('f')
|
->withType('f')
|
||||||
->withSuffix('js')
|
->withSuffix('js')
|
||||||
@@ -155,26 +191,31 @@ $files = id(new FileFinder($root))
|
|||||||
|
|
||||||
echo "Processing ".count($files)." files";
|
echo "Processing ".count($files)." files";
|
||||||
|
|
||||||
$resource_hash = PhabricatorEnv::getEnvConfig('celerity.resource-hash');
|
|
||||||
|
|
||||||
$file_map = array();
|
$file_map = array();
|
||||||
foreach ($files as $path => $hash) {
|
foreach ($files as $path => $raw_hash) {
|
||||||
echo ".";
|
echo ".";
|
||||||
$name = '/'.Filesystem::readablePath($path, $root);
|
$path = '/'.Filesystem::readablePath($path, $root);
|
||||||
$file_map[$name] = array(
|
$data = Filesystem::readFile($root.$path);
|
||||||
'hash' => md5($hash.$name.$resource_hash),
|
|
||||||
|
$data = $xformer->transformResource($path, $data);
|
||||||
|
$hash = md5($data);
|
||||||
|
$hash = md5($hash.$path.$resource_hash);
|
||||||
|
|
||||||
|
$file_map[$path] = array(
|
||||||
|
'hash' => $hash,
|
||||||
'disk' => $path,
|
'disk' => $path,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
echo "\n";
|
echo "\n";
|
||||||
|
|
||||||
$runtime_map = array();
|
|
||||||
$resource_graph = array();
|
$resource_graph = array();
|
||||||
$hash_map = array();
|
$hash_map = array();
|
||||||
|
|
||||||
$parser = new PhutilDocblockParser();
|
$parser = new PhutilDocblockParser();
|
||||||
foreach ($file_map as $path => $info) {
|
foreach ($file_map as $path => $info) {
|
||||||
$data = Filesystem::readFile($info['disk']);
|
$type = CelerityResourceTransformer::getResourceType($path);
|
||||||
|
|
||||||
|
$data = Filesystem::readFile($root.$info['disk']);
|
||||||
$matches = array();
|
$matches = array();
|
||||||
$ok = preg_match('@/[*][*].*?[*]/@s', $data, $matches);
|
$ok = preg_match('@/[*][*].*?[*]/@s', $data, $matches);
|
||||||
if (!$ok) {
|
if (!$ok) {
|
||||||
@@ -202,11 +243,6 @@ foreach ($file_map as $path => $info) {
|
|||||||
|
|
||||||
$provides = reset($provides);
|
$provides = reset($provides);
|
||||||
|
|
||||||
$type = 'js';
|
|
||||||
if (preg_match('/\.css$/', $path)) {
|
|
||||||
$type = 'css';
|
|
||||||
}
|
|
||||||
|
|
||||||
$uri = '/res/'.substr($info['hash'], 0, 8).$path;
|
$uri = '/res/'.substr($info['hash'], 0, 8).$path;
|
||||||
|
|
||||||
$hash_map[$provides] = $info['hash'];
|
$hash_map[$provides] = $info['hash'];
|
||||||
|
|||||||
@@ -7,6 +7,349 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
celerity_register_resource_map(array(
|
celerity_register_resource_map(array(
|
||||||
|
'/rsrc/image/apps.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'f7cb4abeb73245fea4098a02fd784653',
|
||||||
|
'uri' => '/res/f7cb4abe/rsrc/image/apps.png',
|
||||||
|
'disk' => '/rsrc/image/apps.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/credit_cards.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '681448de424ea159b6ea68af04c046ae',
|
||||||
|
'uri' => '/res/681448de/rsrc/image/credit_cards.png',
|
||||||
|
'disk' => '/rsrc/image/credit_cards.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/custom/example_facebook.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '062911a848dd7b58159d4184488ecac4',
|
||||||
|
'uri' => '/res/062911a8/rsrc/image/custom/example_facebook.png',
|
||||||
|
'disk' => '/rsrc/image/custom/example_facebook.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/custom/example_rainbow.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '7af08c16d969a2d63b4acdbd5cee2e8f',
|
||||||
|
'uri' => '/res/7af08c16/rsrc/image/custom/example_rainbow.png',
|
||||||
|
'disk' => '/rsrc/image/custom/example_rainbow.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/custom/example_template.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '9971fe1adb16682a18f9b588c4fc051b',
|
||||||
|
'uri' => '/res/9971fe1a/rsrc/image/custom/example_template.png',
|
||||||
|
'disk' => '/rsrc/image/custom/example_template.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/grippy_texture.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'a8945e12ceeaddd5b491a8d81cfa19c1',
|
||||||
|
'uri' => '/res/a8945e12/rsrc/image/grippy_texture.png',
|
||||||
|
'disk' => '/rsrc/image/grippy_texture.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/arrow_branch.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'f27b67520766e3d971722bcff703f3a8',
|
||||||
|
'uri' => '/res/f27b6752/rsrc/image/icon/fatcow/arrow_branch.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/arrow_branch.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/arrow_merge.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'c4bd97f3b1257439e2123ef69d2194d0',
|
||||||
|
'uri' => '/res/c4bd97f3/rsrc/image/icon/fatcow/arrow_merge.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/arrow_merge.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/calendar_edit.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'de249c0f4f37bf5b2c69ff39ec5573fb',
|
||||||
|
'uri' => '/res/de249c0f/rsrc/image/icon/fatcow/calendar_edit.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/calendar_edit.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/flag_blue.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '75a080492f900fbe489e4b27e403962b',
|
||||||
|
'uri' => '/res/75a08049/rsrc/image/icon/fatcow/flag_blue.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/flag_blue.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/flag_finish.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '4af11fc7fab8e4610cbc3c88a02d4f78',
|
||||||
|
'uri' => '/res/4af11fc7/rsrc/image/icon/fatcow/flag_finish.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/flag_finish.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/flag_ghost.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '14c9f30a37b43f276f27a27a924bf02d',
|
||||||
|
'uri' => '/res/14c9f30a/rsrc/image/icon/fatcow/flag_ghost.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/flag_ghost.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/flag_green.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'fed01374cd396cb774872762dcc447e1',
|
||||||
|
'uri' => '/res/fed01374/rsrc/image/icon/fatcow/flag_green.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/flag_green.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/flag_orange.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '88008cb8bb99761a37e5a743e2455aeb',
|
||||||
|
'uri' => '/res/88008cb8/rsrc/image/icon/fatcow/flag_orange.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/flag_orange.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/flag_pink.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '2f199f06ffc3dfc81b7561a057e0bc33',
|
||||||
|
'uri' => '/res/2f199f06/rsrc/image/icon/fatcow/flag_pink.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/flag_pink.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/flag_purple.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '16358629dc86c39550b575586eb5df80',
|
||||||
|
'uri' => '/res/16358629/rsrc/image/icon/fatcow/flag_purple.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/flag_purple.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/flag_red.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '210c28b4d93c439a499f5814f5e05772',
|
||||||
|
'uri' => '/res/210c28b4/rsrc/image/icon/fatcow/flag_red.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/flag_red.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/flag_yellow.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'bdfd73744a80bb80329ae50bc8a5f962',
|
||||||
|
'uri' => '/res/bdfd7374/rsrc/image/icon/fatcow/flag_yellow.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/flag_yellow.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/folder.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '25e46cf9d210dde2242332296f79938c',
|
||||||
|
'uri' => '/res/25e46cf9/rsrc/image/icon/fatcow/folder.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/folder.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/folder_go.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'ba922ff7959309f51a14cb7ed5124d8b',
|
||||||
|
'uri' => '/res/ba922ff7/rsrc/image/icon/fatcow/folder_go.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/folder_go.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/key_question.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '530a6448a4b91edec091a9292ccfd3d9',
|
||||||
|
'uri' => '/res/530a6448/rsrc/image/icon/fatcow/key_question.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/key_question.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/link.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'be1bea49b216548433014f3324902928',
|
||||||
|
'uri' => '/res/be1bea49/rsrc/image/icon/fatcow/link.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/link.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/page_white_link.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '1cfbad14412bda6c6f132dcc7c8725fd',
|
||||||
|
'uri' => '/res/1cfbad14/rsrc/image/icon/fatcow/page_white_link.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/page_white_link.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/page_white_put.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'bb7308aa5ac40137a8262da395a267fd',
|
||||||
|
'uri' => '/res/bb7308aa/rsrc/image/icon/fatcow/page_white_put.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/page_white_put.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/page_white_text.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'e47d590b626f617fb7d1d44e96e8fd11',
|
||||||
|
'uri' => '/res/e47d590b/rsrc/image/icon/fatcow/page_white_text.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/page_white_text.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/source/conduit.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '1cae0656580aa3cd0b54b9d98306b1b9',
|
||||||
|
'uri' => '/res/1cae0656/rsrc/image/icon/fatcow/source/conduit.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/source/conduit.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/source/email.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '93bdb3e168da1ed68f50c42125729d4e',
|
||||||
|
'uri' => '/res/93bdb3e1/rsrc/image/icon/fatcow/source/email.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/source/email.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/source/fax.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'd7dedf229841f2d041b347afd881596f',
|
||||||
|
'uri' => '/res/d7dedf22/rsrc/image/icon/fatcow/source/fax.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/source/fax.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/source/mobile.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '786e7146d1e7d7318baf76c9d2baad97',
|
||||||
|
'uri' => '/res/786e7146/rsrc/image/icon/fatcow/source/mobile.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/source/mobile.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/source/tablet.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '374cd40e4965be6b2fbdef4059d0ca05',
|
||||||
|
'uri' => '/res/374cd40e/rsrc/image/icon/fatcow/source/tablet.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/source/tablet.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/source/web.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'f4882a8f5619ba505ca033f72a340635',
|
||||||
|
'uri' => '/res/f4882a8f/rsrc/image/icon/fatcow/source/web.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/source/web.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/thumbnails/default160x120.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '1b52ebd1fe0eee3ed0abfc382991b265',
|
||||||
|
'uri' => '/res/1b52ebd1/rsrc/image/icon/fatcow/thumbnails/default160x120.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/thumbnails/default160x120.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/thumbnails/default60x45.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '048d851d8d1daad4754e891e734c1899',
|
||||||
|
'uri' => '/res/048d851d/rsrc/image/icon/fatcow/thumbnails/default60x45.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/thumbnails/default60x45.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/thumbnails/image160x120.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '434acbd8dbbc2da9f09f6205a396eba1',
|
||||||
|
'uri' => '/res/434acbd8/rsrc/image/icon/fatcow/thumbnails/image160x120.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/thumbnails/image160x120.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/thumbnails/image60x45.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '29f7872dc53588fe0b8f0b330c7ee23a',
|
||||||
|
'uri' => '/res/29f7872d/rsrc/image/icon/fatcow/thumbnails/image60x45.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/thumbnails/image60x45.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/thumbnails/pdf160x120.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '39d2e22541658a3472ba41ae2fa548e5',
|
||||||
|
'uri' => '/res/39d2e225/rsrc/image/icon/fatcow/thumbnails/pdf160x120.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/thumbnails/pdf160x120.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/thumbnails/pdf60x45.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'b3572e9317cbed5184d12bdfabed2727',
|
||||||
|
'uri' => '/res/b3572e93/rsrc/image/icon/fatcow/thumbnails/pdf60x45.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/thumbnails/pdf60x45.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/thumbnails/zip160x120.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'e505108688a903b5cfb674707a289bcc',
|
||||||
|
'uri' => '/res/e5051086/rsrc/image/icon/fatcow/thumbnails/zip160x120.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/thumbnails/zip160x120.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/fatcow/thumbnails/zip60x45.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'f00716f4e8f7a95e70d43504f06be0a6',
|
||||||
|
'uri' => '/res/f00716f4/rsrc/image/icon/fatcow/thumbnails/zip60x45.png',
|
||||||
|
'disk' => '/rsrc/image/icon/fatcow/thumbnails/zip60x45.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/subscribe.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '5f47a4b17de245af39a4e7a097e40623',
|
||||||
|
'uri' => '/res/5f47a4b1/rsrc/image/icon/subscribe.png',
|
||||||
|
'disk' => '/rsrc/image/icon/subscribe.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/tango/attachment.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '776fed2de89803fd8a0ba4b9deede230',
|
||||||
|
'uri' => '/res/776fed2d/rsrc/image/icon/tango/attachment.png',
|
||||||
|
'disk' => '/rsrc/image/icon/tango/attachment.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/tango/edit.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'c0028d99dcf4e9559bbf3c88ce2d8a8d',
|
||||||
|
'uri' => '/res/c0028d99/rsrc/image/icon/tango/edit.png',
|
||||||
|
'disk' => '/rsrc/image/icon/tango/edit.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/tango/log.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'a6f72499bef279ff6807a7dbc5148f1e',
|
||||||
|
'uri' => '/res/a6f72499/rsrc/image/icon/tango/log.png',
|
||||||
|
'disk' => '/rsrc/image/icon/tango/log.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/tango/upload.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '8c11b63d6d99db3d7159c5d9a94e3062',
|
||||||
|
'uri' => '/res/8c11b63d/rsrc/image/icon/tango/upload.png',
|
||||||
|
'disk' => '/rsrc/image/icon/tango/upload.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/icon/unsubscribe.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '29429ad65aa3af50b072b32087057361',
|
||||||
|
'uri' => '/res/29429ad6/rsrc/image/icon/unsubscribe.png',
|
||||||
|
'disk' => '/rsrc/image/icon/unsubscribe.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/phabricator_logo.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '7e62ff4001914cb3c87893a228f400c4',
|
||||||
|
'uri' => '/res/7e62ff40/rsrc/image/phabricator_logo.png',
|
||||||
|
'disk' => '/rsrc/image/phabricator_logo.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/phabricator_logo_admin.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '98c8fd922b8ccf21c268b3451393a28f',
|
||||||
|
'uri' => '/res/98c8fd92/rsrc/image/phabricator_logo_admin.png',
|
||||||
|
'disk' => '/rsrc/image/phabricator_logo_admin.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/sprite.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '8c6200d3191c0deea30f22e7b8166b15',
|
||||||
|
'uri' => '/res/8c6200d3/rsrc/image/sprite.png',
|
||||||
|
'disk' => '/rsrc/image/sprite.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/swf/aphlict.swf' =>
|
||||||
|
array(
|
||||||
|
'hash' => '1ca0c776448792b23edd38ab0bb9c0c2',
|
||||||
|
'uri' => '/res/1ca0c776/rsrc/swf/aphlict.swf',
|
||||||
|
'disk' => '/rsrc/swf/aphlict.swf',
|
||||||
|
'type' => 'swf',
|
||||||
|
),
|
||||||
'aphront-attached-file-view-css' =>
|
'aphront-attached-file-view-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/a6ca5487/rsrc/css/aphront/attached-file-view.css',
|
'uri' => '/res/a6ca5487/rsrc/css/aphront/attached-file-view.css',
|
||||||
@@ -72,7 +415,7 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'aphront-form-view-css' =>
|
'aphront-form-view-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/aec38c95/rsrc/css/aphront/form-view.css',
|
'uri' => '/res/3e7be7b8/rsrc/css/aphront/form-view.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
@@ -81,7 +424,7 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'aphront-headsup-action-list-view-css' =>
|
'aphront-headsup-action-list-view-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/aff0a541/rsrc/css/aphront/headsup-action-list-view.css',
|
'uri' => '/res/9c5cd292/rsrc/css/aphront/headsup-action-list-view.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
@@ -286,7 +629,7 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'diffusion-icons-css' =>
|
'diffusion-icons-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/b7e2a749/rsrc/css/application/diffusion/diffusion-icons.css',
|
'uri' => '/res/b93e32c9/rsrc/css/application/diffusion/diffusion-icons.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
@@ -1467,7 +1810,7 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'maniphest-task-summary-css' =>
|
'maniphest-task-summary-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/6e55a34a/rsrc/css/application/maniphest/task-summary.css',
|
'uri' => '/res/6e67cb30/rsrc/css/application/maniphest/task-summary.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
@@ -1536,7 +1879,7 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'phabricator-app-buttons-css' =>
|
'phabricator-app-buttons-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/4ce62d37/rsrc/css/application/directory/phabricator-app-buttons.css',
|
'uri' => '/res/1e153463/rsrc/css/application/directory/phabricator-app-buttons.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
@@ -1563,7 +1906,7 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'phabricator-core-buttons-css' =>
|
'phabricator-core-buttons-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/89b939ae/rsrc/css/core/buttons.css',
|
'uri' => '/res/0f32dc32/rsrc/css/core/buttons.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
@@ -1637,7 +1980,7 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'phabricator-flag-css' =>
|
'phabricator-flag-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/81d9e551/rsrc/css/application/flag/flag.css',
|
'uri' => '/res/36d4af36/rsrc/css/application/flag/flag.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
@@ -1762,7 +2105,7 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'phabricator-remarkup-css' =>
|
'phabricator-remarkup-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/43702d3c/rsrc/css/core/remarkup.css',
|
'uri' => '/res/fb10d329/rsrc/css/core/remarkup.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
@@ -1801,7 +2144,7 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'phabricator-standard-page-view' =>
|
'phabricator-standard-page-view' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/5be1dd54/rsrc/css/application/base/standard-page-view.css',
|
'uri' => '/res/f65061d9/rsrc/css/application/base/standard-page-view.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
@@ -2037,7 +2380,7 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'stripe-payment-form-css' =>
|
'stripe-payment-form-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/e2358ded/rsrc/css/application/phortune/stripe-payment-form.css',
|
'uri' => '/res/634a6371/rsrc/css/application/phortune/stripe-payment-form.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
@@ -2056,7 +2399,7 @@ celerity_register_resource_map(array(
|
|||||||
), array(
|
), array(
|
||||||
'packages' =>
|
'packages' =>
|
||||||
array(
|
array(
|
||||||
'803864a4' =>
|
'c7d9f973' =>
|
||||||
array(
|
array(
|
||||||
'name' => 'core.pkg.css',
|
'name' => 'core.pkg.css',
|
||||||
'symbols' =>
|
'symbols' =>
|
||||||
@@ -2081,7 +2424,7 @@ celerity_register_resource_map(array(
|
|||||||
17 => 'aphront-pager-view-css',
|
17 => 'aphront-pager-view-css',
|
||||||
18 => 'phabricator-transaction-view-css',
|
18 => 'phabricator-transaction-view-css',
|
||||||
),
|
),
|
||||||
'uri' => '/res/pkg/803864a4/core.pkg.css',
|
'uri' => '/res/pkg/c7d9f973/core.pkg.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
),
|
),
|
||||||
'21d01ed8' =>
|
'21d01ed8' =>
|
||||||
@@ -2106,7 +2449,7 @@ celerity_register_resource_map(array(
|
|||||||
'uri' => '/res/pkg/21d01ed8/core.pkg.js',
|
'uri' => '/res/pkg/21d01ed8/core.pkg.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
),
|
),
|
||||||
'18be02e0' =>
|
'216b9542' =>
|
||||||
array(
|
array(
|
||||||
'name' => 'differential.pkg.css',
|
'name' => 'differential.pkg.css',
|
||||||
'symbols' =>
|
'symbols' =>
|
||||||
@@ -2124,7 +2467,7 @@ celerity_register_resource_map(array(
|
|||||||
10 => 'phabricator-content-source-view-css',
|
10 => 'phabricator-content-source-view-css',
|
||||||
11 => 'differential-local-commits-view-css',
|
11 => 'differential-local-commits-view-css',
|
||||||
),
|
),
|
||||||
'uri' => '/res/pkg/18be02e0/differential.pkg.css',
|
'uri' => '/res/pkg/216b9542/differential.pkg.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
),
|
),
|
||||||
'4d8b2d16' =>
|
'4d8b2d16' =>
|
||||||
@@ -2182,7 +2525,7 @@ celerity_register_resource_map(array(
|
|||||||
'uri' => '/res/pkg/4fbae2af/javelin.pkg.js',
|
'uri' => '/res/pkg/4fbae2af/javelin.pkg.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
),
|
),
|
||||||
'47770cea' =>
|
'8db30c56' =>
|
||||||
array(
|
array(
|
||||||
'name' => 'maniphest.pkg.css',
|
'name' => 'maniphest.pkg.css',
|
||||||
'symbols' =>
|
'symbols' =>
|
||||||
@@ -2191,7 +2534,7 @@ celerity_register_resource_map(array(
|
|||||||
1 => 'maniphest-transaction-detail-css',
|
1 => 'maniphest-transaction-detail-css',
|
||||||
2 => 'aphront-attached-file-view-css',
|
2 => 'aphront-attached-file-view-css',
|
||||||
),
|
),
|
||||||
'uri' => '/res/pkg/47770cea/maniphest.pkg.css',
|
'uri' => '/res/pkg/8db30c56/maniphest.pkg.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
),
|
),
|
||||||
'86fc0b0c' =>
|
'86fc0b0c' =>
|
||||||
@@ -2226,28 +2569,28 @@ celerity_register_resource_map(array(
|
|||||||
),
|
),
|
||||||
'reverse' =>
|
'reverse' =>
|
||||||
array(
|
array(
|
||||||
'aphront-attached-file-view-css' => '47770cea',
|
'aphront-attached-file-view-css' => '8db30c56',
|
||||||
'aphront-crumbs-view-css' => '803864a4',
|
'aphront-crumbs-view-css' => 'c7d9f973',
|
||||||
'aphront-dialog-view-css' => '803864a4',
|
'aphront-dialog-view-css' => 'c7d9f973',
|
||||||
'aphront-form-view-css' => '803864a4',
|
'aphront-form-view-css' => 'c7d9f973',
|
||||||
'aphront-headsup-action-list-view-css' => '18be02e0',
|
'aphront-headsup-action-list-view-css' => '216b9542',
|
||||||
'aphront-list-filter-view-css' => '803864a4',
|
'aphront-list-filter-view-css' => 'c7d9f973',
|
||||||
'aphront-pager-view-css' => '803864a4',
|
'aphront-pager-view-css' => 'c7d9f973',
|
||||||
'aphront-panel-view-css' => '803864a4',
|
'aphront-panel-view-css' => 'c7d9f973',
|
||||||
'aphront-side-nav-view-css' => '803864a4',
|
'aphront-side-nav-view-css' => 'c7d9f973',
|
||||||
'aphront-table-view-css' => '803864a4',
|
'aphront-table-view-css' => 'c7d9f973',
|
||||||
'aphront-tokenizer-control-css' => '803864a4',
|
'aphront-tokenizer-control-css' => 'c7d9f973',
|
||||||
'aphront-typeahead-control-css' => '803864a4',
|
'aphront-typeahead-control-css' => 'c7d9f973',
|
||||||
'differential-changeset-view-css' => '18be02e0',
|
'differential-changeset-view-css' => '216b9542',
|
||||||
'differential-core-view-css' => '18be02e0',
|
'differential-core-view-css' => '216b9542',
|
||||||
'differential-inline-comment-editor' => '4d8b2d16',
|
'differential-inline-comment-editor' => '4d8b2d16',
|
||||||
'differential-local-commits-view-css' => '18be02e0',
|
'differential-local-commits-view-css' => '216b9542',
|
||||||
'differential-revision-add-comment-css' => '18be02e0',
|
'differential-revision-add-comment-css' => '216b9542',
|
||||||
'differential-revision-comment-css' => '18be02e0',
|
'differential-revision-comment-css' => '216b9542',
|
||||||
'differential-revision-comment-list-css' => '18be02e0',
|
'differential-revision-comment-list-css' => '216b9542',
|
||||||
'differential-revision-detail-css' => '18be02e0',
|
'differential-revision-detail-css' => '216b9542',
|
||||||
'differential-revision-history-css' => '18be02e0',
|
'differential-revision-history-css' => '216b9542',
|
||||||
'differential-table-of-contents-css' => '18be02e0',
|
'differential-table-of-contents-css' => '216b9542',
|
||||||
'diffusion-commit-view-css' => '4ccda8a6',
|
'diffusion-commit-view-css' => '4ccda8a6',
|
||||||
'javelin-behavior' => '4fbae2af',
|
'javelin-behavior' => '4fbae2af',
|
||||||
'javelin-behavior-aphront-basic-tokenizer' => '2af849fb',
|
'javelin-behavior-aphront-basic-tokenizer' => '2af849fb',
|
||||||
@@ -2292,25 +2635,25 @@ celerity_register_resource_map(array(
|
|||||||
'javelin-util' => '4fbae2af',
|
'javelin-util' => '4fbae2af',
|
||||||
'javelin-vector' => '4fbae2af',
|
'javelin-vector' => '4fbae2af',
|
||||||
'javelin-workflow' => '21d01ed8',
|
'javelin-workflow' => '21d01ed8',
|
||||||
'maniphest-task-summary-css' => '47770cea',
|
'maniphest-task-summary-css' => '8db30c56',
|
||||||
'maniphest-transaction-detail-css' => '47770cea',
|
'maniphest-transaction-detail-css' => '8db30c56',
|
||||||
'phabricator-app-buttons-css' => '803864a4',
|
'phabricator-app-buttons-css' => 'c7d9f973',
|
||||||
'phabricator-content-source-view-css' => '18be02e0',
|
'phabricator-content-source-view-css' => '216b9542',
|
||||||
'phabricator-core-buttons-css' => '803864a4',
|
'phabricator-core-buttons-css' => 'c7d9f973',
|
||||||
'phabricator-core-css' => '803864a4',
|
'phabricator-core-css' => 'c7d9f973',
|
||||||
'phabricator-directory-css' => '803864a4',
|
'phabricator-directory-css' => 'c7d9f973',
|
||||||
'phabricator-drag-and-drop-file-upload' => '4d8b2d16',
|
'phabricator-drag-and-drop-file-upload' => '4d8b2d16',
|
||||||
'phabricator-dropdown-menu' => '21d01ed8',
|
'phabricator-dropdown-menu' => '21d01ed8',
|
||||||
'phabricator-jump-nav' => '803864a4',
|
'phabricator-jump-nav' => 'c7d9f973',
|
||||||
'phabricator-keyboard-shortcut' => '21d01ed8',
|
'phabricator-keyboard-shortcut' => '21d01ed8',
|
||||||
'phabricator-keyboard-shortcut-manager' => '21d01ed8',
|
'phabricator-keyboard-shortcut-manager' => '21d01ed8',
|
||||||
'phabricator-menu-item' => '21d01ed8',
|
'phabricator-menu-item' => '21d01ed8',
|
||||||
'phabricator-object-selector-css' => '18be02e0',
|
'phabricator-object-selector-css' => '216b9542',
|
||||||
'phabricator-paste-file-upload' => '21d01ed8',
|
'phabricator-paste-file-upload' => '21d01ed8',
|
||||||
'phabricator-remarkup-css' => '803864a4',
|
'phabricator-remarkup-css' => 'c7d9f973',
|
||||||
'phabricator-shaped-request' => '4d8b2d16',
|
'phabricator-shaped-request' => '4d8b2d16',
|
||||||
'phabricator-standard-page-view' => '803864a4',
|
'phabricator-standard-page-view' => 'c7d9f973',
|
||||||
'phabricator-transaction-view-css' => '803864a4',
|
'phabricator-transaction-view-css' => 'c7d9f973',
|
||||||
'syntax-highlighting-css' => '803864a4',
|
'syntax-highlighting-css' => 'c7d9f973',
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -104,6 +104,8 @@ phutil_register_library_map(array(
|
|||||||
'CelerityResourceController' => 'infrastructure/celerity/controller',
|
'CelerityResourceController' => 'infrastructure/celerity/controller',
|
||||||
'CelerityResourceGraph' => 'infrastructure/celerity/graph',
|
'CelerityResourceGraph' => 'infrastructure/celerity/graph',
|
||||||
'CelerityResourceMap' => 'infrastructure/celerity/map',
|
'CelerityResourceMap' => 'infrastructure/celerity/map',
|
||||||
|
'CelerityResourceTransformer' => 'infrastructure/celerity/transformer',
|
||||||
|
'CelerityResourceTransformerTestCase' => 'infrastructure/celerity/transformer/__tests__',
|
||||||
'CelerityStaticResourceResponse' => 'infrastructure/celerity/response',
|
'CelerityStaticResourceResponse' => 'infrastructure/celerity/response',
|
||||||
'ConduitAPIMethod' => 'applications/conduit/method/base',
|
'ConduitAPIMethod' => 'applications/conduit/method/base',
|
||||||
'ConduitAPIRequest' => 'applications/conduit/protocol/request',
|
'ConduitAPIRequest' => 'applications/conduit/protocol/request',
|
||||||
@@ -948,6 +950,7 @@ phutil_register_library_map(array(
|
|||||||
'_qsprintf_check_scalar_type' => 'storage/qsprintf',
|
'_qsprintf_check_scalar_type' => 'storage/qsprintf',
|
||||||
'_qsprintf_check_type' => 'storage/qsprintf',
|
'_qsprintf_check_type' => 'storage/qsprintf',
|
||||||
'celerity_generate_unique_node_id' => 'infrastructure/celerity/api',
|
'celerity_generate_unique_node_id' => 'infrastructure/celerity/api',
|
||||||
|
'celerity_get_resource_uri' => 'infrastructure/celerity/api',
|
||||||
'celerity_register_resource_map' => 'infrastructure/celerity/map',
|
'celerity_register_resource_map' => 'infrastructure/celerity/map',
|
||||||
'javelin_render_tag' => 'infrastructure/javelin/markup',
|
'javelin_render_tag' => 'infrastructure/javelin/markup',
|
||||||
'phabricator_date' => 'view/utils',
|
'phabricator_date' => 'view/utils',
|
||||||
@@ -1054,6 +1057,7 @@ phutil_register_library_map(array(
|
|||||||
'AphrontWebpageResponse' => 'AphrontResponse',
|
'AphrontWebpageResponse' => 'AphrontResponse',
|
||||||
'CelerityResourceController' => 'AphrontController',
|
'CelerityResourceController' => 'AphrontController',
|
||||||
'CelerityResourceGraph' => 'AbstractDirectedGraph',
|
'CelerityResourceGraph' => 'AbstractDirectedGraph',
|
||||||
|
'CelerityResourceTransformerTestCase' => 'PhabricatorTestCase',
|
||||||
'ConduitAPI_arcanist_Method' => 'ConduitAPIMethod',
|
'ConduitAPI_arcanist_Method' => 'ConduitAPIMethod',
|
||||||
'ConduitAPI_arcanist_projectinfo_Method' => 'ConduitAPI_arcanist_Method',
|
'ConduitAPI_arcanist_projectinfo_Method' => 'ConduitAPI_arcanist_Method',
|
||||||
'ConduitAPI_audit_Method' => 'ConduitAPIMethod',
|
'ConduitAPI_audit_Method' => 'ConduitAPIMethod',
|
||||||
|
|||||||
@@ -424,7 +424,9 @@ class AphrontDefaultApplicationConfiguration
|
|||||||
protected function getResourceURIMapRules() {
|
protected function getResourceURIMapRules() {
|
||||||
return array(
|
return array(
|
||||||
'/res/' => array(
|
'/res/' => array(
|
||||||
'(?P<package>pkg/)?(?P<hash>[a-f0-9]{8})/(?P<path>.+\.(?:css|js))'
|
'(?P<package>pkg/)?'.
|
||||||
|
'(?P<hash>[a-f0-9]{8})/'.
|
||||||
|
'(?P<path>.+\.(?:css|js|jpg|png|swf|gif))'
|
||||||
=> 'CelerityResourceController',
|
=> 'CelerityResourceController',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -106,7 +106,9 @@ final class PhabricatorFileTransformController
|
|||||||
throw new Exception("Unsupported transformation type!");
|
throw new Exception("Unsupported transformation type!");
|
||||||
}
|
}
|
||||||
|
|
||||||
$path = "/rsrc/image/icon/fatcow/thumbnails/{$prefix}{$suffix}.png";
|
$path = celerity_get_resource_uri(
|
||||||
|
"/rsrc/image/icon/fatcow/thumbnails/{$prefix}{$suffix}.png");
|
||||||
|
|
||||||
return id(new AphrontRedirectResponse())
|
return id(new AphrontRedirectResponse())
|
||||||
->setURI($path);
|
->setURI($path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ phutil_require_module('phabricator', 'applications/files/controller/base');
|
|||||||
phutil_require_module('phabricator', 'applications/files/storage/file');
|
phutil_require_module('phabricator', 'applications/files/storage/file');
|
||||||
phutil_require_module('phabricator', 'applications/files/storage/transformed');
|
phutil_require_module('phabricator', 'applications/files/storage/transformed');
|
||||||
phutil_require_module('phabricator', 'applications/files/transform');
|
phutil_require_module('phabricator', 'applications/files/transform');
|
||||||
|
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||||
|
|
||||||
phutil_require_module('phutil', 'utils');
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'infrastructure/celerity/map');
|
||||||
phutil_require_module('phabricator', 'infrastructure/celerity/response');
|
phutil_require_module('phabricator', 'infrastructure/celerity/response');
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Facebook, Inc.
|
* Copyright 2012 Facebook, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Include a CSS or JS static resource by name. This function records a
|
* Include a CSS or JS static resource by name. This function records a
|
||||||
* dependency for the current page, so when a response is generated it can be
|
* dependency for the current page, so when a response is generated it can be
|
||||||
@@ -57,3 +56,22 @@ function celerity_generate_unique_node_id() {
|
|||||||
return 'UQ'.$block.'_'.($uniq++);
|
return 'UQ'.$block.'_'.($uniq++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the versioned URI for a raw resource, like an image.
|
||||||
|
*
|
||||||
|
* @param string Path to the raw image.
|
||||||
|
* @return string Versioned path to the image, if one is available.
|
||||||
|
*
|
||||||
|
* @group celerity
|
||||||
|
*/
|
||||||
|
function celerity_get_resource_uri($resource) {
|
||||||
|
$map = CelerityResourceMap::getInstance();
|
||||||
|
|
||||||
|
$info = $map->lookupFileInformation($resource);
|
||||||
|
if ($info) {
|
||||||
|
return $info['uri'];
|
||||||
|
} else {
|
||||||
|
return $resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,11 +38,17 @@ final class CelerityResourceController extends AphrontController {
|
|||||||
public function processRequest() {
|
public function processRequest() {
|
||||||
$path = $this->path;
|
$path = $this->path;
|
||||||
|
|
||||||
// Sanity checking to keep this from exposing anything sensitive.
|
// Sanity checking to keep this from exposing anything sensitive, since it
|
||||||
$path = preg_replace('@(//|\\.\\.)@', '', $path);
|
// ultimately boils down to disk reads.
|
||||||
$matches = null;
|
if (preg_match('@(//|\.\.)@', $path)) {
|
||||||
if (!preg_match('/\.(css|js)$/', $path, $matches)) {
|
return new Aphront400Response();
|
||||||
throw new Exception("Only CSS and JS resources may be served.");
|
}
|
||||||
|
|
||||||
|
$type = CelerityResourceTransformer::getResourceType($path);
|
||||||
|
$type_map = $this->getSupportedResourceTypes();
|
||||||
|
|
||||||
|
if (empty($type_map[$type])) {
|
||||||
|
throw new Exception("Only static resources may be served.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
|
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
|
||||||
@@ -52,8 +58,6 @@ final class CelerityResourceController extends AphrontController {
|
|||||||
return $this->makeResponseCacheable(new Aphront304Response());
|
return $this->makeResponseCacheable(new Aphront304Response());
|
||||||
}
|
}
|
||||||
|
|
||||||
$type = $matches[1];
|
|
||||||
|
|
||||||
$root = dirname(phutil_get_library_root('phabricator'));
|
$root = dirname(phutil_get_library_root('phabricator'));
|
||||||
|
|
||||||
if ($this->package) {
|
if ($this->package) {
|
||||||
@@ -80,21 +84,29 @@ final class CelerityResourceController extends AphrontController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = new AphrontFileResponse();
|
$xformer = new CelerityResourceTransformer();
|
||||||
$data = $this->minifyData($data, $type);
|
$xformer->setMinify(PhabricatorEnv::getEnvConfig('celerity.minify'));
|
||||||
$response->setContent($data);
|
$xformer->setCelerityMap(CelerityResourceMap::getInstance());
|
||||||
switch ($type) {
|
|
||||||
case 'css':
|
|
||||||
$response->setMimeType("text/css; charset=utf-8");
|
|
||||||
break;
|
|
||||||
case 'js':
|
|
||||||
$response->setMimeType("text/javascript; charset=utf-8");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
$data = $xformer->transformResource($path, $data);
|
||||||
|
|
||||||
|
$response = new AphrontFileResponse();
|
||||||
|
$response->setContent($data);
|
||||||
|
$response->setMimeType($type_map[$type]);
|
||||||
return $this->makeResponseCacheable($response);
|
return $this->makeResponseCacheable($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getSupportedResourceTypes() {
|
||||||
|
return array(
|
||||||
|
'css' => 'text/css; charset=utf-8',
|
||||||
|
'js' => 'text/javascript; charset=utf-8',
|
||||||
|
'png' => 'image/png',
|
||||||
|
'gif' => 'image/gif',
|
||||||
|
'jpg' => 'image/jpg',
|
||||||
|
'swf' => 'application/x-shockwave-flash',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private function makeResponseCacheable(AphrontResponse $response) {
|
private function makeResponseCacheable(AphrontResponse $response) {
|
||||||
$response->setCacheDurationInSeconds(60 * 60 * 24 * 30);
|
$response->setCacheDurationInSeconds(60 * 60 * 24 * 30);
|
||||||
$response->setLastModified(time());
|
$response->setLastModified(time());
|
||||||
@@ -102,48 +114,4 @@ final class CelerityResourceController extends AphrontController {
|
|||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function minifyData($data, $type) {
|
|
||||||
if (!PhabricatorEnv::getEnvConfig('celerity.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':
|
|
||||||
$root = dirname(phutil_get_library_root('phabricator'));
|
|
||||||
$bin = $root.'/externals/javelin/support/jsxmin/jsxmin';
|
|
||||||
|
|
||||||
if (@file_exists($bin)) {
|
|
||||||
$future = new ExecFuture("{$bin} __DEV__:0");
|
|
||||||
$future->write($data);
|
|
||||||
list($err, $result) = $future->resolve();
|
|
||||||
if (!$err) {
|
|
||||||
$data = $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,14 @@
|
|||||||
|
|
||||||
phutil_require_module('phabricator', 'aphront/controller');
|
phutil_require_module('phabricator', 'aphront/controller');
|
||||||
phutil_require_module('phabricator', 'aphront/response/304');
|
phutil_require_module('phabricator', 'aphront/response/304');
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/400');
|
||||||
phutil_require_module('phabricator', 'aphront/response/404');
|
phutil_require_module('phabricator', 'aphront/response/404');
|
||||||
phutil_require_module('phabricator', 'aphront/response/file');
|
phutil_require_module('phabricator', 'aphront/response/file');
|
||||||
phutil_require_module('phabricator', 'infrastructure/celerity/map');
|
phutil_require_module('phabricator', 'infrastructure/celerity/map');
|
||||||
|
phutil_require_module('phabricator', 'infrastructure/celerity/transformer');
|
||||||
phutil_require_module('phabricator', 'infrastructure/env');
|
phutil_require_module('phabricator', 'infrastructure/env');
|
||||||
|
|
||||||
phutil_require_module('phutil', 'filesystem');
|
phutil_require_module('phutil', 'filesystem');
|
||||||
phutil_require_module('phutil', 'future/exec');
|
|
||||||
phutil_require_module('phutil', 'moduleutils');
|
phutil_require_module('phutil', 'moduleutils');
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group celerity
|
||||||
|
*/
|
||||||
|
final class CelerityResourceTransformer {
|
||||||
|
|
||||||
|
private $minify;
|
||||||
|
private $rawResourceMap;
|
||||||
|
private $celerityMap;
|
||||||
|
|
||||||
|
public function setMinify($minify) {
|
||||||
|
$this->minify = $minify;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRawResourceMap(array $raw_resource_map) {
|
||||||
|
$this->rawResourceMap = $raw_resource_map;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCelerityMap(CelerityResourceMap $celerity_map) {
|
||||||
|
$this->celerityMap = $celerity_map;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function transformResource($path, $data) {
|
||||||
|
$type = self::getResourceType($path);
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'css':
|
||||||
|
$data = preg_replace_callback(
|
||||||
|
'@url\s*\((\s*[\'"]?/rsrc/.*?)\)@s',
|
||||||
|
array($this, 'translateResourceURI'),
|
||||||
|
$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':
|
||||||
|
$root = dirname(phutil_get_library_root('phabricator'));
|
||||||
|
$bin = $root.'/externals/javelin/support/jsxmin/jsxmin';
|
||||||
|
|
||||||
|
if (@file_exists($bin)) {
|
||||||
|
$future = new ExecFuture("{$bin} __DEV__:0");
|
||||||
|
$future->write($data);
|
||||||
|
list($err, $result) = $future->resolve();
|
||||||
|
if (!$err) {
|
||||||
|
$data = $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getResourceType($path) {
|
||||||
|
return last(explode('.', $path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function translateResourceURI(array $matches) {
|
||||||
|
$uri = trim($matches[1], "'\" \r\t\n");
|
||||||
|
|
||||||
|
if ($this->rawResourceMap) {
|
||||||
|
if (isset($this->rawResourceMap[$uri]['uri'])) {
|
||||||
|
$uri = $this->rawResourceMap[$uri]['uri'];
|
||||||
|
}
|
||||||
|
} else if ($this->celerityMap) {
|
||||||
|
$info = $this->celerityMap->lookupFileInformation($uri);
|
||||||
|
if ($info) {
|
||||||
|
$uri = $info['uri'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'url('.$uri.')';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
14
src/infrastructure/celerity/transformer/__init__.php
Normal file
14
src/infrastructure/celerity/transformer/__init__.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'future/exec');
|
||||||
|
phutil_require_module('phutil', 'moduleutils');
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('CelerityResourceTransformer.php');
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group celerity
|
||||||
|
*/
|
||||||
|
final class CelerityResourceTransformerTestCase extends PhabricatorTestCase {
|
||||||
|
|
||||||
|
public function testTransformation() {
|
||||||
|
$files = dirname(__FILE__).'/data/';
|
||||||
|
foreach (Filesystem::listDirectory($files) as $file) {
|
||||||
|
$name = basename($file);
|
||||||
|
$data = Filesystem::readFile($files.'/'.$file);
|
||||||
|
$parts = preg_split('/^~~~+\n/m', $data);
|
||||||
|
$parts = array_merge($parts, array(null));
|
||||||
|
|
||||||
|
list($options, $in, $expect) = $parts;
|
||||||
|
|
||||||
|
$options = PhutilSimpleOptions::parse($options) + array(
|
||||||
|
'minify' => false,
|
||||||
|
'name' => $name,
|
||||||
|
);
|
||||||
|
|
||||||
|
$xformer = new CelerityResourceTransformer();
|
||||||
|
$xformer->setRawResourceMap(
|
||||||
|
array(
|
||||||
|
'/rsrc/example.png' => array(
|
||||||
|
'uri' => '/res/hash/example.png',
|
||||||
|
),
|
||||||
|
));
|
||||||
|
$xformer->setMinify($options['minify']);
|
||||||
|
|
||||||
|
$result = $xformer->transformResource($options['name'], $in);
|
||||||
|
|
||||||
|
$this->assertEqual(rtrim($expect), rtrim($result), $file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'infrastructure/celerity/transformer');
|
||||||
|
phutil_require_module('phabricator', 'infrastructure/testing/testcase');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'filesystem');
|
||||||
|
phutil_require_module('phutil', 'parser/simpleoptions');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('CelerityResourceTransformerTestCase.php');
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
minify=1
|
||||||
|
~~~~~~
|
||||||
|
.rule {
|
||||||
|
color: #aabbcc; /* Colorful! */
|
||||||
|
}
|
||||||
|
.rule2 {margin :1px ;}
|
||||||
|
~~~~~~
|
||||||
|
.rule{color:#abc}.rule2{margin:1px}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
~~~~~~
|
||||||
|
.rule1 {
|
||||||
|
background-image: url(/rsrc/example.png);
|
||||||
|
}
|
||||||
|
.rule2 {
|
||||||
|
background-image: url(/some/unknown/resource.jpg);
|
||||||
|
}
|
||||||
|
.rule3 {
|
||||||
|
background-image: url(
|
||||||
|
/rsrc/example.png
|
||||||
|
);
|
||||||
|
}
|
||||||
|
~~~~~~
|
||||||
|
.rule1 {
|
||||||
|
background-image: url(/res/hash/example.png);
|
||||||
|
}
|
||||||
|
.rule2 {
|
||||||
|
background-image: url(/some/unknown/resource.jpg);
|
||||||
|
}
|
||||||
|
.rule3 {
|
||||||
|
background-image: url(/res/hash/example.png);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user