# Code Snippets

# Rich Text Snippet

Full Code

//prismic-richtext.liquid

<div class="richtext">
  {% for block in richtext %}
    {%- assign block_type = block.type -%}
    {%- assign spans = block.spans -%}
    {%- assign text = block.text -%}
    {%- assign text_length = text | size  -%}
    {%- assign formatted_text = '' -%}
    {%- assign text_cursor = 0 -%}
  
    {%- if spans.size > 0 -%}
      {%- for span in spans -%}
        {%- assign span_start = span.start -%}
        {%- assign span_end  = span.end -%}
        {%- assign span_length = span_end | minus: span_start -%}
  
        {%- comment -%}Copy the text from the last span (or start of string) to the start of this span{%- endcomment -%}
        {%- assign cursor_to_span_length = span_start | minus: text_cursor -%}
        {%- assign cursor_to_span = text | slice: text_cursor, cursor_to_span_length -%}
        {%- assign formatted_text = formatted_text | append: cursor_to_span -%}
  
        {%- comment -%}Format and copy span{%- endcomment -%}
        {%- assign span_text = text | slice: span_start, span_length -%}
        {%- assign span_type = span.type -%}
        {%- case span_type -%}
          {%- when 'strong' -%}
            {%- capture formatted_span -%}<strong>{{span_text}}</strong>{%- endcapture -%}
          {%- when 'em' -%}
            {%- capture formatted_span -%}<em>{{span_text}}</em>{%- endcapture -%}
          {%- when 'hyperlink' -%}
            {%- capture formatted_span -%}<a class="richtext__link" href={{span.data.url}} {%- if span.data.target != blank -%}target="{{ span.data.target }}"{%- endif -%}>{{span_text}}</a>{%- endcapture -%}
          {%- when 'label' -%}
            {%- capture formatted_span -%}<span class="richtext__label-{{ span.data.label | handleize }}">{{span_text}}</span>{%- endcapture -%}
          {%- else -%}
            {%- capture formatted_span -%}<span class="richtext__{{ span_type }}">{{span_text}}</span>{%- endcapture -%}
        {%- endcase -%}
  
        {%- assign formatted_text = formatted_text | append: formatted_span -%}
  
        {%- comment -%}Move cursor{%- endcomment -%}
        {%- assign text_cursor = span_end -%}
      {%- endfor -%}
  
      {%- comment -%}Copy remaining text{%- endcomment -%}
      {%- assign cursor_to_end = text | slice: text_cursor, text_length -%}
        {%- assign formatted_text = formatted_text | append: cursor_to_end -%}
      {%- else -%}
        {%- assign formatted_text = text -%}
      {%- endif -%}
  
      {% case block_type %}
          {% when 'paragraph' %}
              <p class="richtext__text">{{formatted_text}}</p>
          {% when 'heading1' %}
              <div class="richtext__heading1" data-richText-heading>{{formatted_text}}</div>
          {% when 'heading2' %}
            <div class="richtext__heading2" data-richText-heading>{{formatted_text}}</div>
          {% when 'heading3' %}
            <div class="richtext__heading3" data-richText-heading>{{formatted_text}}</div>
          {% when 'heading4' %}
            <div class="richtext__heading4" data-richText-heading>{{formatted_text}}</div>
          {% when 'heading5' %}
            <div class="richtext__heading5" data-richText-heading>{{formatted_text}}</div>
          {% when 'heading6' %}
            <div class="richtext__heading6" data-richText-heading>{{formatted_text}}</div>
          {% when 'o-list-item' %}
            <ol class="richtext__ol">
              <li class="richtext__olItem">{{formatted_text}}</li>
            </ol>
          {% when 'list-item' %}
            <ul class="richtext__ul">
              <li class="richtext__ul-item">{{formatted_text}}</li>
            </ul>
          {% when 'image' %}
            <img src="{{block.url}}" alt="{{block.alt}}">
          {% else %}
            <span>{{formatted_text}}</span>
      {% endcase %}
  {% endfor %}
</div>

Example

{% assign section = metafields[module] %}
{% render 'prismic-richtext', richtext: section.richtext %}

# Fetch content of a repeated-zone

Fetching content through the repeated zone might get tricky. That's because, Each placeholder aka, metafields key on repeated-zone is saved with metafields with _{index number}

Full Code

snippets/test-slice.liquid

<!-- fetch metafields based on namespace(slice_test) -->
{% assign section = metafields[module] %} 

<! -- fetch total number of repetable items based on namespace -->
{%- assign length = section.count | minus: 1 -%}

<!-- Render data -->
<div class="item__list">
   <!--  Loop within the total count  -->
    {% for index in (0..length) %}
       <!-- Generate metafields key -->
        {%- assign title = 'block_title_' | append: index -%} 
        {%- assign description = 'block_description_' | append: index -%}
       <div class="item__single">
         <h2 class="item__title">{{section[title]}}</h2> 
         <p class="item__text">{{section[description]}}</p>
       </div>
    {% endfor %}
</div>

TIP

Want to learn more about this code ? Learn more


# LazyLoading Images

Existing Lazyloading snippet might not work with prismic because of the cdn url it gives. The CDN url for images provided by prismic offers fetching of images of different resolutions by using &w suffix.

So we have two approach here :

# Lazyload image With existing snippet(any)

Follow this Procedure

DANGER

We are using lazysizes plugin for lazyloading images. So check package.json if its installed.


Full Code

//lazy-images.liquid

{%- assign lazy_image_url = image.url |  append: '&w={width}' -%}
{%- assign default_image_url = image.url |  append: '&w=10' -%}
{%- assign noscript_image_url = image.url |  append: '&w=2048' -%}

{% comment %}Need to add a crop parameter to the image urls to fit the aspect{% endcomment %}
{%- if aspect_ratio != blank -%}
  {%- assign lazy_image_url = lazy_image_url |  append: '&h={height}&fit=crop' -%}
  {%- assign default_image_url = default_image_url |  append: '&h={height}&fit=crop' -%}
  {%- assign noscript_image_url = noscript_image_url |  append: '&h={height}&fit=crop' -%}
{%- endif -%}

{%- if crop_parameters != blank -%}
  {%- assign lazy_image_url = lazy_image_url | append: '&crop=' | append: crop_parameters -%}
  {%- assign default_image_url = default_image_url |  append: '&crop=' | append: crop_parameters -%}
  {%- assign noscript_image_url = noscript_image_url |  append: '&crop=' | append: crop_parameters -%}
{%- endif  -%}

{%- assign height_float = image.dimensions.height | times: 1.0 -%}
{%- assign image_aspect_ratio = image.dimensions.width | divided_by: height_float -%}
{%- assign aspect_ratio = aspect_ratio | default: image_aspect_ratio -%}

{% render 'responsive-image',
    max_width: max_width,
    max_height: max_height,
    image_id: image.id,
    lazy_image_url: lazy_image_url,
    default_image_url: default_image_url,
    noscript_image_url: noscript_image_url,
    image_aspect_ratio: aspect_ratio,
    image_width: image.dimensions.width,
    image_height: image.dimensions.height,
    image_alt: image.alt,
    image_class: image_class,
    image_attributes: image_attributes,
    wrapper_class: wrapper_class,
    wrapper_attributes: wrapper_attributes %}

//responsive-image.liquid

{%- comment -%}
    It creates a style tag and it restricts an image from growing larger than its max resolution.

    Dependencies:
    - Lazysizes plugin (https://github.com/aFarkas/lazysizes) which enable responsive image with faster load time and better performance.
    - Lazysizes Responsive Images as a Service (https://github.com/aFarkas/lazysizes/tree/gh-pages/plugins/rias) To load the correct image size with our CDN
    - Lazysizes Bgset (https://github.com/aFarkas/lazysizes/tree/gh-pages/plugins/bgset) To use responsive images on background-image (CSS)

    Accepts:
    - max_width: {Number} Max width of the image container
    - max_height: {Number} Max height of the image container
    - image_id: a unique ID for the image
    - lazy_image_url: {String} the url to lazy load the image (with necessary {width} and/or {height} replacement parameters)
    - default_image_url: {String} the default image to load before lazy-loading,
    - noscript_image_url: {String} the image to load when javascript is unavailable,
    - image_aspect_ratio: {Number} the image aspect ratio,
    - image_width: {Number} the image width,
    - image_height: {Number} the image height,
    - image_alt: {String} the image alt text,
    - image_class: {String} class name of the <img />
    - image_attributes: {String}  additional HTML attributes of the <img />
    - wrapper_class: {String} class name of the <div> wrapper
    - wrapper_attributes: {String} additional HTML attributes of the <div> wrapper

    Usage:
    In your liquid template file, copy the following line
    - {% include 'responsive-image' with image: featured_image, image_class: "css-class", wrapper_class: "wrapper-css-class", max_width: 700, max_height: 800 %}
{%- endcomment -%}

{%- comment -%} Added generated number to avoid conflict styling code when the same images are using this snippet {%- endcomment -%}
{%- assign min = 100 -%}
{%- assign max = 10000 -%}
{%- assign diff = max | minus: min -%}
{%- assign generated_image_id = "now" | date: "%N" | modulo: diff | plus: min -%}

{%- assign max_height = max_height | default: 1900 -%}
{%- assign max_width = max_width | default: 1900 -%}

<style>
  {%- comment -%}
    The image aspect ratio tells us the orientation of the image:
    - less than 1.0 is portrait
    - exactly 1.0 is square
    - greater than 1.0 is landscape
  {%- endcomment -%}
  {%- if image_aspect_ratio <= 1 -%}
    {%- assign max_height_image = image_height | at_most: max_height -%}
    {%- assign max_width_image = max_height_image | times: image_aspect_ratio -%}
  {%- else -%}
    {%- if image_width > 1280 -%}
      {%- comment -%} If we have a really big image, assume that it's a hero image that needs to be fullscreen {%- endcomment -%}
      {%- assign max_width_image = max_width -%}
    {%- else -%}
      {%- assign max_width_image = image_width | at_most: max_width -%}
    {%- endif -%}
    {%- assign max_height_image = max_width_image | divided_by: image_aspect_ratio -%}
  {%- endif -%}

  {%- assign max_width_image_float = max_width_image | times: 1.0  -%}

  #Image-{{ image_id }}-{{ generated_image_id }} {
    max-width: {{ max_width_image }}px;
    max-height: {{ max_height_image }}px;
  }
  #ImageWrapper-{{ image_id }}-{{ generated_image_id }} {
    max-width: {{ max_width_image }}px;
  }

  #ImageWrapper-{{ image_id }}-{{ generated_image_id }}::before {
    {%- comment -%}
      When you change the window screen width, we want to make sure that the container's size is proportionally calculated.
      Note regarding padding percentage: The percentage is calculated with respect to the width of the generated box's containing block (source: http://www.w3.org/TR/2011/REC-CSS2-20110607/box.html#padding-properties)
    {%- endcomment -%}
    padding-top:{{ max_height_image | divided_by: max_width_image_float | times: 100}}%;
  }
</style>

{%- comment -%} Limit image widths to valid options based on image_width {%- endcomment -%}
{%- assign image_widths = '180,360,540,720,900,1080,1296,1512,1728,1944,2160,2376,2592,2808,3024' | split: ',' -%}
{%- capture image_widths -%}
  {%- for width in image_widths -%}
    {%- comment -%} Check if image width is less or equal to width {%- endcomment -%}
    {%- assign width_num = width | plus: 0 | round -%}
    {%- if image_width >= width_num -%}{{ width_num }},{%- endif -%}
  {%- endfor -%}
  {{ image_width }}
{%- endcapture -%}
{%- assign image_widths = image_widths | strip_newlines -%}

<div id="ImageWrapper-{{ image_id }}-{{ generated_image_id }}" data-image-id="{{ image_id }}" class="responsive-image__wrapper {{ wrapper_class }}" {{ wrapper_attributes }}>
  <img id="Image-{{ image_id }}-{{ generated_image_id }}"
    class="responsive-image__image lazyload {{ image_class }}"
    src="{{ default_image_url }}"
    srcset="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/u3zfwAJrQPhbkYXzAAAAABJRU5ErkJggg=="
    data-src="{{ lazy_image_url }}"
    data-widths="[{{ image_widths }}]"
    data-aspectratio="{{ image_aspect_ratio }}"
    data-sizes="auto"
    tabindex="-1"
    alt="{{ image_alt | escape }}"
    {{ image_attributes }}
  >
</div>

<noscript>
  <img class="{{ image_class }}" src="{{ noscript_image_url }}" alt="{{ image_alt | escape }}">
</noscript>

Example

{% render 'prismic-responsive-image', image: section.desktop_image, aspect_ratio: aspect_ratio %}

{% comment %}Aspect ratio is optional here {% endcomment %}

Options Provided

image
This accepts object image object that prismic saves as a metafield.

aspectRatio
It defines the the width/height ratio of an image.
If value is more than 1, it means image have more width than height.
If less than 1 , it means image have more height than width.


# Lazyload Images only for prismic

Full Code

{%- assign image_widths_array = "100,116,134,156,182,210,244,282,328,380,442,512,594,688,798,926,1074,1246,1446,1678,1946,2258,2618,3038" | split: ',' %}
 
{%- unless imageId -%}		
	{%- assign min = 100 %}
	{%- assign max = 10000 %}
	{%- assign diff = max | minus: min %}
	{%- assign imageId = "now" | date: "%N" | modulo: diff | plus: min %}
{%- endunless -%}

{%- if width -%}
	{%- assign imageWidth = width -%}
{%- endif -%}

{% if prismic %}
	{%- assign src = imageData.url %}
	{%- unless imageWidth -%}
	{%- assign imageWidth = imageData.dimensions.width %}
	{%- endunless -%}
	{%- assign imageHeight = imageData.dimensions.height %}
	{%- assign widthParam = "&w=" %}
	{%- assign initialSrc = src | append: '&w=10' %}
	{%- assign alt = imageData.alt %}
{% else %}
	{%- assign src = imageData | img_url: "master" %}
	{%- unless imageWidth -%}
	{%- assign imageWidth = imageData.width %}
	{%- endunless -%}
	{%- assign imageHeight = imageData.height %}
	{%- assign widthParam = "&width=" %}
	{%- assign initialSrc = imageData | img_url: '10x10' %}
	{%- assign alt = imageData.alt %}
{% endif %}

{%- if src contains '.svg' -%}
	{%- assign isSVG = true -%}
{%- else -%}
	{%- assign isSVG = false -%}
{%- endif -%}

{%- if isSVG -%}
	{%- assign initialSrc = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' %}
{%- endif -%}

{%- capture image_widths_array -%}
  {%- for width in image_widths_array -%}
    {%- comment -%} Check if image width is less or equal to width {%- endcomment -%}
    {%- assign width_num = width | plus: 0 | round -%}
    {%- if imageWidth >= width_num -%}{{ src | append: widthParam | append: width_num | append: " " | append: width_num | append: "w"}},{%- endif -%}
  {%- endfor -%}
  {{ src | append: widthParam | append: imageWidth | append: " " | append: imageWidth | append: "w"}}
{%- endcapture -%}
{%- assign image_widths_array = image_widths_array | strip -%}
{%- assign iwidth = imageWidth | times: 1.0 %}

{%- if aspectRatio -%}
	{%- assign aspect_ratio = aspectRatio -%}
{%- else -%}
	{%- assign aspect_ratio = imageHeight | divided_by: iwidth -%}
{%- endif -%}

{%- if imageWidth > imageHeight -%}
	{%- assign mode = 'image--landscape' -%}
{%- elsif imageHeight > imageWidth -%}
	{%- assign mode = 'image--portrait' -%}
{%- else -%}
	{%- assign mode = 'image--square' -%}
{%- endif -%}

<picture id="image{{imageId}}" class="image {{class}} {{mode}}" style="--maxw: {{imageWidth}}px;--maxh: {{imageHeight}}px;--aspect-ratio:var(--ov-aspect-ratio, {{ aspect_ratio }});{%- if fit -%}--image-fit:{{fit}};{%- endif -%}" data-loaded="{%- if load -%}true{%- else -%}false{%- endif -%}" {%- if isSVG -%}data-svg="true"{%- endif -%}>
	{%- unless isSVG -%}
		<source 
			{% if load %} srcset="{{ image_widths_array }}"{% else %}data-srcset="{{ image_widths_array }}"{%- endif -%}
			sizes="{{ sizes }}"
			aria-hidden="true"
		/>
	{%- endunless -%}
	{%- if isSVG and load -%}
		<img
			class="image__elem"
			src="{{ src }}"
			alt="{{ alt }}" 
		/>
	{%- elsif isSVG -%}
		<img
			class="image__elem"
			src="{{ initialSrc }}"
			alt="{{ alt }}" 
			data-src="{{ src }}"
		/>
	{%- else -%}
		<img
			class="image__elem"
			src="{{ initialSrc }}"
			alt="{{ alt }}"
		/>
	{%- endif -%}
</picture>

{%- unless noscript or load -%}

<script>
	{
		{%- if globalObject -%}
			const objectName = '{{ globalObject }}'
			window[objectName] = {
				width: {{imageWidth}},
				height: {{imageHeight}}
			};
		{%- endif -%}
		const lazyImages = window.lazyImages = window.lazyImages || []
		const el = document.querySelector("#image{{imageId}}")
		if(el && window.lazyImageFn) window.lazyImageFn(el);
		else if(el) lazyImages.push(el)
	}
</script>
{%- endunless -%}

Example

{% include 'lazyimage', imageData:section['placeholder_id'], prismic: true, fit: "fill", noscript: true, aspectRatio: aspectRatio %}

Options Provided

imageData
This accepts object image file that prismic saves as a metafield.

prismic If true, this will look for url key instead of src , because prismic image object consists image url in key of url instead of common key, src.

fit Options:

  • "fit" : This will crop the image, if image resolution is higher than container. Image wont expand to fill the space, if image resolution is lower than container.

  • "fill" This will sqeeze the image , if image resolution is higher than container. Image will expand to fill the container if image resolution is lower than the container.

aspectRatio
It defines the the height/width ratio of an image.
If value is more than 1, it means image have more height than width.
If less than 1 , it means image have more width than height.


# JSON output for non-repeatable zone

Well this is preety straight forward. Hope i didn't kill your hype. 😛

Ok, so create a new snippet.

snippets > json-output-{namespace}.liquid

{%- assign namespace = 'namespace-name' -%}
{% assign page_handle = 'page-handle' %}
{% assign section = pages[page_handle].metafields %}
{% assign block_content = section[namespace] %}
{%- assign length = block_content.count | minus: 1 -%}
{% assign title = section['title'] %}

[
 {
     "title": "{{title}}"
 }
]

# JSON output for repeatable zone

snippets > json-output-{namespace}.liquid

{%- assign namespace = 'namespace-name' -%}
{% assign page_handle = 'page-handle' %}
{% assign section = pages[page_handle].metafields %}
{% assign block_content = section[namespace] %}
{%- assign length = block_content.count | minus: 1 -%}


[
{% for index in (0..length) %}
 {% assign title = 'title_' | append: index %}
 {
     "title" : "{{title}}"
 }
 {% unless forloop.last %}
 ,
 {% endunless %}
{% endfor %}
]

# JSON Usage Example

templates > Collection.liquid

<script>
{
  "data": {% render "json-output-{namespace}" %}
}
</script>

TIP

You can pass the required variable like namespace or page handle directly into the snippet.
This is just a basic implementation.