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