1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-27 15:08:20 +01:00

Line highlighting for pastes

Summary:
Add the ability to select singular and multiple lines in paste to highlight.
This is related to T3627

Test Plan: Create a paste, select one or more lines.

Reviewers: epriestley, tberman

Reviewed By: epriestley

CC: aran, chad

Maniphest Tasks: T3627

Differential Revision: https://secure.phabricator.com/D6668
This commit is contained in:
Korvin Szanto 2013-08-04 12:11:10 -07:00 committed by epriestley
parent a5f790e192
commit 40cf765ca2
9 changed files with 98 additions and 48 deletions

View file

@ -1140,7 +1140,7 @@ celerity_register_resource_map(array(
),
'diffusion-source-css' =>
array(
'uri' => '/res/e76bcd50/rsrc/css/application/diffusion/diffusion-source.css',
'uri' => '/res/162c8794/rsrc/css/application/diffusion/diffusion-source.css',
'type' => 'css',
'requires' =>
array(
@ -1667,19 +1667,6 @@ celerity_register_resource_map(array(
),
'disk' => '/rsrc/js/application/diffusion/behavior-jump-to.js',
),
'javelin-behavior-diffusion-line-linker' =>
array(
'uri' => '/res/12866f13/rsrc/js/application/diffusion/behavior-line-linker.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-history',
),
'disk' => '/rsrc/js/application/diffusion/behavior-line-linker.js',
),
'javelin-behavior-diffusion-pull-lastmodified' =>
array(
'uri' => '/res/29fe2790/rsrc/js/application/diffusion/behavior-pull-lastmodified.js',
@ -2067,6 +2054,19 @@ celerity_register_resource_map(array(
),
'disk' => '/rsrc/js/core/behavior-keyboard-shortcuts.js',
),
'javelin-behavior-phabricator-line-linker' =>
array(
'uri' => '/res/1cefdb6a/rsrc/js/core/behavior-line-linker.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-history',
),
'disk' => '/rsrc/js/core/behavior-line-linker.js',
),
'javelin-behavior-phabricator-nav' =>
array(
'uri' => '/res/afabcf16/rsrc/js/core/behavior-phabricator-nav.js',
@ -2249,7 +2249,7 @@ celerity_register_resource_map(array(
),
'javelin-behavior-pholio-mock-view' =>
array(
'uri' => '/res/3ff82e28/rsrc/js/application/pholio/behavior-pholio-mock-view.js',
'uri' => '/res/f9588dcf/rsrc/js/application/pholio/behavior-pholio-mock-view.js',
'type' => 'js',
'requires' =>
array(
@ -3498,7 +3498,7 @@ celerity_register_resource_map(array(
),
'phabricator-source-code-view-css' =>
array(
'uri' => '/res/979d5280/rsrc/css/layout/phabricator-source-code-view.css',
'uri' => '/res/70bcbea4/rsrc/css/layout/phabricator-source-code-view.css',
'type' => 'css',
'requires' =>
array(

View file

@ -241,7 +241,7 @@ final class DiffusionBrowseFileController extends DiffusionController {
'table',
array(
'class' => "diffusion-source remarkup-code PhabricatorMonospaced",
'sigil' => 'diffusion-source',
'sigil' => 'phabricator-source',
),
$rows);
@ -728,12 +728,12 @@ final class DiffusionBrowseFileController extends DiffusionController {
'th',
array(
'class' => 'diffusion-line-link',
'sigil' => 'diffusion-line-link',
'sigil' => 'phabricator-source-line',
'style' => $style,
),
$line_link);
Javelin::initBehavior('diffusion-line-linker');
Javelin::initBehavior('phabricator-line-linker');
if ($line['target']) {
Javelin::initBehavior(
@ -768,7 +768,9 @@ final class DiffusionBrowseFileController extends DiffusionController {
$rows[] = phutil_tag(
'tr',
array(
'class' => ($line['highlighted'] ? 'highlighted' : null),
'class' => ($line['highlighted'] ?
'phabricator-source-highlight' :
null),
),
$blame);

View file

@ -33,12 +33,13 @@ final class PhabricatorApplicationPaste extends PhabricatorApplication {
public function getRoutes() {
return array(
'/P(?P<id>[1-9]\d*)' => 'PhabricatorPasteViewController',
'/P(?P<id>[1-9]\d*)(?:\$(?P<lines>\d+(?:-\d+)?))?'
=> 'PhabricatorPasteViewController',
'/paste/' => array(
'(query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorPasteListController',
'create/' => 'PhabricatorPasteEditController',
'edit/(?P<id>[1-9]\d*)/' => 'PhabricatorPasteEditController',
'comment/(?P<id>[1-9]\d*)/' => 'PhabricatorPasteCommentController',
'comment/(?P<id>[1-9]\d*)/' => 'PhabricatorPasteCommentController',
),
);
}

View file

@ -42,13 +42,16 @@ abstract class PhabricatorPasteController extends PhabricatorController {
public function buildSourceCodeView(
PhabricatorPaste $paste,
$max_lines = null) {
$max_lines = null,
$highlights = array()) {
$lines = phutil_split_lines($paste->getContent());
return id(new PhabricatorSourceCodeView())
->setLimit($max_lines)
->setLines($lines);
->setLines($lines)
->setHighlights($highlights)
->setURI(new PhutilURI($paste->getURI()));
}
}

View file

@ -6,6 +6,7 @@
final class PhabricatorPasteViewController extends PhabricatorPasteController {
private $id;
private $highlightMap;
public function shouldAllowPublic() {
return true;
@ -13,6 +14,21 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController {
public function willProcessRequest(array $data) {
$this->id = $data['id'];
$raw_lines = idx($data, 'lines');
$map = array();
if ($raw_lines) {
$lines = explode('-', $raw_lines);
$first = idx($lines, 0, 0);
$last = idx($lines, 1);
if ($last) {
$min = min($first, $last);
$max = max($first, $last);
$map = array_fuse(range($min, $max));
} else {
$map[$first] = $first;
}
}
$this->highlightMap = $map;
}
public function processRequest() {
@ -52,7 +68,10 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController {
$header = $this->buildHeaderView($paste);
$actions = $this->buildActionView($user, $paste, $file);
$properties = $this->buildPropertyView($paste, $fork_phids);
$source_code = $this->buildSourceCodeView($paste);
$source_code = $this->buildSourceCodeView(
$paste,
null,
$this->highlightMap);
$crumbs = $this->buildApplicationCrumbs($this->buildSideNavView())
->setActionList($actions)

View file

@ -4,6 +4,7 @@ final class PhabricatorSourceCodeView extends AphrontView {
private $lines;
private $limit;
private $uri;
private $highlights = array();
public function setLimit($limit) {
@ -16,8 +17,13 @@ final class PhabricatorSourceCodeView extends AphrontView {
return $this;
}
public function setHighlights(array $highlights) {
$this->highlights = array_fuse($highlights);
public function setURI(PhutilURI $uri) {
$this->uri = $uri;
return $this;
}
public function setHighlights(array $array) {
$this->highlights = array_fuse($array);
return $this;
}
@ -26,10 +32,12 @@ final class PhabricatorSourceCodeView extends AphrontView {
require_celerity_resource('syntax-highlighting-css');
Javelin::initBehavior('phabricator-oncopy', array());
Javelin::initBehavior('phabricator-line-linker');
$line_number = 1;
$rows = array();
foreach ($this->lines as $line) {
$hit_limit = $this->limit &&
($line_number == $this->limit) &&
@ -53,16 +61,33 @@ final class PhabricatorSourceCodeView extends AphrontView {
$row_attributes['class'] = 'phabricator-source-highlight';
}
// TODO: Provide nice links.
$line_uri = $this->uri . "$" . $line_number;
$line_href = (string) new PhutilURI($line_uri);
$tag_number = javelin_tag(
'a',
array(
'href' => $line_href
),
$line_number);
$rows[] = phutil_tag(
'tr',
$row_attributes,
hsprintf(
'<th class="phabricator-source-line">%s</th>'.
'<td class="phabricator-source-code">%s</td>',
$content_number,
$content_line));
array(
javelin_tag(
'th',
array(
'class' => 'phabricator-source-line',
'sigil' => 'phabricator-source-line'
),
$tag_number),
phutil_tag(
'td',
array(
'class' => 'phabricator-source-code'
),
$content_line)));
if ($hit_limit) {
break;
@ -81,10 +106,11 @@ final class PhabricatorSourceCodeView extends AphrontView {
array(
'class' => 'phabricator-source-code-container',
),
phutil_tag(
javelin_tag(
'table',
array(
'class' => implode(' ', $classes),
'sigil' => 'phabricator-source'
),
phutil_implode_html('', $rows)));
}

View file

@ -9,7 +9,7 @@
font-size: 10px;
}
.diffusion-source tr.highlighted {
.diffusion-source tr.phabricator-source-highlight {
background: #ffff00;
}

View file

@ -10,6 +10,7 @@
.phabricator-source-code {
white-space: pre-wrap;
padding: 2px 8px 1px;
width: 100%;
}
.phabricator-source-line {

View file

@ -1,44 +1,43 @@
/**
* @provides javelin-behavior-diffusion-line-linker
* @provides javelin-behavior-phabricator-line-linker
* @requires javelin-behavior
* javelin-stratcom
* javelin-dom
* javelin-history
*/
JX.behavior('diffusion-line-linker', function() {
JX.behavior('phabricator-line-linker', function() {
var origin = null;
var target = null;
var root = null;
function getRowNumber(tr) {
var th = JX.DOM.find(tr, 'th', 'diffusion-line-link');
var th = JX.DOM.find(tr, 'th', 'phabricator-source-line');
return +(th.textContent || th.innerText);
}
JX.Stratcom.listen(
'mousedown',
'diffusion-line-link',
'phabricator-source-line',
function(e) {
if (e.isRightButton()) {
if (!e.isNormalMouseEvent()) {
return;
}
origin = e.getNode('tag:tr');
target = origin;
root = e.getNode('diffusion-source');
root = e.getNode('phabricator-source');
e.kill();
});
JX.Stratcom.listen(
'click',
'diffusion-line-link',
'phabricator-source-line',
function(e) {
e.kill();
});
var highlight = function(e) {
if (!origin || e.getNode('diffusion-source') !== root) {
if (!origin || e.getNode('phabricator-source') !== root) {
return;
}
target = e.getNode('tag:tr');
@ -51,14 +50,14 @@ JX.behavior('diffusion-line-linker', function() {
highlighting = true;
source = trs[i];
}
JX.DOM.alterClass(trs[i], 'highlighted', highlighting);
JX.DOM.alterClass(trs[i], 'phabricator-source-highlight', highlighting);
if (trs[i] === (source === origin ? target : origin)) {
highlighting = false;
}
}
};
JX.Stratcom.listen('mouseover', 'diffusion-source', highlight);
JX.Stratcom.listen('mouseover', 'phabricator-source', highlight);
JX.Stratcom.listen(
'mouseup',
@ -73,10 +72,9 @@ JX.behavior('diffusion-line-linker', function() {
var o = getRowNumber(origin);
var t = getRowNumber(target);
var lines = (o == t ? o : Math.min(o, t) + '-' + Math.max(o, t));
var th = JX.DOM.find(origin, 'th', 'diffusion-line-link');
var th = JX.DOM.find(origin, 'th', 'phabricator-source-line');
var uri = JX.DOM.find(th, 'a').href;
uri = uri.replace(/(.*\$)\d+/, '$1' + lines);
origin = null;
target = null;
e.kill();