2011-09-06 11:35:14 -07:00
|
|
|
/**
|
|
|
|
|
* @provides javelin-behavior-repository-crossreference
|
|
|
|
|
* @requires javelin-behavior
|
|
|
|
|
* javelin-dom
|
2012-09-17 14:50:49 -07:00
|
|
|
* javelin-stratcom
|
2011-09-06 11:35:14 -07:00
|
|
|
* javelin-uri
|
|
|
|
|
*/
|
|
|
|
|
|
2015-05-28 15:32:58 -07:00
|
|
|
JX.behavior('repository-crossreference', function(config, statics) {
|
2011-09-06 11:35:14 -07:00
|
|
|
|
2015-05-28 15:32:58 -07:00
|
|
|
var highlighted;
|
|
|
|
|
var linked = [];
|
|
|
|
|
|
2018-04-08 09:10:03 -07:00
|
|
|
function isMacOS() {
|
|
|
|
|
return (navigator.platform.indexOf('Mac') > -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isHighlightModifierKey(e) {
|
|
|
|
|
var signal_key;
|
|
|
|
|
if (isMacOS()) {
|
|
|
|
|
// On macOS, use the "Command" key.
|
|
|
|
|
signal_key = 91;
|
|
|
|
|
} else {
|
|
|
|
|
// On other platforms, use the "Control" key.
|
|
|
|
|
signal_key = 17;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (e.getRawEvent().keyCode === signal_key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function hasHighlightModifierKey(e) {
|
|
|
|
|
if (isMacOS()) {
|
|
|
|
|
return e.getRawEvent().metaKey;
|
|
|
|
|
} else {
|
|
|
|
|
return e.getRawEvent().ctrlKey;
|
|
|
|
|
}
|
2015-05-28 15:32:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var classHighlight = 'crossreference-item';
|
|
|
|
|
var classMouseCursor = 'crossreference-cursor';
|
|
|
|
|
|
|
|
|
|
// TODO maybe move the dictionary part of this list to the server?
|
|
|
|
|
var class_map = {
|
|
|
|
|
nc : 'class',
|
|
|
|
|
nf : 'function',
|
|
|
|
|
na : null,
|
|
|
|
|
nb : 'builtin',
|
2018-01-26 06:29:35 -08:00
|
|
|
n : null
|
|
|
|
|
};
|
2011-09-06 11:35:14 -07:00
|
|
|
|
Support symbol linking in Remarkup code blocks
Summary:
Trigger the crossreference behavior on code blocks. Limited to
Differential, where we know what the project is, but includes regular
comments, inline comments, and previews of both.
(Hopefully event handlers on deleted elements also get deleted, so we
don't leak memory? Also, caching is a problem, and I didn't find a way
to mark existing cache entries as stale, like
`DifferentialChangesetParser::CACHE_VERSION`...)
Test Plan:
Load Differential revision, make lots of comments, click on
things.
Reviewers: epriestley
Reviewed By: epriestley
CC: aran, Korvin
Maniphest Tasks: T1602
Differential Revision: https://secure.phabricator.com/D3283
2012-08-14 14:03:26 -07:00
|
|
|
function link(element, lang) {
|
|
|
|
|
JX.DOM.alterClass(element, 'repository-crossreference', true);
|
2015-05-28 15:32:58 -07:00
|
|
|
linked.push(element);
|
Support symbol linking in Remarkup code blocks
Summary:
Trigger the crossreference behavior on code blocks. Limited to
Differential, where we know what the project is, but includes regular
comments, inline comments, and previews of both.
(Hopefully event handlers on deleted elements also get deleted, so we
don't leak memory? Also, caching is a problem, and I didn't find a way
to mark existing cache entries as stale, like
`DifferentialChangesetParser::CACHE_VERSION`...)
Test Plan:
Load Differential revision, make lots of comments, click on
things.
Reviewers: epriestley
Reviewed By: epriestley
CC: aran, Korvin
Maniphest Tasks: T1602
Differential Revision: https://secure.phabricator.com/D3283
2012-08-14 14:03:26 -07:00
|
|
|
JX.DOM.listen(
|
|
|
|
|
element,
|
2015-05-28 15:32:58 -07:00
|
|
|
['mouseover', 'mouseout', 'click'],
|
Support symbol linking in Remarkup code blocks
Summary:
Trigger the crossreference behavior on code blocks. Limited to
Differential, where we know what the project is, but includes regular
comments, inline comments, and previews of both.
(Hopefully event handlers on deleted elements also get deleted, so we
don't leak memory? Also, caching is a problem, and I didn't find a way
to mark existing cache entries as stale, like
`DifferentialChangesetParser::CACHE_VERSION`...)
Test Plan:
Load Differential revision, make lots of comments, click on
things.
Reviewers: epriestley
Reviewed By: epriestley
CC: aran, Korvin
Maniphest Tasks: T1602
Differential Revision: https://secure.phabricator.com/D3283
2012-08-14 14:03:26 -07:00
|
|
|
'tag:span',
|
|
|
|
|
function(e) {
|
2015-05-28 15:32:58 -07:00
|
|
|
if (e.getType() === 'mouseout') {
|
2015-08-27 04:15:40 -07:00
|
|
|
unhighlight();
|
2015-05-28 15:32:58 -07:00
|
|
|
return;
|
|
|
|
|
}
|
2018-04-08 09:10:03 -07:00
|
|
|
if (!hasHighlightModifierKey(e)) {
|
2015-05-28 15:32:58 -07:00
|
|
|
return;
|
|
|
|
|
}
|
2017-10-31 13:52:23 -07:00
|
|
|
|
|
|
|
|
var target = e.getTarget();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// If we're in an inline comment, don't link symbols.
|
|
|
|
|
if (JX.DOM.findAbove(target, 'div', 'differential-inline-comment')) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} catch (ex) {
|
|
|
|
|
// Continue if we're not inside an inline comment.
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-26 06:29:35 -08:00
|
|
|
// If only part of the symbol was edited, the symbol name itself will
|
|
|
|
|
// have another "<span />" inside of it which highlights only the
|
|
|
|
|
// edited part. Skip over it.
|
|
|
|
|
if (JX.DOM.isNode(target, 'span') && (target.className === 'bright')) {
|
|
|
|
|
target = target.parentNode;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-28 15:32:58 -07:00
|
|
|
if (e.getType() === 'mouseover') {
|
2018-01-26 06:29:35 -08:00
|
|
|
while (target && target !== document.body) {
|
2015-05-28 15:32:58 -07:00
|
|
|
if (JX.DOM.isNode(target, 'span') &&
|
|
|
|
|
(target.className in class_map)) {
|
|
|
|
|
highlighted = target;
|
|
|
|
|
JX.DOM.alterClass(highlighted, classHighlight, true);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
target = target.parentNode;
|
2012-08-09 15:19:02 -07:00
|
|
|
}
|
2015-05-28 15:32:58 -07:00
|
|
|
} else if (e.getType() === 'click') {
|
2018-04-08 09:10:03 -07:00
|
|
|
openSearch(target, {lang: lang});
|
2012-07-31 17:01:57 -07:00
|
|
|
}
|
Support symbol linking in Remarkup code blocks
Summary:
Trigger the crossreference behavior on code blocks. Limited to
Differential, where we know what the project is, but includes regular
comments, inline comments, and previews of both.
(Hopefully event handlers on deleted elements also get deleted, so we
don't leak memory? Also, caching is a problem, and I didn't find a way
to mark existing cache entries as stale, like
`DifferentialChangesetParser::CACHE_VERSION`...)
Test Plan:
Load Differential revision, make lots of comments, click on
things.
Reviewers: epriestley
Reviewed By: epriestley
CC: aran, Korvin
Maniphest Tasks: T1602
Differential Revision: https://secure.phabricator.com/D3283
2012-08-14 14:03:26 -07:00
|
|
|
});
|
|
|
|
|
}
|
2015-08-27 04:15:40 -07:00
|
|
|
function unhighlight() {
|
|
|
|
|
highlighted && JX.DOM.alterClass(highlighted, classHighlight, false);
|
|
|
|
|
highlighted = null;
|
|
|
|
|
}
|
Support symbol linking in Remarkup code blocks
Summary:
Trigger the crossreference behavior on code blocks. Limited to
Differential, where we know what the project is, but includes regular
comments, inline comments, and previews of both.
(Hopefully event handlers on deleted elements also get deleted, so we
don't leak memory? Also, caching is a problem, and I didn't find a way
to mark existing cache entries as stale, like
`DifferentialChangesetParser::CACHE_VERSION`...)
Test Plan:
Load Differential revision, make lots of comments, click on
things.
Reviewers: epriestley
Reviewed By: epriestley
CC: aran, Korvin
Maniphest Tasks: T1602
Differential Revision: https://secure.phabricator.com/D3283
2012-08-14 14:03:26 -07:00
|
|
|
|
2018-04-08 09:10:03 -07:00
|
|
|
function openSearch(target, context) {
|
2015-05-28 15:32:58 -07:00
|
|
|
var symbol = target.textContent || target.innerText;
|
2018-04-08 09:10:03 -07:00
|
|
|
|
|
|
|
|
context = context || {};
|
|
|
|
|
context.lang = context.lang || null;
|
|
|
|
|
context.repositories =
|
|
|
|
|
context.repositories ||
|
|
|
|
|
(config && config.repositories) ||
|
|
|
|
|
[];
|
|
|
|
|
|
|
|
|
|
var query = JX.copy({}, context);
|
|
|
|
|
if (query.repositories.length) {
|
|
|
|
|
query.repositories = query.repositories.join(',');
|
|
|
|
|
} else {
|
|
|
|
|
delete query.repositories;
|
|
|
|
|
}
|
|
|
|
|
query.jump = true;
|
|
|
|
|
|
2015-05-28 15:32:58 -07:00
|
|
|
var c = target.className;
|
|
|
|
|
c = c.replace(classHighlight, '').trim();
|
2018-01-26 06:42:16 -08:00
|
|
|
|
2015-05-28 15:32:58 -07:00
|
|
|
if (class_map[c]) {
|
|
|
|
|
query.type = class_map[c];
|
|
|
|
|
}
|
2018-01-26 06:42:16 -08:00
|
|
|
|
2015-05-28 15:32:58 -07:00
|
|
|
if (target.hasAttribute('data-symbol-context')) {
|
|
|
|
|
query.context = target.getAttribute('data-symbol-context');
|
|
|
|
|
}
|
2018-01-26 06:42:16 -08:00
|
|
|
|
2015-05-28 15:32:58 -07:00
|
|
|
if (target.hasAttribute('data-symbol-name')) {
|
|
|
|
|
symbol = target.getAttribute('data-symbol-name');
|
|
|
|
|
}
|
2018-01-25 18:21:00 -08:00
|
|
|
|
|
|
|
|
var line = getLineNumber(target);
|
|
|
|
|
if (line !== null) {
|
|
|
|
|
query.line = line;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-08 09:10:03 -07:00
|
|
|
if (!query.hasOwnProperty('path')) {
|
|
|
|
|
var path = getPath(target);
|
|
|
|
|
if (path !== null) {
|
|
|
|
|
query.path = path;
|
|
|
|
|
}
|
2018-01-25 18:21:00 -08:00
|
|
|
}
|
|
|
|
|
|
2018-01-26 06:29:35 -08:00
|
|
|
var char = getChar(target);
|
|
|
|
|
if (char !== null) {
|
|
|
|
|
query.char = char;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-29 09:37:22 -07:00
|
|
|
var uri_symbol = symbol;
|
|
|
|
|
|
|
|
|
|
// In some cases, lexers may include whitespace in symbol tags. Trim it,
|
|
|
|
|
// since symbols with semantic whitespace aren't supported.
|
|
|
|
|
uri_symbol = uri_symbol.trim();
|
|
|
|
|
|
|
|
|
|
// See T13437. Symbols like "#define" need to be encoded.
|
|
|
|
|
uri_symbol = encodeURIComponent(uri_symbol);
|
|
|
|
|
|
|
|
|
|
var uri = JX.$U('/diffusion/symbol/' + uri_symbol + '/');
|
2015-05-28 15:32:58 -07:00
|
|
|
uri.addQueryParams(query);
|
2018-04-08 09:10:03 -07:00
|
|
|
|
|
|
|
|
window.open(uri.toString());
|
2015-05-28 15:32:58 -07:00
|
|
|
}
|
|
|
|
|
|
2014-06-24 03:27:47 +10:00
|
|
|
function linkAll() {
|
2013-05-12 06:52:53 -07:00
|
|
|
var blocks = JX.DOM.scry(document.body, 'div', 'remarkup-code-block');
|
Support symbol linking in Remarkup code blocks
Summary:
Trigger the crossreference behavior on code blocks. Limited to
Differential, where we know what the project is, but includes regular
comments, inline comments, and previews of both.
(Hopefully event handlers on deleted elements also get deleted, so we
don't leak memory? Also, caching is a problem, and I didn't find a way
to mark existing cache entries as stale, like
`DifferentialChangesetParser::CACHE_VERSION`...)
Test Plan:
Load Differential revision, make lots of comments, click on
things.
Reviewers: epriestley
Reviewed By: epriestley
CC: aran, Korvin
Maniphest Tasks: T1602
Differential Revision: https://secure.phabricator.com/D3283
2012-08-14 14:03:26 -07:00
|
|
|
for (var i = 0; i < blocks.length; ++i) {
|
|
|
|
|
if (blocks[i].hasAttribute('data-code-lang')) {
|
|
|
|
|
var lang = blocks[i].getAttribute('data-code-lang');
|
|
|
|
|
link(blocks[i], lang);
|
2011-09-06 11:35:14 -07:00
|
|
|
}
|
Support symbol linking in Remarkup code blocks
Summary:
Trigger the crossreference behavior on code blocks. Limited to
Differential, where we know what the project is, but includes regular
comments, inline comments, and previews of both.
(Hopefully event handlers on deleted elements also get deleted, so we
don't leak memory? Also, caching is a problem, and I didn't find a way
to mark existing cache entries as stale, like
`DifferentialChangesetParser::CACHE_VERSION`...)
Test Plan:
Load Differential revision, make lots of comments, click on
things.
Reviewers: epriestley
Reviewed By: epriestley
CC: aran, Korvin
Maniphest Tasks: T1602
Differential Revision: https://secure.phabricator.com/D3283
2012-08-14 14:03:26 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-25 18:21:00 -08:00
|
|
|
function getLineNumber(target) {
|
|
|
|
|
|
|
|
|
|
// Figure out the line number by finding the most recent "<th />" in this
|
|
|
|
|
// row with a number in it. We may need to skip over one "<th />" if the
|
|
|
|
|
// diff is being displayed in unified mode.
|
|
|
|
|
|
|
|
|
|
var cell = JX.DOM.findAbove(target, 'td');
|
|
|
|
|
if (!cell) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var row = JX.DOM.findAbove(target, 'tr');
|
|
|
|
|
if (!row) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var ii;
|
|
|
|
|
|
|
|
|
|
var cell_list = [];
|
|
|
|
|
for (ii = 0; ii < row.childNodes.length; ii++) {
|
|
|
|
|
cell_list.push(row.childNodes[ii]);
|
|
|
|
|
}
|
|
|
|
|
cell_list.reverse();
|
|
|
|
|
|
|
|
|
|
var found = false;
|
|
|
|
|
for (ii = 0; ii < cell_list.length; ii++) {
|
|
|
|
|
if (cell_list[ii] === cell) {
|
|
|
|
|
found = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (found && JX.DOM.isType(cell_list[ii], 'th')) {
|
|
|
|
|
var int_value = parseInt(cell_list[ii].textContent, 10);
|
|
|
|
|
if (int_value) {
|
|
|
|
|
return int_value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getPath(target) {
|
2020-05-07 08:42:35 -07:00
|
|
|
// This method works in Differential, when browsing a changeset.
|
2018-01-26 06:42:16 -08:00
|
|
|
var changeset;
|
|
|
|
|
try {
|
|
|
|
|
changeset = JX.DOM.findAbove(target, 'div', 'differential-changeset');
|
|
|
|
|
return JX.Stratcom.getData(changeset).path;
|
|
|
|
|
} catch (ex) {
|
|
|
|
|
// Ignore.
|
|
|
|
|
}
|
2018-01-25 18:21:00 -08:00
|
|
|
|
2018-01-26 06:42:16 -08:00
|
|
|
return null;
|
2018-01-25 18:21:00 -08:00
|
|
|
}
|
|
|
|
|
|
2018-01-26 06:29:35 -08:00
|
|
|
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;
|
|
|
|
|
char += content.length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
Support symbol linking in Remarkup code blocks
Summary:
Trigger the crossreference behavior on code blocks. Limited to
Differential, where we know what the project is, but includes regular
comments, inline comments, and previews of both.
(Hopefully event handlers on deleted elements also get deleted, so we
don't leak memory? Also, caching is a problem, and I didn't find a way
to mark existing cache entries as stale, like
`DifferentialChangesetParser::CACHE_VERSION`...)
Test Plan:
Load Differential revision, make lots of comments, click on
things.
Reviewers: epriestley
Reviewed By: epriestley
CC: aran, Korvin
Maniphest Tasks: T1602
Differential Revision: https://secure.phabricator.com/D3283
2012-08-14 14:03:26 -07:00
|
|
|
JX.Stratcom.listen(
|
|
|
|
|
'differential-preview-update',
|
|
|
|
|
null,
|
|
|
|
|
function(e) {
|
|
|
|
|
linkAll(e.getData().container);
|
2011-09-06 11:35:14 -07:00
|
|
|
});
|
|
|
|
|
|
2015-08-27 04:15:40 -07:00
|
|
|
|
2015-05-28 15:32:58 -07:00
|
|
|
JX.Stratcom.listen(
|
|
|
|
|
['keydown', 'keyup'],
|
|
|
|
|
null,
|
|
|
|
|
function(e) {
|
2018-04-08 09:10:03 -07:00
|
|
|
if (!isHighlightModifierKey(e)) {
|
2015-05-28 15:32:58 -07:00
|
|
|
return;
|
|
|
|
|
}
|
2018-04-08 09:10:03 -07:00
|
|
|
|
2015-08-27 04:15:40 -07:00
|
|
|
setCursorMode(e.getType() === 'keydown');
|
2015-05-28 15:32:58 -07:00
|
|
|
|
|
|
|
|
if (!statics.active) {
|
2015-08-27 04:15:40 -07:00
|
|
|
unhighlight();
|
2015-05-28 15:32:58 -07:00
|
|
|
}
|
|
|
|
|
});
|
2015-08-27 04:15:40 -07:00
|
|
|
|
|
|
|
|
JX.Stratcom.listen(
|
|
|
|
|
'blur',
|
|
|
|
|
null,
|
|
|
|
|
function(e) {
|
|
|
|
|
if (e.getTarget()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
unhighlight();
|
|
|
|
|
setCursorMode(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function setCursorMode(active) {
|
|
|
|
|
statics.active = active;
|
|
|
|
|
linked.forEach(function(element) {
|
|
|
|
|
JX.DOM.alterClass(element, classMouseCursor, statics.active);
|
|
|
|
|
});
|
|
|
|
|
}
|
2018-04-08 09:10:03 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if (config && config.container) {
|
|
|
|
|
link(JX.$(config.container), config.lang);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JX.Stratcom.listen(
|
|
|
|
|
['mouseover', 'mouseout', 'click'],
|
|
|
|
|
['has-symbols', 'tag:span'],
|
|
|
|
|
function(e) {
|
|
|
|
|
var type = e.getType();
|
|
|
|
|
|
|
|
|
|
if (type === 'mouseout') {
|
|
|
|
|
unhighlight();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!hasHighlightModifierKey(e)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var target = e.getTarget();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// If we're in an inline comment, don't link symbols.
|
|
|
|
|
if (JX.DOM.findAbove(target, 'div', 'differential-inline-comment')) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} catch (ex) {
|
|
|
|
|
// Continue if we're not inside an inline comment.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If only part of the symbol was edited, the symbol name itself will
|
|
|
|
|
// have another "<span />" 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 (type === 'click') {
|
|
|
|
|
openSearch(target, e.getNodeData('has-symbols').symbols);
|
|
|
|
|
e.kill();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (e.getType() === 'mouseover') {
|
|
|
|
|
while (target && target !== document.body) {
|
|
|
|
|
if (!JX.DOM.isNode(target, 'span')) {
|
|
|
|
|
target = target.parentNode;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!class_map.hasOwnProperty(target.className)) {
|
|
|
|
|
target = target.parentNode;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
highlighted = target;
|
|
|
|
|
JX.DOM.alterClass(highlighted, classHighlight, true);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2011-09-06 11:35:14 -07:00
|
|
|
});
|