Last active
July 21, 2021 01:57
-
-
Save watershed/e6d7b013d5d5c3903bf1575419a85e4b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{##### | |
For a `body` field with type:fieldHandles structure: | |
collStart: collId*, attr | |
subheading: text*, customId, hWrap, incToC | |
text: text* | |
quote: text*, cite, citeUrl | |
images images* (needs work) | |
video: videoUrl*,ratio | |
collEnd collId* | |
Plugin dependencies are 'Empty Coalesce', and 'Twig Perversion' for the {% return %} scope within macros. | |
A macro for each block type plus: | |
* An `updateBody` macro to update the cumulative html and hWrap status captured in a `results` hash | |
* Utility macros called within the block type macros for: | |
* setAspect : sets aspect ratio | |
* youTubeSrc: ensures coherent YouTube embed for most inputs | |
* vimeoSrc : ensures coherent Vimeo embed for most inputs | |
* docDetails: generates a <details> element with error help text from a `Docs` entry | |
#####} | |
{# | |
Set an aspect ratio from a Matrix block with a ratio field | |
The default is '16 / 9' | |
#} | |
{% macro setAspect(block, width) %} | |
{% set ratio = block.ratio ??? null %} | |
{% if ratio %} | |
{% set ratioArr = ratio|split(':') %} | |
{% set factor = ratioArr[0] / ratioArr[1] %} | |
{% set height = width // factor %} | |
{% endif %} | |
{% set ratio = ratio ? ratio|split(':')|join(' / ') : '16 / 9' %} | |
{% set aspect = { | |
width : width, | |
height: height, | |
ratio : ratio | |
} %} | |
{% return aspect %} | |
{% endmacro %} | |
{# Create a YouTube embed URL #} | |
{% macro youTubeSrc(vidUrl) %} | |
{% set vidId = 'embed' in vidUrl ? vidUrl|replace('/^http.*embed\\/([^\\?]+)(\\?.*)?$/', '$1') : null %} | |
{% set vidId = 'watch' in vidUrl ? vidUrl|replace('/^http.*\\?v=([^\\&]+)(\\&.*)?$/', '$1') : null %} | |
{% set vidId = '.be/' in vidUrl ? vidUrl|replace('/^http.*\\.be\\/([^\\?]+)(\\?.*)?$/', '$1') : null %} | |
{% set srcUrl = vidId ? "https://www.youtube.com/embed/#{vidId}" : null %} | |
{% return srcUrl %} | |
{% endmacro %} | |
{# Create a Vimeo embed URL #} | |
{% macro vimeoSrc(vidUrl) %} | |
{% set vidId = vidUrl|replace('/^http.*video\\/([0-9]+)(\\?.*)?$/', '$1') %} | |
{% set vidId = vidId ? vidId : vidUrl|replace('/^http.*\\.com(.*)?\\/([0-9]+)(\\?.*)?$/', '$2') %} | |
{% set srcUrl = vidId ? "https://player.vimeo.com/video/#{vidId}" : null %} | |
{% return srcUrl %} | |
{% endmacro %} | |
{# Set an alert message #} | |
{% macro docDetails(doc) %} | |
{% set inner = doc.body.type('text').one() ?? null %} | |
{% set inner = inner ? "<summary>View guidance</summary>#{inner|md}" : null %} | |
{% set html = inner ? "<details>#{inner}</details>" : '' %} | |
{% return html %} | |
{% endmacro %} | |
{# Body content: collection start #} | |
{% macro collStart(block) %} | |
{% set html = "<div id=\"#{block.collId|kebab}\" #{block.attr}>" %} | |
{% return html %} | |
{% endmacro %} | |
{# Body content: subheading | |
text (required) | |
customId | |
hWrap | |
inToC | |
#} | |
{% macro subheading(block) %} | |
{% set hWrap = block.hWrap %} | |
{% set prefix = hWrap ? '<div class="hwrap">' : '' %} | |
{% set hId = block.customId ??? null %} | |
{% set html = block.text matches '/^#+.*$/' ? block.text|md : "<h2>#{block.text}</h2>" %} | |
{% set hasId = hId ? true : 'id=' in html %} | |
{% set autoId = hasId ? hId : block.text|replace('/(^#+)?(.*)$/', '$2')|trim|kebab %} | |
{% set html = autoId ? html|replace('/^(<h[^>]+)>(.*)$/', "$1 id=\"#{autoId}\">$2") : html %} | |
{% set html = "#{prefix}#{html}" %} | |
{% return html %} | |
{% endmacro %} | |
{# Body content: text #} | |
{% macro text(block) %} | |
{% set html = block.text|md %} | |
{% return html %} | |
{% endmacro %} | |
{# Body content: quote | |
text (required) | |
cite | |
citeUrl | |
#} | |
{% macro quote(block) %} | |
{% set citeAttr = block.citeUrl ??? null %} | |
{% set citeAttr = citeAttr ? "cite=\"#{citeAttr}\"" : '' %} | |
{% set citeElem = block.cite|md(inlineOnly=true) %} | |
{% set citeElem = citeElem ? "<cite>#{citeElem}</cite>" : '' %} | |
{% set html = "<blockquote #{citeAttr}>#{block.text|md} #{citeElem}</blockquote>" %} | |
{% return html %} | |
{% endmacro %} | |
{# Body content: images | |
images (required) | |
#} | |
{% macro images(block) %} | |
{# #} | |
{% return results %} | |
{% endmacro %} | |
{# Body content: video #} | |
{% macro video(block) %} | |
{% import _self as macro %} | |
{# | |
Initialise an HTML width of 352 to comfortably fit within a 375px mobile viewport, | |
which is then resized by appropriate CSS | |
#} | |
{% set aspect = macro.setAspect(block, 352) %} | |
{% set vidUrl = block.videoUrl %} | |
{% set srcUrl = null %} | |
{% if 'youtu' in vidUrl %} | |
{% set srcUrl = macro.youTubeSrc(vidUrl) %} | |
{% endif %} | |
{% if 'vimeo' in vidUrl %} | |
{% set srcUrl = macro.vimeoSrc(vidUrl) %} | |
{% endif %} | |
{% if srcUrl %} | |
{% set iframe %} | |
{{ tag('iframe', { | |
id : "video-#{vidId}", | |
src : srcUrl, | |
width : aspect.width, | |
height : aspect.height, | |
frameborder : '0', | |
allowfullscreen: true | |
}) }} | |
{% endset %} | |
{% set html %} | |
{{ tag('figure', { | |
style: "aspect-ratio:#{aspect.ratio}", | |
html: iframe | |
}) }} | |
{% endset %} | |
{% else %} | |
{% if admin %} | |
{% set doc = craft.entries.section('doc').slug('embedding-videos').one() ?? null %} | |
{% set details = doc ? macro.docDetails(doc) : '' %} | |
{% set html %} | |
<div class="alert"> | |
<p>Sorry, we couldn’t insert an embedded video from the video URL format provided.</p> | |
{{ details|raw }} | |
</div> | |
{% endset %} | |
{% endif %} | |
{% endif %} | |
{% return html %} | |
{% endmacro %} | |
{# Body content: collection end #} | |
{% macro collEnd(block, results) %} | |
{% set collId = block.collId|kebab %} | |
{% set alert = "<div class=\"alert\">The collection called ‘#{collId}’ has not been started, so it can’t be ended!</div>" %} | |
{% set html = "id=\"#{collId}\"" in results.html ? '</div>' : alert %} | |
{% return html %} | |
{% endmacro %} | |
{# Update body html after processing a block #} | |
{% macro updateBody(results, html, nextType, openWrap) %} | |
{% set hWrap = openWrap is not null ? openWrap : null %} | |
{% set suffix = '' %} | |
{% if (results.hWrap and nextType == 'subheading') or (results.hWrap and nextType == 'collEnd') or (results.hWrap and not nextType) %} | |
{% set suffix = '</div>' %} | |
{% set hWrap = hWrap ? false : hWrap %} | |
{% endif %} | |
{% set html = "#{results.html}#{html}#{suffix}" %} | |
{% set results = results|merge({ | |
html : html, | |
hWrap: hWrap, | |
}) %} | |
{% return results %} | |
{% endmacro %} | |
{##### | |
The above macros called in a template partial which does the following | |
#####} | |
{# Initialise a hash to contain our HTML #} | |
{% set results = { | |
html : '', | |
hWrap: false | |
} %} | |
{% for block in body %} | |
{% set openWrap = null %} | |
{% set next = block.next ?? false %} | |
{% set nextType = next ? next.type.handle : false %} | |
{% switch block.type.handle %} | |
{% case 'collStart' %} | |
{% set html = siteMacros.collStart(block) %} | |
{% case 'subheading' %} | |
{% set html = siteMacros.subheading(block) %} | |
{% set openWrap = 'hwrap' in html %} | |
{% case 'text' %} | |
{% set html = siteMacros.text(block) %} | |
{% case 'quote' %} | |
{% set html = siteMacros.quote(block) %} | |
{% case 'images' %} | |
{% set html = siteMacros.images(block) %} | |
{% case 'video' %} | |
{% set html = siteMacros.video(block) %} | |
{% case 'collEnd' %} | |
{% set html = siteMacros.collEnd(block, results) %} | |
{% endswitch %} | |
{% set results = siteMacros.updateBody(results, html, nextType, openWrap) %} | |
{% endfor %} | |
{{ results.html|raw }} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment