← back to Dw Theme Compact Toolbar

snippets/rimg.liquid

398 lines

{%- capture _ -%}
  {% comment %}
    @param img
      An Image Drop to display.

    @param lazy (optional)
      Lazy-load the image. Outputs markup to connect with the rimg JS.
      Defaults to false.

    @param background (optional)
      Output the image markup as a background image.
      Defaults to false.

    @param size (optional)
      The size to display the image at. Uses the same syntax as `img_url`.
      Defaults to the image's native size.

    @param crop (optional)
      The crop type to use. One of: top, center, bottom, left, right.
      Defaults to no cropping.

    @param scale (optional)
      A number to scale the image by.
      Defaults to '1'.

    @param format (optional)
      The format type to use. One of: jpg, pjpg.
      Defaults to original image format.

    @param placeholder (optional)
      The size to display to placeholder image at. Uses the same syntax as
      `img_url`. Only applies if `lazy` is true.
      Defaults to no placeholder image.

    @param alt (optional)
      Alt text for the image.
      Defaults to the img's alt property or an empty string if none exists.

    @param class (optional)
      CSS class names to add to the image tag's `class` attribute.
      Defaults to blank.

    @param style (optional)
      CSS styles to apply to the image tag's `style` attribute.
      Defaults to blank.

    @param attr (optional)
      Extra attributes to add to the image tag. For example: `id="example"`.
      Defaults to blank.

    @param canvas (optional)
      Add an extra element, useful for styling loaders.
      Defaults to false.

    @param disable_noscript (optional)
      Eliminates noscript tags, saving data in the cases when they aren't required.
      Defaults to false.

    @param focal_point (optional)
      Applies `background-size:cover;background-position:{{ focal_point }};` to the style property
      of the container if the image is a background-image and `object-fit:cover;object-position:[focal point]`
      otherwise on the image element.
      Defaults to blank.
  {% endcomment %}

  {% comment %}
    Defaults
  {% endcomment %}
  {% assign lazy = lazy | default: false %}
  {% assign background = background | default: false %}
  {% assign size_default = img.width | append: 'x' | append: img.height %}
  {% assign size = size | default: size_default %}
  {% assign crop = crop | default: false %}
  {% assign scale = scale | default: 1 %}
  {% assign format = format | default: '' %}
  {% assign placeholder = placeholder | default: false %}
  {% assign alt = alt | default: img.alt | default: '' %}
  {% assign class = class | default: blank %}
  {% assign style = style | default: blank %}
  {% assign attr = attr | default: blank %}
  {% assign canvas = canvas | default: false %}
  {% assign disable_noscript = disable_noscript | default: false %}
  {% assign focal_point = focal_point | default: blank %}
  {% comment %}
    Parse size parameter and force to numbers.
  {% endcomment %}
  {% assign rimg_s = size | split: 'x' %}
  {% assign rimg_w = rimg_s[0] %}
  {% assign rimg_h = rimg_s[1] %}
  {% assign rimg_size_aspect_ratio = rimg_w | times: 1.0 | divided_by: rimg_h %}

  {% comment %}
    Include focal point in style parameter if it exists
  {% endcomment %}
  {% if focal_point != blank %}
    {%- capture focal_point_style -%}
      {% if background %}
        background-size:cover;background-position:{{ focal_point }};
      {% else %}
        object-fit:cover;object-position:{{ focal_point }};
      {% endif %}
    {%- endcapture -%}

    {% if style != blank %}
      {% assign style = style | append: focal_point_style %}
    {% else %}
      {% assign style = focal_point_style %}
    {% endif %}
  {% endif %}

  {% comment %}
    Calculate width and height based on the size parameter.
  {% endcomment %}
  {% if rimg_w == blank and rimg_h == blank %}
    {% assign rimg_w = img.width %}
    {% assign rimg_h = img.height %}

  {% comment %} Size to a specific height {% endcomment %}
  {% elsif rimg_w == blank %}
    {% assign rimg_w = rimg_h | times: img.aspect_ratio %}
    {% if rimg_w > img.width %}
      {% assign rimg_w = img.width %}
      {% assign rimg_h = rimg_w | divided_by: img.aspect_ratio %}
    {% endif %}

  {% comment %} Size to a specific width {% endcomment %}
  {% elsif rimg_h == blank %}
    {% assign rimg_h = rimg_w | divided_by: img.aspect_ratio %}
    {% if rimg_h > img.height %}
      {% assign rimg_h = img.height %}
      {% assign rimg_w = rimg_h | times: img.aspect_ratio %}
    {% endif %}

  {% comment %} Size to a width and height, no crop {% endcomment %}
  {% elsif crop == blank %}
    {% if img.aspect_ratio > rimg_size_aspect_ratio %}
      {% assign rimg_h = rimg_w | divided_by: img.aspect_ratio %}
      {% if rimg_h > img.height %}
        {% assign rimg_h = img.height %}
        {% assign rimg_w = rimg_h | times: img.aspect_ratio %}
      {% endif %}

    {% else %}
      {% assign rimg_w = rimg_h | times: img.aspect_ratio %}
      {% if rimg_w > img.width %}
        {% assign rimg_w = img.width %}
        {% assign rimg_h = rimg_w | divided_by: img.aspect_ratio %}
      {% endif %}
    {% endif %}

  {% comment %} Otherwise we are sizing to a width and height, and cropping.
  If requested size is larger than the image size then we should use the
  largest possible size while maintaining the requested aspect ratio. {% endcomment %}
  {% else %}
    {% if img.aspect_ratio > rimg_size_aspect_ratio %}
      {% comment %} fit height {% endcomment %}
      {% assign rimg_h = rimg_w | divided_by: rimg_size_aspect_ratio %}
      {% if rimg_h > img.height or rimg_w > img.width  %}
        {% assign rimg_h = img.height %}
        {% assign rimg_w = rimg_h | times: rimg_size_aspect_ratio %}
      {% endif %}

    {% else %}
      {% comment %} fit width {% endcomment %}
      {% assign rimg_w = rimg_h | times: rimg_size_aspect_ratio %}
      {% if rimg_h > img.height or rimg_w > img.width %}
        {% assign rimg_w = img.width %}
        {% assign rimg_h = rimg_w | divided_by: rimg_size_aspect_ratio %}
      {% endif %}

    {% endif %}

  {% endif %}

  {% assign rimg_w = rimg_w | ceil %}
  {% assign rimg_h = rimg_h | ceil %}

  {% assign rimg_size = '' | append: rimg_w | append: 'x' | append: rimg_h %}

  {% comment %}
    Set the scale, default to 1.
  {% endcomment %}
  {% assign rimg_scale = scale %}

  {% comment %}
    Set the format
  {% endcomment %}
  {% assign rimg_format = format %}

  {% comment %}
    Try to guess the alt text based off the image if none is provided.
  {% endcomment %}
  {% assign rimg_alt = alt | escape %}

  {% comment %}
    Define a URL template. We use this to generate exact-size URLs in JS.
  {% endcomment %}
  {% assign rimg_url_template = img
    | img_url: '1x1', crop: crop
    | replace: '_1x1', '_{size}'
  %}

  {% unless rimg_format == '' %}
    {% assign rimg_url_template = img
      | img_url: '1x1', crop: crop, format: rimg_format
      | replace: '_1x1', '_{size}'
    %}
  {% endunless %}

  {% comment %}
    Define a placeholder SVG that shares the image's aspect ratio.

    Setting the image's initial `srcset` attribute to this inline SVG allows the
    image to have the correct aspect ratio before we actually load the image.
  {% endcomment %}
  {% assign rimg_placeholder = 'data:image/svg+xml;utf8,'
    | append: "<svg xmlns='http://www.w3.org/2000/svg' width='X' height='Y'></svg>"
    | replace: 'X', rimg_w
    | replace: 'Y', rimg_h
    | replace: ' ', '%20'
  %}

  {% comment %}
    Generate a `srcset` string.
  {% endcomment %}
  {% assign rimg_density = '' %}
  {% for i in (1..4) %}
    {% assign rimg_densities_w = rimg_w | times: i | round %}
    {% assign rimg_densities_h = rimg_h | times: i | round %}

    {% assign rimg_density = rimg_density | append: ' ' %}

    {% if rimg_densities_w > img.width or rimg_densities_h > img.height %}
      {% if img.aspect_ratio > rimg_size_aspect_ratio %}
        {% assign rimg_max_density = img.height | divided_by: rimg_h %}
        {% assign rimg_max_density_float = img.height | times: 100 | divided_by: rimg_h | times: 0.01 %}
      {% else %}
        {% assign rimg_max_density = img.width | divided_by: rimg_w %}
        {% assign rimg_max_density_float = img.width | times: 100 | divided_by: rimg_w | times: 0.01 %}
      {% endif %}

      {% if rimg_max_density != rimg_max_density_float %}
        {% assign rimg_max_density = rimg_max_density_float %}
      {% endif %}

      {% unless rimg_density contains rimg_max_density %}
        {% assign rimg_density = rimg_density | append: rimg_max_density %}
      {% endunless %}
      {% break %}
    {% else %}
      {% assign rimg_density = rimg_density | append: i %}
    {% endif %}
  {% endfor %}

  {% assign rimg_densities = rimg_density | split: ' ' %}
  {% assign rimg_density_srcset = '' %}
  {% for rimg_densities_i in rimg_densities %}
    {% assign rimg_densities_w = rimg_w | times: rimg_densities_i | round %}
    {% assign rimg_densities_h = rimg_h | times: rimg_densities_i | round %}

    {% assign rimg_densities_size = rimg_densities_w | append: 'x' | append: rimg_densities_h %}
    {% assign rimg_density_src = img | img_url: rimg_densities_size, crop: crop %}

    {% unless rimg_format == '' %}
      {% assign rimg_density_src = img | img_url: rimg_densities_size, crop: crop, format: rimg_format %}
    {% endunless %}

    {% assign rimg_density_srcset = rimg_density_srcset
      | append: ', '
      | append: rimg_density_src
      | append: ' '
      | append: rimg_densities_i
      | append: 'x'
    %}
  {% endfor %}
  {% assign rimg_density_srcset = rimg_density_srcset | remove_first: ', ' %}

{%- endcapture -%}

{% comment %} Background image {% endcomment %}
{% if background %}
  {% if lazy %}
    data-rimg="lazy"
    data-rimg-scale="{{ rimg_scale }}"
    data-rimg-template="{{ rimg_url_template }}"
    data-rimg-max="{{ img.width }}x{{ img.height }}"
    data-rimg-crop="{{ crop }}"
    {% if placeholder %}data-rimg-placeholder="{{ placeholder }}"{% endif %}
    {% if class != blank %}class="{{ class }}"{% endif %}
    {% if style != blank %}style="{{ style }}"{% endif %}
    {% if attr != blank %}{{ attr }}{% endif %}

  {% else %}
    {% if class != blank %}class="{{ class }}"{% endif %}
    style="
      {% if rimg_format == '' %}
        background-image: url('{{ img | img_url: rimg_size, crop: crop }}');
      {% else %}
        background-image: url('{{ img | img_url: rimg_size, format: rimg_format }}');
      {% endif %}

      {% if style != blank %}{{ style }}{% endif %}
    "
    {% if attr != blank %}{{ attr }}{% endif %}

  {% endif %}

{% comment %} Image tag {% endcomment %}
{% else %}
  {% if lazy and disable_noscript != true %}
    <noscript data-rimg-noscript>
      <img
        {% if rimg_format == '' %}
          src="{{ img | img_url: rimg_size, crop: crop }}"
        {% else %}
          src="{{ img | img_url: rimg_size, crop: crop, format: rimg_format }}"
        {% endif %}

        alt="{{ rimg_alt }}"
        data-rimg="noscript"
        srcset="{{ rimg_density_srcset }}"
        {% if class != blank %}class="{{ class }}"{% endif %}
        {% if style != blank %}style="{{ style }}"{% endif %}
        {% if attr != blank %}{{ attr }}{% endif %}
      >
    </noscript>
  {% endif %}

  <img
    {% if rimg_format == '' %}
      src="{{ img | img_url: rimg_size, crop: crop }}"
    {% else %}
      src="{{ img | img_url: rimg_size, crop: crop, format: rimg_format }}"
    {% endif %}
    alt="{{ rimg_alt }}"

    {% if lazy %}
      data-rimg="lazy"
      data-rimg-scale="{{ rimg_scale }}"
      data-rimg-template="{{ rimg_url_template }}"
      data-rimg-max="{{ img.width }}x{{ img.height }}"
      data-rimg-crop="{{ crop }}"
      {% if placeholder %}data-rimg-placeholder="{{ placeholder }}"{% endif %}
      srcset="{{ rimg_placeholder }}"
    {% else %}
      data-rimg
      srcset="{{ rimg_density_srcset }}"
    {% endif %}

    {% if class != blank %}class="{{ class }}"{% endif %}
    {% if style != blank %}style="{{ style }}"{% endif %}
    {% if attr != blank %}{{ attr }}{% endif %}
  >
{% endif %}

{% if canvas %}
  <div data-rimg-canvas></div>
{% endif %}

{%- capture _ -%}
  {% comment %}
    Unset all parameters so they don't leak between snippet calls.
  {% endcomment %}
  {% assign lazy = nil %}
  {% assign background = nil %}
  {% assign size = nil %}
  {% assign crop = nil %}
  {% assign scale = nil %}
  {% assign format = nil %}
  {% assign placeholder = nil %}
  {% assign alt = nil %}
  {% assign class = nil %}
  {% assign style = nil %}
  {% assign attr = nil %}
  {% assign canvas = nil %}
  {% assign disable_noscript = nil %}
  {% assign focal_point = nil %}
  {% comment %}
    Unset all local variables so they don't pollute the global scope.
  {% endcomment %}
  {% assign rimg_s = blank %}
  {% assign rimg_w = blank %}
  {% assign rimg_h = blank %}
  {% assign rimg_size_aspect_ratio = blank %}
  {% assign rimg_scale = blank %}
  {% assign rimg_url_template = blank %}
  {% assign rimg_alt = blank %}
  {% assign rimg_density = blank %}
  {% assign rimg_densities = blank %}
  {% assign rimg_densities_i = blank %}
  {% assign rimg_densities_w = blank %}
  {% assign rimg_densities_h = blank %}
  {% assign rimg_density_src = blank %}
  {% assign rimg_densities_size = blank %}
  {% assign rimg_density_srcset = blank %}
  {% assign rimg_placeholder = blank %}
{%- endcapture -%}