Files
i2p.www/i2p2www/spec/views.py

176 lines
5.0 KiB
Python
Raw Normal View History

2015-11-10 08:15:11 +00:00
import codecs
2016-04-03 11:30:29 +00:00
from docutils import io
2016-03-06 06:23:19 +00:00
from docutils.core import (
2016-04-03 11:30:29 +00:00
Publisher,
2016-03-06 06:23:19 +00:00
publish_doctree,
publish_from_doctree,
publish_parts,
)
2016-04-03 11:30:29 +00:00
from docutils.readers.doctree import Reader
2015-11-10 08:15:11 +00:00
from flask import (
abort,
g,
make_response,
redirect,
render_template,
render_template_string,
request,
safe_join,
url_for,
)
import os.path
2016-04-03 11:30:29 +00:00
from i2p2www import PROPOSAL_DIR, SPEC_DIR
2015-11-10 08:15:11 +00:00
from i2p2www import helpers
SPEC_METATAGS = {
'accuratefor': None,
2016-04-01 23:28:07 +00:00
'category': '',
2015-11-10 08:15:11 +00:00
'lastupdated': None,
}
SPEC_LIST_METATAGS = [
]
2016-04-01 23:28:07 +00:00
SPEC_CATEGORY_SORT = {
'Design': 1,
'Transports': 2,
'Protocols': 3,
'': 999,
}
2015-11-10 08:15:11 +00:00
2016-04-03 11:30:29 +00:00
PROPOSAL_METATAGS = {
'author': u'I2P devs',
'created': None,
'lastupdated': None,
'status': u'Draft',
'thread': None,
}
PROPOSAL_LIST_METATAGS = [
]
PROPOSAL_STATUS_SORT = {
'Draft': 1,
2016-04-04 12:50:16 +00:00
'Rejected': 100,
2016-04-03 11:30:29 +00:00
'': 999,
}
2015-11-10 08:15:11 +00:00
2016-04-03 11:30:29 +00:00
METATAG_LABELS = {
'accuratefor': u'Accurate for',
'author': u'Author',
'category': u'Category',
'created': u'Created',
'lastupdated': u'Last updated',
'status': u'Status',
'thread': u'Thread',
}
def get_rsts(directory, meta_parser):
rsts = []
for f in os.listdir(directory):
2015-11-10 08:15:11 +00:00
if f.endswith('.rst'):
2016-04-03 11:30:29 +00:00
path = safe_join(directory, f)
# read file header
header = ''
2015-11-10 08:15:11 +00:00
with codecs.open(path, encoding='utf-8') as fd:
for line in fd:
header += line
if not line.strip():
break
2016-04-03 11:30:29 +00:00
parts = publish_parts(source=header, source_path=directory, writer_name="html")
meta = meta_parser(parts['meta'])
2015-11-10 08:15:11 +00:00
2016-04-03 11:30:29 +00:00
rst = {
2015-11-10 08:15:11 +00:00
'name': f[:-4],
'title': parts['title'],
}
2016-04-03 11:30:29 +00:00
rst.update(meta)
rsts.append(rst)
return rsts
2015-11-10 08:15:11 +00:00
2016-04-03 11:30:29 +00:00
def spec_index():
specs = get_rsts(SPEC_DIR, spec_meta)
2016-04-01 23:28:07 +00:00
specs.sort(key=lambda s: (SPEC_CATEGORY_SORT[s['category']], s['title']))
2015-11-10 08:15:11 +00:00
return render_template('spec/index.html', specs=specs)
2016-04-03 11:30:29 +00:00
def proposal_index():
proposals = get_rsts(PROPOSAL_DIR, proposal_meta)
for i in range(0, len(proposals)):
proposals[i]['num'] = int(proposals[i]['name'][:3])
proposals.sort(key=lambda s: (PROPOSAL_STATUS_SORT[s['status']], s['num']))
return render_template('spec/proposal-index.html', proposals=proposals)
def render_rst(directory, name, meta_parser, template):
2015-11-10 08:15:11 +00:00
# check if that file actually exists
2016-04-03 11:30:29 +00:00
path = safe_join(directory, name + '.rst')
2015-11-10 08:15:11 +00:00
if not os.path.exists(path):
abort(404)
# read file
with codecs.open(path, encoding='utf-8') as fd:
content = fd.read()
2016-04-03 11:30:29 +00:00
if not template:
2015-11-10 08:15:11 +00:00
# Strip out RST
content = content.replace('.. meta::\n', '')
2016-03-06 06:23:19 +00:00
content = content.replace('.. contents::\n\n', '')
2015-11-10 08:15:11 +00:00
content = content.replace('.. raw:: html\n\n', '')
content = content.replace('\n.. [', '\n[')
2015-11-14 20:41:05 +00:00
content = content.replace(']_.', '].')
content = content.replace(']_', '] ')
2015-11-10 08:15:11 +00:00
# Change highlight formatter
content = content.replace('{% highlight', "{% highlight formatter='textspec'")
2016-04-03 11:30:29 +00:00
# Metatags
for (metatag, label) in METATAG_LABELS.items():
content = content.replace(' :%s' % metatag, label)
2015-11-10 08:15:11 +00:00
# render the post with Jinja2 to handle URLs etc.
rendered_content = render_template_string(content)
rendered_content = rendered_content.replace('</pre></div>', ' </pre></div>')
2016-04-03 11:30:29 +00:00
if not template:
2015-11-10 08:15:11 +00:00
# Send response
r = make_response(rendered_content)
r.mimetype = 'text/plain'
return r
2016-03-06 06:23:19 +00:00
# Render the ToC
doctree = publish_doctree(source=rendered_content)
bullet_list = doctree[1][1]
doctree.clear()
doctree.append(bullet_list)
2016-04-03 11:30:29 +00:00
reader = Reader(parser_name='null')
pub = Publisher(reader, None, None,
source=io.DocTreeInput(doctree),
destination_class=io.StringOutput)
pub.set_writer('html')
pub.publish()
toc = pub.writer.parts['fragment']
2016-03-06 06:23:19 +00:00
# Remove the ToC from the main document
rendered_content = rendered_content.replace('.. contents::\n', '')
# publish the spec with docutils
2016-04-03 11:30:29 +00:00
parts = publish_parts(source=rendered_content, source_path=directory, writer_name="html")
meta = meta_parser(parts['meta'])
2016-04-04 12:50:16 +00:00
meta['num'] = int(name[:3])
2015-11-10 08:15:11 +00:00
2016-04-03 11:30:29 +00:00
return render_template(template, title=parts['title'], toc=toc, body=parts['fragment'], name=name, meta=meta)
def spec_show(name):
return render_rst(SPEC_DIR, name, spec_meta, 'spec/show.html')
2015-11-10 08:15:11 +00:00
def spec_show_txt(name):
2016-04-03 11:30:29 +00:00
return render_rst(SPEC_DIR, name, spec_meta, None)
def proposal_show(name):
return render_rst(PROPOSAL_DIR, name, proposal_meta, 'spec/proposal-show.html')
2015-11-10 08:15:11 +00:00
2016-04-03 11:30:29 +00:00
def proposal_show_txt(name):
return render_rst(PROPOSAL_DIR, name, proposal_meta, None)
def spec_meta(meta):
2015-11-10 08:15:11 +00:00
return helpers.get_metadata_from_meta(meta, SPEC_METATAGS, SPEC_LIST_METATAGS)
2016-04-03 11:30:29 +00:00
def proposal_meta(meta):
return helpers.get_metadata_from_meta(meta, PROPOSAL_METATAGS, PROPOSAL_LIST_METATAGS)