ES6ify gr-linked-text/*

Change-Id: I28622a432c57a9309a4a93aec2b6aae65bcbd4fa
This commit is contained in:
Kasper Nilsson
2018-08-17 14:31:07 -07:00
parent cb99177699
commit 4e418c40e4
3 changed files with 129 additions and 129 deletions

View File

@@ -60,15 +60,15 @@
* commentLink patterns
*/
_contentOrConfigChanged(content, config) {
var output = Polymer.dom(this.$.output);
const output = Polymer.dom(this.$.output);
output.textContent = '';
var parser = new GrLinkTextParser(config,
const parser = new GrLinkTextParser(config,
this._handleParseResult.bind(this), this.removeZeroWidthSpace);
parser.parse(content);
// Ensure that links originating from HTML commentlink configs open in a
// new tab. @see Issue 5567
output.querySelectorAll('a').forEach(function(anchor) {
output.querySelectorAll('a').forEach(anchor => {
anchor.setAttribute('target', '_blank');
anchor.setAttribute('rel', 'noopener');
});
@@ -87,9 +87,9 @@
* @param {DocumentFragment|undefined} fragment
*/
_handleParseResult(text, href, fragment) {
var output = Polymer.dom(this.$.output);
const output = Polymer.dom(this.$.output);
if (href) {
var a = document.createElement('a');
const a = document.createElement('a');
a.href = href;
a.textContent = text;
a.target = '_blank';

View File

@@ -37,29 +37,29 @@ limitations under the License.
</test-fixture>
<script>
suite('gr-linked-text tests', function() {
var element;
var sandbox;
suite('gr-linked-text tests', () => {
let element;
let sandbox;
setup(function() {
setup(() => {
element = fixture('basic');
sandbox = sinon.sandbox.create();
element.config = {
ph: {
match: '([Bb]ug|[Ii]ssue)\\s*#?(\\d+)',
link: 'https://code.google.com/p/gerrit/issues/detail?id=$2'
link: 'https://code.google.com/p/gerrit/issues/detail?id=$2',
},
changeid: {
match: '(I[0-9a-f]{8,40})',
link: '#/q/$1'
link: '#/q/$1',
},
changeid2: {
match: 'Change-Id: +(I[0-9a-f]{8,40})',
link: '#/q/$1'
link: '#/q/$1',
},
googlesearch: {
match: 'google:(.+)',
link: 'https://bing.com/search?q=$1', // html should supercede link.
link: 'https://bing.com/search?q=$1', // html should supercede link.
html: '<a href="https://google.com/search?q=$1">$1</a>',
},
hashedhtml: {
@@ -74,27 +74,27 @@ limitations under the License.
};
});
teardown(function() {
teardown(() => {
sandbox.restore();
});
test('URL pattern was parsed and linked.', function() {
// Reguar inline link.
var url = 'https://code.google.com/p/gerrit/issues/detail?id=3650';
test('URL pattern was parsed and linked.', () => {
// Regular inline link.
const url = 'https://code.google.com/p/gerrit/issues/detail?id=3650';
element.content = url;
var linkEl = element.$.output.childNodes[0];
const linkEl = element.$.output.childNodes[0];
assert.equal(linkEl.target, '_blank');
assert.equal(linkEl.rel, 'noopener');
assert.equal(linkEl.href, url);
assert.equal(linkEl.textContent, url);
});
test('Bug pattern was parsed and linked', function() {
test('Bug pattern was parsed and linked', () => {
// "Issue/Bug" pattern.
element.content = 'Issue 3650';
var linkEl = element.$.output.childNodes[0];
var url = 'https://code.google.com/p/gerrit/issues/detail?id=3650';
let linkEl = element.$.output.childNodes[0];
const url = 'https://code.google.com/p/gerrit/issues/detail?id=3650';
assert.equal(linkEl.target, '_blank');
assert.equal(linkEl.href, url);
assert.equal(linkEl.textContent, 'Issue 3650');
@@ -107,26 +107,26 @@ limitations under the License.
assert.equal(linkEl.textContent, 'Bug 3650');
});
test('Change-Id pattern was parsed and linked', function() {
test('Change-Id pattern was parsed and linked', () => {
// "Change-Id:" pattern.
var changeID = 'I11d6a37f5e9b5df0486f6c922d8836dfa780e03e';
var prefix = 'Change-Id: ';
const changeID = 'I11d6a37f5e9b5df0486f6c922d8836dfa780e03e';
const prefix = 'Change-Id: ';
element.content = prefix + changeID;
var textNode = element.$.output.childNodes[0];
var linkEl = element.$.output.childNodes[1];
const textNode = element.$.output.childNodes[0];
const linkEl = element.$.output.childNodes[1];
assert.equal(textNode.textContent, prefix);
var url = '/q/' + changeID;
const url = '/q/' + changeID;
assert.equal(linkEl.target, '_blank');
// Since url is a path, the host is added automatically.
assert.isTrue(linkEl.href.endsWith(url));
assert.equal(linkEl.textContent, changeID);
});
test('Multiple matches', function() {
test('Multiple matches', () => {
element.content = 'Issue 3650\nIssue 3450';
var linkEl1 = element.$.output.childNodes[0];
var linkEl2 = element.$.output.childNodes[2];
const linkEl1 = element.$.output.childNodes[0];
const linkEl2 = element.$.output.childNodes[2];
assert.equal(linkEl1.target, '_blank');
assert.equal(linkEl1.href,
@@ -139,22 +139,22 @@ limitations under the License.
assert.equal(linkEl2.textContent, 'Issue 3450');
});
test('Change-Id pattern parsed before bug pattern', function() {
test('Change-Id pattern parsed before bug pattern', () => {
// "Change-Id:" pattern.
var changeID = 'I11d6a37f5e9b5df0486f6c922d8836dfa780e03e';
var prefix = 'Change-Id: ';
const changeID = 'I11d6a37f5e9b5df0486f6c922d8836dfa780e03e';
const prefix = 'Change-Id: ';
// "Issue/Bug" pattern.
var bug = 'Issue 3650';
const bug = 'Issue 3650';
var changeUrl = '/q/' + changeID;
var bugUrl = 'https://code.google.com/p/gerrit/issues/detail?id=3650';
const changeUrl = '/q/' + changeID;
const bugUrl = 'https://code.google.com/p/gerrit/issues/detail?id=3650';
element.content = prefix + changeID + bug;
var textNode = element.$.output.childNodes[0];
var changeLinkEl = element.$.output.childNodes[1];
var bugLinkEl = element.$.output.childNodes[2];
const textNode = element.$.output.childNodes[0];
const changeLinkEl = element.$.output.childNodes[1];
const bugLinkEl = element.$.output.childNodes[2];
assert.equal(textNode.textContent, prefix);
@@ -167,41 +167,41 @@ limitations under the License.
assert.equal(bugLinkEl.textContent, 'Issue 3650');
});
test('html field in link config', function() {
test('html field in link config', () => {
element.content = 'google:do a barrel roll';
var linkEl = element.$.output.childNodes[0];
const linkEl = element.$.output.childNodes[0];
assert.equal(linkEl.getAttribute('href'),
'https://google.com/search?q=do a barrel roll');
assert.equal(linkEl.textContent, 'do a barrel roll');
});
test('removing hash from links', function() {
test('removing hash from links', () => {
element.content = 'hash:foo';
var linkEl = element.$.output.childNodes[0];
const linkEl = element.$.output.childNodes[0];
assert.isTrue(linkEl.href.endsWith('/awesomesauce'));
assert.equal(linkEl.textContent, 'foo');
});
test('disabled config', function() {
test('disabled config', () => {
element.content = 'foo:baz';
assert.equal(element.$.output.innerHTML, 'foo:baz');
});
test('R=email labels link correctly', function() {
test('R=email labels link correctly', () => {
element.removeZeroWidthSpace = true;
element.content = 'R=\u200Btest@google.com';
assert.equal(element.$.output.textContent, 'R=test@google.com');
assert.equal(element.$.output.innerHTML.match(/(R=<a)/g).length, 1);
});
test('CC=email labels link correctly', function() {
test('CC=email labels link correctly', () => {
element.removeZeroWidthSpace = true;
element.content = 'CC=\u200Btest@google.com';
assert.equal(element.$.output.textContent, 'CC=test@google.com');
assert.equal(element.$.output.innerHTML.match(/(CC=<a)/g).length, 1);
});
test('only {http,https,mailto} protocols are linkified', function() {
test('only {http,https,mailto} protocols are linkified', () => {
element.content = 'xx mailto:test@google.com yy';
let links = element.$.output.querySelectorAll('a');
assert.equal(links.length, 1);
@@ -226,7 +226,7 @@ limitations under the License.
assert.equal(links.length, 0);
});
test('overlapping links', function() {
test('overlapping links', () => {
element.config = {
b1: {
match: '(B:\\s*)(\\d+)',
@@ -238,7 +238,7 @@ limitations under the License.
},
};
element.content = '- B: 123, 45';
var links = Polymer.dom(element.root).querySelectorAll('a');
const links = Polymer.dom(element.root).querySelectorAll('a');
assert.equal(links.length, 2);
assert.equal(element.$$('span').textContent, '- B: 123, 45');
@@ -250,31 +250,31 @@ limitations under the License.
assert.equal(links[1].textContent, '45');
});
test('_contentOrConfigChanged called with config', function() {
var contentStub = sandbox.stub(element, '_contentChanged');
var contentConfigStub = sandbox.stub(element, '_contentOrConfigChanged');
test('_contentOrConfigChanged called with config', () => {
const contentStub = sandbox.stub(element, '_contentChanged');
const contentConfigStub = sandbox.stub(element, '_contentOrConfigChanged');
element.content = 'some text';
assert.isTrue(contentStub.called);
assert.isTrue(contentConfigStub.called);
});
});
suite('gr-linked-text with null config', function() {
var element;
var sandbox;
suite('gr-linked-text with null config', () => {
let element;
let sandbox;
setup(function() {
setup(() => {
element = fixture('basic');
sandbox = sinon.sandbox.create();
});
teardown(function() {
teardown(() => {
sandbox.restore();
});
test('_contentOrConfigChanged not called without config', function() {
var contentStub = sandbox.stub(element, '_contentChanged');
var contentConfigStub = sandbox.stub(element, '_contentOrConfigChanged');
test('_contentOrConfigChanged not called without config', () => {
const contentStub = sandbox.stub(element, '_contentChanged');
const contentConfigStub = sandbox.stub(element, '_contentOrConfigChanged');
element.content = 'some text';
assert.isTrue(contentStub.called);
assert.isFalse(contentConfigStub.called);

View File

@@ -41,8 +41,8 @@
* @param {Object|null|undefined} linkConfig Comment links as specified by the
* commentlinks field on a project config.
* @param {Function} callback The callback to be fired when an intermediate
* parse result is emitted. The callback is passed text and href strings if
* a link is to be created, or a document fragment otherwise.
* parse result is emitted. The callback is passed text and href strings
* if a link is to be created, or a document fragment otherwise.
* @param {boolean|undefined} opt_removeZeroWidthSpace If true, zero-width
* spaces will be removed from R=<email> and CC=<email> expressions.
*/
@@ -73,14 +73,14 @@
*/
GrLinkTextParser.prototype.processLinks = function(text, outputArray) {
this.sortArrayReverse(outputArray);
var fragment = document.createDocumentFragment();
var cursor = text.length;
const fragment = document.createDocumentFragment();
let cursor = text.length;
// Start inserting linkified URLs from the end of the String. That way, the
// string positions of the items don't change as we iterate through.
outputArray.forEach(function(item) {
// Add any text between the current linkified item and the item added before
// if it exists.
outputArray.forEach(item => {
// Add any text between the current linkified item and the item added
// before if it exists.
if (item.position + item.length !== cursor) {
fragment.insertBefore(
document.createTextNode(
@@ -130,32 +130,32 @@
*/
GrLinkTextParser.prototype.addItem =
function(text, href, html, position, length, outputArray) {
var htmlOutput = '';
let htmlOutput = '';
if (href) {
var a = document.createElement('a');
a.href = href;
a.textContent = text;
a.target = '_blank';
a.rel = 'noopener';
htmlOutput = a;
} else if (html) {
var fragment = document.createDocumentFragment();
if (href) {
const a = document.createElement('a');
a.href = href;
a.textContent = text;
a.target = '_blank';
a.rel = 'noopener';
htmlOutput = a;
} else if (html) {
const fragment = document.createDocumentFragment();
// Create temporary div to hold the nodes in.
var div = document.createElement('div');
div.innerHTML = html;
while (div.firstChild) {
fragment.appendChild(div.firstChild);
}
htmlOutput = fragment;
}
const div = document.createElement('div');
div.innerHTML = html;
while (div.firstChild) {
fragment.appendChild(div.firstChild);
}
htmlOutput = fragment;
}
outputArray.push({
html: htmlOutput,
position: position,
length: length,
});
};
outputArray.push({
html: htmlOutput,
position,
length,
});
};
/**
* Create a CommentLinkItem for a link and append it to the given output
@@ -171,9 +171,9 @@
*/
GrLinkTextParser.prototype.addLink =
function(text, href, position, length, outputArray) {
if (!text || this.hasOverlap(position, length, outputArray)) { return; }
this.addItem(text, href, null, position, length, outputArray);
};
if (!text || this.hasOverlap(position, length, outputArray)) { return; }
this.addItem(text, href, null, position, length, outputArray);
};
/**
* Create a CommentLinkItem specified by an HTMl string and append it to the
@@ -188,9 +188,9 @@
*/
GrLinkTextParser.prototype.addHTML =
function(html, position, length, outputArray) {
if (this.hasOverlap(position, length, outputArray)) { return; }
this.addItem(null, null, html, position, length, outputArray);
};
if (this.hasOverlap(position, length, outputArray)) { return; }
this.addItem(null, null, html, position, length, outputArray);
};
/**
* Does the given range overlap with anything already in the item list.
@@ -200,18 +200,18 @@
*/
GrLinkTextParser.prototype.hasOverlap =
function(position, length, outputArray) {
var endPosition = position + length;
for (var i = 0; i < outputArray.length; i++) {
var arrayItemStart = outputArray[i].position;
var arrayItemEnd = outputArray[i].position + outputArray[i].length;
if ((position >= arrayItemStart && position < arrayItemEnd) ||
const endPosition = position + length;
for (let i = 0; i < outputArray.length; i++) {
const arrayItemStart = outputArray[i].position;
const arrayItemEnd = outputArray[i].position + outputArray[i].length;
if ((position >= arrayItemStart && position < arrayItemEnd) ||
(endPosition > arrayItemStart && endPosition <= arrayItemEnd) ||
(position === arrayItemStart && position === arrayItemEnd)) {
return true;
}
}
return false;
};
}
}
return false;
};
/**
* Parse the given source text and emit callbacks for the items that are
@@ -241,9 +241,9 @@
text = text.replace(/^(CC|R)=\u200B/gm, '$1=');
}
// If the href is provided then ba-linkify has recognized it as a URL. If the
// source text does not include a protocol, the protocol will be added by
// ba-linkify. Create the link if the href is provided and its protocol
// If the href is provided then ba-linkify has recognized it as a URL. If
// the source text does not include a protocol, the protocol will be added
// by ba-linkify. Create the link if the href is provided and its protocol
// matches the expected pattern.
if (href && URL_PROTOCOL_PATTERN.test(href)) {
this.addText(text, href);
@@ -262,9 +262,10 @@
* object.
*/
GrLinkTextParser.prototype.parseLinks = function(text, patterns) {
// The outputArray is used to store all of the matches found for all patterns.
var outputArray = [];
for (var p in patterns) {
// The outputArray is used to store all of the matches found for all
// patterns.
const outputArray = [];
for (const p in patterns) {
if (patterns[p].enabled != null && patterns[p].enabled == false) {
continue;
}
@@ -279,38 +280,37 @@
}
}
var pattern = new RegExp(patterns[p].match, 'g');
const pattern = new RegExp(patterns[p].match, 'g');
var match;
var textToCheck = text;
var susbtrIndex = 0;
let match;
let textToCheck = text;
let susbtrIndex = 0;
while ((match = pattern.exec(textToCheck)) != null) {
textToCheck = textToCheck.substr(match.index + match[0].length);
var result = match[0].replace(pattern,
let result = match[0].replace(pattern,
patterns[p].html || patterns[p].link);
let i;
// Skip portion of replacement string that is equal to original.
for (var i = 0; i < result.length; i++) {
if (result[i] !== match[0][i]) {
break;
}
for (i = 0; i < result.length; i++) {
if (result[i] !== match[0][i]) { break; }
}
result = result.slice(i);
if (patterns[p].html) {
this.addHTML(
result,
susbtrIndex + match.index + i,
match[0].length - i,
outputArray);
result,
susbtrIndex + match.index + i,
match[0].length - i,
outputArray);
} else if (patterns[p].link) {
this.addLink(
match[0],
result,
susbtrIndex + match.index + i,
match[0].length - i,
outputArray);
match[0],
result,
susbtrIndex + match.index + i,
match[0].length - i,
outputArray);
} else {
throw Error('linkconfig entry ' + p +
' doesnt contain a link or html attribute.');