2097 lines
101 KiB
Python
2097 lines
101 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Generate a test EPUB that exercises edge cases in spine/TOC relationships.
|
|
|
|
Edge cases covered:
|
|
|
|
1. Multiple TOC entries → single spine item (via fragment anchors)
|
|
- frontmatter.xhtml: Dedication (#dedication), Epigraph (#epigraph),
|
|
Foreword (#foreword) — three TOC entries, one spine item
|
|
- chapter3.xhtml: Chapter 3 heading + three sub-sections
|
|
(#the-reef, #the-current, #the-depths) — four TOC entries, one spine item
|
|
- chapter5.xhtml: Chapter 5 heading + three sub-sections
|
|
(#isle-of-echoes, #compass-rose-atoll, #whirlpool-narrows) — four TOC entries
|
|
- appendix.xhtml: Appendix A (#appendix-a), B (#appendix-b),
|
|
C (#appendix-c), D (#appendix-d), E (#appendix-e)
|
|
— five TOC entries, one spine item (D and E are deliberately tiny)
|
|
|
|
2. Single TOC entry → multiple spine items (chapter spans files)
|
|
- Chapter 2: chapter2_part1.xhtml + chapter2_part2.xhtml — one TOC entry,
|
|
two spine items
|
|
- Chapter 4: chapter4_part1.xhtml + chapter4_part2.xhtml +
|
|
chapter4_part3.xhtml — one TOC entry, three spine items
|
|
|
|
3. Spine item with no TOC entry
|
|
- interlude.xhtml: present in spine order, absent from TOC nav
|
|
|
|
4. TOC entry pointing to mid-file anchor (not file start)
|
|
- backmatter.xhtml#colophon: the file starts with an Author's Note,
|
|
but only the mid-file Colophon anchor appears in the TOC
|
|
|
|
5. Nested TOC hierarchy
|
|
- Chapter 3 and Chapter 5 use nested <ol> sub-entries in the nav
|
|
|
|
6. Normal 1:1 spine-to-TOC mapping (baseline)
|
|
- chapter1.xhtml: one spine item, one TOC entry
|
|
"""
|
|
|
|
import io
|
|
import os
|
|
import zipfile
|
|
import uuid
|
|
from datetime import datetime
|
|
|
|
try:
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
except ImportError:
|
|
print("Please install Pillow: pip install Pillow")
|
|
exit(1)
|
|
|
|
|
|
_PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
_BOOKERLY_FONT = os.path.join(
|
|
_PROJECT_ROOT, "lib", "EpdFont", "builtinFonts", "source",
|
|
"Bookerly", "Bookerly-Regular.ttf",
|
|
)
|
|
|
|
|
|
def _get_font(size=20):
|
|
"""Get the Bookerly font at the requested size, with system fallbacks."""
|
|
for path in [_BOOKERLY_FONT]:
|
|
try:
|
|
return ImageFont.truetype(path, size)
|
|
except (OSError, IOError):
|
|
continue
|
|
return ImageFont.load_default(size)
|
|
|
|
|
|
def _draw_text_centered(draw, y, text, font, fill, width):
|
|
bbox = draw.textbbox((0, 0), text, font=font)
|
|
text_width = bbox[2] - bbox[0]
|
|
x = (width - text_width) // 2
|
|
draw.text((x, y), text, font=font, fill=fill)
|
|
|
|
|
|
def create_cover_image():
|
|
"""Generate a cover image and return JPEG bytes."""
|
|
width, height = 536, 800
|
|
bg_color = (15, 55, 65)
|
|
text_color = (225, 220, 205)
|
|
|
|
img = Image.new("RGB", (width, height), bg_color)
|
|
draw = ImageDraw.Draw(img)
|
|
|
|
font_title = _get_font(72)
|
|
font_subtitle = _get_font(26)
|
|
font_author = _get_font(14)
|
|
font_ornament = _get_font(64)
|
|
|
|
title_lines = ["Spine", "& Anchor"]
|
|
title_y = 140
|
|
for line in title_lines:
|
|
_draw_text_centered(draw, title_y, line, font_title, text_color, width)
|
|
title_y += 90
|
|
|
|
ornament_y = title_y + 10
|
|
_draw_text_centered(draw, ornament_y, "*", font_ornament, text_color, width)
|
|
|
|
subtitle_y = ornament_y + 72
|
|
_draw_text_centered(draw, subtitle_y, "A Nautical Misadventure",
|
|
font_subtitle, text_color, width)
|
|
|
|
_draw_text_centered(draw, height - 70, "CROSSPOINT TEST FIXTURES",
|
|
font_author, text_color, width)
|
|
|
|
buf = io.BytesIO()
|
|
img.save(buf, "JPEG", quality=90)
|
|
return buf.getvalue()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Book metadata
|
|
# ---------------------------------------------------------------------------
|
|
|
|
BOOK_UUID = str(uuid.uuid5(uuid.NAMESPACE_URL, "crosspoint:test:spine-anchor"))
|
|
TITLE = "Spine & Anchor: A Nautical Misadventure"
|
|
AUTHOR = "Crosspoint Test Fixtures"
|
|
DATE = datetime.now().strftime("%Y-%m-%d")
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# FRONTMATTER — three TOC anchors in one spine item
|
|
# ---------------------------------------------------------------------------
|
|
|
|
FRONTMATTER = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head><title>Front Matter</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/></head>
|
|
<body>
|
|
|
|
<h2 id="dedication">Dedication</h2>
|
|
|
|
<p>For every reader whose bookmark landed on the wrong page, and every
|
|
navigator whose chart placed the lighthouse on the wrong shore.</p>
|
|
|
|
<h2 id="epigraph">Epigraph</h2>
|
|
|
|
<blockquote>
|
|
<p>“A captain who trusts a single table of contents has never
|
|
sailed past the edge of a spine.”</p>
|
|
<p>— Admiral Fragmenta, <i>On the Perils of Pagination</i></p>
|
|
</blockquote>
|
|
|
|
<h2 id="foreword">Foreword</h2>
|
|
|
|
<p>The document you hold in your hands — or rather, the document
|
|
your e-reader is attempting to reassemble from its constituent
|
|
parts — is deliberately, almost aggressively, tangled.</p>
|
|
|
|
<p>Some chapters sprawl across multiple files. Others cram several
|
|
table-of-contents entries into a single page. At least one section
|
|
appears in the reading order yet refuses to show up in the table of
|
|
contents at all. And if you look carefully, you will find a table of
|
|
contents entry that points not to the beginning of its file, but to a
|
|
spot squarely in the middle.</p>
|
|
|
|
<p>This is all by design. If your reader survives, it can survive
|
|
anything.</p>
|
|
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# CHAPTER 1 — normal 1:1 spine-to-TOC (baseline)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
CHAPTER_1 = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head><title>Chapter 1</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/></head>
|
|
<body>
|
|
|
|
<h1>Chapter 1<br/>Setting Sail</h1>
|
|
|
|
<p>Anchora had packed three things for the voyage: a sextant with a
|
|
cracked lens, a notebook whose pages were already curling from salt air,
|
|
and an unshakeable conviction that every archipelago deserved a proper
|
|
atlas.</p>
|
|
|
|
<p>The sextant had belonged to her grandmother, a woman who had charted
|
|
the entire Leeward Passage in an open dinghy using nothing but dead
|
|
reckoning and a vocabulary of profanity that could strip barnacles at
|
|
forty paces. The crack in the lens was the result of an encounter with
|
|
a boom during an unexpected jibe — not Anchora’s
|
|
grandmother’s boom, but rather the boom of a racing yacht that
|
|
had cut across her bow in the harbor approaches at a speed the
|
|
grandmother had described, with characteristic understatement, as
|
|
“imprudent.”</p>
|
|
|
|
<p>The notebook was new, purchased from a stationer in the port town
|
|
who specialized in paper for maritime use. It was bound in oilskin and
|
|
stitched with waxed thread, and the pages were a heavy cream stock that
|
|
the stationer claimed would resist salt spray, coffee spills, and the
|
|
tears of frustrated navigators in roughly equal measure. Anchora had
|
|
tested the first two claims. She hoped not to test the third.</p>
|
|
|
|
<p>“The trouble with charts,” she told the harbour-master
|
|
as he untied her bowline, “is that they assume the world sits
|
|
still long enough to be drawn.”</p>
|
|
|
|
<p>The harbour-master, whose name was Gideon and whose experience of
|
|
the sea was limited to watching it from the end of the municipal pier,
|
|
nodded politely and threw her the rope. He had heard variations of this
|
|
sentiment from every cartographer, surveyor, and marine geologist who
|
|
had passed through his harbour in thirty-one years of service, and he
|
|
had learned that the most efficient response was agreement.</p>
|
|
|
|
<p>“Tides shift, sandbars migrate, and new rocks appear where
|
|
no rocks have any business being,” Anchora continued, warming to
|
|
her theme. She was coiling the bowline with the automatic precision of
|
|
someone who has coiled ten thousand ropes. “By the time you
|
|
publish an atlas, half the coastline has wandered off. You might as well
|
|
try to draw a portrait of a cloud.”</p>
|
|
|
|
<p>“And yet you keep drawing them,” Gideon observed.</p>
|
|
|
|
<p>“And yet I keep drawing them,” Anchora agreed. She
|
|
stowed the coiled rope in the lazarette and checked the halyards. The
|
|
main was neatly furled on the boom; the jib was hanked on and ready.
|
|
Everything was in order. Everything was always in order aboard the
|
|
<i>Pagination</i>. Anchora tolerated chaos in the natural world because
|
|
she had no choice, but she would not tolerate it aboard her own boat.</p>
|
|
|
|
<p>The <i>Pagination</i> was a twenty-eight-foot sloop of a design that
|
|
had been fashionable forty years ago and was now merely practical, which
|
|
suited Anchora considerably better. She had a long waterline, a shallow
|
|
keel for poking into the kind of anchorages that deeper boats could only
|
|
look at wistfully, and a rig that one person could handle in all but
|
|
the most theatrical weather. Her hull was white, her boot-stripe was
|
|
navy, and her name was painted across the transom in gold leaf that was
|
|
beginning, after twelve seasons, to develop the kind of distinguished
|
|
patina that a less generous observer might have called peeling.</p>
|
|
|
|
<p>Anchora had bought her for a sum that the previous owner had
|
|
described as “a bargain” and that Anchora’s bank
|
|
manager had described as “concerning.” That had been eight
|
|
years ago. In the intervening time, the <i>Pagination</i> had carried
|
|
Anchora to thirty-seven islands, through four named storms, across two
|
|
time zones, and into one regrettable encounter with a shipping container
|
|
that had fallen off a freighter in heavy weather and was drifting,
|
|
unmarked, at exactly the height of a sloop’s waterline. The
|
|
encounter had cost Anchora a starboard stanchion and three weeks in a
|
|
boatyard. The container, so far as she knew, was still drifting.</p>
|
|
|
|
<p>She cast off the stern line and let the <i>Pagination</i> drift clear
|
|
of the dock. The wind was from the northwest at eight knots, which was
|
|
enough to move but not enough to excite. She unfurled the jib, sheeted
|
|
it in, and felt the boat come alive beneath her feet — that small,
|
|
particular pleasure of a hull finding its groove in the water.</p>
|
|
|
|
<p>The harbour fell away behind her: the stone breakwater, the red and
|
|
green channel markers, the row of chandleries and fish restaurants that
|
|
constituted the town’s entire economy. Gideon was still standing
|
|
on the dock, growing smaller. He raised a hand. Anchora raised hers in
|
|
return.</p>
|
|
|
|
<p>Beyond the breakwater, the sea opened up. It was mid-morning and the
|
|
light was the flat, even grey of an overcast day — not dramatic,
|
|
not beautiful, but excellent for navigation. Dramatic light made for
|
|
good paintings but unreliable bearings. Anchora preferred her horizons
|
|
unambiguous.</p>
|
|
|
|
<p>She unrolled the chart she had prepared the night before and pinned
|
|
it to the table in the companionway. It was mostly blank. A few
|
|
coastlines sketched from Admiralty data. A scattering of depth soundings
|
|
copied from a survey that was either thirty or sixty years old,
|
|
depending on which edition you believed. A compass rose in the corner,
|
|
drawn with the care of someone who understood that a compass rose is
|
|
both a tool and a promise.</p>
|
|
|
|
<p>The rest was empty space. White paper waiting for ink. Terra
|
|
incognita, or rather aqua incognita, which sounded less impressive in
|
|
Latin but was considerably more relevant to someone in a boat.</p>
|
|
|
|
<p>She spread a fresh sheet of vellum on the chart table, uncapped her
|
|
pen, and wrote at the top in careful block letters: <b>ATLAS OF THE
|
|
UNCHARTED REACH</b>.</p>
|
|
|
|
<p>Below this she added, in smaller letters: <i>Compiled from original
|
|
observations by A. Vellum, Master Cartographer, aboard the sloop
|
|
Pagination.</i> This was perhaps optimistic — the atlas currently
|
|
contained no observations at all — but Anchora believed in
|
|
stating one’s intentions clearly. A blank atlas was not an
|
|
admission of ignorance; it was a declaration of ambition.</p>
|
|
|
|
<p>She set the pen down, took a bearing on the harbour entrance —
|
|
now two miles astern and shrinking — and plotted her first
|
|
position fix on the chart. A small cross, precisely drawn, with the time
|
|
noted beside it: <i>09:17, departure.</i></p>
|
|
|
|
<p>The first mark on a new chart. It never got old.</p>
|
|
|
|
<p>She adjusted course to the southeast, trimmed the jib, and settled
|
|
into the cockpit with her notebook on her knee. The <i>Pagination</i>
|
|
heeled gently to port and began to make way. The wake streamed out
|
|
behind in a narrow V, the only mark she would leave on the water. By
|
|
evening it would be gone. By tomorrow the sea would have no memory of
|
|
her passage at all.</p>
|
|
|
|
<p>That was the fundamental asymmetry of cartography. The cartographer
|
|
remembers the sea; the sea does not remember the cartographer. You
|
|
could spend a lifetime recording every depth, every current, every
|
|
contour of a coastline, and the ocean would regard you with precisely
|
|
the same indifference it had shown the first person who ever put to
|
|
sea on a log.</p>
|
|
|
|
<p>Anchora found this oddly comforting. It meant the work was never
|
|
finished. It meant there was always another chart to draw.</p>
|
|
|
|
<p>She uncapped her pen again and began to sketch the headland that was
|
|
passing to starboard: a blunt promontory of dark rock, topped with
|
|
scrub grass and a navigation light that blinked every four seconds. She
|
|
noted the light’s characteristics in the margin —
|
|
<i>Fl(1) 4s, 12m, 8M</i> — and added a small annotation about
|
|
the rocks that extended from the headland’s base in a series of
|
|
jagged shelves. These rocks did not appear on the Admiralty chart. They
|
|
were, she suspected, a relatively recent arrival, deposited by a
|
|
landslip that no one had bothered to report to the hydrographic
|
|
office.</p>
|
|
|
|
<p>This was exactly the sort of thing that justified the voyage. The
|
|
official charts were not wrong, exactly. They were merely incomplete.
|
|
And in navigation, incomplete and wrong amounted to the same thing
|
|
when your keel was the instrument of discovery.</p>
|
|
|
|
<p>By noon, the headland was well astern and the coast had receded to
|
|
a thin grey line on the port beam. Anchora made a sandwich from the
|
|
provisions she had stowed in the ice-box — hard cheese, cured
|
|
ham, and bread that would be stale by tomorrow — and ate it in
|
|
the cockpit with one hand on the tiller. The wind was backing toward
|
|
the west and strengthening. She would need to reef before evening.</p>
|
|
|
|
<p>She washed the sandwich down with coffee from the thermos, plotted
|
|
another position fix, and wrote in her notebook: <i>Day 1, 12:30.
|
|
Twenty miles offshore. Wind NW 12 kn, backing. Seas moderate. One
|
|
headland charted, with previously unreported rocks. Atlas begun.</i></p>
|
|
|
|
<p>She had no idea how uncharted things were about to become.</p>
|
|
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# CHAPTER 2 — one TOC entry, TWO spine items
|
|
# ---------------------------------------------------------------------------
|
|
|
|
CHAPTER_2_PART1 = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head><title>Chapter 2 (Part 1)</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/></head>
|
|
<body>
|
|
|
|
<h1>Chapter 2<br/>The Twin Harbors</h1>
|
|
|
|
<p>The first landmark on Anchora’s route was a pair of harbors so
|
|
close together that early cartographers had drawn them as one. Later
|
|
cartographers, attempting to correct the error, had split the entry in
|
|
two — but neglected to update the name on the second sheet. The
|
|
result was a pair of harbors that existed on some charts as a single
|
|
entity and on others as two separate places with the same name,
|
|
separated by a narrow cut of water that was either an inlet, a channel,
|
|
or “the bit in the middle,” depending on whom you
|
|
asked.</p>
|
|
|
|
<p>Anchora first spotted the harbors from three miles out. They
|
|
presented themselves as a low, dark line of wharves and warehouses,
|
|
punctuated by the vertical strokes of mast-heads and the occasional
|
|
plume of woodsmoke from a chandler’s stove. Behind the
|
|
waterfront, the town rose in terraces: whitewashed houses with terracotta
|
|
roofs, a church tower, and what appeared to be either a lighthouse or a
|
|
very ambitious chimney.</p>
|
|
|
|
<p>She consulted her chart. According to the Admiralty edition, this was
|
|
Port Gemini — a single harbor with a single entrance. According
|
|
to the pilot book, it was East Harbor and West Harbor, two separate
|
|
harbors sharing a common breakwater. According to the local fishing
|
|
cooperative’s newsletter, which Anchora had found pinned to a
|
|
notice board during her last provisioning stop, it was “the
|
|
Twins,” and had been called that for longer than anyone could
|
|
remember, which is to say at least forty years.</p>
|
|
|
|
<p>A pilot boat emerged from behind the breakwater as Anchora rounded
|
|
the outer buoy. It was a stubby craft, painted orange, with a cabin
|
|
that looked like it had been designed by someone who believed windows
|
|
were a sign of weakness. A man stood on the foredeck, holding a coiled
|
|
line and wearing an expression of professional neutrality.</p>
|
|
|
|
<p>“So which is East Harbor and which is West?” Anchora
|
|
called across the narrowing gap.</p>
|
|
|
|
<p>“Depends which chart you’re reading,” the pilot
|
|
replied cheerfully. “On mine, you’re entering East. On
|
|
the harbourmaster’s, this is still West. We gave up arguing about
|
|
it years ago.”</p>
|
|
|
|
<p>“And the Admiralty?”</p>
|
|
|
|
<p>“The Admiralty says there’s only one harbor, which will
|
|
come as a surprise to the three hundred boats moored in the other one.
|
|
We sent them a letter about it. Twice. They sent back a form asking us
|
|
to confirm the coordinates of the harbor we were claiming didn’t
|
|
exist, which rather missed the point.”</p>
|
|
|
|
<p>The pilot threw his line to Anchora, who caught it, made it fast to
|
|
the midship cleat, and allowed herself to be towed through the entrance
|
|
at a stately two knots. The breakwater slid past: massive blocks of
|
|
granite, green with weed below the tide line, topped with a rusting
|
|
iron railing and a row of bollards that had seen better centuries.</p>
|
|
|
|
<p>Inside the breakwater, the harbor opened up. It was larger than
|
|
Anchora had expected — a broad basin ringed with pontoons,
|
|
moorings, and the kind of stone quay walls that speak of an era when
|
|
civic infrastructure was built to impress rather than merely to
|
|
function. Fishing boats occupied most of the moorings: trawlers with
|
|
rust-streaked hulls, lobster boats bristling with pots, and the
|
|
occasional sleek yacht that looked profoundly uncomfortable in such
|
|
working company.</p>
|
|
|
|
<p>“This is East Harbor, then?” Anchora asked as the
|
|
pilot pointed her toward an empty berth on the visitors’
|
|
pontoon.</p>
|
|
|
|
<p>“If you like,” the pilot said agreeably. “The
|
|
post office calls it East. The tax office calls it West. The pub calls
|
|
it ‘here.’ I find that last one the most accurate.”
|
|
</p>
|
|
|
|
<p>Anchora secured the <i>Pagination</i> to the pontoon with a bowline
|
|
fore and aft, adjusted the fenders, and stepped ashore. The pontoon
|
|
swayed under her feet in a way that she found pleasantly familiar. Solid
|
|
ground, by contrast, always felt slightly unreliable.</p>
|
|
|
|
<p>She spent the morning exploring the first harbor on foot, making
|
|
notes and sketches. The quay wall was three hundred and twelve paces
|
|
long — she measured it, because that was the kind of person she
|
|
was. The depth alongside ranged from two to four metres, depending on
|
|
the state of the tide, which was semi-diurnal with a range of about two
|
|
metres. There were fourteen pontoons, each capable of berthing eight to
|
|
ten boats. The harbor entrance was fifty metres wide, oriented to the
|
|
southwest, and partially sheltered by the breakwater from the prevailing
|
|
swell.</p>
|
|
|
|
<p>All of this she recorded in her notebook, then transferred to her
|
|
chart in the careful, precise hand that was her professional signature.
|
|
She drew the quay walls in solid black lines, the pontoons in dashed
|
|
lines, the depth contours in fine blue, and added a small compass rose
|
|
in the corner of the inset. It was satisfying work. By lunchtime she
|
|
had a complete survey of what she was, for the sake of her sanity,
|
|
calling East Harbor.</p>
|
|
|
|
<p>In the afternoon she walked through the narrow cut that connected the
|
|
two basins. It was barely thirty metres wide — a slot in the
|
|
rock through which the tide funneled with surprising force. The walls
|
|
of the cut were sheer, rising six or seven metres above the waterline,
|
|
and covered with the layered evidence of centuries of marine growth:
|
|
barnacles, mussels, a fur of green algae, and the occasional optimistic
|
|
sea anemone.</p>
|
|
|
|
<p>Anchora recorded the discrepancy in her notebook — one harbor
|
|
or two? — and sailed the <i>Pagination</i> through the narrow
|
|
cut under engine. The water changed from grey-green to a deep cobalt as
|
|
the bottom dropped away. The echo of the engine bounced off the cut
|
|
walls and returned with a slight delay, as though the passage were
|
|
thinking about what it had heard before deciding to repeat it.</p>
|
|
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
CHAPTER_2_PART2 = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head><title>Chapter 2 (Part 2)</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/></head>
|
|
<body>
|
|
|
|
<p>On the far side of the cut, the second harbor opened like a cupped
|
|
hand. Fishing boats bobbed in neat rows, their hulls painted in fading
|
|
primaries: cadmium red, cerulean blue, chrome yellow. This harbor was
|
|
slightly smaller than the first but considerably busier: a fish market
|
|
was in full cry along the north quay, and the air smelled of brine,
|
|
diesel, and the particular sharp tang of fresh-caught mackerel.</p>
|
|
|
|
<p>Anchora nosed the <i>Pagination</i> into a gap between two lobster
|
|
boats whose skippers were engaged in a conversation conducted entirely
|
|
in hand gestures and appeared to concern the ownership of a crate of
|
|
bait. She made fast, fore and aft, and went ashore with her notebook.</p>
|
|
|
|
<p>The second harbor was, if anything, more confusing than the first.
|
|
It had its own harbourmaster — a different one from the East
|
|
Harbor harbourmaster, which suggested a degree of administrative
|
|
independence that was hard to reconcile with the Admiralty’s
|
|
insistence that this was all one place. It also had its own set of
|
|
charts, posted on a notice board outside the harbourmaster’s
|
|
office, and these charts were not merely different from the Admiralty
|
|
charts; they were different from the charts posted in the East
|
|
Harbor office.</p>
|
|
|
|
<p>“We draw our own,” the West Harbor harbourmaster
|
|
explained when Anchora asked about this. Her name was Constance and she
|
|
had the weathered complexion and steady gaze of someone who had spent
|
|
forty years watching boats do foolish things. “The Admiralty
|
|
charts are… aspirational. We prefer something grounded in what
|
|
we can actually see.”</p>
|
|
|
|
<p>“And East Harbor?”</p>
|
|
|
|
<p>“They draw their own as well. Different from ours, naturally.
|
|
We disagree about the depth in the cut — they say three metres at
|
|
low water, we say two and a half. We also disagree about the location
|
|
of the inner reef — they put it forty metres south of where we
|
|
put it. We have been disagreeing about this for, I believe, about
|
|
seventy years.”</p>
|
|
|
|
<p>“Has anyone thought of measuring?” Anchora
|
|
ventured.</p>
|
|
|
|
<p>Constance gave her a look that suggested this question had been asked
|
|
before and that the answer was both yes and complicated.</p>
|
|
|
|
<p>“Three times,” Constance said. “The first
|
|
survey found three metres. The second found two and a half. The third
|
|
found two point seven but was conducted by the East Harbor
|
|
harbourmaster’s nephew and is therefore inadmissible.”</p>
|
|
|
|
<p>Anchora spent two days surveying the second harbor with the same
|
|
methodical care she had applied to the first. She measured the quay
|
|
walls, sounded the depths, timed the tides, and charted the moorings.
|
|
She also, because she was thorough, measured the cut from both ends and
|
|
found it to be two point six metres at low water springs, which
|
|
satisfied nobody but at least had the virtue of being her own
|
|
measurement.</p>
|
|
|
|
<p>On the second evening, as the sun dropped below the breakwater and
|
|
turned the water in the harbor to molten copper, the pilot boat came
|
|
alongside the <i>Pagination</i>. The pilot — whose name, Anchora
|
|
had learned, was Rufus — was sitting on the gunwale eating an
|
|
apple.</p>
|
|
|
|
<p>“You’ll want to note,” he called across,
|
|
“that neither harbor appears on the Admiralty chart. Officially,
|
|
this is all open water.”</p>
|
|
|
|
<p>“I had noticed,” Anchora said.</p>
|
|
|
|
<p>“The chart shows a straight coastline where we’re
|
|
sitting. No indentation, no breakwater, no harbors. According to the
|
|
Royal Hydrographic Office, we are currently bobbing about in the open
|
|
sea. I sometimes think about this when I’m tying up to the
|
|
pontoon.”</p>
|
|
|
|
<p>Anchora drew both harbors on a single sheet — one chart, two
|
|
basins, no ambiguity — and labeled it with coordinates she
|
|
trusted rather than names she did not. She drew the cut at its correct
|
|
width, marked the depth as 2.6 m LAT, and added the inner reef in the
|
|
position she had determined by triangulation from three fixed points on
|
|
shore. She used blue for the water, black for the structures, and a
|
|
particularly assertive shade of red for the reef, because reefs that
|
|
are subject to a seventy-year argument deserve to be drawn in a colour
|
|
that commands attention.</p>
|
|
|
|
<p>She pinned the completed chart to the wall above her berth, where
|
|
the varnished wood held brass tacks with the grip of long practice.
|
|
The chart looked good. Clean lines, clear labels, unambiguous depth
|
|
figures. For a moment — a brief, perfect moment — the
|
|
world felt like a place that could be made orderly.</p>
|
|
|
|
<p>She would not feel that way again for some time.</p>
|
|
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# CHAPTER 3 — one spine item, FOUR TOC entries (chapter + 3 sub-sections)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
CHAPTER_3 = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head><title>Chapter 3</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/></head>
|
|
<body>
|
|
|
|
<h1>Chapter 3<br/>Charting the Depths</h1>
|
|
|
|
<p>Beyond the Twin Harbors, the continental shelf dropped away in three
|
|
distinct terraces. Anchora’s fathom-line, weighted with lead and
|
|
tallow, told the story in numbers: ten, forty, two hundred. Each number
|
|
represented a different world — a different temperature, a
|
|
different colour, a different set of hazards — and she intended
|
|
to chart them all.</p>
|
|
|
|
<p>She had sailed out of the second harbor at dawn, motoring through
|
|
the cut in the grey half-light while the fishing boats were still
|
|
sorting their nets. Constance had waved from the harbourmaster’s
|
|
office window. Rufus had been asleep on his pilot boat and had not
|
|
waved at all.</p>
|
|
|
|
<p>Each terrace had its own character, its own light, its own hazards.
|
|
She gave each a name and — because she was, above all, a
|
|
cartographer — a sub-heading.</p>
|
|
|
|
<h2 id="the-reef">The Reef</h2>
|
|
|
|
<p>The first terrace was a broad shelf of coral, alive with colour and
|
|
peril in roughly equal measure. It extended for perhaps two miles from
|
|
the outer edge of the harbor approaches, a gradually shoaling platform
|
|
of limestone and living coral that the chart described as “foul
|
|
ground” and the local fishermen described with a word that
|
|
Anchora did not record in her notebook but committed to memory for
|
|
future use.</p>
|
|
|
|
<p>Staghorn formations reached toward the hull like bony fingers. Fan
|
|
corals swayed in the current with the slow grace of a metronome. Brain
|
|
corals squatted on the seabed like boulders, their surfaces etched with
|
|
grooves that looked, from above, like the contour lines on a
|
|
particularly complicated chart. Anchora appreciated the irony. Even
|
|
the ocean floor was trying to be a map.</p>
|
|
|
|
<p>The water over the reef was extraordinarily clear. She could see the
|
|
bottom in seven metres of water as though it were behind glass: every
|
|
coral head, every sandy patch, every dark crevice where a moray eel
|
|
might be contemplating its options. Fish moved through this landscape in
|
|
schools and squadrons, their colours too vivid for the grey day
|
|
— electric blue, acid yellow, a hot pink that no chart
|
|
convention had a symbol for.</p>
|
|
|
|
<p>Anchora worked her way across the reef under reduced sail, taking
|
|
soundings every hundred metres. The depth varied unpredictably: three
|
|
metres here, seven metres there, and in one alarming spot, barely one
|
|
and a half metres over a coral head that lurked just below the surface
|
|
like a geological ambush. She marked each sounding on her chart with
|
|
the compulsive precision of someone who knows that a single missed
|
|
hazard can ruin a hull and a reputation in the same instant.</p>
|
|
|
|
<p>“Beautiful,” she murmured, leaning over the rail to
|
|
watch a school of parrotfish graze on the coral below. The fish were
|
|
vivid turquoise, the size of dinner plates, and they ate the coral with
|
|
an audible crunching sound that was both fascinating and faintly
|
|
disturbing. Then her keel scraped limestone — a sound like a
|
|
giant clearing its throat — and she revised her opinion to
|
|
“beautiful but inconvenient.”</p>
|
|
|
|
<p>She started the engine and motored off the coral head, checking the
|
|
bilge for leaks (none, thank goodness; the <i>Pagination</i>’s
|
|
hull was tougher than it looked) and the keel for damage (a scrape,
|
|
nothing more, but a scrape that would need antifouling paint before
|
|
the season was out). The parrotfish watched her departure with the
|
|
sublime indifference of creatures that do not have keels.</p>
|
|
|
|
<p>By late morning she had completed her survey of the reef. It covered
|
|
an area of roughly four square miles and contained, by her count,
|
|
twenty-three significant coral heads within two metres of the surface
|
|
at low water. She inked the reef in hatched lines on her chart, shading
|
|
the shallowest areas in a warning blue, and adding a marginal note:
|
|
<i>Draft exceeding 1.5 m: proceed with caution and strong
|
|
language.</i></p>
|
|
|
|
<p>She added, after a moment’s thought: <i>Draft exceeding 2.0 m:
|
|
do not proceed at all. Go around.</i></p>
|
|
|
|
<p>The reef chart was one of the most detailed pieces of work she had
|
|
produced. She allowed herself a moment of satisfaction, then turned her
|
|
attention to the second terrace.</p>
|
|
|
|
<h2 id="the-current">The Current</h2>
|
|
|
|
<p>Below the reef shelf, the seabed fell away sharply — not
|
|
gradually, not gently, but with the decisiveness of a cliff edge. One
|
|
moment the depth sounder was reading eight metres; the next it was
|
|
reading forty, and still dropping. The colour of the water changed too,
|
|
from the pale turquoise of the reef to a deep, serious blue that
|
|
suggested the ocean was no longer in a playful mood.</p>
|
|
|
|
<p>And the water began to move. Not the slow, companionable drift of
|
|
tidal flow, not the rhythmic surge of swell, but a purposeful lateral
|
|
current that pushed the <i>Pagination</i> sideways at a rate Anchora
|
|
found personally offensive. She had been sailing a straight course
|
|
toward a landmark on the far shore; within ten minutes, the landmark
|
|
had migrated from dead ahead to thirty degrees off the starboard bow,
|
|
and the <i>Pagination</i> was crabbing sideways like a startled dog on
|
|
a polished floor.</p>
|
|
|
|
<p>Anchora dropped the jib, started the engine, and pointed the bow
|
|
directly into the current. The <i>Pagination</i> held position, but
|
|
only just. The engine was working at three-quarters throttle to make
|
|
zero progress over the ground, which was the nautical equivalent of
|
|
running on a treadmill.</p>
|
|
|
|
<p>She set a kedge anchor — a small, light anchor attached to a
|
|
long line that she rowed out in the dinghy and dropped on the seabed
|
|
upstream of the current. With the boat held in place by the anchor, she
|
|
could take bearings without the distraction of being pushed steadily
|
|
toward a different postcode.</p>
|
|
|
|
<p>The boat swung in lazy arcs at the end of her anchor line, like a
|
|
weathervane that could not quite decide where the wind was coming from.
|
|
Anchora took bearings on three fixed points on shore every fifteen
|
|
minutes, plotted them on her chart, and calculated the current’s
|
|
speed and direction from the resulting drift vectors.</p>
|
|
|
|
<p>The current, she calculated, ran at two and a quarter knots on the
|
|
ebb tide, swinging to three and a half on the flood. It flowed roughly
|
|
parallel to the coast, with a slight onshore component during the flood
|
|
that would push an unwary vessel toward the reef. At springs —
|
|
when the tidal range was at its greatest — she estimated the
|
|
current would exceed four knots, which was faster than many boats could
|
|
motor against and would certainly be faster than any sailboat could
|
|
point into.</p>
|
|
|
|
<p>It was the kind of data that looked innocent in a table and lethal on
|
|
a lee shore. Anchora had a healthy respect for currents. They were the
|
|
ocean’s way of reminding you that it was bigger than you and had
|
|
somewhere to be.</p>
|
|
|
|
<p>She spent the rest of the day anchored in the current zone, taking
|
|
readings at half-hour intervals. By evening she had enough data to draw
|
|
a current chart: a pattern of arrows showing direction and speed at
|
|
various states of the tide, annotated with times referenced to high
|
|
water at the Twin Harbors. She added a caution box in the margin:
|
|
<i>Spring rates may exceed 4 kn. Passage against the flood inadvisable
|
|
for vessels under power of 15 hp. Passage under sail alone is a matter
|
|
for the individual conscience.</i></p>
|
|
|
|
<p>She noted it all down, adding small arrows to indicate direction and
|
|
strength. The chart was filling up nicely. She had coral, she had
|
|
current, and she had the beginnings of a bathymetric profile that would
|
|
make a hydrographer weep with something that might have been either
|
|
admiration or envy.</p>
|
|
|
|
<h2 id="the-depths">The Depths</h2>
|
|
|
|
<p>Past the current, the water turned from blue to black. It was a
|
|
gradual transition — not a line, not a boundary, but a slow
|
|
deepening of colour that spoke of depths where sunlight was a rumour
|
|
and pressure was a fact of life. The <i>Pagination</i> sailed into
|
|
this darker water on a light breeze, and Anchora felt the temperature
|
|
drop a degree as the deep water exhaled its chill.</p>
|
|
|
|
<p>Anchora’s lead-line ran out at two hundred fathoms and found
|
|
nothing. She tied on an extension — fifty fathoms of spare line
|
|
she kept coiled in the lazarette for exactly this purpose. At three
|
|
hundred fathoms: nothing. The line hung straight down into the black
|
|
water, trembling slightly with the current, offering no information
|
|
except that the bottom was not yet here.</p>
|
|
|
|
<p>She tied on a second extension. At four hundred fathoms —
|
|
nearly half a mile of line, its weight now enough to make her arms ache
|
|
from the hauling — she felt a distant, uncertain bump. The lead
|
|
had found something. Whether it was bedrock, sediment, a drowned
|
|
mountain, or the roof of something she preferred not to think about,
|
|
the line could not tell her. It only knew that it had stopped going
|
|
down.</p>
|
|
|
|
<p>“Well,” she said to the empty cockpit, “there
|
|
is apparently a bottom.”</p>
|
|
|
|
<p>She hauled the line in, arm over arm, for what felt like an hour but
|
|
was probably fifteen minutes. The lead came up coated in a fine grey
|
|
clay that told her the bottom was soft sediment — the
|
|
accumulated drift of millennia, particles of sand and silt and the
|
|
ground-down remains of creatures that had lived and died in the water
|
|
column above and settled, with infinite slowness, to the floor.</p>
|
|
|
|
<p>She examined the clay sample with the professional interest of
|
|
someone who understands that even mud has a story to tell. It was
|
|
fine-grained, slightly sticky, with no visible shell fragments or
|
|
organic material. Deep-water sediment. The kind of bottom that offers
|
|
poor holding for an anchor but excellent preservation for anything that
|
|
sinks to it.</p>
|
|
|
|
<p>She took three more soundings over the course of the afternoon,
|
|
sailing a line perpendicular to the coast. The depths were remarkably
|
|
consistent: three hundred and eighty fathoms, four hundred and ten,
|
|
three hundred and ninety-five. The seabed here was a flat plain,
|
|
featureless and unchanging, stretching into the darkness in every
|
|
direction.</p>
|
|
|
|
<p>She drew a single contour line on her chart — the four-hundred
|
|
fathom line, traced with a steady hand despite the gentle rolling of
|
|
the boat — and wrote <i>400+ fm</i> beside it. Below the line
|
|
she left blank space: the cartographer’s admission that some
|
|
things are simply too deep to record, too far from light and air and
|
|
the concerns of surface-dwellers to justify the ink.</p>
|
|
|
|
<p>But she kept the clay sample, sealed in a small glass jar and
|
|
labeled with the date, position, and depth. A cartographer records
|
|
what can be recorded. The blank space on the chart was not ignorance.
|
|
It was honesty.</p>
|
|
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# INTERLUDE — in spine, NOT in TOC
|
|
# ---------------------------------------------------------------------------
|
|
|
|
INTERLUDE = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head><title>Interlude</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/></head>
|
|
<body>
|
|
|
|
<h1>The Phantom Island</h1>
|
|
|
|
<p>Between Chapter Three and Chapter Four, Anchora sailed past an island
|
|
that did not exist.</p>
|
|
|
|
<p>She spotted it on the morning of her third day out from the Twin
|
|
Harbors, in a stretch of sea where her charts showed nothing but open
|
|
water and a scattering of depth soundings that ranged from
|
|
“deep” to “very deep.” It appeared first
|
|
as a dark smudge on the horizon, which she initially took for a low
|
|
cloud or a particularly ambitious wave. But clouds do not stay in one
|
|
place, and waves do not have palm trees, and this thing had both.</p>
|
|
|
|
<p>She altered course to investigate. A cartographer who sails past an
|
|
uncharted island without investigating is not, in Anchora’s
|
|
professional opinion, a cartographer at all, but merely someone with a
|
|
boat and a collection of pens.</p>
|
|
|
|
<p>The island resolved itself as she approached. It was small —
|
|
perhaps a quarter of a mile across, roughly circular, fringed with a
|
|
beach of white sand that was so bright in the morning sun it made her
|
|
squint. Behind the beach, a stand of coconut palms rose to a modest
|
|
height, their fronds rustling in a breeze that Anchora could not feel
|
|
from the water. At the island’s centre, a low hill rose perhaps
|
|
fifty feet above sea level, covered in scrub grass and what appeared to
|
|
be a single, determined frangipani tree in full bloom.</p>
|
|
|
|
<p>It had, in short, all the attributes of an island. It had mass, it
|
|
had volume, it had geographic coordinates that Anchora carefully noted
|
|
from her sextant readings. It had a beach of white sand that squeaked
|
|
underfoot when she rowed the dinghy ashore and stepped out, which is a
|
|
very specific and tactile quality that imaginary places tend not to
|
|
possess.</p>
|
|
|
|
<p>It had a small but enthusiastic colony of penguins, which was
|
|
geographically improbable but zoologically undeniable. They were small
|
|
penguins — about eighteen inches tall, with blue-grey backs and
|
|
white fronts and an air of having been expecting her. They stood in a
|
|
loose group near the tree line, regarding her with the intensity of
|
|
creatures who have opinions about visitors but lack the vocal apparatus
|
|
to express them clearly.</p>
|
|
|
|
<p>“You’re not supposed to be here,” Anchora told
|
|
them. Penguins, she was fairly certain, belonged in the southern
|
|
hemisphere, on rocky coasts and ice shelves, in places where the water
|
|
was cold and the fish were plentiful and the nearest palm tree was
|
|
several thousand miles away. These penguins appeared not to have read
|
|
the relevant literature.</p>
|
|
|
|
<p>She walked the perimeter of the island, which took twenty-three
|
|
minutes at a brisk pace. The beach was continuous — fine white
|
|
sand, no rocks, gently shelving into water that was a shade of turquoise
|
|
that postcards aspire to but rarely achieve. The interior was equally
|
|
unremarkable: the palm grove, the scrub hill, the frangipani, and an
|
|
absence of anything that might explain why this island was here. No
|
|
volcanic cone. No coral atoll. No geological justification
|
|
whatsoever.</p>
|
|
|
|
<p>She took careful measurements. She recorded the latitude and
|
|
longitude from three separate sextant shots, all of which agreed. She
|
|
sounded the water around the island’s shore and found a uniform
|
|
depth of four fathoms, dropping sharply to twenty fathoms fifty metres
|
|
out. She noted the compass bearing to the nearest known landmark
|
|
— the headland beyond the Twin Harbors, barely visible on the
|
|
horizon — and calculated the distance.</p>
|
|
|
|
<p>All the data said the island was real. The numbers were precise and
|
|
consistent. The sand was tangible. The penguins were audible (they had
|
|
begun a low, conversational muttering among themselves that suggested
|
|
they were discussing her survey technique).</p>
|
|
|
|
<p>She reached for her pen to add it to the atlas, then paused.</p>
|
|
|
|
<p>The island was not in the table of contents. She checked —
|
|
carefully, methodically, the way she checked everything. She ran her
|
|
finger down the list of chapters, sections, and appendices. The
|
|
Foreword was there. The five chapters were there. The appendices were
|
|
there. But between Chapter Three and Chapter Four, where this island
|
|
chronologically belonged, there was no entry. No heading, no
|
|
sub-heading, no footnote.</p>
|
|
|
|
<p>It was not listed in the index. It appeared in the reading order
|
|
— she was, after all, reading about it right now, and so were
|
|
you — but no navigation entry pointed to it. If you were using
|
|
the table of contents to move through this book, you would skip from
|
|
Chapter Three directly to Chapter Four and never know this island was
|
|
here. It existed in the spine but not in the navigation. It was
|
|
structurally present but navigationally invisible.</p>
|
|
|
|
<p>“If a place has no entry,” she asked one of the
|
|
penguins, “does it really exist?”</p>
|
|
|
|
<p>The penguin regarded her with the weary patience of a creature that
|
|
has heard this question before — perhaps from other
|
|
cartographers who had stumbled upon the island and grappled with the
|
|
same ontological difficulty. It tilted its head to one side, blinked
|
|
once with each eye in sequence, and then waddled back to the surf with
|
|
the unhurried dignity of a creature whose existence does not depend on
|
|
being listed in a table of contents.</p>
|
|
|
|
<p>Anchora sat on the beach for a while, thinking about this. The
|
|
penguins went about their business around her: waddling, swimming,
|
|
standing in small groups and staring at the horizon with the focused
|
|
attention of creatures who are waiting for something but have forgotten
|
|
what. The waves lapped at the sand. The palm fronds rustled. The
|
|
frangipani released its scent into the warm air.</p>
|
|
|
|
<p>It was, she had to admit, a very pleasant island. Peaceful.
|
|
Unhurried. The kind of place where you could sit for an afternoon and
|
|
forget that you had charts to draw and depths to sound and harbors to
|
|
argue about. Perhaps that was the point. Perhaps some places are better
|
|
off uncharted — hidden in the reading order, reachable only by
|
|
those patient enough to read every page rather than jumping from heading
|
|
to heading.</p>
|
|
|
|
<p>She considered this philosophical position for approximately four
|
|
minutes, then rejected it. She was a cartographer. Uncharted places
|
|
were not romantic; they were errors.</p>
|
|
|
|
<p>And yet.</p>
|
|
|
|
<p>She closed her notebook. She rowed back to the <i>Pagination</i>.
|
|
She hauled up the anchor, set the jib, and sailed away from the island
|
|
on a reaching course that would bring her to the coordinates she had
|
|
been given for the beginning of the Long Voyage.</p>
|
|
|
|
<p>She did not add the island to her chart. There was no heading for it
|
|
in the atlas, no entry in the navigation, no place for it in the
|
|
structure she had so carefully planned. An island without a table of
|
|
contents entry was, from a cartographic perspective, an orphan —
|
|
and Anchora’s atlas did not have room for orphans.</p>
|
|
|
|
<p>She did, however, add penguins to her growing list of things that
|
|
were not supposed to be there but were. The list, she reflected, was
|
|
getting longer with every day of the voyage. She was not sure whether
|
|
this said something about the world or about her list.</p>
|
|
|
|
<p>Behind her, the island shimmered in the heat haze and slowly sank
|
|
below the horizon, taking its penguins and its palm trees and its
|
|
existential questions with it. By evening it was gone. By morning she
|
|
would not be entirely sure she had seen it at all.</p>
|
|
|
|
<p>But the sand between her toes — fine, white, faintly
|
|
squeaky — suggested otherwise.</p>
|
|
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# CHAPTER 4 — one TOC entry, THREE spine items
|
|
# ---------------------------------------------------------------------------
|
|
|
|
CHAPTER_4_PART1 = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head><title>Chapter 4 (Day 1)</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/></head>
|
|
<body>
|
|
|
|
<h1>Chapter 4<br/>The Long Voyage</h1>
|
|
|
|
<h2>Day One — Departure</h2>
|
|
|
|
<p>The passage to the outer archipelago was, by all accounts, a
|
|
three-day sail. This estimate came from Rufus the pilot, who had never
|
|
made the passage himself but had spoken to several people who had, and
|
|
from Constance the harbourmaster, who had made it once, thirty years
|
|
ago, in a boat considerably faster than the <i>Pagination</i> and in
|
|
weather considerably better than the forecast was promising.</p>
|
|
|
|
<p>Anchora provisioned accordingly: three days of hard-tack, three days
|
|
of tinned sardines, and three days of the sort of instant coffee that
|
|
dissolves under protest. She also packed a fourth day’s supplies,
|
|
because she had learned through experience that three-day passages have
|
|
a way of becoming four-day passages, and a sailor without coffee on
|
|
day four is a sailor without hope.</p>
|
|
|
|
<p>She reviewed her charts one more time before casting off. The outer
|
|
archipelago was marked on the Admiralty chart as a cluster of small
|
|
islands approximately seventy miles to the southeast — close
|
|
enough to reach in three days of moderate sailing, far enough to
|
|
require planning, provisioning, and the acceptance that the nearest
|
|
help, should help be needed, was a day’s sail behind her. The
|
|
islands themselves were drawn as rough outlines, their coastlines
|
|
sketched from satellite imagery and the reports of passing ships. No
|
|
one had surveyed them properly. That was why Anchora was going.</p>
|
|
|
|
<p>She cast off at first light, motoring through the harbor and out
|
|
past the breakwater into open water. The dawn was a thin line of amber
|
|
on the eastern horizon, and the sea was a flat expanse of grey that
|
|
merged, at the edges, with a sky of precisely the same shade. The wind
|
|
was light from the southeast — a soldier’s wind, steady
|
|
and reliable, the kind of wind that does not require constant attention
|
|
to the sheets.</p>
|
|
|
|
<p>Day one was, in the main, uneventful. The wind held steady, the seas
|
|
were moderate — a long, low swell from the south that the
|
|
<i>Pagination</i> rode with an easy, rocking motion — and the
|
|
boat made six knots on a beam reach without complaint. This was her
|
|
best point of sail: the wind on the beam, the sails drawing well, the
|
|
hull slicing through the water with the minimum of fuss and the maximum
|
|
of speed.</p>
|
|
|
|
<p>Anchora spent the daylight hours sketching coastline profiles from
|
|
the deck. The coast was still visible to the northwest, a low grey line
|
|
that rose occasionally into headlands and fell back into bays. She
|
|
drew each headland as she passed it, noting its shape, its height, its
|
|
distinguishing features. A lighthouse here. A radio mast there. A cliff
|
|
face that had collapsed into a jumble of rocks that would, she
|
|
suspected, not appear on any chart for another decade.</p>
|
|
|
|
<p>By mid-morning the coast had begun to recede, and by early
|
|
afternoon it was little more than a suggestion — a slight
|
|
thickening of the horizon, a shade of grey that was fractionally darker
|
|
than the grey of the sea. Anchora took a last bearing on the highest
|
|
headland, plotted it on her chart, and acknowledged that she was, for
|
|
practical purposes, out of sight of land.</p>
|
|
|
|
<p>This was a moment that some sailors dreaded and others relished.
|
|
Anchora was in the second category. Out of sight of land, the world
|
|
simplified itself. There was the boat, there was the sea, and there was
|
|
the compass. Everything else — the harbors and their arguments,
|
|
the charts and their disagreements, the penguins and their inexplicable
|
|
geography — fell away. What remained was navigation in its purest
|
|
form: a vessel, a heading, and the conviction that the maths would
|
|
work out.</p>
|
|
|
|
<p>She spent the evening hours transferring her coastline sketches to
|
|
the master chart, working by the light of the oil lamp that swung from
|
|
a hook above the chart table. The lamp threw a warm, yellow circle of
|
|
light that moved gently with the boat’s motion, and the shadows
|
|
it cast gave the chart a depth and texture that the flat light of day
|
|
did not. She added her soundings from the reef and current zones, drew
|
|
the four-hundred-fathom contour line she had found over the deep water,
|
|
and penciled in a tentative route to the archipelago.</p>
|
|
|
|
<p>By sunset, the Twin Harbors had sunk below the horizon and there was
|
|
nothing in any direction but water and the thin, bright line where it
|
|
met the sky. The sky turned from grey to amber to a deep blue-violet
|
|
that held the first stars in its upper reaches. The wind eased slightly
|
|
as the land breeze died and the sea breeze had not yet arrived. The
|
|
<i>Pagination</i> slowed to four knots, then three, and the water
|
|
around her hull changed from a hiss to a whisper.</p>
|
|
|
|
<p>Anchora set the self-steering gear — a wind-vane device of
|
|
her own construction that held the boat on course without human
|
|
intervention, provided the wind did not shift by more than fifteen
|
|
degrees, which it did roughly once an hour — and went below to
|
|
make dinner. Tinned sardines on hard-tack, with a cup of instant coffee
|
|
that tasted, as always, of ambition unfulfilled.</p>
|
|
|
|
<p>She marked her position on the chart with a small cross and the
|
|
time: <i>Day 1, 18:47, all well. 42 miles made good. Barometer steady.
|
|
Wind SE 8 kn. Coffee: adequate.</i></p>
|
|
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
CHAPTER_4_PART2 = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head><title>Chapter 4 (Day 2)</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/></head>
|
|
<body>
|
|
|
|
<h2>Day Two — Becalmed</h2>
|
|
|
|
<p>The wind died at dawn and did not return. It did not die gradually,
|
|
the way winds usually die — fading through a series of
|
|
diminishing puffs until the last breath of air gives up and the sails
|
|
go slack. It died all at once, as though someone had closed a door.
|
|
One moment the <i>Pagination</i> was sailing; the next she was not.</p>
|
|
|
|
<p>The <i>Pagination</i> sat on water so flat it reflected the clouds
|
|
like a tray of mercury. Every ripple, every swell, every hint of motion
|
|
had been smoothed away. The sea was a mirror. The sky was reflected in
|
|
it so perfectly that the horizon vanished, and Anchora had the
|
|
unsettling sensation of floating in the centre of a sphere, with
|
|
identical views in every direction, up and down included.</p>
|
|
|
|
<p>The sails hung in dispirited loops. The main sagged against the
|
|
shrouds. The jib, unfurled and hopeful an hour ago, now hung from the
|
|
forestay like a bedsheet on a clothesline. Even the tell-tales —
|
|
small strips of yarn attached to the shrouds to indicate wind direction
|
|
— drooped vertically, pointing at the deck with the resigned
|
|
finality of arrows that have given up looking for a target.</p>
|
|
|
|
<p>Anchora tried whistling for wind (maritime tradition). She stood in
|
|
the cockpit and whistled a jaunty tune toward each of the four cardinal
|
|
points in turn, which was supposed to summon a breeze from the
|
|
direction you whistled at. The tradition did not specify what to do when
|
|
all four directions were equally windless. Anchora whistled at all of
|
|
them anyway, on the principle that comprehensive failure was preferable
|
|
to targeted failure.</p>
|
|
|
|
<p>She tried tapping the barometer (maritime superstition). The
|
|
barometer was a fine brass instrument mounted on the bulkhead in the
|
|
companionway, and it showed 1024 millibars, which was high and stable
|
|
and thoroughly uninterested in change. Tapping it — a gentle,
|
|
respectful tap with the knuckle of the index finger, as tradition
|
|
demanded — produced no change. She tapped it again, harder.
|
|
Still nothing. The barometer regarded her with the mechanical smugness
|
|
of a device that knows it is right.</p>
|
|
|
|
<p>She tried simply sitting in the cockpit and staring at the horizon
|
|
(maritime realism). This was, in many ways, the most honest response to
|
|
a calm: the acceptance that the wind would return when it chose and not
|
|
before, and that no amount of whistling, tapping, or staring would
|
|
hasten its arrival. Sailors who raged against calms accomplished nothing
|
|
except to make themselves hot and irritable. Sailors who accepted them
|
|
at least stayed cool.</p>
|
|
|
|
<p>The morning passed in a haze of heat and stillness. Anchora read a
|
|
chapter of the pilot book, made a cup of coffee (the second-to-last
|
|
packet of instant — she was rationing now), and wrote a long
|
|
entry in her notebook about the geology of the continental shelf,
|
|
drawing on the soundings she had taken over the past few days. The
|
|
writing helped. It gave her hands something to do and her mind something
|
|
to chew on that was not the infuriating absence of wind.</p>
|
|
|
|
<p>By noon the heat was ferocious. The sun stood directly overhead,
|
|
pouring its energy into the flat sea and the flat boat and the flat
|
|
cartographer who was beginning to feel like a piece of hard-tack left
|
|
on a windowsill. The deck was too hot to touch barefoot. The cabin was
|
|
an oven. The cockpit, shaded by the boom, was merely oppressive rather
|
|
than unbearable, which was the best that could be said for it.</p>
|
|
|
|
<p>She rigged a sun-shade from the spare jib, draping the heavy
|
|
sailcloth over the boom and tying it to the shrouds on either side.
|
|
This created a rectangle of shade over the cockpit that was eight feet
|
|
by six feet and reduced the temperature from “punitive”
|
|
to “merely unpleasant.” She sat in this shade and spent
|
|
the afternoon measuring the depth with her lead-line, which was at
|
|
least productive even if it was not comfortable.</p>
|
|
|
|
<p>The bottom here was sixty fathoms of soft mud — the same
|
|
fine grey clay she had found in the deep water, but closer to the
|
|
surface. The mud yielded to the lead with a reluctant sucking sound
|
|
that Anchora could feel through the line, a hundred and twenty metres
|
|
away. She noted this on the chart, adding a small sounding figure at
|
|
her current position, though she suspected no one would ever care.
|
|
Sixty fathoms of mud in the middle of nowhere was not the kind of
|
|
information that made it into the Admiralty Notices to Mariners.</p>
|
|
|
|
<p>She took several more soundings as the afternoon wore on, drifting
|
|
imperceptibly — the current was weak here, barely a quarter of
|
|
a knot — and recording each depth. Fifty-eight fathoms.
|
|
Sixty-two. Fifty-five. The seabed was gently undulating, rising and
|
|
falling by a few fathoms over a distance of perhaps half a mile. She
|
|
drew these contours on her chart, and the result looked like the gentle
|
|
hills of a drowned landscape, which is precisely what it was.</p>
|
|
|
|
<p>At sunset, a catspaw rippled the surface to the north — a
|
|
small, dark patch of ruffled water that raced across the mirror-flat
|
|
sea like a whispered secret. Anchora leaped to her feet, freed the
|
|
jib sheet, and hauled in the main, her hands moving with the desperate
|
|
speed of someone who has been waiting all day for this exact moment.
|
|
By the time she had the sails trimmed, the catspaw had arrived,
|
|
touched the <i>Pagination</i>’s sails with the lightest of
|
|
fingers, and moved on. The sails filled for a moment — a
|
|
single, heartbreaking moment — and then fell slack again.</p>
|
|
|
|
<p>The catspaw raced on to the south and disappeared. The sea
|
|
returned to its mirror state. The tell-tales drooped.</p>
|
|
|
|
<p>Anchora sat down in the cockpit and regarded the empty horizon with
|
|
an expression that, in a less disciplined cartographer, might have been
|
|
called despair. In Anchora it was merely a very thorough species of
|
|
disappointment.</p>
|
|
|
|
<p>She marked her position: <i>Day 2, 19:02, becalmed. 3 miles made
|
|
good by drift. Barometer 1024, steady. Wind: none. Morale stable but
|
|
coffee supply critical. Lead-line soundings taken; seabed contour added
|
|
to chart. If the wind does not return by morning I shall motor, which
|
|
is an admission of defeat but at least it is defeat with forward
|
|
progress.</i></p>
|
|
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
CHAPTER_4_PART3 = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head><title>Chapter 4 (Day 3)</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/></head>
|
|
<body>
|
|
|
|
<h2>Day Three — Arrival</h2>
|
|
|
|
<p>The wind returned overnight with the subtlety of a cannon shot. One
|
|
moment the <i>Pagination</i> was drifting, her hull barely creasing the
|
|
water, her sails hanging like theatre curtains after the final act. The
|
|
next moment she was heeled over at twenty degrees, spray flying from the
|
|
bow in white sheets, the rigging singing a chord in B-flat minor that
|
|
rose in pitch as the gusts built and fell again as they passed.</p>
|
|
|
|
<p>Anchora, who had been asleep in the quarterberth with her head on a
|
|
folded chart and her feet on a coil of rope, arrived on deck wearing
|
|
one boot and an expression of startled competence. The wind was from
|
|
the northwest — exactly the direction she needed — and
|
|
blowing at what she estimated was twenty knots, gusting twenty-five.
|
|
This was more wind than the <i>Pagination</i> wanted with full sail
|
|
set, and considerably more wind than Anchora wanted at three o’clock
|
|
in the morning with one boot on.</p>
|
|
|
|
<p>She reefed the main in the dark, working by feel and muscle memory.
|
|
The reef points were where her fingers expected them to be; the lines
|
|
ran through the blocks without snagging; the sail came down to its
|
|
first reef in under two minutes. She trimmed the jib to match, easing
|
|
the sheet until the sail stopped flogging and settled into the shape it
|
|
wanted, and pointed the bow toward the coordinates she had been given
|
|
for the outer archipelago.</p>
|
|
|
|
<p>The <i>Pagination</i> responded immediately. With the reef in, she
|
|
was balanced, manageable, and making seven knots through the water
|
|
— her best speed of the voyage. The bow wave hissed along the
|
|
hull. The wake stretched out behind in a long, white tail. The self-
|
|
steering gear held the course without complaint, and Anchora, who was
|
|
now fully awake and beginning to enjoy herself, went below to find the
|
|
other boot.</p>
|
|
|
|
<p>Dawn came slowly, the way it does at sea: a gradual lightening of
|
|
the eastern sky, from black to charcoal to a pale grey that spread
|
|
upward like water rising in a glass. The horizon emerged from the
|
|
darkness, sharp and clean, and Anchora scanned it with the practiced
|
|
eye of someone who has been looking for land from the deck of a small
|
|
boat for most of her adult life.</p>
|
|
|
|
<p>Nothing. Not yet. But the chart said the archipelago should be
|
|
visible by mid-morning at this speed, and Anchora trusted her chart
|
|
because she had drawn it herself and she knew exactly how much trust
|
|
it deserved, which was a moderate amount tempered by professional
|
|
humility.</p>
|
|
|
|
<p>She made coffee — the last packet, which she regarded as both
|
|
a sacrifice and an incentive — and drank it in the cockpit while
|
|
the <i>Pagination</i> sailed herself. The wind was settling down to a
|
|
steady eighteen knots, the gusts becoming less frequent, the sea
|
|
developing a regular pattern of waves that the boat cut through with
|
|
a satisfying, rhythmic motion. This was good sailing. The kind of
|
|
sailing you remember long after the voyage is over.</p>
|
|
|
|
<p>At ten o’clock she saw something on the horizon that was not
|
|
cloud and not sea. It was a faint, dark irregularity in the line
|
|
where sky met water — a slight bump, barely perceptible, that
|
|
could have been a distant ship or a trick of the light but wasn’t.
|
|
She knew what it was. She had been looking for it for three days.</p>
|
|
|
|
<p>Land appeared at noon: a low, dark smudge that resolved slowly into
|
|
individual islands, then individual trees, then individual birds
|
|
perched in the individual trees. She counted seven major islands and
|
|
an uncountable number of rocks, shoals, and ambiguous features that
|
|
might have been either. The islands were spread across perhaps ten miles
|
|
of sea, arranged in a rough arc that opened toward the northwest
|
|
— toward her, as it happened, which felt like a welcome even
|
|
though she knew it was merely geography.</p>
|
|
|
|
<p>She sailed closer, reducing speed as the water shallowed. The
|
|
depth sounder, which had been reading “deep” for two
|
|
days, suddenly began producing numbers: 80 metres, 60, 40, 30. She
|
|
could see the bottom now — a sandy seabed dappled with shadows
|
|
from the islands above. Fish scattered as the <i>Pagination</i>’s
|
|
shadow passed over them.</p>
|
|
|
|
<p>She rounded the northern tip of the largest island, staying well
|
|
clear of a line of rocks that extended from the shore like a broken
|
|
jetty, and found herself in a sheltered anchorage on the island’s
|
|
lee side. The water was calm here, protected from the northwest wind
|
|
by the island’s bulk. She dropped anchor in four fathoms of
|
|
sand, felt it bite, and paid out enough chain to hold in a gale.</p>
|
|
|
|
<p>Then she sat in the cockpit and looked at the islands spread before
|
|
her. Seven islands. Uncharted, unsurveyed, waiting. This was why she
|
|
had come. Not for the harbors with their naming disputes, not for the
|
|
reefs with their lurking coral heads, not for the currents with their
|
|
treacherous pull. She had come for this: blank space on the chart,
|
|
waiting to be filled.</p>
|
|
|
|
<p>She uncapped her pen. This, at last, was what she had come for.</p>
|
|
|
|
<p>She marked her position one final time: <i>Day 3, 12:15, landfall.
|
|
Anchored in the lee of the largest island, 4 fm sand. Seven islands
|
|
visible. Wind NW 18 kn. Coffee: exhausted. The atlas begins in
|
|
earnest.</i></p>
|
|
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# CHAPTER 5 — one spine item, nested TOC (chapter + 3 sub-entries)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
CHAPTER_5 = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head><title>Chapter 5</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/></head>
|
|
<body>
|
|
|
|
<h1>Chapter 5<br/>Archipelago of Wonders</h1>
|
|
|
|
<p>The outer archipelago comprised seven islands, but Anchora quickly
|
|
learned that three of them demanded most of her attention. The other
|
|
four were low, sandy, and profoundly uninteresting — the kind of
|
|
islands that exist primarily to give seabirds somewhere to argue. She
|
|
surveyed them anyway, because a cartographer who skips the boring bits
|
|
produces an atlas with holes in it, and an atlas with holes is just a
|
|
collection of maps pretending to be complete.</p>
|
|
|
|
<p>The four minor islands took two days to chart. They were, as expected,
|
|
unremarkable: flat coral platforms, none more than ten feet above sea
|
|
level, covered in coarse grass and nesting terns. Each island had a
|
|
fringing reef, a scattering of rocks, and a beach that was pleasant
|
|
enough in theory but occupied in practice by large numbers of
|
|
territorial seabirds that regarded Anchora’s survey equipment
|
|
with undisguised hostility.</p>
|
|
|
|
<p>She drew them quickly and moved on to the three islands that
|
|
mattered.</p>
|
|
|
|
<h2 id="isle-of-echoes">Isle of Echoes</h2>
|
|
|
|
<p>The first notable island was ringed by basalt cliffs so sheer they
|
|
formed a natural amphitheatre. The cliffs rose two hundred feet from
|
|
the waterline, sheer and dark, their faces carved into columns by
|
|
millennia of cooling and cracking. At the base, where the waves struck,
|
|
the rock had been hollowed into caves and arches that amplified every
|
|
sound into a symphony of percussion.</p>
|
|
|
|
<p>Every sound bounced from wall to wall in diminishing repetitions:
|
|
the crash of a wave became a series of claps; a shout became a
|
|
conversation with oneself; the rattle of an anchor chain became a
|
|
cascading diminuendo that lasted for eight or nine seconds before
|
|
finally fading into the ambient hiss of the sea.</p>
|
|
|
|
<p>Anchora discovered the echoes accidentally. She was approaching the
|
|
island from the northeast, looking for an anchorage, when she called
|
|
out “Hello!” to see if anyone was ashore. The island
|
|
replied: <i>Hello … hello … hello … ello
|
|
… lo …</i> It was, she reflected, the most polite
|
|
island she had ever visited. Most islands ignored you entirely.</p>
|
|
|
|
<p>She tested the acoustics systematically, because that was her nature.
|
|
She stood in the cockpit, positioned the <i>Pagination</i> at measured
|
|
distances from the cliff face, and shouted a series of test words:
|
|
single syllables first, then multi-syllable words, then complete
|
|
sentences. She timed the echoes with her watch and recorded the results
|
|
in her notebook.</p>
|
|
|
|
<p>She tested the acoustics further by reading her coordinates aloud.
|
|
“Fourteen degrees, thirty-seven minutes south,” she
|
|
announced in a clear, carrying voice. The cliffs repeated it back,
|
|
each echo slightly garbled by the complex geometry of the rock face,
|
|
until by the seventh repetition the island appeared to be declaring
|
|
itself at forty-seven degrees north. She noted this as a navigational
|
|
hazard of a kind not typically covered in the pilot books.</p>
|
|
|
|
<p>The anchorage, when she found it, was on the island’s
|
|
sheltered western side, where the cliffs gave way to a small bay with
|
|
a sandy bottom in three fathoms. She anchored here and spent two days
|
|
surveying the island from the dinghy, rowing along the cliff face with
|
|
a notebook in one hand and an oar in the other, measuring the height
|
|
of the cliffs by trigonometry and the depth of the water by lead-line.
|
|
The caves at the base of the cliffs were deep enough to row into
|
|
— dark, dripping spaces where the sound of the oars echoed in
|
|
unsettling ways and the water was so still it reflected the cave roof
|
|
like polished obsidian.</p>
|
|
|
|
<p>She mapped each cave entrance, noting its position, width, height,
|
|
and the depth of water at its threshold. There were eleven caves in
|
|
total, ranging from barely large enough for the dinghy to a cathedral-
|
|
sized chamber that could have sheltered a small fishing fleet. In the
|
|
largest cave she found the remains of an old mooring ring, bolted into
|
|
the rock at waterline level and rusted to a deep orange-brown. Someone
|
|
had been here before. Someone had anchored in this cave, in this
|
|
darkness, and had thought it worthwhile to drill a hole in the basalt
|
|
and hammer in a ring.</p>
|
|
|
|
<p>She added this to the chart with a small symbol and the annotation:
|
|
<i>Old mooring ring, condition poor. Cave depth 14 m, width 8 m,
|
|
height 5 m at entrance. Adequate shelter in westerly weather.</i></p>
|
|
|
|
<p>The chart grew a detailed inset of the Isle of Echoes, complete with
|
|
soundings, anchorage notes, cave positions, and a warning about acoustic
|
|
anomalies that she phrased with care: <i>Echoes from basalt cliffs may
|
|
distort voice communications. Coordinates heard from echo may not
|
|
correspond to coordinates spoken. Fog signals unreliable within 0.5 nm
|
|
of cliff face.</i></p>
|
|
|
|
<h2 id="compass-rose-atoll">Compass Rose Atoll</h2>
|
|
|
|
<p>The second island was not, strictly speaking, an island at all. It
|
|
was an atoll: a ring of coral enclosing a shallow lagoon, with four
|
|
narrow passes at the cardinal points. From the air — or from a
|
|
sufficiently tall mast — it looked exactly like a compass rose,
|
|
its four passes aligned so precisely with north, south, east, and west
|
|
that Anchora suspected the coincidence was too perfect to be entirely
|
|
natural and too natural to be entirely coincidence.</p>
|
|
|
|
<p>The atoll was roughly circular, perhaps a mile across, its rim
|
|
barely six feet above the water at its highest point. The coral was
|
|
old and dense, covered with a thin layer of sand and scrub vegetation
|
|
that had taken hold wherever the salt spray was not too fierce. On the
|
|
wider sections of the rim, coconut palms grew in sparse lines, their
|
|
trunks curved by years of prevailing wind into identical
|
|
question-mark shapes.</p>
|
|
|
|
<p>Anchora sailed through the north pass and anchored in the lagoon.
|
|
The pass was narrow — barely thirty metres wide, with coral
|
|
walls on either side that rose steeply from a bottom of clean white
|
|
sand — and the current through it was brisk on the flood tide,
|
|
perhaps two knots, which required attention but not alarm. She entered
|
|
on the slack, when the current was negligible, and dropped anchor in
|
|
the centre of the lagoon.</p>
|
|
|
|
<p>The water was so clear she could see her anchor chain lying on the
|
|
bottom in gentle curves, like cursive script. The bottom was four
|
|
fathoms of white sand, undisturbed by current, and the anchor had dug
|
|
in with the easy confidence of a hook in soft ground. Fish moved
|
|
through the water column above the sand: small, bright, purposeful
|
|
fish that paid no attention to the boat or its occupant.</p>
|
|
|
|
<p>She spent a full day surveying the atoll, measuring each pass and
|
|
sounding the lagoon. The symmetry was remarkable: each pass was within
|
|
a boat-length of the same width, and the lagoon was uniformly four
|
|
fathoms deep. The north and south passes were slightly wider than the
|
|
east and west — thirty-two metres versus twenty-eight —
|
|
but the difference was so small it might have been within the margin of
|
|
error of her measuring method, which involved rowing the dinghy across
|
|
the pass and counting oar-strokes.</p>
|
|
|
|
<p>She sounded the lagoon on a grid pattern, rowing the dinghy in
|
|
north-south lines spaced fifty metres apart and dropping the lead
|
|
every twenty metres. The result was a bathymetric chart of extraordinary
|
|
regularity: a flat, featureless bowl of sand, uniformly four fathoms
|
|
deep, with no coral heads, no rocks, no obstacles of any kind. It was,
|
|
she reflected, the most boring piece of underwater terrain she had ever
|
|
surveyed, and also one of the most useful: a lagoon with a flat bottom
|
|
and predictable depth was a sailor’s dream, a place where you
|
|
could anchor anywhere with equal confidence.</p>
|
|
|
|
<p>Nature, it seemed, had a taste for geometry. Anchora, who also had
|
|
a taste for geometry, appreciated this more than most.</p>
|
|
|
|
<p>She drew the atoll with particular care, using a compass to lay out
|
|
the circular rim and placing each pass at its precisely measured bearing.
|
|
The chart of Compass Rose Atoll was, she thought, the most beautiful
|
|
piece of cartography she had produced on the voyage: clean lines,
|
|
perfect symmetry, four passes opening like the petals of a flower.
|
|
She added a small compass rose in the corner of the inset chart, which
|
|
created the pleasing recursion of a compass rose drawn inside a
|
|
compass rose.</p>
|
|
|
|
<h2 id="whirlpool-narrows">The Whirlpool Narrows</h2>
|
|
|
|
<p>Between the second and third islands, the tidal flow compressed
|
|
through a gap barely a cable’s length wide. The two islands were
|
|
close here — so close that their reefs almost touched, leaving
|
|
only a narrow channel of deep water between them. Through this channel,
|
|
twice a day, the entire volume of water that filled and emptied the
|
|
lagoons and bays of the archipelago had to pass, and it did so with
|
|
considerable energy and very little patience.</p>
|
|
|
|
<p>The result was a whirlpool that spun with metronomic regularity:
|
|
clockwise on the ebb, counterclockwise on the flood, and in a state
|
|
of churning indecision at slack water. The whirlpool was not large
|
|
— perhaps twenty metres across at its widest — but it
|
|
was vigorous, and the water within it moved with a purposeful circular
|
|
motion that was both mesmerizing and slightly alarming.</p>
|
|
|
|
<p>Anchora observed the whirlpool from a safe distance, anchored in
|
|
the lee of the eastern island, and made detailed notes. The clockwise
|
|
rotation during the ebb was faster than the counterclockwise rotation
|
|
during the flood, which she attributed to the shape of the channel:
|
|
slightly wider at the southern end, which gave the ebb current —
|
|
flowing from north to south — more room to accelerate before
|
|
hitting the narrows. She estimated the rotational speed at three
|
|
revolutions per minute during the peak ebb and two during the
|
|
peak flood.</p>
|
|
|
|
<p>The whirlpool was accompanied by an array of secondary effects that
|
|
were equally interesting and equally dangerous. Standing waves formed
|
|
at the edges of the narrows, where the moving water met the still
|
|
water beyond, creating a line of breaking crests that would have been
|
|
at home on a surfing beach. Eddies spun off the main whirlpool like
|
|
sparks from a wheel, racing downstream in tight spirals before
|
|
dissipating in the calmer water beyond. And the sound — a low,
|
|
continuous roar, punctuated by the slap of breaking waves —
|
|
carried for half a mile in every direction.</p>
|
|
|
|
<p>Anchora timed the cycles, measured the diameter, and estimated the
|
|
rotational speed. She also measured the current through the narrows at
|
|
various states of the tide, using a timing float — a sealed
|
|
bottle with a small flag attached — that she dropped into the
|
|
current and tracked with bearings. The maximum current was four and a
|
|
half knots during the spring ebb, which was faster than the
|
|
<i>Pagination</i> could motor against and considerably faster than
|
|
anyone would want to sail through.</p>
|
|
|
|
<p>The slack water between the ebb and flood was brief — eight
|
|
minutes by her measurement, during which the whirlpool lost its
|
|
coherence, the standing waves subsided, and the channel was briefly,
|
|
deceptively calm. This was the transit window: eight minutes in which
|
|
a careful boat could pass through the narrows without being spun,
|
|
swamped, or swept sideways into the reef.</p>
|
|
|
|
<p>Eight minutes was not a generous margin. It was, however, sufficient
|
|
for a boat that was ready and a skipper who was decisive. Anchora filed
|
|
this information under “useful” and drew the whirlpool
|
|
on her chart as a neat spiral with arrows, then added the note:
|
|
<i>Transit at slack water only. Allow margin for error. Do not bring
|
|
the good sextant.</i></p>
|
|
|
|
<p>She had now been in the archipelago for four days, and her chart was
|
|
beginning to look like something a real navigator might trust. The
|
|
blank spaces were filling in. The coastlines were taking shape. The
|
|
soundings and current data were building a picture of an archipelago
|
|
that was complex, challenging, and deeply satisfying to chart.</p>
|
|
|
|
<p>This pleased her more than she would have admitted to the
|
|
penguins.</p>
|
|
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# APPENDIX — one spine item, THREE TOC entries via anchors
|
|
# ---------------------------------------------------------------------------
|
|
|
|
APPENDIX = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head><title>Appendices</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/></head>
|
|
<body>
|
|
|
|
<h1 id="appendix-a">Appendix A<br/>Knot Types Employed</h1>
|
|
|
|
<p>The following knots were tied at various points during the voyage
|
|
and are reproduced here for the edification of the reader. Each knot
|
|
is described in terms of its construction, its application aboard the
|
|
<i>Pagination</i>, and Anchora’s personal assessment of its
|
|
character, because all knots have character, and some have more
|
|
character than their tyers would prefer.</p>
|
|
|
|
<p><b>Bowline.</b> The king of knots. Used to secure the
|
|
<i>Pagination</i> to docks, bollards, and on one occasion a
|
|
surprisingly cooperative palm tree on the Isle of Echoes. The bowline
|
|
forms a fixed loop at the end of a line that will not slip under load
|
|
and will not jam when you want to untie it, which is a combination of
|
|
virtues that very few knots can claim. Anchora tied bowlines
|
|
instinctively; her fingers would form the loop, pass the tail around
|
|
the standing part, and thread it back through the loop in a single
|
|
fluid motion that took approximately one and a half seconds. She had
|
|
once won a bowline-tying competition at a sailing club in the Leeward
|
|
Islands, beating a boatswain with forty years’ experience and
|
|
very large hands. The boatswain had been gracious in defeat and had
|
|
bought her a rum, which is the traditional currency of nautical
|
|
respect. Advantages: does not slip, does not jam, can be tied under
|
|
load if necessary. Disadvantages: requires two hands, which is one
|
|
more than a sailor holding a coffee cup has available.</p>
|
|
|
|
<p><b>Cleat hitch.</b> Used at every marina, every pontoon, and every
|
|
dock that the <i>Pagination</i> visited. The cleat hitch is not a
|
|
glamorous knot — it is the workhorse of the marina, the knot
|
|
equivalent of a reliable sedan — but it is satisfyingly quick
|
|
to tie and untie, and it holds with absolute reliability in any
|
|
conditions. Anchora could do it in four seconds. She timed herself,
|
|
because she was the sort of person who timed herself tying knots, and
|
|
she regarded this as a perfectly normal hobby. The cleat hitch involves
|
|
one full turn around the base of the cleat, followed by two
|
|
figure-eight turns over the horns, finished with a locking hitch. The
|
|
locking hitch is optional but recommended by Anchora, who had once seen
|
|
an unlocked cleat hitch work loose in a gale and release a thirty-foot
|
|
yacht into the fairway, where it drifted gently into a row of dinghies
|
|
and caused what the insurance industry would later describe as a
|
|
“multi-vessel incident.”</p>
|
|
|
|
<p><b>Figure-eight.</b> Used as a stopper knot on every sheet and
|
|
halyard aboard the <i>Pagination</i>. The figure-eight prevents the
|
|
line from running out through its block or fairlead, which is the kind
|
|
of thing that happens at the worst possible moment — during a
|
|
tack, in heavy weather, when both hands are already occupied with
|
|
something else that is going wrong. The figure-eight is the kind of
|
|
knot that, once learned, the fingers tie without consulting the brain.
|
|
Anchora tied figure-eights the way other people blink: automatically,
|
|
unconsciously, and with a frequency that suggested a deep-seated
|
|
neurological commitment to the prevention of runaway lines.</p>
|
|
|
|
<p><b>Round turn and two half-hitches.</b> Used for securing the dinghy
|
|
painter to rocks, trees, and the occasional bollard that was too large
|
|
or too oddly shaped for a bowline. This knot is not elegant, but it is
|
|
secure, adjustable, and can be tied around objects of any shape, which
|
|
makes it the knot of last resort — the one you reach for when
|
|
nothing else will work. Anchora used it approximately once per week and
|
|
thought about it approximately never, which is the highest compliment
|
|
a sailor can pay a knot.</p>
|
|
|
|
<p><b>Reef knot.</b> Used for tying reef points when shortening sail.
|
|
The reef knot is perhaps the most misunderstood knot in the nautical
|
|
lexicon: it is often taught as a general-purpose binding knot, which it
|
|
is not. It will slip if loaded unevenly, it will jam if loaded
|
|
heavily, and it will capsize if looked at sternly. For tying reef
|
|
points, however, it is perfect: quick to tie, quick to untie, and
|
|
adequate for the modest loads involved. Anchora tied reef knots in the
|
|
dark, in the rain, on a heaving deck, with numb fingers, and the reef
|
|
knot never once let her down, because she never once asked it to do
|
|
anything it was not designed to do.</p>
|
|
|
|
<p><b>Sheet bend.</b> Used for joining two lines of different diameter.
|
|
Anchora used this knot exactly once during the voyage, when she needed
|
|
to extend her lead-line with a lighter-weight extension over the deep
|
|
water. The sheet bend held, the sounding was taken, and the knot was
|
|
untied. It was, she reflected, the knot equivalent of a specialist
|
|
consultant: expensive to learn, rarely needed, but invaluable on the
|
|
one occasion you called upon it.</p>
|
|
|
|
<h1 id="appendix-b">Appendix B<br/>Signal Flags Observed</h1>
|
|
|
|
<p>During the voyage, the following International Code of Signals flags
|
|
were observed flying from other vessels. The International Code is a
|
|
system of flag signals that allows ships of different nationalities to
|
|
communicate without a common language, which is an admirable ambition
|
|
that works considerably better in theory than in practice, because the
|
|
system assumes that all parties can identify forty flags at a distance
|
|
and under conditions that typically include spray, glare, and a
|
|
rolling deck.</p>
|
|
|
|
<p><b>Alpha.</b> A white and blue swallowtail flag. “I have a
|
|
diver down; keep well clear at slow speed.” Observed near the
|
|
reef, flying from a battered workboat whose diver was, presumably,
|
|
somewhere below, doing whatever it is that divers do in two metres of
|
|
water over a coral reef. Anchora kept well clear, as instructed, and
|
|
made a note of the workboat’s position so that she could add a
|
|
“diving operations” annotation to her chart of the reef.
|
|
She later removed the annotation on the grounds that the diving was
|
|
presumably temporary, whereas the chart was intended to be permanent, or
|
|
at least as permanent as a chart of a reef can be when the reef is
|
|
still growing.</p>
|
|
|
|
<p><b>Bravo.</b> A red swallowtail flag. “I am taking in, or
|
|
discharging, or carrying dangerous goods.” Observed at the Twin
|
|
Harbors, flying from a rusty coaster that was moored alongside the
|
|
north quay in East Harbor (or possibly West Harbor; the question, as
|
|
always, remained unresolved). The dangerous goods turned out to be a
|
|
crate of live chickens, which the harbourmaster’s regulations
|
|
classified as “livestock” but which the chickens’
|
|
behaviour — aggressive, noisy, and apparently attempting to
|
|
escape — suggested might more accurately have been classified as
|
|
“hazardous materials.”</p>
|
|
|
|
<p><b>Hotel.</b> A white flag with a red vertical stripe. “I
|
|
have a pilot on board.” Observed on Rufus’s pilot boat,
|
|
naturally, and on several vessels entering and leaving the Twin Harbors
|
|
under his guidance. The Hotel flag is one of the more useful signals in
|
|
the code, as it tells other vessels that the flagged vessel is being
|
|
navigated by someone who knows the local waters, and that any unusual
|
|
manoeuvres it performs are probably intentional rather than accidental.
|
|
Anchora flew the Hotel flag exactly once, when Rufus came aboard to
|
|
guide her through the cut between the two harbors, and she removed it
|
|
the moment he left, because flying a pilot flag without a pilot aboard
|
|
is both improper and illegal, and Anchora was punctilious about such
|
|
things.</p>
|
|
|
|
<p><b>November.</b> A chequered blue and white flag. “No”
|
|
or “negative.” Observed on a yacht that was being hailed
|
|
by the coast guard and appeared to be declining to stop. Anchora watched
|
|
this exchange with professional interest and noted in her log that the
|
|
yacht was making nine knots downwind, which was probably insufficient
|
|
to outrun the coast guard cutter but was certainly a spirited attempt.
|
|
The outcome of the pursuit was not recorded, as the <i>Pagination</i>
|
|
had by then sailed out of visual range.</p>
|
|
|
|
<p><b>Quebec.</b> A solid yellow flag. “My vessel is healthy and
|
|
I request free pratique.” Flown by the <i>Pagination</i> herself
|
|
upon arrival at each port, mostly out of optimism. Free pratique is
|
|
permission to make contact with the shore, granted by the port health
|
|
authority after they have satisfied themselves that your vessel is not
|
|
carrying plague, cholera, or any other communicable disease. In modern
|
|
times, the flag is largely ceremonial — most ports grant
|
|
pratique automatically — but Anchora flew it anyway, because
|
|
traditions are traditions, and because a yellow flag on a small sloop
|
|
entering a foreign harbor has a certain jaunty charm that she privately
|
|
enjoyed.</p>
|
|
|
|
<h1 id="appendix-c">Appendix C<br/>Tidal Observations</h1>
|
|
|
|
<p>Tidal data collected during the voyage is summarized below. All
|
|
times are approximate, all heights are measured from chart datum, and
|
|
all predictions should be treated with the same confidence one extends
|
|
to a weather forecast — which is to say, they are probably
|
|
correct, but you should not bet your keel on it.</p>
|
|
|
|
<p>Tides in the region are predominantly semi-diurnal, with two high
|
|
waters and two low waters in each lunar day. The tidal range varies
|
|
with the phase of the moon: greatest at springs (when the sun and moon
|
|
are aligned) and smallest at neaps (when they are at right angles).
|
|
Anchora recorded tidal observations at every anchorage, using a
|
|
graduated staff driven into the seabed at the waterline, which she
|
|
read at hourly intervals whenever she was aboard and awake, and at
|
|
less regular intervals when she was not.</p>
|
|
|
|
<p><b>Twin Harbors.</b> Semi-diurnal, range 1.8–2.4 m at
|
|
springs, 0.8–1.2 m at neaps. High water approximately coincides
|
|
with lunar transit, with a lag of roughly forty minutes that Anchora
|
|
attributed to the constriction of the harbor entrance and the friction
|
|
of the water flowing over the shallow bar at the approach channel. The
|
|
two basins exhibit a 12-minute phase lag — high water in East
|
|
Harbor occurs twelve minutes before high water in West Harbor —
|
|
which the locals blame on a submerged rock formation in the cut between
|
|
the two basins and Anchora blames on insufficient data. She measured
|
|
the phase lag on three consecutive tidal cycles and got three different
|
|
results: 10 minutes, 14 minutes, and 12 minutes. The average was 12
|
|
minutes. She reported 12 minutes. The truth, she suspected, was
|
|
considerably more complicated than a single number could express, but
|
|
a single number was what the chart demanded, and the chart was, for
|
|
better or worse, what people would rely on.</p>
|
|
|
|
<p><b>The Reef.</b> Tidal range similar to the Twin Harbors. The
|
|
critical observation for the reef is not the range but the height of
|
|
low water at springs, which determines how much of the coral is
|
|
exposed. At LAT (Lowest Astronomical Tide), several of the larger
|
|
coral heads break the surface, creating visible markers that are useful
|
|
for daylight navigation but invisible — and therefore lethal
|
|
— at night. Anchora marked these drying heights on her chart
|
|
with the standard symbol: a depth figure with a line underneath,
|
|
indicating that the number represents elevation above chart datum rather
|
|
than depth below it.</p>
|
|
|
|
<p><b>Whirlpool Narrows.</b> Tidal streams reach 4.5 kn at springs,
|
|
2.8 kn at neaps. The flood stream sets northward; the ebb sets
|
|
southward. Slack water occurs approximately 15 minutes before local
|
|
high and low water and lasts approximately 8 minutes at springs, 12
|
|
minutes at neaps. This is not a generous margin in either case, but
|
|
it is sufficient for a transit if the vessel is prepared and the skipper
|
|
decisive. Anchora recommended approaching the narrows under power
|
|
rather than sail, on the grounds that an engine provides consistent
|
|
thrust regardless of wind angle, whereas a sail provides consistent
|
|
anxiety regardless of everything.</p>
|
|
|
|
<p><b>Compass Rose Atoll.</b> Negligible tidal range inside the lagoon
|
|
(0.3 m at springs, barely measurable at neaps). This is because the
|
|
four passes, while wide enough for navigation, are narrow enough to
|
|
attenuate the tidal wave as it enters the lagoon, spreading the rise
|
|
and fall over a much longer period and reducing its amplitude to
|
|
almost nothing. The practical consequence is that the lagoon maintains
|
|
a nearly constant depth, which makes it an ideal anchorage in any
|
|
conditions — a rare and valuable quality in an archipelago where
|
|
most of the water is trying to go somewhere in a hurry. Currents
|
|
through the passes reach 2 kn on springs but are predictable and
|
|
well-behaved. Anchora described them in her notes as “the only
|
|
polite water in the archipelago.”</p>
|
|
|
|
<p><b>Isle of Echoes.</b> Semi-diurnal, range 1.6–2.0 m. The
|
|
tidal stream along the cliff face sets to the north on the flood and
|
|
to the south on the ebb, reaching 1.5 kn at springs. The stream is
|
|
strongest at the headlands and weakest in the embayments, which is the
|
|
normal pattern for tidal flow around a rocky island and was entirely
|
|
predictable from the chart. What was not predictable was the acoustic
|
|
effect of the tide on the cave systems at the base of the cliffs:
|
|
at certain states of the tide, the incoming water compressed the air
|
|
inside the caves and produced a low, resonant boom that could be heard
|
|
from the anchorage, half a mile away. Anchora noted this phenomenon
|
|
in her log but did not add it to the chart, on the grounds that
|
|
“makes spooky noises at half tide” was not a recognised
|
|
chart annotation.</p>
|
|
|
|
<h1 id="appendix-d">Appendix D<br/>Errata</h1>
|
|
|
|
<p>No errors have been found. This is, in itself, suspicious.</p>
|
|
|
|
<h1 id="appendix-e">Appendix E<br/>Acknowledgments</h1>
|
|
|
|
<p>The author wishes to thank the penguins.</p>
|
|
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# BACKMATTER — TOC points to #colophon (mid-file), not file start
|
|
# ---------------------------------------------------------------------------
|
|
|
|
BACKMATTER = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head><title>Back Matter</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/></head>
|
|
<body>
|
|
|
|
<h2>Author’s Note</h2>
|
|
|
|
<p>This section has no entry in the table of contents. If you have
|
|
arrived here by paging forward from the appendices, congratulations:
|
|
you are reading in spine order, which is the only reliable way to find
|
|
content that the navigation has chosen to ignore.</p>
|
|
|
|
<p>The Author’s Note exists to test a specific edge case: a
|
|
spine item whose table-of-contents entry points not to the beginning
|
|
of the file, but to an anchor partway through it. Everything above the
|
|
anchor is “dark matter” — present in the document,
|
|
reachable by paging, but invisible to the TOC.</p>
|
|
|
|
<p>Consider, for a moment, what this means for a reading application.
|
|
When a user taps “Colophon” in the table of contents,
|
|
the application must navigate not to the start of this file, but to
|
|
the <i>colophon</i> anchor partway through it. The content above the
|
|
anchor — the text you are reading right now — exists in
|
|
the spine, occupies space on the page, and can be reached by turning
|
|
pages forward from the appendices. But it cannot be reached by any
|
|
navigation element. It is, in the language of the EPUB specification,
|
|
part of the spine order but outside the navigation document.</p>
|
|
|
|
<p>This creates an interesting problem for any reader that attempts to
|
|
map TOC entries to page ranges. If the TOC says the Colophon begins
|
|
at anchor #colophon, what is the page range of the content before
|
|
that anchor? Does it belong to the previous TOC entry (Appendix C)?
|
|
Does it belong to the Colophon? Does it belong to no entry at all?
|
|
These are the kinds of questions that this test fixture is designed
|
|
to provoke.</p>
|
|
|
|
<p>Anchora would have had opinions about this. Cartographers do not
|
|
approve of places that exist but cannot be navigated to. An island
|
|
without a name on the chart is an island that will, sooner or later,
|
|
catch a keel.</p>
|
|
|
|
<p>But perhaps some content is meant to be found only by those who
|
|
read sequentially, page by page, without jumping ahead. Perhaps the
|
|
Author’s Note is a reward for patience. Or perhaps it is
|
|
simply a test fixture dressed up in a narrative voice.</p>
|
|
|
|
<p>Either way, you have found it. Well done.</p>
|
|
|
|
<h2 id="colophon">Colophon</h2>
|
|
|
|
<p>This EPUB was generated by a Python script as a test fixture for the
|
|
Crosspoint Reader project. It is not a real book, though it contains
|
|
real sentences arranged in a real order, which is more than can be said
|
|
for some publications that aspire to the title.</p>
|
|
|
|
<p>The spine of this EPUB contains fourteen items. Its table of contents
|
|
contains eighteen entries. The relationship between the two is, by
|
|
design, entertainingly non-trivial. Specifically:</p>
|
|
|
|
<p>Three TOC entries point to anchors within <i>frontmatter.xhtml</i>,
|
|
making it a single spine item with multiple navigation targets. Four
|
|
TOC entries (one parent and three children) point to anchors within
|
|
<i>chapter3.xhtml</i>, and four more point into <i>chapter5.xhtml</i>,
|
|
testing nested TOC hierarchies within a single spine item. Three TOC
|
|
entries point to anchors within <i>appendix.xhtml</i>, the same
|
|
pattern without nesting. Two of these appendix entries (D and E)
|
|
are deliberately tiny — a single sentence each — to
|
|
test how the reader handles TOC sections too small to fill a
|
|
screen.</p>
|
|
|
|
<p>Chapter 2 occupies two spine items (<i>chapter2_part1.xhtml</i> and
|
|
<i>chapter2_part2.xhtml</i>) but appears as a single entry in the TOC.
|
|
Chapter 4 occupies three spine items and also appears as a single TOC
|
|
entry. These test the case where a reader must determine that consecutive
|
|
spine items belong to the same logical chapter.</p>
|
|
|
|
<p>The interlude (<i>interlude.xhtml</i>) appears in the spine between
|
|
Chapter 3 and Chapter 4 but has no TOC entry whatsoever, testing the
|
|
case where spine items exist outside the navigation hierarchy.</p>
|
|
|
|
<p>And this very file (<i>backmatter.xhtml</i>) has a TOC entry that
|
|
points to the #colophon anchor, which is not at the beginning of the
|
|
file. The Author’s Note above occupies the first portion of the
|
|
file but is invisible to the TOC, testing the case where a navigation
|
|
target lands in the middle of a document.</p>
|
|
|
|
<p>The cover image was generated programmatically using the Bookerly
|
|
typeface at 536×800 pixels, rendered on a deep teal background
|
|
(RGB 15, 55, 65) with light beige text (RGB 225, 220, 205).</p>
|
|
|
|
<p>No penguins were harmed in the making of this book. Several were
|
|
mildly inconvenienced, but they bore it with their customary dignity.</p>
|
|
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# EPUB boilerplate
|
|
# ---------------------------------------------------------------------------
|
|
|
|
COVER_XHTML = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head><title>Cover</title>
|
|
<style>
|
|
body { margin: 0; padding: 0; text-align: center; }
|
|
img { max-width: 100%; max-height: 100%; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<img src="cover.jpg" alt="Spine & Anchor: A Nautical Misadventure"/>
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
STYLESHEET = """\
|
|
body {
|
|
font-family: serif;
|
|
margin: 2em;
|
|
line-height: 1.6;
|
|
}
|
|
h1 {
|
|
font-size: 1.5em;
|
|
text-align: center;
|
|
margin-bottom: 1.5em;
|
|
line-height: 1.3;
|
|
}
|
|
h2 {
|
|
font-size: 1.15em;
|
|
margin-top: 1.5em;
|
|
margin-bottom: 0.5em;
|
|
}
|
|
p {
|
|
text-indent: 1.5em;
|
|
margin: 0.25em 0;
|
|
text-align: justify;
|
|
}
|
|
blockquote p {
|
|
text-indent: 0;
|
|
margin: 0.5em 1.5em;
|
|
font-style: italic;
|
|
}
|
|
"""
|
|
|
|
CONTAINER_XML = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
|
|
<rootfiles>
|
|
<rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/>
|
|
</rootfiles>
|
|
</container>
|
|
"""
|
|
|
|
CONTENT_OPF = f"""\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="BookId" version="3.0">
|
|
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
|
|
<dc:identifier id="BookId">urn:uuid:{BOOK_UUID}</dc:identifier>
|
|
<dc:title>{TITLE}</dc:title>
|
|
<dc:creator>{AUTHOR}</dc:creator>
|
|
<dc:language>en</dc:language>
|
|
<dc:date>{DATE}</dc:date>
|
|
<meta property="dcterms:modified">{DATE}T00:00:00Z</meta>
|
|
<meta name="cover" content="cover-image"/>
|
|
</metadata>
|
|
<manifest>
|
|
<item id="cover-image" href="cover.jpg" media-type="image/jpeg" properties="cover-image"/>
|
|
<item id="cover" href="cover.xhtml" media-type="application/xhtml+xml"/>
|
|
<item id="style" href="style.css" media-type="text/css"/>
|
|
<item id="frontmatter" href="frontmatter.xhtml" media-type="application/xhtml+xml"/>
|
|
<item id="ch1" href="chapter1.xhtml" media-type="application/xhtml+xml"/>
|
|
<item id="ch2p1" href="chapter2_part1.xhtml" media-type="application/xhtml+xml"/>
|
|
<item id="ch2p2" href="chapter2_part2.xhtml" media-type="application/xhtml+xml"/>
|
|
<item id="ch3" href="chapter3.xhtml" media-type="application/xhtml+xml"/>
|
|
<item id="interlude" href="interlude.xhtml" media-type="application/xhtml+xml"/>
|
|
<item id="ch4p1" href="chapter4_part1.xhtml" media-type="application/xhtml+xml"/>
|
|
<item id="ch4p2" href="chapter4_part2.xhtml" media-type="application/xhtml+xml"/>
|
|
<item id="ch4p3" href="chapter4_part3.xhtml" media-type="application/xhtml+xml"/>
|
|
<item id="ch5" href="chapter5.xhtml" media-type="application/xhtml+xml"/>
|
|
<item id="appendix" href="appendix.xhtml" media-type="application/xhtml+xml"/>
|
|
<item id="backmatter" href="backmatter.xhtml" media-type="application/xhtml+xml"/>
|
|
<item id="toc" href="toc.xhtml" media-type="application/xhtml+xml" properties="nav"/>
|
|
</manifest>
|
|
<spine>
|
|
<itemref idref="cover"/>
|
|
<itemref idref="toc"/>
|
|
<itemref idref="frontmatter"/>
|
|
<itemref idref="ch1"/>
|
|
<itemref idref="ch2p1"/>
|
|
<itemref idref="ch2p2"/>
|
|
<itemref idref="ch3"/>
|
|
<itemref idref="interlude"/>
|
|
<itemref idref="ch4p1"/>
|
|
<itemref idref="ch4p2"/>
|
|
<itemref idref="ch4p3"/>
|
|
<itemref idref="ch5"/>
|
|
<itemref idref="appendix"/>
|
|
<itemref idref="backmatter"/>
|
|
</spine>
|
|
</package>
|
|
"""
|
|
|
|
TOC_XHTML = """\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops"
|
|
xml:lang="en" lang="en">
|
|
<head><title>Table of Contents</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css"/></head>
|
|
<body>
|
|
<h1>Spine & Anchor</h1>
|
|
<nav epub:type="toc">
|
|
<ol>
|
|
<li><a href="frontmatter.xhtml#dedication">Dedication</a></li>
|
|
<li><a href="frontmatter.xhtml#epigraph">Epigraph</a></li>
|
|
<li><a href="frontmatter.xhtml#foreword">Foreword</a></li>
|
|
<li><a href="chapter1.xhtml">Chapter 1 – Setting Sail</a></li>
|
|
<li><a href="chapter2_part1.xhtml">Chapter 2 – The Twin Harbors</a></li>
|
|
<li>
|
|
<a href="chapter3.xhtml">Chapter 3 – Charting the Depths</a>
|
|
<ol>
|
|
<li><a href="chapter3.xhtml#the-reef">The Reef</a></li>
|
|
<li><a href="chapter3.xhtml#the-current">The Current</a></li>
|
|
<li><a href="chapter3.xhtml#the-depths">The Depths</a></li>
|
|
</ol>
|
|
</li>
|
|
<li><a href="chapter4_part1.xhtml">Chapter 4 – The Long Voyage</a></li>
|
|
<li>
|
|
<a href="chapter5.xhtml">Chapter 5 – Archipelago of Wonders</a>
|
|
<ol>
|
|
<li><a href="chapter5.xhtml#isle-of-echoes">Isle of Echoes</a></li>
|
|
<li><a href="chapter5.xhtml#compass-rose-atoll">Compass Rose Atoll</a></li>
|
|
<li><a href="chapter5.xhtml#whirlpool-narrows">The Whirlpool Narrows</a></li>
|
|
</ol>
|
|
</li>
|
|
<li><a href="appendix.xhtml#appendix-a">Appendix A – Knot Types</a></li>
|
|
<li><a href="appendix.xhtml#appendix-b">Appendix B – Signal Flags</a></li>
|
|
<li><a href="appendix.xhtml#appendix-c">Appendix C – Tidal Observations</a></li>
|
|
<li><a href="appendix.xhtml#appendix-d">Appendix D – Errata</a></li>
|
|
<li><a href="appendix.xhtml#appendix-e">Appendix E – Acknowledgments</a></li>
|
|
<li><a href="backmatter.xhtml#colophon">Colophon</a></li>
|
|
</ol>
|
|
</nav>
|
|
</body>
|
|
</html>
|
|
"""
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Build
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def build_epub(output_path: str):
|
|
cover_data = create_cover_image()
|
|
|
|
with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as zf:
|
|
zf.writestr("mimetype", "application/epub+zip", compress_type=zipfile.ZIP_STORED)
|
|
zf.writestr("META-INF/container.xml", CONTAINER_XML)
|
|
zf.writestr("OEBPS/content.opf", CONTENT_OPF)
|
|
zf.writestr("OEBPS/toc.xhtml", TOC_XHTML)
|
|
zf.writestr("OEBPS/style.css", STYLESHEET)
|
|
zf.writestr("OEBPS/cover.jpg", cover_data)
|
|
zf.writestr("OEBPS/cover.xhtml", COVER_XHTML)
|
|
zf.writestr("OEBPS/frontmatter.xhtml", FRONTMATTER)
|
|
zf.writestr("OEBPS/chapter1.xhtml", CHAPTER_1)
|
|
zf.writestr("OEBPS/chapter2_part1.xhtml", CHAPTER_2_PART1)
|
|
zf.writestr("OEBPS/chapter2_part2.xhtml", CHAPTER_2_PART2)
|
|
zf.writestr("OEBPS/chapter3.xhtml", CHAPTER_3)
|
|
zf.writestr("OEBPS/interlude.xhtml", INTERLUDE)
|
|
zf.writestr("OEBPS/chapter4_part1.xhtml", CHAPTER_4_PART1)
|
|
zf.writestr("OEBPS/chapter4_part2.xhtml", CHAPTER_4_PART2)
|
|
zf.writestr("OEBPS/chapter4_part3.xhtml", CHAPTER_4_PART3)
|
|
zf.writestr("OEBPS/chapter5.xhtml", CHAPTER_5)
|
|
zf.writestr("OEBPS/appendix.xhtml", APPENDIX)
|
|
zf.writestr("OEBPS/backmatter.xhtml", BACKMATTER)
|
|
print(f"EPUB written to {output_path}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
out = os.path.join(project_root, "test", "epubs", "test_spine_toc_edges.epub")
|
|
os.makedirs(os.path.dirname(out), exist_ok=True)
|
|
build_epub(out)
|