php8
[web.mtrack] / MTrack / SyntaxHighlight.php
1 <?php # vim:ts=2:sw=2:et:
2 /* For licensing and copyright terms, see the file named LICENSE */
3
4 class MTrack_SyntaxHighlight {
5   static $schemes = array(
6     '' => 'No syntax highlighting',
7     'plain' => "Plain",
8     'wezterm' => "Wez's Terminal",
9     'zenburn' => "Zenburn",
10     'vibrant-ink' => "Vibrant Ink",
11     
12   );
13   static $lang_by_ext = array(
14       'c' => 'cpp',
15       'cc' => 'cpp',
16       'cpp' => 'cpp',
17       'h' => 'cpp',
18       'hpp' => 'cpp',
19       'icl' => 'cpp',
20       'ipp' => 'cpp',
21       'css' => 'css',
22       'php' => 'php',
23       'php3' => 'php',
24       'php4' => 'php',
25       'php5' => 'php',
26       'phtml' => 'php',
27       'pl' => 'perl',
28       'pm' => 'perl',
29       't' => 'perl',
30       'bash' => 'shell',
31       'sh' => 'shell',
32       'js' => 'javascript',
33       'json' => 'javascript',
34       'vb' => 'vb',
35       'xml' => 'xml',
36       'xsl' => 'xml',
37       'xslt' => 'xml',
38       'xsd' => 'xml',
39       'html' => 'xml',
40       'diff' => 'diff',
41       'patch' => 'diff',
42       'wiki' => 'wiki',
43     );
44   static $langs = array(
45     '' => 'No particular file type',
46     'cpp' => 'C/C++',
47     'css' => 'CSS (Cascading Style Sheet)',
48     'php' => 'PHP',
49     'perl' => 'Perl',
50     'shell' => 'Shell script',
51     'javascript' => 'Javascript',
52     'vb' => 'Visual Basic',
53     'xml' => 'HTML, XML, XSL',
54     'wiki' => 'Wiki Markup',
55     'diff' => 'Diff/Patch',
56   );
57
58   static function inferFileTypeFromContents($data) {
59     if (preg_match("/vim:.*ft=(\S+)/", $data, $M)) {
60       return $M[1];
61     }
62     if (preg_match("/^#!.*env\s+(\S+)/", $data, $M)) {
63       return $M[1];
64     }
65     if (preg_match("/^#!\s*(\S+)/", $data, $M)) {
66       return basename($M[1]);
67     }
68     return null;
69   }
70
71   static function highlightSource($data, $type = null, $filename = null, $line_numbers = false) {
72     if ($type === null) {
73       $type = self::inferFileTypeFromContents($data);
74       if ($type === null && $filename !== null) {
75         if (preg_match("/\.([^.]+)$/", $filename, $M)) {
76           $ext = strtolower($M[1]);
77           if (isset(self::$lang_by_ext[$ext])) {
78             $type = self::$lang_by_ext[$ext];
79           }
80         }
81       }
82     }
83     if ($type == 'diff') {
84       return mtrack_diff($data);
85     }
86     if (strlen($type) && isset(self::$langs[$type])) {
87       require_once dirname(__FILE__) . '/hyperlight/hyperlight.php';
88       $hl = new Hyperlight($type);
89       $hdata = $hl->render($data);
90     } else {
91       $hdata = htmlentities($data);
92     }
93     if (!$line_numbers) {
94       return "<span class='source-code plain'>$hdata</span>";
95     }
96     $lines = preg_split("/\r?\n/", $data);
97     $html = <<<HTML
98 <table class='codeann'>
99   <tr>
100     <th class='line'>line</th>
101     <th class='code'>code</th>
102   </tr>
103 HTML;
104     $nlines = count($lines);
105     for ($i = 1; $i <= $nlines; $i++) {
106       $html .= "<tr><td class='line'><a name='l$i'></a><a href='#l$i'>$i</a></td>";
107       if ($i == 1) {
108         $html .= "<td rowspan='$nlines' width='100%' class='source-code plain'>$hdata</td>";
109       }
110       $html .= "</tr>\n";
111     }
112     return $html . "</table>\n";
113   }
114
115   static function getSchemeSelect($selected = 'plain') {
116     $html = <<<HTML
117 <select class='select-hl-scheme'>
118 HTML;
119     foreach (self::$schemes as $k => $v) {
120       $sel = $selected == $k ? " selected" : '';
121       $html .= "<option value='$k'$sel>" .
122         htmlentities($v, ENT_QUOTES, 'utf-8') .
123         "</option>\n";
124     }
125     return $html . "</select>";
126   }
127
128   static function getLangSelect($name, $value) {
129     return mtrack_select_box($name, self::$langs, $value);
130   }
131
132 }
133