@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
fork

Configure Feed

Select the types of activity you want to include in your feed.

Highlight inline diff context in HTML mail

Summary:
Ref T10694. Ref T9790. When generating inline diff context, highlight it and then mangle the highlighted output into `style="..."` so it works in HTML.

Also try to tighten up some spacing/formatting stuff.

Test Plan:
Got some output in this vein:

{F1259937}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9790, T10694

Differential Revision: https://secure.phabricator.com/D15852

+223 -28
+2
src/__phutil_library_map__.php
··· 370 370 'DifferentialChangesetFileTreeSideNavBuilder' => 'applications/differential/view/DifferentialChangesetFileTreeSideNavBuilder.php', 371 371 'DifferentialChangesetHTMLRenderer' => 'applications/differential/render/DifferentialChangesetHTMLRenderer.php', 372 372 'DifferentialChangesetListView' => 'applications/differential/view/DifferentialChangesetListView.php', 373 + 'DifferentialChangesetOneUpMailRenderer' => 'applications/differential/render/DifferentialChangesetOneUpMailRenderer.php', 373 374 'DifferentialChangesetOneUpRenderer' => 'applications/differential/render/DifferentialChangesetOneUpRenderer.php', 374 375 'DifferentialChangesetOneUpTestRenderer' => 'applications/differential/render/DifferentialChangesetOneUpTestRenderer.php', 375 376 'DifferentialChangesetParser' => 'applications/differential/parser/DifferentialChangesetParser.php', ··· 4559 4560 'DifferentialChangesetFileTreeSideNavBuilder' => 'Phobject', 4560 4561 'DifferentialChangesetHTMLRenderer' => 'DifferentialChangesetRenderer', 4561 4562 'DifferentialChangesetListView' => 'AphrontView', 4563 + 'DifferentialChangesetOneUpMailRenderer' => 'DifferentialChangesetRenderer', 4562 4564 'DifferentialChangesetOneUpRenderer' => 'DifferentialChangesetHTMLRenderer', 4563 4565 'DifferentialChangesetOneUpTestRenderer' => 'DifferentialChangesetTestRenderer', 4564 4566 'DifferentialChangesetParser' => 'Phobject',
+14 -6
src/applications/differential/editor/DifferentialTransactionEditor.php
··· 1212 1212 } 1213 1213 1214 1214 if ($inlines) { 1215 - $body->addTextSection( 1216 - pht('INLINE COMMENTS'), 1217 - $this->renderInlineCommentsForMail($object, $inlines)); 1215 + $this->appendInlineCommentsForMail($object, $inlines, $body); 1218 1216 } 1219 1217 1220 1218 $changed_uri = $this->getChangedPriorToCommitURI(); ··· 1374 1372 return $result; 1375 1373 } 1376 1374 1377 - private function renderInlineCommentsForMail( 1375 + private function appendInlineCommentsForMail( 1378 1376 PhabricatorLiskDAO $object, 1379 - array $inlines) { 1380 - return id(new DifferentialInlineCommentMailView()) 1377 + array $inlines, 1378 + PhabricatorMetaMTAMailBody $body) { 1379 + 1380 + $section = id(new DifferentialInlineCommentMailView()) 1381 1381 ->setViewer($this->getActor()) 1382 1382 ->setInlines($inlines) 1383 1383 ->buildMailSection(); 1384 + 1385 + $header = pht('INLINE COMMENTS'); 1386 + 1387 + $section_text = "\n".$section->getPlaintext(); 1388 + $section_html = $section->getHTML(); 1389 + 1390 + $body->addPlaintextSection($header, $section_text, false); 1391 + $body->addHTMLSection($header, $section_html); 1384 1392 } 1385 1393 1386 1394 private function loadDiff($phid, $need_changesets = false) {
+62 -20
src/applications/differential/mail/DifferentialInlineCommentMailView.php
··· 71 71 $context_html = $this->renderInline($parent, true, true); 72 72 } 73 73 } else { 74 - $patch = $this->getPatch($hunk_parser, $comment); 75 - $context_text = $this->renderPatch($comment, $patch, false); 76 - $context_html = $this->renderPatch($comment, $patch, true); 74 + $patch_text = $this->getPatch($hunk_parser, $comment, false); 75 + $context_text = $this->renderPatch($comment, $patch_text, false); 76 + 77 + $patch_html = $this->getPatch($hunk_parser, $comment, true); 78 + $context_html = $this->renderPatch($comment, $patch_html, true); 77 79 } 78 80 79 81 $render_text = $this->renderInline($comment, false, false); ··· 83 85 $section->addHTMLFragment($context_html); 84 86 85 87 $section->addPlaintextFragment($spacer_text); 86 - $section->addHTMLFragment($spacer_html); 87 88 88 89 $section->addPlaintextFragment($render_text); 89 90 $section->addHTMLFragment($render_html); ··· 180 181 $content = $this->renderRemarkupContent($content, $is_html); 181 182 182 183 if ($is_quote) { 184 + if ($is_html) { 185 + $style = array( 186 + 'padding: 4px 0;', 187 + ); 188 + 189 + $content = phutil_tag( 190 + 'div', 191 + array( 192 + 'style' => implode(' ', $style), 193 + ), 194 + $content); 195 + } 183 196 $header = $this->renderHeader($comment, $is_html, true); 184 197 } else { 185 198 $header = null; ··· 254 267 'padding: 4px 8px;', 255 268 'background: #F8F9FC;', 256 269 'border-left: 3px solid #a7b5bf;', 270 + 'margin: 4px 0 0;', 257 271 ); 258 272 259 273 $styles = implode(' ', $styles); ··· 268 282 269 283 private function getPatch( 270 284 DifferentialHunkParser $parser, 271 - DifferentialTransactionComment $comment) { 285 + DifferentialTransactionComment $comment, 286 + $is_html) { 272 287 273 288 $changeset = $this->getChangeset($comment->getChangesetID()); 274 - $hunks = $changeset->getHunks(); 275 - 276 289 $is_new = $comment->getIsNewFile(); 277 290 $start = $comment->getLineNumber(); 278 291 $length = $comment->getLineLength(); 279 292 280 - $diff = $parser->makeContextDiff($hunks, $is_new, $start, $length, 1); 293 + if (!$is_html) { 294 + $hunks = $changeset->getHunks(); 295 + $patch = $parser->makeContextDiff($hunks, $is_new, $start, $length, 1); 296 + $patch = phutil_split_lines($patch); 281 297 282 - return $diff; 298 + // Remove the "@@ -x,y +u,v @@" line. 299 + array_shift($patch); 300 + 301 + return implode('', $patch); 302 + } 303 + 304 + $viewer = $this->getViewer(); 305 + $engine = new PhabricatorMarkupEngine(); 306 + 307 + if ($is_new) { 308 + $offset_mode = 'new'; 309 + } else { 310 + $offset_mode = 'old'; 311 + } 312 + 313 + $parser = id(new DifferentialChangesetParser()) 314 + ->setUser($viewer) 315 + ->setChangeset($changeset) 316 + ->setOffsetMode($offset_mode) 317 + ->setMarkupEngine($engine); 318 + 319 + $parser->setRenderer(new DifferentialChangesetOneUpMailRenderer()); 320 + 321 + return $parser->render($start - 1, $length + 3, array()); 283 322 } 284 323 285 324 private function renderPatch( ··· 287 326 $patch, 288 327 $is_html) { 289 328 290 - $patch = phutil_split_lines($patch); 291 - 292 - // Remove the "@@ -x,y +u,v @@" line. 293 - array_shift($patch); 294 - 295 - $patch = implode('', $patch); 296 - 297 329 if ($is_html) { 298 330 $style = array( 299 331 'font: 11px/15px "Menlo", "Consolas", "Monaco", monospace;', 300 - 'padding: 0', 332 + 'padding: 4px 0;', 301 333 'margin: 0;', 302 334 ); 303 335 ··· 346 378 347 379 $header = "{$path}:{$range}"; 348 380 if ($is_html) { 349 - $header = phutil_tag('strong', array(), $header); 381 + $header = phutil_tag( 382 + 'span', 383 + array( 384 + 'style' => 'color: #000000', 385 + ), 386 + $header); 350 387 } 351 388 352 389 if ($with_author) { ··· 359 396 $byline = '@'.$author->getName(); 360 397 361 398 if ($is_html) { 362 - $byline = phutil_tag('strong', array(), $byline); 399 + $byline = phutil_tag( 400 + 'span', 401 + array( 402 + 'style' => 'color: #000000', 403 + ), 404 + $byline); 363 405 } 364 406 365 407 $header = pht('%s wrote in %s', $byline, $header); ··· 371 413 $header = phutil_tag( 372 414 'div', 373 415 array( 374 - 'style' => 'font-style: italic', 416 + 'style' => 'font-style: italic; color: #74777d', 375 417 ), 376 418 $header); 377 419 }
+42
src/applications/differential/parser/DifferentialChangesetParser.php
··· 50 50 private $showEditAndReplyLinks = true; 51 51 private $canMarkDone; 52 52 private $objectOwnerPHID; 53 + private $offsetMode; 53 54 54 55 private $rangeStart; 55 56 private $rangeEnd; ··· 136 137 137 138 public function getObjectOwnerPHID() { 138 139 return $this->objectOwnerPHID; 140 + } 141 + 142 + public function setOffsetMode($offset_mode) { 143 + $this->offsetMode = $offset_mode; 144 + return $this; 145 + } 146 + 147 + public function getOffsetMode() { 148 + return $this->offsetMode; 139 149 } 140 150 141 151 public static function getDefaultRendererForViewer(PhabricatorUser $viewer) { ··· 829 839 } 830 840 831 841 $this->tryCacheStuff(); 842 + 843 + // If we're rendering in an offset mode, treat the range numbers as line 844 + // numbers instead of rendering offsets. 845 + $offset_mode = $this->getOffsetMode(); 846 + if ($offset_mode) { 847 + if ($offset_mode == 'new') { 848 + $offset_map = $this->new; 849 + } else { 850 + $offset_map = $this->old; 851 + } 852 + 853 + $range_end = $this->getOffset($offset_map, $range_start + $range_len); 854 + $range_start = $this->getOffset($offset_map, $range_start); 855 + $range_len = $range_end - $range_start; 856 + } 857 + 832 858 $render_pch = $this->shouldRenderPropertyChangeHeader($this->changeset); 833 859 834 860 $rows = max( ··· 1632 1658 return $results; 1633 1659 } 1634 1660 1661 + private function getOffset(array $map, $line) { 1662 + if (!$map) { 1663 + return null; 1664 + } 1665 + 1666 + $line = (int)$line; 1667 + foreach ($map as $key => $spec) { 1668 + if ($spec && isset($spec['line'])) { 1669 + if ((int)$spec['line'] >= $line) { 1670 + return $key; 1671 + } 1672 + } 1673 + } 1674 + 1675 + return $key; 1676 + } 1635 1677 1636 1678 }
+98
src/applications/differential/render/DifferentialChangesetOneUpMailRenderer.php
··· 1 + <?php 2 + 3 + final class DifferentialChangesetOneUpMailRenderer 4 + extends DifferentialChangesetRenderer { 5 + 6 + public function isOneUpRenderer() { 7 + return true; 8 + } 9 + 10 + protected function getRendererTableClass() { 11 + return 'diff-1up-mail'; 12 + } 13 + 14 + public function getRendererKey() { 15 + return '1up-mail'; 16 + } 17 + 18 + protected function renderChangeTypeHeader($force) { 19 + return null; 20 + } 21 + 22 + protected function renderUndershieldHeader() { 23 + return null; 24 + } 25 + 26 + public function renderShield($message, $force = 'default') { 27 + return null; 28 + } 29 + 30 + protected function renderPropertyChangeHeader() { 31 + return null; 32 + } 33 + 34 + public function renderFileChange( 35 + $old_file = null, 36 + $new_file = null, 37 + $id = 0, 38 + $vs = 0) { 39 + return null; 40 + } 41 + 42 + public function renderTextChange( 43 + $range_start, 44 + $range_len, 45 + $rows) { 46 + 47 + $primitives = $this->buildPrimitives($range_start, $range_len); 48 + return $this->renderPrimitives($primitives, $rows); 49 + } 50 + 51 + protected function renderPrimitives(array $primitives, $rows) { 52 + $out = array(); 53 + foreach ($primitives as $k => $p) { 54 + $type = $p['type']; 55 + switch ($type) { 56 + case 'old': 57 + case 'new': 58 + case 'old-file': 59 + case 'new-file': 60 + $is_old = ($type == 'old' || $type == 'old-file'); 61 + 62 + if ($is_old) { 63 + if ($p['htype']) { 64 + $style = 'background: #ffd0d0;'; 65 + } else { 66 + $style = null; 67 + } 68 + } else { 69 + if ($p['htype']) { 70 + $style = 'background: #d0ffd0;'; 71 + } else { 72 + $style = null; 73 + } 74 + } 75 + 76 + $out[] = phutil_tag( 77 + 'div', 78 + array( 79 + 'style' => $style, 80 + ), 81 + $p['render']); 82 + break; 83 + default: 84 + break; 85 + } 86 + } 87 + 88 + $style_map = id(new PhabricatorDefaultSyntaxStyle()) 89 + ->getRemarkupStyleMap(); 90 + 91 + $styled_body = id(new PhutilPygmentizeParser()) 92 + ->setMap($style_map) 93 + ->parse((string)hsprintf('%s', $out)); 94 + 95 + return phutil_safe_html($styled_body); 96 + } 97 + 98 + }
+5 -2
src/applications/metamta/view/PhabricatorMetaMTAMailBody.php
··· 111 111 return $this; 112 112 } 113 113 114 - public function addPlaintextSection($header, $text) { 115 - $this->sections[] = $header."\n".$this->indent($text); 114 + public function addPlaintextSection($header, $text, $indent = true) { 115 + if ($indent) { 116 + $text = $this->indent($text); 117 + } 118 + $this->sections[] = $header."\n".$text; 116 119 return $this; 117 120 } 118 121