jekyll-theme-endless
A Jekyll Theme ready for AsciiDoc

jekyll-theme-endless

jekyll-theme-endless is a theme for the static site generator Jekyll. The theme is ready to be used with posts written in AsciiDoc using the Jekyll AsciiDoc plugin. Moreover, it is shipped with a plugin that generates a tag cloud and a page for each tag, listing all posts associated with it. The syntax of source code is highlighted using Rouge. Below you’ll find a list of the key features of this theme.

The repository of this Jekyll theme is located at: https://gitlab.com/jekyll-theme-endless/jekyll-theme-endless.gitlab.io. An example page using this theme can be viewed at: https://jekyll-theme-endless.gitlab.io. The gem is published on https://rubygems.org/gems/jekyll-theme-endless.

Quicktstart for testing

  • Clone the repository

  • Run bundle exec jekyll serve --config _config.yml,_data.yml

  • Open http://127.0.0.1:4000/ to view a page using this theme

Installation

Add this line to your Jekyll site’s Gemfile:

gem "jekyll-theme-endless"

In your Jekyll site’s _config.yml:

  1. activate the theme

  2. activate the plugin to generate pages for each tag linked in the tag-cloud

theme: jekyll-theme-endless
plugins:
  - jekyll-theme-endless

And then execute:

bundle

Or install it yourself as:

gem install jekyll-theme-endless

Features

  • Tag Cloud and Tag Pages A tag cloud for easy topic navigation, with individual tag pages displaying a list of posts for each tag (0.3.0), including tag descriptions (0.10.0).

  • Mathematical Formulas Support for displaying mathematical formulas, ideal for technical and academic content. (0.14.0)

  • Text-Based Diagrams Diagrams can be added as code (PlantUML, Dot/GraphViz, Ditaa, etc.) to your pages and post using AsciiDoc’s diagram capabilities. (0.15.0)

  • Schema.org Annotations for Blog Posts Built-in Schema.org metadata for enhanced SEO and better content categorization by search engines. (0.12.0)

  • Glossary An automatically generated glossary for the tags you use, displaying their descriptions in a clear and organized manner. (0.16.0)

  • RSS Feed Automatic RSS feed generation to keep subscribers updated on new posts. (0.12.0)

  • Automatic Menu Generation Auto-generation of menu entries for pages, streamlining site navigation management. (0.0.0, 0.1.0)

  • Responsive Design with Bootstrap Mobile-friendly, fully responsive design utilizing Bootstrap for a consistent experience across devices. (0.1.0)

  • AsciiDoc-Ready for Posts and Pages Full support for writing posts and pages in AsciiDoc (0.0.0), including features like:

    • Code highlighting (with language display) using Rouge (0.5.0)

    • Admonitions (notes, warnings, tips, etc.) (0.6.0)

    • Tables, quotations, glossaries, and table of contents (0.7.0, 0.10.0)

    • See the AsciiDoc Showroom for examples and capabilities.

  • Comprehensive Documentation Extensive documentation covering all theme features and configuration options, including detailed guides for config files.

  • Complete Docker Image for CI/CD Pipelines Provides a Docker image that contains all essential tools and dependencies required for building and deploying your Jekyll site. (0.15.0)

  • Multiple Include Points Numerous built-in include points allowing additional content (such as ads, extra scripts, and blog navigation) to be added without modifying layout files, making customizations easy without re-implementing the layout. (0.12.0)

  • Several Blog Post List Layouts There are two layouts for blog post lists, and you can easily add your own designs. (0.13.0)

Planned features

  • Swipe Navigation for Blog Posts with Allowing users to navigate between blog posts using swipe gestures on touch devices.

  • Cookie Consent Built-in cookie consent functionality to comply with data privacy regulations.

  • No CDN Dependency The theme can be run without relying on Content Delivery Networks (CDNs) for improved data privacy and offline functionality.

  • Multilingual Support Enabling the theme to support multiple languages for international audiences.

  • Author List A feature to display a list of all contributing authors.

  • Additional Blog Post List Layouts More layout options for blog post lists, including pagination for better content management.

General information

The theme is styled using Bootstrap that is added via a content delivery network (CDN; here: https://www.jsdelivr.com/).

The output of page variables (e.g. page.title or page.menu_label) is not escaped by the theme-layout. The reason is, that Jekyll-AsciiDoc (in contrast to Markdown) escapes HTML by default. Thus, using (unescaped) HTML-commands e.g. in titles of Markdown posts/pages might break the layout. If you want to use Markdown AND have HTML-commands in the title, simply escape them (e.g. use &lt; instead of <).

Example posts and pages

The project repository contains

If you want to use special characters in your tags, you need to create them through the Jekyll front matter instead of the AsciiDoc variable page-tags. Further explanations can be found in the examples above and the release notes of version 0.12.0.

Usage

Here I describe available layouts, includes, SASS- and other assets.

To copy all the files of the theme into a folder, you can use the following command (in the root directory of your Jekyll project):

cp -r "$(bundle show jekyll-theme-endless)" .

This will copy the theme-folder containing all its files into the current directory. From there, you can selectively move files to your project and modify them as needed. Your (modified) copy will afterwards overwrite the contents provided by the theme.

If you only want to copy the example pages (like the AsciiDoc showroom) to your project, use:

cp -r "$(bundle show jekyll-theme-endless)/pages_examples" .
Whenever you create custom versions of files in this theme, consider whether they might also be useful for others. In that case, you could contribute the changes to the project. Feel free to contact me about it.

Layouts

_layouts/html.html

HTML boilerplate code used for all layouts.

_layouts/default.html

Default website structure (menue, tag cloud, …​) used for pages and posts.

Contains a navigation bar with a configurable brand-label. Set brand in your _config.yml, to determine what is shown on the left side of the navigation. Example:

The values for brand, title and subtitle are not escaped by the layout. Thus, you can use HTML-commands.
brand: '"<i>endless</i>"-Theme'

Contains a configurable title bar. Set title and subtitle in your _config.yml, to determine what is shown below the navigation bar. If none of the two values is set, the title bar is omitted. Example:

title: 'Brandname'
subtitle: 'Vision statement'

Contains a configurable footer. Includes content_footer-usernames.html to generate a list of contact options. Configure values in _config.yml. Example:

author: Sven Boekhoff
copydate: 2020
disclaimer: >- # this means to ignore newlines until the next entry
  I'm creating this Jekyll theme because I want to use it myself.
  Therefore, many things (e.g. the support of AsciiDoc) are based on personal requirements.
  You are welcome to use the theme (at your own risk) and contribute to the development.
_layouts/page.html

Layout of page-content.

Start a new page in AsciiDoc by adding a file ending with .adoc. Do not forget the page--prefix when setting page variables. Jekyll-AsciiDoc has an auto-detection mechanism for the layout. Thus, you typically do not have to set the layout to page or post.

= Page title
:page-layout: page

Content.

Start a new page in Markdown by adding a file ending with .md.

---
layout: page
# Use either a `# Heading` OR set the title in the front matter.
# Using both will result in two headings.
---
# Page title

Content
_layouts/page-glossary.html

This is a layout for a page that displays, at its end, a list of all terms from the file _data/tag-descriptions.yml along with their respective explanations. The explanations can include complex content, such as lists, code blocks, or admonitions.

_layouts/page-postlist.html

The page-postlist layout is designed to add a list of blog posts at the end of any page that uses this layout. The post list can currently be configured using two values via Jekyll front matter or page variables:

page-postlist-css-class: This specifies the CSS class for the <ul> element where the posts will be listed, allowing for different list styles.

page-postlist-format-function: This specifies the code to be included for generating the HTML structure of each post in the list. Currently, two designs are available (_includes/function_post-in-list-short.html [view postlist using the 'short design'] and _includes/function_post-in-list-long.html [view postlist using the 'long design']), but you can create your own custom formats.

To set the values, simply add them as front matter or page variables. For front matter (e.g., in Markdown pages, layouts, or even AsciiDoc pages), it might look like this:

---
# Layout that attaches blog posts to the end of the page-content.
layout: page-postlist
menu_position: 500
page-menu_label: Blog
summary: "150 character description of the page."
## Configuration of the postlist layout (page-postlist.html):
postlist-css-class: "post-list-long"
postlist-format-function: "function_post-in-list-long.html"
---
# Page title

Content

For AsciiDoc pages, you can also set it as a page variable:

= Page title
// Layout that attaches blog posts to the end of the page-content.
:page-layout: page-postlist
:page-menu_position: 500
:page-menu_label: Blog
:page-summary: "150 character description of the page."
// Configuration of the postlist layout (page-postlist.html):
:page-postlist-css-class: "post-list-short"
:page-postlist-format-function: "function_post-in-list-short.html"

Content
If you want to set the values for page-tag.html (the layout used by the plugin to create the tag pages), then the configuration must be done directly in that file, even if the layout page-postlist is defined in a downstream layout like page-tag-template.
_layouts/page-tag.html

Layout of pages containing a list of those posts being tagged with a given tag. This file is required by the generate-tagpages-plugin.

It seems that plugins cannot read the files provided by themes. Thus, the file has to be created in the _layouts folder in every Jekyll project.

For simplicity, I have designed a basic layout in the file page-tag-template.html that you can include. Alternatively, you can copy the content of page-tag-template.html into your page-tags.html.

The content can be for example the following:

---
layout: page-tag-template
menu_position: -10
## Configuration of the postlist layout (page-postlist.html):
postlist-css-class: "post-list-long"
postlist-format-function: "function_post-in-list-long.html"
#postlist-sort-by:
#postlist-sort-order:
---
_layouts/page-tag-template.html

Simple page that allows you to define the content of the tag pages. This file is a template layout that can be included in page-tag.html.

_layouts/post.html

Layout of blog-posts.

Start a new post in AsciiDoc by adding a file ending with .adoc to the _posts/-folder. Do not forget the page--prefix when setting page variables. Jekyll-AsciiDoc has an auto-detection mechanism for the layout. Thus, you typically do not have to set the layout to page or post.

= Page title
:page-layout: post

Content.

Start a new post in Markdown by adding a file ending with .md.

---
layout: post
# If the title of the post should be different from parts of the filename,
# change it using the title variable.
# Using a `# Heading` will result in two headings in the post.
title: Page title
---

Content
_layouts/statistics.html

Simple page that displays statistics about the blog (such as the number of posts, number of tags, etc.), as well as potential issues (e.g., "posts without a tag"). I typically use this page as a layout for my "about" page.

Includes

_includes/aside_navigation.html

The first of three elements displayed alongside the page content (or at the end of the page on mobile devices). This typically contains blog navigation elements such as 'Recent Articles,' 'Tag Cloud,' etc. It’s best practice to wrap the content in an <aside> element.

_includes/aside_info.html

The second of the three elements, typically providing additional information about the blog (e.g., a link to the RSS feed). This content is also ideally wrapped in an <aside> element.

_includes/aside_more.html

The third of the three elements is typically used to display links to partner sites, sponsorships, or advertisements relevant to the blog’s audience. Similar to the other sections, this content is best organized within an <aside> element to ensure it complements the main content without disrupting the reader’s experience.

_includes/container_end-of-document.html

An empty file that can be overwritten by the user of the theme. The file is included directly before the </body>. It can be used to e.g. append JavaScript commands to the end of the file without having to rewrite a complete layout file.

_includes/container_head-of-document.html

An empty file that can be overwritten by the theme user to add content to the header of the HTML document. It is included directly after the <link> commands for libraries and before the <link> command for main.css. This allows you to add libraries and modify settings in main.css as needed.

_includes/container_start-of-main.html

The content of this file is inserted above the main content area (the section containing the page content and blog navigation). The content should be wrapped in a <div> element.

_includes/container_end-of-main.html

The content of this file is inserted below the main content area — above the footer. The content should be wrapped in a <div> element.

_includes/container_start-of-page.html

The content of this file is inserted between the heading and the main content of the page. The content should be enclosed within a <div> element.

_includes/container_end-of-page.html

The content of this file is inserted at the end of the page content—directly after the main page content. The content should be enclosed within a <div> element.

_includes/container_start-of-post.html

The content of this file is inserted between the tag list and the main content of the post. The content should be enclosed within a <div> element.

_includes/container_end-of-post.html

The content of this file is inserted at the end of the post, below the navigation buttons linking to the previous and next posts. The content should be enclosed within a <div> element.

_includes/function_glossary-entry.html

This function is called to display an entry in the glossary.

_includes/function_list-pages.html

Generates the code containing links to each page. The text of the link is the title of the page.

If the text should be different from the page-title, set the page variable menu_label. In AsciiDoc files this could be e.g.: :page-menu_label: 'AnotherText'.

By default, the links in the menu are ordered alphabetically. The order of the links can be explicitly determined using the page variable menu_position (in AsciiDoc page attributes e.g. :page-menu_position: 100; in Jekyll front matter e.g. menu_position: 50). Pages with higher numbers appear on the left side of the menu. Pages with a negative value for menu_position will be hidden from the menu. This can be useful for your 404 page, which should be generated by Jekyll, but not visible in the menu.

_includes/function_list-posts.html

Generates a list containing blog posts.

_includes/function_post-in-list-long.html

Generates the code to display a single post in the list of blog posts. An entry consists of the title of the blog post (linked to the article), a summary, the creation date and a list of tags associates with the post.

_includes/function_post-in-list-short.html

Generates the code to display a single post in the list of blog posts. An entry consists of the title of the blog post linked to the article. If a permalink is configured for the article, this is indicated by an icon.

_includes/function_post-in-list-recent.html

Generates the code to display a single post in the list of recent blog posts. An entry consists only of the title of the blog post (linked to the article).

_includes/function_post-in-list-duplicate-tags.html

Generates the code to display a single post in the list of blog posts that have duplicate tags. An entry consists of the blog post title (linked to the article) and a list of tags that are mentioned multiple times in the tag list, along with their frequency.

_includes/function_tag-cloud.html

Generates a tag cloud.

_includes/function_tag-list.html

Generates a formatted list of tags. This is e.g. used to display the tags of a blog post.

_includes/function_tag.html

Generates the code for a tag-"pill" in a <li>-Element.

_includes/content_footer-powered-by.html

Contains the information at the very bottom right of the footer, where the powered-by details are displayed. This section can be replaced or removed as desired.

_includes/content_footer-usernames.html

Creates a list of contact options based on provided usernames and addresses. The entries are preceded with the icons of (e.g.) the social network and are linked to the corresponding profile.

In your _config.yml use for example:

email: your-email@example.com
username_gitlab: XXXX
username_github: XXXX
username_xing: XXXX
username_linkedin: XXXX
_includes/function_show-dates.html

Show the creation date and (if present) the date a blog post was last edited. The date of the last edit can be configured by setting a value for the page-variable last_modified_at.

In AsciiDoc this would be e.g.:

:page-last_modified_at: 2024-10-27
_includes/function_show-prev-next-navigation.html

Displays links to the previous and the next post of your blog.

Plugins

lib/jekyll-theme-endless/generate-tagpages.rb

Generates a page for each tag listed in site.tags. The files created are by default named tags/<tagname>/index.html. The content is generated using the layout file _layouts/page-tag.html

The following values can be set in _config.yml:

# Settings for tag cloud:
# The name of the directory in which the files for each tag are created
# default: `tags`
tag_dir: post-for-tag
# Prefix to be used for the title of the tag-page
# default: `Tag: `
tag_title_prefix: "Posts tagged with: "
lib/jekyll-theme-endless/liquid-match-filter.rb

Liquid filter match that enables checking whether a string matches a regular expression.

Example of how to use the match filter in Liquid
{% assign string = "Xapple" %}
{% assign result = string | match: "^a" %}

{% if result  %}
  "{{ string }}" begins with the letter "a".
{% else %}
  "{{ string }}" does not begin with the letter "a".
{% endif %}

Styles

In order to contribute SCSS-code, simply add a file _sass/user.scss, containing your SCSS-code. This file is included by assets/css/main.scss.

Since version 0.10.0, you can also add stylesheets dynamically to assets/css/main.scss using the site-variable additional-stylesheets in _config.yml. Example

# You can dynamically add import statements to assets/css/main.css
# Just add the path (relative to the folder `_sass`) to this array
# CAUTION: omit the ending ".scss"
additional-stylesheets:
  - "../theme-specific/debug"

Data-files

_data/tag-description.yml

You have the option to store descriptions for your tags in a YAML file. This is useful to ensure that everyone has the same understanding of each tag. In the current theme, the descriptions are used in three places:

  • On the tag page, below the page header (If available, the long description is preferred here.)

  • As the title of each tag in the tag cloud (Only the short description is used here.)

  • In the glossary layout (If available, the long description is preferred here.)

The descriptions in the YAML file can include AsciiDoc code, as shown in the following example:

Tag:
  short: "Short description for the tag 'Tag'."
AsciiDoc:
  short: "A lightweight but feature-rich markup language used for writing documentation in plain text."
  long: > # folded block - single newlines are replaced with spaces.
    AsciiDoc is a lightweight yet powerful markup language
    designed for writing documentation in plain text format.
    It supports a rich set of features, including the ability to create
    structured documents, such as articles, books, and slides.
    AsciiDoc's syntax is intuitive and easy to learn, while providing
    advanced capabilities like tables, lists, code blocks, and cross-references.

    Additionally, AsciiDoc content can be converted to various output formats,
    including HTML, PDF, and DocBook, making it highly versatile for
    technical documentation and publishing workflows."
Bootstrap:
  short: "A popular front-end framework for building responsive, mobile-first websites using CSS and JavaScript components."
CSS:
  long: | # literal block - newlines are preserved.
    Cascading Style Sheets (CSS) is a stylesheet language used to describe the presentation
    of a web page, including its layout, colors, fonts, and other design elements.
    CSS allows developers to separate content from design, enabling better
    maintainability and consistency across multiple pages.
    It provides powerful tools for responsive design, enabling web pages to
    adapt seamlessly to different screen sizes and devices.
    By utilizing selectors and rules, CSS can target specific elements of a page
    to apply styles, making it a core technology of modern web development.

    Example CSS

    [source,css]
    ----
    /* Basic CSS example for styling a web page */
    body {
      font-family: Arial, sans-serif;
      background-color: #f4f4f4;
      margin: 0;
      padding: 0;
    }

    h1 {
      color: #333;
      text-align: center;
    }

    p {
      line-height: 1.6;
      color: #666;
    }
    ----

    This snippet demonstrates how CSS is used to style a webpage, including defining fonts,
    background color, margins, and text styles for headers and paragraphs.
  short: "Cascading Style Sheets, a language used for describing the presentation of a web page, including layout, colors, and fonts."
Be aware that the tags are case-sensitive!

To check if you haven’t created a description for a tag, you can simply create a style for the class no-tag-description in the _sass/user.scss file. I use, for example:

.no-tag-description {
	background-color: lightcoral;
	border-radius: 999px;
	padding: .01em .35em;
	color: white;
}

Dockerfile

This repository includes a Dockerfile that defines a custom Docker image, built and stored in the GitLab Docker registry during the CI/CD process. This image provides an optimized environment for building your Jekyll site with all necessary tools pre-installed, including:

  • An SSH client, enabling deployment to your own server

  • Dependency managers like Yarn, for handling JavaScript and CSS dependencies

  • Tools for generating graphics from text-based diagrams, such as Graphviz, Ditaa, and PlantUML

If you are using GitLab CI/CD, you can easily leverage this pre-built image by adding the following image: line to your .gitlab-ci.yml file:

# Use the pre-built Docker image provided by 'jekyll-theme-endless'
image: "registry.gitlab.com/jekyll-theme-endless/jekyll-theme-endless.gitlab.io:latest"

By using this Docker image, you avoid the need to install each required tool individually in a separate base image (such as ruby:latest) during every build process. This approach not only simplifies your CI/CD configuration but also reduces build times, as all necessary dependencies are already bundled into a single, reusable image.

Settings

Language

The language of the content can be set using page.lang which overrides site.lang. The default is en.

  • use e.g. :page-lang: en in AsciiDoc page attributes

  • use e.g. lang: en in Jekyll front matter

  • use e.g. lang: en in _config.yml

Contributing

Bug reports and pull requests are welcome on GitLab at https://gitlab.com/jekyll-theme-endless/jekyll-theme-endless.gitlab.io. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

Development

To set up your environment to develop this theme:

  1. clone this repository

  2. run bundle install

The theme is setup just like a normal Jekyll site! To test the theme, run bundle exec jekyll serve and open your browser at http://localhost:4000. This starts a Jekyll server using your theme. To test the theme with example-data, run:

bundle exec jekyll serve --config _config.yml,_data.yml

If you want additional debug output, simply set the log-level to debug:

JEKYLL_LOG_LEVEL=debug bundle exec jekyll serve --config _config.yml,_data.yml

Values for theme specific configurations are stored in _data.yml and not in the themes _config.yml. Since the _config.yml is shipped with the gem, the users of your theme would otherwise have to unset the values in their own config.yml.

Add pages, documents, data, etc. like normal to test your theme’s contents. As you make modifications to your theme and to your content, your site will regenerate and you should see the changes in the browser after a refresh, just like normal.

When your theme is released, only the files in _layouts, _includes, _sass and assets tracked with Git will be bundled. To add a custom directory to your theme-gem, please edit the regexp in jekyll-theme-endless.gemspec accordingly.

License

The theme is available as open source under the terms of the MIT License.