diff --git a/phpBB/assets/iconify/iconify-bundle.js b/phpBB/assets/iconify/iconify-bundle.js index 34f7e483b6..571ed92bde 100644 --- a/phpBB/assets/iconify/iconify-bundle.js +++ b/phpBB/assets/iconify/iconify-bundle.js @@ -1,441 +1,19 @@ (function() { - function add(data) { - try { - if (typeof self.Iconify === 'object' && self.Iconify.addCollection) { - self.Iconify.addCollection(data); - return; - } - if (typeof self.IconifyPreload === 'undefined') { - self.IconifyPreload = []; - } - self.IconifyPreload.push(data); - } catch (err) { - } - } - add({ - "prefix": "fa", - "icons": { - "angle-left": { - "body": "", - "width": 608, - "height": 1280, - "inlineTop": -256 - }, - "arrow-left": { - "body": "", - "width": 1472, - "height": 1600, - "inlineTop": -160 - }, - "bar-chart": { - "body": "", - "width": 2048 - }, - "bars": { - "body": "", - "height": 1280, - "inlineTop": -256 - }, - "bell": { - "body": "", - "width": 1664, - "height": 1792, - "inlineTop": 0 - }, - "caret-down": { - "body": "", - "width": 1024, - "height": 1280, - "inlineTop": -256 - }, - "check-circle": { - "body": "" - }, - "chevron-circle-up": { - "body": "" - }, - "chevron-left": { - "body": "", - "width": 1088, - "height": 1664, - "inlineTop": 0 - }, - "circle": { - "body": "" - }, - "clone": { - "body": "", - "width": 1792, - "height": 1792, - "inlineTop": 0 - }, - "code": { - "body": "", - "width": 1856, - "height": 1408, - "inlineTop": -256 - }, - "cog": { - "body": "" - }, - "cogs": { - "body": "", - "width": 1920, - "height": 1792, - "inlineTop": 0 - }, - "dot-circle-o": { - "body": "" - }, - "envelope-o": { - "body": "", - "width": 1792, - "height": 1408, - "inlineTop": -256 - }, - "exclamation": { - "body": "", - "width": 448, - "height": 1408 - }, - "exclamation-triangle": { - "body": "", - "width": 1856, - "height": 1664, - "inlineTop": 0 - }, - "external-link": { - "body": "", - "width": 1792, - "inlineTop": 0 - }, - "external-link-square": { - "body": "" - }, - "file": { - "body": "", - "height": 1792, - "inlineTop": 0 - }, - "file-o": { - "body": "", - "height": 1792, - "inlineTop": 0 - }, - "gavel": { - "body": "", - "width": 1760, - "height": 1760, - "inlineTop": -32 - }, - "group": { - "body": "", - "width": 1920, - "height": 1792, - "inlineTop": 0 - }, - "home": { - "body": "", - "width": 1664, - "height": 1312, - "inlineTop": -224 - }, - "inbox": { - "body": "", - "height": 1280, - "inlineTop": -256 - }, - "info": { - "body": "", - "width": 640, - "height": 1408 - }, - "key": { - "body": "", - "width": 1696, - "height": 1600 - }, - "lock": { - "body": "", - "width": 1152, - "height": 1408 - }, - "mail-forward": { - "body": "", - "width": 1792, - "height": 1600, - "inlineTop": -64 - }, - "paperclip": { - "body": "", - "width": 1408 - }, - "pencil": { - "body": "" - }, - "edit": { - "body": "", - "width": 1792, - "height": 1408 - }, - "power-off": { - "body": "", - "height": 1664, - "inlineTop": 0 - }, - "print": { - "body": "", - "width": 1664 - }, - "question": { - "body": "", - "width": 928, - "height": 1280, - "inlineTop": -256 - }, - "question-circle": { - "body": "" - }, - "quote-left": { - "body": "", - "width": 1664, - "height": 1408 - }, - "recycle": { - "body": "", - "width": 1792, - "height": 1728, - "inlineTop": 0 - }, - "refresh": { - "body": "" - }, - "mail-reply": { - "body": "", - "width": 1792, - "height": 1600, - "inlineTop": -64 - }, - "rss-square": { - "body": "" - }, - "search": { - "body": "", - "width": 1664, - "height": 1664 - }, - "share-alt": { - "body": "" - }, - "shield": { - "body": "", - "width": 1280 - }, - "sliders": { - "body": "", - "height": 1408, - "inlineTop": -256 - }, - "sort-amount-asc": { - "body": "", - "width": 1760, - "height": 1792, - "inlineTop": 0 - }, - "times-circle": { - "body": "" - }, - "tint": { - "body": "", - "width": 1024, - "height": 1472, - "inlineTop": -64 - }, - "trash": { - "body": "", - "width": 1408 - }, - "user": { - "body": "", - "width": 1280 - }, - "wrench": { - "body": "", - "width": 1664, - "height": 1664 - } - }, - "aliases": { - "angle-right": { - "parent": "angle-left", - "hFlip": true - }, - "arrow-right": { - "parent": "arrow-left", - "hFlip": true - }, - "chevron-right": { - "parent": "chevron-left", - "hFlip": true - }, - "pencil-square-o": { - "parent": "edit" - }, - "reply": { - "parent": "mail-reply" - } - }, - "width": 1536, - "height": 1536, - "inlineHeight": 1792, - "inlineTop": -128, - "verticalAlign": -0.143 -}); -add({ - "prefix": "ic", - "icons": { - "outline-directions": { - "body": "" - }, - "outline-print": { - "body": "" - } - }, - "width": 24, - "height": 24 -}); -add({ - "prefix": "mdi", - "icons": { - "alert-decagram": { - "body": "" - }, - "arrow-right-bold": { - "body": "" - }, - "at": { - "body": "" - }, - "bookmark-plus-outline": { - "body": "" - }, - "comment-account-outline": { - "body": "" - }, - "comment-processing-outline": { - "body": "" - }, - "comment-text-outline": { - "body": "" - }, - "earth": { - "body": "" - }, - "eye-minus-outline": { - "body": "" - }, - "eye-plus-outline": { - "body": "" - }, - "facebook-box": { - "body": "", - "hidden": true - }, - "file": { - "body": "" - }, - "file-account-outline": { - "body": "" - }, - "text-box-multiple-outline": { - "body": "" - }, - "text-box-outline": { - "body": "" - }, - "file-document-outline": { - "body": "" - }, - "file-hidden": { - "body": "" - }, - "file-question-outline": { - "body": "" - }, - "file-upload-outline": { - "body": "" - }, - "fire": { - "body": "" - }, - "format-bold": { - "body": "" - }, - "format-italic": { - "body": "" - }, - "format-list-bulleted": { - "body": "" - }, - "format-list-numbered": { - "body": "" - }, - "format-quote-open": { - "body": "" - }, - "format-underline": { - "body": "" - }, - "image-outline": { - "body": "" - }, - "information-variant": { - "body": "" - }, - "link-variant": { - "body": "" - }, - "lock": { - "body": "" - }, - "playlist-plus": { - "body": "" - }, - "send-circle-outline": { - "body": "" - }, - "skype": { - "body": "" - }, - "star": { - "body": "" - }, - "twitter": { - "body": "" - }, - "update": { - "body": "" - }, - "youtube": { - "body": "" - } - }, - "aliases": { - "file-document-box-multiple-outline": { - "parent": "text-box-multiple-outline" - }, - "file-document-box-outline": { - "parent": "text-box-outline" - }, - "info-variant": { - "parent": "information-variant" - }, - "playlist-add": { - "parent": "playlist-plus" - } - }, - "width": 24, - "height": 24 -}); + function add(data) { + try { + if (typeof self.Iconify === 'object' && self.Iconify.addCollection) { + self.Iconify.addCollection(data); + return; + } + if (typeof self.IconifyPreload === 'undefined') { + self.IconifyPreload = []; + } + self.IconifyPreload.push(data); + } catch (err) { + } + } + add({"prefix":"fa","icons":{"angle-left":{"body":"","width":608,"height":1280,"inlineTop":-256},"bar-chart":{"body":"","width":2048},"bars":{"body":"","height":1280,"inlineTop":-256},"bell":{"body":"","width":1664,"height":1792,"inlineTop":0},"caret-down":{"body":"","width":1024,"height":1280,"inlineTop":-256},"check-circle":{"body":""},"chevron-circle-up":{"body":""},"chevron-left":{"body":"","width":1088,"height":1664,"inlineTop":0},"circle":{"body":""},"clone":{"body":"","width":1792,"height":1792,"inlineTop":0},"code":{"body":"","width":1856,"height":1408,"inlineTop":-256},"cog":{"body":""},"cogs":{"body":"","width":1920,"height":1792,"inlineTop":0},"envelope":{"body":"","width":1792,"height":1408,"inlineTop":-256},"exclamation":{"body":"","width":448,"height":1408},"exclamation-triangle":{"body":"","width":1856,"height":1664,"inlineTop":0},"external-link":{"body":"","width":1792,"inlineTop":0},"external-link-square":{"body":""},"file":{"body":"","height":1792,"inlineTop":0},"file-o":{"body":"","height":1792,"inlineTop":0},"gavel":{"body":"","width":1760,"height":1760,"inlineTop":-32},"group":{"body":"","width":1920,"height":1792,"inlineTop":0},"home":{"body":"","width":1664,"height":1312,"inlineTop":-224},"inbox":{"body":"","height":1280,"inlineTop":-256},"info":{"body":"","width":640,"height":1408},"lock":{"body":"","width":1152,"height":1408},"mail-forward":{"body":"","width":1792,"height":1600,"inlineTop":-64},"paperclip":{"body":"","width":1408},"pencil":{"body":""},"edit":{"body":"","width":1792,"height":1408},"power-off":{"body":"","height":1664,"inlineTop":0},"print":{"body":"","width":1664},"question":{"body":"","width":928,"height":1280,"inlineTop":-256},"question-circle":{"body":""},"quote-left":{"body":"","width":1664,"height":1408},"recycle":{"body":"","width":1792,"height":1728,"inlineTop":0},"refresh":{"body":""},"mail-reply":{"body":"","width":1792,"height":1600,"inlineTop":-64},"rss-square":{"body":""},"search":{"body":"","width":1664,"height":1664},"shield":{"body":"","width":1280},"sliders":{"body":"","height":1408,"inlineTop":-256},"sort-amount-asc":{"body":"","width":1760,"height":1792,"inlineTop":0},"close":{"body":"","width":1216,"height":1312,"inlineTop":-256},"times-circle":{"body":""},"tint":{"body":"","width":1024,"height":1472,"inlineTop":-64},"trash":{"body":"","width":1408},"user":{"body":"","width":1280},"wrench":{"body":"","width":1664,"height":1664}},"aliases":{"angle-right":{"parent":"angle-left","hFlip":true},"chevron-right":{"parent":"chevron-left","hFlip":true},"pencil-square-o":{"parent":"edit"},"reply":{"parent":"mail-reply"},"times":{"parent":"close"}},"width":1536,"height":1536,"inlineHeight":1792,"inlineTop":-128,"verticalAlign":-0.143}); +add({"prefix":"ic","icons":{"outline-directions":{"body":""},"outline-print":{"body":""}},"width":24,"height":24}); +add({"prefix":"mdi","icons":{"alert-decagram":{"body":""},"arrow-right-bold":{"body":""},"at":{"body":""},"bookmark-plus-outline":{"body":""},"comment-account-outline":{"body":""},"comment-processing-outline":{"body":""},"comment-text-outline":{"body":""},"earth":{"body":""},"eye-minus-outline":{"body":""},"eye-plus-outline":{"body":""},"facebook-box":{"body":"","hidden":true},"file":{"body":""},"file-account-outline":{"body":""},"text-box-multiple-outline":{"body":""},"text-box-outline":{"body":""},"file-document-outline":{"body":""},"file-hidden":{"body":""},"file-question-outline":{"body":""},"file-upload-outline":{"body":""},"fire":{"body":""},"format-bold":{"body":""},"format-italic":{"body":""},"format-list-bulleted":{"body":""},"format-list-numbered":{"body":""},"format-quote-open":{"body":""},"format-underline":{"body":""},"image-outline":{"body":""},"information-variant":{"body":""},"link-variant":{"body":""},"lock":{"body":""},"playlist-plus":{"body":""},"send-circle-outline":{"body":""},"skype":{"body":""},"star":{"body":""},"twitter":{"body":""},"update":{"body":""},"youtube":{"body":""}},"aliases":{"file-document-box-multiple-outline":{"parent":"text-box-multiple-outline"},"file-document-box-outline":{"parent":"text-box-outline"},"info-variant":{"parent":"information-variant"},"playlist-add":{"parent":"playlist-plus"}},"width":24,"height":24}); })(); diff --git a/phpBB/phpbb/assets/iconify_bundler.php b/phpBB/phpbb/assets/iconify_bundler.php new file mode 100644 index 0000000000..7e68d56309 --- /dev/null +++ b/phpBB/phpbb/assets/iconify_bundler.php @@ -0,0 +1,243 @@ + + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\assets; + +use phpbb\exception\runtime_exception; +use Iconify\JSONTools\Collection; +use Symfony\Component\Finder\Finder; + +class iconify_bundler +{ + protected $root_path = ''; + protected $icons_list = []; + + public function __construct(string $root_path) + { + $this->root_path = $root_path; + } + + public function run() + { + $this->find_icons(); + + $organized_icons = $this->organize_icons_list(); + + $output = $this->load_icons_data($organized_icons); + + $output = '(function() { + function add(data) { + try { + if (typeof self.Iconify === \'object\' && self.Iconify.addCollection) { + self.Iconify.addCollection(data); + return; + } + if (typeof self.IconifyPreload === \'undefined\') { + self.IconifyPreload = []; + } + self.IconifyPreload.push(data); + } catch (err) { + } + } + ' . $output . ' +})();' . "\n"; + + return $output; + } + + protected function find_icons() + { + $finder = new Finder(); + $finder->files()->in($this->root_path . '/styles/') + ->in($this->root_path . '/adm/style/') + ->name('*.html') + ->name('*.twig') + ->contains("Icon('iconify',"); + + foreach ($finder as $file) + { + $contents = $file->getContents(); + $matches = []; + preg_match_all("/Icon\('iconify', *(?:'(?[^']+(?' ~ S_CONTENT_FLOW_(?:BEGIN|END))?)|(?{[^}]+}))/m", $contents, $matches, PREG_SET_ORDER); + foreach ($matches as $match_data) + { + if (!empty($match_data['content_flow'])) + { + $base_icon_name = str_replace($match_data['content_flow'], '', $match_data['text']); + $this->add_icon($base_icon_name . 'left'); + $this->add_icon($base_icon_name . 'right'); + } + else if (!empty($match_data['json'])) + { + preg_match_all("/\s'(?[^']+)'/", $match_data['json'], $icons_array, PREG_SET_ORDER); + foreach ($icons_array as $icon) + { + $this->add_icon($icon['text']); + } + } + else if (!empty($match_data['text'])) + { + $this->add_icon($match_data['text']); + } + else + { + throw new runtime_exception('Found unexpected icon name `%1$s` in `%2$s`', [$match_data[0], $file->getPath()]); + } + } + } + + sort($this->icons_list, SORT_NATURAL); + } + + protected function add_icon(string $icon_name): void + { + if (!in_array($icon_name, $this->icons_list)) + { + $this->icons_list[] = $icon_name; + } + } + + /** + * Organize icons list by prefix + * + * Result is an object, where key is prefix, value is array of icon names + */ + protected function organize_icons_list(): array + { + $results = []; + + foreach ($this->icons_list as $icon_name) + { + // Split icon to prefix and name + $icon = $this->name_to_icon($icon_name); + if ($icon === null || $icon['provider'] !== '') + { + // Invalid name or icon name has provider. + // All icons in this example are from Iconify, so providers are not supported. + throw new \Error('Invalid icon name: ' . $icon_name); + } + + $prefix = $icon['prefix']; + $name = $icon['name']; + + // Add icon to results + if (!isset($results[$prefix])) + { + $results[$prefix] = [$name]; + continue; + } + if (!in_array($name, $results[$prefix])) + { + $results[$prefix][] = $name; + } + } + + return $results; + } + + /** + * Convert icon name from string to object. + * + * Object properties: + * - provider (ignored in this example) + * - prefix + * - name + * + * This function was converted to PHP from @iconify/utils/src/icon/name.ts + * See https://github.com/iconify/iconify/blob/master/packages/utils/src/icon/name.ts + * + * @param string $icon_name + */ + protected function name_to_icon(string $icon_name): ?array + { + $provider = ''; + $colonSeparated = explode(':', $icon_name); + + // Check for provider with correct '@' at start + if (substr($icon_name, 0, 1) === '@') + { + // First part is provider + if (count($colonSeparated) < 2 || count($colonSeparated) > 3) + { + return null; + } + $provider = substr(array_shift($colonSeparated), 1); + } + + // Check split by colon: "prefix:name", "provider:prefix:name" + if (!$colonSeparated || count($colonSeparated) > 3) + { + return null; + } + + if (count($colonSeparated) > 1) + { + // "prefix:name" + $name = array_pop($colonSeparated); + $prefix = array_pop($colonSeparated); + return [ + // Allow provider without '@': "provider:prefix:name" + 'provider' => count($colonSeparated) > 0 ? $colonSeparated[0] : $provider, + 'prefix' => $prefix, + 'name' => $name, + ]; + } + + // Attempt to split by dash: "prefix-name" + $dashSeparated = explode('-', $colonSeparated[0]); + if (count($dashSeparated) > 1) + { + return [ + 'provider' => $provider, + 'prefix' => array_shift($dashSeparated), + 'name' => implode('-', $dashSeparated), + ]; + } + + return null; + } + + protected function load_icons_data($icons): string + { + // Load icons data + $output = ''; + foreach ($icons as $prefix => $iconsList) + { + // Load icon set + $collection = new Collection($prefix); + if (!$collection->loadIconifyCollection($prefix)) { + throw new Error( + 'Icons with prefix "' . $prefix . '" do not exist in Iconify. Update iconify/json?' + ); + } + + // Make sure all icons exist + foreach ($iconsList as $name) { + if (!$collection->iconExists($name)) { + // Uncomment next line to throw error if an icon does not exist + // throw new Error('Could not find icon: "' . $prefix . ':' . $name . '"'); + echo 'Could not find icon: "', $prefix, ':', $name, "\"\n"; + } + } + + // Get data for all icons as string + $output .= $collection->scriptify([ + 'icons' => $iconsList, + 'callback' => 'add', + 'optimize' => true, + ]); + } + + return $output; + } +}