lib/commonmarker.rb in commonmarker-0.1.3 vs lib/commonmarker.rb in commonmarker-0.2.0

- old
+ new

@@ -1,281 +1,63 @@ #!/usr/bin/env ruby require 'commonmarker/commonmarker' require 'commonmarker/config' require 'commonmarker/renderer' require 'commonmarker/renderer/html_renderer' +require 'commonmarker/version' begin require 'awesome_print' rescue LoadError; end -NODE_TYPES = %i(none document blockquote list list_item - code_block html paragraph - header hrule text softbreak - linebreak code inline_html - emph strong link image) - -LIST_TYPES = %i(no_list bullet_list ordered_list) - -NONE_TYPE = 'NONE' - module CommonMarker - class NodeError < StandardError + # Public: Parses a Markdown string into an HTML string. + # + # text - A {String} of text + # option - Either a {Symbol} or {Array of Symbol}s indicating the parse options + # + # Returns a {String} of converted HTML. + def self.render_html(text, option = :default) + fail TypeError, 'text must be a string!' unless text.is_a?(String) + Node.markdown_to_html(text, Config.process_options(option)) end - class Node - attr_reader :pointer + # Public: Parses a Markdown string into a `document` node. + # + # string - {String} to be parsed + # option - A {Symbol} or {Array of Symbol}s indicating the parse options + # + # Returns the `document` node. + def self.render_doc(text, option = :default) + fail TypeError, 'text must be a string!' unless text.is_a?(String) + Node.parse_document(text, text.bytesize, Config.process_options(option)) + end - # Creates a Node. Either +type+ or +pointer+ should be provided; the - # other should be nil. If +type+ is provided, a new node with that - # type is created. If +pointer+ is provided, a node is created from the - # C node at +pointer+. - # Params: - # +type+:: +node_type+ of the node to be created (nil if +pointer+ is used). - # +pointer+:: pointer to C node (nil if +type+ is used). - def initialize(type = nil, pointer = nil) - if pointer - @pointer = pointer - else - idx = NODE_TYPES.index(type) - fail NodeError, "node type does not exist #{type}" unless idx - @pointer = CMark.node_new(type) - end - - fail NodeError, "could not create node of type #{type}" if @pointer.nil? - end - - # Parses a string into a :document Node. - # Params: - # +s+:: +String+ to be parsed. - def self.parse_string(s, option = :default) - Config.option_exists?(option) - Node.new(nil, CMark.parse_document(s, s.bytesize, Config.to_h[option])) - end - - # Parses a file into a :document Node. - # Params: - # +f+:: +File+ to be parsed (caller must open and close). - def self.parse_file(f) - s = f.read() - self.parse_string(s) - end - - def first_child - Node.new(nil, CMark.node_first_child(@pointer)) - end - - def last_child - Node.new(nil, CMark.node_last_child(@pointer)) - end - - def parent - Node.new(nil, CMark.node_parent(@pointer)) - end - - def previous - Node.new(nil, CMark.node_previous(@pointer)) - end - - def next - Node.new(nil, CMark.node_next(@pointer)) - end - - # Iterator over the children (if any) of this Node. - def each_child - childptr = CMark.node_first_child(@pointer) - until CMark.node_get_type_string(childptr) == NONE_TYPE - nextptr = CMark.node_next(childptr) - yield Node.new(nil, childptr) - childptr = nextptr - end - end - - # Deletes the node and unlinks it (fixing pointers in - # parents and siblings appropriately). Note: this method - # does not free the node. - def delete - CMark.node_unlink(@pointer) - end - - # Insert a node before this Node. - # Params: - # +sibling+:: Sibling node to insert. - def insert_before(sibling) - res = CMark.node_insert_before(@pointer, sibling.pointer) - fail NodeError, 'could not insert before' if res == 0 - end - - # Insert a node after this Node. - # Params: - # +sibling+:: Sibling Node to insert. - def insert_after(sibling) - res = CMark.node_insert_before(@pointer, sibling.pointer) - fail NodeError, 'could not insert after' if res == 0 - end - - # Prepend a child to this Node. - # Params: - # +child+:: Child Node to prepend. - def prepend_child(child) - res = CMark.node_prepend_child(@pointer, child.pointer) - fail NodeError, 'could not prepend child' if res == 0 - end - - # Returns string content of this Node. - def string_content - CMark.node_get_string_content(@pointer) - end - - # Sets string content of this Node. - # Params: - # +s+:: +String+ containing new content. - def string_content=(s) - res = CMark.node_set_string_content(@pointer, s) - fail NodeError, 'could not set string content' if res == 0 - end - - # Returns header level of this Node (must be a :header). - def header_level - fail NodeError, 'can\'t get header_level for non-header' unless type == :header - CMark.node_get_header_level(@pointer) - end - - # Sets header level of this Node (must be a :header). - # Params: - # +level+:: New header level (+Integer+). - def header_level=(level) - fail NodeError, 'can\'t set header_level for non-header' unless type == :header - if !level.is_a?(Integer) || level < 0 || level > 6 - fail NodeError, 'level must be between 1-6' - end - res = CMark.node_set_header_level(@pointer, level) - fail NodeError, 'could not set header level' if res == 0 - end - - # Returns list type of this Node (must be a :list). - def list_type - fail NodeError, 'can\'t get list_type for non-list' unless type == :list - LIST_TYPES[CMark.node_get_list_type(@pointer)] - end - - # Sets list type of this Node (must be a :list). - # Params: - # +list_type+:: New list type (+:list_type+), either - # :ordered_list or :bullet_list. - def list_type=(list_type) - fail NodeError, 'can\'t set list_type for non-list' unless type == :list - res = CMark.node_set_list_type(@pointer, list_type) - fail NodeError, 'could not set list_type' if res == 0 - end - - # Returns start number of this Node (must be a :list of - # list_type :ordered_list). - def list_start - if type != :list || list_type != :ordered_list - fail NodeError, 'can\'t get list_start for non-ordered list' - end - CMark.node_get_list_start(@pointer) - end - - # Sets start number of this Node (must be a :list of - # list_type :ordered_list). - # Params: - # +start+:: New start number (+Integer+). - def list_start=(start) - if type != :list || list_type != :ordered_list - fail NodeError, 'can\'t set list_start for non-ordered list' - end - fail NodeError, 'start must be Integer' unless start.is_a?(Integer) - res = CMark.node_set_list_start(@pointer, start) - fail NodeError, 'could not set list_start' if res == 0 - end - - # Returns tight status of this Node (must be a :list). - def list_tight - fail NodeError, 'can\'t get list_tight for non-list' unless type == :list - CMark.node_get_list_tight(@pointer) - end - - # Sets tight status of this Node (must be a :list). - # Params: - # +tight+:: New tight status (boolean). - def list_tight=(tight) - fail NodeError, 'can\'t set list_tight for non-list' unless type == :list - res = CMark.node_set_list_tight(@pointer, tight) - fail NodeError, 'could not set list_tight' if res == 0 - end - - # Returns URL of this Node (must be a :link or :image). - def url - fail NodeError, 'can\'t get URL for non-link or image' if !(type == :link || type == :image) - CMark.node_get_url(@pointer) - end - - # Sets URL of this Node (must be a :link or :image). - # Params: - # +URL+:: New URL (+String+). - def url=(url) - fail NodeError, 'can\'t set URL for non-link or image' if !(type == :link || type == :image) - fail NodeError, 'url must be a String' unless url.is_a?(String) - res = CMark.node_set_url(@pointer, url) - fail NodeError, 'could not set header level' if res == 0 - end - - # Returns title of this Node (must be a :link or :image). - def title - fail NodeError, 'can\'t get title for non-link or image' if !(type == :link || type == :image) - CMark.node_get_title(@pointer) - end - - # Sets title of this Node (must be a :link or :image). - # Params: - # +title+:: New title (+String+). - def title=(title) - fail NodeError, 'can\'t set title for non-link or image' if !(type == :link || type == :image) - fail NodeError, 'title must be a String' unless title.is_a?(String) - res = CMark.node_set_title(@pointer, title) - fail NodeError, 'could not set header level' if res == 0 - end - - # Returns fence info of this Node (must be a :code_block). - def fence_info - fail NodeError, 'can\'t get fence_info for non code_block' unless type == :code_block - CMark.node_get_fence_info(@pointer) - end - - # Sets fence_info of this Node (must be a :code_block). - # Params: - # +info+:: New info (+String+). - def fence_info=(info) - fail NodeError, 'can\'t set fence_info for non code_block' unless type == :code_block - fail NodeError, 'info must be a String' unless info.is_a?(String) - res = CMark.node_set_fence_info(@pointer, info) - fail NodeError, 'could not set info' if res == 0 - end - - # An iterator that "walks the tree," descending into children - # recursively. + class Node + # Public: An iterator that "walks the tree," descending into children recursively. + # + # blk - A {Proc} representing the action to take for each child def walk(&blk) yield self each_child do |child| child.walk(&blk) end end - # Returns the type of this Node. - def type - NODE_TYPES[CMark.node_get_type(@pointer)] - end - - def type_string - CMark.node_get_type_string(@pointer) - end - - # Convert to HTML using libcmark's fast (but uncustomizable) renderer. + # Public: Convert the node to an HTML string. + # + # Returns a {String}. def to_html(option = :default) - Config.option_exists?(option) - CMark.render_html(@pointer, Config.to_h[option]).force_encoding('utf-8') + _render_html(Config.process_options(option)).force_encoding('utf-8') end + # Internal: Iterate over the children (if any) of the current pointer. + def each_child + child = first_child + while child + nextchild = child.next + yield child + child = nextchild + end + end end end