import re
def publish(master_fn):
'''
We use one master file that contains all the Showell markup, and
then we publish to Django templates.
master_fn should be the name of a file that has several sections
with banners like you get from the unix "more" command...
::::::::::::::
./apps/comment/templates/comment_form.html
::::::::::::::
[some markup to be preprocessed]
Each section of the master file gets converted and written to
the output file.
'''
f = open(master_fn)
fn = body = None
while True:
line = f.readline()
if not line: break
if line.startswith('::::'):
if fn:
convert(fn, body)
fn = f.readline().strip()
f.readline()
body = ''
else:
body += line
convert(fn, body)
def convert(fn, in_body):
out_body = convert_text(in_body)
open(fn, 'w').write(out_body)
def convert_text(in_body):
'''
You can call convert_text directly to convert Showell markup
to HTML/Django markup.
'''
lines = []
indenter = Indenter()
for line in in_body.split('\n'):
m = re.match('(\s*)(.*\S)(.*)', line)
if m:
prefix, line, cruft = m.groups()
if line.startswith('>>'):
block_tag(prefix, line, indenter)
elif line.startswith('%%'):
django_block(prefix, line, indenter)
elif line.startswith('DEDENT'):
indenter.dedent()
elif line.startswith('END_DEDENT'):
indenter.end_dedent(prefix)
else:
line = fix_line(line)
indenter.add(prefix, line+cruft)
else:
indenter.add('', line)
return indenter.body()
def block_tag(prefix, line, indenter):
'''
Block tags have syntax like this:
>> table
>> tr
>> td
foo
>> td
bar
FORM is just a shortcut.
'''
m = re.match('>> (.*)', line)
markup = m.group(1)
m = re.match('FORM (.*)', markup)
if m:
markup = 'form action="{%% url %s %%}" method="POST"' % m.group(1)
start_tag = '<%s>' % markup
end_tag = '%s>' % markup.split()[0]
indenter.push(prefix, start_tag, end_tag)
def django_block(prefix, line, indenter):
'''
Enable code like this:
%% extends 'base.html'
%% load smartif
%% block body
%% for book in books
{{ book }}
%% if condition
Display this
%% elif condition
Display that
%% else
%% include 'other.html'
'''
m = re.match('%% (.*)', line)
markup = m.group(1)
tag = markup.split()[0]
start_tag = '{%% %s %%}' % markup
if tag in ['elif', 'else', 'include', 'extends', 'load']:
indenter.insert(prefix, start_tag)
else:
end_tag = '{%% end%s %%}' % tag
indenter.push(prefix, start_tag, end_tag)
def fix_line(line):
'''
Fix up individual lines of HTML:
List item one | b | li ; br
Home LINK home.home
LINK is just a django-specific shortcut.
This is a bit crufty...there are some mini features
that just allowed me to match some old markup without
creating diffs.
'''
if line == '':
return ''
if line[-1] in [':', ',']:
return fix_line(line[:-1]) + line[-1]
if line.endswith('| ()'):
line = line[:-len('| ()')]
return '(%s)' % fix_line(line).rstrip()
if line.endswith('; br'):
line = line[:-len('; br')]
return fix_line(line).rstrip() + '
'
if line.endswith('; hr'):
line = line[:-len('; hr')]
return fix_line(line).rstrip() + '