Beispiel #1
0
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
Beispiel #2
0
 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))
Beispiel #3
0
    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)
Beispiel #4
0
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
Beispiel #5
0
    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)
Beispiel #6
0
    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)