]
[project.scripts]
-render = "render:main"
+render = "krass.render:main"
[project.urls]
Homepage = "None"
--- /dev/null
+import os
+from pathlib import Path
+from typing import Optional
+
+from markdown_it import MarkdownIt
+
+from proto import command, get_argspecs
+from proto.io import Stdio
+
+
+def render_contents(contents: str)->str:
+ return MarkdownIt().render(contents)
+
+@command
+def render_file(infile: Optional[Path]=None, outfile: Optional[Path]=None):
+ file_contents = Stdio.read(infile)
+ output = render_contents(file_contents)
+ Stdio.write(output, outfile)
+
+@get_argspecs.register
+def bool_argspecs(annotation: bool)->dict:
+ """ Implements get_argspecs for Booleans. """
+ return {'action':'store_true'}
+
+@get_argspecs.register
+def list_argspecs(annotation: list)->dict:
+ """ Implements argspecs for a list of one or more items."""
+ return {'nargs':'+', 'type':Path}
+
+@command
+def render_files(files: list, norecursion: bool = False):
+ for path in files:
+ if path.exists and path.is_file():
+ outfile= Path(path.parent).joinpath(path.stem + ".html")
+ render_file(infile=path, outfile=outfile)
+ elif path.exists and path.is_dir() and not norecursion:
+ children = [path.joinpath(child) for child in os.listdir(path)]
+ render_files(files=children)
+ else:
+ raise Exception(f"The specified path does not exist or is not a file: {path}.")
+
+def main():
+ render_files.parse()
+ render_files.run()
--- /dev/null
+# Title
+
+This is a paragraph.
+
+* Unordered item one
+* Unordered item two
+
+``` python
+print("This is code")
+```
+
+## Subtitle
+
+This line has *emphasized* text.
+
+This line has **strong** text.
+
+This line has `inline code`.
+
+1. Enumerated one
+2. Enumerated two
+
+| Column One | Column Two |
+| ---------- | ---------- |
+| Entry 1, 1 | Entry 1, 2 |
+| Entry 2, 1 | Entry 2, 2 |
\ No newline at end of file
--- /dev/null
+import os
+import shlex
+import shutil
+from pathlib import Path
+
+import pytest
+
+from krass.render import render_file, render_files
+
+DATA = Path.cwd().joinpath("tests/data/test.md")
+
+# TODO: When you create outdir option, rewrite tests to write to tmp rather than copying.
+# TODO: Test --norecursion
+
+def test_single_file(tmp_path):
+ infile = Path(shutil.copy(DATA, tmp_path))
+ outfile = Path(tmp_path).joinpath(infile.stem + ".html")
+ render_file.parse(args=shlex.split(f"--infile {infile} --outfile={outfile}"))
+ render_file.run()
+ contents = os.listdir(tmp_path)
+ assert outfile.name in contents
+
+def test_two_files(tmp_path):
+ infile1 = Path(shutil.copy(DATA, tmp_path))
+ infile2 = Path(shutil.copy(DATA, tmp_path.joinpath("test2.md")))
+ outfile1 = Path(tmp_path).joinpath(infile1.stem + ".html")
+ outfile2 = Path(tmp_path).joinpath(infile2.stem + ".html")
+ render_files.parse(args=shlex.split(f"{infile1} {infile2}"))
+ render_files.run()
+ contents = os.listdir(tmp_path)
+ assert outfile1.name in contents
+ assert outfile2.name in contents
+
+def test_non_file():
+ with pytest.raises(Exception):
+ render_files.parse(args=shlex.split("/not/a/path"))
+ render_files.run()
--- /dev/null
+# TODO:
+
+## Krass
+* Add --outdir to render_files to separate A
+* With --outdir, clean up tests
+* BUG: In render_files: list should be list[Path] See proto.infer._parse_type bug
+ * Note: It doesn't look like you can dispatch on list[T] for various T.
+ * Per https://stackoverflow.com/questions/68381197/is-it-possible-to-use-functools-singledispatch-with-composite-nested-container-t
+ * I wonder if you can get around that by singledispatch currying
+ * e.g. dispatch on list to a generic function that is itself dispatched on T.
+* Clean up Exception raised in render_files. Make specific and push upstream.
+
+## Proto
+* Refine Stdio stuff. (Binding infile to content, define hook in command decorator)
+ * This will probably be done under the hood with functools.partial.
+ * Turn this into a context manager?
+ ``` python
+ with Stdio:
+ do_command(*args, **kwargs)
+ ```
+ * Still need a way to bind infile_contents -> do_command argument and otherwise pass args.
+ * `@command(io=Stdio, infile="contents")`
+ * Alt: `@command(io=Stdio(infile="contents"))`
+* Continue work with subparsers branch
+* Consider defining walk(predicate, function) as a way to render files.
+* Add Stdio check for Path.exists and Path.is_file
+* Add Stdio tests?
\ No newline at end of file