{ "metadata": { "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python", "version": "3.7.2", "mimetype": "text/x-python", "codemirror_mode": { "name": "ipython", "version": 3 }, "pygments_lexer": "ipython3", "nbconvert_exporter": "python", "file_extension": ".py" } }, "nbformat_minor": 2, "nbformat": 4, "cells": [ { "cell_type": "markdown", "source": [ "# Jupyter Books\n", "\n", "## 1. Installation\n", "\n", "To install the Jupyter Book command-line interface (CLI), use `pip`!" ], "metadata": { "azdata_cell_guid": "97541c75-b1c9-4e4c-9f0a-f93df4a550ef" } }, { "cell_type": "code", "source": [ "import sys\r\n", "\r\n", "#install jupyter-book\r\n", "cmd = f'{sys.executable} -m pip show jupyter-book'\r\n", "cmdOutput = !{cmd}\r\n", "if len(cmdOutput) > 1 and '0.6.4' in cmdOutput[1]:\r\n", " print('Jupyter-book required version is already installed!')\r\n", "else:\r\n", " !pip install jupyter-book" ], "metadata": { "azdata_cell_guid": "8bd77173-2f63-4bf8-95e8-af2a654fc91e", "tags": [] }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "## 2. Create a new book\r\n", "\r\n", "Create a book using your own notebooks and markdown pages:\r\n", "\r\n", "Note: Notebook and markdown filenames cannot contain spaces" ], "metadata": { "azdata_cell_guid": "6a1b6bb8-9cb8-43d5-878f-2029d1eacb0e" } }, { "cell_type": "code", "source": [ "import os, re, shutil\r\n", "\r\n", "overwrite = False\r\n", "book_name = input('Please provide the path where the book needs to be saved along with the book name ex-> D:\\Book1: ') \r\n", "\r\n", "if (os.path.exists(book_name)):\r\n", " new_book_name = input('A folder named ' + book_name + ' already exists. Enter a new name or the same name to overwrite the existing folder.\\n')\r\n", " if book_name == new_book_name:\r\n", " overwrite = True\r\n", " book_name = new_book_name\r\n", "\r\n", "content_folder = input('Please provide the path to your folder containing notebooks and markdown files: ')\r\n", "\r\n", "while (not os.path.exists(content_folder)):\r\n", " content_folder = input('Cannot find folder ' + content_folder + '. Please provide another path: ')\r\n", " \r\n", "if overwrite:\r\n", " !jupyter-book create \"$book_name\" --content-folder \"$content_folder\" --overwrite\r\n", "else:\r\n", " !jupyter-book create \"$book_name\" --content-folder \"$content_folder\"" ], "metadata": { "azdata_cell_guid": "d1a363f0-d854-4466-be87-d01d4c7e51ef", "tags": [] }, "outputs": [], "execution_count": null }, { "cell_type": "code", "source": [ "# Update toc file, book title and clean up the directores\n", "tocFilePath = os.path.join(book_name, \"_data\", \"toc.yml\")\n", "f = open(tocFilePath, \"r\")\n", "title = ''\n", "replacedString = ''\n", "result = f.read()\n", "f.close()\n", "contentFolders = []\n", "\n", "firstLevelUrls = re.findall(r'^(?:\\s+$[\\r\\n]+)+(\\- url: [a-zA-Z0-9\\\\.\\s\\-\\/]+$[\\r\\n]+)', result, re.MULTILINE)\n", "urls = re.findall(r'- url: [a-zA-Z0-9\\\\.\\s\\-\\/]+$', result, re.MULTILINE)\n", "headers = re.findall(r'- header: [a-zA-Z0-9\\\\.\\s-]+$', result, re.MULTILINE)\n", "\n", "try:\n", " if (firstLevelUrls or headers or urls):\n", " if (firstLevelUrls and len(firstLevelUrls) == 1):\n", " for url in firstLevelUrls:\n", " title = url[url.rindex(os.path.sep)+1:].rstrip()\n", " if (not headers):\n", " markdownUrl = urls[len(urls) -1]\n", " title = markdownUrl[markdownUrl.rindex(os.path.sep)+1:].rstrip()\n", " replacedString = \"\\n- title: %s\\n url: /%s\\n not_numbered: true\\n expand_sections: true\\n sections: %s\" % (title, title, url)\n", " result = result.replace(markdownUrl, '')\n", " else:\n", " replacedString = \"\\n- title: %s\\n url: /%s\\n not_numbered: true\\n\" % (title, title)\n", " result = result.replace(url, replacedString)\n", " if (headers):\n", " for header in headers:\n", " title = header[10:].rstrip()\n", " contentFolders.append(title.lower())\n", " filtered = list(filter(lambda x: (\"%s%s%s\" % (os.path.sep, title.lower(), os.path.sep)) in x, urls))\n", " index = urls.index(filtered[len(filtered)-1])\n", " urlValue = urls[index][urls[index].rindex(os.path.sep)+1:].rstrip()\n", " replacedString = \"\\n- title: %s\\n url: /%s/%s\\n not_numbered: true\\n expand_sections: true\\n sections: \" % (title, title.lower(), urlValue)\n", " result = result.replace(header, replacedString)\n", " result = result.replace(urls[index], '')\n", " del urls[index]\n", " if (urls):\n", " for url in urls:\n", " title = url[url.rindex(os.path.sep)+1:].rstrip()\n", " urlValue = title\n", " if (len(contentFolders) > 0):\n", " folders = url[7:].split(os.path.sep)\n", " if (folders[len(folders)-2] in contentFolders):\n", " parentFolder = contentFolders.index(folders[len(folders)-2])\n", " urlValue = \"%s/%s\" % (contentFolders[parentFolder], title)\n", " replacedString = \"\\n - title: %s\\n url: /%s\" % (title, urlValue)\n", " result = result.replace(url, replacedString)\n", " fwrite = open(tocFilePath, \"w\")\n", " fwrite.write(result)\n", " fwrite.close()\n", " else:\n", " raise SystemExit(f'\\n File Name contains unsupported-characters (ex: underscores) by Jupyter Book.\\n')\n", " # Update the Book title in config file\n", " configFilePath = os.path.join(book_name, \"_config.yml\")\n", " f = open(configFilePath, \"r\")\n", " result = f.read()\n", " f.close()\n", " titleLine = re.search(r'title: [a-zA-Z0-9\\\\.\\s\\-\\/]+$', result, re.MULTILINE).group()\n", " title = 'title: %s' % (os.path.splitext(os.path.basename(book_name))[0])\n", " result = result.replace(titleLine, title)\n", " fwrite = open(configFilePath, \"w\")\n", " fwrite.write(result)\n", " fwrite.close()\n", " # cleanup the directories\n", " with os.scandir(book_name) as root_dir:\n", " for path in root_dir:\n", " if path.is_file() and path.name not in ('_config.yml'):\n", " os.remove(path)\n", " if path.is_dir() and path.name not in ('_data', 'content'):\n", " shutil.rmtree(path)\n", "except Exception as e:\n", " print(str(e))" ], "metadata": { "azdata_cell_guid": "6124730b-f52e-4103-8dbb-e3a62325fb55", "tags": [ "hide_input" ] }, "outputs": [], "execution_count": null }, { "cell_type": "markdown", "source": [ "### Issue: generate_toc.py is missing\r\n", "\r\n", "Jupyter Book uses the Table of Contents to define the structure of your book. For example, your chapters, sub-chapters, etc.\r\n", "\r\n", "Need to manually modify the Table of Contents (located here: mybookname/_data/toc.yml) following structure below:\r\n", "\r\n", "```\r\n", "- title: mytitle # Title of chapter or section\r\n", " url: /myurl # URL of section relative to the /content/ folder.\r\n", " sections: # Contains a list of more entries that make up the chapter's sections\r\n", " not_numbered: true # if the section shouldn't have a number in the sidebar\r\n", " (e.g. Introduction or appendices)\r\n", " expand_sections: true # if you'd like the sections of this chapter to always\r\n", " be expanded in the sidebar.\r\n", " external: true # Whether the URL is an external link or points to content in the book\r\n", "```\r\n", "\r\n", "Example from demo book:\r\n", "\r\n", "```\r\n", "- title: Getting started\r\n", " url: /guide/01_overview\r\n", " not_numbered: true\r\n", " expand_sections: true\r\n", " sections:\r\n", " - title: Create your book\r\n", " url: /guide/02_create\r\n", " - title: Build and publish your book\r\n", " url: /guide/03_build\r\n", " - title: FAQ\r\n", " url: /guide/04_faq\r\n", " - title: How-to and advanced topics\r\n", " url: /guide/05_advanced\r\n", "```" ], "metadata": { "azdata_cell_guid": "5439d5e9-6a98-4255-8afa-3c2ba48bfc7e" } }, { "cell_type": "markdown", "source": [ "## 3. Open your Book!\r\n", "**Run the below cell and click on the link to view your book in Azure Data Studio.**" ], "metadata": { "azdata_cell_guid": "ab100e5c-13f4-484a-9a4a-49bb13cad027" } }, { "cell_type": "code", "source": [ "import re, os\r\n", "from IPython.display import *\r\n", "if os.name == 'nt':\r\n", " display(HTML(\"
You are good to view your book in Azure Data Studio by clicking on the above link.
\"))" ], "metadata": { "azdata_cell_guid": "bd2fe173-66ce-48b3-8dc3-c4d7560953c8" }, "outputs": [], "execution_count": null } ] }