20. Unordered Lists
If you were to create a list in an e-mail, how would you do it? Chances are, you’d mark list items using the same characters that Asciidoctor uses to find list items.
In the example below, each list item is marked using an asterisk (*), the AsciiDoc syntax specifying an unordered list item.
* Edgar Allan Poe
* Sheri S. Tepper
* Bill Bryson
A list item’s first line of text must be offset from the marker (*) by at least one space.
If you prefer, you can indent list items.
Blank lines are required before and after a list.
Additionally, blank lines are permitted, but not required, between list items.
-
Edgar Allan Poe
-
Sheri S. Tepper
-
Bill Bryson
You can add a title to a list by prefixing the title with a period (.).
.Kizmet's Favorite Authors
* Edgar Allan Poe
* Sheri S. Tepper
* Bill Bryson
-
Edgar Allan Poe
-
Sheri S. Tepper
-
Bill Bryson
Was your instinct to use a hyphen (-) instead of an asterisk to mark list items?
Guess what?
That works too!
- Edgar Allan Poe
- Sheri S. Tepper
- Bill Bryson
You should reserve the hyphen for lists that only have a single level because the hyphen marker (-) doesn’t work for nested lists.
Now that we’ve mentioned nested lists, let’s go to the next section and learn how to create lists with multiple levels.
20.1. Nested
To nest an item, just add another asterisk (*) to the marker, and another for each subsequent level.
.Possible DefOps manual locations
* West wood maze
** Maze heart
*** Reflection pool
** Secret exit
* Untracked file in git repository
-
West wood maze
-
Maze heart
-
Reflection pool
-
-
Secret exit
-
-
Untracked file in git repository
In Asciidoctor 1.5.7 and earlier you could only have up to six (6) levels of nesting (assuming one level uses the hyphen marker).
Since Asciidoctor 1.5.8, you can nest unordered lists to any depth. Keep in mind, however, that some interfaces will begin flatting lists after a certain depth. GitHub starts flattening list after 10 levels of nesting.
* level 1
** level 2
*** level 3
**** level 4
***** level 5
* level 1
-
level 1
-
level 2
-
level 3
-
level 4
-
level 5
-
-
-
-
-
level 1
While it would seem as though the number of asterisks represents the nesting level, that’s not how depth is determined. A new level is created for each unique marker encountered. However, it’s much more intuitive to follow the convention that the number of asterisks equals the level of nesting. After all, we’re shooting for plain text markup that is readable as is.
20.2. Complex List Content
Aside from nested lists, all of the list items you’ve seen only have one line of text. But like with regular paragraph text, the text in a list item can wrap across any number of lines, as long as all the lines are adjacent. The wrapped lines can be indented, and they will still be treated as normal paragraph text. For example:
* The header in AsciiDoc is optional, but if
it is used it must start with a document title.
* Optional Author and Revision information
immediately follows the header title.
* The document header must be separated from
the remainder of the document by one or more
blank lines and cannot contain blank lines.
-
The header in AsciiDoc is optional, but if it is used it must start with a document title.
-
Optional Author and Revision information immediately follows the header title.
-
The document header must be separated from the remainder of the document by one or more blank lines and cannot contain blank lines.
| When items contain more than one line of text, leave a blank line before the next item to make the list easier to read. |
A list item may contain any type of AsciiDoc content, including paragraphs, delimited blocks, and block macros. You just need to attach them to the list item.
20.2.1. List continuation
To add additional paragraphs or other block elements to a list item, you must “attach” them (in a series) using a list continuation.
A list continuation is a + symbol on a line by itself, immediately adjacent to the block being attached.
Here’s an example:
* The header in AsciiDoc must start with a document title.
+
The header is optional.
-
The header in AsciiDoc must start with a document title.
The header is optional.
Using the list continuation, you can attach any number of block elements to a list item. Each block must be preceded by a list continuation to form a chain of blocks.
Here’s an example that attaches both a listing block and an admonition paragraph to the first item:
* The header in AsciiDoc must start with a document title.
+
----
= Document Title
----
+
Keep in mind that the header is optional.
* Optional Author and Revision information immediately follows the header title.
+
----
= Document Title
Doc Writer <doc.writer@asciidoc.org>
v1.0, 2013-01-01
----
Here’s how the source is rendered:
-
The header in AsciiDoc must start with a document title.
= Document TitleKeep in mind that the header is optional.
-
Optional Author and Revision information immediately follows the header title.
= Document Title Doc Writer <doc.writer@asciidoc.org> v1.0, 2013-01-01
If you’re attaching more than one block to a list item, you’re strongly encouraged to wrap the content inside an open block. That way, you only need a single list continuation line to attach the open block to the list item. Within the open block, you write like you normally would, no longer having to worry about adding list continuations between the blocks to keep them attached to the list item.
Here’s an example of wrapping complex list content in an open block:
* The header in AsciiDoc must start with a document title.
+
--
Here's an example of a document title:
----
= Document Title
----
NOTE: The header is optional.
--
Here’s how that content is rendered:
-
The header in AsciiDoc must start with a document title.
Here’s an example of a document title:
= Document TitleThe header is optional.
The open block wrapper is also useful if you’re including content from a shared file into a list item. For example:
* list item
+
--
include::shared-content.adoc[]
--
By wrapping the include directive in an open block, the content can be used unmodified.
The only limitation of this technique is that the content itself may not contain an open block (since open blocks cannot be nested).
20.2.2. Dropping the principal text
If the principal text of a list item is blank, the node for the principal text is dropped.
This is how you can get the first block (such as a listing block) to line up with the list marker.
You can make the principal text blank by using the {blank} attribute reference.
Here’s an example of a list that has items with only complex content.
. {blank}
+
----
print("one")
----
. {blank}
+
----
print("one")
----
Here’s how the source is rendered:
-
print("one") -
print("one")
20.2.3. Attaching to an ancestor list
You may find that you need to attach block content to a parent list item instead of the current one. In other words, you want to attach the block content to the parent list item, so it becomes a sibling of the child list. To do this, you add a blank line before the list continuation. The blank line signals to the list continuation to move out of the current list so it attaches the block to the last item of the parent list.
Here’s an example of a paragraph that’s attached to the parent list item, placing it adjacent to the child list (instead of inside of it).
* parent list item
** child list item
+
paragraph attached to parent list item
Here’s how the source is rendered:
-
parent list item
-
child list item
paragraph attached to parent list item
-
Each blank line that precedes the list continuation signals a move up one level of nesting. Here’s an example that shows how to attach a paragraph to a grandparent list item using two leading blank lines:
* grandparent list item
** parent list item
*** child list item
+
paragraph attached to grandparent list item
Here’s how the source is rendered:
-
grandparent list item
-
parent list item
-
child list item
-
paragraph attached to grandparent list item
-
Using blank lines to back out of the nesting may feel fragile. A more robust way to accomplish the same thing is to enclose the nested lists in an open block. That way, it’s clear where the nested list ends and the enclosing list continues.
* grandparent list item
+
--
** parent list item
*** child list item
--
+
paragraph attached to grandparent list item
Here’s how the source is rendered:
-
grandparent list item
-
parent list item
-
child list item
-
paragraph attached to grandparent list item
-
As you’ve learned in this section, the primary text of a list item can wrap to any number of adjacent lines. You can also attach any type of content to a list item using the list continuation. Combining those features with the open block makes it even easier to create lists with complex content.
20.3. Custom Markers
Asciidoctor offers numerous bullet styles for lists. The list marker (bullet) is set using the list’s block style.
The unordered list marker can be set using any of the following block styles:
-
square
-
circle
-
disc
-
none or no-bullet (indented, but no bullet)
-
unstyled (no indentation or bullet) (HTML only)
| These styles are supported by the default Asciidoctor stylesheet. |
When present, the style name is assigned to the unordered list element as follows:
- For HTML
-
the style name is assigned to the
classattribute on the<ul>element. - For DocBook
-
the style name is assigned to the
markattribute on the<itemizedlist>element.
Here’s an unordered list that has square bullets:
[square]
* one
* two
* three
-
one
-
two
-
three
20.4. Checklist
List items can be marked complete using checklists.
Checklists (i.e., task lists) are unordered lists that have items marked as checked ([*] or [x]) or unchecked ([ ]).
Here’s an example:
* [*] checked
* [x] also checked
* [ ] not checked
* normal list item
-
✓ checked
-
✓ also checked
-
❏ not checked
-
normal list item
| Not all items in the list have to be checklist items, as the previous example shows. |
When checklists are converted to HTML, the checkbox markup is transformed into an HTML checkbox with the appropriate checked state.
The data-item-complete attribute on the checkbox is set to 1 if the item is checked, 0 if not.
The checkbox is used in place of the item’s bullet.
Since HTML generated by Asciidoctor is usually static, the checkbox is set as disabled to make it appear as a simple mark.
If you want to make the checkbox interactive (i.e., clickable), add the interactive option to the checklist (shown here using the shorthand syntax for Options):
[%interactive]
* [*] checked
* [x] also checked
* [ ] not checked
* normal list item
-
checked
-
also checked
-
not checked
-
normal list item
As a bonus, if you enable font-based icons, the checkbox markup (in non-interactive lists) is transformed into a font-based icon!
-
checked
-
also checked
-
not checked
-
normal list item