@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 PhutilPygmentsSyntaxHighlighter extends Phobject {
4
5 private $config = array();
6
7 public function setConfig($key, $value) {
8 $this->config[$key] = $value;
9 return $this;
10 }
11
12 public function getHighlightFuture($source) {
13 $language = idx($this->config, 'language');
14
15 if (preg_match('/\r(?!\n)/', $source)) {
16 // TODO: Pygments converts "\r" newlines into "\n" newlines, so we can't
17 // use it on files with "\r" newlines. If we have "\r" not followed by
18 // "\n" in the file, skip highlighting.
19 $language = null;
20 }
21
22 if ($language) {
23 $language = $this->getPygmentsLexerNameFromLanguageName($language);
24
25 // See T13224. Under Ubuntu, avoid leaving an intermedite "dash" shell
26 // process so we hit "pygmentize" directly if we have to SIGKILL this
27 // because it explodes.
28
29 $future = new ExecFuture(
30 'exec pygmentize -O encoding=utf-8 -O stripnl=False -f html -l %s',
31 $language);
32
33 $scrub = false;
34 if ($language == 'php' && strpos($source, '<?') === false) {
35 $source = "<?php\n".$source;
36 $scrub = true;
37 }
38
39 // See T13224. In some cases, "pygmentize" has explosive runtime on small
40 // inputs. Put a hard cap on how long it is allowed to run for to limit
41 // the amount of damage it can do.
42 $future->setTimeout(15);
43
44 $future->write($source);
45
46 return new PhutilDefaultSyntaxHighlighterEnginePygmentsFuture(
47 $future,
48 $source,
49 $scrub);
50 }
51
52 return id(new PhutilDefaultSyntaxHighlighter())
53 ->getHighlightFuture($source);
54 }
55
56 private function getPygmentsLexerNameFromLanguageName($language) {
57 static $map = array(
58 'adb' => 'ada',
59 'ads' => 'ada',
60 'ahkl' => 'ahk',
61 'as' => 'as3',
62 'asax' => 'aspx-vb',
63 'ascx' => 'aspx-vb',
64 'ashx' => 'aspx-vb',
65 'ASM' => 'nasm',
66 'asm' => 'nasm',
67 'asmx' => 'aspx-vb',
68 'aspx' => 'aspx-vb',
69 'autodelegate' => 'myghty',
70 'autohandler' => 'mason',
71 'aux' => 'tex',
72 'axd' => 'aspx-vb',
73 'b' => 'brainfuck',
74 'bas' => 'vb.net',
75 'bf' => 'brainfuck',
76 'bmx' => 'blitzmax',
77 'c++' => 'cpp',
78 'c++-objdump' => 'cpp-objdump',
79 'cc' => 'cpp',
80 'cfc' => 'cfm',
81 'cfg' => 'ini',
82 'cfml' => 'cfm',
83 'cl' => 'common-lisp',
84 'clj' => 'clojure',
85 'cmd' => 'bat',
86 'coffee' => 'coffee-script',
87 'cs' => 'csharp',
88 'csh' => 'tcsh',
89 'cw' => 'redcode',
90 'cxx' => 'cpp',
91 'cxx-objdump' => 'cpp-objdump',
92 'darcspatch' => 'dpatch',
93 'def' => 'modula2',
94 'dhandler' => 'mason',
95 'di' => 'd',
96 'duby' => 'rb',
97 'dyl' => 'dylan',
98 'ebuild' => 'bash',
99 'eclass' => 'bash',
100 'el' => 'common-lisp',
101 'eps' => 'postscript',
102 'erl' => 'erlang',
103 'erl-sh' => 'erl',
104 'f' => 'fortran',
105 'f90' => 'fortran',
106 'feature' => 'Cucumber',
107 'fhtml' => 'velocity',
108 'flx' => 'felix',
109 'flxh' => 'felix',
110 'frag' => 'glsl',
111 'g' => 'antlr-ruby',
112 'G' => 'antlr-ruby',
113 'gdc' => 'gooddata-cl',
114 'gemspec' => 'rb',
115 'geo' => 'glsl',
116 'GNUmakefile' => 'make',
117 'h' => 'c',
118 'h++' => 'cpp',
119 'hh' => 'cpp',
120 'hpp' => 'cpp',
121 'hql' => 'sql',
122 'hrl' => 'erlang',
123 'hs' => 'haskell',
124 'htaccess' => 'apacheconf',
125 'htm' => 'html',
126 'html' => 'html+evoque',
127 'hxx' => 'cpp',
128 'hy' => 'hybris',
129 'hyb' => 'hybris',
130 'ik' => 'ioke',
131 'inc' => 'pov',
132 'j' => 'objective-j',
133 'jbst' => 'duel',
134 'kid' => 'genshi',
135 'ksh' => 'bash',
136 'less' => 'css',
137 'lgt' => 'logtalk',
138 'lisp' => 'common-lisp',
139 'll' => 'llvm',
140 'm' => 'objective-c',
141 'mak' => 'make',
142 'Makefile' => 'make',
143 'makefile' => 'make',
144 'man' => 'groff',
145 'mao' => 'mako',
146 'mc' => 'mason',
147 'md' => 'minid',
148 'mhtml' => 'mason',
149 'mi' => 'mason',
150 'ml' => 'ocaml',
151 'mli' => 'ocaml',
152 'mll' => 'ocaml',
153 'mly' => 'ocaml',
154 'mm' => 'objective-c',
155 'mo' => 'modelica',
156 'mod' => 'modula2',
157 'moo' => 'moocode',
158 'mu' => 'mupad',
159 'myt' => 'myghty',
160 'ns2' => 'newspeak',
161 'pas' => 'delphi',
162 'patch' => 'diff',
163 'phtml' => 'html+php',
164 'pl' => 'prolog',
165 'plot' => 'gnuplot',
166 'plt' => 'gnuplot',
167 'pm' => 'perl',
168 'po' => 'pot',
169 'pp' => 'puppet',
170 'pro' => 'prolog',
171 'proto' => 'protobuf',
172 'ps' => 'postscript',
173 'pxd' => 'cython',
174 'pxi' => 'cython',
175 'py' => 'python',
176 'pyw' => 'python',
177 'pyx' => 'cython',
178 'R' => 'splus',
179 'r' => 'rebol',
180 'r3' => 'rebol',
181 'rake' => 'rb',
182 'Rakefile' => 'rb',
183 'rbw' => 'rb',
184 'rbx' => 'rb',
185 'rest' => 'rst',
186 'rl' => 'ragel-em',
187 'robot' => 'robotframework',
188 'Rout' => 'rconsole',
189 'rss' => 'xml',
190 's' => 'gas',
191 'S' => 'splus',
192 'sc' => 'python',
193 'scm' => 'scheme',
194 'SConscript' => 'python',
195 'SConstruct' => 'python',
196 'scss' => 'css',
197 'sh' => 'bash',
198 'sh-session' => 'console',
199 'spt' => 'cheetah',
200 'sqlite3-console' => 'sqlite3',
201 'st' => 'smalltalk',
202 'sv' => 'v',
203 'tac' => 'python',
204 'tmpl' => 'cheetah',
205 'toc' => 'tex',
206 'tpl' => 'smarty',
207 'txt' => 'text',
208 'vapi' => 'vala',
209 'vb' => 'vb.net',
210 'vert' => 'glsl',
211 'vhd' => 'vhdl',
212 'vimrc' => 'vim',
213 'vm' => 'velocity',
214 'weechatlog' => 'irc',
215 'wlua' => 'lua',
216 'wsdl' => 'xml',
217 'xhtml' => 'html',
218 'xml' => 'xml+evoque',
219 'xqy' => 'xquery',
220 'xsd' => 'xml',
221 'xsl' => 'xslt',
222 'xslt' => 'xml',
223 'yml' => 'yaml',
224 );
225
226 return idx($map, $language, $language);
227 }
228
229}