class TiptapService class << self def to_html(node, tags) return '' if node.nil? children(node[:content], tags) end private def children(content, tags) content.map { node_to_html(_1, tags) }.join end def node_to_html(node, tags) case node in type: 'header', content: "
#{children(content, tags)}
" in type: 'footer', content:, **rest "#{children(content, tags)}" in type: 'headerColumn', content:, **rest "#{children(content, tags)}" in type: 'paragraph', content:, **rest "#{children(content, tags)}

" in type: 'title', content:, **rest "#{children(content, tags)}" in type: 'heading', attrs: { level:, **attrs }, content: "#{children(content, tags)}" in type: 'bulletList', content: "
    #{children(content, tags)}
" in type: 'orderedList', content: "
    #{children(content, tags)}
" in type: 'listItem', content: "
  • #{children(content, tags)}
  • " in type: 'text', text:, **rest if rest[:marks].present? apply_marks(text, rest[:marks]) else text end in type: 'mention', attrs: { id: }, **rest if rest[:marks].present? apply_marks(tags[id], rest[:marks]) else tags[id] end end end def text_align(attrs) if attrs.present? && attrs[:textAlign].present? " style=\"text-align: #{attrs[:textAlign]}\"" else "" end end def apply_marks(text, marks) marks.reduce(text) do |text, mark| case mark in type: 'bold' "#{text}" in type: 'italic' "#{text}" in type: 'underline' "#{text}" in type: 'strike' "#{text}" in type: 'highlight' "#{text}" end end end end end