Trefoil documentation

Miguel A. Gabriel - magabriel@gmail.com

About this edition

Trefoil documentation

Author:

  Miguel A. Gabriel - magabriel@gmail.com

Version 2019.1.915 - 202112111841


ALL RIGHTS RESERVED. This book contains material protected under International and Federal Copyright Laws and Treaties. Any unauthorized reprint or use of this material is prohibited. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage and retrieval system without express written permission from the author and/or publisher.


Introduction

This is the documentation of trefoil, a project conceived as an extension to easybook (https://easycorp.io/EasyBook).

trefoil extends easybook to provide additional features for publication of ebooks, both fiction and non-fiction.

Note

This documentation is a trefoil book itself, intended to be published into one of the supported formats.

To create the documentation, go to the directory where trefoil is installed and run one of the following commands:

To get the epub version:

book publish trefoil-doc ebook

To get the kindle version (please ensure you have the kindlegen application installed):

book publish trefoil-doc kindle

To get the pdf version:

book publish trefoil-doc print

To get the doc-website version:

book publish trefoil-doc doc-website

Other formats may be supported, so look at <trefoil-dir>/doc/trefoil-doc/config.yml to see all the options available.

License

Application Code

Copyright (c) 2014 Miguel Angel Gabriel magabriel@gmail.com


Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Libraries and packages used

See their own license files in vendor/ directory

Resources used

See their own license files in app/Resources/ directory

Part 1 About Trefoil

The whats, whys and hows of trefoil.

Chapter 1 About this project

This project aims to provide a great tool for creating ebooks. It does that by extending the already superb easybook (https://easycorp.io/EasyBook) to provide additional features specifically targeted towards generation of ebooks.

1.1 Installing

1.- Clone the trefoil repository:

mkdir trefoil
git clone http://github.com/magabriel/trefoil trefoil/

2.- Download the vendors and dependencies:

cd trefoil/
php composer.phar install

1.2 Usage

TIP

You should really be familiar with the easybook documentation https://easycorp.io/EasyBook to understand what’s going on here ;)

The basic usage is the same as easybook:

book publish my-book-slug my-edition

trefoil adds a new optional argument --themes_dir that allows using custom themes stored in whatever location in the file system:

book publish my-book-slug my-edition --themes_dir=../my/themes/directory

Example:

book publish the-origin-of-species ebook --themes_dir=~/themes/trefoil

1.3 Extending Easybook

If you are reading this, it is assumed that you are familiar with easybook documentation. If you are not, please go to http://easybook-project.org and read it. You can even install a test version of easybook and play with it a little to gain first-hand knowledge of its capabilities. When you are done with it you should return to this document and continue reading.

NOTICE

trefoil is not a fork of easybook but an extension.

1.3.1 Compatibility

trefoil has been developed as an extension of easybook, so it is fully backwards compatible with easybook. That means that any book prepared to be published by easybook should publish under trefoil without alterations.

1.3.2 Motivation

easybook is a wonderful project that really eases auto-publishing work, making possible to get professional results with limited knowledge or resources. But it is primarily focused on the technical writer, lacking some features needed by non-technical works, both fiction and non-fiction. While these features could of course be implemented into easybook itself, the extension approach was chosen because of the progressive nature of the development (the features were being developed as needed, during preparation of a real book that was eventually published to Amazon Kindle Store). As such, it would have been highĺy impractical trying to influence easybook project to go the way we needed (and cope with the numerous mistakes that were made all over the road).

Looking at the final result, it becomes evident that some features could (or even may or should) be integrated into easybook. As on any other open source project, only time will tell.

Part 2 Trefoil plugins

The biggest part of trefoil functionality is implemented into the included plugins.

Chapter 2 Plugin system enhancements

Plugins are the core of easybook extensibilty. But considerably more flexibility was needed in order to allow implementation of all the needed functionality, so the first task was to extend the plugins system.

The first things to be enhanced were:

  • There are no way of reusing user-created plugins other than copying the code from one book to another.

  • Plugins are not namespaced, precluding autoloading and extensibility.

2.1 Namespaces for plugins

All of trefoil plugins are namespaced. The optional plugins (more on that later) are under the namespace (you guess) Trefoil\Plugins\Optional.

So a typical plugin now looks like:

<?php
// trefoil\src\Trefoil\Plugins\Optional\AwesomePlugin.php
namespace Trefoil\Plugins\Optional;
 
use ...;
 
class AwesomePlugin extends BasePlugin implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        //....
    }
 
    //...
}

BasePlugin is a base class that provides some utility methods and properties to plugins:

<?php
// trefoil\src\Trefoil\Plugins\BasePlugin.php
namespace Trefoil\Plugins;
 
use Trefoil\Util\Toolkit;
use Easybook\Events\BaseEvent;
 
/**
 * Base class for all plugins
 *
 */
abstract class BasePlugin
{
    protected $app;
    protected $output;
    protected $edition;
    protected $format;
    protected $theme;
    protected $item;
 
    /**
     * Do some initialization tasks.
     * Must be called explicitly for each plugin at the begining
     * of each event handler method.
     *
     * @param BaseEvent $event
     */
    public function init(BaseEvent $event)
    {
        $this->event = $event;
        $this->app = $event->app;
        $this->output = $this->app->get('console.output');
        $this->edition = $this->app['publishing.edition'];
        $this->format = Toolkit::getCurrentFormat($this->app);
        $this->theme = ucfirst($this->app->edition('theme'));
        $this->item = $event->getItem();
    }
 
    //... more methods
 
}

The init() method defines a bunch of useful properties to make them available for the plugins.

2.2 Selectively enabling optional plugins

trefoil introduces the concept of optional plugins: each book’s edition can enable only certain plugins (easybook standard plugins, on the other hand, are always enabled).

book:
    ....
    editions:
        <edition-name>
            plugins:
                enabled: [ plugin1, plugin2, ...]
                options:
                    ...

enabled is a list of all the enabled plugins without the Plugin suffix, so if you wanted to enable plugins DropCapsPlugin and TableExtraPlugin for edition ebook you would write:

book:
    ....
    editions:
        ebook:
            plugins:
                enabled: [ DropCaps, TableExtra ]

Chapter 3 The Trefoil book formatting plugins

This chapter describes the book formatting plugins. These plugins provide functionalities to enhance the book’s appearance or to ease applying advanced formatting.

3.1 DropCapsPlugin

This plugin handles adding drop caps to the book, either automatically or manually.

3.1.1 Availability

This plugin is available for all editions.

3.1.2 Usage

# <book-dir>/config.yml 
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ DropCaps ]
                options:
                    DropCaps:
                        levels:     [1]           
                        mode:       letter        
                        length:     1             
                        elements:   ['chapter']

where the options are:

  • levels: The heading levels to add drop caps after. Values 1 to 6 (default: 1).
  • mode: Values letter or word (default: letter).
  • length: Number of letters or words to turn into drop caps (default: 1).
  • elements: Array of book elements to process (default: [‘chapter’]).

3.1.3 Description

There are several ways to add drop caps to the book:

  1. Automatic drop caps.
  2. Manual drop caps HTML markup.
  3. Markdown-like manual drop caps.

3.1.3.1 Automatic drop caps

Drop caps can be automatically added to the first paragraph after a heading. This behaviour can be influenced on a per-edition base setting options in the plugins configuration section inside the book’s config.yml.

Note

This book has automatic drop caps applied with the default options.

3.1.3.2 Manual drop caps HTML markup

HTML can be freely mixed into Markdown. So a way to manually add drop caps to the text is:

<span class="dropcaps">T</span>his is a paragraph that starts with a manually-added drop cap.

trefoil will produce the following HTML code that can be easily styled:

<p class="has-dropcaps"><span class="dropcaps">T</span>his is a paragraph that starts with a manually-added drop cap.</p>

3.1.3.3 Markdown-like manual drop caps

Besides adding the HTML markup directly, a Markdown-like markup is provided for greater convenience.

[[T]]his text has first-letter drop caps.
 
[[But]] this text has first-word drop caps.

will produce the following HTML:

<p class="has-dropcaps"><span class="dropcaps">T</span>his text has first-letter drop caps.</p>
<p class="has-dropcaps"><span class="dropcaps">But</span> this text has first-word drop caps.</p>

and will be shown in the book as (with some dummy text added):

This text has first-letter drop caps. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumyeirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diamvoluptua.

But this text has first-word drop caps. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumyeirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diamvoluptua.

3.2 FootnotesExtraPlugin (deprecated)

This plugin processes footnotes generated by the Markdown parser and transform them into endnotes (i.e. at the end of the book).

3.2.1 Availability

This plugin is available for all editions.

Deprecated

This plugin is deprecated. Use FootnotesExtendPlugin instead

3.2.2 Usage

# <book-dir>/config.yml 
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ FootnotesExtra ]

3.2.3 Description

The Markdown parser converts footnotes into hyperlinks, where the link target is the note text at the bottom of the document.

While this behavior is adequate for printed books, ebooks are a different mattter. The “footnotes at the end of the chapter” approach does not work well for electronic reading devices or applications because the notes stand in the way of the normal reading flow.

This plugin collects all footnotes markup generated by the Markdown parser (at the end of each book element) and then generates a consolidated footnotes list element with all the book’s footnotes.

Note

As this plugin is deprecated, it is not active for this book. Use FootnotesExtendPlugin instead.

The plugin will generate a report in the output directory called report-FootnotesPlugin.txt with a summary of terms processed and problems found.

3.3 FootnotesExtendPlugin

This plugin extends footnotes to support several formats.

3.3.1 Availability

This plugin is available for all editions.

3.3.2 Usage

# <book-dir>/config.yml 
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ FootnotesExtend ]       
                options:
                    FootnotesExtend:
                        type: end  # (end, inject, item, inline)

where the options are:

  • type: Type of footnotes to render.

    • end: Normal Markdown-rendered footnotes.
    • inject: Inject footnotes in text.
    • item: Use a separated footnotes book item.
    • inline: Use inline footnotes (i.e. for PrinceXML).

3.3.3 Description

A footnote is a short clarification text wich is associated to a certain position in the main text but without interrupting the normal reading flow.

The footnote text will be shown in another part of the text (normally the page footer, hence its name) but it could also be shown at the end of the chapter or even the end of the book.

3.3.3.1 Footnotes in Markdown

A footnote can be created in Markdown by inserting [^note1] at the desired text position, where note1 is just a key1 which will not be shown to the user and that it is only used to associate the footnote to its text.

The footnote’s text can be defined2 with a paragraph containing:

[^note1]: This the footnote's text.

which can be placed anywhere in the same document.

The Markdown parser converts footnotes into hyperlinks, where the link target is the note text at the bottom of the document (for easybook and trefoil books that means the end of the edition item). The user can “click” in the footnote and the footnote will be show. The user needs to “click” in another link to return to the footnote’s position and continue reading.

3.3.3.2 The problem to solve

While the default Markdown parser’s footnotes implementation could be adequate in certain situations, several problems arise specific to the edition format being produced:

  • For ebooks (epub and mobi formats), the “footnotes at the end of the chapter” approach does not work well because, in electronic reading devices or applications, the notes stand in the way of the normal reading flow.

  • For PDF books (which normally will be printed), it would be desirable being able to use the traditional footnotes’ rendering, while each footnote appears at the bottom of the page where it is referred. This type of rendering is called “inline footnotes” and is supported by PrinceXML rendering tool.

3.3.3.3 The solution

This plugin provides a comprehensive solution to these problems by defining four types of footnotes:

  • end: This is the normal Markdown-rendered footnotes. They will be rendered at the end of each book item, separated by an <hr/> tag. This is the default.

  • inject: This is a variant of type end, where each item’s footnotes will be injected at a certain injection point inside the item itself. Just write <div class="footnotes"></div> at the point where where the footnotes should be injected.

  • item: All the footnotes in the book will be collected and rendered in a separated item called ‘footnotes’ that need to exist in the book.

  • inline: PrinceXML supports inline footnotes, where the full text of the note must be inlined into the text, instead of just a reference. PrinceXML will manage the numbering.

3.3.3.4 About PrinceXML inline footnotes

PrinceXML natively manages footnotes as:

some text<span class="fn">Text of the footnote</span> more text

This plugin will take care of the rendering, but one limitation is that the footnote text cannot contain block elements (as paragraphs, tables, lists). The plugin overcomes this partially by replacing paragraph tags with <br/> tags.

3.3.3.5 Examples

Tip

You can see an example of footnotes in this section (look at the source text).

3.4 HtmlTweaksPlugin

This plugin provides a way to tweak the book HTML after it has been generated. It works modifying the HTML code produced by the Markdown processor or by the theme templates, so the final HTML code can meet specific requirements.

3.4.1 Availability

This plugin is available for all editions.

3.4.2 Usage

# <book-dir>/config.yml
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ HtmlTweaks ]

The actual tweaks definitions are read from a separate yaml file:

# <book-dir>/Contents/html-tweaks.yml
#  or
# <current-theme>/<format>/Config/html-tweaks.yml
#  or
# <current-theme>/Common/Config/html-tweaks.yml
tweaks:
    # replacements to be made at onPreParse time
    onPreParse:
        tweak-name-free:                 # just a name
            tag: 'tag name'              # tag name to find
            class: 'class-name'          # OPTIONAL class name of tag
 
            # either one of 'insert', 'surround' or 'replace' operations
 
            insert:    # insert HTML code inside the tag (surround content)
                open:  'some html text'  # opening text
                close: 'more html text'  # closing text
 
            surround:  # surround tag with HTML code (surround the tag)
                open:  'some html text'  # opening text
                close: 'more html text'  # closing text
 
            replace:   # replace tag with another one
                tag:  'another html tag' # replacement tag
 
    # replacements to be made at onPostParse time
    onPostParse:        
        another-tweak-name:
            tag: 'tag name'
            # same options than onPreParse
            # ...

3.4.3 Description

The Markdown processor generates fixed HTML structures for each Markdown tag that cannot be configured or parameterized. In occasisons could be desireable to customize the generated HTML to meet certain requierements.

Examples:

  • Surround all <pre>...</pre> tags with <div class="box">...</div>.
  • Append <hr> tag to each <h2> tag.

Instead of having to write a dedicated plugin for that task, this plugin provides the funcionality to resolve some simple cases.

Note

This plugin uses a separate configuration file html-tweaks.yml to provide the tweaks’ definitions. This file can be loaded from the theme in use or from the book contents directory.

3.4.3.1 The configuration file

The tweaks’ definitions are read from file html-tweaks.yml, that can be located:

  • In the book /Contents directory
  • In the theme /<format>/Config directory
  • In the theme /Common/Config directory

The first one found will be used. This allows distributing the tweaks as part of the theme, or customizing them for an specific book.

The onPreParse tweaks will be made before the Markdown parser has processed the item (so they can easyly pick any raw HTML embedded into the Markdown text), while the onPostParse tweaks will work on the HTML produced by the Markdown processor.

3.4.3.2 Example

# <book-dir>/Contents/html-tweaks.yml
#  or
# <current-theme>/<format>/Config/html-tweaks.yml
#  or
# <current-theme>/Common/Config/html-tweaks.yml
tweaks:
    onPreParse:
        # enclose contents of all divs of class "one" with box1
        tweak-div-one:                                 
            tag: 'div'
            class: 'one'   
            insert:
                open:  '<div class="box1" markdown="1">'
                close: '</div>'
 
        # surround all divs of class "two" with box2
        tweak-div-two:                                 
            tag: 'div'
            class: 'two'   
            surround: 
                open:  '<div class="box2">'
                close: '</div>'
 
        # replace all spans with divs
        tweak-span-three: 
            tag: 'span'
            replace: 
                tag:  'div'                  
 
    onPostParse:
        # enclose contents of 'pre' tags between lines
        tweak-pre:                                 
            tag: 'pre'   
            insert:
                open:  '======\n'
                close: '\n------'
 
        # surround tables with box1
        tweak-table:
            tag: 'table'
            surround: 
                open:  '<div class="box1">'
                close: '</div>'
 
        # convert all unordered lists into ordered lists
        tweak-ul:
            tag: 'ul'
            replace: 
                tag:  'ol'

3.5 Illustrations Plugin

This plugin will manage the illustrations in the book.

An illustration is a delimited block which can be styled and automatically numbered.

Note

When enabled, this plugin will take over the normal “tables” numbering and listing of easybook. If a table is needed as an illustration it will need to be done with this new markup. Ordinary tables (outside an illustration markup) will be ignored and just parsed as Markdown tables, not easybook tables

3.5.1 Availability

This plugin is available for all editions.

3.5.2 Usage

# <book-dir>/config.yml 
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ Illustrations ]

3.5.3 Description

Out of the box, easybook provides the functionality to automatically number figures (images) and tables (real Markdown tables). But sometimes it would be preferrable to use some text as a figure (instead of an image) or to mix a table with some text (as a caption, for example). This plugin provides such functionality with a simple syntax:

{@ ======== illustration_begin("This is the illustration caption" ".optional-class") @}
. . . whatever Markdown or HTML content
{@ ======== illustration_end() @}

where illustration_begin() and illustration_end() are trefoil markers.

The .optional-classis one or several CSS classes to be applied to style the illustration.

What are Trefoil markers?

Trefoil markers are a kind of function call wich produces HTML code to be processed later. They are similar to Twig function calls but are enclosed between {@ ... @} delimiters. The “======” series between the opening {@ and the function name is an optional delimiter to help visually identifiying the block in the text.

Old syntax (deprecated)

<< ========= "This is the illustration caption" ========= {.optional-class}
. . . whatever Markdown or HTML content
<</ =================

ATX-style headers can be used inside the illustration content and will not be parsed by easybook (i.e. not added labels and ignored in the TOC).

The rendering of illustrations can be customized with the illustration.twig template, but the plugin will apply a default rendering if the template is not present.

3.5.4 Example

{@ ======== illustration_begin("A list as an illustration", ".class1 .class2") @}
 
This is a list:
 
- One.
- Two.
- Three.
 
{@ ======== illustration_end() @}
 
{@ ======== illustration_begin("A table as an illustration", ".class1 .class2") @}
 
This is a table:
 
| Header 1  | Header 2  
| --------- | ----------
| One       | One text.
| Two       | Two text.
 
{@ ======== illustration_end() @}

Will be rendered as:

Illustration 3.1 - A list as an illustration


This is a list:

  • One.
  • Two.
  • Three.

Illustration 3.2 - A table as an illustration


This is a table:

Header 1Header 2
OneOne text.
TwoTwo text.

3.6 ImageExtraPlugin

This plugin provides an extended image syntax to allow more precise styling of images.

3.6.1 Availability

This plugin is available for all editions.

3.6.2 Usage

# <book-dir>/config.yml
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ ImageExtra ]

3.6.3 Description

Features:

  • Explicit image path.
  • Extended image syntax.
  • Extended styles in themes.

3.6.3.1 Explicit image path

Some Markdown editors provide a live preview of the rendered HTML result. Some of them even provide live preview for images (like the fabulous MdCharm), but for this to work the image path must point to the relative location of the image:

# This is the easybook way,
# but the preview won't work:
![This is image 1](image1.jpeg)
 
# You can write it this way,
# an the preview will work:
![This is image 1](images/image1.jpeg)

Both ways will render exactly the same, but only the second one will produce a preview in editors like MdCharm.

3.6.3.2 Extended image syntax

trefoil extends the Markdown syntax for images providing a class and style arguments with similar syntax than the HTML counterparts.

  • class: You can provide one or several classes to be applied to the image markup.
  • style: You can even apply any CSS style specification.
Tip

The included trefoil templates are ready to make use the extended markup. The standard easybook templates, on the other hand, are not.

![caption](image.name?class="myclass"&style="any_css_style_specification")

Example:

![Lorem ipsum](php.jpg?class="half my-class"&style="background: #cde; padding-right: 2em;")
Note

Standard easybook image alignment syntax still works:

![ Left aligned](php.jpg?class="narrower")

3.6.3.3 Extended styles in themes

trefoil themes come with some predefined image classes:

  • narrower: 1/4 of the page width (up to 4 images side by side).
  • narrow: 1/3 of the page width (up to 3 images side by side).
  • half: 1/2 of the page width (up to 2 images side by side).
  • wide: full page width.

3.6.3.4 Examples

3.6.3.4.1 Narrower right
Lorem ipsum 1

Figure 3.1 Lorem ipsum 1

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sit amet velit a libero congue molestie. Integer ipsum massa, posuere nec massa eu, dapibus volutpat justo. Nullam enim dolor, scelerisque non dui et, ornare ultricies enim. Mauris sed felis sem. Praesent aliquam quam nec diam mollis ultrices. Nunc mattis pretium tellus, et luctus augue commodo sed. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut orci tortor, malesuada ac mauris sit amet, ornare sollicitudin massa.

3.6.3.4.2 Narrower 4 in a row
Lorem ipsum 2

Figure 3.2 Lorem ipsum 2

Lorem ipsum 3

Figure 3.3 Lorem ipsum 3

Lorem ipsum 4

Figure 3.4 Lorem ipsum 4

Lorem ipsum 5

Figure 3.5 Lorem ipsum 5

3.6.3.4.3 Narrower centered
Lorem ipsum 6

Figure 3.6 Lorem ipsum 6

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sit amet velit a libero congue molestie. Integer ipsum massa, posuere nec massa eu, dapibus volutpat justo. Nullam enim dolor, scelerisque non dui et, ornare ultricies enim. Mauris sed felis sem. Praesent aliquam quam nec diam mollis ultrices. Nunc mattis pretium tellus, et luctus augue commodo sed. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut orci tortor, malesuada ac mauris sit amet, ornare sollicitudin massa.

3.6.3.4.4 Narrow right
Lorem ipsum 7

Figure 3.7 Lorem ipsum 7

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sit amet velit a libero congue molestie. Integer ipsum massa, posuere nec massa eu, dapibus volutpat justo. Nullam enim dolor, scelerisque non dui et, ornare ultricies enim. Mauris sed felis sem. Praesent aliquam quam nec diam mollis ultrices. Nunc mattis pretium tellus, et luctus augue commodo sed. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut orci tortor, malesuada ac mauris sit amet, ornare sollicitudin massa.

3.6.3.4.5 Narrow 3 in a row
Lorem ipsum 8

Figure 3.8 Lorem ipsum 8

Lorem ipsum 9

Figure 3.9 Lorem ipsum 9

Lorem ipsum 10

Figure 3.10 Lorem ipsum 10

3.6.3.4.6 Narrow centered
Lorem ipsum 11

Figure 3.11 Lorem ipsum 11

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sit amet velit a libero congue molestie. Integer ipsum massa, posuere nec massa eu, dapibus volutpat justo. Nullam enim dolor, scelerisque non dui et, ornare ultricies enim. Mauris sed felis sem. Praesent aliquam quam nec diam mollis ultrices. Nunc mattis pretium tellus, et luctus augue commodo sed. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut orci tortor, malesuada ac mauris sit amet, ornare sollicitudin massa.

3.6.3.4.7 Half left
Lorem ipsum 12

Figure 3.12 Lorem ipsum 12

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sit amet velit a libero congue molestie. Integer ipsum massa, posuere nec massa eu, dapibus volutpat justo. Nullam enim dolor, scelerisque non dui et, ornare ultricies enim. Mauris sed felis sem. Praesent aliquam quam nec diam mollis ultrices. Nunc mattis pretium tellus, et luctus augue commodo sed. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut orci tortor, malesuada ac mauris sit amet, ornare sollicitudin massa.

3.6.3.4.8 Half 2 in a row
Lorem ipsum 13

Figure 3.13 Lorem ipsum 13

Lorem ipsum 14

Figure 3.14 Lorem ipsum 14

3.6.3.4.9 Half centered
Lorem ipsum 15

Figure 3.15 Lorem ipsum 15

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sit amet velit a libero congue molestie. Integer ipsum massa, posuere nec massa eu, dapibus volutpat justo. Nullam enim dolor, scelerisque non dui et, ornare ultricies enim. Mauris sed felis sem. Praesent aliquam quam nec diam mollis ultrices. Nunc mattis pretium tellus, et luctus augue commodo sed. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut orci tortor, malesuada ac mauris sit amet, ornare sollicitudin massa.

3.6.3.4.10 Wide
Lorem ipsum 16

Figure 3.16 Lorem ipsum 16

3.6.3.4.11 Class and style
Lorem ipsum 17

Figure 3.17 Lorem ipsum 17

3.7 KindleTweaksPlugin

This plugin provides several tweaks to make the ebook more compatible with Kindle MOBI format.

This is only needed for the old MOBI format, not the new KF8 format, so if you are not targeting old Kindle devices you may not need this plugin.

3.7.1 Availability

This plugin is available for Epub and Mobi editions.

Note

The provided tweaks are specificaly targeted to Kindle readers, but could also be useful for some EPUB reader devices or applications. That is the reason why the plugin is available also for Epub editions.

3.7.2 Usage

# <book-dir>/config.yml
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ KindleTweaks ]

3.7.3 Description

The plugin provides the following tweaks:

  • Convert paragraphs inside list elements to line breaks.
  • Explicit table cell alignment.

3.7.3.1 Convert paragraphs inside lists

The Markdown processor allows two kinds of markup to generate a list:

A list without blank lines between elements:
 
- One.
- Two.
- Three.
 
The same list but element "Two" has a second line:
 
- One.
- Two.
 
  This is second line of "Two" element.
 
- Three.

The generated HTML will look like:

<p>A list without blank lines between elements:</p>
 
<ul>
<li>One.</li>
<li>Two.</li>
<li>Three.</li>
</ul>
 
<p>The same list but element "Two" has a second line:</p>
 
<ul>
<li>One.</li>
<li><p>Two.</p>
 
<p>This is second line of "Two" element.</p></li>
<li><p>Three.</p></li>
</ul>

In the second list, elements “One” and “Three” are still rendered “as is”, but element “Two” has paragraph tags enclosing each “paragraph”. This could cause rendering issues with older Kindles, making element “Two” look different than elements “One” and “Three”.

When this plugin is activated all elements will be rendered without the extra paragraph tags, and all internal paragraph tags will be replaced by a line break tag:

<p>The same list but element "Two" has a second line:</p>
 
<ul>
<li>One.</li>
<li>Two.<br/>
 
This is second line of "Two" element.</li>
<li>Three.</li>
</ul>

3.7.3.2 Explicit table cell alignment

Table cell alignment assigned via CSS classes doesn’t work in older Kindles. This plugin will assign explicit alignment via HTML attributes to the table cells.

3.8 LiteralLists Plugin

This plugin adds support for literal lists, a kind of ordered lists where the list elements can be some literals instead of numbers.

3.8.1 Availability

This plugin is available for all editions.

3.8.2 Usage

# <book-dir>/config.yml 
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ LiteralLists ]

3.8.3 Description

A literal list is an ordered list using literals other than numbers.

The list literal can be one of the following:

  • “a)”, “b)”… (a letter followed by a closing parenthesis)
  • “I)”, “II)”…(a latin numeral followed by a closing parenthesis)
  • “1º”, “2º”… (a number followed by the masculine sign)
  • “1ª”, “2ª”… (a number followed by the feminine sign)

The plugin detects the list by the type of starting literal of the first item in an unordered list, and adds the class “list-literal” to the `

<

ul>’ tag to alow styling.

At the HTML level, the following input:

<ul>
    <li>a) First item.</li>
    ...
    <li>x) Last item.</>
</ul>

Is transformed into the following output which can be CSS styled to look like a real list with a)...n) literals.

<ul class="list-literal">
    <li>a) First item.</li>
    ...
    <li>x) Last item.</>
</ul>

3.8.4 Example

Type a)

- a) The first item.
- b) The second item.
- c) The third item.

Will be rendered as:

  • a) The first item.
  • b) The second item.
  • c) The third item.

Type I)

- I) The first item.
- II) The second item.
- II) The third item.

Will be rendered as:

  • I) The first item.
  • II) The second item.
  • III) The third item.

Type 1º

- 1º The first item.
- 2º The second item.
- 3º The third item.

Will be rendered as:

  • The first item.
  • The second item.
  • The third item.

Type 1ª

- 1ª The first item.
- 2ª The second item.
- 3ª The third item.

Will be rendered as:

  • The first item.
  • The second item.
  • The third item.

3.9 ManualTitleLabelsPlugin

This plugin allows adding manual title labels to book items.

3.9.1 Availability

This plugin is available for all editions.

3.9.2 Usage

# <book-dir>/config.yml 
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ ManualTitleLabels ]

3.9.3 Description

Item labels are rendered with different markup than the title, creating a nice effect, like Chapter 1 - The first chapter title (where Chapter 1 is the label while The first chapter title is the title).

Automatic labels can be added to item titles by easybook using its labeling mechanism, but sometimes it could be useful having a way to manually specify labels using markup in the source file.

This plugin provides simple markup to achieve just this, just enclosing the label part in [[..]].

Example:

# [[Chapter 1]] The first chapter title

3.10 TableExtraPlugin

This plugin provides extra functionality to Markdown tables:

  • Ability to “colspan” or “rowspan” cells.

  • Multiline cells.

  • Automatic header cells for headless tables.

3.10.1 Availability

This plugin is available for all editions.

3.10.2 Usage

# <book-dir>/config.yml
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ TableExtra ]

3.10.3 Description

Markdown syntax for tables is pretty limited:

Column 1  | Column 2  | Column 3
----------|-----------|------------
1.One     | 1.Two     | 1.Three
2.One     | 2.Two     | 2.Three

will render as:

Column 1Column 2Column 3
1.One1.Two1.Three
2.One2.Two2.Three

3.10.3.1 Adding rowspanned cells

A cell containig only " or ' (a double or single quote) will be joined with the above cell in the previous row:

Column 1  | Column 2  | Column 3
----------|-----------|------------
1.One     | 1.Two     | 1.Three
  "       | 2.Two     | 2.Three
1.One     | 1.Two     | 1.Three
  '       | 2.Two     | 2.Three

This will render as:

Column 1Column 2Column 3
1.One1.Two1.Three
2.Two2.Three
1.One top1.Two1.Three
2.Two2.Three

Usin single quote instead of double quote will make the rowspanned cell contents align to the cell top of instead than the middle.

3.10.3.2 Adding colspanned cells

An empty cell will be joined whith the preceding cell in the same row:

Column 1  | Column 2  | Column 3
----------|-----------|------------
1.One                || 1.Three
2.One     | 2.Two     | 2.Three

This will render as:

Column 1Column 2Column 3
1.One1.Three
2.One2.Two2.Three
Tip

To avoid a blank cell to be interpreted as colspanned, enter &nbsp; as its contents, as in the following example.

Column 1Column 2Column 3
1.One 1.Three
2.One2.Two2.Three

3.10.3.3 A more complex example

The following example mixes rowspanned and colspanned cells and makes use of table column alignment syntax:

Column 1  | Column 2  | Column 3
---------:|:----------|:----------:
1.One                || 1.Three
"                    || 2.Three
3.One     | 3.Two     | 3.Three
4.One     | 4.Two     | 4.Three

The rendered result will be:

Column 1Column 2Column 3
1.One1.Three
2.Three
3.One3.Two3.Three
4.One4.Two4.Three

3.10.3.4 Multiline cells

This is a table with multiline cells:

Column 1  | Column 2  | Column 3
----------|-----------|------------
One       | Two       | Tree: +
          |           | - Three            +
          |           | - Three continued  +          
          |           | - Three continued 2
One       | Two       | Three

Which will be rendered as:

Column 1Column 2Column 3
OneTwo

Tree:

  • Three

  • Three continued

  • Three continued 2

OneTwoThree

3.10.3.5 Automatic header cells for headless tables

This is a headless table:

 | | |
----------|-----------|------------
One 1     | Two 1     | Three 1
One 2     | Two 2     | Three 2

Normally rendered as:

One 1Two 1Three 1
One 2Two 2Three 2

By adding strong emphasis to some cells we have:

 | | |
----------|-----------|------------
**One 1** | Two 1     | Three 1
One 2     | Two 2     | Three 2
**One 3** | Two 3     | Three 3
One 1Two 1Three 1
One 2Two 2Three 2
One 3Two 3Three 3

This can lead to interesting effects:

 | | |
----------|-----------|------------
**One 1** | | 
One 2     | Two 2     | Three 2
**One 3** | |
One 4     | Two 4     | Three 4
One 1
One 2Two 2Three 2
One 3
One 4Two 4Three 4

3.11 TabularListsPlugin

This plugin adds support for tabular lists, funcionality, which represents a list that can be alternatively shown as a table without loosing information (and vice versa).

Its intended use is providing an adequate representation of tables in ebooks (where wide tables are not appropriate) while maintaining the table as-is for wider formats like PDF.

3.11.1 Availability

This plugin is available for all editions.

3.11.2 Usage

# <book-dir>/config.yml
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ TabularLists ]

To activate this feature for a certain list, it must be enclosed between the following markup:

{@ ========== tabularlist_begin() @}
 
    ...the markdown list definition
 
{@ ========== tabularlist_end() @}

where tabularlist_begin() and tabularlist_end() are trefoil markers.

What are Trefoil markers?

Trefoil markers are a kind of function call wich produces HTML code to be processed later. They are similar to Twig function calls but are enclosed between {@ ... @} delimiters. The “======” series between the opening {@ and the function name is an optional delimiter to help visually identifiying the block in the text.

3.11.3 Description

Tables are always problematic in ebooks because they do not work well in such a narrow screen (think of a table with 3 or more columns). The clasical solutions are:

  • Convert the table to image. This is often far from ideal and it can also become work-intensive and tedious. On the plus side, the result will also work unmodified in wider editions types, like PDF.

  • Convert the table to a list (“linearize” the table). This will provide better usability in an ebook reader but at the cost of losing readability on wider edition types.

So the problem we want to solve is: How to render a table as a list or a list as a table in such a way that it remains readable both in ebook (or HTML) and PDF editions?

The plugin uses the pragmatic approach of accepting the list version of the table (which works in all formats as is) and providing the transformation to table to meet the requirements of the format being rendered.

The target table looks like that:

CategoryACategoryBAttribute 1Attribute 2
A1B1A1.B1.1.1A1.B1.2.1
B2A1.B2.1.2A1.B2.2.2
A2B3A2.B3.1.3A1.B3.2.3
B4A2.B4.1.4A1.B4.2.4

There are two categories and two attributes for each category. The representation as HTML table uses rowspan and colspan to show the relations.

This can be linearized as:

  • CategoryA: A1
    • CategoryB: B1
      • Attribute 1: A1.B1.1.1
      • Attribute 2: A1.B1.2.1
    • CategoryB: B2
      • Attribute 1: A1.B2.1.2
      • Attribute 2: A1.B2.2.2
  • CategoryA: A2
    • CategoryB: B3
      • Attribute 1: A2.B3.1.3
      • Attribute 2: A2.B3.2.3
    • CategoryB: B4
      • Attribute 1: A2.B4.1.4
      • Attribute 2: A2.B4.2.4

We call the above list a tabularlist, because it is a list which can be tabularized (converted to table) and get the following results:

CategoryACategoryBAttribute 1Attribute 2
A1 B1 A1.B1.1.1A1.B1.2.1
B2 A1.B2.1.2A1.B2.2.2
A2 B3 A2.B3.1.3A2.B3.2.3
B4 A2.B4.1.4A2.B4.2.4

…wich is exactly the target table. But the source for the above rendering is just our input list surrounded with the appropriate markup:

{@ tabularlist_begin() @}
 
- **CategoryA**: A1
    - **CategoryB**: B1
        - **Attribute 1**: A1.B1.1.1
        - **Attribute 2**: A1.B1.2.1
    - **CategoryB**: B2
        - **Attribute 1**: A1.B2.1.2
        - **Attribute 2**: A1.B2.2.2
- **CategoryA**: A2
    - **CategoryB**: B3
        - **Attribute 1**: A2.B3.1.3
        - **Attribute 2**: A2.B3.2.3
    - **CategoryB**: B4
        - **Attribute 1**: A2.B4.1.4
        - **Attribute 2**: A2.B4.2.4
 
{@ tabularlist_end() @}

The above tabularlist is using a default number of columns (by not specifying it). The plugin will infer the number of columns by adding the list deep (the number of nested lists, 3 in the example) to the number of items in the most inner list (2 in the example) minus one. So the default number of columns in the example will be 4.

The tabularlist can also be rendered with any number of columns between 0 and the maximum of 4. This is achieved passing an optional argument to the tabularlist_begin() with a list of pairs of the form {key:value, ... ,key:value}, where each key can be:

  • The name of an edition or format.
  • all to represent all the cases.

And the value is the number of columns to use. Example:

  • {@ tabularlist_begin( {all:2} ) @}: The table is rendered with two columns for all the editions and formats.

  • {@ tabularlist_begin( {ebook:1, pdf:3} ) @}: The table is rendered with 1 column for the ebook editions and three columns for all the editions with pdf format. All other cases are rendered with the default number of columns.

  • {@ tabularlist_begin( {ebook:1, pdf:3, all:2} ) @}: The table is rendered with 1 column for the ebook editions and three columns for all the editions with pdf format. All other cases are rendered with two columns.


Rendering examples:

0 columns:

  • CategoryA: A1
    • CategoryB: B1
      • Attribute 1: A1.B1.1.1
      • Attribute 2: A1.B1.2.1
    • CategoryB: B2
      • Attribute 1: A1.B2.1.2
      • Attribute 2: A1.B2.2.2
  • CategoryA: A2
    • CategoryB: B3
      • Attribute 1: A2.B3.1.3
      • Attribute 2: A2.B3.2.3
    • CategoryB: B4
      • Attribute 1: A2.B4.1.4
      • Attribute 2: A2.B4.2.4

1 column:

CategoryA
A1
  • CategoryB: B1

    • Attribute 1: A1.B1.1.1

    • Attribute 2: A1.B1.2.1

  • CategoryB: B2

    • Attribute 1: A1.B2.1.2

    • Attribute 2: A1.B2.2.2

A2
  • CategoryB: B3

    • Attribute 1: A2.B3.1.3

    • Attribute 2: A2.B3.2.3

  • CategoryB: B4

    • Attribute 1: A2.B4.1.4

    • Attribute 2: A2.B4.2.4

2 columns:

CategoryACategoryB
A1 B1
  • Attribute 1: A1.B1.1.1

  • Attribute 2: A1.B1.2.1

B2
  • Attribute 1: A1.B2.1.2

  • Attribute 2: A1.B2.2.2

A2 B3
  • Attribute 1: A2.B3.1.3

  • Attribute 2: A2.B3.2.3

B4
  • Attribute 1: A2.B4.1.4

  • Attribute 2: A2.B4.2.4

3 columns:

CategoryACategoryBAttribute 1
A1 B1 A1.B1.1.1
A1.B1.2.1
B2 A1.B2.1.2
A1.B2.2.2
A2 B3 A2.B3.1.3
A2.B3.2.3
B4 A2.B4.1.4
A2.B4.2.4

4 columns, same as the default:

CategoryACategoryBAttribute 1Attribute 2
A1 B1 A1.B1.1.1A1.B1.2.1
B2 A1.B2.1.2A1.B2.2.2
A2 B3 A2.B3.1.3A2.B3.2.3
B4 A2.B4.1.4A2.B4.2.4

The plugin tries its best to produce a readable table which is consistent with the input tabularlist.

3.12 TypographyPlugin

This plugin replaces certain symbols with its typographic equivalents. It makes use of the SmartyPants library: http://daringfireball.net/projects/smartypants/

3.12.1 Availability

This plugin is available for all editions.

3.12.2 Usage

# <book-dir>/config.yml 
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ TypographyPlugin ]
                options:
                    Typography:
                        checkboxes: true
                        fix_spanish_style_dialog: false

3.12.3 Description

The following symbols are replaced with its typographic equivalents whenever appropriate:

  • Double quotes ("..") and backtick quotes (``..'') are converted to typograhic double quotes (“..”).
  • Three dots (...) are converted to the ellipsis typographic symbol (…).
  • Two dashes (--) are converted to em-dash (—).
  • Two less-than or greater-than symbols (<< and >>) are converted to angle quotes («..»).

Option checkboxes allows writing a checkbox-like sign, both unchecked and checked.

  • Checkboxes can be writen as [ ] and [/] and will be converted to ☐ and ☑.

Option fix_spanish_style_dialog fixes the usage of dash (‘-‘) instead of em-dash (‘—’) for dialog transcription in Spanish.

Note

The correct way of writing dialogs between characters in Spanish books is using the em-dash symbol (“—”, called “raya” in Spanish) instead of using quotes like the English written dialogs. That is only the more obvious difference, but there are several other typographic conventions and rules that must be followed when writing dialogs in Spanish books.

3.12.3.1 Example of Spanish-style written dialog

The following example is extracted from “The Adventures of Sherlock Holmes: A scandal in Bohemia”:

Original dialog in English:

“Wedlock suits you,” he remarked. “I think, Watson, that you have put on seven and a half pounds since I saw you.”

“Seven!” I answered.

Spanish translation:

—El matrimonio le sienta bien —comentó—. Yo diría, Watson, que ha engordado usted siete libras y media desde la última vez que le vi.

—Siete —respondí.

3.13 TwigExtensionPlugin

This plugin extends Twig to provide some useful functionalities:

3.13.1 Availability

This plugin is available for all editions.

3.13.2 Usage

# <book-dir>/config.yml 
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ TwigExtension ]
                options:
                    TwigExtension: 
                        itemtoc:
                            deep: 2  # defaults to <edition>.toc.deep + 1

3.13.3 Description

The funcionalities provided are:

  • Twig in content.
  • Configuration options in content.
  • Local TOC (table of contents).
  • Include files into content.

3.13.3.1 Twig in content

trefoil adds the ability to write Twig code in content:

{# this is a Twig comment inside a content item #}
**Lorem ipsum** dolor sit amen. 

{% if 1 == 2 %} 
**Awesome,** it seems that 1 equals 2!!!
{% else %}
No, definitely 1 does not equal 2.
{% endif %}

The above piece of text will render as:

Lorem ipsum dolor sit amen.

No, definitely 1 does not equal 2.

But why in the world would you want to mix Twig code or functions with your content? Some complex pieces of content could benefit from having some logic applied (example: using some book configuration option value to hide or show some section). And the ability to mix Twig comments in the text is definitely a good thing (example: to write some TODO note so you remember to change some part of the text in a future revision).

3.13.3.2 Configuration options in content

easybook only allows configuration options in templates but not in content. But thanks to the “Twig in content” functonality now you can do it:

**This will not work without this plugin:**

> The title of this book is "*{{ book.title }}*".

This plugin provides such functionality, allowing the use of any configuration option in the content.

With this plugin activated, it works:

The title of this book is “Trefoil documentation”.

3.13.3.3 Local TOC

Large ebooks with lots of sections and subsections could benefit from having a table of contents at the begining of each chapter (think of a text book, where each lesson is a book chapter).

This plugin provides a Twig function itemtoc() that can be inserted anywhere in the item content (thanks to the “configuration options in content” functionality).

It uses de itemtoc.twig template that must be available either as a local or global template.

Usage:

{{ itemtoc() }}
Note

You can see an example at the begining of each chapter of the epub or kindle editions of this book.

3.13.3.4 Include files into content

Sometimes it could be useful to divide a large chapter into smaller pieces, and then including all the pieces into the chapter’s content.

This plugin provides a fragment() Twig function that works pretty much like PHP’s include()function, allowing the inclusion of another file.

Usage:

{{ fragment(filename, variables, options) }}

where “variables” and “options” are optional hash tables where you can pass variables to the included file as in {'variable': 'value'}, or options that affect the rendering.

The available options are:

  • {'pagebreak': true}: insert a page break after the included file (false by default)
Note

You can see an example in the source text of this chapter. Pagebreaks will only work on Kindle readers and certain epub readers.

Deprecation notice: The former file() function is deprecated. Please use fragment() instead.

Chapter 4 The Trefoil utility plugins

This chapter describes the utility plugins. These plugins provide functionalities that, while not related to the book’s appearance, bring useful and convenient enhancements to the publication workflow.

4.1 EbookRenamePlugin

This plugin copies the generated file book.<ext> to <new-name>.<ext>. The original book.<ext> file can be optionally kept.

4.1.1 Availability

This plugin is available for all editions.

4.1.2 Usage

# <book-dir>/config.yml 
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ EbookRename ]
                options:
                    EbookRename:
                        schema:  '{publishing.book.slug}-{book.version}' 
                        keep_original:  true

4.1.3 Description

The naming schema is derived from Twig syntax but with single curly brackets.

Allowed variables are:

  • publishing.book.slug (the book slug).
  • any book or edition config variable.

4.2 EpubCheckPlugin

This plugin checks the generated epub ebook using the EpubCheck utility. See https://github.com/IDPF/epubcheck for download options and more information.

4.2.1 Availability

This plugin is available for epub editions.

4.2.2 Usage

# <book-dir>/config.yml 
easybook:
    parameters:
        epubcheck.path: '/path/to/epubcheck.jar'
        epubcheck.command_options: ''

book:
    ....
    editions:
        <edition-name>
            plugins:
                enabled: [ EpubCheck ]

4.2.3 Description

EpubCheck is a tool to validate epub files (version 2.0 and later).

To use it, download the relevant .jar file to some directory on your computer and configure that path in the epubcheck.path option of config.yml as shown above. You can also pass some options via the epubcheck.command_options option.

4.2.4 Output

The plugin will generate a report in the output directory called report-EpubCheckPlugin.txt.

4.3 EpubUncompressPlugin

This plugin uncompresses the geneated book.epub file to make it easy looking at its contents.

This can be useful when debugging templates, to make it sure the final HTML inside the EPUB file is correct.

4.3.1 Availability

This plugin is available for epub editions.

4.3.2 Usage

# <book-dir>/config.yml 
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ EpubUncompress ]

4.3.3 Description

The uncompressed contents are left into the same directory where the book.epub file is generated.

4.4 LinkCheckPlugin

This plugin checks all the internal and external links in the book.

4.4.1 Availability

This plugin is available for all editions.

4.4.2 Usage

# <book-dir>/config.yml 
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ LinkCheckPlugin ]
                options:
                    LinkCheck:
                        check_external_links: true

4.4.3 Description

Internal links are checked by looking for a valid link target, i.e. an html element whith id=”the-link-target” in the whole book. This is useful for manually inserted links or anchors in the text (remember that you can freely insert pure HTML into Markdown).

This is valid:

#### My section {anchor-to-my-section}
 
I can link to [my section](#anchor-to-my-section).
 
<div id="other-anchor"></div>
 
Lorem ipsum...
 
And also can link to [other anchor](#other-anchor)

External links are (optionally) checked for existence by performing a network lookup. This behaviour is off by default because could be very time consuming if the book has a large number of external links. To turn it on, set the following option in the book’s `config.yml’ .

4.4.4 Output

The plugin will generate a report in the output directory called report-LinkCheckPlugin.txt.

4.5 QualityControlPlugin

This plugin checks the book for common problems or mistakes.

4.5.1 Availability

This plugin is available for all editions.

4.5.2 Usage

# <book-dir>/config.yml
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ QualityControl ]

4.5.3 Description

The checks performed are:

  • Unused images: Any unused image in the final book can cause problems, like adding extra size to the generated file or even failing a validation (like the EpubCheck utility for epub editions).

  • Emphasis marks not processed: The Markdown makes and excelent work but sometimes it can get confused with some edge cases, leaving emphasis marks slip unprocessed into the final book text.

Consider the following example, where the writer intended to add bold emphasis to word “dolor” but left an extra espace after the word inside the closing “**” (word “sadipscing”, on the other hand, is correctly emphasized):

Lorem ipsum **dolor ** sit amet, consetetur **sadipscing** elitr.

This will be rendered as:

Lorem ipsum dolor ** sit amet, consetetur **sadipscing elitr

Instead of the intended:

Lorem ipsum dolor sit amet, consetetur sadipscing elitr

The plugin will report the problem so it can be easily spotted and fixed.

4.5.4 Output

The plugin will generate a report in the output directory called report-QualityCheckPlugin.txt.

4.6 VersionUpdaterPlugin

This plugin updates an optional version string from config.yml.

The format of the version string must be "<version>.<revision>", where each component is an integer and the separator is a single dot.

4.6.1 Availability

This plugin is available for all editions.

4.6.2 Usage

# <book-dir>/config.yml 
book:
    version: '1.0'  # This is the version string
    editions:
        <edition-name>
            plugins:
                enabled: [ VersionUpdater ]
                options:
                    VersionUpdater:
                        increment_ver: false # don't increment the version (default)
                        increment_rev: true  # increment the revision (default)

4.6.3 Description

Having a version string in book.yml is useful because it can be used in the templates (for example in title.twig) to make it easy to distinguish between two different versions of the book. Also, if you have the TwigExtensionPlugin enabled, you can also use its contents in any content element.

This plugin performs an automatic update of the version string in config.yml so you don’t have to remember incrementing the revision after each time the book is generated.

Note

The version is updated after the book is generated. This way is easy to know the value of the next version of the book just looking into config.yml.

The arguments allow selectively incrementing any of the components.

When the version component is incremented, the revision component is reset to 0.

Tip

You could set a normal ebook edition that only increments the revision component each time you produce a new “work in progress” ebook, and another separate edition ebook-ok to increment the version part each time you want to generate a “ready to publish” ebook. Taking advantage of the editions inheritance make it even more convenient.

Chapter 5 The Trefoil interactive plugins

This chapter describes the interactive plugins. These plugins provide some interactive capabilities to ebooks, making them more appealing for textbooks or technical publications.

5.1 AutoGlossaryPlugin

The auto-glossary plugin handles the generation of a glossary of terms that are automatically hyperlinked to its definitions.

5.1.1 Availability

This plugin is available for all editions.

5.1.2 Usage

# <book-dir>/config.yml
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ AutoGlossary ]
                options:
                    AutoGlossary:
                        pagebreaks: true  # use pagebreaks between defined terms

The terms’ definitions are read from two files:

  • Global glossary: Contains the terms to be replaced into the whole book.
  • Item glossary: Contains the terms to be replaced only into certain book item.

The global glossary definition is called auto-glossary.yml:

# <book-dir>/Contents/auto-glossary.yml
# Global glossary definitions
glossary:
    options: 
        # 'all': all ocurrences
        # 'item': (default) only first ocurrence 
        #         into an item (i.e. chapter)
        # 'first': first ocurrence in the whole book
        coverage: 'item'
 
        # Elements to process (default: "chapter")
        elements: ["chapter"]
 
    ####
    # Global definitions of terms:
    #
    #   "term": Term definition
    #
    # Variants are allowed (singular, plural)
    #
    #   "term[s]": Definition which is applied 
    #              to "term" and "terms"
    #   "term [one|two]": Definition which is 
    #              applied to "term one" and "term two"
    ####
    terms:
        "term": Definition

The glossary definitions for each book item are named after the item it applies to (so the glossary for chapter1.md item should be chapter1-auto-glossary.yml)

# <book-dir>/Contents/chapter1-auto-glossary.yml
# Glossary definitions for chapter 1 
glossary:
    ####
    # Definitions of terms for chapter-1:
    #
    #   "term": Term definition
    #
    # Variants are allowed (singular, plural)
    #
    #   "term[s]": Definition which is applied 
    #              to "term" and "terms"
    #   "term [one|two]": Definition which is 
    #              applied to "term one" and "term two"
    ####
    terms:
        "term": Definition

5.1.3 Description

Depending on the coverage options, each ocurrence (or only the first one) of a defined term is replaced by an hyperlink to its definition.

The glossary term definitions are of the form "term": Term definition, where each “term” can be either a literal expresion or a variant expression:

glossary:
    terms:
        # literal expression
        "Lorem ipsum": Pseudo-latin text used as filler or dummy text.
        # variant expressions 
        "car[s]": Definition which is applied to "car" and "cars"
        "orange [car|truck]": Definition which is applied to "orange car" and "orange truck"

Using variants is possible to create defintitions that cover several cases (like singular and plural of a word or expression).

The global glossary definitions file also have an options section with several values that affect how the glossary terms are processed:

  • glossary.options.coverage defines how many ocurrences of a term will be converted into glossary items links:

    • all: all ocurrences in the book.
    • item: (default) only the first ocurrence inside a content item.
    • first: only the first ocurrence in the whole book.
  • elements is a list of all element types to be processed. By default only chapter items are processed.

Example:

  • This paragraph contains the expressions “example term 1” and “example term 2” that should be converted into glossary terms.
Note

While this autoglossary implementation can potentially work for every edition type, whether it really does work depends mostly on the reader platform capabilities:

  • Epub:: Some readers can follow hyperliks, but most do not.
  • Kindle: The Kindle readers can follow hyperlinks and do page breaks. It works OK.
  • PDF: It depends. The official Adobe Reader is OK, but other implementations may vary.
  • HTML: No problems.

But, as this implementation is mostly focused on ebooks, even if it produces a clickable autoglossary it may not give the best results on a printed edition.

NOTE

The version of the autoglossary in this documentation is not the same than the one you will get for an epub or mobi ebook because of the limited capabilities of the format. Moreover, as this documentation uses Twitter Bootstrap 3, it has some additional differences:

  • The epub or mobi versions are rendered using only HTML.
  • This version uses Javascript to implement the user interactions.

Please generate the epub or mobi versions of this documentation to fully appreciate the differences.

5.1.4 Output

The plugin will generate a report in the output directory called report-AutoGlossaryPlugin.txt with a summary of terms processed and problems found.

5.2 AutoIndexPlugin

The auto-index plugin handles the generation of an index of terms which are automatically hyperlinked to its occurrences in the text. It also allows manual index entries.

5.2.1 Availability

This plugin is available for all editions.

5.2.2 Usage

# <book-dir>/config.yml
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ AutoIndex ]

5.2.3 Description

This plugin replicates the “back of the book index” functionality of written books (an alphabetized, cross-referenced list of meaningful terms which helps the reader finding where in the book a topic is written about).

The index definition file is called auto-index.yml and has the following format.

# <book-dir>/Contents/auto-index.yml
index:
    options: # optional section
         # items where the auto index terms should be applied
         elements: [chapter] # default
 
    # definitions for automatically-added terms
    terms:
        # A simple term definition:
        term: text (optional)
 
        # A complex term definition (group):
        term:
            text: "Term text" (optional)
            terms:
                "subterm 1": "subterm 1 text" (optional)
                # ...
                "subterm n": "subterm n text" (optional)
 
    # definitions for manually-added terms
    manual-terms:
        # A simple term definition:
        term-key-1: text (optional)
 
        #A complex term definition (group):
        group-name:
            text: "Term text for group" (optional)
            terms:
                subterm-key-1: "subterm 1 text" (optional)
                # ...
                subterm-key-n: "subterm n text" (optional)

The index definitions has the following sections:

5.2.3.1 Options

Values that affect how the index terms are processed:

  • elements is a list of all element types to be processed. By default only chapter items are processed.

5.2.3.2 Terms (automatically-marked index entries)

The terms definitions to be included automatically in the index whenever they are found in the book text (contolled by the options.elements value).

5.2.3.2.1 Simple terms

A simple term has the form:

terms:
    term: some text

where term is the word or expression to be indexed if found in the book text, and some text is the optional text to be used in the index entry as a replacement for the term.

Example:

terms:
    JSON:
    yaml: YAML file format
  • Each ocurrence of “JSON” (capitalization does not matter) will be indexed under the “JSON” entry.
  • Each ocurrence of “yaml” will be indexed under the “YAML file format” entry.

Terms can include variants in their definitions, which makes it possible to create index entries that cover several cases (like singular and plural forms of a word or expression).

terms:
    telephone[s]: # "telephone" or "telephones"
    media [file|document]: # "media file" or "media document"
5.2.3.2.2 Complex terms (groups)

A complex term or group has the following form:

terms:
    term:
        text: "Term text" # optional
        terms:
            "subterm 1": "subterm 1 text" # optional
            # ...
            "subterm n": "subterm n text" # optional

Each term groups other subterms which will be indexed as part of the main term.

5.2.3.3 Manual terms (manually-marked index entries)

It is possible to add index entries by marking them explicitly (a.k.a. “the tradditional way”). To achiveve this there are two methods:


Method 1.- Using an index mark

This is a **markdown**|@| text where the previous occurrence of the word 'markdown' is marked for indexing.

The term to index is marked by inserting |@| next to it.

Rules for manual indexing:

  • The index mark |@| must be immediately following the term to index.
  • The term can be:
    • A single word.
    • One or more words delimited by double quotes (“the term”), single qoutes (‘the term’) or emphasis marks (**the term** or _the term_). The mark must be placed outside the closing mark.

Method 2.- Enclosing the term

This is a |markdown text| where the previous occurrence of the words 'markdown text' are marked for indexing.

The term to index is marked by enclosing it between |.

Both methods can potentially render the same results.

Note

If the indexed term exists in the manual-terms section of the auto-index.yml file, its definition will be taken into account when creating the index. If the term does not exist, it will be indexed with default values.

5.2.3.3.1 The manual-terms definition section

The definition file can optionally contain something similar to:

# manual terms definition
manual-terms:
    term1: This is a term
     # A complex term definition (group):
    term2-group:
        text: "Term text for group" (optional)
        terms:
            subterm-key-1: "subterm 1 text" (optional)
            # ...
            subterm-key-n: "subterm n text" (optional)

Example:

The following paragraphs contain example index terms. You can go directly to the index section to check it out, and then click on the term link to return here.

  1. This paragraph contains the expressions “example index term 1” and “example index term 2” which should be automatically converted into index entries.

  2. This paragraph contains “example index term 3” which is manually marked as index term.

  3. This paragraph has example index term 4 which is manually marked as index term. And also, a second time bold marking: the example index term 4.

Note

While this autoindex implementation can potentially work for every edition type, whether it really does work depends mostly on the reader platform capabilities:

  • Epub:: Some readers can follow hyperliks, but most do not.
  • Kindle: The Kindle readers can follow hyperlinks. It works OK.
  • PDF: It depends. The official Adobe Reader is OK, but other implementations may vary.
  • HTML: No problems.

But, as this implementation is mostly focused on ebooks, even if it produces a clickable autoindex it may not give the best results on a printed edition.

5.2.4 Output

The plugin will generate a report in the output directory called report-AutoIndexPlugin.txt with a summary of terms processed and problems found.

5.3 EbookQuizPlugin

The quiz plugin allows adding interactive test functionality to an ebook (mainly for epub or mobi formats, read below note on compatibility).

5.3.1 Availability

This plugin is available for all editions (read below note on compatibility).

5.3.2 Usage

# <book-dir>/config.yml
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ EbookQuiz ]                
                options:
                    EbookQuiz:
                        ynb:
                            yes: [ "Yes", "True" ]
                            no: [ "No", "False" ]
                            both: [ "Both" ]

5.3.3 Description

This plugin allows creating an ebook with some interactive functions, like a question-response test where the user is presented with a set of questions, each one with a number of predefined responses in the form of hyperlinks. The user “cliks” on one response and the “system” tells him if he has selected the right answer.

First of all, lets define the scope of our solution:

5.3.3.1 Target platforms

The solution MUST work on Amazon Kindle readers compatible with the new KF8 format. It MAY also work in another platforms (even with reduced functionality), but the Amazon Kindle readers are the main target.

The problem is that the KF8 format does not allow any kind of interactivity other than plain-old hyperlinks (no javascript or another client-side language), so we need to circumvent the limitation and find another way to do it.

5.3.3.2 Types of tests

A “Quiz” is an interactive test. There are two types of quizes:

  • Multiple questions / single answer, like “A: first response”, “B: second response” and so on. An especial subtype is a “True/False” test, where the only allowed responses are either “True” of “False” (with an optional “Both”). These types will be referred to as “ABC” and “YNB” respectively.

  • Questionnaire, where the user is presented with a series of questions that do not have a predefined set of responses but require elaboration or reasoning. When the user has created its own response he can select an option to “reveal” the right answer.

5.3.3.3 Technical requirements

As the main target is the Amazon Kindle readers that use KF8 format (basically, a subset of EPUB3, more information here: http://wiki.mobileread.com/wiki/KF8) the solution must stick to be just HTML + CSS (without any scripting language).

Another self-imposed constraint is that the solution must respect the Markdown spirit, where the unparsed text is readable by humans. So no extraneous or made-up syntax will be used, only standard Markdown features.

5.3.3.4 Implementation

All types of quizes will be implemented as standard Markdown syntax with a predefined structure. This structure is also easily readable and just “makes sense”, so even if the book doesn’t enable this plugin the resulting ebook will be valid (but without the interactive features, of course).

5.3.3.5 Syntax of a quiz

The different quiz types share a common syntax, with the following remarks:

  • The whole quiz markup is enclosed in an HTML <div> block. This is totally allowed by Markdown and allows the quiz to be parsed effectively by the plugin:

    <div markdown="1" class="quiz-xxxxx" data-id="xxxxx">...</div>

    • The markdown="1" attribute is needed in order for the contents to be processed by the Markdown parser.

    • The class="quiz-xxxxx" tells the plugin parser the quiz type that follows. Allowed values are quiz-activity and quiz-questionnaire. The parser will automatically decide if a “quiz-activity” is of type “ABC” or “YBN” (more on that later).

    • The data-id="xxxxx" attribute assigns an unique id to this quiz.

  • The markup itself has a few optional parts. If not provided they will be left blank in the quiz rendering or assigned sensible defaults.

  • The questions are represented by an ordered list, and the responses with another embedded ordered list. The correct response to each question must be denoted with bold format.

  • Please note that the quiz markup MUST be correctly parsable by Markdown or the plugin will be unable to process it.

  • For the interactive solutions to be rendered, a book element of type “ebook-quiz-solution” must be present at the end of the book.

5.3.3.6 Compatibility notes

  • The generated quizes will only work on Amazon Kindle devices or applications with KF8 capabilities (this includes the Kindle 4 devices onwards).

  • KindleTweaksPlugin interferes with this plugin. Do not enable it if you use this plugin.

5.3.4 Examples

5.3.4.1 ABC-type quiz syntax

<div markdown="1" class="quiz-activity" data-id="quiz-id-1">
##### Activity 1 heading
###### Activity subheading (optional).
 
Activity description (optional). Lorem ipsum dolor sit amet,
consetetur sadipscing elitr, sed diam non umyeirmod.
 
1. First question.
 
    1. **First response.**
    2. Second response.
    3. Third response.
 
2. Second question.
 
    1. First response.
    2. **Second response**.
 
        This is an optional explanation.
 
        Lorem ipsum dolor sit amet, consetetur
        sadipscing elitr, sed diam nonumyeirmod
        tempor invidunt ut labore et dolore magna
        aliquyam erat, sed diamvoluptua.
 
    3. Third response.
    4. Fourth response.
 
</div>

5.3.4.2 YNB-type quiz syntax

<div markdown="1" class="quiz-activity" data-id="quiz-id-2">
##### Activity 2 heading
###### Activity subheading (optional).
 
Activity description (optional). Lorem ipsum dolor sit amet, 
consetetur sadipscing elitr, sed diam non umyeirmod.
 
1. First question.
 
    1. **True**
 
        This is the correct response (true).
 
    2. False
 
2. Second question.
 
    1. True
    2. **False**
 
        This is the correct response (false).
 
</div>

5.3.4.3 Questionnaire-type quiz syntax

<div markdown="1" class="quiz-questionnaire" data-id="quiz-id-3" >
##### Questionnaire 1 heading
###### Questionnaire subheading (optional).
 
Questionnaire description (optional). Lorem ipsum dolor sit amet, 
consetetur sadipscing elitr, sed diam non umyeirmod.
 
1. First question.
 
  ###### Solution
 
    The solution to the first question (optional).
 
2. Second question.
 
3. Third question.
 
  ###### Solution
 
    The solution to the third question (optional).
 
</div>

5.3.5 Rendered examples

The quizes shown above as examples will render as follows:

NOTE

The following rendered version of the examples is not the same than the one you will get for an epub or mobi ebook because of the limited capabilities of the format. Main differences are:

  • The epub or mobi versions are rendered using only HTML.
  • This version uses Javascript to implement the user interactions.

Please generate the epub or mobi versions of this documentation to fully appreciate the differences.

5.3.5.1 ABC-type quiz syntax

5.3.5.1.1 Activity 1 heading
5.3.5.1.1.1 Activity subheading (optional).

Activity description (optional). Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam non umyeirmod.

1

First question.

 First response.

 Second response.

 Third response.

2

Second question.

 First response.

 Second response.

 Third response.

 Fourth response.

5.3.5.2 YNB-type quiz syntax

5.3.5.2.1 Activity 2 heading
5.3.5.2.1.1 Activity subheading (optional).

Activity description (optional). Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam non umyeirmod.

1

First question.

2

Second question.

5.3.5.3 Questionnaire-type quiz syntax

5.3.5.3.1 Questionnaire 1 heading
5.3.5.3.1.1 Questionnaire subheading (optional).

Questionnaire description (optional). Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam non umyeirmod.

1

First question.

2

Second question.

Ask your teacher to provide the solution.

3

Third question.

Chapter 6 The Trefoil content generation plugins

This chapter describes the content generation plugins. These plugins provide a way to automatically generate content for your book.

6.1 WordSearchPlugin

This plugin allows generating wordsearch puzzles automatically, like the following one:

Difficulty: Medium
FYSUNDAYYP
JAAWMEDYWW
QDHDHPAMEL
YSHPSDEDEB
UEBLRRNEZA
EUFUPEUIIR
CTTUSEXHGZ
EAVDXKNLTZ
STASYADNOM
IYYADIRFMZ
  • MONDAY
  • TUESDAY
  • WEDNESDAY
  • THURSDAY
  • FRIDAY
  • SATURDAY
  • SUNDAY

6.1.1 Availability

This plugin is available for all editions.

6.1.2 Usage

# <book-dir>/config.yml
book:
    editions:
        <edition-name>
            plugins:
                enabled: [ WordSearch ]       
                options:
                    WordSearch:
                        grid_size: 20
                        solution_grid_size: 10
                        highlight_type: shadow
                        word_files:
                          - { label: my_label_1, name: my/words/file/path/and/name_1.txt }
                          - { label: my_label_n, name: my/words/file/path/and/name_n.txt }
                        default:
                          filler: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                          difficulty: "medium"
                        strings:
                          title: ""
                          solution_title: ""
                          text: "" 
                          text2: ""
                          difficulty:
                            easy: "Dificulty: Easy"
                            medium: "Dificulty: Medium"
                            hard: "Dificulty: Hard"
                            very-hard: "Dificulty: Very Hard"

6.1.2.1 Plugin options

This is a complex plugin with lots of options to allow extensive customization. All of them are optional and have sensible defaults that are shown in the previous YAML block.

  • grid_size: Size of the puzzle grid in pixels.
  • solution_grid_size: Size of the solution grid in pixels.
  • highlight_type: The highlight type of the solution. Either line or shadow.
  • word_files: Labels for the word files to use with the automatic word selection feature. The name can include a path and its relative to the book’s Content directory.
  • default: Some default values to use.
    • filler: A string with all the letters or signs to use as filler for empty puzzle places.
    • difficulty: The puzzle difficulty. Either easy, medium, hard, or very-hard.
  • string: Some string used on the puzzle and solution rendering.
    • easy: Text for easy puzzles.
    • medium: Text for medium puzzles.
    • hard: Text for hard puzzles.
    • very-hard: Text for very hard puzzles.

This feature uses several trefoil markers to achieve it complex functionality.

What are Trefoil markers?

Trefoil markers are a kind of function call wich produces HTML code to be processed later. They are similar to Twig function calls but are enclosed between {@ ... @} delimiters. The “======” series between the opening {@ and the function name is an optional delimiter to help visually identifiying the block in the text.

6.1.2.2 Case 1: Word search with explicit words

{@ wordsearch_begin(id, {options} ) @}
 
   ...list of words...
 
{@ wordsearch_end() @}
 
{@ wordsearch_wordlist(id, {options} ) @}    
 
{@ wordsearch_solution(id, {options} ) @}

Arguments for wordsearch_begin()

  • id: A numeric identifier for a particular puzzle. It is used to link all the other trefoil marker calls together.
  • options: A list of argument in the form {key:value, … ,key:value}. They are:

    • rows: The number of rows of the puzzle.
    • cols: The number of columns of the puzzle.
    • filler: A string with all the letters or signs to use as filler for empty puzzle places.
    • title: The title of the puzzle.
      • It can include HTML markup.
      • The puzzle id can be included one or two times using sprintf syntax.
      • Example: <span>%s</span>Puzzle<span>%s</span>
    • text: A text to show before the puzzle. It can include HTML markup.
    • text2: Another text. It can include HTML markup.
    • difficulty: Difficulty of the puzzle. Either easy, medium, hard, or very-hard.
    • seed: The seed used for the pseudo-random numbers generator (see explanation below). If not provided, the pluting will generate a different puzzle on each run, so it is better to set a specific seed to get repeatable results.
  • list of words is a list with the words to use in the puzzle.

Puzzle difficulty

The puzzle difficulty can be graduated as follows:

  • easy: Not very long words, never reversed.

  • medium: Not very long words, with a few of them reversed.

  • hard: Longer words, with a few of them reversed.

  • very-hard: Longer words, always reversed.

Arguments for wordsearch_wordlist()

  • id: The id of the puzzle to show the wordlist.
  • options A list of argument in the form {key:value, … ,key:value}. They are:
    • sorted: Whether the list should be shown sorted or unsorted. Default is unsorted.
    • chunks: The number of parts that the wordlist should be divided into. Useful for styling the list in columns. Default is 1.

Arguments for wordsearch_solution()

  • id: The id of the puzzle to show the wordlist.
  • options A list of argument in the form {key:value, … ,key:value}. They are:
    • title: The title of the solution.
      • It can include HTML markup.
      • The puzzle id can be included one or two times using sprintf syntax.
      • Example: Soluton <span>%s</span>
    • text: A text to show before the solution.
      • It can include HTML markup.
About pseudo-random numbers generation

This plugin uses a pseudo-random number generator to generate all the needed variations. The difference with a true random numbers generator is that, while the true random generator will generate a true random sequence, the pseudo-random one will generate a repeatable sequence that is only apparently random.
Pseudo-random number generators use a “seed” to start the sequence. Two sequences using the same seed will be identical.

Example

{@ wordsearch_begin( 100, {
        seed: 1,
        rows: 10,
        cols: 10,
        title: 'This is the puzzle',
        text: 'Days of the week in Spanish.',
        text2: 'Find the words hidden between the letters.',
        difficulty: 'hard'
}) @}
 
- Lunes
- Martes
- Miércoles
- Jueves
- Viernes
- Sábado
- Domingo
 
{@ wordsearch_end() @}
 
{@ wordsearch_wordlist( 100 ) @}
 
{@ wordsearch_solution( 100, { title: 'This is the solution'} ) @}

This will render as follows:

This is the puzzle
Days of the week in Spanish.
Find the words hidden between the letters.
Difficulty: Hard
SDOMINGOML
FEWZQPNGCD
OKVLJSEEMD
JWVEEFNYJB
ZDENUNKKEO
OQUEYJTTCD
XLSENREIVA
SELOCREIMB
GDSETRAMIA
UNDEFAKHNS
  • LUNES
  • MARTES
  • MIÉRCOLES
  • JUEVES
  • VIERNES
  • SÁBADO
  • DOMINGO
This is the solution
S
D
O
M
I
N
G
O
M
L
F
E
W
Z
Q
P
N
G
C
D
O
K
V
L
J
S
E
E
M
D
J
W
V
E
E
F
N
Y
J
B
Z
D
E
N
U
N
K
K
E
O
O
Q
U
E
Y
J
T
T
C
D
X
L
S
E
N
R
E
I
V
A
S
E
L
O
C
R
E
I
M
B
G
D
S
E
T
R
A
M
I
A
U
N
D
E
F
A
K
H
N
S

6.1.2.3 Case 2: Word search with random words from file

{@ wordsearch(id, {options} ) @}
 
{@ wordsearch_wordlist(id, {options} ) @}    
 
{@ wordsearch_solution(id, {options} ) @}

Arguments for wordsearch()

This marker accepts the same arguments as wordsearch_begin() but needs additional arguments:

  • options:
    • word_file: The label of a file with words to choose from, as specified in the plugin options. If no file is specified the marker will generate a puzzle with a default content (useful for quick testing);
    • number_of_words : The number of words to randomly select from the file.

Arguments for wordsearch_wordlist()

Same usage as in the previous case.

Arguments for wordsearch_solution()

Same usage as in the previous case.

Example

Assuming that config.yml contains:

# <book-dir>/config.yml
book:
    ...
    plugins:
        ...
        options:
            WordSearch:
                ...
                word_files:
                    - { label: word_file_1, name: word_file_1.txt }
                ...

And the following code:

{@ wordsearch( 101, {
        seed: 1,
        rows: 10,
        cols: 10,
        title: 'This is the puzzle number %s',
        text: 'Days of the week in Spanish.',
        text2: 'Find the words hidden between the letters.',
        difficulty: 'hard',
        word_file: 'word_file_1',
        number_of_words: 10
        }) @}
 
{@ wordsearch_wordlist( 101 ) @}
 
{@ wordsearch_solution( 101, { title: 'Solution %s'} ) @}

This will render as follows:

This is the puzzle number 101
Days of the week in Spanish.
Find the words hidden between the letters.
Difficulty: Hard
ADEQUATESF
SCIHNXTCEM
BZCTKUWNRN
VPSOLCOAIU
AFFORDIVUP
SKSWSDBDQS
ABROADIACK
ADDITIONAL
ADDRESSXGN
ADVENTUREO
  • ADDITIONAL
  • ABROAD
  • ADVENTURE
  • ADEQUATE
  • AFFORD
  • ACQUIRE
  • ACCORDING
  • ADDRESS
  • ABSOLUTE
  • ADVANCE
Solution 101
A
D
E
Q
U
A
T
E
S
F
S
C
I
H
N
X
T
C
E
M
B
Z
C
T
K
U
W
N
R
N
V
P
S
O
L
C
O
A
I
U
A
F
F
O
R
D
I
V
U
P
S
K
S
W
S
D
B
D
Q
S
A
B
R
O
A
D
I
A
C
K
A
D
D
I
T
I
O
N
A
L
A
D
D
R
E
S
S
X
G
N
A
D
V
E
N
T
U
R
E
O

Part 3 Trefoil themes

trefoil greatly enhances the functionality of easybook themes.

Chapter 7 Themes system enhancements

Themes functionality has been greatly enhanced in trefoil, making them more flexible and easy to customize. Also, trefoil themes can provide not only CCS styles and HTML templates but also images and fonts.

7.1 Trefoil themes

trefoil comes with some standard themes:

  • TrefoilOne is a classic-looking theme, suitable for novels, essays and other literary works.

  • TrefoilTwo is a modern theme.

  • TrefoilDoc is used for generating this documentation. It is based on TrefoilTwo but adds an HTML edition doc-website that uses Twitter Bootstrap 3.

To use them, as always, just put the name of the theme in the book’s config.yml:

# <book-dir>/config.yml
book:
    editions:
        <edition-name>
            theme: TrefoilTwo

The theme definitions will be looked up into <trefoil-dir>/app/Resources/Themes. If the theme is not found there, trefoil will try to use an standard easybook theme of the same name. If that is also missing, the standard Base theme will be used, which is likely to cause problems if you activated some plugin that requires a non-standard template.

Note

trefoil themes are backwards-compatible with easybook themes, meaning that any book that can be published by easybook can also be published by trefoil. Of course, you will need to use an trefoil theme to make use of its new features.

7.2 Custom themes

trefoil allows creating custom themes. Their structure is the same than the standard trefoil themes but can be created anywhere in the file system, allowing the creation of a personal theme library without the need to modify the trefoil app/Resources directory.

To use a custom theme you just need to invoke the book publish command with the new optional argument --themes_dir:

book publish my-book-slug my-edition --themes_dir=../my/themes/directory

Example:

book publish the-origin-of-species ebook --themes_dir=~/themes/trefoil

7.3 Structure of a theme

A theme, whether standard or custom, must follow this structure:

<themes-dir>
└─ <theme-name>
   ├─ Common      <== Common definitions
   │  ├─ Contents    
   │  ├─ Resources
   │  │  ├─ Fonts
   │  │  └─ images
   │  └─ Templates
   ├─ <edition-type1>  <== For edition type 1
   │  ├─ Contents
   │  ├─ Resources
   │  │  ├─ images
   │  │  └─ Translations
   │  └─ Templates
   │  ...
   └─ <edition-typeN>  <== For edition type N
      ├─ Contents
      ├─ Resources
      │  ├─ images
      │  └─ Translations
      └─ Templates
Note

Standard trefoil themes do not support all the edition types, but epub and mobi are available in each theme (please look at each theme directory to find out which ones are available). But you are free to implement support for other edition types in your custom themes.

7.4 Components of a theme

7.4.1 Contents

  • Common\Contents directory contains default content for book items that are common to all editions.

  • <edition-type>\Contents directory contain content that is specific to that edition.

If a content file is not found into one of these directories it will be looked up into the standard easybook content directories (most likely, the Base theme).

7.4.2 Fonts

  • Common\Resources\Fonts directory contains additional font files for the book.

There is no per-edition font directory, but you can select which fonts are packed into the final book for a given edition with the following configuration:

book:
    editions:
        edition-name:
            include_fonts: true
            fonts:
                - Inconsolata-Regular
                - Inconsolata-Bold

Only the listed font files will be included into the final ebook (i.e. book.epub). This is a useful technique for limiting the final size of an edition output by only including the needed fonts.

7.4.3 Templates

  • Common\Templates directory contains templates that are common to all editions.
  • <edition-type>\Templates directory contain templates specific to that edition.

7.4.4 Images

  • Common\Resources\images directory contains images that are common to all editions.
  • <edition-type>\Resources\images directory contain images specific to that edition.

You can organize the image files into whatever subdirectories structure inside the images directories. Upon book publishing, all of them will be copied to a flat images files into the book contents (so beware of duplicated names). Images per-edition type overwrite common images of the same name.

7.4.5 Translations

  • Common\Resources\Translations directory contains label files that are common to all editions.

  • <edition-type>\Resources\Translations directory contain label files specific to that edition.

As usual, per-edition translations overwrite common translations.

Part 4 Other functionality

Other enhancements and extra functionality in trefoil.

Chapter 8 Other funcionality

8.1 Content exclusion

Some kinds of contents do not make sense for certain edition formats. They will be automatically excluded:

  • epub ebooks usually do not include a visible table of contents (HTML TOC), as reader apps and devices heavily rely on the navigational TOC. But it could make sense to include it on certain situations, so a config.yml parameter could be added to explicitly request it:
# config.yml
book:
    editions:
        ebook:
            format: epub
            include_html_toc: true # An HTML TOC will be included

8.2 Content filtering

For books with several editions may be convenient to have a way to include some content in just one of them and not in the others, or to include an item based on the format of the edition.

Example:

  • Item ebook-usage-instructions.md must only be included in ebook and kindle edition.

  • Item pdf-print-instruccions.md must be excluded from all editions whose output format is not pdf, regarding of the edition name.

To achieve that we can use content filtering. Consider the following book definition:

# config.yml
book:
    contents:
        - { element: edition }
        - { element: toc }
        - { element: usage-instructions, content: usage-instructions.md, editions: [ebook, kindle] }
        - { element: print-instructions, content: print-instructions.md, formats: [pdf] }
        - { element: chapter, number: 1, content: chapter1.md }

8.2.0.1 Syntax

For a content item, the following options can be added:

  • editions: an array of the edition names which will contain that item.

  • formats: an array of the allowed formats for that item. Only editions with these formats will contain the item.

Prefixing the edition or format value with not- will negate it.

Note

In previous versions the negation prefix was ‘!’. This was changed because of a conflict with the new “custom tags” feature of the Yaml parser.

Example:

  • editions: [ebook, kindle] ==> only ebook and kindle editions.
  • editions: [not-print] ==> all editions except print.
  • formats: [epub, mobi] ==> only editions with epub or mobi format.
  • formats: [not-pdf] ==> all editions except those with pdf format.

If both editions and formats are used in the same item, it will only be included in editions that fulfill both sets of conditions.

8.3 Config import

In some cases may be convenient to being able to somehow “import” some book config definitions into our book config, to avoid repeating common values.

Example:

  • Assume we are producing a series of ten books (i.e. lessons of a course) and all of them will have the same editions: ‘ebook’, ‘kindle’ and ‘print’.

  • We want to avoid defining again and again the same editions’ definitions in all of ten books’ config.yml.

This functionality allows just that:

# my_series/config.yml
easybook:
    # all of easybook parameters
book:
    editions:
        ebook:
            # definition of ebook edition
        kindle:
            # definition of kindle edition
        print:
            # definition of print edition

And then:

# my_series/book1/config.yml
import:
    - ".."
 
book:
    title: '...'
 
    # no 'editions' definitions!

The import value is an array of all the directories where a suitable config.yml file will be looked up for inclusion. The first one will be used, and used as the base definition in which the “local” definitions will be merged in.

Footnotes

The next pages contain the footnotes referred from the text.

To return to the text, please “click” on the return link of each note.


  1. This is a footnote just for showing an example. [↩]

  2. Another footnote, also with dummy text just to have something to work with. [↩]

Index

This is the book index. Each term has one or more links to its usages in the contents.

Note

The automatic index functionality is intended for printed media (pdfformat). While it still works in epub, mobi and html editions, the results may not be optimal because it can produce a lot of backlinks to the indexed terms.

D
E
H
M
P
T