Reusing markdown docs from github repo in Zola site

I would like to create a documentation site that will take the docs directory from three different repos:

  • https://github.com/simpleiot/hardware/tree/master/docs
  • https://github.com/simpleiot/simpleiot/tree/master/docs
  • https://github.com/simpleiot/firmware/tree/master/docs

and have each one of these “docs” directory be a section in my zola generated site: hardware, application, and firmware.

The idea is that the documentation can live close to the source/projects where it will more likely get maintained and be easy to view in Github/text editor, or in the dedicated documentation site – it will just look a little prettier in the docs site. One reason this is important is you always have documentation with your source code that matches the version you are using – this is important for industrial products with long product life cycles.

Thus far, I’ve used the convention that images used in the docs simply live in the same directory as the markdown file. If I copy the hardware/docs directory to the content/hardware directory in my Zola project and have a relay-node.md file that references an image, then Zola looks for the image at the following location:

http://127.0.0.1:1111/hardware/node-relay/node-relay.jpg

However, the original docs have the files arranged like so:

Looking through the zola examples, it seems one way to do this is to move the above two files to:

  • node-relay/index.md
  • node-relay/node-relay.jpg

I really like the fact that images can live in the same directory as markdown in Zola, vs having to be in a static/ directory or something like that – that is a huge improvement over other generators I’ve tried. However, is there any way to convince Zola to reference an image in the parent directory path if a markdown file is not index.md? Using the above example, I’d like Zola to generate the following link for the image:

http://127.0.0.1:1111/hardware/node-relay.jpg

Is there any way to make this work? Thanks!

Not currently as it would require to copy the assets n times, where n is the number of .md files in the directory. No easy way to solve that so we don’t handle it right now.

Thanks for the reply. I’m stilling trying to understand this …

If there is an asset:

hardware/node-relay.md

That references an image:

![node-relay](node-relay.jpg)

Wouldn’t it be safe to assume that node-relay.jpg lives at:

hardware/node-relay.jpg

instead of

hardware/node-relay/node-relay.jpg

The reason for this is the node-relay.md is a file, not a directory, so there is no way for node-relay/node-relay.jpg to exist, and Zola should know this.

I’m new to Zola, so probably missing something fundamental here.

What if there is another file like another.md that has a path set in the front-matter to /something but also uses ![node-relay](node-relay.jpg)?

The patch i made a while back dealt with that: site::render_page() only copies assets for pages called index.md but copies assets for all sections. Pages sharing assets with a section had links to assets replaced on the fly in rendering::markdown::fix_link()

I’m happy to revive it with more docs/comments if that’s something you would appreciate

Did it support arbitrary paths in the front-matter but pointing to relative assetS?

Not sure what you mean. Something like this?

{% for i in page.extra.images %}
<img src="{{ config.base_url }}/{{ i }}">
{% endfor %}

I don’t believe that would work because it should resolve to the parent folder (section), as the fix_link function did for Markdown internal links. Maybe exposing fix_link as a template function could help?

Also i’m not sure how my patch dealt with aliases for sections and pages and stuff like that. It somehow makes sense that a page P1 belonging in section S1 in the content folder, but with output path manually set to /P1.html (not inside the section output folder) could not access those assets… However i think the proposed patch would just fail silently, which is only acceptable if well documented (because that’s a very narrow usecase).

More like you have something like:

projects
  -> _index.md
  -> one.md (where path = "secret-project")
  -> two.md (no path set, so rendering at `projects/two/`)
  -> hello.jpg

If all markdown files refer to hello.jpg, the file would need to be copied in 3 locations if we want to keep it relative.

(because that’s a very narrow usecase).

I don’t think aliases are a narrow usecase, they are pretty common if you are moving from another system of URLs but want to keep all existing links alive.

say we hypothetically have a directory structure like:

  • projects/
    • file1.md
    • file2.md (with front matter set to /something)
    • image.png

Both of the above files include [image](image.png)

Why couldn’t the output look like:

  • something/
    • index.html (<img src="/projects/image.png" />)
  • projects/
    • image.png
    • file1/
      • index.html (<img src="/projects/image.png" />)

Does the image need copied to all the destination locations in case it gets resized or something? (vs simply referring in the output directory structure)?

Again, I’m very new to Zola so likely still figuring out the basics of how it works.

Yes but specifically having assets shared between pages who have entirely different path? I assumed it was narrow, but i may be wrong.

A few ideas:

  • expose asset paths are internal links (@/path) and have internal links also resolve other files within content folder, by looking up [_]index.md from the same folder in the permalinks
  • store/expose asset paths as mapping from relative path (from current page/section path) to relative URLs (from the site root) ; this way page.assets would expose enough information for both Markdown rendering and template rendering i believe
  • come up with a path rewriting algorithm that’s capable to generate a relative URLs from any reference path in the site ; this way we could have something like asset_link = find_relative_section(parent) / relative_asset_link

So the 3rd idea is definitely more complex but somehow i feel once paths are unified properly across parameters/variables, converting between absolute and relative URLs will become a lot easier, which will make a lot of people happy, including myself (i’d rather not rebuild the site for every baseURL since i intend to support more and more). Maybe it becomes a viable option then.

That’s more or less what my patch did. Except asset resolution was not applied to images (forgot about that). I just did a patch for that here.

The only difference with your expectation is that something/index.html (not something.html) will produce a link to BASEURL/test.png because the proposed asset resolution strips the page’s component from the path, in order to link to the parent’s asset, like so:

<img src="http://127.0.0.1:1111/test.png" alt="test" />

That’s far from ideal, we could:

  • solve the problem correctly once and for all with path unification and relative/absolute paths manipulation functions (will take considerable amounts of effort and won’t be achieved overnight)
  • as a quick hack, add path overriden in frontmatter as another condition feeding index=true to the RenderContext (asking it to copy over the assets in the output dir for this page), like self.file.name == "index" || self.meta.path.is_some()

Note: this index field in RenderContext is a bad name. It should probably be renamed copy_assets or something like this. It happened to match whether the page was called [_]index.md but even then that was not an explicit variable name.

Thanks, fixed my post to reflect this.

for now, I’m just using a script to fix up a few things:

This is still easier than fixing up stuff like this for other generators like Hugo or Docusaurus.

So far, it is working great! The book theme is a nice starting point for documentation sites.

From your envsetup.sh:

      if [ "$file_name" = "README.md" ]; then
        cp "$f" "$dest/_index.md"
      else
        cp "$f" "$dest/"
      fi

I’ve written lines like that in the past, maybe that would be worth implementing it into zola. Many development projects use README.md from submodules as either page or section index file, one way or another. Maybe we could have a setting like:

[content]
section_index = [ "_index.md" ]
page_index = [ "index.md" ]

I initially thought that each setting should be a String, which would be easier to implement. I settled for a Vec<String> because using some README.md does not mean all sections are structured in the same way (slightly more difficult because it can introduce output path conflicts).

Maybe ignored_content settings could go in there as well? Slightly off-topic, but i really like the recent move of top-level settings to dedicated tables. Going further down this road would make understanding the config a lot easier for newcomers, and the documentation easier to extend/maintain.

1st pass is deployed:

source repos:

  • https://github.com/simpleiot/simpleiot/tree/master/docs
  • https://github.com/simpleiot/hardware/tree/master/docs

(above are plain text as I can’t post more than two links yet)

are used to produce this:

Note, the source repos documentation are usable in Github, though not as pretty as the Zola version.

Here is the Zola config:

Very pleased with this solution.

1 Like