Merge changes Ia1f80d5b,Ic98530bf
* changes:
Fix token highlighting after surrogate pairs
Make assertAnnotation calls more obvious
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/token-highlight-layer.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/token-highlight-layer.ts
index 1e5dd65..e9076aa 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-builder/token-highlight-layer.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-builder/token-highlight-layer.ts
@@ -139,11 +139,17 @@
let atLeastOneTokenMatched = false;
while ((match = tokenMatcher.exec(text))) {
const token = match[0];
- const index = match.index;
- const length = token.length;
+
// Binary files encoded as text for example can have super long lines
// with super long tokens. Let's guard against this scenario.
- if (length > TOKEN_LENGTH_LIMIT) continue;
+ if (token.length > TOKEN_LENGTH_LIMIT) continue;
+
+ // This is to correctly count surrogate pairs in text and token.
+ // If the index calculation becomes a hotspot, we could precompute a code
+ // unit to code point index map for text before iterating over the results
+ const index = GrAnnotation.getStringLength(text.slice(0, match.index));
+ const length = GrAnnotation.getStringLength(token);
+
atLeastOneTokenMatched = true;
const highlightTypeClass =
token === this.currentHighlight ? CSS_HIGHLIGHT : '';
@@ -339,7 +345,7 @@
start_line: line,
start_column: index + 1, // 1-based inclusive
end_line: line,
- end_column: index + token.length, // 1-based inclusive
+ end_column: index + GrAnnotation.getStringLength(token), // 1-based inclusive
};
this.tokenHighlightListener({token, element, side, range});
}
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/token-highlight-layer_test.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/token-highlight-layer_test.ts
index 1beed46..8fd03bb 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-builder/token-highlight-layer_test.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-builder/token-highlight-layer_test.ts
@@ -105,15 +105,17 @@
suite('annotate', () => {
function assertAnnotation(
args: any[],
- el: HTMLElement,
- start: number,
- length: number,
- cssClass: string
+ expected: {
+ parent: HTMLElement;
+ offset: number;
+ length: number;
+ cssClass: string;
+ }
) {
- assert.equal(args[0], el);
- assert.equal(args[1], start);
- assert.equal(args[2], length);
- assert.equal(args[3], cssClass);
+ assert.equal(args[0], expected.parent);
+ assert.equal(args[1], expected.offset);
+ assert.equal(args[2], expected.length);
+ assert.equal(args[3], expected.cssClass);
}
test('annotate adds css token', () => {
@@ -121,27 +123,51 @@
const el = createLine('these are words');
annotate(el);
assert.isTrue(annotateElementStub.calledThrice);
- assertAnnotation(
- annotateElementStub.args[0],
- el,
- 0,
- 5,
- 'tk-text-these tk-index-0 token '
- );
- assertAnnotation(
- annotateElementStub.args[1],
- el,
- 6,
- 3,
- 'tk-text-are tk-index-6 token '
- );
- assertAnnotation(
- annotateElementStub.args[2],
- el,
- 10,
- 5,
- 'tk-text-words tk-index-10 token '
- );
+ assertAnnotation(annotateElementStub.args[0], {
+ parent: el,
+ offset: 0,
+ length: 5,
+ cssClass: 'tk-text-these tk-index-0 token ',
+ });
+ assertAnnotation(annotateElementStub.args[1], {
+ parent: el,
+ offset: 6,
+ length: 3,
+ cssClass: 'tk-text-are tk-index-6 token ',
+ });
+ assertAnnotation(annotateElementStub.args[2], {
+ parent: el,
+ offset: 10,
+ length: 5,
+ cssClass: 'tk-text-words tk-index-10 token ',
+ });
+ });
+
+ test('annotate adds css tokens w/ emojis', () => {
+ const annotateElementStub = sinon.stub(GrAnnotation, 'annotateElement');
+ const el = createLine('these 💩 are 👨👩👧👦 words');
+
+ annotate(el);
+
+ assert.isTrue(annotateElementStub.calledThrice);
+ assertAnnotation(annotateElementStub.args[0], {
+ parent: el,
+ offset: 0,
+ length: 5,
+ cssClass: 'tk-text-these tk-index-0 token ',
+ });
+ assertAnnotation(annotateElementStub.args[1], {
+ parent: el,
+ offset: 8,
+ length: 3,
+ cssClass: 'tk-text-are tk-index-8 token ',
+ });
+ assertAnnotation(annotateElementStub.args[2], {
+ parent: el,
+ offset: 20,
+ length: 5,
+ cssClass: 'tk-text-words tk-index-20 token ',
+ });
});
test('annotate adds mouse handlers', () => {