Handle tabs for range comments
Changes: - wrapping in HL now adds cssClass instead of discarding previous ones. - getLength accounts for tab tags correctly. - generic splitNode, potentially should be moved into util. - more tests. Feature: Issue 3915 Change-Id: Id8a646a5de4fd702aa112678c039df9ff8dd8c0b
This commit is contained in:
@@ -327,7 +327,7 @@
|
||||
},
|
||||
|
||||
/**
|
||||
* Traverse diff content from right to left, call callback for each node.
|
||||
* Traverse Element from right to left, call callback for each node.
|
||||
* Stops if callback returns true.
|
||||
*
|
||||
* @param {!Node} startNode
|
||||
@@ -338,7 +338,9 @@
|
||||
var travelLeft = opt_flags && opt_flags.left;
|
||||
var node = startNode;
|
||||
while (node) {
|
||||
if (node instanceof Element && node.tagName !== 'HL') {
|
||||
if (node instanceof Element &&
|
||||
node.tagName !== 'HL' &&
|
||||
node.tagName !== 'SPAN') {
|
||||
break;
|
||||
}
|
||||
var nextNode = travelLeft ? node.previousSibling : node.nextSibling;
|
||||
@@ -360,7 +362,6 @@
|
||||
node = node.firstChild;
|
||||
var length = 0;
|
||||
while (node) {
|
||||
// Only measure Text nodes and <hl>
|
||||
if (node instanceof Text || node.tagName == 'HL') {
|
||||
length += this._getLength(node);
|
||||
}
|
||||
@@ -380,10 +381,16 @@
|
||||
* @return {!Element} Wrapped node.
|
||||
*/
|
||||
_wrapInHighlight: function(node, cssClass) {
|
||||
var hl = document.createElement('hl');
|
||||
var hl;
|
||||
if (node.tagName === 'HL') {
|
||||
hl = node;
|
||||
hl.classList.add(cssClass);
|
||||
} else {
|
||||
hl = document.createElement('hl');
|
||||
hl.className = cssClass;
|
||||
Polymer.dom(node.parentElement).replaceChild(hl, node);
|
||||
hl.appendChild(node);
|
||||
}
|
||||
return hl;
|
||||
},
|
||||
|
||||
@@ -394,7 +401,7 @@
|
||||
* @param {number} offset
|
||||
* @return {!Text} Trailing Text Node.
|
||||
*/
|
||||
_splitText: function(node, offset) {
|
||||
_splitTextNode: function(node, offset) {
|
||||
if (node.textContent.match(REGEX_ASTRAL_SYMBOL)) {
|
||||
// DOM Api for splitText() is broken for Unicode:
|
||||
// https://mathiasbynens.be/notes/javascript-unicode
|
||||
@@ -412,11 +419,42 @@
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Split Node at offset.
|
||||
* If Node is Element, it's cloned and the node at offset is split too.
|
||||
*
|
||||
* @param {!Node} node
|
||||
* @param {number} offset
|
||||
* @return {!Node} Trailing Node.
|
||||
*/
|
||||
_splitNode: function(element, offset) {
|
||||
if (element instanceof Text) {
|
||||
return this._splitTextNode(element, offset);
|
||||
}
|
||||
var tail = element.cloneNode(false);
|
||||
element.parentElement.insertBefore(tail, element.nextSibling);
|
||||
// Skip nodes before offset.
|
||||
var node = element.firstChild;
|
||||
while (node &&
|
||||
this._getLength(node) <= offset ||
|
||||
this._getLength(node) === 0) {
|
||||
offset -= this._getLength(node);
|
||||
node = node.nextSibling;
|
||||
}
|
||||
if (this._getLength(node) > offset) {
|
||||
tail.appendChild(this._splitNode(node, offset));
|
||||
}
|
||||
while (node.nextSibling) {
|
||||
tail.appendChild(node.nextSibling);
|
||||
}
|
||||
return tail;
|
||||
},
|
||||
|
||||
/**
|
||||
* Split Text Node and wrap it in hl with cssClass.
|
||||
* Wraps trailing part after split, tailing one if opt_firstPart is true.
|
||||
*
|
||||
* @param {!Text} node
|
||||
* @param {!Node} node
|
||||
* @param {number} offset
|
||||
* @param {string} cssClass
|
||||
* @param {boolean=} opt_firstPart
|
||||
@@ -426,10 +464,10 @@
|
||||
return this._wrapInHighlight(node, cssClass);
|
||||
} else {
|
||||
if (opt_firstPart) {
|
||||
this._splitText(node, offset);
|
||||
this._splitNode(node, offset);
|
||||
// Node points to first part of the Text, second one is sibling.
|
||||
} else {
|
||||
node = this._splitText(node, offset);
|
||||
node = this._splitNode(node, offset);
|
||||
}
|
||||
return this._wrapInHighlight(node, cssClass);
|
||||
}
|
||||
@@ -467,29 +505,21 @@
|
||||
if (startNode instanceof Text) {
|
||||
startNode =
|
||||
this._splitAndWrapInHighlight(startNode, startOffset, cssClass);
|
||||
startContent.insertBefore(startNode, startNode.nextSibling);
|
||||
// Edge case: single line, text node wraps the highlight.
|
||||
if (isOneLine && this._getLength(startNode) > length) {
|
||||
var extra = this._splitText(startNode.firstChild, length);
|
||||
var extra = this._splitTextNode(startNode.firstChild, length);
|
||||
startContent.insertBefore(extra, startNode.nextSibling);
|
||||
startContent.normalize();
|
||||
}
|
||||
} else if (startNode.tagName == 'HL') {
|
||||
if (!startNode.classList.contains(cssClass)) {
|
||||
var hl = startNode;
|
||||
startNode = this._splitAndWrapInHighlight(
|
||||
startNode.firstChild, startOffset, cssClass);
|
||||
startContent.insertBefore(startNode, hl.nextSibling);
|
||||
// Edge case: single line, <hl> wraps the highlight.
|
||||
if (isOneLine && this._getLength(startNode) > length) {
|
||||
var trailingHl = hl.cloneNode(false);
|
||||
trailingHl.appendChild(
|
||||
this._splitText(startNode.firstChild, length));
|
||||
startContent.insertBefore(trailingHl, startNode.nextSibling);
|
||||
}
|
||||
if (hl.textContent.length === 0) {
|
||||
hl.remove();
|
||||
// Should leave wrapping HL's content after the highlight.
|
||||
if (isOneLine && startOffset + length < this._getLength(startNode)) {
|
||||
this._splitNode(startNode, startOffset + length);
|
||||
}
|
||||
startNode =
|
||||
this._splitAndWrapInHighlight(startNode, startOffset, cssClass);
|
||||
}
|
||||
} else {
|
||||
startNode = null;
|
||||
@@ -531,8 +561,7 @@
|
||||
// Split text inside HL.
|
||||
var hl = endNode;
|
||||
endNode = this._splitAndWrapInHighlight(
|
||||
endNode.firstChild, endOffset, cssClass, true);
|
||||
endContent.insertBefore(endNode, hl);
|
||||
endNode, endOffset, cssClass, true);
|
||||
if (hl.textContent.length === 0) {
|
||||
hl.remove();
|
||||
}
|
||||
@@ -562,19 +591,32 @@
|
||||
|
||||
// Grow starting highlight until endNode or end of line.
|
||||
if (startNode && startNode != endNode) {
|
||||
this._traverseContentSiblings(startNode.nextSibling, function(node) {
|
||||
startNode.textContent += node.textContent;
|
||||
var growStartHl = function(node) {
|
||||
if (node instanceof Text || node.tagName === 'SPAN') {
|
||||
startNode.appendChild(node);
|
||||
} else if (node.tagName === 'HL') {
|
||||
this._traverseContentSiblings(node.firstChild, growStartHl);
|
||||
node.remove();
|
||||
}
|
||||
return node == endNode;
|
||||
});
|
||||
}.bind(this);
|
||||
this._traverseContentSiblings(startNode.nextSibling, growStartHl);
|
||||
startNode.normalize();
|
||||
}
|
||||
|
||||
if (!isOneLine && endNode) {
|
||||
// Prepend text up to line start to the ending highlight.
|
||||
this._traverseContentSiblings(endNode.previousSibling, function(node) {
|
||||
endNode.textContent = node.textContent + endNode.textContent;
|
||||
var growEndHl = function(node) {
|
||||
if (node instanceof Text || node.tagName === 'SPAN') {
|
||||
endNode.insertBefore(node, endNode.firstChild);
|
||||
} else if (node.tagName === 'HL') {
|
||||
this._traverseContentSiblings(node.firstChild, growEndHl);
|
||||
node.remove();
|
||||
}, {left: true});
|
||||
}
|
||||
}.bind(this);
|
||||
// Prepend text up to line start to the ending highlight.
|
||||
this._traverseContentSiblings(
|
||||
endNode.previousSibling, growEndHl, {left: true});
|
||||
endNode.normalize();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -42,21 +42,19 @@ limitations under the License.
|
||||
<tr class="diff-row side-by-side" left-type="remove" right-type="add">
|
||||
<td class="left lineNum" data-value="140">140</td>
|
||||
<!-- Next tag is formatted to eliminate zero-length text nodes. -->
|
||||
<td class="content remove lightHighlight">na💢ti <hl class="foo">te, inquit</hl>, sumus <hl class="bar">aliquando</hl> otiosum, <hl>certe</hl> a udiam, <hl>quid</hl> sit, quod <hl>Epicurum</hl><gr-diff-comment-thread>
|
||||
<td class="content remove lightHighlight">na💢ti <hl class="foo">te, inquit</hl>, sumus <hl class="bar">aliquando</hl> otiosum, <hl>certe</hl> a <hl><span class="tab withIndicator" style="tab-size:8;"></span></hl>udiam, <hl>quid</hl> sit, <span class="tab withIndicator" style="tab-size:8;"></span>quod <hl>Epicurum</hl><gr-diff-comment-thread>
|
||||
[Yet another random diff thread content here]
|
||||
</gr-diff-comment-thread></td>
|
||||
<td class="right lineNum" data-value="120">120</td>
|
||||
<td class="content add lightHighlight">nacti ,
|
||||
<hl>,</hl>
|
||||
sumus otiosum, audiam, sit, quod
|
||||
</td>
|
||||
<!-- Next tag is formatted to eliminate zero-length text nodes. -->
|
||||
<td class="content add lightHighlight">nacti , <hl>,</hl> sumus <hl><span class="tab withIndicator" style="tab-size:8;"></span></hl> otiosum, <span class="tab withIndicator" style="tab-size:8;"></span> audiam, sit, quod</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody class="section both">
|
||||
<tr class="diff-row side-by-side" left-type="both" right-type="both">
|
||||
<td class="left lineNum" data-value="141"></td>
|
||||
<td class="content both darkHighlight">nam et complectitur verbis, quod vult, et dicit plane, quod intellegam;</td>
|
||||
<td class="content both darkHighlight">nam et<hl><span class="tab withIndicator" style="tab-size:8;"> </span></hl>complectitur<span class="tab withIndicator" style="tab-size:8;"> </span>verbis, quod vult, et dicit plane, quod intellegam;</td>
|
||||
<td class="right lineNum" data-value="130"></td>
|
||||
<td class="content both darkHighlight">nam et complectitur verbis, quod vult, et dicit plane, quod intellegam;</td>
|
||||
</tr>
|
||||
@@ -97,7 +95,7 @@ limitations under the License.
|
||||
<td class="left lineNum" data-value="165"></td>
|
||||
<td class="content both darkHighlight">in physicis, quibus maxime gloriatur, primum totus est alienus. Democritea dicit</td>
|
||||
<td class="right lineNum" data-value="147"></td>
|
||||
<td class="content both darkHighlight">in physicis, quibus maxime gloriatur, primum totus est alienus. Democritea dicit</td>
|
||||
<td class="content both darkHighlight">in physicis, <hl><span class="tab withIndicator" style="tab-size:8;"> </span></hl> quibus maxime gloriatur, primum totus est alienus. Democritea dicit</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -222,7 +220,6 @@ limitations under the License.
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('renders lines in comment range on comment discard', function(done) {
|
||||
element.fire('comment-discard', {
|
||||
comment: {
|
||||
@@ -314,10 +311,10 @@ limitations under the License.
|
||||
var diff = element.querySelector('#diffTable');
|
||||
var startContent =
|
||||
diff.querySelector('.left.lineNum[data-value="138"] ~ .content');
|
||||
var endContent =
|
||||
diff.querySelector('.left.lineNum[data-value="141"] ~ .content');
|
||||
var betweenContent =
|
||||
diff.querySelector('.left.lineNum[data-value="140"] ~ .content');
|
||||
var endContent =
|
||||
diff.querySelector('.left.lineNum[data-value="141"] ~ .content');
|
||||
var commentThread =
|
||||
diff.querySelector('gr-diff-comment-thread');
|
||||
var builder = {
|
||||
@@ -333,7 +330,7 @@ limitations under the License.
|
||||
startContent);
|
||||
builder.getContentByLine.withArgs(141, 'left').returns(
|
||||
endContent);
|
||||
element._applyRangedHighlight('some', 138, 4, 141, 8, 'left');
|
||||
element._applyRangedHighlight('some', 138, 4, 141, 28, 'left');
|
||||
assert.instanceOf(startContent.childNodes[0], Text);
|
||||
assert.equal(startContent.childNodes[0].textContent, '[14]');
|
||||
assert.instanceOf(startContent.childNodes[1], Element);
|
||||
@@ -342,14 +339,6 @@ limitations under the License.
|
||||
assert.equal(startContent.childNodes[1].tagName, 'HL');
|
||||
assert.equal(startContent.childNodes[1].className, 'some');
|
||||
|
||||
assert.instanceOf(endContent.childNodes[0], Element);
|
||||
assert.equal(endContent.childNodes[0].textContent, 'nam et c');
|
||||
assert.equal(endContent.childNodes[0].tagName, 'HL');
|
||||
assert.equal(endContent.childNodes[0].className, 'some');
|
||||
assert.instanceOf(endContent.childNodes[1], Text);
|
||||
assert.equal(endContent.childNodes[1].textContent,
|
||||
'omplectitur verbis, quod vult, et dicit plane, quod intellegam;');
|
||||
|
||||
assert.instanceOf(betweenContent.firstChild, Element);
|
||||
assert.equal(betweenContent.firstChild.tagName, 'HL');
|
||||
assert.equal(betweenContent.firstChild.className, 'some');
|
||||
@@ -364,6 +353,22 @@ limitations under the License.
|
||||
|
||||
assert.strictEqual(betweenContent.querySelector('gr-diff-comment-thread'),
|
||||
commentThread, 'Comment threads should be preserved.');
|
||||
|
||||
assert.instanceOf(endContent.childNodes[0], Element);
|
||||
assert.equal(endContent.childNodes[0].textContent,
|
||||
'nam et\tcomplectitur\tverbis, ');
|
||||
assert.equal(endContent.childNodes[0].tagName, 'HL');
|
||||
assert.equal(endContent.childNodes[0].className, 'some');
|
||||
assert.instanceOf(endContent.childNodes[1], Text);
|
||||
assert.equal(endContent.childNodes[1].textContent,
|
||||
'quod vult, et dicit plane, quod intellegam;');
|
||||
var endHl = endContent.querySelector('hl.some');
|
||||
assert.equal(endHl.childNodes.length, 5);
|
||||
var tabs = endHl.querySelectorAll('span.tab');
|
||||
assert.equal(tabs.length, 2);
|
||||
assert.equal(tabs[0].previousSibling.textContent, 'nam et');
|
||||
assert.equal(tabs[1].previousSibling.textContent, 'complectitur');
|
||||
assert.equal(tabs[1].nextSibling.textContent, 'verbis, ');
|
||||
});
|
||||
|
||||
suite('single line ranges', function() {
|
||||
@@ -394,10 +399,18 @@ limitations under the License.
|
||||
assert.equal(content.firstChild.tagName, 'HL');
|
||||
assert.equal(content.firstChild.className, 'some');
|
||||
assert.equal(content.childNodes.length, 2);
|
||||
assert.equal(content.firstChild.childNodes.length, 1);
|
||||
assert.equal(content.firstChild.childNodes.length, 5);
|
||||
assert.equal(content.firstChild.textContent,
|
||||
'na💢ti te, inquit, sumus aliquando otiosum, certe a udiam, ' +
|
||||
'quid sit, quod Epicurum');
|
||||
var tabs = content.querySelectorAll('span.tab');
|
||||
assert.equal(tabs.length, 2);
|
||||
assert.strictEqual(tabs[1].previousSibling, tabs[0].nextSibling);
|
||||
assert.equal(tabs[0].previousSibling.textContent,
|
||||
'na💢ti te, inquit, sumus aliquando otiosum, certe a ');
|
||||
assert.equal(tabs[1].previousSibling.textContent,
|
||||
'udiam, quid sit, ');
|
||||
assert.equal(tabs[1].nextSibling.textContent, 'quod Epicurum');
|
||||
});
|
||||
|
||||
test('merging multiple other hls', function() {
|
||||
@@ -406,7 +419,8 @@ limitations under the License.
|
||||
assert.equal(content.childNodes.length, 4);
|
||||
var hl = content.querySelector('hl.some');
|
||||
assert.strictEqual(content.firstChild, hl.previousSibling);
|
||||
assert.equal(hl.childNodes.length, 1);
|
||||
assert.equal(hl.childNodes.length, 5);
|
||||
assert.equal(content.querySelectorAll('span.tab').length, 2);
|
||||
assert.equal(hl.textContent,
|
||||
'a💢ti te, inquit, sumus aliquando otiosum, certe a udiam, ' +
|
||||
'quid sit, quod Epicuru');
|
||||
@@ -435,7 +449,7 @@ limitations under the License.
|
||||
// After: na💢ti <hl class="foo">te, in</hl><hl class="some">quit, ...
|
||||
element._applyRangedHighlight('some', 140, 12, 140, 21, 'left');
|
||||
var hl = content.querySelector('hl.some');
|
||||
assert.equal(hl.outerHTML, '<hl class="some">quit, sum</hl>');
|
||||
assert.equal(hl.textContent, 'quit, sum');
|
||||
assert.equal(
|
||||
hl.previousSibling.outerHTML, '<hl class="foo">te, in</hl>');
|
||||
});
|
||||
@@ -445,7 +459,7 @@ limitations under the License.
|
||||
// After: <hl class="foo">t</hl><hl="some">e, i</hl><hl class="foo">n..
|
||||
element._applyRangedHighlight('some', 140, 7, 140, 12, 'left');
|
||||
var hl = content.querySelector('hl.some');
|
||||
assert.equal(hl.outerHTML, '<hl class="some">e, in</hl>');
|
||||
assert.equal(hl.textContent, 'e, in');
|
||||
assert.equal(hl.previousSibling.outerHTML, '<hl class="foo">t</hl>');
|
||||
assert.equal(hl.nextSibling.outerHTML, '<hl class="foo">quit</hl>');
|
||||
});
|
||||
@@ -453,7 +467,7 @@ limitations under the License.
|
||||
test('hl starts and ends in different hls', function() {
|
||||
element._applyRangedHighlight('some', 140, 8, 140, 27, 'left');
|
||||
var hl = content.querySelector('hl.some');
|
||||
assert.equal(hl.outerHTML, '<hl class="some">, inquit, sumus ali</hl>');
|
||||
assert.equal(hl.textContent, ', inquit, sumus ali');
|
||||
assert.equal(hl.previousSibling.outerHTML, '<hl class="foo">te</hl>');
|
||||
assert.equal(hl.nextSibling.outerHTML, '<hl class="bar">quando</hl>');
|
||||
});
|
||||
@@ -468,9 +482,7 @@ limitations under the License.
|
||||
test('hl starting and ending in boundaries', function() {
|
||||
element._applyRangedHighlight('some', 140, 6, 140, 33, 'left');
|
||||
var hl = content.querySelector('hl.some');
|
||||
assert.equal(
|
||||
hl.outerHTML, '<hl class="some">te, inquit, sumus aliquando</hl>');
|
||||
assert.notOk(content.querySelector('.foo'));
|
||||
assert.equal(hl.textContent, 'te, inquit, sumus aliquando');
|
||||
assert.notOk(content.querySelector('.bar'));
|
||||
});
|
||||
|
||||
@@ -482,7 +494,7 @@ limitations under the License.
|
||||
assert.equal(hl.outerHTML, '<hl class="some">a💢t</hl>');
|
||||
});
|
||||
|
||||
test('growing hl left including another hl', function() {
|
||||
test('growing hl right including another hl', function() {
|
||||
element._applyRangedHighlight('some', 140, 1, 140, 4, 'left');
|
||||
element._applyRangedHighlight('some', 140, 3, 140, 10, 'left');
|
||||
assert.equal(content.querySelectorAll('hl.some').length, 1);
|
||||
@@ -491,7 +503,7 @@ limitations under the License.
|
||||
assert.equal(hl.nextSibling.outerHTML, '<hl class="foo">inquit</hl>');
|
||||
});
|
||||
|
||||
test('growing hl right to start of line', function() {
|
||||
test('growing hl left to start of line', function() {
|
||||
element._applyRangedHighlight('some', 140, 2, 140, 5, 'left');
|
||||
element._applyRangedHighlight('some', 140, 0, 140, 3, 'left');
|
||||
assert.equal(content.querySelectorAll('hl.some').length, 1);
|
||||
@@ -499,6 +511,14 @@ limitations under the License.
|
||||
assert.equal(hl.outerHTML, '<hl class="some">na💢ti</hl>');
|
||||
assert.strictEqual(content.firstChild, hl);
|
||||
});
|
||||
|
||||
test('splitting hl containing a tab', function() {
|
||||
element._applyRangedHighlight('some', 140, 63, 140, 72, 'left');
|
||||
assert.equal(content.querySelector('hl.some').textContent, 'sit, quod');
|
||||
element._applyRangedHighlight('another', 140, 66, 140, 81, 'left');
|
||||
assert.equal(content.querySelector('hl.another').textContent,
|
||||
', quod Epicurum');
|
||||
});
|
||||
});
|
||||
|
||||
test('_applyAllHighlights', function() {
|
||||
@@ -644,6 +664,21 @@ limitations under the License.
|
||||
});
|
||||
|
||||
test('multiline', function() {
|
||||
var startContent = stubContent(119, 'right');
|
||||
var endContent = stubContent(120, 'right');
|
||||
emulateSelection(
|
||||
startContent.firstChild, 10, endContent.lastChild, 7);
|
||||
assert.isTrue(element.isRangeSelected());
|
||||
assert.deepEqual(getActionRange(), {
|
||||
startLine: 119,
|
||||
startChar: 10,
|
||||
endLine: 120,
|
||||
endChar: 34,
|
||||
});
|
||||
assert.equal(getActionSide(), 'right');
|
||||
});
|
||||
|
||||
test('multiline grow end highlight over tabs', function() {
|
||||
var startContent = stubContent(119, 'right');
|
||||
var endContent = stubContent(120, 'right');
|
||||
emulateSelection(startContent.firstChild, 10, endContent.firstChild, 2);
|
||||
@@ -693,7 +728,7 @@ limitations under the License.
|
||||
|
||||
test('multiple hl', function() {
|
||||
var content = stubContent(140, 'left');
|
||||
var hl = content.querySelectorAll('hl')[3];
|
||||
var hl = content.querySelectorAll('hl')[4];
|
||||
emulateSelection(content.firstChild, 2, hl.firstChild, 2);
|
||||
assert.isTrue(element.isRangeSelected());
|
||||
assert.deepEqual(getActionRange(), {
|
||||
@@ -766,7 +801,7 @@ limitations under the License.
|
||||
test('ends in context element', function() {
|
||||
var contextControl = diff.querySelector('.contextControl');
|
||||
var content = stubContent(141, 'left');
|
||||
emulateSelection(content.firstChild, 7, contextControl, 0);
|
||||
emulateSelection(content.firstChild, 2, contextControl, 0);
|
||||
// TODO (viktard): Select nearest line.
|
||||
assert.isFalse(element.isRangeSelected());
|
||||
});
|
||||
@@ -785,6 +820,35 @@ limitations under the License.
|
||||
assert.equal(getActionSide(), 'right');
|
||||
});
|
||||
|
||||
test('ends at a tab', function() {
|
||||
var content = stubContent(140, 'left');
|
||||
emulateSelection(
|
||||
content.firstChild, 1, content.querySelector('span'), 0);
|
||||
assert.isTrue(element.isRangeSelected());
|
||||
assert.deepEqual(getActionRange(), {
|
||||
startLine: 140,
|
||||
startChar: 1,
|
||||
endLine: 140,
|
||||
endChar: 51,
|
||||
});
|
||||
assert.equal(getActionSide(), 'left');
|
||||
});
|
||||
|
||||
test('starts at a tab', function() {
|
||||
var content = stubContent(140, 'left');
|
||||
emulateSelection(
|
||||
content.querySelectorAll('hl')[3], 0,
|
||||
content.querySelectorAll('span')[1], 0);
|
||||
assert.isTrue(element.isRangeSelected());
|
||||
assert.deepEqual(getActionRange(), {
|
||||
startLine: 140,
|
||||
startChar: 51,
|
||||
endLine: 140,
|
||||
endChar: 68,
|
||||
});
|
||||
assert.equal(getActionSide(), 'left');
|
||||
});
|
||||
|
||||
// TODO (viktard): Selection starts in line number.
|
||||
// TODO (viktard): Empty lines in selection start.
|
||||
// TODO (viktard): Empty lines in selection end.
|
||||
|
||||
Reference in New Issue
Block a user