@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
3/**
4 * Simple syntax highlighter for the ".diviner" format, which is just Remarkup
5 * with a specific ruleset. This should also work alright for Remarkup.
6 */
7final class PhutilDivinerSyntaxHighlighter extends Phobject {
8
9 private $config = array();
10 private $replaceClass;
11
12 public function setConfig($key, $value) {
13 $this->config[$key] = $value;
14 return $this;
15 }
16
17 public function getHighlightFuture($source) {
18 $source = phutil_escape_html($source);
19
20 // This highlighter isn't perfect but tries to do an okay job at getting
21 // some of the basics at least. There's lots of room for improvement.
22
23 $blocks = explode("\n\n", $source);
24 foreach ($blocks as $key => $block) {
25 if (preg_match('/^[^ ](?! )/m', $block)) {
26 $blocks[$key] = $this->highlightBlock($block);
27 }
28 }
29 $source = implode("\n\n", $blocks);
30
31 $source = phutil_safe_html($source);
32 return new ImmediateFuture($source);
33 }
34
35 private function highlightBlock($source) {
36 // Highlight "@{class:...}" links to other documentation pages.
37 $source = $this->highlightPattern('/@{([\w@]+?):([^}]+?)}/', $source, 'nc');
38
39 // Highlight "@title", "@group", etc.
40 $source = $this->highlightPattern('/^@(\w+)/m', $source, 'k');
41
42 // Highlight bold, italic and monospace.
43 $source = $this->highlightPattern('@\\*\\*(.+?)\\*\\*@s', $source, 's');
44 $source = $this->highlightPattern('@(?<!:)//(.+?)//@s', $source, 's');
45 $source = $this->highlightPattern(
46 '@##([\s\S]+?)##|\B`(.+?)`\B@',
47 $source,
48 's');
49
50 // Highlight stuff that looks like headers.
51 $source = $this->highlightPattern('/^=(.*)$/m', $source, 'nv');
52
53 return $source;
54 }
55
56 private function highlightPattern($regexp, $source, $class) {
57 $this->replaceClass = $class;
58 $source = preg_replace_callback(
59 $regexp,
60 array($this, 'replacePattern'),
61 $source);
62
63 return $source;
64 }
65
66 public function replacePattern($matches) {
67
68 // NOTE: The goal here is to make sure a <span> never crosses a newline.
69
70 $content = $matches[0];
71 $content = explode("\n", $content);
72 foreach ($content as $key => $line) {
73 $content[$key] =
74 '<span class="'.$this->replaceClass.'">'.
75 $line.
76 '</span>';
77 }
78 return implode("\n", $content);
79 }
80
81}