@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 PhabricatorIconRemarkupRule extends PhutilRemarkupRule {
4
5 public function getPriority() {
6 return 200.0;
7 }
8
9 public function apply($text) {
10 return preg_replace_callback(
11 '@{icon\b((?:[^}\\\\]+|\\\\.)*)}@m',
12 array($this, 'markupIcon'),
13 $text);
14 }
15
16 public function markupIcon(array $matches) {
17 $engine = $this->getEngine();
18 $text_mode = $engine->isTextMode();
19 $mail_mode = $engine->isHTMLMailMode();
20
21 if (!$this->isFlatText($matches[0]) || $text_mode || $mail_mode) {
22 return $matches[0];
23 }
24
25 $extra = idx($matches, 1);
26
27 // We allow various forms, like these:
28 //
29 // {icon}
30 // {icon camera}
31 // {icon,camera}
32 // {icon camera color=red}
33 // {icon, camera, color=red}
34
35 $extra = ltrim($extra, ", \n");
36 $extra = preg_split('/[\s,]+/', $extra, 2);
37
38 // Choose some arbitrary default icon so that previews render in a mostly
39 // reasonable way as you're typing the syntax.
40 $icon = idx($extra, 0, 'paw');
41
42 $defaults = array(
43 'color' => null,
44 'spin' => false,
45 );
46
47 $options = idx($extra, 1, '');
48 $parser = new PhutilSimpleOptions();
49 $options = $parser->parse($options) + $defaults;
50
51 // NOTE: We're validating icon and color names to prevent users from
52 // adding arbitrary CSS classes to the document. Although this probably
53 // isn't dangerous, it's safer to validate.
54
55 static $icon_names;
56 if (!$icon_names) {
57 $icon_names = array_fuse(PHUIIconView::getIcons());
58 }
59
60 static $color_names;
61 if (!$color_names) {
62 $color_names = array_fuse(PHUIIconView::getIconColors());
63 }
64
65 if (empty($icon_names['fa-'.$icon])) {
66 $icon = 'paw';
67 }
68
69 $color = $options['color'];
70 if ($color !== null && empty($color_names[$color])) {
71 $color = null;
72 }
73
74 $classes = array();
75 $classes[] = $color;
76
77 $spin = $options['spin'];
78 if ($spin) {
79 $classes[] = 'ph-spin';
80 }
81
82 $icon_view = id(new PHUIIconView())
83 ->setIcon('fa-'.$icon, implode(' ', $classes));
84
85 return $this->getEngine()->storeText($icon_view);
86 }
87
88}