diff --git a/resources/celerity/map.php b/resources/celerity/map.php index f88fc5857e..5a7f117e26 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -13,7 +13,7 @@ return array( 'core.pkg.js' => '4c79d74f', 'darkconsole.pkg.js' => '1f9a31bc', 'differential.pkg.css' => '45951e9e', - 'differential.pkg.js' => 'c1af2de3', + 'differential.pkg.js' => 'b69ae3ec', 'diffusion.pkg.css' => 'a2d17c7d', 'diffusion.pkg.js' => '6134c5a1', 'favicon.ico' => '30672e08', @@ -443,7 +443,7 @@ return array( 'rsrc/js/application/releeph/releeph-preview-branch.js' => 'b2b4fbaf', 'rsrc/js/application/releeph/releeph-request-state-change.js' => 'a0b57eb8', 'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'de2e896f', - 'rsrc/js/application/repository/repository-crossreference.js' => 'c5627622', + 'rsrc/js/application/repository/repository-crossreference.js' => 'fc2d8ffd', 'rsrc/js/application/search/behavior-reorder-profile-menu-items.js' => 'e2e0a072', 'rsrc/js/application/search/behavior-reorder-queries.js' => 'e9581f08', 'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => '887ad43f', @@ -692,7 +692,7 @@ return array( 'javelin-behavior-reorder-applications' => '76b9fc3e', 'javelin-behavior-reorder-columns' => 'e1d25dfb', 'javelin-behavior-reorder-profile-menu-items' => 'e2e0a072', - 'javelin-behavior-repository-crossreference' => 'c5627622', + 'javelin-behavior-repository-crossreference' => 'fc2d8ffd', 'javelin-behavior-scrollbar' => '834a1173', 'javelin-behavior-search-reorder-queries' => 'e9581f08', 'javelin-behavior-select-content' => 'bf5374ef', @@ -1922,12 +1922,6 @@ return array( 'javelin-stratcom', 'phabricator-tooltip', ), - 'c5627622' => array( - 'javelin-behavior', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-uri', - ), 'c587b80f' => array( 'javelin-install', ), @@ -2165,6 +2159,12 @@ return array( 'javelin-install', 'javelin-dom', ), + 'fc2d8ffd' => array( + 'javelin-behavior', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-uri', + ), 'fc91ab6c' => array( 'javelin-behavior', 'javelin-dom', diff --git a/src/applications/diffusion/controller/DiffusionSymbolController.php b/src/applications/diffusion/controller/DiffusionSymbolController.php index 20c25dad82..b855f967db 100644 --- a/src/applications/diffusion/controller/DiffusionSymbolController.php +++ b/src/applications/diffusion/controller/DiffusionSymbolController.php @@ -69,6 +69,13 @@ final class DiffusionSymbolController extends DiffusionController { $external_query->withLines(array($request->getInt('line'))); } + if ($request->getInt('char')) { + $external_query->withCharacterPositions( + array( + $request->getInt('char'), + )); + } + if ($repos) { $external_query->withRepositories($repos); } diff --git a/src/applications/diffusion/symbol/DiffusionExternalSymbolQuery.php b/src/applications/diffusion/symbol/DiffusionExternalSymbolQuery.php index f1f916d9d4..719496dcdf 100644 --- a/src/applications/diffusion/symbol/DiffusionExternalSymbolQuery.php +++ b/src/applications/diffusion/symbol/DiffusionExternalSymbolQuery.php @@ -9,6 +9,7 @@ final class DiffusionExternalSymbolQuery extends Phobject { private $paths = array(); private $lines = array(); private $repositories = array(); + private $characterPositions = array(); public function withLanguages(array $languages) { $this->languages = $languages; @@ -40,6 +41,11 @@ final class DiffusionExternalSymbolQuery extends Phobject { return $this; } + public function withCharacterPositions(array $positions) { + $this->characterPositions = $positions; + return $this; + } + public function withRepositories(array $repositories) { assert_instances_of($repositories, 'PhabricatorRepository'); $this->repositories = $repositories; @@ -74,6 +80,10 @@ final class DiffusionExternalSymbolQuery extends Phobject { return $this->repositories; } + public function getCharacterPositions() { + return $this->characterPositions; + } + public function matchesAnyLanguage(array $languages) { return (!$this->languages) || array_intersect($languages, $this->languages); } diff --git a/webroot/rsrc/js/application/repository/repository-crossreference.js b/webroot/rsrc/js/application/repository/repository-crossreference.js index 882ccd2960..7a7a4d77b8 100644 --- a/webroot/rsrc/js/application/repository/repository-crossreference.js +++ b/webroot/rsrc/js/application/repository/repository-crossreference.js @@ -28,8 +28,8 @@ JX.behavior('repository-crossreference', function(config, statics) { nf : 'function', na : null, nb : 'builtin', - n : null, - }; + n : null + }; function link(element, lang) { JX.DOM.alterClass(element, 'repository-crossreference', true); @@ -58,8 +58,15 @@ JX.behavior('repository-crossreference', function(config, statics) { // Continue if we're not inside an inline comment. } + // If only part of the symbol was edited, the symbol name itself will + // have another "" inside of it which highlights only the + // edited part. Skip over it. + if (JX.DOM.isNode(target, 'span') && (target.className === 'bright')) { + target = target.parentNode; + } + if (e.getType() === 'mouseover') { - while (target !== document.body) { + while (target && target !== document.body) { if (JX.DOM.isNode(target, 'span') && (target.className in class_map)) { highlighted = target; @@ -107,6 +114,11 @@ JX.behavior('repository-crossreference', function(config, statics) { query.path = path; } + var char = getChar(target); + if (char !== null) { + query.char = char; + } + var uri = JX.$U('/diffusion/symbol/' + symbol + '/'); uri.addQueryParams(query); window.open(uri); @@ -173,6 +185,32 @@ JX.behavior('repository-crossreference', function(config, statics) { return JX.Stratcom.getData(changeset).path; } + function getChar(target) { + var cell = JX.DOM.findAbove(target, 'td'); + if (!cell) { + return null; + } + + var char = 1; + for (var ii = 0; ii < cell.childNodes.length; ii++) { + var node = cell.childNodes[ii]; + + if (node === target) { + return char; + } + + var content = '' + node.textContent; + + // Strip off any ZWS characters. These are marker characters used to + // improve copy/paste behavior. + content = content.replace(/\u200B/g, ''); + + char += content.length; + } + + return null; + } + if (config.container) { link(JX.$(config.container), config.lang); } else if (config.section) {