class Object
Constants
- ElementalCreation
Entry-point for MediaMolecules to render HTML (and maybe eventually other formats!).
Liquid is arguably a poor choice for this use case since it is designed to handle arbitrary user-supplied templates in a safe way, versus e.g. ERB which allows in-template execution of arbitrary Ruby code, but our templates are bundled here in the Gem (ostensibly) should be trustworthy.
I considered using Nokogiri's DocumentFragment Builder instead: fragment = Nokogiri::HTML::DocumentFragment.parse(''.freeze) Nokogiri::HTML::Builder.with(fragment) do |doc|
doc.picture { changes.each { |change| doc.source(:srcset=change.name) } }
end fragment.to_html
But the way DistorteD works (with MIME::Type#distorted_template_method) means we would need a way to collate child elements anyway, since each call to a :distorted_template_method should generate only one variation, meaning we'd end up with a bunch of <source> tag Strings but would still need to collect them under a parent <picture> with a sibling <img>.
Liquid is already heavily used by
Jekyll
, and of course DistorteD-Jekyll itself is a Liquid::Tag, so we may as well use it. Nokogiri, on the other hand, is not an explicit dependency ofJekyll
. It will most likely be available, and DD itself pulls it in via SVGO and others, but Liquid will also allow us the flexibility to render formats other than just HTML/XML, e.g. BBCode or even Markdown.I might revisit this design decision once I experience working with more media formats and in more page contexts :)
- FATAL_FURY
- MD_IMAGE_REGEX
Replace standard Markdown image syntax with instances of DistorteD via its Liquid tag.
SYNTAX
I'm calling individual media elements “images” here because I'm overloading the Markdown image syntax to express them. There is no dedicated syntax for other media types in any flavor of Markdown as of 2019, so that seemed like the cleanest and sanest way to deal with non-images in DistorteD.
DistorteD::Invoker will do the media type inspection and handling once we get into Liquid Land. This is the approach suggested by CommonMark: talk.commonmark.org/t/embedded-audio-and-video/441/15
Media elements will display as a visibly related group when two or more Markdown image tags exist in consecutive Markdown unordered (e.g. *-+) list item or ordered (e.g. 1.) list item lines. Their captions should be hidden until opened in a lightbox or as a tooltip on desktop browsers via ::hover state.
The inspiration for this display can be seen in the handling of two, three, or four images in any single post on Tw*tter. DistorteD expands on the concept by supporting things such as groups of more than four media elements and elements of heterogeneous media types.
Standalone image elements (not contained in list item) should be displayed as single solo elements spanning the entire usable width of the container element, whatever that happens to be at the point where our regex excised a block of Markdown for us to work with.
TECHNICAL CONSIDERATIONS
Jekyll
processes Liquid templates before processing page/post Markdown, so we can't rely on customizing the Markdown renderer's `:img` element output as a means to invoke DistorteD. jekyllrb.com/tutorials/orderofinterpretation/Prefer the POSIX-style bracket expressions (e.g. [[:digit:]]) over basic character classes (e.g. d) in regex because they match Unicode instead of just ASCII. ruby-doc.org/core/Regexp.html#class-Regexp-label-Character+Classes
INLINE ATTRIBUTE LISTS
Support additional arguments passed to DistorteD via Kramdown-style inline attribute lists. kramdown.gettalong.org/syntax.html#images kramdown.gettalong.org/syntax.html#inline-attribute-lists
IALs can be on the same line or on a line before or after their associated flow element. In ambiguous situations (flow elements both before and after an IAL), the IAL applies to the flow element before it. All associated elements and IALs must be on contiguous lines.
This page provides a regex for parsing IALs, Section 5.3: golem.ph.utexas.edu/~distler/maruku/proposal.html
SOLUTION
A `pre_render` hook uses this regex to process Markdown source files and replace instances of the Markdown image syntax with instances of DistorteD's Liquid tags. Single images will be replaced with {% distorted %}. Multiple list-item images will be replaced with a {% distort %} block.
By doing with with a regex (sorry!!) I hope to avoid a hard dependency on any one particular Markdown engine. Though I only support
Kramdown
for now, any engine that supports IALs should be fine.High-level explanation of what we intend to match:
{:optional_ial => line_before_image} # Iff preceded by a blank line! (optional_list_item)? {:optional_ial => same_line} {:optional_ial => next_consecutive_line} Repeat both preceding matches (together) any number of times to parse a {% distort %} block. See inline comments below for more detail.
- UPDATE_RUBY
Public Instance Methods
# File lib/distorted-jekyll/md_injection.rb, line 151 def md_injection Proc.new { |document, payload| # Compare any given document's file extension to the list of enabled # Markdown file extensions in Jekyll's config. if payload['site']['markdown_ext'].include? document.extname.downcase[1..-1] # Convert Markdown images to {% distorted %} tags. # # Use the same Markdown parser as Jekyll to avoid parsing inconsistencies # between this pre_render hook and the main Markdown render step. # This is still effectively a Markdown-parsing regex (and still # effectively a bad idea lol) but it's the cleanest way I can come up # with right now for separating DistorteD-destined Markdown from # the rest of any given page. # NOTE: Attribute List Definitions elsewhere in a Markdown document # will be lost when converting this way. I might end up just parsing # the entire document once with my own `to_liquid` converter, but I've been # avoiding that as it seems wasteful because Jekyll then renders the entire # Markdown document a second time immediately after our Liquid tag. # It's fast enough that I should stop trying to prematurely optimize this :) # TODO: Implement MD → DD love using only the #{CONFIGURED_MARKDOWN_ENGINE}, # searching for :img elements inside :li elements to build BLOCKS. document.content = document.content.gsub(MD_IMAGE_REGEX) { |match| Kramdown::Document.new(match).to_liquid } end } end
# File lib/distorted-jekyll.rb, line 9 def update_ruby if defined? RUBY_PLATFORM if (/freebsd/ =~ RUBY_PLATFORM) != nil return 'pkg install lang/ruby27' elsif (/darwin/ =~ RUBY_PLATFORM) != nil return 'brew upgrade ruby' elsif (/win/ =~ RUBY_PLATFORM) != nil return 'https://rubyinstaller.org/' elsif (/linux/ =~ RUBY_PLATFORM) != nil if File.exists?('/etc/lsb-release') lsb = File.read('/etc/lsb-release') if (/Ubuntu|LinuxMint/ =~ lsb) != nil return 'https://www.brightbox.com/docs/ruby/ubuntu/#installation' end end end end return 'https://github.com/rbenv/ruby-build' end