Yaml in Shortcodes!

I’d like to use YAML inside my shortcodes so that I can have complex elements. I got the idea from Command-line Interfaces (CLIs) - The Go Programming Language and they use:

{{ section-videos `

- resources/videos/youtube/isU2kPc5HFw
- resources/videos/youtube/\_rJoehoYIVA
- resources/videos/youtube/Wvdh1lJfcLM
- resources/videos/youtube/3jYFD-6_kZk

`}}

I was trying to do something like:

{{< section-videos >}}
- resources/videos/youtube/isU2kPc5HFw
- resources/videos/youtube/\_rJoehoYIVA
- resources/videos/youtube/Wvdh1lJfcLM
- resources/videos/youtube/3jYFD-6_kZk
{{< /section-videos >}}

But its 1) not rendering well in VSCode, and 2) I can’t seam to get access to the content as YAML as it wants it to be markdown…

Any ideas how to do this with shortcodes, or how to do it as go.dev has it?

{{ $data := .Inner | transform.Unmarshal "application/x-yaml" }}
<section class="container my-5">
  <div class="row">
    {{ if and (not (eq $data nil)) (gt (len $data) 0) }}
      {{ range $index, $videos := $data }}
        <div class="col-lg-6 col-sm-12 col-md-12 p-2">
          <!-- e -->
          {{ $videoItem := .Site.GetPage $videos }}
          {{ if $videoItem }}
            <div class="p-4 bg-white">
              <iframe
                width="560"
                height="315"
                src="https://www.youtube.com/embed/{{ $videoItem.Params.videoId }}"
                title="{{ $videoItem.Params.title }}"
                frameborder="0"
                allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
                referrerpolicy="strict-origin-when-cross-origin"
                allowfullscreen></iframe>
            </div>
          {{ else }}
            <p>Video `{{ $videos }}` not found.</p>
          {{ end }}
        </div>
      {{ end }}
    {{ else }}
      <div class="row">
        <div class="col-lg-6 col-sm-12 col-md-12 p-2">
          <div class="p-4 bg-white">
            <iframe
              width="560"
              height="315"
              src="https://www.youtube.com/embed/yCyjGBNaRqI"
              title="NKD Agility Mission and Purpose"
              frameborder="0"
              allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
              referrerpolicy="strict-origin-when-cross-origin"
              allowfullscreen></iframe>
          </div>
        </div>
        <div class="col-lg-6 col-sm-12 col-md-12 p-2">
          <div class="p-4 bg-white">
            <iframe
              width="560"
              height="315"
              src="https://www.youtube.com/embed/BJZdyEqHhXc"
              title=""
              frameborder="0"
              allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
              referrerpolicy="strict-origin-when-cross-origin"
              allowfullscreen></iframe>
          </div>
        </div>
      </div>
    {{ end }}
  </div>
</section>

OK, so I got it to work in a hacky kind of way… I’d love some feedback!

In my markdown I have:

<!-- prettier-ignore -->
<div>
{{< section-videos `
items:
- resources/videos/youtube/isU2kPc5HFw
- resources/videos/youtube/\_rJoehoYIVA
- resources/videos/youtube/Wvdh1lJfcLM
- resources/videos/youtube/3jYFD-6_kZk
`>}}
</div>

And then my shortcode is:

{{ $data :=  transform.Unmarshal (.Get 0) }}
{{ .Site }}
<section class="container my-5">
  <div class="row">
    {{ if and (not (eq $data.items nil)) (gt (len $data.items) 0) }}
      {{ range $index, $videos := $data.items }}
        <div class="col-lg-6 col-sm-12 col-md-12 p-2">
          <!-- e -->
          {{ $videoItem := $.Page.Site.GetPage $videos }}
          {{ if $videoItem }}
            <div class="p-4 bg-white">
              <iframe
                width="560"
                height="315"
                src="https://www.youtube.com/embed/{{ $videoItem.Params.videoId }}"
                title="{{ $videoItem.Params.title }}"
                frameborder="0"
                allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
                referrerpolicy="strict-origin-when-cross-origin"
                allowfullscreen></iframe>
            </div>
          {{ else }}
            <p>Video `{{ $videos }}` not found.</p>
          {{ end }}
        </div>
      {{ end }}
    {{ else }}
      <div class="row">
        <div class="col-lg-6 col-sm-12 col-md-12 p-2">
          <div class="p-4 bg-white">
            <iframe
              width="560"
              height="315"
              src="https://www.youtube.com/embed/yCyjGBNaRqI"
              title="NKD Agility Mission and Purpose"
              frameborder="0"
              allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
              referrerpolicy="strict-origin-when-cross-origin"
              allowfullscreen></iframe>
          </div>
        </div>
        <div class="col-lg-6 col-sm-12 col-md-12 p-2">
          <div class="p-4 bg-white">
            <iframe
              width="560"
              height="315"
              src="https://www.youtube.com/embed/BJZdyEqHhXc"
              title=""
              frameborder="0"
              allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
              referrerpolicy="strict-origin-when-cross-origin"
              allowfullscreen></iframe>
          </div>
        </div>
      </div>
    {{ end }}
  </div>
</section>

This works:

{{ $data := .Inner | transform.Unmarshal }}

There’s (currently) no option transform.Unmarshal, we look at the content to see if it’s YAML, TOML, JSON or CSV.

… but

transform.Unmarshal transforms YAML into a map, so you need a root, e.g.

videos:
   - foo
   - bar
1 Like

This markdown looks quite ok for me in vscode:

  • written without the blank lines and formatted by prettier plugin
{{< section-videos >}}

```
-  resources/videos/youtube/isU2kPc5HFw
-  resources/videos/youtube/_rJoehoYIVA
-  resources/videos/youtube/Wvdh1lJfcLM
-  resources/videos/youtube/3jYFD-6_kZk
```

{{< /section-videos >}}

dunno if it’s less hacky but …

  • trim the "formatting pre and postfix
  • add a root
{{ $data := add "items:\n" (trim .Inner "\n` ") }}

{{ $data := $data | transform.Unmarshal }}

{{ range $data.items }}
   {{ warnf "VIDEO: %s" . }}
{{ end }}
2 Likes

Is add a … template function I don’t know about? But yea, that concept will also work.

1 Like

From math.Add | Hugo

You can also use the add function to concatenate strings.

{{ add "hu" "go" }} → hugo

Simpler for simple concats of tow or three strings. Guess it will also be faster than delimit or printf

3 Likes

(i really apriciate your reponces @irkode & @bep. You have been a great help)

I guess Im trying to do this in as good a way as possible. With @irkode’s option vscode does not recognise it as YAML (don’t know how to do that) so it will be harder for others to edit.

I’m trying to figure out a good way to organise my pages…

At the moment I use this is the front matter:

sections:
  - title: NKD Agility Migration Services
    content: Azure DevOps Migration and Process Optimization services overview.
    type: features
    features:
      - media: images/upgrade-2022.png
        title: Our Migration Services for Azure DevOps Migration
        content: |
          - *Complete Transition*: We manage the entire process of moving your on-premises TFS environment to Azure DevOps, including data, code repositories, and builds. We can handle any Collection size from a few hundred to a few thousand gigabytes.
          - *Legacy System Migration*: We handle complex integrations, including importing data from outdated systems like Visual SourceSafe or other obsolete systems.
      - media: images/nkdagility-azure-devops-process.jpg
        title: Process Optimization & Migration
        content: |
          - *Customized Configurations*: We help you optimize your Azure DevOps environment by customizing process templates and workflows to match your development processes.
          - *Change Process*: Ensuring seamless transitions from one process to another when there are lots of changes.
      - media: images/nkdagility-azure-devops-migration-tools.jpg
        title: Project Optimisation & Migration
        content: |
          We build, maintain, and support the tools recommended by Microsoft and used by consultants around the world to manage and migrate the contents of TFS & Azure DevOps Projects. We have helped customers migrate nearly two billion work item revisions. 
          - *Project manipulation*: We have experience in both TFS and Azure DevOps in splitting or merging projects within a collection/account or between them.
          - *Account / Collection Consolidation*: We can move a Project from one collection/account to another.
    source: inline
  - title: Courses For Azure DevOps
    content: Here is a list of courses related to Azure DevOps.
    type: courses
    related:
      - /capabilities/training-courses/courses/accentient-managing-projects-using-visual-studio-and-scrum
    source: data
  - title: null
    content: null
    type: videos
    related:
      - resources/videos/youtube/isU2kPc5HFw
      - resources/videos/youtube/_rJoehoYIVA
      - resources/videos/youtube/Wvdh1lJfcLM
      - resources/videos/youtube/3jYFD-6_kZk
    source: data

Then I have a single partial in the template that iterates through the “sections” and redners them… however its not as versatile as using the inline shortcodes which would enable me to reorder and organise inline…

What do you guys do when you are building marketing pages?

guess it depends on your toolchain, knowledge of the editors, amount of data …

Often that data will be stored in a database or a headless CMS with proper input forms and then merged at build time

If one set thing is layouting in VSCode and YAML is the one you could do (which will highlight in vscode.)

{{< section-videos >}}

```yaml
videos:
   - resources/videos/youtube/isU2kPc5HFw
   - resources/videos/youtube/_rJoehoYIVA
   - resources/videos/youtube/Wvdh1lJfcLM
   - resources/videos/youtube/3jYFD-6_kZk
```

{{< /section-videos >}}

A bare markdown list has the problem with escaping the _ by the formatter and would need special treatment (also for *…) simple lines only will collapse

If the section is just the video list, I would keep that in the frontmatter and just have a `{{< section-videos >}} shortcode that grabs the data from front matter. or if it’s generic for all/some pages move it to a layout and partial. That depends on the freedom of placing things somewhere.

1 Like

Thanks @irkode this is great.

I think that I may have multiple video lists on some pages. And the video is just a sample…

using

{{< section-courses >}}

\`\`\`YAML
title: Courses For Azure DevOps
content: Here is a list of courses related to Azure DevOps.
type: courses
related:
  - /capabilities/training-courses/courses/accentient-managing-projects-using-visual-studio-and-scrum
\`\`\`
{{< /section-courses >}}

or

{{< section-features >}}

\`\`\`YAML
  title: NKD Agility Migration Services
  content: Azure DevOps Migration and Process Optimization services overview.
  type: features
  features:
    - media: images/upgrade-2022.png
      title: Our Migration Services for Azure DevOps Migration
      content: |
        - *Complete Transition*: We manage the entire process of moving your on-premises TFS environment to Azure DevOps, including data, code repositories, and builds. We can handle any Collection size from a few hundred to a few thousand gigabytes.
        - *Legacy System Migration*: We handle complex integrations, including importing data from outdated systems like Visual SourceSafe or other obsolete systems.
    - media: images/nkdagility-azure-devops-process.jpg
      title: Process Optimization & Migration
      content: |
        - *Customized Configurations*: We help you optimize your Azure DevOps environment by customizing process templates and workflows to match your development processes.
        - *Change Process*: Ensuring seamless transitions from one process to another when there are lots of changes.
    - media: images/nkdagility-azure-devops-migration-tools.jpg
      title: Project Optimisation & Migration
      content: |
        We build, maintain, and support the tools recommended by Microsoft and used by consultants around the world to manage and migrate the contents of TFS & Azure DevOps Projects. We have helped customers migrate nearly two billion work item revisions.
        - *Project manipulation*: We have experience in both TFS and Azure DevOps in splitting or merging projects within a collection/account or between them.
        - *Account / Collection Consolidation*: We can move a Project from one collection/account to another.
 \`\`\`  
  {{< /section-features >}}

My current setup of just iterating through a sections yaml in the front matter restricts what can be put in between to that which is implemented in the sesions layouts… with the above I can have more control over the content.