Exemple #1
0
def test_replace():
    """
    Includes testing link creation.
    """
    parts = {
        'index':
        trim("""
            Test document

            - The Simple Test
            - The More Complex Test
            """),
        'test':
        trim("""
            This is a @[simple] test.

            This is a @[-more complex] test.
            """),
    }

    outline = Outline(parts, default_counters())
    placeholders = CrossReferences(parts, outline)

    tokenized = placeholders.insert(parts)
    html_parts = placeholders.replace(tokenized)
    out = html_parts['test']

    assert 'The Simple Test' in out
    assert '&sect;2' in out  # <-- complex uses shorthand
    assert 'the-simple-test' in out
    assert 'the-more-complex-test' in out
Exemple #2
0
def test_is_index_page():
    page = trim("""
        Title

        OK
        """)
    assert not is_index_part(page)
    page = trim("""
        Title

        $ AUTHOR = Author Name

        OK
        """)
    assert is_index_part(page)
    page = trim("""
        Title

        OK

        - Part One
        - - Part One Aye
        - Part Two
        """)
    assert is_index_part(page)
Exemple #3
0
def test_split_to_array():
    "Note one_line behaviour in split_to_array."
    arg = trim("""

        = x
        = y
        y
        = z

        """)
    out = [('=', 'x'), ('=', 'y y'), ('=', 'z')]
    assert split_to_array(arg, '=') == out

    arg = trim("""
        + Heading
        """)
    out = [('+', 'Heading')]
    assert split_to_array(arg, '.%#+') == out

    arg = trim("""

        . x
        . y
        .
        .
        . z

        """)
    out = [('.', 'x'), ('.', 'y'), ('.', ''), ('.', ''), ('.', 'z')]
    assert split_to_array(arg, '.') == out
Exemple #4
0
def test_iterate_parts():
    text = trim("""
            Chapter {}

            Text goes here.
            """)
    index = trim("""
            Title

            - Chapter One
            - - Chapter One Aye
            - Chapter Two
            """)
    arg = {
        'index': index,
        'chapter-one': text.format('One'),
        'chapter-one-aye': text.format('One Aye'),
        'chapter-two': text.format('Two')
    }
    gen = iterate_parts(arg)
    assert next(gen) == (['0'], 'Title', 'index', index)
    assert next(gen) == (['1'], 'Chapter One', 'chapter-one',
                         text.format('One'))
    assert next(gen) == (['1', 'a'], 'Chapter One Aye', 'chapter-one-aye',
                         text.format('One Aye'))
    assert next(gen) == (['2'], 'Chapter Two', 'chapter-two',
                         text.format('Two'))
Exemple #5
0
def test_basic_replacements():
    """
    @todo: There is an occassional thus-far-non-reproducable issue with DEMO
    blocks in the editor; they will sometimes wrap into e.g. ...

    DEMO === + Headline

    ... in cases like the one below. It's caused by the DEMO placeholders not
    matching their blocks, and the DEMO line being taken as the start of a
    paragraph and rewrapped accordingly.
    """
    settings = Settings()
    demo = Demo(settings)
    parts = {
        'test':
        trim("""
        Test

        DEMO ===
        TEST
        ===

        Test

        ~

        DEMO ===
        + Headline

        > Blockquote
        ===

        Test
        """)
    }
    tokenized = demo.insert(parts)
    expected = {
        'test':
        trim("""
        Test

        %sdemo:1%s

        Test

        ~

        %sdemo:2%s

        Test
        """) % (DELIMITER, DELIMITER, DELIMITER, DELIMITER)
    }
    assert expected == tokenized

    decorated = demo.replace(tokenized)
    __ = html.fromstring(decorated['test'])
    assert __.xpath("count(//div[@class='wiki-demo space'])") == 2
    assert __.xpath("//pre[contains(., Test)]")
    assert __.xpath("//article/section")
Exemple #6
0
    def decorate(self, pattern, part_slug):
        """
        When we process a new demo block it needs to be assigned a unique
        id_prefix as its config:document name. Micro chance of a collision;
        maybe replace with a singleton to track random IDs in use.
        """
        self.settings.set('config:document', random_slug('demo'))

        wiki = Wiki(self.settings)
        options = match_demo_options(pattern)
        fragment = ('index' not in options)
        part_slug = 'index' if 'index' in options else random_slug('demo-')
        lines = pattern.splitlines()
        source = "\n".join(lines[1:-1])
        output = wiki.process(None, None, {part_slug: source}, fragment)

        env = Environment(autoescape=True)
        if 'wide' in options:
            tpl = env.from_string(
                trim("""
                <div class="wiki-demo-wide space">
                    <table>
                        <tbody>
                            <tr>
                                <td>
                                    <pre>{{ source|safe }}</pre>
                                </td>
                            </tr>
                            <tr>
                                <td class="wiki-demo-output">
                                    {{ output|safe }}
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            """))
        else:
            tpl = env.from_string(
                trim("""
                <div class="wiki-demo space">
                    <table>
                        <tbody>
                            <tr>
                                <td width="50%">
                                    <pre>{{ source|safe }}</pre>
                                </td>
                                <td>&nbsp;</td>
                                <td width="48%" class="wiki-demo-output">
                                    {{ output|safe }}
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            """))

        return tpl.render(source=escape(source), output=output)
Exemple #7
0
def test_trim():
    assert trim("\n   x\n   x\n") == 'x\nx'
    assert trim("\n   x\n    x\n") == 'x\n x'
    doc = """

        This is a test doc!

    """
    assert trim(doc) == 'This is a test doc!'
Exemple #8
0
def test_replace():
    defaults = {'default_variable': 'default setting'}
    settings = Settings(defaults)
    settings.read_settings_block(
        trim("""
        $ variable = setting
        """))
    out = settings.replace(
        trim("""
        This is a $[variable], and a $[default_variable]!
        """))
    assert out == "This is a setting, and a default setting!"
Exemple #9
0
    def footnote(self, prefix, pattern, part_slug, count):
        """
        Take ^[some link] and return a link to its Index line.
        Also store the back-link for when the index is generated.
        If the reference if a link, make the inline text that link.
        """
        numbering = self.outline.find_numbering(part_slug)
        number = get_number(numbering)
        nav_id = get_nav_id(numbering, count)

        link_markup, punctuation = split_pattern(pattern)

        footnote_text = ''
        if part_slug in self.footnotes:
            if count in self.footnotes[part_slug]:
                footnote_text = self.footnotes[part_slug][count]

        if validators.url(footnote_text):
            ref_text = footnote_text
            # print('URL', ref_text)
        else:
            ref_text = self.inline.process(footnote_text)
            # print('NOT URL', footnote_text, ref_text)

        _ = '<a class="%s" id="%s_footnote_%s" href="#%s_link_%s">%s</a>'
        ref_link = _ % ('web-marker', self.id_prefix, nav_id, self.id_prefix,
                        nav_id, count)

        if number not in self.backlinks:
            self.backlinks[number] = {}

        self.backlinks[number][count] = (ref_link, ref_text)

        if validators.url(footnote_text):

            link = trim("""
                <a class="web-link" title="%s" href="%s"
                   target="_blank">%s</a>%s<a class="web-marker"
                   id="%s_link_%s" href="#%s_footnote_%s"><sup>%s</sup></a>
                """) % (strip_markup(footnote_text), footnote_text,
                        link_markup, punctuation, self.id_prefix, nav_id,
                        self.id_prefix, nav_id, count)

        else:

            link = trim("""
                <a class="web-link" title="%s" id="%s_link_%s"
                    href="#%s_footnote_%s">%s%s<sup>%s</sup></a>
                """) % (strip_markup(footnote_text), self.id_prefix,
                        nav_id, self.id_prefix, nav_id,
                        self.inline.process(link_markup), punctuation, count)

        return link
Exemple #10
0
def test_empty_function_block():
    spaced = trim("""
        COMPACT ---

        ---
        """)
    unspaced = trim("""
        COMPACT ---
        ---
        """)
    blocks = BlockList(spaced)
    assert blocks.text() == unspaced
    blocks = BlockList(unspaced)
    assert blocks.text() == unspaced
def test_split_bibliography():
    content = trim("""
        This is the body.
        """)
    assert split_bibliography(content) == ("This is the body.", None)
    content = trim("""
        This is the body.

        ___

        This is the bibliography.
        """)
    assert split_bibliography(content) == [
        "This is the body.", "This is the bibliography."
    ]
Exemple #12
0
def test_list_block():
    "Test function block with zero lines"
    text = trim("""
        # Test 1
        # Test 2
        """)
    expect = trim("""
        <ol>
        <li>
        Test 1</li><li>Test 2
        </li>
        </ol>
        """)
    actual = list_block(text, Settings())
    assert expect == actual
Exemple #13
0
def wrap(alignment_name, html, options):
    """
    Shortcut for wrapping html with alignment and width; see Wrapper and
    subclasses. Handles css_dimensions in options.
    """
    dimension = get_option(options, 1, 'dimension', None)
    if dimension == "":
        dimension = 'auto'
    if alignment_name == 'center':
        properties = ["style=\"width: %s; margin: auto;\"" % dimension]
        return trim("""
            <div %s>%s</div>
            """) % (" ".join(properties), html)
    properties = ["style=\"width: %s;\"" % dimension]
    class_property = {
        'left': 'text-left',
        'center': 'text-center',
        'right': 'pull-right',
        'indent': 'text-indent',
    }.get(alignment_name, None)
    if class_property:
        properties += ["class=\"%s\"" % class_property]
    clear = '<div class="clear"></div>' if alignment_name == 'right' else ''
    return "<div %s><span>%s</span></div>" % (" ".join(properties),
                                              html) + clear
def test_nonempty_lines():
    content = trim("""
        This is a test.

        This is a test.
        """)
    assert nonempty_lines(content) == ['This is a test.'] * 2
Exemple #15
0
    def tag(self, alias1, tag1, subtag1, punctuation, numbering, count):
        """
        Take #Tags:Tag and return a link to its Index line.
        Also store the back-link for when the index is generated.
        """

        alias = one_line(alias1)
        tag = one_line(tag1)
        subtag = one_line(subtag1)

        number = get_number(numbering)
        nav_id = get_nav_id(tag, subtag, numbering, count)

        if tag not in self.tags:
            self.tags[tag] = {}
        if subtag not in self.tags[tag]:
            self.tags[tag][subtag] = {}
        if number not in self.tags[tag][subtag]:
            self.tags[tag][subtag][number] = []

        link = trim("""
                <a id=\"%s\" href=\"#ref_%s\">%s%s<sup>%s</sup></a>
            """) % (
            nav_id, nav_id, alias, punctuation, count
        )

        ref_link = "<a id=\"ref_%s\" href=\"#%s\">%s</a>" % \
                   (nav_id, nav_id, count)

        self.tags[tag][subtag][number] += [ref_link]
        return link
Exemple #16
0
    def html_spare_parts(self, doc_parts, edit_base_uri):
        """
        Generate a list of links to a document's parts not appearing in the
        outline.

        @todo Get headings and word count.
        """
        found = [slug for (_, slug, _, _, _) in self.elements]
        spare_parts = [
            _ for _ in list(doc_parts.keys())
            if _ not in found and _ not in ['index', 'biblio']
        ]

        env = Environment(autoescape=True)
        tpl = env.from_string(
            trim("""
            {% if spare_parts|length > 0 %}
            <div class="wiki-note">
                These parts  do not appear in the index's outline:
                    {% for slug in spare_parts %}
                    • <a href="{{ edit_base_uri }}/{{ slug }}">{{ slug }}</a>
                {% endfor %}
                ({{ spare_parts|length }}).
            </div>
            {% endif %}
            """))
        return tpl.render(spare_parts=spare_parts, edit_base_uri=edit_base_uri)
Exemple #17
0
def test_replace_title():
    text = trim("""
        Index

        - Chapter One
        - - Chapter One Aye
        - Chapter Two
        """)
    expect = trim("""
        Index

        - The NEW Chapter One
        - - Chapter One Aye
        - Chapter Two
        """)
    assert expect == replace_title(text, "Chapter One", "The NEW Chapter One")
Exemple #18
0
def makeBokehSvg(backgroundColor, width, height):
    fuzzy_circles = drawCircles(randint(30, 40), sizes=[3, 3, 3, 4, 5])
    sharp_circles = drawCircles(randint(45, 65),
                                sizes=[1, 1, 1, 1, 1, 1, 1, 2, 2])
    env = Environment(autoescape=False)
    tpl = env.from_string(
        trim("""
        <svg
            xmlns="http://www.w3.org/2000/svg"
            style="background-color: {{ backgroundColor }}"
            viewBox="0 0 {{ width }} {{ height }}"
            width="100%" height="100%"
        >
            <defs>
            <filter id="blur">
            <feGaussianBlur stdDeviation="4"></feGaussianBlur>
            </filter>
            </defs>
            {% for circle in sharp_circles %}
            {{ circle }}
            {% endfor %}
            {% for circle in fuzzy_circles %}
            {{ circle }}
            {% endfor %}
        </svg>
    """))
    return tpl.render(
        backgroundColor=backgroundColor,
        width=width,
        height=height,
        fuzzy_circles=fuzzy_circles,
        sharp_circles=sharp_circles,
    )
Exemple #19
0
def test_rename_article():

    do_login_as_admin()

    index_renamed = trim("""
        Test Article Renamed

        = My important message!

        ` Part One
        ` Part Two
        """)

    clicks_on_save = {
        'content': index_renamed,
        'they_selected_save': 'YES',
    }

    old_part = 'test-article'
    new_part = 'test-article-renamed'

    uri = EDIT_URI.format(ADMIN_USER, old_part, 'index')
    old_uri = READ_URI.format(ADMIN_USER, old_part)
    new_uri = READ_URI.format(ADMIN_USER, new_part)

    _ = test.post(uri, clicks_on_save, status=HTTP_REDIRECT)
    assert _.headers['location'].endswith(new_uri)

    _ = test.get(old_uri, status=HTTP_NOT_FOUND)
    _ = test.get(new_uri, status=HTTP_OK)

    # New URI must be linked in Latest Changes.
    _ = test.get(ADMIN_HOME_URI)
    assert _.lxml.xpath(match_link(new_uri))
Exemple #20
0
def test_create_index():
    """
    Creating an article should result in accurate metadata.
    """

    do_login_as_admin()

    index = trim("""
        Test Article

        = My important message!

        $ AUTHOR = Author Name
        $ DATE = 31 December 1999

        ` Part One
        ` Part Two
        """)
    doc_slug = 'test-article'
    clicks_on_preview = {
        'content': index,
        'they_selected_preview': 'YES',
    }

    uri = EDIT_URI.format(ADMIN_USER, '_', 'index')
    _ = test.post(uri, clicks_on_preview, status=HTTP_OK)  # Preview
    assert _.lxml.xpath("count(//h1)") == 1

    clicks_on_save = {
        'content': index,
        'they_selected_save': 'YES',
    }

    uri = EDIT_URI.format(ADMIN_USER, '_', 'index')
    new_uri = READ_URI.format(ADMIN_USER, 'test-article')

    _ = test.post(uri, clicks_on_save, status=HTTP_REDIRECT)  # Save
    assert _.headers['location'].endswith(new_uri)

    # Page should have article and links.
    _ = test.get(new_uri, status=HTTP_OK)
    assert "Test Article" in _
    assert "My important message!" in _
    assert "Author Name" in _
    nav_links = [
        ADMIN_HOME_URI,
        EDIT_URI.format(ADMIN_USER, doc_slug, 'index'),
        EDIT_URI.format(ADMIN_USER, doc_slug, 'biblio'),
        "/upload/{:s}/{:s}".format(ADMIN_USER, doc_slug),
        "/download/{:s}/{:s}".format(ADMIN_USER, doc_slug),
    ]
    for href in nav_links:
        assert _.lxml.xpath(match_link(href))

    # Check Latest Changes on the user page has the new article.

    _ = test.get(ADMIN_HOME_URI, status=HTTP_OK)
    assert 'Test Article' in _
    assert 'My important message!' in _
    assert '31 December 1999' in _
Exemple #21
0
def test_character_block():
    block = CharacterBlock(trim("""
        @ X
        """))
    assert block.text() == '\n@ X'  # <-- with leading space for a heading
    expected = '<p class="subhead">X</p>'
    assert block.html_only(Html(), Settings()) == expected
Exemple #22
0
class Compact(Wrapper):
    """
    Make the text occupy as little space as possible. This is usually for a
    suplementary text that migt be read but probably will not.
    """

    examples = [
        trim("""
            COMPACT (2cols) ---
            lots of text lots of text lots of text lots of text lots of
            text lots of text lots of text lots of text lots of text lots
            of text lots of text lots of text lots of text lots of text
            lots of text lots of text lots of text lots of text lots of
            text lots of text lots of text lots of text lots of text lots
            of text lots of text lots of text lots of text lots of text
            ---
        """),
    ]

    option_list = {'1': "2cols, 3cols (optional)"}

    def wrap(self, html):
        """
        Just set bootstrap column options.
        """
        if '2cols' in self.options:
            columns = ' columns-x2 column-rule'
        elif '3cols' in self.options:
            columns = ' columns-x3 column-rule'
        else:
            columns = ''
        return "<div class=\"compact%s\">%s</div>" % (columns, html)
Exemple #23
0
 def make_footer(self):
     """
     <footer>
         <section id="prefix-footnotes">
         <section id="prefix-bibliography">
         <section id="prefix-index">
     """
     endmatter = [
         _ for _ in [
             # self.footnotes.html(),
             self.bibliography.html(),
             # self.index.html(),
         ] if _.strip() != ""
     ]
     env = Environment(autoescape=True)
     tpl = env.from_string(
         trim("""
             <footer>
             {% if endmatter|length > 0 %}
                 <hr class="div-left div-solid"/>
                 {% for html in endmatter %}
                     {{ html | safe }}
                 {% endfor %}
             {% endif %}
             </footer>
         """))
     return tpl.render(endmatter=endmatter,
                       biblio_link=self.settings.get_base_uri('edit') +
                       '/biblio')
Exemple #24
0
def html_heading(numbering: list, title: str, slug: str,
                 base_edit_uri: str) -> str:
    """
    Generate the first line of each block, including the anchor tag, and
    any navigational links.

    The numbering depth determines H1..H6.
    """
    env = Environment(autoescape=True)
    tpl = env.from_string(
        trim("""
        <div class="pull-right">
            <span>
                <a href="{{ base_edit_uri }}{{ slug }}">Edit</a>
            </span>
        </div>
        <{{ tag }} class="balance-text">
            <a id="{{ name }}" href="#{{ name }}">
                {{ title }}
            </a>
        </{{ tag }}>
        """))
    return tpl.render(base_edit_uri=base_edit_uri,
                      name=anchor_name(numbering, slug),
                      slug=slug,
                      tag='h%d' % max(1, min(6, len(numbering))),
                      title=title)
Exemple #25
0
    def html(self, renderer):
        html_rows = []
        for row in [row.strip() for row in self.text.split("===")]:
            html_cells = []
            for cell in [cell.strip() for cell in row.split("---")]:
                blocks = BlockList(clean_text(cell))
                slug = random_slug('grid-')
                html = blocks.html([0], slug, renderer.settings, fragment=True)
                html_cells.append(html)
            html_rows.append(html_cells)

        env = Environment(autoescape=True)
        tpl = env.from_string(
            trim("""
            <table class="table table-condensed">
            <tbody>
            {% for html_row in html_rows %}
                <tr>
                    {% for html_cell in html_row %}
                    <td>{{ html_cell|safe }}</td>
                    {% endfor %}
                </tr>
            {% endfor %}
            </tbody>
            </table>
        """))

        return tpl.render(html_rows=html_rows)
Exemple #26
0
def test_backslashes():
    """
    Using backslash replacement for testing; there is an actual backslashes
    class that does this in the wiki.
    """
    parts = {'test': trim(r"""
        That\'s what it\'s about.
        """)}

    marker = 'test'

    delimiter = '|'  # <-- For easy testing. This normally defaults to

    #     chr(30), an invisible 'record separator' in ASCII.

    def callback(x, _):
        return x[1:]  # <-- Remove leading slash from pattern;

    #     Ignore slug.

    backslashes = Placeholders(r'\\.', marker, delimiter)

    tokenized = backslashes.insert(parts)
    assert {'test': "That|test:1|s what it|test:2|s about."} == tokenized

    decorated = backslashes.replace(callback, tokenized)
    assert {'test': "That's what it's about."} == decorated
Exemple #27
0
    def html(self, renderer, settings):
        """
        Map divider patterns to HTML, which doesn't change.

        (Settings are unused.)
        """
        html = {
            # Markers
            '*':
            '<p class="text-center text-large space"><span>✻</span></p>',
            '-':
            rule('div-solid div-center'),
            '* * *':
            trim("""
                <p class="text-center text-large big-space">
                    <span>✻ ✻ ✻</span>
                </p>
                """),
            '- - -':
            rule('div-solid'),
            '. . .':
            rule('div-dotted div-wide'),
            '= = =':
            rule('div-thick div-wide'),
            # Spacers
            '~':
            space(1),
            '~ ~':
            space(2),
            '~ ~ ~':
            space(3),
            '~ ~ ~ ~':
            space(4),
        }.get(self.content, '')
        return (html, settings)
Exemple #28
0
def test_process_simple():
    wiki = Wiki(Settings())
    document = {
        'sample':
        trim("""
        Title

        > Quote
        = Calvin, /Institutes/

        @ Headline

        Paragraph

        * Bullets
        * Bullets
        """)
    }
    _ = wiki.process('user-slug', 'doc-slug', document)
    __ = html.fromstring(str(_))
    assert __.xpath("//article/section")
    assert __.xpath("//h1/a[contains(., 'Title')]")
    assert __.xpath("//blockquote[contains(., 'Quote')]")
    assert __.xpath("//p[@class='caption'] and contains(., 'Calvin')")
    assert __.xpath("//p[@class='caption']/em[contains(., 'Institutes')]")
    assert __.xpath("//p[@class='subhead'][contains(., 'Headline')]")
    assert __.xpath("//p[contains(., 'Paragraph')]")
    assert __.xpath("count(//ul/li[contains(., 'Bullets')])") == 2
Exemple #29
0
class Box(Wrapper):
    """
    Just a simple box.
    """

    examples = [
        trim("""
            BOX ---
            lots of text lots of text lots of text lots of text lots of
            text lots of text lots of text lots of text lots of text lots
            of text lots of text lots of text lots of text lots of text
            lots of text lots of text lots of text lots of text lots of
            text lots of text lots of text lots of text lots of text lots
            of text lots of text lots of text lots of text lots of text
            ---
        """),
    ]

    option_list = {}

    def wrap(self, html):
        """
        Wrap inner HTML.
        """
        return "<div class=\"box-dotted\">%s</div>" % html
Exemple #30
0
def test_constructor():
    parts = {
        'index':
        trim("""
            My Document!

            It contains a reference to ~[Chapman, /Conversation/, p.34].
        """),
        'biblio':
        trim("""
            Chapman, Nigel. 2014. Private conversation.
            Chapman, Nigel. 2014. Private conversation. #2.
        """),
    }

    outline = Outline(parts, default_counters())
    bibliography = Bibliography(parts, outline, id_prefix)
    citations = Citations(bibliography)

    assert bibliography.entries == SortedDict({
        "Chapman, Nigel. 2014a.":
        "Private conversation.",
        "Chapman, Nigel. 2014b.":
        "Private conversation. #2.",
    })

    new_parts = citations.insert(parts)

    assert new_parts == {
        'index':
        trim("""
            My Document!

            It contains a reference to %scitation:1%s
            """) % (DELIMITER, DELIMITER),  # ^ note the missing fullstop
        'biblio':
        trim("""
            Chapman, Nigel. 2014. Private conversation.
            Chapman, Nigel. 2014. Private conversation. #2.
            """),
    }

    end_parts = citations.replace(new_parts)
    assert '<em>Conversation</em>' in end_parts['index']
    assert 'p.34' in end_parts['index']
    dom = html.fragment_fromstring(end_parts['index'], create_parent='body')[0]
    assert len(dom.cssselect('a')) == 1