@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
at recaptime-dev/main 81 lines 2.3 kB view raw
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}