6
votes

Jekyll version 2.5.3

We are trying to write a plugin to promote content that is agnostic as to whether or not its a page or a post. However there is some difference between pages and posts that is not clear.

  # this does not work
  site.pages.each do |page|
    # this does not show up in liquid
    page.data['baz'] = 'Foo'
  end

  # this does work
  site.posts.each do |post|
    # this does show up in liquid
    post.data['baz'] = 'Bar'
  end

Any ideas as to why mutating the .data hash for posts is accessible in liquid, but mutating the .data hash for pages has no effect?

We've also tested this with .data["title"] and it has an effect on posts but page titles are uneffected.


{% for post in site.posts %}
   <div class="postbaz">{{ post.baz }}</div>
{% endfor %}

{% for page in site.pages %}
   <div class="pagebaz">{{ page.baz }}</div>
{% endfor %}

yields

<div class="postbaz">Foo</div>
<div class="postbaz">Foo</div>
<div class="postbaz">Foo</div>
<div class="pagebaz"></div>
<div class="pagebaz"></div>
1
In my prod code it was page. In my reproduction code it was pages, good catch; I moved it back to page and have the same problem.Fresheyeball
@Fresheyeball do you have any update on that question?EugZol
Not since the last one.Fresheyeball

1 Answers

2
votes

You are missing something. Adding values to data works perfectly fine both for pages and posts.

See my repository for reference.

Here I add 'foo' attribute to all pages and posts

_plugins/foo.rb

module Foo
  class Generator < Jekyll::Generator
    def generate(site)
      puts "Our plugin is running"
      puts site.pages.inspect
      puts site.posts.inspect
      site.pages.each do |page|
        page.data['foo'] = 'bar'
      end
      site.posts.each do |post|
        post.data['foo'] = 'bar'
      end
    end
  end
end

Here I add 'foo' to posts layout:

post.html

<article class="post-content">
  {{ content }}
  {{ page.foo }}
</article>

And to pages layout:

page.html

<article class="post-content">
  {{ content }}
  {{ page.foo }}
</article>

After I ran jekyll b I can see output in both post and page, just where I expect them to be.

In separate branch I re-created your setup, where you iterate over all pages and posts:

default.html (source)

{% for post in site.posts %}
   <div class="postbaz">{{ post.foo }}</div>
{% endfor %}

{% for page in site.pages %}
   <div class="pagebaz">{{ page.foo }}</div>
{% endfor %}

_plugins/foo.rb (source)

site.pages.each do |page|
  page.data['foo'] = 'bar'
end
site.posts.each do |post|
  post.data['foo'] = 'baz'
end

(Notice the property is 'bar' for page, and 'baz' for post.)

It renders as expected:

site/index.html (source)

<div class="postbaz">baz</div>



<div class="pagebaz">bar</div>

<div class="pagebaz">bar</div>

<div class="pagebaz">bar</div>

<div class="pagebaz">bar</div>