module Docks::Processors

Constants

CODE_BLOCK_INDICATOR
HEADING_INDICATOR
HEADING_UNDERLINE_INDICATOR
LIST_ITEM_INDICATOR

Public Instance Methods

code_block_with_language_and_description(content) click to toggle source

Public: Processes the passed content by splitting it on commas, spaces, and pipes (and removing associated whitespace).

content - An Array or String representing the parsed result.

Examples

CodeBlockWithLanguage.process([ "html - The markup.",
                                "<div class="foo">Bar</div>",
                                "<div class="bar">Baz</div>" ])
# => {language: "html", description: "The markup", code: "<div class=\"foo\">Bar</div>\n<div class=\"foo\">Bar</div>"}

CodeBlockWithLanguage.process([ "<div class="foo">Bar</div>",
                                "<div class="bar">Baz</div>" ])
# => {code: "<div class=\"foo\">Bar</div>\n<div class=\"foo\">Bar</div>"}

Returns a Hash containing the language, description, and code block.

# File lib/docks/processors.rb, line 401
def code_block_with_language_and_description(content)
  result = {}
  content = Array(content)
  possible_line_details = content.first.strip.split(/\s*\-\s*/, 2)

  if Docks::Languages.extensions.include?(possible_line_details.first)
    result[:language] = possible_line_details.first
    result[:description] = possible_line_details.last if possible_line_details.length > 1
    content.shift
  end

  result[:code] = content.join("\n")
  result
end
ensure_valid_demo_type(content) click to toggle source

Public: Processes the passed content by returning it if it’s a valid demo type, and otherwise returning the default demo type.

content - A string representing the desired demo type.

Examples

ensure_valid_demo_type(Docks::Types::Demo::SELECT)
# => "select"

ensure_valid_demo_type("foo")
# => "none"

Returns the processed string.

# File lib/docks/processors.rb, line 378
def ensure_valid_demo_type(content)
  @demo_types ||= Docks::Types::Demo.constants.map { |const| Docks::Types::Demo.const_get(const) }
  @demo_types.include?(content) ? content : Docks::Types::Demo::DEFAULT
end
join_with_smart_line_breaks(content, join = "\n\n") click to toggle source

Public: Processes the passed content by joining it with line breaks as required. to create markdown-parsable paragraphs and code blocks.

content - An Array representing the parsed result. join - The string with which to join two different paragraphs together.

Examples

join_with_smart_line_breaks(["One paragraph that", "spans two lines.", "And another!"])
# => "One paragraph that spans two lines.\n\nAnd another!"

join_with_smart_line_breaks(["One paragraph", "```html", "<p>A code block</p>", "```", "another paragraph."])
# => "One paragraph.\n\n```html\n<p>A code block</p>\n```\n\nanother paragraph"

Returns the processed string.

# File lib/docks/processors.rb, line 162
def join_with_smart_line_breaks(content, join = "\n\n")
  return content unless content.kind_of?(Array)

  text = ""
  in_code_block = false
  in_list = false
  at_start_of_paragraph = true

  content.each_with_index do |line, index|
    stripped_line = line.strip

    if stripped_line.start_with?(CODE_BLOCK_INDICATOR)
      # Either the start or end of a code block
      if in_code_block
        in_code_block = false
        at_start_of_paragraph = true

        text << "\n#{line}#{join}"
      else
        in_code_block = true
        text << "#{join}#{line}"
      end

    elsif in_code_block || (in_list && stripped_line =~ LIST_ITEM_INDICATOR)
      # Either:
      # 1. In a code block — just keep appending lines, or
      # 2. Last item was a list item and this item is directly below it,
      #    so just add that line below.
      text << "\n#{line}"

    elsif stripped_line.length == 0
      # Empty line — new paragraph
      at_start_of_paragraph = true

      text << join

    elsif stripped_line =~ LIST_ITEM_INDICATOR && at_start_of_paragraph
      # Line that looks like a list item and we're ready for a new paragraph
      in_list = true
      at_start_of_paragraph = false

      text << line

    elsif stripped_line =~ HEADING_INDICATOR
      # Starts and ends a "## Header"-style heading
      at_start_of_paragraph = true
      text << "\n#{line}\n"

    elsif stripped_line =~ HEADING_UNDERLINE_INDICATOR
      # Ends a "Header\n======"-style heading
      at_start_of_paragraph = true
      text << "#{line}#{join}"

    elsif content[index + 1] && content[index + 1].strip =~ HEADING_UNDERLINE_INDICATOR
      # Start of a "Header\n======"-style heading
      text << "\n#{line}\n"

    elsif at_start_of_paragraph
      # New line at the start of a regular paragraph
      at_start_of_paragraph = false
      in_list = false

      text << line

    else
      # Line that isn't at the start of a paragraph — pin it to the previous line.
      text << " #{stripped_line}"
    end
  end

  text.strip!
  text.gsub!(/\n{3,}/, "\n\n")
  text.length > 0 ? text : nil
end
multiline_description(content) { |line| ... } click to toggle source

Public: Processes the passed content by yielding to the passed block in order to create a base hash, then adding any subsequent lines to the description (which can start on the first line — just set the description part as the returned hash’s :description key. The description is then joined with smart line breaks.

Yields the first line (item) of content.

content - An Array of Strings representing the multiline description.

Examples

multiline_description(['bar', 'baz']) { |first_line| { foo: first_line } }
# => { foo: 'bar', description: 'baz' }

multiline_description(['bar', 'Baz']) { |first_line| { foo: first_line, description: 'Already started!' } }
# => { foo: 'bar', description: "Already started!\n\nBaz" }

Returns the processed Hash.

# File lib/docks/processors.rb, line 336
def multiline_description(content)

  content = Array(content)
  description = []
  item = nil

  content.each do |line|
    if item.nil?
      item = yield(line) if block_given?

      if !item.kind_of?(Hash)
        item = Hash.new
        description << line
      elsif !item[:description].nil?
        description << item.delete(:description)
      end
    else
      description << line
    end
  end

  unless item.nil?
    item[:description] = join_with_smart_line_breaks(description)
    item
  end
end
name_and_parenthetical(content, name_key=:name, default_for_parenthetical=nil) click to toggle source

Public: parses a string with names and optional parentheticals into an array of hashes with the name as the ‘name_key` and the parsed parenthetical options using the optional `default_for_parenthetical`.

content - The string with the name and optional parenthetical. name_key - An optional Symbol representing the key that should be

used for the non-parenthetical portion. Defaults to :name.

default_key - An optional Symbol to be used as the default key for an

unpaired item in the parentheses.

Examples

name_and_parenthetical(':matches?', :setter)
# => [{setter: ':matches?'}]

name_and_parenthetical(':size (SIZE::LARGE)', :setter, :constant)
# => [{setter: ':size', constant: 'SIZE::LARGE'}]

name_and_parenthetical([':size (SIZE::LARGE)', ':checked?'], :setter, :constant)
# => [{setter: ':size', constant: 'SIZE::LARGE'}, {setter: ':checked?'}]

Returns the parsed hash.

# File lib/docks/processors.rb, line 260
def name_and_parenthetical(content, name_key=:name, default_for_parenthetical=nil)
  result = {}
  match = content.match(/\s*(?<name>[^\(]*)(?:\s*\((?<paren>[^\)]*)\))?/)
  result[name_key] = match[:name].strip

  if (parenthetical = match[:paren]).nil?
    result
  else
    result.merge(parenthetical_options(parenthetical, default_for_parenthetical))
  end
end
parenthetical_options(content, default=nil) click to toggle source

Public:

content - A String of the parenthetical. default - An optional Symbol representing the key that should be used if

an un-paired value is provided.

Examples

parenthetical_options('Activate with : foo , active : false')
# => {activate_with: 'foo', active: 'false'}

parenthetical_options('select, active : false, javascript action: $(this).text(1 + 1)', :demo_type)
# => {demo_type: 'select', active: 'false', javascript_action: '$(this).text(1 + 1)'}

Returns the processed Hash.

# File lib/docks/processors.rb, line 288
def parenthetical_options(content, default=nil)
  return content unless content.kind_of?(String)
  result, default_only = {}, true
  default = default.to_sym unless default.nil?
  # Strip leading and trailing parentheses
  content = content.strip.sub(/^\(/, '').sub(/\)$/, '')

  # Get a leading, un-keyed value. This will be set to the default
  # key (`default`), if it was passed
  content.sub!(/\s*([^,]*),?\s*/) do |match|
    if match.index(': ').nil?
      result[default] = $1.strip unless default.nil?
      ''
    else
      match
    end
  end

  # Cycle over key value pairs and add to the return Hash
  content.scan(/\s*(?<attribute>[^:]*):\s+(?<value>[^,]*),?\s*/).each do |match|
    default_only = false
    # Ensure that the key looks like a regular symbol
    result[match[0].strip.downcase.gsub(/\s+/, '_').to_sym] = match[1].strip
  end

  result
end
split_on_characters(content, split_on="\,\s") click to toggle source

Public: Processes the passed content splitting it on type-delimitting symbols ({/} to declare the type, ,/|/s to separate them).

content - The String to break apart. split_on - The characters, passed as a single String or an Array of Strings,

on which the content string should be split. Defaults to "\,\s".

Examples

split_on_characters("String, Array", "\s\,")
# => ["String", "Array"]

Returns an Array with the split pieces.

# File lib/docks/processors.rb, line 110
def split_on_characters(content, split_on="\,\s")
  return content unless content.kind_of?(String)

  split_on = split_on.join("") if split_on.kind_of?(Array)
  return content unless split_on.kind_of?(String)

  content.split(/[#{split_on}]/).select { |piece| piece.length > 0 }
end
split_on_commas_spaces_and_pipes(content) click to toggle source

Public: Processes the passed content by splitting it on commas, spaces, and pipes (and removing associated whitespace).

content - An Array or String representing the parsed result.

Examples

split_on_commas_spaces_and_pipes("String, Array | Object")
# => ["String", "Array", "Object"]

Returns an Array of the split results.

# File lib/docks/processors.rb, line 17
def split_on_commas_spaces_and_pipes(content)
  split_on_characters(content, [",", "|", "\s"])
end
split_on_top_level_parens_commas_and_pipes(content) click to toggle source
# File lib/docks/processors.rb, line 21
def split_on_top_level_parens_commas_and_pipes(content)
  return content unless content.kind_of?(String)

  indexes = []
  depth = 0

  split_on = /[\|,]/
  content.chars.each_with_index do |char, index|
    if char == "("
      depth += 1
    elsif char == ")"
      new_depth = [0, depth - 1].max

      if new_depth == 0 && depth != 0
        indexes << index
      end

      depth = new_depth
    elsif split_on =~ char && depth == 0
      indexes << index
    end
  end


  result = []
  start_index = 0

  start_strip = /^\s*[,\|]*\s*/
  end_strip = /\s*[,\|]*\s*$/
  indexes.each do |index|
    if index > start_index
      item = content[start_index..index].gsub(start_strip, "").gsub(end_strip, "")
      result << item if item.length > 0
    end

    start_index = index + 1
  end

  if start_index < content.length
    result << content[start_index..-1].gsub(start_strip, "").gsub(end_strip, "")
  end

  result
end
split_types(content) click to toggle source

Public: Processes the passed content by splitting it on type-delimitting symbols ({/} to declare the type, ,/|/s to separate them).

content - An Array or String representing the parsed result.

Examples

split_types("{String, Number |Object[]}")
# => [
       OpenStruct.new(name: "String", array: false),
       OpenStruct.new(name: "Number", array: false),
       OpenStruct.new(name: "Object", array: true)
     ]

Returns an Array of types.

# File lib/docks/processors.rb, line 82
def split_types(content)
  split_on_commas_spaces_and_pipes(content.gsub(/[\{\}]/, "").strip).map do |type|
    array, type = if /\[\]/ =~ type
      [true, type.split("[").first]
    else
      [false, type]
    end

    type = "Anything" if type == "*"

    OpenStruct.new(name: type, array: array)
  end
end
stringy_boolean(content) click to toggle source

Public: Processes the passed String by converting it to a boolean where any string other than one matching /false/ will be considered true.

content - A String representing the parsed result.

Examples

stringy_boolean("  false ")
# => false

stringy_boolean("foo")
# => true

Returns a boolean version of the content.

# File lib/docks/processors.rb, line 135
def stringy_boolean(content)
  return false if content.nil?
  return content unless content.kind_of?(String)
  !content.include?("false")
end