.. Licensed 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.

.. _contributing:

==================================
Contributing to this Documentation
==================================

The documentation lives in its own source tree. We'll start by forking and
cloning the CouchDB documentation GitHub mirror. That will allow us to send the
contribution to CouchDB with a pull request.

If you don't have a GitHub account yet, it is a good time to get one, they are
free. If you don't want to use GitHub, there are alternate ways to
contributing back, that we'll cover next time.

Go to https://github.com/apache/couchdb and click the "fork"
button in the top right. This will create a fork of CouchDB in your GitHub
account. If your account is `username`, your fork lives at
https://github.com/username/couchdb. In the header, it tells me my
"GitHub Clone URL". We need to copy that and start a terminal:

.. code-block:: bash

    $ git clone https://github.com/username/couchdb.git
    $ cd couchdb/src/docs
    $ subl .

I'm opening the whole CouchDB documentation source tree in my favourite editor.
It gives me the usual directory listing:

.. code-block:: bash

    ebin/
    ext/
    .git/
    .gitignore
    images/
    LICENSE
    make.bat
    Makefile
    NOTICE
    rebar.config
    src/
    static/
    templates/
    themes/
    .travis.yml

The documentation sources live in `src/docs/src`, you can safely
ignore all the other files and directories.

First we should determine where we want to document this inside the
documentation. We can look through http://docs.couchdb.org/en/latest/
for inspiration. The `JSON Structure Reference`_ looks like a fine place to
write this up.

.. _JSON Structure Reference: http://docs.couchdb.org/en/latest/json-structure.html

The current state includes mostly tables describing the JSON structure (after
all, that's the title of this chapter), but some prose about the number
representation can't hurt. For future reference, since the topic in the thread
includes views and different encoding in views (as opposed to the storage
engine), we should remember to make a note in the views documentation as well,
but we'll leave this for later.

Let's try and find the source file that builds the file
http://docs.couchdb.org/en/latest/json-structure.html -- we are in luck, under
`share/doc/src` we find the file `json-structure.rst`. That looks promising.
`.rst` stands for ReStructured Text (see
http://thomas-cokelaer.info/tutorials/sphinx/rest_syntax.html
for a markup reference), which is an ASCII format for writing
documents, documentation in this case. Let's have a look and open it.

We see ASCII tables with some additional formatting, all looking like the
final HTML. So far so easy. For now, let's just add to the bottom of this. We
can worry about organising this better later.

We start by adding a new headline::

    Number Handling
    ===============

Now we paste in the rest of the main email of the thread. It is mostly text,
but it includes some code listings. Let's mark them up. We'll turn::

    ejson:encode(ejson:decode(<<"1.1">>)).
    <<"1.1000000000000000888">>

Into::

    .. code-block:: erlang

        ejson:encode(ejson:decode(<<"1.1">>)).
        <<"1.1000000000000000888">>

And we follow along with the other code samples. We turn::

    Spidermonkey

    $ js -h 2>&1 | head -n 1
    JavaScript-C 1.8.5 2011-03-31
    $ js
    js> JSON.stringify(JSON.parse("1.01234567890123456789012345678901234567890"))
    "1.0123456789012346"
    js> var f = JSON.stringify(JSON.parse("1.01234567890123456789012345678901234567890"))
    js> JSON.stringify(JSON.parse(f))
    "1.0123456789012346"

into::

    Spidermonkey::

        $ js -h 2>&1 | head -n 1
        JavaScript-C 1.8.5 2011-03-31
        $ js
        js> JSON.stringify(JSON.parse("1.01234567890123456789012345678901234567890"))
        "1.0123456789012346"
        js> var f = JSON.stringify(JSON.parse("1.01234567890123456789012345678901234567890"))
        js> JSON.stringify(JSON.parse(f))
        "1.0123456789012346"

And then follow all the other ones.

I cleaned up the text a little but to make it sound more like a documentation
entry as opposed to a post on a mailing list.

The next step would be to validate that we got all the markup right. I'll
leave this for later. For now we'll contribute our change back to CouchDB.

First, we commit our changes::

    $ > git commit -am 'document number encoding'
    [main a84b2cf] document number encoding
    1 file changed, 199 insertions(+)

Then we push the commit to our CouchDB fork::

    $ git push origin main

Next, we go back to our GitHub page
https://github.com/username/couchdb and click the "Pull Request"
button. Fill in the description with something useful and hit the
"Send Pull Request" button.

And we're done!

Style Guidelines for this Documentation
=======================================

When you make a change to the documentation, you should make sure that you
follow the style. Look through some files and you will see that the style is
quite straightforward. If you do not know if your formatting is in compliance
with the style, ask yourself the following question::

    Is it needed for correct syntax?

If the answer is ``No.`` then it is probably not.

These guidelines strive be simple, without contradictions and exceptions. The
best style is the one that is followed because it seems to be the natural way of
doing it.

The guidelines
--------------

The guidelines are in descending priority.

#. Syntax

   * Correct syntax is always more important than style. This includes
     configuration files, HTML responses, etc.

#. Encoding

   * All files are ``UTF-8``.

#. Line ending

   * All lines end with ``\n``.
   * No trailing whitespace.

#. Line length

   * The maximum line length is ``90`` characters.

#. Links

   * All internal links are relative.

#. Indentation

   * ``4`` spaces.

#. Titles

   * The highest level titles in a file is over and underlined with ``=``.
   * Lower level titles are underlined with the following characters in
     descending order::

        = - ^ *  + # ` : . " ~ _

   * Over and underline match the title length.

#. Empty lines

   * No empty line at the end of the file.
   * Lists may separated each item with an empty line.
