Content fragments?

5 views
Skip to first unread message

Lou Quillio

unread,
Oct 29, 2009, 1:42:40 PM10/29/09
to nanoc
Perhaps I'm missing something obvious, but what's the most straight-
forward way to maintain fragments of content that aren't output as
pages themselves, rather assembled together, then compiled, layout-ed
and routed?

My only goal here is to ease maintenance of a particularly long page
-- an API reference document. It would be much easier to deal with if
sections of content were pulled-in from separate files just before
compile.

I can think of several ways to get this done, but each is a bit
inelegant in one way or another. Any ideas welcome.

LQ

Denis Defreyne

unread,
Oct 29, 2009, 3:31:13 PM10/29/09
to na...@googlegroups.com

Hi,

The way I usually do this, is by creating sub-items of the "assembled"
item, give them a route that returns nil, and then let the assembled
item collect the content of all sub-items.

So, for example, suppose I have the item

/help/manual/

but this item, because it is so huge, should be split in chapters. So
I create sub-pages:

/help/manual/chapter-1/
/help/manual/chapter-2/
/help/manual/chapter-3/

The individual sub-items should probably be compiled using as little
filters as possible, and no layout; the manual page will be laid out
but the individual chapters shouldn't be. So:

compile '/help/manual/*/' do
filter :bluecloth
# or a different filter, or no filter at all,
# depending on what this item is formatted as
end

Now, the /help/manual/ page should grab the contents of these items,
like this:

<% @item.children.each do |subitem| %>
<%= subitem.reps[0].content_at_snapshot(:last) %>
<% end %>

"reps[0]" gets the first representation (assuming there only is one,
which is likely true). content_at_snapshot() then fetches the fully
compiled content (hence the :last snapshot). If you use the
#compiled_content extension mentioned in some other, older thread
(which I can't find right now, unfortunately) and which will be in
nanoc 3.1, the code is a bit easier:

<% @item.children.each do |subitem| %>
<%= subitem.compiled_content %>
<% end %>

The manual page itself should be compiled like this, then:

compile '/help/manual/' do
# necessary to execute the code that includes the subitems
filter :erb

# it's a real page, so it needs a layout
layout 'default'

# to use curly quotes, real ellipsises etc… optional, but nice
filter :rubypants
end

One last thing to do: the individual chapters should not be written to
HTML files. To do this, make a route that returns nil instead of a
string, to prevent them from being outputted:

route '/help/manual/*/' do
nil
end

This method is fairly short and also fairly elegant. Let me know what
you think!

Regards,

Denis

--
Denis Defreyne
denis.d...@stoneship.org

Lou Quillio

unread,
Oct 29, 2009, 5:36:48 PM10/29/09
to na...@googlegroups.com
Thanks, Denis. This mostly works, but I had some trouble with it.

On Thu, Oct 29, 2009 at 3:31 PM, Denis Defreyne
<denis.d...@stoneship.org> wrote:

...

>        compile '/help/manual/*/' do
>          filter :bluecloth
>          # or a different filter, or no filter at all,
>          # depending on what this item is formatted as
>        end
>
> Now, the /help/manual/ page should grab the contents of these items,
> like this:
>
>        <% @item.children.each do |subitem| %>
>          <%= subitem.reps[0].content_at_snapshot(:last) %>
>        <% end %>
>

Good so far.

...

> The manual page itself should be compiled like this, then:
>
>        compile '/help/manual/' do
>          # necessary to execute the code that includes the subitems
>          filter :erb
>
>          # it's a real page, so it needs a layout
>          layout 'default'
>
>          # to use curly quotes, real ellipsises etc… optional, but nice
>          filter :rubypants
>        end

Output as expected. The three grandchild pages are generated here
still, but their content is incorporated in `help/manual`, as desired.

...

> One last thing to do: the individual chapters should not be written to
> HTML files. To do this, make a route that returns nil instead of a
> string, to prevent them from being outputted:
>
>        route '/help/manual/*/' do
>          nil
>        end

Here's where things break. This rule prevents the grandchild pages
from generating (expected), but also prevents nanoc from detecting
changes to their content. Also, I first tested this by creating all of
the example items and rules before doing a compile, and it wouldn't
work at all until I allowed the grandchildren to be generated.

Any ideas? Thanks.

LQ

Denis Defreyne

unread,
Oct 30, 2009, 5:17:49 AM10/30/09
to na...@googlegroups.com
On 29 Oct 2009, at 22:36, Lou Quillio wrote:

> Thanks, Denis. This mostly works, but I had some trouble with it.
>

> [..]


>
>> One last thing to do: the individual chapters should not be written
>> to
>> HTML files. To do this, make a route that returns nil instead of a
>> string, to prevent them from being outputted:
>>
>> route '/help/manual/*/' do
>> nil
>> end
>
> Here's where things break. This rule prevents the grandchild pages
> from generating (expected), but also prevents nanoc from detecting
> changes to their content. Also, I first tested this by creating all of
> the example items and rules before doing a compile, and it wouldn't
> work at all until I allowed the grandchildren to be generated.

Hi,

This is odd… I've tried reproducing the problem, but nanoc3 behaves
properly here: when a sub-page is modified, the aggregating page is
updated accordingly.

My guess is that the dependencies cache is somehow corrupted. Can you
try compiling with the --force command? This will tell nanoc3 to
disable its dependency tracker and to compile all items, whether they
are outdated or not. You could also get rid of tmp/dependencies, which
stores dependency information. After running compile with --force or
removing tmp/dependencies, you should be able to run compile without --
force again, and it should behave properly. Let me know whether that
works.

Lou Quillio

unread,
Nov 6, 2009, 4:56:10 PM11/6/09
to na...@googlegroups.com
On Fri, Oct 30, 2009 at 4:17 AM, Denis Defreyne
<denis.d...@stoneship.org> wrote:

> My guess is that the dependencies cache is somehow corrupted.  Can you
> try compiling with the --force command? This will tell nanoc3 to
> disable its dependency tracker and to compile all items, whether they
> are outdated or not. You could also get rid of tmp/dependencies, which
> stores dependency information. After running compile with --force or
> removing tmp/dependencies, you should be able to run compile without --
> force again, and it should behave properly. Let me know whether that
> works.

--force or deleting the dependency tracker doesn't help.

Should mention that I'm using a filesystem_combined datasource. To be
a little more specific, I start with this:

~~~~~~~~~~~~~~~~~~~~~~~~~
compile '/api/' do
filter :erb
filter :phpmarkdownextra
layout 'default'
end

compile '/api/*/' do
nil
end
~~~~~~~~~~~~~~~~~~~~~~~~~

... and it works again. Changes to parent or child items are
recompiled. But since I don't need pages for the child items, I add
this routing rule:

~~~~~~~~~~~~~~~~~~~~~~~~~
route '/api/*/' do
nil
end
~~~~~~~~~~~~~~~~~~~~~~~~~

... and that breaks it, but produces a clue: both the item at '/api/'
and its children are now ignored. If I add an explicit routing rule
for '/api/', everything works again:

~~~~~~~~~~~~~~~~~~~~~~~~~
route '/api/' do
item.identifier + 'index.html'
end

route '/api/*/' do
nil
end
~~~~~~~~~~~~~~~~~~~~~~~~~

So if that's expected behavior, I guess it's solved.

LQ

Denis Defreyne

unread,
Nov 6, 2009, 5:24:06 PM11/6/09
to na...@googlegroups.com
On 06 Nov 2009, at 22:56, Lou Quillio wrote:

> [..] But since I don't need pages for the child items, I add this

> routing rule:
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~
> route '/api/*/' do
> nil
> end
> ~~~~~~~~~~~~~~~~~~~~~~~~~
>
> ... and that breaks it, but produces a clue: both the item at '/api/'
> and its children are now ignored. If I add an explicit routing rule
> for '/api/', everything works again:
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~
> route '/api/' do
> item.identifier + 'index.html'
> end
>
> route '/api/*/' do
> nil
> end
> ~~~~~~~~~~~~~~~~~~~~~~~~~
>
> So if that's expected behavior, I guess it's solved.

Hi,

This is a bug in nanoc; '/api/*/' should only match children of /api/
(because * stands for 0 or more characters). I don't have a fix yet,
but i'll let you know ASAP when I do.

Denis Defreyne

unread,
Nov 6, 2009, 6:25:39 PM11/6/09
to na...@googlegroups.com
On 06 Nov 2009, at 23:24, Denis Defreyne wrote:

> This is a bug in nanoc; '/api/*/' should only match children of /
> api/ (because * stands for 0 or more characters). I don't have a fix
> yet, but i'll let you know ASAP when I do.

Hi,

I've fixed the bug; check out these URLs for details:

* hg: http://projects.stoneship.org/hg/nanoc/rev/8a279acfa097
* git: http://github.com/ddfreyne/nanoc/commit/57011238f26737c4a4f7c158f2148992c4c55cf2

Can you give the fixed #identifier_to_regex method a try? Basically,
apply the diff, or, perhaps easier, clone the repository (hg or git),
install the gem and give the updated version a try.

If this change fixes the issue for you, I'll release nanoc 3.0.2 soon.

Lou Quillio

unread,
Nov 6, 2009, 9:54:06 PM11/6/09
to na...@googlegroups.com
On Fri, Nov 6, 2009 at 6:25 PM, Denis Defreyne
<denis.d...@stoneship.org> wrote:
> Can you give the fixed #identifier_to_regex method a try? Basically,
> apply the diff, or, perhaps easier, clone the repository (hg or git),
> install the gem and give the updated version a try.
>
> If this change fixes the issue for you, I'll release nanoc 3.0.2 soon.

After patching `compiler_dsl.rb`, an explicit routing rule for the
parent item is not required for changes to either parent or children
to be seen and processed. Seems fixed. Merçi, Denis.

LQ

Reply all
Reply to author
Forward
0 new messages