200
by Holger Rapp
Fixed line endings in some python files |
1 |
# -*- coding: UTF-8 -*-
|
2 |
||
3 |
"""
|
|
4 |
Post Markup
|
|
5 |
Author: Will McGugan (http://www.willmcgugan.com)
|
|
6 |
"""
|
|
7 |
||
438.1.6
by franku
run the script |
8 |
__version__ = '1.1.3' |
200
by Holger Rapp
Fixed line endings in some python files |
9 |
|
10 |
import re |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
11 |
from urllib.parse import quote, unquote, quote_plus |
12 |
from urllib.parse import urlparse, urlunparse |
|
200
by Holger Rapp
Fixed line endings in some python files |
13 |
|
14 |
pygments_available = True |
|
15 |
try: |
|
16 |
from pygments import highlight |
|
17 |
from pygments.lexers import get_lexer_by_name, ClassNotFound |
|
18 |
from pygments.formatters import HtmlFormatter |
|
19 |
except ImportError: |
|
20 |
# Make Pygments optional
|
|
21 |
pygments_available = False |
|
22 |
||
23 |
||
24 |
def annotate_link(domain): |
|
438.1.6
by franku
run the script |
25 |
"""This function is called by the url tag. Override to disable or change
|
26 |
behaviour.
|
|
200
by Holger Rapp
Fixed line endings in some python files |
27 |
|
28 |
domain -- Domain parsed from url
|
|
29 |
||
30 |
"""
|
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
31 |
return " [%s]" % _escape(domain) |
438.1.6
by franku
run the script |
32 |
|
33 |
||
34 |
re_url = re.compile( |
|
35 |
r"((https?):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)", re.MULTILINE | re.UNICODE) |
|
36 |
||
37 |
||
38 |
re_html = re.compile('<.*?>|\&.*?\;') |
|
39 |
||
40 |
||
200
by Holger Rapp
Fixed line endings in some python files |
41 |
def textilize(s): |
438.1.6
by franku
run the script |
42 |
"""Remove markup from html."""
|
43 |
return re_html.sub('', s) |
|
200
by Holger Rapp
Fixed line endings in some python files |
44 |
|
45 |
re_excerpt = re.compile(r'\[".*?\]+?.*?\[/".*?\]+?', re.DOTALL) |
|
46 |
re_remove_markup = re.compile(r'\[.*?\]', re.DOTALL) |
|
47 |
||
438.1.6
by franku
run the script |
48 |
|
200
by Holger Rapp
Fixed line endings in some python files |
49 |
def remove_markup(post): |
50 |
"""Removes html tags from a string."""
|
|
438.1.6
by franku
run the script |
51 |
return re_remove_markup.sub('', post) |
52 |
||
200
by Holger Rapp
Fixed line endings in some python files |
53 |
|
54 |
def get_excerpt(post): |
|
55 |
"""Returns an excerpt between ["] and [/"]
|
|
56 |
||
438.1.6
by franku
run the script |
57 |
post -- BBCode string
|
58 |
||
59 |
"""
|
|
200
by Holger Rapp
Fixed line endings in some python files |
60 |
|
61 |
match = re_excerpt.search(post) |
|
62 |
if match is None: |
|
438.1.6
by franku
run the script |
63 |
return '' |
200
by Holger Rapp
Fixed line endings in some python files |
64 |
excerpt = match.group(0) |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
65 |
excerpt = excerpt.replace('\n', "<br/>") |
200
by Holger Rapp
Fixed line endings in some python files |
66 |
return remove_markup(excerpt) |
67 |
||
438.1.6
by franku
run the script |
68 |
|
200
by Holger Rapp
Fixed line endings in some python files |
69 |
def strip_bbcode(bbcode): |
438.1.6
by franku
run the script |
70 |
"""Strips bbcode tags from a string.
|
200
by Holger Rapp
Fixed line endings in some python files |
71 |
|
72 |
bbcode -- A string to remove tags from
|
|
73 |
||
74 |
"""
|
|
75 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
76 |
return "".join([t[1] for t in PostMarkup.tokenize(bbcode) if t[0] == PostMarkup.TOKEN_TEXT]) |
200
by Holger Rapp
Fixed line endings in some python files |
77 |
|
78 |
||
79 |
def create(include=None, exclude=None, use_pygments=True, **kwargs): |
|
80 |
"""Create a postmarkup object that converts bbcode to XML snippets.
|
|
81 |
||
82 |
include -- List or similar iterable containing the names of the tags to use
|
|
83 |
If omitted, all tags will be used
|
|
84 |
exclude -- List or similar iterable containing the names of the tags to exclude.
|
|
85 |
If omitted, no tags will be excluded
|
|
86 |
use_pygments -- If True, Pygments (http://pygments.org/) will be used for the code tag,
|
|
87 |
otherwise it will use <pre>code</pre>
|
|
438.1.6
by franku
run the script |
88 |
|
200
by Holger Rapp
Fixed line endings in some python files |
89 |
"""
|
90 |
||
91 |
postmarkup = PostMarkup() |
|
92 |
postmarkup_add_tag = postmarkup.tag_factory.add_tag |
|
93 |
||
94 |
def add_tag(tag_class, name, *args, **kwargs): |
|
95 |
if include is None or name in include: |
|
96 |
if exclude is not None and name in exclude: |
|
97 |
return
|
|
98 |
postmarkup_add_tag(tag_class, name, *args, **kwargs) |
|
99 |
||
100 |
add_tag(SimpleTag, 'b', 'strong') |
|
101 |
add_tag(SimpleTag, 'i', 'em') |
|
102 |
add_tag(SimpleTag, 'u', 'u') |
|
103 |
add_tag(SimpleTag, 's', 'strike') |
|
104 |
||
105 |
add_tag(LinkTag, 'link', **kwargs) |
|
106 |
add_tag(LinkTag, 'url', **kwargs) |
|
107 |
||
108 |
add_tag(QuoteTag, 'quote') |
|
109 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
110 |
add_tag(SearchTag, 'wiki', |
111 |
"http://en.wikipedia.org/wiki/Special:Search?search=%s", 'wikipedia.com', **kwargs) |
|
112 |
add_tag(SearchTag, 'google', |
|
113 |
"http://www.google.com/search?hl=en&q=%s&btnG=Google+Search", 'google.com', **kwargs) |
|
114 |
add_tag(SearchTag, 'dictionary', |
|
115 |
"http://dictionary.reference.com/browse/%s", 'dictionary.com', **kwargs) |
|
116 |
add_tag(SearchTag, 'dict', |
|
117 |
"http://dictionary.reference.com/browse/%s", 'dictionary.com', **kwargs) |
|
118 |
||
119 |
add_tag(ImgTag, 'img') |
|
120 |
add_tag(ListTag, 'list') |
|
121 |
add_tag(ListItemTag, '*') |
|
122 |
||
123 |
add_tag(SizeTag, "size") |
|
124 |
add_tag(ColorTag, "color") |
|
125 |
add_tag(CenterTag, "center") |
|
200
by Holger Rapp
Fixed line endings in some python files |
126 |
|
127 |
if use_pygments: |
|
438.1.6
by franku
run the script |
128 |
assert pygments_available, 'Install Pygments (http://pygments.org/) or call create with use_pygments=False' |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
129 |
add_tag(PygmentsCodeTag, 'code', **kwargs) |
200
by Holger Rapp
Fixed line endings in some python files |
130 |
else: |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
131 |
add_tag(CodeTag, 'code', **kwargs) |
200
by Holger Rapp
Fixed line endings in some python files |
132 |
|
133 |
return postmarkup |
|
134 |
||
135 |
||
136 |
_postmarkup = None |
|
438.1.6
by franku
run the script |
137 |
|
138 |
||
139 |
def render_bbcode(bbcode, encoding='ascii', exclude_tags=None, auto_urls=True): |
|
200
by Holger Rapp
Fixed line endings in some python files |
140 |
"""Renders a bbcode string in to XHTML. This is a shortcut if you don't
|
141 |
need to customize any tags.
|
|
142 |
||
143 |
bbcode -- A string containing the bbcode
|
|
144 |
encoding -- If bbcode is not unicode, then then it will be encoded with
|
|
145 |
this encoding (defaults to 'ascii'). Ignore the encoding if you already have
|
|
146 |
a unicode string
|
|
147 |
||
148 |
"""
|
|
149 |
||
150 |
global _postmarkup |
|
151 |
if _postmarkup is None: |
|
152 |
_postmarkup = create(use_pygments=pygments_available) |
|
153 |
||
154 |
return _postmarkup(bbcode, encoding, exclude_tags=exclude_tags, auto_urls=auto_urls) |
|
155 |
||
156 |
||
157 |
class TagBase(object): |
|
158 |
||
159 |
def __init__(self, name, enclosed=False, auto_close=False, inline=False, strip_first_newline=False, **kwargs): |
|
160 |
"""Base class for all tags.
|
|
161 |
||
162 |
name -- The name of the bbcode tag
|
|
163 |
enclosed -- True if the contents of the tag should not be bbcode processed.
|
|
164 |
auto_close -- True if the tag is standalone and does not require a close tag.
|
|
165 |
inline -- True if the tag generates an inline html tag.
|
|
166 |
||
167 |
"""
|
|
168 |
||
169 |
self.name = name |
|
170 |
self.enclosed = enclosed |
|
171 |
self.auto_close = auto_close |
|
172 |
self.inline = inline |
|
173 |
self.strip_first_newline = strip_first_newline |
|
174 |
||
175 |
self.open_pos = None |
|
176 |
self.close_pos = None |
|
177 |
self.open_node_index = None |
|
178 |
self.close_node_index = None |
|
179 |
||
180 |
def open(self, parser, params, open_pos, node_index): |
|
438.1.6
by franku
run the script |
181 |
"""Called when the open tag is initially encountered."""
|
200
by Holger Rapp
Fixed line endings in some python files |
182 |
self.params = params |
183 |
self.open_pos = open_pos |
|
184 |
self.open_node_index = node_index |
|
185 |
||
186 |
def close(self, parser, close_pos, node_index): |
|
438.1.6
by franku
run the script |
187 |
"""Called when the close tag is initially encountered."""
|
200
by Holger Rapp
Fixed line endings in some python files |
188 |
self.close_pos = close_pos |
189 |
self.close_node_index = node_index |
|
190 |
||
191 |
def render_open(self, parser, node_index): |
|
438.1.6
by franku
run the script |
192 |
"""Called to render the open tag."""
|
200
by Holger Rapp
Fixed line endings in some python files |
193 |
pass
|
194 |
||
195 |
def render_close(self, parser, node_index): |
|
438.1.6
by franku
run the script |
196 |
"""Called to render the close tag."""
|
200
by Holger Rapp
Fixed line endings in some python files |
197 |
pass
|
198 |
||
199 |
def get_contents(self, parser): |
|
200 |
"""Returns the string between the open and close tag."""
|
|
201 |
return parser.markup[self.open_pos:self.close_pos] |
|
202 |
||
203 |
def get_contents_text(self, parser): |
|
438.1.6
by franku
run the script |
204 |
"""Returns the string between the the open and close tag, minus bbcode
|
205 |
tags."""
|
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
206 |
return "".join(parser.get_text_nodes(self.open_node_index, self.close_node_index)) |
200
by Holger Rapp
Fixed line endings in some python files |
207 |
|
208 |
def skip_contents(self, parser): |
|
209 |
"""Skips the contents of a tag while rendering."""
|
|
210 |
parser.skip_to_node(self.close_node_index) |
|
211 |
||
212 |
def __str__(self): |
|
438.1.6
by franku
run the script |
213 |
return '[%s]' % self.name |
200
by Holger Rapp
Fixed line endings in some python files |
214 |
|
215 |
||
216 |
class SimpleTag(TagBase): |
|
217 |
||
438.1.6
by franku
run the script |
218 |
"""A tag that can be rendered with a simple substitution."""
|
200
by Holger Rapp
Fixed line endings in some python files |
219 |
|
220 |
def __init__(self, name, html_name, **kwargs): |
|
221 |
""" html_name -- the html tag to substitute."""
|
|
222 |
TagBase.__init__(self, name, inline=True) |
|
223 |
self.html_name = html_name |
|
224 |
||
225 |
def render_open(self, parser, node_index): |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
226 |
return "<%s>" % self.html_name |
200
by Holger Rapp
Fixed line endings in some python files |
227 |
|
228 |
def render_close(self, parser, node_index): |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
229 |
return "</%s>" % self.html_name |
200
by Holger Rapp
Fixed line endings in some python files |
230 |
|
231 |
||
232 |
class DivStyleTag(TagBase): |
|
233 |
||
234 |
"""A simple tag that is replaces with a div and a style."""
|
|
235 |
||
236 |
def __init__(self, name, style, value, **kwargs): |
|
237 |
TagBase.__init__(self, name) |
|
238 |
self.style = style |
|
239 |
self.value = value |
|
240 |
||
241 |
def render_open(self, parser, node_index): |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
242 |
return '<div style="%s:%s;">' % (self.style, self.value) |
200
by Holger Rapp
Fixed line endings in some python files |
243 |
|
244 |
def render_close(self, parser, node_index): |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
245 |
return '</div>' |
200
by Holger Rapp
Fixed line endings in some python files |
246 |
|
247 |
||
248 |
class LinkTag(TagBase): |
|
249 |
||
250 |
def __init__(self, name, annotate_links=True, **kwargs): |
|
251 |
TagBase.__init__(self, name, inline=True) |
|
252 |
||
253 |
self.annotate_links = annotate_links |
|
254 |
||
255 |
def render_open(self, parser, node_index): |
|
256 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
257 |
self.domain = '' |
200
by Holger Rapp
Fixed line endings in some python files |
258 |
tag_data = parser.tag_data |
438.1.6
by franku
run the script |
259 |
nest_level = tag_data['link_nest_level'] = tag_data.setdefault( |
260 |
'link_nest_level', 0) + 1 |
|
200
by Holger Rapp
Fixed line endings in some python files |
261 |
|
262 |
if nest_level > 1: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
263 |
return "" |
200
by Holger Rapp
Fixed line endings in some python files |
264 |
|
265 |
if self.params: |
|
266 |
url = self.params.strip() |
|
267 |
else: |
|
268 |
url = self.get_contents_text(parser).strip() |
|
269 |
||
438.1.6
by franku
run the script |
270 |
self.domain = '' |
271 |
# Unquote the url
|
|
200
by Holger Rapp
Fixed line endings in some python files |
272 |
self.url = unquote(url) |
273 |
||
438.1.6
by franku
run the script |
274 |
# Disallow javascript links
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
275 |
if "javascript:" in self.url.lower(): |
438.1.6
by franku
run the script |
276 |
return '' |
200
by Holger Rapp
Fixed line endings in some python files |
277 |
|
438.1.6
by franku
run the script |
278 |
# Disallow non http: links
|
200
by Holger Rapp
Fixed line endings in some python files |
279 |
url_parsed = urlparse(self.url) |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
280 |
if url_parsed[0] and not url_parsed[0].lower().startswith('http'): |
438.1.6
by franku
run the script |
281 |
return '' |
200
by Holger Rapp
Fixed line endings in some python files |
282 |
|
438.1.6
by franku
run the script |
283 |
# Prepend http: if it is not present
|
200
by Holger Rapp
Fixed line endings in some python files |
284 |
if not url_parsed[0]: |
438.1.6
by franku
run the script |
285 |
self.url = 'http://' + self.url |
200
by Holger Rapp
Fixed line endings in some python files |
286 |
url_parsed = urlparse(self.url) |
287 |
||
438.1.6
by franku
run the script |
288 |
# Get domain
|
200
by Holger Rapp
Fixed line endings in some python files |
289 |
self.domain = url_parsed[1].lower() |
290 |
||
438.1.6
by franku
run the script |
291 |
# Remove www for brevity
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
292 |
if self.domain.startswith('www.'): |
200
by Holger Rapp
Fixed line endings in some python files |
293 |
self.domain = self.domain[4:] |
294 |
||
438.1.6
by franku
run the script |
295 |
# Quote the url
|
200
by Holger Rapp
Fixed line endings in some python files |
296 |
#self.url="http:"+urlunparse( map(quote, (u"",)+url_parsed[1:]) )
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
297 |
self.url = str(urlunparse( |
438.1.6
by franku
run the script |
298 |
[quote(component.encode('utf-8'), safe='/=&?:+') for component in url_parsed])) |
200
by Holger Rapp
Fixed line endings in some python files |
299 |
|
300 |
if not self.url: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
301 |
return "" |
200
by Holger Rapp
Fixed line endings in some python files |
302 |
|
303 |
if self.domain: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
304 |
return '<a href="%s">' % self.url |
200
by Holger Rapp
Fixed line endings in some python files |
305 |
else: |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
306 |
return "" |
200
by Holger Rapp
Fixed line endings in some python files |
307 |
|
308 |
def render_close(self, parser, node_index): |
|
309 |
||
310 |
tag_data = parser.tag_data |
|
311 |
tag_data['link_nest_level'] -= 1 |
|
312 |
||
313 |
if tag_data['link_nest_level'] > 0: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
314 |
return '' |
200
by Holger Rapp
Fixed line endings in some python files |
315 |
|
316 |
if self.domain: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
317 |
return '</a>' + self.annotate_link(self.domain) |
200
by Holger Rapp
Fixed line endings in some python files |
318 |
else: |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
319 |
return '' |
200
by Holger Rapp
Fixed line endings in some python files |
320 |
|
321 |
def annotate_link(self, domain=None): |
|
322 |
||
323 |
if domain and self.annotate_links: |
|
324 |
return annotate_link(domain) |
|
325 |
else: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
326 |
return "" |
200
by Holger Rapp
Fixed line endings in some python files |
327 |
|
328 |
||
329 |
class QuoteTag(TagBase): |
|
330 |
||
331 |
def __init__(self, name, **kwargs): |
|
332 |
TagBase.__init__(self, name, strip_first_newline=True) |
|
333 |
||
334 |
def open(self, parser, *args): |
|
335 |
TagBase.open(self, parser, *args) |
|
336 |
||
337 |
def close(self, parser, *args): |
|
338 |
TagBase.close(self, parser, *args) |
|
339 |
||
340 |
def render_open(self, parser, node_index): |
|
341 |
if self.params: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
342 |
return '<blockquote><em>%s</em><br/>' % (PostMarkup.standard_replace(self.params)) |
200
by Holger Rapp
Fixed line endings in some python files |
343 |
else: |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
344 |
return '<blockquote>' |
200
by Holger Rapp
Fixed line endings in some python files |
345 |
|
346 |
def render_close(self, parser, node_index): |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
347 |
return "</blockquote>" |
200
by Holger Rapp
Fixed line endings in some python files |
348 |
|
349 |
||
350 |
class SearchTag(TagBase): |
|
351 |
||
438.1.6
by franku
run the script |
352 |
def __init__(self, name, url, label='', annotate_links=True, **kwargs): |
200
by Holger Rapp
Fixed line endings in some python files |
353 |
TagBase.__init__(self, name, inline=True) |
354 |
self.url = url |
|
355 |
self.label = label |
|
356 |
self.annotate_links = annotate_links |
|
357 |
||
358 |
def render_open(self, parser, node_idex): |
|
359 |
||
360 |
if self.params: |
|
438.1.6
by franku
run the script |
361 |
search = self.params |
200
by Holger Rapp
Fixed line endings in some python files |
362 |
else: |
438.1.6
by franku
run the script |
363 |
search = self.get_contents(parser) |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
364 |
link = '<a href="%s">' % self.url |
365 |
if '%' in link: |
|
438.1.6
by franku
run the script |
366 |
return link % quote_plus(search.encode('UTF-8')) |
200
by Holger Rapp
Fixed line endings in some python files |
367 |
else: |
368 |
return link |
|
369 |
||
370 |
def render_close(self, parser, node_index): |
|
371 |
||
372 |
if self.label: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
373 |
ret = '</a>' |
200
by Holger Rapp
Fixed line endings in some python files |
374 |
if self.annotate_links: |
375 |
ret += annotate_link(self.label) |
|
376 |
return ret |
|
377 |
else: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
378 |
return '' |
200
by Holger Rapp
Fixed line endings in some python files |
379 |
|
380 |
||
381 |
class PygmentsCodeTag(TagBase): |
|
382 |
||
383 |
def __init__(self, name, pygments_line_numbers=False, **kwargs): |
|
384 |
TagBase.__init__(self, name, enclosed=True, strip_first_newline=True) |
|
385 |
self.line_numbers = pygments_line_numbers |
|
386 |
||
387 |
def render_open(self, parser, node_index): |
|
388 |
||
389 |
contents = self.get_contents(parser) |
|
390 |
self.skip_contents(parser) |
|
391 |
||
392 |
try: |
|
393 |
lexer = get_lexer_by_name(self.params, stripall=True) |
|
394 |
except ClassNotFound: |
|
395 |
contents = _escape(contents) |
|
396 |
return '<div class="code"><pre>%s</pre></div>' % contents |
|
397 |
||
438.1.6
by franku
run the script |
398 |
formatter = HtmlFormatter(linenos=self.line_numbers, cssclass='code') |
200
by Holger Rapp
Fixed line endings in some python files |
399 |
return highlight(contents, lexer, formatter) |
400 |
||
401 |
||
402 |
class CodeTag(TagBase): |
|
403 |
||
404 |
def __init__(self, name, **kwargs): |
|
405 |
TagBase.__init__(self, name, enclosed=True, strip_first_newline=True) |
|
406 |
||
407 |
def render_open(self, parser, node_index): |
|
408 |
||
409 |
contents = _escape_no_breaks(self.get_contents(parser)) |
|
410 |
self.skip_contents(parser) |
|
411 |
return '<div class="code"><pre>%s</pre></div>' % contents |
|
412 |
||
413 |
||
414 |
class ImgTag(TagBase): |
|
415 |
||
416 |
def __init__(self, name, **kwargs): |
|
417 |
TagBase.__init__(self, name, inline=True) |
|
418 |
||
419 |
def render_open(self, parser, node_index): |
|
420 |
||
421 |
contents = self.get_contents(parser) |
|
422 |
self.skip_contents(parser) |
|
423 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
424 |
contents = strip_bbcode(contents).replace('"', '%22') |
200
by Holger Rapp
Fixed line endings in some python files |
425 |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
426 |
return '<img src="%s"></img>' % contents |
200
by Holger Rapp
Fixed line endings in some python files |
427 |
|
428 |
||
429 |
class ListTag(TagBase): |
|
430 |
||
431 |
def __init__(self, name, **kwargs): |
|
432 |
TagBase.__init__(self, name, strip_first_newline=True) |
|
433 |
||
434 |
def open(self, parser, params, open_pos, node_index): |
|
435 |
TagBase.open(self, parser, params, open_pos, node_index) |
|
436 |
||
437 |
def close(self, parser, close_pos, node_index): |
|
438 |
TagBase.close(self, parser, close_pos, node_index) |
|
439 |
||
440 |
def render_open(self, parser, node_index): |
|
441 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
442 |
self.close_tag = "" |
200
by Holger Rapp
Fixed line endings in some python files |
443 |
|
444 |
tag_data = parser.tag_data |
|
438.1.6
by franku
run the script |
445 |
tag_data.setdefault('ListTag.count', 0) |
200
by Holger Rapp
Fixed line endings in some python files |
446 |
|
438.1.6
by franku
run the script |
447 |
if tag_data['ListTag.count']: |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
448 |
return "" |
200
by Holger Rapp
Fixed line endings in some python files |
449 |
|
438.1.6
by franku
run the script |
450 |
tag_data['ListTag.count'] += 1 |
451 |
||
452 |
tag_data['ListItemTag.initial_item'] = True |
|
453 |
||
454 |
if self.params == '1': |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
455 |
self.close_tag = "</li></ol>" |
456 |
return "<ol><li>" |
|
438.1.6
by franku
run the script |
457 |
elif self.params == 'a': |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
458 |
self.close_tag = "</li></ol>" |
459 |
return '<ol style="list-style-type: lower-alpha;"><li>' |
|
438.1.6
by franku
run the script |
460 |
elif self.params == 'A': |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
461 |
self.close_tag = "</li></ol>" |
462 |
return '<ol style="list-style-type: upper-alpha;"><li>' |
|
200
by Holger Rapp
Fixed line endings in some python files |
463 |
else: |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
464 |
self.close_tag = "</li></ul>" |
465 |
return "<ul><li>" |
|
200
by Holger Rapp
Fixed line endings in some python files |
466 |
|
467 |
def render_close(self, parser, node_index): |
|
468 |
||
469 |
tag_data = parser.tag_data |
|
438.1.6
by franku
run the script |
470 |
tag_data['ListTag.count'] -= 1 |
200
by Holger Rapp
Fixed line endings in some python files |
471 |
|
472 |
return self.close_tag |
|
473 |
||
474 |
||
475 |
class ListItemTag(TagBase): |
|
476 |
||
477 |
def __init__(self, name, **kwargs): |
|
478 |
TagBase.__init__(self, name) |
|
479 |
self.closed = False |
|
480 |
||
481 |
def render_open(self, parser, node_index): |
|
482 |
||
483 |
tag_data = parser.tag_data |
|
438.1.6
by franku
run the script |
484 |
if not tag_data.setdefault('ListTag.count', 0): |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
485 |
return "" |
200
by Holger Rapp
Fixed line endings in some python files |
486 |
|
438.1.6
by franku
run the script |
487 |
if tag_data['ListItemTag.initial_item']: |
488 |
tag_data['ListItemTag.initial_item'] = False |
|
200
by Holger Rapp
Fixed line endings in some python files |
489 |
return
|
490 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
491 |
return "</li><li>" |
200
by Holger Rapp
Fixed line endings in some python files |
492 |
|
493 |
||
494 |
class SizeTag(TagBase): |
|
495 |
||
438.1.6
by franku
run the script |
496 |
valid_chars = frozenset('0123456789') |
200
by Holger Rapp
Fixed line endings in some python files |
497 |
|
498 |
def __init__(self, name, **kwargs): |
|
499 |
TagBase.__init__(self, name, inline=True) |
|
500 |
||
501 |
def render_open(self, parser, node_index): |
|
502 |
||
503 |
try: |
|
438.1.6
by franku
run the script |
504 |
self.size = int( |
505 |
''.join([c for c in self.params if c in self.valid_chars])) |
|
200
by Holger Rapp
Fixed line endings in some python files |
506 |
except ValueError: |
507 |
self.size = None |
|
508 |
||
509 |
if self.size is None: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
510 |
return "" |
200
by Holger Rapp
Fixed line endings in some python files |
511 |
|
512 |
self.size = self.validate_size(self.size) |
|
513 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
514 |
return '<span style="font-size:%spx">' % self.size |
200
by Holger Rapp
Fixed line endings in some python files |
515 |
|
516 |
def render_close(self, parser, node_index): |
|
517 |
||
518 |
if self.size is None: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
519 |
return "" |
200
by Holger Rapp
Fixed line endings in some python files |
520 |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
521 |
return '</span>' |
200
by Holger Rapp
Fixed line endings in some python files |
522 |
|
523 |
def validate_size(self, size): |
|
524 |
||
525 |
size = min(64, size) |
|
526 |
size = max(4, size) |
|
527 |
return size |
|
528 |
||
529 |
||
530 |
class ColorTag(TagBase): |
|
531 |
||
438.1.6
by franku
run the script |
532 |
valid_chars = frozenset('#0123456789abcdefghijklmnopqrstuvwxyz') |
200
by Holger Rapp
Fixed line endings in some python files |
533 |
|
534 |
def __init__(self, name, **kwargs): |
|
535 |
TagBase.__init__(self, name, inline=True) |
|
536 |
||
537 |
def render_open(self, parser, node_index): |
|
538 |
||
539 |
valid_chars = self.valid_chars |
|
540 |
color = self.params.split()[0:1][0].lower() |
|
438.1.6
by franku
run the script |
541 |
self.color = ''.join([c for c in color if c in valid_chars]) |
200
by Holger Rapp
Fixed line endings in some python files |
542 |
|
543 |
if not self.color: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
544 |
return "" |
200
by Holger Rapp
Fixed line endings in some python files |
545 |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
546 |
return '<span style="color:%s">' % self.color |
200
by Holger Rapp
Fixed line endings in some python files |
547 |
|
548 |
def render_close(self, parser, node_index): |
|
549 |
||
550 |
if not self.color: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
551 |
return '' |
552 |
return '</span>' |
|
200
by Holger Rapp
Fixed line endings in some python files |
553 |
|
554 |
||
555 |
class CenterTag(TagBase): |
|
556 |
||
557 |
def render_open(self, parser, node_index, **kwargs): |
|
558 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
559 |
return '<div style="text-align:center">' |
200
by Holger Rapp
Fixed line endings in some python files |
560 |
|
561 |
def render_close(self, parser, node_index): |
|
562 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
563 |
return '</div>' |
200
by Holger Rapp
Fixed line endings in some python files |
564 |
|
565 |
# http://effbot.org/zone/python-replace.htm
|
|
438.1.6
by franku
run the script |
566 |
|
567 |
||
200
by Holger Rapp
Fixed line endings in some python files |
568 |
class MultiReplace: |
569 |
||
570 |
def __init__(self, repl_dict): |
|
571 |
||
572 |
# string to string mapping; use a regular expression
|
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
573 |
keys = list(repl_dict.keys()) |
438.1.6
by franku
run the script |
574 |
keys.sort() # lexical order |
575 |
keys.reverse() # use longest match first |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
576 |
pattern = "|".join([re.escape(key) for key in keys]) |
200
by Holger Rapp
Fixed line endings in some python files |
577 |
self.pattern = re.compile(pattern) |
578 |
self.dict = repl_dict |
|
579 |
||
580 |
def replace(self, s): |
|
581 |
# apply replacement dictionary to string
|
|
582 |
||
583 |
def repl(match, get=self.dict.get): |
|
584 |
item = match.group(0) |
|
585 |
return get(item, item) |
|
586 |
return self.pattern.sub(repl, s) |
|
587 |
||
588 |
__call__ = replace |
|
589 |
||
590 |
||
591 |
def _escape(s): |
|
592 |
return PostMarkup.standard_replace(s.rstrip('\n')) |
|
593 |
||
438.1.6
by franku
run the script |
594 |
|
200
by Holger Rapp
Fixed line endings in some python files |
595 |
def _escape_no_breaks(s): |
596 |
return PostMarkup.standard_replace_no_break(s.rstrip('\n')) |
|
597 |
||
438.1.6
by franku
run the script |
598 |
|
200
by Holger Rapp
Fixed line endings in some python files |
599 |
class TagFactory(object): |
600 |
||
601 |
def __init__(self): |
|
602 |
||
603 |
self.tags = {} |
|
604 |
||
605 |
@classmethod
|
|
606 |
def tag_factory_callable(cls, tag_class, name, *args, **kwargs): |
|
438.1.6
by franku
run the script |
607 |
"""Returns a callable that returns a new tag instance."""
|
200
by Holger Rapp
Fixed line endings in some python files |
608 |
def make(): |
609 |
return tag_class(name, *args, **kwargs) |
|
610 |
||
611 |
return make |
|
612 |
||
613 |
def add_tag(self, cls, name, *args, **kwargs): |
|
614 |
||
615 |
self.tags[name] = self.tag_factory_callable(cls, name, *args, **kwargs) |
|
616 |
||
617 |
def __getitem__(self, name): |
|
618 |
||
619 |
return self.tags[name]() |
|
620 |
||
621 |
def __contains__(self, name): |
|
622 |
||
623 |
return name in self.tags |
|
624 |
||
625 |
def get(self, name, default=None): |
|
626 |
||
627 |
if name in self.tags: |
|
628 |
return self.tags[name]() |
|
629 |
||
630 |
return default |
|
631 |
||
632 |
||
633 |
class _Parser(object): |
|
634 |
||
438.1.6
by franku
run the script |
635 |
"""This is an interface to the parser, used by Tag classes."""
|
200
by Holger Rapp
Fixed line endings in some python files |
636 |
|
637 |
def __init__(self, post_markup): |
|
638 |
||
639 |
self.pm = post_markup |
|
640 |
self.tag_data = {} |
|
641 |
self.render_node_index = 0 |
|
642 |
||
643 |
def skip_to_node(self, node_index): |
|
438.1.6
by franku
run the script |
644 |
"""Skips to a node, ignoring intermediate nodes."""
|
645 |
assert node_index is not None, 'Node index must be non-None' |
|
200
by Holger Rapp
Fixed line endings in some python files |
646 |
self.render_node_index = node_index |
647 |
||
648 |
def get_text_nodes(self, node1, node2): |
|
438.1.6
by franku
run the script |
649 |
"""Retrieves the text nodes between two node indices."""
|
200
by Holger Rapp
Fixed line endings in some python files |
650 |
|
651 |
if node2 is None: |
|
438.1.6
by franku
run the script |
652 |
node2 = node1 + 1 |
200
by Holger Rapp
Fixed line endings in some python files |
653 |
|
654 |
return [node for node in self.nodes[node1:node2] if not callable(node)] |
|
655 |
||
656 |
def begin_no_breaks(self): |
|
438.1.6
by franku
run the script |
657 |
"""Disables replacing of newlines with break tags at the start and end
|
658 |
of text nodes.
|
|
200
by Holger Rapp
Fixed line endings in some python files |
659 |
|
660 |
Can only be called from a tags 'open' method.
|
|
661 |
||
662 |
"""
|
|
438.1.6
by franku
run the script |
663 |
assert self.phase == 1, 'Can not be called from render_open or render_close' |
200
by Holger Rapp
Fixed line endings in some python files |
664 |
self.no_breaks_count += 1 |
665 |
||
666 |
def end_no_breaks(self): |
|
667 |
"""Re-enables auto-replacing of newlines with break tags (see begin_no_breaks)."""
|
|
668 |
||
438.1.6
by franku
run the script |
669 |
assert self.phase == 1, 'Can not be called from render_open or render_close' |
200
by Holger Rapp
Fixed line endings in some python files |
670 |
if self.no_breaks_count: |
671 |
self.no_breaks_count -= 1 |
|
672 |
||
673 |
||
674 |
class PostMarkup(object): |
|
675 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
676 |
standard_replace = MultiReplace({'<': '<', |
677 |
'>': '>', |
|
678 |
'&': '&', |
|
679 |
'\n': '<br/>'}) |
|
680 |
||
681 |
standard_replace_no_break = MultiReplace({'<': '<', |
|
682 |
'>': '>', |
|
683 |
'&': '&', }) |
|
684 |
||
685 |
TOKEN_TAG, TOKEN_PTAG, TOKEN_TEXT = list(range(3)) |
|
200
by Holger Rapp
Fixed line endings in some python files |
686 |
|
687 |
# I tried to use RE's. Really I did.
|
|
688 |
@classmethod
|
|
689 |
def tokenize(cls, post): |
|
690 |
||
691 |
text = True |
|
692 |
pos = 0 |
|
693 |
||
694 |
def find_first(post, pos, c): |
|
695 |
f1 = post.find(c[0], pos) |
|
696 |
f2 = post.find(c[1], pos) |
|
697 |
if f1 == -1: |
|
698 |
return f2 |
|
699 |
if f2 == -1: |
|
700 |
return f1 |
|
701 |
return min(f1, f2) |
|
702 |
||
703 |
while True: |
|
704 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
705 |
brace_pos = post.find('[', pos) |
200
by Holger Rapp
Fixed line endings in some python files |
706 |
if brace_pos == -1: |
438.1.6
by franku
run the script |
707 |
if pos < len(post): |
200
by Holger Rapp
Fixed line endings in some python files |
708 |
yield PostMarkup.TOKEN_TEXT, post[pos:], pos, len(post) |
709 |
return
|
|
710 |
if brace_pos - pos > 0: |
|
711 |
yield PostMarkup.TOKEN_TEXT, post[pos:brace_pos], pos, brace_pos |
|
712 |
||
713 |
pos = brace_pos |
|
438.1.6
by franku
run the script |
714 |
end_pos = pos + 1 |
200
by Holger Rapp
Fixed line endings in some python files |
715 |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
716 |
open_tag_pos = post.find('[', end_pos) |
717 |
end_pos = find_first(post, end_pos, ']=') |
|
200
by Holger Rapp
Fixed line endings in some python files |
718 |
if end_pos == -1: |
719 |
yield PostMarkup.TOKEN_TEXT, post[pos:], pos, len(post) |
|
720 |
return
|
|
721 |
||
722 |
if open_tag_pos != -1 and open_tag_pos < end_pos: |
|
723 |
yield PostMarkup.TOKEN_TEXT, post[pos:open_tag_pos], pos, open_tag_pos |
|
724 |
end_pos = open_tag_pos |
|
725 |
pos = end_pos |
|
726 |
continue
|
|
727 |
||
728 |
if post[end_pos] == ']': |
|
438.1.6
by franku
run the script |
729 |
yield PostMarkup.TOKEN_TAG, post[pos:end_pos + 1], pos, end_pos + 1 |
730 |
pos = end_pos + 1 |
|
200
by Holger Rapp
Fixed line endings in some python files |
731 |
continue
|
732 |
||
733 |
if post[end_pos] == '=': |
|
734 |
try: |
|
735 |
end_pos += 1 |
|
736 |
while post[end_pos] == ' ': |
|
737 |
end_pos += 1 |
|
738 |
if post[end_pos] != '"': |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
739 |
end_pos = post.find(']', end_pos + 1) |
200
by Holger Rapp
Fixed line endings in some python files |
740 |
if end_pos == -1: |
741 |
return
|
|
438.1.6
by franku
run the script |
742 |
yield PostMarkup.TOKEN_TAG, post[pos:end_pos + 1], pos, end_pos + 1 |
200
by Holger Rapp
Fixed line endings in some python files |
743 |
else: |
532.1.1
by franku
converted to python 3.6 using 2to3 script |
744 |
end_pos = find_first(post, end_pos, '"]') |
200
by Holger Rapp
Fixed line endings in some python files |
745 |
|
438.1.6
by franku
run the script |
746 |
if end_pos == -1: |
200
by Holger Rapp
Fixed line endings in some python files |
747 |
return
|
748 |
if post[end_pos] == '"': |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
749 |
end_pos = post.find('"', end_pos + 1) |
438.1.6
by franku
run the script |
750 |
if end_pos == -1: |
751 |
return
|
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
752 |
end_pos = post.find(']', end_pos + 1) |
438.1.6
by franku
run the script |
753 |
if end_pos == -1: |
754 |
return
|
|
755 |
yield PostMarkup.TOKEN_PTAG, post[pos:end_pos + 1], pos, end_pos + 1 |
|
200
by Holger Rapp
Fixed line endings in some python files |
756 |
else: |
438.1.6
by franku
run the script |
757 |
yield PostMarkup.TOKEN_TAG, post[pos:end_pos + 1], pos, end_pos |
758 |
pos = end_pos + 1 |
|
200
by Holger Rapp
Fixed line endings in some python files |
759 |
except IndexError: |
760 |
return
|
|
761 |
||
438.1.6
by franku
run the script |
762 |
def tagify_urls(self, postmarkup): |
763 |
"""Surrounds urls with url bbcode tags."""
|
|
200
by Holger Rapp
Fixed line endings in some python files |
764 |
|
765 |
def repl(match): |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
766 |
return '[url]%s[/url]' % match.group(0) |
200
by Holger Rapp
Fixed line endings in some python files |
767 |
|
768 |
text_tokens = [] |
|
769 |
for tag_type, tag_token, start_pos, end_pos in self.tokenize(postmarkup): |
|
770 |
||
771 |
if tag_type == PostMarkup.TOKEN_TEXT: |
|
772 |
text_tokens.append(re_url.sub(repl, tag_token)) |
|
773 |
else: |
|
774 |
text_tokens.append(tag_token) |
|
775 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
776 |
return "".join(text_tokens) |
200
by Holger Rapp
Fixed line endings in some python files |
777 |
|
778 |
def __init__(self, tag_factory=None): |
|
779 |
||
780 |
self.tag_factory = tag_factory or TagFactory() |
|
781 |
||
782 |
def default_tags(self): |
|
438.1.6
by franku
run the script |
783 |
"""Add some basic tags."""
|
200
by Holger Rapp
Fixed line endings in some python files |
784 |
|
785 |
add_tag = self.tag_factory.add_tag |
|
786 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
787 |
add_tag(SimpleTag, 'b', 'strong') |
788 |
add_tag(SimpleTag, 'i', 'em') |
|
789 |
add_tag(SimpleTag, 'u', 'u') |
|
790 |
add_tag(SimpleTag, 's', 's') |
|
200
by Holger Rapp
Fixed line endings in some python files |
791 |
|
792 |
def get_supported_tags(self): |
|
438.1.6
by franku
run the script |
793 |
"""Returns a list of the supported tags."""
|
200
by Holger Rapp
Fixed line endings in some python files |
794 |
|
795 |
return sorted(self.tag_factory.tags.keys()) |
|
796 |
||
797 |
def render_to_html(self, |
|
798 |
post_markup, |
|
438.1.6
by franku
run the script |
799 |
encoding='ascii', |
200
by Holger Rapp
Fixed line endings in some python files |
800 |
exclude_tags=None, |
801 |
auto_urls=True): |
|
802 |
"""Converts Post Markup to XHTML.
|
|
803 |
||
804 |
post_markup -- String containing bbcode.
|
|
805 |
encoding -- Encoding of string, defaults to "ascii".
|
|
806 |
exclude_tags -- A collection of tag names to ignore.
|
|
807 |
auto_urls -- If True, then urls will be wrapped with url bbcode tags.
|
|
808 |
||
809 |
"""
|
|
810 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
811 |
if not isinstance(post_markup, str): |
812 |
post_markup = str(post_markup, encoding, 'replace') |
|
200
by Holger Rapp
Fixed line endings in some python files |
813 |
|
814 |
if auto_urls: |
|
815 |
post_markup = self.tagify_urls(post_markup) |
|
816 |
||
817 |
parser = _Parser(self) |
|
818 |
parser.markup = post_markup |
|
819 |
||
820 |
if exclude_tags is None: |
|
821 |
exclude_tags = [] |
|
822 |
||
823 |
tag_factory = self.tag_factory |
|
824 |
||
825 |
nodes = [] |
|
826 |
parser.nodes = nodes |
|
827 |
||
828 |
parser.phase = 1 |
|
829 |
parser.no_breaks_count = 0 |
|
830 |
enclosed_count = 0 |
|
831 |
open_stack = [] |
|
832 |
tag_stack = [] |
|
833 |
break_stack = [] |
|
834 |
remove_next_newline = False |
|
835 |
||
836 |
def check_tag_stack(tag_name): |
|
837 |
||
838 |
for tag in reversed(tag_stack): |
|
839 |
if tag_name == tag.name: |
|
840 |
return True |
|
841 |
return False |
|
842 |
||
843 |
def redo_break_stack(): |
|
844 |
||
845 |
while break_stack: |
|
846 |
tag = break_stack.pop() |
|
847 |
open_tag(tag) |
|
848 |
tag_stack.append(tag) |
|
849 |
||
850 |
def break_inline_tags(): |
|
851 |
||
852 |
while tag_stack: |
|
853 |
if tag_stack[-1].inline: |
|
854 |
tag = tag_stack.pop() |
|
855 |
close_tag(tag) |
|
856 |
break_stack.append(tag) |
|
857 |
else: |
|
858 |
break
|
|
859 |
||
860 |
def open_tag(tag): |
|
861 |
def call(node_index): |
|
862 |
return tag.render_open(parser, node_index) |
|
863 |
nodes.append(call) |
|
864 |
||
865 |
def close_tag(tag): |
|
866 |
def call(node_index): |
|
867 |
return tag.render_close(parser, node_index) |
|
868 |
nodes.append(call) |
|
869 |
||
870 |
# Pass 1
|
|
871 |
for tag_type, tag_token, start_pos, end_pos in self.tokenize(post_markup): |
|
872 |
||
873 |
raw_tag_token = tag_token |
|
874 |
||
875 |
if tag_type == PostMarkup.TOKEN_TEXT: |
|
876 |
if parser.no_breaks_count: |
|
877 |
tag_token = tag_token.strip() |
|
878 |
if not tag_token: |
|
879 |
continue
|
|
880 |
if remove_next_newline: |
|
881 |
tag_token = tag_token.lstrip(' ') |
|
882 |
if tag_token.startswith('\n'): |
|
883 |
tag_token = tag_token.lstrip(' ')[1:] |
|
884 |
if not tag_token: |
|
885 |
continue
|
|
886 |
remove_next_newline = False |
|
887 |
||
888 |
if tag_stack and tag_stack[-1].strip_first_newline: |
|
889 |
tag_token = tag_token.lstrip() |
|
890 |
tag_stack[-1].strip_first_newline = False |
|
891 |
if not tag_stack[-1]: |
|
892 |
tag_stack.pop() |
|
893 |
continue
|
|
894 |
||
895 |
if not enclosed_count: |
|
896 |
redo_break_stack() |
|
897 |
||
898 |
nodes.append(self.standard_replace(tag_token)) |
|
899 |
continue
|
|
900 |
||
901 |
elif tag_type == PostMarkup.TOKEN_TAG: |
|
902 |
tag_token = tag_token[1:-1].lstrip() |
|
903 |
if ' ' in tag_token: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
904 |
tag_name, tag_attribs = tag_token.split(' ', 1) |
200
by Holger Rapp
Fixed line endings in some python files |
905 |
tag_attribs = tag_attribs.strip() |
906 |
else: |
|
907 |
if '=' in tag_token: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
908 |
tag_name, tag_attribs = tag_token.split('=', 1) |
200
by Holger Rapp
Fixed line endings in some python files |
909 |
tag_attribs = tag_attribs.strip() |
910 |
else: |
|
911 |
tag_name = tag_token |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
912 |
tag_attribs = "" |
200
by Holger Rapp
Fixed line endings in some python files |
913 |
else: |
914 |
tag_token = tag_token[1:-1].lstrip() |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
915 |
tag_name, tag_attribs = tag_token.split('=', 1) |
200
by Holger Rapp
Fixed line endings in some python files |
916 |
tag_attribs = tag_attribs.strip()[1:-1] |
917 |
||
918 |
tag_name = tag_name.strip().lower() |
|
919 |
||
920 |
end_tag = False |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
921 |
if tag_name.startswith('/'): |
200
by Holger Rapp
Fixed line endings in some python files |
922 |
end_tag = True |
923 |
tag_name = tag_name[1:] |
|
924 |
||
925 |
if enclosed_count and tag_stack[-1].name != tag_name: |
|
926 |
continue
|
|
927 |
||
928 |
if tag_name in exclude_tags: |
|
929 |
continue
|
|
930 |
||
931 |
if not end_tag: |
|
932 |
||
933 |
tag = tag_factory.get(tag_name, None) |
|
934 |
if tag is None: |
|
935 |
continue
|
|
936 |
||
937 |
redo_break_stack() |
|
938 |
||
939 |
if not tag.inline: |
|
940 |
break_inline_tags() |
|
941 |
||
942 |
tag.open(parser, tag_attribs, end_pos, len(nodes)) |
|
943 |
if tag.enclosed: |
|
944 |
enclosed_count += 1 |
|
945 |
tag_stack.append(tag) |
|
946 |
||
947 |
open_tag(tag) |
|
948 |
||
949 |
if tag.auto_close: |
|
950 |
tag = tag_stack.pop() |
|
438.1.6
by franku
run the script |
951 |
tag.close(self, start_pos, len(nodes) - 1) |
200
by Holger Rapp
Fixed line endings in some python files |
952 |
close_tag(tag) |
953 |
||
954 |
else: |
|
955 |
||
956 |
if break_stack and break_stack[-1].name == tag_name: |
|
957 |
break_stack.pop() |
|
958 |
tag.close(parser, start_pos, len(nodes)) |
|
959 |
elif check_tag_stack(tag_name): |
|
960 |
while tag_stack[-1].name != tag_name: |
|
961 |
tag = tag_stack.pop() |
|
962 |
break_stack.append(tag) |
|
963 |
close_tag(tag) |
|
964 |
||
965 |
tag = tag_stack.pop() |
|
966 |
tag.close(parser, start_pos, len(nodes)) |
|
967 |
if tag.enclosed: |
|
968 |
enclosed_count -= 1 |
|
969 |
||
970 |
close_tag(tag) |
|
971 |
||
972 |
if not tag.inline: |
|
973 |
remove_next_newline = True |
|
974 |
||
975 |
if tag_stack: |
|
976 |
redo_break_stack() |
|
977 |
while tag_stack: |
|
978 |
tag = tag_stack.pop() |
|
979 |
tag.close(parser, len(post_markup), len(nodes)) |
|
980 |
if tag.enclosed: |
|
981 |
enclosed_count -= 1 |
|
982 |
close_tag(tag) |
|
983 |
||
984 |
parser.phase = 2 |
|
985 |
# Pass 2
|
|
986 |
parser.nodes = nodes |
|
987 |
||
988 |
text = [] |
|
989 |
parser.render_node_index = 0 |
|
990 |
while parser.render_node_index < len(parser.nodes): |
|
991 |
i = parser.render_node_index |
|
992 |
node_text = parser.nodes[i] |
|
993 |
if callable(node_text): |
|
994 |
node_text = node_text(i) |
|
995 |
if node_text is not None: |
|
996 |
text.append(node_text) |
|
997 |
parser.render_node_index += 1 |
|
998 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
999 |
return "".join(text) |
200
by Holger Rapp
Fixed line endings in some python files |
1000 |
|
1001 |
__call__ = render_to_html |
|
1002 |
||
1003 |
||
1004 |
def _tests(): |
|
1005 |
||
1006 |
import sys |
|
1007 |
#sys.stdout=open('test.htm', 'w')
|
|
1008 |
||
1009 |
post_markup = create(use_pygments=True) |
|
1010 |
||
1011 |
tests = [] |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
1012 |
print("""<link rel="stylesheet" href="code.css" type="text/css" />\n""") |
200
by Holger Rapp
Fixed line endings in some python files |
1013 |
|
1014 |
tests.append(']') |
|
1015 |
tests.append('[') |
|
1016 |
tests.append(':-[ Hello, [b]World[/b]') |
|
1017 |
||
438.1.6
by franku
run the script |
1018 |
tests.append('[link=http://www.willmcgugan.com]My homepage[/link]') |
200
by Holger Rapp
Fixed line endings in some python files |
1019 |
tests.append('[link="http://www.willmcgugan.com"]My homepage[/link]') |
438.1.6
by franku
run the script |
1020 |
tests.append('[link http://www.willmcgugan.com]My homepage[/link]') |
1021 |
tests.append('[link]http://www.willmcgugan.com[/link]') |
|
200
by Holger Rapp
Fixed line endings in some python files |
1022 |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
1023 |
tests.append("[b]Hello AndrУЉ[/b]") |
1024 |
tests.append("[google]AndrУЉ[/google]") |
|
438.1.6
by franku
run the script |
1025 |
tests.append('[s]Strike through[/s]') |
1026 |
tests.append('[b]bold [i]bold and italic[/b] italic[/i]') |
|
1027 |
tests.append('[google]Will McGugan[/google]') |
|
1028 |
tests.append('[wiki Will McGugan]Look up my name in Wikipedia[/wiki]') |
|
200
by Holger Rapp
Fixed line endings in some python files |
1029 |
|
438.1.6
by franku
run the script |
1030 |
tests.append('[quote Will said...]BBCode is very cool[/quote]') |
200
by Holger Rapp
Fixed line endings in some python files |
1031 |
|
1032 |
tests.append("""[code python] |
|
1033 |
# A proxy object that calls a callback when converted to a string
|
|
1034 |
class TagStringify(object):
|
|
1035 |
def __init__(self, callback, raw):
|
|
1036 |
self.callback = callback
|
|
1037 |
self.raw = raw
|
|
1038 |
r[b]=3
|
|
1039 |
def __str__(self):
|
|
1040 |
return self.callback()
|
|
1041 |
def __repr__(self):
|
|
1042 |
return self.__str__()
|
|
1043 |
[/code]""") |
|
1044 |
||
532.1.1
by franku
converted to python 3.6 using 2to3 script |
1045 |
tests.append("[img]http://upload.wikimedia.org/wikipedia/commons" |
438.1.6
by franku
run the script |
1046 |
'/6/61/Triops_longicaudatus.jpg[/img]') |
1047 |
||
1048 |
tests.append('[list][*]Apples[*]Oranges[*]Pears[/list]') |
|
200
by Holger Rapp
Fixed line endings in some python files |
1049 |
tests.append("""[list=1] |
1050 |
[*]Apples
|
|
1051 |
[*]Oranges
|
|
1052 |
are not the only fruit
|
|
1053 |
[*]Pears
|
|
1054 |
[/list]""") |
|
438.1.6
by franku
run the script |
1055 |
tests.append('[list=a][*]Apples[*]Oranges[*]Pears[/list]') |
1056 |
tests.append('[list=A][*]Apples[*]Oranges[*]Pears[/list]') |
|
200
by Holger Rapp
Fixed line endings in some python files |
1057 |
|
438.1.6
by franku
run the script |
1058 |
long_test = """[b]Long test[/b] |
200
by Holger Rapp
Fixed line endings in some python files |
1059 |
|
1060 |
New lines characters are converted to breaks."""\
|
|
1061 |
"""Tags my be [b]ove[i]rl[/b]apped[/i].
|
|
1062 |
||
1063 |
[i]Open tags will be closed.
|
|
1064 |
[b]Test[/b]"""
|
|
1065 |
||
1066 |
tests.append(long_test) |
|
1067 |
||
438.1.6
by franku
run the script |
1068 |
tests.append('[dict]Will[/dict]') |
1069 |
||
1070 |
tests.append( |
|
1071 |
"[code unknownlanguage]10 print 'In yr code'; 20 goto 10[/code]") |
|
1072 |
||
1073 |
tests.append( |
|
1074 |
'[url=http://www.google.com/coop/cse?cx=006850030468302103399%3Amqxv78bdfdo]CakePHP Google Groups[/url]') |
|
1075 |
tests.append('[url=http://www.google.com/search?hl=en&safe=off&client=opera&rls=en&hs=pO1&q=python+bbcode&btnG=Search]Search for Python BBCode[/url]') |
|
200
by Holger Rapp
Fixed line endings in some python files |
1076 |
#tests = []
|
1077 |
# Attempt to inject html in to unicode
|
|
438.1.6
by franku
run the script |
1078 |
tests.append( |
1079 |
"[url=http://www.test.com/sfsdfsdf/ter?t=\"></a><h1>HACK</h1><a>\"]Test Hack[/url]") |
|
200
by Holger Rapp
Fixed line endings in some python files |
1080 |
|
438.1.6
by franku
run the script |
1081 |
tests.append( |
1082 |
'Nested urls, i.e. [url][url]www.becontrary.com[/url][/url], are condensed in to a single tag.') |
|
200
by Holger Rapp
Fixed line endings in some python files |
1083 |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
1084 |
tests.append('[google]ЩИЮВfvЮИУАsz[/google]') |
1085 |
||
1086 |
tests.append('[size 30]Hello, World![/size]') |
|
1087 |
||
1088 |
tests.append('[color red]This should be red[/color]') |
|
1089 |
tests.append('[color #0f0]This should be green[/color]') |
|
1090 |
tests.append("[center]This should be in the center!") |
|
200
by Holger Rapp
Fixed line endings in some python files |
1091 |
|
438.1.6
by franku
run the script |
1092 |
tests.append( |
1093 |
'Nested urls, i.e. [url][url]www.becontrary.com[/url][/url], are condensed in to a single tag.') |
|
200
by Holger Rapp
Fixed line endings in some python files |
1094 |
|
1095 |
#tests = []
|
|
1096 |
tests.append('[b]Hello, [i]World[/b]! [/i]') |
|
1097 |
||
1098 |
tests.append('[b][center]This should be centered![/center][/b]') |
|
1099 |
||
1100 |
tests.append('[list][*]Hello[i][*]World![/i][/list]') |
|
1101 |
||
1102 |
tests.append("""[list=1] |
|
1103 |
[*]Apples
|
|
1104 |
[*]Oranges
|
|
1105 |
are not the only fruit
|
|
1106 |
[*]Pears
|
|
1107 |
[/list]""") |
|
1108 |
||
438.1.6
by franku
run the script |
1109 |
tests.append( |
1110 |
'[b]urls such as http://www.willmcgugan.com are authomaticaly converted to links[/b]') |
|
200
by Holger Rapp
Fixed line endings in some python files |
1111 |
|
1112 |
tests.append(""" |
|
1113 |
[b]
|
|
1114 |
[code python]
|
|
1115 |
parser.markup[self.open_pos:self.close_pos]
|
|
1116 |
[/code]
|
|
1117 |
asdasdasdasdqweqwe
|
|
1118 |
""") |
|
1119 |
||
1120 |
tests.append("""[list 1] |
|
1121 |
[*]Hello
|
|
1122 |
[*]World
|
|
1123 |
[/list]""") |
|
1124 |
||
438.1.6
by franku
run the script |
1125 |
# tests=["""[b]b[i]i[/b][/i]"""]
|
200
by Holger Rapp
Fixed line endings in some python files |
1126 |
|
1127 |
for test in tests: |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
1128 |
print("<pre>%s</pre>" % str(test.encode('ascii', 'xmlcharrefreplace'))) |
1129 |
print("<p>%s</p>" % str(post_markup(test).encode('ascii', 'xmlcharrefreplace'))) |
|
1130 |
print("<hr/>") |
|
1131 |
print() |
|
1132 |
||
1133 |
print(repr(post_markup('[url=<script>Attack</script>]Attack[/url]'))) |
|
1134 |
||
1135 |
print(repr(post_markup('http://www.google.com/search?as_q=bbcode&btnG=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA'))) |
|
200
by Holger Rapp
Fixed line endings in some python files |
1136 |
|
1137 |
p = create(use_pygments=False) |
|
532.1.1
by franku
converted to python 3.6 using 2to3 script |
1138 |
print((p('[code]foo\nbar[/code]'))) |
200
by Holger Rapp
Fixed line endings in some python files |
1139 |
|
438.1.6
by franku
run the script |
1140 |
# print render_bbcode("[b]For the lazy, use the http://www.willmcgugan.com
|
1141 |
# render_bbcode function.[/b]")
|
|
200
by Holger Rapp
Fixed line endings in some python files |
1142 |
|
1143 |
||
1144 |
def _run_unittests(): |
|
1145 |
||
1146 |
# TODO: Expand tests for better coverage!
|
|
1147 |
||
1148 |
import unittest |
|
1149 |
||
1150 |
class TestPostmarkup(unittest.TestCase): |
|
1151 |
||
1152 |
def testsimpletag(self): |
|
1153 |
||
1154 |
postmarkup = create() |
|
1155 |
||
438.1.6
by franku
run the script |
1156 |
tests = [('[b]Hello[/b]', '<strong>Hello</strong>'), |
1157 |
('[i]Italic[/i]', '<em>Italic</em>'), |
|
1158 |
('[s]Strike[/s]', '<strike>Strike</strike>'), |
|
1159 |
('[u]underlined[/u]', '<u>underlined</u>'), |
|
200
by Holger Rapp
Fixed line endings in some python files |
1160 |
]
|
1161 |
||
1162 |
for test, result in tests: |
|
1163 |
self.assertEqual(postmarkup(test), result) |
|
1164 |
||
1165 |
def testoverlap(self): |
|
1166 |
||
1167 |
postmarkup = create() |
|
1168 |
||
438.1.6
by franku
run the script |
1169 |
tests = [('[i][b]Hello[/i][/b]', '<em><strong>Hello</strong></em>'), |
1170 |
('[b]bold [u]both[/b] underline[/u]', |
|
1171 |
'<strong>bold <u>both</u></strong><u> underline</u>') |
|
200
by Holger Rapp
Fixed line endings in some python files |
1172 |
]
|
1173 |
||
1174 |
for test, result in tests: |
|
1175 |
self.assertEqual(postmarkup(test), result) |
|
1176 |
||
1177 |
def testlinks(self): |
|
1178 |
||
1179 |
postmarkup = create(annotate_links=False) |
|
1180 |
||
438.1.6
by franku
run the script |
1181 |
tests = [('[link=http://www.willmcgugan.com]blog1[/link]', '<a href="http://www.willmcgugan.com">blog1</a>'), |
1182 |
('[link="http://www.willmcgugan.com"]blog2[/link]', |
|
1183 |
'<a href="http://www.willmcgugan.com">blog2</a>'), |
|
1184 |
('[link http://www.willmcgugan.com]blog3[/link]', |
|
1185 |
'<a href="http://www.willmcgugan.com">blog3</a>'), |
|
1186 |
('[link]http://www.willmcgugan.com[/link]', |
|
1187 |
'<a href="http://www.willmcgugan.com">http://www.willmcgugan.com</a>') |
|
200
by Holger Rapp
Fixed line endings in some python files |
1188 |
]
|
1189 |
||
1190 |
for test, result in tests: |
|
1191 |
self.assertEqual(postmarkup(test), result) |
|
1192 |
||
1193 |
suite = unittest.TestLoader().loadTestsFromTestCase(TestPostmarkup) |
|
1194 |
unittest.TextTestRunner(verbosity=2).run(suite) |
|
1195 |
||
1196 |
||
438.1.6
by franku
run the script |
1197 |
if __name__ == '__main__': |
200
by Holger Rapp
Fixed line endings in some python files |
1198 |
|
1199 |
_tests() |
|
1200 |
_run_unittests() |