diff --git a/.gitignore b/.gitignore index 32fc916..e2075ba 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ venv/ dist/ build/ adr_viewer.egg-info/ -.pytest_cache/ \ No newline at end of file +.pytest_cache/ +.DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..775b1c4 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,57 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + +## [1.3.0](https://pypi.org/project/adr-viewer/1.3.0/) - 2022-02-28 + +### Added +- Ignore badly-formed ADR files and report +- Allow template override and pass in a teplate directory +- Customizing server port + +### Fixed +- Some typos + +### Removed +- Support for Python 2.7 + +## [1.2.0](https://pypi.org/project/adr-viewer/1.2.0/) - 2019-06-19 + +### Added +- Support for Pending ADRs + +## [1.1.1](https://pypi.org/project/adr-viewer/1.1.1/) - 2019-02-26 + +### Added +- Python 3 support + + +### Fixed +- Included HTML file in package + +## [1.1.0](https://pypi.org/project/adr-viewer/1.1.0/) - 2018-09-10 + +### Added +- Pypi release details +- Accepted records are green +- Superceded records are now grey and have their titles struck through +- Records with unknown state default to white +- Amended records are yellow +- Since multiple statuses are possible in ADR files, we now extract all `p` objects below the Status header and use those for deciding on which style to apply +- Statuses also now represented by icons (colour-blindness) +- Created and updated this project's ADRs and visualised them +- Improved `README.md` + +## [1.0.1](https://pypi.org/project/adr-viewer/1.0.1/) - 2018-09-02 + +### Added +- Classifiers to `setup.py` + + +## [1.0.0](https://pypi.org/project/adr-viewer/1.0.0/) - 2018-09-02 + +### Initial Release + diff --git a/README.md b/README.md index 27199d1..7e704b4 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,66 @@ $ python setup.py install Usage: adr-viewer [OPTIONS] Options: - --adr-path TEXT Directory containing ADR files. [default: doc/adr/] - --output TEXT File to write output to. [default: index.html] - --serve Serve content at http://localhost:8000/ - --port INT Custom server port [default: 8000] - --help Show this message and exit. + --adr-path TEXT Directory containing ADR files. [default: doc/adr/] + --output TEXT File to write output to. [default: index.html] + --serve Serve content at http://localhost:8000/ + --port INTEGER Change port for the server [default: 8000] + --template-dir TEXT Template directory. + --heading TEXT ADR Page Heading [default: ADR Viewer - ] + --config TEXT Configuration settings [default: config.toml] + --help Show this message and exit. +``` + +The configuration file (in [TOML](http://toml.io) format) has settings that control the look of the ADR page. These settings are specifically targetted at the colours of the page to aid with those who have colour-blindness. + +The colours (the example used here is `green`) can be specified in a number of formats: + + - Hex values: #00FF00 + - HTML Colour codes: Green + - RGB values: rgb(0,255,0) + - RGB with alpha: rgba(0,255,0,0) + - HSL values: hsl(0,100%,50%) + - HSL with alpha: hsla(0,100%,50%,0) + +More information about codes and names for HTML colours can be found [here](http://htmlcolorcodes.com). + +The icons for each bar can also be modified using the `.icon` property of each bar. The icon names can be sourced from the [`fontawesome` library's documentation](https://fontawesome.com/v4/icons/). + +Note that only ***FREE*** icons are allowed. ***Pro*** icons will not be displayed. + +```bash +# Configuration for adr-viewer +# in TOML format http://toml.io + +title = "TOML Configuration for adr-viewer colours" + +[page] +# Properties for the page +background-color = "white" + +[status] +# Properties for the bars that display each ADR + +# Accepted +accepted.icon = "fa-check" +accepted.background-color = "lightgreen" + +# Amended +amended.icon = "fa-arrow-down" +amended.background-color = "yellow" + +# Pending +pending.icon = "fa-hourglass-half" +pending.background-color = "lightblue" + +# Superseded +superseded.icon = "fa-times" +superseded.background-color = "lightgrey" +superseded.text-decoration = "line-through" + +# Unknown +unknown.icon = "fa-question" +unknown.background-color = "white" ``` The default for `--adr-path` is `doc/adr/` because this is the default path generated by `adr-tools`. diff --git a/adr_viewer/__init__.py b/adr_viewer/__init__.py index 8093691..ad67359 100644 --- a/adr_viewer/__init__.py +++ b/adr_viewer/__init__.py @@ -1,11 +1,14 @@ -import glob -from jinja2.loaders import FileSystemLoader -import mistune import os +import glob +import toml +import ast + +from bottle import Bottle, run from bs4 import BeautifulSoup -from jinja2 import Environment, PackageLoader, select_autoescape import click -from bottle import Bottle, run +from jinja2 import Environment, PackageLoader, select_autoescape +from jinja2.loaders import FileSystemLoader +import mistune def extract_statuses_from_adr(page_object): @@ -31,12 +34,13 @@ def parse_adr_to_config(path): soup = BeautifulSoup(adr_as_html, features='html.parser') status = list(extract_statuses_from_adr(soup)) - - if any([line.startswith("Amended by") for line in status]): + if any([line.startswith("Amended") for line in status]): status = 'amended' elif any([line.startswith("Accepted") for line in status]): status = 'accepted' - elif any([line.startswith("Superseded by") for line in status]): + elif any([line.startswith("Superceded") for line in status]): + status = 'superseded' + elif any([line.startswith("Superseded") for line in status]): status = 'superseded' elif any([line.startswith("Pending") for line in status]): status = 'pending' @@ -46,7 +50,7 @@ def parse_adr_to_config(path): header = soup.find('h1') if header: - return { + return { 'status': status, 'body': adr_as_html, 'title': header.text @@ -58,7 +62,7 @@ def parse_adr_to_config(path): def render_html(config, template_dir_override=None): env = Environment( - loader=PackageLoader('adr_viewer', 'templates') if template_dir_override is None else FileSystemLoader(template_dir_override), + loader = PackageLoader('adr_viewer', 'templates') if template_dir_override is None else FileSystemLoader(template_dir_override), autoescape=select_autoescape(['html', 'xml']) ) @@ -80,15 +84,52 @@ def run_server(content, port): run(app, host='localhost', port=port, quiet=True) -def generate_content(path, template_dir_override=None): +def generate_content(path, template_dir_override=None, + heading=None, configuration=None): files = get_adr_files("%s/*.md" % path) + if not heading: + heading = 'ADR Viewer - ' + os.path.basename(os.getcwd()) + config = { - 'project_title': os.path.basename(os.getcwd()), - 'records': [] + 'heading': heading, + 'records': [], + 'page': [] } + # Set defaults for colours (or use passed in configuration) + conf = {} + if type(configuration) == type(None): + conf = ast.literal_eval('{ \ + "accepted": { \ + "icon": "fa-check", \ + "background-color": "lightgreen"}, \ + "amended": {\ + "icon": "fa-arrow-down", \ + "background-color": "yellow"}, \ + "pending": { \ + "icon": "fa-hourglass-half", \ + "background-color": "lightblue"}, \ + "superseded": { \ + "icon" : "fa-times",\ + "background-color": "lightgrey", \ + "text-decoration": "line-through"}, \ + "unknown": { \ + "icon" : "fa-question", \ + "background-color": "white"}}') + config['page'] = ast.literal_eval('{"background-color": "white"}') + else: + conf = configuration['status'] + config['page'] = configuration['page'] + + # Retrieve properties from configuration + for status in conf: + properties = {} + for property in conf[status]: + properties[property] = conf[status][property] + config[status] = properties + for index, adr_file in enumerate(files): adr_attributes = parse_adr_to_config(adr_file) @@ -104,16 +145,37 @@ def generate_content(path, template_dir_override=None): @click.command() -@click.option('--adr-path', default='doc/adr/', help='Directory containing ADR files.', show_default=True) -@click.option('--output', default='index.html', help='File to write output to.', show_default=True) -@click.option('--serve', default=False, help='Serve content at http://localhost:8000/', is_flag=True) -@click.option('--port', default=8000, help='Change port for the server', show_default=True) -@click.option('--template-dir', default=None, help='Template directory.', show_default=True) -def main(adr_path, output, serve, port, template_dir): - content = generate_content(adr_path, template_dir) +@click.option('--adr-path', default='doc/adr/', + help='Directory containing ADR files.', show_default=True) +@click.option('--output', default='index.html', + help='File to write output to.', show_default=True) +@click.option('--serve', default=False, + help='Serve content at http://localhost:8000/', is_flag=True) +@click.option('--port', default=8000, + help='Change port for the server', show_default=True) +@click.option('--template-dir', default=None, + help='Template directory.', show_default=True) +@click.option('--heading', default='ADR Viewer - ', + help='ADR Page Heading', show_default=True) +@click.option('--config', default='config.toml', + help='Configuration settings', show_default=True) +def main(adr_path, output, serve, port, template_dir, heading, config): + from os.path import exists + # Ensure that there is a configuration file + if exists(config): + configuration_file = toml.load(config) + else: + configuration_file = None + + content = generate_content(adr_path, template_dir, + heading, configuration_file) if serve: run_server(content, port) else: with open(output, 'w') as out: out.write(content) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/adr_viewer/config.toml b/adr_viewer/config.toml new file mode 100644 index 0000000..ebdf706 --- /dev/null +++ b/adr_viewer/config.toml @@ -0,0 +1,32 @@ +# Configuration for adr-viewer +# in TOML format http://toml.io + +title = "TOML Configuration for adr-viewer look and feel" + +[page] +# Properties for the page +background-color = "white" + +[status] +# Properties for the bars that display each ADR + +# Accepted +accepted.icon = "fa-check" +accepted.background-color = "lightgreen" + +# Amended +amended.icon = "fa-arrow-down" +amended.background-color = "yellow" + +# Pending +pending.icon = "fa-hourglass-half" +pending.background-color = "lightblue" + +# Superseded +superseded.icon = "fa-times" +superseded.background-color = "lightgrey" +superseded.text-decoration = "line-through" + +# Unknown +unknown.icon = "fa-question" +unknown.background-color = "white" diff --git a/adr_viewer/templates/index.html b/adr_viewer/templates/index.html index 6f5639b..993b2d0 100644 --- a/adr_viewer/templates/index.html +++ b/adr_viewer/templates/index.html @@ -5,8 +5,9 @@ - - ADR Viewer - {{ config.project_title }} + + + {{ config.heading }}