gem "jekyll-theme-endless"
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
:
In your Jekyll site’s _config.yml
:
-
activate the theme
-
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:
-
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 <
instead of <
).
Example posts and pages
The project repository contains
-
Two example posts with examples and explanations on which front matter variables you can use in posts and pages, and how to use them.
-
Two example pages (the showrooms) where you can explore the features of Markdown and AsciiDoc. In the source code, you can see how to implement these yourself.
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
andsubtitle
are not escaped by the layout. Thus, you can use HTML-commands.brand: '"<i>endless</i>"-Theme'
Contains a configurable title bar. Set
title
andsubtitle
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 thepage-
-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 topage
orpost
.= 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 layoutpage-postlist
is defined in a downstream layout likepage-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 ofpage-tag-template.html
into yourpage-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 thepage-
-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 topage
orpost
.= 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 formain.css
. This allows you to add libraries and modify settings inmain.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 formenu_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 namedtags/<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 thematch
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:
-
clone this repository
-
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.