Skip to content

Commit

Permalink
Add trailing bracket matching to channel linking (kiwiirc#1838)
Browse files Browse the repository at this point in the history
* Add trailing bracket matching to channel linking

* more tests
  • Loading branch information
ItsOnlyBinary authored Nov 21, 2023
1 parent e9eaf17 commit 774b076
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 16 deletions.
29 changes: 29 additions & 0 deletions src/helpers/Misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,35 @@ export function makePluginObject(pluginId, componentOrElement, args = {}) {
return plugin;
}

/**
* Check for trailing close bracket and return true if no matching open bracket is found
* @param {String} str The string to check for trailing brackets
* @returns {Boolean} Boolean true when trailing bracket and no matching open bracket
*/
export function hasUnmatchedTrailingBracket(str) {
const brackets = [
{ o: '(', c: ')' },
{ o: '[', c: ']' },
{ o: '{', c: '}' },
];

const type = brackets.find((t) => t.c === str[str.length - 1]);
if (!type) {
return false;
}

let unmatched = 0;
for (let i = str.length - 1; i >= 0; i--) {
if (str[i] === type.c) {
unmatched++;
} else if (str[i] === type.o) {
unmatched--;
}
}

return (unmatched === 1);
}

// This provides a better sort for numbered nicks but does not work on ios9
let intlCollator;
if (global.Intl) {
Expand Down
29 changes: 13 additions & 16 deletions src/libs/MessageParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { trim } from 'lodash';

import * as EmojiProvider from '@/libs/EmojiProvider';
import * as Misc from '@/helpers/Misc';
import formatIrcMessage, { createNewBlock } from '@/libs/MessageFormatter';
import { urlRegex, channelRegex } from '@/helpers/TextFormatting';

Expand Down Expand Up @@ -101,12 +102,20 @@ function matchChannel(word) {
return false;
}

let channel = channelMatch[3];

// When the end of channel name is a closing bracket check for matching opening bracket
// if no matching opening bracket is found consider the trailing bracket as punctuation
if (Misc.hasUnmatchedTrailingBracket(channel)) {
channel = channel.substring(0, channel.length - 1);
}

return [{
index: channelMatch[1].length + channelMatch[2].length,
match: channelMatch[3],
match: channel,
type: 'channel',
meta: {
channel: channelMatch[3],
channel,
},
}];
}
Expand Down Expand Up @@ -147,20 +156,8 @@ function matchUrl(word) {
// bracket and should be part of the URL.
// If there isn't a matching opening bracket but the URL ends in a closing bracket,
// consider the closing bracket as punctuation outside of the URL.
if (url[url.length - 1] === ')') {
let unmatched = 0;

for (let i = url.length - 1; i >= 0; i--) {
if (url[i] === ')') {
unmatched++;
} else if (url[i] === '(') {
unmatched--;
}
}

if (unmatched === 1) {
url = url.substring(0, url.length - 1);
}
if (Misc.hasUnmatchedTrailingBracket(url)) {
url = url.substring(0, url.length - 1);
}

// Add the http if no protocol was found
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/MessageParser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ describe('MessageParser.js', () => {
['#chan;nel', '#chan;nel'],
['#channel.', '#channel'],
['#chan;el;', '#chan;el'],
['#channel),', '#channel'],
['#chan(n)el,', '#chan(n)el'],
['#chan(n)el),', '#chan(n)el'],
['#chan(nel),', '#chan(nel)'],
['#chan[n]el,', '#chan[n]el'],
['#chan[n]el],', '#chan[n]el'],
['#chan[nel],', '#chan[nel]'],
['#channel.name,', '#channel.name'],
['#channel.name.,', '#channel.name'],
['#channel.,', '#channel'],
Expand Down

0 comments on commit 774b076

Please sign in to comment.