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:
- Objects and filters that emit client side placeholders cannot be passed as arguments to tags or other filters.
- 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
date_format
– The format that should be used to render name of the date, specified in strftime format, defaults to"%B %Y"
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
date_format
– The format that should be used to render the date of the post in the result, specified in strftime format, defaults to"%B %e, %Y"
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
window_size
– The number of pages to show on either side of the current page in the paging window. The maximum is 10. Set tofalse
to remove the paging window entirely (i.e. only show first/previous/next/last).
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:
- Straight quotes ( “ and ’ ) into “curly” quote HTML entities
- Backticks-style quotes (``like this”) into “curly” quote HTML entities
- Dashes (“–” and “—”) into en- and em-dash entities
- Three consecutive dots (“…”) into an ellipsis entity
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.
message
– The alert messagetype
– The type of the alert, current values include:error
,success
Archive
The archive object includes UI elements for the archive page. See the archive related tags archive_months
and archive_results
for examples.
all_dates_link
– Used with the archive_months tag to insert the link that clears the current month selection. Cannot be used with Liquid filters.pagination
– Used with the archive_results tag to insert pagination link placeholders into theme, which we be renderd client side into previous and next page links as needed. Cannot be used with Liquid filters.
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.
count
– A placeholder for the number of posts for the monthdate
– A placeholder for the date, use to thedate_format
argument to thearchive_months
tag to specify format.url
– A placeholder for the URL of the month filter. This must be set to thehref
attribute of an HTML<a>
tag for correct archive functionality.
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.
date
– A placeholder for the date, use to thedate_format
argument to thearchive_results
tag to specify format.snippet
– A placeholder for the post snipped containing the search query if availabletitle
– A placeholder for the title of the posturl
– A placeholder for the URL of the post
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.
bio
– The HTML bio of the author, if setid
– The internal Posthaven id of the author, if anyname
– The name of the author, if anyphoto
– A profile picture object the author’s profile image, if seturl
– The URL for the page listing all the author’s post, see the author template
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 %}
body
– The body of the commentcreated_at
– The datetime when the comment was createddisplay_name
– The display name for the user who created the commentid
– Internal Posthaven id for the commenttype
– Returns “comment”, useful when iterating over post responses which may be comments or upvotes
Image
height
– The height of the image in pixelswidth
– The width of the image in pixelsurl
– The url of the image
Post Image
{% if request.template == 'post' %}
<!-- code for blog post page -->
{% if post.post_image %}
<img src="{{ post.post_image.xlarge.url }}" />
{% endif %}
{% else %}
<!-- code for other pages (blog index, tag, search results) -->
{% if post.post_image %}
<img src="{{ post.post_image.xlarge.url }}" />
{% endif %}
{% endif %}
This displays the image uploaded to the Post Image field in the post editor.
If you’re developing a theme where an image is needed on the index, tag and search results pages, use the post_image_or_first_image
object instead.
Post Image (with Fallback)
{% if post.post_image_or_first_image %}
<img src="{{ post.post_image_or_first_image.xlarge.url }}" />
{% endif %}
post_image_or_first_image
If no post_image
is available, the first image used in the post is selected. This is useful for blog index, tag and search result pages where the presence of an image is important to a theme’s layout.
Note: This object should not be used in the blog post page, as it will duplicate the first image in the post. If you want to reference only the post image, see
post_image
.
Menu
{% 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.
id
– The internal Posthaven id for the Menuitems
– Array of Menu Item objectstitle
– The title of the menu
Menu Item
See Menu above.
id
– The internal Posthaven id of the menu itemtitle
– The title of the menu itemurl
– The URL of the menu item
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.
body
– The content of the pageid
– The internal Posthaven id for the pagepublishing?
– Returns true if the page is not yet done publishing and fully public yettitle
– The title of the pagetype
– Returns “page”url
– A URL object for the page
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>…</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.
first
– A pagination page for the first page or blank if the current page is the firstlast
– A pagination page for the last page or blank if the current page is the lastnext
– A pagination page for the next page or blank if there is no next pageprevious
– A pagination page for the previous page or blank if there is no previous pagewindow
– A array of pagination pages with 4 pages before and after the current page. Entries withurl
set to blank will be appended to the start or end of the array to represent missing pages between the first page in the window and page 1 or the last page in the window and the last overall page.
Pagination Page
Pagination pages are returned by pagination objects and represent a single page.
active?
– Returns true if this item is the current pagetitle
– A title for the page, this will be the page number for pages in the pagination windowurl
– The URL for the page (a string and not a URL object, useactive?
above to check if this represents the current page)
Post
<article class="post post-{{ post.id }}">
<header>
{% if post.private? %}
<div class="private-indicator"
title="This post is private">
🔒
</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.
anon_upvote_count
– The number of anonymous upvotes the post hasauthor
– The author of the post as an author objectbody
– The body of the postcomments
– A array of comments for the post ordered reverse chronologicallycomment_count
– The number of comments the post hasexcerpt_or_body
– If the post has a more break inserted then the excerpt before the break along with a “Read more” link, otherwise the full post bodyid
– An internal Posthaven id for the postprivate?
– Returns true if the post is privatepublished_at
– The display published date of the postpublishing?
– Returns true if the post is not yet done publishing and fully public yetresponse_count
– The total count of all upvotes and commentsresponses
– A array of all post upvotes and comments ordered reverse chronologicallyshow_byline?
– Returns true if it is appropriate to show a byline for the post. Checks if the post author has a display name available and if the site has multiple authors to displaytags
– A array of tags for the posttitle
– The post’s titletype
– Returns “post”upvotes
- A array of all post upvotes ordered reverse chronologicallyupvote_count
– The total number of upvotes the post hasurl
– The URL of the post as a URL object
Posthaven
The Posthaven object contains HTML snippets and info related to internal Posthaven functionality.
alerts
– Any page alerts that should be show to the user, see the alerts objectincludes_for_body
– Required Posthaven HTML that must be included before the close of the HTML page<body>
tagincludes_for_head
– Required Posthaven HTML that must be include in the HTML<head>
tagurl
– Posthaven’s URL for https://posthaven.com/user_menu
– The HTML of the Posthaven user menu including login, logut and site managment links. It is strongly recommended this be included in themes to provide basic functionality). Output cannot be used with Liquid filters or tags.
Posts
A array of posts with additional pagination information.
current_page
– The current page of postsfirst
– The first post in the arraylast
– The last post in the arraypagination
– A pagination objectper_page
– The maximum number of posts per pagesize
– The number of posts in the array for the current pagetotal_count
– The total number of poststotal_pages
– The total number of pages
Post Picture
Post images have a key for each available image size. Each returns an Image object with url
, height
and width
keys.
thumb
– 200px by 200px squaremedium
– No larger than 800px on either dimensionlarge
– No larger than 1200px on either dimensionxlarge
– No larger than 2400px on either dimension
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.
tiny
– 16px squaresmall
– 32px squaremedium
– 72px squarelarge
– 200px squarexlarge
– 1024px square
Request
The request object contains information related to the incoming request and current content being rendered.
page_description
– A description of the current pagepage_title
– A title based on the current pagetemplate
– The name of the current theme template without “.liquid”url
– The current URL
Settings
When
config/theme.yml
contains abackground_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
archive_url
– A relative URL object to the site’s archive pageblogroll
– An array of menu objects with the sites blogroll menuscomments_enabled?
– true if comments are enabled on the sitecontributors
– An array of author objects of site contributors who have at least a name available, see Contributors and Site Profiles below for more informationdescription
– The site’s descriptionfacebook_sharing_enabled?
– true if Facebook sharing is enabled on the sitefeed_url
– The URL of the site’s Atom feedhomepage_view_count
– The current number of homepage views. This outputs a placeholder for rendering client side and cannot be passed to other Liquid filters or tags.host
– The full hostname of the siteid
– An internal Posthaven id for the sitename
– The site namenavigation_menu
– A menu object with the sites navigation menuprofile
– A site profile object for the site’s owner or, the custom profile for the site if setsubscription_enabled?
– true if email subscriptions are enabled for the sitetags
– An array of the tag objects for the sitetags_url
– A relative URL object to the site’s all tags pagetwitter_sharing_enabled?
– true if sharing on twitter is enabled for the siteupvotes_enabled?
– true if Posthaven upvotes are enabled on the siteurl
– A URL object with the full URL for the 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.url }}"
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.
bio
– The bio of the user or site, can contain limited HTMLname
– The name of user or sitephoto
– The photo of user or site as a profile picture object
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.
name
– The name of the tagpost_count
– The number of public posts with the tagurl
– A URL object for the page displaying all the posts with the tag
Upvote
{% for upvote in post.upvotes %}
{% unless upvote.anon? %}
<div class="upvote">
<strong>{{ upvote.display_name }}</strong>
upvoted this post.
</div>
{% endunless %}
{% endfor %}
anon?
– true if the upvote was created anonymouslycreated_at
– The datetime when the upvote was createddisplay_name
– The display name for the user who created the upvote if availableid
– An internaltype
– Returns “upvote”
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.
current_page?
– true if the URL is that of the current page, false otherwise.