Commit 023b130c authored by Robin Sonnabend's avatar Robin Sonnabend
Browse files

Footnotes and small fixes

/close #132
/close #130
parent c87b0e0a
......@@ -4,6 +4,7 @@ from collections import OrderedDict
from enum import Enum
from shared import escape_tex
from utils import footnote_hash
import config
......@@ -223,6 +224,8 @@ class Tag:
r"\textit{{({})}}".format(self.decision.get_categories_str())
)
return " ".join(parts)
elif self.name == "footnote":
return r"\footnote{{{}}}".format(self.values[0])
return r"\textbf{{{}:}} {}".format(escape_tex(self.name.capitalize()), escape_tex(";".join(self.values)))
elif render_type == RenderType.plaintext:
if self.name == "url":
......@@ -231,6 +234,8 @@ class Tag:
if not show_private:
return ""
return self.values[0]
elif self.name == "footnote":
return "[^]({})".format(self.values[0])
return "{}: {}".format(self.name.capitalize(), ";".join(self.values))
elif render_type == RenderType.wikitext:
if self.name == "url":
......@@ -239,6 +244,8 @@ class Tag:
if not show_private:
return ""
return self.todo.render_wikitext(current_protocol=protocol)
elif self.name == "footnote":
return "<ref>{}</ref>".format(self.values[0])
return "'''{}:''' {}".format(self.name.capitalize(), ";".join(self.values))
elif render_type == RenderType.html:
if self.name == "url":
......@@ -259,6 +266,9 @@ class Tag:
return " ".join(parts)
else:
return "<b>Beschluss:</b> {}".format(self.values[0])
elif self.name == "footnote":
return '<sup id="#fnref{0}"><a href="#fn{0}">Fn</a></sup>'.format(
footnote_hash(self.values[0]))
else:
raise _not_implemented(self, render_type)
......@@ -284,7 +294,7 @@ class Tag:
# v3: also match [] without semicolons inbetween, as there is not other use for that
PATTERN = r"\[(?<content>[^\]]*)\]"
KNOWN_TAGS = ["todo", "url", "beschluss"]
KNOWN_TAGS = ["todo", "url", "beschluss", "footnote"]
class Empty(Element):
......@@ -495,6 +505,16 @@ class Fork(Element):
else:
return 1
def get_visible_elements(self, show_private, elements=None):
if elements is None:
elements = set()
if show_private or not self.test_private(self.name):
for child in self.children:
elements.add(child)
if isinstance(child, Fork):
child.get_visible_elements(show_private, elements)
return elements
@staticmethod
def create_root():
return Fork(None, None, None, 0)
......
......@@ -21,7 +21,7 @@ import mimetypes
import config
from shared import db, date_filter, datetime_filter, date_filter_long, date_filter_short, time_filter, time_filter_short, user_manager, security_manager, current_user, check_login, login_required, group_required, class_filter, needs_date_test, todostate_name_filter, code_filter, indent_tab_filter
from utils import is_past, mail_manager, url_manager, get_first_unused_int, set_etherpad_text, get_etherpad_text, split_terms, optional_int_arg, fancy_join
from utils import is_past, mail_manager, url_manager, get_first_unused_int, set_etherpad_text, get_etherpad_text, split_terms, optional_int_arg, fancy_join, footnote_hash
from decorators import db_lookup, require_public_view_right, require_private_view_right, require_modify_right, require_publish_right, require_admin_right
from models.database import ProtocolType, Protocol, DefaultTOP, TOP, LocalTOP, Document, Todo, Decision, MeetingReminder, Error, TodoMail, DecisionDocument, TodoState, Meta, DefaultMeta, DecisionCategory, Like
from views.forms import LoginForm, ProtocolTypeForm, DefaultTopForm, MeetingReminderForm, NewProtocolForm, DocumentUploadForm, KnownProtocolSourceUploadForm, NewProtocolSourceUploadForm, generate_protocol_form, TopForm, LocalTopForm, SearchForm, DecisionSearchForm, ProtocolSearchForm, TodoSearchForm, NewProtocolFileUploadForm, NewTodoForm, TodoForm, TodoMailForm, DefaultMetaForm, MetaForm, MergeTodosForm, DecisionCategoryForm, DocumentEditForm
......@@ -60,6 +60,7 @@ app.jinja_env.filters["todo_get_name"] = todostate_name_filter
app.jinja_env.filters["code"] = code_filter
app.jinja_env.filters["indent_tab"] = indent_tab_filter
app.jinja_env.filters["fancy_join"] = fancy_join
app.jinja_env.filters["footnote_hash"] = footnote_hash
app.jinja_env.tests["auth_valid"] = security_manager.check_user
app.jinja_env.tests["needs_date"] = needs_date_test
......
......@@ -12,7 +12,7 @@ from models.database import Document, Protocol, Error, Todo, Decision, TOP, Defa
from models.errors import DateNotMatchingException
from server import celery, app
from shared import db, escape_tex, unhyphen, date_filter, datetime_filter, date_filter_long, date_filter_short, time_filter, class_filter, KNOWN_KEYS
from utils import mail_manager, url_manager, encode_kwargs, decode_kwargs, add_line_numbers, set_etherpad_text, get_etherpad_text
from utils import mail_manager, url_manager, encode_kwargs, decode_kwargs, add_line_numbers, set_etherpad_text, get_etherpad_text, footnote_hash
from parser import parse, ParserException, Element, Content, Text, Tag, Remark, Fork, RenderType
from wiki import WikiClient, WikiException
from calendarpush import Client as CalendarClient, CalendarException
......@@ -168,6 +168,8 @@ def parse_protocol_async_inner(protocol, encoded_kwargs):
return
# tags
tags = tree.get_tags()
elements = tree.get_visible_elements(show_private=True)
public_elements = tree.get_visible_elements(show_private=False)
for tag in tags:
if tag.name not in Tag.KNOWN_TAGS:
error = protocol.create_error("Parsing", "Invalid tag",
......@@ -304,11 +306,20 @@ def parse_protocol_async_inner(protocol, encoded_kwargs):
db.session.commit()
todo_tag.todo = todo
# Decisions
decision_tags = [tag for tag in tags if tag.name == "beschluss"]
for decision_tag in decision_tags:
if decision_tag not in public_elements:
error = protocol.create_error("Parsing", "Decision in private context.",
"The decision in line {} is in a private context, but decisions are "
"and have to be public. Please move it to a public spot.".format(
decision_tag.linenumber))
db.session.add(error)
db.session.commit()
return
old_decisions = list(protocol.decisions)
for decision in old_decisions:
protocol.decisions.remove(decision)
db.session.commit()
decision_tags = [tag for tag in tags if tag.name == "beschluss"]
decisions_to_render = []
for decision_tag in decision_tags:
if len(decision_tag.values) == 0:
......@@ -352,9 +363,15 @@ def parse_protocol_async_inner(protocol, encoded_kwargs):
decision_top = decision_tag.fork.get_top()
decision_content = texenv.get_template("decision.tex").render(
render_type=RenderType.latex, decision=decision,
protocol=protocol, top=decision_top, show_private=False)
protocol=protocol, top=decision_top, show_private=True)
maxdepth = decision_top.get_maxdepth()
compile_decision(decision_content, decision, maxdepth=maxdepth)
# Footnotes
footnote_tags = [tag for tag in tags if tag.name == "footnote"]
public_footnote_tags = [tag for tag in footnote_tags if tag in public_elements]
# TOPs
old_tops = list(protocol.tops)
for top in old_tops:
protocol.tops.remove(top)
......@@ -365,31 +382,47 @@ def parse_protocol_async_inner(protocol, encoded_kwargs):
db.session.add(top)
db.session.commit()
render_kwargs = {
# render
private_render_kwargs = {
"protocol": protocol,
"tree": tree
"tree": tree,
"footnotes": footnote_tags,
}
public_render_kwargs = copy(private_render_kwargs)
public_render_kwargs["footnotes"] = public_footnote_tags
render_kwargs = {True: private_render_kwargs, False: public_render_kwargs}
maxdepth = tree.get_maxdepth()
privacy_states = [False]
content_private = render_template("protocol.txt", render_type=RenderType.plaintext, show_private=True, **render_kwargs)
content_public = render_template("protocol.txt", render_type=RenderType.plaintext, show_private=False, **render_kwargs)
content_private = render_template("protocol.txt", render_type=RenderType.plaintext, show_private=True, **private_render_kwargs)
content_public = render_template("protocol.txt", render_type=RenderType.plaintext, show_private=False, **public_render_kwargs)
if content_private != content_public:
privacy_states.append(True)
protocol.content_private = content_private
protocol.content_public = content_public
protocol.content_html_private = render_template("protocol.html",
render_type=RenderType.html, show_private=True, **render_kwargs)
render_type=RenderType.html, show_private=True, **private_render_kwargs)
protocol.content_html_public = render_template("protocol.html",
render_type=RenderType.html, show_private=False, **render_kwargs)
render_type=RenderType.html, show_private=False, **public_render_kwargs)
for show_private in privacy_states:
latex_source = texenv.get_template("protocol.tex").render(render_type=RenderType.latex, show_private=show_private, **render_kwargs)
latex_source = texenv.get_template("protocol.tex").render(
render_type=RenderType.latex,
show_private=show_private,
**render_kwargs[show_private])
compile(latex_source, protocol, show_private=show_private, maxdepth=maxdepth)
if protocol.protocoltype.use_wiki:
wiki_source = wikienv.get_template("protocol.wiki").render(render_type=RenderType.wikitext, show_private=not protocol.protocoltype.wiki_only_public, **render_kwargs).replace("\n\n\n", "\n\n")
wiki_infobox_source = wikienv.get_template("infobox.wiki").render(protocoltype=protocol.protocoltype)
push_to_wiki(protocol, wiki_source, wiki_infobox_source, "Automatisch generiert vom Protokollsystem 3.0")
show_private = not protocol.protocoltype.wiki_only_public
wiki_source = wikienv.get_template("protocol.wiki").render(
render_type=RenderType.wikitext,
show_private=show_private,
**render_kwargs[show_private]
).replace("\n\n\n", "\n\n")
wiki_infobox_source = wikienv.get_template("infobox.wiki").render(
protocoltype=protocol.protocoltype)
push_to_wiki(protocol, wiki_source, wiki_infobox_source,
"Automatisch generiert vom Protokollsystem 3.0")
protocol.done = True
db.session.commit()
......
......@@ -4,3 +4,10 @@
{% endif %}
{% endfor %}
{% if footnotes|length > 0 %}
<hr />
{% for footnote in footnotes %}
<p><sup id="fn{{footnote.values[0]|footnote_hash}}">{{loop.index}}. {{footnote.values[0]}} <a href="#fnref{{footnote.values[0]|footnote_hash}}"></a></sup></p>
{% endfor %}
{% endif %}
......@@ -28,4 +28,8 @@
<env> endif </env>
<env> endfor </env>
<env> if footnotes|length > 0 </env>
<references />
<env> endif </env>
[[Kategorie:<var>protocol.protocoltype.wiki_category</var>]]
......@@ -200,3 +200,6 @@ def fancy_join(values, sep1=" und ", sep2=", "):
last = values[-1]
start = values[:-1]
return "{}{}{}".format(sep2.join(start), sep1, last)
def footnote_hash(text, length=5):
return str(sum(ord(c) * i for i, c in enumerate(text)) % 10**length)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment