repubmark/lib/repubmark/elems/list_item.rb

141 lines
3.1 KiB
Ruby

# frozen_string_literal: true
module Repubmark
module Elems
class ListItem < Base
extend Forwardable
parents :List
attr_reader :index, :titled_ref
def initialize(parent, index, titled_ref = nil)
super parent
self.index = index
self.titled_ref = titled_ref
@caption = Caption.new self
@sublist = nil
end
#################
# Basic methods #
#################
def word_count = @caption.word_count + (@sublist&.word_count || 0)
def to_html
[
"<li>\n",
build_ref(:html),
@caption.to_html,
@sublist&.to_html,
"</li>\n",
].join.freeze
end
def to_gemtext
[
if titled_ref
"#{build_ref(:gemtext)}#{@caption.to_gemtext}".strip
else
"* #{unicode_decor_own}#{@caption.to_gemtext}".strip
end,
@sublist&.to_gemtext,
].join("\n").freeze
end
##################
# Helper methods #
##################
def level = parent.level
def last? = index >= parent.items_count - 1
def unicode_decor_own
"#{parent.unicode_decor}#{last? ? '└' : '├'} " unless level.zero?
end
def unicode_decor_parent = parent.unicode_decor
###################
# Builder methods #
###################
def subolist
raise 'No nested link lists' if titled_ref
raise 'Sublist already exists' if @sublist
@sublist = List.new self, links: false, ordered: true
yield @sublist
nil
end
def subulist
raise 'No nested link lists' if titled_ref
raise 'Sublist already exists' if @sublist
@sublist = List.new self, links: false, ordered: false
yield @sublist
nil
end
def respond_to_missing?(method_name, _include_private)
@caption.respond_to?(method_name) || super
end
def method_missing(method_name, ...)
if @caption.respond_to? method_name
raise 'Caption after sublist' if @sublist
@caption.public_send(method_name, ...)
else
super
end
end
private
def parent=(parent)
unless parent.instance_of? List
raise TypeError, "Expected #{List}, got #{parent.class}"
end
@parent = parent
end
def index=(index)
index = Integer index
raise 'Invalid index' if index.negative?
@index = index
end
def titled_ref=(titled_ref)
return @titled_ref = nil if titled_ref.nil?
unless titled_ref.instance_of? TitledRef
raise TypeError, "Expected #{TitledRef}, got #{titled_ref.class}"
end
@titled_ref = titled_ref
end
def build_ref(format)
return if titled_ref.nil?
case format
when :html
"<a href=\"#{titled_ref.url}\">#{titled_ref.title}</a>\n".freeze
when :gemtext
"=> #{titled_ref.url} #{unicode_decor_own}#{titled_ref.title} ".freeze
else
raise 'Invalid format'
end
end
end
end
end