# Editing

In this chapter, we explain how to edit, build, preview, and serve the book locally. You can use any text editors to edit the book, and we will show some tips for using the RStudio IDE. We will introduce the underlying R functions for building, previewing, and serving the book before we introduce the editor, so that you really understand what happens behind the scenes when you click a certain button in the RStudio IDE, and can also customize other editors calling these functions.

## Build the book

To build all Rmd files into a book, you can call the `render_book()`\index{bookdown::render\_book()} function in **bookdown**. Below are the arguments of `render_book()`:

```{r eval=FALSE, code=formatR::usage(bookdown::render_book, output=FALSE)}
```

The most important argument is `output_format`, which can take a character string of the output format (e.g., `'bookdown::gitbook'`). You can leave this argument empty, and the default output format will be the first output format specified in the YAML metadata of the first Rmd file or a separate YAML file `_output.yml`, as mentioned in Section \@ref(configuration). If you plan to generate multiple output formats for a book, you are recommended to specify all formats in `_output.yml`.

Once all formats are specified in `_output.yml`, it is easy to write an R or Shell script or Makefile to compile the book. Below is a simple example of using a Shell script to compile a book to HTML (with the GitBook style) and PDF:

```bash
#!/usr/bin/env Rscript

bookdown::render_book("index.Rmd", "bookdown::gitbook")
bookdown::render_book("index.Rmd", "bookdown::pdf_book")
```

The Shell script does not work on Windows (not strictly true, though), but hopefully you get the idea.

The argument `...` is passed to the output format function. Arguments `clean` and `envir` are passed to `rmarkdown::render()`, to decide whether to clean up the intermediate files, and specify the environment to evaluate R code, respectively.

The output directory of the book can be specified via the `output_dir` argument. By default, the book is generated to the `_book` directory. This can also be changed via the `output_dir` field in the configuration file `_bookdown.yml`, so that you do not have to specify it multiple times for rendering a book to multiple output formats. The `new_session` argument has been explained in Section \@ref(new-session). When you set `preview = TRUE`, only the Rmd files specified in the `input` argument are rendered, which can be convenient when previewing a certain chapter, since you do not recompile the whole book, but when publishing a book, this argument should certainly be set to `FALSE`.

When you render the book to multiple formats in the same R session, you need to be careful because the next format may have access to R objects created from the previous format. You are recommended to render the book with a clean environment for each output format. The argument `clean_envir` can be used to clean all objects in the environment specified by `envir`. By default, it is `TRUE` for non-interactive R sessions (e.g., in batch mode). Note that even `clean_envir = TRUE` does not really guarantee the R session is clean. For example, packages loaded when rendering the previous format will remain in the session for the next output format. To make sure each format is rendered in a completely clean R session, you have to actually launch a new R session to build each format, e.g., use the command line

```sh
Rscript -e "bookdown::render_book('index.Rmd', 'bookdown::gitbook')"
Rscript -e "bookdown::render_book('index.Rmd', 'bookdown::pdf_book')"
```

A number of output files will be generated by `render_book()`. Sometimes you may want to clean up the book directory and start all over again, e.g., remove the figure and cache files that were generated automatically from **knitr**. The function `clean_book()` was designed for this purpose. By default, it tells you which output files you can possibly delete. If you have looked at this list of files, and are sure no files were mistakenly identified as output files (you certainly do not want to delete an input file that you created by hand), you can delete all of them using `bookdown::clean_book(TRUE)`. Since deleting files is a relatively dangerous operation, we would recommend that you maintain your book through version control tools such as GIT, or a service that supports backup and restoration, so you will not lose certain files forever if you delete them by mistake.

## Preview a chapter

Building the whole book can be slow when the size of the book is big. Two things can affect the speed of building a book: the computation in R code chunks, and the conversion from Markdown to other formats via Pandoc. The former can be improved by enabling caching in **knitr** using the chunk option `cache = TRUE`, and there is not much you can do to make the latter faster. However, you can choose to render only one chapter at a time using the function `preview_chapter()` in **bookdown**, and usually this will be much faster than rendering the whole book. Only the Rmd files passed to `preview_chapter()` will be rendered.

Previewing the current chapter is helpful when you are only focusing on that chapter, since you can quickly see the actual output as you add more content or revise the chapter. Although the preview works for all output formats, we recommend that you preview the HTML output.

One downside of previewing a chapter is that the cross-references to other chapters will not work, since **bookdown** knows nothing about other chapters in this case. That is a reasonably small price to pay for the gain in speed. Since previewing a chapter only renders the output for that specific chapter, you should not expect that the content of other chapters is correctly rendered as well. For example, when you navigate to a different chapter, you are actually viewing the old output of that chapter (which may not even exist).

## Serve the book

Instead of running `render_book()` or `preview_chapter()` over and over again, you can actually live preview the book in the web browser, and the only thing you need to do is save the Rmd file. The function `serve_book()`\index{bookdown::serve\_book()} in **bookdown** can start a local web server to serve the HTML output based on the **servr** package [@R-servr].

```{r serve-book-usage, eval=FALSE, code=formatR::usage(bookdown::serve_book, output=FALSE)}
```

You pass the root directory of the book to the `dir` argument, and this function will start a local web server so you can view the book output using the server. The default URL to access the book output is `http://127.0.0.1:4321`. If you run this function in an interactive R session, this URL will be automatically opened in your web browser. If you are in the RStudio IDE, the RStudio Viewer will be used as the default web browser, so you will be able to write the Rmd source files and preview the output in the same environment (e.g., source on the left and output on the right).

The server will listen to changes in the book root directory: whenever you modify any files in the book directory, `serve_book()` can detect the changes, recompile the Rmd files, and refresh the web browser automatically. If the modified files do not include Rmd files, it just refreshes the browser (e.g., if you only updated a certain CSS file). This means once the server is launched, all you have to do next is simply write the book and save the files. Compilation and preview will take place automatically as you save files.

If it does not really take too much time to recompile the whole book, you may set the argument `preview = FALSE`, so that every time you update the book, the whole book is recompiled, otherwise only the modified chapters are recompiled via `preview_chapter()`.

The arguments in `...` are passed to `servr::httw()`, and please refer to its help page to see all possible options, such as `daemon` and `port`. There are pros and cons of using `in_session = TRUE` or `FALSE`:

- For `in_session = TRUE`, you will have access to all objects created in the book in the current R session: if you use a daemonized server (via the argument `daemon = TRUE`), you can check the objects at any time when the current R session is not busy; otherwise you will have to stop the server before you can check the objects. This can be useful when you need to interactively explore the R objects in the book. The downside of `in_session = TRUE` is that the output may be different with the book compiled from a fresh R session, because the state of the current R session may not be clean.
- For `in_session = FALSE`, you do not have access to objects in the book from the current R session, but the output is more likely to be reproducible since everything is created from new R sessions. Since this function is only for previewing purposes, the cleanness of the R session may not be a big concern.

You may choose `in_session = TRUE` or `FALSE` depending on your specific use cases. Eventually, you should run `render_book()` from a fresh R session to generate a reliable copy of the book output.

## RStudio IDE

We recommend that you [upgrade](https://www.rstudio.com/products/rstudio/download/) your RStudio IDE\index{RStudio IDE} if your version is lower than 1.0.0. As mentioned in Section \@ref(usage), all R Markdown files must be encoded in UTF-8. This is important especially when your files contain multibyte characters. To save a file with the UTF-8 encoding, you can use the menu `File -> Save with Encoding`, and choose `UTF-8`.

When you click the `Knit` button to compile an R Markdown document in the RStudio IDE, the default function called by RStudio is `rmarkdown::render()`, which is not what we want for books. To call the function `bookdown::render_book()` instead, you can set the `site` field to be `bookdown::bookdown_site` in the YAML metadata of the R Markdown document `index.Rmd`, e.g.,

```yaml
---
title: "A Nice Book"
site: bookdown::bookdown_site
output:
  bookdown::gitbook: default
---
```

When you have set `site: bookdown::bookdown_site` in `index.Rmd`, RStudio will be able to discover the directory as a book source directory,^[This directory has to be an RStudio project.] and you will see a button `Build Book` in the `Build` pane. You can click the button to build the whole book in different formats, and if you click the `Knit` button on the toolbar, RStudio will automatically preview the current chapter, and you do not need to use `preview_chapter()` explicitly.

The **bookdown** package comes with a few addins for RStudio. If you are not familiar with RStudio addins, you may check out the documentation at http://rstudio.github.io/rstudioaddins/. After you have installed the **bookdown** package and use RStudio v0.99.878 or later, you will see a dropdown menu on the toolbar named "Addins"\index{RStudio addin} and menu items like "Preview Book" and "Input LaTeX Math" after you open the menu.

The addin "Preview Book" calls `bookdown::serve_book()` to compile and serve the book. It will block your current R session, i.e., when `serve_book()` is running, you will not be able to do anything in the R console anymore. To avoid blocking the R session, you can daemonize the server using `bookdown::serve_book(daemon = TRUE)`. Note that this addin must be used when the current document opened in RStudio is under the root directory of your book, otherwise `serve_book()` may not be able to find the book source.

The addin "Input LaTeX Math" is essentially a small Shiny application that provides a text box to help you type LaTeX math expressions\index{LaTeX math expression} (Figure \@ref(fig:mathquill)). As you type, you will see the preview of the math expression and its LaTeX source code. This will make it much less error-prone to type math expressions --- when you type a long LaTeX math expression without preview, it is easy to make mistakes such as `X_ij` when you meant `X_{ij}`, or omitting a closing bracket. If you have selected a LaTeX math expression in the RStudio editor before clicking the addin, the expression will be automatically loaded and rendered in the text box. This addin was built on top of the MathQuill library (http://mathquill.com). It is not meant to provide full support to all LaTeX commands for math expressions, but should help you type some common math expressions.

```{r mathquill, echo=FALSE, fig.align='center', fig.cap='The RStudio addin to help input LaTeX math.'}
knitr::include_graphics('images/mathquill.png', dpi = NA)
```

There are also other R packages that provide addins to help you author books. The **citr** package [@R-citr] provides an addin named "Insert citations", which makes it easy to insert citations\index{citation} into R Markdown documents. It scans your bibliography databases, and shows all citation items in a drop-down menu, so you can choose from the list without remembering which citation key corresponds to which citation item (Figure \@ref(fig:citr)).

```{r citr, echo=FALSE, fig.align='center', fig.cap='The RStudio addin to help insert citations.'}
knitr::include_graphics('images/citr.png', dpi = NA)
```

## Collaboration

Writing a book will almost surely involve more than a single person. You may have co-authors, and readers who give you feedback from time to time.

Since all book chapters are plain-text files, they are perfect for version control tools, which means if all your co-authors and collaborators have basic knowledge of a version control tool like GIT, you can collaborate with them on the book content using these tools. In fact, collaboration with GIT is possible even if they do not know how to use GIT, because GitHub\index{GitHub} has made it possible to create and edit files online right in your web browser. Only one person has to be familiar with GIT, and that person can set up the book repository. The rest of the collaborators can contribute content online, although they will have more freedom if they know the basic usage of GIT to work locally.

Readers can contribute in two ways. One way is to contribute content directly, and the easiest way, is through [GitHub pull requests](https://help.github.com/articles/about-pull-requests/) if your book source is hosted on GitHub. Basically, any GitHub user can click the edit button on the page of an Rmd source file, edit the content, and submit the changes to you for your approval. If you are satisfied with the changes proposed (you can clearly see what exactly was changed), you can click a "Merge" button to merge the changes. If you are not satisfied, you can provide your feedback in the pull request, so the reader can further revise it according to your requirements. We mentioned the edit button in the GitBook style in Section \@ref(gitbook-style). That button is linked to the Rmd source of each page, and can guide you to create the pull request. There is no need to write emails back and forth to communicate simple changes, such as fixing a typo.

Another way for readers to contribute to your book is to leave comments. Comments can be left in multiple forms: emails, GitHub issues, or HTML page comments. Here we use Disqus (see Section \@ref(yaml-options)) as an example. Disqus is a service to embed a discussion area on your web pages, and can be loaded via JavaScript. You can find the JavaScript code after you register and create a new forum on Disqus, which looks like this:

```html
<div id="disqus_thread"></div>
<script>
(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = '//yihui.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the
<a href="https://disqus.com/?ref_noscript">
  comments powered by Disqus.</a></noscript>
```

Note that you will need to replace the name `yihui` with your own forum name (this name has to be provided when you create a new Disqus forum). You can save the code to an HTML file named, for example, `disqus.html`. Then you can embed it at the end of every page via the `after_body` option (Figure \@ref(fig:disqus) shows what the discussion area looks like):

```yaml
---
output:
  bookdown::gitbook:
    includes:
      after_body: disqus.html
---
```

```{r disqus, fig.cap='A book page with a discussion area.', out.width='100%', echo=FALSE}
knitr::include_graphics('images/disqus.png', dpi = NA)
```
