Package supermark

Expand source code
from .build_html import build_html
from .build_latex import build_latex
from .chunks import Chunk, HTMLChunk, MarkdownChunk, YAMLChunk, YAMLDataChunk
from .parse import RawChunk

__version__ = "0.2.2"

__all__ = [
    "RawChunk",
    "Chunk",
    "YAMLChunk",
    "YAMLDataChunk",
    "MarkdownChunk",
    "HTMLChunk",
    "build_html",
    "build_latex",
    "build_latex_yaml",
]

Sub-modules

supermark.button
supermark.chunks
supermark.code
supermark.command
supermark.core
supermark.figure
supermark.hint
supermark.hint2
supermark.lines
supermark.parse
supermark.report
supermark.table
supermark.tell
supermark.video

Functions

def build_html(input_path, output_path, template_file, rebuild_all_pages=True, abort_draft=True, verbose=False)
Expand source code
def build_html(
    input_path,
    output_path,
    template_file,
    rebuild_all_pages=True,
    abort_draft=True,
    verbose=False,
):
    reports = []
    report = Report(None)
    template = load_html_template(template_file, report)
    jobs = []
    for filename in os.listdir(input_path):
        source_file_path = os.path.join(input_path, filename)
        if os.path.isfile(source_file_path) and filename.endswith(".md"):
            target_file_name = os.path.splitext(os.path.basename(filename))[0] + ".html"
            target_file_path = os.path.join(output_path, target_file_name)
            if _create_target(
                source_file_path, target_file_path, template_file, rebuild_all_pages
            ):
                jobs.append(
                    {
                        "source_file_path": source_file_path,
                        "target_file_path": target_file_path,
                        "template": template,
                        "abort_draft": abort_draft,
                    }
                )
    with ThreadPoolExecutor() as e:
        with tqdm(total=len(jobs)) as progress:
            futures = []
            for job in jobs:
                future = e.submit(
                    process_file,
                    job["source_file_path"],
                    job["target_file_path"],
                    job["template"],
                    job["abort_draft"],
                )
                future.add_done_callback(lambda p: progress.update())
                futures.append(future)
            for future in futures:
                reports.append(future.result())
    print_reports(reports)
def build_latex(build_file, base_path)
Expand source code
def build_latex(build_file, base_path):
    with open(build_file) as file:
        for doc in load_all(file, Loader=SafeLoader):
            b = Builder(doc, base_path)
            b.to_latex()

Classes

class Chunk (raw_chunk, page_variables)

Base class for a chunk.

Expand source code
class Chunk:
    """ Base class for a chunk.
    """

    def __init__(self, raw_chunk, page_variables):
        self.raw_chunk = raw_chunk
        self.page_variables = page_variables
        self.aside = False
        self.asides = []

    def is_aside(self):
        return self.aside

    def get_asides(self):
        return self.asides

    def get_first_line(self):
        return self.raw_chunk.lines[0]

    def get_last_line(self):
        return self.raw_chunk.lines[-1]

    def get_type(self):
        return self.raw_chunk.type

    def get_start_line_number(self):
        return self.raw_chunk.start_line_number

    def get_content(self):
        return "".join(self.raw_chunk.lines)

    def to_latex(self, builder):
        print("No conversion to latex: " + self.get_content())
        return None

    @staticmethod
    def create_hash(content):
        shake = hashlib.shake_128()
        shake.update(content.encode("utf-8"))
        return shake.hexdigest(3)

    def get_dir_cached(self):
        cached = self.raw_chunk.parent_path / "cached"
        cached.mkdir(parents=True, exist_ok=True)
        return cached

Subclasses

Static methods

def create_hash(content)
Expand source code
@staticmethod
def create_hash(content):
    shake = hashlib.shake_128()
    shake.update(content.encode("utf-8"))
    return shake.hexdigest(3)

Methods

def get_asides(self)
Expand source code
def get_asides(self):
    return self.asides
def get_content(self)
Expand source code
def get_content(self):
    return "".join(self.raw_chunk.lines)
def get_dir_cached(self)
Expand source code
def get_dir_cached(self):
    cached = self.raw_chunk.parent_path / "cached"
    cached.mkdir(parents=True, exist_ok=True)
    return cached
def get_first_line(self)
Expand source code
def get_first_line(self):
    return self.raw_chunk.lines[0]
def get_last_line(self)
Expand source code
def get_last_line(self):
    return self.raw_chunk.lines[-1]
def get_start_line_number(self)
Expand source code
def get_start_line_number(self):
    return self.raw_chunk.start_line_number
def get_type(self)
Expand source code
def get_type(self):
    return self.raw_chunk.type
def is_aside(self)
Expand source code
def is_aside(self):
    return self.aside
def to_latex(self, builder)
Expand source code
def to_latex(self, builder):
    print("No conversion to latex: " + self.get_content())
    return None
class HTMLChunk (raw_chunk, page_variables)

Base class for a chunk.

Expand source code
class HTMLChunk(Chunk):
    def __init__(self, raw_chunk, page_variables):
        super().__init__(raw_chunk, page_variables)

    def to_html(self):
        return super().get_content()

    def html_to_latex(self):
        extra_args = ["--ascii", "--highlight-style", "pygments"]
        extra_args = ["--highlight-style", "pygments"]
        return pypandoc.convert_text(
            super().get_content(), "latex", format="html", extra_args=extra_args
        )
        # return None

    def to_latex(self, builder):
        if super().get_content().startswith("<!--"):
            return None
        else:
            print("HTML to Latex:")
            print(super().get_content())
            print()
            print(
                pypandoc.convert_text(super().get_content(), "mediawiki", format="html")
            )
            return self.html_to_latex()

Ancestors

Methods

def html_to_latex(self)
Expand source code
def html_to_latex(self):
    extra_args = ["--ascii", "--highlight-style", "pygments"]
    extra_args = ["--highlight-style", "pygments"]
    return pypandoc.convert_text(
        super().get_content(), "latex", format="html", extra_args=extra_args
    )
def to_html(self)
Expand source code
def to_html(self):
    return super().get_content()
def to_latex(self, builder)
Expand source code
def to_latex(self, builder):
    if super().get_content().startswith("<!--"):
        return None
    else:
        print("HTML to Latex:")
        print(super().get_content())
        print()
        print(
            pypandoc.convert_text(super().get_content(), "mediawiki", format="html")
        )
        return self.html_to_latex()
class MarkdownChunk (raw_chunk, page_variables)

Base class for a chunk.

Expand source code
class MarkdownChunk(Chunk):
    def __init__(self, raw_chunk, page_variables):
        super().__init__(raw_chunk, page_variables)
        self.content = "".join(self.raw_chunk.lines)
        self.is_section = super().get_first_line().startswith("# ")
        if raw_chunk.get_tag() is not None:
            self.class_tag = super().get_first_line().strip().split(":")[1].lower()
            self.aside = self.class_tag == "aside"
            self.content = self.content[len(self.class_tag) + 2 :].strip()
        else:
            self.class_tag = None
            self.aside = False

    def get_content(self):
        return self.content

    def pandoc_to_html(self):
        extra_args = ["--ascii", "--highlight-style", "pygments"]
        extra_args = ["--highlight-style", "pygments"]
        return pypandoc.convert_text(
            self.get_content(), "html", format="md", extra_args=extra_args
        )

    def to_html(self):
        if self.aside:
            aside_id = Chunk.create_hash(self.content)
            output = []
            output.append(
                '<span name="{}"></span><aside name="{}">'.format(aside_id, aside_id)
            )
            output.append(self.pandoc_to_html())
            output.append("</aside>")
            return "".join(output)
        else:
            if self.class_tag:
                output = self.pandoc_to_html()
                output = '<div class="{}">{}</div>'.format(self.class_tag, output)
            else:
                output = self.pandoc_to_html()
            return output

    def wrap(self, content):
        return (
            "\\begin{tcolorbox}[colback=red!5!white,colframe=red!75!black,arc=0pt,outer arc=0pt,leftrule=2pt,rightrule=0pt,toprule=0pt,bottomrule=0pt]"
            + content
            + r"\end{tcolorbox}"
        )

    def bold_prefix(self, prefix):
        return "\\textbf{{{}}} ".format(prefix + ":")

    def markdown_to_latex(self):
        extra_args = ["--ascii", "--highlight-style", "pygments"]
        extra_args = ["--highlight-style", "pygments"]
        content = pypandoc.convert_text(
            self.get_content(), "latex", format="md", extra_args=extra_args
        )
        return content

    def to_latex(self, builder):
        output = self.markdown_to_latex()
        if self.class_tag is None:
            return output
        elif self.class_tag == "aside":
            return self.wrap(output)
        elif self.class_tag == "goals":
            return self.wrap(output)
        elif self.class_tag == "warning":
            return self.wrap(self.bold_prefix("Warning") + output)
        elif self.class_tag == "tip":
            return self.wrap(self.bold_prefix("Tip") + output)
        return output

Ancestors

Subclasses

Methods

def bold_prefix(self, prefix)
Expand source code
def bold_prefix(self, prefix):
    return "\\textbf{{{}}} ".format(prefix + ":")
def get_content(self)
Expand source code
def get_content(self):
    return self.content
def markdown_to_latex(self)
Expand source code
def markdown_to_latex(self):
    extra_args = ["--ascii", "--highlight-style", "pygments"]
    extra_args = ["--highlight-style", "pygments"]
    content = pypandoc.convert_text(
        self.get_content(), "latex", format="md", extra_args=extra_args
    )
    return content
def pandoc_to_html(self)
Expand source code
def pandoc_to_html(self):
    extra_args = ["--ascii", "--highlight-style", "pygments"]
    extra_args = ["--highlight-style", "pygments"]
    return pypandoc.convert_text(
        self.get_content(), "html", format="md", extra_args=extra_args
    )
def to_html(self)
Expand source code
def to_html(self):
    if self.aside:
        aside_id = Chunk.create_hash(self.content)
        output = []
        output.append(
            '<span name="{}"></span><aside name="{}">'.format(aside_id, aside_id)
        )
        output.append(self.pandoc_to_html())
        output.append("</aside>")
        return "".join(output)
    else:
        if self.class_tag:
            output = self.pandoc_to_html()
            output = '<div class="{}">{}</div>'.format(self.class_tag, output)
        else:
            output = self.pandoc_to_html()
        return output
def to_latex(self, builder)
Expand source code
def to_latex(self, builder):
    output = self.markdown_to_latex()
    if self.class_tag is None:
        return output
    elif self.class_tag == "aside":
        return self.wrap(output)
    elif self.class_tag == "goals":
        return self.wrap(output)
    elif self.class_tag == "warning":
        return self.wrap(self.bold_prefix("Warning") + output)
    elif self.class_tag == "tip":
        return self.wrap(self.bold_prefix("Tip") + output)
    return output
def wrap(self, content)
Expand source code
def wrap(self, content):
    return (
        "\\begin{tcolorbox}[colback=red!5!white,colframe=red!75!black,arc=0pt,outer arc=0pt,leftrule=2pt,rightrule=0pt,toprule=0pt,bottomrule=0pt]"
        + content
        + r"\end{tcolorbox}"
    )
class RawChunk (lines, chunk_type, start_line_number, path, report)
Expand source code
class RawChunk:
    def __init__(self, lines, chunk_type, start_line_number, path, report):
        self.lines = lines
        self.type = chunk_type
        self.start_line_number = start_line_number
        self.path = path
        self.parent_path = Path(path).parent.parent
        self.report = report
        # check if we only got empty lines
        def all_empty(lines):
            if len(lines) == 0:
                return True
            for line in lines:
                if line.strip():
                    return False
            return True

        self._is_empty = all_empty(self.lines)
        # remove blank lines from the beginning
        while len(self.lines) > 0 and is_empty(self.lines[0].strip()):
            self.lines.pop(0)
            self.start_line_number = self.start_line_number + 1
        self.tag = None
        if len(self.lines) > 0:
            if has_class_tag(self.lines[0]):
                self.tag = self.lines[0].strip().split(":")[1].lower()
        self.post_yaml = None

    def get_tag(self):
        return self.tag

    def is_empty(self):
        return self._is_empty

    def get_type(self):
        return self.type

    def get_first_line(self):
        if len(self.lines) == 0:
            return "empty"
        return self.lines[0]

Methods

def get_first_line(self)
Expand source code
def get_first_line(self):
    if len(self.lines) == 0:
        return "empty"
    return self.lines[0]
def get_tag(self)
Expand source code
def get_tag(self):
    return self.tag
def get_type(self)
Expand source code
def get_type(self):
    return self.type
def is_empty(self)
Expand source code
def is_empty(self):
    return self._is_empty
class YAMLChunk (raw_chunk, dictionary, page_variables, required=None, optional=None)

Base class for a chunk.

Expand source code
class YAMLChunk(Chunk):
    def __init__(
        self, raw_chunk, dictionary, page_variables, required=None, optional=None
    ):
        super().__init__(raw_chunk, page_variables)
        self.dictionary = dictionary
        required = required or []
        optional = optional or []
        for key in required:
            if key not in self.dictionary:
                raw_chunk.report.tell(
                    "YAML section misses required parameter '{}'.".format(key),
                    level=Report.ERROR,
                    chunk=raw_chunk,
                )
        for key in self.dictionary.keys():
            if (key not in required) and (key not in optional) and (key != "type"):
                raw_chunk.report.tell(
                    "YAML section has unknown parameter '{}'.".format(key),
                    level=Report.WARNING,
                    chunk=raw_chunk,
                )

    def has_post_yaml(self):
        return self.raw_chunk.post_yaml is not None

    def get_post_yaml(self):
        return "".join(self.raw_chunk.post_yaml)

Ancestors

Subclasses

Methods

def get_post_yaml(self)
Expand source code
def get_post_yaml(self):
    return "".join(self.raw_chunk.post_yaml)
def has_post_yaml(self)
Expand source code
def has_post_yaml(self):
    return self.raw_chunk.post_yaml is not None
class YAMLDataChunk (raw_chunk, dictionary, page_variables)

Base class for a chunk.

Expand source code
class YAMLDataChunk(YAMLChunk):
    def __init__(self, raw_chunk, dictionary, page_variables):
        super().__init__(raw_chunk, dictionary, page_variables, optional=["status"])

    def to_latex(self, builder):
        return None

Ancestors

Methods

def to_latex(self, builder)
Expand source code
def to_latex(self, builder):
    return None