= AsciiDoc Recommended Practices Dan Allen v1.0-HEAD, 2016-12-21 :description: This document catalogs a set of recommended practices for composing documents in AsciiDoc. :page-layout: docs {description} .DRAFT **** This document is only a rough draft. These recommendations are not doctrine and are subject to change. **** AsciiDoc offers multiple ways to accomplish the same thing, and is often very lenient with the syntax. This guide helps bring consistency to your documents that will maximize efficiency, improve readability and minimize maintenance. == Document extension AsciiDoc doesn't care which extension you use. GitHub supports the extensions `.asciidoc`, `.adoc` and `.asc`. `.adoc` seems to be the most often used extension and the one we prefer. It does not conflict with other well known applications, is distinct, and not excessively long (like `.asciidoc`). It also reads as "`a doc`". Our recommendation, therefore, is to use `.adoc`. NOTE: We strongly recommend _against_ using the `.asc` extension. The connection to AsciiDoc isn't immediately obvious and it gets falsely identified as a PGP file on Linux. == One Sentence Per Line Don't wrap text at a fixed column width. Instead, put each sentence on its own line, a technique called _sentence per line_. This technique is similar to how you write and organize source code. The result can be spectacular. Here are some of the advantages of using the sentence per line style: * It prevents reflows (meaning a change early in the paragraph won't cause the remaining lines in the paragraph to reposition). * You can easily swap sentences. * You can easily separate or join paragraphs. * You can comment out sentences or add commentary to them. * You can spot sentences which are too long or sentences that vary widely in length. * You can spot redundant (and thus mundane) patterns in your writing. We picked up this idea from the writing guide in the https://neo4j.com/docs/2.2.8/community-docs.html#_writing[Neo4j documentation]. However, it seems like the idea dates back a discovery by Buckminster Fuller in the 1930s, who called it https://vanemden.wordpress.com/2009/01/01/ventilated-prose/[ventilated prose]. The technique was also recommended in 2009 by Brandon Rhodes in a blog post about https://rhodesmill.org/brandon/2012/one-sentence-per-line/[Semantic Linefeeds]. It's important to note that this technique works because AsciiDoc doesn't treat wrapped lines in prose as hard line breaks. At least, it doesn't show up that way to the reader. The line breaks between contiguous lines of prose will not be visible in the rendered document (i.e., as the reader sees it). //This practice might be odd for readers who read the plain text file, but the text viewer should best be able to break lines at the screen's width. CAUTION: While a single line break doesn't appear in the output, two consecutive line breaks starts a new paragraph (or other block). == Section Titles There are three ways to define a section title. These variants can be classified into two types of styles, _atx_ and _setext_ (historical names). *The asymmetric Atx-style is the style we recommend to define your section titles.* .Atx-style In the Atx-style, the section title is defined on a single line. The section title begins with one or more equal characters (i.e., `=`) followed by a space and the section title. The number of leading characters representing the depth. The top-level section is reserved for the document title, so the first section in the document will have two leading characters. == First Section This example uses the asymmetric Atx-style. It requires the least number of characters and it's intuitive since the number of leading characters represents the heading level. When using the HTML backend, this section title will be transformed into an h2 heading (likely wrapped in a section block for styling):

First Section

The symmetric Atx-style bookends the section title between a matching pair of delimiters. == First Section == While this syntax may look nicer to some, it requires twice the number of delimiters without adding any additional semantics. Therefore, I consider it a waste of keystrokes and don't recommend using it. However, either of the Atx-style section titles are better than the Setext style. .Setext In the Setext-style, the section title is defined on two lines. The second line is a string of characters that form an underline below the section title. Here's an example of a section title from above defined in the Setext-style. First Section ------------- Since the length of the line is determined by the number of characters in the section title, another dimension must be introduced to determine the level. That dimension is the character used for the underline. The characters used are (sorted from document title to level 5 section) `=`, `-`, `~`, `^`, and `+`. I _strongly_ recommend against using the Setext style for section titles. Keeping the length of the underline in sync with the title length is an unnecessary task and time waster. A more substantial reason is that the mapping between character and heading level is *very* difficult to remember and not obvious to new AsciiDoc adopters. All in all, using Setext section titles is a _bad practice_. *Don't use them!* TIP: The recommendation is to use the asymmetric Atx-style for section titles. It's the most simple and intuitive method for writing, as well as for reading in the plain text (source) file. === Document title Since the document title occurs only once in a document, I consider it acceptable (but strongly discouraged) to use the Setext style in this instance, so long as you *also* disable the compat-mode attribute (otherwise, it puts the processor into compat mode). Document Title ============== Author Name :compat-mode!: IMPORTANT: You must explicitly disable compatibility mode (i.e., `compat-mode!`) in this case if you don't want it enabled. Compatibility mode is automatically enabled when using the Setext style document title. See the https://docs.asciidoctor.org/asciidoctor/latest/migrate/asciidoc-py/[migration guide] for details. Be sure to include your name immediately following the document title. NOTE: AsciiDoc only supports an e-mail following the author line. It does not support a personal URL. Asciidoctor supports a raw URL as well as an inline link macro. It's a good practice to also include a revision line following the author line. Document Title ============== Author Name v1.0, 2012-02-10 :compat-mode!: The version number is optional. The revision line may consist of a date only. Document Title ============== Author Name 2012-02-10 :compat-mode!: == Delimited Blocks Delimited blocks contain special text such as code listings, quotes, sidebar text, tables and so on. As you may have guessed, they are bounded by a string of delimiters. The delimiters are defined on a line by themselves. The content goes in between the delimiter lines. Here's an example of a listing: ---- $ asciidoctor -b html5 recommended-practices.adoc ---- Delimited blocks require four or more repeating characters on a line by themselves to mark the boundary of the block. The one exception is the open block, which only requires two `-` repeating characters. You may be tempted to extend the line further, either to a predetermined length or to match the length of the content. ------------------------------------------------- $ asciidoctor -b html5 recommended-practices.adoc ------------------------------------------------- *Don't do this!* Maintaining long delimiter lines is _a colossal waste of time_, not to mention arbitrary and error prone. I strongly urge you to _use the minimum number of characters necessary_ to form a delimited block and move on to drafting the content. The reader will never see these long strings of delimiters anyway since they are not carried over to the output (HTML, DocBook, etc). NOTE: AsciiDoc does not enforce that the length of the line that opens the delimited block match the length of the line that closes the delimited block, but I think _it should_. Asciidoctor enforces this requirement, so make sure they match! == Document Attributes (i.e., Variables) You can save yourself a lot of typing by leveraging document attributes. Document attributes promote frequently occurring references and phrases to the top of the document (or section). You can declare information once by assigning it to an attribute, then refer to that attribute throughout the document. In that sense, you can think of attributes like variables for AsciiDoc. Storing information in attributes that you declare at the top of the document makes finding the information easy and saves you from having to update the information in multiple places (i.e., keeps the document DRY). When you update the value of the attribute, the value will change everywhere in the document that attribute is referenced. === DRY URLs A common use for attributes is to store URLs. URLs frequently change, can be rather long, and often have special characters that need escaping. All of these challenges are solved by declaring the URLs in attributes. You simply assign the URL to a short, easy to remember attribute: [source,asciidoc] ---- :url-issues: https://github.com/asciidoctor/asciidoctor/issues ---- Then you reference this attribute whenever you want to use the URL in your document, such as to make a link: [source,asciidoc] ---- Submit bug fixes and feature requests to the {url-issues}[issue tracker]. ---- Since you may define attributes for many different things, it's good to employ a system to keep them organized. Let's study one such system. === Attribute Groups If you define a lot of document attributes, the document header can get messy. To keep it tidy, it's a good idea to: * Name related attributes using a common prefix (i.e., give them a namespace) * Group related attributes together underneath a banner For example, we recommend using either the prefix `url-` or `uri-` when declaring attributes that hold URL values. This is done for several reasons: . It communicates the type of value the attribute holds (e.g., `url-issues` is a URL for the issue tracker) . It avoids collisions with attributes used for other purposes (e.g., using `org` for the organization URL could collide with `org` used for the organization name) . It causes a code assist tool in an editor (such as text auto-completion) to naturally group related attributes (e.g., bring up a list of all URL attributes by typing `url-`) Grouping related attributes makes it easy to see where new attributes should be added, thus helping to keep the document header tidy. It also opens the door for reorganizing the groups into separate files in the future. Within a group, you might consider alphabetizing the attributes. One exception to this rule is if an attribute references another attribute, in which case you have to define the attribute being referenced first. Here are some of the banners we recommend for grouping related attributes in the document header: * _Metadata_ - Attributes that define information that goes into the header of the output document for indexing * _Settings_ - Attributes that control built-in conversion and formatting behavior * _Refs_ - Attributes that are referenced in the content, such as URLs; prefix each attribute by its type to make auto-complete work nicer, such as `url-` for a URL. You can use whatever additional groups feel natural to you. Here's how that looks when put these recommendations together: [source,asciidoc] ---- = Document Title Author Name // Metadata: :description: The description of this page. :keywords: writing, documentation, publishing // Settings: :icons: font :idprefix: :idseparator: - // Refs: :url-project: https://asciidoctor.org :url-docs: {url-project}/docs :url-issues: https://github.com/asciidoctor/asciidoctor :img-ci: https://github.com/asciidoctor/asciidoctor/workflows/CI/badge.svg ---- === Counters Counters are backed by document attributes. Since they share the same global namespace as all other document attributes, it's a good idea to apply a prefix to counter names to avoid collisions with other attributes. For example: {counter:cnt-step} === Document settings Most document settings are controlled using attributes. Document settings are configured using attribute entries immediately following the document title (without any blank lines in between). There are several options of interest. .Section numbering You can enable numbering of sections using the `sectnums` attribute (off by default). :sectnums: .Document description You can set the description of the document using the `description` attribute. The description is included in the header of the document. :description: This document catalogs a set of recommended practices for writing in AsciiDoc. You can break any https://docs.asciidoctor.org/asciidoc/latest/attributes/wrap-values/[attribute value across several lines] by ending the lines in a `{backslash}` preceded by a space. :description: This document catalogs a set of recommended practices \ for composing documents in AsciiDoc. You can use this text anywhere in the document by referencing it as an attribute. {description} .Section title IDs and ID prefixes IDs are generated for each section title by default. The ID is generated from the section title, prefixed with an underscore (i.e., `_`) by default. You can change the prefix using the `idprefix` attribute. :idprefix: id_ If you want to remove the prefix, assign it to an empty value: :idprefix: To disable the auto-generation of section IDs, unset the `sectids` attribute: :sectids!: .Table of contents Set the `toc` attribute to activate an auto-generated table of contents at the top of the document: :toc: == Images and Other Media TODO .Paths don't include the images directory in each image reference .Block vs inline ... == Conditional Inclusion TODO how to use, reason for using == Lists .Unordered list markers AsciiDoc supports both `*` (one or more) and `-` (only one) as markers for a top-level list item. .... * first * second * third .... or .... - first - second - third .... However, the dash marker _cannot_ be repeated when defining a list item. This can lead to confusion since AsciiDoc increases the nesting level each time it encounters a _different_ marker. For instance, in the following case, the item that has an asterisk marker is *nested* inside the first item. .... - first * nested item - second - third .... This nesting rule is true even when the number of asterisks seems to indicate the level: .... *** first * nested item *** second *** third .... _Yep, that's right, the second list item is nested inside the first list item._ If you stick to convention, the number of asterisks _can_ represent the nesting level: .... * first ** nested item * second * third .... Now *that's* intuitive. I strongly recommend using the asterisk marker if you are going to be using nested lists. If you only have top-level list items, then using either marker is reasonable. I may even recommend using the dash marker for lists that are not intended to have nested items and the asterisk marker for lists that do have nested items. That way it's easy to identify them as different types. .Description lists They exist! .Separating lists Adjacent lists sometimes like to fuse. To force the start of a new list, offset the two lists by an empty line comment: .... * apples * oranges * bananas //- * carrots * tomatoes * celery .... == Literal Text TODO backticks vs plus and passthough stuffs recommendation for inline code quote char == Tables .Stacked cells Leverage them, makes it easy to read