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

In Jupyter notebooks, read strings stored in the raw as either "string" or "list<string>" more consistently

Summary:
Ref PHI1835. Generally, Jupyter notebooks in the wild may store source and markdown content as either a single string or a list of strings.

Make the renderer read these formats more consistently. In particular, this fixes rendering of code blocks stored as a single string.

This also fixes an issue where cell labels were double-rendered in diff views.

Test Plan:
Created a notebook with a code block represented on disk as a single string, rendered a diff from it.

{F7696071}

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

+32 -48
+32 -48
src/applications/files/document/PhabricatorJupyterDocumentEngine.php
··· 85 85 if ($utype === $vtype) { 86 86 switch ($utype) { 87 87 case 'markdown': 88 - $usource = idx($ucell, 'source'); 89 - if (is_array($usource)) { 90 - $usource = implode('', $usource); 91 - } 92 - 93 - $vsource = idx($vcell, 'source'); 94 - if (is_array($vsource)) { 95 - $vsource = implode('', $vsource); 96 - } 88 + $usource = $this->readString($ucell, 'source'); 89 + $vsource = $this->readString($vcell, 'source'); 97 90 98 91 $diff = id(new PhutilProseDifferenceEngine()) 99 92 ->getDiff($usource, $vsource); ··· 117 110 $vsource = idx($vcell, 'raw'); 118 111 $udisplay = idx($ucell, 'display'); 119 112 $vdisplay = idx($vcell, 'display'); 120 - $ulabel = idx($ucell, 'label'); 121 - $vlabel = idx($vcell, 'label'); 122 113 123 114 $intraline_segments = ArcanistDiffUtils::generateIntralineDiff( 124 115 $usource, ··· 142 133 $vdisplay, 143 134 $v_segments); 144 135 145 - $u_content = $this->newCodeLineCell($ucell, $usource); 146 - $v_content = $this->newCodeLineCell($vcell, $vsource); 136 + list($u_label, $u_content) = $this->newCodeLineCell($ucell, $usource); 137 + list($v_label, $v_content) = $this->newCodeLineCell($vcell, $vsource); 147 138 148 139 $classes = array( 149 140 'jupyter-cell-flush', 150 141 ); 151 142 152 - $u_content = $this->newJupyterCell($ulabel, $u_content, $classes); 153 - $v_content = $this->newJupyterCell($vlabel, $v_content, $classes); 143 + $u_content = $this->newJupyterCell($u_label, $u_content, $classes); 144 + $v_content = $this->newJupyterCell($v_label, $v_content, $classes); 154 145 155 146 $u_content = $this->newCellContainer($u_content); 156 147 $v_content = $this->newCellContainer($v_content); ··· 259 250 $hash_input = $cell['raw']; 260 251 break; 261 252 case 'markdown': 262 - $hash_input = $cell['source']; 263 - if (is_array($hash_input)) { 264 - $hash_input = implode('', $cell['source']); 265 - } 253 + $hash_input = $this->readString($cell, 'source'); 266 254 break; 267 255 default: 268 256 $hash_input = serialize($cell); ··· 334 322 'be rendered as a Jupyter notebook.')); 335 323 } 336 324 337 - 338 325 $nbformat = idx($data, 'nbformat'); 339 326 if (!strlen($nbformat)) { 340 327 throw new Exception( ··· 376 363 foreach ($cells as $cell) { 377 364 $cell_type = idx($cell, 'cell_type'); 378 365 if ($cell_type === 'markdown') { 379 - $source = $cell['source']; 380 - if (is_array($source)) { 381 - $source = implode('', $source); 382 - } 366 + $source = $this->readString($cell, 'source'); 383 367 384 368 // Attempt to split contiguous blocks of markdown into smaller 385 369 // pieces. ··· 404 388 405 389 $label = $this->newCellLabel($cell); 406 390 407 - $lines = idx($cell, 'source'); 408 - if (!is_array($lines)) { 409 - $lines = array(); 410 - } 411 - 391 + $lines = $this->readStringList($cell, 'source'); 412 392 $content = $this->highlightLines($lines); 413 393 414 394 $count = count($lines); ··· 526 506 } 527 507 528 508 private function newMarkdownCell(array $cell) { 529 - $content = idx($cell, 'source'); 530 - if (!is_array($content)) { 531 - $content = array(); 532 - } 509 + $content = $this->readStringList($cell, 'source'); 533 510 534 511 // TODO: This should ideally highlight as Markdown, but the "md" 535 512 // highlighter in Pygments is painfully slow and not terribly useful. ··· 549 526 private function newCodeCell(array $cell) { 550 527 $label = $this->newCellLabel($cell); 551 528 552 - $content = idx($cell, 'source'); 553 - if (!is_array($content)) { 554 - $content = array(); 555 - } 556 - 529 + $content = $this->readStringList($cell, 'source'); 557 530 $content = $this->highlightLines($content); 558 531 559 532 $outputs = array(); ··· 660 633 continue; 661 634 } 662 635 663 - $raw_data = $data[$image_format]; 664 - if (!is_array($raw_data)) { 665 - $raw_data = array($raw_data); 666 - } 667 - $raw_data = implode('', $raw_data); 636 + $raw_data = $this->readString($data, $image_format); 668 637 669 638 $content = phutil_tag( 670 639 'img', ··· 695 664 break; 696 665 case 'stream': 697 666 default: 698 - $content = idx($output, 'text'); 699 - if (!is_array($content)) { 700 - $content = array(); 701 - } 702 - $content = implode('', $content); 667 + $content = $this->readString($output, 'text'); 703 668 break; 704 669 } 705 670 ··· 759 724 760 725 public function shouldSuggestEngine(PhabricatorDocumentRef $ref) { 761 726 return true; 727 + } 728 + 729 + private function readString(array $src, $key) { 730 + $list = $this->readStringList($src, $key); 731 + return implode('', $list); 732 + } 733 + 734 + private function readStringList(array $src, $key) { 735 + $list = idx($src, $key); 736 + 737 + if (is_array($list)) { 738 + $list = $list; 739 + } else if (is_string($list)) { 740 + $list = array($list); 741 + } else { 742 + $list = array(); 743 + } 744 + 745 + return $list; 762 746 } 763 747 764 748 }