def blockquote2div(key, value, format, meta): """Convert a blockquote into a div if it begins with a header that has attributes containing a single class that is in the allowed classes. This function can be passed directly to toJSONFilter from pandocfilters. """ if key == 'BlockQuote': blockquote = value header = find_header(blockquote) if not header: return else: level, attr, inlines = header id, classes, kvs = attr ltitle = pf.stringify(inlines).lower() if ltitle in SPECIAL_TITLES: classes.append(SPECIAL_TITLES[ltitle]) return pf.Div(attr, blockquote) elif len(classes) == 1 and classes[0] in SPECIAL_CLASSES: remove_attributes(blockquote) # a blockquote is just a list of blocks, so it can be # passed directly to Div, which expects Div(attr, blocks) return pf.Div(attr, blockquote)
def enclose_input_code(key, value, format, metadata): """Enclose any input code in a div to allow collapsing. 'Input code' is a code block that has 'n' defined (the prompt number). """ if key == 'CodeBlock': div_attr = {'classes': ['collapsible']} code_attr = PandocAttributes(value[0], format='pandoc') if 'n' not in code_attr.kvs: return else: button = pf.RawBlock('html', collapse_button(n=code_attr['n'])) code = pf.CodeBlock(*value) content = [button, pf.Div(pf.attributes({}), [code])] return pf.Div(pf.attributes(div_attr), content)
def block_hands(key, value, fmt, meta): if key == 'CodeBlock': lines = value[1].split('\n') hands = {} for line in lines: m = re.match('([NSEW]): (.*)', line) if m: hands[m.group(1)] = m.group(2) if len(hands) == 0: return None empty_cell = [pf.Plain([])] diagram = [[empty_cell] * 3 for _ in range(3)] pos = {'N': (0, 1), 'S': (2, 1), 'E': (1, 2), 'W': (1, 0)} for (player, hand) in hands.items(): i, j = pos[player] diagram[i][j] = [hand_diagram(hand)] AlignLeft = {'t': 'AlignLeft'} table = pf.Table([], [AlignLeft, AlignLeft, AlignLeft], [0, 0, 0], [], diagram) attr = ('', ['hands'], []) return pf.Div(attr, [table]) return None
def blockquote2div(key, value, format, meta): """Convert a blockquote into a div if it begins with a header that has attributes containing a single class that is in the allowed classes. This function can be passed directly to toJSONFilter from pandocfilters. """ if key == 'BlockQuote': blockquote = value header = find_header(blockquote) if not header: return else: level, attr, inlines = header id, classes, kvs = attr if len(classes) == 1 and classes[0] in SPECIAL_CLASSES: panel_kind, glyphicon_kind = SPECIAL_CLASSES[classes[0]] h_level, h_attr, h_inlines = blockquote[0]['c'] # insert an icon as the first sub-item of the header span = pf.Span(["", ["glyphicon", glyphicon_kind], []], []) h_inlines.insert(0, span) # only the header goes into panel-heading # WARNING: pandoc doesn't preserve header attributes when the # header is nested under blockquote. This makes it # impossible to alter header's "class" attribute, for # example. header = pf.Header(h_level, h_attr, h_inlines) panel_header = pf.Div(("", ["panel-heading"], []), [header]) # the rest of the blockquote goes into panel-body panel_body = pf.Div(("", ["panel-body"], []), blockquote[1:]) # apply Bootstrap panel classes to the div classes.append("panel") classes.append(panel_kind) # a blockquote is just a list of blocks, so it can be # passed directly to Div, which expects Div(attr, blocks) return pf.Div((id, classes, kvs), [panel_header, panel_body])
def bidding_divs(key, value, fmt, meta): global prev_key if key == 'BulletList' and prev_key != pf.stringify(value[0]): prev_key = pf.stringify(value[0]) if is_bidding(value): attr = ('', ['bids'], []) return pf.Div(attr, [pf.BulletList(value)]) return None
def figure_replacement(self, key, value, format, metadata): """Replace figures with appropriate representation. This works with Figure, which is our special type for images with attributes. This allows us to set an id in the attributes. The other way of doing it would be to pull out a '\label{(.*)}' from the caption of an Image and use that to update the references. """ _caption, (filename, target), attrs = value caption = pf.stringify(_caption) attr = PandocAttributes(attrs) if 'unnumbered' in attr.classes: star = '*' fcaption = caption else: self.fig_replacement_count += 1 if not attr.id: attr.id = self.auto_fig_id(self.fig_replacement_count) ref = self.references[attr.id] star = '' if caption: fcaption = u'Figure {n}: {caption}'.format(n=ref['id'], caption=caption) else: fcaption = u'Figure {n}'.format(n=ref['id']) if 'figure' not in attr.classes: attr.classes.insert(0, 'figure') if format in self.formats: figure = self.figure_styles[format].format(attr=attr, filename=filename, alt=fcaption, fcaption=fcaption, caption=caption, star=star).encode('utf-8') return RawBlock(format, figure) else: alt = [pf.Str(fcaption)] target = (filename, '') image = pf.Image(alt, target) figure = pf.Para([image]) return pf.Div(attr.to_pandoc(), [figure])
def save_uri(key, value, format, metadata): if format == 'latex' and isOutputFigure(key, value): attr, blocks = value image = blocks[0]['c'][ 0] # should be only inline in only block in the div caption, (uri, title) = image['c'] global image_count image_count += 1 fname = 'build/figures/{i:05d}.png'.format(i=image_count) match = png_uri.search(uri) if match: data = match.groups()[0] else: return with open(fname, 'wb') as f: f.write(base64.b64decode(data)) return pf.Div(attr, [pf.Plain([pf.Image(caption, (fname, title))])])
def tableattrs_replacement(self, key, value, format, metadata): """Replace TableAttrs with appropriate representation. TableAttrs is our special type for tables with attributes, allowing us to set an id in the attributes. """ caption, alignment, size, headers, rows, (id, classes, kvs) = value if 'unnumbered' in classes: fcaption = caption else: self.table_replacement_count += 1 if not id: id = self.auto_table_id(self.table_replacement_count) ref = self.references[id] if caption: fcaption = [ pf.Str('Table'), pf.Space(), pf.Str(str(ref['id']) + ':'), pf.Space() ] + caption else: fcaption = [ pf.Str('Table'), pf.Space(), pf.Str(str(ref['id'])) ] if format == 'latex' or format == 'beamer': return latex_table(caption, alignment, size, headers, rows, id, classes, kvs) else: return pf.Div([id, classes, kvs], [pf.Table(fcaption, alignment, size, headers, rows)])
def walker(key, value, fmt, meta): 'walk down the pandoc AST and invoke workers for CodeBlocks' if key == 'CodeBlock': return dispatch(value, fmt, meta).image() elif key == 'Div': # Process Div & try to merge its (subsequent) Image's [[ident, classes, kvs], blocks] = value if not "im_merge" in classes: return None # keep it as-is classes = [x for x in classes if x != 'im_merge'] rv = [] for block in blocks: if block['t'] != 'CodeBlock': rv.append(block) else: elm = dispatch(block['c'], fmt, meta).image() rest = mergeImages(rv, elm) rv.extend(rest) return pf.Div([ident, classes, kvs], rv)
def blockquote2div(key, value, format, meta): """Convert a blockquote into a div if it begins with a header that has attributes containing a single class that is in the allowed classes. This function can be passed directly to toJSONFilter from pandocfilters. """ if key == 'BlockQuote': blockquote = value header = find_header(blockquote) if not header: return else: level, attr, inlines = header id, classes, kvs = attr if len(classes) == 1 and classes[0] in SPECIAL_CLASSES: panel_kind, glyphicon_kind = SPECIAL_CLASSES[classes[0]] h_level, h_attr, h_inlines = blockquote[0]['c'] # insert an icon as the first sub-item of the header span = pf.Span(["", ["glyphicon", glyphicon_kind], []], []) h_inlines.insert(0, span) # only the header goes into panel-heading header = pf.Header(h_level, [h_attr[0], [], []], h_inlines) panel_header = pf.Div(("", ["panel-heading"], []), [header]) # the rest of the blockquote goes into panel-body panel_body = pf.Div(("", ["panel-body"], []), blockquote[1:]) # apply Bootstrap panel classes to the div classes.append("panel") classes.append(panel_kind) # a blockquote is just a list of blocks, so it can be # passed directly to Div, which expects Div(attr, blocks) if classes[0] == "callout": return [{ "t": "RawBlock", "c": [ "html", "<aside class=\"{0}\">".format(' '.join(classes)) ] }, panel_header, panel_body, { "t": "RawBlock", "c": ["html", "</aside>"] }] else: return [{ "t": "RawBlock", "c": [ "html", "<section class=\"{0}\">".format(' '.join(classes)) ] }, panel_header, panel_body, { "t": "RawBlock", "c": ["html", "</section>"] }]
def block_bids(key, value, fmt, meta): def disp_bid(b): if b == 'p': return 'pass' elif b[0] in '1234567' and b[1] in 'CDHS': return b[0] + '!' + b[1:] else: return b if key == 'CodeBlock': m = re.match('(NS|EW|all)(/[NSEW])?: (.*)', value[1]) if m is None: return None players = m.group(1) def_mod = {'NS': 1, 'EW': 0, 'all': -1} raw_bids = m.group(3) auction_done = raw_bids[-1] != '-' if not auction_done: raw_bids = raw_bids[:-1] bids = raw_bids.split('-') first_player = 1 if players == 'EW' else 0 if m.group(2): first_player = 'NESW'.find(m.group(2)[1]) player = first_player res = [] for bid in bids: defence = bid[0] == '(' and bid[-1] == ')' if player % 2 == def_mod[players] and not defence: res.append('p') player = (player + 1) % 4 if defence: res.append(bid[1:-1]) else: res.append(bid) player = (player + 1) % 4 if auction_done: while len(res) < 3 or res[-3:].count('p') != 3: res.append('p') res = [disp_bid(b) for b in res] empty_cell = [pf.Plain([])] def make_cell(r): return [pf.Plain([pf.Str(r)])] flat_cells = [empty_cell] * first_player + [make_cell(r) for r in res] cells = reshape(4, flat_cells, empty_cell) names = [make_cell(x) for x in ['North', 'East', 'South', 'West']] AlignCenter = {'t': 'AlignCenter'} table = pf.Table([], [AlignCenter] * 4, [0] * 4, names, cells) attr = ('', ['bidding'], []) return pf.Div(attr, [table]) return None