class Clerq::Services::ReadNode

The service reads nodes from file and returns array of nodes It returns array because the file can have a few root nodes

Constants

NODE_REGX

Public Class Methods

new(filename, on_error = nil) click to toggle source

@param filename [String] input file for reading @param on_error [Proc] proc object {|error| …}

# File lib/clerq/services/read_node.rb, line 31
def initialize(filename, on_error = nil)
  @filename = filename
  @on_error = on_error
  @node = Node.new(id: filename)
end

Public Instance Methods

call() click to toggle source
# File lib/clerq/services/read_node.rb, line 13
def call
  # FIXME: something wrong here when foreach!
  #
  text = File.read(@filename)
  read_nodes(text) do |node_text|
    level, node = parse_node(node_text)
    next unless node
    node[:filename] = @filename
    insert_node(node, level)
  end

  ary = Array.new(@node.items)
  ary.each(&:orphan!)
  ary
end

Protected Instance Methods

insert_node(node, level) click to toggle source
# File lib/clerq/services/read_node.rb, line 55
def insert_node(node, level)
  parent = @node
  while parent.last_item && (parent.nesting_level + 1) < level
    parent = parent.last_item
  end
  unless (parent.nesting_level + 1) == level
    msg = "invalid header level: #{'#' * level} #{node.title}"
    @on_error.call(msg) if @on_error
    parent = @node
  end
  parent << node
end
parse_meta(text) click to toggle source
# File lib/clerq/services/read_node.rb, line 84
def parse_meta(text)
  text.strip.split(/[;,\n]/).inject({}) do |h, i|
    pair = /\s?(\w*):\s*(.*)/.match(i)
    h.merge(pair[1].to_sym => pair[2])
  end || {}
rescue StandardError
  msg = "invalid meta format:\n{{#{text}}}"
  @on_error.call(msg) if @on_error
  {}
end
parse_node(text) click to toggle source
# File lib/clerq/services/read_node.rb, line 68
def parse_node(text)
  text += "\n" unless text.end_with?("\n")
  parts = NODE_REGX.match(text)
  lv = parts[1] || ''
  id = parts[3] || ''
  title = parts[4] || ''
  body = parts[7] || ''
  meta = {}
  meta.merge!(parse_meta(parts[6])) if parts[6]
  [lv.size, Node.new(id: id, title: title, body: body.strip, meta: meta)]
rescue StandardError
  msg = "invalid node format: #{text}"
  @on_error.call(msg) if @on_error
  [nil, nil]
end
read_nodes(text, &block) click to toggle source

@param [Enumerator<String>] text @return [Array<String>] where each item represents one node

# File lib/clerq/services/read_node.rb, line 41
def read_nodes(text, &block)
  quote, node = false, []
  text = text.split(?\n) unless text.is_a? Enumerator
  text.each do |line|
    if line.start_with?('#') && !quote && !node.empty?
      block.call(node.join("\n"))
      node = []
    end
    node << line
    quote = !quote if line.start_with?('```')
  end
  block.call(node.join("\n")) unless node.empty?
end