# frozen_string_literal: true # Released under the MIT License. # Copyright, 2015-2020, by Garen Torikian. # Copyright, 2015, by Nick Wellnhofer. # Copyright, 2017, by Yuki Izumi. # Copyright, 2017-2019, by Ashe Connor. # Copyright, 2018, by Michael Camilleri. # Copyright, 2020-2023, by Samuel Williams. require_relative 'generic' require 'cgi' module Markly module Renderer class HTML < Generic def initialize(ids: false, tight: false, **options) super(**options) @ids = ids @section = nil @tight = tight @footnotes = {} end def document(_) @section = false super out("\n\n") if @written_footnote_ix out("") if @section end def id_for(node) if @ids id = node.to_plaintext.chomp.downcase.gsub(/\s+/, '-') return " id=\"#{CGI.escape_html id}\"" end end def header(node) block do if @ids out('') if @section @section = true out("") end out('", :children, '') end end def paragraph(node) if @tight && node.parent.type != :blockquote out(:children) else block do container("", '

') do out(:children) if node.parent.type == :footnote_definition && node.next.nil? out(' ') out_footnote_backref end end end end end def list(node) old_tight = @tight @tight = node.list_tight block do if node.list_type == :bullet_list container("\n", '') do out(:children) end else start = if node.list_start == 1 "\n" else "
    \n" end container(start, '
') do out(:children) end end end @tight = old_tight end def list_item(node) block do tasklist_data = tasklist(node) container("#{' ' if tasklist?(node)}", '') do out(:children) end end end def tasklist(node) return '' unless tasklist?(node) state = if checked?(node) 'checked="" disabled=""' else 'disabled=""' end ">\n", '') do out(:children) end end end def hrule(node) block do out("") end end def code_block(node) block do if flag_enabled?(GITHUB_PRE_LANG) out("') else out("') else out('>') end end out(escape_html(node.string_content)) out('') end end def html(node) block do if flag_enabled?(UNSAFE) out(tagfilter(node.string_content)) else out('') end end end def inline_html(node) if flag_enabled?(UNSAFE) out(tagfilter(node.string_content)) else out('') end end def emph(node) out('', :children, '') end def strong(node) if node.parent.nil? || node.parent.type == node.type out(:children) else out('', :children, '') end end def link(node) out('', :children, '') end def image(node) out('', :children, '') end def text(node) out(escape_html(node.string_content)) end def code(node) out('') out(escape_html(node.string_content)) out('') end def linebreak(_node) out("
\n") end def softbreak(_) if flag_enabled?(HARD_BREAKS) out("
\n") elsif flag_enabled?(NO_BREAKS) out(' ') else out("\n") end end def table(node) @alignments = node.table_alignments @needs_close_tbody = false out("\n", :children) out("\n") if @needs_close_tbody out("\n") end def table_header(node) @column_index = 0 @in_header = true out("\n\n", :children, "\n\n") @in_header = false end def table_row(node) @column_index = 0 if !@in_header && !@needs_close_tbody @needs_close_tbody = true out("\n") end out("\n", :children, "\n") end def table_cell(node) align = case @alignments[@column_index] when :left then ' align="left"' when :right then ' align="right"' when :center then ' align="center"' else; '' end out(@in_header ? "" : "", :children, @in_header ? "\n" : "\n") @column_index += 1 end def strikethrough(_) out('', :children, '') end def footnote_reference(node) label = node.parent_footnote_def.string_content out("#{node.string_content}") # out(node.to_html) end def footnote_definition(node) unless @footnote_ix out("
\n
    \n") @footnote_ix = 0 end @footnote_ix += 1 label = node.string_content @footnotes[@footnote_ix] = label out("
  1. \n", :children) out("\n") if out_footnote_backref out("
  2. \n") #
#
end private def out_footnote_backref return false if @written_footnote_ix == @footnote_ix @written_footnote_ix = @footnote_ix out("") true end def tasklist?(node) node.type_string == 'tasklist' end def checked?(node) node.tasklist_item_checked? end end end end