Skip to content

Commit

Permalink
adding simple page building
Browse files Browse the repository at this point in the history
  • Loading branch information
choldgraf committed Jul 30, 2019
1 parent 60551fc commit 621c5ec
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 48 deletions.
116 changes: 73 additions & 43 deletions jupyter_book/build.py
Expand Up @@ -219,53 +219,14 @@ def build_book(path_book, path_toc_yaml=None, path_ssg_config=None,

# Convert notebooks or just copy md if no notebook.
if path_url_page.endswith('.ipynb'):
notebook_name = op.splitext(op.basename(path_url_page))[0]
ntbk = nbf.read(path_url_page, nbf.NO_CONVERT)

########################################
# Notebook cleaning

# Clean up the file before converting
cleaner = NotebookCleaner(ntbk)
cleaner.remove_cells(empty=True)
cleaner.clear('stderr')
ntbk = cleaner.ntbk
_clean_notebook_cells(ntbk)

#############################################
# Conversion to HTML
# create a configuration object that changes the preprocessors
c = Config()
c.FilesWriter.build_directory = path_build_new_folder
# So the images are written to disk
c.HTMLExporter.preprocessors = ['nbconvert.preprocessors.ExtractOutputPreprocessor']
# The text used as the text for anchor links. Set to empty since we'll use anchor.js for the links
c.HTMLExporter.anchor_link_text = " "
# Excluding input/output prompts
c.HTMLExporter.exclude_input_prompt = True
c.HTMLExporter.exclude_output_prompt = True

if execute is True:
# Excution of the notebook if we wish
ep = ExecutePreprocessor(timeout=600, kernel_name=kernel_name)
ep.preprocess(ntbk, {'metadata': {'path': op.dirname(path_url_folder)}})

# Define the path to images and then the relative path to where they'll originally be placed
# Decide the path where the images will be placed, relative to the HTML location
path_after_build_folder = path_build_new_folder.split(
os.sep + BUILD_FOLDER_NAME + os.sep)[-1]
path_images_new_folder = op.join(
PATH_IMAGES_FOLDER, path_after_build_folder)
path_images_rel = op.relpath(path_images_new_folder, path_build_new_folder)
PATH_IMAGES_FOLDER, path_after_build_folder)

# Generate HTML from our notebook using the template

output_resources = {'output_files_dir': path_images_rel, 'unique_key': notebook_name}
exp = HTMLExporter(template_file=path_template, config=c)
markdown, resources = exp.from_notebook_node(ntbk, resources=output_resources)

# Now write the markdown and resources
writer = FilesWriter(config=c)
writer.write(markdown, resources, notebook_name=notebook_name)
# Build the HTML for this book
build_page(path_url_page, path_build_new_folder, path_images_new_folder, path_template=path_template)

elif path_url_page.endswith('.md'):
# If a non-notebook file, just copy it over.
Expand Down Expand Up @@ -345,3 +306,72 @@ def build_book(path_book, path_toc_yaml=None, path_ssg_config=None,
msg += ["Your Jupyter Book is now in `{}/`.".format(BUILD_FOLDER_NAME)]
msg += ["Demo your Jupyter book with `make serve` or push to GitHub!"]
print_message_box('\n'.join(msg))


def build_page(path_ntbk, path_html_output, path_media_output=None, execute=False, path_template=None, verbose=False):
"""Build the HTML for a single notebook page.
Inputs
======
path_ntbk : string
The path to a notebook we want to convert.
path_html_output : string
The path to the folder where the HTML will be output.
path_media_output : string | None
If a string, the path to where images should be extracted. If None,
images will be embedded in the HTML.
execute : bool
Whether to execute the notebook before converting
path_template : string
A path to the template used in conversion.
"""
ntbk = nbf.read(path_ntbk, nbf.NO_CONVERT)
notebook_name = op.splitext(op.basename(path_ntbk))[0]

########################################
# Notebook cleaning

# Clean up the file before converting
cleaner = NotebookCleaner(ntbk)
cleaner.remove_cells(empty=True)
cleaner.clear('stderr')
ntbk = cleaner.ntbk
_clean_notebook_cells(ntbk)

#############################################
# Conversion to HTML
# create a configuration object that changes the preprocessors
c = Config()

c.FilesWriter.build_directory = path_html_output
# So the images are written to disk
c.HTMLExporter.preprocessors = ['nbconvert.preprocessors.ExtractOutputPreprocessor']

# The text used as the text for anchor links. Set to empty since we'll use anchor.js for the links
c.HTMLExporter.anchor_link_text = " "

# Excluding input/output prompts
c.HTMLExporter.exclude_input_prompt = True
c.HTMLExporter.exclude_output_prompt = True

if execute is True:
# Excution of the notebook if we wish
ep = ExecutePreprocessor(timeout=600, kernel_name=kernel_name)
ep.preprocess(ntbk, {'metadata': {'path': op.dirname(path_url_folder)}})

# Define the path to images and then the relative path to where they'll originally be placed
if isinstance(path_media_output, str):
path_media_output_rel = op.relpath(path_media_output, path_html_output)

# Generate HTML from our notebook using the template

output_resources = {'output_files_dir': path_media_output_rel, 'unique_key': notebook_name}
exp = HTMLExporter(template_file=path_template, config=c)
html, resources = exp.from_notebook_node(ntbk, resources=output_resources)

# Now write the markdown and resources
writer = FilesWriter(config=c)
writer.write(html, resources, notebook_name=notebook_name)
if verbose:
print("Finished writing notebook to {}".format(path_html_output))
2 changes: 1 addition & 1 deletion jupyter_book/commands/__init__.py
@@ -1,5 +1,5 @@
"""Defines the commands that the CLI will use."""
from .build import build
from .build import build, page
from .create import create
from .upgrade import upgrade
from .run import run
Expand Down
36 changes: 33 additions & 3 deletions jupyter_book/commands/build.py
Expand Up @@ -3,11 +3,12 @@

import argparse

from jupyter_book.build import build_book
from jupyter_book.build import build_book, build_page

DESCRIPTION = ("Convert a collection of Jupyter Notebooks into Jekyll "
"markdown suitable for a course textbook.")
DESCRIPTION = ("Convert a collection of Jupyter Notebooks into HTML "
"suitable for a course textbook.")

DESCRIPTION_PAGE = ("Convert a single Jupyter Notebook into HTML.")

def build():
parser = argparse.ArgumentParser(description=DESCRIPTION)
Expand Down Expand Up @@ -50,3 +51,32 @@ def build():

build_book(PATH_BOOK, PATH_TOC_YAML, CONFIG_FILE,
PATH_TEMPLATE, local_build, execute, overwrite)

def page():
parser = argparse.ArgumentParser(description=DESCRIPTION_PAGE)
parser.add_argument(
"path_ntbk", help="Path to the notebook you'll convert.")
parser.add_argument(
"path_html_output", help="Path to the folder where HTML will be placed.")
parser.add_argument("template", help="Path to a template to render the HTML")
parser.add_argument("--path_media_output", default=None,
help="The path to where images should be extracted")
parser.add_argument("--execute", action='store_true', help="Execute the notebook before converting")
parser.set_defaults(execute=False)

###############################################
# Default values and arguments

args = parser.parse_args(sys.argv[2:])
execute = bool(args.execute)

# Paths for our notebooks
PATH_PAGE = op.abspath(args.path_ntbk)
PATH_HTML_OUTPUT = op.abspath(args.path_html_output)
PATH_MEDIA_OUTPUT = args.path_media_output if args.path_media_output is not None else PATH_HTML_OUTPUT

# Choose the template we'll use
path_template = op.abspath(args.template)

build_page(PATH_PAGE, PATH_HTML_OUTPUT, PATH_MEDIA_OUTPUT,
execute, path_template)
3 changes: 2 additions & 1 deletion jupyter_book/main.py
@@ -1,7 +1,7 @@
import sys
import argparse

from .commands import build, create, upgrade, version
from .commands import build, create, upgrade, version, page
from .run import run_book
from .toc import build_toc

Expand All @@ -10,6 +10,7 @@
" Jekyll. Type `jupyter-book <command> -h` for help.")
commands = {'create': create,
'build': build,
'page': page,
'upgrade': upgrade,
'run': run_book,
'toc': build_toc,
Expand Down

0 comments on commit 621c5ec

Please sign in to comment.