I’m working on documentation for an open-source project that has a hosted/managed counterpart. The two products are mostly identical, but there are important differences between them. To provide a better experience, we’ve decided to create separate docs for both the open source (OSS) and the hosted/managed (cloud) versions:
To avoid having to manage the same content in two doc sets, I came up with the idea to pull the content of the OSS files into corresponding cloud files, and then use shortcodes to show and hide content based on the context.
Approach
I started by creating files in the content/cloud/ directory to match files in the content/oss/ directory. Each of the cloud .md files has frontmatter, but the content of the file is just a shortcode:
{{< duplicate-oss >}}
The {{< duplicate-oss >}} shortcode uses .GetPage to pull in the content of the the corresponding OSS page:
To show/hide cloud/oss specific content in each context, I have {{< cloud-only >}} and {{< oss-only >}} shortcodes. These attempt to use .Page.RelPermalink to identify their context:
cloud-only.html
{{- if in .Page.RelPermalink "/cloud/" -}}{{ .Inner }}{{- end -}}
oss-only.html
{{- if in .Page.RelPermalink "/oss/" -}}{{ .Inner }}{{- end -}}
This has a few issues:
Issues
By using .GetPage, the “imported” content maintains the scope and data of the OSS page. So even when the content is rendered at http://docs..../cloud/, .Page.RelPermlink returns the relative permalink of the OSS page. So my shortcodes for hiding and showing content don’t work because they always inherit the OSS context.
I tried simply pulling in the file contents in the duplicate-oss shortcode and rendering them with markdownify, but markdownify doesn’t render shortcodes and we use shortcodes heavily in our docs.
I tried using .Page.Scratch in the duplicate-oss shortcode to identify the context, but since the scratch is applied to the .Page, it affects the rendering in both the OSS and cloud contexts.
Questions
Is there a way to inject some type of data into the rendering of .Content that could then be used in shortcode logic?
Is there a way to temporarily modify the context of a .Page?
Is there another approach that I’m just not seeing?
---
title: This is the OSS example
---
This is the {{< cloud-only>}}Cloud{{< /cloud-only > }}{{< oss-only >}}OSS{{< /oss-only >}} version of this document.
content/cloud/example.md
---
title: This is the Cloud example
---
{{< duplicate-oss >}}
Pages render as:
/oss/example/
This is the OSS example
This is the OSS version of this document.
/cloud/example/
This is the Cloud example
This is the OSS version of this document.
The titles are different because they’re being pulled from the frontmatter of each page, but the content is rendered the same for both because .GetPage inherits the OSS context.
Thanks @bep. I’m not familiar with mounts or cascade, but I’m looking into them.
Shortcodes have access to all metadata, including .Page.Params.
I tried this approach as well, but because of how I’m pulling in the content, I still ran into the same issue. Because the {{< cloud-only >}} shortcode is in the .Content that gets pulled in with $page.Content, .Page.Params returns the parameters of the $page which resolves to the OSS version of the page.
You cannot change .Page, but there are other ways to store state (dict, scratch)
Is it possible to pass a dict or a scratch to the $page.Content execution? This is where it would need to happen, but when I tried, it didn’t work.
.Content` is rendered once per output format. And again, I have not read your long post in detail, so I don’t understand the detail in what you’re doing.
@bep Mounts are working, but it’s adding another set of problems and I’m wondering if you have any insights into potential solutions. Most center around frontmatter:
Can I prevenet files in mounted directories from getting built/rendered
Does cascade override existing frontmatter? For example, can I bulk change the menu value or a custom taxonomy in all children pages?
I have aliases for a lot of the docs in our doc set (file location changes over time). All the aliases are pointing to the pages generated from the mounts. Is there a way to keep aliases unique to a source file vs a target file?