Commit 36a917e1 authored by Fatih Acet's avatar Fatih Acet

RepoEditor: Implement line and range linking.

parent 92173ac5
...@@ -28,52 +28,56 @@ ...@@ -28,52 +28,56 @@
// </div> // </div>
// </div> // </div>
// //
(function() {
this.LineHighlighter = (function() { const LineHighlighter = function(options = {}) {
// CSS class applied to highlighted lines options.highlightLineClass = options.highlightLineClass || 'hll';
LineHighlighter.prototype.highlightClass = 'hll'; options.fileHolderSelector = options.fileHolderSelector || '.file-holder';
options.scrollFileHolder = options.scrollFileHolder || false;
// Internal copy of location.hash so we're not dependent on `location` in tests options.hash = options.hash || location.hash;
LineHighlighter.prototype._hash = '';
this.options = options;
function LineHighlighter(hash) { this._hash = options.hash;
if (hash == null) { this.highlightLineClass = options.highlightLineClass;
// Initialize a LineHighlighter object
//
// hash - String URL hash for dependency injection in tests
hash = location.hash;
}
this.setHash = this.setHash.bind(this); this.setHash = this.setHash.bind(this);
this.highlightLine = this.highlightLine.bind(this); this.highlightLine = this.highlightLine.bind(this);
this.clickHandler = this.clickHandler.bind(this); this.clickHandler = this.clickHandler.bind(this);
this.highlightHash = this.highlightHash.bind(this); this.highlightHash = this.highlightHash.bind(this);
this._hash = hash;
this.bindEvents(); this.bindEvents();
this.highlightHash(); this.highlightHash();
} };
LineHighlighter.prototype.bindEvents = function() {
const $fileHolder = $(this.options.fileHolderSelector);
LineHighlighter.prototype.bindEvents = function() {
const $fileHolder = $('.file-holder');
$fileHolder.on('click', 'a[data-line-number]', this.clickHandler); $fileHolder.on('click', 'a[data-line-number]', this.clickHandler);
$fileHolder.on('highlight:line', this.highlightHash); $fileHolder.on('highlight:line', this.highlightHash);
}; };
LineHighlighter.prototype.highlightHash = function() { LineHighlighter.prototype.highlightHash = function() {
var range; var range;
if (this._hash !== '') { if (this._hash !== '') {
range = this.hashToRange(this._hash); range = this.hashToRange(this._hash);
if (range[0]) { if (range[0]) {
this.highlightRange(range); this.highlightRange(range);
$.scrollTo("#L" + range[0], { const lineSelector = `#L${range[0]}`;
const scrollOptions = {
// Scroll to the first highlighted line on initial load // Scroll to the first highlighted line on initial load
// Offset -50 for the sticky top bar, and another -100 for some context // Offset -50 for the sticky top bar, and another -100 for some context
offset: -150 offset: -150
}); };
if (this.options.scrollFileHolder) {
$(this.options.fileHolderSelector).scrollTo(lineSelector, scrollOptions);
} else {
$.scrollTo(lineSelector, scrollOptions);
} }
} }
}; }
};
LineHighlighter.prototype.clickHandler = function(event) { LineHighlighter.prototype.clickHandler = function(event) {
var current, lineNumber, range; var current, lineNumber, range;
event.preventDefault(); event.preventDefault();
this.clearHighlight(); this.clearHighlight();
...@@ -93,25 +97,24 @@ ...@@ -93,25 +97,24 @@
this.setHash(range[0], range[1]); this.setHash(range[0], range[1]);
return this.highlightRange(range); return this.highlightRange(range);
} }
}; };
LineHighlighter.prototype.clearHighlight = function() { LineHighlighter.prototype.clearHighlight = function() {
return $("." + this.highlightClass).removeClass(this.highlightClass); return $("." + this.highlightLineClass).removeClass(this.highlightLineClass);
// Unhighlight previously highlighted lines };
};
// Convert a URL hash String into line numbers // Convert a URL hash String into line numbers
// //
// hash - Hash String // hash - Hash String
// //
// Examples: // Examples:
// //
// hashToRange('#L5') # => [5, null] // hashToRange('#L5') # => [5, null]
// hashToRange('#L5-15') # => [5, 15] // hashToRange('#L5-15') # => [5, 15]
// hashToRange('#foo') # => [null, null] // hashToRange('#foo') # => [null, null]
// //
// Returns an Array // Returns an Array
LineHighlighter.prototype.hashToRange = function(hash) { LineHighlighter.prototype.hashToRange = function(hash) {
var first, last, matches; var first, last, matches;
// ?L(\d+)(?:-(\d+))?$/) // ?L(\d+)(?:-(\d+))?$/)
matches = hash.match(/^#?L(\d+)(?:-(\d+))?$/); matches = hash.match(/^#?L(\d+)(?:-(\d+))?$/);
...@@ -122,19 +125,19 @@ ...@@ -122,19 +125,19 @@
} else { } else {
return [null, null]; return [null, null];
} }
}; };
// Highlight a single line // Highlight a single line
// //
// lineNumber - Line number to highlight // lineNumber - Line number to highlight
LineHighlighter.prototype.highlightLine = function(lineNumber) { LineHighlighter.prototype.highlightLine = function(lineNumber) {
return $("#LC" + lineNumber).addClass(this.highlightClass); return $("#LC" + lineNumber).addClass(this.highlightLineClass);
}; };
// Highlight all lines within a range // Highlight all lines within a range
// //
// range - Array containing the starting and ending line numbers // range - Array containing the starting and ending line numbers
LineHighlighter.prototype.highlightRange = function(range) { LineHighlighter.prototype.highlightRange = function(range) {
var i, lineNumber, ref, ref1, results; var i, lineNumber, ref, ref1, results;
if (range[1]) { if (range[1]) {
results = []; results = [];
...@@ -145,10 +148,10 @@ ...@@ -145,10 +148,10 @@
} else { } else {
return this.highlightLine(range[0]); return this.highlightLine(range[0]);
} }
}; };
// Set the URL hash string // Set the URL hash string
LineHighlighter.prototype.setHash = function(firstLineNumber, lastLineNumber) { LineHighlighter.prototype.setHash = function(firstLineNumber, lastLineNumber) {
var hash; var hash;
if (lastLineNumber) { if (lastLineNumber) {
hash = "#L" + firstLineNumber + "-" + lastLineNumber; hash = "#L" + firstLineNumber + "-" + lastLineNumber;
...@@ -157,19 +160,17 @@ ...@@ -157,19 +160,17 @@
} }
this._hash = hash; this._hash = hash;
return this.__setLocationHash__(hash); return this.__setLocationHash__(hash);
}; };
// Make the actual hash change in the browser // Make the actual hash change in the browser
// //
// This method is stubbed in tests. // This method is stubbed in tests.
LineHighlighter.prototype.__setLocationHash__ = function(value) { LineHighlighter.prototype.__setLocationHash__ = function(value) {
return history.pushState({ return history.pushState({
url: value url: value
// We're using pushState instead of assigning location.hash directly to // We're using pushState instead of assigning location.hash directly to
// prevent the page from scrolling on the hashchange event // prevent the page from scrolling on the hashchange event
}, document.title, value); }, document.title, value);
}; };
return LineHighlighter; window.LineHighlighter = LineHighlighter;
})();
}).call(window);
<script> <script>
/* global LineHighlighter */
import Store from '../stores/repo_store'; import Store from '../stores/repo_store';
export default { export default {
data: () => Store, data: () => Store,
mounted() {
this.highlightFile();
},
computed: { computed: {
html() { html() {
return this.activeFile.html; return this.activeFile.html;
}, },
}, },
methods: { methods: {
highlightFile() { highlightFile() {
$(this.$el).find('.file-content').syntaxHighlight(); $(this.$el).find('.file-content').syntaxHighlight();
}, },
}, },
mounted() {
this.highlightFile();
this.lineHighlighter = new LineHighlighter({
fileHolderSelector: '.blob-viewer-container',
scrollFileHolder: true,
});
},
watch: { watch: {
html() { html() {
this.$nextTick(() => { this.$nextTick(() => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment