Skip to content
9 changes: 8 additions & 1 deletion lib/slack_transformer/html.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
require 'slack_transformer/html/bold'
require 'slack_transformer/html/code'
require 'slack_transformer/html/hyperlinks'
require 'slack_transformer/html/newline'
require 'slack_transformer/html/paragraph'
require 'slack_transformer/html/italics'
require 'slack_transformer/html/lists'
require 'slack_transformer/html/preformatted'
Expand All @@ -10,12 +13,16 @@ class Html
attr_reader :input

TRANSFORMERS = [
# Need to use the transformers using Nokogiri first before using gsub.
SlackTransformer::Html::Newline,
SlackTransformer::Html::Paragraph,
SlackTransformer::Html::Lists,
SlackTransformer::Html::Bold,
SlackTransformer::Html::Italics,
SlackTransformer::Html::Strikethrough,
SlackTransformer::Html::Code,
SlackTransformer::Html::Preformatted,
SlackTransformer::Html::Lists
SlackTransformer::Html::Hyperlinks
]

def initialize(input)
Expand Down
32 changes: 32 additions & 0 deletions lib/slack_transformer/html/hyperlinks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require 'nokogiri'

module SlackTransformer
class Html
class Hyperlinks
attr_reader :input

def initialize(input)
@input = input
end

def to_slack
fragment = Nokogiri::HTML.fragment(input)

links_to_replace = {}
fragment.children.each do |child|
if child.name == 'a'
hyperlink_text = child.text.empty? ? child.attr('href') : child.text
hyperlink = "<#{child.attr('href')}|#{hyperlink_text}>"
links_to_replace[child.to_s] = hyperlink
end
end

links_to_replace.each do |html, hyperlink|
input.gsub!(html, hyperlink)
end

input
end
end
end
end
39 changes: 29 additions & 10 deletions lib/slack_transformer/html/lists.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,41 @@ def to_slack
fragment.children.each do |child|
case child.name
when 'ul'
list = child.children.map do |c|
"• #{c.children.to_html}"
end

child.replace(list.join("\n"))
child.replace(indent_nested_list(child))
when 'ol'
list = child.children.map.with_index do |c, i|
"#{i + 1}. #{c.children.to_html}"
end

child.replace(list.join("\n"))
child.replace(indent_nested_number_list(child))
end
end

fragment.to_html
end

def indent_nested_list(child, num_indent = 0)
child.children.map do |c|

case c.name
when 'li'
indent_nested_list(c, num_indent)
when 'ul'
indent_nested_list(c, num_indent += 1)
else
"#{"\t" * num_indent}• #{c.to_html}"
end
end.join("\n")
end

def indent_nested_number_list(child, num_indent = 0, index = 0)
child.children.map do |c|
case c.name
when 'li'
indent_nested_number_list(c, num_indent, index += 1)
when 'ol'
indent_nested_number_list(c, num_indent += 1, 0)
else
"#{"\t" * num_indent}#{index}. #{c.to_html}"
end
end.join("\n")
end
end
end
end
23 changes: 23 additions & 0 deletions lib/slack_transformer/html/newline.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require 'nokogiri'

module SlackTransformer
class Html
class Newline
attr_reader :input

def initialize(input)
@input = input
end

def to_slack
fragment = Nokogiri::HTML.fragment(input)

fragment.children.each do |child|
child.replace("\n") if child.name == 'br'
end

fragment.to_html
end
end
end
end
32 changes: 32 additions & 0 deletions lib/slack_transformer/html/paragraph.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require 'nokogiri'

module SlackTransformer
class Html
class Paragraph
attr_reader :input

def initialize(input)
@input = input
end

def to_slack
fragment = Nokogiri::HTML.fragment(input)
previous = nil
fragment.children.each do |child|
if child.name == 'p'
newline = previous.nil? ? "" : "\n"
child.replace("#{newline}#{child.children.to_html}")
# We don't want to add a newline after the last paragraph tag if it's empty.
previous = child.children.empty? ? nil : 'p'
else
current = child.name
child.replace("\n#{child.to_html}") if previous == 'p'
previous = current
end
end

fragment.to_html
end
end
end
end
21 changes: 21 additions & 0 deletions spec/slack_transformer/html/hyperlinks_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'slack_transformer/html/hyperlinks'

RSpec.describe SlackTransformer::Html::Hyperlinks do
let(:transformation) { described_class.new(input) }

describe '#to_slack' do
context 'when hyperlink text is present' do
let(:input) { '<a href="test.com">test link</a>' }
it 'replaces HTML a Tag with slack hyperlink' do
expect(transformation.to_slack).to eq('<test.com|test link>')
end
end

context 'when hyperlink text is not present' do
let(:input) { '<a href="test.com"></a>' }
it 'uses the href as the hyperlink text' do
expect(transformation.to_slack).to eq('<test.com|test.com>')
end
end
end
end
16 changes: 16 additions & 0 deletions spec/slack_transformer/html/lists_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,28 @@
end
end

context 'when a nested list is unordered' do
let(:input) { '<ul><li>foo<ul><li>bar<ul><li>baz</li></ul></ul></ul>' }

it 'replaces the list' do
expect(transformation.to_slack).to eq("• foo\n\t• bar\n\t\t• baz")
end
end

context 'when a list is ordered' do
let(:input) { '<ol><li>foo</li><li>bar</li><li>baz</li></ol>' }

it 'replaces the list' do
expect(transformation.to_slack).to eq("1. foo\n2. bar\n3. baz")
end
end

context 'when a nested list is ordered' do
let(:input) { '<ol><li>foo<ol><li>bar<ol><li>baz</li></ol></ol></ol>' }

it 'replaces the list' do
expect(transformation.to_slack).to eq("1. foo\n\t1. bar\n\t\t1. baz")
end
end
end
end
35 changes: 35 additions & 0 deletions spec/slack_transformer/html/newline_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require 'slack_transformer/html/newline'


RSpec.describe SlackTransformer::Html::Newline do
let(:transformation) { described_class.new(input) }

describe '#to_slack' do

context 'when <br> tag exist' do
let(:input) { '<br>newline' }

it 'just add a newline at the beginning' do
expect(transformation.to_slack).to eq("\nnewline")
end
end

context 'when <br/> tag exist' do
let(:input) { '<br/>newline' }

it 'just add a newline at the beginning' do
expect(transformation.to_slack).to eq("\nnewline")
end
end

context 'when <br></br> tag exist' do
let(:input) { '<br>newline</br>' }

it 'just add a newline at the beginning' do
expect(transformation.to_slack).to eq("\nnewline")
end
end

end
end

73 changes: 73 additions & 0 deletions spec/slack_transformer/html/paragraph_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
require 'slack_transformer/html/paragraph'


RSpec.describe SlackTransformer::Html::Paragraph do
let(:transformation) { described_class.new(input) }

describe '#to_slack' do
context '<p>Hello World</p>' do
let(:input) { '<p>Hello World</p>' }

it 'return Hello World' do
expect(transformation.to_slack).to eq('Hello World')
end
end

context '<p>Hello</p><p>World</p>' do
let(:input) { '<p>Hello</p><p>World</p>' }

it 'return World on a newline' do
expect(transformation.to_slack).to eq("Hello\nWorld")
end
end

context 'Hello<p>World</p>Again' do
let(:input) { 'Hello<p>World</p>Again' }

it 'return World and Again on a newline' do
expect(transformation.to_slack).to eq("Hello\nWorld\nAgain")
end
end

context 'Hello<p>World</p>' do
let(:input) { 'Hello<p>World</p>' }

it 'return World on a newline' do
expect(transformation.to_slack).to eq("Hello\nWorld")
end
end

context '<p>Hello</p>World' do
let(:input) { '<p>Hello</p>World' }

it 'return World on a newline' do
expect(transformation.to_slack).to eq("Hello\nWorld")
end
end

context 'Hello<p></p>World' do
let(:input) { 'Hello<p></p>World' }

it 'return World on a newline' do
expect(transformation.to_slack).to eq("Hello\nWorld")
end
end

context 'Hello<p></p>World<p></p>' do
let(:input) { 'Hello<p></p>World<p></p>' }

it 'return World on a newline' do
expect(transformation.to_slack).to eq("Hello\nWorld\n")
end
end

context '<p></p>Hello<p></p><p></p><p></p>World' do
let(:input) { '<p></p>Hello<p></p><p></p><p></p>World' }

it 'return World on a newline' do
expect(transformation.to_slack).to eq("Hello\nWorld")
end
end
end
end