mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-05-18 20:23:27 +02:00
Moved mod_str function from forms.py back to stats.py, and black formatting.
This commit is contained in:
+33
-22
@@ -11,10 +11,7 @@ from dungeonsheets.forms import dice_re, jinja_environment
|
|||||||
|
|
||||||
|
|
||||||
def create_epub(
|
def create_epub(
|
||||||
chapters: Mapping,
|
chapters: Mapping, title: str, basename: str, use_dnd_decorations: bool = False
|
||||||
title: str,
|
|
||||||
basename: str,
|
|
||||||
use_dnd_decorations: bool = False
|
|
||||||
):
|
):
|
||||||
"""Prepare an EPUB file from the list of chapters.
|
"""Prepare an EPUB file from the list of chapters.
|
||||||
|
|
||||||
@@ -34,14 +31,18 @@ def create_epub(
|
|||||||
"""
|
"""
|
||||||
# Create a new epub book
|
# Create a new epub book
|
||||||
book = epub.EpubBook()
|
book = epub.EpubBook()
|
||||||
book.set_identifier('id123456')
|
book.set_identifier("id123456")
|
||||||
book.set_title(title)
|
book.set_title(title)
|
||||||
book.set_language('en')
|
book.set_language("en")
|
||||||
# Add the css files
|
# Add the css files
|
||||||
css_template = jinja_env.get_template("dungeonsheets_epub.css")
|
css_template = jinja_env.get_template("dungeonsheets_epub.css")
|
||||||
style = css_template.render(use_dnd_decorations=use_dnd_decorations)
|
style = css_template.render(use_dnd_decorations=use_dnd_decorations)
|
||||||
css = epub.EpubItem(uid="style_default", file_name="style/gm_sheet.css",
|
css = epub.EpubItem(
|
||||||
media_type="text/css", content=style)
|
uid="style_default",
|
||||||
|
file_name="style/gm_sheet.css",
|
||||||
|
media_type="text/css",
|
||||||
|
content=style,
|
||||||
|
)
|
||||||
book.add_item(css)
|
book.add_item(css)
|
||||||
toc = ["nav"]
|
toc = ["nav"]
|
||||||
# Create the separate chapters
|
# Create the separate chapters
|
||||||
@@ -49,15 +50,22 @@ def create_epub(
|
|||||||
for chap_title, content in chapters.items():
|
for chap_title, content in chapters.items():
|
||||||
chap_fname = chap_title.replace(" - ", "-").replace(" ", "_").lower()
|
chap_fname = chap_title.replace(" - ", "-").replace(" ", "_").lower()
|
||||||
chap_fname = "{}.html".format(chap_fname)
|
chap_fname = "{}.html".format(chap_fname)
|
||||||
chapter = epub.EpubHtml(title=chap_title,
|
chapter = epub.EpubHtml(
|
||||||
file_name=chap_fname, lang="en",
|
title=chap_title,
|
||||||
media_type="application/xhtml+xml")
|
file_name=chap_fname,
|
||||||
|
lang="en",
|
||||||
|
media_type="application/xhtml+xml",
|
||||||
|
)
|
||||||
chapter.set_content(content)
|
chapter.set_content(content)
|
||||||
chapter.add_item(css)
|
chapter.add_item(css)
|
||||||
book.add_item(chapter)
|
book.add_item(chapter)
|
||||||
html_chapters.append(chapter)
|
html_chapters.append(chapter)
|
||||||
# Add entries for the table of contents
|
# Add entries for the table of contents
|
||||||
toc.append(toc_from_headings(html=content, filename=chap_fname, chapter_title=chap_title))
|
toc.append(
|
||||||
|
toc_from_headings(
|
||||||
|
html=content, filename=chap_fname, chapter_title=chap_title
|
||||||
|
)
|
||||||
|
)
|
||||||
# Add the table of contents
|
# Add the table of contents
|
||||||
book.toc = toc
|
book.toc = toc
|
||||||
book.spine = ("nav", *html_chapters)
|
book.spine = ("nav", *html_chapters)
|
||||||
@@ -92,7 +100,7 @@ class HeadingParser(HTMLParser):
|
|||||||
# Found a heading, so process the properties
|
# Found a heading, so process the properties
|
||||||
self._curr_level = this_level
|
self._curr_level = this_level
|
||||||
attrs = {k: v for k, v in attrs}
|
attrs = {k: v for k, v in attrs}
|
||||||
self._curr_id = attrs.get('id')
|
self._curr_id = attrs.get("id")
|
||||||
|
|
||||||
def handle_endtag(self, tag):
|
def handle_endtag(self, tag):
|
||||||
this_level = self.heading_level(tag)
|
this_level = self.heading_level(tag)
|
||||||
@@ -100,7 +108,7 @@ class HeadingParser(HTMLParser):
|
|||||||
heading = {
|
heading = {
|
||||||
"level": this_level,
|
"level": this_level,
|
||||||
"id": self._curr_id,
|
"id": self._curr_id,
|
||||||
"title": self._curr_title
|
"title": self._curr_title,
|
||||||
}
|
}
|
||||||
self.headings.append(heading)
|
self.headings.append(heading)
|
||||||
|
|
||||||
@@ -110,7 +118,9 @@ class HeadingParser(HTMLParser):
|
|||||||
self._curr_title = data
|
self._curr_title = data
|
||||||
|
|
||||||
|
|
||||||
def toc_from_headings(html: str, filename: str = "", chapter_title: str = "Sheet") -> list:
|
def toc_from_headings(
|
||||||
|
html: str, filename: str = "", chapter_title: str = "Sheet"
|
||||||
|
) -> list:
|
||||||
"""Accept a chapter of HTML, and extract a table of contents segment.
|
"""Accept a chapter of HTML, and extract a table of contents segment.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
@@ -149,18 +159,19 @@ def toc_from_headings(html: str, filename: str = "", chapter_title: str = "Sheet
|
|||||||
href = f"{filename}#{heading['id']}"
|
href = f"{filename}#{heading['id']}"
|
||||||
parent_section = sections_stack[-1]
|
parent_section = sections_stack[-1]
|
||||||
is_last = idx == (len(headings) - 1)
|
is_last = idx == (len(headings) - 1)
|
||||||
is_leaf = is_last or heading['level'] >= headings[idx+1]['level']
|
is_leaf = is_last or heading["level"] >= headings[idx + 1]["level"]
|
||||||
# Add a leaf or branch depending on the heading structure
|
# Add a leaf or branch depending on the heading structure
|
||||||
if is_leaf:
|
if is_leaf:
|
||||||
parent_section[1].append(epub.Link(href=href, title=heading['title'], uid=href))
|
parent_section[1].append(
|
||||||
|
epub.Link(href=href, title=heading["title"], uid=href)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
new_section = (epub.Section(href=href, title=heading['title']),
|
new_section = (epub.Section(href=href, title=heading["title"]), [])
|
||||||
[])
|
|
||||||
parent_section[1].append(new_section)
|
parent_section[1].append(new_section)
|
||||||
sections_stack.append(new_section)
|
sections_stack.append(new_section)
|
||||||
# Walk back up the stack
|
# Walk back up the stack
|
||||||
if not is_last:
|
if not is_last:
|
||||||
for idx in range(max(0, heading['level'] - headings[idx + 1]['level'])):
|
for idx in range(max(0, heading["level"] - headings[idx + 1]["level"])):
|
||||||
sections_stack.pop()
|
sections_stack.pop()
|
||||||
|
|
||||||
return toc
|
return toc
|
||||||
@@ -258,5 +269,5 @@ def to_heading_id(inpt: str) -> str:
|
|||||||
|
|
||||||
# Prepare the jinja environment
|
# Prepare the jinja environment
|
||||||
jinja_env = jinja_environment()
|
jinja_env = jinja_environment()
|
||||||
jinja_env.filters['rst_to_html'] = rst_to_html
|
jinja_env.filters["rst_to_html"] = rst_to_html
|
||||||
jinja_env.filters['to_heading_id'] = to_heading_id
|
jinja_env.filters["to_heading_id"] = to_heading_id
|
||||||
|
|||||||
@@ -25,5 +25,6 @@ class JSONFormatError(RuntimeError):
|
|||||||
class UnknownFileType(RuntimeError):
|
class UnknownFileType(RuntimeError):
|
||||||
"""The input file does not match one of the known formats."""
|
"""The input file does not match one of the known formats."""
|
||||||
|
|
||||||
|
|
||||||
class UnknownOutputFormat(RuntimeError):
|
class UnknownOutputFormat(RuntimeError):
|
||||||
"""The output format requested is not one of the known outputs."""
|
"""The output format requested is not one of the known outputs."""
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ def create_character_pdf_template(character, basename, flatten=False):
|
|||||||
# Additional attacks beyond 3
|
# Additional attacks beyond 3
|
||||||
attack = [
|
attack = [
|
||||||
f"{w.name}: Atk {w.attack_modifier:+d}, Dam {w.damage}/{w.damage_type}"
|
f"{w.name}: Atk {w.attack_modifier:+d}, Dam {w.damage}/{w.damage_type}"
|
||||||
for w in character.weapons[len(weapon_fields):]
|
for w in character.weapons[len(weapon_fields) :]
|
||||||
]
|
]
|
||||||
# Other attack information
|
# Other attack information
|
||||||
if character.armor:
|
if character.armor:
|
||||||
|
|||||||
@@ -3,15 +3,13 @@ import re
|
|||||||
from jinja2 import Environment, PackageLoader
|
from jinja2 import Environment, PackageLoader
|
||||||
|
|
||||||
|
|
||||||
|
from dungeonsheets.stats import mod_str
|
||||||
|
|
||||||
|
|
||||||
# A dice string, with optional backticks: ``1d6 + 3``
|
# A dice string, with optional backticks: ``1d6 + 3``
|
||||||
dice_re = re.compile(r"`*(\d+d\d+(?:\s*\+\s*\d+)?)`*")
|
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():
|
def jinja_environment():
|
||||||
"""Prepare a new environment for Jinja templates.
|
"""Prepare a new environment for Jinja templates.
|
||||||
|
|
||||||
@@ -34,5 +32,3 @@ def jinja_environment():
|
|||||||
)
|
)
|
||||||
jinja_env.filters["mod_str"] = mod_str
|
jinja_env.filters["mod_str"] = mod_str
|
||||||
return jinja_env
|
return jinja_env
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,12 @@ def _remove_temp_files(basename_):
|
|||||||
filename.unlink()
|
filename.unlink()
|
||||||
|
|
||||||
|
|
||||||
def create_latex_pdf(tex: str, basename: str, keep_temp_files: bool=False, use_dnd_decorations: bool=False):
|
def create_latex_pdf(
|
||||||
|
tex: str,
|
||||||
|
basename: str,
|
||||||
|
keep_temp_files: bool = False,
|
||||||
|
use_dnd_decorations: bool = False,
|
||||||
|
):
|
||||||
# Create tex document
|
# Create tex document
|
||||||
tex_file = f"{basename}.tex"
|
tex_file = f"{basename}.tex"
|
||||||
with open(tex_file, mode="w", encoding="utf-8") as f:
|
with open(tex_file, mode="w", encoding="utf-8") as f:
|
||||||
|
|||||||
@@ -11,7 +11,15 @@ from multiprocessing import Pool, cpu_count
|
|||||||
from itertools import product
|
from itertools import product
|
||||||
from typing import Union, Sequence, Optional
|
from typing import Union, Sequence, Optional
|
||||||
|
|
||||||
from dungeonsheets import character as _char, exceptions, readers, latex, epub, monsters, forms
|
from dungeonsheets import (
|
||||||
|
character as _char,
|
||||||
|
exceptions,
|
||||||
|
readers,
|
||||||
|
latex,
|
||||||
|
epub,
|
||||||
|
monsters,
|
||||||
|
forms,
|
||||||
|
)
|
||||||
from dungeonsheets.forms import mod_str
|
from dungeonsheets.forms import mod_str
|
||||||
from dungeonsheets.content_registry import find_content
|
from dungeonsheets.content_registry import find_content
|
||||||
from dungeonsheets.fill_pdf_template import (
|
from dungeonsheets.fill_pdf_template import (
|
||||||
@@ -132,8 +140,9 @@ def create_random_tables_content(
|
|||||||
use_dnd_decorations: bool = False,
|
use_dnd_decorations: bool = False,
|
||||||
) -> str:
|
) -> str:
|
||||||
template = jinja_env.get_template(f"random_tables_template.{suffix}")
|
template = jinja_env.get_template(f"random_tables_template.{suffix}")
|
||||||
return template.render(conjure_animals=conjure_animals,
|
return template.render(
|
||||||
use_dnd_decorations=use_dnd_decorations)
|
conjure_animals=conjure_animals, use_dnd_decorations=use_dnd_decorations
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def make_sheet(
|
def make_sheet(
|
||||||
@@ -236,7 +245,10 @@ def make_gm_sheet(
|
|||||||
summary = gm_props.pop("summary", "")
|
summary = gm_props.pop("summary", "")
|
||||||
content.append(
|
content.append(
|
||||||
create_party_summary_content(
|
create_party_summary_content(
|
||||||
party, summary_rst=summary, suffix=content_suffix, use_dnd_decorations=fancy_decorations
|
party,
|
||||||
|
summary_rst=summary,
|
||||||
|
suffix=content_suffix,
|
||||||
|
use_dnd_decorations=fancy_decorations,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
# Add the monsters
|
# Add the monsters
|
||||||
@@ -257,10 +269,14 @@ def make_gm_sheet(
|
|||||||
monsters_.append(new_monster)
|
monsters_.append(new_monster)
|
||||||
if len(monsters_) > 0:
|
if len(monsters_) > 0:
|
||||||
content.append(
|
content.append(
|
||||||
create_monsters_content(monsters_, suffix=content_suffix, use_dnd_decorations=fancy_decorations)
|
create_monsters_content(
|
||||||
|
monsters_, suffix=content_suffix, use_dnd_decorations=fancy_decorations
|
||||||
|
)
|
||||||
)
|
)
|
||||||
# Add the random tables
|
# Add the random tables
|
||||||
random_tables = [s.replace(" ", "_").lower() for s in gm_props.pop("random_tables", [])]
|
random_tables = [
|
||||||
|
s.replace(" ", "_").lower() for s in gm_props.pop("random_tables", [])
|
||||||
|
]
|
||||||
content.append(
|
content.append(
|
||||||
create_random_tables_content(
|
create_random_tables_content(
|
||||||
conjure_animals=("conjure_animals" in random_tables),
|
conjure_animals=("conjure_animals" in random_tables),
|
||||||
@@ -303,7 +319,8 @@ def make_gm_sheet(
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise exceptions.UnknownOutputFormat(
|
raise exceptions.UnknownOutputFormat(
|
||||||
f"Unknown output format requested: {output_format}. Valid options are: 'pdf', 'epub'"
|
f"Unknown output format requested: {output_format}. Valid options are:"
|
||||||
|
" 'pdf', 'epub'"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -512,7 +529,8 @@ def main(args=None):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--output-format", "-o",
|
"--output-format",
|
||||||
|
"-o",
|
||||||
help="Specify the output format for the sheets.",
|
help="Specify the output format for the sheets.",
|
||||||
choices=["pdf", "epub"],
|
choices=["pdf", "epub"],
|
||||||
default="pdf",
|
default="pdf",
|
||||||
|
|||||||
@@ -4,7 +4,13 @@ game mechanics."""
|
|||||||
from dungeonsheets.spells import Spell
|
from dungeonsheets.spells import Spell
|
||||||
from dungeonsheets.features import Feature
|
from dungeonsheets.features import Feature
|
||||||
from dungeonsheets.infusions import Infusion
|
from dungeonsheets.infusions import Infusion
|
||||||
from dungeonsheets.weapons import Weapon, MeleeWeapon, RangedWeapon, SimpleWeapon, MartialWeapon
|
from dungeonsheets.weapons import (
|
||||||
|
Weapon,
|
||||||
|
MeleeWeapon,
|
||||||
|
RangedWeapon,
|
||||||
|
SimpleWeapon,
|
||||||
|
MartialWeapon,
|
||||||
|
)
|
||||||
from dungeonsheets.armor import Armor, Shield
|
from dungeonsheets.armor import Armor, Shield
|
||||||
from dungeonsheets.magic_items import MagicItem
|
from dungeonsheets.magic_items import MagicItem
|
||||||
from dungeonsheets.monsters import Monster
|
from dungeonsheets.monsters import Monster
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from dungeonsheets.stats import Ability
|
|||||||
|
|
||||||
|
|
||||||
class Baboon(Monster):
|
class Baboon(Monster):
|
||||||
""" Pack Tactics.
|
"""Pack Tactics.
|
||||||
The baboon has advantage on an attack roll against a creature if
|
The baboon has advantage on an attack roll against a creature if
|
||||||
at least one of the baboon's allies is within 5 ft. of the
|
at least one of the baboon's allies is within 5 ft. of the
|
||||||
creature and the ally isn't incapacitated.
|
creature and the ally isn't incapacitated.
|
||||||
|
|||||||
@@ -528,9 +528,7 @@ class FoundryCharacterReader(JSONCharacterReader):
|
|||||||
tool_profs.extend([s.strip() for s in custom_tool_profs.split(";")])
|
tool_profs.extend([s.strip() for s in custom_tool_profs.split(";")])
|
||||||
char_props["_proficiencies_text"] = tool_profs
|
char_props["_proficiencies_text"] = tool_profs
|
||||||
# Combat stats
|
# Combat stats
|
||||||
char_props["hp_max"] = self.as_int(
|
char_props["hp_max"] = self.as_int(json_data["data"]["attributes"]["hp"]["max"])
|
||||||
json_data["data"]["attributes"]["hp"]["max"]
|
|
||||||
)
|
|
||||||
# Equipment
|
# Equipment
|
||||||
currency = json_data["data"]["currency"]
|
currency = json_data["data"]["currency"]
|
||||||
char_props["cp"] = currency["cp"]
|
char_props["cp"] = currency["cp"]
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ from dungeonsheets.features import (
|
|||||||
log = logging.getLogger(__name__)
|
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"))
|
AbilityScore = namedtuple("AbilityScore", ("value", "modifier", "saving_throw"))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user