@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class CeleritySpriteGenerator extends Phobject {
4
5 public function buildTokenSheet() {
6 $icons = $this->getDirectoryList('tokens_1x');
7 $scales = array(
8 '1x' => 1,
9 '2x' => 2,
10 );
11 $template = id(new PhutilSprite())
12 ->setSourceSize(18, 18);
13
14 $sprites = array();
15 $prefix = 'tokens_';
16 foreach ($icons as $icon) {
17 $sprite = id(clone $template)
18 ->setName('tokens-'.$icon)
19 ->setTargetCSS('.tokens-'.$icon);
20
21 foreach ($scales as $scale_key => $scale) {
22 $path = $this->getPath($prefix.$scale_key.'/'.$icon.'.png');
23 $sprite->setSourceFile($path, $scale);
24 }
25 $sprites[] = $sprite;
26 }
27
28 $sheet = $this->buildSheet('tokens', true);
29 $sheet->setScales($scales);
30 foreach ($sprites as $sprite) {
31 $sheet->addSprite($sprite);
32 }
33
34 return $sheet;
35 }
36
37 public function buildLoginSheet() {
38 $icons = $this->getDirectoryList('login_1x');
39 $scales = array(
40 '1x' => 1,
41 '2x' => 2,
42 );
43 $template = id(new PhutilSprite())
44 ->setSourceSize(28, 28);
45
46 $sprites = array();
47 $prefix = 'login_';
48 foreach ($icons as $icon) {
49 $sprite = id(clone $template)
50 ->setName('login-'.$icon)
51 ->setTargetCSS('.login-'.$icon);
52
53 foreach ($scales as $scale_key => $scale) {
54 $path = $this->getPath($prefix.$scale_key.'/'.$icon.'.png');
55 $sprite->setSourceFile($path, $scale);
56 }
57 $sprites[] = $sprite;
58 }
59
60 $sheet = $this->buildSheet('login', true);
61 $sheet->setScales($scales);
62 foreach ($sprites as $sprite) {
63 $sheet->addSprite($sprite);
64 }
65
66 return $sheet;
67 }
68
69 private function getPath($to_path = null) {
70 $root = dirname(phutil_get_library_root('phabricator'));
71 return $root.'/resources/sprite/'.$to_path;
72 }
73
74 private function getDirectoryList($dir) {
75 $path = $this->getPath($dir);
76
77 $result = array();
78
79 $images = Filesystem::listDirectory($path, $include_hidden = false);
80 foreach ($images as $image) {
81 if (!preg_match('/\.png$/', $image)) {
82 throw new Exception(
83 pht(
84 "Expected file '%s' in '%s' to be a sprite source ending in '%s'.",
85 $image,
86 $path,
87 '.png'));
88 }
89 $result[] = substr($image, 0, -4);
90 }
91
92 return $result;
93 }
94
95 private function buildSheet(
96 $name,
97 $has_retina,
98 $type = null,
99 $extra_css = '') {
100
101 $sheet = new PhutilSpriteSheet();
102
103 $at = '@';
104
105 switch ($type) {
106 case PhutilSpriteSheet::TYPE_STANDARD:
107 default:
108 $type = PhutilSpriteSheet::TYPE_STANDARD;
109 $repeat_rule = 'no-repeat';
110 break;
111 case PhutilSpriteSheet::TYPE_REPEAT_X:
112 $repeat_rule = 'repeat-x';
113 break;
114 case PhutilSpriteSheet::TYPE_REPEAT_Y:
115 $repeat_rule = 'repeat-y';
116 break;
117 }
118
119 $retina_rules = null;
120 if ($has_retina) {
121 $retina_rules = <<<EOCSS
122@media
123only screen and (-webkit-min-device-pixel-ratio: 1.5),
124only screen and (min-resolution: 1.5dppx) {
125 .sprite-{$name}{$extra_css} {
126 background-image: url(/rsrc/image/sprite-{$name}-X2.png);
127 background-size: {X}px {Y}px;
128 }
129}
130EOCSS;
131 }
132
133 $sheet->setSheetType($type);
134 $sheet->setCSSHeader(<<<EOCSS
135/**
136 * @provides sprite-{$name}-css
137 * {$at}generated
138 */
139
140.sprite-{$name}{$extra_css} {
141 background-image: url(/rsrc/image/sprite-{$name}.png);
142 background-repeat: {$repeat_rule};
143}
144
145{$retina_rules}
146
147EOCSS
148);
149
150 return $sheet;
151 }
152}