[MFM] Improve URL parsing

Fix #3368
This commit is contained in:
syuilo 2018-11-22 05:02:38 +09:00
parent 67df681a48
commit 8cbb961493
No known key found for this signature in database
GPG Key ID: BDC4C49D06AB9D69
2 changed files with 46 additions and 10 deletions

View File

@ -245,11 +245,25 @@ const mfm = P.createLanguage({
const match = text.match(/^https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.,=\+\-]+/); const match = text.match(/^https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.,=\+\-]+/);
if (!match) return P.makeFailure(i, 'not a url'); if (!match) return P.makeFailure(i, 'not a url');
let url = match[0]; let url = match[0];
const before = input[i - 1]; let pendingBracket = 0;
const end = url.split('').findIndex(char => {
if (char == ')') {
if (pendingBracket > 0) {
pendingBracket--;
return false;
} else {
return true;
}
} else if (char == '(') {
pendingBracket++;
return false;
} else {
return false;
}
});
if (end > 0) url = url.substr(0, end);
if (url.endsWith('.')) url = url.substr(0, url.lastIndexOf('.')); if (url.endsWith('.')) url = url.substr(0, url.lastIndexOf('.'));
if (url.endsWith(',')) url = url.substr(0, url.lastIndexOf(',')); if (url.endsWith(',')) url = url.substr(0, url.lastIndexOf(','));
if (url.endsWith(')') && before == '(') url = url.substr(0, url.lastIndexOf(')'));
if (url.endsWith(']') && before == '[') url = url.substr(0, url.lastIndexOf(']'));
return P.makeSuccess(i + url.length, url); return P.makeSuccess(i + url.length, url);
}) })
.map(x => makeNode('url', { url: x })), .map(x => makeNode('url', { url: x })),

View File

@ -381,6 +381,15 @@ describe('Text', () => {
], tokens); ], tokens);
}); });
it('ignore parent brackets 2', () => {
const tokens = analyze('(foo https://example.com/foo)');
assert.deepEqual([
text('(foo '),
node('url', { url: 'https://example.com/foo' }),
text(')')
], tokens);
});
it('ignore parent brackets with internal brackets', () => { it('ignore parent brackets with internal brackets', () => {
const tokens = analyze('(https://example.com/foo(bar))'); const tokens = analyze('(https://example.com/foo(bar))');
assert.deepEqual([ assert.deepEqual([
@ -391,7 +400,8 @@ describe('Text', () => {
}); });
}); });
it('link', () => { describe('link', () => {
it('simple', () => {
const tokens = analyze('[foo](https://example.com)'); const tokens = analyze('[foo](https://example.com)');
assert.deepEqual([ assert.deepEqual([
nodeWithChildren('link', [ nodeWithChildren('link', [
@ -400,6 +410,18 @@ describe('Text', () => {
], tokens); ], tokens);
}); });
it('in text', () => {
const tokens = analyze('before[foo](https://example.com)after');
assert.deepEqual([
text('before'),
nodeWithChildren('link', [
text('foo')
], { url: 'https://example.com', silent: false }),
text('after'),
], tokens);
});
});
it('emoji', () => { it('emoji', () => {
const tokens1 = analyze(':cat:'); const tokens1 = analyze(':cat:');
assert.deepEqual([ assert.deepEqual([