@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 83 lines 2.0 kB view raw
1<?php 2 3/** 4 * Parser that converts `pygmetize` output or similar HTML blocks from "class" 5 * attributes to "style" attributes. 6 */ 7final class PhutilPygmentizeParser extends Phobject { 8 9 private $map = array(); 10 11 public function setMap(array $map) { 12 $this->map = $map; 13 return $this; 14 } 15 16 public function getMap() { 17 return $this->map; 18 } 19 20 public function parse($block) { 21 $class_look = 'class="'; 22 $class_len = strlen($class_look); 23 24 $class_start = null; 25 26 $map = $this->map; 27 28 $len = strlen($block); 29 $out = ''; 30 $mode = 'text'; 31 for ($ii = 0; $ii < $len; $ii++) { 32 $c = $block[$ii]; 33 switch ($mode) { 34 case 'text': 35 // We're in general text between tags, and just passing characters 36 // through unmodified. 37 if ($c == '<') { 38 $mode = 'tag'; 39 } 40 $out .= $c; 41 break; 42 case 'tag': 43 // We're inside a tag, and looking for `class="` so we can rewrite 44 // it. 45 if ($c == '>') { 46 $mode = 'text'; 47 } 48 if ($c == 'c') { 49 if (!substr_compare($block, $class_look, $ii, $class_len)) { 50 $mode = 'class'; 51 $ii += $class_len; 52 $class_start = $ii; 53 } 54 } 55 56 if ($mode != 'class') { 57 $out .= $c; 58 } 59 break; 60 case 'class': 61 // We're inside a `class="..."` tag, and looking for the ending quote 62 // so we can replace it. 63 if ($c == '"') { 64 $class = substr($block, $class_start, $ii - $class_start); 65 66 // If this class is present in the map, rewrite it into an inline 67 // style attribute. 68 if (isset($map[$class])) { 69 $out .= 'style="'.phutil_escape_html($map[$class]).'"'; 70 } else { 71 $out .= 'class="'.$class.'"'; 72 } 73 74 $mode = 'tag'; 75 } 76 break; 77 } 78 } 79 80 return $out; 81 } 82 83}