Formatting Vaadin Documentation With AsciiDoc

This document describes basic styling of Vaadin AsciiDoc documentation.

Cross-References

You should always try to make cross-references to relevant related articles, and between corresponding articles in Flow and Fusion. Validity of cross-references is checked during Docs compilation, and reported in the test builds at GitHub.

Within a Page

A referred section or figure needs an ID. IDs should only have lower-case letters, numbers, dash, and dots. Please follow a dot-separated hierarchical order.

For example:

[[xrefs]]
== Cross-References

[[xrefs.within-a-page]]
=== Within a Page

Such a section can be referenced with:

See <<xrefs.within-a-page>> for more information.

See Within a Page for more information.

Between Pages

Cross-references between pages need a path to the page. For pages in the same folder or product it is most convenient to use relative paths. The file reference must be terminated with dash (#), which can be followed by a sub-target within the page. The reference also needs to include the title of the reference article or section.

For example:

See <<style-guidelines#, Style Guidelines>> for more information.
See <<style-guidelines#source.one-line-per-sentence, One Line per Sentence>> for even more detailed information.
See <<../contributing/overview#, Contributing to Projects>> for general information about contributing.

See Style Guidelines for more information. See One Line per Sentence for even more detailed information. See Contributing to Projects for general information about contributing.

You can have relative references to other folders, like in the above example. References to a menu section should be to an overview article or equivalent.

Note
Update headings in cross-references
If you change any heading text, you have the responsibility to change the cross-reference texts elsewhere in the documentation.

Absolute Paths

You can also use absolute paths using the {articles} variable.

See <<{articles}/contributing-docs/style-guidelines#, Style Guidelines>>.

Lists

AsciiDoc has three types of lists: unordered (bullet) lists, ordered (numbered) lists, and variable lists.

Unordered Lists

Unordered lists show as bullet points.

* Item 1
* Item 2
  • Item 1

  • Item 2

Numbered Lists

Numbered lists have a sequence 1, 2, …​, and hierarchically a, b, c, …​

. Item 1
. Item 2
  1. Item 1

  2. Item 2

Variable Lists

`someVariable`::
  This is the description of the item.
`anotherVariable`::
  This is the description of the other item.
someVariable

This is the description of the item.

anotherVariable

This is the description of the other item.

Images

Image Basics

Images include screenshots and diagrams. They should always have a caption and an ID, unless inside a step-by-step list. The ID should follow the ID hierarchy of the containing section. It should be prefixed with figure.. Images can be referenced from text.

<<figure.images.example>> shows the result.

[[figure.images.example]]
.An example of an image
image::images/mymodule-example.png[width=70%, scaledwidth=100%]

It would render as:

An example of an image shows the result.

An example of an image

Images should be located under an images sub-folder.

Inline Images

You can display images also inline, without an image frame and caption. This is recommended in task lists with screenshots, and in other cases where a caption is not needed and an image frame might be distracting. To do so, have only one colon in image:.

For example:

. Click the button.
. The image should now look as follows:
image:images/example-image.png[width=30%]

It would render as:

  1. Click the button.

  2. The image should now look as follows:

Image Captions

An image caption should not be in title case.

References to images use the caption text in the reference. However, it is used differently in Vaadin Docs and the print edition.

The website shows it in the link.

See the result in An example of an image.

In print or PDF version, the reference includes "Figure x.x <caption>", with the chapter number and figure number in the chapter.

See the result in Figure 1.1, "An example of an image".

Requirements for Illustrations

Illustrations have the following requirements:

Always use white background

Paper is white, and some of the documentation is exported as PDF or in a print edition. When taking screenshots, use a white background when necessary. Make sure the white background does not get transparent when taking screenshots.

Do not use transparency in images

PNG and GIF images allow transparency. While they may or may not show fine in the website, in PDF the transparent parts are rendered as black. This makes them ugly, and therefore unusable.

Use high resolution for screenshots

Otherwise, pixels show up ugly when the images are scaled. You can use the browser zoom feature to enlarge Vaadin UIs. Scale the images as described in Image Scaling.

Minimize screenshot content

Space is precious in the print edition. Select only the relevant area for the screenshot. Sometimes, adding some cut context may clarify the screenshot. Some views or dialog windows can be overly complex or large. You should consider simplifying them with an image editor. You can use PhotoShop or Gimp or whatever.

Fonts must not be too small

The text column in the print edition is 82 mm (3.23 inches) wide. Height of the normal font is 2 mm or 6 points (1/72"). That means around 1/40 of the text column width. Text in diagrams should not be much smaller than this. If text is less than half of this, it is unreadable.

For example, if an image is 800 pixels wide and scaled as 100%, the normal font should be 20 pixels high. Text would have to be at least 10 pixels high, and anything smaller would anyhow be blurry.

Image Scaling

Images are displayed in at least three formats: website, pocket-book sized print edition, and large size PDF. There could also be an ePub format. All images need to be scaled for all these resolutions.

AsciiDoc has two scaling parameters: width and scaledwidth.

image::img/mymodule[width=70%]
width (optional)

This parameter is used for the HTML web edition in Vaadin Docs. The images are automatically limited to the maximum width of the text area.

Code Examples

You can display program or other text formatted in monospace letters in a box separated with ----.

For example:

  ----
  This is some kind of {code} text.
  ----

It would render as:

This is some kind of {code} text.

Source File Types

AsciiDoc supports syntax highlighting for various languages.

For example:

  [source, java]
  ----
  Button button = new Button("My Button");
  ----

It would render as:

Button button = new Button("My Button");

Use Include for Java and TypeScript Code

You should write the code examples in Java or TypeScript files that are compiled. Some technical cases, where you can’t use compiled examples, require writing inline examples.

Java and TypeScript examples are located in the source tree under src/main/java/com/vaadin/demo for Java and frontend/demo for TypeScript.

The source tree is organized as follows:

docs/
├── articles/           AsciiDoc content
├── frontend/
│   └── demo/           TypeScript examples
│       ├── component/  Vaadin component examples in TypeScript
│       ├── domain/     General definitions (1)
│       ├── fusion/     TypeScript UI examples
│       └── flow/       TypeScript counterparts of Java examples (2)
└── src/
    └── main/java/com/vaadin/demo/ Java examples
        ├── component/  Vaadin component examples in Java
        ├── domain/     General definitions (1)
        ├── flow/       Java UI examples
        └── fusion/     Java backends for Fusion TypeScript examples
  1. The general definitions include things like domain objects for example data used in the examples.

  2. See Live Java examples require TypeScript counterpart.

Use include:: to include them in code blocks as follows:

  [source,java]
  ----
  include::{root}/src/main/java/com/vaadin/demo/flow/application/events/EventsLambda.java[tags=snippet,indent=0]
  ----

The tags parameter specifies a tag from where to extract the source code shown in the listing.

The source code has a class with a constructor as follows:

public EventsLambda() {
    // tag::snippet[]
    Button button = new Button("Click me!",
      event -> event.getSource().setText("Clicked!!!"));
    add(button);
    // end::snippet[]
}

The above example shows as follows:

Button button = new Button("Click me!",
  event -> event.getSource().setText("Clicked!!!"));
add(button);

Listing Multiple Files in a Code Box

You can have multiple files in a code box if you specify them inside an example style block. This is a good practice for showing a UI source code example, while having a data model or resource files available.

  [.example]
  --
  [source,java]
  ----
  include::{root}/src/main/java/com/vaadin/demo/flow/application/events/EventsLambda.java[tags=snippet,indent=0]
  ----

  [source,java]
  ----
  include::{root}/src/main/java/com/vaadin/demo/flow/application/events/EventsAnon.java[tags=snippet,indent=0]
  ----
  --

The above looks as follows:

Button button = new Button("Click me!",
  event -> event.getSource().setText("Clicked!!!"));
add(button);

Include Parameters

The include:: statement has the following parameters:

render

Renders a live example, as described in Live Examples.

A live example of a Java class requires that it has a DemoExporter implementation as a static subclass, and that there is a TypeScript counterpart that includes the used components, as described in Live Java Examples Require TypeScript Counterpart.

hidden

Hides the example. This is necessary for TypeScript counterparts of Java examples, which are only included to load component styles, as described in Live Java Examples Require TypeScript Counterpart.

tags=<name>

Specifies tags for extracting a source code snippets. You can give multiple tags separated by semicolons or tags=* to show all tag content. For a convention, you should use snippet for a single snippet in a source file.

The tags in source files have format tag::<name>[] for a start tag and end::<name>[] for an end tag. You can have the same tag multiple times in a file, in which case the their content is concatenated. The tags must be enclosed in code comments: // or /* …​ */ in Java and TypeScript and <!-- …​ -→ in HTML in TypeScript.

indent=<spaces>

Specifies the indentation of the code inside the listing. Without the parameter, the indentation in the source listing is used. You should use indent=0.

group=<name>

Groups the file under a group tab. You should use this for language groups, such as group=Java and group=TypeScript in corresponding include statements. You should not use it if you only have a single group, as it would show an unnecessary tab.

Live Examples

An example is rendered live if the include:: statement contains a render attribute. You also need to contain the example in a [.example] style block. The optional .show-code style shows the code automatically. Otherwise the reader needs to click to open it.

  [.example]
  --
  Here is optional text to describe the Java example.
  You could mention things like the [classname]#Button# class.

  [source,java]
  ----
  include::{root}/src/main/java/com/vaadin/demo/flow/application/events/EventsBasic.java[render,tags=snippet,indent=0,group=Java]
  ----

  Here is optional text to describe the TypeScript example.
  You could mention things like the [methodname]#render()# method.

  [source,typescript]
  ----
  include::{root}/frontend/demo/flow/application/events/events-basic.ts[render, indent=0, group=TypeScript]
  ----
  --

A Java class used to render a live example requires an inner static demo exporter implementation class, such as in the following:

@Route("application-events-lambda")
public class EventsLambda extends Div {
    ...

    public static class Exporter extends DemoExporter<EventsLambda> { // hidden-source-line
    } // hidden-source-line
}

The full listing does not show the lines marked with // hidden-source-line when you toggle Expand code.

The above example renders as follows:

Open in a
new tab

Here is optional text to describe the Java example. You could mention things like the Button class.

Button button = new Button("Click me!");

class MyClickListener implements ComponentEventListener<ClickEvent<Button>> {
    int count = 0;
    @Override
    public void onComponentEvent(ClickEvent<Button> event) {
        event.getSource().setText("You have clicked me " +
                (++count) + " times");
    }
}
button.addClickListener(new MyClickListener());

add(button);

Example Box Styles

As shown above, an example box shows live and multi-language examples with source code. The following styles control its behaviour:

example

The basic example box style.

show-code

Automatically shows the code listing. It is by default initially closed.

[.example.show-code]
render-only

Do not show code listing at all.

[.example.render-only]

Notice that this does not disable the language group tabs. An example box shows them if the include statement has the group parameter.

Single-Language Examples

You can have examples only in one language. In such case, you should leave the group parameter out, as otherwise the example has an unnecessary group tab.

Live Java Examples Require TypeScript Counterpart

Styles for any components that are used in an example are only loaded for TypeScript examples. You therefore always need a TypeScript counterpart for any Java example. Otherwise, the components are not styled and the example appears broken. The TypeScript example does not need to be functional, just contain the needed components.

The example should not have a group parameter, and the TypeScript example should have parameter hidden instead of render.

  [.example.show-code]
  --
  [source,java]
  ----
  include::{root}/src/main/java/com/vaadin/demo/flow/application/events/EventsBasic.java[render,tags=snippet,indent=0,group=Java]
  ----

  [source,typescript]
  ----
  include::{root}/frontend/demo/flow/application/events/events-basic.ts[hidden, indent=0, group=TypeScript]
  ----
  --

The above renders, with the TypeScript code hidden, as follows:

Open in a
new tab
Button button = new Button("Click me!");

class MyClickListener implements ComponentEventListener<ClickEvent<Button>> {
    int count = 0;
    @Override
    public void onComponentEvent(ClickEvent<Button> event) {
        event.getSource().setText("You have clicked me " +
                (++count) + " times");
    }
}
button.addClickListener(new MyClickListener());

add(button);

Inline Examples

Certain technical examples must be unique, so you can’t use include:: described later. For example, examples about Java annotations like @Theme that can only be defined for a single class in an application can’t be inline. Java examples in Vaadin Docs run in a single Vaadin application, so they can’t have more unique definitions.

Code Formatting Conventions

You should keep line length at maximum of around 63 characters.