def test_second_level_toc_links_point_to_html_files(context): "The second_level file should have correct html links for markdown files" project = Project.discover(context.project_path) theme = Theme.load_by_name('touch-of-pink') destination = Generator(project, theme) generated = sorted(destination.persist(context.output_path), key=sort_files) generated.should.have.length_of(7) second_level = generated[2] second_level.should.contain('docs/output.html') html = open(second_level).read() dom = lhtml.fromstring(html) links = dom.cssselect('a.toc') links.should.have.length_of(4) l1, l2, l3, l4 = links l1.attrib.should.have.key('href').being.equal('../index.html') l2.attrib.should.have.key('href').being.to.match('./\w+.html') l3.attrib.should.have.key('href').being.to.match('./\w+.html') l4.attrib.should.have.key('href').being.equal('./even/deeper/item.html')
def test_relative_link_callback_with_asset_already_to_copy(exists): ("Generator#relative_link_callback(original_link, current_document_info," " destination_root) with an asset") theme = Mock() project = Mock() project.node = FakeNode("/coolproject") engine = Generator(project, theme) engine.files_to_copy = [ "/coolproject/css/style.css", "/css/style.css", "css/style.css", "style.css", ] destination_root = FakeNode("/output") value = engine.relative_link_callback( "css/style.css", {"relative_path": "docs/index.md"}, destination_root, ) value.should.equal(u'../css/style.css')
def test_index_has_correct_links_for_md_files(context): "The index file should have correct html links for markdown files" project = Project.discover(context.project_path) theme = Theme.load_from_path( LOCAL_FILE('sandbox_simple', 'themes', 'turbo')) destination = Generator(project, theme) generated = sorted(destination.persist(context.output_path), key=sort_files) generated.should.have.length_of(5) index = generated[0] index.should.contain('index') html = open(index).read() dom = lhtml.fromstring(html) links = dom.cssselect('a') links.should.have.length_of(3) l1, l2, l3 = links l1.attrib.should.have.key('href').being.equal('#python-tutorial') l2.attrib.should.have.key('href').being.equal('./docs/output.html') l3.attrib.should.have.key('href').being.equal('./docs/strings.html')
def test_persist_when_does_not_exist(exists, io, os): ("Generator#persist(destination_path)" " when path already does not exist") exists.return_value = False theme = Mock() theme.index = {'static_path': '/themes/cool'} project = Mock() project.generate.return_value = [{ "type": "tree", "path": "/simple/", "relative_path": "./", }, { "type": "blob", "html": "<h1>Foobar</h1>", "markdown": "# Foobar\n", "path": "/simple/index.md", "relative_path": "./index.md", }] engine = Generator(project, theme) generated = engine.persist("/output") generated.should.equal(["/output/index.html"]) os.makedirs.assert_called_once_with("/output")
def test_second_level_has_correct_links_for_md_files(context): "The second_level file should have correct html links for markdown files" project = Project.discover(context.project_path) theme = Theme.load_from_path( LOCAL_FILE('sandbox_simple', 'themes', 'simple-index')) destination = Generator(project, theme) generated = sorted(destination.persist(context.output_path), key=sort_files) generated.should.have.length_of(5) second_level = generated[1] second_level.should.contain('docs/output.html') html = open(second_level).read() dom = lhtml.fromstring(html) links = dom.cssselect('a.index') links.should.have.length_of(4) l1, l2, l3, l4 = links l1.attrib.should.have.key('href').being.equal('../index.html') l2.attrib.should.have.key('href').being.to.match('./\w+.html') l3.attrib.should.have.key('href').being.to.match('./\w+.html') l4.attrib.should.have.key('href').being.equal('./even/deeper/item.html')
def test_rename_markdown_file(): ("Generator#rename_markdown_filename(path)") project = Mock() theme = Mock() gen = Generator(project, theme) gen.rename_markdown_filename("/bb/foo.md").should.equal('/bb/foo.html')
def test_get_levels(): ("Generator#get_levels(link)") project = Mock() theme = Mock() gen = Generator(project, theme) fixed, levels = gen.get_levels('../../buz.py') fixed.should.equal('buz.py') levels.should.equal(['..', '..'])
def main(): args = parser.parse_args() if not args.PORCELAIN: from markment.plugins import couleur_output else: from markment.plugins import porcelain_output if args.SITEMAP_PREFIX: from markment.plugins import sitemap if args.AUTOINDEX: from markment.plugins import autoindex if args.JUST_LIST_THEMES: if not args.PORCELAIN: print LOGO return list_themes(args.PORCELAIN) project_path = abspath(args.SOURCE) output_path = abspath(args.OUTPUT) before.all.shout(args) project = Project.discover(project_path) if exists(join(args.THEME, 'markment.yml')): theme = Theme.load_from_path(args.THEME) elif os.sep not in args.THEME: try: theme = Theme.load_by_name(args.THEME) except InvalidThemePackage: print "." * 20 print "\033[1;32m Invalid theme name\033[0m" print "." * 20 print print "\033[1;31mMarkment doesn't have a builtin theme called \033[0m'{0}'".format( args.THEME) print return list_themes() else: print "Invalid theme name:", args.THEME print return list_themes() if args.RUNSERVER: print "\033[1;32mMarkment is serving the documentation " print "under \033[1;31m'./{0}' \033[1;32mdynamically\033[0m".format( relpath(project_path)) print print "\033[1;33mNow you can just change whatever files you want" print "and refresh your browser\033[0m" print return server(project_path, theme).run(debug=True, use_reloader=False) destination = Generator(project, theme) generated = destination.persist(output_path, gently=True) after.all.shout(args, project, theme, generated)
def test_relative_link_callback_with_markdown(exists): ("Generator#relative_link_callback(original_link, current_document_info," " destination_root) with a markdown file") theme = Mock() project = Mock() project.node = FakeNode("/coolproject/") engine = Generator(project, theme) destination_root = FakeNode("/output") value = engine.relative_link_callback( "../docs/index.md", {"relative_path": "docs/faq.md"}, destination_root, ) value.should.equal('./index.html')
def test_generate_files(context): "Markment should find files and generate them" project = Project.discover(context.project_path) theme = Theme.load_by_name('touch-of-pink') destination = Generator(project, theme) generated = sorted(destination.persist(context.output_path), key=sort_files) generated.should.be.a(list) map(relpath, generated).should.equal( map(relpath, [ LOCAL_FILE('output/index.html'), LOCAL_FILE('output/assets/style.css'), LOCAL_FILE('output/docs/output.html'), LOCAL_FILE('output/docs/strings.html'), LOCAL_FILE('output/img/logo.png'), LOCAL_FILE('output/assets/img/favicon.png'), LOCAL_FILE('output/docs/even/deeper/item.html'), ]))
def test_persist_when_exists(io, exists): ("Generator#persist(destination_path)" " when path already exists") theme = Mock() theme.index = {'static_path': '/themes/cool'} project = Mock() project.generate.return_value = [{ "type": "blob", "html": "<h1>Foobar</h1>", "markdown": "# Foobar\n", "path": "/simple/index.md", "relative_path": "./index.md", }] engine = Generator(project, theme) generated = engine.persist("/output") generated.should.equal(["/output/index.html"])
def test_static_url_callback_with_asset(exists): ("Generator#static_url_callback(original_link, current_document_info," " destination_root) finding an asset") # TODO: this test should raise an exception project = Mock() theme = Mock() theme.node = FakeNode("/coolproject/") engine = Generator(project, theme) destination_root = FakeNode("/output") value = engine.static_url_callback( "css/style.css", {"relative_path": "faq.md"}, destination_root, ) value.should.equal("./css/style.css")
def test_persist_with_files_to_copy_from_theme(Node, exists, io, os, shutil, Cloner): ("Generator#persist(destination_path)" " with files to copy from the theme") os.sep = '/' Node.side_effect = FakeNode exists.return_value = False theme = Mock() theme.index = {'static_path': '/themes/cool'} project = Mock() project.node = FakeNode("/simple/") project.node.find = Mock(return_value=None) theme.node = FakeNode("/themes/cool") project.generate.return_value = [{ "type": "tree", "path": "/simple/", "relative_path": "./", }, { "type": "blob", "html": "<h1>Foobar</h1>", "markdown": "# Foobar\n", "path": "/simple/index.md", "relative_path": "./index.md", }] engine = Generator(project, theme) engine.files_to_copy = [ "style.css", "logo.png", ] generated = engine.persist("/output") generated.should.equal([ '/output/./index.html', '/output/style.css', '/output/logo.png', ])
def test_relative_link_callback_with_asset_not_found(exists): ("Generator#relative_link_callback(original_link, current_document_info," " destination_root) with asset not found") # TODO: this test should raise an exception theme = Mock() project = Mock() project.node = FakeNode("/coolproject/") project.node.find = Mock(return_value=None) engine = Generator(project, theme) destination_root = FakeNode("/output") value = engine.relative_link_callback( "../css/style.css", {"relative_path": "css/faq.md"}, destination_root, ) value.should.equal('../css/style.css')
def test_static_url_callback_with_asset_with_levels(exists): ("Generator#static_url_callback(original_link, current_document_info," " destination_root) with asset not found [\033[31mthere is a TODO here\033[0m]" ) # TODO: this test should raise an exception project = Mock() theme = Mock() theme.node = FakeNode("/coolproject/") engine = Generator(project, theme) destination_root = FakeNode("/output") value = engine.static_url_callback( "help.md", {"relative_path": "docs/index.md"}, destination_root, ) value.should.equal("../help.html")
def test_static_url_callback_with_asset_not_found(exists): ("Generator#static_url_callback(original_link, current_document_info," " destination_root) with asset not found") # TODO: this test should raise an exception project = Mock() theme = Mock() theme.node = FakeNode("/coolproject/") theme.node.find = Mock(return_value=None) engine = Generator(project, theme) destination_root = FakeNode("/output") engine.static_url_callback.when.called_with( "style.css", { "relative_path": "css/faq.md" }, destination_root, ).should.throw(IOError, "BOOM, could not find style.css anywhere")
def test_persist_with_files_to_copy_missing(Node, exists, io, os, shutil, Cloner): ("Generator#persist(destination_path,gently=False)" " with files to copy from the theme") os.sep = '/' Node.side_effect = FakeNode exists.return_value = True theme = Mock() theme.index = {'static_path': '/themes/cool'} project = Mock() project.node = FakeNode("/simple/") project.node.find = Mock(return_value=None) theme.node = FakeNode("/themes/cool") theme.node.find = Mock(return_value=None) project.generate.return_value = [{ "type": "tree", "path": "/simple/", "relative_path": "./", }, { "type": "blob", "html": "<h1>Foobar</h1>", "markdown": "# Foobar\n", "path": "/simple/index.md", "relative_path": "./index.md", }] engine = Generator(project, theme) engine.files_to_copy = [ "style.css", "logo.png", ] engine.persist.when.called_with("/output").should.throw( IOError, "The documentation refers to style.css, logo.png but they doesn't exist anythere" )
def test_relative_link_callback_with_markdown_not_found(exists): ("Generator#relative_link_callback(original_link, current_document_info," " destination_root) with a markdown not found [\033[2;31mthere is a TODO here\033[0m]" ) # TODO: this test should raise an exception theme = Mock() project = Mock() project.node = FakeNode("/coolproject/") project.node.find = Mock(return_value=None) engine = Generator(project, theme) destination_root = FakeNode("/output") value = engine.relative_link_callback( "../docs/index.md", {"relative_path": "docs/faq.md"}, destination_root, ) value.should.equal('../docs/index.md')
def test_index_file(context): "The index file should have the assets pointing to the right path" project = Project.discover(context.project_path) theme = Theme.load_by_name('touch-of-pink') destination = Generator(project, theme) generated = sorted(destination.persist(context.output_path), key=lambda x: len(x.split(os.sep))) generated.should.have.length_of(7) index = generated[0] html = open(index).read() dom = lhtml.fromstring(html) links = dom.cssselect('link.theme-asset') links.should.have.length_of(1) style = links[0] style.attrib.should.have.key("href").being.equal("./assets/style.css")
def test_index_images_point_to_right_place(context): "The index file should have correct html paths to images" project = Project.discover(context.project_path) theme = Theme.load_by_name('touch-of-pink') destination = Generator(project, theme) generated = sorted(destination.persist(context.output_path), key=sort_files) generated.should.have.length_of(7) index = generated[0] index.should.contain('index') html = open(index).read() dom = lhtml.fromstring(html) images = dom.cssselect('img') images.should.have.length_of(1) img = images[0] img.attrib.should.have.key('src').being.equal("./img/logo.png")
def test_second_level_file(context): "The second_level file should have the assets pointing to the right path" project = Project.discover(context.project_path) theme = Theme.load_by_name('touch-of-pink') destination = Generator(project, theme) generated = sorted(destination.persist(context.output_path), key=sort_files) generated.should.have.length_of(7) second_level = generated[2] second_level.should.contain('docs/output.html') html = open(second_level).read() dom = lhtml.fromstring(html) links = dom.cssselect('link.theme-asset') links.should.have.length_of(1) style = links[0] style.attrib.should.have.key("href").being.equal("../assets/style.css")
def test_second_level_stylesheets_point_to_right_place(context): "The second_level file should have correct html paths to stylesheets" project = Project.discover(context.project_path) theme = Theme.load_by_name('touch-of-pink') destination = Generator(project, theme) generated = sorted(destination.persist(context.output_path), key=sort_files) generated.should.have.length_of(7) second_level = generated[2] second_level.should.contain('docs/output.html') html = open(second_level).read() dom = lhtml.fromstring(html) stylesheets = dom.cssselect('link.theme-asset') stylesheets.should.have.length_of(1) img = stylesheets[0] img.attrib.should.have.key('href').being.equal("../assets/style.css")
def test_first_level_file(context): "The first level file should have the assets pointing to the right path" project = Project.discover(context.project_path) theme = Theme.load_from_path(context.theme_path) destination = Generator(project, theme) generated = sorted(filter_html(destination.persist(context.output_path)), key=lambda x: len(x.split(os.sep))) generated.should.have.length_of(2) first_level = generated[0] first_level.should.contain('index.html') html = open(first_level).read() dom = lhtml.fromstring(html) links = dom.cssselect('link.theme-asset') links.should.have.length_of(1) style = links[0] style.attrib.should.have.key("href").being.equal( "./assets/stylesheets/stylesheet.css")