Ejemplo n.º 1
0
class Entities(object):
    """
    Extract backslashes characters; restore with backslashes removed.
    """

    regex = r'\&\w+;'

    def __init__(self):
        "This is a thin wrapper for Placeholders"
        self.placeholders = Placeholders(self.regex, 'en')

    def insert(self, parts):
        "Add placeholders."
        result = self.placeholders.insert(parts)
        return result

    def decorate(self, pattern, part_slug=None):
        """
        It's safe HTML, so insert it unchanged.
        """
        return pattern

    def replace(self, html_parts):
        "Replace backslashes characters."
        return self.placeholders.replace(self.decorate, html_parts)
Ejemplo n.º 2
0
class Urls(object):
    """
    Extract backslashes characters; restore with backslashes removed.
    """
    def __init__(self):
        "This is a thin wrapper for Placeholders"
        url_chars = re.escape(r'.:\/_+?&=-#%~')
        regexps = [
            r'https?://[\w%s]+\w' % url_chars,  # <-- url
            r'[\w\.\-\_]+@[\w\.\-\_]+\w'  # <-- email
        ]
        regexp = '(' + '|'.join(regexps) + ')'
        self.placeholders = Placeholders(regexp, 'ur')

    def insert(self, parts):
        "Add placeholders."
        return self.placeholders.insert(parts)

    def decorate(self, pattern, part_slug=None):
        "HTML encode the URLs."
        if email(pattern):
            link = "mailto:%s" % pattern
        else:
            link = pattern
        html = "<a href=\"%s\" target=\"_blank\">%s</a>"
        return html % (link, escape(pattern))

    def replace(self, html_parts):
        "Put the URLs back in the finishes text"
        return self.placeholders.replace(self.decorate, html_parts)
Ejemplo n.º 3
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
Ejemplo n.º 4
0
class CrossReferences(object):
    """
    Manage internal links within a document.
    """
    def __init__(self, parts, outline):
        """
        Create contents list, replace cross-references with placeholders.
        """

        assert isinstance(parts, dict)
        assert all([isinstance(_, str) for _ in list(parts.keys())])
        assert all([isinstance(_, str) for _ in parts])
        assert isinstance(outline, Outline)

        self.regex = r'\@\[[^\]]+\][.,!?;:·]?'
        self.placeholders = Placeholders(self.regex, 'cr')
        self.outline = outline

    def insert(self, parts):
        """
        Use the placeholders object defined in init().
        """
        return self.placeholders.insert(parts)

    def decorate(self, pattern, part_slug=None):
        """
        Find first title that contains ALL terms.
        """
        terms = get_words(pattern)
        for (numbering, slug, title, title_slug, _) in self.outline:
            title_terms = get_words(title)
            # Require all given terms to match the title.
            # print set(terms), set(title_terms), set(terms) < set(title_terms)
            if set(terms) <= set(title_terms):
                section = ".".join(str(i) for i in numbering)
                slug = section + '_' + slug
                # leading '-' for short form
                if pattern[2] == '-':
                    fmt = "<a class=\"unmarked\" href=\"#%s\">&sect;%s</a>"
                    link = fmt % (slug, section)
                else:
                    fmt = "<a class=\"unmarked\" href=\"#%s\"><i>%s</i> (&sect;%s)</a>"
                    link = fmt % (slug, title.strip(), section)
                # trailing punctuation
                if pattern[-1] in ",.?!:;·":
                    link += pattern[-1]
                return link
        error = "<kbd class=\"wiki-error\">%s</kbd>"
        return error % escape(pattern)

    def replace(self, html_parts):
        """
        Replace each @[...] with a link to that section's #id.
        """
        return self.placeholders.replace(self.decorate, html_parts)
Ejemplo n.º 5
0
class Citations(object):
    """
    Manage citations of the bibliography.
    """
    def __init__(self, bibliography):
        """
        Create bibliography entries, and setup placeholder identifiers.
        """
        assert isinstance(bibliography, Bibliography)
        self.bibliography = bibliography

        regex = r'~\[[^\)]+?\][%s]?' % re.escape(Config.punctuation)
        self.placeholders = Placeholders(regex, 'citation')

        self.ibid = None  # <-- last bibliography label; @todo add opcit?
        self.counters = {}

    # ------------------------------------------------------------
    # Insert, decorate and replace make this work as a Placeholder
    # ------------------------------------------------------------

    def insert(self, parts):
        """
        Replace the bibliography brackets with markers, to exclude them from
        wiki processing.
        """
        return self.placeholders.insert(parts)

    def decorate(self, pattern, part_slug=None):
        """
        Format a bibliography bracket into a link to its bibliography entry.
        """
        numbering = self.bibliography.outline.find_numbering(part_slug)
        citation, note, punctuation = split_pattern(pattern)
        if self.ibid and slugify(citation) == 'ibid':
            index = self.bibliography.get_count(part_slug)
            return self.bibliography.citation(citation, note, punctuation,
                                              self.ibid, numbering, index)
        label = self.bibliography.match(citation)
        if label:
            self.ibid = label
            index = self.bibliography.get_count(part_slug)
            return self.bibliography.citation(citation, note, punctuation,
                                              label, numbering, index)
        else:
            self.ibid = None
            return self.bibliography.outline.error(
                part_slug, pattern, "Citation not matched in bibliography.")

    def replace(self, html_parts):
        """
        Replace the placeholders with HTML links.
        """
        return self.placeholders.replace(self.decorate, html_parts)
Ejemplo n.º 6
0
class Links(object):
    """
    Manage tags appearing in the index.
    """
    def __init__(self, footnotes, prefix=None):
        """
        Create bibliography entries, and setup placeholder identifiers.
        """
        assert isinstance(footnotes, Footnotes)
        self.footnotes = footnotes

        # If no prefix, pick a random one.
        if prefix is not None:
            self.prefix = prefix
        else:
            self.prefix = random_slug('random_')

        regex = r'\^\[[^\]]+\][.,!?;:·]?'  # <-- see decorator
        self.placeholders = Placeholders(regex, 'link')

    # ------------------------------------------------------------
    # Insert, decorate and replace make this work as a Placeholder
    # ------------------------------------------------------------

    def insert(self, parts):
        """
        Replace the bibliography brackets with markers, to exclude them from
        wiki processing.
        """
        return self.placeholders.insert(parts)

    def decorate(self, pattern, part_slug=None):
        """
        Format a bibliography bracket into a link to its bibliography entry.
        """
        index = self.footnotes.get_count(part_slug)
        return self.footnotes.footnote(self.prefix, pattern, part_slug, index)

    def replace(self, html_parts):
        """
        Replace the placeholders with HTML links.
        """
        return self.placeholders.replace(self.decorate, html_parts)
Ejemplo n.º 7
0
class Verbatim(object):
    """
    Extract {{ verbatim }} blocks; restores as exact text entered; no markup.
    """
    def __init__(self):
        "This is a thin wrapper for Placeholders"
        regex = r"{{[^}]*}}"
        self.placeholders = Placeholders(regex, 'verbatim')

    def insert(self, parts):
        "Add placeholders."
        return self.placeholders.insert(parts)

    def decorate(self, pattern, part_slug=None):
        "Strip braces."
        trim_brackets = pattern[2:-2]
        return escape(trim_brackets)

    def replace(self, html_parts):
        "Replace verbatim text."
        return self.placeholders.replace(self.decorate, html_parts)
Ejemplo n.º 8
0
class Tags(object):
    """
    Manage tags appearing in the index.
    """
    def __init__(self, index):
        """
        Create bibliography entries, and setup placeholder identifiers.
        """
        assert isinstance(index, Index)
        self.index = index

        regex = r'[#%%]\[[^\]]+\][%s]?' % re.escape(Config.punctuation)
        self.placeholders = Placeholders(regex, 'tag')

    # ------------------------------------------------------------
    # Insert, decorate and replace make this work as a Placeholder
    # ------------------------------------------------------------

    def insert(self, parts):
        """
        Replace the bibliography brackets with markers, to exclude them from
        wiki processing.
        """
        return self.placeholders.insert(parts)

    def decorate(self, pattern, part_slug=None):
        """
        Format a bibliography bracket into a link to its bibliography entry.
        """
        numbering = self.index.outline.find_numbering(part_slug)
        alias, tag, subtag, punctuation = split_pattern(pattern)
        index = self.index.get_count(part_slug)
        return self.index.tag(alias, tag, subtag, punctuation, numbering,
                              index)

    def replace(self, html_parts):
        """
        Replace the placeholders with HTML links.
        """
        return self.placeholders.replace(self.decorate, html_parts)
Ejemplo n.º 9
0
class Backslashes(object):
    """
    Extract backslashes characters; restore with backslashes removed.
    """
    def __init__(self):
        "This is a thin wrapper for Placeholders"
        self.placeholders = Placeholders(r'\\.', 'bs')

    def insert(self, parts):
        "Add placeholders."
        return self.placeholders.insert(parts)

    def decorate(self, pattern, part_slug=None):
        """
        Strip the leading slash, and HTML encode.
        This ensures that \< won't allow arbitrary script injection.
        """
        return escape(pattern[1:])

    def replace(self, html_parts):
        "Replace backslashes characters."
        return self.placeholders.replace(self.decorate, html_parts)
Ejemplo n.º 10
0
class Demo(object):
    """
    Process DEMO blocks and their arguments.

    Located here because of interdependency with Wiki().
    """
    regex = r"DEMO\s+(\([^)]+\)\s)?\s*([%s])\2\2\s*\n.+?\n\2\2\2" % \
        re.escape(Config.delimiters)

    def __init__(self, settings=None):
        "Just a thin wrapper for Placeholders; parse options in replace()."
        self.placeholders = Placeholders(self.regex, 'demo')
        if settings:
            self.settings = settings.copy()
        else:
            self.settings = Settings()
            self.settings.set('config:user', '_')
            self.settings.set('config:document', random_slug('demo'))

    def insert(self, parts):
        "Add placeholders."
        return self.placeholders.insert(parts)

    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)

    def replace(self, html_parts, decorator=None):
        "Generate demo blocks."
        if decorator:
            return self.placeholders.replace(decorator, html_parts)
        else:
            return self.placeholders.replace(self.decorate, html_parts)