diff --git a/lib/slack_transformer/html.rb b/lib/slack_transformer/html.rb index 3952abd..5bb2833 100644 --- a/lib/slack_transformer/html.rb +++ b/lib/slack_transformer/html.rb @@ -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' @@ -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) diff --git a/lib/slack_transformer/html/hyperlinks.rb b/lib/slack_transformer/html/hyperlinks.rb new file mode 100644 index 0000000..68ecbbb --- /dev/null +++ b/lib/slack_transformer/html/hyperlinks.rb @@ -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 diff --git a/lib/slack_transformer/html/lists.rb b/lib/slack_transformer/html/lists.rb index c4a8753..e81f337 100644 --- a/lib/slack_transformer/html/lists.rb +++ b/lib/slack_transformer/html/lists.rb @@ -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 diff --git a/lib/slack_transformer/html/newline.rb b/lib/slack_transformer/html/newline.rb new file mode 100644 index 0000000..65f2b3b --- /dev/null +++ b/lib/slack_transformer/html/newline.rb @@ -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 diff --git a/lib/slack_transformer/html/paragraph.rb b/lib/slack_transformer/html/paragraph.rb new file mode 100644 index 0000000..fe7d42b --- /dev/null +++ b/lib/slack_transformer/html/paragraph.rb @@ -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 diff --git a/spec/slack_transformer/html/hyperlinks_spec.rb b/spec/slack_transformer/html/hyperlinks_spec.rb new file mode 100644 index 0000000..c8b797a --- /dev/null +++ b/spec/slack_transformer/html/hyperlinks_spec.rb @@ -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) { 'test link' } + it 'replaces HTML a Tag with slack hyperlink' do + expect(transformation.to_slack).to eq('') + end + end + + context 'when hyperlink text is not present' do + let(:input) { '' } + it 'uses the href as the hyperlink text' do + expect(transformation.to_slack).to eq('') + end + end + end +end diff --git a/spec/slack_transformer/html/lists_spec.rb b/spec/slack_transformer/html/lists_spec.rb index b949af5..b581eee 100644 --- a/spec/slack_transformer/html/lists_spec.rb +++ b/spec/slack_transformer/html/lists_spec.rb @@ -12,6 +12,14 @@ end end + context 'when a nested list is unordered' do + let(:input) { '' } + + 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) { '
  1. foo
  2. bar
  3. baz
' } @@ -19,5 +27,13 @@ expect(transformation.to_slack).to eq("1. foo\n2. bar\n3. baz") end end + + context 'when a nested list is ordered' do + let(:input) { '
  1. foo
    1. bar
      1. baz
' } + + it 'replaces the list' do + expect(transformation.to_slack).to eq("1. foo\n\t1. bar\n\t\t1. baz") + end + end end end diff --git a/spec/slack_transformer/html/newline_spec.rb b/spec/slack_transformer/html/newline_spec.rb new file mode 100644 index 0000000..b8aa77a --- /dev/null +++ b/spec/slack_transformer/html/newline_spec.rb @@ -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
tag exist' do + let(:input) { '
newline' } + + it 'just add a newline at the beginning' do + expect(transformation.to_slack).to eq("\nnewline") + end + end + + context 'when
tag exist' do + let(:input) { '
newline' } + + it 'just add a newline at the beginning' do + expect(transformation.to_slack).to eq("\nnewline") + end + end + + context 'when

tag exist' do + let(:input) { '
newline
' } + + it 'just add a newline at the beginning' do + expect(transformation.to_slack).to eq("\nnewline") + end + end + + end + end + \ No newline at end of file diff --git a/spec/slack_transformer/html/paragraph_spec.rb b/spec/slack_transformer/html/paragraph_spec.rb new file mode 100644 index 0000000..a4af628 --- /dev/null +++ b/spec/slack_transformer/html/paragraph_spec.rb @@ -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 '

Hello World

' do + let(:input) { '

Hello World

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

Hello

World

' do + let(:input) { '

Hello

World

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

World

Again' do + let(:input) { 'Hello

World

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

World

' do + let(:input) { 'Hello

World

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

Hello

World' do + let(:input) { '

Hello

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

World' do + let(:input) { 'Hello

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

World

' do + let(:input) { 'Hello

World

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

Hello

World' do + let(:input) { '

Hello

World' } + + it 'return World on a newline' do + expect(transformation.to_slack).to eq("Hello\nWorld") + end + end + end + end + \ No newline at end of file