diff --git a/src/wireviz/DataClasses.py b/src/wireviz/DataClasses.py index fac6ab58..5927d734 100644 --- a/src/wireviz/DataClasses.py +++ b/src/wireviz/DataClasses.py @@ -21,6 +21,7 @@ ImageScale = PlainText # = Literal['false', 'true', 'width', 'height', 'both'] Color = PlainText # Two-letter color name = Literal[wv_colors._color_hex.keys()] ColorScheme = PlainText # Color scheme name = Literal[wv_colors.COLOR_CODES.keys()] +ColorMode = PlainText # = Literal['full', 'FULL', 'hex', 'HEX', 'short', 'SHORT', 'ger', 'GER'] # Type combinations Colors = PlainText # One or more two-letter color names (Color) concatenated into one string @@ -30,6 +31,19 @@ OneOrMoreWires = Union[Wire, Tuple[Wire, ...]] # One or a tuple of wires +@dataclass +class Metadata: + title: Optional[PlainText] = None + description: Optional[MultilineHypertext] = None + notes: Optional[MultilineHypertext] = None + + +@dataclass +class Options: + color_mode: ColorMode = 'SHORT' + mini_bom_mode: bool = True + + @dataclass class Image: gv_dir: InitVar[Path] # Directory of .gv file injected as context during parsing diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index 9d83a3df..a2258688 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -4,12 +4,13 @@ from graphviz import Graph from collections import Counter from typing import List, Union +from dataclasses import dataclass from pathlib import Path from itertools import zip_longest import re from wireviz import wv_colors, __version__, APP_NAME, APP_URL -from wireviz.DataClasses import Connector, Cable +from wireviz.DataClasses import Metadata, Options, Connector, Cable from wireviz.wv_colors import get_color_hex from wireviz.wv_gv_html import nested_html_table, html_colorbar, html_image, \ html_caption, remove_links, html_line_breaks @@ -20,11 +21,12 @@ open_file_read, open_file_write +@dataclass class Harness: + metadata: Metadata + options: Options - def __init__(self): - self.color_mode = 'SHORT' - self.mini_bom_mode = True + def __post_init__(self): self.connectors = {} self.cables = {} self._bom = [] # Internal Cache for generated bom @@ -225,7 +227,7 @@ def create_graph(self) -> Graph: wireinfo = [] if cable.show_wirenumbers: wireinfo.append(str(i)) - colorstr = wv_colors.translate_color(connection_color, self.color_mode) + colorstr = wv_colors.translate_color(connection_color, self.options.color_mode) if colorstr: wireinfo.append(colorstr) if cable.wirelabels: @@ -361,7 +363,7 @@ def output(self, filename: (str, Path), view: bool = False, cleanup: bool = True with open_file_write(f'{filename}.bom.tsv') as file: file.write(tuplelist2tsv(bomlist)) # HTML output - generate_html_output(filename, bomlist) + generate_html_output(filename, bomlist, self.metadata) def bom(self): if not self._bom: diff --git a/src/wireviz/wireviz.py b/src/wireviz/wireviz.py index 9ecef5a0..3c83405b 100755 --- a/src/wireviz/wireviz.py +++ b/src/wireviz/wireviz.py @@ -13,6 +13,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) from wireviz import __version__ +from wireviz.DataClasses import Metadata, Options from wireviz.Harness import Harness from wireviz.wv_helper import expand, open_file_read @@ -34,7 +35,11 @@ def parse(yaml_input: str, file_out: (str, Path) = None, return_types: (None, st yaml_data = yaml.safe_load(yaml_input) - harness = Harness() + # Assign default metadata.title here to avoid needing file_out in Metadata.__init__(). + harness = Harness( + Metadata(**{'title': Path(file_out).stem, **yaml_data.get('metadata', {})}), + Options(**yaml_data.get('options', {})), + ) # add items sections = ['connectors', 'cables', 'connections'] diff --git a/src/wireviz/wv_bom.py b/src/wireviz/wv_bom.py index ac5b071d..4cda4832 100644 --- a/src/wireviz/wv_bom.py +++ b/src/wireviz/wv_bom.py @@ -14,7 +14,7 @@ def get_additional_component_table(harness, component: Union[Connector, Cable]) rows.append(["Additional components"]) for extra in component.additional_components: qty = extra.qty * component.get_qty_multiplier(extra.qty_multiplier) - if harness.mini_bom_mode: + if harness.options.mini_bom_mode: id = get_bom_index(harness, extra.description, extra.unit, extra.manufacturer, extra.mpn, extra.pn) rows.append(component_table_entry(f'#{id} ({extra.type.rstrip()})', qty, extra.unit)) else: diff --git a/src/wireviz/wv_html.py b/src/wireviz/wv_html.py index b328ba3d..d4b394b3 100644 --- a/src/wireviz/wv_html.py +++ b/src/wireviz/wv_html.py @@ -2,21 +2,26 @@ # -*- coding: utf-8 -*- from pathlib import Path +from typing import List, Union import re from wireviz import __version__, APP_NAME, APP_URL +from wireviz.DataClasses import Metadata from wireviz.wv_helper import flatten2d, open_file_read, open_file_write -def generate_html_output(filename: (str, Path), bom_list): +def generate_html_output(filename: Union[str, Path], bom_list: List[List[str]], metadata: Metadata): with open_file_write(f'{filename}.html') as file: file.write('\n') file.write('\n') file.write(' \n') file.write(f' \n') - file.write(f' {APP_NAME} Diagram and BOM\n') + file.write(f' {metadata.title}\n') file.write('\n') - file.write('

Diagram

') + file.write(f'

{metadata.title}

\n') + if metadata.description: + file.write(f'

{metadata.description}

\n') + file.write('

Diagram

\n') with open_file_read(f'{filename}.svg') as svg: file.write(re.sub( '^<[?]xml [^?>]*[?]>[^<]*]*>', @@ -25,7 +30,7 @@ def generate_html_output(filename: (str, Path), bom_list): for svgdata in svg: file.write(svgdata) - file.write('

Bill of Materials

') + file.write('

Bill of Materials

\n') listy = flatten2d(bom_list) file.write('') file.write('') @@ -39,6 +44,9 @@ def generate_html_output(filename: (str, Path), bom_list): align = 'text-align:right; ' if listy[0][i] == 'Qty' else '' file.write(f'') file.write('') - file.write('
{item_str}
') + file.write('\n') + + if metadata.notes: + file.write(f'

Notes

\n

{metadata.notes}

\n') file.write('')