3 final class PhabricatorIconRemarkupRule
extends PhutilRemarkupRule
{
5 public function getPriority() {
9 public function apply($text) {
10 return preg_replace_callback(
11 '@{icon\b((?:[^}\\\\]+|\\\\.)*)}@m',
12 array($this, 'markupIcon'),
16 public function markupIcon(array $matches) {
17 $engine = $this->getEngine();
18 $text_mode = $engine->isTextMode();
19 $mail_mode = $engine->isHTMLMailMode();
21 if (!$this->isFlatText($matches[0]) ||
$text_mode ||
$mail_mode) {
25 $extra = idx($matches, 1);
27 // We allow various forms, like these:
32 // {icon camera color=red}
33 // {icon, camera, color=red}
35 $extra = ltrim($extra, ", \n");
36 $extra = preg_split('/[\s,]+/', $extra, 2);
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');
47 $options = idx($extra, 1, '');
48 $parser = new PhutilSimpleOptions();
49 $options = $parser->parse($options) +
$defaults;
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.
57 $icon_names = array_fuse(PHUIIconView
::getIcons());
62 $color_names = array_fuse(PHUIIconView
::getIconColors());
65 if (empty($icon_names['fa-'.$icon])) {
69 $color = $options['color'];
70 if (empty($color_names[$color])) {
77 $spin = $options['spin'];
79 $classes[] = 'ph-spin';
82 $icon_view = id(new PHUIIconView())
83 ->setIcon('fa-'.$icon, implode(' ', $classes));
85 return $this->getEngine()->storeText($icon_view);