예제 #1
0
def meta_format_caption(category, definition, defined):
    """
    Compute format caption for a category.

    Arguments
    ---------
        category:
        definition:
        defined:
    """
    if "format-caption-classic" in definition:
        if isinstance(definition["format-caption-classic"], MetaInlines):
            defined[category]["format-caption-classic"] = stringify(
                definition["format-caption-classic"])
        else:
            debug(
                "[WARNING] pandoc-numbering: format-caption-classic is not correct for category "
                + category)

    if "format-caption-title" in definition:
        if isinstance(definition["format-caption-title"], MetaInlines):
            defined[category]["format-caption-title"] = stringify(
                definition["format-caption-title"])
        else:
            debug(
                "[WARNING] pandoc-numbering: format-caption-title is not correct for category "
                + category)
예제 #2
0
def h_html_header(e, doc):
    if not isinstance(e, pf.Header) or doc.format != "html": return None
    if doc.get_metadata("indexpage", False): return None
    if doc.chapternum == "99": return None
    logstring(f"--Evaluating header {e} level {e.level} vs {doc.currentlevel}",
              doc)
    if e.level > 1 and not pf.stringify(e): return None

    if e.level > len(doc.currentplace):
        doc.currentplace += ["0"] * (e.level - len(doc.currentplace))
    if e.level > 1:
        doc.currentplace = doc.currentplace[:e.level]
        t = int(doc.currentplace[e.level - 1])
        doc.currentplace[e.level - 1] = str(t + 1)
    href = "" if e.level == 1 else labelref(e, doc)
    if href in doc.labels and doc.labels[href]["number"]:
        place = doc.labels[href]["number"].split(".")
    else:
        place = doc.currentplace
    place[0] = doc.chapternum
    # title = doc.get_metadata("title","---") if e.level==1 else pf.stringify(e)
    title = pf.stringify(e)
    if not title: return e
    addtocline(doc.toc,
               place=place,
               title=title,
               file=doc.get_metadata("filename", "") + ".html",
               href=href)
    return e
예제 #3
0
    def match(elem: panflute.Element) -> Optional[Match[str]]:
        """Pattern match for a key in the element

        We can convert a given element to a string and match it against
        the known format for an acronym key.  This method manages
        converting an element to a string, while appropriately stripping
        unnecessary punctuation, and passing the result to the
        :func:`re.match`.

        Parameters
        ----------

        elem: :class:`panflute.Element`
            The document element to inspect for an acronym key.

        Returns
        -------

        Match:
            The result of the :func:`re.match` call with the string
            version of the element.

        """
        if isinstance(elem, panflute.Str):
            content = panflute.stringify(elem)
            if isinstance(elem.parent, panflute.Quoted):
                content = re.sub("['\"]", "", content)

        elif isinstance(elem, panflute.Span):
            content = panflute.stringify(elem.content[0]) \
                if len(elem.content) == 1 else ""
        else:
            content = ""

        return Key.PATTERN.match(content)
예제 #4
0
def fix_appendix(elem, doc):
    """Looks for headings titled 'Bibliography' or 'Abbreviations',
    adds a page break before them and puts them at the end of the
    documents.

    :param elem:
    :param doc:
    """

    if isinstance(elem, pf.Header) and pf.stringify(elem) in (
            "Bibliography",
            "Abbreviations",
    ):
        list_ = (doc.abbreviations if pf.stringify(elem) == "Abbreviations"
                 else doc.bibliography)

        elem.classes.append("page-break-before")

        list_.append(elem)
        next_ = elem.next

        while True:
            next = next_

            if (isinstance(next, pf.Header)
                    and next.level == elem.level) or next is None:
                break
            else:
                next_ = next.next
                list_.append(next)
                next.parent.content.pop(next.index)

                return []
예제 #5
0
def h_html_header(e,doc):
    if not isinstance(e,pf.Header) or doc.format != "html": return None
    if doc.get_metadata("indexpage",False): return None
    if doc.chapternum=="99": return None
    logstring(f"--Evaluating header {e} level {e.level} vs {doc.currentlevel}",doc)
    if e.level>1 and not pf.stringify(e): return None

    if e.level> len(doc.currentplace):
        doc.currentplace += ["0"]*(e.level-len(doc.currentplace))
    if e.level>1:
        doc.currentplace = doc.currentplace[:e.level]
        t = int(doc.currentplace[e.level-1])
        doc.currentplace[e.level-1] = str(t+1)
    href = "" if e.level==1 else labelref(e,doc)
    if href in doc.labels and doc.labels[href]["number"]:
        place = doc.labels[href]["number"].split(".")
    else:
        place = doc.currentplace
    place[0] = doc.chapternum
    # title = doc.get_metadata("title","---") if e.level==1 else pf.stringify(e)
    title = pf.stringify(e)
    if not title: return e
    addtocline(doc.toc,place=place,
    title=title,file=doc.get_metadata("filename","")+".html",href=href)
    return e
예제 #6
0
def render_citations(elem, doc, string=False):
    if isinstance(elem, pf.Cite):
        if doc.format == "latex" and not doc.get_metadata(
            "doit_citeproc_for_latex", True
        ):

            latex_commands = []
            latex_command = "\\autocite{{{ids}}}"

            if hasattr(elem, "latex_command") and elem.latex_command:
                for command in elem.latex_command:
                    head = "" if command.startswith("\\") else "\\cite"
                    latex_command = "{head}{command}{{{{{{ids}}}}}}".format(
                        head=head, command=command
                    )

                    latex_commands.append(latex_command)
            else:
                latex_commands.append(latex_command)

            citations = ",".join([c.id for c in elem.citations])

            raw = "".join(lc.format(ids=citations) for lc in latex_commands)

            if string:
                return raw
            else:
                return pf.RawInline(raw, format="latex")
        else:
            if hasattr(elem, "latex_command") and "author" in elem.latex_command:

                names = []
                amount_citations = len(elem.citations)

                for i in range(1, amount_citations + 1):
                    citation = elem.citations[i - 1]
                    citation = doc.bibliography.get(citation.id, False)

                    if citation:
                        names_list = citation.get(
                            "author", citation.get("editor", False)
                        )

                        if names_list:
                            names.extend(utils.format_names(names_list))

                            if not i == amount_citations:
                                names.extend([pf.Str(", "), pf.Space])

                if names:
                    if elem.next:
                        if pf.stringify(names[-1]).endswith(".") and pf.stringify(
                            elem.next
                        ).startswith("."):
                            names[-1] = pf.Str(pf.stringify(names[-1])[:-1])

                            return pf.Span(*names)

            return pf.Cite(citations=elem.citations)
예제 #7
0
def action(elem, doc):
    if isinstance(elem, pf.ListItem) and elem.content and isinstance(
            elem.content[0], pf.Plain):
        plain = elem.content[0]

        stringy = pf.stringify(elem)
        matches = tag_pattern.findall(stringy)
        identifier = None
        outcome = None

        # strip the tags from the element before we proceed any further
        for tag in matches:
            elem = elem.replace_keyword(tag, pf.Space())

        # strip the trailing whitespace (this is equivalent to a trim operation)
        while type(plain.content[-1]) in (pf.Space, pf.SoftBreak):
            del plain.content[-1]

        # gather all of the tags/IDs on the learning objective into something
        # that we can write out to an attribute on the span.
        outcomes = []
        identifiers = []
        courses = []
        for tag in matches:
            if "&" in tag:
                # this is not a tag, it's a course reference
                courses.append(tag[1:-1])
            elif "#" in tag:
                identifiers.append(tag[tag.index("#") + 1:-1])
                outcomes.append(tag[:tag.index("#")] + ":")
            else:
                outcomes.append(tag)
        outcomes = " ".join(outcomes)
        courses = " ".join(courses)

        if len(identifiers) == 1:
            identifier = identifiers[0]
        elif len(identifiers) > 1:
            pf.debug(f"Found multiple IDs: {identifiers}")
            identifier = identifiers[0]
        else:
            identifier = ""

        # Take the existing contents of the `pf.Plain` that's the first child
        # of the `pf.ListItem` and embed that into a `pf.Span`. Then make the
        # `pf.Span` the only child of the `pf.Plain`.
        if matches:
            span = pf.Span(*plain.content,
                           identifier=identifier,
                           attributes={
                               "outcomes": outcomes,
                               "course": pf.stringify(doc.metadata["title"])
                           })
            if courses:
                span.attributes["used-in"] = courses
            plain.content.clear()
            plain.content.append(span)

        return elem
예제 #8
0
def action(elem, doc):
    if doc.get_metadata('title') is None:
        # No title -> Beancount Options Reference
        if isinstance(elem, Para):
            # Convert all paragraphs to code blocks
            text = stringify(elem)
            if not text.startswith('option'):
                text = '    ' + text
            return CodeBlock(text)
        # Skip everything else
        return

    if isinstance(elem, BlockQuote):
        if isinstance(elem.parent, ListItem):
            # Don't use blockquotes in lists
            assert len(elem.content) == 1
            return elem.content[0]
        elif any(isinstance(item, CodeBlock) for item in elem.content):
            # Remove blockquotes around code blocks
            return [item for item in elem.content]
        elif len(elem.content) == 1:
            # Convert blockquotes to code blocks
            code = ''
            for item in elem.content[0].content:
                if isinstance(item, Link):
                    # Don't convert links to code
                    break
                elif isinstance(item, Str):
                    code += item.text
                elif isinstance(item, Space):
                    code += ' '
                elif isinstance(item, LineBreak):
                    code += '\n'
                else:
                    code += stringify(item)
            else:
                return CodeBlock(code)

    elif isinstance(elem, Header):
        # There must be only one level 1 header
        if elem.identifier != 'title':
            elem.level += 1

    elif isinstance(elem, Link):
        if elem.url == stringify(elem):
            # Displayed as url, skip
            pass
        else:
            resolved = resolve_url(elem.url)
            if resolved:
                elem.url = resolved

    elif isinstance(elem, CodeBlock):
        # Remove unnecessary leading tabs from code blocks
        elem.text = re.sub(r'^\t', '', elem.text, flags=re.MULTILINE)

    elif isinstance(elem, Image):
        elem.url = './' + elem.url
예제 #9
0
    def action(self, elem, doc):
        if isinstance(elem, pf.Header):
            if elem.level == 1:
                day_text = elem.content[0].text
                try:
                    self.current_day = datetime.datetime.strptime(
                        day_text, "%Y-%m-%d"
                    ).date()
                except ValueError:
                    if "NOWARN" not in pf.stringify(elem):
                        self.warnings.append(
                            f"Ignoring header for day {pf.stringify(elem)}"
                        )
                    self.current_day = None
            if elem.level == 2:
                period_text = elem.content[0].text
                try:
                    begin_time, end_time = map(
                        lambda d: datetime.datetime.strptime(d, "%H:%M").time(),
                        period_text.split("-"),
                    )
                    begin = datetime.datetime.combine(self.current_day, begin_time)
                    end = datetime.datetime.combine(self.current_day, end_time)
                    self.period = Period(begin=begin, end=end)
                    self.periods.append(self.period)
                except ValueError:
                    if "NOWARN" not in pf.stringify(elem):
                        self.warnings.append(
                            f"Ignoring header for period {pf.stringify(elem)}"
                        )
                    self.period = None
            if elem.level == 3:
                # first, partition on '/'s
                def is_slash(e):
                    return isinstance(e, pf.Str) and e.text == "/"

                parts = [
                    list(content)
                    for group, content in itertools.groupby(elem.content, is_slash)
                    if not group
                ]

                def elem_to_text(e):
                    if isinstance(e, pf.Space):
                        return " "
                    return e.text

                def elems_to_text(e):
                    return " ".join(map(elem_to_text, e)).strip()

                task_hierarchy = list(map(elems_to_text, parts))
                self.period.task_hierarchies.append(task_hierarchy)
        else:
            if self.period and isinstance(elem, pf.ListItem):
                self.period.items.append(elem)
예제 #10
0
def action(elem, doc):
    if isinstance(elem, pf.BulletList) and doc.format == 'latex':
        div = pf.Div()
        for item in elem.content.list:
            plain = item.content.list[0]
            key = plain.content.pop(0)
            cv_line_tex = "\cvitem{%s}{%s}{}" % (pf.stringify(key),
                                                 pf.stringify(plain))
            raw_inline = pf.RawInline(cv_line_tex, format='latex')
            div.content.extend([pf.Plain(raw_inline)])
        return div
def action(elem, doc):
    if isinstance(elem, pf.Header) and elem.level == 1:
        if doc.current_heading and len(doc.section_content) > 10:
            output_section(doc)
            doc.section_content = []
            doc.current_heading = pf.stringify(elem)
            doc.seq = str(float(doc.seq) + float(doc.seq_inc))
            doc.current_heading = pf.stringify(elem)
        else:
            doc.current_heading = pf.stringify(elem)
            doc.section_content = []
    else:
        doc.section_content.append(pf.stringify(elem))
예제 #12
0
def action(elem, doc):
    global collect_objectives

    if isinstance(elem,
                  pf.Header) and pf.stringify(elem) == "Learning objectives":
        collect_objectives = True
    # we're explicitly expecting learning objectives to be `pf.Span` that
    # appear after the "Learning objectives" header.
    if isinstance(elem, pf.Span) and collect_objectives:
        # We're interested in collecting the `pf.ListItem` so that we can
        # stuff them into a `pf.OrderedList` later. When we write them out
        # in the collection at the end, we **do not** want them to have any
        # of the metadata, so make a deep copy of the `pf.ListItem` and its
        # children, then strip any metadata from that copy
        listitem = pfp.copy_listitem(elem.ancestor(2))

        def delete_span_meta(elem, doc):
            if isinstance(elem, pf.Span) and "outcomes" in elem.attributes:
                elem.identifier = ""
                del elem.attributes["outcomes"]

        listitem.walk(delete_span_meta)

        # Learning objectives that have an ID should also have an "outcomes"
        # attribute, we'll use that to put the learning objective into a dict
        outcomes = elem.attributes["outcomes"].split()
        for outcome in outcomes:
            objectives[outcome].append(listitem)
예제 #13
0
def parse_citations(elem, doc):
    if isinstance(elem, pf.Link) and "table_note" not in elem.classes:
        text = pf.stringify(elem)

        if link_is_cite.search(text):
            return to_cite(text, doc)

    elif (
        hasattr(elem, "text")
        and len(elem.text) > 0
        and not isinstance(elem.parent, pf.Link)
        and not isinstance(elem, (pf.Code, pf.CodeBlock))
    ):

        text = elem.text

        if str_is_cite.search(text):
            content = []

            for s, c in utils.re_split(str_is_cite, text):
                content.append(s)

                if c:
                    content.append(to_cite(c, doc))

            return pf.Span(*content)
예제 #14
0
def action(elem, doc):
    if isinstance(elem, pf.Table):
        table = elem.caption.list[0].text
        headers = list(map(pf.stringify, elem.header.content))
        headers_sql = ",".join(headers)
        placeholders_sql = ",".join(["?"] * len(headers))
        doc.sql.execute(f"create table {table} ({headers_sql})")
        for row in elem.content:
            row_values = [pf.stringify(cell) for cell in row.content]
            doc.sql.execute(
                f"insert into {table}({headers_sql}) values ({placeholders_sql})",
                row_values,
            )
        return []
    if isinstance(elem, pf.CodeBlock):
        if elem.classes != ["pandocsql"]:
            return
        table = doc.sql.execute(elem.text)
        headers = [col[0] for col in table.description]
        rows = list(table)

        def c(t):
            return pf.TableCell(pf.Para(pf.Str(str(t))))

        def r(cs):
            return pf.TableRow(*list(map(c, cs)))

        return [pf.Table(*list(map(r, rows)), header=r(headers))]
예제 #15
0
def is_include_line(elem):
    # value: return 0 for false, 1 for include file, 2 for include header
    value = 0
    config = {}
    name = None
    if not hasattr(elem, "_content"):
        value = 0
    elif (len(elem.content) not in [3, 4]) \
        or (not isinstance(elem.content[0], pf.Str)) \
        or (elem.content[0].text not in ['!include', '$include', '!include-header', '$include-header']) \
        or (not isinstance(elem.content[-2], pf.Space)) \
        or (len(elem.content) == 4 and not isinstance(elem.content[1], pf.Code)):
        value = 0
    else:
        if elem.content[0].text in ['!include', '$include']:
            # include file
            value = 1
        else:
            # include header
            value = 2

        # filename
        fn = elem.content[-1]
        if isinstance(fn, pf.Quoted):
            # Convert list to args of Para
            name = pf.stringify(pf.Para(*fn.content), newlines=False)
        else:
            name = fn.text

        # config
        if len(elem.content) == 4:
            config = parseConfig(elem.content[1].text)

    return value, name, config
예제 #16
0
def gl_latex(e, doc):
    label = pf.stringify(e).lower()
    name = e.attributes.get('name')
    description = e.attributes.get('description')

    if label and name and description:
        values = {
            'label':
            label,
            'name':
            name,
            'description':
            pf.convert_text(description,
                            extra_args=['--biblatex'],
                            input_format='markdown',
                            output_format='latex'),
            'text':
            e.attributes.get('text'),
            'plural':
            e.attributes.get('plural'),
            'uppercase':
            'up' in e.classes
        }
        doc.glsentries[label] = values

    tex = USE_TERM.render(label=label,
                          plural='pl' in e.classes,
                          uppercase='up' in e.classes)
    return pf.RawInline(tex, format='latex')
def action(elem, doc):
    if isinstance(elem, panflute.Header):
        if elem.level == 1:
            doc.metadata["title"] = panflute.stringify(elem)
            return []
        else:
            elem.level -= 1
예제 #18
0
def render_links(elem, doc):
    if isinstance(elem, pf.Link) and doc.format == "latex":
        url = elem.url

        ref = _get_ref(url, doc)

        head = "\\myref{{{ref}}}"
        tail = ""

        if ref:
            if elem.content:
                head = "\\myref{{{ref}}}["
                tail = "]"

            return [
                pf.RawInline(head.format(ref=ref), format="latex"),
                *elem.content,
                pf.RawInline(tail, format="latex"),
            ]

        alt_url = pf.stringify(elem).strip()
        ref = _get_ref(alt_url, doc)

        if ref:
            return [
                pf.RawInline(head.format(ref=ref), format="latex"),
                pf.RawInline(tail, format="latex"),
            ]

        logger.debug(url)
예제 #19
0
def action(elem, doc):
    if isinstance(elem, panflute.Header):
        if elem.level == 1:
            text = panflute.stringify(elem)
            rainbow_header = '<h1 id="' + text + '">' + rainbowify(
                text) + '</h1>'
            return (panflute.RawBlock(rainbow_header))
예제 #20
0
    def test_handle_mtest_section_title(self):
        """MTest"""
        doc = pf.Doc(metadata={"lang": "en"})
        elem_content = r"""
        \begin{MTest}{Abschlusstest Kapitel \arabic{section}}
            Foo bar
        \end{MXContent}"""
        doc.content.extend([pf.RawBlock(elem_content, format="latex")])
        elem = doc.content[0]  # this sets up elem.parent

        ret = self.environments.handle_mtest(
            "Foo bar", [r"Abschlusstest Kapitel \arabic{section}"], elem)

        self.assertEqual(len(ret), 2)

        header = ret[0]
        self.assertIsInstance(header, pf.Header)
        self.assertEqual(pf.stringify(header), "Abschlusstest")

        para = ret[1]
        self.assertIsInstance(para.content[0], pf.Str)
        self.assertEqual(para.content[0].text, "Foo")
        self.assertIsInstance(para.content[1], pf.Space)
        self.assertIsInstance(para.content[2], pf.Str)
        self.assertEqual(para.content[2].text, "bar")
def action(elem, doc):
    if isinstance(elem, pf.Para) and is_include_line(elem):
        raw_path = pf.stringify(elem,
                                newlines=False).split(maxsplit=1)[1].strip()
        if raw_path[0:2] == '@/':
            raw_path = './' + raw_path[2:]
        else:
            raise ValueError(f'[code import] {raw_path} should begin with @/')

        rawPathRegexp = r'^(.+(?:\.([a-z]+)))(?:#([\w-]+))?(?: ?({\d+(?:[,-]\d+)?}))?$'
        search = re.search(rawPathRegexp, raw_path)

        if search is None:
            raise ValueError(f'[code import] invalid parameter {raw_path}')

        (filepath, extension, region_name, meta) = search.groups()

        if not path.isfile(filepath):
            raise ValueError(f'[code import] file not found: {filepath}')

        basename = path.basename(filepath).split('.')
        extension = basename[-1]
        subextension = ''
        if len(basename) > 2:
            subextension = basename[-2]

        with open(filepath) as f:
            raw = f.read()

        region = extract_region(raw, region_name, filepath)
        return pf.CodeBlock(dedent(region), '',
                            [get_code_type(extension, subextension)])
예제 #22
0
def h_latex_cite(e, doc):
    """Handle cite. Just feed it to a cite command and hope for the best. This is pretty hacky and should be changed."""

    if not isinstance(e, pf.Cite): return None
    logstring(f"I am {e} and my parent is {e.parent}", doc)
    if isinstance(e.parent, pf.Citation): return []
    s = pf.stringify(e).replace("[", "").replace("]", "").replace("@",
                                                                  "").strip()
    if s[-1] == ",": s = s[:-1]
    if doc.format == "latex":
        tex = f"\\cite{{{s}}}"
        return pf.RawInline(tex, format="latex")
    if doc.format == "html":
        html = ""
        for a in s.split(','):
            a = a.strip()
            if a in doc.bibentries:
                D = doc.bibentries[a]
                authors, title, year = D["author"], D["title"], D["year"]
                authors = bibtexparser.customization.getnames([
                    i.strip()
                    for i in authors.replace('\n', ' ').split(" and ")
                ])
                author = ", ".join([a.split(',')[0] for a in authors])
                T_encode = latex_accents.LaTexAccents_to_UTF8()
                author = T_encode.decode_Tex_Accents(author)
                title = T_encode.decode_Tex_Accents(title)
                q = f'{author} {title}'.replace(' ', '+')

                html += rf' (<a href="https://scholar.google.com/scholar?hl=en&q={q}" target="_blank">{author}, {year}</a>) '
        if not html: html = s
        return pf.RawInline(html, format="html")
예제 #23
0
def wrapfig(elem, doc):
    attrs = elem.attributes
    caption = ''.join(pf.stringify(e) for e in elem.content)
    #  caption = elem.content
    #  pf.debug(caption)
    target = elem.url
    fmt = "latex"

    # Strip tag
    size = attrs.get("width")
    if "lineheight" in attrs:
        lineheight = attrs.lineheight
        latex_begin = r"\begin{wrapfigure}[" + lineheight + "]{l}{" + size + "}"
    else:
        latex_begin = r"\begin{wrapfigure}{l}{" + size + "}"

    if len(caption) > 0:
        latex_fig = r"\centering\includegraphics{" + target + "}\caption{"
        latex_end = r"}\end{wrapfigure}"
        return pf.RawInline(latex_begin + latex_fig + caption + latex_end, fmt)
        # return list(pf.RawInline(latex_begin + latex_fig), caption, pf.RawInline(latex_end))
    else:
        latex_fig = r"\centering\includegraphics{" + target[0] + "}"
        latex_end = r"\end{wrapfigure}"
        return pf.RawInline(latex_begin + latex_fig + latex_end, fmt)
예제 #24
0
파일: rexex.py 프로젝트: rknuus/GReCo
def match_example_header(element):
    if not isinstance(element, panflute.Header):
        return None
    try:
        return example.search(panflute.stringify(element)).group(0)
    except Exception:
        return None
예제 #25
0
파일: rexex.py 프로젝트: rknuus/GReCo
def match_rule_id(element):
    if not isinstance(element, panflute.Header):
        return None
    try:
        return rule_id.search(panflute.stringify(element)).group(1)
    except Exception:
        return None
예제 #26
0
def create_example(number, elem):
    '''Create an example LaTeX block.'''
    examples = []

    # For each example in the list, extract each part of the example.
    # Then substitute the parts into the example template.
    for example in elem.content:
        content = [line.strip() for line in pf.stringify(example).split(',')]

        parts = {}
        parts['target'] = content[0]

        # Format the gloss in small caps
        parts['gloss'] = ' '.join(
            ['\\textsc{' + x + '}' for x in content[1].split(' ')])

        parts['native'] = content[2]

        example_LaTeX = string.Template(EXAMPLE_TEMPLATE).substitute(parts)
        examples.append(example_LaTeX)

    # Substitute examples into the block div.
    block_settings = {'examples': '\n'.join(examples)}
    example_block = string.Template(EXAMPLE_BLOCK_TEMPLATE)

    return pf.RawBlock(example_block.substitute(block_settings),
                       format='latex')
예제 #27
0
def test_forced_first_use() -> None:
    """Check the two usages work as expected

    Based on the rules, after the first use that counts, the default for
    subsequent uses should be the short version.
    """
    keys = []
    for type in ("long", ""):
        key = Key()
        key.value = value
        key.type = type
        key.plural = False
        key.capitalize = False
        key.count = True
        keys.append(key)

    text = meta + "-   " + "\n-   ".join(str(k) for k in keys)
    doc = panflute.convert_text(text, standalone=True)
    acronyms = {
        k: panflute.stringify(doc.metadata["acronyms"]["mwe"][k])
        for k in doc.metadata["acronyms"]["mwe"].content
    }
    result = panflute.convert_text(text,
                                   output_format="markdown",
                                   extra_args=["-F", "pandoc-acro"])
    lines = (line for line in result.splitlines())
    assert "-   " + acronyms["long"] == next(lines).rstrip()
    assert "-   " + acronyms["short"] == next(lines).rstrip()
예제 #28
0
def test_plain() -> None:
    """Check the results of the starred plain text output"""
    text, keys = generate()
    doc = panflute.convert_text(text, standalone=True)
    acronyms = {
        k: panflute.stringify(doc.metadata["acronyms"]["mwe"][k])
        for k in doc.metadata["acronyms"]["mwe"].content
    }

    result = panflute.convert_text(text,
                                   output_format="markdown",
                                   extra_args=["-F", "pandoc-acro"])
    lines = (line for line in result.splitlines())
    first = True
    for key in keys:
        if key.type == "long":
            expected = acronyms["long"] + ("s" if key.plural else "")
        elif key.type == "short":
            expected = acronyms["short"] + ("s" if key.plural else "")
        elif key.type == "full":
            expected = acronyms["long"] + ("s" if key.plural else "") \
                + " (" + acronyms["short"] + ")"
        else:
            if first:
                expected = acronyms["long"] + ("s" if key.plural else "") \
                    + " (" + acronyms["short"] + ")"
            else:
                expected = acronyms["short"] + ("s" if key.plural else "")

        if key.count:
            first = False

        head, *tail = (s for s in expected)
        expected = (head.upper() if key.capitalize else head) + "".join(tail)
        assert "-   " + expected == next(lines).rstrip()
예제 #29
0
def handleHeaderBlockLevel(e, doc):
    """

    :param e:
    :param doc:
    :return:
    """
    global blocktag
    tag = blocktag
    blocktag = None
    before = None
    if tag:
        before = pf.RawBlock("\\end{" + tag + "}\n", "latex")
        if "endblock" in e.classes:
            return before

    for blocktype in BLOCKCLASSES:
        if blocktype in e.classes:
            logging.debug("BLOCKTYPE:" + blocktype)
            if not isinstance(e.content, pf.ListContainer):
                logging.debug("CONTENT:" + pf.stringify(e.content))
                tag = TEX_BLOCKCLASSES_TAG[blocktype]
                elem = pf.Div()
                elem.content = [
                    pf.Plain(pf.RawInline("\n\\begin{" + tag + "}[", "latex"),
                             e.content, pf.RawInline("]\n", "latex"))
                ]

                blocktag = tag

                if before:
                    return [before, elem]
                return elem
            else:
                logging.debug("CONTENT: Listcontainer")
예제 #30
0
def test_quotes_129():
    #pf https://github.com/sergiocorreia/panflute/issues/129
    text = [pf.Str("Some"), pf.Space, pf.Str("quoted text")]
    quoted_text = pf.Quoted(*text)
    para = pf.Para(quoted_text)
    output = pf.stringify(para, False)
    assert output == '"Some quoted text"'
예제 #31
0
def h_latex_cite(e,doc):
    """Handle cite. Just feed it to a cite command and hope for the best. This is pretty hacky and should be changed."""

    if not isinstance(e,pf.Cite): return None
    logstring(f"I am {e} and my parent is {e.parent}", doc)
    if isinstance(e.parent,pf.Citation): return []
    s = pf.stringify(e).replace("[","").replace("]","").replace("@","").strip()
    if s[-1]==",": s = s[:-1]
    if doc.format=="latex":
        tex = f"\\cite{{{s}}}"
        return pf.RawInline(tex,format="latex")
    if doc.format=="html":
        html = ""
        for a in s.split(','):
            a = a.strip()
            if a in doc.bibentries:
                D = doc.bibentries[a]
                authors,title,year = D["author"],D["title"],D["year"]
                authors = bibtexparser.customization.getnames([i.strip() for i in authors.replace('\n', ' ').split(" and ")])
                author = ", ".join([a.split(',')[0] for a in authors])
                T_encode = latex_accents.LaTexAccents_to_UTF8()
                author = T_encode.decode_Tex_Accents(author)
                title = T_encode.decode_Tex_Accents(title)
                q = f'{author} {title}'.replace(' ','+')

                html += rf' (<a href="https://scholar.google.com/scholar?hl=en&q={q}" target="_blank">{author}, {year}</a>) '
        if not html: html = s
        return pf.RawInline(html, format="html")
예제 #32
0
def elem2cite(elem, doc):
    """Safely extract a Cite element and convert to RawInline"""
    if isinstance(elem, pf.Cite):
        citation = elem.content[0]
        tex = pf.RawInline(str2cite(pf.stringify(citation)), format="latex")
        #  pf.debug(tex)
        return tex
예제 #33
0
def h_add_search(e,doc):
    """Add text to search index"""
    if isinstance(e,pf.Header):
        doc.searchtext += " "+pf.stringify(e)
        return None
    if isinstance(e,pf.Div):
        t = e.attributes.get("title","")
        doc.searchtext += " " + t
    return None
예제 #34
0
def action(elem, doc):
    if isinstance(elem, pf.Link) and elem.url.startswith('wiki://'):
        title = pf.stringify(elem).strip()
        baseurl = 'https://en.wikipedia.org/w/api.php'
        query = {'format': 'json', 'action': 'query', 'prop': 'extracts',
            'explaintext': '', 'titles': title}
        r = requests.get(baseurl, params=query)
        data = r.json()
        extract = list(data['query']['pages'].values())[0]['extract']
        extract = extract.split('.', maxsplit=1)[0]
        return pf.RawInline(extract)
예제 #35
0
def action(e, doc):
    if isinstance(e, pf.Link) and e.url == 'acro':
        acronym = pf.stringify(e)
        definition = e.title
        # Only update dictionary if definition is not empty
        if definition:
            doc.acronyms[acronym] = definition
        
        if doc.format == 'latex':
            tex = '\gls{{}}'.format(acronym)
            tex = TEMPLATE_GLS.safe_substitute(acronym=acronym)
            return pf.RawInline(tex, format='latex')
예제 #36
0
def getgitlink(elem_in, elem_out, linkstr=''):
    for i in elem_in.content:
        istr = pf.stringify(i)
        if linkstr or istr[:2] == '[[':
            linkstr += istr
            # is the link complete?
            if linkstr[-2:] == ']]':
                link = linkstr[2:-2].split('|')
                elem_out.content.append(pf.Link(pf.Str(link[0]), url=link[-1] + '.html'))
                linkstr = ''
        else:
            elem_out.content.append(i)

    return linkstr
예제 #37
0
def h_link_ref(e,doc):
    """Change links of class .ref to latex labels"""
    if not isinstance(e,pf.Link): return None
    if not e.classes: return None
    label = "".join(pf.stringify(a) for a in e.content)
    if label[0]=="#": label = label[1:]
    if not label: label="???"
    if doc.format == 'latex':
        if 'ref' in e.classes:
            return pf.RawInline(f"\\cref{{{label}}}", format = "latex")
        if  'eqref' in e.classes:
            return pf.RawInline(f"\\eqref{{{label}}}", format = "latex")
    if doc.format =='html':
        name, link = getlabel(label,doc)
        if 'ref' in e.classes or 'eqref' in e.classes:
            return pf.RawInline(fr"<a href='{link}'>{name}</a>",format='html')
    return e
예제 #38
0
def inner_test_stringify(input_fn, output_fn):

    output_txt_benchmark = './tests/temp_benchmark.txt'
    output_txt_panflute = './tests/temp_panflute.txt'

    print('Testing stringify()')
    with open(input_fn, encoding='utf-8') as f:
        doc = pf.load(f)
    ans = pf.stringify(doc)
    #print(repr(ans).encode('utf-8'))
    with open(output_txt_panflute, encoding='utf-8', mode='w') as f:
        f.write(ans)

    with open(input_fn, encoding='utf-8') as f:
        doc = json.load(f)
    ans = pandocfilters.stringify(doc)
    with open(output_txt_benchmark, encoding='utf-8', mode='w') as f:
        f.write(ans)
예제 #39
0
파일: wg21.py 프로젝트: mpark/wg21
    def pnum():
        num = pf.stringify(elem)

        if not num.replace('.', '').isdigit():
            raise SyntaxError('`pnum` must be integrals with optional `.` separators.')

        if '.' in num:
            num = '({})'.format(num)

        if doc.format == 'latex':
            return pf.RawInline('\\pnum{{{}}}'.format(num), 'latex')

        if doc.format == 'html':
            return pf.RawInline(
                '<div class="marginalizedparent">' \
                    '<a class="marginalized">{}</a>' \
                '</div>'.format(num), 'html')

        return pf.Superscript(pf.Str(num))
예제 #40
0
def figure(options, data, element, doc):

    # Get options
    fn = os.path.abspath(options['source']).replace('\\', '/')
    title = options.get('title', 'Untitled')
    notes = data
    label = options.get('label', os.path.splitext(os.path.basename(fn))[0])

    if doc.format == 'latex':
        subs = {'fn': fn, 'label': label}
        subs['title'] = pf.convert_markdown(title, format='latex')
        subs['notes'] = pf.convert_markdown(notes, format='latex')
        backmatter = doc.get_metadata('format.backmatter', False)
        pagebreak = doc.get_metadata('format.media-pagebreak', False)

        w = options.get('width', 1.0)
        subs['width'] = w
        subs['innerwidth'] = options.get('innerwidth', w) / w
        subs['notesize'] = options.get('notesize', 'small')
        subs['pagebreak'] = '\\clearpage\n' if pagebreak else ''

        text = LATEX_TEMPLATE.safe_substitute(subs)
        ans = pf.RawBlock(text=text, format='latex')

        if backmatter:
            doc.backmatter.append(ans)
            msg = '\hyperref[fig:{}]{{[\Cref{{fig:{}}} Goes Here]}}'
            msg = msg.format(label, label)
            return pf.Plain(pf.Str(msg))
        else:
            return ans
    else:
        title = pf.convert_markdown(title)
        assert len(title)==1, title
        title = (title[0]).items

        notes = pf.Div(*pf.convert_markdown(notes), classes=['note'])
        title_text = pf.stringify(title)
        img = pf.Image(*title, url=fn, title=title_text, identifier=label)
        ans = pf.Div(pf.Plain(img), pf.Plain(pf.LineBreak), notes, classes=['figure'])
        return ans
예제 #41
0
파일: wg21.py 프로젝트: mpark/wg21
def tonytable(table, doc):
    """
    Tony Tables: CodeBlocks are the first-class entities that get added
    to the table. The last (if any) header leading upto a CodeBlock is
    the header that gets attached to the table cell with the CodeBlock.

    Each CodeBlock entry is pushed onto the current row. Horizontal rule
    is used to move to the next row.

    # Example

    ::: tonytable

    ### Before
    ```cpp
    std::visit([&](auto&& x) {
      strm << "got auto: " << x;
    }, v);
    ```

    ### After
    ```cpp
    inspect (v) {
      <auto> x: strm << "got auto: " << x;
    }
    ```

    ---

    ```cpp
    std::visit([&](auto&& x) {
      using X = std::remove_cvref_t<decltype(x)>;
      if constexpr (C1<X>()) {
        strm << "got C1: " << x;
      } else if constexpr (C2<X>()) {
        strm << "got C2: " << x;
      }
    }, v);
    ```

    ```cpp
    inspect (v) {
      <C1> c1: strm << "got C1: " << c1;
      <C2> c2: strm << "got C2: " << c2;
    }
    ```

    :::

    # Generates

    +------------------------------------------------+-------------------------------------------------+
    | __Before__                                     | __After__                                       |
    +------------------------------------------------+-------------------------------------------------+
    | ```cpp                                         | ```cpp                                          |
    | std::visit([&](auto&& x) {                     | inspect (v) {                                   |
    |   strm << "got auto: " << x;                   |   <auto> x: strm << "got auto: " << x;          |
    | }, v);                                         | }                                               |
    |                                                | ```                                             |
    +------------------------------------------------+-------------------------------------------------+
    | std::visit([&](auto&& x) {                     | ```cpp                                          |
    |   using X = std::remove_cvref_t<decltype(x)>;  | inspect (v) {                                   |
    |   if constexpr (C1<X>()) {                     |   <C1> c1: strm << "got C1: " << c1;            |
    |     strm << "got C1: " << x;                   |   <C2> c2: strm << "got C2: " << c2;            |
    |   } else if constexpr (C2<X>()) {              | }                                               |
    |     strm << "got C2: " << x;                   | ```                                             |
    |   }                                            |                                                 |
    | }, v);                                         |                                                 |
    +------------------------------------------------+-------------------------------------------------+
    """

    def build_header(elem):
        # We use a `pf.RawInline` here because setting the `align`
        # attribute on `pf.Div` does not work for some reason.
        header = pf.Plain(pf.RawInline('<div align="center">', 'html'),
                          pf.Strong(*elem.content),
                          pf.RawInline('</div>', 'html'))
        width = float(elem.attributes['width']) if 'width' in elem.attributes else 0
        return header, width

    def build_code(elem, format):
        if (format != 'gfm'):
            return elem
        lang = ' lang="{}"'.format(elem.classes[0]) if elem.classes else ''
        code = html.escape(elem.text)
        return pf.RawBlock('\n\n<pre{lang}>\n{code}\n</pre>'.format(lang=lang, code=code))

    def build_row(elems):
        return pf.TableRow(*[pf.TableCell(elem) for elem in elems])

    if not isinstance(table, pf.Div) or 'tonytable' not in table.classes:
        return None

    rows = []

    kwargs = {}

    headers = []
    widths = []
    examples = []

    header = pf.Null()
    width = 0
    table.content.append(pf.HorizontalRule())
    for elem in table.content:
        if isinstance(elem, pf.Header):
            header, width = build_header(elem)
        elif isinstance(elem, pf.CodeBlock):
            headers.append(header)
            widths.append(width)
            header = pf.Null()
            width = 0

            examples.append(build_code(elem, doc.format))
        elif isinstance(elem, pf.HorizontalRule) and examples:
            if not all(isinstance(header, pf.Null) for header in headers):
                rows.append(build_row(headers))

            if 'width' not in kwargs:
                kwargs['width'] = widths

            rows.append(build_row(examples))

            headers = []
            widths = []
            examples = []
        else:
            pf.debug("[Warning] The following is ignored by a Tony Table:",
                     pf.stringify(elem))

    return pf.Table(*rows, **kwargs)
예제 #42
0
def get_filename(elem):
    fn = pf.stringify(elem, newlines=False).split(maxsplit=1)[1]
    if not os.path.splitext(fn)[1]:
        fn += '.md'
    return fn
예제 #43
0
def h_paragraph(e,doc):
    """Make lines starting with bold become paragraphs."""
    if not isinstance(e,pf.Strong) or doc.format != 'latex': return None
    if isinstance(e.parent , pf.Para) and e.parent.parent == doc and e.parent.content.index(e)==0:
        return pf.RawInline(r"\paragraph{"+pf.stringify(e)+"}",format='latex')
    return None
예제 #44
0
파일: run_tests.py 프로젝트: Bvggy/panflute
	f.write('\n')
print(' - Done!')
print(' - Comparing...')
with open(input_fn, encoding='utf-8') as f:
	input_data = f.read()
with open(output_fn, encoding='utf-8') as f:
	output_data = f.read()
print(' - Are both files the same?')
print('   - Length:', len(input_data) == len(output_data), len(input_data), len(output_data))
print('   - Content:', input_data == output_data)


assert input_data == output_data



print('Testing stringify()')
with open(input_fn, encoding='utf-8') as f:
	doc = pf.load(f)
ans = pf.stringify(doc)
#print(repr(ans).encode('utf-8'))
with open(output_txt_panflute, encoding='utf-8', mode='w') as f:
	f.write(ans)

import pandocfilters, json
with open(input_fn, encoding='utf-8') as f:
	doc = json.load(f)
ans = pandocfilters.stringify(doc)
with open(output_txt_benchmark, encoding='utf-8', mode='w') as f:
	f.write(ans)
예제 #45
0
def h_emph(e,doc):
    if isinstance(e,pf.Emph) or isinstance(e,pf.Strong):
        doc.searchtext += " " + pf.stringify(e)
    return None
def action(elem, doc):
    if isinstance(elem, pf.Superscript) and doc.format == 'markdown':
        text = '<sup>' + pf.stringify(elem) + '</sup>'
        return pf.RawInline(text)
예제 #47
0
def labelref(e,doc):
    if e.identifier: return e.identifier
    regex = re.compile(r'[^a-zA-Z\-]')
    t =  regex.sub('', pf.stringify(e).replace(' ','-'))[:25]
    if t: return t
    return "temp"