mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-05-18 20:23:27 +02:00
Added ability to make epub files for character sheets (missing stats and spell list).
This commit is contained in:
@@ -3,6 +3,9 @@ examples/*.pdf
|
|||||||
examples/*.aux
|
examples/*.aux
|
||||||
examples/*.tex
|
examples/*.tex
|
||||||
|
|
||||||
|
# Generated epub files
|
||||||
|
examples/*.epub
|
||||||
|
|
||||||
# Emacs temp files
|
# Emacs temp files
|
||||||
*~
|
*~
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,6 @@ class SlipperyMind(Feature):
|
|||||||
proficiency in Wisdom saving throws.
|
proficiency in Wisdom saving throws.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = "Slippery Mind"
|
name = "Slippery Mind"
|
||||||
source = "Rogue"
|
source = "Rogue"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<h1 id="known-beasts">Known Beasts</h1>
|
||||||
|
|
||||||
|
[% for shape in character.all_wild_shapes|sort(attribute='challenge_rating') %]
|
||||||
|
|
||||||
|
|
||||||
|
<block class="[% if not character.can_assume_shape(shape) %]known-beast-disabled[% endif %]">
|
||||||
|
|
||||||
|
<h2 id="known-beasts-[[ shape.name | to_heading_id ]]">[[ shape.name ]]</h2>
|
||||||
|
|
||||||
|
[% if shape.description %]
|
||||||
|
<p>[[ shape.description ]]</p>
|
||||||
|
[% endif %]
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Armor Class</th>
|
||||||
|
<th>Hit Points</th>
|
||||||
|
<th>Speed</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>[[ shape.armor_class ]]</td>
|
||||||
|
<td>[[ shape.hp_max ]] ([[ shape.hit_dice ]])</td>
|
||||||
|
<td>[[ shape.speed ]][% if shape.swim_speed %], [[ shape.swim_speed ]] swim[% endif %][% if shape.fly_speed %], [[ shape.fly_speed ]] fly[% endif %]</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>STR</th>
|
||||||
|
<th>DEX</th>
|
||||||
|
<th>CON</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>[[ shape.strength.value ]] ([[ shape.strength.modifier|mod_str ]])</td>
|
||||||
|
<td>[[ shape.dexterity.value ]] ([[ shape.dexterity.modifier|mod_str ]])</td>
|
||||||
|
<td>[[ shape.constitution.value ]] ([[ shape.constitution.modifier|mod_str ]])</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>Skills:</dt><dd>[[ shape.skills ]]</dd>
|
||||||
|
<dt>Senses:</dt><dd>[[ shape.senses ]]</dd>
|
||||||
|
<dt>Languages:</dt><dd>[[ shape.languages ]]</dd>
|
||||||
|
<dt>Resistance:</dt><dd>[[ shape.damage_resistance ]]</dd>
|
||||||
|
<dt>Immunities:</dt><dd>[[ shape.condition_immunities ]]</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<p>[[ shape.__doc__ | rst_to_html(top_heading_level=2) ]]</p>
|
||||||
|
|
||||||
|
[% endfor %]
|
||||||
|
|
||||||
|
</block>
|
||||||
@@ -1,7 +1,20 @@
|
|||||||
h1, h2, h3, h4, h5, h6 {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
color: #58180d;
|
color: #58180d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End fancy decorations */
|
/* End fancy decorations */
|
||||||
|
.known-beast-disabled {
|
||||||
|
color: lightgrey;
|
||||||
|
}
|
||||||
|
.not-implemented {
|
||||||
|
font-weight: bold;
|
||||||
|
color: darkred;
|
||||||
|
background: pink;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-school {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
@@ -32,10 +45,10 @@ dd > p {
|
|||||||
|
|
||||||
div.system-message {
|
div.system-message {
|
||||||
background: pink;
|
background: pink;
|
||||||
border-color: red;
|
border-color: darkred;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-width: 2px;
|
border-width: 2px;
|
||||||
color: red;
|
color: darkred;
|
||||||
}
|
}
|
||||||
.literal {
|
.literal {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<h1 id="features">Features</h1>
|
||||||
|
|
||||||
|
[% for feat in character.features %]
|
||||||
|
<h2 id="features-[[ feat.name | to_heading_id ]]">[[ feat.name ]]</h2>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>Source:</dt>
|
||||||
|
<dd>[[ feat.source ]]</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
[[ feat.__doc__|rst_to_html ]]
|
||||||
|
|
||||||
|
[% endfor %]
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<h1 id="infusions">Infusions</h1>
|
||||||
|
|
||||||
|
[% for inf in character.infusions %]
|
||||||
|
<h2 id="infusions-[[ inf.name | to_heading_id ]]">[[ inf.name ]]</h2>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
[% if inf.prerequisite %]
|
||||||
|
<dt>Prerequisite:</dt>
|
||||||
|
<dd>[[ inf.prerequisite ]]</dd>
|
||||||
|
[% endif %]
|
||||||
|
[% if inf.item %]
|
||||||
|
<dt>Item:</dt>
|
||||||
|
<dd>[[ inf.item ]]</dd>
|
||||||
|
[% endif %]
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
[[ inf.__doc__ | rst_to_html(top_heading_level=2) ]]
|
||||||
|
|
||||||
|
[% endfor %]
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<h1 id="magic-items">Magic Items</h1>
|
||||||
|
|
||||||
|
[% for mitem in character.magic_items %]
|
||||||
|
<h2 id="magic-items-[[ mitem.name | to_heading_id ]]">[[ mitem.name ]]</h2>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>Requires Attunement:</dt>
|
||||||
|
<dd>[[ mitem.requires_attunement ]]</dd>
|
||||||
|
<dt>Rarity:</dt>
|
||||||
|
<dd>[[ mitem.rarity ]]</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
[% if mitem.needs_implementation %]
|
||||||
|
<p class="not-implemented">**Not included in stats on Character Sheet</p>
|
||||||
|
[% endif %]
|
||||||
|
|
||||||
|
[[ mitem.__doc__|rst_to_html ]]
|
||||||
|
|
||||||
|
[% endfor %]
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<h1 id="spells">Spells</h1>
|
||||||
|
|
||||||
|
[% for spl in character.spells %]
|
||||||
|
|
||||||
|
<h2 id="spells-[[ spl.name | to_heading_id ]]">[[ spl.name ]]</h2>
|
||||||
|
|
||||||
|
<p class="spell-school">
|
||||||
|
<!-- Spell school and level -->
|
||||||
|
[% if spl.level > 0 %]
|
||||||
|
[[ spl.magic_school ]] Level [[ spl.level ]]
|
||||||
|
[% else %]
|
||||||
|
[[ spl.magic_school ]] Cantrip
|
||||||
|
[% endif %]
|
||||||
|
|
||||||
|
<!-- Ritual and/or concentration -->
|
||||||
|
[% if spl.ritual and spl.concentration %]
|
||||||
|
(ritual, concentration)
|
||||||
|
[% elif spl.ritual %]
|
||||||
|
(ritual)
|
||||||
|
[% elif spl.concentration %]
|
||||||
|
(concentration)
|
||||||
|
[% endif %]
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<dl class="spell-details">
|
||||||
|
<dt>Casting Time:</dt>
|
||||||
|
<dd>[[ spl.casting_time ]]</dd>
|
||||||
|
<dt>Duration:</dt>
|
||||||
|
<dd>[[ spl.duration ]]</dd>
|
||||||
|
<dt>Range:</dt>
|
||||||
|
<dd>[[ spl.casting_range ]]</dd>
|
||||||
|
<dt>Components:</dt>
|
||||||
|
<dd>[[ spl.component_string ]]</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<block class="spell-description">
|
||||||
|
[[ spl.__doc__ | rst_to_html(top_heading_level=1) ]]
|
||||||
|
</block>
|
||||||
|
|
||||||
|
[% endfor %]
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<h1 id="subclasses">Subclasses</h1>
|
||||||
|
|
||||||
|
[% for sc in character.subclasses if sc not in ['', None, 'None', 'none']%]
|
||||||
|
<h2 id="subclasses-[[ sc.name | to_heading_id ]]">[[ sc.name ]]</h2><!-- Would like to add source here -->
|
||||||
|
|
||||||
|
[[ sc.__doc__ | rst_to_html(top_heading_level=2) ]]
|
||||||
|
|
||||||
|
[% endfor %]
|
||||||
@@ -61,28 +61,22 @@ jinja_env.filters["to_heading_id"] = epub.to_heading_id
|
|||||||
File = Union[Path, str]
|
File = Union[Path, str]
|
||||||
|
|
||||||
|
|
||||||
def create_subclasses_tex(
|
class CharacterRenderer():
|
||||||
character: Character,
|
def __init__(self, template_name: str):
|
||||||
use_dnd_decorations: bool = False,
|
self.template_name = template_name
|
||||||
) -> str:
|
|
||||||
template = jinja_env.get_template("subclasses_template.tex")
|
def __call__(self, character: Character, content_suffix: str = "tex", use_dnd_decorations: bool = False):
|
||||||
return template.render(character=character, use_dnd_decorations=use_dnd_decorations)
|
template = jinja_env.get_template(self.template_name.format(suffix=content_suffix))
|
||||||
|
return template.render(character=character,
|
||||||
|
use_dnd_decorations=use_dnd_decorations, ordinals=ORDINALS)
|
||||||
|
|
||||||
|
|
||||||
def create_features_tex(
|
create_subclasses_content = CharacterRenderer("subclasses_template.{suffix}")
|
||||||
character: Character,
|
create_features_content = CharacterRenderer("features_template.{suffix}")
|
||||||
use_dnd_decorations: bool = False,
|
create_magic_items_content = CharacterRenderer("magic_items_template.{suffix}")
|
||||||
) -> str:
|
create_spellbook_content = CharacterRenderer("spellbook_template.{suffix}")
|
||||||
template = jinja_env.get_template("features_template.tex")
|
create_infusions_content = CharacterRenderer("infusions_template.{suffix}")
|
||||||
return template.render(character=character, use_dnd_decorations=use_dnd_decorations)
|
create_druid_shapes_content = CharacterRenderer("druid_shapes_template.{suffix}")
|
||||||
|
|
||||||
|
|
||||||
def create_magic_items_tex(
|
|
||||||
character: Character,
|
|
||||||
use_dnd_decorations: bool = False,
|
|
||||||
) -> str:
|
|
||||||
template = jinja_env.get_template("magic_items_template.tex")
|
|
||||||
return template.render(character=character, use_dnd_decorations=use_dnd_decorations)
|
|
||||||
|
|
||||||
|
|
||||||
def create_monsters_content(
|
def create_monsters_content(
|
||||||
@@ -108,30 +102,6 @@ def create_party_summary_content(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_spellbook_tex(
|
|
||||||
character: Character,
|
|
||||||
use_dnd_decorations: bool = False,
|
|
||||||
) -> str:
|
|
||||||
template = jinja_env.get_template("spellbook_template.tex")
|
|
||||||
return template.render(
|
|
||||||
character=character, ordinals=ORDINALS, use_dnd_decorations=use_dnd_decorations
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def create_infusions_tex(
|
|
||||||
character: Character,
|
|
||||||
use_dnd_decorations: bool = False,
|
|
||||||
) -> str:
|
|
||||||
template = jinja_env.get_template("infusions_template.tex")
|
|
||||||
return template.render(character=character, use_dnd_decorations=use_dnd_decorations)
|
|
||||||
|
|
||||||
|
|
||||||
def create_druid_shapes_tex(
|
|
||||||
character: Character,
|
|
||||||
use_dnd_decorations: bool = False,
|
|
||||||
) -> str:
|
|
||||||
template = jinja_env.get_template("druid_shapes_template.tex")
|
|
||||||
return template.render(character=character, use_dnd_decorations=use_dnd_decorations)
|
|
||||||
|
|
||||||
|
|
||||||
def create_random_tables_content(
|
def create_random_tables_content(
|
||||||
@@ -184,6 +154,7 @@ def make_sheet(
|
|||||||
ret = make_character_sheet(
|
ret = make_character_sheet(
|
||||||
char_file=sheet_file,
|
char_file=sheet_file,
|
||||||
flatten=flatten,
|
flatten=flatten,
|
||||||
|
output_format=output_format,
|
||||||
fancy_decorations=fancy_decorations,
|
fancy_decorations=fancy_decorations,
|
||||||
debug=debug,
|
debug=debug,
|
||||||
)
|
)
|
||||||
@@ -328,6 +299,7 @@ def make_character_sheet(
|
|||||||
char_file: Union[str, Path],
|
char_file: Union[str, Path],
|
||||||
character: Optional[Character] = None,
|
character: Optional[Character] = None,
|
||||||
flatten: bool = False,
|
flatten: bool = False,
|
||||||
|
output_format: str = "pdf",
|
||||||
fancy_decorations: bool = False,
|
fancy_decorations: bool = False,
|
||||||
debug: bool = False,
|
debug: bool = False,
|
||||||
):
|
):
|
||||||
@@ -343,6 +315,8 @@ def make_character_sheet(
|
|||||||
flatten
|
flatten
|
||||||
If true, the resulting PDF will look better and won't be
|
If true, the resulting PDF will look better and won't be
|
||||||
fillable form.
|
fillable form.
|
||||||
|
output_format
|
||||||
|
Either "pdf" or "epub" to generate a PDF file or an EPUB file.
|
||||||
fancy_decorations
|
fancy_decorations
|
||||||
Use fancy page layout and decorations for extra sheets, namely
|
Use fancy page layout and decorations for extra sheets, namely
|
||||||
the dnd style file: https://github.com/rpgtex/DND-5e-LaTeX-Template.
|
the dnd style file: https://github.com/rpgtex/DND-5e-LaTeX-Template.
|
||||||
@@ -360,13 +334,14 @@ def make_character_sheet(
|
|||||||
person_base = basename + "_person"
|
person_base = basename + "_person"
|
||||||
sheets = [char_base + ".pdf", person_base + ".pdf"]
|
sheets = [char_base + ".pdf", person_base + ".pdf"]
|
||||||
pages = []
|
pages = []
|
||||||
tex = [
|
# Prepare the tex/html content
|
||||||
jinja_env.get_template("preamble.tex").render(
|
content_suffix = format_suffixes[output_format]
|
||||||
|
content = [
|
||||||
|
jinja_env.get_template(f"preamble.{content_suffix}").render(
|
||||||
use_dnd_decorations=fancy_decorations,
|
use_dnd_decorations=fancy_decorations,
|
||||||
title="Features, Magical Items and Spells",
|
title="Features, Magical Items and Spells",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
# Start of PDF gen
|
# Start of PDF gen
|
||||||
char_pdf = create_character_pdf_template(
|
char_pdf = create_character_pdf_template(
|
||||||
character=character, basename=char_base, flatten=flatten
|
character=character, basename=char_base, flatten=flatten
|
||||||
@@ -387,50 +362,47 @@ def make_character_sheet(
|
|||||||
features_base = "{:s}_features".format(basename)
|
features_base = "{:s}_features".format(basename)
|
||||||
# Create a list of subcasses
|
# Create a list of subcasses
|
||||||
if character.subclasses:
|
if character.subclasses:
|
||||||
tex.append(
|
content.append( create_subclasses_content(character,
|
||||||
create_subclasses_tex(character, use_dnd_decorations=fancy_decorations)
|
content_suffix=content_suffix,
|
||||||
)
|
use_dnd_decorations=fancy_decorations) )
|
||||||
|
# Create a list of features and magic items
|
||||||
# Create a list of features
|
|
||||||
if character.features:
|
if character.features:
|
||||||
tex.append(
|
content.append(
|
||||||
create_features_tex(character, use_dnd_decorations=fancy_decorations)
|
create_features_content(character, content_suffix=content_suffix, use_dnd_decorations=fancy_decorations)
|
||||||
)
|
)
|
||||||
|
|
||||||
if character.magic_items:
|
if character.magic_items:
|
||||||
tex.append(
|
content.append(
|
||||||
create_magic_items_tex(character, use_dnd_decorations=fancy_decorations)
|
create_magic_items_content(character, content_suffix=content_suffix, use_dnd_decorations=fancy_decorations)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a list of spells
|
# Create a list of spells
|
||||||
if character.is_spellcaster:
|
if character.is_spellcaster:
|
||||||
tex.append(
|
content.append(
|
||||||
create_spellbook_tex(character, use_dnd_decorations=fancy_decorations)
|
create_spellbook_content(character, content_suffix=content_suffix, use_dnd_decorations=fancy_decorations)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a list of Artificer infusions
|
# Create a list of Artificer infusions
|
||||||
if getattr(character, "infusions", []):
|
if getattr(character, "infusions", []):
|
||||||
tex.append(
|
content.append(
|
||||||
create_infusions_tex(character, use_dnd_decorations=fancy_decorations)
|
create_infusions_content(character, content_suffix=content_suffix, use_dnd_decorations=fancy_decorations)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a list of Druid wild_shapes
|
# Create a list of Druid wild_shapes
|
||||||
if getattr(character, "wild_shapes", []):
|
if getattr(character, "wild_shapes", []):
|
||||||
tex.append(
|
content.append(
|
||||||
create_druid_shapes_tex(character, use_dnd_decorations=fancy_decorations)
|
create_druid_shapes_content(character, content_suffix=content_suffix, use_dnd_decorations=fancy_decorations)
|
||||||
)
|
)
|
||||||
|
|
||||||
tex.append(
|
content.append(
|
||||||
jinja_env.get_template("postamble.tex").render(
|
jinja_env.get_template(f"postamble.{content_suffix}").render(
|
||||||
use_dnd_decorations=fancy_decorations
|
use_dnd_decorations=fancy_decorations
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Typeset combined LaTeX file
|
# Typeset combined LaTeX file
|
||||||
|
if output_format == "pdf":
|
||||||
try:
|
try:
|
||||||
if len(tex) > 2:
|
if len(content) > 2:
|
||||||
latex.create_latex_pdf(
|
latex.create_latex_pdf(
|
||||||
tex="".join(tex),
|
tex="".join(content),
|
||||||
basename=features_base,
|
basename=features_base,
|
||||||
keep_temp_files=debug,
|
keep_temp_files=debug,
|
||||||
use_dnd_decorations=fancy_decorations,
|
use_dnd_decorations=fancy_decorations,
|
||||||
@@ -442,6 +414,18 @@ def make_character_sheet(
|
|||||||
log.warning(
|
log.warning(
|
||||||
f"``pdflatex`` not available. Skipping features for {character.name}"
|
f"``pdflatex`` not available. Skipping features for {character.name}"
|
||||||
)
|
)
|
||||||
|
elif output_format == "epub":
|
||||||
|
epub.create_epub(
|
||||||
|
chapters={character.name: "".join(content)},
|
||||||
|
basename=basename,
|
||||||
|
title=character.name,
|
||||||
|
use_dnd_decorations=fancy_decorations,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise exceptions.UnknownOutputFormat(
|
||||||
|
f"Unknown output format requested: {output_format}. Valid options are:"
|
||||||
|
" 'pdf', 'epub'"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def merge_pdfs(src_filenames, dest_filename, clean_up=False):
|
def merge_pdfs(src_filenames, dest_filename, clean_up=False):
|
||||||
|
|||||||
@@ -54,18 +54,23 @@ class MakeSheetsTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
class EpubOutputTestCase(unittest.TestCase):
|
class EpubOutputTestCase(unittest.TestCase):
|
||||||
gm_epub = Path(f"{GMFILE.stem}.epub").resolve()
|
gm_epub = Path(f"{GMFILE.stem}.epub").resolve()
|
||||||
|
char_epub = Path(f"{CHARFILE.stem}.epub").resolve()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
for f in [self.gm_epub]:
|
for f in [self.gm_epub, self.char_epub]:
|
||||||
if f.exists():
|
if f.exists():
|
||||||
f.unlink()
|
f.unlink()
|
||||||
|
|
||||||
def test_file_created(self):
|
def test_gm_file_created(self):
|
||||||
# Check that a file is created once the function is run
|
# Check that a file is created once the function is run
|
||||||
# self.assertFalse(os.path.exists(pdf_name), f'{pdf_name} already exists.')
|
|
||||||
make_sheets.make_gm_sheet(gm_file=GMFILE, output_format="epub")
|
make_sheets.make_gm_sheet(gm_file=GMFILE, output_format="epub")
|
||||||
self.assertTrue(self.gm_epub.exists(), f"{self.gm_epub} not created.")
|
self.assertTrue(self.gm_epub.exists(), f"{self.gm_epub} not created.")
|
||||||
|
|
||||||
|
def test_character_file_created(self):
|
||||||
|
# Check that a file is created once the function is run
|
||||||
|
make_sheets.make_character_sheet(char_file=CHARFILE, output_format="epub")
|
||||||
|
self.assertTrue(self.char_epub.exists(), f"{self.char_epub} not created.")
|
||||||
|
|
||||||
|
|
||||||
class PdfOutputTestCase(unittest.TestCase):
|
class PdfOutputTestCase(unittest.TestCase):
|
||||||
basename = "clara"
|
basename = "clara"
|
||||||
@@ -121,37 +126,37 @@ class TexCreatorTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
def test_create_subclasses_tex(self):
|
def test_create_subclasses_tex(self):
|
||||||
char = self.new_character()
|
char = self.new_character()
|
||||||
tex = make_sheets.create_subclasses_tex(character=char)
|
tex = make_sheets.create_subclasses_content(character=char, content_suffix="tex")
|
||||||
self.assertIn(r"\section*{Subclasses}", tex)
|
self.assertIn(r"\section*{Subclasses}", tex)
|
||||||
self.assertIn(r"\subsection*{Way of the Open Hand}", tex)
|
self.assertIn(r"\subsection*{Way of the Open Hand}", tex)
|
||||||
|
|
||||||
def test_create_features_tex(self):
|
def test_create_features_tex(self):
|
||||||
char = self.new_character()
|
char = self.new_character()
|
||||||
tex = make_sheets.create_features_tex(character=char)
|
tex = make_sheets.create_features_content(character=char, content_suffix="tex")
|
||||||
self.assertIn(r"\section*{Features}", tex)
|
self.assertIn(r"\section*{Features}", tex)
|
||||||
self.assertIn(r"\subsection*{Martial Arts}", tex)
|
self.assertIn(r"\subsection*{Martial Arts}", tex)
|
||||||
|
|
||||||
def test_create_magic_items_tex(self):
|
def test_create_magic_items_tex(self):
|
||||||
char = self.new_character()
|
char = self.new_character()
|
||||||
tex = make_sheets.create_magic_items_tex(character=char)
|
tex = make_sheets.create_magic_items_content(character=char, content_suffix="tex")
|
||||||
self.assertIn(r"\section*{Magic Items}", tex)
|
self.assertIn(r"\section*{Magic Items}", tex)
|
||||||
self.assertIn(r"\subsection*{Cloak of Protection}", tex)
|
self.assertIn(r"\subsection*{Cloak of Protection}", tex)
|
||||||
|
|
||||||
def test_create_spellbook_tex(self):
|
def test_create_spellbook_tex(self):
|
||||||
char = self.new_character()
|
char = self.new_character()
|
||||||
tex = make_sheets.create_spellbook_tex(character=char)
|
tex = make_sheets.create_spellbook_content(character=char, content_suffix="tex")
|
||||||
self.assertIn(r"\section*{Spells}", tex)
|
self.assertIn(r"\section*{Spells}", tex)
|
||||||
self.assertIn(r"\section*{Invisibility}", tex)
|
self.assertIn(r"\section*{Invisibility}", tex)
|
||||||
|
|
||||||
def test_create_infusions_tex(self):
|
def test_create_infusions_tex(self):
|
||||||
char = self.new_character()
|
char = self.new_character()
|
||||||
tex = make_sheets.create_infusions_tex(character=char)
|
tex = make_sheets.create_infusions_content(character=char, content_suffix="tex")
|
||||||
self.assertIn(r"\section*{Infusions}", tex)
|
self.assertIn(r"\section*{Infusions}", tex)
|
||||||
self.assertIn(r"\subsection*{Boots of the Winding Path}", tex)
|
self.assertIn(r"\subsection*{Boots of the Winding Path}", tex)
|
||||||
|
|
||||||
def test_create_druid_shapes_tex(self):
|
def test_create_druid_shapes_tex(self):
|
||||||
char = self.new_character()
|
char = self.new_character()
|
||||||
tex = make_sheets.create_druid_shapes_tex(character=char)
|
tex = make_sheets.create_druid_shapes_content(character=char, content_suffix="tex")
|
||||||
self.assertIn(r"\section*{Known Beasts}", tex)
|
self.assertIn(r"\section*{Known Beasts}", tex)
|
||||||
self.assertIn(r"\section*{Crocodile}", tex)
|
self.assertIn(r"\section*{Crocodile}", tex)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user