-
-
Notifications
You must be signed in to change notification settings - Fork 47
Tour of a theme
This article will take a tour of a Chyrp theme, to help you understand the things you'll need to know before developing a theme of your own or customising an existing theme. For this article, the theme we will be taking a tour of is Blossom, the default theme for Chyrp Lite, however many of the elements we will encounter are common to all Chyrp themes.
If you're making a theme, twigs are what it's all about. Twigs are text files filled mostly with HTML but also with some instructions for Chyrp to follow, so that the twig can tell Chyrp what to do with it. When a user visits your website, Chyrp will build a web page by combining twigs together in various ways.
You can think of a twig as a fragment of a web page, just like a twig in real life is a fragment of a tree. The final product of every twig Chyrp processes will be a page fragment. When you view a twig, bear that in mind: nothing but the HTML will remain in the final web page as served to the user.
Download the latest release of Chyrp Lite and expand the zip archive. Now take a look inside the expanded chyrp-lite/themes/blossom/ folder. We're going to take a tour of the key elements in here.
The first twig we'll look at is default.twig
in the layouts directory. Open the file in your favourite text editor. If you have a text editor with syntax highlighting, switching it to HTML mode will make it a lot easier to inspect twigs.
default.twig
is different from most twigs: the contents of this twig look almost like a normal web page with a head and a body. That's because default.twig
is the basis for all the other twigs, like the trunk of a tree. No matter what page a user visits on your website, default.twig
will be used as the basis to build it.
Amongst the <head>
and <body>
tags and the other things you'd expect to see in a HTML file, you'll see strange bits of syntax that aren't markup. These are the instructions I mentioned - otherwise known as statements - that allow twigs to give orders to Chyrp. Anything you see between a {% %} is a statement for Chyrp to follow.
Perhaps the most important statement is {% block content %}
{% endblock %}
which tells Chyrp “whatever other twigs you add to this one, add them at this location in the page.” Depending on what page the user has asked to see, this content block might be filled with a bunch of blog posts, or just one, or a login form.
You'll also see conditional statements: {% if this %}
{% else %}
{% end if %}
. If you've ever dealt with JavaScript , you'll understand what's going on here. The twig is telling Chyrp to use different markup under different circumstances, for example the twig tells Chyrp to include some admin controls on the page if the user is logged in and has admin privileges.
The other oddity you'll see repeated in twigs is text prefixed with $
or inside a set of curly brackets like this: ${ }
. These prefixed elements are variables that will result in Chyrp replacing this bit of text with a corresponding value. For example, $theme.stylesheets
will be replaced with a set of <link>
tags to the theme's stylesheets, and ${ "Stats" | translate }
will be replaced with the word “Stats” or an appropriate translation to another language.
Tip: you can customise the text in the next and previous page links with the following Twig commands:
{% if posts.prev_page %}
${ posts.prev_link( ( "Show me newer stuff!" | translate ) ) }
{% endif %}
{% if posts.next_page %}
${ posts.next_link( ( "Show me older stuff!" | translate ) ) }
{% endif %}
You'll be seeing this twig a lot on your site, it's the twig that outputs the basic markup that surrounds all blog posts. The obvious choice with post.twig is to have it output an <article>
element to contain each of your blog posts, so that you can easily arrange and style your posts using a stylesheet – and that's exactly what Blossom does.
A few lines into the twig, you'll see something familiar: {% block content %}
{% endblock %}
. What's going on here? Content blocks can be nested, so default.twig tells Chyrp where in the page to insert the next twig, and that next twig might be post.twig, in which case post.twig
adds a few elements of its own to the page and also provides a place for the next twig to be inserted. That next twig will be different depending on the kind of post this is: text, photo, etc.
After the content block, this twig adds some metadata that are useful for any type of post: the date of the post, the tags categories and comments associated with it, and buttons to edit or delete the post. Remember what we learned about conditional statements when we looked at default.twig
? Look closely at post.twig
and you'll see a lot of conditional statements, displaying comments only if the commenting module of Chyrp is enabled, displaying the edit and delete buttons only if the user viewing the page has the rights to perform these actions, and so on.
If you're building a custom theme just for your own use and you don't want some of these features, just don't include them, it's that simple. You can rearrange, add, remove, and customise the appearance of your blog as much as you like.
Let's suppose a visitor to your site lands on the home page of your blog. Chyrp will fill the page with several instances of post.twig
(how many posts are displayed depends on your administration settings). We've seen that post.twig
reserves a content block for the blog post but itself doesn't display blog posts, so what twig is responsible for that task? Well, if your post is plain text then text.twig
is responsible.
text.twig
is a special kind of twig that allows Chyrp to render different types of content in your blog posts. Each twig in this folder corresponds to a Chyrp Feather: an extension that enables Chyrp to support different content types in blog posts. Take a look in the feathers directory and you'll see the names of several other twigs dedicated to certain types of content – photos, quotes, links, and so on. The simplest kind of blog post is plain text, and that's what text.twig
is here to display. First of all, this twig declares which twig it's here to extend: {% extends "content/post.twig" %}
. Then we get down to business. Plain text is so simple that text.twig is very simple too. It adds a title element to the page if one exists, and it tells Chyrp where to insert the content of the post using the variable ${ post.body | read_more }
with a filter that will trim the post down to a summary if the read more module is enabled in Chyrp.
I'm not going to cover the other feathers. I think you'll be able to figure them out. Next up, we'll check out some forms.
This twig displays a form that allows visitors to your blog to log in, if they are registered users. Even if your blog doesn't allow users to register you'll still be seeing a lot of this form yourself, every time you log in to write a post.
Firstly login.twig
declares it's here to extend layouts/default.twig
. This means any HTML this twig outputs will be inserted in default.twig's content block. The rest of the twig is a fairly straightforward HTML form with just a few Chyrp variables such as {% url "login" %}
that will be replaced with the correct URL for submitting the login form, and some translation filters such as ${ "Username" | translate }
. You will see translation filters quite often as we continue our tour of the Blossom theme.
Wow, that's a big form. It's scary but we're going to look at it closely and once we're done everything will make sense. Firstly, what is this thing? Let's say you are a logged-in user and you are viewing a blog post that you have the right to edit or delete. You'll see some buttons (added by post.twig
) that offer you those options. If you click on the edit button, the blog post will disappear, and in it's place will appear this form occupying exactly the same place on the page where the blog post had been.
The first new discovery here is something I haven't mentioned before now, a trigger. There's one near the top of this twig:
${ trigger.call("before_ajax_edit_post_fields", feather) }
The trigger will “fire” when Chyrp processes this line in the twig. Think of a trigger like a JavaScript event. Triggers are used by Chyrp and its modules to do clever things in response to certain situations - and unless you know what you're doing it's probably best to reproduce each trigger in your custom theme exactly as you find it in the default theme.
After the trigger, there's a new type of Chyrp statement: a loop. The statement is {% for field in feather.fields %}
and it works in a similar way to a JavaScript for loop. For every field of data a feather has added to the post, the loop will inspect the field and add an appropriate form element to the page. For a plain text post, this will result in a <input>
field for the post's title and a <textarea>
containing the body of the post. There's a clever little conditional statement in this loop that adds the text “(optional)” to the label of form elements that are not required.
Next the twig adds a <select>
element if the user has the right to set the status of a post. Then follow several form elements that will always be present no matter the type of post, such as pinned status, timestamp, and so on.
Next is another loop that creates elements for post options. Most often this will result in an <input>
field containing the tags for the post. Below the text area the $field.extra
variable will be replaced with a collection of <a>
elements for other tags that can be added to the post by clicking them.
Finally, there's "Save" and "Cancel" buttons with translation filters, and some hidden <input>
fields to hold other data needed by Chyrp.
When the "Save" or "Cancel" buttons are clicked, this form and the entire contents of this twig will disappear and be replaced by the freshly updated blog post. It's important that the form element in this twig is the outermost element and has the attribute id="post_edit_form_$post.id"
in order for inline editing to function correctly.
The pages directory contains many twigs of a type distinctly different from feathers and forms. Not to be confused with paginated blog content, all the twigs in the pages directory are templates that extend default.twig for different viewing contexts. What do I mean by a context? Well, let's say a visitor lands on the home page of your blog – that's one context. After the home page, perhaps the most commonly seen context is the permalink or viewing context; this is a page that displays just one particular blog post in isolation, and view.twig
is responsible for that context.
Firstly view.twig
announces that it's here to extend default.twig
then it gets started adding content to the page. If the blog has other posts before and after the one being viewed, the twig adds links to them. ${ post.next.title | truncate(40) }
is a filter that reduces the post title to 40 characters, to ensure the hypertext text does become unwieldy. You can enter any number you prefer to set your own limit, or remove the filter entirely.
Next we have something new: {% include "feathers/" ~ post.feather ~ ".twig" %}
. Actually, if you had been looking closely you would have seen something similar in default.twig
. This is an include statement, and default.twig
uses one to add a sidebar to the page. The include statement is similar to block but it's used in situations where the twig knows exactly what content it wants to add to the page, similar to a CSS @import
rule that injects one stylesheet into another. A block says: “if you've got something to add, add it here.” An include says: “I want this specific thing injected into the page here.”
In this case the twig is telling Chyrp to inject the suitable twig for the Feather type of the blog post the visitor is viewing. For a text post that means text.twig
, and because text.twig
extends post.twig
that means post.twig
is coming along as well. What we'll end up with in the rendered page is a nest of twigs, each adding its own little bit of content to the page:
-
default.twig
-
view.twig
-
post.twig
text.twig
-
-
After the include statement, view.twig
adds some content to the page only if Chyrp's commenting module is enabled.
This is your blog's index, a very simple twig that fills the page with blog posts. The index is what visitors will see when they land on the homepage of your blog. The number of posts on the page is controlled in the administration console, and if there is more than one page of posts, default.twig
will add <a>
elements linking to the next and previous pages of the index (if applicable). If your blog is configured to display 4 blog posts per page, your page will be constructed as follows:
-
default.twig
-
index.twig
-
post.twig
text.twig
-
post.twig
text.twig
-
post.twig
text.twig
-
post.twig
text.twig
-
-
This is another simple twig that displays the results of a search. If your blog has a search bar, this is the page where visitors will come to view the search results. Firstly an if
statement tries to determine if it should display a <h3>
element. Next, a for
loop iterates through the search results and includes the appropriate twig for each of the blog posts to be displayed on the page.
The javascripts directory contains all the JavaScripts you want to make available to your theme's pages. When Chyrp processes default.twig
, it searches this directory and adds a <link>
to the page header for every file it finds here.
You can add as many scripts as you like, and adding files with a “.js” file extension is ok. However the Blossom theme does something a little different. The one file in the Javascripts directory of this theme is theme.js.php
. What's going on here? This is a normal JavaScript wrapped in PHP, which allows the file to be processed on the server before it is delivered to the visitor. Here's the structure:
<?php
define('JAVASCRIPT', true);
require_once "../../../includes/common.php";
error_reporting(0);
header("Content-Type: application/x-javascript");
?>
<!-- --><script>
// Insert your JavaScript here
<!-- --></script>
You don't need to wrap your scripts in PHP if you don't want to, but it can be useful if you are familiar with PHP and you want to add some server-side magic to your JavaScripts. Blossom uses some PHP to determine the URL of the theme directory and to insert some translated alt-text for improved accessibility.
While we're on the subject, it's also worth noting that Chyrp uses the jQuery JavaScript library. jQuery comes bundled with Chyrp and is automatically available on every page of your blog, so you won't need to add it to the javascripts directory.
Here our tour ends. You haven't seen everything that's needed to build a Chyrp theme, but you've seen enough to figure out the rest on your own. If you want more technical detail about Chyrp themes, read the article Anatomy of a Theme and if you want to learn more about Twig read the Twig Reference.
This is the wiki for Chyrp Lite: An ultra-lightweight blogging engine, written in PHP.
- About Permissions
- Tour of a Theme
- Twig Reference
- Twig Variables
- Object Attributes
- Routes and Controllers
- Making Your First Module
- Debug and Tester Modes
- About Errors
- Introduction to Helpers
- Introduction to Translations
- Introduction to Triggers
- Anatomy of info.php Files
- Anatomy of a Feather
- Anatomy of a Module
- Anatomy of a Theme
- Anatomy of a Post
- Localizing Extensions
- Adding Ajax Functionality
- Working with JavaScript
- Working with Model
- Working with Config