def process_js(tag: QqTag): """ Output: \_codeblock \_item \_code ...(str)... \_output ...(str)... \_item \_code ...(str)... \_output ...(str)... \ref ... \seealso ... \require ... :param tag: :return: """ codeblock = QqTag("_codeblock") cumulative_code = [] current_chunk = [] for child in itertools.chain(tag, [None]): if isinstance(child, str) and child.strip(): cumulative_code.append(child) current_chunk.append(child) elif child is None or child.name == 'out': code = "".join(cumulative_code) if current_chunk: res = node_exec(code) if res or child is None: code_tag = QqTag( "_code", [strip_blank_lines("".join(current_chunk))]) codeblock.append_child(code_tag) if res: codeblock.append_child(QqTag("_output", [res])) current_chunk.clear() if child is not None: logger = "console.log({})".format(child.text_content) res = node_exec(code + ";\n" + logger) code_tag = QqTag("_code", [ strip_blank_lines("".join(current_chunk) + child.text_content.rstrip() + ";") ]) current_chunk.clear() codeblock.append_child(code_tag) codeblock.append_child(QqTag("_output", [res])) else: codeblock.append_child(child) return codeblock
def make_chapters(self): for heading, *contents in split_by_predicate( self.root, predicate=lambda tag: (isinstance(tag, QqTag) and tag.name == "chapter"), zero_delim=QqTag("_zero_chapter")): self.add_chapter(Chapter(heading, [heading] + contents))
def make_numbers(self, root: QqTag) -> None: """ Uses tags: number, label, nonumber, flabel :return: """ for tag in root.children_tags(): 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.label_to_number[label] = str(counter) # self.label_to_title[label] = tag.text_content if tag.find('label') and tag.find('number'): self.label_to_number[tag.label_.value] = tag.number_.value if tag.find('label'): self.label_to_tag[tag.label_.value] = tag if tag.find('flabel'): self.flabel_to_tag[tag.flabel_.value.lower()] = tag self.make_numbers(tag)
def process_python(tag: QqTag): """ Output: \_codeblock \_code ...(str)... \_output ...(str)... \_code ...(str)... \_output ...(str)... \_code ...(str)... .... \ref ... \seealso ... \require ... :param tag: :return: """ loc = {} glob = {} codeblock = QqTag("_codeblock") chunk = [] for child in tag: if isinstance(child, str): with stdout_io() as s: try: exec(child, loc, glob) except Exception as e: print("Exception: {}\n{}".format(e.__class__.__name__, e)) chunk.append(strip_blank_lines(child) + "\n"), if s.getvalue(): codeblock.append(QqTag("_code", ["".join(chunk)])) codeblock.append(QqTag("_output", [s.getvalue()])) chunk.clear() elif child.name == 'out': chunk.append(strip_blank_lines(child.text_content)) codeblock.append(QqTag("_code", ["".join(chunk)])) chunk.clear() res = eval(child.text_content, loc, glob) codeblock.append(QqTag("_output", [repr(res)])) elif child.name != 'flush': codeblock.append(child) if chunk: codeblock.append(QqTag("_code", ["".join(chunk)])) return codeblock
def handle_quiz(self, tag: QqTag) -> str: """ 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=os.path.join(self.templates_dir, "quiz.html")) return template.render(formatter=self, tag=tag)
def __init__(self, root: QqTag = QqTag("_root"), with_chapters=True, eq_preview_by_labels=False) -> None: self.templates_dir = os.path.join( os.path.dirname(os.path.realpath(__file__)), "templates") self.with_chapters = with_chapters self.eq_preview_by_labels = eq_preview_by_labels self.label_to_number: Dict[str, str] = {} self.label_to_title: Dict[str, str] = {} self.label_to_tag: Dict[str, QqTag] = {} self.label_to_chapter: Dict[str, int] = {} self.flabel_to_tag: Dict[str, QqTag] = {} self.root: QqTag = root self.counters = {} self.chapters: List[Chapter] = [] self.heading_to_level = { 'chapter': 1, 'section': 2, 'subsection': 3, 'subsubsection': 4 } self.mode = 'wholedoc' #: how to render the doc? the following options are available: #: - 'wholedoc' - the whole document on one page #: - 'bychapters' - every chapter on its own page chapters_counter = None if with_chapters: chapters_counter = Counter() self.counters['chapter'] = chapters_counter self.counters['section'] = spawn_or_create_counter(chapters_counter) self.counters['subsection'] = (self.counters['section'].spawn_child()) self.counters['subsubsection'] = ( self.counters['subsection'].spawn_child()) self.counters['equation'] = spawn_or_create_counter(chapters_counter) self.counters['equation'].showparents = True self.counters['item'] = {'align': self.counters['equation']} self.counters['figure'] = spawn_or_create_counter(chapters_counter) self.enumerateable_envs = { name: name.capitalize() for name in [ 'remark', 'theorem', 'example', 'exercise', 'definition', 'proposition', 'lemma', 'question', 'corollary' ] } self.metatags = { 'meta', 'author', 'affiliation', 'link', 'license', 'title', 'url', 'lang', 'role' } # You can make self.localnames = {} to use # plain English localization self.localizations = { 'ru': { 'Remark': 'Замечание', 'Theorem': 'Теорема', 'Example': 'Пример', 'Exercise': 'Упражнение', 'Definition': 'Определение', 'Proposition': 'Утверждение', 'Lemma': 'Лемма', 'Proof': 'Доказательство', 'Proof outline': 'Набросок доказательства', 'Figure': 'Рисунок', 'Fig.': "Рис.", 'Question': 'Вопрос', 'Corollary': 'Следствие', } } self.localnames: Dict[str, str] = None self.formulaenvs = {'eq', 'equation', 'align'} for env in self.enumerateable_envs: self.counters[env] = spawn_or_create_counter(chapters_counter) self.counters[env].showparents = False self.figures_dir = None self.default_figname = "fig" plt.rcParams['figure.figsize'] = (6, 4) self.pythonfigure_globals = {'plt': plt} self.code_prefixes = dict( pythonfigure='import matplotlib.pyplot as plt\n', plotly=("import plotly\n" "import plotly.graph_objs as go\n" "from plotly.offline import iplot " "as plot\n" "from plotly.offline import " "init_notebook_mode\n\n" "init_notebook_mode()\n\n"), rawhtml='') self.plotly_plotter = PlotlyPlotter() self.plotly_globals: Dict[str, Any] = {} self.css: Dict[str, str] = {} self.js_top: Dict[str, str] = {} self.js_bottom: Dict[str, str] = {} self.js_onload: Dict[str, str] = {} self.safe_tags = (set(self.enumerateable_envs) | set( self.formulaenvs) | { 'item', 'figure', 'label', 'number', 'ref', 'nonumber', 'snref', 'snippet', 'flabel', 'name', 'proof', 'outline', 'of', 'caption', 'showcode', 'collapsed', 'hidden', 'backref', 'label', 'em', 'emph', 'quiz', 'choice', 'correct', 'comment' } | set(self.heading_to_level) | self.metatags)