def main() -> None: """Setuptools entrypoint for the deparagraph CLI. Use this filter as:: pandoc [..] --filter=lander-deparagraph """ toJSONFilter(deparagraph)
f.close() p = call(["pdflatex", 'tikz.tex'], stdout=sys.stderr) os.chdir(olddir) if filetype == 'pdf': shutil.copyfile(tmpdir + '/tikz.pdf', outfile + '.pdf') else: call(["convert", tmpdir + '/tikz.pdf', outfile + '.' + filetype]) shutil.rmtree(tmpdir) def tikz(elem, doc): if type(elem) == RawBlock and elem.format == "latex": code = elem.text if re.match("\\\\begin{tikzpicture}", code): outfile = imagedir + '/' + sha1(code) filetype = {'html': 'png', 'latex': 'pdf'}.get(doc.format, 'png') src = outfile + '.' + filetype if not os.path.isfile(src): try: os.mkdir(imagedir) sys.stderr.write('Created directory ' + imagedir + '\n') except OSError: pass tikz2image(code, filetype, outfile) sys.stderr.write('Created image ' + src + '\n') return Para(Image(url=src)) if __name__ == "__main__": toJSONFilter(tikz)
import panflute as pf def add_one(e, doc): if type(e)==pf.Table: for row in e.items: for cell in row: if len(cell) == 1 and len(cell[0].items)==1: text = cell[0].items[0].text if text.isdigit(): cell[0].items[0].text = str(int(text)+1) return e def idea(e, doc): selector = 'Table Items Rows Cells' if any(type(a)==pf.Table for a in e.ancestors()): pass if __name__ == '__main__': pf.toJSONFilter(add_one)
elif "threecolumnsep" in e.classes: return doColumnsSeperator('0.33') elif "threecolumnsend" in e.classes: return doColumnsEnd() elif "twocolumnsbigleftbegin" in e.classes: return doColumnsBegin('0.66') elif "twocolumnsbigleftsep" in e.classes: return doColumnsSeperator('0.33') elif "twocolumnsbigleftend" in e.classes: return doColumnsEnd() elif "fourquadone" in e.classes: return RawBlock("\\FourQuad{%\n", format="latex") elif "fourquadtwo" in e.classes: return RawBlock("\n}{%\n", format="latex") elif "fourquadthree" in e.classes: return RawBlock("\n}{%\n", format="latex") elif "fourquadfour" in e.classes: return RawBlock("\n}{%\n", format="latex") elif "fourquadend" in e.classes: return RawBlock("\n}% END QuadFour\n", format="latex") else: return else: return else: return if __name__ == "__main__": toJSONFilter(splitblockold, prepare=prepare, finalize=finalize)
def main(): logging.debug("Start typography.py") pf.toJSONFilter(action=action) logging.debug("End typography.py")
#!/usr/bin/env python """ Pandoc filter to allow interpolation of metadata fields into a document. %{fields} will be replaced by the field's value. """ from panflute import toJSONFilter, Span, Str, MetaInlines import re pattern = re.compile('%\{(.*)\}$') def metavars(elem, doc): if type(elem) == Str: m = pattern.match(elem.text) if m: field = m.group(1) result = doc.get_metadata(field, None) if type(result) == MetaInlines: return Span(*result.content, classes=['interpolated'], attributes={'field': field}) elif isinstance(result, str): return Str(result) if __name__ == "__main__": toJSONFilter(metavars)
#!/usr/bin/env python """ Pandoc filter to convert all regular text to uppercase. Code, link URLs, etc. are not affected. """ from panflute import toJSONFilter, Str def caps(elem, doc): if type(elem) == Str: elem.text = elem.text.upper() return elem if __name__ == "__main__": toJSONFilter(caps)
""" Convert the text in all headers to uppercase """ import panflute as pf def upper_str(elem, doc): if isinstance(elem, pf.Str): elem.text = elem.text.upper() def upper_header(elem, doc): if isinstance(elem, pf.Header): return elem.walk(upper_str) if __name__ == '__main__': pf.toJSONFilter(upper_header)
#!/usr/bin/env python """ Pandoc filter to convert definition lists to bullet lists with the defined terms in strong emphasis (for compatibility with standard markdown). """ from panflute import toJSONFilter, DefinitionList, BulletList, ListItem, Para, Strong def deflists(elem, doc): if type(elem) == DefinitionList: bullets = [tobullet(item) for item in elem.content] return BulletList(*bullets) def tobullet(item): ans = [Para(Strong(*item.term))] for definition in item.definitions: for block in definition.content: ans.append(block) return ListItem(*ans) if __name__ == "__main__": toJSONFilter(deflists)
#!/usr/bin/env python import panflute as pf """ Pandoc filter that causes emphasis to be rendered using the custom macro '\myemph{...}' rather than '\emph{...}' in latex. Other output formats are unaffected. """ def latex(s): return pf.RawInline(s, format='latex') def myemph(e, doc): if type(e) == pf.Emph and doc.format == 'latex': return pf.Span(latex('\\myemph{'), *e.items, latex('}')) if __name__ == "__main__": pf.toJSONFilter(myemph)
doc.content.insert( pos + inc, RawBlock("\n\\section*{" + name + "}\n", format="latex")) inc = inc + 1 debug('Ending "sections.py" ...') def sections(e, doc): # print(doc.format) if doc.format == "latex" or doc.format == "beamer": if isinstance(e, Header): # debug(e) if e.level == 2: if "section" in e.classes: newsection = e.attributes['name'] global sectionlist sectionlist += [(e.index, newsection)] debug('new section:' + newsection) return else: return else: return else: return if __name__ == "__main__": toJSONFilter(sections, prepare=prepare, finalize=finalize)
if m and m.group(1) in TO_CONVERT: env = '{' + m.group(1) + '}' # sys.stderr.write('Parsing contents of ' + env + '\n') startstr = '\\begin' + env + (m.group(2) or '') + (m.group(3) or '') # Ideally we will run pandoc with all the filters that were invoked # originally. But panflute does not know that. # Perhaps if parse-latexenv-panflute runs *first* then the other # filters will be fine to run after? If it passes JSON output # to the next filter I think we will be fine, but if it passes # (say) LaTeX then we won't. # I need to apply pandoc to the contents with this filter. return ([pf.RawBlock(text=startstr, format='latex')] + pf.convert_text( m.group(4), extra_args=[ '--filter={}'.format(os.path.realpath(__file__)) ]) + [pf.RawBlock(text='\\end' + env, format='latex')]) # This is OK, *but* any arguments to the begin{} are dropped. # So \begin{block}{Title} --> \begin{block} and a *literal* {Title} # So perhaps I automatically gobble up any [] {} after the begin # and if you don't want it gobbled you'll just have to put a space # in between (what does LaTeX do about this sort of thing anyway?) if __name__ == "__main__": pf.toJSONFilter(parseRawLatexBlock)
def main(): #tags = {'figure': figure, 'table': table} pf.toJSONFilter(pf.yaml_filter, prepare=prepare, finalize=finalize, tag='figure', function=figure)
def sha1(x): return hashlib.sha1(x.encode(sys.getfilesystemencoding())).hexdigest() imagedir = "graphviz-images" def graphviz(elem, doc): if type(elem) == CodeBlock and 'graphviz' in elem.classes: code = elem.text caption = "caption" G = pygraphviz.AGraph(string=code) G.layout() filename = sha1(code) filetype = {'html': 'png', 'latex': 'pdf'}.get(doc.format, 'png') alt = Str(caption) src = imagedir + '/' + filename + '.' + filetype if not os.path.isfile(src): try: os.mkdir(imagedir) sys.stderr.write('Created directory ' + imagedir + '\n') except OSError: pass G.draw(src) sys.stderr.write('Created image ' + src + '\n') return Para(Image(alt, url=source, title='')) if __name__ == "__main__": toJSONFilter(graphviz)
right = RawInline(']' + label + '\n', format='latex') n = Plain() n.content = [left] + list(e.content) + [right] i = 1 length = len(doc.content) # debug(doc.content[e.index+i]) while not (isinstance(doc.content[e.index + i], Header)): i += 1 if (e.index + i) >= length: break ret = RawBlock(endTag(tag), format='latex') if (e.index + i) >= length: # We need to add it at the end of the list! doc.content.append(ret) else: doc.content.insert(e.index + i, ret) return n else: return else: return else: return if __name__ == "__main__": toJSONFilter(moreblocks, prepare=prepare, finalize=finalize)
""" Pandoc filter using panflute, for fenced code blocks """ import panflute as pf def prepare(doc): pass def fenced_action(options, data, element, doc): if doc.format == 'latex': pass # return None -> element unchanged # return [] -> delete element def finalize(doc): pass if __name__ == '__main__': pf.toJSONFilter(pf.yaml_filter, prepare=prepare, finalize=finalize, tag='sometag', function=fenced_action) # tags = {'sometag': fenced_action, 'another_tag': another_action} # pf.toJSONFilter(pf.yaml_filter, prepare, finalize, tags=tags)
#!/usr/bin/env python import panflute as pf """ Pandoc filter that causes emphasis to be rendered using the custom macro '\myemph{...}' rather than '\emph{...}' in latex. Other output formats are unaffected. """ def latex(s): return pf.RawInline(s, format='latex') def myemph(e, doc): if type(e)==pf.Emph and doc.format=='latex': return pf.Span(latex('\\myemph{'), *e.items, latex('}')) if __name__ == "__main__": pf.toJSONFilter(myemph)
else: label = '\\label{' + elem.identifier + '}' return latex( '\\includely[staffsize=%s]{%s}' % (staffsize, contents) + label ) else: infile = contents + ( '.ly' if '.ly' not in contents else '' ) with open(infile, 'r') as doc: code = doc.read() return Image(url=png(code, staffsize)) if type(elem) == CodeBlock and 'ly' in elem.classes: staffsize = int(elem.attributes.get('staffsize', '20')) if doc.format == "latex": if elem.identifier == "": label = "" else: label = '\\label{' + elem.identifier + '}' return latexblock( '\\lily[staffsize=%s]{%s}' % (staffsize, code) + label ) else: return Para(Image(url=png(code, staffsize))) if __name__ == "__main__": toJSONFilter(lily)
elif type(elem.content[1]) != pf.Space: return False else: return True 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 def action(elem, doc): if isinstance(elem, pf.Para) and is_include_line(elem): fn = get_filename(elem) if not os.path.isfile(fn): return with open(fn) as f: raw = f.read() new_elems = pf.convert_text(raw) div = pf.Div(*new_elems, attributes={'source': fn}) return div if __name__ == '__main__': pf.toJSONFilter(action)
""" Pandoc filter using panflute """ import panflute as pf def prepare(doc): pass def action(elem, doc): if isinstance(elem, pf.Element) and doc.format == 'latex': pass # return None -> element unchanged # return [] -> delete element def finalize(doc): pass if __name__ == '__main__': pf.toJSONFilter(action, prepare=prepare, finalize=finalize)
def main(): pf.toJSONFilter(action=action)
src = os.path.join(imagedir, filename + '.uml') dest = os.path.join(imagedir, filename + '.' + filetype) if not os.path.isfile(dest): try: os.mkdir(imagedir) sys.stderr.write('Created directory ' + imagedir + '\n') except OSError: pass txt = code.encode("utf-8") if not txt.startswith("@start"): txt = "@startuml\n" + txt + "\n@enduml\n" with open(src, "w") as f: f.write(txt) call(["java", "-jar", "plantuml.jar", "-t" + filetype, src]) sys.stderr.write('Created image ' + dest + '\n') return Para( Image(*caption, identifier=elem.identifier, attributes=elem.attributes, url=dest, title=typef)) if __name__ == "__main__": toJSONFilter(plantuml)
import sys from panflute import toJSONFilter, Str, Para, Image, CodeBlock, Block, Header, Div, SmallCaps, convert_text, LineBlock, LineItem #LEVELS = set("tip note warning danger".split()) EMOJI = { "tip": "тЬЕ", "note": "ЁЯЫИ", "warning": "тЪая╕П", "danger": "тШая╕П", } LEVELS = set(EMOJI.keys()) # In case [Foo] references exists inside tip REFERENCES = "\n" + open("docs/_includes/references.liquid").read() def admonition(elem, doc): if type(elem) == CodeBlock and (LEVELS & set(elem.classes)): level = LEVELS & set(elem.classes) code = elem.text levelClass = level.pop() levelText = Str(EMOJI[levelClass] + " " + levelClass.capitalize()) content = convert_text(code + REFERENCES) # re-parse as markdown header = LineBlock(LineItem(SmallCaps(levelText))) return Div(header, Div(*content), classes="admonition %s" % levelClass) if __name__ == "__main__": toJSONFilter(admonition)
else: label = '\\label{' + elem.identifier + '}' return latex("\n\\smallskip\n{%\n" + latexsnippet('\\gregorioscore{' + elem.text + '}', elem.attributes) + "%\n}" + label) else: infile = elem.text + ('.gabc' if '.gabc' not in elem.text else '') with open(infile, 'r') as doc: code = doc.read().split('%%\n')[1] return Image( png(elem.text, latexsnippet('\\gregorioscore', elem.attributes))) elif type(elem) == CodeBlock and "gabc" in elem.classes: if doc.format == "latex": if elem.identifier == "": label = "" else: label = '\\label{' + elem.identifier + '}' return latexblock("\n\\smallskip\n{%\n" + latexsnippet('\\gabcsnippet{' + elem.text + '}', elem.attributes) + "%\n}" + label) else: return Para( Image(url=png(elem.text, latexsnippet('\\gabcsnippet', elem.attributes)))) if __name__ == "__main__": toJSONFilter(gabc)
if isinstance(segment, pf.LineBreak): needs_to_be_split = True if needs_to_be_split: for segment in elem.content: if isinstance(segment, pf.LineBreak): splitParas.append(pf.Para(*singleParaElems)) singleParaElems = [] else: singleParaElems.append(segment) splitParas.append(pf.Para(*singleParaElems)) # pf.debug("Before--------------------") # pf.debug(elem.parent.content) # pf.debug("Before--------------------") for i, item in enumerate(splitParas, elem.index + 1): elem.parent.content.insert(i, item) # pf.debug("Afer--------------------") # pf.debug(elem.parent.content) # pf.debug("Afer--------------------") #Delete the original Para return [] else: # pf.debug("no softbreak or linebreak found") # pf.debug(elem) return elem if __name__ == "__main__": pf.toJSONFilter(break_newpara)
#!/usr/bin/env python import panflute as pf import re """ Pandoc filter that causes everything between '<!-- BEGIN COMMENT -->' and '<!-- END COMMENT -->' to be ignored. The comment lines must appear on lines by themselves, with blank lines surrounding them. """ def prepare(doc): doc.ignore = False def comment(el, doc): is_relevant = (type(el) == pf.RawBlock) and (doc.format == 'html') if is_relevant and re.search("<!-- BEGIN COMMENT -->", el.text): doc.ignore = True if doc.ignore: if is_relevant and re.search("<!-- END COMMENT -->", el.text): doc.ignore = False return [] if __name__ == "__main__": pf.toJSONFilter(comment, prepare=prepare)
def main(): pf.toJSONFilter(code_filter)
+ e.url + '}}') return [youtube] elif type(e) == pf.Link and doc.format == 'html': if 'youtube.com' in e.url: regex = re.compile( r'(https?://)?(www\.)?(youtube|youtu|youtube-nocookie)\.(com|be)/(watch\?v=|embed/|v/|.+\?v=)?(?P<id>[A-Za-z0-9\-=_]{11})?&?(?P<params>.*)' ) match = regex.match(e.url) if match: params = match.group('params').split('&') for param in params: if 't=' in param: youtube = html( '<div style="text-align: center;"><iframe height="250" src="' + 'https://www.youtube.com/embed/' + match.group('id') + '?rel=0&start=' + param.split('=')[1] + '" frameborder="0" allow="encrypted-media" allowfullscreen></iframe></div>' ) return [youtube] youtube = html( '<div style="text-align: center;"><iframe height="250" src="' + 'https://www.youtube.com/embed/' + match.group('id') + '?rel=0" frameborder="0" allow="encrypted-media" allowfullscreen></iframe></div>' ) return [youtube] if __name__ == "__main__": pf.toJSONFilter(youtubevideo)
#!/usr/bin/env python """ Pandoc filter that causes emphasized text to be displayed in ALL CAPS. """ from panflute import toJSONFilter, Emph, Str from caps import caps def deemph(elem, doc): if type(elem) == Emph: # Make Str elements in Emph uppercase elem.walk(caps) # Append them to Emph's parent (after the emph) for i, item in enumerate(elem.content, elem.index + 1): elem.parent.content.insert(i, item) # Delete the emph return [] if __name__ == "__main__": toJSONFilter(deemph)
def main(): pf.toJSONFilter(graphviz_filter)
def main(): # pf.run_filter(action) pf.toJSONFilter(action=action)
""" Panflute filter to parse CSV in fenced YAML code blocks """ import io import csv import panflute as pf def fenced_action(options, data, element, doc): # We'll only run this for CodeBlock elements of class 'csv' title = options.get('title', 'Untitled Table') title = [pf.Str(title)] has_header = options.get('has-header', False) with io.StringIO(data) as f: reader = csv.reader(f) body = [] for row in reader: cells = [pf.TableCell(pf.Plain(pf.Str(x))) for x in row] body.append(pf.TableRow(*cells)) header = body.pop(0) if has_header else None table = pf.Table(*body, header=header, caption=title) return table if __name__ == '__main__': pf.toJSONFilter(pf.yaml_filter, tag='csv', function=fenced_action)
def main(): pf.toJSONFilter(pf.yaml_filter, prepare=prepare, finalize=finalize, tag='figure', function=figure)
#!/usr/bin/env python import panflute as pf import re """ Pandoc filter that causes everything between '<!-- BEGIN COMMENT -->' and '<!-- END COMMENT -->' to be ignored. The comment lines must appear on lines by themselves, with blank lines surrounding them. """ def prepare(doc): doc.ignore = False def comment(el, doc): is_relevant = (type(el) == pf.RawBlock) and (el.format == 'html') if is_relevant and re.search("<!-- BEGIN COMMENT -->", el.text): doc.ignore = True if doc.ignore: if is_relevant and re.search("<!-- END COMMENT -->", el.text): doc.ignore = False return [] if __name__ == "__main__": pf.toJSONFilter(comment, prepare=prepare)
return hashlib.sha1(x.encode(sys.getfilesystemencoding())).hexdigest() def abc2eps(abc, filetype, outfile): p = Popen(["abcm2ps", "-O", outfile + '.eps', "-"], stdin=PIPE) p.stdin.write(abc) p.communicate() p.stdin.close() call(["convert", outfile + '.eps', outfile + '.' + filetype]) def abc(elem, doc): if type(elem) == CodeBlock and 'abc' in elem.classes: code = elem.text outfile = os.path.join(imagedir, sha1(code)) filetype = {'html': 'png', 'latex': 'pdf'}.get(doc.format, 'png') src = outfile + '.' + filetype if not os.path.isfile(src): try: os.mkdir(imagedir) sys.stderr.write('Created directory ' + imagedir + '\n') except OSError: pass abc2eps(code.encode("utf-8"), filetype, outfile) sys.stderr.write('Created image ' + src + '\n') return Para(Image(url=src)) if __name__ == "__main__": toJSONFilter(abc)