Pulling in and transcluding content from external files

33 views
Skip to first unread message

Austin Ziegler

unread,
Aug 23, 2022, 4:49:55 PM8/23/22
to nanoc
I’m just starting to play with Nanoc, but I have a bit of a complex thing I want to do. I could do a bunch of pre-processing or duplicate a lot of data, to get things set up *just so*, but both of those feel wrong. And it *feels* like this should be possible with some combination of render, external data sources, and 

What I want to do is have something like the following:

```
---
# changelog.md.erb
---

<%= include "../../changelog.md" %>
```

I want to

1. Have a file that has two extensions so that `changelog.html` is processed through both `erb` and `kramdown` filters.
2. Include the contents of a file that is external to the main nanoc site during the ERB phase and have the Kramdown process the transcluded file.

Is what I want possible?

Background on the request is that I’m setting up a repository that contains a spec and three reference implementations in three different languages, and also contains a nanoc site in docs/. I don’t want to put YAML preamble on all of the markdown files (most of the Markdown files will be consumed by *other* parsers when building the documentation for each of the reference implementations), and I don’t want to make *nearly identical* copies of each of the markdown files excepting the YAML preamble.

Thanks,
-Austin

Denis Defreyne

unread,
Aug 27, 2022, 3:49:46 AM8/27/22
to noreply-spamdigest
Hi Austin,

I made Nanoc so I could do complex stuff with it, and I believe you can get this to work. I’ll write up a couple of points.

To include content that’s external to the Nanoc site, it’s best to create a data source that pulls in this data. This way, Nanoc can track dependencies and changes to it. See the documentation on writing data sources at https://nanoc.app/doc/data-sources/#writing-data-sources for details. By coincidence, that page also gives an example of a data source that returns a single item, namely the changelog (NEWS.md file) from a Ruby gem.

To run multiple filters on an item based on the file extensions, you could use the #exts method. For instance:

    compile "/changelog.*" do
      item.exts.reverse_each do |ext|
        case ext
        when "erb"
          filter :erb
        when "md"
          filter :kramdown
        else
          raise "don’t know what to do with this extension"
        end
      end

      layout "/default.*"
      write "/changelog.html"
    end

See also the documentation for identifiers at https://nanoc.app/doc/identifiers-and-patterns/, which documents the #exts method.

To include content from one file into another, you can use something like

    <%= @items["/changelog.*"].compiled_content %>

This will get the compiled content for that item (compiling it first if needed), right before any layout is applied. So, if you had a rule like the compile "/changelog.*" one I showed above, then the compiled content would be the content with the :kramdown and :erb filters applied, but not the layout. See also the documentation at https://nanoc.app/doc/reference/variables/, which documents which methods are available on items and layouts.

I hope this helps! Let me know how it goes.

Best,

Denis Defreyne
[dəˈni] • pronouns: he/him

--
You received this message because you are subscribed to the Google Groups "nanoc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nanoc+un...@googlegroups.com.

Austin Ziegler

unread,
Sep 1, 2022, 3:18:07 PM9/1/22
to na...@googlegroups.com
So, if I have `content/changelog.html.erb` and I write a data source that reads `../changelog.md`, `../elixir/changelog.md`, `../ruby/changelog.md`, and `../ts/changelog.md` and presents it as items, can I write `content/changelog.html.erb` to do something like:

 <%= @items["/changelog/root.*"].compiled_content %>
 <%= @items["/changelog/elixir.*"].compiled_content %>
 <%= @items["/changelog/ruby.*"].compiled_content %>
 <%= @items["/changelog/ts.*"].compiled_content %>

And not actually write the root, elixir, ruby, and ts changelog files? I’m going to try it, but what I’m trying to figure out is how I can use the kramdown and erb filters with external sources (all Markdown) but *only* write it into files that have been suitably prepared to transclude the content, like above?

I’m oversimplifying, but I’m ultimately trying to connect the overall narrative here. (That is to say, the nanoc documentation is very good, but for a bunch of reasons, I’m not currently seeing the path I need to get where I want. It’s probably my reading comprehension.)

-a


You received this message because you are subscribed to a topic in the Google Groups "nanoc" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/nanoc/Ih6AWLDYF-A/unsubscribe.
To unsubscribe from this group and all its topics, send an email to nanoc+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/nanoc/f96482fd-4b8e-47f0-a311-26906e5674db%40www.fastmail.com.


--

Denis Defreyne

unread,
Sep 7, 2022, 6:39:02 AM9/7/22
to noreply-spamdigest
Hi Austin,

I’ll reply inline!

On Thu, Sep 1, 2022, at 21:17, Austin Ziegler wrote:
So, if I have `content/changelog.html.erb` and I write a data source that reads `../changelog.md`, `../elixir/changelog.md`, `../ruby/changelog.md`, and `../ts/changelog.md` and presents it as items, can I write `content/changelog.html.erb` to do something like:

 <%= @items["/changelog/root.*"].compiled_content %>
 <%= @items["/changelog/elixir.*"].compiled_content %>
 <%= @items["/changelog/ruby.*"].compiled_content %>
 <%= @items["/changelog/ts.*"].compiled_content %>

And not actually write the root, elixir, ruby, and ts changelog files?

That is correct! Those files wouldn’t physically exist in the content/ directory.

what I’m trying to figure out is how I can use the kramdown and erb filters with external sources (all Markdown) but *only* write it into files that have been suitably prepared to transclude the content, like above?

There’s no such thing as an “external source” necessarily — all data sources are similar. The data source that Nanoc sites come with by default, `filesystem`, is a data source much like any other. So, the way you’d treat files in content/ (which come from the filesystem data source) could be quite similar to the way you’d treat files that live elsewhere (outside of the content/ directory).

I’m not quite sure what you mean by “suitably prepared” though.

For the changelog files themselves: If you were to only want a single changelog .html file in the output, you’d need a rule that matches that single main changelog file (the one which has all the <%= … %> transclusions):

    compile "/changelog.*" do
      filter :erb
      layout "/default.*"
      write "/changelog.html"
    end

The sub-changelogs, which would have identifiers /changelog/root.md and so on, could have a rule like this:

    compile "/changelog/*.md" do
      filter :kramdown
    end

There is no #write call here, because those sub-changelog files wouldn’t be written to the output folder. I’ve left out the item.exts.reverse_each approach I mentioned previously, but of course you can still apply that:

    compile "/changelog/*" do
      item.exts.reverse_each do |ext|
        case ext
        when "erb"
          filter :erb
        when "md"
          filter :kramdown
        else
          raise "don’t know what to do with this extension"
        end
      end
    end

Hope this helps! Let me know your thoughts.

Best,

Denis Defreyne
[dəˈni] • pronouns: he/him

Austin Ziegler

unread,
Sep 7, 2022, 11:57:08 AM9/7/22
to na...@googlegroups.com
Merci beaucoup, Denis.

I’m taking a break from the project that I’ll be using Nanoc for (tempo on other projects has picked up), but I think you’ve answered my questions and I’ll be able to do what I need to do. If I have any further questions, I’ll let you know, and when I get it all worked out, I’ll let you know that, too.

-a

Reply all
Reply to author
Forward
0 new messages