I am trying to create an EPUB that has a nested chapter structure. There are top-level sections, with sub-chapters, and then subheadings below those sub-chapters. I would like this to be reflected in the TOC. Here is an example of what it looks like:
Section 1
Here is some preamble about what is going to happen in Chapter 1
Chapter 1
This is the contents of Section 1, Chapter 1.
Chapter 2
This is the contents of Section 1, Chapter 2.
Section 2
Preamble for section 2.
Chapter 1
Section 2, Chapter 1.
I have created this MWE that I think should represent the structure I want:
# /// script
# dependencies = [
# "ebooklib"
# ]
# ///
from ebooklib import epub
def create_epub():
book = epub.EpubBook()
book.set_title("Minimal EPUB Example")
book.set_language("en")
book.add_author("Author Name")
# Section 1
section1_preamble = epub.EpubHtml(
title="Section 1 Preamble",
file_name="section1_preamble.xhtml",
content="<h1>Section 1</h1><p>Preamble text...</p>",
)
chapter1 = epub.EpubHtml(
title="Chapter 1",
file_name="chapter1.xhtml",
content="<h2>Chapter 1</h2><p>Content of Chapter 1</p>",
)
chapter2 = epub.EpubHtml(
title="Chapter 2",
file_name="chapter2.xhtml",
content="<h2>Chapter 2</h2><p>Content of Chapter 2</p>",
)
# Section 2
chapter3 = epub.EpubHtml(
title="Chapter 1 (Section 2)",
file_name="chapter3.xhtml",
content="<h2>Chapter 1 (Section 2)</h2><p>Content of Chapter 1 in Section 2</p>",
)
# Add chapters to book
for item in [section1_preamble, chapter1, chapter2, chapter3]:
book.add_item(item)
# Define table of contents with nesting
book.toc = (
(epub.Section("Section 1"), [section1_preamble, chapter1, chapter2]),
(epub.Section("Section 2"), [chapter3]),
)
# Define book spine
book.spine = ["nav", section1_preamble, chapter1, chapter2, chapter3]
# Add navigation files
book.add_item(epub.EpubNcx())
book.add_item(epub.EpubNav())
# Write to file
epub.write_epub("minimal_epub.epub", book, {})
print("EPUB created: minimal_epub.epub")
if __name__ == "__main__":
create_epub()
However, the EPUB this creates doesn't work quite right:
There are three problems I'm having with this:
- The "Section" links don't work (I get a "Destination does not exist" error)
- I would prefer it if the "preamble" text were not its own chapter. I want the "Section" link to be a chapter with sub-chapters.
- I would like it if there were not an enforced page break after each sub-chapter, and certainly not after the preamble. The way I've got it structured now, "Section 1 Preamble" points to this:
But I would like it if "Chapter 1" were a subheading here, directly under "Preamble text". There can still be enforced page breaks at the end of a section.
I am trying to create an EPUB that has a nested chapter structure. There are top-level sections, with sub-chapters, and then subheadings below those sub-chapters. I would like this to be reflected in the TOC. Here is an example of what it looks like:
Section 1
Here is some preamble about what is going to happen in Chapter 1
Chapter 1
This is the contents of Section 1, Chapter 1.
Chapter 2
This is the contents of Section 1, Chapter 2.
Section 2
Preamble for section 2.
Chapter 1
Section 2, Chapter 1.
I have created this MWE that I think should represent the structure I want:
# /// script
# dependencies = [
# "ebooklib"
# ]
# ///
from ebooklib import epub
def create_epub():
book = epub.EpubBook()
book.set_title("Minimal EPUB Example")
book.set_language("en")
book.add_author("Author Name")
# Section 1
section1_preamble = epub.EpubHtml(
title="Section 1 Preamble",
file_name="section1_preamble.xhtml",
content="<h1>Section 1</h1><p>Preamble text...</p>",
)
chapter1 = epub.EpubHtml(
title="Chapter 1",
file_name="chapter1.xhtml",
content="<h2>Chapter 1</h2><p>Content of Chapter 1</p>",
)
chapter2 = epub.EpubHtml(
title="Chapter 2",
file_name="chapter2.xhtml",
content="<h2>Chapter 2</h2><p>Content of Chapter 2</p>",
)
# Section 2
chapter3 = epub.EpubHtml(
title="Chapter 1 (Section 2)",
file_name="chapter3.xhtml",
content="<h2>Chapter 1 (Section 2)</h2><p>Content of Chapter 1 in Section 2</p>",
)
# Add chapters to book
for item in [section1_preamble, chapter1, chapter2, chapter3]:
book.add_item(item)
# Define table of contents with nesting
book.toc = (
(epub.Section("Section 1"), [section1_preamble, chapter1, chapter2]),
(epub.Section("Section 2"), [chapter3]),
)
# Define book spine
book.spine = ["nav", section1_preamble, chapter1, chapter2, chapter3]
# Add navigation files
book.add_item(epub.EpubNcx())
book.add_item(epub.EpubNav())
# Write to file
epub.write_epub("minimal_epub.epub", book, {})
print("EPUB created: minimal_epub.epub")
if __name__ == "__main__":
create_epub()
However, the EPUB this creates doesn't work quite right:
There are three problems I'm having with this:
- The "Section" links don't work (I get a "Destination does not exist" error)
- I would prefer it if the "preamble" text were not its own chapter. I want the "Section" link to be a chapter with sub-chapters.
- I would like it if there were not an enforced page break after each sub-chapter, and certainly not after the preamble. The way I've got it structured now, "Section 1 Preamble" points to this:
But I would like it if "Chapter 1" were a subheading here, directly under "Preamble text". There can still be enforced page breaks at the end of a section.
Share Improve this question asked Feb 6 at 15:07 PaulPaul 10.9k14 gold badges54 silver badges93 bronze badges1 Answer
Reset to default 0So I think I actually figured this out, and all three are solved by:
- Using
epub.Link
or a tuple ofepub.Link
and a tuple ofepub.Link
objects pointing to sub-chapters (recursively, for further hierarchies). - Instead of using
epub.EpubHtml
items for each chapter, concatenating the chapter contents into the top-level chapter and manually adding an<a name="unique-anchor-here">
tag to the chapter heading. which is the target of the links.
Here's an updated MWE:
# /// script
# dependencies = [
# "ebooklib"
# ]
# ///
from ebooklib import epub
def create_epub():
book = epub.EpubBook()
book.set_title("Minimal EPUB Example")
book.set_language("en")
book.add_author("Author Name")
# Section 1
section1 = epub.EpubHtml(
title="Section 1",
file_name="section1.xhtml",
content="<a name='section1'><h1>Section 1</h1><p>Preamble text...</p>\n" +
"<a name='section1-chapter1'><h2>Chapter 1</h2><p>Content of Chapter 1</p>\n" +
"<a name='section1-chapter1'><h2>Chapter 2</h2><p>Content of Chapter 2</p>",
)
# Section 2
chapter3 = epub.EpubHtml(
title="Chapter 1 (Section 2)",
file_name="chapter3.xhtml",
content="<h2>Chapter 1 (Section 2)</h2><p>Content of Chapter 1 in Section 2</p>",
)
# Add chapters to book
for item in [section1, chapter3]:
book.add_item(item)
# Define table of contents with Link
book.toc = [
(epub.Link("section1.xhtml", "Section 1", "sec1"), (
epub.Link("section1.xhtml#section1-chapter1", "Chapter 1", "chap1"),
epub.Link("section1.xhtml#section1-chapter2", "Chapter 2", "chap2"),
)),
epub.Link("chapter3.xhtml", "Chapter 1 (Section 2)", "chap3"),
]
# Define book spine
book.spine = ["nav", section1, chapter3]
# Add navigation files
book.add_item(epub.EpubNcx())
book.add_item(epub.EpubNav())
# Write to file
epub.write_epub("minimal_epub_link.epub", book, {})
print("EPUB created: minimal_epub_link.epub")
if __name__ == "__main__":
create_epub()