Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Add typing to (and smarten up) render logic #58

Merged
merged 7 commits into from
Oct 8, 2023
41 changes: 5 additions & 36 deletions adr_viewer/__init__.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,12 @@
import glob
import os
from typing import List

from click import option, command

from adr_viewer.parse import parse_adr
from adr_viewer.render import render_html
from adr_viewer.parse import parse_adr, parse_adr_files, Adr
from adr_viewer.render import render_html, AdrTemplateConfig, generate_content
from adr_viewer.server import run_server


def get_adr_files(path) -> List[str]:
files = glob.glob(path)
files.sort()
return files


def generate_content(path, template_dir_override=None, title=None) -> str:
files = get_adr_files("%s/*.md" % path)

config = {
"project_title": title if title else os.path.basename(os.getcwd()),
"records": [],
"include_mermaid": False,
}

for index, adr_file in enumerate(files):
markdown = open(adr_file).read()
adr_attributes = parse_adr(markdown)

if adr_attributes:
adr_attributes.index = index
if not config["include_mermaid"]:
config["include_mermaid"] = adr_attributes.includes_mermaid

config["records"].append(adr_attributes)
else:
print("Could not parse %s in ADR format, ignoring." % adr_file)

return render_html(config, template_dir_override)


# fmt: off
@command()
@option('--adr-path', default='doc/adr/', help='Directory containing ADR files.', show_default=True)
Expand All @@ -50,7 +17,9 @@ def generate_content(path, template_dir_override=None, title=None) -> str:
@option('--template-dir', default=None, help='Template directory.', show_default=True)
# fmt: on
def main(adr_path, output, title, serve, port, template_dir) -> None:
content = generate_content(adr_path, template_dir, title)
adrs: List[Adr] = parse_adr_files("%s/*.md" % adr_path)

content = generate_content(adrs, template_dir, title)

if serve:
run_server(content, port)
Expand Down
23 changes: 22 additions & 1 deletion adr_viewer/parse.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Iterator, Optional, Dict
import glob
from typing import Iterator, Optional, List
from bs4 import BeautifulSoup
from dataclasses import dataclass

Expand Down Expand Up @@ -31,6 +32,26 @@ def extract_statuses_from_adr(page_object) -> Iterator[str]:
continue


def parse_adr_files(path: str) -> List[Adr]:
files: List[str] = glob.glob(path)
files.sort()

adrs: List[Adr] = []

for file in files:
content = open(file).read()

adr = parse_adr(content)

if not adr:
print("Could not parse %s in ADR format, ignoring." % file)
continue

adrs.append(adr)

return adrs


def parse_adr(content: str) -> Optional[Adr]:
adr_as_html = mistune.markdown(content)

Expand Down
29 changes: 28 additions & 1 deletion adr_viewer/render.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
import os
from dataclasses import dataclass
from typing import List

from jinja2 import Environment, PackageLoader, select_autoescape
from jinja2.loaders import FileSystemLoader, BaseLoader

from adr_viewer.parse import Adr


@dataclass
class AdrTemplateConfig:
project_title: str
records: List[Adr]
include_mermaid: bool = False

def render_html(config, template_dir_override=None) -> str:

def render_html(config: AdrTemplateConfig, template_dir_override=None) -> str:
loader: BaseLoader

if template_dir_override:
Expand All @@ -18,3 +31,17 @@ def render_html(config, template_dir_override=None) -> str:
template = env.get_template("index.html")

return template.render(config=config)


def generate_content(adrs: List[Adr], template_dir_override=None, title=None) -> str:
config = AdrTemplateConfig(
project_title=title if title else os.path.basename(os.getcwd()), records=[]
)

for index, adr in enumerate(adrs):
adr.index = index
adr.includes_mermaid |= config.include_mermaid

config.records.append(adr)

return render_html(config, template_dir_override)
18 changes: 11 additions & 7 deletions adr_viewer/test_render.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
from adr_viewer import render_html
from adr_viewer import render_html, AdrTemplateConfig
from adr_viewer.parse import Adr


def test_should_render_html_with_project_title():
html = render_html({"project_title": "my-project"})
html = render_html(AdrTemplateConfig(project_title="my-project", records=[]))

assert "<title>ADR Viewer - my-project</title>" in html


def test_should_render_html_with_record_status():
adr = Adr("title", "accepted", "content")
html = render_html({"records": [adr]})
html = render_html(AdrTemplateConfig(project_title="my-project", records=[adr]))

assert '<div class="panel-heading adr-accepted">' in html


def test_should_render_html_with_record_body():
adr = Adr("title", "status", "<h1>This is my ADR</h1>")

html = render_html({"records": [adr]})
html = render_html(AdrTemplateConfig(project_title="my-project", records=[adr]))

assert '<div class="panel-body"><h1>This is my ADR</h1></div>' in html

Expand All @@ -27,18 +27,22 @@ def test_should_render_html_with_collapsible_index():
adr = Adr("Record 123", "status", "content")
adr.index = 123

html = render_html({"records": [adr]})
html = render_html(AdrTemplateConfig(project_title="my-project", records=[adr]))

assert '<a data-toggle="collapse" href="#collapse123">Record 123</a>' in html


def test_should_render_html_with_mermaid():
html = render_html({"include_mermaid": True})
html = render_html(
AdrTemplateConfig(project_title="my-project", records=[], include_mermaid=True)
)

assert "mermaid.min.js" in html


def test_should_render_html_without_mermaid():
html = render_html({"include_mermaid": False})
html = render_html(
AdrTemplateConfig(project_title="my-project", records=[], include_mermaid=False)
)

assert "mermaid.min.js" not in html