There are several ways you can do this, and I bet you could get fancy with URL filters, but here is the way I know how to do it
Reference
Before I begin, you should learn the assign
tag for creating variables. It is powerful and helps you avoid that nest for/if loop you created by using the where
filter, as you will see in my answer below.
My understanding of the question
You have a folder that I will just call docs
. Under that folder there are a number of files and folders, like this:
/docs/RootDoc.md
/docs/index.md (or index.html)
/docs/subdocs/SubDoc.md
The RootDoc.md file looks something like this:
---
layout: default
title: Rootdoc
category: NDT
---
This is a page located at the root of the RootDoc folder...
The SubDoc folder looks something like this:
---
layout: page
title: Subdoc
category: NDT
---
This is a page located in the SubDocs folder, underneath RootDoc...
The index page should only display the list of pages where that index file resides.
Option #1: Add more YML front matter (your least preferred option)
Of course, one way to solve this problem is to add some new YAML element(s) to filter the content more easily. I added a new YML front matter item called subfolder
and set that to true
or false
in my simplistic example.
---
layout: page
title: Subdoc
category: NDT
subfolder: false
---
This is a page located in the SubDocs folder, underneath RootDoc...
With that code in place, I can then write code like this:
{% assign ndtPages = site.pages | where: "category", "NDT" | where: "subfolder", false %}
{% for ndtPage in ndtPages %}
title: {{ ndtPage.title }}
{% endfor %}
You mention that this method is not ideal because you have to edit many files. Search this site for regex
, and you will see several recent posts that cover how to do that global replacement in a folder of files using Visual Studio Code.
Option #2: Count the number of subfolders (proposed solution)
If you want to know where the document is located, you can get the page.url
, and it will return something that looks like this:
/docs/rootdoc.html
You can use the Liquid string split
filter to turn the URL into an array, breaking up the string using the slash (/
). Since there are 2 slashes in my example, the array will be a size of 3.
Here is a document in a subfolder:
/docs/subdocs/subdoc.html
There are 3 slashes in that example, so you get an array size of 4.
Now, let’s use this knowledge to our advantage.
Here is the code I would write to only get a split URL string with an array size of 3 (or 2 slashes):
{% assign ndtPages = site.pages | where: "category", "NDT" %}
{% for ndtPage in ndtPages %}
{% assign folderCount = ndtPage.url | split: '/' %}
{% if folderCount.size == 3 %}
Page title: {{ ndtPage.title }}
Page folder location: {{ ndtPage.url }}
{% endif %}
{% endfor %}
First, we use assign
to create a collection of pages
that contain a category
of NDT
in the YML front matter.
We then loop through all the pages, but before we do anything, we assign
a variable to convert the URL to an array with each item split based on the /
.
Now that we have the array, we will only act on the page if the new array has a value of 3 (or two slashes /
).
From there, we put whatever content we want on the page, such as displaying the page title and whatever else you want within the if
statement.
Considerations
I do not know how deep your folder structure goes, so display the page.url
somewhere, count the slashes, and add +1.
Once you get the folder count size right, you will hard-code the folder count into your code. In my case, I have {% if folderCount.size == 3 %}
, but yours might be 5 or 8, or whatever. You may also move around the structure of your site.
I recommend you decide how many levels your pages have and add those values to your _config.yml
file. For example, you could add the following line anywhere:
# Folder structure+1 for what level of doc to display:
rootDoc: 3
subDoc: 4
Then, you can replace:
{% if folderCount.size == 3 %}
With:
{% if folderCount.size == site.rootDoc %}
With that consistency in place, if you move your pages around, all you need to do is change the _config.yml
file, rather than the logic in all your index pages.
Final note
I will be honest, I could not figure out why split
output a 3 instead of a 2 because I rarely use it. Just in case my +1 logic does not work, use this sample code:
{% assign ndtPages = site.pages | where: "category", "NDT" %}
{% for ndtPage in ndtPages %}
{% assign folderCount = ndtPage.url | split: '/' %}
Array size: {{ folderCount.size }}
title: {{ ndtPage.title }}
folder: {{ ndtPage.url }}
{% endfor %}
That will display all pages with NDT and you can get the Array size
number to find out the number to put into your if
statement in the solution I provided earlier.
Hope this helps!