@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 111 lines 2.7 kB view raw
1<?php 2 3final class PhutilRemarkupLiteralBlockRule extends PhutilRemarkupBlockRule { 4 5 public function getPriority() { 6 return 450; 7 } 8 9 public function getMatchingLineCount(array $lines, $cursor) { 10 // NOTE: We're consuming all contiguous blocks of %%% literals, so this: 11 // 12 // %%%a%%% 13 // %%%b%%% 14 // 15 // ...is equivalent to: 16 // 17 // %%%a 18 // b%%% 19 // 20 // If they are separated by a blank newline, they are parsed as two 21 // different blocks. This more clearly represents the original text in the 22 // output text and assists automated escaping of blocks coming into the 23 // system. 24 25 $start_pattern = '(^\s*%%%)'; 26 $end_pattern = '(%%%\s*$)'; 27 $trivial_pattern = '(^\s*%%%\s*$)'; 28 29 if (!preg_match($start_pattern, $lines[$cursor])) { 30 return 0; 31 } 32 33 $start_cursor = $cursor; 34 35 $found_empty = false; 36 $block_start = null; 37 while (true) { 38 if (!isset($lines[$cursor])) { 39 break; 40 } 41 42 $line = $lines[$cursor]; 43 44 if ($block_start === null) { 45 $is_start = preg_match($start_pattern, $line); 46 47 // If we've matched a block and then consumed one or more empty lines 48 // after it, stop merging more blocks into the match. 49 if ($found_empty) { 50 break; 51 } 52 53 if ($is_start) { 54 $block_start = $cursor; 55 } 56 } 57 58 if ($block_start !== null) { 59 $is_end = preg_match($end_pattern, $line); 60 61 // If a line contains only "%%%", it will match both the start and 62 // end patterns, but it only counts as a block start. 63 if ($is_end && ($cursor === $block_start)) { 64 $is_trivial = preg_match($trivial_pattern, $line); 65 if ($is_trivial) { 66 $is_end = false; 67 } 68 } 69 70 if ($is_end) { 71 $block_start = null; 72 $cursor++; 73 continue; 74 } 75 } 76 77 if ($block_start === null) { 78 if (strlen(trim($line))) { 79 break; 80 } 81 $found_empty = true; 82 } 83 84 $cursor++; 85 } 86 87 return ($cursor - $start_cursor); 88 } 89 90 public function markupText($text, $children) { 91 $text = rtrim($text); 92 $text = phutil_split_lines($text, $retain_endings = true); 93 foreach ($text as $key => $line) { 94 $line = preg_replace('/^\s*%%%/', '', $line); 95 $line = preg_replace('/%%%(\s*)\z/', '\1', $line); 96 $text[$key] = $line; 97 } 98 99 if ($this->getEngine()->isTextMode()) { 100 return implode('', $text); 101 } 102 103 return phutil_tag( 104 'p', 105 array( 106 'class' => 'remarkup-literal', 107 ), 108 phutil_implode_html(phutil_tag('br', array()), $text)); 109 } 110 111}