@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
3abstract class PhutilRemarkupQuotedBlockRule
4 extends PhutilRemarkupBlockRule {
5
6 final public function supportsChildBlocks() {
7 return true;
8 }
9
10 public function willMarkupChildBlocks() {
11 $engine = $this->getEngine();
12
13 $depth = $engine->getQuoteDepth();
14 $depth = $depth + 1;
15 $engine->setQuoteDepth($depth);
16 }
17
18 public function didMarkupChildBlocks() {
19 $engine = $this->getEngine();
20
21 $depth = $engine->getQuoteDepth();
22 $depth = $depth - 1;
23 $engine->setQuoteDepth($depth);
24 }
25
26 final protected function normalizeQuotedBody($text) {
27 $text = phutil_split_lines($text, true);
28 foreach ($text as $key => $line) {
29 $text[$key] = substr($line, 1);
30 }
31
32 // If every line in the block is empty or begins with at least one leading
33 // space, strip the initial space off each line. When we quote text, we
34 // normally add "> " (with a space) to the beginning of each line, which
35 // can disrupt some other rules. If the block appears to have this space
36 // in front of each line, remove it.
37
38 $strip_space = true;
39 foreach ($text as $key => $line) {
40 $len = strlen($line);
41
42 if (!$len) {
43 // We'll still strip spaces if there are some completely empty
44 // lines, they may have just had trailing whitespace trimmed.
45 continue;
46 }
47
48 // If this line is part of a nested quote block, just ignore it when
49 // realigning this quote block. It's either an author attribution
50 // line with ">>!", or we'll deal with it in a subrule when processing
51 // the nested quote block.
52 if ($line[0] == '>') {
53 continue;
54 }
55
56 if ($line[0] == ' ' || $line[0] == "\n") {
57 continue;
58 }
59
60 // The first character of this line is something other than a space, so
61 // we can't strip spaces.
62 $strip_space = false;
63 break;
64 }
65
66 if ($strip_space) {
67 foreach ($text as $key => $line) {
68 $len = strlen($line);
69 if (!$len) {
70 continue;
71 }
72
73 if ($line[0] !== ' ') {
74 continue;
75 }
76
77 $text[$key] = substr($line, 1);
78 }
79 }
80
81 // Strip leading empty lines.
82 foreach ($text as $key => $line) {
83 if (!strlen(trim($line))) {
84 unset($text[$key]);
85 } else {
86 break;
87 }
88 }
89
90 return implode('', $text);
91 }
92
93 final protected function getQuotedText($text) {
94 $text = rtrim($text, "\n");
95
96 $no_whitespace = array(
97 // For readability, we render nested quotes as ">> quack",
98 // not "> > quack".
99 '>' => true,
100
101 // If the line is empty except for a newline, do not add an
102 // unnecessary dangling space.
103 "\n" => true,
104 );
105
106 $text = phutil_split_lines($text, true);
107 foreach ($text as $key => $line) {
108 $c = null;
109 if (isset($line[0])) {
110 $c = $line[0];
111 } else {
112 $c = '';
113 }
114
115 if (isset($no_whitespace[$c])) {
116 $text[$key] = '>'.$line;
117 } else {
118 $text[$key] = '> '.$line;
119 }
120 }
121 $text = implode('', $text);
122
123 return $text;
124 }
125
126}