source: wikiextrasplugin/tags/1.3.1/tracwikiextras/symbols.py

Last change on this file was 17307, checked in by Jun Omae, 5 years ago

TracWikiExtras 1.3.1dev: fix unable to escape symbol markups (closes #13497)

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 4.7 KB
Line 
1# -*- coding: iso-8859-1 -*-
2#
3# Copyright (C) 2011 Mikael Relbe <mikael@relbe.se>
4# All rights reserved.
5#
6# Copyright (C) 2006 Christian Boos <cboos@neuf.fr>
7# All rights reserved.
8#
9# This software is licensed as described in the file COPYING, which
10# you should have received as part of this distribution. The terms
11# are also available at http://trac.edgewall.com/license.html.
12#
13# Author: Christian Boos <cboos@neuf.fr>
14#         Mikael Relbe <mikael@relbe.se>
15
16from trac.util.html import Markup, html as tag
17
18from trac.config import BoolOption, ConfigSection, ListOption
19from trac.core import implements, Component
20from trac.wiki import IWikiSyntaxProvider, IWikiMacroProvider
21
22from tracwikiextras.util import prepare_regexp, render_table
23
24
25SYMBOLS = {
26    '<-': '&larr;',
27    '->': '&rarr;',
28    '<->': '&harr;',
29    '<=': '&lArr;',
30    '=>': '&rArr;',
31    '<=>': '&hArr;',
32    '>=': '&ge;',
33    '=<': '&le;', # ... as <= is already used for &lArr;
34    '<>': '&ne;', # '!=' can't be used, because of the '!' escaping
35    '--': '&mdash;',
36    '(c)': '&copy;',
37    '(C)': '&copy;',
38    '(R)': '&reg;',
39    '1/2': '&frac12;',
40    '1/4': '&frac14;',
41    '3/4': '&frac34;',
42    '+/-': '&plusmn;',
43    '/\\': '&and;',
44    '\\/': '&or;',
45    '(TM)': '&trade;',
46    '...': '&hellip;',
47    }
48
49
50class Symbols(Component):
51    """Replace character sequences with symbols.
52
53    Characters and symbols are configurable in the `[wikiextras-symbols]`
54    section in `trac.ini`. Use the `ShowSymbols` macro to display a list of
55    currently defined symbols.
56    """
57
58    implements(IWikiMacroProvider, IWikiSyntaxProvider)
59
60    symbols_section = ConfigSection('wikiextras-symbols',
61            """The set of symbols is configurable by providing associations
62            between symbols and wiki keywords. A default set of symbols and
63            keywords is defined, which can be revoked one-by-one (_remove) or
64            all at once (_remove_defaults).
65
66            Example:
67            {{{
68            [wikiextras-symbols]
69            _remove_defaults = true
70            _remove = <- ->
71            &laquo; = <<
72            &raquo; = >>
73            &sum; = (SUM)
74            &hearts; = <3
75            }}}
76
77            Keywords are space-separated!
78
79            A symbol can also be removed by associating it with no keyword:
80            {{{
81            &larr; =
82            }}}
83
84            Use the `ShowSymbols` macro to find out the current set of symbols
85            and keywords.
86            """)
87
88    remove_defaults = BoolOption('wikiextras-symbols', '_remove_defaults',
89                                 False, doc="Set to true to remove all "
90                                            "default symbols.")
91
92    remove = ListOption('wikiextras-symbols', '_remove', sep=' ', doc="""\
93            Space-separated(!) list of keywords that shall not be interpreted
94            as symbols (even if defined in this section).""")
95
96    def __init__(self):
97        self.symbols = None
98
99    # IWikiSyntaxProvider methods
100
101    def get_wiki_syntax(self):
102        if self.symbols is None:
103            self.symbols = SYMBOLS.copy()
104            if self.remove_defaults:
105                self.symbols = {}
106            for symbol, value in self.symbols_section.options():
107                if not symbol.startswith('_remove'):
108                    if value:
109                        for keyword in value.split():
110                            self.symbols[keyword.strip()] = symbol
111                    else:
112                        # no keyword, remove all keywords associated with
113                        # symbol
114                        for k in self.symbols.keys():
115                            if self.symbols[k] == symbol:
116                               del self.symbols[k]
117            for keyword in self.remove:
118                if keyword in self.symbols:
119                    del self.symbols[keyword]
120
121        if self.symbols:
122            yield ('!?(?:%s)' % prepare_regexp(self.symbols),
123                   self._format_symbol)
124        else:
125            yield (None, None)
126
127    def get_link_resolvers(self):
128        return []
129
130    #noinspection PyUnusedLocal
131    def _format_symbol(self, formatter, match, fullmatch):
132        return Markup(self.symbols[match])
133
134    # IWikiMacroProvider methods
135
136    def get_macros(self):
137        yield 'ShowSymbols'
138
139    #noinspection PyUnusedLocal
140    def get_macro_description(self, name):
141        return ("Renders in a table the list of known symbols. "
142                "Optional argument is the number of columns in the table "
143                "(defaults 3).")
144
145    #noinspection PyUnusedLocal
146    def expand_macro(self, formatter, name, content, args=None):
147        return render_table(self.symbols.keys(), content,
148                            lambda s: self._format_symbol(formatter, s, None),
149                            colspace=4)
Note: See TracBrowser for help on using the repository browser.