Exemplo n.º 1
0
    def handle_mnref(self, cmd_args, elem):
        r"""Handle ``\MNRef`` command.

        This command inserts a section link.
        """
        target = cmd_args[0]
        return block_wrap(
            pf.Link(url=target, attributes={"data-mnref": "true"}), elem)
Exemplo n.º 2
0
    def handle_mref(self, cmd_args, elem):
        r"""Handle ``\MRef`` command.

        This command translates to ``\vref``.
        """
        url = "#%s" % cmd_args[0]
        return block_wrap(pf.Link(url=url, attributes={"data-mref": "true"}),
                          elem)
Exemplo n.º 3
0
def table_links(elem, doc):
    if isinstance(elem, pf.Str):
        text = pf.stringify(elem)

        if str_is_table_link.search(text):
            label = str_is_table_link.search(text).group(1)

            return pf.Link(pf.Str(label), url=label, classes=["table_note"])
Exemplo n.º 4
0
def header(elem, doc):
    if not isinstance(elem, pf.Header):
        return None

    if elem.identifier == 'bibliography':
        elem.classes.remove('unnumbered')

    elem.content.append(
        pf.Link(url='#{}'.format(elem.identifier), classes=['self-link']))
Exemplo n.º 5
0
    def handle_mextlink(self, cmd_args, elem):
        r"""Handle ``\MExtLink`` command.

        This command inserts an external link.
        """
        url = cmd_args[0]
        text = destringify(cmd_args[1])
        link = pf.Link(*text, url=url)
        return block_wrap(link, elem)
Exemplo n.º 6
0
def finalize(doc):
    try:
        filepath = doc.get_metadata('filepath')
        label = 'Link'
    except:
        filepath = ''
        label = 'No link'
    doc.content.insert(0, pf.Para(pf.Link(pf.Str(label), url=filepath)))
    return doc
Exemplo n.º 7
0
    def handle_msref(self, cmd_args, elem):
        r"""Handle ``\MSRef`` command.

        This command inserts a fragment-style link.
        """
        url = "#%s" % cmd_args[0]
        description = destringify(cmd_args[1])
        return block_wrap(
            pf.Link(*description, url=url, attributes={"data-msref": "true"}),
            elem,
        )
Exemplo n.º 8
0
def parse_abbreviations(elem, doc):
    if hasattr(elem, "text") and is_abbreviation.search(elem.text):
        # text = pf.stringify(elem)
        text = elem.text
        content = []
        logger.debug(f"Original element: {elem}")

        for s, c in utils.re_split(is_abbreviation, text):
            logger.debug(f"re_plit of {text} gave {s} > {c}")
            content.append(s)

            if c:
                pl = "1" if elem.text.startswith("++") else ""

                c = c.split("@")

                if len(c) > 1:
                    specifier = c.pop(0)
                else:
                    specifier = ""

                identifier = c.pop(0)

                uppercase = "1" if identifier[
                    0] in string.ascii_uppercase else ""

                # Now we know whether it's uppercase
                identifier = identifier.lower()

                if (identifier not in doc.abbr["aliases"]
                        and identifier[-1] == "s" and not pl
                        and identifier[:-1] in doc.abbr["aliases"]):
                    identifier = identifier[:-1]
                    pl = "1"

                identifier = doc.abbr["aliases"].get(identifier, identifier)

                doc.abbr["used"].append(identifier)

                attributes = {
                    "identifier": identifier,
                    "plural": pl,
                    "uppercase": uppercase,
                    "specifier": specifier,
                }

                content.append(
                    pf.Link(pf.Str(identifier),
                            classes=["abbr"],
                            attributes=attributes))

        return pf.Span(*content)
Exemplo n.º 9
0
    def handle_myoutubevideo(self, cmd_args, elem):
        r"""Handle ``\MYoutubeVideo``.

        Just return a Link Element.
        """
        title, _, _, url = cmd_args
        link = pf.Link(
            *destringify(title),
            url=url,
            title=title,
            classes=ELEMENT_CLASSES["MYOUTUBE_VIDEO"],
        )
        return block_wrap(link, elem)
Exemplo n.º 10
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
Exemplo n.º 11
0
    def handle_mvideo(self, cmd_args, elem):
        r"""Handle ``\MVideo``.

        Just return a Link Element.
        """
        filename = "{}.mp4".format(cmd_args[0])
        title = cmd_args[1]
        link = pf.Link(
            *destringify(title),
            url=filename,
            title=title,
            classes=ELEMENT_CLASSES["MVIDEO"],
        )
        remember(elem.doc, "label", link)
        return block_wrap(link, elem)
Exemplo n.º 12
0
def action ( elem,doc ) :
  """
    action of filter, get all equations with class and ref them 
  """
  if isinstance(elem,pf.Header):
    doc.heq.incHeader(elem.level)
  if isinstance(elem,pf.Para) and has_eq(elem) and len(elem.content) > 1  :
    doc.heq.n += 1
    doc.heq.elemToId(elem)
    doc.backmatter.append( doc.heq.itself() )

    eq = elem.content[0]
    anchor = pf.Link(identifier=doc.heq.label(),url=doc.heq.url(),classes=["eq"])

    return pf.Para(eq,anchor)
Exemplo n.º 13
0
def _table_links(elem, doc):
    table_note_prefix = doc.table_note_prefix

    if isinstance(elem, pf.Str):
        text = pf.stringify(elem)

        match = TABLE_LINK.search(text)
        if match:
            label = match.group("label")
            label = _num_label_to_symbol(label)
            label = _format_label(label)

            if doc.format == "latex":
                return pf.RawInline(f"\\tnotex{{{table_note_prefix}:{label}}}",
                                    format="latex")
            else:
                return pf.Link(pf.Str(label),
                               url=label,
                               classes=["table_note"])
Exemplo n.º 14
0
def action(elem, doc):

    global section

    nameref = "\\nameref{"
    if isinstance(elem, pf.RawInline
                  ) and elem.format == 'tex' and elem.text.startswith(nameref):
        # get the ref out of the text (turns "\nameref{header}" into "header"):
        section_id = elem.text[len(nameref):-1]

        # find *any* element that has an ID that matches the one we just extracted
        def matches_id(elem, doc):
            global section
            if hasattr(elem, 'identifier') and elem.identifier == section_id:
                section = elem

        doc.walk(matches_id)

        # Make a link to that section
        link = pf.Link(pf.Str(pf.stringify(section)), url=f"#{section_id}")
        section = None
        return link
Exemplo n.º 15
0
def formatCell(text):
	if len(text) < 10 or text.isdigit():
		return pf.Plain(pf.Str(text))
	try:
		text = float(text)
		if text > 0 and text < .001:
			return pf.Plain(pf.Str('%.3E' % text))
		return pf.Plain(pf.Str('%.3f' % text))
	except (ValueError, TypeError):
		# transform links
		elems = []
		lastend = None
		for m in re.finditer(r'\[(.+?)\]\((.+?)\)', text):
			if lastend is None:
				elems.append(pf.Str(text[:m.start()]))
			else:
				elems.append(pf.Str(text[lastend:m.start()]))
			elems.append(pf.Link(pf.Str(m.group(1)), url = m.group(2)))
			lastend = m.end()
		if elems:
			elems.append(pf.Str(text[lastend:]))
			return pf.Plain(*elems)
		return pf.Plain(pf.Str(text))
Exemplo n.º 16
0
def fenced_action(options, data, element, doc):
	# We'll only run this for CodeBlock elements of class 'table'
	caption     = options.get('caption', 'Untitled Table')
	#caption     = [pf.Str(caption)]
	filepath    = options.get('file')
	has_header  = options.get('header', True)
	width       = options.get('width', 1)
	total_width = float(options.get('total_width', .8))
	align       = options.get('align', 'default')
	nrows       = options.get('rows', 0)
	ncols       = options.get('cols', 0)
	csvargs     = options.get('csvargs', {})
	dtargs      = options.get('dtargs', {})
	mediadir    = doc.get_metadata('mediadir')

	csvargs['dialect']   = csvargs.get('dialect', "unix")
	csvargs['delimiter'] = csvargs.get('delimiter', "\t").encode().decode('unicode_escape')

	f = io.StringIO(data) if data else open(filepath)
	try:
		reader = csv.reader(f, **csvargs)
		body = []
		for i, row in enumerate(reader):
			if nrows and i > nrows:
				continue
			cells = [	pf.TableCell(formatCell(x))
						for k, x in enumerate(row) if not ncols or k < ncols]
			body.append(pf.TableRow(*cells))
	finally:
		f.close()

	ncols = min(ncols, len(row)) if ncols else len(row)
	if has_header:
		header = body.pop(0)
		if body and len(body[0].content) == len(header.content) + 1:
			header.content.insert(0, pf.TableCell(pf.Plain(pf.Str(''))))
	elif nrows:
		header = None
		body = body[:nrows]

	if not isinstance(width, list):
		width = [width]
	if len(width) == 1 and ncols:
		width = width * ncols
	sumwidth    = float(sum(width))
	total_width = min(total_width, 1)
	width       = [float(wid)*float(total_width)/sumwidth for wid in width]
	if not isinstance(align, list):
		align = [align]
	if len(align) == 1 and ncols:
		align = align * ncols
	align = ['Align' + al.capitalize() for al in align]

	if mediadir and filepath:
		# copy file to mediadir and check if file exists
		filepath = Path(filepath)
		mediadir = Path(mediadir)
		mediadir.mkdir(exist_ok = True, parents = True)
		destfile = mediadir / filepath.name
		destfile = _copyfile(filepath, destfile)

		caption = [pf.Link(	pf.Str(caption),
							url = str(destfile.relative_to(destfile.parent.parent)),
							title = 'Right clink and "Save link as" to download whole table.',
							attributes = {'target': '_blank'})]
	else:
		caption = [pf.Str(caption)]

	table = pf.Table(*body,
		header=header, caption=caption, width=width, alignment = align)
	if dtargs is False:
		return pf.Div(table, classes = ['tablewrapper'])
	else:
		return pf.Div(table, classes = ['tablewrapper', 'datatablewrapper'], attributes = {
			'data-datatable': json.dumps(dtargs)
		})
Exemplo n.º 17
0
def render_abbreviations(elem, doc):
    if isinstance(elem, pf.Link) and "abbr" in elem.classes:
        identifier = elem.attributes["identifier"]
        uppercase = elem.attributes["uppercase"]
        plural = elem.attributes["plural"]
        specifier = elem.attributes["specifier"]

        if identifier not in doc.abbr["definitions"]:
            return pf.Str(identifier)
        else:
            abbr = doc.abbr["definitions"][identifier]
            short = abbr[0]
            long_ = abbr[1]
            description = long_.title()  # needed later for definition liat
            options = abbr[2]

            if doc.format == "latex":
                if identifier not in doc.abbr["rendered"]:
                    doc.abbr["rendered"].append(identifier)

                pl = "pl" if plural else ""
                gls = "Gls" if uppercase else "gls"
                specifier = f"xtr{specifier}" if specifier else specifier

                raw = pf.RawInline(f"\\{gls}{specifier}{pl}{{{identifier}}}",
                                   format="latex")

                return raw
            else:

                category = options.get("category")

                if uppercase:
                    short = short.upper()
                    long_ = long_.title()

                if plural:
                    short = pluralize.plural(short)
                    long_ = pluralize.plural(long_)

                if identifier not in doc.abbr["rendered"]:
                    text = f"{long_} ({short})"

                    if category == "alwaysshort":
                        text = short
                    elif category == "nevershort":
                        text = long_

                    definition_item = pf.Span(pf.Str(short),
                                              identifier=f"abbr:{identifier}")

                    definition_description = pf.Para(pf.Str(description))

                    if not options.get("type") == "ignored":
                        doc.abbr["appendix"].append((
                            identifier,
                            pf.DefinitionItem(
                                [definition_item],
                                [pf.Definition(definition_description)],
                            ),
                        ))

                    doc.abbr["rendered"].append(identifier)
                else:
                    text = short

                    if category == "nevershort":
                        text = long_

                return pf.Link(pf.Str(text),
                               url=f"#abbr:{identifier}",
                               title=long_)
Exemplo n.º 18
0
    def convert(self):
        doc = panflute.Doc(
            api_version=(1, 17, 5),
            metadata={
                'pagetitle': self.title,
            },
        )

        doc.content.append(panflute.Header(panflute.Str(self.title)))

        lists = {}
        tables = {}
        table_rows = {}
        table_cells = {}

        for chunk in self._attr_chunks():
            self.logger.debug(chunk)
            container = panflute.Para()
            cdiv = panflute.Div(container)

            # Handle lists
            if 'list_class' in chunk[0]['attrs']:
                lc = chunk[0]['attrs']['list_class']
                check_state = None
                if lc in ['checked', 'unchecked']:
                    check_state = lc
                    lc = 'checklist'
                ld = chunk[0]['attrs']['list_depth']

                # prune any lists that are lower than us, they're finished
                for i in list(lists.keys()):
                    if i > ld:
                        lists.pop(i)

                # non-homogenous list types can be immediately adjacent without
                # ending up merged
                if ld in lists and lists[ld]['class'] != lc:
                    lists.pop(ld)

                # checklists are a special case, they can't contain other lists
                if lc != 'checklist' and lists and lists[1][
                        'class'] == 'checklist':
                    lists = {}

                # make sure any intermediate lists were created, including
                # the top level because boxnotes
                for i in range(1, ld + 1):
                    if i not in lists:
                        lists[i] = self._list(lc, i)
                        if i != ld:
                            lists[i]['pf'].content.append(panflute.ListItem())
                        lp = lists[i]['pf']
                        if lc == 'checklist':
                            lp = panflute.Div(lp, classes=['checklist'])
                        if i == 1:
                            doc.content.append(lp)
                        else:
                            lists[i - 1]['pf'].content[-1].content.append(lp)

                # set the container for the other subchunks
                container = panflute.Plain()
                cdiv.content = [container]
                cdiv.classes.append(lc)
                if check_state:
                    cdiv.classes.append(check_state)
                lists[ld]['pf'].content.append(panflute.ListItem(cdiv))

                if check_state == 'checked':
                    container.content.append(panflute.Str(CHECKED))
                elif check_state == 'unchecked':
                    container.content.append(panflute.Str(UNCHECKED))

            elif 'table_id' in chunk[-1]['attrs']:
                table_id = chunk[-1]['attrs']['table_id']
                row_id = chunk[-1]['attrs']['table_row']
                cell_id = row_id + chunk[-1]['attrs']['table_col']

                if table_id not in tables:
                    # There's some magic in the constructor for panflute tables
                    # that isn't exposed in any other way, so we can't create
                    # the table until we've finished populating the rows.
                    # Instead, use a placeholder div to locate it within the
                    # document.
                    tables[table_id] = {
                        'div': panflute.Div(),
                        'rows': [],
                    }
                    doc.content.append(tables[table_id]['div'])
                if row_id not in table_rows:
                    table_rows[row_id] = panflute.TableRow()
                    tables[table_id]['rows'].append(table_rows[row_id])
                if cell_id not in table_cells:
                    cdiv = panflute.Div(panflute.Plain())
                    table_cells[cell_id] = panflute.TableCell(cdiv)
                    table_rows[row_id].content.append(table_cells[cell_id])
                container = table_cells[cell_id].content[0].content[0]

            else:
                lists = {}
                doc.content.append(cdiv)

            if 'align' in chunk[0]['attrs']:
                cdiv.attributes['style'] = 'text-align: ' + chunk[0]['attrs'][
                    'align'] + ';'

            for subchunk in chunk:
                if subchunk['newlines'] > 1:
                    # we've had an extra linebreak, no more adding on to lists
                    lists = {}

                # don't do anything with markers
                if subchunk['text'] == '*' and 'lmkr' in subchunk['attrs']:
                    continue

                scont = container
                if 'href' in subchunk['attrs']:
                    scont = panflute.Link(url=subchunk['attrs']['href'])
                    container.content.append(scont)

                if 'image' in subchunk['attrs']:
                    scont.content.append(
                        panflute.Image(
                            url=self._image(subchunk['attrs']['author'],
                                            subchunk['attrs']['image'])))
                    continue

                span = panflute.Span()
                lines = subchunk['text'].splitlines()
                while lines:
                    subtext = lines.pop(0)
                    span.content.append(panflute.Str(subtext))
                    if lines:
                        span.content.append(panflute.LineBreak())

                if 'font' in subchunk['attrs']:
                    color = subchunk['attrs']['font'].get('color', '000000')
                    size = subchunk['attrs']['font'].get('size', 'medium')
                    span.classes.append('font-size-' + size)
                    span.classes.append('font-color-' + color)

                    # I don't actually know what the possible colors are and I
                    # don't feel like finding out, so just inject it as an
                    # inline style.
                    if color != '000000':
                        span.attributes['style'] = 'color: #' + color + ';'

                if subchunk['attrs'].get('underline'):
                    span.classes.append('underline')
                if subchunk['attrs'].get('bold'):
                    span = panflute.Strong(span)
                if subchunk['attrs'].get('italic'):
                    span = panflute.Emph(span)
                if subchunk['attrs'].get('strikethrough'):
                    span = panflute.Strikeout(span)
                scont.content.append(span)

        # Actually create the tables
        for x in tables:
            tables[x]['div'].content.append(panflute.Table(*tables[x]['rows']))

        with io.StringIO() as f:
            panflute.dump(doc, f)
            return f.getvalue()
Exemplo n.º 19
0
 def toLink(self):
   return pf.Link(pf.Str(self.label()),url=self.url(),classes=["aeq"])
Exemplo n.º 20
0
def header(elem, doc):
    if not isinstance(elem, pf.Header):
        return None

    elem.content.append(
        pf.Link(url='#{}'.format(elem.identifier), classes=['self-link']))
Exemplo n.º 21
0
def divspan(elem, doc):
    """
    Non-code diffs: `add` and `rm` are classes that can be added to
    a `Div` or a `Span`. `add` colors the text with `addcolor` and
    `rm` colors the text `rmcolor`. For `Span`s, `add` underlines
    and `rm` strikes out the text.

    # Example

    ## `Div`

    Unchanged portion

    ::: add
    New paragraph

    > Quotes

    More new paragraphs
    :::

    ## `Span`

    > The return type is `decltype(`_e_(`m`)`)` [for the first form]{.add}.
    """

    def _wrap(opening, closing):
        if isinstance(elem, pf.Div):
            if elem.content and isinstance(elem.content[0], pf.Para):
                elem.content[0].content.insert(0, opening)
            else:
                elem.content.insert(0, pf.Plain(opening))
            if elem.content and isinstance(elem.content[-1], pf.Para):
                elem.content[-1].content.append(closing)
            else:
                elem.content.append(pf.Plain(closing))
        elif isinstance(elem, pf.Span):
            elem.content.insert(0, opening)
            elem.content.append(closing)

    def _color(html_color):
        _wrap(pf.RawInline('{{\\color[HTML]{{{}}}'.format(html_color), 'latex'),
              pf.RawInline('}', 'latex'))
        elem.attributes['style'] = 'color: #{}'.format(html_color)

    def _nonnormative(name):
        _wrap(pf.Span(pf.Str('[ '), pf.Emph(pf.Str('{}:'.format(name.title()))), pf.Space),
              pf.Span(pf.Str(' — '), pf.Emph(pf.Str('end {}'.format(name.lower()))), pf.Str(' ]')))

    def _diff(color, latex_tag, html_tag):
        if isinstance(elem, pf.Span):
            def protect_code(elem, doc):
                if isinstance(elem, pf.Code):
                    return pf.Span(pf.RawInline('\\mbox{', 'latex'),
                                   elem,
                                   pf.RawInline('}', 'latex'))
            elem.walk(protect_code)
            _wrap(pf.RawInline('\\{}{{'.format(latex_tag), 'latex'),
                  pf.RawInline('}', 'latex'))
            _wrap(pf.RawInline('<{}>'.format(html_tag), 'html'),
                  pf.RawInline('</{}>'.format(html_tag), 'html'))
        _color(doc.get_metadata(color))

    def pnum():
        num = pf.stringify(elem)

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

        if doc.format == 'latex':
            return pf.RawInline('\\pnum{{{}}}'.format(num), 'latex')
        elif doc.format == 'html':
            return pf.Span(
                pf.RawInline('<a class="marginalized">{}</a>'.format(num), 'html'),
                classes=['marginalizedparent'])

        return pf.Superscript(pf.Str(num))

    def example(): _nonnormative('example')
    def note():    _nonnormative('note')
    def ednote():
        _wrap(pf.Str("[ Editor's note: "), pf.Str(' ]'))
        _color('0000ff')

    def add(): _diff('addcolor', 'uline', 'ins')
    def rm():  _diff('rmcolor', 'sout', 'del')

    if not any(isinstance(elem, cls) for cls in [pf.Div, pf.Span]):
        return None

    if 'pnum' in elem.classes and isinstance(elem, pf.Span):
        return pnum()

    if 'sref' in elem.classes and isinstance(elem, pf.Span):
        target = pf.stringify(elem)
        number = stable_names.get(target)
        link = pf.Link(
            pf.Str('[{}]'.format(target)),
            url='https://wg21.link/{}'.format(target))
        if number is not None:
            return pf.Span(pf.Str(number), pf.Space(), link)
        else:
            pf.debug('mpark/wg21: stable name', target, 'not found')
            return link

    note_cls = next(iter(cls for cls in elem.classes if cls in {'example', 'note', 'ednote'}), None)
    if note_cls == 'example':  example()
    elif note_cls == 'note':   note()
    elif note_cls == 'ednote': ednote(); return

    diff_cls = next(iter(cls for cls in elem.classes if cls in {'add', 'rm'}), None)
    if diff_cls == 'add':  add()
    elif diff_cls == 'rm': rm()
Exemplo n.º 22
0
def Image_to_Link(elem, doc):
    if type(elem) == pf.Image:
        text = elem.content
        url = elem.url
        return pf.Link(*text, url=url)