Class: BBortcodes::Shortcode

Inherits:
Literal::Object
  • Object
show all
Defined in:
lib/bbortcodes/shortcode.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.allowed_childrenObject

Override in subclasses to specify allowed child shortcodes Return :all to allow all children Return [] to allow no children (content is just text) Return array of shortcode classes to allow specific children



31
32
33
# File 'lib/bbortcodes/shortcode.rb', line 31

def allowed_children
  :all
end

.allows_child?(shortcode_class) ⇒ Boolean

Check if a given shortcode class is allowed as a child

Returns:

  • (Boolean)


36
37
38
39
40
41
# File 'lib/bbortcodes/shortcode.rb', line 36

def allows_child?(shortcode_class)
  return true if allowed_children == :all
  return false if allowed_children.empty?

  allowed_children.include?(shortcode_class)
end

.shortcode_attribute_reader(name, attribute_name: name) ⇒ void

This method returns an undefined value.

Defines a helper method to retrieve a shortcode attribute.

This macro creates an instance method that retrieves the specified attribute value. The generated method respects the auto_escape_attributes configuration setting.

Examples:

Basic usage

class VideoShortcode < BBortcodes::Shortcode
  shortcode_attribute_reader :url

  def render(context)
    "<video src=\"#{url}\"></video>"
  end
end

Custom attribute name mapping

class ImageShortcode < BBortcodes::Shortcode
  shortcode_attribute_reader :image_url, attribute_name: "url"

  def render(context)
    "<img src=\"#{image_url}\" />"
  end
end

Multiple attribute readers

class ButtonShortcode < BBortcodes::Shortcode
  shortcode_attribute_reader :href
  shortcode_attribute_reader :color
  shortcode_attribute_reader :size

  def render(context)
    "<a href=\"#{href}\" class=\"btn-#{color} btn-#{size}\">Click</a>"
  end
end

Parameters:

  • name (Symbol)

    The method name to define

  • attribute_name (Symbol, String) (defaults to: name)

    The attribute name to retrieve (defaults to method name)



88
89
90
# File 'lib/bbortcodes/shortcode.rb', line 88

def shortcode_attribute_reader(name, attribute_name: name)
  define_method(name) { attribute(attribute_name) }
end

.tag_nameObject

Override in subclasses to specify the shortcode tag name If not overridden, uses the class name converted to snake_case



18
19
20
21
22
23
# File 'lib/bbortcodes/shortcode.rb', line 18

def tag_name
  name.split("::").last
    .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
    .gsub(/([a-z\d])([A-Z])/, '\1_\2')
    .downcase
end

Instance Method Details

#attribute(name, default = nil, escape: nil) ⇒ String, Object

Get the value of an attribute with optional default Automatically escapes HTML if auto_escape_attributes is enabled

Parameters:

  • name (String, Symbol)

    The attribute name

  • default (Object) (defaults to: nil)

    Default value if attribute not found

  • escape (Boolean) (defaults to: nil)

    Override auto-escape setting for this attribute

Returns:

  • (String, Object)

    The attribute value



151
152
153
154
155
156
157
158
159
# File 'lib/bbortcodes/shortcode.rb', line 151

def attribute(name, default = nil, escape: nil)
  value = @attributes.fetch(name.to_s, default)
  return value if value.nil?

  # Determine if we should escape
  should_escape = escape.nil? ? BBortcodes.config.auto_escape_attributes : escape

  should_escape ? escape_html(value) : value
end

#escape_html(text) ⇒ String

Escape HTML entities to prevent XSS attacks

Parameters:

  • text (String)

    The text to escape

Returns:

  • (String)

    HTML-escaped text



138
139
140
141
# File 'lib/bbortcodes/shortcode.rb', line 138

def escape_html(text)
  return text if text.nil?
  CGI.escapeHTML(text.to_s)
end

#has_attribute?(name) ⇒ Boolean

Check if an attribute exists

Returns:

  • (Boolean)


162
163
164
# File 'lib/bbortcodes/shortcode.rb', line 162

def has_attribute?(name)
  @attributes.key?(name.to_s)
end

#render(context) ⇒ String

Render the shortcode to a string Must be implemented by subclasses

Parameters:

  • context (Context)

    The rendering context

Returns:

  • (String)

    The rendered output

Raises:

  • (NotImplementedError)


99
100
101
# File 'lib/bbortcodes/shortcode.rb', line 99

def render(context)
  raise NotImplementedError, "#{self.class.name} must implement #render"
end

#render_content(context, parser) ⇒ String

Helper method to render content (for paired shortcodes) This will recursively render nested shortcodes and text

Parameters:

  • context (Context)

    The rendering context

  • parser (Parser)

    The parser instance for rendering nested shortcodes

Returns:

  • (String)

    The rendered content



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/bbortcodes/shortcode.rb', line 110

def render_content(context, parser)
  return "" if @content.nil? || @content.empty?

  @content.map do |node|
    case node
    when Shortcode
      node.render(context)
    when String
      node
    when Hash
      # Handle raw parsed nodes that haven't been converted to Shortcode instances yet
      if node[:type] == :text
        node[:value]
      else
        # This is a parsed shortcode node, let the parser handle it
        ""
      end
    else
      node.to_s
    end
  end.join
end