class Kramdown::Converter::Liquid

Public Instance Methods

children(el, type) click to toggle source

The incoming parsed Markdown tree will include many spurious elements, like container paragraph elements and the list item elements when parsing DD Grid style Markdown. Use this function to map a tree of arbitrary elements to a flat list of elements of a single type.

# File lib/distorted-jekyll/md_injection.rb, line 191
def children(el, type)
  matched = []

  if el.is_a? Enumerable
  # We might want to run this against an Array output from an
  # earlier invokation of this method.
    el.each {
      |item| matched.push(*children(item, type))
    }
  elsif el.type.equal? type
    # If we find the type we're looking for, stop and return it.
    # Let it bring its children along with it instead of recursing
    # into them. This will let us match container-only elements
    # such as <li> by type without considering the type of its children,
    # for situation where its children are really what we want.
    matched.push(el)
  else
    # Otherwise keep looking down the tree.
    unless el.children.empty?
      el.children.each {
        |child| matched.push(*children(child, type))
      }
    end
  end
  matched
end
convert(el) click to toggle source

Kramdown entry point

# File lib/distorted-jekyll/md_injection.rb, line 267
def convert(el)
  # The parsed "images" may also be audio, video, or some other
  # media type. There is only one Markdown image tag, however.
  imgs = children(el, :img)

  # Enable conceptual-grouping (BLOCKS) mode if the count of list item
  # elements matches the count of image elements in our
  # chunk of Markdown. Technically I should check to make sure each
  # image is the child of one of those list items,
  # but this is way easier until I (hopefully never) find a parsing
  # corner-case where this doesn't hold up.
  lists = children(el, :li)
  list_imgs = lists.map{|li| children(li, :img)}.flatten

  case lists.count
  when 0..1
    # Render one (1) image/video/whatever. This behavior is the same
    # regardless if the image is in a single-item list or just by itself.
    distorted(
      flatten_attributes(imgs.first),
      additional_defaults: {:crop => 'none'.freeze},
    )
  else
    # Render a conceptual group (DD::BLOCKS)

    if imgs.count != list_imgs.count
      # Sanity check :img count vs :img-in-:li count.
      # We should support the corner case where the regex matches
      # multiple consecutive lines, but with mixed list item status,
      # e.g. a solo image abuts a conceptual group and gets globbed
      # into a single match.
      # For now, however:
      raise "MD->img regex returned an unequal number of listed and unlisted tags."
    end

    "{% distort -%}\n#{list_imgs.map{ |img|
      distorted(flatten_attributes(img))
    }.join("\n")}\n{% enddistort %}"
  end
end
distorted(attributes, additional_defaults: {}) click to toggle source

Geenerates a DistorteD Liquid tag String given a Hash of element attributes. Examples:

{% distorted rpg-ra11.nfo alt="HellMarch INTENSIFIES" title="C&C RA2:YR NoCD NFO" encoding="IBM437" crop="none" %}
{% distorted DistorteD.png alt="DistorteD logo" title="This is so cool" crop="none" loading="lazy" %}

The :additional_defaults Hash contains attribute values to set iff those attributes have no user-given value.

# File lib/distorted-jekyll/md_injection.rb, line 252
def distorted(attributes, additional_defaults: {})
  "{% distorted #{additional_defaults.transform_keys{ |k|
    # We will end up with a Hash of String-keys and String-values,
    # so make sure override-defaults are String-keyed too.
    k.to_s
  }.merge(attributes).select{ |k, v|
    # Filter out empty values, e.g. from an unfilled title/alt field
    # in a Markdown image.
    not v.empty?
  }.map{ |k, v|
    k.to_s + '="'.freeze + v.to_s + '"'.freeze
  }.join(' '.freeze)} %}"
end
flatten_attributes(el, type = :img) click to toggle source
# File lib/distorted-jekyll/md_injection.rb, line 218
def flatten_attributes(el, type = :img)
  matched = {}

  if el.is_a? Enumerable
    # Support an Array of elements...
    el.each {
      |child| matched.merge!(flatten_attributes(child, type))
    }
  else
    # ...or a tree of elements.
    if el.type.equal? type
      # Images won't have a `:value` — only `:attr`s — and the only
      # important things in their `:options` (e.g. IAL contents)
      # will be duplicated in `class` or some other `:attr` anyway.
      # Those things should be added here if this is ever used in a
      # more generic context than just parsing the image tags.
      matched.merge!(el.attr) unless el.attr.empty?
    end
    unless el.children.empty?
      # Keep looking even if this element was one we are looking for.
      el.children.each {
        |child| matched.merge!(flatten_attributes(child, type))
      }
    end
  end
  matched
end