Metadata
Attributes
Attributes are used to do everything from specify the language of code blocks, add ids for crosslinking and even support extensions to Markua. We have already seen attributes in the attribute lists we have encountered.
Attribute List Format
An attribute list is one or more key-value, comma-separated pairs:
{key_one: value1, key_two: value_two, key_three: "value three!", key_four: true, key_five: 0, key_six: 3.14}
Note that you can skip the space between the colon and the value: the following {format: ruby} and {format:ruby} both work. However, for consistency I recommend always adding a space.
An attribute list can be inserted into a Markua document in one of three ways:
- Immediately above a block element (e.g. heading, figure, aside, blurb, quiz, etc.), with one newline separating it from the block element.
- Immediately after a span element (e.g. a word, italicized phrase, etc.) in normal paragraphs and in similarly-simple contexts, with no spaces separating it from the span element.
- On a line by itself, with one blank line above and below it. In this format, the attribute list contains directives.
Regarding #2 and #3: Any line outside of a code resource which starts with an opening curly brace { and ends with a closing curly brace } is assumed to be an attribute list, and will not be output by Leanpub. If you want to start a line with a literal opening curly brace { you need to preface it with a backslash (\).
Regarding #2: There is some deliberate ambiguity here. If a Leanpub cannot handle the attribute list (including just an id attribute added with in the given context, it should just ignore the attribute list and add a warning to any list of warnings when generating the book. For example, Leanpub does not support attribute lists in headers or in captions. So, in Leanpub, you cannot do this:
# Chapter One{#one}
That doesn't work.
# Chapter{id: chapter-two} Two
That doesn't work either.
You also cannot say  in Leanpub.
In both cases, what you want to do is just define the attribute list on the outer element:
{#one}
# Chapter One
That works.
{id: chapter-two}
# Chapter Two
That works too.
You also can say {#horse} in Leanpub.
Attribute Keys
The keys of attributes must consist exclusively of lowercase letters, hyphens (-) and underscores (_). Uppercase letters are not permitted in attribute keys: Leanpub must treat uppercase letters in attribute keys as an error.
If a key is duplicated in an attribute list, the first key value is used and subsequent ones are ignored. Leanpub should add a warning in its list of warnings, which are not output in the output itself.
Attribute Values
All attributes are text. Leanpub interprets text values of “true” and “false” as representing true and false. Quotes are optional for attribute values, and are only needed if the attribute value contains whitespace or special characters.
If a text attribute value contains a quote, it must be “escaped” with a backslash: e.g. {caption: "\"Fresh\" Fish"}
id Attributes
As previously discussed, there is special syntactic sugar for ids: {#foo} is equivalent to {id: foo}. However, ids are just attributes.
Conditional Inclusion Attributes on Headings: book, sample
Markua headings (and only headings) may have various attributes which specify which output formats their content (of the part, chapter, section, sub-section, etc.) should be included in. If the given attribute is not present, the default value of it is that specified by the nearest ancestor heading. If no such attribute is present at a top-level heading, the default is given by the default value for the attribute defined of Markua.
There are eight attributes which specify conditional inclusion in output targets; four for books, and four for courses.
book- If
true, include this heading and its content (including nested sections, subsections, etc.) in the book (PDF, EPUB and/or MOBI) that is being generated. Iffalse, omit it. The default istrue. Setting this tofalseis an easy way to “comment out” a section of your book. sample- If
true, include the content under this heading (including nested sections, subsections, etc.) in the sample of the book that is being generated. Iffalse, omit it. The default isfalse. Note that this attribute just governs the inclusion of the content, not the heading itself. Leanpub may choose to include every heading in the sample version of a book or course, in order to produce a representative Table of Contents. In a case such as this wheresampleisfalse, Leanpub may output special content inside the chapter, section or subsection to indicate that the content itself is being omitted from the sample. This attribute applies to both the book version (PDF, EPUB and/or MOBI) and the web version of the sample.
This set of defaults means that by default, there is no book or course content included in the sample version of a book or course. As discussed, the headings themselves may all be included, in order to generate an appropriate Table of Contents for the sample book or course.
The reason that there are different attributes used for books and courses, instead of a course just reusing the same values that are used by a book, is that this way the same manuscript can be used to produce a book and a course. This approach is obviously not for everyone, but it may appeal to highly technical authors who wish to not repeat themselves, and who don’t want to have to maintain separate git branches for a book and a course. Our assumption, however, is that most books or courses will require separate git branches, and that thus this approach merely saves some labour at the cost of some added complexity.
Note that specifying one of these attributes in a nested section overrides any value inherited from its ancestors, or from the default. This way, you can include a chapter in the sample, except for a specific section of the chapter.
Example:
{sample: true}
# Chapter One
This is included in the sample.
## Section One
This is included in the sample.
{sample: false}
## Section Two
This is *not* included in the sample.
## Section Three
This is included in the sample.
{book: false, sample: true}
# Buy the book!
What you read was just a sample. Why not buy the full book?
# Chapter Two
This is not included in the sample.
To be clear: ALL conditional inclusion attributes ONLY have meaning when used as an attribute list on headings, i.e. the things that are defined with 1-6 # signs followed by a space, followed by text.
For example, you can only say {sample: true} immediately above a heading. You can’t have a blank line below it (otherwise it would be a directive, and not be valid) and you can’t attach it to anything other than a heading (like a paragraph, figure, etc.).
Leanpub must raise an error if it encounters a conditional inclusion attribute used incorrectly, so as to help the author understand how to properly use them.
Directives
Directives are switches which affect the parsing of a Markua document.
The syntax for directives is simple: they are just contained in an attribute list. The only difference is that the attribute list is inserted an a line by itself, with one blank line above and below it. (There are two exceptions: if the directive is at the beginning of a manuscript file, you can omit the blank line above it; if it’s at the end of a manuscript file, you can omit the blank line below it.)
A directive does not have any kind of “closing tag”–it simply remains in effect for the rest of the Markua document, or until the directive is overridden by another use of the same directive with a different value.
Currently the only directives supported by Leanpub are:
-
{frontmatter}(for Roman numeral numbering of things like a preface) -
{mainmatter}(for the start of normal numbering) -
{backmatter}(to indicate the start of back matter, like appendices)
Here’s an example:
{frontmatter}
# Preface
Foo
{mainmatter}
# Chapter One
Bar
# Chapter Two
Baz
{backmatter}
# Appendix
Hello world.
Page Breaks
Despite how much Markua encourages you to not worry about formatting, sometimes you really just need to add a page break. Pretending otherwise would not be pragmatic.
So, Markua supports adding a page break with {pagebreak}. This looks a lot like a directive, but it’s not, since it only has an effect once, not going forward.
Here’s an example:
foo
{pagebreak}
bar