From eae2694b5d512e088395d119ba87c038282c635e Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Thu, 26 Aug 2021 18:50:08 +0200 Subject: [PATCH] Implement template-based HTML output --- src/wireviz/templates/din-6771.html | 284 ++++++++++++++++++++++++++++ src/wireviz/templates/simple.html | 45 +++++ src/wireviz/wv_helper.py | 19 ++ src/wireviz/wv_html.py | 120 +++++++----- 4 files changed, 424 insertions(+), 44 deletions(-) create mode 100644 src/wireviz/templates/din-6771.html create mode 100644 src/wireviz/templates/simple.html diff --git a/src/wireviz/templates/din-6771.html b/src/wireviz/templates/din-6771.html new file mode 100644 index 0000000..aec0f90 --- /dev/null +++ b/src/wireviz/templates/din-6771.html @@ -0,0 +1,284 @@ + + + + + + + <!-- %title% --> + + + + +
+
+ +
+ +
+ +
+ + + +
+ +
+ +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DateName
Sheet
of
RevChangelogDateName
+
+ +
+
+ + diff --git a/src/wireviz/templates/simple.html b/src/wireviz/templates/simple.html new file mode 100644 index 0000000..961ef9d --- /dev/null +++ b/src/wireviz/templates/simple.html @@ -0,0 +1,45 @@ + + + + + <!-- %title% --> + + +

+

Diagram

+ +
+ +
+ +
+ +
+ +
+ +
+ +

Bill of Materials

+ +
+ +
+ + diff --git a/src/wireviz/wv_helper.py b/src/wireviz/wv_helper.py index 6b39fef..d5d6456 100644 --- a/src/wireviz/wv_helper.py +++ b/src/wireviz/wv_helper.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from typing import List +from pathlib import Path import re awg_equiv_table = { @@ -134,3 +135,21 @@ def aspect_ratio(image_src): except Exception as error: print(f'aspect_ratio(): {type(error).__name__}: {error}') return 1 # Assume 1:1 when unable to read actual image size + + +def smart_file_resolve(filename, possible_paths): + filename = Path(filename) + if filename.is_absolute(): + if filename.exists(): + return filename + else: + raise Exception(f'{filename} does not exist.') + else: # search all possible paths in decreasing order of precedence + possible_paths = [Path(path).resolve() for path in possible_paths] + for possible_path in possible_paths: + resolved_path = (possible_path / filename).resolve() + if (resolved_path).exists(): + return resolved_path + else: + raise Exception(f'{filename} was not found in any of the following locations: \n' + + '\n'.join([str(x) for x in possible_paths])) diff --git a/src/wireviz/wv_html.py b/src/wireviz/wv_html.py index 0b81974..09bba26 100644 --- a/src/wireviz/wv_html.py +++ b/src/wireviz/wv_html.py @@ -1,54 +1,86 @@ # -*- coding: utf-8 -*- from pathlib import Path -from typing import List, Union +from typing import Dict, List, Union import re from wireviz import __version__, APP_NAME, APP_URL, wv_colors from wireviz.DataClasses import Metadata, Options -from wireviz.wv_helper import flatten2d, open_file_read, open_file_write +from wireviz.wv_helper import flatten2d, open_file_read, open_file_write, smart_file_resolve +from wireviz.wv_gv_html import html_line_breaks def generate_html_output(filename: Union[str, Path], bom_list: List[List[str]], metadata: Metadata, options: Options): + + # load HTML template + if 'name' in metadata.get('template',{}): + # if relative path to template was provided, check directory of YAML file first, fall back to built-in template directory + templatefile = smart_file_resolve(f'{metadata["template"]["name"]}.html', [Path(filename).parent, Path(__file__).parent / 'templates']) + else: + # fall back to built-in simple template if no template was provided + templatefile = Path(__file__).parent / 'templates/simple.html' + + with open_file_read(templatefile) as file: + html = file.read() + + # embed SVG diagram + with open_file_read(f'{filename}.svg') as file: + svgdata = file.read() + svgdata = re.sub( + '^<[?]xml [^?>]*[?]>[^<]*]*>', + '', + svgdata, 1) + html = html.replace('', svgdata) + + # generate BOM table + bom = flatten2d(bom_list) + + # generate BOM header (may be at the top or bottom of the table) + bom_header_html = ' \n' + for item in bom[0]: + th_class = f'bom_col_{item.lower()}' + bom_header_html = f'{bom_header_html} {item}\n' + bom_header_html = f'{bom_header_html} \n' + + # generate BOM contents + bom_contents = [] + for row in bom[1:]: + row_html = ' \n' + for i, item in enumerate(row): + td_class = f'bom_col_{bom[0][i].lower()}' + row_html = f'{row_html} {item}\n' + row_html = f'{row_html} \n' + bom_contents.append(row_html) + + bom_html = '\n' + bom_header_html + ''.join(bom_contents) + '
\n' + bom_html_reversed = '\n' + ''.join(list(reversed(bom_contents))) + bom_header_html + '
\n' + + # insert BOM table + html = html.replace('', bom_html) + html = html.replace('', bom_html_reversed) + + # insert generator + html = html.replace('', f'{APP_NAME} {__version__} - {APP_URL}') + + # insert other metadata + if metadata: + + html = html.replace(f'"sheetsize_default"', '"{}"'.format(metadata.get('template',{}).get('sheetsize', ''))) # include quotes so no replacement happens within