NAV

Theme Basics

Liquid Reference

General

Posthaven themes use the Liquid Templating Engine. Please read the Client Side Rendering note below for an important idiosyncrasy in our use of Liquid.

Client Side Rendering

For performance reasons many parts of Posthaven blogs are rendered in the browser. To this end many Posthaven Liquid objects, filters, and tags output placeholders intended to be manipulated by internal Javascript. This has two consequences:

  1. Objects and filters that emit client side placeholders cannot be passed as arguments to tags or other filters.
  2. Tags that emit client side placeholders cannot cannot include other Liquid tags inside their bodies.

Relevant objects, filters and tags are noted below.

Tags

Posthaven provides a few Liquid tags to expose site functionality. In addition all built-in Liquid tags are supported. See the Liquid tags documentation for reference.

archive_months

<div class="archive-months">
  <ul>
    {% archive_months date_format:"%B %Y" %}
      <li>
        <a href={{ month.url }}>
          {{ month.date }}
        </a> 
        ({{ month.count }})
      </li>
    {% endarchive_months %}
  </ul>
  <div class="archive-all-dates">
    {{ archive.all_dates_link }}
  </div>
</div>

The archive_months tag emits a client-side placeholder and cannot include other liquid tags. See client side rendering above.

The archive_months tag is used to render the month menu on the archive page. It is only available in the archive.liquid template (or snippets included from that template).

Inside the tag the month variable will be set to an archive month object. The archive_months tag functions like a for loop in that the contents will be rendered once for each month in the archive. The tag outputs placeholders which are rendered on the client-side the result variable cannont be used with Liquid filters or other tags.

The all_dates_link key on the archive object provides a placeholder for the link to clear the current month filter.

Arguments

archive_results

<div class="archive-results">
  {% form 'archive' %}

  <ul>
    {% archive_results date_format:"%B %e, %Y" %}
      <li class="archive-entry">
        <a href="{{ result.url }}">
          <span>{{ result.title }}</span>
        </a>
        <div class="search-highlight">
          {{ result.snippet }}
        </div>
        <div class="archive-date">
          {{ result.date }}
        </div>
      </li>
    {% endarchive_results %}
  </ul>

  <div class="archive-pagination">
    {{ archive.pagination }}
  </div>
</div>

The archive_results tag emits a client-side placeholder and cannot include other liquid tags. See client side rendering above.

The archive_months tag is used to render the results of an archive page search or month filter. It is only available in the archive.liquid template (or snippets included from that template).

Inside the tag the result variable will be set to an archive result object. The archive_results tag functions like a for loop in that the contents will be rendered once for each result on the page. The tag outputs placeholders which are rendered on the client-side the result variable cannont be used with Liquid filters or other tags.

The pagination key on the archive object provides a placeholder for the link to clear the current month filter.

Arguments

default_pagination

{% if posts.pagination %}
  <footer class="pagination">
    {% default_pagination %}
  </footer>
{% endif %}

The default_pagination tag outputs pagination for the current list of posts. It only outputs HTML on templates where the posts variable is set.

It output an HTML <ul> with an <li> for first, previous, next, last and a page window including the current page with placeholders for gaps.

See the pagination object for more precise control over the pagination HTML.

Arguments

form

The form tag outputs HTML forms for actions on the Posthaven site. The first arguments is the type of form and there are currently three valid values, comment, subscribe, and archive.

Comment

{% form 'comment' %}

The comment form allows a Posthaven user or anonymous user to submit a comment and as such will be rendered appropriately for the current context. The comment form is only available on an individual post’s page (i.e. NOT on the blog homepage).

Subscribe

Render the form directly:

{% form 'subscribe' %}

Render the form hidden behind a call to action:

{% form 'subscribe' include_prompt:true %}

The subscribe form allows Posthaven users to follow the site and anonymous users to enter their email address to subscribe by email. In the anonymous out case by default the form will be rendered directly, but if include_prompt:true is passed to the tag a call to action will be shown first and then form will be revealed after the call to action is clicked.

Archive

{% form 'archive' %}

The archive form outputs a search input for the user to search the site archive. On the archive page (i.e. the archive.liquid template) the search will be updated live, on all other pages the form submission will go to the archive page.

Filters

In addition to the custom Posthaven Liquid filters below built-in Liquid filters are supported. See the Liquid filter documentation for reference.

asset_url

For a file in your theme at assets/cats.jpg:

<img src="{{ 'cats.jpg' | asset_url }}">

Converts the name of a file in the assets/ directory of a theme to that file’s URL.

local_date

{{ post.published_at | local_date: "%B %e, %Y at %l:%M %p" }}

This filter outputs a placeholder for rendering client side and cannot be passed to other Liquid filters or tags.

Converts a date into the current time zone of the users browser. Accepts a format string as an argument in the strftime format.

pluralize

The plural form will be inferred by default:

{{ post.response_count | pluralize: 'response' }}

The plural can also be specified:

{{ post.upvote_count | pluralize: 'upvote', 'upvotes' }}

Outputs the singular or plural version of a string based on the value of a number. Accepts two parameters: the singular version of the string, the plural version of the string.

relative_date

{{ post.published_at | relative_date }}

This filter outputs a placeholder for rendering client side and cannot be passed to other Liquid filters or tags.

Converts a date into relative terms from the current time, e.g. ‘3 weeks ago’.

script_tag

{{ 'blog.js' | asset_url | script_tag }}

Convenience method for generating <script src="..."> tags for including external Javascript files.

share_buttons

{{ post | share_buttons }}

Outputs the default set of share buttons for the post depending on the settings for the site. By default it will include the Posthaven upvote button, Twitter tweet button and Facebook share button, but the site owner can disable any of these.

smarty_pants

<h1 class="name">{{ site.name | smarty_pants }}</h1>

Follows the SmartyPants logic to replaces ASCII punctuation with the “smart” typographic punctuation HTML entities. The following transformations are included:

stylesheet_tag

{{ 'blog.css' | asset_url | stylesheet_tag }}

Convenience method for generating <link rel="stylesheet" ... > tags to include external style sheets.

text_if_current

By default the returned string will be the string "current"

<li class="{{ menu_item.url | text_if_current }}">
  <a href="{{ menu_item.url }}">{{ menu_item.title }}</a>
</li>

But the return value can also be specified

{{ "/archive" | text_if_current: "You're on the archive page!" }}

Accepts a URL (as a string or URL object) and returns a string if that URL is the current page being rendered. By default it will return current but that can be overriden via the first argument. Often useful for adding CSS classes to links to the current page.

upvote_button

{{ post | upvote_button }}

Outputs the Posthaven upvote button if upvotes are enabled on the site. This is not needed when share_buttons below is used because that also includes the upvote button. Useful in situations where the theme designer wants full control over the Twitter and Facebook share HTML.

view_count

Without a label:

{{ post | view_count }}

With a label

{{ post | view_count: 'view' }}

This filter outputs a placeholder for rendering client side and cannot be passed to other Liquid filters or tags.

When passed a post or site object it ouputs the current post or homepage view count, respectively. By default it only outputs the number but if given arguments it will output a label. The arguments are similiar to those for pluralize: the first is the singular form of the label and the optional second the plural (if omitted the plural will be derived from the singular).

Objects

Alert

<div class='alerts'>
  {% for alert in posthaven.alerts %}
    <div class="alert alert-{{ alert.type }}">
      {{ alert.message }}
    </div>
  {% endfor %}
</div>

Alerts contain messages for the user about their recent activity. E.g. when they enter the incorrect password on a private site or have just logged in successfully.

Archive

The archive object includes UI elements for the archive page. See the archive related tags archive_months and archive_results for examples.

Archive Month

An archive month object contains the information to render a single link in the archive_months tag. All fields contain placeholders for client side rendering and cannot be used with liquid filters.

Archive Result

An archive month object contains the information to render a single result (i.e. post on the site) in the archive_results tag. All fields contain placeholders for client side rendering and cannot be used with liquid filters.

Author

<span class="author">
  posted by
  {% if post.author.url %}
    <a href="{{ post.author.url }}">{{ post.author.name }}</a>
  {% else %}
    {{ post.author.name }}
  {% endif %}
</span>

The author object contains information about post authors and site contributors. Most author fields may be empty depending on if the author is a full Posthaven user or email-only contributor and upon what information they have provided.

Comment

{% for comment in post.comments %}
  <div class="comment">
    <div class="body">
      {{ comment.body }}
    </div>
    <div class="byline">
      by {{ comment.display_name }}
      <span class="time-ago">{{ comment.created_at | relative_date }}</span>
    </div>
  </div>
{% endfor %}

Image

{% if site.navigation_menu.items != empty %}
  <nav class="nav-menu">
    <ul>
    {% for menu_item in site.navigation_menu.items %}
      <li class="{{ menu_item.url | text_if_current }}">
        <a href="{{ menu_item.url }}">{{ menu_item.title }}</a>
      </li>
    {% endfor %}
    </ul>
  </nav>
{% endif %}

Menus contain array of Menu Item objects with links or Posthaven pages. See the navigation_menu and blogroll keys of the Site object.

See Menu above.

Page

<article class="page page-{{ page.id }}">
  <header>
    <h1 class="title"><a href="{{ page.url }}">{{ page.title }}</a></h1>
  </header>

  <section class="body">
    {{ page.body }}
  </section>
</article>

Page objects contain the attributes for static pages. Available in the page template.

Pagination

Loop over everything in pagination:

{% for page in posts.pagination %}
  {% if page.url %}
    <li class="{% if page.active? %}active{% endif %}" 
          href="{{ page.url }}">
        {{ page.title }}
      </a>
    </li>
  {% else %}
    <li class="gap">
      <a>{{ page.title }}</a>
    </li>
  {% endif %}
{% endif %}

Or handle the parts separately:

{% if posts.pagination %}
  <div class="pagination">
    <ul class="clearfix">
      {% if posts.pagination.first %}
        <li>
          <a href="{{ posts.pagination.first.url }}">
            First Page!
          </a>
        </li>
      {% endif %}

      {% if posts.pagination.prev %}
        <li>
          <a href="{{ posts.pagination.prev.url }}">
            Previous Page
          </a>
        </li>
      {% endif %}

      {% for page in posts.pagination.window %}
        {% if page.url %}
          <li class="{% if page.active? %}active{% endif %}">
            <a href="{{ page.url }}"> {{ page.title }} </a>
          </li>
        {% else %}
          <li class="gap"><a>&hellip;</a></li>
        {% endif %}
      {% endfor %}

      {% if posts.pagination.next %}
        <li>
          <a href="{{ posts.pagination.next.url }}">
            Next Page!
          </a>
        </li>
      {% endif %}

      {% if posts.pagination.last %}
        <li>
          <a href="{{ posts.pagination.last.url }}">
            Last Page!
          </a>
        </li>
      {% endif %}
    </ul>
  </div>
{% endif %}

The pagination object encapsulates the logic needed to render pagination links. Pagination objects can be used in a for loop which will include first/previous/next/last and the window.

Pagination Page

Pagination pages are returned by pagination objects and represent a single page.

Post

<article class="post post-{{ post.id }}">
  <header>
    {% if post.private? %}
      <div class="private-indicator" 
           title="This post is private">
        &#128274;
      </div>
    {% endif %}
    <h1 class="title">
      <a href="{{ post.url }}">{{ post.title }}</a>
    </h1>
  </header>

  <div class="body">
    {{ post.body }}
  </div>

  <footer>
    <div class="details">
      {% if posts.comment_count > 0 %}
        <a href="{{ post.url }}" 
           class="{{ post.url | text_if_current }}">
          {{ post.comments.size | pluralize: 'comment' }}
        </a>
      {% endif %}
      posted
      <a href="{{ post.url }}" 
         class="{{ post.url | text_if_current }}">
        {{ post.published_at | relative_date }}
      </a>

      {% if post.show_byline? %}
        <span class="author">
          by
          {% if post.author.url %}
            <a href="{{ post.author.url }}">
              {{ post.author.name }}
            </a>
          {% else %}
            {{ post.author.name }}
          {% endif %}
        </span>
      {% endif %}
    </div>
    {{ post | share_buttons }}
  </footer>
</article>

The post object contains attributes for individual posts.

Posthaven

The Posthaven object contains HTML snippets and info related to internal Posthaven functionality.

Posts

A array of posts with additional pagination information.

Post Picture

Post images have a key for each available image size. Each returns an Image object with url, height and width keys.

Profile Picture

{% if site.profile.photo.tiny %}
  <img src="{{ site.profile.photo.tiny.src }}"
       width="{{ site.profile.photo.tiny.width }}"
       height="{{ site.profile.photo.tiny.height }}">
{% endif %}

Author and site pictures with a key for each available image size. Each returns an Image object with url, height and width keys.

Request

The request object contains information related to the incoming request and current content being rendered.

Settings

When config/theme.yml contains a background_color setting:

settings:
  key: background_color
  label: Primary Color
  default_value: #000
  type: color"

settings will contain the corresponding key:

{% if settings.background_color %}
<style>
  body {
    background-color: {{ settings.background_color }};
  }
</style>
{% endif %}

The settings object contains the user settings as defined for the theme. See Configuration.

Site

Contributors and Site Profiles

The site profile defaults to that of the site owner, but site owners can set site specific profiles for each of their sites. The contributors array will only contain the site owner if the site has a site specific profile. In other words the site owner’s information will never be returned both as site.profile and in site.contributors so all of the returned contributors and the full site profile can be shown without duplication.

Site Profile

<section class='profile>
  <h1>{{ site.profile.name }}</h1>

  {{ site.profile.bio }}

  {% if site.profile.photo %}
    <div class="profile-pic">
      <img src="{{ site.profile.photo.medium.src }}"
           width="{{ site.profile.photo.medium.width }}"
           height="{{ site.profile.photo.medium.height }}">
    </div>
  {% endif %}
</section>

The site profile object contains the information displayed as the primary author on the site. By default this is the site owner, but owners can set site-specific details to be shown.

Tag

{% for tag in site.tags limit:10 %}
  <li class="{{ tag.url | text_if_current}}">
    <a href="{{ tag.url }}">{{ tag.name }}</a>
    <span class="tag-count">{{ tag.post_count }}</span>
  </li>
{% endfor %}

Tag objects contain information for a tag given to at least one post on the site.

Upvote

{% for upvote in post.upvotes %}
  {% unless upvote.anon? %}
    <div class="upvote">
      <strong>{{ upvote.display_name }}</strong> 
      upvoted this post.
    </div>
  {% endunless %}
{% endfor %}

URL

{% if post.url.current_page? %}
  You are are looking at this {{ post.url }}!
{% else %}
  You are not looking at {{ post.url }}.
  <a href="{{ post.url }}">Go check it out!</a>
{% endif %}

URL both output a URL string when used as a variable and have a current_page? key which when return true if the URL links to the current page.