def handle_proof(self, tag: QqTag) -> str: """ Uses tags: proof, label, outline, of Examples: \proof Here is the proof \proof \of theorem \ref{thm:1} Now we pass to proof of theorem \ref{thm:1} :param tag: :return: HTML of proof """ doc, html, text = Doc().tagtext() with html("div", klass="env env__proof"): if tag.find("label"): doc.attr(id=self.label2id(tag._label.value)) with html("span", klass="env-title env-title__proof"): if tag.exists("outline"): proofline = 'Proof outline' else: proofline = 'Proof' doc.asis( join_nonempty( self.localize(proofline), self.format(tag.find("of"), blanks_to_pars=False)).rstrip() + ".") doc.asis(rstrip_p(" " + self.format(tag, blanks_to_pars=True))) doc.asis("<span class='end-of-proof'>∎</span>") return doc.getvalue() + "\n<p>"
def handle_h(self, tag: QqTag) -> str: """ Uses tags: h1, h2, h3, h4, label, number Example: \h1 This is first header \h2 This is the second header \label{sec:second} :param tag: :return: """ doc, html, text = Doc().tagtext() with html(tag.name): doc.attr(id=self.tag_id(tag)) if tag.find("number"): with html("span", klass="section__number"): with html("a", href="#"+self.tag_id(tag), klass="section__number"): text(tag._number.value) text(self.format(tag, blanks_to_pars=False)) ret = doc.getvalue() if tag.next() and isinstance(tag.next(), str): ret += "<p>" return doc.getvalue()
def handle_h(self, tag: QqTag) -> str: """ Uses tags: h1, h2, h3, h4, label, number Example: \h1 This is first header \h2 This is the second header \label{sec:second} :param tag: :return: """ doc, html, text = Doc().tagtext() with html(tag.name): doc.attr(id=self.tag_id(tag)) if tag.find("number"): with html("span", klass="section__number"): with html("a", href="#" + self.tag_id(tag), klass="section__number"): text(tag._number.value) text(self.format(tag, blanks_to_pars=False)) ret = doc.getvalue() if tag.next() and isinstance(tag.next(), str): ret += "<p>" return doc.getvalue()
def handle_proof(self, tag: QqTag) -> str: """ Uses tags: proof, label, outline, of Examples: \proof Here is the proof \proof \of theorem \ref{thm:1} Now we pass to proof of theorem \ref{thm:1} :param tag: :return: HTML of proof """ doc, html, text = Doc().tagtext() with html("div", klass="env env__proof"): if tag.find("label"): doc.attr(id=self.label2id(tag._label.value)) with html("span", klass="env-title env-title__proof"): if tag.exists("outline"): proofline = 'Proof outline' else: proofline = 'Proof' doc.asis(join_nonempty(self.localize(proofline), self.format(tag.find("of"), blanks_to_pars=False)).rstrip()+".") doc.asis(rstrip_p(" " + self.format(tag, blanks_to_pars=True))) doc.asis("<span class='end-of-proof'>∎</span>") return doc.getvalue()+"\n<p>"
def handle_figure(self, tag: QqTag) -> str: """ Currently, only python-generated figures and plotly figures are supported. Example: \figure \label fig:figure \pythonfigure plt.plot([1, 2, 3], [1, 4, 9]) \caption Some figure Uses tags: figure, label, caption, number, showcode, collapsed :param tag: QqTag :return: HTML of figure """ doc, html, text = Doc().tagtext() subtags = ['pythonfigure', 'plotly', 'rawhtml'] langs = { 'pythonfigure': 'python', 'plotly': 'python', 'rawhtml': 'html' } with html("div", klass="figure"): if tag.find("label"): doc.attr(id=self.label2id(tag._label.value)) label = tag._label.value else: label = None for child in tag: if isinstance(child, QqTag): if child.name in subtags: if tag.exists("showcode"): doc.asis( self.showcode( child, collapsed=tag.exists("collapsed"), lang=langs.get(child.name))) doc.asis(self.handle(child)) elif child.name == 'caption': with html("div", klass="figure_caption"): if label is not None: with html("a", klass="figure_caption_anchor", href="#" + self.label2id(label)): text( join_nonempty(self.localize("Fig."), tag.get("number"))) text(": ") else: text( join_nonempty(self.localize("Fig."), tag.get("number")) + ": ") doc.asis(self.format(child, blanks_to_pars=True)) return doc.getvalue()
def handle_snippet(self, tag: QqTag) -> str: """ Uses tags: hidden, backref, label :param tag: :return: """ anchor = "" if not tag.exists("backref") and tag.exists("label"): anchor = "<span id='{}'></span>".format(self.label2id(tag._label.value)) if tag.exists("hidden"): return anchor return anchor + self.format(tag, blanks_to_pars=True)
def test_qqtag_backlinks(self): q = QqTag('a', [ QqTag('b', 'hello'), QqTag('c', 'world'), QqTag('b', 'this'), QqTag('--+-', [ QqTag('b', 'way'), "this" ])]) self.assertTrue(q._is_consistent()) new_tag = QqTag({'qqq' : 'bbb'}) q.append_child(new_tag) self.assertEqual(new_tag.my_index, 4) del q[0] self.assertEqual(new_tag.my_index, 3) self.assertTrue(q._is_consistent()) other_tag = QqTag({'other': ['some', 'values']}) q.insert(2, other_tag) self.assertEqual(other_tag.my_index, 2) self.assertEqual(new_tag.my_index, 4) third_tag = QqTag({'this': 'hi'}) q[3] = third_tag self.assertEqual(third_tag.my_index, 3) self.assertTrue(q._is_consistent())
def handle_snippet(self, tag: QqTag) -> str: """ Uses tags: hidden, backref, label :param tag: :return: """ anchor = "" if not tag.exists("backref") and tag.exists("label"): anchor = "<span id='{}'></span>".format( self.label2id(tag._label.value)) if tag.exists("hidden"): return anchor return anchor + self.format(tag, blanks_to_pars=True)
def preprocess(self, root: QqTag): """ Uses tags: number, label, nonumber, flabel :return: """ for tag in root: if isinstance(tag, QqTag): name = tag.name if (name in self.counters or name in self.enumerateable_envs ) and not (tag.find('number') or tag.exists('nonumber')): counter = self.get_counter_for_tag(tag) if counter is not None: counter.increase() tag.append_child(QqTag({'number': str(counter)})) if tag.find('label'): label = tag._label.value self.label2number[label] = str(counter) # self.label2title[label] = tag.text_content if tag.find('label') and tag.find('number'): self.label2number[tag._label.value] = tag._number.value if tag.find('label'): self.label2tag[tag._label.value] = tag if tag.find('flabel'): self.flabel2tag[tag._flabel.value.lower()] = tag self.preprocess(tag)
def test_qqtag_accessors(self): q = QqTag('a', [ QqTag('b', 'hello'), QqTag('c', 'world'), QqTag('b', 'this'), QqTag('--+-', [ QqTag('b', 'way'), "this" ])]) self.assertEqual(q._b.value, 'hello') self.assertEqual(q._c.value, 'world') self.assertEqual([b.as_list() for b in q('b')], [['b', 'hello'], ['b', 'this']]) self.assertEqual(q.find('--+-')._b.value, 'way') self.assertEqual(q[0].value, 'hello') self.assertEqual(q[1].value, 'world') self.assertEqual(q[3][0].value, 'way')
def test_split_by_sep(self): doc = r"""\splittedtag[one|two\three|four]""" parser = QqParser(allowed_tags={'splittedtag', 'three'}) tree = parser.parse(doc) splitted = tree._splittedtag.split_by_sep() self.assertEqual(splitted, [['one'], ['two', QqTag('three')], ['four']])
def mk_chapters(self): curchapter = Chapter(QqTag("_zero_chapter"), []) self.chapters = [] for tag in self.root: if isinstance(tag, QqTag) and tag.name == 'h1': self.add_chapter(curchapter) curchapter = Chapter(tag, []) curchapter.content.append(tag) self.add_chapter(curchapter)
def handle_figure(self, tag: QqTag) -> str: """ Currently, only python-generated figures and plotly figures are supported. Example: \figure \label fig:figure \pythonfigure plt.plot([1, 2, 3], [1, 4, 9]) \caption Some figure Uses tags: figure, label, caption, number, showcode, collapsed :param tag: QqTag :return: HTML of figure """ doc, html, text = Doc().tagtext() subtags = ['pythonfigure', 'plotly', 'rawhtml'] langs = {'pythonfigure': 'python', 'plotly': 'python', 'rawhtml': 'html'} with html("div", klass="figure"): if tag.find("label"): doc.attr(id=self.label2id(tag._label.value)) label = tag._label.value else: label = None for child in tag: if isinstance(child, QqTag): if child.name in subtags: if tag.exists("showcode"): doc.asis(self.showcode(child, collapsed=tag.exists("collapsed"), lang = langs.get(child.name))) doc.asis(self.handle(child)) elif child.name == 'caption': with html("div", klass="figure_caption"): if label is not None: with html("a", klass="figure_caption_anchor", href="#" + self.label2id(label)): text(join_nonempty(self.localize("Fig."), tag.get("number"))) text(": ") else: text(join_nonempty(self.localize("Fig."), tag.get("number"))+": ") doc.asis(self.format(child, blanks_to_pars=True)) return doc.getvalue()
def test_create_qqtag(self): q = QqTag({'a': 'b'}) self.assertEqual(q.name, 'a') self.assertEqual(q.value, 'b') q = QqTag('a', [ QqTag('b', 'hello'), QqTag('c', 'world'), QqTag('b', 'this'), QqTag('--+-', [QqTag('b', 'way'), "this"]) ]) self.assertEqual(q.name, 'a') #self.assertEqual(q._children, IndexedList([QqTag('b', ['hello']), QqTag('c', ['world']), QqTag('b', ['this']), # QqTag('--+-', [QqTag('b', ['way']), 'this'])])) #self.assertEqual(eval(repr(q)), q) self.assertEqual(q.as_list(), [ 'a', ['b', 'hello'], ['c', 'world'], ['b', 'this'], ['--+-', ['b', 'way'], 'this'] ])
def test_create_qqtag(self): q = QqTag({'a': 'b'}) self.assertEqual(q.name, 'a') self.assertEqual(q.value, 'b') q = QqTag('a', [ QqTag('b', 'hello'), QqTag('c', 'world'), QqTag('b', 'this'), QqTag('--+-', [ QqTag('b', 'way'), "this" ])]) self.assertEqual(q.name, 'a') #self.assertEqual(q._children, IndexedList([QqTag('b', ['hello']), QqTag('c', ['world']), QqTag('b', ['this']), # QqTag('--+-', [QqTag('b', ['way']), 'this'])])) #self.assertEqual(eval(repr(q)), q) self.assertEqual(q.as_list(), ['a', ['b', 'hello'], ['c', 'world'], ['b', 'this'], ['--+-', ['b', 'way'], 'this']])
def test_qqtag_accessors(self): q = QqTag('a', [ QqTag('b', 'hello'), QqTag('c', 'world'), QqTag('b', 'this'), QqTag('--+-', [QqTag('b', 'way'), "this"]) ]) self.assertEqual(q._b.value, 'hello') self.assertEqual(q._c.value, 'world') self.assertEqual([b.as_list() for b in q('b')], [['b', 'hello'], ['b', 'this']]) self.assertEqual(q.find('--+-')._b.value, 'way') self.assertEqual(q[0].value, 'hello') self.assertEqual(q[1].value, 'world') self.assertEqual(q[3][0].value, 'way')
def handle_quiz(self, tag: QqTag): """ Uses tags: choice, correct, comment Example: \question Do you like qqmbr? \quiz \choice No. \comment You didn't even try! \choice \correct Yes, i like it very much! \comment And so do I! :param tag: :return: """ if not tag.exists('md5id'): tag.append_child(QqTag('md5id', [self.tag_hash_id(tag)])) template = Template(filename="templates/quiz.html") return template.render(formatter=self, tag=tag)
def handle_pythonfigure(self, tag: QqTag) -> str: """ Uses tags: pythonfigure, style :param tag: :return: """ path = self.make_python_fig(tag.text_content, exts=("svg")) doc, html, text = Doc().tagtext() with html("img", klass="figure img-responsive", src=self.url_for_figure(path + "/" + self.default_figname + ".svg")): if tag.exists("style"): doc.attr(style=tag._style.value) return doc.getvalue()
def handle_snref(self, tag: QqTag) -> str: """ Makes snippet ref. Example: Consider \snref[Initial Value Problem|sn:IVP]. Here sn:IVP -- label of snippet. If no separator present, fuzzy search will be performed over flabels Example: \snippet \label sn:IVP \flabel Initial Value Problem Initial Value Problem is a problem with initial value Consider \snref[initial value problem]. :param tag: :return: """ doc, html, text = Doc().tagtext() if tag.exists("separator"): title, labelfield = tag.split_by_sep() label = "".join(labelfield) else: title = tag.value.replace("\n", " ") target = self.find_tag_by_flabel(title) label = target._label.value data_url = self.url_for_snippet(label) with html("a", ('data-url', data_url), klass="snippet-ref"): doc.asis(self.format(title, blanks_to_pars=True)) return doc.getvalue()
def handle_equation(self, tag: QqTag) -> str: """ Uses tags: equation, number, label Example: \equation \label eq:first x^2 + y^2 = z^2 :param tag: :return: """ doc, html, text = Doc().tagtext() with html("div", klass="latex_equation"): text("\\[\n") text("\\begin{equation}\n") if tag.find('number'): text("\\tag{{{}}}\n".format(tag._number.value)) if tag.find('label'): doc.attr(id=self.label2id(tag._label.value)) text(self.format(tag, blanks_to_pars=False)) text("\\end{equation}\n") text("\\]\n") return doc.getvalue()
def test_qqtag_prev_next(self): q = QqTag('a', [ QqTag('b', 'hello'), QqTag('c', 'world'), QqTag('b', 'this'), QqTag('--+-', [QqTag('b', 'way'), "this"]) ]) self.assertEqual(q._c.prev().value, 'hello') self.assertEqual(q._b.next().value, 'world') self.assertEqual(q._c.next().value, 'this')
def get_counter_for_tag(self, tag: QqTag) -> Counter: name = tag.name counters = self.counters while True: if tag.exists('nonumber'): return None current = counters.get(name) if current is None: return None if isinstance(current, Counter): return current if isinstance(current, dict): counters = current tag = tag.parent name = tag.name continue return None
def handle_ref(self, tag: QqTag): """ Examples: See Theorem \ref{thm:existence} Other way: See \ref[Theorem|thm:existence] In this case word ``Theorem'' will be part of a reference: e.g. in HTML it will look like See <a href="#label_thm:existence">Theorem 1</a> If you want to omit number, just use \nonumber tag like so: See \ref[Theorem\nonumber|thm:existence] This will produce HTML like See <a href="#label_thm:existence">Theorem</a> Uses tags: ref, nonumber :param tag: :return: """ doc, html, text = Doc().tagtext() if tag.is_simple: prefix = None label = tag.value else: prefix, labelfield = tag.split_by_sep() label = "".join(labelfield).strip() number = self.label2number.get(label, "???") target = self.label2tag[label] href = "" if self.mode == 'bychapters': if 'snippet' not in [t.name for t in tag.ancestor_path()]: # check that we're not inside snippet now fromindex = self.tag2chapter(tag) else: fromindex = None href = self.url_for_chapter(self.tag2chapter(target), fromindex=fromindex) eqref = target.name in self.formulaenvs or target.name == 'item' and target.parent.name in self.formulaenvs if eqref: href += "#mjx-eqn-" + str(number) else: href += "#"+self.label2id(label) with html("span", klass="ref"): with html("a", klass="a-ref", href=href, title=self.label2title.get(label, "")): if prefix: doc.asis(self.format(prefix, blanks_to_pars=False)) if eqref and hasattr(self, 'url_for_eq_snippet'): doc.attr(('data-url', self.url_for_eq_snippet(number))) if not tag.exists("nonumber"): if prefix: doc.asis(" ") if eqref: text("(" + number + ")") else: text(number) return doc.getvalue()
def test_qqtag_backlinks(self): q = QqTag('a', [ QqTag('b', 'hello'), QqTag('c', 'world'), QqTag('b', 'this'), QqTag('--+-', [QqTag('b', 'way'), "this"]) ]) self.assertTrue(q._is_consistent()) new_tag = QqTag({'qqq': 'bbb'}) q.append_child(new_tag) self.assertEqual(new_tag.my_index, 4) del q[0] self.assertEqual(new_tag.my_index, 3) self.assertTrue(q._is_consistent()) other_tag = QqTag({'other': ['some', 'values']}) q.insert(2, other_tag) self.assertEqual(other_tag.my_index, 2) self.assertEqual(new_tag.my_index, 4) third_tag = QqTag({'this': 'hi'}) q[3] = third_tag self.assertEqual(third_tag.my_index, 3) self.assertTrue(q._is_consistent())
def handle_ref(self, tag: QqTag): """ Examples: See Theorem \ref{thm:existence} Other way: See \ref[Theorem|thm:existence] In this case word ``Theorem'' will be part of a reference: e.g. in HTML it will look like See <a href="#label_thm:existence">Theorem 1</a> If you want to omit number, just use \nonumber tag like so: See \ref[Theorem\nonumber|thm:existence] This will produce HTML like See <a href="#label_thm:existence">Theorem</a> Uses tags: ref, nonumber :param tag: :return: """ doc, html, text = Doc().tagtext() if tag.is_simple: prefix = None label = tag.value else: prefix, labelfield = tag.split_by_sep() label = "".join(labelfield).strip() number = self.label2number.get(label, "???") target = self.label2tag[label] href = "" if self.mode == 'bychapters': if 'snippet' not in [t.name for t in tag.ancestor_path()]: # check that we're not inside snippet now fromindex = self.tag2chapter(tag) else: fromindex = None href = self.url_for_chapter(self.tag2chapter(target), fromindex=fromindex) eqref = target.name in self.formulaenvs or target.name == 'item' and target.parent.name in self.formulaenvs if eqref: href += "#mjx-eqn-" + str(number) else: href += "#" + self.label2id(label) with html("span", klass="ref"): with html("a", klass="a-ref", href=href, title=self.label2title.get(label, "")): if prefix: doc.asis(self.format(prefix, blanks_to_pars=False)) if eqref and hasattr(self, 'url_for_eq_snippet'): doc.attr(('data-url', self.url_for_eq_snippet(number))) if not tag.exists("nonumber"): if prefix: doc.asis(" ") if eqref: text("(" + number + ")") else: text(number) return doc.getvalue()