From 31042c1edaab3ece6d4e771c3673c3d469a15949 Mon Sep 17 00:00:00 2001 From: Kevin Alberts Date: Thu, 4 Aug 2016 22:27:14 +0200 Subject: [PATCH 1/8] Added formatting conversions to messages. Text formatting like bold, italics and underlining will now be converted between discord and IRC. --- lib/bot.js | 9 ++++++- lib/formatting.js | 58 +++++++++++++++++++++++++++++++++++++++++ test/formatting.test.js | 26 ++++++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 lib/formatting.js create mode 100644 test/formatting.test.js diff --git a/lib/bot.js b/lib/bot.js index c943d674..ba3f668f 100644 --- a/lib/bot.js +++ b/lib/bot.js @@ -4,6 +4,7 @@ import logger from 'winston'; import discord from 'discord.js'; import { ConfigurationError } from './errors'; import { validateChannelMapping } from './validators'; +import { formatFromDiscordToIRC, formatFromIRCToDiscord } from './formatting'; const REQUIRED_FIELDS = ['server', 'nickname', 'channelMapping', 'discordToken']; const NICK_COLORS = ['light_blue', 'dark_blue', 'light_red', 'dark_red', 'light_green', @@ -173,6 +174,9 @@ class Bot { this.ircClient.say(ircChannel, text); } else { if (text !== '') { + // Convert formatting + text = formatFromDiscordToIRC(text); + text = `<${displayUsername}> ${text}`; logger.debug('Sending message to IRC', ircChannel, text); this.ircClient.say(ircChannel, text); @@ -203,7 +207,10 @@ class Bot { return; } - const withMentions = text.replace(/@[^\s]+\b/g, (match) => { + // Convert text formatting (bold, italics, underscore) + const withFormat = formatFromIRCToDiscord(text); + + const withMentions = withFormat.replace(/@[^\s]+\b/g, (match) => { const search = match.substring(1); const guild = discordChannel.guild; const nickUser = guild.members.find('nickname', search); diff --git a/lib/formatting.js b/lib/formatting.js new file mode 100644 index 00000000..7c317a7e --- /dev/null +++ b/lib/formatting.js @@ -0,0 +1,58 @@ +/* eslint-disable no-unused-vars */ + +export function formatFromDiscordToIRC(text) { + // Apply formatting rules, from most specific to least specific. + return text.replace(/~~(.*?)~~/g, '$1') // Remove unsupported strikethrough + .replace(/__\*\*\*(.*?)\*\*\*__/g, '\u001F\u001D\u0002$1\u000F') // Apply underline-italics-bold + .replace(/__\*\*(.*?)\*\*__/g, '\u001F\u0002$1\u000F') // Apply underline-bold + .replace(/__\*(.*?)\*__/g, '\u001F\u001D$1\u000F') // Apply underline-italics + .replace(/__(.*?)__/g, '\u001F$1\u000F') // Apply underline + .replace(/\*\*\*(.*?)\*\*\*/g, '\u0002\u001D$1\u000F') // Apply bold-italics + .replace(/\*\*(.*?)\*\*/g, '\u0002$1\u000F') // Apply bold + .replace(/\*(.*?)\*/g, '\u001D$1\u000F'); // Apply italics +} + +export function formatFromIRCToDiscord(text) { + // Regex doesn't work here, because formatting can be applied arbitrarily in IRC. + // Iterate over the string, and keep track of which formatting is active, + // and close all formatting if a reset symbol is encountered. + + const FORMATTERS = { + BOLD: 1, + ITALICS: 2, + UNDERLINE: 3, + discordSymbols: { + 1: '**', + 2: '*', + 3: '__' + } + }; + + let activeFormatters = []; + let resultString = ''; + + for (let i = 0; i < text.length; i++) { + const char = text[i]; + if (char === '\u001D') { // italics + activeFormatters.push(FORMATTERS.ITALICS); + resultString = resultString.concat('*'); + } else if (char === '\u0002') { // bold + activeFormatters.push(FORMATTERS.BOLD); + resultString = resultString.concat('**'); + } else if (char === '\u001F') { // underline + activeFormatters.push(FORMATTERS.UNDERLINE); + resultString = resultString.concat('__'); + } else if (char === '\u000F') { // reset + // Reset all active formattings + for (let j = (activeFormatters.length - 1); j >= 0; j--) { + resultString = resultString.concat(FORMATTERS.discordSymbols[activeFormatters[j]]); + } + activeFormatters = []; + } else { + // Add character + resultString = resultString.concat(char); + } + } + + return resultString; +} diff --git a/test/formatting.test.js b/test/formatting.test.js new file mode 100644 index 00000000..842a1c5a --- /dev/null +++ b/test/formatting.test.js @@ -0,0 +1,26 @@ +/* eslint-disable prefer-arrow-callback */ + +import chai from 'chai'; +import { formatFromDiscordToIRC, formatFromIRCToDiscord } from '../lib/formatting'; + +const expect = chai.expect; + +describe('formatFromDiscordToIRC', function() { + it('should parse a discord string into an irc string', function() { + const result = formatFromDiscordToIRC('**Hello!** *This* ~~is~~ __*a*__ __**discord**__ ' + + '__string__ __***with***__ *some* ***formatting.***'); + expect(result).to.equal('\u0002Hello!\u000F \u001DThis\u000F is \u001F\u001Da\u000F ' + + '\u001F\u0002discord\u000F \u001Fstring\u000F \u001F\u001D\u0002with\u000F ' + + '\u001Dsome\u000F \u0002\u001Dformatting.\u000F'); + }); +}); + +describe('formatFromIRCToDiscord', function() { + it('should parse an irc string into a discord string', function() { + const result = formatFromIRCToDiscord('\u0002Hello!\u000F \u001DThis\u000F is ' + + '\u001F\u001Da\u000F \u001F\u0002discord\u000F \u001Fstring\u000F ' + + '\u001F\u001D\u0002with\u000F \u001Dsome\u000F \u0002\u001Dformatting.\u000F'); + expect(result).to.equal('**Hello!** *This* is __*a*__ __**discord**__ __string__ ' + + '__***with***__ *some* ***formatting.***'); + }); +}); From 43d5e27ca19a087beddf56f6b2009bc0564fd7ce Mon Sep 17 00:00:00 2001 From: Kevin Alberts Date: Thu, 4 Aug 2016 22:50:38 +0200 Subject: [PATCH 2/8] Remove colors from IRC messages sent to Discord, as Discord does not support colorized text. --- lib/formatting.js | 5 ++++- test/formatting.test.js | 9 ++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/formatting.js b/lib/formatting.js index 7c317a7e..547daa10 100644 --- a/lib/formatting.js +++ b/lib/formatting.js @@ -15,7 +15,7 @@ export function formatFromDiscordToIRC(text) { export function formatFromIRCToDiscord(text) { // Regex doesn't work here, because formatting can be applied arbitrarily in IRC. // Iterate over the string, and keep track of which formatting is active, - // and close all formatting if a reset symbol is encountered. + // and close all formatting in order if a reset symbol is encountered. const FORMATTERS = { BOLD: 1, @@ -54,5 +54,8 @@ export function formatFromIRCToDiscord(text) { } } + // Remove all color markers from the message, as discord does not support colored text + resultString = resultString.replace(/\u0003(\d\d(,\d\d)?)?/g, ''); + return resultString; } diff --git a/test/formatting.test.js b/test/formatting.test.js index 842a1c5a..7337e2af 100644 --- a/test/formatting.test.js +++ b/test/formatting.test.js @@ -5,7 +5,7 @@ import { formatFromDiscordToIRC, formatFromIRCToDiscord } from '../lib/formattin const expect = chai.expect; -describe('formatFromDiscordToIRC', function() { +describe('Formatting', function() { it('should parse a discord string into an irc string', function() { const result = formatFromDiscordToIRC('**Hello!** *This* ~~is~~ __*a*__ __**discord**__ ' + '__string__ __***with***__ *some* ***formatting.***'); @@ -13,13 +13,12 @@ describe('formatFromDiscordToIRC', function() { '\u001F\u0002discord\u000F \u001Fstring\u000F \u001F\u001D\u0002with\u000F ' + '\u001Dsome\u000F \u0002\u001Dformatting.\u000F'); }); -}); -describe('formatFromIRCToDiscord', function() { it('should parse an irc string into a discord string', function() { const result = formatFromIRCToDiscord('\u0002Hello!\u000F \u001DThis\u000F is ' + - '\u001F\u001Da\u000F \u001F\u0002discord\u000F \u001Fstring\u000F ' + - '\u001F\u001D\u0002with\u000F \u001Dsome\u000F \u0002\u001Dformatting.\u000F'); + '\u001F\u001Da\u000F \u001F\u0002discord\u000F \u001F\u000306string\u0003\u000F ' + + '\u001F\u001D\u0002with\u000F \u001D\u000304,01some\u0003\u000F ' + + '\u0002\u001Dformatting.\u000F'); expect(result).to.equal('**Hello!** *This* is __*a*__ __**discord**__ __string__ ' + '__***with***__ *some* ***formatting.***'); }); From 0684668c821548ce066f72b8fb97a36180cb3305 Mon Sep 17 00:00:00 2001 From: Kevin Alberts Date: Thu, 4 Aug 2016 23:27:07 +0200 Subject: [PATCH 3/8] Make the leading 0 in the color optional in the regex. --- lib/formatting.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/formatting.js b/lib/formatting.js index 547daa10..80616edf 100644 --- a/lib/formatting.js +++ b/lib/formatting.js @@ -55,7 +55,7 @@ export function formatFromIRCToDiscord(text) { } // Remove all color markers from the message, as discord does not support colored text - resultString = resultString.replace(/\u0003(\d\d(,\d\d)?)?/g, ''); + resultString = resultString.replace(/\u0003(\d\d?(,\d\d?)?)?/g, ''); return resultString; } From cb35b49e4c1c9487a9f2a290fed68b0221232f27 Mon Sep 17 00:00:00 2001 From: Rahat Ahmed Date: Sat, 25 Mar 2017 12:22:31 -0500 Subject: [PATCH 4/8] Use irc-formatting for irc to discord formatting --- lib/formatting.js | 66 ++++++++--------------------------------- package.json | 1 + test/formatting.test.js | 8 ++--- 3 files changed, 18 insertions(+), 57 deletions(-) diff --git a/lib/formatting.js b/lib/formatting.js index 80616edf..2ec1881c 100644 --- a/lib/formatting.js +++ b/lib/formatting.js @@ -1,61 +1,21 @@ -/* eslint-disable no-unused-vars */ +import ircFormatting from 'irc-formatting'; export function formatFromDiscordToIRC(text) { - // Apply formatting rules, from most specific to least specific. - return text.replace(/~~(.*?)~~/g, '$1') // Remove unsupported strikethrough - .replace(/__\*\*\*(.*?)\*\*\*__/g, '\u001F\u001D\u0002$1\u000F') // Apply underline-italics-bold - .replace(/__\*\*(.*?)\*\*__/g, '\u001F\u0002$1\u000F') // Apply underline-bold - .replace(/__\*(.*?)\*__/g, '\u001F\u001D$1\u000F') // Apply underline-italics + return text + .replace(/~~(.*?)~~/g, '$1') // Remove unsupported strikethrough .replace(/__(.*?)__/g, '\u001F$1\u000F') // Apply underline - .replace(/\*\*\*(.*?)\*\*\*/g, '\u0002\u001D$1\u000F') // Apply bold-italics .replace(/\*\*(.*?)\*\*/g, '\u0002$1\u000F') // Apply bold - .replace(/\*(.*?)\*/g, '\u001D$1\u000F'); // Apply italics + .replace(/\*(.*?)\*/g, '\u001D$1\u000F') // Apply italics + .replace(/_(.*?)_/g, '\u001D$1\u000F'); // Apply alternate italics } export function formatFromIRCToDiscord(text) { - // Regex doesn't work here, because formatting can be applied arbitrarily in IRC. - // Iterate over the string, and keep track of which formatting is active, - // and close all formatting in order if a reset symbol is encountered. - - const FORMATTERS = { - BOLD: 1, - ITALICS: 2, - UNDERLINE: 3, - discordSymbols: { - 1: '**', - 2: '*', - 3: '__' - } - }; - - let activeFormatters = []; - let resultString = ''; - - for (let i = 0; i < text.length; i++) { - const char = text[i]; - if (char === '\u001D') { // italics - activeFormatters.push(FORMATTERS.ITALICS); - resultString = resultString.concat('*'); - } else if (char === '\u0002') { // bold - activeFormatters.push(FORMATTERS.BOLD); - resultString = resultString.concat('**'); - } else if (char === '\u001F') { // underline - activeFormatters.push(FORMATTERS.UNDERLINE); - resultString = resultString.concat('__'); - } else if (char === '\u000F') { // reset - // Reset all active formattings - for (let j = (activeFormatters.length - 1); j >= 0; j--) { - resultString = resultString.concat(FORMATTERS.discordSymbols[activeFormatters[j]]); - } - activeFormatters = []; - } else { - // Add character - resultString = resultString.concat(char); - } - } - - // Remove all color markers from the message, as discord does not support colored text - resultString = resultString.replace(/\u0003(\d\d?(,\d\d?)?)?/g, ''); - - return resultString; + const blocks = ircFormatting.parse(text); + return blocks.map((block) => { + let mdText = block.text; + if (block.italic) mdText = `*${mdText}*`; + if (block.bold) mdText = `**${mdText}**`; + if (block.underline) mdText = `__${mdText}__`; + return mdText; + }).join(''); } diff --git a/package.json b/package.json index 777ce810..0de94726 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "commander": "2.9.0", "discord.js": "11.0.0", "irc": "0.5.2", + "irc-formatting": "^1.0.0-rc3", "lodash": "^4.17.4", "strip-json-comments": "2.0.1", "winston": "2.3.1" diff --git a/test/formatting.test.js b/test/formatting.test.js index 7337e2af..abfbb556 100644 --- a/test/formatting.test.js +++ b/test/formatting.test.js @@ -5,16 +5,16 @@ import { formatFromDiscordToIRC, formatFromIRCToDiscord } from '../lib/formattin const expect = chai.expect; -describe('Formatting', function() { - it('should parse a discord string into an irc string', function() { +describe('Formatting', function () { + it('should parse a discord string into an irc string', function () { const result = formatFromDiscordToIRC('**Hello!** *This* ~~is~~ __*a*__ __**discord**__ ' + - '__string__ __***with***__ *some* ***formatting.***'); + '__string__ __***with***__ *some* _**formatting.**_'); expect(result).to.equal('\u0002Hello!\u000F \u001DThis\u000F is \u001F\u001Da\u000F ' + '\u001F\u0002discord\u000F \u001Fstring\u000F \u001F\u001D\u0002with\u000F ' + '\u001Dsome\u000F \u0002\u001Dformatting.\u000F'); }); - it('should parse an irc string into a discord string', function() { + it('should parse an irc string into a discord string', function () { const result = formatFromIRCToDiscord('\u0002Hello!\u000F \u001DThis\u000F is ' + '\u001F\u001Da\u000F \u001F\u0002discord\u000F \u001F\u000306string\u0003\u000F ' + '\u001F\u001D\u0002with\u000F \u001D\u000304,01some\u0003\u000F ' + From 336e87e8614543dc4b47f94437630097335f2f24 Mon Sep 17 00:00:00 2001 From: Rahat Ahmed Date: Sat, 25 Mar 2017 12:55:48 -0500 Subject: [PATCH 5/8] Use simple-markdown to format discord to irc --- lib/formatting.js | 20 ++++++++++++++------ package.json | 2 ++ test/formatting.test.js | 8 ++++---- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/lib/formatting.js b/lib/formatting.js index 2ec1881c..03d9a743 100644 --- a/lib/formatting.js +++ b/lib/formatting.js @@ -1,12 +1,20 @@ import ircFormatting from 'irc-formatting'; +import SimpleMarkdown from 'simple-markdown'; +import colors from 'irc-colors'; +import _ from 'lodash'; + +function mdNodeToIRC(node) { + let content = node.content; + if (_.isArray(content)) content = content.map(mdNodeToIRC).join(''); + if (node.type === 'em') return colors.italic(content); + if (node.type === 'strong') return colors.bold(content); + if (node.type === 'u') return colors.underline(content); + return content; +} export function formatFromDiscordToIRC(text) { - return text - .replace(/~~(.*?)~~/g, '$1') // Remove unsupported strikethrough - .replace(/__(.*?)__/g, '\u001F$1\u000F') // Apply underline - .replace(/\*\*(.*?)\*\*/g, '\u0002$1\u000F') // Apply bold - .replace(/\*(.*?)\*/g, '\u001D$1\u000F') // Apply italics - .replace(/_(.*?)_/g, '\u001D$1\u000F'); // Apply alternate italics + const markdownAST = SimpleMarkdown.defaultInlineParse(text); + return markdownAST.map(mdNodeToIRC).join(''); } export function formatFromIRCToDiscord(text) { diff --git a/package.json b/package.json index 0de94726..ddc0993c 100644 --- a/package.json +++ b/package.json @@ -40,8 +40,10 @@ "commander": "2.9.0", "discord.js": "11.0.0", "irc": "0.5.2", + "irc-colors": "^1.3.2", "irc-formatting": "^1.0.0-rc3", "lodash": "^4.17.4", + "simple-markdown": "^0.2.1", "strip-json-comments": "2.0.1", "winston": "2.3.1" }, diff --git a/test/formatting.test.js b/test/formatting.test.js index abfbb556..daf2f735 100644 --- a/test/formatting.test.js +++ b/test/formatting.test.js @@ -8,10 +8,10 @@ const expect = chai.expect; describe('Formatting', function () { it('should parse a discord string into an irc string', function () { const result = formatFromDiscordToIRC('**Hello!** *This* ~~is~~ __*a*__ __**discord**__ ' + - '__string__ __***with***__ *some* _**formatting.**_'); - expect(result).to.equal('\u0002Hello!\u000F \u001DThis\u000F is \u001F\u001Da\u000F ' + - '\u001F\u0002discord\u000F \u001Fstring\u000F \u001F\u001D\u0002with\u000F ' + - '\u001Dsome\u000F \u0002\u001Dformatting.\u000F'); + '__string__ __***with***__ *some* ***formatting.***'); + expect(result).to.equal('\u0002Hello!\u0002 \u0016This\u0016 is \u001f\u0016a\u0016\u001f ' + + '\u001f\u0002discord\u0002\u001f \u001fstring\u001f \u001f\u0016\u0002with\u0002\u0016\u001f ' + + '\u0016some\u0016 \u0016\u0002formatting.\u0002\u0016'); }); it('should parse an irc string into a discord string', function () { From bc712281b8fe59f3a7af93317bcda18905e4e2be Mon Sep 17 00:00:00 2001 From: Rahat Ahmed Date: Sat, 25 Mar 2017 13:28:56 -0500 Subject: [PATCH 6/8] Add tests & catch reverse irc format --- lib/formatting.js | 2 +- test/formatting.test.js | 66 +++++++++++++++++++++++++++++++---------- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/lib/formatting.js b/lib/formatting.js index 03d9a743..6f6d69cf 100644 --- a/lib/formatting.js +++ b/lib/formatting.js @@ -21,7 +21,7 @@ export function formatFromIRCToDiscord(text) { const blocks = ircFormatting.parse(text); return blocks.map((block) => { let mdText = block.text; - if (block.italic) mdText = `*${mdText}*`; + if (block.italic || block.reverse) mdText = `*${mdText}*`; if (block.bold) mdText = `**${mdText}**`; if (block.underline) mdText = `__${mdText}__`; return mdText; diff --git a/test/formatting.test.js b/test/formatting.test.js index daf2f735..b977edaf 100644 --- a/test/formatting.test.js +++ b/test/formatting.test.js @@ -3,23 +3,57 @@ import chai from 'chai'; import { formatFromDiscordToIRC, formatFromIRCToDiscord } from '../lib/formatting'; -const expect = chai.expect; - -describe('Formatting', function () { - it('should parse a discord string into an irc string', function () { - const result = formatFromDiscordToIRC('**Hello!** *This* ~~is~~ __*a*__ __**discord**__ ' + - '__string__ __***with***__ *some* ***formatting.***'); - expect(result).to.equal('\u0002Hello!\u0002 \u0016This\u0016 is \u001f\u0016a\u0016\u001f ' + - '\u001f\u0002discord\u0002\u001f \u001fstring\u001f \u001f\u0016\u0002with\u0002\u0016\u001f ' + - '\u0016some\u0016 \u0016\u0002formatting.\u0002\u0016'); +chai.should(); + +describe('Formatting', () => { + describe('Discord to IRC', () => { + it('should convert bold markdown', () => { + formatFromDiscordToIRC('**text**').should.equal('\x02text\x02'); + }); + + it('should convert italic markdown', () => { + formatFromDiscordToIRC('*text*').should.equal('\x16text\x16'); + formatFromDiscordToIRC('_text_').should.equal('\x16text\x16'); + }); + + it('should convert underline markdown', () => { + formatFromDiscordToIRC('__text__').should.equal('\x1ftext\x1f'); + }); + + it('should ignore strikethrough markdown', () => { + formatFromDiscordToIRC('~~text~~').should.equal('text'); + }); + + it('should convert nested markdown', () => { + formatFromDiscordToIRC('**bold *italics***') + .should.equal('\x02bold \x16italics\x16\x02'); + }); }); - it('should parse an irc string into a discord string', function () { - const result = formatFromIRCToDiscord('\u0002Hello!\u000F \u001DThis\u000F is ' + - '\u001F\u001Da\u000F \u001F\u0002discord\u000F \u001F\u000306string\u0003\u000F ' + - '\u001F\u001D\u0002with\u000F \u001D\u000304,01some\u0003\u000F ' + - '\u0002\u001Dformatting.\u000F'); - expect(result).to.equal('**Hello!** *This* is __*a*__ __**discord**__ __string__ ' + - '__***with***__ *some* ***formatting.***'); + describe('IRC to Discord', () => { + it('should convert bold IRC format', () => { + formatFromIRCToDiscord('\x02text\x02').should.equal('**text**'); + }); + + it('should convert reverse IRC format', () => { + formatFromIRCToDiscord('\x16text\x16').should.equal('*text*'); + }); + + it('should convert italic IRC format', () => { + formatFromIRCToDiscord('\x1dtext\x1d').should.equal('*text*'); + }); + + it('should convert underline IRC format', () => { + formatFromIRCToDiscord('\x1ftext\x1f').should.equal('__text__'); + }); + + it('should ignore color IRC format', () => { + formatFromIRCToDiscord('\x0306,08text\x03').should.equal('text'); + }); + + it('should convert nested IRC format', () => { + formatFromIRCToDiscord('\x02bold \x16italics\x16\x02') + .should.equal('**bold *italics***'); + }); }); }); From 86fadd597960db375d504a33d5b5bd0703c5f136 Mon Sep 17 00:00:00 2001 From: Rahat Ahmed Date: Sat, 25 Mar 2017 14:10:41 -0500 Subject: [PATCH 7/8] Fix IRC to discord formatting nested styles --- lib/formatting.js | 34 ++++++++++++++++++++++++++-------- test/formatting.test.js | 5 +++++ 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/lib/formatting.js b/lib/formatting.js index 6f6d69cf..04f05250 100644 --- a/lib/formatting.js +++ b/lib/formatting.js @@ -18,12 +18,30 @@ export function formatFromDiscordToIRC(text) { } export function formatFromIRCToDiscord(text) { - const blocks = ircFormatting.parse(text); - return blocks.map((block) => { - let mdText = block.text; - if (block.italic || block.reverse) mdText = `*${mdText}*`; - if (block.bold) mdText = `**${mdText}**`; - if (block.underline) mdText = `__${mdText}__`; - return mdText; - }).join(''); + const blocks = ircFormatting.parse(text).map(block => + // Consider reverse as italic, some IRC clients use that + _.assign({}, block, { italic: block.italic || block.reverse }) + ); + let mdText = ''; + + for (let i = 0; i <= blocks.length; i += 1) { + // Default to unstyled blocks when index out of range + const block = blocks[i] || {}; + const prevBlock = blocks[i - 1] || {}; + + // Add start markers when style turns from false to true + if (!prevBlock.italic && block.italic) mdText += '*'; + if (!prevBlock.bold && block.bold) mdText += '**'; + if (!prevBlock.underline && block.underline) mdText += '__'; + + // Add end markers when style turns from true to false + // (and apply in reverse order to maintain nesting) + if (prevBlock.underline && !block.underline) mdText += '__'; + if (prevBlock.bold && !block.bold) mdText += '**'; + if (prevBlock.italic && !block.italic) mdText += '*'; + + mdText += block.text || ''; + } + + return mdText; } diff --git a/test/formatting.test.js b/test/formatting.test.js index b977edaf..d14f518f 100644 --- a/test/formatting.test.js +++ b/test/formatting.test.js @@ -55,5 +55,10 @@ describe('Formatting', () => { formatFromIRCToDiscord('\x02bold \x16italics\x16\x02') .should.equal('**bold *italics***'); }); + + it('should convert nested IRC format', () => { + formatFromIRCToDiscord('\x02bold \x1funderline\x1f\x02') + .should.equal('**bold __underline__**'); + }); }); }); From 200a0b996e0d224a5fda23f4fd3e0f16db728e65 Mon Sep 17 00:00:00 2001 From: Rahat Ahmed Date: Wed, 29 Mar 2017 14:52:07 -0500 Subject: [PATCH 8/8] Use es6+ features instead of lodash --- lib/formatting.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/formatting.js b/lib/formatting.js index 04f05250..78e6022c 100644 --- a/lib/formatting.js +++ b/lib/formatting.js @@ -1,11 +1,10 @@ import ircFormatting from 'irc-formatting'; import SimpleMarkdown from 'simple-markdown'; import colors from 'irc-colors'; -import _ from 'lodash'; function mdNodeToIRC(node) { let content = node.content; - if (_.isArray(content)) content = content.map(mdNodeToIRC).join(''); + if (Array.isArray(content)) content = content.map(mdNodeToIRC).join(''); if (node.type === 'em') return colors.italic(content); if (node.type === 'strong') return colors.bold(content); if (node.type === 'u') return colors.underline(content); @@ -18,10 +17,11 @@ export function formatFromDiscordToIRC(text) { } export function formatFromIRCToDiscord(text) { - const blocks = ircFormatting.parse(text).map(block => + const blocks = ircFormatting.parse(text).map(block => ({ // Consider reverse as italic, some IRC clients use that - _.assign({}, block, { italic: block.italic || block.reverse }) - ); + ...block, + italic: block.italic || block.reverse + })); let mdText = ''; for (let i = 0; i <= blocks.length; i += 1) {