def test_activate_nav(): files = types.Files( [ types.File( input_path="index.md", output_path="index.html", input_dir="docs", output_dir="build", convertor=MarkdownPages(), ), types.File( input_path=os.path.join("topics", "a.md"), output_path=os.path.join("topics", "a", "index.html"), input_dir="docs", output_dir="build", convertor=MarkdownPages(), ), types.File( input_path=os.path.join("topics", "b.md"), output_path=os.path.join("topics", "b", "index.html"), input_dir="docs", output_dir="build", convertor=MarkdownPages(), ), ] ) nav = types.Nav( [ types.NavPage(title="Home", file=files[0]), types.NavGroup( title="Topics", children=[ types.NavPage(title="Topic A", file=files[1]), types.NavPage(title="Topic B", file=files[2]), ], ), ] ) nav.activate(files[0]) assert nav[0].is_active assert not nav[1].is_active assert not nav[1].children[0].is_active assert not nav[1].children[0].is_active nav.deactivate() nav.activate(files[1]) assert not nav[0].is_active assert nav[1].is_active assert nav[1].children[0].is_active assert not nav[1].children[1].is_active nav.deactivate() nav.activate(files[2]) assert not nav[0].is_active assert nav[1].is_active assert not nav[1].children[0].is_active assert nav[1].children[1].is_active nav.deactivate()
def test_load_nav(): input_dir = "input" output_dir = "output" template_dir = "templates" config = {"site": {"url": "/"}, "build": {"template_dir": template_dir}} markdown_convertor = convertors.MarkdownConvertor(config=config) files = types.Files([ types.File( input_rel_path="index.md", output_rel_path="index.html", input_dir=input_dir, output_dir=output_dir, convertor=markdown_convertor, ), types.File( input_rel_path=os.path.join("topics", "a.md"), output_rel_path=os.path.join("topics", "a", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=markdown_convertor, ), types.File( input_rel_path=os.path.join("topics", "b.md"), output_rel_path=os.path.join("topics", "b", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=markdown_convertor, ), ]) nav_info = { "Home": "index.md", "Topics": { "Topic A": os.path.join("topics", "a.md"), "Topic B": os.path.join("topics", "b.md"), }, } nav = core.load_nav_info(nav_info, files) assert nav == [ types.NavPage(title="Home", file=files[0]), types.NavGroup( title="Topics", children=[ types.NavPage(title="Topic A", file=files[1]), types.NavPage(title="Topic B", file=files[2]), ], ), ] home = nav[0] topics = nav[1] topic_a = topics.children[0] topic_b = topics.children[1] assert home.parent is None assert topics.parent is None assert topic_a.parent is topics assert topic_b.parent is topics
def gather_files( input_dir: str, output_dir: str, convertors: typing.List[types.Convertor], sub_dir: str = "", ) -> types.Files: """ Determine all of the files in the input directory. """ files = types.Files() dirname = os.path.join(input_dir, sub_dir) for basename in sorted(os.listdir(dirname)): path = os.path.join(dirname, basename) if os.path.isdir(path): # Descend into sub-directories. next_sub_dir = os.path.join(sub_dir, basename) files += gather_files( input_dir=input_dir, output_dir=output_dir, convertors=convertors, sub_dir=next_sub_dir, ) else: # Determine if there are any convertors that handle the given file. input_path = os.path.join(sub_dir, basename) for convertor in convertors: if convertor.should_handle_file(input_path): output_path = convertor.get_output_path(input_path) file = types.File( input_path=input_path, output_path=output_path, input_dir=input_dir, output_dir=output_dir, convertor=convertor, ) files.append(file) break # Add any extra files that are provided by a convertor class. for convertor in convertors: for path in convertor.get_extra_paths(): file = types.File( input_path="", output_path=path, input_dir="", output_dir=output_dir, convertor=convertor, ) files.append(file) return files
def test_nav_relative_urls(): input_dir = "input" output_dir = "output" files = types.Files( [ types.File( input_path="index.md", output_path="index.html", input_dir=input_dir, output_dir=output_dir, convertor=MarkdownPages(), ), types.File( input_path=os.path.join("topics", "a.md"), output_path=os.path.join("topics", "a", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=MarkdownPages(), ), types.File( input_path=os.path.join("topics", "b.md"), output_path=os.path.join("topics", "b", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=MarkdownPages(), ), ] ) nav = types.Nav( items=[ types.NavPage(title="Home", file=files[0]), types.NavGroup( title="Topics", children=[ types.NavPage(title="Topic A", file=files[1]), types.NavPage(title="Topic B", file=files[2]), ], ), ], base_url=None, ) nav.activate(files[1]) assert nav[0].url == "../../" assert nav[1].children[0].url == "." assert nav[1].children[1].url == "../b/" nav.deactivate()
def test_gather_files(tmpdir): """ Ensure that `gather_files` collects all the files in the input directory. """ input_dir = os.path.join(tmpdir, "input") output_dir = os.path.join(tmpdir, "output") template_dir = os.path.join(tmpdir, "templates") config = {"site": {"url": "/"}, "build": {"template_dir": template_dir}} markdown_convertor = convertors.MarkdownConvertor(config=config) index_md = os.path.join(input_dir, "index.md") a_md = os.path.join(input_dir, "a.md") b_md = os.path.join(input_dir, "b", "b.md") write_file(index_md, "index") write_file(a_md, "aaa") write_file(b_md, "bbb") file_convertors = {"**.md": markdown_convertor} files = core.gather_files(input_dir=input_dir, output_dir=output_dir, file_convertors=file_convertors) assert files == types.Files([ types.File( input_rel_path="a.md", output_rel_path=os.path.join("a", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=markdown_convertor, ), types.File( input_rel_path=os.path.join("b", "b.md"), output_rel_path=os.path.join("b", "b", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=markdown_convertor, ), types.File( input_rel_path="index.md", output_rel_path="index.html", input_dir=input_dir, output_dir=output_dir, convertor=markdown_convertor, ), ])
def test_urls_for_files(): file = types.File( input_path="index.md", output_path="index.html", input_dir="input", output_dir="output", convertor=MarkdownPages(), ) assert file.url == "/" file = types.File( input_path="page.html", output_path="page.html", input_dir="input", output_dir="output", convertor=MarkdownPages(), ) assert file.url == "/page.html"
def test_gather_files(tmpdir): """ Ensure that `gather_files` collects all the files in the input directory. """ input_dir = os.path.join(tmpdir, "input") output_dir = os.path.join(tmpdir, "output") convertors = [MarkdownPages()] index_md = os.path.join(input_dir, "index.md") a_md = os.path.join(input_dir, "a.md") b_md = os.path.join(input_dir, "b", "b.md") write_file(index_md, "index") write_file(a_md, "aaa") write_file(b_md, "bbb") files = core.gather_files( input_dir=input_dir, output_dir=output_dir, convertors=convertors ) assert files == types.Files( [ types.File( input_path="a.md", output_path=os.path.join("a", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=convertors[0], ), types.File( input_path=os.path.join("b", "b.md"), output_path=os.path.join("b", "b", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=convertors[0], ), types.File( input_path="index.md", output_path="index.html", input_dir=input_dir, output_dir=output_dir, convertor=convertors[0], ), ] )
def test_urls_for_files(): config = {"site": {"url": "/"}, "build": {"template_dir": "templates"}} markdown_convertor = convertors.MarkdownConvertor(config=config) file = types.File( input_rel_path="index.md", output_rel_path="index.html", input_dir="input", output_dir="output", convertor=markdown_convertor, ) assert file.url == "/" file = types.File( input_rel_path="page.html", output_rel_path="page.html", input_dir="input", output_dir="output", convertor=markdown_convertor, ) assert file.url == "/page.html"
def gather_files( input_dir: str, output_dir: str, default_convertor: types.Convertor = None, file_convertors: typing.Dict[str, types.Convertor] = None, sub_dir: str = "", ) -> types.Files: """ Determine all of the files in the input directory. """ if default_convertor is None: default_convertor = convertors.StaticFileConvertor(config={}) if file_convertors is None: file_convertors = {} files = types.Files() dirname = os.path.join(input_dir, sub_dir) for basename in sorted(os.listdir(dirname)): path = os.path.join(dirname, basename) if os.path.isdir(path): next_sub_dir = os.path.join(sub_dir, basename) files += gather_files( input_dir=input_dir, output_dir=output_dir, default_convertor=default_convertor, file_convertors=file_convertors, sub_dir=next_sub_dir, ) else: input_rel_path = os.path.join(sub_dir, basename) convertor = default_convertor for pattern, file_convertor in file_convertors.items(): if fnmatch.fnmatch(input_rel_path, pattern): convertor = file_convertor break output_rel_path = convertor.get_output_path(input_rel_path) file = types.File( input_rel_path=input_rel_path, output_rel_path=output_rel_path, input_dir=input_dir, output_dir=output_dir, convertor=convertor, ) files.append(file) return files
def test_overwrite_files(tmpdir): """ Adding `gather_files` together should allow overwriting, so that only one instance is included for each unique input path. ie. docs files can override theme files. """ primary_input_dir = os.path.join(tmpdir, "primary") secondary_input_dir = os.path.join(tmpdir, "secondary") output_dir = os.path.join(tmpdir, "output") primary_txt = os.path.join(primary_input_dir, "a.txt") secondary_txt = os.path.join(secondary_input_dir, "a.txt") write_file(primary_txt, "aaa") write_file(secondary_txt, "bbb") convertors = [StaticFiles()] secondary = core.gather_files( input_dir=secondary_input_dir, output_dir=output_dir, convertors=convertors ) primary = core.gather_files( input_dir=primary_input_dir, output_dir=output_dir, convertors=convertors ) files = secondary + primary assert len(files) == 1 assert files == types.Files( [ types.File( input_path="a.txt", output_path="a.txt", input_dir=primary_input_dir, output_dir=output_dir, convertor=convertors[0], ) ] )
def test_overwrite_files(tmpdir): """ Adding `gather_files` together should allow overwriting, so that only one instance is included for each unique input path. ie. docs files can override theme files. """ primary_input_dir = os.path.join(tmpdir, "primary") secondary_input_dir = os.path.join(tmpdir, "secondary") output_dir = os.path.join(tmpdir, "output") template_dir = os.path.join(tmpdir, "templates") config = {"site": {"url": "/"}, "build": {"template_dir": template_dir}} markdown_convertor = convertors.MarkdownConvertor(config=config) static_file_convertor = convertors.StaticFileConvertor(config=config) primary_txt = os.path.join(primary_input_dir, "a.txt") secondary_txt = os.path.join(secondary_input_dir, "a.txt") write_file(primary_txt, "aaa") write_file(secondary_txt, "bbb") secondary = core.gather_files(input_dir=secondary_input_dir, output_dir=output_dir) primary = core.gather_files(input_dir=primary_input_dir, output_dir=output_dir) files = secondary + primary assert len(files) == 1 assert files == types.Files([ types.File( input_rel_path="a.txt", output_rel_path="a.txt", input_dir=primary_input_dir, output_dir=output_dir, convertor=static_file_convertor, ) ])
def test_url_function(): input_dir = "input" output_dir = "output" files = types.Files( [ types.File( input_path="index.md", output_path="index.html", input_dir=input_dir, output_dir=output_dir, convertor=MarkdownPages(), ), types.File( input_path=os.path.join("topics", "a.md"), output_path=os.path.join("topics", "a", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=MarkdownPages(), ), types.File( input_path=os.path.join("topics", "b.md"), output_path=os.path.join("topics", "b", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=MarkdownPages(), ), ] ) nav = types.Nav( [ types.NavPage(title="Home", file=files[0]), types.NavGroup( title="Topics", children=[ types.NavPage(title="Topic A", file=files[1]), types.NavPage(title="Topic B", file=files[2]), ], ), ] ) assert files[0].url == "/" assert files[1].url == "/topics/a/" assert files[2].url == "/topics/b/" assert nav[0].url == "/" assert nav[1].children[0].url == "/topics/a/" assert nav[1].children[1].url == "/topics/b/" # No base URL. env = types.Env(files=files, nav=nav, template_dir="templates") url = functools.partial(env.get_url, from_file=files[0]) assert url("#anchor") == "#anchor" assert url("https://www.example.com") == "https://www.example.com" assert url("topics/a.md") == "topics/a/" assert url("topics/b.md") == "topics/b/" assert url("/topics/a/") == "topics/a/" assert url("/topics/b/") == "topics/b/" url = functools.partial(env.get_url, from_file=files[1]) assert url("../index.md") == "../../" assert url("b.md") == "../b/" assert url("/") == "../../" assert url("/topics/b/") == "../b/" url = functools.partial(env.get_url, from_file=files[2]) assert url("../index.md") == "../../" assert url("a.md#anchor") == "../a/#anchor" assert url("/") == "../../" assert url("/topics/a/#anchor") == "../a/#anchor" # Host relative base URL. env = types.Env(files=files, nav=nav, template_dir="templates", base_url="/") url = functools.partial(env.get_url, from_file=files[0]) assert url("#anchor") == "#anchor" assert url("https://www.example.com") == "https://www.example.com" assert url("topics/a.md") == "/topics/a/" assert url("topics/b.md") == "/topics/b/" assert url("/topics/a/") == "/topics/a/" assert url("/topics/b/") == "/topics/b/" url = functools.partial(env.get_url, from_file=files[1]) assert url("../index.md") == "/" assert url("b.md") == "/topics/b/" assert url("/") == "/" assert url("/topics/b/") == "/topics/b/" url = functools.partial(env.get_url, from_file=files[2]) assert url("../index.md") == "/" assert url("a.md#anchor") == "/topics/a/#anchor" assert url("/") == "/" assert url("/topics/a/#anchor") == "/topics/a/#anchor" # Absolute base URL. env = types.Env( files=files, nav=nav, template_dir="templates", base_url="https://example.com" ) url = functools.partial(env.get_url, from_file=files[0]) assert url("#anchor") == "#anchor" assert url("https://www.example.com") == "https://www.example.com" assert url("topics/a.md") == "https://example.com/topics/a/" assert url("topics/b.md") == "https://example.com/topics/b/" assert url("/topics/a/") == "https://example.com/topics/a/" assert url("/topics/b/") == "https://example.com/topics/b/" url = functools.partial(env.get_url, from_file=files[1]) assert url("../index.md") == "https://example.com/" assert url("b.md") == "https://example.com/topics/b/" assert url("/") == "https://example.com/" assert url("/topics/b/") == "https://example.com/topics/b/" url = functools.partial(env.get_url, from_file=files[2]) assert url("../index.md") == "https://example.com/" assert url("a.md#anchor") == "https://example.com/topics/a/#anchor" assert url("/") == "https://example.com/" assert url("/topics/a/#anchor") == "https://example.com/topics/a/#anchor"
def test_load_nav(): input_dir = "input" output_dir = "output" markdown_convertor = MarkdownPages() files = types.Files( [ types.File( input_path="index.md", output_path="index.html", input_dir=input_dir, output_dir=output_dir, convertor=markdown_convertor, ), types.File( input_path=os.path.join("topics", "a.md"), output_path=os.path.join("topics", "a", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=markdown_convertor, ), types.File( input_path=os.path.join("topics", "b.md"), output_path=os.path.join("topics", "b", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=markdown_convertor, ), ] ) nav_info = { "Home": "index.md", "Topics": { "Topic A": os.path.join("topics", "a.md"), "Topic B": os.path.join("topics", "b.md"), }, } nav = core.load_nav(nav_info, files) assert nav == types.Nav( [ types.NavPage(title="Home", file=files[0]), types.NavGroup( title="Topics", children=[ types.NavPage(title="Topic A", file=files[1]), types.NavPage(title="Topic B", file=files[2]), ], ), ] ) home = nav[0] topics = nav[1] topic_a = topics.children[0] topic_b = topics.children[1] assert home.parent is None assert topics.parent is None assert topic_a.parent is topics assert topic_b.parent is topics # Ensure basic `__bool__`, `__len__`, `__iter__` interfaces are supported. assert nav assert len(nav) == 2 assert len(list(nav)) == 2
def test_url_function(): config = {"site": {"url": "/"}, "build": {"template_dir": "templates"}} markdown_convertor = convertors.MarkdownConvertor(config=config) input_dir = "input" output_dir = "output" files = types.Files([ types.File( input_rel_path="index.md", output_rel_path="index.html", input_dir=input_dir, output_dir=output_dir, convertor=markdown_convertor, ), types.File( input_rel_path=os.path.join("topics", "a.md"), output_rel_path=os.path.join("topics", "a", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=markdown_convertor, ), types.File( input_rel_path=os.path.join("topics", "b.md"), output_rel_path=os.path.join("topics", "b", "index.html"), input_dir=input_dir, output_dir=output_dir, convertor=markdown_convertor, ), ]) assert files[0].url == "/" assert files[1].url == "/topics/a/" assert files[2].url == "/topics/b/" # No base URL. url = core.url_function_for_file(files[0], files) assert url("#anchor") == "#anchor" assert url("https://www.example.com") == "https://www.example.com" assert url("topics/a.md") == "topics/a/" assert url("topics/b.md") == "topics/b/" assert url("/topics/a/") == "topics/a/" assert url("/topics/b/") == "topics/b/" url = core.url_function_for_file(files[1], files) assert url("../index.md") == "../../" assert url("b.md") == "../b/" assert url("/") == "../../" assert url("/topics/b/") == "../b/" url = core.url_function_for_file(files[2], files) assert url("../index.md") == "../../" assert url("a.md#anchor") == "../a/#anchor" assert url("/") == "../../" assert url("/topics/a/#anchor") == "../a/#anchor" # Host relative base URL. url = core.url_function_for_file(files[0], files, base_url="/") assert url("#anchor") == "#anchor" assert url("https://www.example.com") == "https://www.example.com" assert url("topics/a.md") == "/topics/a/" assert url("topics/b.md") == "/topics/b/" assert url("/topics/a/") == "/topics/a/" assert url("/topics/b/") == "/topics/b/" url = core.url_function_for_file(files[1], files, base_url="/") assert url("../index.md") == "/" assert url("b.md") == "/topics/b/" assert url("/") == "/" assert url("/topics/b/") == "/topics/b/" url = core.url_function_for_file(files[2], files, base_url="/") assert url("../index.md") == "/" assert url("a.md#anchor") == "/topics/a/#anchor" assert url("/") == "/" assert url("/topics/a/#anchor") == "/topics/a/#anchor" # Absolute base URL. url = core.url_function_for_file(files[0], files, base_url="https://example.com") assert url("#anchor") == "#anchor" assert url("https://www.example.com") == "https://www.example.com" assert url("topics/a.md") == "https://example.com/topics/a/" assert url("topics/b.md") == "https://example.com/topics/b/" assert url("/topics/a/") == "https://example.com/topics/a/" assert url("/topics/b/") == "https://example.com/topics/b/" url = core.url_function_for_file(files[1], files, base_url="https://example.com") assert url("../index.md") == "https://example.com/" assert url("b.md") == "https://example.com/topics/b/" assert url("/") == "https://example.com/" assert url("/topics/b/") == "https://example.com/topics/b/" url = core.url_function_for_file(files[2], files, base_url="https://example.com") assert url("../index.md") == "https://example.com/" assert url("a.md#anchor") == "https://example.com/topics/a/#anchor" assert url("/") == "https://example.com/" assert url("/topics/a/#anchor") == "https://example.com/topics/a/#anchor"