Fine-tune linkification technique for link previews
This commit is contained in:
parent
021e807180
commit
858c7e629f
3 changed files with 104 additions and 3 deletions
|
@ -1,5 +1,6 @@
|
||||||
/* global URL */
|
/* global URL */
|
||||||
|
|
||||||
|
const { isNumber, compact } = require('lodash');
|
||||||
const he = require('he');
|
const he = require('he');
|
||||||
const LinkifyIt = require('linkify-it');
|
const LinkifyIt = require('linkify-it');
|
||||||
|
|
||||||
|
@ -96,9 +97,28 @@ function getImageMetaTag(html) {
|
||||||
return _getMetaTag(html, META_IMAGE);
|
return _getMetaTag(html, META_IMAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
function findLinks(text) {
|
function findLinks(text, caretLocation) {
|
||||||
|
const haveCaretLocation = isNumber(caretLocation);
|
||||||
|
const textLength = text ? text.length : 0;
|
||||||
|
|
||||||
const matches = linkify.match(text || '') || [];
|
const matches = linkify.match(text || '') || [];
|
||||||
return matches.map(match => match.text);
|
return compact(
|
||||||
|
matches.map(match => {
|
||||||
|
if (!haveCaretLocation) {
|
||||||
|
return match.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match.lastIndex === textLength && caretLocation === textLength) {
|
||||||
|
return match.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match.index > caretLocation || match.lastIndex < caretLocation) {
|
||||||
|
return match.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDomain(url) {
|
function getDomain(url) {
|
||||||
|
|
|
@ -1700,6 +1700,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageText = this.$messageField.val().trim();
|
const messageText = this.$messageField.val().trim();
|
||||||
|
const caretLocation = this.$messageField.get(0).selectionStart;
|
||||||
|
|
||||||
if (!messageText) {
|
if (!messageText) {
|
||||||
this.resetLinkPreview();
|
this.resetLinkPreview();
|
||||||
|
@ -1709,7 +1710,10 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const links = window.Signal.LinkPreviews.findLinks(messageText);
|
const links = window.Signal.LinkPreviews.findLinks(
|
||||||
|
messageText,
|
||||||
|
caretLocation
|
||||||
|
);
|
||||||
const { currentlyMatchedLink } = this;
|
const { currentlyMatchedLink } = this;
|
||||||
if (links.includes(currentlyMatchedLink)) {
|
if (links.includes(currentlyMatchedLink)) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const { assert } = require('chai');
|
const { assert } = require('chai');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
findLinks,
|
||||||
getTitleMetaTag,
|
getTitleMetaTag,
|
||||||
getImageMetaTag,
|
getImageMetaTag,
|
||||||
isLinkInWhitelist,
|
isLinkInWhitelist,
|
||||||
|
@ -228,4 +229,80 @@ describe('Link previews', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#findLinks', () => {
|
||||||
|
it('returns all links if no caretLocation is provided', () => {
|
||||||
|
const text =
|
||||||
|
'Check out this link: https://github.com/signalapp/Signal-Desktop\nAnd this one too: https://github.com/signalapp/Signal-Android';
|
||||||
|
|
||||||
|
const expected = [
|
||||||
|
'https://github.com/signalapp/Signal-Desktop',
|
||||||
|
'https://github.com/signalapp/Signal-Android',
|
||||||
|
];
|
||||||
|
|
||||||
|
const actual = findLinks(text);
|
||||||
|
assert.deepEqual(expected, actual);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes all links if cursor is not in a link', () => {
|
||||||
|
const text =
|
||||||
|
'Check out this link: https://github.com/signalapp/Signal-Desktop\nAnd this one too: https://github.com/signalapp/Signal-Android';
|
||||||
|
const caretLocation = 10;
|
||||||
|
|
||||||
|
const expected = [
|
||||||
|
'https://github.com/signalapp/Signal-Desktop',
|
||||||
|
'https://github.com/signalapp/Signal-Android',
|
||||||
|
];
|
||||||
|
|
||||||
|
const actual = findLinks(text, caretLocation);
|
||||||
|
assert.deepEqual(expected, actual);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('excludes a link not at the end if the caret is inside of it', () => {
|
||||||
|
const text =
|
||||||
|
'Check out this link: https://github.com/signalapp/Signal-Desktop\nAnd this one too: https://github.com/signalapp/Signal-Android';
|
||||||
|
const caretLocation = 30;
|
||||||
|
|
||||||
|
const expected = ['https://github.com/signalapp/Signal-Android'];
|
||||||
|
|
||||||
|
const actual = findLinks(text, caretLocation);
|
||||||
|
assert.deepEqual(expected, actual);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('excludes a link not at the end if the caret is at its end', () => {
|
||||||
|
const text =
|
||||||
|
'Check out this link: https://github.com/signalapp/Signal-Desktop\nAnd this one too: https://github.com/signalapp/Signal-Android';
|
||||||
|
const caretLocation = 64;
|
||||||
|
|
||||||
|
const expected = ['https://github.com/signalapp/Signal-Android'];
|
||||||
|
|
||||||
|
const actual = findLinks(text, caretLocation);
|
||||||
|
assert.deepEqual(expected, actual);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('excludes a link at the end of the caret is inside of it', () => {
|
||||||
|
const text =
|
||||||
|
'Check out this link: https://github.com/signalapp/Signal-Desktop\nAnd this one too: https://github.com/signalapp/Signal-Android';
|
||||||
|
const caretLocation = 100;
|
||||||
|
|
||||||
|
const expected = ['https://github.com/signalapp/Signal-Desktop'];
|
||||||
|
|
||||||
|
const actual = findLinks(text, caretLocation);
|
||||||
|
assert.deepEqual(expected, actual);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes link at the end if cursor is at its end', () => {
|
||||||
|
const text =
|
||||||
|
'Check out this link: https://github.com/signalapp/Signal-Desktop\nAnd this one too: https://github.com/signalapp/Signal-Android';
|
||||||
|
const caretLocation = text.length;
|
||||||
|
|
||||||
|
const expected = [
|
||||||
|
'https://github.com/signalapp/Signal-Desktop',
|
||||||
|
'https://github.com/signalapp/Signal-Android',
|
||||||
|
];
|
||||||
|
|
||||||
|
const actual = findLinks(text, caretLocation);
|
||||||
|
assert.deepEqual(expected, actual);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue