Skip to content
Snippets Groups Projects
Unverified Commit e1f2efe8 authored by Tomas Beuzen's avatar Tomas Beuzen Committed by GitHub
Browse files

:sparkles: NEW: Add `jupyter-book create --cookiecutter` (#888)

This adds a `--cookiecutter` option to `jb create`, to allow users to use the [Jupyter Book cookiecutter](https://github.com/executablebooks/cookiecutter-jupyter-book

) to create a book template:

```console
jupyter-book create --cookiecutter mybookpath/
```

Co-authored-by: default avatarChris Sewell <chrisj_sewell@hotmail.com>
parent d2baf1a8
No related branches found
No related tags found
No related merge requests found
...@@ -49,6 +49,7 @@ Note this warning from the [`ghp-import` GitHub repository](https://github.com/d ...@@ -49,6 +49,7 @@ Note this warning from the [`ghp-import` GitHub repository](https://github.com/d
"...*`ghp-import` will DESTROY your gh-pages branch...and assumes that the `gh-pages` branch is 100% derivative. You should never edit files in your `gh-pages` branch by hand if you're using this script...*" "...*`ghp-import` will DESTROY your gh-pages branch...and assumes that the `gh-pages` branch is 100% derivative. You should never edit files in your `gh-pages` branch by hand if you're using this script...*"
``` ```
(publish/gh-actions)=
## Automatically host your book with GitHub Actions ## Automatically host your book with GitHub Actions
[GitHub Actions](https://docs.github.com/en/actions) is a tool that allows you to automate things on GitHub. [GitHub Actions](https://docs.github.com/en/actions) is a tool that allows you to automate things on GitHub.
...@@ -83,6 +84,20 @@ Ensure that Jupyter Book's version in your `requirements.txt` file is at least ...@@ -83,6 +84,20 @@ Ensure that Jupyter Book's version in your `requirements.txt` file is at least
`0.7.0`. `0.7.0`.
``` ```
:::{tip}
You can use the [Jupyter Book cookiecutter](https://github.com/executablebooks/cookiecutter-jupyter-book), to quickly create a book template that already includes the GitHub Actions workflow file needed to automatically deploy your book to GitHub Pages:
```bash
jupyter-book create --cookiecutter mybookpath/
```
For more help, see the [Jupyter Book cookiecutter GitHub repository](https://github.com/executablebooks/cookiecutter-jupyter-book), or run:
```bash
jupyter-book create --help
```
:::
Here is a simple YAML configuration Here is a simple YAML configuration
for a github action that will publish your book to a `gh-pages` branch. for a github action that will publish your book to a `gh-pages` branch.
......
...@@ -85,6 +85,22 @@ And it will generate a TOC for you. Note that there must be at least one content ...@@ -85,6 +85,22 @@ And it will generate a TOC for you. Note that there must be at least one content
file in each folder in order for any sub-folders to be parsed. file in each folder in order for any sub-folders to be parsed.
```` ````
:::{tip}
Jupyter Book also provides a [cookiecutter](https://github.com/executablebooks/cookiecutter-jupyter-book) that can be used to interactively create a book directory structure.
The cookiecutter is suitable for more advanced users that want to create a ready-to-go repository to host their book that includes pre-populated metafiles such as README, LICENSE, CONDUCT, CONTRIBUTING, etc., as well as GitHub Actions workflow files to {ref}`publish/gh-actions`.
To try the cookiecutter template, run the following command:
```bash
jupyter-book create mybookpath/ --cookiecutter
```
For more help, see the [Jupyter Book cookiecutter GitHub repository](https://github.com/executablebooks/cookiecutter-jupyter-book), or run:
```bash
jupyter-book create --help
```
:::
### Inspecting your book's contents ### Inspecting your book's contents
Let's take a quick look at some important files in the demo book you created: Let's take a quick look at some important files in the demo book you created:
......
...@@ -11,7 +11,7 @@ more popular ones. ...@@ -11,7 +11,7 @@ more popular ones.
Regardless of the approach you use for publishing your book online, it will require Regardless of the approach you use for publishing your book online, it will require
you to host your book's content in an online repository such as GitHub. This section describes one approach you can use to create your own GitHub repository and add your book's content to it. you to host your book's content in an online repository such as GitHub. This section describes one approach you can use to create your own GitHub repository and add your book's content to it.
1. First, log-in to GitHub, then go to the "create a new repository" page:<https://github.com/new> 1. First, log-in to GitHub, then go to the "create a new repository" page: <https://github.com/new>
2. Next, give your online repository a name and a description. Make your repository public and do not initialize with a README file, then click "Create repository". 2. Next, give your online repository a name and a description. Make your repository public and do not initialize with a README file, then click "Create repository".
......
...@@ -263,11 +263,26 @@ def build( ...@@ -263,11 +263,26 @@ def build(
@main.command() @main.command()
@click.argument("path-book", type=click.Path(file_okay=False, exists=False)) @click.argument("path-book", type=click.Path(file_okay=False, exists=False))
def create(path_book): @click.option(
"""Create a simple Jupyter Book that you can customize.""" "--cookiecutter",
is_flag=True,
help="Use cookiecutter to interactively create a Jupyter Book template.",
)
def create(path_book, cookiecutter):
"""Create a Jupyter Book template that you can customize."""
book = Path(path_book) book = Path(path_book)
template_path = Path(__file__).parent.parent.joinpath("book_template") if not cookiecutter: # this will be the more common option
sh.copytree(template_path, book) template_path = Path(__file__).parent.parent.joinpath("book_template")
sh.copytree(template_path, book)
else:
cc_url = "gh:executablebooks/cookiecutter-jupyter-book"
try:
from cookiecutter.main import cookiecutter
except ModuleNotFoundError as e:
_error(
f"{e}. To install, run\n\n\tpip install cookiecutter", kind=e.__class__,
)
book = cookiecutter(cc_url, output_dir=Path(path_book))
_message_box(f"Your book template can be found at\n\n {book}{os.sep}") _message_box(f"Your book template can be found at\n\n {book}{os.sep}")
...@@ -390,8 +405,7 @@ def myst(): ...@@ -390,8 +405,7 @@ def myst():
"--kernel", help="The name of the Jupyter kernel to attach to this markdown file." "--kernel", help="The name of the Jupyter kernel to attach to this markdown file."
) )
def init(path, kernel): def init(path, kernel):
"""Add Jupytext metadata for your markdown file(s), with optional Kernel name. """Add Jupytext metadata for your markdown file(s), with optional Kernel name."""
"""
from ..utils import init_myst_file from ..utils import init_myst_file
for ipath in path: for ipath in path:
...@@ -441,7 +455,7 @@ def sphinx(ctx, path_source, config, toc): ...@@ -441,7 +455,7 @@ def sphinx(ctx, path_source, config, toc):
def find_config_path(path: Path) -> Tuple[Path, bool]: def find_config_path(path: Path) -> Tuple[Path, bool]:
""" checks for any _config.yml file in current/parent dirs. """checks for any _config.yml file in current/parent dirs.
if found then returns the path which has _config.yml, if found then returns the path which has _config.yml,
else returns the present dir as the path. else returns the present dir as the path.
""" """
......
...@@ -29,6 +29,7 @@ test_reqs = [ ...@@ -29,6 +29,7 @@ test_reqs = [
"sphinx_tabs", "sphinx_tabs",
"pyppeteer", "pyppeteer",
"beautifulsoup4", "beautifulsoup4",
"cookiecutter",
] + doc_reqs ] + doc_reqs
setup( setup(
name="jupyter-book", name="jupyter-book",
......
...@@ -23,6 +23,18 @@ def test_create(temp_with_override: Path, cli): ...@@ -23,6 +23,18 @@ def test_create(temp_with_override: Path, cli):
assert len(list(book.iterdir())) == 9 assert len(list(book.iterdir())) == 9
def test_create_from_cookiecutter(temp_with_override: Path, cli):
book = temp_with_override / "new_book"
result = cli.invoke(commands.create, [book.as_posix(), "--cookiecutter"])
assert result.exit_code == 0
# this test uses default cookiecutter prompt values
# note that default cookiecutter book name is "my_book"
assert book.joinpath("my_book", "my_book", "_config.yml").exists()
assert len(list(book.joinpath("my_book").iterdir())) == 7
assert len(list(book.joinpath("my_book", ".github", "workflows").iterdir())) == 1
assert len(list(book.joinpath("my_book", "my_book").iterdir())) == 8
def test_build_from_template(temp_with_override, cli): def test_build_from_template(temp_with_override, cli):
"""Test building the book template and a few test configs.""" """Test building the book template and a few test configs."""
# Create the book from the template # Create the book from the template
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment