mirror of
https://github.com/Threnklyn/dungeon-sheets.git
synced 2026-05-18 20:23:27 +02:00
Added ability to parse JSON files exported from Foundry.
This commit is contained in:
+57
-104
@@ -21,105 +21,25 @@ from dungeonsheets.fill_pdf_template import (
|
||||
)
|
||||
from dungeonsheets.character import Character
|
||||
|
||||
"""Program to take character definitions and build a PDF of the
|
||||
character sheet."""
|
||||
|
||||
PDFTK_CMD = "pdftk"
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
ORDINALS = {
|
||||
1: "1st",
|
||||
2: "2nd",
|
||||
3: "3rd",
|
||||
4: "4th",
|
||||
5: "5th",
|
||||
6: "6th",
|
||||
7: "7th",
|
||||
2: "2nd",
|
||||
3: "3rd",
|
||||
4: "4th",
|
||||
5: "5th",
|
||||
6: "6th",
|
||||
7: "7th",
|
||||
8: "8th",
|
||||
9: "9th"
|
||||
9: "9th",
|
||||
}
|
||||
|
||||
"""Program to take character definitions and build a PDF of the
|
||||
character sheet."""
|
||||
|
||||
bold_re = re.compile(r"\*\*([^*]+)\*\*")
|
||||
it_re = re.compile(r"\*([^*]+)\*")
|
||||
verb_re = re.compile(r"``([^`]+)``")
|
||||
heading_re = re.compile(r"^[ \t\r\f\v]*(.+)\n\s*([-=\^]+)$", flags=re.MULTILINE)
|
||||
# What defines a list in reST:
|
||||
# - a blank line
|
||||
# - one or more of the following
|
||||
# - "- [a-z]"
|
||||
# - an additional line of text (if multi-line bullets)
|
||||
# - a blank line
|
||||
# - a blank line
|
||||
# - a non-list line or end of file
|
||||
# list_re = re.compile('^[ \t\r\f\v]*\n((?:\s*[-*+]\s+[^\n]*\n)+)', flags=re.MULTILINE)
|
||||
list_re = re.compile(
|
||||
r"^[ \t\r\f\v]*\n" # A blank line
|
||||
r"((?:\s*[-*+]\s+[^\n]*\n)+)" # The first line of each list item
|
||||
"",
|
||||
flags=re.MULTILINE,
|
||||
)
|
||||
# What defines a list item in reST:
|
||||
# - a line starting with "- " then some text
|
||||
# - zero or more lines starting with anything other than "- "
|
||||
list_item_re = re.compile(r"^\s*[-*+]\s+", flags=re.MULTILINE)
|
||||
|
||||
|
||||
def _parse_rst_lists(rst):
|
||||
"""Read lists in reST and iterate.
|
||||
|
||||
Yields
|
||||
======
|
||||
list_rst : str
|
||||
The matching reST list found in the input text
|
||||
list_items : list
|
||||
A python list of the items found in the reST list.
|
||||
|
||||
"""
|
||||
for match in list_re.finditer(rst):
|
||||
list_rst = match.group(0)
|
||||
# Separate the list items
|
||||
list_items = list_item_re.split(match.group(1))
|
||||
# Clean up separated list items
|
||||
list_items = list_items[1:] # First item is an empty string
|
||||
list_items = [item.replace("\n", " ").strip() for item in list_items]
|
||||
yield list_rst, list_items
|
||||
|
||||
|
||||
def _parse_rst_headings(rst):
|
||||
"""Read headings in reST and iterate.
|
||||
|
||||
Yields
|
||||
======
|
||||
heading_rst : str
|
||||
The matching reST heading found in the input text.
|
||||
heading : str
|
||||
The text of the heading with underlining removed.
|
||||
level : int
|
||||
How deep the heading is: 0 is top-level, 1 is next level down,
|
||||
etc.
|
||||
|
||||
"""
|
||||
heading_levels = {
|
||||
"=": 0,
|
||||
"-": 1,
|
||||
"^": 2,
|
||||
}
|
||||
for match in heading_re.finditer(rst):
|
||||
heading_rst = match.group(0)
|
||||
heading, underline = match.groups()
|
||||
# Check for valid heading
|
||||
if len(underline) < len(heading):
|
||||
log.debug("Skipping malformed reST heading: '%s\n%s'", heading, underline)
|
||||
continue
|
||||
if len(set(underline)) > 1:
|
||||
log.debug("Skipping malformed reST heading: '%s\n%s'", heading, underline)
|
||||
continue
|
||||
# Valid heading, so determine how many levels deep it is
|
||||
level = heading_levels[underline[0]]
|
||||
yield heading_rst, heading, level
|
||||
|
||||
|
||||
jinja_env = Environment(
|
||||
loader=PackageLoader("dungeonsheets", "forms"),
|
||||
block_start_string="[%",
|
||||
@@ -141,6 +61,7 @@ def create_subclasses_tex(
|
||||
template = jinja_env.get_template("subclasses_template.tex")
|
||||
return template.render(character=character, use_dnd_decorations=use_dnd_decorations)
|
||||
|
||||
|
||||
def create_features_tex(
|
||||
character: Character,
|
||||
use_dnd_decorations: bool = False,
|
||||
@@ -148,6 +69,7 @@ def create_features_tex(
|
||||
template = jinja_env.get_template("features_template.tex")
|
||||
return template.render(character=character, use_dnd_decorations=use_dnd_decorations)
|
||||
|
||||
|
||||
def create_magic_items_tex(
|
||||
character: Character,
|
||||
use_dnd_decorations: bool = False,
|
||||
@@ -155,12 +77,16 @@ def create_magic_items_tex(
|
||||
template = jinja_env.get_template("magic_items_template.tex")
|
||||
return template.render(character=character, use_dnd_decorations=use_dnd_decorations)
|
||||
|
||||
|
||||
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)
|
||||
return template.render(
|
||||
character=character, ordinals=ORDINALS, use_dnd_decorations=use_dnd_decorations
|
||||
)
|
||||
|
||||
|
||||
def create_infusions_tex(
|
||||
character: Character,
|
||||
@@ -169,6 +95,7 @@ def create_infusions_tex(
|
||||
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,
|
||||
@@ -211,7 +138,11 @@ def make_sheet(
|
||||
char_base = os.path.splitext(character_file)[0] + "_char"
|
||||
sheets = [char_base + ".pdf"]
|
||||
pages = []
|
||||
tex = [jinja_env.get_template("preamble.tex").render(use_dnd_decorations=fancy_decorations)]
|
||||
tex = [
|
||||
jinja_env.get_template("preamble.tex").render(
|
||||
use_dnd_decorations=fancy_decorations
|
||||
)
|
||||
]
|
||||
|
||||
# Start of PDF gen
|
||||
char_pdf = create_character_pdf_template(
|
||||
@@ -230,33 +161,54 @@ def make_sheet(
|
||||
features_base = "{:s}_features".format(os.path.splitext(character_file)[0])
|
||||
# Create a list of subcasses
|
||||
if character.subclasses:
|
||||
tex.append(create_subclasses_tex(character, use_dnd_decorations=fancy_decorations))
|
||||
tex.append(
|
||||
create_subclasses_tex(character, use_dnd_decorations=fancy_decorations)
|
||||
)
|
||||
|
||||
# Create a list of features
|
||||
if character.features:
|
||||
tex.append(create_features_tex(character, use_dnd_decorations=fancy_decorations))
|
||||
tex.append(
|
||||
create_features_tex(character, use_dnd_decorations=fancy_decorations)
|
||||
)
|
||||
|
||||
if character.magic_items:
|
||||
tex.append(create_magic_items_tex(character, use_dnd_decorations=fancy_decorations))
|
||||
tex.append(
|
||||
create_magic_items_tex(character, use_dnd_decorations=fancy_decorations)
|
||||
)
|
||||
|
||||
# Create a list of spells
|
||||
if character.is_spellcaster:
|
||||
tex.append(create_spellbook_tex(character, use_dnd_decorations=fancy_decorations))
|
||||
tex.append(
|
||||
create_spellbook_tex(character, use_dnd_decorations=fancy_decorations)
|
||||
)
|
||||
|
||||
# Create a list of Artificer infusions
|
||||
if getattr(character, "infusions", []):
|
||||
tex.append(create_infusions_tex(character, use_dnd_decorations=fancy_decorations))
|
||||
|
||||
tex.append(
|
||||
create_infusions_tex(character, use_dnd_decorations=fancy_decorations)
|
||||
)
|
||||
|
||||
# Create a list of Druid wild_shapes
|
||||
if getattr(character, "wild_shapes", []):
|
||||
tex.append(create_druid_shapes_tex(character, use_dnd_decorations=fancy_decorations))
|
||||
|
||||
tex.append(jinja_env.get_template("postamble.tex").render(use_dnd_decorations=fancy_decorations))
|
||||
|
||||
tex.append(
|
||||
create_druid_shapes_tex(character, use_dnd_decorations=fancy_decorations)
|
||||
)
|
||||
|
||||
tex.append(
|
||||
jinja_env.get_template("postamble.tex").render(
|
||||
use_dnd_decorations=fancy_decorations
|
||||
)
|
||||
)
|
||||
|
||||
# Typeset combined LaTeX file
|
||||
try:
|
||||
if len(tex) > 2:
|
||||
latex.create_latex_pdf("".join(tex), features_base, keep_temp_files=debug, use_dnd_decorations=fancy_decorations)
|
||||
latex.create_latex_pdf(
|
||||
"".join(tex),
|
||||
features_base,
|
||||
keep_temp_files=debug,
|
||||
use_dnd_decorations=fancy_decorations,
|
||||
)
|
||||
sheets.append(features_base + ".pdf")
|
||||
final_pdf = os.path.splitext(character_file)[0] + ".pdf"
|
||||
merge_pdfs(sheets, final_pdf, clean_up=True)
|
||||
@@ -293,7 +245,8 @@ def merge_pdfs(src_filenames, dest_filename, clean_up=False):
|
||||
os.remove(sheet)
|
||||
|
||||
|
||||
load_character_file = readers.read_character_file
|
||||
# # Deprecated:
|
||||
# load_character_file = readers.read_character_file
|
||||
|
||||
|
||||
def _build(filename, args) -> int:
|
||||
|
||||
Reference in New Issue
Block a user