30.3. Writing Neo4j Documentation

[Note]Note

Other than writing documentation, you can help out by providing comments — head over to the online HTML version to do that!

For how to build the manual see: readme

The documents use the asciidoc format, see:

The cheatsheet is really useful!

Overall Flow

Each (sub)project has its own documentation, which will produce a docs.jar file. By default this file is assembled from the contents in src/docs/. Asciidoc documents have the .asciidoc file extension.

The documents can use code snippets which will extract code from the project. The corresponding code must be deployed to the sources.jar or test-sources.jar file.

By setting up a unit test accordingly, documentation can be written directly in the JavaDoc comment.

The above files are all consumed by the build of the manual (by adding them as dependencies). To get content included in the manual, it has to be explicitly included by a document in the manual as well.

Note that different ways to add documentation works best for different cases:

  • For detail level documentation, it works well to write the documentation as part of unit tests (in the JavaDoc comment). In this case, you typically do not want to link to the source code in the documentation.
  • For tutorial level documentation, the result will be best by writing a .asciidoc file containing the text. Source snippets and output examples can then be included from there. In this case you typically want to link to the source code, and users should be able to run it without any special setup.

File Structure in docs.jar

Directory Contents

dev/

content aimed at developers

dev/images/

images used by the dev docs

ops/

content aimed at operations

ops/images/

images used by the ops docs

man/

manpages

Additional subdirectories are used as needed to structure the documents, like dev/tutorial/, ops/tutorial/ etc.

Headings and document structure

Each document starts over with headings from level zero (the document title). Each document should have an id. In some cases sections in the document need to have id’s as well, this depends on where they fit in the overall structure. To be able to link to content, it has to have an id. Missing id’s in mandatory places will fail the build.

This is how a document should start:

[[unique-id-verbose-is-ok]]
= The Document Title =

To push the headings down to the right level in the output, the leveloffset attribute is used when including the document inside of another document.

Subsequent headings in a document should use the following syntax:

== Subheading ==

... content here ...

=== Subsubheading ===

content here ...

Asciidoc comes with one more syntax for headings, but in this project it’s not used.

Writing

Put one sentence on each line. This makes it easy to move content around, and also easy to spot (too) long sentences.

Gotchas

  • A chapter can’t be empty. (the build will fail on the docbook xml validity check)
  • Always leave a blank line at the end of documents (or the title of the next document might end up in the last paragraph of the document)
  • As {} are used for Asciidoc attributes, everything inside will be treated as an attribute. What you have to do is to escape the opening brace: \{. If you don’t, the braces and the text inside them will be removed without any warning being issued!

Text Formatting

  • _Italics_ is rendered as Italics and used for emphasis.
  • *Bold* is rendered as Bold and used sparingly, for strong emphasis only.
  • +methodName()+ is rendered as methodName() and is used for literals as well (note: the content between the + signs will be parsed).
  • `command` is rendered as command (typically used for command-line) (note: the content between the ` signs will not be parsed).
  • Mono++space++d is rendered as Monospaced and is used for monospaced letters.
  • 'my/path/' is rendered as my/path/ (used for file names and paths).
  • ``Double quoted'' (that is two grave accents to the left and two acute accents to the right) renders as “Double quoted”.
  • `Single quoted' (that is a single grave accent to the left and a single acute accent to the right) renders as ‘Single quoted’.

Admonitions

These are very useful and should be used where appropriate. Choose from the following (write all caps and no, we can’t easily add new ones):

[Note]Note

Note.

[Tip]Tip

Tip.

[Important]Important

Important

[Caution]Caution

Caution

[Warning]Warning

Warning

Here’s how it’s done:

NOTE: Note.

A multiline variation:

[TIP]
Tiptext.
Line 2.

Which is rendered as:

[Tip]Tip

Tiptext. Line 2.

Images

[Important]Important

All images in the entire manual share the same namespace. You know how to handle that.

Images Files

To include an image file, make sure it resides in the images/ directory relative to the document you’re including it from. Then go:

image::neo4j-logo.png[]

Which is rendered as:

Static Graphviz/DOT

We use the Graphviz/DOT language to describe graphs. For documentation see http://graphviz.org/.

This is how to include a simple example graph:

 ["dot", "community-docs-graphdb-rels.svg"]
 ----
 "Start node" -> "End node" [label="relationship"]
 ----

Which is rendered as:

Here’s an example using some predefined variables available in the build:

 ["dot", "community-docs-graphdb-rels-overview.svg", "meta"]
 ----
 "A Relationship" [fillcolor="NODEHIGHLIGHT"]
 "Start node" [fillcolor="NODE2HIGHLIGHT"]
 "A Relationship" -> "Start node" [label="has a"]
 "A Relationship" -> "End node" [label="has a"]
 "A Relationship" -> "Relationship type" [label="has a"]
 "Name" [TEXTNODE]
 "Relationship type" -> "Name" [label="uniquely identified by" color="EDGEHIGHLIGHT" fontcolor="EDGEHIGHLIGHT"]
 ----

Which is rendered as:

The optional second argument given to the dot filter defines the style to use:

  • when not defined: Default styling for nodespace examples.
  • neoviz: Nodespace view generated by Neoviz.
  • meta: Graphs that don’t resemble db contents, but rather concepts.
[Caution]Caution

Keywords of the DOT language have to be surrounded by double quotes when used for other purposes. The keywords include node, edge, graph, digraph, subgraph, and strict.

Attributes

Common attributes you can use in documents:

  • {neo4j-version} - rendered as "2.1.6"
  • {neo4j-git-tag} - rendered as "2.1.6"
  • {lucene-version} - rendered as "3_6_2"

These can substitute part of URLs that point to for example APIdocs or source code. Note that neo4j-git-tag also handles the case of snapshot/master.

Sample Asciidoc attributes which can be used:

  • {docdir} - root directory of the documents
  • {nbsp} - non-breaking space

Comments

There’s a separate build including comments. The comments show up with a yellow background. This build doesn’t run by default, but after a normal build, you can use make annotated to build it. You can also use the resulting page to search for content, as the full manual is on a single page.

Here’s how to write a comment:

// this is a comment

The comments are not visible in the normal build. Comment blocks won’t be included in the output of any build at all. Here’s a comment block:

////
Note that includes in here will still be processed, but not make it into the output.
That is, missing includes here will still break the build!
////

Code Snippets

Explicitly defined in the document

[Warning]Warning

Use this kind of code snippets as little as possible. They are well known to get out of sync with reality after a while.

This is how to do it:

 [source,cypher]
 ----
 start n=(2, 1) where (n.age < 30 and n.name = "Tobias") or not(n.name = "Tobias")  return n
 ----

Which is rendered as:

start n=(2, 1) where (n.age < 30 and n.name = "Tobias") or not(n.name = "Tobias")  return n

If there’s no suitable syntax highlighter, just omit the language: [source].

Currently the following syntax highlighters are enabled:

  • Bash
  • Cypher
  • Groovy
  • Java
  • JavaScript
  • Python
  • XML

For other highlighters we could add see http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/.

Fetched from source code

Code can be automatically fetched from source files. You need to define:

  • component: the artifactId of the Maven coordinates,
  • source: path to the file inside the jar it’s deployed to,
  • classifier: sources or test-sources or any other classifier pointing to the artifact,
  • tag: tag name to search the file for,
  • the language of the code, if a corresponding syntax highlighter is available.

Note that the artifact has to be included as a Maven dependency of the Manual project so that the files can be found.

Be aware of that the tag "abc" will match "abcd" as well. It’s a simple on/off switch, meaning that multiple occurrences will be assembled into a single code snippet in the output. This behavior can be user to hide away assertions from code examples sourced from tests.

This is how to define a code snippet inclusion:

 [snippet,java]
 ----
 component=neo4j-examples
 source=org/neo4j/examples/JmxDocTest.java
 classifier=test-sources
 tag=getStartTime
 ----

This is how it renders:

private static Date getStartTimeFromManagementBean(
        GraphDatabaseService graphDbService )
{
    ObjectName objectName = JmxUtils.getObjectName( graphDbService, "Kernel" );
    Date date = JmxUtils.getAttribute( objectName, "KernelStartTime" );
    return date;
}

Query Results

There’s a special filter for Cypher query results. This is how to tag a query result:

 .Result
 [queryresult]
 ----
 +----------------------------------+
 | friend_of_friend.name | count(*) |
 +----------------------------------+
 | Ian                   | 2        |
 | Derrick               | 1        |
 | Jill                  | 1        |
 +----------------------------------+
 3 rows, 12 ms
 ----

This is how it renders:

Result

friend_of_friend.namecount(*)
3 rows, 12 ms

Ian

2

Derrick

1

Jill

1

A sample Java based documentation test

For Java, there are a couple of premade utilities that keep code and documentation together in Javadocs and code snippets that generate Asciidoc for the rest of the toolchain.

To illustrate this, look at the following documentation that generates the Asciidoc file hello-world-title.asciidoc with a content of:

[[examples-hello-world-sample-chapter]]
Hello world Sample Chapter
==========================

This is a sample documentation test, demonstrating different ways of
bringing code and other artifacts into Asciidoc form. The title of the
generated document is determined from the method name, replacing "+_+" with
" ".

Below you see a number of different ways to generate text from source,
inserting it into the JavaDoc documentation (really being Asciidoc markup)
via the snippet markers (see below) and programmatic adding with runtime data
in the Java code.

- The annotated graph as http://www.graphviz.org/[GraphViz]-generated visualization:

.Hello World Graph
["dot", "Hello-World-Graph-hello-world-Sample-Chapter.svg", "neoviz", ""]
----
  N0 [
    label = "{Node\[0\]name = \'you\'\l}"
  ]
  N1 [
    label = "{Node\[1\]name = \'I\'\l}"
  ]
  N1 -> N0 [
    color = "#2e3436"
    fontcolor = "#2e3436"
    label = "know\n"
  ]
----

- A sample Cypher query:

[source,cypher]
----
START n = node(1)
RETURN n
----

- A sample text output snippet:

[source]
----
Hello graphy world!
----

- a generated source link to the original GIThub source for this test:

https://github.com/neo4j/neo4j/blob/{neo4j-git-tag}/community/embedded-examples/src/test/java/org/neo4j/examples/DocumentationDocTest.java[DocumentationDocTest.java]

- The full source for this example as a source snippet, highlighted as Java code:

[snippet,java]
----
component=neo4j-examples
source=org/neo4j/examples/DocumentationDocTest.java
classifier=test-sources
tag=sampleDocumentation
----

This is the end of this chapter.

this file is included in this documentation via

  :leveloffset: 3
  include::{importdir}/neo4j-examples-docs-jar/dev/examples/hello-world-sample-chapter.asciidoc[]

which renders the following chapter:

Hello world Sample Chapter

This is a sample documentation test, demonstrating different ways of bringing code and other artifacts into Asciidoc form. The title of the generated document is determined from the method name, replacing "_" with " ".

Below you see a number of different ways to generate text from source, inserting it into the JavaDoc documentation (really being Asciidoc markup) via the snippet markers (see below) and programmatic adding with runtime data in the Java code.

  • The annotated graph as GraphViz-generated visualization:

Figure 30.1. Hello World Graph

  • A sample Cypher query:
START n = node(1)
RETURN n
  • A sample text output snippet:
Hello graphy world!
  • a generated source link to the original GIThub source for this test:

DocumentationDocTest.java

  • The full source for this example as a source snippet, highlighted as Java code:
// START SNIPPET: _sampleDocumentation
package org.neo4j.examples;

import org.junit.Test;

import org.neo4j.kernel.impl.annotations.Documented;
import org.neo4j.test.GraphDescription.Graph;

import static org.neo4j.visualization.asciidoc.AsciidocHelper.createGraphVizWithNodeId;
import static org.neo4j.visualization.asciidoc.AsciidocHelper.createOutputSnippet;

public class DocumentationDocTest extends ImpermanentGraphJavaDocTestBase
{
    /**
     * This is a sample documentation test, demonstrating different ways of
     * bringing code and other artifacts into Asciidoc form. The title of the
     * generated document is determined from the method name, replacing "+_+" with
     * " ".
     *
     * Below you see a number of different ways to generate text from source,
     * inserting it into the JavaDoc documentation (really being Asciidoc markup)
     * via the snippet markers (see below) and programmatic adding with runtime data
     * in the Java code.
     *
     * - The annotated graph as http://www.graphviz.org/[GraphViz]-generated visualization:
     *
     * @@graph
     *
     * - A sample Cypher query:
     *
     * @@cypher
     *
     * - A sample text output snippet:
     *
     * @@output
     *
     * - a generated source link to the original GIThub source for this test:
     *
     * @@github
     *
     * - The full source for this example as a source snippet, highlighted as Java code:
     *
     * @@sampleDocumentation
     *
     * This is the end of this chapter.
     */
    @Test
    // signaling this to be a documentation test
    @Documented
    // the graph data setup as simple statements
    @Graph( "I know you" )
    // title is determined from the method name
    public void hello_world_Sample_Chapter()
    {
        // initialize the graph with the annotation data
        data.get();
        gen.get().addTestSourceSnippets( this.getClass(), "sampleDocumentation" );
        gen.get()
                .addGithubTestSourceLink( "github", this.getClass(),
                        "community/embedded-examples" );

        gen.get().addSnippet( "output",
                createOutputSnippet( "Hello graphy world!" ) );

        gen.get().addSnippet(
                "graph",
                createGraphVizWithNodeId( "Hello World Graph", graphdb(),
                        gen.get().getTitle() ) );
        // A cypher snippet referring to the generated graph in the start clause
        gen.get().addSnippet(
                "cypher",
                createCypherSnippet( "start n = node(" + data.get().get( "I" ).getId()
                                     + ") return n" ) );
    }
}
// END SNIPPET: _sampleDocumentation

This is the end of this chapter.

Integrated Live Console

An interactive console can be added and will show up in the online HTML version. An optional title can be added, which will be used for the text of the button.

This is how to do it, using Cypher to define the data, with an empty line to separate it from the query:

 .Interactive Example
 [console]
 ----
 CREATE (n {name: 'Neo4j'})

 MATCH (n)
 return n
 ----

And this is the result:

Interactive Example. CREATE (n {name: 'Neo4j'}) MATCH (n) return n

Toolchain

Useful links when configuring the docbook toolchain: