# frozen_string_literal: true
module Slackert
# Block elements that a Slack message can be composed of.
module Blocks
# Abstract BlockElement.
# Subclass and override +to_slack+ to add a new block element.
class BlockElement
def initialize(type)
@type = type
end
# Returns a hash of the element, ready to be added to the block formatted message.
# Abstract method that needs to be implemented in each subclassed element.
#
def to_slack
raise NoMethodError, 'Override this implementation'
end
end
# Header block element provides a title, rendered as a larger bold text on top of the message.
class Header < BlockElement
# @param text [String] header text
def initialize(text)
super('header')
@text = text
end
# See {BlockElement#to_slack}
def to_slack
{
'type': @type,
'text': {
'type': 'plain_text',
'text': @text
}
}
end
end
# Divider block element provides a horizontal separator, simlarly to HTML's +
+
class Divider < BlockElement
def initialize
super('divider')
end
# See {BlockElement#to_slack}
def to_slack
{
'type': @type
}
end
end
# Section block element is a very flexible layout block that can serve as a simple text block but it also allows
# for adding block elements such as field text, buttons, images and more. Currently only section text and field
# texts are supported.
#
# To learn more, visit https://api.slack.com/reference/block-kit/blocks#section
#
class Section < BlockElement
def initialize
@text = {}
@fields = []
super('section')
end
# Initialize field text objects from a hash.
# @param [Hash] key, value pairs that each will become a field text object
# @param line_break [Boolean] add a line break after each key so values render right under the key
# instead of next to it
# @param bold_keys [Boolean] apply bold text formatting to the keys
# @return [Section]
def self.new_from_hash(values, line_break: true, bold_keys: true)
s = new
values.each do |key, value|
title = bold_keys ? "*#{key}*" : key
title = line_break ? "#{title}\n" : title
s.add_field_text("#{title}#{value}")
end
s
end
# Adds a text object on top of the section. There can only be one section text added. Adding more will replace
# the previously added section text. It is limited to 3000 characters.
# @param message [String] section text message
# @param type [String] can be either mrkdwn or plain_text
#
def add_section_text(message, type = 'mrkdwn')
raise ArgumentError, 'Maximum number of characters in text exceeded' if message.length > 3000
@text = {
'type': type,
'text': message
}
end
# Adds a field text object to the message. Field texts render in two columns on desktop and are added left
# to right. They show as one column on mobile.
# There can only be 10 fields added in total and each text item has a limit of 2000 characters.
# @param message [String] field text message
# @param type [String] can be either mrkdwn or plain_text
# @raise [RuntimeError] if maximum capacity of 10 field objects has been reached
#
def add_field_text(message, type = 'mrkdwn')
raise StandardError, 'Maximum field text objects has been reached.' if @fields.length == 10
raise ArgumentError, 'Maximum number of characters in text exceeded' if message.length > 2000
@fields.push(
{
'type': type,
'text': message
}
)
end
# See {BlockElement#to_slack}
def to_slack
if @text.empty? && @fields.empty?
raise 'Either section text or field text needs to be filled in order to compose the section.'
end
section = { 'type': @type }
section['text'] = @text unless @text.empty?
section['fields'] = @fields unless @fields.empty?
section
end
end
end
end