Class: Kramdown::Converter::Liquid

Inherits:
Base
  • Object
show all
Defined in:
lib/distorted-jekyll/md_injection.rb

Instance Method Summary collapse

Instance Method Details

#attrs(el, type = :img) ⇒ Object



218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/distorted-jekyll/md_injection.rb', line 218

def attrs(el, type = :img)
  matched = []

  if el.is_a? Enumerable
    # Support an Array of elements...
    el.each {
      |child| matched.push(*attrs(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 << 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.push(*attrs(child, type))
      }
    end
  end
  matched
end

#children(el, type) ⇒ Object

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.



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# 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) ⇒ Object

Kramdown entry point



263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/distorted-jekyll/md_injection.rb', line 263

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(attrs(imgs.first)&.first&.merge({
      # Images default to `attention` cropping for desktop/mobile versatility.
      # Override this for single images unless a cropping value was already set.
      'crop'.freeze => attrs(imgs.first)&.first&.dig('crop'.freeze) || '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(*attrs(img))}.join("\n")}\n{% enddistort %}"
  end
end

#distorted(attrs) ⇒ Object



258
259
260
# File 'lib/distorted-jekyll/md_injection.rb', line 258

def distorted(attrs)
  "{% distorted #{attrs.map{|k,v| to_attrs(k, v)}.join(' ')} %}"
end

#to_attrs(k, v) ⇒ Object

Convert Markdown element attributes to a string key=value, except for ‘src` (DD-specific)



248
249
250
251
252
253
254
255
256
# File 'lib/distorted-jekyll/md_injection.rb', line 248

def to_attrs(k, v)
  # DistorteD prefers the media filename as a positional argument,
  # not a named kwarg.
  if k == 'src'
    v.to_s
  else
    k.to_s + '="' + v.to_s + '"'
  end
end