Ejemplo n.º 1
0
    def __init__(self, parts, outline, id_prefix):
        """
        Create bibliography entries, and the structure for recording citations
        as they occur (These will be back-linked in the bibliography's
        citations list). The unique entry_id will be a slug of author/date,
        with an added Letters() counter for uniqueness.

                        / SortedDict
        self.entries = {entry_id: entry_text}

                                       / SortedDict
        self.citations = {entry_id: {part_number: [indexes]}}
        """
        assert isinstance(outline, Outline)
        assert isinstance(parts, dict)

        self.outline = outline
        self.entries = collate_bibliography(parts)

        self.id_prefix = id_prefix

        self.citations = {}
        self.counters = {}

        self.inline = Inline()
Ejemplo n.º 2
0
 def __init__(self, settings=None):
     """
     Note that the _first_ one created will have its config used.
     """
     self.settings = settings
     self.inline = Inline()
     self.list_counter = 1
Ejemplo n.º 3
0
def test_dashes():
    test = Inline()
    assert '0–9' == test.process("0-9")
    assert 'x – y' == test.process("x -- y")
    assert 'x—y' == test.process("x---y")
    assert '– x – y –' == test.process("-- x -- y --")
    assert '–x–y–' == test.process("--x--y--")
    assert '—x—y—' == test.process("--- x --- y ---")
    assert '—x—y—' == test.process("---x---y---")
Ejemplo n.º 4
0
def test_typography():
    test = Inline()
    assert "x—x – x © ™" == \
        test.typography("x --- x -- x (C) (TM)")
    assert "6×9 … 9½ 9¼ 9¾" == \
        test.typography("6x9 ... 9(1/2) 9(1/4) 9(3/4)")
    assert "“That’s ‘OK’,” I sez." == \
        test.typography("\"That's 'OK',\" I sez.")
    assert '    ' == \
        test.typography("(4EM)")
Ejemplo n.º 5
0
def alert(content, dump_vars=None):
    """
    Show a visual error notice.
    """
    inline = Inline()
    pattern = "<div class=\"alert alert-warning\" role=\"alert\">%s</div>"
    html = pattern % inline.process(content)
    if not dump_vars:
        dump_vars = []
    html += "\n\n".join([pformat(var) for var in dump_vars])
    return html
Ejemplo n.º 6
0
def test_happy_path():
    test = Inline()
    out = '<strong>To boldly</strong> go where <u>none</u> have gone <em>before.</em>'
    assert out == test.process(
        "*[To boldly] go where _[none] have gone /[before.]")
    out = '<ins>To boldly</ins> go where <del>none</del> ' + \
          'have gone <kbd>before</kbd>.'
    assert out == test.process(
        '+[To boldly] go where -[none] have gone `[before].')
    out = '<sup>To boldly</sup> go where <sub>none</sub> ' + \
          'have gone before.'
    assert out == test.process(
        "'[To boldly] go where ,[none] have gone before.")
Ejemplo n.º 7
0
    def list_block_recursor(char, items, settings, depth=1):
        """
        Recursion handler for list_block().

        $ NUMBERING = ... is the next item to count from.
        $ CONTINUE = ... is the count to use if NUMBERING = continue
        """
        inline = Inline()
        list_tag = 'ol' if char == '#' else 'ul'
        properties = ['']
        if list_tag == 'ol' and depth == 1:
            numbering = settings.get('NUMBERING', '')
            if numbering.isdigit():
                properties += ['start="%s"' % numbering]
                settings.set('CONTINUE', int(numbering))
                settings.set('NUMBERING', '')
            elif numbering == 'continue':
                properties += ['start="%s"' % settings.get('CONTINUE')]
                settings.set('NUMBERING', '')
            else:
                settings.set('CONTINUE', 1)
        if char == '_':
            properties += ['class="checkboxes"']

        # XHTML (for ebooks) requires that a child list appears inside the
        # preceeding <li> rather than inside it's own <li>. So we'll accumulate
        # display_items distinct from structural items, and join these into an
        # HTML list at the end.
        open_tag = "<%s%s>" % (list_tag, ' '.join(properties))
        display_items = []
        for item in items:
            if isinstance(item, list):
                # There should always be a preceding element when we reach a
                # sublist. Append to that:
                if len(display_items) > 0:
                    last = len(display_items) - 1
                    sub_list = list_block_recursor(char, item, settings,
                                                   depth + 1)
                    display_items[last] += sub_list
            else:
                display_items += [inline.process(item)]
                if list_tag == 'ol' and depth == 1:
                    settings.set('CONTINUE', settings.get('CONTINUE') + 1)
        close_tag = "</%s>" % list_tag
        lines = [open_tag]
        for item in display_items:
            lines.append("<li>" + item + "</li>")
        lines.append(close_tag)
        return "\n".join(lines)
Ejemplo n.º 8
0
def tag(tag_name, text, class_name=''):
    """
    Regular tag+class convenience function
    """
    inline = Inline()
    if text == "":
        html = "&nbsp;"
    else:
        html = inline.process(text)
    if class_name != '':
        tpl = "<%s class=\"%s\">%s</%s>"
        return tpl % (tag_name, class_name, html, tag_name)
    else:
        tpl = "<%s>%s</%s>"
        return tpl % (tag_name, html, tag_name)
Ejemplo n.º 9
0
def get_cell_formatting(align, cell):
    """
    For table_block: align is one of lrc$
    """
    inline = Inline()
    if align == 'r':
        return ("class=\"text-right\"", inline.process(cell))
    elif align == 'c':
        return ("class=\"text-center\"", inline.process(cell))
    elif align == '$':
        try:
            # @todo: Allow locale to be set with settings.
            value = locale.currency(float(cell), grouping=True)
        except ValueError:
            value = cell
        return ("class=\"text-right\"", value)
    else:
        return ("class=\"text-left\"", inline.process(cell))
Ejemplo n.º 10
0
    def split_author(self, author):
        """
        UNUSED FOR NOW. v.0.1.0 is SINGLE_USER.

        Split into authors and lines.

        $ AUTHOR = Author / Affiliation
                 + Author2 / Affiliation2

        No author should return an empty list.
        """
        inline = Inline()
        if author.strip() == '':
            return []
        else:
            return [[
                inline.process(line.strip()) for line in block.split(' / ')
            ] for block in author.split(' + ')]
Ejemplo n.º 11
0
    def __init__(self, parts, outline, id_prefix):
        """
        Matches ^[link] and

        ^ That link's corresponding footnote.

        Constructs: {part_numbering, {count: (link_text, footnote_text)}}
        """
        assert isinstance(outline, Outline)
        self.outline = outline

        assert isinstance(parts, dict)
        self.links, self.footnotes = self.collate_footnotes(parts)
        self.backlinks = SortedDict()

        self.id_prefix = id_prefix

        self.inline = Inline()
        self.counters = {}
Ejemplo n.º 12
0
def gloss_block(text, settings):
    """
    Build HTML from text.
    """
    inline = Inline()
    char = text[0]  # '/', as used here
    gloss = []
    num = None
    for _, line in split_to_array(text, char):
        parts = line.split(" %s " % char)
        if len(parts) == 1:
            num = parts.pop(0)
        else:
            source_html = inline.process(parts.pop(0))
            translations_html = [inline.process(part) for part in parts]
            if num is not None:
                gloss += [[(str(num), ''), (source_html, translations_html)]]
                num = None
            else:
                gloss += [[(source_html, translations_html)]]

    env = Environment(autoescape=True)
    tpl = env.from_string(
        trim("""
        <div class="gloss">
        {% for translation_group in gloss %}
            <div class="phrase-group">
                {% for source_html, translations in translation_group %}
                <div class="phrase">
                    <div class="source">{{ source_html|safe }}</div>
                    {% for translation_html in translations %}
                    <div class="translation">{{ translation_html|safe }}</div>
                    {% endfor %}
                </div>
                {% endfor %}
            </div>
        {% endfor %}
        </div>
    """))

    return tpl.render(gloss=gloss)
Ejemplo n.º 13
0
    def make_index(self, text):
        """
        Front matter preceding index text.
        Multi-author blocks are disabled for now; v.0.1.0 is SINGLE_USER.
        """
        env = Environment(autoescape=True)
        tpl = env.from_string(
            trim("""
        <header>

            {% if title_html != "" %}
            <hgroup>
                <h1 class="balance-text">{{ title_html|safe }}</h1>
            {% if summary != "" %}
                <h2 class="balance-text">{{ summary_html|safe }}</h2>
            {% endif %}
            </hgroup>
            {% endif %}

            {% if author != "" or email != "" %}
            <div class="author-list">
                <address>
                {% if author != "" %}
                    <div>{{ author }}</div>
                {% endif %}
                {% if email != "" %}
                    <div><a href="mailto:{{ email }}">{{ email }}</a></div>
                {% endif %}
                </address>
            </div>
            {% endif %}

            {% if facebook != "" or twitter != "" %}
            <p class="space space-between">
                {% if facebook != "" %}
                <a href="https://facebook.com/{{ facebook }}" target="_blank">
                    FB: {{ facebook }}
                </a>
                {% endif %}
                {% if twitter != "" %}
                <a href="https://twitter.com/{{ twitter }}" target="_blank">
                    TW: {{ twitter }}
                </a>
                {% endif %}
            </p>
            {% endif %}

            {% if date %}
            <p class="space" rel="date">
                {% if parsed_date != None %}
                <time pubdate datetime="{{ parsed_date }}">{{ date }}</time>
                {% else %}
                {{ date }}
                {% endif %}
            </p>
            {% endif %}

        </header>
        <section class="depth-0">
            {{ content_html|safe }}
        </section>
        """))

        inline = Inline()
        content, _ = split_bibliography(text)
        blocks = BlockList(content)
        title, summary = blocks.pop_titles()
        content_html = blocks.html(['0'],
                                   'index',
                                   self.settings,
                                   fragment=True)

        date_string = inline.process(self.settings.get('DATE', ''))
        try:
            dt = parse(date_string)
            date_yyyymmdd = dt.date().isoformat()
        except ValueError:
            date_yyyymmdd = None

        # author = self.split_author()
        return tpl.render(
            title_html=inline.process(title),
            summary_html=inline.process(summary),
            author=self.settings.get('AUTHOR', ''),
            email=self.settings.get('EMAIL', ''),
            facebook=self.settings.get('FACEBOOK', ''),
            twitter=self.settings.get('TWITTER', ''),
            date=date_string,
            parsed_date=date_yyyymmdd,
            edit_link=self.settings.get_base_uri('edit') + '/index',
            content_html=content_html,
        )
Ejemplo n.º 14
0
def user_page(user_slug):
    """
    Show <user_slug>/fixtures/author + user documents.
    """
    header_buttons = [login_or_logout_button()]
    login = get_login()
    if login and login['username'] == user_slug:
        header_buttons += [
            new_article_button(user_slug),
        ]

    header_buttons += [
        edit_button(user_slug, 'fixtures', 'author'),
    ]

    if not login:
        header_buttons += [subscribe_button(), rss_button(user_slug)]

    footer_buttons = []
    if config['ARTICLE_WIKI_CREDIT'] == 'YES':
        footer_buttons += [source_button()]
    footer_buttons += [help_button()]
    if has_authority_for_user(user_slug):
        footer_buttons += [export_archive_button(user_slug)]

    slugs = data.userDocumentSet_list(user_slug)
    changes_list = data.userDocumentLastChanged_list(user_slug)

    if not has_authority_for_user(user_slug):
        # Show only those that have been published
        changes_list, __ = split_published(changes_list)

    article_slugs = [_ for _ in slugs if _ not in ['fixtures', 'templates']]
    article_keys = [
        data.userDocumentMetadata_key(user_slug, _) for _ in article_slugs
    ]
    article_list = sorted(data.get_hashes(article_keys),
                          key=lambda _: _.get('title', ''))

    published_articles, unpublished_articles = split_published(article_list)
    if not has_authority_for_user(user_slug):
        unpublished_articles = []

    settings = Settings({
        'config:host': domain_name(bottle.request),
        'config:user': user_slug,
        'config:document': 'fixtures',
    })
    wiki = Wiki(settings)
    document = data.userDocument_get(user_slug, 'fixtures')
    if not document:
        msg = "User '{:s}' not found."
        bottle.abort(HTTP_NOT_FOUND, msg.format(user_slug))
    if 'author' in document:
        text = document['author']
    else:
        text = trim("""
            Author Page

            (Author information to be added here...)
            """)

    blocks = BlockList(clean_text(text))
    page_title, page_summary = blocks.pop_titles()
    content_html = wiki.process(None,
                                None, {'index': blocks.text()},
                                fragment=True,
                                preview=True)
    inline = Inline()

    return views.get_template('user.html').render(
        config=config,
        user=user_slug,
        page_title="{:s} - {:s}".format(page_title, page_summary),
        title_html=inline.process(page_title),
        summary_html=inline.process(page_summary),
        header_buttons=header_buttons,
        footer_buttons=footer_buttons,
        changes_list=changes_list,
        published_articles=published_articles,
        unpublished_articles=unpublished_articles,
        content_html=content_html,
        pluralize=pluralize  # <-- hack function injection
    )
Ejemplo n.º 15
0
    def html(self, edit_base_uri):
        """
        Generate a table of contents.
        """
        env = Environment(autoescape=True)
        tpl = env.from_string(
            trim("""
            {% if outline|length > 0 %}
            <h2>Table of Contents</h2>
            <table class="table table-of-contents table-condensed">
                <tbody>
                    {% for numbering, name, slug, title, word_count, subtotal in outline %}
                    <tr>
                        {% if slug == 'index' %}
                        <td></td>
                        <td class="word-count" colspan="{{ (max_depth * 2) - 1 }}">
                            Index.
                        </td>
                        <td class="word-count">{{ word_count }}</td>
                        {% else %}

                            {% for i in range(numbering|length - 1) %}
                        <td></td>
                            {% endfor %}

                        <td class="text-right">
                            <b>{{ numbering | join('.') }}</b>.
                        </td>

                        {% if subtotal == "0" %}
                        <td colspan="{{ (max_depth - numbering|length) * 2 + 1 }}">
                        {% else %}
                        <td colspan="{{ (max_depth - numbering|length) * 2 }}">
                        {% endif %}

                            {% if word_count == "0" %}
                            <a href="{{ edit_base_uri }}/{{ slug }}?title={{ title|urlencode }}" class="unmarked">
                                <i>{{ title|safe }}</i>
                            </a>
                            {% else %}
                            <a href="#{{ name }}" class="unmarked">
                                {{ title|safe }}
                            </a>
                            {% endif %}
                        </td>

                        <td class="word-count">
                            {% if word_count == "0" %}&mdash;{% else %}{{ word_count }}{% endif %}
                        </td>

                            {% if numbering|length > 1 or subtotal != "0" %}
                                {% if subtotal != "0" %}
                        <td class="word-count">
                            \\&nbsp;<b>{{ subtotal }}</b>
                        </td>
                                {% endif %}
                                {% for i in range(numbering|length - 2) %}
                        <td>
                        </td>
                                {% endfor %}
                            {% endif %}
                        {% endif %}
                    </tr>
                    {% endfor %}
                    <tr>
                        <td></td>
                        <td class="word-count" colspan="{{ (max_depth * 2) - 1 }}">
                            Total words.
                        </td>
                        <td class="word-count"><b>{{ total_word_count }}</b></td>
                    </tr>
                </tbody>
            </table>
            {% endif %}
            """))
        inline = Inline()
        max_depth = max([len(nums) for (nums, _, _, _, _) in self.elements])
        formatted = [(
            numbering,
            anchor_name(numbering, slug),
            slug,
            inline.process(title),
            '{:,d}'.format(word_count),
            '{:,d}'.format(subtotal),
        ) for (numbering, slug, title, total_slug, word_count,
               subtotal) in totalize(self.elements)]
        return tpl.render(outline=formatted,
                          max_depth=max_depth,
                          edit_base_uri=edit_base_uri,
                          total_word_count='{:,d}'.format(
                              self.total_word_count()))
Ejemplo n.º 16
0
def test_apostrophes():
    test = Inline()
    assert '‘X’' == test.process("'X'")
    assert 'X’s' == test.process("X's")
    assert '(‘x)' == test.process("('x)")
Ejemplo n.º 17
0
def test_brackets():
    test = Inline()
    assert '<strong>bold face</strong>' == test.brackets('*', "bold face")
    assert '<em><strong><u>bold-underline-italics</u></strong></em>' == \
        test.brackets('*_/', "bold-underline-italics")