def replace_unit(key, value, format, meta): """ Try to perform the replacements in `value` according to `pattern`. If nothing is replaced the this function does not return any value. If a replacement is performed then a `RawInline` object is returned to pandoc. Parameters ---------- key : (string) The pandoc element type. Here we check if it is 'Str'. value : (string) The original text. format : (string) The output format of pandoc. meta : Not used here. """ if key == 'Str': if format == 'html' or format == 'html5': replacement = ("<span class=\"phy-quantity\">" # First regex group is the number "<span class=\"phy-number\">\\1</span>" # First regex group is the unit "<span class=\"phy-unit\">\\2</span>" "</span>") newValue = pattern.sub(replacement, value) if newValue != value: return RawInline("html", newValue) elif format == 'latex': replacement = "\\SI{\\1}{\\2}" newValue = pattern.sub(replacement, value) if newValue != value: return RawInline("latex", newValue) else: # For other formats we just add a space between the number and # the unit replacement = "\\1 \\2" newValue = pattern.sub(replacement, value) if newValue != value: return Str(newValue) elif key == 'Math': if format == 'latex': mathText = value[1] replacement = "\\\\SI{\\1}{\\2}" newMathText = pattern.sub(replacement, mathText) if newMathText != mathText: value[1] = newMathText return Math(value[0], value[1]) else: mathText = value[1] replacement = "\\1\\;\\\\text{\\2}" newMathText = pattern.sub(replacement, mathText) if newMathText != mathText: value[1] = newMathText return Math(value[0], value[1])
def gitlab_markdown(key, value, format, meta): if key == "CodeBlock": [[identification, classes, keyvals], code] = value if classes[0] == "math": fmt = {'t': 'DisplayMath', 'c': []} return Para([Math(fmt, code)]) elif key == "Math": [fmt, code] = value if isinstance(fmt, dict) and fmt['t'] == "InlineMath": # if fmt['t'] == "InlineMath": return Math(fmt, code.strip('`'))
def gitlab_markdown(key, value, format, meta): if key == "CodeBlock": [[identification, classes, keyvals], code] = value if len(classes) > 0 and classes[0] == "math": fmt = {'t': 'DisplayMath', 'c': []} return Para([Math(fmt, code)]) elif key == "Link": if len(value) <= 2: return None # sys.stderr.write("Raw ") # sys.stderr.write(str(len(value))) # sys.stderr.write(str(value)) # sys.stderr.write("\n") link = value[2] if str(link[0]).endswith(".md"): link = '#' needSep = 0 for item in value[1]: if 't' in item: if item['t'] == 'Str': if needSep != 0: link += '-' link += item['c'].lower() needSep = 1 # sys.stderr.write(str(link)) value[2] = [link, '']
def wordpressify(key, value, format_, meta): ''' Convert math formulas so they work with WordPress. When writing to HTML, use -m in pandoc so the $s are preserved ''' if key == 'Math': return Math(value[0], "LaTeX " + value[1])
def _add_markup(fmt, eq, value): """Adds markup to the output.""" attrs = eq['attrs'] # Context-dependent output if eq['is_unnumbered']: # Unnumbered is also unreferenceable ret = None elif fmt in ['latex', 'beamer']: ret = RawInline('tex', r'\begin{equation}%s\end{equation}' % value[-1]) elif fmt in ('html', 'html5', 'epub', 'epub2', 'epub3') and \ LABEL_PATTERN.match(attrs.id): # Present equation and its number in a span num = str(references[attrs.id].num) outer = RawInline('html', '<span%sclass="eqnos">' % \ (' ' if eq['is_unreferenceable'] else ' id="%s" '%attrs.id)) inner = RawInline('html', '<span class="eqnos-number">') eqno = Math({"t":"InlineMath"}, '(%s)' % num[1:-1]) \ if num.startswith('$') and num.endswith('$') \ else Str('(%s)' % num) endtags = RawInline('html', '</span></span>') ret = [outer, AttrMath(*value), inner, eqno, endtags] elif fmt == 'docx': # As per http://officeopenxml.com/WPhyperlink.php bookmarkstart = \ RawInline('openxml', '<w:bookmarkStart w:id="0" w:name="%s"/><w:r><w:t>' %attrs.id) bookmarkend = \ RawInline('openxml', '</w:t></w:r><w:bookmarkEnd w:id="0"/>') ret = [bookmarkstart, AttrMath(*value), bookmarkend] return ret
def cleanup(k, v, fmt, meta): if k in ['Math']: if fmt in ['latex', 'beamer', 'json', 'html5']: math_type = v[0].get('t', None) if math_type in [u'InlineMath'] and len(v) > 1: solution_match = STRIP_BACKTICKS_RE.search(v[1]) if solution_match: return Math(v[0], solution_match.group('contents'))
def process_equations(key, value, fmt, meta): """Processes the attributed equations.""" if key == 'Math' and len(value) == 3: # Process the equation eq = _process_equation(value, fmt) # Get the attributes and label attrs = eq['attrs'] label = attrs[0] if eq['is_unreferenceable']: attrs[0] = '' # The label isn't needed outside this function # Context-dependent output if eq['is_unnumbered']: # Unnumbered is also unreferenceable return None if fmt in ['latex', 'beamer']: return RawInline('tex', r'\begin{equation}%s\end{equation}' % value[-1]) if fmt in ('html', 'html5') and LABEL_PATTERN.match(label): # Present equation and its number in a span text = str(references[label]) outerspan = RawInline('html', '<span %s style="display: inline-block; ' 'position: relative; width: 100%%">'%(''\ if eq['is_unreferenceable'] \ else 'id="%s"'%label)) innerspan = RawInline( 'html', '<span style="position: absolute; ' 'right: 0em; top: %s; line-height:0; ' 'text-align: right">' % ('0' if text.startswith('$') and text.endswith('$') else '50%', )) num = Math({"t":"InlineMath"}, '(%s)' % text[1:-1]) \ if text.startswith('$') and text.endswith('$') \ else Str('(%s)' % text) endspans = RawInline('html', '</span></span>') return [outerspan, AttrMath(*value), innerspan, num, endspans] if fmt in ('epub', 'epub2', 'epub3') and LABEL_PATTERN.match(label): outerspan = RawInline('html', '<span %s style="display: inline-block; ' 'position: relative; width: 100%%">'%(''\ if eq['is_unreferenceable'] \ else 'id="%s"'%label)) endspan = RawInline('html', '</span>') return [outerspan, AttrMath(*value), endspan] if fmt == 'docx': # As per http://officeopenxml.com/WPhyperlink.php bookmarkstart = \ RawInline('openxml', '<w:bookmarkStart w:id="0" w:name="%s"/><w:r><w:t>' %label) bookmarkend = \ RawInline('openxml', '</w:t></w:r><w:bookmarkEnd w:id="0"/>') return [bookmarkstart, AttrMath(*value), bookmarkend] return None
def processMathTag(key, value, _format, _meta): if key == "Math": [fmt, code] = value searchRe = re.search(r'\s*\\tag\s*{(.+)}|\s*\\tag\s*(\d)', code) if searchRe != None: if searchRe.group(1): tagContent = searchRe.group(1).replace('$', '') else: tagContent = searchRe.group(2).replace('$', '') code = code.replace(searchRe.group(), '\\#(' + tagContent + ')') return Math(fmt, code)
def cleveref_ast_sub(source): res = [] sub_res = cleveref_re.sub(cleveref_sub, source) try: prefix_str, ref_str = sub_res.split('~') res += [Str(prefix_str + u'\xa0')] except: ref_str = sub_res res += [Math({'t': 'InlineMath', 'c': []}, ref_str)] return res
def tikz(key, value, format, meta): global N_FIGS, N_TABS if key == 'Div': if "figure*" in str(value): N_FIGS += 1 [[ident, classes, kvs], _contents] = value newcontents = [html(fig.format(path=f"float{N_FIGS:03}.png"))] ident = f"fig:{N_FIGS}" return Div([ident, classes, kvs], newcontents) if key == 'Table': N_TABS += 1 newcontents = [html(fig.format(path=f"float{N_TABS:03}.png"))] ident = f"tab:{N_TABS}" return Div([ident, [], []], newcontents) if key == 'Link': label = value[-1][0].replace("#", "") if len(label.split(",")) > 1: links = [] for label in label.split(","): pref = label.split(":")[0] # ppprint(pref, "pref") links.append( link(href=f"#{pref}:{label_to_fignum[label]}", label=f"{label_to_fignum[label]}"), ) links.append(Str(",")) del links[-1] return links if label in label_to_fignum: pref = label.split(":")[0] value[-2][0]['c'] = f"{label_to_fignum[label]}" value[-1][0] = f"#{pref}:{label_to_fignum[label]}" if "eq:" in label: return Math({'t': 'InlineMath'}, f"\eqref{{{label}}}") if "sec:" in label: value[-2][0]['c'] = value[-2][0]['c'][1:-1].split(":")[1] if key == 'Span' and "label" in str(value): value[-1][0]['c'] = "" if key == 'Para': ret = [] rets = [] for v in value: if v['t'] == 'Math' and v['c'][0]['t'] == 'DisplayMath': rets.append(Para(ret)) rets.append(Para([v])) ret = [] else: ret.append(v) if len(ret): ret = Para(ret) rets.append(ret) if len(rets): return rets
def replace_smallcaps(key, val, fmt=None, meta=None): """ Replaces \textsc with a hack that has the same effect. https://stackoverflow.com/questions/11576237/mathjax-textsc """ if key != 'Math': return latex = val[1] latex = TEXTSC_REGEX.sub(_textsc_replace, latex) return Math(val[0], latex)
def _adjust_caption(fmt, fig, value): """Adjusts the caption.""" attrs, caption = fig['attrs'], fig['caption'] if fmt in ['latex', 'beamer']: # Append a \label if this is referenceable if PANDOCVERSION < '1.17' and not fig['is_unreferenceable']: # pandoc >= 1.17 installs \label for us value[0]['c'][1] += \ [RawInline('tex', r'\protect\label{%s}'%attrs.id)] else: # Hard-code in the caption name and number/tag if fig['is_unnumbered']: return sep = { 'none': '', 'colon': ':', 'period': '.', 'space': ' ', 'quad': u'\u2000', 'newline': '\n' }[separator] num = targets[attrs.id].num if isinstance(num, int): # Numbered target if fmt in ['html', 'html5', 'epub', 'epub2', 'epub3']: value[0]['c'][1] = [ RawInline('html', r'<span>'), Str(captionname), Space(), Str('%d%s' % (num, sep)), RawInline('html', r'</span>') ] else: value[0]['c'][1] = [ Str(captionname), Space(), Str('%d%s' % (num, sep)) ] value[0]['c'][1] += [Space()] + list(caption) else: # Tagged target if num.startswith('$') and num.endswith('$'): # Math math = num.replace(' ', r'\ ')[1:-1] els = [Math({"t": "InlineMath", "c": []}, math), Str(sep)] else: # Text els = [Str(num + sep)] if fmt in ['html', 'html5', 'epub', 'epub2', 'epub3']: value[0]['c'][1] = \ [RawInline('html', r'<span>'), Str(captionname), Space()] + els + [RawInline('html', r'</span>')] else: value[0]['c'][1] = [Str(captionname), Space()] + els value[0]['c'][1] += [Space()] + list(caption)
def _add_markup(fmt, eq, value): """Adds markup to the output.""" attrs = eq['attrs'] # Context-dependent output if eq['is_unnumbered']: # Unnumbered is also unreferenceable ret = None elif fmt in ['latex', 'beamer']: if re.search(r'&', value[-1]) is not None: # check if it's an aligned multiline equation equation = r'\begin{split}%s\end{split}'%value[-1] environment = "equation" elif re.search(r'\\\\', value[-1]) is not None: # check if it's an unaligned multiline equation equation = value[-1] environment = "multiline" else: # regular equation equation = value[-1] environment = "equation" ret = RawInline('tex', "\\begin{{{env}}}{eq}\\end{{{env}}}".format(env=environment, eq=equation)) elif fmt in ('html', 'html5', 'epub', 'epub2', 'epub3') and \ LABEL_PATTERN.match(attrs.id): # Present equation and its number in a span num = str(references[attrs.id].num) outer = RawInline('html', '<span%sclass="eqnos">' % \ (' ' if eq['is_unreferenceable'] else ' id="%s" '%attrs.id)) inner = RawInline('html', '<span class="eqnos-number">') eqno = Math({"t":"InlineMath"}, '(%s)' % num[1:-1]) \ if num.startswith('$') and num.endswith('$') \ else Str('(%s)' % num) endtags = RawInline('html', '</span></span>') ret = [outer, AttrMath(*value), inner, eqno, endtags] elif fmt == 'docx': # As per http://officeopenxml.com/WPhyperlink.php bookmarkstart = \ RawInline('openxml', '<w:bookmarkStart w:id="0" w:name="%s"/><w:r><w:t>' %attrs.id) bookmarkend = \ RawInline('openxml', '</w:t></w:r><w:bookmarkEnd w:id="0"/>') ret = [bookmarkstart, AttrMath(*value), bookmarkend] return ret
def _cite_replacement(key, value, fmt, meta): """Returns context-dependent content to replace a Cite element.""" assert key == 'Cite' attrs, label = value[0], _get_label(key, value) attrs = PandocAttributes(attrs, 'pandoc') assert label in references # Get the replacement value text = str(references[label]) # Choose between \Cref, \cref and \ref use_cleveref = attrs['modifier'] in ['*', '+'] \ if 'modifier' in attrs.kvs else use_cleveref_default plus = attrs['modifier'] == '+' if 'modifier' in attrs.kvs \ else use_cleveref_default name = plusname[0] if plus else starname[0] # Name used by cref # The replacement depends on the output format if fmt == 'latex': if use_cleveref: # Renew commands needed for cleveref fakery if not 'xnos-cleveref-fake' in meta or \ get_meta(meta, 'xnos-cleveref-fake'): faketex = (r'\xrefname' if plus else r'\Xrefname') + \ '{%s}' % name else: faketex = '' macro = r'\cref' if plus else r'\Cref' ret = RawInline('tex', r'%s%s{%s}'%(faketex, macro, label)) elif use_eqref: ret = RawInline('tex', r'\eqref{%s}'%label) else: ret = RawInline('tex', r'\ref{%s}'%label) else: if use_eqref: text = '(' + text + ')' linktext = [Math({"t":"InlineMath", "c":[]}, text[1:-1]) \ if text.startswith('$') and text.endswith('$') \ else Str(text)] link = elt('Link', 2)(linktext, ['#%s' % label, '']) \ if _PANDOCVERSION < '1.16' else \ Link(['', [], []], linktext, ['#%s' % label, '']) ret = ([Str(name), Space()] if use_cleveref else []) + [link] return ret
def insert_equation_labels(val): ''' Insert equation numbers as strings after equations. Returns the ID of the equation and its new children. ''' latex = val[1] match = LABEL_REGEX.search(latex) if match: label = match.group(1) index = incr_latest_index('equation') ref_index = 'equation-%d' % index # Replace label with actual number in the equation latex = latex.replace(match.group(0), '') latex = latex + '\\tag{%s}' % index label_map[label] = Label( ref_string='Equation %d' % index, ref_index=ref_index, prev_strings=['equation', 'eqn.', 'eqn', 'eq.', 'eq'], ) return ref_index, [Math(val[0], latex)] return '', [Math(*val)]
def _adjust_caption(fmt, table, value): """Adjusts the caption.""" attrs, caption = table['attrs'], table['caption'] num = references[attrs.id].num if fmt in ['latex', 'beamer']: # Append a \label if this is referenceable if not table['is_unreferenceable']: value[1] += [RawInline('tex', r'\label{%s}' % attrs.id)] else: # Hard-code in the caption name and number/tag sep = { 'none': '', 'colon': ':', 'period': '.', 'space': ' ', 'quad': u'\u2000', 'newline': '\n' }[separator] if isinstance(num, int): # Numbered reference if fmt in ['html', 'html5', 'epub', 'epub2', 'epub3']: value[1] = [ RawInline('html', r'<span>'), Str(captionname), Space(), Str('%d%s' % (num, sep)), RawInline('html', r'</span>') ] else: value[1] = [ Str(captionname), Space(), Str('%d%s' % (num, sep)) ] value[1] += [Space()] + list(caption) else: # Tagged reference assert isinstance(num, STRTYPES) if num.startswith('$') and num.endswith('$'): math = num.replace(' ', r'\ ')[1:-1] els = [Math({"t": "InlineMath", "c": []}, math), Str(sep)] else: # Text els = [Str(num + sep)] if fmt in ['html', 'html5', 'epub', 'epub2', 'epub3']: value[1] = \ [RawInline('html', r'<span>'), Str(captionname), Space()] + els + [RawInline('html', r'</span>')] else: value[1] = [Str(captionname), Space()] + els value[1] += [Space()] + list(caption)
def cross_refs(key, value, fmt, meta): """Lookup reference and return number or create reference/number.""" global crossrefs if key == 'Str': crossref, string = parse(crossrefs, value) if crossref: return Str(string) if key == 'Math': t, s = value crossref, string = parse(crossrefs, s) if crossref: s = s.replace('@{' + crossref + '}', string) return Math(t, s)
def processMathDoubleBackslash(key, value, _format, _meta): if key == 'Para': if len(value) == 1 and value[0]['t'] == 'Math': [fmt, code] = value[0]['c'] if '\\\\' in code: if fmt['t'] == 'DisplayMath': res = code.split('\\\\') for item in res: if item.count('\\begin') != item.count('\\end'): return return list(map(lambda item : Para([Math(fmt, item)]), res)) elif key == 'Math': [fmt, code] = value if '\\\\' in code: if fmt['t'] == 'InlineMath': res = list(filter(None, re.split(r'( *\\\\ *)', code))) mathlist = list(map(lambda item : LineBreak() if re.match(r'( *\\\\ *)', item) else Math(fmt, item), res)) return mathlist
def _add_markup(fmt, thm, value): """Adds markup to the output.""" attrs = thm['attrs'] ret = None if fmt in ['latex', 'beamer']: # remark: tagged theorems are not (yet) supported # Present theorem as a definition list env = attrs.id.split(':')[0] tmp = value[0][0]['c'][1] title = '' if len(tmp) >= 1: title = '[%s]' % stringify(tmp) start = RawBlock('tex', r'\begin{%s}%s%s' % \ (env, title, '' if thm['is_unreferenceable'] else r'\label{%s} '%attrs.id)) endtags = RawBlock('tex', r'\end{%s}' % env) content = value[1][0] ret = [start] + content + [endtags] elif fmt in ('html', 'html5', 'epub', 'epub2', 'epub3'): if isinstance(targets[attrs.id].num, int): # Numbered reference num = Str(' %d' % targets[attrs.id].num) else: # Tagged reference assert isinstance(targets[attrs.id].num, STRTYPES) text = ' ' + targets[attrs.id].num if text.startswith('$') and text.endswith('$'): math = text.replace(' ', r'\ ')[1:-1] num = Math({"t": "InlineMath", "c": []}, math) else: # Text num = Str(text) # Present theorem as a definition list outer = RawBlock('html', '<dl%sclass="theoremnos">' % \ (' ' if thm['is_unreferenceable'] else ' id="%s" '%attrs.id)) name = names[attrs.id.split(':')[0]] head = RawBlock('html', '<dt>') endhead = RawBlock('html', '</dt><dd>') title = value[0][0]['c'][1] if len(title) >= 1: title.insert(0, Str(' (')) title.insert(0, num) title.append(Str(')')) else: title.append(num) title.insert(0, Str('%s' % name)) title.append(Str(':')) content = value[1][0] endtags = RawBlock('html', '</dd></dl>') ret = [outer, head, Plain(title), endhead] + content + [endtags] # To do: define default behaviour return ret
def processMathOverToFrac(key, value, _format, _meta): if key == "Math": [fmt, code] = value while '\\over' in code: code = convertOverToFrac(code) return Math(fmt, code)
def filter_main(key, value, format, meta): # f.write(repr(key) + '\n') # f.write(repr(value) + '\n') # f.write('------\n') if key == 'CodeBlock': text = value[1] m = re.match(r'%%%%lyxblog-raw\n(.*)', text, flags=re.DOTALL | re.I) if m: return RawBlock('html', m[1]) elif key == 'Math' and value[0]['t'] == 'DisplayMath': # i.e. not inline # MathJax supports labels and eq. numbering only for AMS envs, so we # convert non-AMS envs into AMS envs. latex = value[1] if not latex.startswith(r'\begin{'): # not AMS env # We assume there are no comments inside math blocks (if the file # is produced by LyX, there shouldn't be any). pos = latex.find(r'\label{') if pos == -1: # no labels => no numbering fixed = r'\begin{align*}' + value[1] + r'\end{align*}' else: fixed = r'\begin{align}' + value[1] + r'\end{align}' return Math(value[0], fixed) elif key == 'Span': # This supports general labels (i.e. labels not in equations, captions # or section headers). id, classes, key_values = value[0] if len(key_values) == 1 and key_values[0][0] == 'label': # we remove the text from the label. return Span(value[0], []) elif key == 'Header': content = value[2] if content[-1]['t'] == 'Span': [id, classes, key_values], text = content[-1]['c'] if len(key_values) == 1 and key_values[0][0] == 'label': # we label the header itself (id) and delete the label-span label_name = key_values[0][1] value[1][0] = label_name return Header(value[0], value[1], content[:-1]) elif key == 'Math' and value[0]['t'] == 'InlineMath': if value[1].startswith('\\ref{') and value[1][-1] == '}': name = value[1][len('\\ref{'):-1] # We try to extract the text from the label itself. # (=00007B and =00007D represent '{' and '}' and are in the TeX # file produced by LyX.) m = re.match(r'.*=00007B([^}]+)=00007D$', name) if m: return RawInline('html', '<a href="#{}">{}</a>'.format(name, m[1])) # We only handle references to sections and images here. # (Mathjax already handles the equations.) num = sec_name_to_num.get(name, img_name_to_num.get(name, None)) if num: return RawInline('html', '<a href="#{}">{}</a>'.format(name, num)) elif key == 'Para' and value[0]['t'] == 'Image': # NOTE: # In pandoc 2, a Para[Image] where Image.title is 'fig:' becomes # a <figure> with a <figcaption>. [id, classes, style], alt, [src, title] = value[0]['c'] style = {k: v for k, v in style} width = float(style.get('width', '100.0%')[:-1]) margin = (100 - width) / 2 global image_idx src = image_info[image_idx] image_idx += 1 label = '' if alt[-1]['t'] == 'Span': id, classes, key_values = alt[-1]['c'][0] # attr key_values = dict(key_values) if 'label' in key_values: # remove the label from the caption (it'll be put right before # the image). alt = alt[:-1] # remove the label from the caption label = key_values['label'] fake_class = '{}:{:.5}%'.format(UID2, margin) img_attrs = make_attrs(label, [fake_class], {'width': '100%'}) caption = [Emph([Str('Figure {}.'.format(image_idx))])] if title == 'fig:': caption += [Space()] + alt para_content = [Image(img_attrs, caption, (src, 'fig:'))] return Para(para_content)
def latex_prefilter(key, value, oformat, meta, *args, **kwargs): r""" A prefilter that adds more latex capabilities to Pandoc's tex to markdown features. Currently implemented: * Keeps unmatched `\eqref` (drops the rest) * Wraps equation blocks with `equation[*]` environment depending on whether or not their body contains a `\label` * Converts custom environments to div objects Set the variables `preserved_tex` and `env_conversions` to allow more raw latex commands and to convert latex environment names to CSS class names, respectively. # TODO: Describe more. # XXX: This filter does some questionable recursive calling at the # shell level. Parameters ========== TODO: Document parameters. """ pandoc_logger.debug((u"Filter key:{}, value:{}, meta:{}," "args:{}, kwargs:{}\n").format( key, value, meta, args, kwargs)) global custom_inline_math, preserved_tex,\ env_conversions, figure_dirs, fig_fname_ext custom_inline_math = custom_inline_math.copy() custom_inline_math.update(meta.get( 'custom_inline_math', {}).get('c', {})) env_conversions = env_conversions.copy() env_conversions.update(meta.get( 'env_conversions', {}).get('c', {})) preserved_tex += meta.get('preserved_tex', {}).get('c', []) figure_dir_meta = meta.get('figure_dir', {}).get('c', None) if figure_dir_meta is not None: figure_dirs.add(figure_dir_meta) fig_fname_ext = meta.get('figure_ext', {}).get('c', None) if key == 'RawInline' and value[0] == 'latex': if any(c_ in value[1] for c_ in preserved_tex): # Check for `\includegraphics` commands and their # corresponding files. new_value = copy(value[1]) figure_files = graphics_pattern.findall(new_value) def repstep(x, y): new_y = rename_find_fig(y, figure_dirs, fig_fname_ext) return x.replace(y, new_y) new_value = reduce(repstep, figure_files, new_value) pandoc_logger.debug("figure_files: {}\tnew_value: {}\n".format( figure_files, new_value)) for from_, to_ in custom_inline_math.items(): if callable(to_): new_value = to_(new_value) else: new_value = new_value.replace(from_, to_) new_value = [Math({'t': 'InlineMath', 'c': []}, new_value)] return new_value else: # Check for `\graphicspaths` commands to parse for # new paths. gpaths_matches = gpath_pattern_1.search(value[1]) if gpaths_matches is not None: for gpaths in gpaths_matches.groups(): gpaths = gpath_pattern_2.findall(gpaths) figure_dirs.update(gpaths) # Do not include `\graphicspath` in output. return [] elif key == "Image": return process_image(key, value, oformat, meta) elif key == "Math" and value[0]['t'] == "DisplayMath": star = '*' if '\\label' in value[1]: star = '' wrapped_value = ("\\begin{{equation{}}}\n" "{}\n" "\\end{{equation{}}}").format( star, value[1], star) return Math(value[0], wrapped_value) if key == 'RawBlock' and value[0] == 'latex': return process_latex_envs(key, value, oformat, meta) elif "Raw" in key: return []
def _cite_replacement(key, value, fmt, meta): """Returns context-dependent content to replace a Cite element.""" assert key == 'Cite' # Extract the attributes attrs = PandocAttributes(value[0], 'pandoc') # Check if the nolink attribute is set nolink = attrs['nolink'].capitalize() == 'True' if 'nolink' in attrs \ else False # Extract the label label = value[-2][0]['citationId'] if allow_implicit_refs and not label in references and ':' in label: testlabel = label.split(':')[-1] if testlabel in references: label = testlabel # Get the target metadata; typecast it as a Target for easier access target = references[label] if label in references else None if target and not isinstance(target, Target): target = Target(*target) # Issue a warning for duplicate targets if _WARNINGLEVEL and target and target.has_duplicate: msg = textwrap.dedent(""" %s: Referenced label has duplicate: %s """ % (_FILTERNAME, label)) STDERR.write(msg) STDERR.flush() # Get the replacement value text = str(target.num) if target else '??' # Choose between \Cref, \cref and \ref use_cleveref = attrs['modifier'] in ['*', '+'] \ if 'modifier' in attrs else use_cleveref_default is_plus_ref = attrs['modifier'] == '+' if 'modifier' in attrs \ else use_cleveref_default refname = plusname[0] if is_plus_ref else starname[0] # Reference name # The replacement content depends on the output format if fmt == 'latex': if use_cleveref: macro = r'\cref' if is_plus_ref else r'\Cref' ret = RawInline('tex', r'%s{%s}' % (macro, label)) elif use_eqref: ret = RawInline('tex', r'\eqref{%s}' % label) else: ret = RawInline('tex', r'\ref{%s}' % label) if nolink: # https://tex.stackexchange.com/a/323919 ret['c'][1] = \ r'{\protect\NoHyper' + ret['c'][1] + r'\protect\endNoHyper}' else: if use_eqref: text = '(' + text + ')' elem = Math({"t":"InlineMath", "c":[]}, text[1:-1]) \ if text.startswith('$') and text.endswith('$') \ else Str(text) if not nolink and target: prefix = 'ch%03d.xhtml' % target.secno \ if fmt in ['epub', 'epub2', 'epub3'] and \ target.secno else '' elem = elt('Link', 2)([elem], ['%s#%s' % (prefix, label), '']) \ if version(_PANDOCVERSION) < version('1.16') else \ Link(['', [], []], [elem], ['%s#%s' % (prefix, label), '']) ret = ([Str(refname + NBSP)] if use_cleveref else []) + [elem] # If the Cite was square-bracketed then wrap everything in a span s = stringify(value[-1]) # pandoc strips off intervening space between the prefix and the Cite; # we may have to add it back in prefix = value[-2][0]['citationPrefix'] spacer = [Space()] \ if prefix and not stringify(prefix).endswith(('{', '+', '*', '!')) \ else [] if s.startswith('[') and s.endswith(']'): els = value[-2][0]['citationPrefix'] + \ spacer + ([ret] if fmt == 'latex' else ret) + \ value[-2][0]['citationSuffix'] # We don't yet know if there will be attributes, so leave them # as None. This is fixed later when attributes are processed. ret = Span(None, els) return ret
def reformat_math(key, value, format, meta): if key != 'Str': return if not any(c in value for c in math_characters): return return Math([], value)
def _process_figure(value, fmt): """Processes the figure. Returns a dict containing figure properties.""" # pylint: disable=global-statement global Nreferences # Global references counter global has_unnumbered_figures # Flags unnumbered figures were found global cursec # Current section # Parse the image attrs, caption = value[0]['c'][:2] # Initialize the return value fig = { 'is_unnumbered': False, 'is_unreferenceable': False, 'is_tagged': False, 'attrs': attrs } # Bail out if the label does not conform if not LABEL_PATTERN.match(attrs[0]): has_unnumbered_figures = True fig['is_unnumbered'] = True fig['is_unreferenceable'] = True return fig # Process unreferenceable figures if attrs[0] == 'fig:': # Make up a unique description attrs[0] = attrs[0] + str(uuid.uuid4()) fig['is_unreferenceable'] = True unreferenceable.append(attrs[0]) # For html, hard-code in the section numbers as tags kvs = PandocAttributes(attrs, 'pandoc').kvs if numbersections and fmt in ['html', 'html5'] and not 'tag' in kvs: if kvs['secno'] != cursec: cursec = kvs['secno'] Nreferences = 1 kvs['tag'] = cursec + '.' + str(Nreferences) Nreferences += 1 # Save to the global references tracker fig['is_tagged'] = 'tag' in kvs if fig['is_tagged']: # Remove any surrounding quotes if kvs['tag'][0] == '"' and kvs['tag'][-1] == '"': kvs['tag'] = kvs['tag'].strip('"') elif kvs['tag'][0] == "'" and kvs['tag'][-1] == "'": kvs['tag'] = kvs['tag'].strip("'") references[attrs[0]] = kvs['tag'] else: Nreferences += 1 references[attrs[0]] = Nreferences # Adjust caption depending on the output format if fmt in ['latex', 'beamer']: # Append a \label if this is referenceable if not fig['is_unreferenceable']: value[0]['c'][1] += [RawInline('tex', r'\label{%s}' % attrs[0])] else: # Hard-code in the caption name and number/tag if type(references[attrs[0]]) is int: # Numbered reference value[0]['c'][1] = [Str(captionname), Space(), Str('%d:'%references[attrs[0]]), Space()] + \ list(caption) else: # Tagged reference assert type(references[attrs[0]]) in STRTYPES text = references[attrs[0]] if text.startswith('$') and text.endswith('$'): # Math math = text.replace(' ', r'\ ')[1:-1] els = [Math({"t": "InlineMath", "c": []}, math), Str(':')] else: # Text els = [Str(text + ':')] value[0]['c'][1] = [Str(captionname), Space()]+ els + [Space()] + \ list(caption) return fig
def test_replace_smallcaps(self): result = replace_smallcaps('Math', [ {'t': 'DisplayMath'}, '\\text{\\textsc{3CosAdd} }']) self.assertEqual(result, Math( {'t': 'DisplayMath'}, '\\rm{3C{\small OS}A{\small DD}}'))