Summary:
Depends on D20843. Ref T13425. Add very basic support for "Show Hidden Context", in the form of folding it behind an unclickable shield. This isn't ideal, but should be better than nothing.
Prepare for "intraline" diffs on content blocks.
Fix newline handling in Markdown sections in Jupyter notebooks.
Remove the word "visibile" from the codebase.
Test Plan: {F6898192}
Maniphest Tasks: T13425
Differential Revision: https://secure.phabricator.com/D20844
176 lines
3.8 KiB
PHP
176 lines
3.8 KiB
PHP
<?php
|
|
|
|
final class PhabricatorDocumentEngineBlocks
|
|
extends Phobject {
|
|
|
|
private $lists = array();
|
|
private $messages = array();
|
|
|
|
public function addMessage($message) {
|
|
$this->messages[] = $message;
|
|
return $this;
|
|
}
|
|
|
|
public function getMessages() {
|
|
return $this->messages;
|
|
}
|
|
|
|
public function addBlockList(PhabricatorDocumentRef $ref, array $blocks) {
|
|
assert_instances_of($blocks, 'PhabricatorDocumentEngineBlock');
|
|
|
|
$this->lists[] = array(
|
|
'ref' => $ref,
|
|
'blocks' => array_values($blocks),
|
|
);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function newTwoUpLayout() {
|
|
$rows = array();
|
|
$lists = $this->lists;
|
|
|
|
if (count($lists) != 2) {
|
|
return array();
|
|
}
|
|
|
|
$specs = array();
|
|
foreach ($this->lists as $list) {
|
|
$specs[] = $this->newDiffSpec($list['blocks']);
|
|
}
|
|
|
|
$old_map = $specs[0]['map'];
|
|
$new_map = $specs[1]['map'];
|
|
|
|
$old_list = $specs[0]['list'];
|
|
$new_list = $specs[1]['list'];
|
|
|
|
$changeset = id(new PhabricatorDifferenceEngine())
|
|
->generateChangesetFromFileContent($old_list, $new_list);
|
|
|
|
$hunk_parser = id(new DifferentialHunkParser())
|
|
->parseHunksForLineData($changeset->getHunks())
|
|
->reparseHunksForSpecialAttributes();
|
|
|
|
$hunk_parser->generateVisibleLinesMask(2);
|
|
$mask = $hunk_parser->getVisibleLinesMask();
|
|
|
|
$old_lines = $hunk_parser->getOldLines();
|
|
$new_lines = $hunk_parser->getNewLines();
|
|
|
|
$rows = array();
|
|
|
|
$count = count($old_lines);
|
|
for ($ii = 0; $ii < $count; $ii++) {
|
|
$old_line = idx($old_lines, $ii);
|
|
$new_line = idx($new_lines, $ii);
|
|
|
|
$is_visible = !empty($mask[$ii + 1]);
|
|
|
|
// TODO: There's currently a bug where one-line files get incorrectly
|
|
// masked. This causes images to completely fail to render. Just ignore
|
|
// the mask if it came back empty.
|
|
if (!$mask) {
|
|
$is_visible = true;
|
|
}
|
|
|
|
if ($old_line) {
|
|
$old_hash = rtrim($old_line['text'], "\n");
|
|
if (!strlen($old_hash)) {
|
|
// This can happen when one of the sources has no blocks.
|
|
$old_block = null;
|
|
} else {
|
|
$old_block = array_shift($old_map[$old_hash]);
|
|
$old_block
|
|
->setDifferenceType($old_line['type'])
|
|
->setIsVisible($is_visible);
|
|
}
|
|
} else {
|
|
$old_block = null;
|
|
}
|
|
|
|
if ($new_line) {
|
|
$new_hash = rtrim($new_line['text'], "\n");
|
|
if (!strlen($new_hash)) {
|
|
$new_block = null;
|
|
} else {
|
|
$new_block = array_shift($new_map[$new_hash]);
|
|
$new_block
|
|
->setDifferenceType($new_line['type'])
|
|
->setIsVisible($is_visible);
|
|
}
|
|
} else {
|
|
$new_block = null;
|
|
}
|
|
|
|
// If both lists are empty, we may generate a row which has two empty
|
|
// blocks.
|
|
if (!$old_block && !$new_block) {
|
|
continue;
|
|
}
|
|
|
|
$rows[] = array(
|
|
$old_block,
|
|
$new_block,
|
|
);
|
|
}
|
|
|
|
return $rows;
|
|
}
|
|
|
|
public function newOneUpLayout() {
|
|
$rows = array();
|
|
$lists = $this->lists;
|
|
|
|
$idx = 0;
|
|
while (true) {
|
|
$found_any = false;
|
|
|
|
$row = array();
|
|
foreach ($lists as $list) {
|
|
$blocks = $list['blocks'];
|
|
$cell = idx($blocks, $idx);
|
|
|
|
if ($cell !== null) {
|
|
$found_any = true;
|
|
}
|
|
|
|
if ($cell) {
|
|
$rows[] = $cell;
|
|
}
|
|
}
|
|
|
|
if (!$found_any) {
|
|
break;
|
|
}
|
|
|
|
$idx++;
|
|
}
|
|
|
|
return $rows;
|
|
}
|
|
|
|
|
|
private function newDiffSpec(array $blocks) {
|
|
$map = array();
|
|
$list = array();
|
|
|
|
foreach ($blocks as $block) {
|
|
$hash = $block->getDifferenceHash();
|
|
|
|
if (!isset($map[$hash])) {
|
|
$map[$hash] = array();
|
|
}
|
|
$map[$hash][] = $block;
|
|
|
|
$list[] = $hash;
|
|
}
|
|
|
|
return array(
|
|
'map' => $map,
|
|
'list' => implode("\n", $list)."\n",
|
|
);
|
|
}
|
|
|
|
}
|