Im using prawn to create pdfs that contain much data in table format and some lists. The problem with the lists is that Im just using text as lists because there is no semantic
Just did this for a customer. For everybody who wants to render preformatted html containing ul / ol lists:
def render_html_text(text, pdf)
#render text (indented if inside ul)
indent = 0 #current indentation (absolute, e.g. n*indent_delta for level n)
indent_delta = 10 #indentation step per list level
states = [] #whether we have an ol or ul at level n
indices = [] #remembers at which index the ol list at level n, currently is
#while there is another list tag do
# => starting position of list tag is at i
# render everything that comes before the tag
# cut everything we have rendered from the whole text
#end
while (i = text.index /<\/?[ou]l>/) != nil do
part = text[0..i-1]
if indent == 0 #we're not in a list, but at the top level
pdf.text part, :inline_format => true
else
pdf.indent indent do
#render all the lis
part.gsub(/<\/li>/, '').split('- ').each do |item|
next if item.blank? #split may return some ugly start and end blanks
item_text = if states.last == :ul
"• #{item}"
else # :ol
indices[indices.length-1] = indices.last + 1
"#{indices.last}. #{item}"
end
pdf.text item_text, :inline_format => true
end
end
end
is_closing = text[i+1] == '/' #closing tag?
if is_closing
indent -= indent_delta
i += ''.length
states.pop
indices.pop
else
pdf.move_down 10 if indent == 0
type_identifier = text[i+1] #<_u_l> or <_o_l>
states << if type_identifier == 'u'
:ul
elsif type_identifier == 'o'
:ol
else
raise "what means type identifier '#{type_identifier}'?"
end
indices << 0
indent += indent_delta
i += '
'.length
end
text = text[i..text.length-1] #cut the text we just rendered
end
#render the last part
pdf.text text, :inline_format => true unless text.blank?
end