Dropcap
This commit is contained in:
1 parent
6edc542ea5
commit
04ea39607d
6 files changed
+158
-10
No files matched your search
+52
-3
@@ -453,11 +453,51 @@ def ref_href(node, book, chapter):
|
||||
return "%s#%s" % (base, verse_id(target_ch, verse))
|
||||
return "%s#ch%d" % (base, target_ch)
|
||||
|
||||
DROPCAP_BLOCKS = ("paragraph", "line", "item")
|
||||
|
||||
def with_dropcap(nodes):
|
||||
"""Split the first letter of the first text off into a dropcap node.
|
||||
|
||||
Returns the new node list, or None when the text does not start with a
|
||||
letter. The initials font has only A-Z and a-z, so a chapter opening on
|
||||
a quotation mark or a digit gets no drop cap rather than a fallback one.
|
||||
"""
|
||||
nodes = list(nodes)
|
||||
for i, node in enumerate(nodes):
|
||||
kind = node["t"]
|
||||
if kind == "verse":
|
||||
continue
|
||||
# A note caller would land between the letter and the rest of its word.
|
||||
if kind == "noteref":
|
||||
return None
|
||||
if kind == "text":
|
||||
text = node["v"].lstrip()
|
||||
if not text:
|
||||
continue
|
||||
if not ("A" <= text[0] <= "Z" or "a" <= text[0] <= "z"):
|
||||
return None
|
||||
nodes[i:i + 1] = [{"t": "dropcap", "v": text[0]},
|
||||
dict(node, v=text[1:])]
|
||||
else:
|
||||
inner = with_dropcap(node.get("c", []))
|
||||
if inner is None:
|
||||
return None
|
||||
nodes[i] = dict(node, c=inner)
|
||||
# The verse number before the drop cap would otherwise sit between
|
||||
# the floated letter and the rest of its word.
|
||||
for j in range(i):
|
||||
if nodes[j]["t"] == "verse":
|
||||
nodes[j] = dict(nodes[j], dropcap=True)
|
||||
return nodes
|
||||
return None
|
||||
|
||||
def render_inline(nodes, book, chapter, out):
|
||||
for node in nodes:
|
||||
kind = node["t"]
|
||||
if kind == "text":
|
||||
out.append(esc(node["v"]))
|
||||
elif kind == "dropcap":
|
||||
out.append('<span class="dropcap">%s</span>' % esc(node["v"]))
|
||||
elif kind == "verse":
|
||||
label = esc(node["label"])
|
||||
vid = verse_id(chapter, node["label"])
|
||||
@@ -466,10 +506,13 @@ def render_inline(nodes, book, chapter, out):
|
||||
# that dialog. Being a real link is also what gives it the
|
||||
# keyboard and context menu a reader expects.
|
||||
out.append('<a class="v" id="%s" href="#%s" '
|
||||
# A non-breaking space keeps the number on the same
|
||||
# line as the word it introduces, as the source does.
|
||||
'aria-label="Verse %s, options">%s</a> '
|
||||
'aria-label="Verse %s, options">%s</a>'
|
||||
% (vid, vid, label, label))
|
||||
# A non-breaking space keeps the number on the same line as the
|
||||
# word it introduces, as the source does. Before a drop cap the
|
||||
# number is hidden and the space would only push the word away.
|
||||
if not node.get("dropcap"):
|
||||
out.append(" ")
|
||||
elif kind == "noteref":
|
||||
n = node["id"].replace("FN", "")
|
||||
out.append('<a class="noteref" id="fnref%s_%s" href="#fn%s_%s">'
|
||||
@@ -550,8 +593,14 @@ def render_chapter(chapter, book, out):
|
||||
out.append(" </ul>\n")
|
||||
group = None
|
||||
|
||||
dropcap = True
|
||||
for block in chapter["blocks"]:
|
||||
btype = block["type"]
|
||||
if dropcap and btype in DROPCAP_BLOCKS:
|
||||
dropcap = False
|
||||
content = with_dropcap(block.get("content", []))
|
||||
if content is not None:
|
||||
block = dict(block, content=content)
|
||||
if btype == "break":
|
||||
close_group()
|
||||
continue
|
||||
|
||||
Reference in new issue
Block a user