Take tab size into account for line-wrapping
Previously, the logic was only checking exact line wrap boundaries and
missed tabs advancing over the boundary.
Also, line breaks were added inside span elements wrapping tabs, which
prevented correct rendering.
Bug: Issue 5597
Change-Id: I750547cb574c02965d5a30ba57f791841779297a
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
index d62dbf8..54a72f6 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
@@ -480,20 +480,38 @@
return index + 1;
};
+ GrDiffBuilder.prototype._advancePastTagClose = function(html, index) {
+ while (index < html.length &&
+ html.charCodeAt(index) !== GrDiffBuilder.GREATER_THAN_CODE) {
+ index++;
+ }
+ return index + 1;
+ };
+
GrDiffBuilder.prototype._addNewlines = function(text, html) {
var htmlIndex = 0;
var indices = [];
var numChars = 0;
+ var prevHtmlIndex = 0;
for (var i = 0; i < text.length; i++) {
if (numChars > 0 && numChars % this._prefs.line_length === 0) {
indices.push(htmlIndex);
}
htmlIndex = this._advanceChar(html, htmlIndex);
if (text[i] === '\t') {
+ // Advance past tab closing tag.
+ htmlIndex = this._advancePastTagClose(html, htmlIndex);
+ // ~~ is a faster Math.floor
+ if (~~(numChars / this._prefs.line_length) !==
+ ~~((numChars + this._prefs.tab_size) / this._prefs.line_length)) {
+ // Tab crosses line limit - push it to the next line.
+ indices.push(prevHtmlIndex);
+ }
numChars += this._prefs.tab_size;
} else {
numChars++;
}
+ prevHtmlIndex = htmlIndex;
}
var result = html;
// Since the result string is being altered in place, start from the end
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
index e5fe1d7..88ce477 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
@@ -97,7 +97,7 @@
assert.equal(buttons[2].textContent, '+10↓');
});
- test('newlines', function() {
+ test('newlines 1', function() {
var text = 'abcdef';
assert.equal(builder._addNewlines(text, text), text);
text = 'a'.repeat(20);
@@ -105,8 +105,10 @@
'a'.repeat(10) +
GrDiffBuilder.LINE_FEED_HTML +
'a'.repeat(10));
+ });
- text = '<span class="thumbsup">👍</span>';
+ test('newlines 2', function() {
+ var text = '<span class="thumbsup">👍</span>';
var html = '<span class="thumbsup">👍</span>';
assert.equal(builder._addNewlines(text, html),
'<span clas' +
@@ -116,10 +118,13 @@
'p">👍</spa' +
GrDiffBuilder.LINE_FEED_HTML +
'n>');
+ });
- text = '01234\t56789';
- assert.equal(builder._addNewlines(text, text),
- '01234\t5' +
+ test('newlines 3', function() {
+ var text = '01234\t56789';
+ var html = '01234<span>\t</span>56789';
+ assert.equal(builder._addNewlines(text, html),
+ '01234<span>\t</span>5' +
GrDiffBuilder.LINE_FEED_HTML +
'6789');
});
@@ -154,6 +159,17 @@
});
});
+ test('_createTextEl linewrap with tabs', function() {
+ var text = _.times(7, _.constant('\t')).join('') + '!';
+ var line = {text: text, highlights: []};
+ var el = builder._createTextEl(line);
+ var tabEl = el.querySelector('.contentText > .br');
+ assert.isOk(tabEl);
+ assert.equal(
+ el.querySelector('.contentText .tab:nth-child(2)').nextSibling,
+ tabEl);
+ });
+
test('text length with tabs and unicode', function() {
assert.equal(builder._textLength('12345', 4), 5);
assert.equal(builder._textLength('\t\t12', 4), 10);