1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 00:42:41 +01:00

Render remarkup in feed in a mostly reasonable way

Summary:
Fixes T4057. This sort of sidesteps the trickiest (but very rare) case of things like embedded slowvotes. We might be able to refine that later.

In the common bad case (macros, large images) it gets reasonable results by using `overflow: hidden` with `max-height`.

We use `PhabriatorMarkupEngine::summarize()` to try to just render the first paragraph.

Test Plan: {F195093}

Reviewers: chad, btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T4057

Differential Revision: https://secure.phabricator.com/D10355
This commit is contained in:
epriestley 2014-08-26 14:36:35 -07:00
parent d13d6963dd
commit 69b0ac724a
7 changed files with 141 additions and 9 deletions

View file

@ -125,7 +125,7 @@ return array(
'rsrc/css/phui/phui-box.css' => '7b3a2eed',
'rsrc/css/phui/phui-button.css' => 'c7412aa1',
'rsrc/css/phui/phui-document.css' => 'a5615198',
'rsrc/css/phui/phui-feed-story.css' => 'e2c9bc83',
'rsrc/css/phui/phui-feed-story.css' => '55dc7732',
'rsrc/css/phui/phui-fontkit.css' => 'fff25cfa',
'rsrc/css/phui/phui-form-view.css' => 'a2d72756',
'rsrc/css/phui/phui-form.css' => 'b78ec020',
@ -771,7 +771,7 @@ return array(
'phui-calendar-list-css' => 'c1d0ca59',
'phui-calendar-month-css' => 'a92e47d2',
'phui-document-view-css' => 'a5615198',
'phui-feed-story-css' => 'e2c9bc83',
'phui-feed-story-css' => '55dc7732',
'phui-font-icon-base-css' => 'eb84f033',
'phui-fontkit-css' => 'fff25cfa',
'phui-form-css' => 'b78ec020',

View file

@ -4376,7 +4376,10 @@ phutil_register_library_map(array(
'PhabricatorFeedPublicStreamController' => 'PhabricatorFeedController',
'PhabricatorFeedQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorFeedSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorFeedStory' => 'PhabricatorPolicyInterface',
'PhabricatorFeedStory' => array(
'PhabricatorPolicyInterface',
'PhabricatorMarkupInterface',
),
'PhabricatorFeedStoryAggregate' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryAudit' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryCommit' => 'PhabricatorFeedStory',

View file

@ -8,7 +8,10 @@
* @task load Loading Stories
* @task policy Policy Implementation
*/
abstract class PhabricatorFeedStory implements PhabricatorPolicyInterface {
abstract class PhabricatorFeedStory
implements
PhabricatorPolicyInterface,
PhabricatorMarkupInterface {
private $data;
private $hasViewed;
@ -19,6 +22,7 @@ abstract class PhabricatorFeedStory implements PhabricatorPolicyInterface {
private $handles = array();
private $objects = array();
private $projectPHIDs = array();
private $markupFieldOutput = array();
/* -( Loading Stories )---------------------------------------------------- */
@ -150,9 +154,46 @@ abstract class PhabricatorFeedStory implements PhabricatorPolicyInterface {
$stories[$key]->setHandles($story_handles);
}
// Load and process story markup blocks.
$engine = new PhabricatorMarkupEngine();
$engine->setViewer($viewer);
foreach ($stories as $story) {
foreach ($story->getFieldStoryMarkupFields() as $field) {
$engine->addObject($story, $field);
}
}
$engine->process();
foreach ($stories as $story) {
foreach ($story->getFieldStoryMarkupFields() as $field) {
$story->setMarkupFieldOutput(
$field,
$engine->getOutput($story, $field));
}
}
return $stories;
}
public function setMarkupFieldOutput($field, $output) {
$this->markupFieldOutput[$field] = $output;
return $this;
}
public function getMarkupFieldOutput($field) {
if (!array_key_exists($field, $this->markupFieldOutput)) {
throw new Exception(
pht(
'Trying to retrieve markup field key "%s", but this feed story '.
'did not request it be rendered.',
$field));
}
return $this->markupFieldOutput[$field];
}
public function setHovercard($hover) {
$this->hovercard = $hover;
return $this;
@ -374,6 +415,10 @@ abstract class PhabricatorFeedStory implements PhabricatorPolicyInterface {
return $this->projectPHIDs;
}
public function getFieldStoryMarkupFields() {
return array();
}
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
@ -425,4 +470,31 @@ abstract class PhabricatorFeedStory implements PhabricatorPolicyInterface {
return null;
}
/* -( PhabricatorMarkupInterface Implementation )--------------------------- */
public function getMarkupFieldKey($field) {
return 'feed:'.$this->getChronologicalKey().':'.$field;
}
public function newMarkupEngine($field) {
return PhabricatorMarkupEngine::newMarkupEngine(array());
}
public function getMarkupText($field) {
throw new PhutilMethodNotImplementedException();
}
public function didMarkupText(
$field,
$output,
PhutilMarkupEngine $engine) {
return $output;
}
public function shouldUseMarkupCache($field) {
return true;
}
}

View file

@ -34,6 +34,35 @@ class PhabricatorApplicationTransactionFeedStory
return $this->getObject($this->getPrimaryTransactionPHID());
}
public function getFieldStoryMarkupFields() {
$xaction_phids = $this->getValue('transactionPHIDs');
$fields = array();
foreach ($xaction_phids as $xaction_phid) {
$xaction = $this->getObject($xaction_phid);
foreach ($xaction->getMarkupFieldsForFeed($this) as $field) {
$fields[] = $field;
}
}
return $fields;
}
public function getMarkupText($field) {
$xaction_phids = $this->getValue('transactionPHIDs');
foreach ($xaction_phids as $xaction_phid) {
$xaction = $this->getObject($xaction_phid);
foreach ($xaction->getMarkupFieldsForFeed($this) as $xaction_field) {
if ($xaction_field == $field) {
return $xaction->getMarkupTextForFeed($this, $field);
}
}
}
return null;
}
public function renderView() {
$view = $this->newStoryView();

View file

@ -788,6 +788,31 @@ abstract class PhabricatorApplicationTransaction
return $this->getTitle();
}
public function getMarkupFieldsForFeed(PhabricatorFeedStory $story) {
$fields = array();
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
$text = $this->getComment()->getContent();
if (strlen($text)) {
$fields[] = 'comment/'.$this->getID();
}
break;
}
return $fields;
}
public function getMarkupTextForFeed(PhabricatorFeedStory $story, $field) {
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
$text = $this->getComment()->getContent();
return PhabricatorMarkupEngine::summarize($text);
}
return null;
}
public function getBodyForFeed(PhabricatorFeedStory $story) {
$old = $this->getOldValue();
$new = $this->getNewValue();
@ -797,10 +822,12 @@ abstract class PhabricatorApplicationTransaction
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
$text = $this->getComment()->getContent();
$body = phutil_escape_html_newlines(
phutil_utf8_shorten($text, 128));
if (strlen($text)) {
$body = $story->getMarkupFieldOutput('comment/'.$this->getID());
}
break;
}
return $body;
}

View file

@ -8,7 +8,7 @@ final class PhabricatorNavigationRemarkupRule extends PhutilRemarkupRule {
public function apply($text) {
return preg_replace_callback(
'@{nav\b((?:[^}\\\\]+|\\\\.)+)}$@m',
'@{nav\b((?:[^}\\\\]+|\\\\.)*)}@m',
array($this, 'markupNavigation'),
$text);
}
@ -99,5 +99,4 @@ final class PhabricatorNavigationRemarkupRule extends PhutilRemarkupRule {
return $this->getEngine()->storeText($out);
}
}

View file

@ -28,9 +28,11 @@
}
.phui-feed-story-body {
padding: 0 8px 8px;
margin: 0 8px 8px;
color: {$darkgreytext};
word-break: break-word;
max-height: 300px;
overflow: hidden;
}
.phui-feed-story-foot {