require "commonmarker" class HeaderWithIdRender < CommonMarker::HtmlRenderer def header(node) block do old_stream = @stream @stream = StringIO.new(String.new.force_encoding("utf-8")) out(:children) content = @stream.string @stream = old_stream id = generate_id(content) out("", content, "") end end def generate_id(content) content.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '') end end markdown = "## My nice long header" doc = CommonMarker.render_doc(markdown, :DEFAULT) puts HeaderWithIdRender.new.render(doc)