diff --git a/utils/mapping_generator.py b/utils/mapping_generator.py index df489032e7f5874e94ac50fcec2edccaefca3ac2..bc3983ed1eacd4da4953f907dfd68dc04bceec66 100755 --- a/utils/mapping_generator.py +++ b/utils/mapping_generator.py @@ -17,6 +17,7 @@ import shutil import math +import os import click import yaml @@ -88,6 +89,13 @@ def cli(): To prepare a template, create an SVG using Inkscape, and assign custom IDs to text elements that should be managed by the mapping generator. + + These elements can be populated by applying user-provided parameters against the template. Parameters are provided + in the form of YAML file. The YAML file should have the 'mappables' key at the top level of the document, which then + contains key-to-value mappings for custom text element IDs. + + The easiest way to generate the initial (blank) parameters file is by using the 'info' command alongside the output + format option. """ pass @@ -137,5 +145,42 @@ def info(template, search, output_format): display_mappables_as_yaml(matched_mappables) +@cli.command() +@click.argument('template', type=click.File('r')) +@click.argument('parameters', type=click.File('r')) +@click.argument('output', type=click.Path(dir_okay=False, writable=True, allow_dash=True)) +@click.option('--force-overwrite', '-f', is_flag=True, help='force overwriting output file') +def apply(template, parameters, output, force_overwrite): + """ + Applies user-provided parameters against the template, and outputs the result. + """ + + template_tree = ElementTree.fromstring(template.read()) + namespaces = { + 'svg': 'http://www.w3.org/2000/svg', + } + + # Inkscape default ID starts with string 'text' unless user assigns custom ID. + mappable_elements = [ + e for e in template_tree.findall('.//svg:text', namespaces) if not e.get('id').startswith('text') + ] + + parameters = yaml.safe_load(parameters.read()) + + for element in mappable_elements: + element_id = element.get('id') + replacement = parameters['mappables'].get(element_id, '') + element.find('svg:tspan', namespaces).text = replacement + + if os.path.exists(output) and not force_overwrite: + raise click.FileError(output, 'file already exists') + + if os.path.isdir(output): + raise click.FileError(output, 'output must be a file path') + + with click.open_file(output, 'wb') as output_file: + output_file.write(ElementTree.tostring(template_tree)) + + if __name__ == '__main__': cli()