mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-06-07 21:23:31 +02:00
Added a CSS file to the epub output format.
This commit is contained in:
+23
-3
@@ -1,11 +1,11 @@
|
||||
from typing import Mapping
|
||||
|
||||
from ebooklib import epub
|
||||
from ebooklib import epub, ITEM_STYLE
|
||||
from docutils import core
|
||||
from sphinx.util.docstrings import prepare_docstring
|
||||
from docutils.writers.html5_polyglot import Writer as HTMLWriter
|
||||
|
||||
from dungeonsheets.latex import dice_re
|
||||
from dungeonsheets.forms import dice_re, jinja_environment
|
||||
|
||||
|
||||
def create_epub(
|
||||
@@ -35,12 +35,21 @@ def create_epub(
|
||||
book.set_identifier('id123456')
|
||||
book.set_title(title)
|
||||
book.set_language('en')
|
||||
# Add the css files
|
||||
css_template = jinja_env.get_template("dungeonsheets_epub.css")
|
||||
style = css_template.render(use_dnd_decorations=use_dnd_decorations)
|
||||
css = epub.EpubItem(uid="style_default", file_name="style/gm_sheet.css",
|
||||
media_type="text/css", content=style)
|
||||
book.add_item(css)
|
||||
# Create the separate chapters
|
||||
html_chapters = []
|
||||
for chap_title, content in chapters.items():
|
||||
chap_fname = "{}.html".format(chap_title.replace(" ", "_").lower())
|
||||
chapter = epub.EpubHtml(title=chap_title, file_name=chap_fname, lang="en")
|
||||
chapter = epub.EpubHtml(title=chap_title,
|
||||
file_name=chap_fname, lang="en",
|
||||
media_type="application/xhtml+xml")
|
||||
chapter.set_content(content)
|
||||
chapter.add_item(css)
|
||||
book.add_item(chapter)
|
||||
html_chapters.append(chapter)
|
||||
# Add the table of contents
|
||||
@@ -137,3 +146,14 @@ def rst_to_html(rst, top_heading_level=0):
|
||||
_html_parts = html_parts(rst)
|
||||
html = _html_parts["body"]
|
||||
return html
|
||||
|
||||
|
||||
def to_heading_id(inpt: str) -> str:
|
||||
"""Take a string and make it suitable for use as an HTML header id."""
|
||||
return inpt.replace(" ", "-")
|
||||
|
||||
|
||||
# Prepare the jinja environment
|
||||
jinja_env = jinja_environment()
|
||||
jinja_env.filters['rst_to_html'] = rst_to_html
|
||||
jinja_env.filters['to_heading_id'] = to_heading_id
|
||||
|
||||
@@ -6,7 +6,7 @@ import warnings
|
||||
import pdfrw
|
||||
from fdfgen import forge_fdf
|
||||
|
||||
from dungeonsheets.stats import mod_str
|
||||
from dungeonsheets.forms import mod_str
|
||||
|
||||
CHECKBOX_ON = "Yes"
|
||||
CHECKBOX_OFF = "Off"
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import re
|
||||
|
||||
from jinja2 import Environment, PackageLoader
|
||||
|
||||
|
||||
# A dice string, with optional backticks: ``1d6 + 3``
|
||||
dice_re = re.compile(r"`*(\d+d\d+(?:\s*\+\s*\d+)?)`*")
|
||||
|
||||
|
||||
def mod_str(modifier):
|
||||
"""Converts a modifier to a string, eg 2 -> '+2'."""
|
||||
return "{:+d}".format(modifier)
|
||||
|
||||
|
||||
def jinja_environment():
|
||||
"""Prepare a new environment for Jinja templates.
|
||||
|
||||
This function loads filters that are agnostic to the output
|
||||
format. Format specific filters (e.g. html, latex, etc.) should be
|
||||
added to ``jinja_env.filters``.
|
||||
|
||||
Returns
|
||||
-------
|
||||
jinja_env
|
||||
The newly created jinja environment.
|
||||
|
||||
"""
|
||||
jinja_env = Environment(
|
||||
loader=PackageLoader("dungeonsheets", "forms"),
|
||||
block_start_string="[%",
|
||||
block_end_string="%]",
|
||||
variable_start_string="[[",
|
||||
variable_end_string="]]",
|
||||
)
|
||||
jinja_env.filters["mod_str"] = mod_str
|
||||
return jinja_env
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: #58180d;
|
||||
}
|
||||
/* End fancy decorations */
|
||||
|
||||
table {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
th {
|
||||
border-style: solid;
|
||||
border-width: 0px;
|
||||
border-bottom-width: 1px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
td {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
dd > p {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
div.system-message {
|
||||
background: pink;
|
||||
border-color: red;
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
color: red;
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
<h1 id="gm-monsters">Monsters</h1>
|
||||
|
||||
[% for monster in monsters|sort(attribute='name') %]
|
||||
<h1 id="gm-monsters-[[ monster.name ]]">[[ monster.name ]]</h1>
|
||||
<h2 id="gm-monsters-[[ monster.name|to_heading_id ]]">[[ monster.name ]]</h1>
|
||||
|
||||
[% if monster.description %]
|
||||
<h2>[[ monster.description ]]</h2>
|
||||
<h3>[[ monster.description ]]</h2>
|
||||
[% endif %]
|
||||
|
||||
<!-- Basic properties -->
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>My title</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -8,15 +8,12 @@ from docutils.writers.latex2e import Writer, Table, LaTeXTranslator
|
||||
from sphinx.util.docstrings import prepare_docstring
|
||||
|
||||
from dungeonsheets import exceptions
|
||||
from dungeonsheets.forms import dice_re
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# A dice string, with optional backticks: ``1d6 + 3``
|
||||
dice_re = re.compile(r"`*(\d+d\d+(?:\s*\+\s*\d+)?)`*")
|
||||
|
||||
|
||||
class LatexWriter(Writer):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
@@ -11,10 +11,8 @@ from multiprocessing import Pool, cpu_count
|
||||
from itertools import product
|
||||
from typing import Union, Sequence, Optional
|
||||
|
||||
from jinja2 import Environment, PackageLoader
|
||||
|
||||
from dungeonsheets import character as _char, exceptions, readers, latex, epub, monsters
|
||||
from dungeonsheets.stats import mod_str
|
||||
from dungeonsheets import character as _char, exceptions, readers, latex, epub, monsters, forms
|
||||
from dungeonsheets.forms import mod_str
|
||||
from dungeonsheets.content_registry import find_content
|
||||
from dungeonsheets.fill_pdf_template import (
|
||||
create_character_pdf_template,
|
||||
@@ -41,21 +39,16 @@ ORDINALS = {
|
||||
9: "9th",
|
||||
}
|
||||
|
||||
jinja_env = Environment(
|
||||
loader=PackageLoader("dungeonsheets", "forms"),
|
||||
block_start_string="[%",
|
||||
block_end_string="%]",
|
||||
variable_start_string="[[",
|
||||
variable_end_string="]]",
|
||||
)
|
||||
jinja_env.filters["rst_to_latex"] = latex.rst_to_latex
|
||||
jinja_env.filters["rst_to_html"] = epub.rst_to_html
|
||||
jinja_env.filters["mod_str"] = mod_str
|
||||
|
||||
|
||||
PDFTK_CMD = "pdftk"
|
||||
|
||||
|
||||
jinja_env = forms.jinja_environment()
|
||||
jinja_env.filters["rst_to_latex"] = latex.rst_to_latex
|
||||
jinja_env.filters["rst_to_html"] = epub.rst_to_html
|
||||
jinja_env.filters["to_heading_id"] = epub.to_heading_id
|
||||
|
||||
|
||||
# Custom types
|
||||
File = Union[Path, str]
|
||||
|
||||
@@ -219,12 +212,13 @@ def make_gm_sheet(
|
||||
gm_file = Path(gm_file)
|
||||
basename = gm_file.stem
|
||||
gm_props = readers.read_sheet_file(gm_file)
|
||||
session_title = gm_props.get("session_title", f"GM Notes: {basename}")
|
||||
# Create the intro tex
|
||||
content_suffix = format_suffixes[output_format]
|
||||
content = [
|
||||
jinja_env.get_template(f"preamble.{content_suffix}").render(
|
||||
use_dnd_decorations=fancy_decorations,
|
||||
title=gm_props.pop("session_title", "GM Session Notes"),
|
||||
title=session_title,
|
||||
)
|
||||
]
|
||||
# Add the party stats table and session summary
|
||||
@@ -302,9 +296,9 @@ def make_gm_sheet(
|
||||
log.warning(f"``pdflatex`` not available. Skipping {basename}")
|
||||
elif output_format == "epub":
|
||||
epub.create_epub(
|
||||
chapters={"GM Sheet": "".join(content)},
|
||||
chapters={session_title: "".join(content)},
|
||||
basename=basename,
|
||||
title=gm_props.get("session_title", f"GM Notes: {basename}"),
|
||||
title=session_title,
|
||||
use_dnd_decorations=fancy_decorations,
|
||||
)
|
||||
else:
|
||||
|
||||
@@ -30,11 +30,6 @@ from dungeonsheets.features import (
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def mod_str(modifier):
|
||||
"""Converts a modifier to a string, eg 2 -> '+2'."""
|
||||
return "{:+d}".format(modifier)
|
||||
|
||||
|
||||
AbilityScore = namedtuple("AbilityScore", ("value", "modifier", "saving_throw"))
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@ setup(name='dungeonsheets',
|
||||
'../VERSION']
|
||||
},
|
||||
install_requires=[
|
||||
'fdfgen', 'npyscreen', 'jinja2', 'pdfrw', 'sphinx', 'EbookLib',
|
||||
'fdfgen', 'npyscreen', 'jinja2', 'pdfrw', 'sphinx',
|
||||
'EbookLib',
|
||||
],
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
|
||||
@@ -55,10 +55,10 @@ class MakeSheetsTestCase(unittest.TestCase):
|
||||
class EpubOutputTestCase(unittest.TestCase):
|
||||
gm_epub = Path(f"{GMFILE.stem}.epub").resolve()
|
||||
|
||||
def tearDown(self):
|
||||
for f in [self.gm_epub]:
|
||||
if f.exists():
|
||||
f.unlink()
|
||||
# def tearDown(self):
|
||||
# for f in [self.gm_epub]:
|
||||
# if f.exists():
|
||||
# f.unlink()
|
||||
|
||||
def test_file_created(self):
|
||||
# Check that a file is created once the function is run
|
||||
|
||||
Reference in New Issue
Block a user