30.3. Writing Neo4j Documentation
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!
Links
To link to other parts of the manual the id of the target is used. This is how such a reference looks:
<<community-docs-overall-flow>>
Which will render like: the section called “Overall Flow”
Note Just write "see <<target-id>>" and similar, that should suffice in most cases. |
If you need to link to another document with your own link text, this is what to do:
<<target-id, link text that fits in the context>>
Note Having lots of linked text may work well in a web context but is a pain in print, and we aim for both! |
External links are added like this:
http://neo4j.com/[Link text here]
Which renders like: Link text here
For short links it may be better not to add a link text, just do:
http://neo4j.com/
Which renders like: http://neo4j.com/
Note It’s ok to have a dot right after the URL, it won’t be part of the link. |
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 Mono
space
d 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. |
Tip Tip. |
Important Important |
Caution Caution |
Warning Warning |
Here’s how it’s done:
NOTE: Note.
A multiline variation:
[TIP] Tiptext. Line 2.
Which is rendered as:
Tip Tiptext. Line 2. |
Images
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 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.0.2"
- {neo4j-git-tag} - rendered as "2.0.2"
- {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 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
ortest-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.name | count(*) |
---|---|
3 rows, 12 ms | |
|
|
|
|
|
|
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 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 and programmatic adding with runtime data
in the Java code.
- The annotated graph as GraphViz-generated visualization:
- 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:
- 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 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: