How to render two files from a single markdown - jekyll

I have a collection of markdown files and I would like to render in two different set of files using two different layout files when building the page:
– html files for the website
– xml files
Is it possible to do this? It seems that a markdown file can be only parsed once. Any suggestions? Many thanks

Instead of having a markdown file that points to a layout file, you're going to need two pages that point to the markdown post file.
There are a number of ways to point to a post file. I like to use a where filter:
{% assign post = site.posts | where:"url", include.url | first %}
Now that you have a post, let's say you have fileOne.html that you want to put that post into. Here's how you'd approach that:
---
layout:main
---
<h1>Some html here</h1>
{% assign post = site.posts | where:"url", include.url | first %}
{{ post.content }}
Then you could do the exact same thing in another file named fileTwo.html.

Browse markdown files from files using each layout and use the liquid filter markdownify to process the same content in different contexts.
Markdownify
Convert a Markdown-formatted string into HTML.
{{ page.content | markdownify }}

You could use Includes for this.
Note: You can either store your source Markdown files in the _includes folder and include them into others with include.
Or you store them directly in the folder where the destination files are and use include_relative.
I'm showing the first option here.
This is the file whose content will end up in another file:
/_includes/foo.md:
**bold**
[Stack Overflow](https://stackoverflow.com)
And here's the file which includes foo.md:
a) When it's a Markdown file:
---
layout: default
title: blah
---
This is the "destination file" for the include.
{% include foo.md %}
b) Anything that's not Markdown:
(if you want the Markdown from foo.md rendered, you have to do this manually)
---
layout: default
title: blah
---
<p>This is the "destination file" for the include.</p>
{% capture tmp %}{% include foo.md %}{% endcapture %}
{{ tmp | markdownify }}
Result in both cases:
<p>This is the "destination file" for the include.</p>
<p><strong>bold</strong></p>
<p>Stack Overflow</p>

Related

Q: Jekyll - 2 sections displaying nearly same content

I have two very similar sections on a jekyll website.
The displayed content change for only some words or resources.
I handle this using 3 files:
One markdown content without Front Matter. This file content the text with if conditions:
# Mardown Content
Here is more info about:
{% if page.section == 'sectionA' %}
[Something About Setion A](/sectionA/something)
{% elsif page.section == "sectionB" %}
[Something About Setion B](/sectionB/somethingelse)
{% endif %}
Two markdown files with front matter including the content
---
layout: myTemplate
section: sectionA/B
title: something
---
{% include content.md %}
I used to have those 3 files in the same directory using {% include_relative content.md %}. This way seems better because the files were in the same directory and the _include folder do not mix up content and html templates.
But my config of jekyll builds also a page for the content file displaying an html page.
Is there a way to prevent serving this html content?
Do you know a better way to handle this?
In _config.yml add :
exclude:
- content.md
This will instruct Jekyll not to process content.md.
Note : I don't get why you cannot put content.md in the _includes folder.

Jekyll include markdown file not rendering html

I have a Jekyll site with an include file. Within that include file I am trying to include another file:
<div class="api-doc api-off api-definition" id="debugging">{% include_relative _apiDocs/debugging.md %}</div>
but this displays the markdown as a string:
--- title: API Reference | Debugging --- #### Debugging Turn on debugging: ```Javascript pbjs.setConfig({ debug: true }); ```
Is there a way to get this to render as HTML?
If you're using Kramdown as your processor, you can handle this by adding the markdown="1" attribute to the parent div:
<div class="api-doc api-off api-definition" id="debugging" markdown="1">{% include_relative _apiDocs/debugging.md %}</div>
If not, you can apply a filter on the included Markdown to convert it to HTML (see the Jekyll docs on the markdownify filter):
{%- capture debugging-doc -%}{% include_relative _apiDocs/debugging.md %}{%- endcapture -%}
<div class="api-doc api-off api-definition" id="debugging">{{ debugging-doc | markdownify }}</div>

I wanna include html file on post! But Liquid say "Could not locate the included file."

I wanna include some HTML file on post!
I wanna show a reference on the right side of my blog.
Reference is HTML file, and it looks like simple doc.
So I created the layout file jekyll.html and I wrote a tag <div>.
Then I added a header variable to my post and reference file is located on _layouts.
This is the code in jekyll.html:
<div class="right">
{% for ref in page.refs %}
{% include ref %}
{% endfor %}
</div>
And this code post's YAML header.
---
layout: jekyll
title: "02. "
date: 2018-12-30 14:38:42 +0900
category: Jekyll
refs: [ bundler.html, test.html ]
---
So, Liquid says:
Liquid Exception: Could not locate the included file 'ref' in any of ["E:/Projects/Jekyll/_includes"]. Ensure it exists in one of those directories and, if it is a symlink, does not point outside your site source. in /_layouts/jekyll.html
What's wrong? Did I do anything wrong?
Or is there another way?
If you want to use a liquid variable in an include tag, you must surround it with curly braces :
{% include {{ ref }} %}

Markdown rendering differs when invoked on members of foreach or via a where filter

I wonder if anyone can illuminate this puzzle. I am using a new installation of vanilla jekyll on a Mac. Everything seems to work fine, but I discovered that some text being shown in my page footer was rendering differently on posts and all other pages. On most pages the text would render as HTML, but in posts it was rendering as Markdown. I found a workaround, but it left me with even more questions.
Context
I have defined footer_sections as a collection to hold portions of the footer. In my _config.yml this looks like:
collections:
footer_sections:
output: false
A footer section is then defined in a Markdown file such as _footer_sections/address.md as:
---
title: Address
order: 1
---
**My Name**
123 My Street
My Town, ST 12345
123-555-5555
In my default.html I had a footer section in my HTML something like this:
<div id="footer">
{{ site.footer_sections | where: "title", "Address" }}
</div>
And my posts are set up like this example:
---
title: Silly new post
date: 2017-02-27T12:33:53+00:00
author: Eric Celeste
layout: post
---
Silly post.
And finally, the post layout is connected to the default layout like this:
---
layout: default
---
<h1>{{ page.title }}</h1>
<p class="meta">{{ page.date | date_to_string }}</p>
<div class="post">
{{ content }}
</div>
The Problem
Notice that the address.md file is defined in Markdown and then its content is shown in the footer by the inclusion of the section in default.html. On all regular pages this would render as HTML (a bold name, a plain address), but on posts like the silly post above, it would render as Markdown (a name surrounded by stars and an address without like breaks).
I thought maybe it had to do with different procedural steps between posts and pages, maybe the Markdown rendering is happening "later" on pages but has already happened "earlier" in posts. I am only two days old on Jekyll, so I really don't know how it works.
In order to test that theory, I tried forcing the Markdown rendering with the markdownify filter. I changed the liquid tags in default.html so that they read:
{% assign section = site.footer_sections | where: "title", "Address" %}
{{ section.content | markdownify }}
Oddly, this produced a worse result everywhere. Now no text of any sort appeared in the footer of regular or post pages.
On the theory that maybe the where filter is actually different from looping through members of an array with foreach I tried another approach:
{% for section in site.footer_sections %}
{% if section.title == "Address" %}
{{ section.content | markdownify }}
{% endif %}
{% endfor %}
That worked! Now the content of the footer sections rendered as HTML on both regular pages and posts.
My Questions
Why didn't the initial approach work? What is the difference between rendering of posts and other pages in Jekyll?
While I found workaround, I don't understand why it works. In what ways does pulling out an item from an array with a where filter differ from using a member from a foreach loop? How does this affect the results of the markdownify filter?
Is there a cleaner, simpler way to grab the HTML-rendered content from my sections than looping through them each time I want to use one of them?
Thanks for any insights you may have!
site.footer_sections is an array and the output of the 'where' filter is still an array (but only containing the values that match your condition).
In your case, you are getting a single-element array but it's still an array object.
To see this for yourself use the inspect filter:
{% assign section = site.footer_sections | where: "title", "Address" %}
{{ section.content | inspect }}
On the other hand, when you loop through the elements with a for loop, at each iteration you get the individual elements of the array. Try using inspect inside your loop to see how the two types of your section variable differ.
For the 'where' method to work you need to get the actual element from the array either with first or [0]:
{% assign section = site.footer_sections | where: "title", "Address" %}
{{ section.first.content | markdownify }}
OR
{% assign section = site.footer_sections | where: "title", "Address" %}
{{ section[0].content | markdownify }}
links:
array documentation
first documentation
where documentation

Jekyll Docs folder

Im my Jekyll website I need to create an documentation section similar to Original website. However I am not sure how the Docs sections renders. For example, the docs folder, which is located in site root, is filled with documentation .md files. This folder doesn't inculde any index.html file responsible for Layouting of website. The link to that folder is
Doc<span class="show-on-mobiles">s</span><span class="hide-on-mobiles">Documentation</span>
Could someone shed a light on how this section is rendering?
The docs folder includes an index.md, which is rendered as index.html in the final site.
If you look at the YAML front matter of index.md, you'll see this:
---
layout: docs
title: Welcome
next_section: quickstart
permalink: /docs/home/
---
The permalink: /docs/home/ line sets the final URL to {{ site.url }}/docs/home/, even though the actual file is in the /docs folder and the /docs/home folder doesn't even exist.
(for more info about the permalink setting, see Predefined Global Variables in the docs)
So that's where the URL comes from.
Concerning the list of documentation topics (the sidebar on the right):
The YAML front matter of index.md (see above), also contains the line layout: docs.
This refers to /_layouts/docs.html, a layout file.
Inside the layout file, there's the line {% include docs_contents.html %}, which refers to _includes/docs_contents.html, an include file, which contains the following code:
{% for section in site.data.docs %}
<h4>{{ section.title }}</h4>
{% include docs_ul.html items=section.docs %}
{% endfor %}
site.data.docs (in the first line) refers to /_data/docs.yml, a YAML data file.
It looks like this (shortened):
- title: Getting Started
docs:
- home
- quickstart
- installation
- usage
- structure
- configuration
- title: Your Content
docs:
- frontmatter
- posts
- drafts
- pages
- variables
- datafiles
- assets
- migrations
The code inside docs_contents.html loops through the items in the data file, displays the title values ("Getting Started", "Your Content"...) and then includes another include file /_includes/docs_ul.html, passing the list of docs from the data file.
This second include file loops through the list of docs, and does the following for each one:
Step 1:
{% assign item_url = item | prepend:'/docs/' | append:'/' %}
This builds the URL of the page based on the list item. For example, quickstart becomes /docs/quickstart/.
Step 2:
{% if item_url == page.url %}
{% assign c = 'current' %}
{% else %}
{% assign c = '' %}
{% endif %}
This marks the current page (used in the next step) by checking if the URL created in the previous step is equal to the URL of the current page.
Step 3:
{% for p in site.pages %}
{% if p.url == item_url %}
<li class="{{ c }}">{{ p.title }}</li>
{% endif %}
{% endfor %}
This loops all pages in the whole site, until it finds the page with the URL created in the first step.
(to make sure that the URL is equal, all Markdown files in the docs folder have set a permalink in the front-matter, for example permalink: /docs/quickstart/ in quickstart.md)
Then, it outputs a <li> with a link to the page, using the title from the respective Markdown file as the link text.
Plus, the class of the <li> is set to current if it's the current page (see step 2), so the current pae is highlighted in the list: