diff --git a/Makefile b/Makefile index 0f201b0c04a..5d44a6ad76c 100644 --- a/Makefile +++ b/Makefile @@ -79,3 +79,6 @@ fail-warning: check-links: $(SPHINX_BUILD) --check-links + +sphinx-epub: + $(SPHINX_BUILD) --build-epub diff --git a/build.py b/build.py index 97c01453605..270e2eedf71 100644 --- a/build.py +++ b/build.py @@ -2,6 +2,7 @@ import argparse from pathlib import Path +import time from sphinx.application import Sphinx @@ -12,6 +13,7 @@ def create_parser(): parser.add_argument("-l", "--check-links", action="store_true") parser.add_argument("-f", "--build-files", action="store_true") parser.add_argument("-d", "--build-dirs", action="store_true") + parser.add_argument("-e", "--build-epub", action="store_true") # flags / options parser.add_argument("-w", "--fail-on-warning", action="store_true") @@ -49,6 +51,8 @@ def create_index_file(html_root: Path, builder: str) -> None: sphinx_builder = "html" elif args.build_dirs: sphinx_builder = "dirhtml" + elif args.build_epub: + sphinx_builder = "epub" elif args.check_links: sphinx_builder = "linkcheck" else: @@ -59,6 +63,18 @@ def create_index_file(html_root: Path, builder: str) -> None: config_overrides = {} if args.nitpicky: config_overrides["nitpicky"] = True + if sphinx_builder == "epub": + config_overrides |= { + "master_doc": "contents-epub", + "epub_theme": "pep_theme_epub", + "templates_path": ["pep_sphinx_extensions/pep_theme_epub/templates"], + "suppress_warnings": ["epub.unknown_project_files"], + # epub metadata: + "version": time.strftime("%Y-%m-%d"), + "epub_copyright": "PSF", + "epub_description": "Python Enhancement Proposals", + "epub_author": "PEP Authors", + } app = Sphinx( source_directory, diff --git a/contents-epub.rst b/contents-epub.rst new file mode 100644 index 00000000000..a251f120e21 --- /dev/null +++ b/contents-epub.rst @@ -0,0 +1,10 @@ + +Python Enhancement Proposals (PEPs) +*********************************** + +.. toctree:: + :maxdepth: 1 + :titlesonly: + :glob: + + pep-* diff --git a/pep_sphinx_extensions/__init__.py b/pep_sphinx_extensions/__init__.py index 37ffde4081c..9e80b05b266 100644 --- a/pep_sphinx_extensions/__init__.py +++ b/pep_sphinx_extensions/__init__.py @@ -39,8 +39,15 @@ def _depart_maths(): def _update_config_for_builder(app: Sphinx): if app.builder.name == "dirhtml": + # Docutils Node Visitor overrides (dirhtml builder) + app.set_translator("dirhtml", pep_html_translator.PEPTranslator) + + # PEP url overrides config.pep_url = f"../{config.pep_stem}" app.env.settings["pep_file_url_template"] = "../pep-%04d" + elif app.builder.name == "epub": + # Docutils Node Visitor overrides (epub builder) + app.set_translator("epub", pep_html_translator.PEPTranslator) def setup(app: Sphinx) -> dict[str, bool]: @@ -50,7 +57,6 @@ def setup(app: Sphinx) -> dict[str, bool]: app.add_source_parser(pep_parser.PEPParser) # Add PEP transforms app.add_role("pep", pep_role.PEPRole(), override=True) # Transform PEP references to links app.set_translator("html", pep_html_translator.PEPTranslator) # Docutils Node Visitor overrides (html builder) - app.set_translator("dirhtml", pep_html_translator.PEPTranslator) # Docutils Node Visitor overrides (dirhtml builder) app.connect("env-before-read-docs", create_pep_zero) # PEP 0 hook app.connect("builder-inited", _update_config_for_builder) # Update configuration values for builder used diff --git a/pep_sphinx_extensions/pep_theme_epub/static/epub.css b/pep_sphinx_extensions/pep_theme_epub/static/epub.css new file mode 100644 index 00000000000..1a318db2c0c --- /dev/null +++ b/pep_sphinx_extensions/pep_theme_epub/static/epub.css @@ -0,0 +1,266 @@ +@charset "UTF-8"; +/* Styles for PEPs + +Changes for ePub: + - header line height reduced + - horizontal line made invisible + - ePub reading mode added + - link target rules added + - breadcrumbs and sidebar rules removed + +Colours: +white: + background + footnotes/references vertical border +#333 + body text +#888 + blockquote left line + header breadcrumbs separator + link underline (hovered/focussed) +#ccc: + scrollbar +#ddd + header bottom border + horizontal rule + table vertical border +#eee: + link underline + table rows & top/bottom border + PEP header rows + footnotes/references rows + admonition note background +#f8f8f8: + inline code background + +#0072aa: + links +# fee: + admonition warning background + +*/ + +/* Set master rules */ +* {box-sizing: border-box} +html { + overflow-y: scroll; + -webkit-font-smoothing: antialiased; + margin: 0; + line-height: 1.4rem; + font-weight: normal; + font-size: 1rem; + font-family: "Source Sans Pro", Arial, sans-serif; +} +body { + writing-mode: horizontal-tb; + line-break: normal; + -epub-writing-mode: horizontal-tb; + -webkit-writing-mode: horizontal-tb; + -epub-line-break: normal; + -webkit-line-break: normal; + margin: 0; + color: #333; + background-color: white; +} +section#pep-page-section { + padding: 0.25rem 0.25rem 0; + display: table; +} + +/* Reduce margin sizes for body text */ +p {margin: .5rem 0} + +/* Header rules */ +h1.page-title { + line-height: 2.3rem; + font-size: 2rem; + font-weight: bold; + margin-top: 2rem; + margin-bottom: 1.5rem; +} +h2 { + font-size: 1.6rem; + font-weight: bold; + margin-top: 1rem; + margin-bottom: .5rem; +} +h3 { + font-size: 1.4rem; + font-weight: normal; + margin-top: 1rem; + margin-bottom: 0.5rem; +} +h4 { + font-size: 1.2rem; + font-weight: normal; + margin-top: .5rem; + margin-bottom: 0; +} +h5, +h6 { + font-size: 1rem; + font-weight: bold; + margin-top: 0; + margin-bottom: 0; +} + +/* Anchor link rules */ +a, +a:active, +a:visited { + color: #0072aa; + text-decoration-color: #eee; + display: inline; +} +a:hover, +a:focus { + text-decoration-color: #888; +} + +/* Blockquote rules */ +blockquote { + font-style: italic; + border-left: 1px solid #888; + margin: .5rem; + padding: .5rem 1rem; +} +blockquote em { + font-style: normal; +} + +cite { + font-style: italic; +} + +/* Code rules (code literals and Pygments highlighting blocks) */ +pre, +code { + font-family: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "DejaVu Sans Mono", Consolas, monospace; + white-space: pre-wrap; + word-wrap: break-word; + -webkit-hyphens: none; + hyphens: none; +} +code.literal { + font-size: .8em; + background-color: #f8f8f8; +} +pre { + padding: .5rem .75rem; +} + +/* Definition list rules */ +dl dt { + font-weight: bold; +} +dl dd { + margin: 0; +} + +/* Horizontal rule rule */ +hr { + display: none; +} +/*Image rules */ +img { + max-width: 100%; +} +a img { + display: block; + margin: 0 auto; +} + +/* List rules */ +ul, +ol { + padding: 0; + margin: 0 0 0 1.5rem; +} +ul {list-style: square} +ol.arabic {list-style: decimal} +ol.loweralpha {list-style: lower-alpha} +ol.upperalpha {list-style: upper-alpha} +ol.lowerroman {list-style: lower-roman} +ol.upperroman {list-style: upper-roman} + +/* Maths rules */ +sub, +sup { + font-size: .75em; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup {top: -0.5em} +sub {bottom: -0.25em} + +/* Table rules */ +table { + width: 100%; + border-collapse: collapse; + border-top: 1px solid #eee; + border-bottom: 1px solid #eee; +} +table caption { + margin: 1rem 0 .75rem; +} +table tbody tr:nth-of-type(odd) { + background-color: #eee; +} +table th, +table td { + text-align: left; + padding: 0.25rem 0.5rem 0.2rem; +} +table td + td { + border-left: 1px solid #ddd; +} + +/* Admonitions rules */ +div.note, +div.warning { + padding: 0.5rem 0.75rem; + margin-top: 1rem; + margin-bottom: 1rem; +} +div.note { + background-color: #eee; +} +div.warning { + background-color: #fee; +} +p.admonition-title { + font-weight: bold; +} + +/* PEP Header / references rules */ +dl.rfc2822, +dl.footnote { + display: grid; + grid-template-columns: fit-content(30%) auto; + width: 100%; + border-top: 1px solid #eee; + border-bottom: 1px solid #eee; +} +dl.rfc2822 > dt, dl.rfc2822 > dd, +dl.footnote > dt, dl.footnote > dd { + padding: .25rem .5rem .2rem; +} +dl.rfc2822 > dt:nth-of-type(even), dl.rfc2822 > dd:nth-of-type(even), +dl.footnote > dt:nth-of-type(even), dl.footnote > dd:nth-of-type(even) { + background-color: #eee; +} +dl.footnote > dt { + font-weight: normal; + border-right: 1px solid white; +} + +/* Link-target rules */ +.link-target { + font-size: 80%; +} + +table .link-target { + /* Do not show links in tables, there is not enough space */ + display: none; +} diff --git a/pep_sphinx_extensions/pep_theme_epub/templates/page.html b/pep_sphinx_extensions/pep_theme_epub/templates/page.html new file mode 100644 index 00000000000..d1d977a3091 --- /dev/null +++ b/pep_sphinx_extensions/pep_theme_epub/templates/page.html @@ -0,0 +1,19 @@ +{# Master layout template for the PEP epub theme. #} + + + + + + {{ title|striptags|e }} + + + + + +
+
+ {{ body }} +
+
+ + diff --git a/pep_sphinx_extensions/pep_theme_epub/theme.conf b/pep_sphinx_extensions/pep_theme_epub/theme.conf new file mode 100644 index 00000000000..8150ef720fa --- /dev/null +++ b/pep_sphinx_extensions/pep_theme_epub/theme.conf @@ -0,0 +1,4 @@ +[theme] +# Theme options +inherit = none +pygments_style = tango