diff options
| -rw-r--r-- | markdown_link_style/_version.py | 2 | ||||
| -rw-r--r-- | markdown_link_style/logging.py | 50 | ||||
| -rw-r--r-- | mdl_style.py | 177 | ||||
| -rw-r--r-- | tests/__init__.py | 0 | ||||
| -rw-r--r-- | tests/data/autolink_00-expected.md | 3 | ||||
| -rw-r--r-- | tests/data/autolink_00.md | 3 | ||||
| -rw-r--r-- | tests/data/footnote_link_style_00-expected.md | 50 | ||||
| -rw-r--r-- | tests/data/footnote_link_style_00.md | 45 | ||||
| -rw-r--r-- | tests/data/inline_link_style_00-expected.md | 26 | ||||
| -rw-r--r-- | tests/data/inline_link_style_00.md | 33 | ||||
| -rw-r--r-- | tests/test_mdl_style.py | 44 | 
11 files changed, 428 insertions, 5 deletions
| diff --git a/markdown_link_style/_version.py b/markdown_link_style/_version.py index 6ae8753..1562223 100644 --- a/markdown_link_style/_version.py +++ b/markdown_link_style/_version.py @@ -18,4 +18,4 @@  #   along with markdown-link-style (see COPYING).  If not, see  #   <http://www.gnu.org/licenses/>. -__version__ = '0.1.0.dev0' +__version__ = '0.1.0.dev1' diff --git a/markdown_link_style/logging.py b/markdown_link_style/logging.py new file mode 100644 index 0000000..2395c40 --- /dev/null +++ b/markdown_link_style/logging.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# +#    Copyright © 2017 markdown-link-style contributors. See CONTRIBUTORS. +# +#    This file is part of markdown-link-style. +# +#   markdown-link-style is free software: you can redistribute it +#   and/or modify it under the terms of the GNU General Public License +#   as published by the Free Software Foundation, either version 3 of +#   the License, or (at your option) any later version. +# +#   markdown-link-style is distributed in the hope that it will be +#   useful, but WITHOUT ANY WARRANTY; without even the implied +#   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +#   See the GNU General Public License for more details. +# +#   You should have received a copy of the GNU General Public License +#   along with markdown-link-style (see COPYING).  If not, see +#   <http://www.gnu.org/licenses/>. + +import logging + +class MDLSLogger(object): +    """Logging utility for modules in markdown-link-style. + +    """ + +    def __init__(self, name): +        self.logger = logging.getLogger(name) + +    def debug(msg, *args, **kwargs): +        self.logger.debug(msg, *args, **kwargs) + +    def info(msg, *args, **kwargs): +        self.logger.info(msg, *args, **kwargs) + +    def warning(msg, *args, **kwargs): +        self.logger.warning(msg, *args, **kwargs) + +    def error(msg, *args, **kwargs): +        self.logger.error(msg, *args, **kwargs) + +    def critical(msg, *args, **kwargs): +        self.logger.critical(msg, *args, **kwargs) + +    def log(msg, *args, **kwargs): +        self.logger.log(msg, *args, **kwargs) + +    def exception(msg, *args, **kwargs): +        self.logger.exception(msg, *args, **kwargs) diff --git a/mdl_style.py b/mdl_style.py index 44cafab..c8573ed 100644 --- a/mdl_style.py +++ b/mdl_style.py @@ -18,5 +18,180 @@  #   along with markdown-link-style (see COPYING).  If not, see  #   <http://www.gnu.org/licenses/>. +import argparse + +from mistune import BlockLexer, InlineLexer, Renderer, Markdown + +from markdown_link_style.logging import MDLSLogger +from markdown_link_style._version import __version__ + +# Initialize logger for this module. +logger = MDLSLogger(__name__) + + +class LSBlockLexer(BlockLexer): +    """Link Style Block Lexer. + +    """ + +    def __init__(self, rules=None, **kwargs): +        super(LSBlockLexer, self).__init__(rules, **kwargs) + +        # Only parse these block rules. +        self.default_rules = ['def_links', 'paragraph', 'text'] + + +class LSInlineLexer(InlineLexer): +    """Link Style Inline Lexer. + +    """ + +    def __init__(self, renderer, rules=None, **kwargs): +        super(LSInlineLexer, self).__init__(renderer, rules, **kwargs) + +        # Only parse these inline rules +        self.default_rules = ['autolink', 'link', 'reflink', 'text'] + + +class LSRenderer(Renderer): +    """Link Style Renderer. + +    """ + +    def __init__(self, **kwargs): +        super(LSRenderer, self).__init__(**kwargs) + +        # Link style is either 'inline' or 'footnote'. +        self.link_style = self.options.get('link_style') + +        self.fn_lnk_num = 0 # footnote style link number +        self.fn_lnk_refs = [] # footnote style link refs + +    def autolink(self, link, is_email=False): +        return '<{}>'.format(link) + +    def paragraph(self, text): +        p = text +        fn_refs = self._pop_fn_refs() + +        if fn_refs: +            # Insert footnote refs, if any, after paragraph. +            return '\n{}\n\n{}'.format(p, fn_refs) + +        return '\n{}\n'.format(p) + +    def link(self, link, title, text): +        link_text = self._stylize_link(link, title, text) +        return link_text + +    def _stylize_link(self, link, title, text): +        if self.link_style == 'inline': +            return self._gen_inline_link(link, title, text) +        else: +            return self._gen_footnote_link(link, title, text) + +    def _gen_inline_link(self, link, title, text): +        if title: +            return '[{}]({} "{}")'.format(text, link, title) +        else: +            return '[{}]({})'.format(text, link) + +    def _gen_footnote_link(self, link, title, text): +        fn_num = self._st_fn_ref(link, title) +        return '[{}][{}]'.format(text, fn_num) + +    def _st_fn_ref(self, link, title): +        """Store footnote link reference. + +        """ +        fn_num = self._get_fn_lnk_num() + +        if title: +            fn_ref = '[{}]: {} ({})'.format(fn_num, link, title) +        else: +            fn_ref = '[{}]: {}'.format(fn_num, link) + +        self.fn_lnk_refs.append(fn_ref) +        return fn_num + +    def _get_fn_lnk_num(self): +        """Get footnote link number. + +        """ +        fn_num = self.fn_lnk_num +        self.fn_lnk_num = self.fn_lnk_num + 1 +        return fn_num + +    def _pop_fn_refs(self): +        """Pop all footnote refs and return them as a string. + +        """ +        refs = '' + +        for ref in self.fn_lnk_refs: +            refs += '{}\n'.format(ref) + +        # empty fn_lnk_refs +        self.fn_lnk_refs = [] + +        return refs + + +class LSMarkdown(Markdown): +    """Link Style Markdown parser. +    """ + +    def __init__(self, renderer=None, inline=None, block=None, **kwargs): +        link_style = kwargs.get('link_style') or 'inline' + +        if not renderer: +            renderer = LSRenderer(link_style=link_style) +        if not inline: +            inline = LSInlineLexer(renderer) +        if not block: +            block = LSBlockLexer() + +        super(LSMarkdown, self).__init__(renderer, inline, block, **kwargs) + +    def parse(self, text): +        out = super(LSMarkdown, self).parse(text) + +        return out.lstrip('\n') + + +class LinkStyler(object): +    """Markdown Link Styler. + +    """ + +    def __init__(self, link_style='inline'): +        self.style = link_style + +    def __call__(self, file_): +        return self._link_stylize(file_) + +    def _link_stylize(self, file_): +        text = file_.read() +        md = LSMarkdown(link_style=self.style) + +        return md(text) + + +def _mdl_stylize(args): +    ls = LinkStyler(args.link_style) +    print(ls(args.file), end='') + + +def _get_args(): +    parser = argparse.ArgumentParser() +    parser.add_argument('--version', action='version', version=__version__) +    parser.add_argument('link_style', choices=['inline', 'footnote'], +                        help="Markdown Link style.") +    parser.add_argument('file', type=argparse.FileType('r'), +                        help="Path to Markdown file.") +    return parser.parse_args() + +  def main(): -    print('md-lnk-style main function') +    args = _get_args() +    _mdl_stylize(args) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/__init__.py diff --git a/tests/data/autolink_00-expected.md b/tests/data/autolink_00-expected.md new file mode 100644 index 0000000..0e83936 --- /dev/null +++ b/tests/data/autolink_00-expected.md @@ -0,0 +1,3 @@ +Information about the GNU project is available at https://gnu.org. + +GNU Guix <https://gnu.org/s/guix> is a GNU project. diff --git a/tests/data/autolink_00.md b/tests/data/autolink_00.md new file mode 100644 index 0000000..0e83936 --- /dev/null +++ b/tests/data/autolink_00.md @@ -0,0 +1,3 @@ +Information about the GNU project is available at https://gnu.org. + +GNU Guix <https://gnu.org/s/guix> is a GNU project. diff --git a/tests/data/footnote_link_style_00-expected.md b/tests/data/footnote_link_style_00-expected.md new file mode 100644 index 0000000..8ebebb7 --- /dev/null +++ b/tests/data/footnote_link_style_00-expected.md @@ -0,0 +1,50 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eu +sapien vestibulum, dignissim ligula ac, porttitor tortor. Nam +fringilla turpis vitae ligula vehicula bibendum. Aliquam tristique, +dolor sed auctor sagittis, sapien augue dapibus lectus, eu consequat +lectus sapien ut nibh. [Mauris][0] placerat +pulvinar risus nec viverra. Sed ac mi nec tortor consequat eleifend ac +a velit. Phasellus tincidunt neque sit amet sapien commodo +finibus. Praesent id blandit turpis. Vivamus felis metus, iaculis vel +nisl vitae, [molestie commodo][1] +lectus. Cras ut augue lacinia, imperdiet lorem quis, [imperdiet +erat][2]. Integer sed urna ullamcorper, semper nibh non, egestas +sem. Pellentesque a tincidunt leo, eget vehicula tortor. Curabitur nec +augue eget urna maximus molestie. + +[0]: https://maur.is/blag +[1]: https://molest.ie/commodo/ +[2]: http://imperdi.et/erat.html + +In ultricies augue in nunc pellentesque, congue egestas velit +sodales. Aenean ac gravida lacus, ut mattis lorem. Aenean auctor eros +et odio maximus, at tempus nunc euismod. Nulla maximus libero ut nulla +malesuada posuere at at quam. Ut luctus facilisis ipsum a +venenatis. Aliquam quis sapien at tellus tincidunt ullamcorper in sed +arcu. [Phasellus sodales odio nec][3] +feugiat feugiat. Etiam justo eros, cursus egestas lacus et, tristique +ullamcorper neque. Duis quis bibendum mi, ut ornare purus. Suspendisse +mollis fermentum est. Vestibulum ac pellentesque ipsum. Maecenas +rutrum nunc ac elit bibendum, in vehicula risus egestas. Vestibulum +ante ipsum primis in [faucibus orci][4] +luctus et ultrices posuere cubilia Curae; Suspendisse ut nisi vel enim +volutpat cursus. Curabitur vitae tellus dictum, placerat tellus sit +amet, volutpat augue. Nam ut dolor sed ipsum lacinia tincidunt a et +dolor. + +[3]: http://phasell.us/wiki/page.html +[4]: http://faucib.us/projects.html + +Proin quis eleifend mi. Curabitur sed venenatis odio, eu sodales +neque. Integer ultrices ullamcorper dui, in finibus enim tristique +eget. Nunc ac arcu fermentum, dapibus ex congue, tincidunt metus. Sed +convallis, erat non eleifend feugiat, orci risus placerat tellus, eu +tincidunt nibh orci quis magna. Nullam efficitur ac libero dignissim +sodales. [Nullam massa eros][5], vestibulum id egestas id, +convallis vitae ex. Maecenas vitae metus finibus, hendrerit arcu a, +scelerisque quam. Suspendisse ut neque dignissim, egestas libero at, +varius est. Sed nulla nulla, maximus in nunc in, dignissim interdum +augue. Aliquam mollis pellentesque lorem. Nulla iaculis luctus +ultrices. + +[5]: http://null.am/articles/massa-eros.html diff --git a/tests/data/footnote_link_style_00.md b/tests/data/footnote_link_style_00.md new file mode 100644 index 0000000..298bd1e --- /dev/null +++ b/tests/data/footnote_link_style_00.md @@ -0,0 +1,45 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eu +sapien vestibulum, dignissim ligula ac, porttitor tortor. Nam +fringilla turpis vitae ligula vehicula bibendum. Aliquam tristique, +dolor sed auctor sagittis, sapien augue dapibus lectus, eu consequat +lectus sapien ut nibh. [Mauris](https://maur.is/blag) placerat +pulvinar risus nec viverra. Sed ac mi nec tortor consequat eleifend ac +a velit. Phasellus tincidunt neque sit amet sapien commodo +finibus. Praesent id blandit turpis. Vivamus felis metus, iaculis vel +nisl vitae, [molestie commodo](https://molest.ie/commodo/) +lectus. Cras ut augue lacinia, imperdiet lorem quis, [imperdiet +erat][imper]. Integer sed urna ullamcorper, semper nibh non, egestas +sem. Pellentesque a tincidunt leo, eget vehicula tortor. Curabitur nec +augue eget urna maximus molestie. + +[imper]: http://imperdi.et/erat.html + +In ultricies augue in nunc pellentesque, congue egestas velit +sodales. Aenean ac gravida lacus, ut mattis lorem. Aenean auctor eros +et odio maximus, at tempus nunc euismod. Nulla maximus libero ut nulla +malesuada posuere at at quam. Ut luctus facilisis ipsum a +venenatis. Aliquam quis sapien at tellus tincidunt ullamcorper in sed +arcu. [Phasellus sodales odio nec](http://phasell.us/wiki/page.html) +feugiat feugiat. Etiam justo eros, cursus egestas lacus et, tristique +ullamcorper neque. Duis quis bibendum mi, ut ornare purus. Suspendisse +mollis fermentum est. Vestibulum ac pellentesque ipsum. Maecenas +rutrum nunc ac elit bibendum, in vehicula risus egestas. Vestibulum +ante ipsum primis in [faucibus orci](http://faucib.us/projects.html) +luctus et ultrices posuere cubilia Curae; Suspendisse ut nisi vel enim +volutpat cursus. Curabitur vitae tellus dictum, placerat tellus sit +amet, volutpat augue. Nam ut dolor sed ipsum lacinia tincidunt a et +dolor. + +Proin quis eleifend mi. Curabitur sed venenatis odio, eu sodales +neque. Integer ultrices ullamcorper dui, in finibus enim tristique +eget. Nunc ac arcu fermentum, dapibus ex congue, tincidunt metus. Sed +convallis, erat non eleifend feugiat, orci risus placerat tellus, eu +tincidunt nibh orci quis magna. Nullam efficitur ac libero dignissim +sodales. [Nullam massa eros][nullam], vestibulum id egestas id, +convallis vitae ex. Maecenas vitae metus finibus, hendrerit arcu a, +scelerisque quam. Suspendisse ut neque dignissim, egestas libero at, +varius est. Sed nulla nulla, maximus in nunc in, dignissim interdum +augue. Aliquam mollis pellentesque lorem. Nulla iaculis luctus +ultrices. + +[nullam]: http://null.am/articles/massa-eros.html diff --git a/tests/data/inline_link_style_00-expected.md b/tests/data/inline_link_style_00-expected.md new file mode 100644 index 0000000..c76751c --- /dev/null +++ b/tests/data/inline_link_style_00-expected.md @@ -0,0 +1,26 @@ +Mauris sit amet urna lacus. Sed id sodales urna. Phasellus accumsan +sapien a pellentesque ultrices. Pellentesque in semper leo, quis +ornare ipsum. Phasellus suscipit arcu ac ipsum tristique +ultrices. [Aliquam erat](http://www.aliquam/erat/) volutpat. Interdum et malesuada +fames ac ante ipsum primis in faucibus. [Proin aliquam](http://pro.in/projects/aliquam) est ut +nulla placerat, vitae aliquet velit dictum. Sed quis justo eget sem +suscipit pulvinar. Nullam nec accumsan dolor. + +Nam aliquam orci id leo ornare tristique. Nam pretium suscipit justo +vitae pretium. Vivamus tortor ligula, fringilla in pretium at, rutrum +et risus. Fusce in purus arcu. Interdum et malesuada fames ac ante +ipsum primis in faucibus. Suspendisse lobortis cursus imperdiet. Fusce +imperdiet risus non erat eleifend condimentum. Sed venenatis augue eu +enim tempus pharetra. [Maecenas](https://maecenas) in velit ut arcu +iaculis facilisis ut a orci. Sed malesuada pulvinar aliquam. Quisque +elementum iaculis felis, non [commodo turpis auctor](http://commo.do/~turpis/articles/auctor.html) +at. Vestibulum at mollis neque. + +Sed ullamcorper risus luctus, placerat diam ac, eleifend purus. Cras +laoreet, est vel pretium interdum, turpis odio interdum sem, eu +consequat sem urna in leo. [Sed egestas massa orci](https://sed.eg/estas/blag/2017/02/18/mass-orci.html), id ultrices +ligula accumsan vel. Phasellus sem orci, pretium at felis quis, tempus +feugiat magna. Donec tortor leo, porttitor ac scelerisque vitae, +vehicula et elit. Pellentesque in venenatis turpis. Lorem ipsum dolor +sit amet, consectetur adipiscing elit. Integer dui quam, tempus et +felis auctor, aliquet elementum magna. diff --git a/tests/data/inline_link_style_00.md b/tests/data/inline_link_style_00.md new file mode 100644 index 0000000..15e2d10 --- /dev/null +++ b/tests/data/inline_link_style_00.md @@ -0,0 +1,33 @@ +Mauris sit amet urna lacus. Sed id sodales urna. Phasellus accumsan +sapien a pellentesque ultrices. Pellentesque in semper leo, quis +ornare ipsum. Phasellus suscipit arcu ac ipsum tristique +ultrices. [Aliquam erat][aliquam] volutpat. Interdum et malesuada +fames ac ante ipsum primis in faucibus. [Proin aliquam][proin] est ut +nulla placerat, vitae aliquet velit dictum. Sed quis justo eget sem +suscipit pulvinar. Nullam nec accumsan dolor. + +[aliquam]: http://www.aliquam/erat/ +[proin]: http://pro.in/projects/aliquam + +Nam aliquam orci id leo ornare tristique. Nam pretium suscipit justo +vitae pretium. Vivamus tortor ligula, fringilla in pretium at, rutrum +et risus. Fusce in purus arcu. Interdum et malesuada fames ac ante +ipsum primis in faucibus. Suspendisse lobortis cursus imperdiet. Fusce +imperdiet risus non erat eleifend condimentum. Sed venenatis augue eu +enim tempus pharetra. [Maecenas](https://maecenas) in velit ut arcu +iaculis facilisis ut a orci. Sed malesuada pulvinar aliquam. Quisque +elementum iaculis felis, non [commodo turpis auctor][commodo] +at. Vestibulum at mollis neque. + +[commodo]: http://commo.do/~turpis/articles/auctor.html + +Sed ullamcorper risus luctus, placerat diam ac, eleifend purus. Cras +laoreet, est vel pretium interdum, turpis odio interdum sem, eu +consequat sem urna in leo. [Sed egestas massa orci][sed], id ultrices +ligula accumsan vel. Phasellus sem orci, pretium at felis quis, tempus +feugiat magna. Donec tortor leo, porttitor ac scelerisque vitae, +vehicula et elit. Pellentesque in venenatis turpis. Lorem ipsum dolor +sit amet, consectetur adipiscing elit. Integer dui quam, tempus et +felis auctor, aliquet elementum magna. + +[sed]: https://sed.eg/estas/blag/2017/02/18/mass-orci.html diff --git a/tests/test_mdl_style.py b/tests/test_mdl_style.py index 487ff3a..07f9480 100644 --- a/tests/test_mdl_style.py +++ b/tests/test_mdl_style.py @@ -18,14 +18,52 @@  #   along with markdown-link-style (see COPYING).  If not, see  #   <http://www.gnu.org/licenses/>. +from mistune import Renderer, Markdown  from nose.tools import * +from pkg_resources import resource_string  from mdl_style import * -class TestMdlStyle(object): + +def _get_data(f): +    rs = resource_string(__name__, '/'.join(['data', f])) +    return rs.decode() + +class TestLSRendererIL(object): +    """Test class for mdl_style.LSRenderer inline link style. + +    """ + +    def setup(self): +        self.md = LSMarkdown(link_style='inline') + +    def test_autolink_00(self): +        d = _get_data('autolink_00.md') +        d_expected = _get_data('autolink_00-expected.md') +        assert_equals(self.md(d), d_expected) + + +    def test_link_footnote_to_inline_style_conversion_00(self): +        d = _get_data('inline_link_style_00.md') +        expected_result = _get_data('inline_link_style_00-expected.md') +        assert_equal(self.md(d), expected_result) + +    def teardown(self): +        pass + + +class TestLSRendererFN(object): +    """Test class for mdl_style.LSRenderer footnote link style. + +    """      def setup(self): -        print('running setup...') +        self.md = LSMarkdown(link_style='footnote') + +    def test_link_inline_to_footnote_style_conversion_00(self): +        d = _get_data('footnote_link_style_00.md') +        expected_result = _get_data('footnote_link_style_00-expected.md') +        assert_equal(self.md(d), d_expected)      def teardown(self): -        print('running teardown...') +        pass | 
