// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
= Apache Ignite Documentation
:toc:
:toc-title:

== Overview
The Apache Ignite documentation is maintained in the repository with the code base, in the "/docs" subdirectory. The directory contains the source files, HTML templates and css styles.


The Apache Ignite documentation is written in link:https://asciidoctor.org/docs/what-is-asciidoc/[asciidoc].
The Asciidoc files are compiled into HTML pages and published to https://ignite.apache.org/docs.


.Content of the “docs” directory
[cols="1,4",opts="stretch"]
|===
| pass:[_]docs  | The directory with .adoc files and code-snippets.
| pass:[_]config.yml | Jekyll configuration file.
|===


== Building the Docs Locally

To build the docs locally, you can install `jekyll` and other dependencies on your machine, or you can use Jekyll docker image.

=== Install Jekyll and Asciidoctor

. Install Jekyll by following this instruction:  https://jekyllrb.com/docs/installation/[window=_blank]
. In the “/docs” directory, run the following command:
+
[source, shell]
----
$ bundle
----
+
This should install all dependencies, including `asciidoctor`.
. Start jekyll:
+
[source, shell]
----
$ bundle exec jekyll s
----
The command compiles the Asciidoc files into HTML pages and starts a local webserver.

Open `http://localhost:4000/docs[window=_blank]` in your browser.

=== Run with Docker

The following command starts jekyll in a container and downloads all dependencies. Run the command in the “/docs” directory.

[source, shell]
----
$ docker run -v "$PWD:/srv/jekyll" -p 4000:4000 jekyll/jekyll:latest jekyll s
----

Open `http://localhost:4000/docs[window=_blank]` in your browser.

== How to Contribute

If you want to contribute to the documentation, add or modify the relevant page in the `docs/_docs` directory.
This directory contains all .adoc files (which are then rendered into HTML pages and published on the web-site).

Because we use asciidoc for documentation, consider the following points:

* Get familiar with the asciidoc format: https://asciidoctor.org/docs/user-manual/. You don’t have to read the entire manual. Search through it when you want to learn how to create a numbered list, or insert an image, or use italics.
* Please read the link:https://asciidoctor.org/docs/asciidoc-recommended-practices:[AsciiDoc Recommended Practices] and try to adhere to those when editing the .adoc source files.


The following sections explain specific asciidoc syntax that we use.

=== Table of content

The table of content is defined in the `_data/toc.yaml` file.
If you want to add a new page, make sure to update the TOC.

=== Links to other sections in the docs
All .adoc files are located in the "docs/_docs" directory.
Any link to the files within the directory must be relative to that directory.
Remove the file extension (.adoc).

For example:
[source, adoc]
----
link:persistence/native-persistence[Native Persistence]
----

This is a link to the Native Persistence page.

=== Links to external resources

When referencing an external resource, make the link to open in a new window by adding the `window=_blank` attribute:

[source, adoc]
----
link:https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html#SunJSSE_Protocols[Supported protocols,window=_blank]
----


=== Tabs

We use custom syntax to insert tabs. Tabs are used to provide code samples for different programming languages.

Tabs are defined by the `tabs` block:
```
[tabs]
--
individual tabs are defined here
--
```

Each tab is defined by the 'tab' directive:

```
tab:tab_name[]
```

where `tab_name` is the title of the tab.

The content of the tab is everything that is given between the tab title, and the next tab or the end of the block.

```asciidoc
[tabs]
--
tab:XML[]

The content of the XML tab goes here

tab:Java[]

The content of the Java tab is here

tab:C#/.NET[]

tab:C++[unsupported]

--
```

=== Code Snippets

Code snippets must be taken from a compilable source code file (e.g. java, cs, js, etc).
We use the `include` feature of asciidoc.
Source code files are located in the `docs/_docs/code-snippets/{language}` folders.


To add a code snippet to a page, follow these steps:

* Create a file in the code snippets directory, e.g. _docs/code-snippets/java/org/apache/ignite/snippets/JavaThinClient.java

* Enclose the piece of code you want to include within named tags (see https://asciidoctor.org/docs/user-manual/#by-tagged-regions). Give the tag a self-evident name.
For example:
+
```
[source, java]
----
// tag::clientConnection[]
ClientConfiguration cfg = new ClientConfiguration().setAddresses("127.0.0.1:10800");
try (IgniteClient client = Ignition.startClient(cfg)) {
    ClientCache<Integer, String> cache = client.cache("myCache");
    // get data from the cache
}
// end::clientConnection[]
----
```

* Include the tag in the adoc file:
+
[source, adoc,subs="macros"]
----
\include::{javaCodeDir}/JavaThinClient.java[tag=clientConnection,indent=0]
----
