yet better markmin has [[NEWLINE]], thanks Vladyslav

This commit is contained in:
mdipierro
2012-08-31 09:02:54 -05:00
parent 92ad68aad7
commit a017996aba
5 changed files with 160 additions and 95 deletions
+1 -1
View File
@@ -1 +1 @@
Version 2.0.3 (2012-08-31 00:31:48) stable Version 2.0.3 (2012-08-31 09:02:48) stable
+15
View File
@@ -33,6 +33,7 @@
'created by': 'created by', 'created by': 'created by',
'crontab': 'crontab', 'crontab': 'crontab',
'currently running': 'currently running', 'currently running': 'currently running',
'currently saved or': 'currently saved or',
'database administration': 'database administration', 'database administration': 'database administration',
'Debug': 'Debug', 'Debug': 'Debug',
'defines tables': 'defines tables', 'defines tables': 'defines tables',
@@ -43,17 +44,22 @@
'Detailed traceback description': 'Detailed traceback description', 'Detailed traceback description': 'Detailed traceback description',
'direction: ltr': 'direction: ltr', 'direction: ltr': 'direction: ltr',
'Disable': 'Disable', 'Disable': 'Disable',
'docs': 'docs',
'download layouts': 'download layouts', 'download layouts': 'download layouts',
'download plugins': 'download plugins', 'download plugins': 'download plugins',
'Edit': 'Edit', 'Edit': 'Edit',
'Edit application': 'Edit application', 'Edit application': 'Edit application',
'edit views:': 'edit views:',
'Editing file "%s"': 'Editing file "%s"',
'Error snapshot': 'Error snapshot', 'Error snapshot': 'Error snapshot',
'Error ticket': 'Error ticket', 'Error ticket': 'Error ticket',
'Errors': 'Errors', 'Errors': 'Errors',
'Exception instance attributes': 'Exception instance attributes', 'Exception instance attributes': 'Exception instance attributes',
'exposes': 'exposes', 'exposes': 'exposes',
'exposes:': 'exposes:',
'extends': 'extends', 'extends': 'extends',
'file does not exist': 'file does not exist', 'file does not exist': 'file does not exist',
'file saved on %s': 'file saved on %s',
'filter': 'filter', 'filter': 'filter',
'Frames': 'Frames', 'Frames': 'Frames',
'Get from URL:': 'Get from URL:', 'Get from URL:': 'Get from URL:',
@@ -64,8 +70,10 @@
'inspect attributes': 'inspect attributes', 'inspect attributes': 'inspect attributes',
'Install': 'Install', 'Install': 'Install',
'Installed applications': 'Installed applications', 'Installed applications': 'Installed applications',
'Key bindings': 'Key bindings',
'languages': 'languages', 'languages': 'languages',
'Languages': 'Languages', 'Languages': 'Languages',
'Last saved on:': 'Last saved on:',
'loading...': 'loading...', 'loading...': 'loading...',
'locals': 'locals', 'locals': 'locals',
'Login': 'Login', 'Login': 'Login',
@@ -89,10 +97,15 @@
'Reload routes': 'Reload routes', 'Reload routes': 'Reload routes',
'request': 'request', 'request': 'request',
'response': 'response', 'response': 'response',
'restore': 'restore',
'revert': 'revert',
'rules are not defined': 'rules are not defined', 'rules are not defined': 'rules are not defined',
'rules:': 'rules:', 'rules:': 'rules:',
"Run tests in this file (to run all files, you may also use the button labelled 'test')": "Run tests in this file (to run all files, you may also use the button labelled 'test')", "Run tests in this file (to run all files, you may also use the button labelled 'test')": "Run tests in this file (to run all files, you may also use the button labelled 'test')",
'Running on %s': 'Running on %s', 'Running on %s': 'Running on %s',
'Save': 'Save',
'Save via Ajax': 'Save via Ajax',
'Saved file hash:': 'Saved file hash:',
'session': 'session', 'session': 'session',
'shell': 'shell', 'shell': 'shell',
'Site': 'Site', 'Site': 'Site',
@@ -110,7 +123,9 @@
'These files are served without processing, your images go here': 'These files are served without processing, your images go here', 'These files are served without processing, your images go here': 'These files are served without processing, your images go here',
'Ticket ID': 'Ticket ID', 'Ticket ID': 'Ticket ID',
'Ticket Missing': 'Ticket Missing', 'Ticket Missing': 'Ticket Missing',
'to previous version.': 'to previous version.',
'To create a plugin, name a file/folder plugin_[name]': 'To create a plugin, name a file/folder plugin_[name]', 'To create a plugin, name a file/folder plugin_[name]': 'To create a plugin, name a file/folder plugin_[name]',
'toggle breakpoint': 'toggle breakpoint',
'Traceback': 'Traceback', 'Traceback': 'Traceback',
'Translation strings for the application': 'Translation strings for the application', 'Translation strings for the application': 'Translation strings for the application',
'Uninstall': 'Uninstall', 'Uninstall': 'Uninstall',
+143 -89
View File
@@ -1,4 +1,4 @@
#!/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# created by Massimo Di Pierro # created by Massimo Di Pierro
# recreated by Vladyslav Kozlovskyy # recreated by Vladyslav Kozlovskyy
@@ -44,8 +44,8 @@ from markmin2pdf import markmin2pdf # requires pdflatex
print markmin2pdf(m) print markmin2pdf(m)
`` ``
==================== ====================
# This is a test block with new features: # This is a test block
with new features:
This is a blockquote with This is a blockquote with
a list with tables in it: a list with tables in it:
----------- -----------
@@ -71,7 +71,9 @@ a list with tables in it:
-----------:blockquoteclass[blockquoteid] -----------:blockquoteclass[blockquoteid]
This this a new paragraph This this a new paragraph
with a table. Table has header, footer, sections, odd and even rows: with a followed table.
Table has header, footer, sections,
odd and even rows:
------------------------------- -------------------------------
**Title 1**|**Title 2**|**Title 3** **Title 1**|**Title 2**|**Title 3**
============================== ==============================
@@ -98,6 +100,8 @@ Now lists can be multilevel:
You can continue item text on You can continue item text on
next strings next strings
. paragraph in an item
++. Ordered item 1 of sublevel 2 with ++. Ordered item 1 of sublevel 2 with
a paragraph (paragraph can start a paragraph (paragraph can start
with point after plus or minus with point after plus or minus
@@ -143,13 +147,13 @@ line 1
line 2 line 2
line 3 line 3
`` ``
++++. Yet another item with code block: ++++. Yet another item with code block (we need to indent \`\` to add code block as part of item):
`` ``
line 1 line 1
line 2 line 2
line 3 line 3
`` ``
This item finishes with this paragraph. This item finishes with this paragraph.
... Item in sublevel 3 can be continued with paragraphs. ... Item in sublevel 3 can be continued with paragraphs.
@@ -201,7 +205,7 @@ We wanted a markup language with the following requirements:
- support table, ul, ol, code - support table, ul, ol, code
- support html5 video and audio elements (html serialization only) - support html5 video and audio elements (html serialization only)
- can align images and resize them - can align images and resize them
- can specify class for tables and code elements - can specify class for tables, blockquotes and code elements
- can add anchors - can add anchors
- does not use _ for markup (since it creates odd behavior) - does not use _ for markup (since it creates odd behavior)
- automatically links urls - automatically links urls
@@ -420,6 +424,23 @@ generates
(the ``!`!`...`!`!:custom`` block is rendered by the ``custom=lambda`` function passed to ``render``). (the ``!`!`...`!`!:custom`` block is rendered by the ``custom=lambda`` function passed to ``render``).
### Line breaks
``[[NEWLINE]]`` tag is used to break lines:
``
#### Multiline [[NEWLINE]]
title
paragraph [[NEWLINE]]
with breaks[[NEWLINE]]in it
``
generates:
#### Multiline [[NEWLINE]]
title
paragraph [[NEWLINE]]
with breaks[[NEWLINE]]in it
### Html5 support ### Html5 support
Markmin also supports the <video> and <audio> html5 tags using the notation: Markmin also supports the <video> and <audio> html5 tags using the notation:
@@ -430,7 +451,7 @@ Markmin also supports the <video> and <audio> html5 tags using the notation:
[[message [title] link video]] [[message [title] link video]]
[[message [title] link audio]] [[message [title] link audio]]
`` ``
where ``message`` will be shown in brousers without HTML5 video/audio tags support. where ``message`` will be shown in browsers without HTML5 video/audio tags support.
### Latex and other extensions ### Latex and other extensions
@@ -512,18 +533,18 @@ DISABLED_META = '\x08'
LATEX = '<img src="http://chart.apis.google.com/chart?cht=tx&chl=%s" />' LATEX = '<img src="http://chart.apis.google.com/chart?cht=tx&chl=%s" />'
regex_URL=re.compile(r'@/(?P<a>\w*)/(?P<c>\w*)/(?P<f>\w*(\.\w+)?)(/(?P<args>[\w\.\-/]+))?') regex_URL=re.compile(r'@/(?P<a>\w*)/(?P<c>\w*)/(?P<f>\w*(\.\w+)?)(/(?P<args>[\w\.\-/]+))?')
regex_env=re.compile(r'@\{(?P<a>[\w\-\.]+?)(\:(?P<b>.*?))?\}') regex_env=re.compile(r'@\{(?P<a>[\w\-\.]+?)(\:(?P<b>.*?))?\}')
regex_expand_meta = re.compile('('+META+'|'+DISABLED_META+')') regex_expand_meta = re.compile('('+META+'|'+DISABLED_META+'|````)')
regex_dd=re.compile(r'\$\$(?P<latex>.*?)\$\$') regex_dd=re.compile(r'\$\$(?P<latex>.*?)\$\$')
regex_code = re.compile('('+META+'|'+DISABLED_META+r')|(``(?P<t>.+?)``(?::(?P<c>[a-zA-Z][_a-zA-Z\-\d]*)(?:\[(?P<p>[^\]]*)\])?)?)',re.S) regex_code = re.compile('('+META+'|'+DISABLED_META+r'|````)|(``(?P<t>.+?)``(?::(?P<c>[a-zA-Z][_a-zA-Z\-\d]*)(?:\[(?P<p>[^\]]*)\])?)?)',re.S)
regex_strong=re.compile(r'\*\*(?P<t>[^\s*]+( +[^\s*]+)*)\*\*') regex_strong=re.compile(r'\*\*(?P<t>[^\s*]+( +[^\s*]+)*)\*\*')
regex_del=re.compile(r'~~(?P<t>[^\s*]+( +[^\s*]+)*)~~') regex_del=re.compile(r'~~(?P<t>[^\s*]+( +[^\s*]+)*)~~')
regex_em=re.compile(r"''(?P<t>[^\s']+(?: +[^\s']+)*)''") regex_em=re.compile(r"''(?P<t>[^\s']+(?: +[^\s']+)*)''")
regex_num=re.compile(r"^\s*[+-]?((\d+(\.\d*)?)|\.\d+)([eE][+-]?[0-9]+)?\s*$") regex_num=re.compile(r"^\s*[+-]?((\d+(\.\d*)?)|\.\d+)([eE][+-]?[0-9]+)?\s*$")
regex_list=re.compile('^(?:(#{1,6}|\.+ |\++ |\++\. |\-+ |\-+\. )\s*)?(.*)$') regex_list=re.compile('^(?:(?:(#{1,6})|(?:(\.+|\++|\-+)(\.)?))\s+)?(.*)$')
regex_bq_headline=re.compile('^(?:(\.+|\++|\-+)(\.)?\s+)?(-{3}-*)$') regex_bq_headline=re.compile('^(?:(\.+|\++|\-+)(\.)?\s+)?(-{3}-*)$')
regex_tq=re.compile('^(-{3}-*)(?::(?P<c>[a-zA-Z][_a-zA-Z\-\d]*)(?:\[(?P<p>[a-zA-Z][_a-zA-Z\-\d]*)\])?)?$') regex_tq=re.compile('^(-{3}-*)(?::(?P<c>[a-zA-Z][_a-zA-Z\-\d]*)(?:\[(?P<p>[a-zA-Z][_a-zA-Z\-\d]*)\])?)?$')
regex_proto = re.compile(r'(?<!["\w>/=])(?P<p>\w+):(?P<k>\w+://[\w\d\-+=?%&/:.]+)', re.M) regex_proto = re.compile(r'(?<!["\w>/=])(?P<p>\w+):(?P<k>\w+://[\w\d\-+=?%&/:.]+)', re.M)
regex_auto = re.compile(r'(?<!["\w>/=])(?P<k>\w+://[^\s\'\"\]\}\)]+)',re.M) regex_auto = re.compile(r'(?<!["\w>/=])(?P<k>\w+://[\w\d\-+_=?%&/:.]+)',re.M)
regex_link=re.compile(r'('+LINK+r')|\[\[(?P<s>.+?)\]\]') regex_link=re.compile(r'('+LINK+r')|\[\[(?P<s>.+?)\]\]')
regex_link_level2=re.compile(r'^(?P<t>\S.*?)?(?:\s+\[(?P<a>.+?)\])?(?:\s+(?P<k>\S+))?(?:\s+(?P<p>popup))?\s*$') regex_link_level2=re.compile(r'^(?P<t>\S.*?)?(?:\s+\[(?P<a>.+?)\])?(?:\s+(?P<k>\S+))?(?:\s+(?P<p>popup))?\s*$')
regex_media_level2=re.compile(r'^(?P<t>\S.*?)?(?:\s+\[(?P<a>.+?)\])?(?:\s+(?P<k>\S+))?\s+(?P<p>img|IMG|left|right|center|video|audio)(?:\s+(?P<w>\d+px))?\s*$') regex_media_level2=re.compile(r'^(?P<t>\S.*?)?(?:\s+\[(?P<a>.+?)\])?(?:\s+(?P<k>\S+))?\s+(?P<p>img|IMG|left|right|center|video|audio)(?:\s+(?P<w>\d+px))?\s*$')
@@ -579,7 +600,8 @@ def render(text,
autolinks='default', autolinks='default',
protolinks='default', protolinks='default',
class_prefix='', class_prefix='',
id_prefix='markmin_'): id_prefix='markmin_',
pretty_print=False):
""" """
Arguments: Arguments:
- text is the text to be processed - text is the text to be processed
@@ -598,7 +620,7 @@ def render(text,
- class_prefix is a prefix for ALL classes in markmin text. E.g. if class_prefix='my_' - class_prefix is a prefix for ALL classes in markmin text. E.g. if class_prefix='my_'
then for ``test``:cls class will be changed to "my_cls" (default value is '') then for ``test``:cls class will be changed to "my_cls" (default value is '')
- id_prefix is prefix for ALL ids in markmin text (default value is 'markmin_'). E.g.: - id_prefix is prefix for ALL ids in markmin text (default value is 'markmin_'). E.g.:
-- [[id]] will be converted to <div class="anchor" id="markmin_id"></div> -- [[id]] will be converted to <a name="markmin_id"></a>
-- [[link #id]] will be converted to <a href="#markmin_id">link</a> -- [[link #id]] will be converted to <a href="#markmin_id">link</a>
-- ``test``:cls[id] will be converted to <code class="cls" id="markmin_id">test</code> -- ``test``:cls[id] will be converted to <code class="cls" id="markmin_id">test</code>
@@ -791,9 +813,18 @@ def render(text,
>>> render('[[id1 [span **messag** in ''markmin''] ]] ... [[**link** to id [link\\\'s title] #mark1]]') >>> render('[[id1 [span **messag** in ''markmin''] ]] ... [[**link** to id [link\\\'s title] #mark1]]')
'<p><div class="anchor" id="markmin_id1">span <strong>messag</strong> in markmin</div> ... <a href="#markmin_mark1" title="link\\\'s title"><strong>link</strong> to id</a></p>' '<p><div class="anchor" id="markmin_id1">span <strong>messag</strong> in markmin</div> ... <a href="#markmin_mark1" title="link\\\'s title"><strong>link</strong> to id</a></p>'
>>> render('# Multiline[[NEWLINE]]\\n title\\nParagraph[[NEWLINE]]\\nwith breaks[[NEWLINE]]\\nin it')
'<h1>Multiline<br /> title</h1><p>Paragraph<br /> with breaks<br /> in it</p>'
>>> render("anchor with name 'NEWLINE': [[NEWLINE [ ] ]]")
'<p>anchor with name \\'NEWLINE\\': <div class="anchor" id="markmin_NEWLINE"></div></p>'
>>> render("anchor with name 'NEWLINE': [[NEWLINE [newline] ]]")
'<p>anchor with name \\'NEWLINE\\': <div class="anchor" id="markmin_NEWLINE">newline</div></p>'
""" """
if autolinks=="default": autolinks = autolinks_simple if autolinks=="default": autolinks = autolinks_simple
if protolinks=="default": protolinks = protolinks_simple if protolinks=="default": protolinks = protolinks_simple
pp='\n' if pretty_print else ''
text = str(text or '') text = str(text or '')
text = regex_backslash.sub(lambda m: m.group(1).translate(ttab_in), text) text = regex_backslash.sub(lambda m: m.group(1).translate(ttab_in), text)
@@ -801,11 +832,22 @@ def render(text,
# this is experimental @{function/args} # this is experimental @{function/args}
# turns into a digitally signed URL # turns into a digitally signed URL
def u1(match,URL=URL): def u1(match,URL=URL):
a,c,f,args = match.group('a','c','f','args') a,c,f,args = match.group('a','c','f','args')
return URL(a=a or None,c=c or None,f = f or None, return URL(a=a or None,c=c or None,f = f or None,
args=args.split('/'), scheme=True, host=True) args=args.split('/'), scheme=True, host=True)
text = regex_URL.sub(u1,text) text = regex_URL.sub(u1,text)
if environment:
def u2(match, environment=environment):
f = environment.get(match.group('a'), match.group(0))
if callable(f):
try:
f = f(match.group('b'))
except Exception, e:
f = 'ERROR: %s' % e
return str(f)
text = regex_env.sub(u2, text)
if latex == 'google': if latex == 'google':
text = regex_dd.sub('``\g<latex>``:latex ', text) text = regex_dd.sub('``\g<latex>``:latex ', text)
@@ -816,9 +858,12 @@ def render(text,
segments = [] segments = []
def mark_code(m): def mark_code(m):
g = m.group(0) g = m.group(0)
if m.group() in ( META, DISABLED_META ): if g in (META, DISABLED_META ):
segments.append((None, None, None, g)) segments.append((None, None, None, g))
return m.group() return m.group()
elif g == '````':
segments.append((None, None, None, ''))
return m.group()
else: else:
c = m.group('c') or '' c = m.group('c') or ''
p = m.group('p') or '' p = m.group('p') or ''
@@ -849,13 +894,13 @@ def render(text,
############################################################# #############################################################
# normalize spaces # normalize spaces
############################################################# #############################################################
strings=[t.strip() for t in text.split('\n')] strings=text.split('\n')
def parse_title(t, s): #out, lev, etags, tag, s): def parse_title(t, s): #out, lev, etags, tag, s):
hlevel=str(len(t)) hlevel=str(len(t))
out.extend(etags[::-1]) out.extend(etags[::-1])
out.append("<h%s>%s"%(hlevel,s)) out.append("<h%s>%s"%(hlevel,s))
etags[:]=["</h%s>"%hlevel] etags[:]=["</h%s>%s"%(hlevel,pp)]
lev=0 lev=0
ltags[:]=[] ltags[:]=[]
tlev[:]=[] tlev[:]=[]
@@ -880,8 +925,8 @@ def render(text,
out.append(etags.pop()) out.append(etags.pop())
ltags.pop() ltags.pop()
for i in xrange(lent-lev): for i in xrange(lent-lev):
out.append('<'+tag+'>') out.append('<'+tag+'>'+pp)
etags.append('</'+tag+'>') etags.append('</'+tag+'>'+pp)
lev+=1 lev+=1
ltags.append(lev) ltags.append(lev)
tlev.append(tag) tlev.append(tag)
@@ -892,8 +937,8 @@ def render(text,
ltags.pop() ltags.pop()
out.append(etags.pop()) out.append(etags.pop())
tlev[-1]=tag tlev[-1]=tag
out.append('<'+tag+'>') out.append('<'+tag+'>'+pp)
etags.append('</'+tag+'>') etags.append('</'+tag+'>'+pp)
ltags.append(lev) ltags.append(lev)
else: else:
if ltags.count(lev)>1: if ltags.count(lev)>1:
@@ -901,7 +946,7 @@ def render(text,
ltags.pop() ltags.pop()
mtag='l' mtag='l'
out.append('<li>') out.append('<li>')
etags.append('</li>') etags.append('</li>'+pp)
ltags.append(lev) ltags.append(lev)
if s[:1] == '-': if s[:1] == '-':
(s, mtag, lineno) = parse_table_or_blockquote(s, mtag, lineno) (s, mtag, lineno) = parse_table_or_blockquote(s, mtag, lineno)
@@ -954,7 +999,7 @@ def render(text,
return (s, mtag, lineno) return (s, mtag, lineno)
lineno+=1 lineno+=1
s = strings[lineno] s = strings[lineno].strip()
if s: if s:
if '|' in s: if '|' in s:
# table # table
@@ -967,7 +1012,7 @@ def render(text,
# parse table: # parse table:
while lineno < strings_len: while lineno < strings_len:
s = strings[lineno] s = strings[lineno].strip()
if s[:1] == '=': if s[:1] == '=':
if s.count('=')==len(s) and len(s)>3: # header or footer if s.count('=')==len(s) and len(s)>3: # header or footer
if not thead: # if thead list is empty: if not thead: # if thead list is empty:
@@ -994,7 +1039,7 @@ def render(text,
if regex_num.match(f) if regex_num.match(f)
else '', else '',
f.strip() f.strip()
) for f in s.split('|')])+'</tr>') ) for f in s.split('|')])+'</tr>'+pp)
rownum+=1 rownum+=1
lineno+=1 lineno+=1
@@ -1002,15 +1047,15 @@ def render(text,
t_id = ' id="%s%s"'%(id_prefix, t_id) if t_id else '' t_id = ' id="%s%s"'%(id_prefix, t_id) if t_id else ''
s = '' s = ''
if thead: if thead:
s += '<thead>'+''.join([l for l in thead])+'</thead>' s += '<thead>'+pp+''.join([l for l in thead])+'</thead>'+pp
if not tbody: # tbody strings are in tout list if not tbody: # tbody strings are in tout list
tbody = tout tbody = tout
tout = [] tout = []
if tbody: # if tbody list is not empty: if tbody: # if tbody list is not empty:
s += '<tbody>'+''.join([l for l in tbody])+'</tbody>' s += '<tbody>'+pp+''.join([l for l in tbody])+'</tbody>'+pp
if tout: # tfoot is not empty: if tout: # tfoot is not empty:
s += '<tfoot>'+''.join([l for l in tout])+'</tfoot>' s += '<tfoot>'+pp+''.join([l for l in tout])+'</tfoot>'+pp
s = '<table%s%s>%s</table>' % (t_cls, t_id, s) s = '<table%s%s>%s%s</table>%s' % (t_cls, t_id, pp, s, pp)
mtag='t' mtag='t'
else: else:
# parse blockquote: # parse blockquote:
@@ -1021,7 +1066,7 @@ def render(text,
# search blockquote closing line: # search blockquote closing line:
while lineno < strings_len: while lineno < strings_len:
s = strings[lineno] s = strings[lineno].strip()
if not t_mode: if not t_mode:
m = regex_tq.match(s) m = regex_tq.match(s)
if m: if m:
@@ -1031,7 +1076,7 @@ def render(text,
break break
if regex_bq_headline.match(s): if regex_bq_headline.match(s):
if lineno+1 < strings_len and strings[lineno+1]: if lineno+1 < strings_len and strings[lineno+1].strip():
t_mode = True t_mode = True
lineno+=1 lineno+=1
continue continue
@@ -1044,7 +1089,7 @@ def render(text,
t_cls = ' class="%s%s"'%(class_prefix,t_cls) if t_cls and t_cls != 'id' else '' t_cls = ' class="%s%s"'%(class_prefix,t_cls) if t_cls and t_cls != 'id' else ''
t_id = ' id="%s%s"'%(id_prefix,t_id) if t_id else '' t_id = ' id="%s%s"'%(id_prefix,t_id) if t_id else ''
s = '<blockquote%s%s>%s</blockquote>' \ s = '<blockquote%s%s>%s</blockquote>%s' \
% (t_cls, % (t_cls,
t_id, t_id,
render('\n'.join(strings[bq_begin:lineno]), render('\n'.join(strings[bq_begin:lineno]),
@@ -1057,7 +1102,9 @@ def render(text,
autolinks, autolinks,
protolinks, protolinks,
class_prefix, class_prefix,
id_prefix) id_prefix,
pretty_print),
pp
) )
mtag='q' mtag='q'
else: else:
@@ -1068,53 +1115,58 @@ def render(text,
if sep == 'p': if sep == 'p':
pbeg = "<p>" pbeg = "<p>"
pend = "</p>" pend = "</p>"+pp
br = '' br = ''
else: else:
pbeg = pend = '' pbeg = pend = ''
br = "<br />" if sep=='br' else '' br = "<br />"+pp if sep=='br' else ''
lev = 0 # рівень вкладеності списків lev = 0 # nesting level of lists
c0 = '' # перший символ поточного рядка c0 = '' # first character of current line
out = [] # результуючий список рядків out = [] # list of processed lines
etags = [] # завершуючі таги etags = [] # trailing tags
ltags = [] # номер рівня відповідний завершуючому тагу ltags = [] # level# correspondent to trailing tag
tlev = [] # таг рівня ('ul' або 'ol') tlev = [] # list of tags for each level ('ul' or 'ol')
mtag = '' # marked tag (~last tag) ('l','.','h','p','t'). Used for set <br/> mtag = '' # marked tag (~last tag) ('l','.','h','p','t'). Used to set <br/>
# and for avoid <p></p> around tables and blockquotes # and to avoid <p></p> around tables and blockquotes
lineno = 0 lineno = 0
strings_len = len(strings) strings_len = len(strings)
while lineno < strings_len: while lineno < strings_len:
s = strings[lineno] s0 = strings[lineno][:1]
s = strings[lineno].strip()
""" # + - . --------------------- """ # + - . ---------------------
## ++ -- .. ------- field | field | field <-title ## ++ -- .. ------- field | field | field <-title
### +++ --- ... quote ===================== ### +++ --- ... quote =====================
#### ++++ ---- .... ------- field | field | field <-body #### ++++ ---- .... ------- field | field | field <-body
##### +++++ ----- ..... ---------------------:class[id] ##### +++++ ----- ..... ---------------------:class[id]
""" """
pc0=c0 # перший символ попереднього рядка pc0=c0 # first character of previous line
c0=s[:1] c0=s[:1]
if c0: # for non empty strings if c0: # for non empty strings
if c0 in "#+-.": # first character is one of: # + - . if c0 in "#+-.": # first character is one of: # + - .
match = regex_list.search(s) (t1,t2,p,ss) = regex_list.findall(s)[0]
(t,p,s) = match.group(1), None, match.group(2) # t1 - tag ("###")
t = (t or '').strip() # t2 - tag ("+++", "---", "...")
if t.endswith('.'): t, p = t[:-1], '.'
# t - tag ("###", "+++", "---", "...")
# p - paragraph point ('.')->for "++." or "--." # p - paragraph point ('.')->for "++." or "--."
# s - other part of string # ss - other part of string
if t: if t1 or t2:
# headers and lists: # headers and lists:
if c0 == '#': # headers if c0 == '#': # headers
(lev, mtag) = parse_title(t, s) (lev, mtag) = parse_title(t1, ss)
lineno+=1
continue
elif c0 == '+': # ordered list elif c0 == '+': # ordered list
(lev, mtag, lineno)= parse_list(t, p, s, 'ol', lev, mtag, lineno) (lev, mtag, lineno)= parse_list(t2, p, ss, 'ol', lev, mtag, lineno)
lineno+=1
continue
elif c0 == '-': # unordered list elif c0 == '-': # unordered list
(lev, mtag, lineno) = parse_list(t, p, s, 'ul', lev, mtag, lineno) (lev, mtag, lineno) = parse_list(t2, p, ss, 'ul', lev, mtag, lineno)
else: # c0 == '.' # paragraph in lists lineno+=1
(lev, mtag, lineno) = parse_point(t, s, lev, mtag, lineno) continue
lineno+=1 elif lev>0: # and c0 == '.' # paragraph in lists
continue (lev, mtag, lineno) = parse_point(t2, ss, lev, mtag, lineno)
lineno+=1
continue
else: else:
if c0 == '-': # table or blockquote? if c0 == '-': # table or blockquote?
(s, mtag, lineno) = parse_table_or_blockquote(s, mtag, lineno) (s, mtag, lineno) = parse_table_or_blockquote(s, mtag, lineno)
@@ -1123,7 +1175,7 @@ def render(text,
# new paragraph # new paragraph
pc0='' pc0=''
if pc0 == '': if pc0 == '' or (mtag != 'p' and s0 not in (' ','\t')):
# paragraph # paragraph
out.extend(etags[::-1]) out.extend(etags[::-1])
etags=[] etags=[]
@@ -1171,12 +1223,12 @@ def render(text,
style = p_begin = p_end = '' style = p_begin = p_end = ''
if p == 'center': if p == 'center':
p_begin = '<p style="text-align:center">' p_begin = '<p style="text-align:center">'
p_end = '</p>' p_end = '</p>'+pp
elif p in ('left','right'): elif p in ('left','right'):
style = ' style="float:%s"' % p style = ' style="float:%s"' % p
if p in ('video','audio'): if p in ('video','audio'):
t = render(t, {}, {}, 'br', URL, environment, latex, t = render(t, {}, {}, 'br', URL, environment, latex,
autolinks, protolinks, class_prefix, id_prefix) autolinks, protolinks, class_prefix, id_prefix, pretty_print)
return '<%(p)s controls="controls"%(title)s%(width)s><source src="%(k)s" />%(t)s</%(p)s>' \ return '<%(p)s controls="controls"%(title)s%(width)s><source src="%(k)s" />%(t)s</%(p)s>' \
% dict(p=p, title=title, width=width, k=k, t=t) % dict(p=p, title=title, width=width, k=k, t=t)
alt = ' alt="%s"'%escape(t).replace(META, DISABLED_META) if t else '' alt = ' alt="%s"'%escape(t).replace(META, DISABLED_META) if t else ''
@@ -1197,13 +1249,16 @@ def render(text,
title = ' title="%s"' % a.replace(META, DISABLED_META) if a else '' title = ' title="%s"' % a.replace(META, DISABLED_META) if a else ''
target = ' target="_blank"' if p == 'popup' else '' target = ' target="_blank"' if p == 'popup' else ''
t = render(t, {}, {}, 'br', URL, environment, latex, autolinks, t = render(t, {}, {}, 'br', URL, environment, latex, autolinks,
protolinks, class_prefix, id_prefix) if t else k protolinks, class_prefix, id_prefix, pretty_print) if t else k
return '<a href="%(k)s"%(title)s%(target)s>%(t)s</a>' \ return '<a href="%(k)s"%(title)s%(target)s>%(t)s</a>' \
% dict(k=k, title=title, target=target, t=t) % dict(k=k, title=title, target=target, t=t)
if t == 'NEWLINE' and not a:
return '<br />'+pp
return '<div class="anchor" id="%s">%s</div>' % (escape(id_prefix+t), return '<div class="anchor" id="%s">%s</div>' % (escape(id_prefix+t),
render(a, {},{},'br', URL, render(a, {},{},'br', URL,
environment, latex, autolinks, environment, latex, autolinks,
protolinks, class_prefix, id_prefix)) protolinks, class_prefix,
id_prefix, pretty_print))
parts = text.split(LINK) parts = text.split(LINK)
text = parts[0] text = parts[0]
@@ -1241,41 +1296,37 @@ def render(text,
return LATEX % code.replace('"','\"').replace('\n',' ') return LATEX % code.replace('"','\"').replace('\n',' ')
elif b in html_colors: elif b in html_colors:
return '<span style="color: %s">%s</span>' \ return '<span style="color: %s">%s</span>' \
% (b, render(code,{},{},'br',URL,environment,latex,autolinks, protolinks)) % (b, render(code, {}, {}, 'br', URL, environment, latex,
autolinks, protolinks, class_prefix, id_prefix, pretty_print))
elif b in ('c', 'color') and p: elif b in ('c', 'color') and p:
c=p.split(':') c=p.split(':')
fg='color: %s;' % c[0] if c[0] else '' fg='color: %s;' % c[0] if c[0] else ''
bg='background-color: %s;' % c[1] if len(c)>1 and c[1] else '' bg='background-color: %s;' % c[1] if len(c)>1 and c[1] else ''
return '<span style="%s%s">%s</span>' \ return '<span style="%s%s">%s</span>' \
% (fg, bg, render(code,{},{},'br', URL, environment, latex, autolinks, protolinks)) % (fg, bg, render(code, {}, {}, 'br', URL, environment, latex,
autolinks, protolinks, class_prefix, id_prefix, pretty_print))
cls = ' class="%s%s"'%(class_prefix,b) if b and b != 'id' else '' cls = ' class="%s%s"'%(class_prefix,b) if b and b != 'id' else ''
id = ' id="%s%s"'%(id_prefix,escape(p)) if p else '' id = ' id="%s%s"'%(id_prefix,escape(p)) if p else ''
beg=(code[:1]=='\n') beg=(code[:1]=='\n')
end=[None,-1][code[-1:]=='\n'] end=[None,-1][code[-1:]=='\n']
if beg and end: if beg and end:
return '<pre><code%s%s>%s</code></pre>' % (cls, id, escape(code[1:-1])) return '<pre><code%s%s>%s</code></pre>%s' % (cls, id, escape(code[1:-1]), pp)
return '<code%s%s>%s</code>' % (cls, id, escape(code[beg:end])) return '<code%s%s>%s</code>' % (cls, id, escape(code[beg:end]))
text = regex_expand_meta.sub(expand_meta, text) text = regex_expand_meta.sub(expand_meta, text)
text = text.translate(ttab_out) text = text.translate(ttab_out)
if environment:
def u2(match, environment=environment):
f = environment.get(match.group('a'), match.group(0))
if callable(f):
try:
f = f(match.group('b'))
except Exception, e:
f = 'ERROR: %s' % e
return str(f)
text = regex_env.sub(u2, text)
return text return text
def markmin2html(text, extra={}, allowed={}, sep='p', def markmin2html(text, extra={}, allowed={}, sep='p',
autolinks='default',protolinks='default'): autolinks='default', protolinks='default',
class_prefix='', id_prefix='markmin_', pretty_print=False):
return render(text, extra, allowed, sep, return render(text, extra, allowed, sep,
autolinks=autolinks, protolinks=protolinks) autolinks=autolinks, protolinks=protolinks,
class_prefix=class_prefix, id_prefix=id_prefix,
pretty_print=pretty_print)
def run_doctests():
import doctest
doctest.testmod()
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys
@@ -1312,7 +1363,9 @@ if __name__ == '__main__':
pre { background-color: #E0E0E0; padding: 5px; } pre { background-color: #E0E0E0; padding: 5px; }
</style>""")[1:] </style>""")[1:]
print html % dict(title="Markmin markup language", style=style, body=markmin2html(__doc__)) print html % dict(title="Markmin markup language",
style=style,
body=markmin2html(__doc__, pretty_print=True))
elif sys.argv[1:2] == ['-t']: elif sys.argv[1:2] == ['-t']:
from timeit import Timer from timeit import Timer
loops=1000 loops=1000
@@ -1338,7 +1391,8 @@ if __name__ == '__main__':
else: else:
markmin_style = "" markmin_style = ""
print html % dict(title=sys.argv[1], style=markmin_style, body=markmin2html(markmin_text)) print html % dict(title=sys.argv[1], style=markmin_style,
body=markmin2html(markmin_text, pretty_print=True))
finally: finally:
fargv.close() fargv.close()
@@ -1348,4 +1402,4 @@ if __name__ == '__main__':
print " -t - timeit __doc__ (for testing purpuse only)" print " -t - timeit __doc__ (for testing purpuse only)"
print " file.markmin [file.css] - process file.markmin + built in file.css (optional)" print " file.markmin [file.css] - process file.markmin + built in file.css (optional)"
print " file.markmin [@path_to/css] - process file.markmin + link path_to/css (optional)" print " file.markmin [@path_to/css] - process file.markmin + link path_to/css (optional)"
doctest.testmod() run_doctests()
-5
View File
@@ -9420,8 +9420,3 @@ DAL.Table = Table # was necessary in gluon/globals.py session.connect
if __name__ == '__main__': if __name__ == '__main__':
import doctest import doctest
doctest.testmod() doctest.testmod()
+1
View File
@@ -9,4 +9,5 @@ from test_storage import *
from test_template import * from test_template import *
from test_utils import * from test_utils import *
from test_contribs import * from test_contribs import *
from test_markmin import *
# from test_web import * # from test_web import *