diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a6b547c..64dc6964 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ### 2.3.1 (Next) * [#516](https://github.com/slack-ruby/slack-ruby-client/pull/516): Add support for Ruby 3.3 - [@olleolleolle](https://github.com/olleolleolle). +* [#520](https://github.com/slack-ruby/slack-ruby-client/pull/520): Support basic markdown formatting - [@nbgoodall](https://github.com/nbgoodall). * Your contribution here. ### 2.3.0 (2024/01/31) diff --git a/README.md b/README.md index 482a6e5f..5b30cb37 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ A Ruby client for the Slack [Web](https://api.slack.com/web), [RealTime Messagin - [Channel ID formatting](#channel-id-formatting) - [User ID formatting](#user-id-formatting) - [URL formatting](#url-formatting) + - [Markdown formatting](#markdown-formatting) - [Parsing Messages](#parsing-messages) - [Unescaping message content](#unescaping-message-content) - [Escaping message content](#escaping-message-content) @@ -657,6 +658,30 @@ Slack::Messages::Formatting.url_link(text, url) # => "" ``` +##### Markdown formatting + +Slack uses a mishmash of regular markdown formatting with its own syntax. Some features like headings aren't supported and will be left as-is, but others like bold, strikethrough, and links are converted. + +```ruby +text = """ +## A heading +**Bold text** +~~Strikethrough text~~ +_Italic text_ +[A link](https://example.com) +`code` +""" +Slack::Messages::Formatting.markdown(text) + # => """ + # ## A heading + # *Bold text* + # ~Strikethrough text~ + # _Italic text_ + # + # `code` + # """ +``` + #### Parsing Messages `Slack::Messages::Formatting` also provides ways to escape or unescape messages. This comes handy, for example, you want to treat all input to a real time bot as plain text. diff --git a/lib/slack/messages/formatting.rb b/lib/slack/messages/formatting.rb index 6052ed01..f44ebe96 100644 --- a/lib/slack/messages/formatting.rb +++ b/lib/slack/messages/formatting.rb @@ -68,6 +68,19 @@ def user_link(user_id) def url_link(text, url) "<#{url}|#{text}>" end + + # + # Converts text from basic markdown into Slack's mishmash + # @see https://api.slack.com/reference/surfaces/formatting#basic-formatting + # + def markdown(text) + text + .gsub(/(?') # links + end end end end diff --git a/spec/slack/messages/formatting_spec.rb b/spec/slack/messages/formatting_spec.rb index d734c840..a6d6096c 100644 --- a/spec/slack/messages/formatting_spec.rb +++ b/spec/slack/messages/formatting_spec.rb @@ -121,4 +121,36 @@ expect(formatting.url_link(text, url)).to eq "<#{url}|#{text}>" end end + + context '#markdown' do + it 'formats markdown bold' do + expect(formatting.markdown('**Le bold**')).to eq '*Le bold*' + end + + it 'formats markdown italic' do + expect(formatting.markdown("*L'italic*")).to eq "_L'italic_" + end + + it 'formats markdown bold and italic' do + expect(formatting.markdown('***Le bold italic***')).to eq '*_Le bold italic_*' + end + + it 'formats markdown strikethrough' do + expect(formatting.markdown('~~Le strikethrough~~')).to eq '~Le strikethrough~' + end + + it 'formats markdown links' do + expect(formatting.markdown('[Le link](https://theuselessweb.site)')).to eq '' + end + + it 'formats nested markdown' do + expect(formatting.markdown('**[Le **bold and ~~struckout with *italic*~~** link](https://theuselessweb.site)**')).to( + eq '**' + ) + end + + it "doesn't format other markdown" do + expect(formatting.markdown('## A heading\n_Italics_\n`code`')).to eq '## A heading\n_Italics_\n`code`' + end + end end