Source code for oasislmf.utils.documentation.markdown
__all__ = [
'MarkdownGenerator'
]
from collections import defaultdict
import re
[docs]
class MarkdownGenerator:
def __init__(self):
"""A simple markdown generator for adding markdown strings
"""
[docs]
def get_markdown(self, generate_toc=False):
"""Returns markdown string from joined self.sections
Args:
generate_toc (bool): Generate table of contents bool.
Returns:
str: Markdown string
"""
if generate_toc:
self.generate_toc()
return "".join(self.sections)
def _slugify(self, title):
"""Make title strings slugified (transform to URL friendly string)
Args:
title (str): Original Title str
Returns:
slug_title (str): Slugified Title str
"""
slug = re.sub(r'[^\w\s-]', '', title).strip().lower()
slug = re.sub(r'\s+', '-', slug)
return slug
[docs]
def generate_toc(self, ):
"""Generate a table of contents from markdown string
Returns:
toc (str): Table of contents markdown string
"""
markdown_text = "".join(self.sections)
lines = markdown_text.split('\n')
toc = []
slug_counts = defaultdict(int)
for line in lines:
match = re.match(r'^(#{1,6})\s+(.*)', line)
if match:
level = len(match.group(1)) - 1
title = match.group(2).strip()
base_slug = self._slugify(title)
slug_counts[base_slug] += 1
anchor = base_slug if slug_counts[base_slug] == 1 else f"{base_slug}-{slug_counts[base_slug] - 1}"
toc.append(f"{' ' * level}- [{title}](#{anchor})")
self.sections = ["## Table of Contents\n\n" + "\n".join(toc) + "\n\n"] + self.sections
[docs]
def add_definition(self, title, content):
"""Adds definition line to markdown in the following format
**title**: content
Args:
title (Any): Name
content (Any): Description
"""
self.sections.append(f"**{title}**: {content}\n\n")
[docs]
def add_table(self, headers, rows):
"""Adds a table to markdown with headers and rows
Args:
headers (List[str]): Headers
rows (List[str]): Rows
"""
if len(rows) > 0:
assert len(rows[0]) == len(headers), \
f"Length of rows ({len(rows[0])}) \
does not equal length of headers \
({len(headers)}) for headers:\n {headers}\n"
table = "| " + " | ".join(headers) + " |\n"
table += "|" + "|".join(["---"] * len(headers)) + "|\n"
for row in rows:
table += "| " + " | ".join(row) + " |\n"
self.sections.append(table)
self.sections.append("\n")
[docs]
def add_list(self, items):
"""Adds list to markdown
Args:
items (List[str]): List of items
"""
for item in items:
self.sections.append(f"- {item}\n")
self.sections.append("\n")
[docs]
def add_collapsible_section(self, text, title="Root"):
"""Adds collapsible section to markdown
Args:
text (str): contents of collapsible section
title (str, optional): Collapsible section title text. Defaults to "Root".
"""
self.add_text(f"<details><summary>{title}</summary>\n\n```json\n" + text + "\n```\n</details>")
[docs]
def add_text(self, content):
"""Adds text to markdown
Args:
content (Any): Text content
"""
self.sections.append(f"{content}\n\n")