aboutsummaryrefslogtreecommitdiff
path: root/commonmark.rb
blob: b782f1bbe48e25785ab7831e91fa3d24d3ddd97c (plain)
  1. require 'ffi'
  2. require 'stringio'
  3. module CMark
  4. extend FFI::Library
  5. ffi_lib ['libcmark', 'cmark']
  6. typedef :pointer, :node
  7. enum :node_type, [:document, :blockquote, :list, :list_item,
  8. :fenced_code, :indented_code, :html, :paragraph,
  9. :atx_header, :setext_header, :hrule, :reference_def,
  10. :str, :softbreak, :linebreak, :code, :inline_html,
  11. :emph, :strong, :link, :image]
  12. attach_function :cmark_free_nodes, [:node], :void
  13. attach_function :cmark_node_unlink, [:node], :void
  14. attach_function :cmark_markdown_to_html, [:string, :int], :string
  15. attach_function :cmark_parse_document, [:string, :int], :node
  16. attach_function :cmark_node_first_child, [:node], :node
  17. attach_function :cmark_node_parent, [:node], :node
  18. attach_function :cmark_node_next, [:node], :node
  19. attach_function :cmark_node_previous, [:node], :node
  20. attach_function :cmark_node_get_type, [:node], :node_type
  21. attach_function :cmark_node_get_string_content, [:node], :string
  22. class Node
  23. attr_accessor :type, :children, :string_content, :pointer
  24. def initialize(pointer)
  25. if pointer.null?
  26. return nil
  27. end
  28. @pointer = pointer
  29. @type = CMark::cmark_node_get_type(pointer)
  30. @children = []
  31. first_child = CMark::cmark_node_first_child(pointer)
  32. b = first_child
  33. while !b.null?
  34. @children << Node.new(b)
  35. b = CMark::cmark_node_next(b)
  36. end
  37. @string_content = CMark::cmark_node_get_string_content(pointer)
  38. if @type == :document
  39. self.free
  40. end
  41. end
  42. def to_html_stream(file)
  43. file.printf("[%s]\n", self.type.to_s)
  44. case self.type
  45. when :document
  46. self.children.each do |child|
  47. child.to_html_stream(file)
  48. end
  49. when :paragraph
  50. self.children.each do |child|
  51. child.to_html_stream(file)
  52. end
  53. when :str
  54. file.puts(self.string_content)
  55. else
  56. end
  57. end
  58. def to_html
  59. self.to_html_stream(StringIO.new)
  60. end
  61. def self.from_markdown(s)
  62. len = s.bytes.length
  63. Node.new(CMark::cmark_parse_document(s, len))
  64. end
  65. def free
  66. CMark::cmark_free_nodes(@pointer)
  67. end
  68. end
  69. end
  70. doc = CMark::Node.from_markdown(STDIN.read())
  71. doc.to_html_stream(STDOUT)
  72. # def markdown_to_html(s)
  73. # len = s.bytes.length
  74. # CMark::cmark_markdown_to_html(s, len)
  75. # end
  76. # print markdown_to_html(STDIN.read())